mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-02-06 13:37:09 +00:00
chore: cleanup and simplify examples (#10743)
This commit is contained in:
parent
c50800023e
commit
ad83d41cb5
@ -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
6
.changes/tauri-build.md
Normal 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
108
.gitignore
vendored
@ -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
60
Cargo.lock
generated
@ -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"
|
||||
|
||||
@ -16,6 +16,10 @@ members = [
|
||||
# integration tests
|
||||
"core/tests/restart",
|
||||
"core/tests/acl",
|
||||
|
||||
# examples
|
||||
"examples/file-associations/src-tauri",
|
||||
"examples/api/src-tauri",
|
||||
]
|
||||
|
||||
exclude = [
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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"]
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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,
|
||||
|
||||
7
examples/api/.gitignore
vendored
7
examples/api/.gitignore
vendored
@ -1,5 +1,2 @@
|
||||
/node_modules/
|
||||
/.vscode/
|
||||
.DS_Store
|
||||
.cargo
|
||||
dist/
|
||||
/dist/*
|
||||
!/dist/.gitkeep
|
||||
|
||||
0
examples/api/dist/.gitkeep
vendored
Normal file
0
examples/api/dist/.gitkeep
vendored
Normal 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"
|
||||
}
|
||||
}
|
||||
|
||||
@ -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"]
|
||||
@ -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");
|
||||
}
|
||||
|
||||
@ -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)]
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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": {
|
||||
|
||||
@ -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)]
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
```
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
WixTools
|
||||
/capabilities/schemas
|
||||
1622
examples/file-associations/src-tauri/Cargo.lock
generated
1622
examples/file-associations/src-tauri/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -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" ]
|
||||
|
||||
@ -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);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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"
|
||||
))
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
"frontendDist": ["index.html"]
|
||||
},
|
||||
"app": {
|
||||
"withGlobalTauri": true,
|
||||
"windows": [
|
||||
{
|
||||
"title": "Welcome to Tauri!",
|
||||
|
||||
92
examples/isolation/dist/index.html
vendored
92
examples/isolation/dist/index.html
vendored
@ -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>
|
||||
|
||||
@ -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])
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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`.
|
||||
@ -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");
|
||||
}
|
||||
@ -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>
|
||||
@ -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
|
||||
})
|
||||
})
|
||||
@ -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>
|
||||
@ -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'
|
||||
@ -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>
|
||||
@ -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'
|
||||
@ -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>
|
||||
@ -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'
|
||||
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -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`.
|
||||
@ -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>
|
||||
@ -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");
|
||||
}
|
||||
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
/target
|
||||
3623
examples/plugins/tauri-plugin-example/Cargo.lock
generated
3623
examples/plugins/tauri-plugin-example/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -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" }
|
||||
@ -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()
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
schemas/
|
||||
@ -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
|
||||
|
||||
@ -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"
|
||||
@ -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/**"
|
||||
@ -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"]
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "resources",
|
||||
"version": "1.0.0",
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"tauri": "node ../../tooling/cli/node/tauri.js"
|
||||
}
|
||||
|
||||
3
examples/resources/src-tauri/.gitignore
vendored
3
examples/resources/src-tauri/.gitignore
vendored
@ -1,3 +0,0 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
1682
examples/resources/src-tauri/Cargo.lock
generated
1682
examples/resources/src-tauri/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -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 = [] }
|
||||
|
||||
@ -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')
|
||||
|
||||
@ -1 +0,0 @@
|
||||
schemas/
|
||||
@ -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"]
|
||||
}
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
6
examples/splashscreen/dist/index.html
vendored
6
examples/splashscreen/dist/index.html
vendored
@ -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>
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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"
|
||||
))
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
@ -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"]
|
||||
}
|
||||
|
||||
8
examples/web/.gitignore
vendored
8
examples/web/.gitignore
vendored
@ -1,8 +0,0 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/build
|
||||
/.svelte-kit
|
||||
/package
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
@ -1 +0,0 @@
|
||||
engine-strict=true
|
||||
@ -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
|
||||
```
|
||||
5048
examples/web/core/Cargo.lock
generated
5048
examples/web/core/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -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" }
|
||||
@ -1,6 +0,0 @@
|
||||
[package]
|
||||
name = "api"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
@ -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}!")
|
||||
}
|
||||
3
examples/web/core/tauri/.gitignore
vendored
3
examples/web/core/tauri/.gitignore
vendored
@ -1,3 +0,0 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
@ -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"
|
||||
@ -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()
|
||||
}
|
||||
@ -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");
|
||||
}
|
||||
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -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"
|
||||
@ -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));
|
||||
}
|
||||
@ -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"
|
||||
}
|
||||
@ -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 })
|
||||
}
|
||||
@ -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))
|
||||
}
|
||||
13
examples/web/src/app.d.ts
vendored
13
examples/web/src/app.d.ts
vendored
@ -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 {}
|
||||
}
|
||||
@ -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>
|
||||
@ -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
|
||||
@ -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 |
@ -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
Loading…
Reference in New Issue
Block a user