chore: cleanup and simplify examples (#10743)

This commit is contained in:
Amr Bashir 2024-08-27 01:25:36 +03:00 committed by GitHub
parent c50800023e
commit ad83d41cb5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
119 changed files with 1925 additions and 18714 deletions

View File

@ -1,4 +1,4 @@
[env]
# workaround needed to prevent `STATUS_ENTRYPOINT_NOT_FOUND` error
# workaround needed to prevent `STATUS_ENTRYPOINT_NOT_FOUND` error in tests
# see https://github.com/tauri-apps/tauri/pull/4383#issuecomment-1212221864
__TAURI_WORKSPACE__ = "true"

6
.changes/tauri-build.md Normal file
View File

@ -0,0 +1,6 @@
---
"tauri-build": "patch:feat"
---
Add `WindowsAttributes::new_without_app_manifest` to create `WindowsAttributes` without the default manifest.

108
.gitignore vendored
View File

@ -1,89 +1,55 @@
# Logs
# dependency directories
node_modules/
# Optional npm and yarn cache directory
.npm/
.yarn/
# Output of 'npm pack'
*.tgz
# dotenv environment variables file
.env
# .vscode workspace settings file
.vscode/settings.json
# npm, yarn and bun lock files
package-lock.json
yarn.lock
bun.lockb
# rust compiled folders
target/
# test video for streaming example
streaming_example_test_video.mp4
# examples /gen directory
/examples/**/gen/
# old cli directories
/tooling/cli.js
/tooling/cli.rs
# logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# smoke-tests repo
/smoke-tests
# Runtime data
# runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional yarn cache directory
.yarn
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# miscellaneous
/.vs
.DS_Store
.Thumbs.db
*.sublime*
.idea
debug.log
package-lock.json
.vscode/settings.json
*/.vscode/
proptest-regressions/
TODO.md
# rust compiled folders
target
# lock for libs
#/Cargo.lock Committed to prevent msrv checks from failing
/tooling/bench/tests/Cargo.lock
/yarn.lock
# ignore frida handlers
__handlers__/
# benches
gh-pages
test_video.mp4
# old cli directories
/tooling/cli.js
/tooling/cli.rs

60
Cargo.lock generated
View File

@ -112,6 +112,25 @@ version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "api"
version = "0.1.0"
dependencies = [
"log",
"serde",
"serde_json",
"tauri",
"tauri-build",
"tauri-plugin-sample",
"tiny_http",
]
[[package]]
name = "ascii"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"
[[package]]
name = "atk"
version = "0.18.0"
@ -395,6 +414,12 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "chunked_transfer"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901"
[[package]]
name = "cipher"
version = "0.4.4"
@ -3917,6 +3942,17 @@ dependencies = [
"url",
]
[[package]]
name = "tauri-file-associations-demo"
version = "0.1.0"
dependencies = [
"serde",
"serde_json",
"tauri",
"tauri-build",
"url",
]
[[package]]
name = "tauri-macros"
version = "2.0.0-rc.5"
@ -3944,6 +3980,17 @@ dependencies = [
"walkdir",
]
[[package]]
name = "tauri-plugin-sample"
version = "0.1.0"
dependencies = [
"log",
"serde",
"tauri",
"tauri-plugin",
"thiserror",
]
[[package]]
name = "tauri-runtime"
version = "2.0.0-rc.6"
@ -4122,6 +4169,19 @@ dependencies = [
"time-core",
]
[[package]]
name = "tiny_http"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0d6ef4e10d23c1efb862eecad25c5054429a71958b4eeef85eb5e7170b477ca"
dependencies = [
"ascii",
"chunked_transfer",
"log",
"time",
"url",
]
[[package]]
name = "tinyvec"
version = "1.6.0"

View File

@ -16,6 +16,10 @@ members = [
# integration tests
"core/tests/restart",
"core/tests/acl",
# examples
"examples/file-associations/src-tauri",
"examples/api/src-tauri",
]
exclude = [

View File

@ -223,14 +223,14 @@ fn cfg_alias(alias: &str, has_feature: bool) {
/// Attributes used on Windows.
#[allow(dead_code)]
#[derive(Debug, Default)]
#[derive(Debug)]
pub struct WindowsAttributes {
window_icon_path: Option<PathBuf>,
/// A string containing an [application manifest] to be included with the application on Windows.
///
/// Defaults to:
/// ```text
#[doc = include_str!("window-app-manifest.xml")]
#[doc = include_str!("windows-app-manifest.xml")]
/// ```
///
/// ## Warning
@ -255,10 +255,28 @@ pub struct WindowsAttributes {
app_manifest: Option<String>,
}
impl Default for WindowsAttributes {
fn default() -> Self {
Self::new()
}
}
impl WindowsAttributes {
/// Creates the default attribute set.
pub fn new() -> Self {
Self::default()
Self {
window_icon_path: Default::default(),
app_manifest: Some(include_str!("windows-app-manifest.xml").into()),
}
}
/// Creates the default attriute set wihtou the default app manifest.
#[must_use]
pub fn new_without_app_manifest() -> Self {
Self {
app_manifest: None,
window_icon_path: Default::default(),
}
}
/// Sets the icon to use on the window. Currently only used on Windows.
@ -275,7 +293,7 @@ impl WindowsAttributes {
///
/// Defaults to:
/// ```text
#[doc = include_str!("window-app-manifest.xml")]
#[doc = include_str!("windows-app-manifest.xml")]
/// ```
///
/// ## Warning
@ -641,8 +659,6 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
if let Some(manifest) = attributes.windows_attributes.app_manifest {
res.set_manifest(&manifest);
} else {
res.set_manifest(include_str!("window-app-manifest.xml"));
}
if let Some(version_str) = &config.version {

View File

@ -2,7 +2,7 @@
name = "tauri"
version = "2.0.0-rc.6"
description = "Make tiny, secure apps for all desktop platforms with Tauri"
exclude = [ "/test", "/.scripts", "CHANGELOG.md", "/target" ]
exclude = ["/test", "/.scripts", "CHANGELOG.md", "/target"]
readme = "README.md"
links = "Tauri"
authors = { workspace = true }
@ -24,30 +24,36 @@ features = [
"image-png",
"protocol-asset",
"test",
"specta"
"specta",
]
rustc-args = [ "--cfg", "docsrs" ]
rustdoc-args = [ "--cfg", "docsrs" ]
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
default-target = "x86_64-unknown-linux-gnu"
targets = [
"x86_64-pc-windows-msvc",
"x86_64-unknown-linux-gnu",
"x86_64-apple-darwin",
"x86_64-linux-android",
"x86_64-apple-ios"
"x86_64-apple-ios",
]
[package.metadata.cargo-udeps.ignore]
normal = [ "reqwest" ]
build = [ "tauri-build" ]
development = [ "quickcheck_macros" ]
normal = ["reqwest"]
build = ["tauri-build"]
development = ["quickcheck_macros"]
[dependencies]
serde_json = { version = "1.0", features = [ "raw_value" ] }
serde = { version = "1.0", features = [ "derive", "rc" ] }
tokio = { version = "1", features = [ "rt", "rt-multi-thread", "sync", "fs", "io-util" ] }
serde_json = { version = "1.0", features = ["raw_value"] }
serde = { version = "1.0", features = ["derive", "rc"] }
tokio = { version = "1", features = [
"rt",
"rt-multi-thread",
"sync",
"fs",
"io-util",
] }
futures-util = "0.3"
uuid = { version = "1", features = [ "v4" ], optional = true }
uuid = { version = "1", features = ["v4"], optional = true }
url = "2"
anyhow = "1.0"
thiserror = "1.0"
@ -61,9 +67,12 @@ state = "0.6"
http = "1.1"
dirs = "5"
percent-encoding = "2.3"
reqwest = { version = "0.12", default-features = false, features = [ "json", "stream" ] }
bytes = { version = "1", features = [ "serde" ] }
raw-window-handle = { version = "0.6", features = [ "std" ]}
reqwest = { version = "0.12", default-features = false, features = [
"json",
"stream",
] }
bytes = { version = "1", features = ["serde"] }
raw-window-handle = { version = "0.6", features = ["std"] }
glob = "0.3"
urlpattern = "0.2"
mime = "0.3"
@ -75,15 +84,20 @@ tracing = { version = "0.1", optional = true }
heck = "0.5"
log = "0.4"
dunce = "1"
specta = { version = "^2.0.0-rc.16", optional = true, default-features = false, features = [ "function", "derive" ] }
specta = { version = "^2.0.0-rc.16", optional = true, default-features = false, features = [
"function",
"derive",
] }
[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\", target_os = \"windows\", target_os = \"macos\"))".dependencies]
muda = { version = "0.14", default-features = false, features = [ "serde" ] }
tray-icon = { version = "0.15", default-features = false, features = [ "serde" ], optional = true }
muda = { version = "0.14", default-features = false, features = ["serde"] }
tray-icon = { version = "0.15", default-features = false, features = [
"serde",
], optional = true }
[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
gtk = { version = "0.18", features = [ "v3_24" ] }
webkit2gtk = { version = "=2.0.1", features = [ "v2_38" ] }
gtk = { version = "0.18", features = ["v3_24"] }
webkit2gtk = { version = "=2.0.1", features = ["v2_38"] }
[target."cfg(target_os = \"macos\")".dependencies]
embed_plist = "1.2"
@ -95,9 +109,9 @@ window-vibrancy = "0.5"
webview2-com = "0.33"
window-vibrancy = "0.5"
[target."cfg(windows)".dependencies.windows]
version = "0.58"
features = ["Win32_Foundation"]
[target."cfg(windows)".dependencies.windows]
version = "0.58"
features = ["Win32_Foundation"]
[target."cfg(target_os = \"android\")".dependencies]
jni = "0.21"
@ -117,48 +131,52 @@ tauri-utils = { path = "../tauri-utils/", version = "2.0.0-rc.6", features = [ "
proptest = "1.4.0"
quickcheck = "1.0.3"
quickcheck_macros = "1.0.0"
serde = { version = "1.0", features = [ "derive" ] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tauri = { path = ".", default-features = false, features = [ "wry" ] }
tokio = { version = "1", features = [ "full" ] }
tauri = { path = ".", default-features = false, features = ["wry"] }
tokio = { version = "1", features = ["full"] }
cargo_toml = "0.17"
http-range = "0.1.5"
[features]
default = [ "wry", "compression", "objc-exception", "common-controls-v6" ]
unstable = [ "tauri-runtime-wry/unstable" ]
common-controls-v6 = [ "tray-icon?/common-controls-v6", "muda/common-controls-v6" ]
tray-icon = [ "dep:tray-icon" ]
tracing = [
"dep:tracing",
"tauri-macros/tracing",
"tauri-runtime-wry/tracing"
default = ["wry", "compression", "objc-exception", "common-controls-v6"]
unstable = ["tauri-runtime-wry/unstable"]
common-controls-v6 = [
"tray-icon?/common-controls-v6",
"muda/common-controls-v6",
]
tray-icon = ["dep:tray-icon"]
tracing = ["dep:tracing", "tauri-macros/tracing", "tauri-runtime-wry/tracing"]
test = []
compression = ["tauri-macros/compression", "tauri-utils/compression"]
wry = ["tauri-runtime-wry"]
objc-exception = ["tauri-runtime-wry/objc-exception"]
linux-ipc-protocol = [
"tauri-runtime-wry/linux-protocol-body",
"webkit2gtk/v2_40",
]
linux-libxdo = ["tray-icon/libxdo", "muda/libxdo"]
isolation = ["tauri-utils/isolation", "tauri-macros/isolation", "uuid"]
custom-protocol = ["tauri-macros/custom-protocol"]
native-tls = ["reqwest/native-tls"]
native-tls-vendored = ["reqwest/native-tls-vendored"]
rustls-tls = ["reqwest/rustls-tls"]
devtools = ["tauri-runtime/devtools", "tauri-runtime-wry/devtools"]
process-relaunch-dangerous-allow-symlink-macos = [
"tauri-utils/process-relaunch-dangerous-allow-symlink-macos",
]
test = [ ]
compression = [ "tauri-macros/compression", "tauri-utils/compression" ]
wry = [ "tauri-runtime-wry" ]
objc-exception = [ "tauri-runtime-wry/objc-exception" ]
linux-ipc-protocol = [ "tauri-runtime-wry/linux-protocol-body", "webkit2gtk/v2_40" ]
linux-libxdo = [ "tray-icon/libxdo", "muda/libxdo" ]
isolation = [ "tauri-utils/isolation", "tauri-macros/isolation", "uuid" ]
custom-protocol = [ "tauri-macros/custom-protocol" ]
native-tls = [ "reqwest/native-tls" ]
native-tls-vendored = [ "reqwest/native-tls-vendored" ]
rustls-tls = [ "reqwest/rustls-tls" ]
devtools = [ "tauri-runtime/devtools", "tauri-runtime-wry/devtools" ]
process-relaunch-dangerous-allow-symlink-macos = [ "tauri-utils/process-relaunch-dangerous-allow-symlink-macos" ]
macos-private-api = [
"tauri-runtime/macos-private-api",
"tauri-runtime-wry/macos-private-api"
"tauri-runtime-wry/macos-private-api",
]
webview-data-url = [ "data-url" ]
protocol-asset = [ "http-range" ]
config-json5 = [ "tauri-macros/config-json5" ]
config-toml = [ "tauri-macros/config-toml" ]
image-ico = [ "image/ico" ]
image-png = [ "image/png" ]
macos-proxy = [ "tauri-runtime-wry/macos-proxy" ]
specta = [ "dep:specta" ]
webview-data-url = ["data-url"]
protocol-asset = ["http-range"]
config-json5 = ["tauri-macros/config-json5"]
config-toml = ["tauri-macros/config-toml"]
image-ico = ["image/ico"]
image-png = ["image/png"]
macos-proxy = ["tauri-runtime-wry/macos-proxy"]
specta = ["dep:specta"]
[[example]]
name = "commands"
@ -171,19 +189,15 @@ path = "../../examples/helloworld/main.rs"
[[example]]
name = "multiwebview"
path = "../../examples/multiwebview/main.rs"
required-features = [ "unstable" ]
required-features = ["unstable"]
[[example]]
name = "multiwindow"
path = "../../examples/multiwindow/main.rs"
[[example]]
name = "parent-window"
path = "../../examples/parent-window/main.rs"
[[example]]
name = "navigation"
path = "../../examples/navigation/main.rs"
name = "run-iteration"
path = "../../examples/run-iteration/main.rs"
[[example]]
name = "splashscreen"
@ -200,8 +214,4 @@ path = "../../examples/streaming/main.rs"
[[example]]
name = "isolation"
path = "../../examples/isolation/main.rs"
required-features = [ "isolation" ]
[[example]]
name = "run-iteration"
path = "../../examples/run-iteration/main.rs"
required-features = ["isolation"]

View File

@ -249,12 +249,12 @@ fn main() {
)
.expect("failed to write checked_features file");
// workaround needed to prevent `STATUS_ENTRYPOINT_NOT_FOUND` error
// workaround needed to prevent `STATUS_ENTRYPOINT_NOT_FOUND` error in tests
// see https://github.com/tauri-apps/tauri/pull/4383#issuecomment-1212221864
let target_env = std::env::var("CARGO_CFG_TARGET_ENV");
let is_tauri_workspace = std::env::var("__TAURI_WORKSPACE__").map_or(false, |v| v == "true");
if is_tauri_workspace && target_os == "windows" && Ok("msvc") == target_env.as_deref() {
add_manifest();
embed_manifest_for_tests();
}
if target_os == "android" {
@ -394,8 +394,8 @@ permissions = [{default_permissions}]
}
}
fn add_manifest() {
static WINDOWS_MANIFEST_FILE: &str = "window-app-manifest.xml";
fn embed_manifest_for_tests() {
static WINDOWS_MANIFEST_FILE: &str = "windows-app-manifest.xml";
let manifest = std::env::current_dir()
.unwrap()

View File

@ -118,7 +118,7 @@ impl<'a> PageLoadPayload<'a> {
/// by internal code and external testing/fuzzing tools. If not used with feature `unstable`, this
/// struct is marked `#[non_exhaustive]` and is non-constructable externally.
#[derive(Debug)]
#[cfg_attr(not(feature = "unstable"), non_exhaustive)]
#[cfg_attr(not(feature = "test"), non_exhaustive)]
pub struct InvokeRequest {
/// The invoke command.
pub cmd: String,

View File

@ -1,5 +1,2 @@
/node_modules/
/.vscode/
.DS_Store
.cargo
dist/
/dist/*
!/dist/.gitkeep

0
examples/api/dist/.gitkeep vendored Normal file
View File

View File

@ -16,10 +16,10 @@
"devDependencies": {
"@iconify-json/codicon": "^1.1.49",
"@iconify-json/ph": "^1.1.13",
"@sveltejs/vite-plugin-svelte": "^3.1.1",
"@unocss/extractor-svelte": "^0.61.0",
"svelte": "^4.2.18",
"unocss": "^0.61.0",
"vite": "^5.3.2"
"@sveltejs/vite-plugin-svelte": "^3.1.1",
"svelte": "^4.2.18",
"vite": "^5.4.1"
}
}

View File

@ -39,12 +39,4 @@ path = "../../../core/tauri"
features = ["test"]
[features]
prod = ["tauri/custom-protocol"]
# default to small, optimized release binaries
[profile.release]
panic = "abort"
codegen-units = 1
lto = true
incremental = false
opt-level = "s"
prod = ["tauri/custom-protocol"]

View File

@ -2,10 +2,13 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use tauri_build::WindowsAttributes;
fn main() {
tauri_build::try_build(
tauri_build::Attributes::new()
.codegen(tauri_build::CodegenContext::new())
.windows_attributes(WindowsAttributes::new_without_app_manifest())
.plugin(
"app-menu",
tauri_build::InlinedPlugin::new().commands(&["toggle", "popup"]),
@ -17,4 +20,32 @@ fn main() {
])),
)
.expect("failed to run tauri-build");
// workaround needed to prevent `STATUS_ENTRYPOINT_NOT_FOUND` error in tests
// see https://github.com/tauri-apps/tauri/pull/4383#issuecomment-1212221864
let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
let target_env = std::env::var("CARGO_CFG_TARGET_ENV");
let is_tauri_workspace = std::env::var("__TAURI_WORKSPACE__").map_or(false, |v| v == "true");
if is_tauri_workspace && target_os == "windows" && Ok("msvc") == target_env.as_deref() {
embed_manifest_for_tests();
}
}
fn embed_manifest_for_tests() {
static WINDOWS_MANIFEST_FILE: &str = "windows-app-manifest.xml";
let manifest = std::env::current_dir()
.unwrap()
.join("../../../core/tauri-build/src")
.join(WINDOWS_MANIFEST_FILE);
println!("cargo:rerun-if-changed={}", manifest.display());
// Embed the Windows application manifest file.
println!("cargo:rustc-link-arg=/MANIFEST:EMBED");
println!(
"cargo:rustc-link-arg=/MANIFESTINPUT:{}",
manifest.to_str().unwrap()
);
// Turn linker warnings into errors.
println!("cargo:rustc-link-arg=/WX");
}

View File

@ -12,13 +12,12 @@ use serde::Serialize;
use tauri::{
ipc::Channel,
webview::{PageLoadEvent, WebviewWindowBuilder},
App, AppHandle, Emitter, Listener, Manager, RunEvent, Runtime, WebviewUrl,
App, Emitter, Listener, Runtime, WebviewUrl,
};
#[allow(unused)]
use tauri::{Manager, RunEvent};
use tauri_plugin_sample::{PingRequest, SampleExt};
pub type SetupHook = Box<dyn FnOnce(&mut App) -> Result<(), Box<dyn std::error::Error>> + Send>;
pub type OnEvent = Box<dyn FnMut(&AppHandle, RunEvent)>;
#[derive(Clone, Serialize)]
struct Reply {
data: String,
@ -27,7 +26,7 @@ struct Reply {
#[cfg(target_os = "macos")]
pub struct AppMenu<R: Runtime>(pub std::sync::Mutex<Option<tauri::menu::Menu<R>>>);
#[cfg(desktop)]
#[cfg(all(desktop, not(test)))]
pub struct PopupMenu<R: Runtime>(tauri::menu::Menu<R>);
#[cfg_attr(mobile, tauri::mobile_entry_point)]

View File

@ -1,6 +1,7 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
#![cfg(all(desktop, not(test)))]
use tauri::{
command,

View File

@ -2,6 +2,8 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
#![cfg(all(desktop, not(test)))]
use std::sync::atomic::{AtomicBool, Ordering};
use tauri::{
include_image,

View File

@ -33,7 +33,7 @@
},
"definitions": {
"DefaultPermission": {
"description": "The default permission set of the plugin.\n\nWorks similarly to a permission with the \"default\" identifier.",
"description": "The default permission set of the plugin.\n\n Works similarly to a permission with the \"default\" identifier.",
"type": "object",
"required": [
"permissions"
@ -49,7 +49,7 @@
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does. Tauri convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does.\n Tauri convention is to use <h4> headings in markdown content\n for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@ -91,7 +91,7 @@
}
},
"Permission": {
"description": "Descriptions of explicit privileges of commands.\n\nIt can enable commands to be accessible in the frontend of the application.\n\nIf the scope is defined it can be used to fine grain control the access of individual or multiple commands.",
"description": "Descriptions of explicit privileges of commands.\n\n It can enable commands to be accessible in the frontend of the application.\n\n If the scope is defined it can be used to fine grain control the access of individual or multiple commands.",
"type": "object",
"required": [
"identifier"
@ -111,7 +111,7 @@
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does. Tauri internal convention is to use <h4> headings in markdown content for Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does.\n Tauri internal convention is to use <h4> headings in markdown content\n for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@ -150,7 +150,7 @@
}
},
"Commands": {
"description": "Allowed and denied commands inside a permission.\n\nIf two commands clash inside of `allow` and `deny`, it should be denied by default.",
"description": "Allowed and denied commands inside a permission.\n\n If two commands clash inside of `allow` and `deny`, it should be denied by default.",
"type": "object",
"properties": {
"allow": {
@ -172,7 +172,7 @@
}
},
"Scopes": {
"description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command. The configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json { \"allow\": [{ \"path\": \"$HOME/**\" }], \"deny\": [{ \"path\": \"$HOME/secret.txt\" }] } ```",
"description": "An argument for fine grained behavior control of Tauri commands.\n\n It can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command.\n The configured scope is passed to the command and will be enforced by the command implementation.\n\n ## Example\n\n ```json\n {\n \"allow\": [{ \"path\": \"$HOME/**\" }],\n \"deny\": [{ \"path\": \"$HOME/secret.txt\" }]\n }\n ```",
"type": "object",
"properties": {
"allow": {

View File

@ -8,7 +8,7 @@ use tauri::ipc::Channel;
#[derive(Serialize)]
pub struct Event {
pub kind: String,
pub value: Option<String>
pub value: Option<String>,
}
#[derive(Serialize)]

View File

@ -1,7 +1,3 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
export default {

View File

@ -6,6 +6,8 @@ This feature is commonly used for functionality such as previewing or editing fi
## Running the example
```
cargo build --example file-associations
```
1. Run the following inside `examples/file-associations/src-tauri`
```
cargo build
```

View File

@ -9,16 +9,11 @@
<body>
<h1>File Associations</h1>
<div id="files"></div>
<pre id="files"></pre>
<script>
const d = document.getElementById('files')
d.textContent = window.openedUrls
window.onFileOpen = (files) => {
console.log(files)
d.textContent = files
}
const filesView = document.getElementById('files')
filesView.textContent = window.openedFiles.join('\n')
</script>
</body>
</html>

View File

@ -1,5 +0,0 @@
# Generated by Cargo
# will have compiled files and executables
/target/
WixTools
/capabilities/schemas

File diff suppressed because it is too large Load Diff

View File

@ -10,9 +10,6 @@ tauri-build = { path = "../../../core/tauri-build", features = ["codegen"] }
[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = [ "derive" ] }
serde = { version = "1.0", features = ["derive"] }
tauri = { path = "../../../core/tauri", features = [] }
url = "2"
[features]
default = [ "tauri/custom-protocol" ]

View File

@ -7,46 +7,54 @@
windows_subsystem = "windows"
)]
use std::{env, sync::Mutex};
use tauri::Manager;
use std::path::PathBuf;
use tauri::AppHandle;
struct OpenedUrls(Mutex<Option<Vec<url::Url>>>);
fn handle_file_associations(app: AppHandle, files: Vec<PathBuf>) {
let files = files
.into_iter()
.map(|f| {
let file = f.to_string_lossy().replace("\\", "\\\\"); // escape backslash
format!("\"{file}\"",) // wrap in quotes for JS array
})
.collect::<Vec<_>>()
.join(",");
tauri::WebviewWindowBuilder::new(&app, "main", Default::default())
.initialization_script(&format!("window.openedFiles = [{files}]"))
.build()
.unwrap();
}
fn main() {
tauri::Builder::default()
.manage(OpenedUrls(Default::default()))
.setup(|app| {
#[cfg(any(windows, target_os = "linux"))]
{
// NOTICE: `args` may include URL protocol (`your-app-protocol://`) or arguments (`--`) if app supports them.
let mut urls = Vec::new();
for arg in env::args().skip(1) {
if let Ok(url) = url::Url::parse(&arg) {
urls.push(url);
let mut files = Vec::new();
// NOTICE: `args` may include URL protocol (`your-app-protocol://`)
// or arguments (`--`) if your app supports them.
// files may aslo be passed as `file://path/to/file`
for maybe_file in std::env::args().skip(1) {
// skip flags like -f or --flag
if maybe_file.starts_with("-") {
continue;
}
// handle `file://` path urls and skip other urls
if let Ok(url) = url::Url::parse(&maybe_file) {
if let Ok(path) = url.to_file_path() {
files.push(path);
}
} else {
files.push(PathBuf::from(maybe_file))
}
}
if !urls.is_empty() {
app.state::<OpenedUrls>().0.lock().unwrap().replace(urls);
}
handle_file_associations(app.handle().clone(), files);
}
let opened_urls = if let Some(urls) = &*app.state::<OpenedUrls>().0.lock().unwrap() {
urls
.iter()
.map(|u| u.as_str().replace("\\", "\\\\"))
.collect::<Vec<_>>()
.join(", ")
} else {
"".into()
};
tauri::WebviewWindowBuilder::new(app, "main", Default::default())
.initialization_script(&format!("window.openedUrls = `{opened_urls}`"))
.initialization_script(&format!("console.log(`{opened_urls}`)"))
.build()
.unwrap();
Ok(())
})
.build(tauri::generate_context!())
@ -56,16 +64,12 @@ fn main() {
|app, event| {
#[cfg(any(target_os = "macos", target_os = "ios"))]
if let tauri::RunEvent::Opened { urls } = event {
if let Some(w) = app.get_webview_window("main") {
let urls = urls
.iter()
.map(|u| u.as_str())
.collect::<Vec<_>>()
.join(",");
let _ = w.eval(&format!("window.onFileOpen(`{urls}`)"));
}
let files = urls
.into_iter()
.filter_map(|url| url.to_file_path().ok())
.collect::<Vec<_>>();
app.state::<OpenedUrls>().0.lock().unwrap().replace(urls);
handle_file_associations(app.clone(), files);
}
},
);

View File

@ -7,5 +7,28 @@
</head>
<body>
<h1>Welcome to Tauri!</h1>
<form id="form">
<input id="name" placeholder="Enter a name..." />
<button>Greet</button>
</form>
<p id="message"></p>
<script>
const { invoke } = window.__TAURI__.core
const form = document.querySelector('#form')
const nameEl = document.querySelector('#name')
const messageEl = document.querySelector('#message')
form.addEventListener('submit', async (e) => {
e.preventDefault()
const name = nameEl.value
const newMessage = await invoke('greet', { name })
messageEl.textContent = newMessage
})
</script>
</body>
</html>

View File

@ -4,8 +4,14 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello {name}, You have been greeted from Rust!")
}
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet])
.run(tauri::generate_context!(
"../../examples/helloworld/tauri.conf.json"
))

View File

@ -7,6 +7,7 @@
"frontendDist": ["index.html"]
},
"app": {
"withGlobalTauri": true,
"windows": [
{
"title": "Welcome to Tauri!",

View File

@ -1,84 +1,34 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<script>
// malicious
window.__TAURI_INTERNALS__.__TAURI_PATTERN__ = Object.freeze({pattern: "malicious"});
</script>
<script>
// malicious defineProperty
Object.defineProperty(window.__TAURI_INTERNALS__, "__TAURI_PATTERN__", {value: Object.freeze({pattern: "malicious"})});
</script>
<meta charset="UTF-8">
<title>Hello Tauri!</title>
<style>
body {
/* Add a nice color scheme to our page and text */
background-color: #222831;
color: #ececec;
/* Make the body tag the exact size of the window */
margin: 0;
height: 100vh;
width: 100vw;
/* Vertically and horizontally center children of the body tag */
display: flex;
justify-content: center;
align-items: center;
}
div {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
</style>
<script type="text/javascript">console.log("inline", window.__TAURI_INTERNALS__.__TAURI_PATTERN__);</script>
</head>
<body>
<div>
<h1>Hello, Tauri!</h1>
<pre><code></code></pre>
<div>
<button id="ping">ping</button>
<span id="pong"></span></div>
</div>
<script>
const code = document.querySelector("code");
const obj = {};
<h1>Hello, Tauri!</h1>
<div>
<button id="ping">ping</button>
<span id="pong"></span>
</div>
</div>
function updateCode(key, value) {
obj[key] = value;
code.innerText = JSON.stringify(obj, null, 2);
}
<script>
const { invoke } = window.__TAURI__.core
const cb = window.__TAURI__.tauri.transformCallback(v => updateCode('response', v));
const error = window.__TAURI__.tauri.transformCallback(e => updateCode('response', e));
window.ipc.postMessage(JSON.stringify({
cmd: "ping",
callback: cb,
error,
}));
const ping = document.querySelector("#ping")
const pong = document.querySelector('#pong')
updateCode('__TAURI_INTERNALS__.__TAURI_PATTERN__', window.__TAURI_INTERNALS__.__TAURI_PATTERN__);
</script>
<!-- set up click handlers on our ping command button -->
<script>
const ping = document.querySelector("#ping")
const pong = document.querySelector('#pong')
ping.addEventListener("click", () => {
window.__TAURI__.core.invoke("ping")
.then(() => {
pong.innerText = `ok: ${Date.now()}`
})
.catch(() => {
pong.innerText = `error: ${Date.now()}`
})
})
</script>
ping.addEventListener("click", () => {
invoke("ping")
.then(() => {
pong.innerText = `ok: ${Date.now()}`
})
.catch(() => {
pong.innerText = `error: ${Date.now()}`
})
})
</script>
</body>
</html>

View File

@ -4,19 +4,11 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use std::time::Instant;
#[tauri::command]
fn ping() {
dbg!(format!("ping: {:?}", Instant::now()));
println!("ping: {:?}", std::time::Instant::now());
}
#[cfg(not(feature = "isolation"))]
fn main() {
compile_error!("Feature `isolation` is required to run this example");
}
#[cfg(feature = "isolation")]
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![ping])

View File

@ -11,6 +11,7 @@ fn main() {
.setup(|app| {
let width = 800.;
let height = 600.;
let window = tauri::window::WindowBuilder::new(app, "main")
.inner_size(width, height)
.build()?;
@ -21,6 +22,7 @@ fn main() {
LogicalPosition::new(0., 0.),
LogicalSize::new(width / 2., height / 2.),
)?;
let _webview2 = window.add_child(
tauri::webview::WebviewBuilder::new(
"main2",
@ -30,6 +32,7 @@ fn main() {
LogicalPosition::new(width / 2., 0.),
LogicalSize::new(width / 2., height / 2.),
)?;
let _webview3 = window.add_child(
tauri::webview::WebviewBuilder::new(
"main3",
@ -39,6 +42,7 @@ fn main() {
LogicalPosition::new(0., height / 2.),
LogicalSize::new(width / 2., height / 2.),
)?;
let _webview4 = window.add_child(
tauri::webview::WebviewBuilder::new(
"main4",

View File

@ -1,88 +1,62 @@
<!doctype html>
<html>
<head>
<style>
#response {
white-space: pre-wrap;
}
</style>
</head>
<h1>Send a message to a window using its label:</h1>
<form id="send-message-form">
<input id="send-message" placeholder="message" />
<input id="send-label" placeholder="Secondary" />
<button type="submit">Send</button>
</form>
<br />
<h1>Create new window</h1>
<form id="new-window-form">
<input id="new-label" placeholder="newLabel" />
<input id="new-title" placeholder="New window" />
<button type="submit">Create</button>
</form>
<br />
<h1>Messages received from other windows:</h1>
<pre id="messages-view"></pre>
<body>
<div id="window-label"></div>
<div id="container"></div>
<div id="response"></div>
<script>
const WebviewWindow = window.__TAURI__.webviewWindow.WebviewWindow
const appWindow = window.__TAURI__.window.getCurrentWindow()
const windowLabel = appWindow.label
const windowLabelContainer = document.getElementById('window-label')
windowLabelContainer.innerText = 'This is the ' + windowLabel + ' window.'
const { WebviewWindow } = window.__TAURI__.webviewWindow
const { getCurrentWebviewWindow } = window.__TAURI__.webviewWindow
const { emitTo } = window.__TAURI__.event
const container = document.getElementById('container')
const sendMessageForm = document.querySelector('#send-message-form')
const sendMessageEl = document.querySelector('#send-message')
const sendLabelEl = document.querySelector('#send-label')
sendMessageForm.addEventListener('submit', (e) => {
e.preventDefault()
console.log(sendLabelEl.value)
console.log(sendMessageEl.value)
function createWindowMessageBtn(label) {
const button = document.createElement('button')
button.innerText = 'Send message to ' + label
button.addEventListener('click', function () {
appWindow.emitTo(label, 'clicked', 'message from ' + windowLabel)
})
container.appendChild(button)
}
// global listener
const responseContainer = document.getElementById('response')
window.__TAURI__.event.listen('clicked', function (event) {
responseContainer.innerHTML +=
'Got ' + JSON.stringify(event) + ' on global listener\n\n'
})
window.__TAURI__.event.listen(
'tauri://webview-created',
function (event) {
createWindowMessageBtn(event.payload.label)
}
)
// listener tied to this window
appWindow.listen('clicked', function (event) {
responseContainer.innerText +=
'Got ' + JSON.stringify(event) + ' on window listener\n\n'
emitTo(sendLabelEl.value, 'message', sendMessageEl.value)
})
const createWindowButton = document.createElement('button')
createWindowButton.innerHTML = 'Create window'
createWindowButton.addEventListener('click', function () {
const id = Math.random().toString().replace('.', '')
const webview = new WebviewWindow(id, {
tabbingIdentifier: windowLabel
})
webview.once('tauri://created', function () {
responseContainer.innerHTML += 'Created new window'
})
webview.once('tauri://error', function (e) {
responseContainer.innerHTML +=
'Error creating new window ' + e.payload
const newWindowForm = document.querySelector('#new-window-form')
const newLabelEl = document.querySelector('#new-label')
const newTitleEl = document.querySelector('#new-title')
newWindowForm.addEventListener('submit', (e) => {
e.preventDefault()
new WebviewWindow(newLabelEl.value, {
title: newTitleEl.value
})
})
container.appendChild(createWindowButton)
const globalMessageButton = document.createElement('button')
globalMessageButton.innerHTML = 'Send global message'
globalMessageButton.addEventListener('click', function () {
// emit to all windows
appWindow.emit('clicked', 'message from ' + windowLabel)
const currentWindow = getCurrentWebviewWindow()
const messagesView = document.querySelector('#messages-view')
window.addEventListener('DOMContentLoaded', () => {
currentWindow.listen('message', (event) => {
const time = new Date().toLocaleTimeString()
messagesView.textContent = `${messagesView.textContent}\n[${time}] ${event.payload}`
})
})
container.appendChild(globalMessageButton)
const allWindows = window.__TAURI__.window.getAllWindows()
for (const index in allWindows) {
const label = allWindows[index].label
if (label === windowLabel) {
continue
}
createWindowMessageBtn(label)
}
</script>
</body>
</html>

View File

@ -4,42 +4,32 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use tauri::{webview::PageLoadEvent, Listener, WebviewWindowBuilder};
use tauri_utils::acl::ExecutionContext;
use tauri::WebviewWindowBuilder;
fn main() {
tauri::Builder::default()
.setup(|app| {
WebviewWindowBuilder::new(app, "Third", tauri::WebviewUrl::default())
.title("Tauri - Third")
.build()?;
Ok(())
})
.run(generate_context())
.expect("failed to run tauri application");
}
fn generate_context() -> tauri::Context {
let mut context = tauri::generate_context!("../../examples/multiwindow/tauri.conf.json");
for cmd in [
"plugin:event|listen",
"plugin:event|emit",
"plugin:event|emit_to",
"plugin:webview|create_webview_window",
] {
context
.runtime_authority_mut()
.__allow_command(cmd.to_string(), ExecutionContext::Local);
.__allow_command(cmd.to_string(), tauri_utils::acl::ExecutionContext::Local);
}
tauri::Builder::default()
.on_page_load(|webview, payload| {
if payload.event() == PageLoadEvent::Finished {
let label = webview.label().to_string();
webview.listen("clicked".to_string(), move |_payload| {
println!("got 'clicked' event on window '{label}'");
});
}
})
.setup(|app| {
#[allow(unused_mut)]
let mut builder =
WebviewWindowBuilder::new(app, "Rust", tauri::WebviewUrl::App("index.html".into()));
#[cfg(target_os = "macos")]
{
builder = builder.tabbing_identifier("Rust");
}
let _webview = builder.title("Tauri - Rust").build()?;
Ok(())
})
.run(context)
.expect("failed to run tauri application");
context
}

View File

@ -1,5 +0,0 @@
# Navigation Example
A very simple Tauri Application with frontend navigation.
To execute run the following on the root directory of the repository: `cargo run --example navigation --features window-create`.

View File

@ -1,13 +0,0 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
fn main() {
tauri::Builder::default()
.run(tauri::generate_context!(
"../../examples/navigation/tauri.conf.json"
))
.expect("error while running tauri application");
}

View File

@ -1,21 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tauri</title>
</head>
<body>
<h1>index.html</h1>
<select id="route">
<option value="secondary.html">secondary.html</option>
<option value="nested/index.html">nested/index.html</option>
<option value="nested/secondary.html">nested/secondary.html</option>
</select>
<button id="open-window">New window</button>
<button id="go">Go</button>
<a id="link" href="secondary.html">Go</a>
<script src="index.js"></script>
</body>
</html>

View File

@ -1,22 +0,0 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
const WebviewWindow = window.__TAURI__.webview.WebviewWindow
const routeSelect = document.querySelector('#route')
const link = document.querySelector('#link')
routeSelect.addEventListener('change', (event) => {
link.href = event.target.value
})
document.querySelector('#go').addEventListener('click', () => {
window.location.href = window.location.origin + '/' + routeSelect.value
})
document.querySelector('#open-window').addEventListener('click', () => {
new WebviewWindow(Math.random().toString().replace('.', ''), {
url: routeSelect.value
})
})

View File

@ -1,18 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tauri</title>
</head>
<body>
<h1></h1>
<button>Back</button>
<script>
const button = document.querySelector('button')
button.addEventListener('click', () => window.history.back())
</script>
<script src="index.js"></script>
</body>
</html>

View File

@ -1,5 +0,0 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
document.querySelector('h1').innerHTML = 'nested/index.html'

View File

@ -1,18 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tauri</title>
</head>
<body>
<h1></h1>
<button>Back</button>
<script>
const button = document.querySelector('button')
button.addEventListener('click', () => window.history.back())
</script>
<script src="secondary.js"></script>
</body>
</html>

View File

@ -1,5 +0,0 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
document.querySelector('h1').innerHTML = 'nested/secondary.html'

View File

@ -1,18 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tauri</title>
</head>
<body>
<h1></h1>
<button>Back</button>
<script>
const button = document.querySelector('button')
button.addEventListener('click', () => window.history.back())
</script>
<script src="secondary.js"></script>
</body>
</html>

View File

@ -1,5 +0,0 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
document.querySelector('h1').innerHTML = 'secondary.html'

View File

@ -1,35 +0,0 @@
{
"$schema": "../../core/tauri-config-schema/schema.json",
"productName": "Navigation",
"version": "0.1.0",
"identifier": "com.tauri.dev",
"build": {
"frontendDist": "public"
},
"app": {
"withGlobalTauri": true,
"windows": [
{
"title": "Welcome to Tauri!",
"width": 800,
"height": 600,
"resizable": true,
"fullscreen": false
}
],
"security": {
"csp": "default-src 'self'; connect-src ipc: http://ipc.localhost"
}
},
"bundle": {
"active": true,
"targets": "all",
"icon": [
"../.icons/32x32.png",
"../.icons/128x128.png",
"../.icons/128x128@2x.png",
"../.icons/icon.icns",
"../.icons/icon.ico"
]
}
}

View File

@ -1,3 +0,0 @@
# Parent Window Example
Run the following at the root directory of the repository to try it out: `cargo run --example parent-window`.

View File

@ -1,57 +0,0 @@
<!doctype html>
<html>
<head>
<style>
#response {
white-space: pre-wrap;
}
</style>
</head>
<body>
<div id="window-label"></div>
<div id="container"></div>
<div id="response"></div>
<script>
const { WebviewWindow } = window.__TAURI__.webviewWindow
const thisTauriWindow = window.__TAURI__.window.getCurrentWindow()
const windowLabel = thisTauriWindow.label
const windowLabelContainer = document.getElementById('window-label')
windowLabelContainer.innerText = 'This is the ' + windowLabel + ' window.'
const container = document.getElementById('container')
const responseContainer = document.getElementById('response')
function runCommand(commandName, args, optional) {
window.__TAURI__.core
.invoke(commandName, args)
.then((response) => {
responseContainer.innerText += `Ok(${response})\n\n`
})
.catch((error) => {
responseContainer.innerText += `Err(${error})\n\n`
})
}
window.__TAURI__.event.listen('tauri://window-created', function (event) {
responseContainer.innerText += 'Got window-created event\n\n'
})
const createWindowButton = document.createElement('button')
const windowId = Math.random().toString().replace('.', '')
let windowNumber = 1
createWindowButton.innerHTML = 'Create child window ' + windowNumber
createWindowButton.addEventListener('click', function () {
new WebviewWindow(`child-${windowId}-${windowNumber}`, {
title: 'Child',
width: 400,
height: 300,
parent: thisTauriWindow
})
windowNumber += 1
createWindowButton.innerHTML = 'Create child window ' + windowNumber
})
container.appendChild(createWindowButton)
</script>
</body>
</html>

View File

@ -1,40 +0,0 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use tauri::{webview::PageLoadEvent, Listener, WebviewUrl, WebviewWindowBuilder};
use tauri_utils::acl::ExecutionContext;
fn main() {
let mut context = tauri::generate_context!("../../examples/parent-window/tauri.conf.json");
for cmd in [
"plugin:event|listen",
"plugin:webview|create_webview_window",
] {
context
.runtime_authority_mut()
.__allow_command(cmd.to_string(), ExecutionContext::Local);
}
tauri::Builder::default()
.on_page_load(|webview, payload| {
if payload.event() == PageLoadEvent::Finished {
let label = webview.label().to_string();
webview.listen("clicked".to_string(), move |_payload| {
println!("got 'clicked' event on window '{label}'");
});
}
})
.setup(|app| {
let _webview = WebviewWindowBuilder::new(app, "main", WebviewUrl::default())
.title("Main")
.inner_size(600.0, 400.0)
.build()?;
Ok(())
})
.run(context)
.expect("failed to run tauri application");
}

View File

@ -1,27 +0,0 @@
{
"$schema": "../../core/tauri-config-schema/schema.json",
"productName": "Parent Window",
"version": "0.1.0",
"identifier": "com.tauri.dev",
"build": {
"frontendDist": ["index.html"]
},
"app": {
"withGlobalTauri": true,
"security": {
"csp": "default-src 'self'; connect-src ipc: http://ipc.localhost"
}
},
"bundle": {
"active": true,
"targets": "all",
"icon": [
"../.icons/32x32.png",
"../.icons/128x128.png",
"../.icons/128x128@2x.png",
"../.icons/icon.icns",
"../.icons/icon.ico"
]
}
}

View File

@ -1 +0,0 @@
/target

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +0,0 @@
[package]
name = "tauri-plugin-example"
version = "0.1.0"
edition = "2021"
links = "tauri-plugin-example"
[build-dependencies]
tauri-plugin = { path = "../../../core/tauri-plugin", features = ["build"] }
[dependencies]
tauri-plugin = { path = "../../../core/tauri-plugin" }

View File

@ -1,9 +0,0 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
const COMMANDS: &[&str] = &[];
fn main() {
tauri_plugin::Builder::new(COMMANDS).build()
}

View File

@ -1 +0,0 @@
schemas/

View File

@ -1,22 +0,0 @@
# Permissions
## deny-home-dir-config
Denies read access to the complete $HOME folder.
## allow-home-dir
Allows read access to the complete $HOME folder.
## allow-full-homefolder-access
Allows read and write access to the complete $HOME folder.
## deny-homefolder-config-access
Denies access to the $HOME/.config folder.
## default
Default permissions granted

View File

@ -1,9 +0,0 @@
"$schema" = "schemas/schema.json"
[[permission]]
version = 1
identifier = "deny-home-dir-config"
description = "Denies read access to the complete $HOME folder."
[[permission.scope.deny]]
path = "$HOME/.config"

View File

@ -1,10 +0,0 @@
"$schema" = "schemas/schema.json"
[[permission]]
version = 1
identifier = "allow-home-dir"
description = "Allows read access to the complete $HOME folder."
commands.allow = ["readDirectory", "readFile"]
[[permission.scope.allow]]
path = "$HOME/**"

View File

@ -1,15 +0,0 @@
"$schema" = "schemas/schema.json"
[default]
description = "Default permissions granted"
permissions = ["allow-home-read-only"]
[[set]]
identifier = "allow-full-homefolder-access"
description = "Allows read and write access to the complete $HOME folder."
permissions = ["allow-home-read-only", "allow-home-write-only"]
[[set]]
identifier = "deny-homefolder-config-access"
description = "Denies access to the $HOME/.config folder."
permissions = ["deny-home-dir-config"]

View File

@ -1,18 +0,0 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
pub fn add(left: usize, right: usize) -> usize {
left + right
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
}
}

View File

@ -3,17 +3,29 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Sidecar</title>
</head>
<body>
<div></div>
<div>
<strong>Resource `assets/index.js` path:</strong>
<span id="path"></span>
</div>
<strong>Resource `assets/index.js` content:</strong>
<pre id="content"></pre>
<script>
const div = document.querySelector('div')
window.__TAURI__.event.listen('message', (event) => {
const p = document.createElement('p')
p.innerText = event.payload
div.appendChild(p)
const { invoke } = window.__TAURI__.core
const { resolveResource } = window.__TAURI__.path
const pathEl = document.querySelector('#path')
const contentEl = document.querySelector('#content')
window.addEventListener('DOMContentLoaded', async () => {
const path = await resolveResource('assets/index.js')
pathEl.textContent = path
const content = await invoke('read_to_string', { path })
contentEl.textContent = content
})
</script>
</body>

View File

@ -1,6 +1,6 @@
{
"name": "resources",
"version": "1.0.0",
"version": "0.1.0",
"scripts": {
"tauri": "node ../../tooling/cli/node/tauri.js"
}

View File

@ -1,3 +0,0 @@
# Generated by Cargo
# will have compiled files and executables
/target/

File diff suppressed because it is too large Load Diff

View File

@ -11,4 +11,4 @@ tauri-build = { path = "../../../core/tauri-build", features = ["codegen"] }
[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = [ "derive" ] }
tauri = { path = "../../../core/tauri" }
tauri = { path = "../../../core/tauri", features = [] }

View File

@ -2,6 +2,4 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
setInterval(() => {
console.log(`[${new Date().toLocaleTimeString()}] new message`)
}, 500)
console.log('hello world')

View File

@ -1 +0,0 @@
schemas/

View File

@ -1,6 +1,6 @@
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "app",
"permissions": ["core:event:default", "core:window:default"],
"permissions": ["core:path:default"],
"windows": ["main"]
}

View File

@ -4,48 +4,29 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use std::{
io::{BufRead, BufReader},
process::{Command, Stdio},
};
use tauri::{Emitter, Manager};
use tauri::Manager;
#[tauri::command]
fn read_to_string(path: &str) -> String {
std::fs::read_to_string(path).unwrap_or_default()
}
fn main() {
tauri::Builder::default()
.setup(move |app| {
let window = app.get_webview_window("main").unwrap();
let script_path = app
let path = app
.path()
.resolve("assets/index.js", tauri::path::BaseDirectory::Resource)
.unwrap()
.to_string_lossy()
.to_string();
std::thread::spawn(move || {
let mut child = Command::new("node")
.args(&[script_path])
.stdout(Stdio::piped())
.spawn()
.expect("Failed to spawn node");
let stdout = child.stdout.take().unwrap();
let mut stdout = BufReader::new(stdout);
.unwrap();
let mut line = String::new();
loop {
let n = stdout.read_line(&mut line).unwrap();
if n == 0 {
break;
}
let content = std::fs::read_to_string(&path).unwrap();
window
.emit("message", Some(format!("'{}'", line)))
.expect("failed to emit event");
line.clear();
}
});
println!("Resource `assets/index.js` path: {}", path.display());
println!("Resource `assets/index.js` content:\n{}\n", content);
Ok(())
})
.invoke_handler(tauri::generate_handler![read_to_string])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}

View File

@ -2,12 +2,12 @@
<html>
<body>
<h1>This is the main window!</h1>
<script>
const { invoke } = window.__TAURI__.core;
document.addEventListener('DOMContentLoaded', () => {
// we delay here just so we can see the splashscreen for a while
setTimeout(() => {
window.__TAURI__.core.invoke('close_splashscreen')
}, 2000)
setTimeout(() => invoke('close_splashscreen'), 2000)
})
</script>
</body>

View File

@ -4,90 +4,26 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
// Application code for a splashscreen system that waits on a Rust initialization script
mod rust {
use std::{thread::sleep, time::Duration};
use tauri::Manager;
use tauri::{AppHandle, Manager};
// this command is here just so the example doesn't throw an error
#[tauri::command]
fn close_splashscreen() {}
pub fn main() {
tauri::Builder::default()
.setup(|app| {
let splashscreen_window = app.get_webview_window("splashscreen").unwrap();
let main_window = app.get_webview_window("main").unwrap();
// we perform the initialization code on a new task so the app doesn't crash
tauri::async_runtime::spawn(async move {
println!("Initializing...");
sleep(Duration::from_secs(2));
println!("Done initializing.");
// After it's done, close the splashscreen and display the main window
splashscreen_window.close().unwrap();
main_window.show().unwrap();
});
Ok(())
})
.invoke_handler(tauri::generate_handler![close_splashscreen])
.run(super::context())
.expect("failed to run app");
}
}
// Application code for a splashscreen system that waits for the UI
mod ui {
use std::sync::{Arc, Mutex};
use tauri::{Manager, State, WebviewWindow};
// wrappers around each Window
// we use a dedicated type because Tauri can only manage a single instance of a given type
struct SplashscreenWindow(Arc<Mutex<WebviewWindow>>);
struct MainWindow(Arc<Mutex<WebviewWindow>>);
#[tauri::command]
fn close_splashscreen(
_: WebviewWindow, // force inference of P
splashscreen: State<SplashscreenWindow>,
main: State<MainWindow>,
) {
// Close splashscreen
splashscreen.0.lock().unwrap().close().unwrap();
// Show main window
main.0.lock().unwrap().show().unwrap();
}
pub fn main() {
let context = super::context();
tauri::Builder::default()
.menu(tauri::menu::Menu::default)
.setup(|app| {
// set the splashscreen and main windows to be globally available with the tauri state API
app.manage(SplashscreenWindow(Arc::new(Mutex::new(
app.get_webview_window("splashscreen").unwrap(),
))));
app.manage(MainWindow(Arc::new(Mutex::new(
app.get_webview_window("main").unwrap(),
))));
Ok(())
})
.invoke_handler(tauri::generate_handler![close_splashscreen])
.run(context)
.expect("error while running tauri application");
}
}
fn context() -> tauri::Context {
tauri::generate_context!("../../examples/splashscreen/tauri.conf.json")
#[tauri::command]
fn close_splashscreen(app: AppHandle) {
// Close splashscreen
app
.get_webview_window("splashscreen")
.unwrap()
.close()
.unwrap();
// Show main window
app.get_webview_window("main").unwrap().show().unwrap();
}
fn main() {
// toggle this flag to experiment with different splashscreen usages
let ui = false;
if ui {
ui::main();
} else {
rust::main();
}
tauri::Builder::default()
.menu(tauri::menu::Menu::default)
.invoke_handler(tauri::generate_handler![close_splashscreen])
.run(tauri::generate_context!(
"../../examples/splashscreen/tauri.conf.json"
))
.expect("error while running tauri application");
}

View File

@ -7,57 +7,42 @@
</head>
<body>
<h3>Counter</h3>
<h3>Counter: <span id="counter"></span></h3>
<div>
<button id="increment-btn">Increment counter</button>
<button id="increment-btn">Increment</button>
<button id="decrement-btn">Decrement</button>
<button id="reset-btn">Reset</button>
</div>
<h3>Database</h3>
<div>
<input id="store-input" placeholder="The value to store" />
<button id="store-btn">Store</button>
</div>
<div>
<button id="read-btn">Read</button>
</div>
<div id="response"></div>
<p>Press Ctrl+R to reload and see the state persist.</p>
<script>
const KEY = 'db-key'
const storeBtn = document.querySelector('#store-btn')
const readBtn = document.querySelector('#read-btn')
const { invoke } = window.__TAURI__.core
const incrementBtn = document.querySelector('#increment-btn')
const storeInput = document.querySelector('#store-input')
const responseContainer = document.querySelector('#response')
const decrementBtn = document.querySelector('#decrement-btn')
const resetBtn = document.querySelector('#reset-btn')
const counterContainer = document.querySelector('#counter')
function updateResponse(response) {
responseContainer.innerText =
typeof response === 'string' ? response : JSON.stringify(response)
}
incrementBtn.addEventListener('click', () => {
window.__TAURI__.core
.invoke('increment_counter')
.then(updateResponse)
.catch(updateResponse)
document.addEventListener('DOMContentLoaded', async () => {
let currentCount = await invoke('get')
counterContainer.innerText = currentCount
console.log('loaded')
})
storeBtn.addEventListener('click', () => {
window.__TAURI__.core
.invoke('db_insert', {
key: KEY,
value: storeInput.value
})
.then(updateResponse)
.catch(updateResponse)
incrementBtn.addEventListener('click', async () => {
let newCount = await invoke('increment')
counterContainer.innerText = newCount
})
readBtn.addEventListener('click', () => {
window.__TAURI__.core
.invoke('db_read', {
key: KEY
})
.then(updateResponse)
.catch(updateResponse)
decrementBtn.addEventListener('click', async () => {
let newCount = await invoke('decrement')
counterContainer.innerText = newCount
})
resetBtn.addEventListener('click', async () => {
let newCount = await invoke('reset')
counterContainer.innerText = newCount
})
</script>
</body>

View File

@ -4,80 +4,42 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use std::{
collections::HashMap,
sync::{
atomic::{AtomicUsize, Ordering},
Arc, Mutex,
},
};
use std::sync::Mutex;
use tauri::State;
struct Counter(AtomicUsize);
#[derive(Default)]
struct Database(Arc<Mutex<HashMap<String, String>>>);
struct Client;
impl Client {
fn send(&self) {}
}
#[derive(Default)]
struct Connection(Mutex<Option<Client>>);
struct Counter(Mutex<usize>);
#[tauri::command]
fn connect(connection: State<'_, Connection>) {
*connection.0.lock().unwrap() = Some(Client {});
fn increment(counter: State<'_, Counter>) -> usize {
let mut c = counter.0.lock().unwrap();
*c += 1;
*c
}
#[tauri::command]
fn disconnect(connection: State<'_, Connection>) {
// drop the connection
*connection.0.lock().unwrap() = None;
fn decrement(counter: State<'_, Counter>) -> usize {
let mut c = counter.0.lock().unwrap();
*c -= 1;
*c
}
#[tauri::command]
fn connection_send(connection: State<'_, Connection>) {
connection
.0
.lock()
.unwrap()
.as_ref()
.expect("connection not initialize; use the `connect` command first")
.send();
fn reset(counter: State<'_, Counter>) -> usize {
let mut c = counter.0.lock().unwrap();
*c = 0;
*c
}
#[tauri::command]
fn increment_counter(counter: State<'_, Counter>) -> usize {
counter.0.fetch_add(1, Ordering::Relaxed) + 1
}
#[tauri::command]
fn db_insert(key: String, value: String, db: State<'_, Database>) {
db.0.lock().unwrap().insert(key, value);
}
#[tauri::command]
fn db_read(key: String, db: State<'_, Database>) -> Option<String> {
db.0.lock().unwrap().get(&key).cloned()
fn get(counter: State<'_, Counter>) -> usize {
*counter.0.lock().unwrap()
}
fn main() {
tauri::Builder::default()
.manage(Counter(AtomicUsize::new(0)))
.manage(Database(Default::default()))
.manage(Connection(Default::default()))
.invoke_handler(tauri::generate_handler![
increment_counter,
db_insert,
db_read,
connect,
disconnect,
connection_send
])
.manage(Counter(Mutex::new(0)))
.invoke_handler(tauri::generate_handler![increment, decrement, reset, get])
.run(tauri::generate_context!(
"../../examples/state/tauri.conf.json"
))

View File

@ -1,7 +1,9 @@
# Streaming example
A simple Tauri Application showcase the streaming functionality.
A simple Tauri Application showcase how to stream video through custom protocol but can be adapted to stream any type of files.
To execute run the following on the root directory of the repository: `cargo run --example streaming`.
By default the example uses a custom URI scheme protocol. To use the builtin `asset` protocol, run `cargo run --example streaming --features protocol-asset`.
### Note
Tauri has a built-in `asset` protocol that implements this streaming functionality so you don't need to. This example just exists as a reference.

View File

@ -19,16 +19,15 @@
<video id="video_source" controls="" autoplay="" name="media">
<source type="video/mp4" />
</video>
<script>
const { invoke, convertFileSrc } = window.__TAURI__.core
const video = document.getElementById('video_source')
const source = document.createElement('source')
invoke('video_uri').then(([scheme, path]) => {
source.type = 'video/mp4'
source.src = convertFileSrc(path, scheme)
video.appendChild(source)
video.load()
})
source.type = 'video/mp4'
source.src = convertFileSrc('test_video.mp4', 'stream')
video.appendChild(source)
video.load()
</script>
</body>
</html>

View File

@ -12,64 +12,6 @@ use std::{
process::{Command, Stdio},
};
fn main() {
let video_file = PathBuf::from("test_video.mp4");
let video_url =
"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4";
if !video_file.exists() {
// Downloading with curl this saves us from adding
// a Rust HTTP client dependency.
println!("Downloading {video_url}");
let status = Command::new("curl")
.arg("-L")
.arg("-o")
.arg(&video_file)
.arg(video_url)
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.output()
.unwrap();
assert!(status.status.success());
assert!(video_file.exists());
}
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![video_uri])
.register_asynchronous_uri_scheme_protocol("stream", move |_app, request, responder| {
match get_stream_response(request) {
Ok(http_response) => responder.respond(http_response),
Err(e) => responder.respond(
ResponseBuilder::new()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.header(CONTENT_TYPE, "text/plain")
.body(e.to_string().as_bytes().to_vec())
.unwrap(),
),
}
})
.run(tauri::generate_context!(
"../../examples/streaming/tauri.conf.json"
))
.expect("error while running tauri application");
}
// returns the scheme and the path of the video file
// we're using this just to allow using the custom `stream` protocol or tauri built-in `asset` protocol
#[tauri::command]
fn video_uri() -> (&'static str, std::path::PathBuf) {
#[cfg(feature = "protocol-asset")]
{
let mut path = std::env::current_dir().unwrap();
path.push("test_video.mp4");
("asset", path)
}
#[cfg(not(feature = "protocol-asset"))]
("stream", "test_video.mp4".into())
}
fn get_stream_response(
request: http::Request<Vec<u8>>,
) -> Result<http::Response<Vec<u8>>, Box<dyn std::error::Error>> {
@ -78,8 +20,8 @@ fn get_stream_response(
.decode_utf8_lossy()
.to_string();
if path != "test_video.mp4" {
// return error 404 if it's not our video
// return error 404 if it's not our video
if path != "streaming_example_test_video.mp4" {
return Ok(ResponseBuilder::new().status(404).body(Vec::new())?);
}
@ -96,7 +38,6 @@ fn get_stream_response(
let mut resp = ResponseBuilder::new().header(CONTENT_TYPE, "video/mp4");
// if the webview sent a range header, we need to send a 206 in return
// Actually only macOS and Windows are supported. Linux will ALWAYS return empty headers.
let http_response = if let Some(range_header) = request.headers().get("range") {
let not_satisfiable = || {
ResponseBuilder::new()
@ -220,3 +161,49 @@ fn random_boundary() -> String {
a
})
}
fn download_video() {
let video_file = PathBuf::from("streaming_example_test_video.mp4");
if !video_file.exists() {
let video_url =
"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4";
// Downloading with curl this saves us from adding
// a Rust HTTP client dependency.
println!("Downloading {video_url}");
let status = Command::new("curl")
.arg("-L")
.arg("-o")
.arg(&video_file)
.arg(video_url)
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.output()
.unwrap();
assert!(status.status.success());
assert!(video_file.exists());
}
}
fn main() {
download_video();
tauri::Builder::default()
.register_asynchronous_uri_scheme_protocol("stream", move |_app, request, responder| {
match get_stream_response(request) {
Ok(http_response) => responder.respond(http_response),
Err(e) => responder.respond(
ResponseBuilder::new()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.header(CONTENT_TYPE, "text/plain")
.body(e.to_string().as_bytes().to_vec())
.unwrap(),
),
}
})
.run(tauri::generate_context!(
"../../examples/streaming/tauri.conf.json"
))
.expect("error while running tauri application");
}

View File

@ -10,15 +10,13 @@
"withGlobalTauri": true,
"windows": [
{
"title": "Welcome to Tauri!",
"title": "Stream video using custom protocol",
"width": 800,
"height": 600,
"resizable": true,
"fullscreen": false
"height": 600
}
],
"security": {
"csp": "default-src 'self'; connect-src ipc: http://ipc.localhost; media-src stream: http://stream.localhost asset: http://asset.localhost",
"csp": "default-src 'self'; connect-src ipc: http://ipc.localhost; media-src stream: http://stream.localhost",
"assetProtocol": {
"scope": ["**/test_video.mp4"]
}

View File

@ -1,8 +0,0 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example

View File

@ -1 +0,0 @@
engine-strict=true

View File

@ -1,35 +0,0 @@
# Desktop / Web Example
This example showcases an application that has shares code between a desktop and a Web target.
The Web application uses WASM to communicate with the Rust backend, while the desktop app leverages Tauri commands.
## Architecture
The Rust code lives in the `core/` folder and it is a Cargo workspace with three crates:
- tauri: desktop application. Contains the commands that are used by the frontend to access the Rust APIs;
- wasm: library that is compiled to WASM to be used by the Web application;
- api: code shared between the Tauri and the WASM crates. Most of the logic should live here, with only the specifics in the tauri and wasm crates.
The Rust code bridge is defined in the `src/api/` folder, which defines `desktop/index.js` and a `web/index.js` interfaces.
To access the proper interface according to the build target, a resolve alias is defined in vite.config.js, so the API can be imported
with `import * as api from '$api'`.
## Running the desktop application
Use the following commands to run the desktop application:
```
yarn
yarn tauri dev
```
## Running the Web application
Use the following commands to run the Web application:
```
yarn
yarn dev:web
```

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +0,0 @@
[workspace]
members = [
"api",
"tauri",
"wasm"
]
resolver = "2"
# Patching the dialog plugin to use the local copy of tauri
[patch.crates-io]
tauri = { path = "../../../core/tauri" }

View File

@ -1,6 +0,0 @@
[package]
name = "api"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@ -1,7 +0,0 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
pub fn greet(name: &str) -> String {
format!("Hello, {name}!")
}

View File

@ -1,3 +0,0 @@
# Generated by Cargo
# will have compiled files and executables
/target/

View File

@ -1,18 +0,0 @@
[package]
name = "app"
version = "0.1.0"
description = "A Tauri App"
authors = ["you"]
license = ""
repository = ""
default-run = "app"
edition = "2021"
rust-version = "1.70"
[build-dependencies]
tauri-build = { path = "../../../../core/tauri-build", features = [] }
[dependencies]
api = { path = "../api" }
tauri = { path = "../../../../core/tauri" }
tauri-plugin-dialog = "2.0.0-alpha.7"

View File

@ -1,7 +0,0 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
fn main() {
tauri_build::build()
}

View File

@ -1,25 +0,0 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use tauri_plugin_dialog::{DialogExt, MessageDialogBuilder};
#[tauri::command]
async fn greet(window: tauri::Window, name: String) -> bool {
MessageDialogBuilder::new(
window.dialog().to_owned(),
"Tauri Example",
format!("Hello {name}"),
)
.parent(&window)
.blocking_show()
}
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}

View File

@ -1,37 +0,0 @@
{
"$schema": "../../../../core/tauri-config-schema/schema.json",
"productName": "app",
"version": "0.1.0",
"identifier": "com.tauri.app",
"build": {
"beforeBuildCommand": "yarn build:tauri",
"beforeDevCommand": "yarn dev:tauri",
"devUrl": "http://localhost:5173",
"frontendDist": "../../build"
},
"app": {
"security": {
"csp": null
},
"windows": [
{
"fullscreen": false,
"height": 600,
"resizable": true,
"title": "Tauri Example",
"width": 800
}
]
},
"bundle": {
"active": true,
"targets": "all",
"icon": [
"../../../.icons/32x32.png",
"../../../.icons/128x128.png",
"../../../.icons/128x128@2x.png",
"../../../.icons/icon.icns",
"../../../.icons/icon.ico"
]
}
}

View File

@ -1,11 +0,0 @@
[package]
name = "wasm"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
api = { path = "../api" }
wasm-bindgen = "0.2"

View File

@ -1,15 +0,0 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern "C" {
pub fn alert(s: &str);
}
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&api::greet(name));
}

View File

@ -1,37 +0,0 @@
{
"name": "web",
"version": "0.0.1",
"private": true,
"scripts": {
"preinstall": "yarn wasm",
"dev:web": "yarn wasm && cross-env TARGET=web vite dev",
"build:web": "yarn wasm && cross-env TARGET=web vite build",
"preview": "vite preview",
"dev:tauri": "cross-env TARGET=tauri vite dev",
"build:tauri": "cross-env TARGET=tauri vite build",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"tauri": "node ../../tooling/cli/node/tauri.js",
"wasm": "wasm-pack build ./core/wasm --target web"
},
"dependencies": {
"@tauri-apps/api": "../../tooling/api/dist",
"wasm": "core/wasm/pkg"
},
"devDependencies": {
"@sveltejs/adapter-auto": "next",
"@sveltejs/adapter-static": "^1.0.0-next.47",
"@sveltejs/kit": "next",
"cross-env": "^7.0.3",
"svelte": "^3.44.0",
"svelte-check": "^2.7.1",
"svelte-preprocess": "^4.10.6",
"tslib": "^2.3.1",
"typescript": "^4.7.4",
"vite": "^3.1.0",
"vite-plugin-static-copy": "^0.11.1",
"vite-plugin-top-level-await": "^1.2.1",
"vite-plugin-wasm": "^3.1.0"
},
"type": "module"
}

View File

@ -1,16 +0,0 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
import { invoke } from '@tauri-apps/api/core'
export const NAME = 'Tauri'
/**
* Greets someone.
* @param {string} name
* @returns
*/
export async function greet(name) {
return invoke('greet', { name })
}

View File

@ -1,20 +0,0 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
import init, * as wasm from 'wasm'
function initialize() {
return init('wasm/wasm_bg.wasm')
}
export const NAME = 'WEB'
/**
* Greets someone.
* @param {string} name
* @returns
*/
export async function greet(name) {
return initialize().then(() => wasm.greet(name))
}

View File

@ -1,13 +0,0 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
// See https://kit.svelte.dev/docs/types#app
// for information about these interfaces
// and what to do when importing types
declare namespace App {
// interface Locals {}
// interface PageData {}
// interface Error {}
// interface Platform {}
}

View File

@ -1,12 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width" />
%sveltekit.head%
</head>
<body>
<div>%sveltekit.body%</div>
</body>
</html>

View File

@ -1,6 +0,0 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
// TODO: how can we disable SSR on Tauri but keep it on the Web target?
export const ssr = false

View File

@ -1,14 +0,0 @@
<script>
import * as api from '$api'
let name = api.NAME
function greet() {
api.greet(name)
}
</script>
<div>
<input bind:value={name} />
<button on:click={greet}>Greet</button>
</div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,27 +0,0 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
import autoAdapter from '@sveltejs/adapter-auto'
import staticAdapter from '@sveltejs/adapter-static'
import preprocess from 'svelte-preprocess'
const TARGET = process.env.TARGET
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://github.com/sveltejs/svelte-preprocess
// for more information about preprocessors
preprocess: preprocess(),
kit: {
adapter:
TARGET === 'tauri'
? staticAdapter({
fallback: 'index.html'
})
: autoAdapter()
}
}
export default config

Some files were not shown because too many files have changed in this diff Show More