initial commit
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
/target
|
||||
node_modules
|
||||
src/*.mjs
|
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "tauri"]
|
||||
path = tauri
|
||||
url = https://github.com/tauri-apps/tauri
|
432
Cargo.lock
generated
Normal file
|
@ -0,0 +1,432 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "async-stream"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e"
|
||||
dependencies = [
|
||||
"async-stream-impl",
|
||||
"futures-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-stream-impl"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "console_error_panic_hook"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
|
||||
dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
|
||||
dependencies = [
|
||||
"unicode-bidi",
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.147"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-wasm-bindgen"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.147"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.87"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-sys"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"thiserror",
|
||||
"tokio-test",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-bindgen-test",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec_macros"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.21.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-stream"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-test"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53474327ae5e166530d17f2d956afcb4f8a004de581b3cae10f12006bc8163e3"
|
||||
dependencies = [
|
||||
"async-stream",
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"serde_json",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test"
|
||||
version = "0.3.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09d2fff962180c3fadf677438054b1db62bee4aa32af26a45388af07d1287e1d"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"js-sys",
|
||||
"scoped-tls",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-bindgen-test-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test-macro"
|
||||
version = "0.3.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4683da3dfc016f704c9f82cf401520c4f1cb3ee440f7f52b3d6ac29506a49ca7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
29
Cargo.toml
Normal file
|
@ -0,0 +1,29 @@
|
|||
[package]
|
||||
name = "tauri-sys"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
serde-wasm-bindgen = "0.4.3"
|
||||
js-sys = "0.3.59"
|
||||
serde = { version = "1.0.140", features = ["derive"] }
|
||||
wasm-bindgen = { version = "0.2.82", features = ["serde_json"] }
|
||||
wasm-bindgen-futures = "0.4.32"
|
||||
url = { version = "2.3.1", optional = true }
|
||||
thiserror = "1.0.37"
|
||||
semver = { version = "1.0.14", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
tokio-test = "0.4.2"
|
||||
wasm-bindgen-test = "0.3.33"
|
||||
|
||||
[features]
|
||||
default = ["all"]
|
||||
all = ["app", "clipboard", "event", "mocks", "tauri"]
|
||||
app = ["dep:semver"]
|
||||
clipboard = []
|
||||
event = []
|
||||
mocks = []
|
||||
tauri = ["dep:url"]
|
72
README.md
Normal file
|
@ -0,0 +1,72 @@
|
|||
# tauri-sys
|
||||
|
||||
Bindings to the [Tauri API] for projects using [wasm-bindgen]
|
||||
|
||||
## Installation
|
||||
|
||||
This crate is not yet published to crates.io, so you need to use it from git.
|
||||
You also need a global installation of [`esbuild`].
|
||||
|
||||
```toml
|
||||
tauri-sys = { git = "https://github.com/JonasKruckenberg/tauri-sys" }
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```rust
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tauri_sys::tauri;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct GreetArgs<'a> {
|
||||
name: &'a str,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
wasm_bindgen_futures::spawn_local(async move {
|
||||
let new_msg: String = tauri::invoke("greet", &GreetArgs { name: &name.get() }).await.unwrap();
|
||||
|
||||
println!("{}", new_msg);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
All modules are gated by accordingly named Cargo features. It is recommended you keep this synced with the features enabled in your [Tauri Allowlist] but no automated tool for this exists (yet).
|
||||
|
||||
- **all**: Enables all modules.
|
||||
- **app**: Enables the `app` module.
|
||||
- **clipboard**: Enables the `clipboard` module.
|
||||
- **event**: Enables the `event` module.
|
||||
- **mocks**: Enables the `mocks` module.
|
||||
- **tauri**: Enables the `tauri` module.
|
||||
|
||||
## Are we Tauri yet?
|
||||
|
||||
These API bindings are not completely on-par with `@tauri-apps/api` yet, but here is the current status-quo:
|
||||
|
||||
- [x] `app`
|
||||
- [ ] `cli`
|
||||
- [x] `clipboard`
|
||||
- [ ] `dialog`
|
||||
- [x] `event`
|
||||
- [ ] `fs`
|
||||
- [ ] `global_shortcut`
|
||||
- [ ] `http`
|
||||
- [x] `mocks`
|
||||
- [ ] `notification`
|
||||
- [ ] `os`
|
||||
- [ ] `path`
|
||||
- [ ] `process`
|
||||
- [ ] `shell`
|
||||
- [x] `tauri`
|
||||
- [ ] `updater`
|
||||
- [ ] `window`
|
||||
|
||||
The current API also very closely mirrors the JS API even though that might not be the most ergonomic choice, ideas for improving the API with quality-of-life features beyond the regular JS API interface are very welcome.
|
||||
|
||||
[Tauri API]: https://tauri.app/v1/api/js/
|
||||
[wasm-bindgen]: https://github.com/rustwasm/wasm-bindgen
|
||||
[Tauri Allowlist]: https://tauri.app/v1/api/config#allowlistconfig
|
||||
[`esbuild`]: https://esbuild.github.io/getting-started/#install-esbuild
|
17
build.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
use std::process::Command;
|
||||
|
||||
fn main() {
|
||||
Command::new("esbuild")
|
||||
.args([
|
||||
"--outdir=dist",
|
||||
"--format=esm",
|
||||
"--bundle",
|
||||
"tauri/tooling/api/src/app.ts",
|
||||
"tauri/tooling/api/src/clipboard.ts",
|
||||
"tauri/tooling/api/src/tauri.ts",
|
||||
"tauri/tooling/api/src/event.ts",
|
||||
"tauri/tooling/api/src/mocks.ts"
|
||||
])
|
||||
.output()
|
||||
.unwrap();
|
||||
}
|
91
dist/app.js
vendored
Normal file
|
@ -0,0 +1,91 @@
|
|||
// tauri/tooling/api/src/tauri.ts
|
||||
function uid() {
|
||||
return window.crypto.getRandomValues(new Uint32Array(1))[0];
|
||||
}
|
||||
function transformCallback(callback, once = false) {
|
||||
const identifier = uid();
|
||||
const prop = `_${identifier}`;
|
||||
Object.defineProperty(window, prop, {
|
||||
value: (result) => {
|
||||
if (once) {
|
||||
Reflect.deleteProperty(window, prop);
|
||||
}
|
||||
return callback?.(result);
|
||||
},
|
||||
writable: false,
|
||||
configurable: true
|
||||
});
|
||||
return identifier;
|
||||
}
|
||||
async function invoke(cmd, args = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const callback = transformCallback((e) => {
|
||||
resolve(e);
|
||||
Reflect.deleteProperty(window, `_${error}`);
|
||||
}, true);
|
||||
const error = transformCallback((e) => {
|
||||
reject(e);
|
||||
Reflect.deleteProperty(window, `_${callback}`);
|
||||
}, true);
|
||||
window.__TAURI_IPC__({
|
||||
cmd,
|
||||
callback,
|
||||
error,
|
||||
...args
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// tauri/tooling/api/src/helpers/tauri.ts
|
||||
async function invokeTauriCommand(command) {
|
||||
return invoke("tauri", command);
|
||||
}
|
||||
|
||||
// tauri/tooling/api/src/app.ts
|
||||
async function getVersion() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "App",
|
||||
message: {
|
||||
cmd: "getAppVersion"
|
||||
}
|
||||
});
|
||||
}
|
||||
async function getName() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "App",
|
||||
message: {
|
||||
cmd: "getAppName"
|
||||
}
|
||||
});
|
||||
}
|
||||
async function getTauriVersion() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "App",
|
||||
message: {
|
||||
cmd: "getTauriVersion"
|
||||
}
|
||||
});
|
||||
}
|
||||
async function show() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "App",
|
||||
message: {
|
||||
cmd: "show"
|
||||
}
|
||||
});
|
||||
}
|
||||
async function hide() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "App",
|
||||
message: {
|
||||
cmd: "hide"
|
||||
}
|
||||
});
|
||||
}
|
||||
export {
|
||||
getName,
|
||||
getTauriVersion,
|
||||
getVersion,
|
||||
hide,
|
||||
show
|
||||
};
|
66
dist/clipboard.js
vendored
Normal file
|
@ -0,0 +1,66 @@
|
|||
// tauri/tooling/api/src/tauri.ts
|
||||
function uid() {
|
||||
return window.crypto.getRandomValues(new Uint32Array(1))[0];
|
||||
}
|
||||
function transformCallback(callback, once = false) {
|
||||
const identifier = uid();
|
||||
const prop = `_${identifier}`;
|
||||
Object.defineProperty(window, prop, {
|
||||
value: (result) => {
|
||||
if (once) {
|
||||
Reflect.deleteProperty(window, prop);
|
||||
}
|
||||
return callback?.(result);
|
||||
},
|
||||
writable: false,
|
||||
configurable: true
|
||||
});
|
||||
return identifier;
|
||||
}
|
||||
async function invoke(cmd, args = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const callback = transformCallback((e) => {
|
||||
resolve(e);
|
||||
Reflect.deleteProperty(window, `_${error}`);
|
||||
}, true);
|
||||
const error = transformCallback((e) => {
|
||||
reject(e);
|
||||
Reflect.deleteProperty(window, `_${callback}`);
|
||||
}, true);
|
||||
window.__TAURI_IPC__({
|
||||
cmd,
|
||||
callback,
|
||||
error,
|
||||
...args
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// tauri/tooling/api/src/helpers/tauri.ts
|
||||
async function invokeTauriCommand(command) {
|
||||
return invoke("tauri", command);
|
||||
}
|
||||
|
||||
// tauri/tooling/api/src/clipboard.ts
|
||||
async function writeText(text) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Clipboard",
|
||||
message: {
|
||||
cmd: "writeText",
|
||||
data: text
|
||||
}
|
||||
});
|
||||
}
|
||||
async function readText() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Clipboard",
|
||||
message: {
|
||||
cmd: "readText",
|
||||
data: null
|
||||
}
|
||||
});
|
||||
}
|
||||
export {
|
||||
readText,
|
||||
writeText
|
||||
};
|
123
dist/event.js
vendored
Normal file
|
@ -0,0 +1,123 @@
|
|||
// tauri/tooling/api/src/tauri.ts
|
||||
function uid() {
|
||||
return window.crypto.getRandomValues(new Uint32Array(1))[0];
|
||||
}
|
||||
function transformCallback(callback, once3 = false) {
|
||||
const identifier = uid();
|
||||
const prop = `_${identifier}`;
|
||||
Object.defineProperty(window, prop, {
|
||||
value: (result) => {
|
||||
if (once3) {
|
||||
Reflect.deleteProperty(window, prop);
|
||||
}
|
||||
return callback?.(result);
|
||||
},
|
||||
writable: false,
|
||||
configurable: true
|
||||
});
|
||||
return identifier;
|
||||
}
|
||||
async function invoke(cmd, args = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const callback = transformCallback((e) => {
|
||||
resolve(e);
|
||||
Reflect.deleteProperty(window, `_${error}`);
|
||||
}, true);
|
||||
const error = transformCallback((e) => {
|
||||
reject(e);
|
||||
Reflect.deleteProperty(window, `_${callback}`);
|
||||
}, true);
|
||||
window.__TAURI_IPC__({
|
||||
cmd,
|
||||
callback,
|
||||
error,
|
||||
...args
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// tauri/tooling/api/src/helpers/tauri.ts
|
||||
async function invokeTauriCommand(command) {
|
||||
return invoke("tauri", command);
|
||||
}
|
||||
|
||||
// tauri/tooling/api/src/helpers/event.ts
|
||||
async function _unlisten(event, eventId) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Event",
|
||||
message: {
|
||||
cmd: "unlisten",
|
||||
event,
|
||||
eventId
|
||||
}
|
||||
});
|
||||
}
|
||||
async function emit(event, windowLabel, payload) {
|
||||
await invokeTauriCommand({
|
||||
__tauriModule: "Event",
|
||||
message: {
|
||||
cmd: "emit",
|
||||
event,
|
||||
windowLabel,
|
||||
payload
|
||||
}
|
||||
});
|
||||
}
|
||||
async function listen(event, windowLabel, handler) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Event",
|
||||
message: {
|
||||
cmd: "listen",
|
||||
event,
|
||||
windowLabel,
|
||||
handler: transformCallback(handler)
|
||||
}
|
||||
}).then((eventId) => {
|
||||
return async () => _unlisten(event, eventId);
|
||||
});
|
||||
}
|
||||
async function once(event, windowLabel, handler) {
|
||||
return listen(event, windowLabel, (eventData) => {
|
||||
handler(eventData);
|
||||
_unlisten(event, eventData.id).catch(() => {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// tauri/tooling/api/src/event.ts
|
||||
var TauriEvent = /* @__PURE__ */ ((TauriEvent2) => {
|
||||
TauriEvent2["WINDOW_RESIZED"] = "tauri://resize";
|
||||
TauriEvent2["WINDOW_MOVED"] = "tauri://move";
|
||||
TauriEvent2["WINDOW_CLOSE_REQUESTED"] = "tauri://close-requested";
|
||||
TauriEvent2["WINDOW_CREATED"] = "tauri://window-created";
|
||||
TauriEvent2["WINDOW_DESTROYED"] = "tauri://destroyed";
|
||||
TauriEvent2["WINDOW_FOCUS"] = "tauri://focus";
|
||||
TauriEvent2["WINDOW_BLUR"] = "tauri://blur";
|
||||
TauriEvent2["WINDOW_SCALE_FACTOR_CHANGED"] = "tauri://scale-change";
|
||||
TauriEvent2["WINDOW_THEME_CHANGED"] = "tauri://theme-changed";
|
||||
TauriEvent2["WINDOW_FILE_DROP"] = "tauri://file-drop";
|
||||
TauriEvent2["WINDOW_FILE_DROP_HOVER"] = "tauri://file-drop-hover";
|
||||
TauriEvent2["WINDOW_FILE_DROP_CANCELLED"] = "tauri://file-drop-cancelled";
|
||||
TauriEvent2["MENU"] = "tauri://menu";
|
||||
TauriEvent2["CHECK_UPDATE"] = "tauri://update";
|
||||
TauriEvent2["UPDATE_AVAILABLE"] = "tauri://update-available";
|
||||
TauriEvent2["INSTALL_UPDATE"] = "tauri://update-install";
|
||||
TauriEvent2["STATUS_UPDATE"] = "tauri://update-status";
|
||||
TauriEvent2["DOWNLOAD_PROGRESS"] = "tauri://update-download-progress";
|
||||
return TauriEvent2;
|
||||
})(TauriEvent || {});
|
||||
async function listen2(event, handler) {
|
||||
return listen(event, null, handler);
|
||||
}
|
||||
async function once2(event, handler) {
|
||||
return once(event, null, handler);
|
||||
}
|
||||
async function emit2(event, payload) {
|
||||
return emit(event, void 0, payload);
|
||||
}
|
||||
export {
|
||||
TauriEvent,
|
||||
emit2 as emit,
|
||||
listen2 as listen,
|
||||
once2 as once
|
||||
};
|
30
dist/mocks.js
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
// tauri/tooling/api/src/mocks.ts
|
||||
function mockIPC(cb) {
|
||||
window.__TAURI_IPC__ = async ({
|
||||
cmd,
|
||||
callback,
|
||||
error,
|
||||
...args
|
||||
}) => {
|
||||
try {
|
||||
window[`_${callback}`](await cb(cmd, args));
|
||||
} catch (err) {
|
||||
window[`_${error}`](err);
|
||||
}
|
||||
};
|
||||
}
|
||||
function mockWindows(current, ...additionalWindows) {
|
||||
window.__TAURI_METADATA__ = {
|
||||
__windows: [current, ...additionalWindows].map((label) => ({ label })),
|
||||
__currentWindow: { label: current }
|
||||
};
|
||||
}
|
||||
function clearMocks() {
|
||||
delete window.__TAURI_IPC__;
|
||||
delete window.__TAURI_METADATA__;
|
||||
}
|
||||
export {
|
||||
clearMocks,
|
||||
mockIPC,
|
||||
mockWindows
|
||||
};
|
46
dist/tauri.js
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
// tauri/tooling/api/src/tauri.ts
|
||||
function uid() {
|
||||
return window.crypto.getRandomValues(new Uint32Array(1))[0];
|
||||
}
|
||||
function transformCallback(callback, once = false) {
|
||||
const identifier = uid();
|
||||
const prop = `_${identifier}`;
|
||||
Object.defineProperty(window, prop, {
|
||||
value: (result) => {
|
||||
if (once) {
|
||||
Reflect.deleteProperty(window, prop);
|
||||
}
|
||||
return callback?.(result);
|
||||
},
|
||||
writable: false,
|
||||
configurable: true
|
||||
});
|
||||
return identifier;
|
||||
}
|
||||
async function invoke(cmd, args = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const callback = transformCallback((e) => {
|
||||
resolve(e);
|
||||
Reflect.deleteProperty(window, `_${error}`);
|
||||
}, true);
|
||||
const error = transformCallback((e) => {
|
||||
reject(e);
|
||||
Reflect.deleteProperty(window, `_${callback}`);
|
||||
}, true);
|
||||
window.__TAURI_IPC__({
|
||||
cmd,
|
||||
callback,
|
||||
error,
|
||||
...args
|
||||
});
|
||||
});
|
||||
}
|
||||
function convertFileSrc(filePath, protocol = "asset") {
|
||||
const path = encodeURIComponent(filePath);
|
||||
return navigator.userAgent.includes("Windows") ? `https://${protocol}.localhost/${path}` : `${protocol}://localhost/${path}`;
|
||||
}
|
||||
export {
|
||||
convertFileSrc,
|
||||
invoke,
|
||||
transformCallback
|
||||
};
|
3
examples/api/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
/dist/
|
||||
/target/
|
||||
/Cargo.lock
|
3
examples/api/.taurignore
Normal file
|
@ -0,0 +1,3 @@
|
|||
/src
|
||||
/public
|
||||
/Cargo.toml
|
21
examples/api/Cargo.toml
Normal file
|
@ -0,0 +1,21 @@
|
|||
[package]
|
||||
name = "tauri-app-ui"
|
||||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[dependencies]
|
||||
tauri-sys = { path = "../../" }
|
||||
serde = { version = "1.0.140", features = ["derive"] }
|
||||
sycamore = { git = "https://github.com/sycamore-rs/sycamore", rev = "abd556cbc02047042dad2ebd04405e455a9b11b2", features = ["suspense", "hydrate"] }
|
||||
sycamore-router = { git = "https://github.com/sycamore-rs/sycamore", rev = "abd556cbc02047042dad2ebd04405e455a9b11b2" }
|
||||
log = "0.4.17"
|
||||
wasm-logger = "0.2.0"
|
||||
gloo-timers = "0.2.4"
|
||||
shared = { path = "shared" }
|
||||
|
||||
[features]
|
||||
ssg = ["sycamore/ssr"]
|
||||
|
||||
[workspace]
|
||||
members = ["src-tauri", "shared"]
|
16
examples/api/Trunk.toml
Normal file
|
@ -0,0 +1,16 @@
|
|||
[build]
|
||||
target = "./index.html"
|
||||
|
||||
[watch]
|
||||
ignore = ["./src-tauri"]
|
||||
|
||||
[serve]
|
||||
address = "127.0.0.1"
|
||||
port = 1420
|
||||
open = false
|
||||
|
||||
[[hooks]]
|
||||
# Runs SSG on production builds
|
||||
stage = "post_build"
|
||||
command = "bash"
|
||||
command_arguments = ["-c", "if [[ $TRUNK_PROFILE == \"release\" ]]; then cargo run --release --features ssg -- $TRUNK_STAGING_DIR; fi"]
|
12
examples/api/index.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Tauri + Yew App</title>
|
||||
<link data-trunk rel="css" href="style.css" />
|
||||
<link data-trunk rel="copy-dir" href="public" />
|
||||
</head>
|
||||
<body>
|
||||
<!--app-html-->
|
||||
</body>
|
||||
</html>
|
BIN
examples/api/public/tauri_logo.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
9
examples/api/shared/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "shared"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0.140", features = ["derive"] }
|
12
examples/api/shared/src/lib.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Reply<'a> {
|
||||
pub data: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct RequestBody<'a> {
|
||||
pub id: i32,
|
||||
pub name: &'a str,
|
||||
}
|
4
examples/api/src-tauri/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
|
28
examples/api/src-tauri/Cargo.toml
Normal file
|
@ -0,0 +1,28 @@
|
|||
[package]
|
||||
name = "tauri-app"
|
||||
version = "0.0.0"
|
||||
description = "A Tauri App"
|
||||
authors = ["you"]
|
||||
license = ""
|
||||
repository = ""
|
||||
edition = "2021"
|
||||
rust-version = "1.57"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { git = "https://github.com/tauri-apps/tauri", features = [] }
|
||||
|
||||
[dependencies]
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tauri = { git = "https://github.com/tauri-apps/tauri", features = ["api-all"] }
|
||||
shared = { path = "../shared" }
|
||||
|
||||
[features]
|
||||
# by default Tauri runs in production mode
|
||||
# when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL
|
||||
default = [ "custom-protocol" ]
|
||||
# this feature is used used for production builds where `devPath` points to the filesystem
|
||||
# DO NOT remove this
|
||||
custom-protocol = [ "tauri/custom-protocol" ]
|
3
examples/api/src-tauri/build.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
fn main() {
|
||||
tauri_build::build()
|
||||
}
|
BIN
examples/api/src-tauri/icons/128x128.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
examples/api/src-tauri/icons/128x128@2x.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
examples/api/src-tauri/icons/32x32.png
Normal file
After Width: | Height: | Size: 974 B |
BIN
examples/api/src-tauri/icons/Square107x107Logo.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
examples/api/src-tauri/icons/Square142x142Logo.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
examples/api/src-tauri/icons/Square150x150Logo.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
examples/api/src-tauri/icons/Square284x284Logo.png
Normal file
After Width: | Height: | Size: 7.6 KiB |
BIN
examples/api/src-tauri/icons/Square30x30Logo.png
Normal file
After Width: | Height: | Size: 903 B |
BIN
examples/api/src-tauri/icons/Square310x310Logo.png
Normal file
After Width: | Height: | Size: 8.4 KiB |
BIN
examples/api/src-tauri/icons/Square44x44Logo.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
examples/api/src-tauri/icons/Square71x71Logo.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
examples/api/src-tauri/icons/Square89x89Logo.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
examples/api/src-tauri/icons/StoreLogo.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
examples/api/src-tauri/icons/icon.icns
Normal file
BIN
examples/api/src-tauri/icons/icon.ico
Normal file
After Width: | Height: | Size: 85 KiB |
BIN
examples/api/src-tauri/icons/icon.png
Normal file
After Width: | Height: | Size: 14 KiB |
38
examples/api/src-tauri/src/main.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
#![cfg_attr(
|
||||
all(not(debug_assertions), target_os = "windows"),
|
||||
windows_subsystem = "windows"
|
||||
)]
|
||||
|
||||
use serde::Deserialize;
|
||||
use shared::{Reply, RequestBody};
|
||||
|
||||
#[tauri::command]
|
||||
fn log_operation(event: String, payload: Option<String>) {
|
||||
println!("{} {:?}", event, payload);
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn perform_request(endpoint: String, body: RequestBody) -> String {
|
||||
println!("{} {:?}", endpoint, body);
|
||||
"message response".into()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tauri::Builder::default()
|
||||
.invoke_handler(tauri::generate_handler![log_operation, perform_request])
|
||||
.on_page_load(|window, _| {
|
||||
let window_ = window.clone();
|
||||
window.listen("js-event", move |event| {
|
||||
println!("got js-event with message '{:?}'", event.payload());
|
||||
let reply = Reply {
|
||||
data: "something else",
|
||||
};
|
||||
|
||||
window_
|
||||
.emit("rust-event", Some(reply))
|
||||
.expect("failed to emit");
|
||||
});
|
||||
})
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
66
examples/api/src-tauri/tauri.conf.json
Normal file
|
@ -0,0 +1,66 @@
|
|||
{
|
||||
"build": {
|
||||
"beforeDevCommand": "trunk serve",
|
||||
"beforeBuildCommand": "trunk build --release",
|
||||
"devPath": "http://localhost:1420",
|
||||
"distDir": "../dist",
|
||||
"withGlobalTauri": true
|
||||
},
|
||||
"package": {
|
||||
"productName": "tauri-app",
|
||||
"version": "0.0.0"
|
||||
},
|
||||
"tauri": {
|
||||
"allowlist": {
|
||||
"all": true
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"category": "DeveloperTool",
|
||||
"copyright": "",
|
||||
"deb": {
|
||||
"depends": []
|
||||
},
|
||||
"externalBin": [],
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
],
|
||||
"identifier": "com.tauri.dev",
|
||||
"longDescription": "",
|
||||
"macOS": {
|
||||
"entitlements": null,
|
||||
"exceptionDomain": "",
|
||||
"frameworks": [],
|
||||
"providerShortName": null,
|
||||
"signingIdentity": null
|
||||
},
|
||||
"resources": [],
|
||||
"shortDescription": "",
|
||||
"targets": "all",
|
||||
"windows": {
|
||||
"certificateThumbprint": null,
|
||||
"digestAlgorithm": "sha256",
|
||||
"timestampUrl": ""
|
||||
}
|
||||
},
|
||||
"security": {
|
||||
"csp": null
|
||||
},
|
||||
"updater": {
|
||||
"active": false
|
||||
},
|
||||
"windows": [
|
||||
{
|
||||
"fullscreen": false,
|
||||
"height": 600,
|
||||
"resizable": true,
|
||||
"title": "tauri-app",
|
||||
"width": 800
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
79
examples/api/src/main.rs
Normal file
|
@ -0,0 +1,79 @@
|
|||
mod views;
|
||||
|
||||
use sycamore::prelude::*;
|
||||
#[cfg(not(feature = "ssg"))]
|
||||
use sycamore_router::{Router, HistoryIntegration};
|
||||
|
||||
#[component]
|
||||
fn Header<G: Html>(cx: Scope) -> View<G> {
|
||||
view! { cx,
|
||||
header(style="display: flex; gap: 1em; margin-bottom: 1em;") {
|
||||
a(href="/") {
|
||||
"Welcome"
|
||||
}
|
||||
a(href="/app") {
|
||||
"App"
|
||||
}
|
||||
a(href="/clipboard") {
|
||||
"Clipboard"
|
||||
}
|
||||
a(href="/communication") {
|
||||
"Communication"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(not(debug_assertions), not(feature = "ssg")))]
|
||||
fn main() {
|
||||
wasm_logger::init(wasm_logger::Config::default());
|
||||
|
||||
sycamore::hydrate(|cx| view! { cx,
|
||||
Header
|
||||
Router(
|
||||
integration=HistoryIntegration::new(),
|
||||
view=views::switch
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(all(debug_assertions, not(feature = "ssg")))]
|
||||
fn main() {
|
||||
use sycamore::view;
|
||||
|
||||
wasm_logger::init(wasm_logger::Config::default());
|
||||
|
||||
sycamore::render(|cx| view! { cx,
|
||||
Header
|
||||
Router(
|
||||
integration=HistoryIntegration::new(),
|
||||
view=views::switch
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(feature = "ssg")]
|
||||
fn main() {
|
||||
use sycamore_router::StaticRouter;
|
||||
|
||||
let out_dir = std::env::args().nth(1).unwrap();
|
||||
|
||||
println!("out_dir {}", out_dir);
|
||||
|
||||
let template = std::fs::read_to_string(format!("{}/index.html", out_dir)).unwrap();
|
||||
|
||||
let html = sycamore::render_to_string(|cx| view! { cx,
|
||||
Header
|
||||
StaticRouter(
|
||||
route=route.clone(),
|
||||
view=views::switch
|
||||
)
|
||||
});
|
||||
|
||||
let html = template.replace("<!--app-html-->\n", &html);
|
||||
|
||||
let path = format!("{}/index.html", out_dir);
|
||||
|
||||
println!("Writing html to file \"{}\"", path);
|
||||
std::fs::write(path, html).unwrap();
|
||||
}
|
78
examples/api/src/views/app.rs
Normal file
|
@ -0,0 +1,78 @@
|
|||
use gloo_timers::callback::Timeout;
|
||||
use sycamore::prelude::*;
|
||||
use tauri_api::app;
|
||||
|
||||
#[component]
|
||||
pub fn App<G: Html>(cx: Scope) -> View<G> {
|
||||
let show_app = |_| {
|
||||
sycamore::futures::spawn_local(async move {
|
||||
let res = app::hide().await;
|
||||
|
||||
log::debug!("app hide res {:?}", res);
|
||||
|
||||
let timeout = Timeout::new(2_000, move || {
|
||||
sycamore::futures::spawn_local(async move {
|
||||
let res = app::show().await;
|
||||
|
||||
log::debug!("app show res {:?}", res);
|
||||
});
|
||||
});
|
||||
|
||||
timeout.forget();
|
||||
});
|
||||
};
|
||||
|
||||
let hide_app = |_| {
|
||||
sycamore::futures::spawn_local(async move {
|
||||
let res = app::hide().await;
|
||||
|
||||
log::debug!("app hide res {:?}", res);
|
||||
});
|
||||
};
|
||||
|
||||
let get_name = |_| {
|
||||
sycamore::futures::spawn_local(async move {
|
||||
let res = app::get_name().await;
|
||||
|
||||
log::debug!("app name {:?}", res);
|
||||
});
|
||||
};
|
||||
|
||||
let get_version = |_| {
|
||||
sycamore::futures::spawn_local(async move {
|
||||
let res = app::get_version().await;
|
||||
|
||||
log::debug!("app version {:?}", res);
|
||||
});
|
||||
};
|
||||
|
||||
let get_tauri_version = |_| {
|
||||
sycamore::futures::spawn_local(async move {
|
||||
let res = app::get_tauri_version().await;
|
||||
|
||||
log::debug!("tauri version {:?}", res);
|
||||
});
|
||||
};
|
||||
|
||||
view! { cx,
|
||||
div {
|
||||
button(class="btn",id="get_name",on:click=get_name) {
|
||||
"Get App Name"
|
||||
}
|
||||
button(class="btn",id="get_version",on:click=get_version) {
|
||||
"Get App Version"
|
||||
}
|
||||
button(class="btn",id="get_tauri_version",on:click=get_tauri_version) {
|
||||
"Get Tauri Version"
|
||||
}
|
||||
}
|
||||
div {
|
||||
button(class="btn",id="show",title="Hides and shows the app after 2 seconds",on:click=show_app) {
|
||||
"Show"
|
||||
}
|
||||
button(class="btn",id="hide",on:click=hide_app) {
|
||||
"Hide"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
42
examples/api/src/views/clipboard.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
use sycamore::prelude::*;
|
||||
use tauri_api::clipboard::{read_text, write_text};
|
||||
|
||||
#[component]
|
||||
pub fn Clipboard<G: Html>(cx: Scope) -> View<G> {
|
||||
let text = create_signal(cx, "clipboard message".to_string());
|
||||
|
||||
let write = move |_| {
|
||||
sycamore::futures::spawn_local_scoped(cx, async move {
|
||||
write_text(&text.get()).await
|
||||
// .then(() => {
|
||||
// onMessage('Wrote to the clipboard')
|
||||
// })
|
||||
// .catch(onMessage)
|
||||
});
|
||||
};
|
||||
|
||||
let read = |_| {
|
||||
sycamore::futures::spawn_local(async move {
|
||||
let text = read_text().await;
|
||||
|
||||
log::info!("Read text from clipboard {:?}", text);
|
||||
// readText()
|
||||
// .then((contents) => {
|
||||
// onMessage(`Clipboard contents: ${contents}`)
|
||||
// })
|
||||
// .catch(onMessage)
|
||||
});
|
||||
};
|
||||
|
||||
view! { cx,
|
||||
div(class="flex gap-1") {
|
||||
input(class="grow input",placeholder="Text to write to the clipboard",bind:value=text)
|
||||
button(class="btn",type="button",on:click=write) {
|
||||
"Write"
|
||||
}
|
||||
button(class="btn",type="button",on:click=read) {
|
||||
"Read"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
90
examples/api/src/views/communication.rs
Normal file
|
@ -0,0 +1,90 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use sycamore::prelude::*;
|
||||
use tauri_api::event::{emit, listen};
|
||||
use tauri_api::tauri::invoke;
|
||||
use shared::RequestBody;
|
||||
|
||||
#[component]
|
||||
pub fn Communication<'a, G: Html>(cx: Scope<'a>) -> View<G> {
|
||||
let unlisten = create_signal::<Option<Box<&dyn FnOnce()>>>(cx, None);
|
||||
|
||||
// on_mount(cx, move || {
|
||||
|
||||
// sycamore::futures::spawn_local_scoped(cx, async move {
|
||||
// let unlisten_raw = listen::<Reply>("rust-event", &|reply| log::debug!("got reply {:?}", reply)).await;
|
||||
|
||||
// unlisten.set(Some(Box::new(&unlisten_raw)));
|
||||
// });
|
||||
// });
|
||||
|
||||
// on_cleanup(cx, || {
|
||||
// if let Some(unlisten) = unlisten .take().as_deref() {
|
||||
// (unlisten)()
|
||||
// }
|
||||
// });
|
||||
|
||||
let log = |_| {
|
||||
#[derive(Serialize)]
|
||||
struct Payload<'a> {
|
||||
event: &'a str,
|
||||
payload: &'a str,
|
||||
}
|
||||
|
||||
sycamore::futures::spawn_local(async move {
|
||||
let res = invoke::<_, ()>(
|
||||
"log_operation",
|
||||
&Payload {
|
||||
event: "tauri-click",
|
||||
payload: "this payload is optional because we used Option in Rust",
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
log::debug!("Emitted event, response {:?}", res);
|
||||
});
|
||||
};
|
||||
|
||||
let perform_request = |_| {
|
||||
sycamore::futures::spawn_local(async move {
|
||||
#[derive(Serialize)]
|
||||
struct Payload<'a> {
|
||||
endpoint: &'a str,
|
||||
body: RequestBody<'a>
|
||||
}
|
||||
|
||||
let res = invoke::<_, String>(
|
||||
"perform_request",
|
||||
&Payload {
|
||||
endpoint: "dummy endpoint arg",
|
||||
body: RequestBody {
|
||||
id: 5,
|
||||
name: "test",
|
||||
},
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
log::debug!("Got reply {:?}", res);
|
||||
});
|
||||
};
|
||||
|
||||
let emit_event = |_| {
|
||||
sycamore::futures::spawn_local(async move {
|
||||
emit("js-event", &"this is the payload string").await;
|
||||
});
|
||||
};
|
||||
|
||||
view! { cx,
|
||||
div {
|
||||
button(class="btn",id="log",on:click=log) {
|
||||
"Call Log API"
|
||||
}
|
||||
button(class="btn",mid="request",on:click=perform_request) {
|
||||
"Call Request (async) API"
|
||||
}
|
||||
button(class="btn",id="event",on:click=emit_event) {
|
||||
"Send event to Rust"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
29
examples/api/src/views/mod.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
mod app;
|
||||
mod clipboard;
|
||||
mod communication;
|
||||
mod welcome;
|
||||
|
||||
use sycamore::view::View;
|
||||
use sycamore_router::Route;
|
||||
use sycamore::prelude::*;
|
||||
|
||||
#[derive(Debug, Clone, Route)]
|
||||
pub enum Page {
|
||||
#[to("/app")]
|
||||
App,
|
||||
#[to("/clipboard")]
|
||||
Clipboard,
|
||||
#[to("/communication")]
|
||||
Communication,
|
||||
#[not_found]
|
||||
NotFound
|
||||
}
|
||||
|
||||
pub fn switch<G: Html>(cx: Scope, route: &ReadSignal<Page>) -> View<G> {
|
||||
match route.get().as_ref() {
|
||||
Page::App => app::App(cx),
|
||||
Page::Clipboard => clipboard::Clipboard(cx),
|
||||
Page::Communication => communication::Communication(cx),
|
||||
Page::NotFound => welcome::Welcome(cx)
|
||||
}
|
||||
}
|
10
examples/api/src/views/welcome.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
use sycamore::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn Welcome<G: Html>(cx: Scope) -> View<G> {
|
||||
view! { cx,
|
||||
h1 {
|
||||
"Welcome"
|
||||
}
|
||||
}
|
||||
}
|
120
examples/api/style.css
Normal file
|
@ -0,0 +1,120 @@
|
|||
.logo.yew:hover {
|
||||
filter: drop-shadow(0 0 2em #20a88a);
|
||||
}
|
||||
.logo.sycamore {
|
||||
color: #0000;
|
||||
font-size: 3rem;
|
||||
line-height: 1;
|
||||
font-weight: 800;
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
background-image: linear-gradient(to right,#fdba74, #f87171);
|
||||
font-family: Inter,system-ui,sans-serif;
|
||||
}
|
||||
.logo.sycamore:hover {
|
||||
filter: drop-shadow(0 0 2em #f87171);
|
||||
}
|
||||
|
||||
:root {
|
||||
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
font-weight: 400;
|
||||
|
||||
color: #0f0f0f;
|
||||
background-color: #f6f6f6;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin: 0;
|
||||
padding-top: 10vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 6em;
|
||||
padding: 1.5em;
|
||||
will-change: filter;
|
||||
transition: 0.75s;
|
||||
}
|
||||
|
||||
.logo.tauri:hover {
|
||||
filter: drop-shadow(0 0 2em #24c8db);
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
color: #0f0f0f;
|
||||
background-color: #ffffff;
|
||||
transition: border-color 0.25s;
|
||||
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
border-color: #396cd8;
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#greet-input {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
color: #f6f6f6;
|
||||
background-color: #2f2f2f;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #24c8db;
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
color: #ffffff;
|
||||
background-color: #0f0f0f98;
|
||||
}
|
||||
}
|
83
src/app.rs
Normal file
|
@ -0,0 +1,83 @@
|
|||
use semver::Version;
|
||||
|
||||
/// Gets the application name.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```typescript
|
||||
/// import { getName } from '@tauri-apps/api/app';
|
||||
/// const appName = await getName();
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn get_name() -> String {
|
||||
inner::getName().await.as_string().unwrap()
|
||||
}
|
||||
|
||||
/// Gets the application version.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_api::app::get_version;
|
||||
///
|
||||
/// let version = get_version().await;
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn get_version() -> Version {
|
||||
Version::parse(&inner::getVersion().await.as_string().unwrap()).unwrap()
|
||||
}
|
||||
|
||||
/// Gets the Tauri version.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_app::app:get_tauri_version;
|
||||
///
|
||||
/// let version = get_tauri_version().await;
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn get_tauri_version() -> Version {
|
||||
Version::parse(&inner::getTauriVersion().await.as_string().unwrap()).unwrap()
|
||||
}
|
||||
|
||||
/// Shows the application on macOS. This function does not automatically focuses any app window.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_api::app::show;
|
||||
///
|
||||
/// show().await;
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn show() {
|
||||
inner::show().await;
|
||||
}
|
||||
|
||||
/// Hides the application on macOS.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_api::app::hide;
|
||||
///
|
||||
/// hide().await;
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn hide() {
|
||||
inner::hide().await;
|
||||
}
|
||||
|
||||
mod inner {
|
||||
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
|
||||
|
||||
#[wasm_bindgen(module = "/dist/app.js")]
|
||||
extern "C" {
|
||||
pub async fn getName() -> JsValue;
|
||||
pub async fn getTauriVersion() -> JsValue;
|
||||
pub async fn getVersion() -> JsValue;
|
||||
pub async fn hide();
|
||||
pub async fn show();
|
||||
}
|
||||
}
|
40
src/clipboard.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
/// Gets the clipboard content as plain text.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_api::clipboard::read_text;
|
||||
///
|
||||
/// let clipboard_text = read_text().await;
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn read_text() -> Option<String> {
|
||||
inner::readText().await.as_string()
|
||||
}
|
||||
|
||||
/// Writes plain text to the clipboard.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_api::clipboard::{write_text, read_text};
|
||||
///
|
||||
/// write_text("Tauri is awesome!").await;
|
||||
/// assert_eq!(read_text().await, "Tauri is awesome!");
|
||||
/// ```
|
||||
///
|
||||
/// @returns A promise indicating the success or failure of the operation.
|
||||
#[inline(always)]
|
||||
pub async fn write_text(text: &str) {
|
||||
inner::writeText(text).await
|
||||
}
|
||||
|
||||
mod inner {
|
||||
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
|
||||
|
||||
#[wasm_bindgen(module = "/dist/clipboard.js")]
|
||||
extern "C" {
|
||||
pub async fn readText() -> JsValue;
|
||||
pub async fn writeText(text: &str);
|
||||
}
|
||||
}
|
134
src/event.rs
Normal file
|
@ -0,0 +1,134 @@
|
|||
use std::fmt::Debug;
|
||||
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Event<T> {
|
||||
/// Event name
|
||||
pub event: String,
|
||||
/// Event identifier used to unlisten
|
||||
pub id: u32,
|
||||
/// Event payload
|
||||
pub payload: T,
|
||||
/// The label of the window that emitted this event
|
||||
pub window_label: String,
|
||||
}
|
||||
|
||||
impl<T: Debug> Debug for Event<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Event")
|
||||
.field("event", &self.event)
|
||||
.field("id", &self.id)
|
||||
.field("payload", &self.payload)
|
||||
.field("window_label", &self.window_label)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// Emits an event to the backend.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_api::event::emit;
|
||||
/// use serde::Serialize;
|
||||
///
|
||||
/// #[derive(Serialize)]
|
||||
/// struct Payload {
|
||||
/// logged_in: bool,
|
||||
/// token: String
|
||||
/// }
|
||||
///
|
||||
/// emit("frontend-loaded", &Payload { logged_in: true, token: "authToken" }).await;
|
||||
/// ```
|
||||
///
|
||||
/// @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`.
|
||||
#[inline(always)]
|
||||
pub async fn emit<T: Serialize>(event: &str, payload: &T) {
|
||||
inner::emit(event, serde_wasm_bindgen::to_value(payload).unwrap()).await
|
||||
}
|
||||
|
||||
/// Listen to an event from the backend.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_api::event::{emit, listen};
|
||||
///
|
||||
/// const unlisten = listen::<String>("error", |event| {
|
||||
/// println!("Got error in window {}, payload: {}", event.window_label, event.payload);
|
||||
/// }).await;
|
||||
///
|
||||
/// // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
|
||||
/// unlisten();
|
||||
/// ```
|
||||
///
|
||||
/// @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`.
|
||||
/// @param handler Event handler callback.
|
||||
/// @returns A promise resolving to a function to unlisten to the event.
|
||||
///
|
||||
/// Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
|
||||
#[inline(always)]
|
||||
pub async fn listen<T: DeserializeOwned>(event: &str, handler: &dyn Fn(Event<T>)) -> impl FnOnce() {
|
||||
let unlisten = inner::listen(event, &|raw| {
|
||||
handler(serde_wasm_bindgen::from_value(raw).unwrap())
|
||||
})
|
||||
.await;
|
||||
|
||||
let unlisten = js_sys::Function::from(unlisten);
|
||||
move || {
|
||||
unlisten.call0(&wasm_bindgen::JsValue::NULL).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Listen to an one-off event from the backend.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_api::event::once;
|
||||
/// use serde::Deserialize;
|
||||
///
|
||||
/// #[derive(Deserialize)]
|
||||
/// interface LoadedPayload {
|
||||
/// logged_in: bool,
|
||||
/// token: String
|
||||
/// }
|
||||
/// const unlisten = once::<LoadedPayload>("loaded", |event| {
|
||||
/// println!("App is loaded, loggedIn: {}, token: {}", event.payload.logged_in, event.payload.token);
|
||||
/// }).await;
|
||||
///
|
||||
/// // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
|
||||
/// unlisten();
|
||||
/// ```
|
||||
///
|
||||
/// @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`.
|
||||
/// @returns A promise resolving to a function to unlisten to the event.
|
||||
///
|
||||
/// Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
|
||||
#[inline(always)]
|
||||
pub async fn once<T: DeserializeOwned>(
|
||||
event: &str,
|
||||
handler: &mut dyn FnMut(Event<T>),
|
||||
) -> impl FnOnce() {
|
||||
let unlisten = inner::once(event, &mut |raw| {
|
||||
handler(serde_wasm_bindgen::from_value(raw).unwrap())
|
||||
})
|
||||
.await;
|
||||
|
||||
let unlisten = js_sys::Function::from(unlisten);
|
||||
move || {
|
||||
unlisten.call0(&wasm_bindgen::JsValue::NULL).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
mod inner {
|
||||
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
|
||||
|
||||
#[wasm_bindgen(module = "/dist/event.js")]
|
||||
extern "C" {
|
||||
pub async fn emit(event: &str, payload: JsValue);
|
||||
pub async fn listen(event: &str, handler: &dyn Fn(JsValue)) -> JsValue;
|
||||
pub async fn once(event: &str, handler: &mut dyn FnMut(JsValue)) -> JsValue;
|
||||
}
|
||||
}
|
22
src/lib.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
use wasm_bindgen::JsValue;
|
||||
|
||||
#[cfg(feature = "app")]
|
||||
pub mod app;
|
||||
#[cfg(feature = "clipboard")]
|
||||
pub mod clipboard;
|
||||
#[cfg(feature = "event")]
|
||||
pub mod event;
|
||||
#[cfg(feature = "mocks")]
|
||||
pub mod mocks;
|
||||
#[cfg(feature = "tauri")]
|
||||
pub mod tauri;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
Serde(#[from] serde_wasm_bindgen::Error),
|
||||
#[error("{0:?}")]
|
||||
Other(JsValue)
|
||||
}
|
||||
|
||||
pub(crate) type Result<T> = std::result::Result<T, Error>;
|
54
src/mocks.rs
Normal file
|
@ -0,0 +1,54 @@
|
|||
use js_sys::Array;
|
||||
use wasm_bindgen::JsValue;
|
||||
|
||||
/// Mocks the current window label
|
||||
/// In non-tauri context it is required to call this function///before* using the `@tauri-apps/api/window` module.
|
||||
///
|
||||
/// This function only mocks the *presence* of a window,
|
||||
/// window properties (e.g. width and height) can be mocked like regular IPC calls using the `mockIPC` function.
|
||||
pub fn mock_window(current: &str) {
|
||||
inner::mockWindows(
|
||||
current,
|
||||
JsValue::UNDEFINED,
|
||||
)
|
||||
}
|
||||
|
||||
/// Mocks many window labels.
|
||||
/// In non-tauri context it is required to call this function///before* using the `@tauri-apps/api/window` module.
|
||||
///
|
||||
/// This function only mocks the *presence* of windows,
|
||||
/// window properties (e.g. width and height) can be mocked like regular IPC calls using the `mockIPC` function.
|
||||
///
|
||||
/// @param current Label of window this JavaScript context is running in.
|
||||
/// @param additionalWindows Label of additional windows the app has.
|
||||
pub fn mock_windows(current: &str, additional_windows: &[&str]) {
|
||||
inner::mockWindows(
|
||||
current,
|
||||
Array::from_iter(additional_windows.iter().map(|str| JsValue::from_str(str))).into(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Intercepts all IPC requests with the given mock handler.
|
||||
///
|
||||
/// This function can be used when testing tauri frontend applications or when running the frontend in a Node.js context during static site generation.
|
||||
pub fn mock_ipc(handler: &dyn Fn(JsValue)) {
|
||||
inner::mockIPC(handler);
|
||||
}
|
||||
|
||||
/// Clears mocked functions/data injected by the other functions in this module.
|
||||
/// When using a test runner that doesn't provide a fresh window object for each test, calling this function will reset tauri specific properties.
|
||||
pub fn clear_mocks() {
|
||||
inner::clearMocks()
|
||||
}
|
||||
|
||||
mod inner {
|
||||
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
|
||||
|
||||
#[wasm_bindgen(module = "/dist/mocks.js")]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(variadic)]
|
||||
pub fn mockWindows(current: &str, rest: JsValue);
|
||||
pub fn mockIPC(handler: &dyn Fn(JsValue));
|
||||
pub fn clearMocks();
|
||||
}
|
||||
}
|
100
src/tauri.rs
Normal file
|
@ -0,0 +1,100 @@
|
|||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use url::Url;
|
||||
|
||||
/// Convert a device file path to an URL that can be loaded by the webview.
|
||||
/// Note that `asset:` and `https://asset.localhost` must be added to [`tauri.security.csp`](https://tauri.app/v1/api/config/#securityconfig.csp) in `tauri.conf.json`.
|
||||
/// Example CSP value: `"csp": "default-src 'self'; img-src 'self' asset: https://asset.localhost"` to use the asset protocol on image sources.
|
||||
///
|
||||
/// Additionally, `asset` must be added to [`tauri.allowlist.protocol`](https://tauri.app/v1/api/config/#allowlistconfig.protocol)
|
||||
/// in `tauri.conf.json` and its access scope must be defined on the `assetScope` array on the same `protocol` object.
|
||||
///
|
||||
/// @param filePath The file path.
|
||||
/// @param protocol The protocol to use. Defaults to `asset`. You only need to set this when using a custom protocol.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_api::path::{app_data_dir, join};
|
||||
/// use tauri_api::tauri::convert_file_src;
|
||||
///
|
||||
/// const app_data_dir_path = app_data_dir().await;
|
||||
/// const file_path = join(app_data_dir_path, "assets/video.mp4").await;
|
||||
/// const asset_url = convert_file_src(file_path);
|
||||
///
|
||||
/// let window = web_sys::window().expect("no global `window` exists");
|
||||
/// let document = window.document().expect("should have a document on window");
|
||||
///
|
||||
/// // Manufacture the element we're gonna append
|
||||
/// let video = document.get_element_by_id("my-video")?;
|
||||
/// let source = document.create_element("source")?;
|
||||
///
|
||||
/// source.set_attribute("type", "video/mp4")?;
|
||||
/// source.set_attribute("src", asset_url.as_str())?;
|
||||
///
|
||||
/// video.append_child(&val)?;
|
||||
/// ```
|
||||
///
|
||||
/// @return the URL that can be used as source on the webview.
|
||||
#[inline(always)]
|
||||
pub async fn convert_file_src(file_path: &str, protocol: Option<&str>) -> Url {
|
||||
Url::parse(
|
||||
&inner::convertFileSrc(file_path, protocol)
|
||||
.await
|
||||
.as_string()
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Sends a message to the backend.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_api::tauri::invoke;
|
||||
///
|
||||
/// struct User<'a> {
|
||||
/// user: &'a str,
|
||||
/// password: &'a str
|
||||
/// }
|
||||
///
|
||||
/// invoke("login", &User { user: "tauri", password: "poiwe3h4r5ip3yrhtew9ty" }).await;
|
||||
/// ```
|
||||
///
|
||||
/// @param cmd The command name.
|
||||
/// @param args The optional arguments to pass to the command.
|
||||
/// @return A promise resolving or rejecting to the backend response.
|
||||
#[inline(always)]
|
||||
pub async fn invoke<A: Serialize, R: DeserializeOwned>(cmd: &str, args: &A) -> crate::Result<R> {
|
||||
let res = inner::invoke(cmd, serde_wasm_bindgen::to_value(args).unwrap()).await;
|
||||
|
||||
let raw = res.map_err(crate::Error::Other)?;
|
||||
serde_wasm_bindgen::from_value(raw).map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Transforms a callback function to a string identifier that can be passed to the backend.
|
||||
/// The backend uses the identifier to `eval()` the callback.
|
||||
///
|
||||
/// @return A unique identifier associated with the callback function.
|
||||
#[inline(always)]
|
||||
pub async fn transform_callback<T: DeserializeOwned>(callback: &dyn Fn(T), once: bool) -> f64 {
|
||||
inner::transformCallback(
|
||||
&|raw| callback(serde_wasm_bindgen::from_value(raw).unwrap()),
|
||||
once,
|
||||
)
|
||||
.await
|
||||
.as_f64()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
mod inner {
|
||||
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
|
||||
|
||||
#[wasm_bindgen(module = "/dist/tauri.js")]
|
||||
extern "C" {
|
||||
pub async fn convertFileSrc(filePath: &str, protocol: Option<&str>) -> JsValue;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn invoke(cmd: &str, args: JsValue) -> Result<JsValue, JsValue>;
|
||||
pub async fn transformCallback(callback: &dyn Fn(JsValue), once: bool) -> JsValue;
|
||||
}
|
||||
}
|
1
tauri
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 35264b4c1801b381e0b867c1c35540f0fbb43365
|