Initial switch to compatibility with Tauri v2. Only event API is implemented, all other APIs have been removed. Irrelevant or deprecated documentation was removed.
This commit is contained in:
parent
dca9e751c5
commit
22267c5862
36 changed files with 363 additions and 10251 deletions
148
Cargo.lock
generated
148
Cargo.lock
generated
|
@ -163,7 +163,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.41",
|
||||
"syn 2.0.68",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -609,7 +609,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "30d2b3721e861707777e3195b0158f950ae6dc4a27e4d02ff9f67e3eb3de199e"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.41",
|
||||
"syn 2.0.68",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -639,7 +639,7 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.41",
|
||||
"syn 2.0.68",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -650,7 +650,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
|
|||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.41",
|
||||
"syn 2.0.68",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -801,7 +801,7 @@ checksum = "f95e2801cd355d4a1a3e3953ce6ee5ae9603a5c833455343a8bfe3f44d418246"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.41",
|
||||
"syn 2.0.68",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -925,9 +925,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.29"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335"
|
||||
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
|
@ -940,9 +940,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.29"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
|
||||
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
|
@ -950,15 +950,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.29"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
|
||||
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.29"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc"
|
||||
checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
|
@ -967,9 +967,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.29"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
|
||||
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
|
||||
|
||||
[[package]]
|
||||
name = "futures-lite"
|
||||
|
@ -988,32 +988,32 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.29"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
|
||||
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.41",
|
||||
"syn 2.0.68",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.29"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
|
||||
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.29"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
|
||||
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.29"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
|
||||
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
|
@ -1714,9 +1714,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
|||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.68"
|
||||
version = "0.3.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee"
|
||||
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
@ -1797,9 +1797,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.20"
|
||||
version = "0.4.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"value-bag",
|
||||
|
@ -2436,7 +2436,7 @@ dependencies = [
|
|||
"phf_shared 0.11.2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.41",
|
||||
"syn 2.0.68",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2581,9 +2581,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.70"
|
||||
version = "1.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
|
||||
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
@ -2599,9 +2599,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
version = "1.0.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
@ -2986,18 +2986,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.193"
|
||||
version = "1.0.203"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
|
||||
checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-wasm-bindgen"
|
||||
version = "0.6.3"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9b713f70513ae1f8d92665bbbbda5c295c2cf1da5542881ae5eefe20c9af132"
|
||||
checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"serde",
|
||||
|
@ -3006,13 +3006,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.193"
|
||||
version = "1.0.203"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
|
||||
checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.41",
|
||||
"syn 2.0.68",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3028,13 +3028,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_repr"
|
||||
version = "0.1.17"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145"
|
||||
checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.41",
|
||||
"syn 2.0.68",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3084,7 +3084,7 @@ dependencies = [
|
|||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.41",
|
||||
"syn 2.0.68",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3397,9 +3397,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.41"
|
||||
version = "2.0.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269"
|
||||
checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -3711,18 +3711,16 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tauri-sys"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"js-sys",
|
||||
"log",
|
||||
"semver 1.0.20",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"serde_repr",
|
||||
"tauri-sys",
|
||||
"thiserror",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-bindgen-test",
|
||||
|
@ -3838,22 +3836,22 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c"
|
|||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.50"
|
||||
version = "1.0.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
|
||||
checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.50"
|
||||
version = "1.0.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
|
||||
checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.41",
|
||||
"syn 2.0.68",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4191,9 +4189,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
|||
|
||||
[[package]]
|
||||
name = "value-bag"
|
||||
version = "1.4.2"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a72e1902dde2bd6441347de2b70b7f5d59bf157c6c62f0c44572607a1d55bbe"
|
||||
checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
|
@ -4279,9 +4277,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.91"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f"
|
||||
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
|
@ -4289,24 +4287,24 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.91"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b"
|
||||
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.41",
|
||||
"syn 2.0.68",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.41"
|
||||
version = "0.4.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97"
|
||||
checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
|
@ -4316,9 +4314,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.91"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed"
|
||||
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
|
@ -4326,28 +4324,28 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.91"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66"
|
||||
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.41",
|
||||
"syn 2.0.68",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.91"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838"
|
||||
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test"
|
||||
version = "0.3.41"
|
||||
version = "0.3.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "143ddeb4f833e2ed0d252e618986e18bfc7b0e52f2d28d77d05b2f045dd8eb61"
|
||||
checksum = "d9bf62a58e0780af3e852044583deee40983e5886da43a271dd772379987667b"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"js-sys",
|
||||
|
@ -4359,13 +4357,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test-macro"
|
||||
version = "0.3.41"
|
||||
version = "0.3.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5211b7550606857312bba1d978a8ec75692eae187becc5e680444fffc5e6f89"
|
||||
checksum = "b7f89739351a2e03cb94beb799d47fb2cac01759b40ec441f7de39b00cbf7ef0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.41",
|
||||
"syn 2.0.68",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
39
Cargo.toml
39
Cargo.toml
|
@ -1,46 +1,31 @@
|
|||
[package]
|
||||
edition = "2021"
|
||||
name = "tauri-sys"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
futures = { version = "0.3.29", optional = true }
|
||||
js-sys = "0.3.66"
|
||||
log = "0.4.20"
|
||||
semver = {version = "1.0.20", optional = true, features = ["serde"]}
|
||||
serde = {version = "1.0.193", features = ["derive"]}
|
||||
serde-wasm-bindgen = "0.6.3"
|
||||
serde_repr = "0.1.17"
|
||||
thiserror = "1.0.50"
|
||||
url = {version = "2.5.0", optional = true, features = ["serde"]}
|
||||
wasm-bindgen = "0.2.89"
|
||||
wasm-bindgen-futures = "0.4.39"
|
||||
futures = { version = "0.3.30", optional = true }
|
||||
js-sys = "0.3.69"
|
||||
log = "0.4.21"
|
||||
serde = {version = "1.0.203", features = ["derive"]}
|
||||
serde-wasm-bindgen = "0.6.5"
|
||||
serde_repr = "0.1.19"
|
||||
thiserror = "1.0.61"
|
||||
wasm-bindgen = "0.2.92"
|
||||
wasm-bindgen-futures = "0.4.42"
|
||||
|
||||
[dev-dependencies]
|
||||
tauri-sys = {path = ".", features = ["all"]}
|
||||
wasm-bindgen-test = "0.3.41"
|
||||
wasm-bindgen-test = "0.3.42"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
[features]
|
||||
all = ["app", "clipboard", "event", "fs", "mocks", "tauri", "window", "process", "dialog", "os", "notification", "path", "updater", "global_shortcut"]
|
||||
app = ["dep:semver"]
|
||||
clipboard = []
|
||||
dialog = []
|
||||
all = ["event"]
|
||||
event = ["dep:futures"]
|
||||
fs = []
|
||||
global_shortcut = []
|
||||
mocks = []
|
||||
notification = []
|
||||
os = []
|
||||
path = []
|
||||
process = []
|
||||
tauri = ["dep:url"]
|
||||
updater = ["dep:futures", "event"]
|
||||
window = ["dep:futures", "event"]
|
||||
|
||||
[workspace]
|
||||
members = ["examples/test", "examples/test/src-tauri"]
|
||||
|
|
36
README.md
36
README.md
|
@ -21,7 +21,8 @@
|
|||
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" }
|
||||
tauri-sys = { git = "https://github.com/JonasKruckenberg/tauri-sys" } // v1, main repo
|
||||
tauri-sys = { git = "https://github.com/bicarlsen/tauri-sys" } // v2 branch
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
@ -49,35 +50,24 @@ fn main() {
|
|||
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.
|
||||
- **dialog**: Enables the `dialog` module.
|
||||
- **event**: Enables the `event` module.
|
||||
- **fs**: Enables the `fs` 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`
|
||||
- [x] `dialog`
|
||||
- [ ] `app`
|
||||
- [ ] `core`
|
||||
- [ ] `dpi`
|
||||
- [x] `event`
|
||||
- [x] `fs`
|
||||
- [x] `global_shortcut`
|
||||
- [ ] `http`
|
||||
- [x] `mocks`
|
||||
- [x] `notification`
|
||||
- [x] `os`
|
||||
- [x] `path`
|
||||
- [x] `process`
|
||||
- [ ] `shell`
|
||||
- [x] `tauri`
|
||||
- [ ] `updater`
|
||||
- [x] `window`
|
||||
- [ ] `image`
|
||||
- [ ] `menu`
|
||||
- [ ] `mocks`
|
||||
- [ ] `path`
|
||||
- [ ] `tray`
|
||||
- [ ] `webview`
|
||||
- [ ] `webviewWindow`
|
||||
- [ ] `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.
|
||||
|
||||
|
|
91
src/app.js
91
src/app.js
|
@ -1,91 +0,0 @@
|
|||
// 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
|
||||
};
|
116
src/app.rs
116
src/app.rs
|
@ -1,116 +0,0 @@
|
|||
//! Get application metadata.
|
||||
//!
|
||||
//! he APIs must be added to tauri.allowlist.app in tauri.conf.json:
|
||||
//! ```json
|
||||
//! {
|
||||
//! "tauri": {
|
||||
//! "allowlist": {
|
||||
//! "app": {
|
||||
//! "all": true, // enable all app APIs
|
||||
//! "show": true,
|
||||
//! "hide": true
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//! It is recommended to allowlist only the APIs you use for optimal bundle size and security.
|
||||
|
||||
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() -> crate::Result<String> {
|
||||
let js_val = inner::getName().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(js_val)?)
|
||||
}
|
||||
|
||||
/// 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() -> crate::Result<Version> {
|
||||
let js_val = inner::getVersion().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(js_val)?)
|
||||
}
|
||||
|
||||
/// 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() -> crate::Result<Version> {
|
||||
let js_val = inner::getTauriVersion().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(js_val)?)
|
||||
}
|
||||
|
||||
/// Shows the application on macOS. This function does not automatically focus the apps windows.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_api::app::show;
|
||||
///
|
||||
/// show().await;
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > app > show`](https://tauri.app/v1/api/config#appallowlistconfig.show) to be enabled.
|
||||
#[inline(always)]
|
||||
pub async fn show() -> crate::Result<()> {
|
||||
Ok(inner::show().await?)
|
||||
}
|
||||
|
||||
/// Hides the application on macOS.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_api::app::hide;
|
||||
///
|
||||
/// hide().await;
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > app > hide`](https://tauri.app/v1/api/config#appallowlistconfig.hide) to be enabled.
|
||||
#[inline(always)]
|
||||
pub async fn hide() -> crate::Result<()> {
|
||||
Ok(inner::hide().await?)
|
||||
}
|
||||
|
||||
mod inner {
|
||||
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
|
||||
|
||||
#[wasm_bindgen(module = "/src/app.js")]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn getName() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn getTauriVersion() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn getVersion() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn hide() -> Result<(), JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn show() -> Result<(), JsValue>;
|
||||
}
|
||||
}
|
55
src/cli.js
55
src/cli.js
|
@ -1,55 +0,0 @@
|
|||
// 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/cli.ts
|
||||
async function getMatches() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Cli",
|
||||
message: {
|
||||
cmd: "cliMatches"
|
||||
}
|
||||
});
|
||||
}
|
||||
export {
|
||||
getMatches
|
||||
};
|
|
@ -1,66 +0,0 @@
|
|||
// 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
|
||||
};
|
|
@ -1,64 +0,0 @@
|
|||
//! Read and write to the system clipboard.
|
||||
//!
|
||||
//! The APIs must be added to tauri.allowlist.clipboard in tauri.conf.json:
|
||||
//! ```json
|
||||
//! {
|
||||
//! "tauri": {
|
||||
//! "allowlist": {
|
||||
//! "clipboard": {
|
||||
//! "all": true, // enable all Clipboard APIs
|
||||
//! "writeText": true,
|
||||
//! "readText": true
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//! It is recommended to allowlist only the APIs you use for optimal bundle size and security.
|
||||
|
||||
/// Gets the clipboard content as plain text.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_api::clipboard::read_text;
|
||||
///
|
||||
/// let clipboard_text = read_text().await;
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > clipboard > readText`](https://tauri.app/v1/api/config#clipboardallowlistconfig.readtext) to be enabled.
|
||||
#[inline(always)]
|
||||
pub async fn read_text() -> crate::Result<String> {
|
||||
let js_val = inner::readText().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(js_val)?)
|
||||
}
|
||||
|
||||
/// 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!");
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > clipboard > writeText`](https://tauri.app/v1/api/config#clipboardallowlistconfig.writetext) to be enabled.
|
||||
#[inline(always)]
|
||||
pub async fn write_text(text: &str) -> crate::Result<()> {
|
||||
Ok(inner::writeText(text).await?)
|
||||
}
|
||||
|
||||
mod inner {
|
||||
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
|
||||
|
||||
#[wasm_bindgen(module = "/src/clipboard.js")]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn readText() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn writeText(text: &str) -> Result<(), JsValue>;
|
||||
}
|
||||
}
|
120
src/dialog.js
120
src/dialog.js
|
@ -1,120 +0,0 @@
|
|||
// 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/dialog.ts
|
||||
async function open(options = {}) {
|
||||
if (typeof options === "object") {
|
||||
Object.freeze(options);
|
||||
}
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Dialog",
|
||||
message: {
|
||||
cmd: "openDialog",
|
||||
options
|
||||
}
|
||||
});
|
||||
}
|
||||
async function save(options = {}) {
|
||||
if (typeof options === "object") {
|
||||
Object.freeze(options);
|
||||
}
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Dialog",
|
||||
message: {
|
||||
cmd: "saveDialog",
|
||||
options
|
||||
}
|
||||
});
|
||||
}
|
||||
async function message(message2, options) {
|
||||
const opts = typeof options === "string" ? { title: options } : options;
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Dialog",
|
||||
message: {
|
||||
cmd: "messageDialog",
|
||||
message: message2.toString(),
|
||||
title: opts?.title?.toString(),
|
||||
type: opts?.type,
|
||||
buttonLabel: opts?.okLabel?.toString()
|
||||
}
|
||||
});
|
||||
}
|
||||
async function ask(message2, options) {
|
||||
const opts = typeof options === "string" ? { title: options } : options;
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Dialog",
|
||||
message: {
|
||||
cmd: "askDialog",
|
||||
message: message2.toString(),
|
||||
title: opts?.title?.toString(),
|
||||
type: opts?.type,
|
||||
buttonLabels: [
|
||||
opts?.okLabel?.toString() ?? "Yes",
|
||||
opts?.cancelLabel?.toString() ?? "No"
|
||||
]
|
||||
}
|
||||
});
|
||||
}
|
||||
async function confirm(message2, options) {
|
||||
const opts = typeof options === "string" ? { title: options } : options;
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Dialog",
|
||||
message: {
|
||||
cmd: "confirmDialog",
|
||||
message: message2.toString(),
|
||||
title: opts?.title?.toString(),
|
||||
type: opts?.type,
|
||||
buttonLabels: [
|
||||
opts?.okLabel?.toString() ?? "Ok",
|
||||
opts?.cancelLabel?.toString() ?? "Cancel"
|
||||
]
|
||||
}
|
||||
});
|
||||
}
|
||||
export {
|
||||
ask,
|
||||
confirm,
|
||||
message,
|
||||
open,
|
||||
save
|
||||
};
|
398
src/dialog.rs
398
src/dialog.rs
|
@ -1,398 +0,0 @@
|
|||
//! Native system dialogs for opening and saving files.
|
||||
//!
|
||||
//! The APIs must be added to `tauri.allowlist.dialog` in `tauri.conf.json`:
|
||||
//! ```json
|
||||
//! {
|
||||
//! "tauri": {
|
||||
//! "allowlist": {
|
||||
//! "dialog": {
|
||||
//! "all": true, // enable all dialog APIs
|
||||
//! "open": true, // enable file open API
|
||||
//! "save": true // enable file save API
|
||||
//! "message": true,
|
||||
//! "ask": true,
|
||||
//! "confirm": true
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//! It is recommended to allowlist only the APIs you use for optimal bundle size and security.
|
||||
|
||||
use js_sys::Array;
|
||||
use serde::Serialize;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::utils::ArrayIterator;
|
||||
#[derive(Debug, Clone, Copy, Hash, Serialize)]
|
||||
struct DialogFilter<'a> {
|
||||
extensions: &'a [&'a str],
|
||||
name: &'a str,
|
||||
}
|
||||
|
||||
/// The file dialog builder.
|
||||
///
|
||||
/// Constructs file picker dialogs that can select single/multiple files or directories.
|
||||
#[derive(Debug, Default, Clone, Hash, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FileDialogBuilder<'a> {
|
||||
default_path: Option<&'a Path>,
|
||||
filters: Vec<DialogFilter<'a>>,
|
||||
title: Option<&'a str>,
|
||||
directory: bool,
|
||||
multiple: bool,
|
||||
recursive: bool,
|
||||
}
|
||||
|
||||
impl<'a> FileDialogBuilder<'a> {
|
||||
/// Gets the default file dialog builder.
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Set starting file name or directory of the dialog.
|
||||
pub fn set_default_path(&mut self, default_path: &'a Path) -> &mut Self {
|
||||
self.default_path = Some(default_path);
|
||||
self
|
||||
}
|
||||
|
||||
/// If directory is true, indicates that it will be read recursively later.
|
||||
/// Defines whether subdirectories will be allowed on the scope or not.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use tauri_sys::dialog::FileDialogBuilder;
|
||||
///
|
||||
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let _builder = FileDialogBuilder::new().set_recursive(true);
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn set_recursive(&mut self, recursive: bool) -> &mut Self {
|
||||
self.recursive = recursive;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the title of the dialog.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use tauri_sys::dialog::FileDialogBuilder;
|
||||
///
|
||||
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let _builder = FileDialogBuilder::new().set_title("Test Title");
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn set_title(&mut self, title: &'a str) -> &mut Self {
|
||||
self.title = Some(title);
|
||||
self
|
||||
}
|
||||
|
||||
/// Add file extension filter. Takes in the name of the filter, and list of extensions
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use tauri_sys::dialog::FileDialogBuilder;
|
||||
///
|
||||
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let _builder = FileDialogBuilder::new().add_filter("Image", &["png", "jpeg"]);
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn add_filter(&mut self, name: &'a str, extensions: &'a [&'a str]) -> &mut Self {
|
||||
self.filters.push(DialogFilter { name, extensions });
|
||||
self
|
||||
}
|
||||
|
||||
/// Add many file extension filters.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use tauri_sys::dialog::FileDialogBuilder;
|
||||
///
|
||||
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let _builder = FileDialogBuilder::new().add_filters(&[("Image", &["png", "jpeg"]),("Video", &["mp4"])]);
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn add_filters(
|
||||
&mut self,
|
||||
filters: impl IntoIterator<Item = (&'a str, &'a [&'a str])>,
|
||||
) -> &mut Self {
|
||||
for (name, extensions) in filters.into_iter() {
|
||||
self.filters.push(DialogFilter {
|
||||
name: name.as_ref(),
|
||||
extensions,
|
||||
});
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Shows the dialog to select a single file.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::dialog::FileDialogBuilder;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let file = FileDialogBuilder::new().pick_file().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > dialog > open`](https://tauri.app/v1/api/config#dialogallowlistconfig.open) to be enabled.
|
||||
pub async fn pick_file(&self) -> crate::Result<Option<PathBuf>> {
|
||||
let raw = inner::open(serde_wasm_bindgen::to_value(&self)?).await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Shows the dialog to select multiple files.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::dialog::FileDialogBuilder;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let files = FileDialogBuilder::new().pick_files().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > dialog > open`](https://tauri.app/v1/api/config#dialogallowlistconfig.open) to be enabled.
|
||||
pub async fn pick_files(&mut self) -> crate::Result<Option<impl Iterator<Item = PathBuf>>> {
|
||||
self.multiple = true;
|
||||
|
||||
let raw = inner::open(serde_wasm_bindgen::to_value(&self)?).await?;
|
||||
|
||||
if let Ok(files) = Array::try_from(raw) {
|
||||
let files =
|
||||
ArrayIterator::new(files).map(|raw| serde_wasm_bindgen::from_value(raw).unwrap());
|
||||
|
||||
Ok(Some(files))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
/// Shows the dialog to select a single folder.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::dialog::FileDialogBuilder;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let files = FileDialogBuilder::new().pick_folder().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > dialog > open`](https://tauri.app/v1/api/config#dialogallowlistconfig.open) to be enabled.
|
||||
pub async fn pick_folder(&mut self) -> crate::Result<Option<PathBuf>> {
|
||||
self.directory = true;
|
||||
|
||||
let raw = inner::open(serde_wasm_bindgen::to_value(&self)?).await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Shows the dialog to select multiple folders.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::dialog::FileDialogBuilder;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let files = FileDialogBuilder::new().pick_folders().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > dialog > open`](https://tauri.app/v1/api/config#dialogallowlistconfig.open) to be enabled.
|
||||
pub async fn pick_folders(&mut self) -> crate::Result<Option<impl Iterator<Item = PathBuf>>> {
|
||||
self.directory = true;
|
||||
self.multiple = true;
|
||||
|
||||
let raw = inner::open(serde_wasm_bindgen::to_value(&self)?).await?;
|
||||
|
||||
if let Ok(files) = Array::try_from(raw) {
|
||||
let files =
|
||||
ArrayIterator::new(files).map(|raw| serde_wasm_bindgen::from_value(raw).unwrap());
|
||||
|
||||
Ok(Some(files))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
/// Open a file/directory save dialog.
|
||||
///
|
||||
/// The selected path is added to the filesystem and asset protocol allowlist scopes.
|
||||
/// When security is more important than the easy of use of this API, prefer writing a dedicated command instead.
|
||||
///
|
||||
/// Note that the allowlist scope change is not persisted, so the values are cleared when the application is restarted.
|
||||
/// You can save it to the filesystem using tauri-plugin-persisted-scope.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::dialog::FileDialogBuilder;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let file = FileDialogBuilder::new().save().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > dialog > save`](https://tauri.app/v1/api/config#dialogallowlistconfig.save) to be enabled.
|
||||
pub async fn save(&self) -> crate::Result<Option<PathBuf>> {
|
||||
let raw = inner::save(serde_wasm_bindgen::to_value(&self)?).await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
}
|
||||
|
||||
/// Types of message, ask and confirm dialogs.
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
|
||||
pub enum MessageDialogKind {
|
||||
#[default]
|
||||
#[serde(rename = "info")]
|
||||
Info,
|
||||
#[serde(rename = "warning")]
|
||||
Warning,
|
||||
#[serde(rename = "error")]
|
||||
Error,
|
||||
}
|
||||
|
||||
/// A builder for message dialogs.
|
||||
#[derive(Debug, Default, Clone, Copy, Hash, Serialize)]
|
||||
pub struct MessageDialogBuilder<'a> {
|
||||
title: Option<&'a str>,
|
||||
#[serde(rename = "type")]
|
||||
kind: MessageDialogKind,
|
||||
}
|
||||
|
||||
impl<'a> MessageDialogBuilder<'a> {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Set the title of the dialog.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use tauri_sys::dialog::MessageDialogBuilder;
|
||||
///
|
||||
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let _builder = MessageDialogBuilder::new().set_title("Test Title");
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn set_title(&mut self, title: &'a str) -> &mut Self {
|
||||
self.title = Some(title);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the type of the dialog.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use tauri_sys::dialog::{MessageDialogBuilder,MessageDialogKind};
|
||||
///
|
||||
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let _builder = MessageDialogBuilder::new().set_kind(MessageDialogKind::Error);
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn set_kind(&mut self, kind: MessageDialogKind) -> &mut Self {
|
||||
self.kind = kind;
|
||||
self
|
||||
}
|
||||
|
||||
/// Shows a message dialog with an `Ok` button.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::dialog::MessageDialogBuilder;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let file = MessageDialogBuilder::new().message("Tauri is awesome").await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > dialog > message`](https://tauri.app/v1/api/config#dialogallowlistconfig.message) to be enabled.
|
||||
pub async fn message(&self, message: &str) -> crate::Result<()> {
|
||||
Ok(inner::message(message, serde_wasm_bindgen::to_value(&self)?).await?)
|
||||
}
|
||||
|
||||
/// Shows a question dialog with `Yes` and `No` buttons.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::dialog::MessageDialogBuilder;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let confirmation = MessageDialogBuilder::new().ask("Are you sure?").await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > dialog > ask`](https://tauri.app/v1/api/config#dialogallowlistconfig.ask) to be enabled.
|
||||
pub async fn ask(&self, message: &str) -> crate::Result<bool> {
|
||||
let raw = inner::ask(message, serde_wasm_bindgen::to_value(&self)?).await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Shows a question dialog with `Ok` and `Cancel` buttons.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::dialog::MessageDialogBuilder;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let confirmation = MessageDialogBuilder::new().confirm("Are you sure?").await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > dialog > confirm`](https://tauri.app/v1/api/config#dialogallowlistconfig.confirm) to be enabled.
|
||||
pub async fn confirm(&self, message: &str) -> crate::Result<bool> {
|
||||
let raw = inner::confirm(message, serde_wasm_bindgen::to_value(&self)?).await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
}
|
||||
|
||||
mod inner {
|
||||
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
|
||||
|
||||
#[wasm_bindgen(module = "/src/dialog.js")]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn ask(message: &str, options: JsValue) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn confirm(message: &str, options: JsValue) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn open(options: JsValue) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn message(message: &str, option: JsValue) -> Result<(), JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn save(options: JsValue) -> Result<JsValue, JsValue>;
|
||||
}
|
||||
}
|
175
src/event.js
175
src/event.js
|
@ -1,123 +1,82 @@
|
|||
// 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;
|
||||
// tauri/tooling/api/src/core.ts
|
||||
function transformCallback(callback, once = false) {
|
||||
return window.__TAURI_INTERNALS__.transformCallback(callback, once)
|
||||
}
|
||||
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
|
||||
});
|
||||
});
|
||||
// NB: `options` ignored as not used here.
|
||||
return window.__TAURI_INTERNALS__.invoke(cmd, args)
|
||||
}
|
||||
|
||||
// tauri/tooling/api/src/helpers/tauri.ts
|
||||
async function invokeTauriCommand(command) {
|
||||
return invoke("tauri", command);
|
||||
}
|
||||
|
||||
// tauri/tooling/api/src/helpers/event.ts
|
||||
// tauri/tooling/api/src/event.ts
|
||||
async function _unlisten(event, eventId) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Event",
|
||||
message: {
|
||||
cmd: "unlisten",
|
||||
event,
|
||||
eventId
|
||||
}
|
||||
});
|
||||
await invoke('plugin:event|unlisten', {
|
||||
event,
|
||||
eventId
|
||||
})
|
||||
}
|
||||
async function emit(event, windowLabel, payload) {
|
||||
await invokeTauriCommand({
|
||||
__tauriModule: "Event",
|
||||
message: {
|
||||
cmd: "emit",
|
||||
event,
|
||||
windowLabel,
|
||||
payload
|
||||
}
|
||||
});
|
||||
async function emit(event, payload) {
|
||||
await invoke('plugin:event|emit', {
|
||||
event,
|
||||
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 emitTo(
|
||||
target,
|
||||
event,
|
||||
payload
|
||||
) {
|
||||
await invoke('plugin:event|emit_to', {
|
||||
target,
|
||||
event,
|
||||
payload
|
||||
})
|
||||
}
|
||||
async function once(event, windowLabel, handler) {
|
||||
return listen(event, windowLabel, (eventData) => {
|
||||
handler(eventData);
|
||||
_unlisten(event, eventData.id).catch(() => {
|
||||
});
|
||||
});
|
||||
async function listen(event, handler, options) {
|
||||
const target =
|
||||
typeof options?.target === 'string'
|
||||
? { kind: 'AnyLabel', label: options.target }
|
||||
: options?.target ?? { kind: 'Any' }
|
||||
return invoke('plugin:event|listen', {
|
||||
event,
|
||||
target,
|
||||
handler: transformCallback(handler)
|
||||
}).then((eventId) => {
|
||||
return async () => _unlisten(event, eventId)
|
||||
})
|
||||
}
|
||||
async function once(event, handler, options) {
|
||||
return listen(
|
||||
event,
|
||||
(eventData) => {
|
||||
handler(eventData)
|
||||
_unlisten(event, eventData.id).catch(() => { })
|
||||
},
|
||||
options
|
||||
)
|
||||
}
|
||||
|
||||
// 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;
|
||||
TauriEvent2["WINDOW_RESIZED"] = 'tauri://resize';
|
||||
TauriEvent2["WINDOW_MOVED"] = 'tauri://move';
|
||||
TauriEvent2["WINDOW_CLOSE_REQUESTED"] = 'tauri://close-requested';
|
||||
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_CREATED"] = 'tauri://window-created';
|
||||
TauriEvent2["WEBVIEW_CREATED"] = 'tauri://webview-created';
|
||||
TauriEvent2["DRAG"] = 'tauri://drag';
|
||||
TauriEvent2["DROP"] = 'tauri://drop';
|
||||
TauriEvent2["DROP_OVER"] = 'tauri://drop-over';
|
||||
TauriEvent2["DROP_CANCELLED"] = 'tauri://drag-cancelled';
|
||||
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
|
||||
TauriEvent,
|
||||
emit,
|
||||
emitTo,
|
||||
listen,
|
||||
once
|
||||
};
|
||||
|
|
181
src/event.rs
181
src/event.rs
|
@ -17,8 +17,22 @@ pub struct Event<T> {
|
|||
pub id: f32,
|
||||
/// Event payload
|
||||
pub payload: T,
|
||||
/// The label of the window that emitted this event
|
||||
pub window_label: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize)]
|
||||
#[serde(tag = "kind", content = "label")]
|
||||
pub enum EventTarget {
|
||||
Any,
|
||||
AnyLabel(String),
|
||||
App,
|
||||
Window(String),
|
||||
Webview(String),
|
||||
WebviewWindow(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize)]
|
||||
struct Options {
|
||||
target: EventTarget,
|
||||
}
|
||||
|
||||
/// Emits an event to the backend.
|
||||
|
@ -46,8 +60,42 @@ pub async fn emit<T: Serialize>(event: &str, payload: &T) -> crate::Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Emits an event to the backend.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_api::event::{EventTarget, emit_to};
|
||||
/// use serde::Serialize;
|
||||
///
|
||||
/// #[derive(Serialize)]
|
||||
/// struct Payload {
|
||||
/// logged_in: bool,
|
||||
/// token: String
|
||||
/// }
|
||||
///
|
||||
/// emit_to(EventTarget::Any, "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_to<T: Serialize>(
|
||||
target: &EventTarget,
|
||||
event: &str,
|
||||
payload: &T,
|
||||
) -> crate::Result<()> {
|
||||
inner::emitTo(
|
||||
serde_wasm_bindgen::to_value(target)?,
|
||||
event,
|
||||
serde_wasm_bindgen::to_value(payload)?,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Listen to an event from the backend.
|
||||
///
|
||||
///
|
||||
/// The returned Future will automatically clean up it's underlying event listener when dropped, so no manual unlisten function needs to be called.
|
||||
/// See [Differences to the JavaScript API](../index.html#differences-to-the-javascript-api) for details.
|
||||
///
|
||||
|
@ -56,8 +104,9 @@ pub async fn emit<T: Serialize>(event: &str, payload: &T) -> crate::Result<()> {
|
|||
/// ```rust,no_run
|
||||
/// use tauri_api::event::listen;
|
||||
/// use web_sys::console;
|
||||
/// use futures::StreamExt;
|
||||
///
|
||||
/// let events = listen::<String>("error");
|
||||
/// let events = listen::<String>("error", EventTarget::Any);
|
||||
///
|
||||
/// while let Some(event) = events.next().await {
|
||||
/// console::log_1(&format!("Got error in window {}, payload: {}", event.window_label, event.payload).into());
|
||||
|
@ -73,7 +122,59 @@ where
|
|||
let closure = Closure::<dyn FnMut(JsValue)>::new(move |raw| {
|
||||
let _ = tx.unbounded_send(serde_wasm_bindgen::from_value(raw).unwrap());
|
||||
});
|
||||
let unlisten = inner::listen(event, &closure).await?;
|
||||
let unlisten = inner::listen(
|
||||
event,
|
||||
&closure,
|
||||
serde_wasm_bindgen::to_value(&Options {
|
||||
target: EventTarget::Any,
|
||||
})?,
|
||||
)
|
||||
.await?;
|
||||
closure.forget();
|
||||
|
||||
Ok(Listen {
|
||||
rx,
|
||||
unlisten: js_sys::Function::from(unlisten),
|
||||
})
|
||||
}
|
||||
|
||||
/// Listen to an event from the backend.
|
||||
///
|
||||
/// The returned Future will automatically clean up it's underlying event listener when dropped, so no manual unlisten function needs to be called.
|
||||
/// See [Differences to the JavaScript API](../index.html#differences-to-the-javascript-api) for details.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_api::event::{EventTarget, listen_to};
|
||||
/// use web_sys::console;
|
||||
/// use futures::StreamExt;
|
||||
///
|
||||
/// let events = listen_to::<String>("error", EventTarget::Any);
|
||||
///
|
||||
/// while let Some(event) = events.next().await {
|
||||
/// console::log_1(&format!("Got error in window {}, payload: {}", event.window_label, event.payload).into());
|
||||
/// }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn listen_to<T>(
|
||||
event: &str,
|
||||
target: EventTarget,
|
||||
) -> crate::Result<impl Stream<Item = Event<T>>>
|
||||
where
|
||||
T: DeserializeOwned + 'static,
|
||||
{
|
||||
let (tx, rx) = mpsc::unbounded::<Event<T>>();
|
||||
|
||||
let closure = Closure::<dyn FnMut(JsValue)>::new(move |raw| {
|
||||
let _ = tx.unbounded_send(serde_wasm_bindgen::from_value(raw).unwrap());
|
||||
});
|
||||
let unlisten = inner::listen(
|
||||
event,
|
||||
&closure,
|
||||
serde_wasm_bindgen::to_value(&Options { target })?,
|
||||
)
|
||||
.await?;
|
||||
closure.forget();
|
||||
|
||||
Ok(Listen {
|
||||
|
@ -109,7 +210,7 @@ impl<T> Stream for Listen<T> {
|
|||
///
|
||||
/// The returned Future will automatically clean up it's underlying event listener when dropped, so no manual unlisten function needs to be called.
|
||||
/// See [Differences to the JavaScript API](../index.html#differences-to-the-javascript-api) for details.
|
||||
///
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
|
@ -122,10 +223,10 @@ impl<T> Stream for Listen<T> {
|
|||
/// logged_in: bool,
|
||||
/// token: String
|
||||
/// }
|
||||
///
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// const event = once::<LoadedPayload>("loaded").await?;
|
||||
///
|
||||
///
|
||||
/// console::log_1!(&format!("App is loaded, loggedIn: {}, token: {}", event.payload.logged_in, event.payload.token).into());
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
|
@ -140,7 +241,65 @@ where
|
|||
let closure: Closure<dyn FnMut(JsValue)> = Closure::once(move |raw| {
|
||||
let _ = tx.send(serde_wasm_bindgen::from_value(raw).unwrap());
|
||||
});
|
||||
let unlisten = inner::once(event, &closure).await?;
|
||||
let unlisten = inner::once(
|
||||
event,
|
||||
&closure,
|
||||
serde_wasm_bindgen::to_value(&Options {
|
||||
target: EventTarget::Any,
|
||||
})?,
|
||||
)
|
||||
.await?;
|
||||
closure.forget();
|
||||
|
||||
let fut = Once {
|
||||
rx,
|
||||
unlisten: js_sys::Function::from(unlisten),
|
||||
};
|
||||
|
||||
fut.await
|
||||
}
|
||||
|
||||
/// Listen to an one-off event from the backend.
|
||||
///
|
||||
/// The returned Future will automatically clean up it's underlying event listener when dropped, so no manual unlisten function needs to be called.
|
||||
/// See [Differences to the JavaScript API](../index.html#differences-to-the-javascript-api) for details.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_api::event::{EventTarget, once_to};
|
||||
/// use serde::Deserialize;
|
||||
/// use web_sys::console;
|
||||
///
|
||||
/// #[derive(Deserialize)]
|
||||
/// interface LoadedPayload {
|
||||
/// logged_in: bool,
|
||||
/// token: String
|
||||
/// }
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// const event = once_to::<LoadedPayload>("loaded", EventTarget::Any).await?;
|
||||
///
|
||||
/// console::log_1!(&format!("App is loaded, loggedIn: {}, token: {}", event.payload.logged_in, event.payload.token).into());
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn once_to<T>(event: &str, target: EventTarget) -> crate::Result<Event<T>>
|
||||
where
|
||||
T: DeserializeOwned + 'static,
|
||||
{
|
||||
let (tx, rx) = oneshot::channel::<Event<T>>();
|
||||
|
||||
let closure: Closure<dyn FnMut(JsValue)> = Closure::once(move |raw| {
|
||||
let _ = tx.send(serde_wasm_bindgen::from_value(raw).unwrap());
|
||||
});
|
||||
let unlisten = inner::once(
|
||||
event,
|
||||
&closure,
|
||||
serde_wasm_bindgen::to_value(&Options { target })?,
|
||||
)
|
||||
.await?;
|
||||
closure.forget();
|
||||
|
||||
let fut = Once {
|
||||
|
@ -186,14 +345,18 @@ mod inner {
|
|||
#[wasm_bindgen(catch)]
|
||||
pub async fn emit(event: &str, payload: JsValue) -> Result<(), JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn emitTo(target: JsValue, event: &str, payload: JsValue) -> Result<(), JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn listen(
|
||||
event: &str,
|
||||
handler: &Closure<dyn FnMut(JsValue)>,
|
||||
options: JsValue,
|
||||
) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn once(
|
||||
event: &str,
|
||||
handler: &Closure<dyn FnMut(JsValue)>,
|
||||
options: JsValue,
|
||||
) -> Result<JsValue, JsValue>;
|
||||
}
|
||||
}
|
||||
|
|
243
src/fs.js
243
src/fs.js
|
@ -1,243 +0,0 @@
|
|||
// 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/fs.ts
|
||||
var BaseDirectory = /* @__PURE__ */ ((BaseDirectory2) => {
|
||||
BaseDirectory2[BaseDirectory2["Audio"] = 1] = "Audio";
|
||||
BaseDirectory2[BaseDirectory2["Cache"] = 2] = "Cache";
|
||||
BaseDirectory2[BaseDirectory2["Config"] = 3] = "Config";
|
||||
BaseDirectory2[BaseDirectory2["Data"] = 4] = "Data";
|
||||
BaseDirectory2[BaseDirectory2["LocalData"] = 5] = "LocalData";
|
||||
BaseDirectory2[BaseDirectory2["Desktop"] = 6] = "Desktop";
|
||||
BaseDirectory2[BaseDirectory2["Document"] = 7] = "Document";
|
||||
BaseDirectory2[BaseDirectory2["Download"] = 8] = "Download";
|
||||
BaseDirectory2[BaseDirectory2["Executable"] = 9] = "Executable";
|
||||
BaseDirectory2[BaseDirectory2["Font"] = 10] = "Font";
|
||||
BaseDirectory2[BaseDirectory2["Home"] = 11] = "Home";
|
||||
BaseDirectory2[BaseDirectory2["Picture"] = 12] = "Picture";
|
||||
BaseDirectory2[BaseDirectory2["Public"] = 13] = "Public";
|
||||
BaseDirectory2[BaseDirectory2["Runtime"] = 14] = "Runtime";
|
||||
BaseDirectory2[BaseDirectory2["Template"] = 15] = "Template";
|
||||
BaseDirectory2[BaseDirectory2["Video"] = 16] = "Video";
|
||||
BaseDirectory2[BaseDirectory2["Resource"] = 17] = "Resource";
|
||||
BaseDirectory2[BaseDirectory2["App"] = 18] = "App";
|
||||
BaseDirectory2[BaseDirectory2["Log"] = 19] = "Log";
|
||||
BaseDirectory2[BaseDirectory2["Temp"] = 20] = "Temp";
|
||||
BaseDirectory2[BaseDirectory2["AppConfig"] = 21] = "AppConfig";
|
||||
BaseDirectory2[BaseDirectory2["AppData"] = 22] = "AppData";
|
||||
BaseDirectory2[BaseDirectory2["AppLocalData"] = 23] = "AppLocalData";
|
||||
BaseDirectory2[BaseDirectory2["AppCache"] = 24] = "AppCache";
|
||||
BaseDirectory2[BaseDirectory2["AppLog"] = 25] = "AppLog";
|
||||
return BaseDirectory2;
|
||||
})(BaseDirectory || {});
|
||||
async function readTextFile(filePath, options = {}) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Fs",
|
||||
message: {
|
||||
cmd: "readTextFile",
|
||||
path: filePath,
|
||||
options
|
||||
}
|
||||
});
|
||||
}
|
||||
async function readBinaryFile(filePath, options = {}) {
|
||||
const arr = await invokeTauriCommand({
|
||||
__tauriModule: "Fs",
|
||||
message: {
|
||||
cmd: "readFile",
|
||||
path: filePath,
|
||||
options
|
||||
}
|
||||
});
|
||||
return Uint8Array.from(arr);
|
||||
}
|
||||
async function writeTextFile(path, contents, options) {
|
||||
if (typeof options === "object") {
|
||||
Object.freeze(options);
|
||||
}
|
||||
if (typeof path === "object") {
|
||||
Object.freeze(path);
|
||||
}
|
||||
const file = { path: "", contents: "" };
|
||||
let fileOptions = options;
|
||||
if (typeof path === "string") {
|
||||
file.path = path;
|
||||
} else {
|
||||
file.path = path.path;
|
||||
file.contents = path.contents;
|
||||
}
|
||||
if (typeof contents === "string") {
|
||||
file.contents = contents ?? "";
|
||||
} else {
|
||||
fileOptions = contents;
|
||||
}
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Fs",
|
||||
message: {
|
||||
cmd: "writeFile",
|
||||
path: file.path,
|
||||
contents: Array.from(new TextEncoder().encode(file.contents)),
|
||||
options: fileOptions
|
||||
}
|
||||
});
|
||||
}
|
||||
async function writeBinaryFile(path, contents, options) {
|
||||
if (typeof options === "object") {
|
||||
Object.freeze(options);
|
||||
}
|
||||
if (typeof path === "object") {
|
||||
Object.freeze(path);
|
||||
}
|
||||
const file = { path: "", contents: [] };
|
||||
let fileOptions = options;
|
||||
if (typeof path === "string") {
|
||||
file.path = path;
|
||||
} else {
|
||||
file.path = path.path;
|
||||
file.contents = path.contents;
|
||||
}
|
||||
if (contents && "dir" in contents) {
|
||||
fileOptions = contents;
|
||||
} else if (typeof path === "string") {
|
||||
file.contents = contents ?? [];
|
||||
}
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Fs",
|
||||
message: {
|
||||
cmd: "writeFile",
|
||||
path: file.path,
|
||||
contents: Array.from(
|
||||
file.contents instanceof ArrayBuffer ? new Uint8Array(file.contents) : file.contents
|
||||
),
|
||||
options: fileOptions
|
||||
}
|
||||
});
|
||||
}
|
||||
async function readDir(dir, options = {}) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Fs",
|
||||
message: {
|
||||
cmd: "readDir",
|
||||
path: dir,
|
||||
options
|
||||
}
|
||||
});
|
||||
}
|
||||
async function createDir(dir, options = {}) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Fs",
|
||||
message: {
|
||||
cmd: "createDir",
|
||||
path: dir,
|
||||
options
|
||||
}
|
||||
});
|
||||
}
|
||||
async function removeDir(dir, options = {}) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Fs",
|
||||
message: {
|
||||
cmd: "removeDir",
|
||||
path: dir,
|
||||
options
|
||||
}
|
||||
});
|
||||
}
|
||||
async function copyFile(source, destination, options = {}) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Fs",
|
||||
message: {
|
||||
cmd: "copyFile",
|
||||
source,
|
||||
destination,
|
||||
options
|
||||
}
|
||||
});
|
||||
}
|
||||
async function removeFile(file, options = {}) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Fs",
|
||||
message: {
|
||||
cmd: "removeFile",
|
||||
path: file,
|
||||
options
|
||||
}
|
||||
});
|
||||
}
|
||||
async function renameFile(oldPath, newPath, options = {}) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Fs",
|
||||
message: {
|
||||
cmd: "renameFile",
|
||||
oldPath,
|
||||
newPath,
|
||||
options
|
||||
}
|
||||
});
|
||||
}
|
||||
async function exists(path, options = {}) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Fs",
|
||||
message: {
|
||||
cmd: "exists",
|
||||
path,
|
||||
options
|
||||
}
|
||||
});
|
||||
}
|
||||
export {
|
||||
BaseDirectory,
|
||||
BaseDirectory as Dir,
|
||||
copyFile,
|
||||
createDir,
|
||||
exists,
|
||||
readBinaryFile,
|
||||
readDir,
|
||||
readTextFile,
|
||||
removeDir,
|
||||
removeFile,
|
||||
renameFile,
|
||||
writeBinaryFile,
|
||||
writeTextFile as writeFile,
|
||||
writeTextFile
|
||||
};
|
513
src/fs.rs
513
src/fs.rs
|
@ -1,513 +0,0 @@
|
|||
//! Access the file system.
|
||||
//!
|
||||
//! The APIs must be added to `tauri.allowlist.fs` in `tauri.conf.json`:
|
||||
//! ```json
|
||||
//! {
|
||||
//! "tauri": {
|
||||
//! "allowlist": {
|
||||
//! "fs": {
|
||||
//! "all": true, // enable all FS APIs
|
||||
//! "readFile": true,
|
||||
//! "writeFile": true,
|
||||
//! "readDir": true,
|
||||
//! "copyFile": true,
|
||||
//! "createDir": true,
|
||||
//! "removeDir": true,
|
||||
//! "removeFile": true,
|
||||
//! "renameFile": true,
|
||||
//! "exists": true
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//! It is recommended to allowlist only the APIs you use for optimal bundle size and security.
|
||||
use crate::Error;
|
||||
use js_sys::ArrayBuffer;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_repr::*;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str;
|
||||
|
||||
#[derive(Serialize_repr, Clone, PartialEq, Eq, Debug)]
|
||||
#[repr(u16)]
|
||||
pub enum BaseDirectory {
|
||||
Audio = 1,
|
||||
Cache = 2,
|
||||
Config = 3,
|
||||
Data = 4,
|
||||
LocalData = 5,
|
||||
Desktop = 6,
|
||||
Document = 7,
|
||||
Download = 8,
|
||||
Executable = 9,
|
||||
Font = 10,
|
||||
Home = 11,
|
||||
Picture = 12,
|
||||
Public = 13,
|
||||
Runtime = 14,
|
||||
Template = 15,
|
||||
Video = 16,
|
||||
Resource = 17,
|
||||
App = 18,
|
||||
Log = 19,
|
||||
Temp = 20,
|
||||
AppConfig = 21,
|
||||
AppData = 22,
|
||||
AppLocalData = 23,
|
||||
AppCache = 24,
|
||||
AppLog = 25,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone, PartialEq, Debug)]
|
||||
pub struct FileEntry {
|
||||
pub path: PathBuf,
|
||||
pub name: Option<String>,
|
||||
pub children: Option<Vec<FileEntry>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone, PartialEq, Debug)]
|
||||
struct FsDirOptions {
|
||||
pub dir: Option<BaseDirectory>,
|
||||
pub recursive: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone, PartialEq, Debug)]
|
||||
struct FsOptions {
|
||||
pub dir: Option<BaseDirectory>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone, PartialEq, Debug)]
|
||||
struct FsTextFileOption {
|
||||
pub contents: String,
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
/// Copies a file to a destination.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::fs;
|
||||
///
|
||||
/// fs::copy_file(source, destination, BaseDirectory::Download).expect("could not copy file");
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > fs > copyFile`](https://tauri.app/v1/api/js/fs) to be enabled.
|
||||
pub async fn copy_file(source: &Path, destination: &Path, dir: BaseDirectory) -> crate::Result<()> {
|
||||
let Some(source) = source.to_str() else {
|
||||
return Err(Error::Utf8(source.to_path_buf()));
|
||||
};
|
||||
|
||||
let Some(destination) = destination.to_str() else {
|
||||
return Err(Error::Utf8(destination.to_path_buf()));
|
||||
};
|
||||
|
||||
let raw = inner::copyFile(
|
||||
source,
|
||||
destination,
|
||||
serde_wasm_bindgen::to_value(&FsOptions { dir: Some(dir) })?,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Creates a directory.
|
||||
/// If one of the path's parent components doesn't exist the promise will be rejected.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::fs;
|
||||
///
|
||||
/// fs::create_dir(dir, BaseDirectory::Download).expect("could not create directory");
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > fs > createDir`](https://tauri.app/v1/api/js/fs) to be enabled.
|
||||
pub async fn create_dir(dir: &Path, base_dir: BaseDirectory) -> crate::Result<()> {
|
||||
let recursive = Some(false);
|
||||
|
||||
let Some(dir) = dir.to_str() else {
|
||||
return Err(Error::Utf8(dir.to_path_buf()));
|
||||
};
|
||||
|
||||
Ok(inner::createDir(
|
||||
dir,
|
||||
serde_wasm_bindgen::to_value(&FsDirOptions {
|
||||
dir: Some(base_dir),
|
||||
recursive,
|
||||
})?,
|
||||
)
|
||||
.await?)
|
||||
}
|
||||
|
||||
/// Creates a directory recursively.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::fs;
|
||||
///
|
||||
/// fs::create_dir_all(dir, BaseDirectory::Download).expect("could not create directory");
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > fs > createDir`](https://tauri.app/v1/api/js/fs) to be enabled.
|
||||
pub async fn create_dir_all(dir: &Path, base_dir: BaseDirectory) -> crate::Result<()> {
|
||||
let recursive = Some(true);
|
||||
|
||||
let Some(dir) = dir.to_str() else {
|
||||
return Err(Error::Utf8(dir.to_path_buf()));
|
||||
};
|
||||
|
||||
Ok(inner::createDir(
|
||||
dir,
|
||||
serde_wasm_bindgen::to_value(&FsDirOptions {
|
||||
dir: Some(base_dir),
|
||||
recursive,
|
||||
})?,
|
||||
)
|
||||
.await?)
|
||||
}
|
||||
|
||||
/// Checks if a path exists.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::fs;
|
||||
///
|
||||
/// let file_exists = fs::exists(path, BaseDirectory::Download).expect("could not check if path exists");
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > fs > exists`](https://tauri.app/v1/api/js/fs) to be enabled.
|
||||
pub async fn exists(path: &Path, dir: BaseDirectory) -> crate::Result<bool> {
|
||||
let Some(path) = path.to_str() else {
|
||||
return Err(Error::Utf8(path.to_path_buf()));
|
||||
};
|
||||
|
||||
let raw = inner::exists(
|
||||
path,
|
||||
serde_wasm_bindgen::to_value(&FsOptions { dir: Some(dir) })?,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Reads a file as a byte array.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::fs;
|
||||
///
|
||||
/// let contents = fs::read_binary_file(filePath, BaseDirectory::Download).expect("could not read file contents");
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > fs > readBinaryFile`](https://tauri.app/v1/api/js/fs) to be enabled.
|
||||
pub async fn read_binary_file(path: &Path, dir: BaseDirectory) -> crate::Result<Vec<u8>> {
|
||||
let Some(path) = path.to_str() else {
|
||||
return Err(Error::Utf8(path.to_path_buf()));
|
||||
};
|
||||
|
||||
let raw = inner::readBinaryFile(
|
||||
path,
|
||||
serde_wasm_bindgen::to_value(&FsOptions { dir: Some(dir) })?,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// List directory files.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::fs;
|
||||
///
|
||||
/// let files = fs::read_dir(path, BaseDirectory::Download).expect("could not read directory");
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > fs > readDir`](https://tauri.app/v1/api/js/fs) to be enabled.
|
||||
pub async fn read_dir(path: &Path, dir: BaseDirectory) -> crate::Result<Vec<FileEntry>> {
|
||||
let recursive = Some(false);
|
||||
let Some(path) = path.to_str() else {
|
||||
return Err(Error::Utf8(path.to_path_buf()));
|
||||
};
|
||||
|
||||
let raw = inner::readDir(
|
||||
path,
|
||||
serde_wasm_bindgen::to_value(&FsDirOptions {
|
||||
dir: Some(dir),
|
||||
recursive,
|
||||
})?,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// List directory files recursively.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::fs;
|
||||
///
|
||||
/// let files = fs::read_dir_all(path, BaseDirectory::Download).expect("could not read directory");
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > fs > readDir`](https://tauri.app/v1/api/js/fs) to be enabled.
|
||||
pub async fn read_dir_all(path: &Path, dir: BaseDirectory) -> crate::Result<Vec<FileEntry>> {
|
||||
let recursive = Some(true);
|
||||
let Some(path) = path.to_str() else {
|
||||
return Err(Error::Utf8(path.to_path_buf()));
|
||||
};
|
||||
|
||||
let raw = inner::readDir(
|
||||
path,
|
||||
serde_wasm_bindgen::to_value(&FsDirOptions {
|
||||
dir: Some(dir),
|
||||
recursive,
|
||||
})?,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Read a file as an UTF-8 encoded string.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::fs;
|
||||
///
|
||||
/// let contents = fs::readTextFile(path, BaseDirectory::Download).expect("could not read file as text");
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > fs > readTextFile`](https://tauri.app/v1/api/js/fs) to be enabled.
|
||||
pub async fn read_text_file(path: &Path, dir: BaseDirectory) -> crate::Result<String> {
|
||||
let Some(path) = path.to_str() else {
|
||||
return Err(Error::Utf8(path.to_path_buf()));
|
||||
};
|
||||
|
||||
let raw = inner::readTextFile(
|
||||
path,
|
||||
serde_wasm_bindgen::to_value(&FsOptions { dir: Some(dir) })?,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Removes a directory.
|
||||
/// If the directory is not empty the promise will be rejected.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::fs;
|
||||
///
|
||||
/// fs::remove_dir(path, BaseDirectory::Download).expect("could not remove directory");
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > fs > removeDir`](https://tauri.app/v1/api/js/fs) to be enabled.
|
||||
pub async fn remove_dir(dir: &Path, base_dir: BaseDirectory) -> crate::Result<()> {
|
||||
let recursive = Some(false);
|
||||
let Some(dir) = dir.to_str() else {
|
||||
return Err(Error::Utf8(dir.to_path_buf()));
|
||||
};
|
||||
|
||||
Ok(inner::removeDir(
|
||||
dir,
|
||||
serde_wasm_bindgen::to_value(&FsDirOptions {
|
||||
dir: Some(base_dir),
|
||||
recursive,
|
||||
})?,
|
||||
)
|
||||
.await?)
|
||||
}
|
||||
|
||||
/// Removes a directory and its contents.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::fs;
|
||||
///
|
||||
/// fs::remove_dir_all(path, BaseDirectory::Download).expect("could not remove directory");
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > fs > removeDir`](https://tauri.app/v1/api/js/fs) to be enabled.
|
||||
pub async fn remove_dir_all(dir: &Path, base_dir: BaseDirectory) -> crate::Result<()> {
|
||||
let recursive = Some(true);
|
||||
let Some(dir) = dir.to_str() else {
|
||||
return Err(Error::Utf8(dir.to_path_buf()));
|
||||
};
|
||||
|
||||
Ok(inner::removeDir(
|
||||
dir,
|
||||
serde_wasm_bindgen::to_value(&FsDirOptions {
|
||||
dir: Some(base_dir),
|
||||
recursive,
|
||||
})?,
|
||||
)
|
||||
.await?)
|
||||
}
|
||||
|
||||
/// Removes a file.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::fs;
|
||||
///
|
||||
/// fs::remove_file(path, BaseDirectory::Download).expect("could not remove file");
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > fs > removeFile`](https://tauri.app/v1/api/js/fs) to be enabled.
|
||||
pub async fn remove_file(file: &Path, dir: BaseDirectory) -> crate::Result<()> {
|
||||
let Some(file) = file.to_str() else {
|
||||
return Err(Error::Utf8(file.to_path_buf()));
|
||||
};
|
||||
|
||||
Ok(inner::removeFile(
|
||||
file,
|
||||
serde_wasm_bindgen::to_value(&FsOptions { dir: Some(dir) })?,
|
||||
)
|
||||
.await?)
|
||||
}
|
||||
|
||||
/// Renames a file.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::fs;
|
||||
///
|
||||
/// fs::rename_file(old_path, new_path, BaseDirectory::Download).expect("could not rename file");
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > fs > renameFile`](https://tauri.app/v1/api/js/fs) to be enabled.
|
||||
pub async fn rename_file(
|
||||
old_path: &Path,
|
||||
new_path: &Path,
|
||||
dir: BaseDirectory,
|
||||
) -> crate::Result<()> {
|
||||
let Some(old_path) = old_path.to_str() else {
|
||||
return Err(Error::Utf8(old_path.to_path_buf()));
|
||||
};
|
||||
|
||||
let Some(new_path) = new_path.to_str() else {
|
||||
return Err(Error::Utf8(new_path.to_path_buf()));
|
||||
};
|
||||
|
||||
Ok(inner::renameFile(
|
||||
old_path,
|
||||
new_path,
|
||||
serde_wasm_bindgen::to_value(&FsOptions { dir: Some(dir) })?,
|
||||
)
|
||||
.await?)
|
||||
}
|
||||
|
||||
/// Writes a byte array content to a file.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::fs;
|
||||
///
|
||||
/// fs::write_binary_file(path, contents, BaseDirectory::Download).expect("could not writes binary file");
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > fs > writeBinaryFile`](https://tauri.app/v1/api/js/fs) to be enabled.
|
||||
pub async fn write_binary_file(
|
||||
path: &Path,
|
||||
contents: ArrayBuffer,
|
||||
dir: BaseDirectory,
|
||||
) -> crate::Result<()> {
|
||||
let Some(path) = path.to_str() else {
|
||||
return Err(Error::Utf8(path.to_path_buf()));
|
||||
};
|
||||
|
||||
Ok(inner::writeBinaryFile(
|
||||
path,
|
||||
contents,
|
||||
serde_wasm_bindgen::to_value(&FsOptions { dir: Some(dir) })?,
|
||||
)
|
||||
.await?)
|
||||
}
|
||||
|
||||
/// Writes a UTF-8 text file.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::fs;
|
||||
///
|
||||
/// fs::write_text_file(path, contents, BaseDirectory::Download).expect("could not writes binary file");
|
||||
/// ```
|
||||
///
|
||||
/// Requires [`allowlist > fs > writeTextFile`](https://tauri.app/v1/api/js/fs) to be enabled.
|
||||
pub async fn write_text_file(path: &Path, contents: &str, dir: BaseDirectory) -> crate::Result<()> {
|
||||
let Some(path) = path.to_str() else {
|
||||
return Err(Error::Utf8(path.to_path_buf()));
|
||||
};
|
||||
|
||||
Ok(inner::writeTextFile(
|
||||
path,
|
||||
&contents,
|
||||
serde_wasm_bindgen::to_value(&FsOptions { dir: Some(dir) })?,
|
||||
)
|
||||
.await?)
|
||||
}
|
||||
|
||||
mod inner {
|
||||
use super::ArrayBuffer;
|
||||
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
|
||||
|
||||
#[wasm_bindgen(module = "/src/fs.js")]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn copyFile(
|
||||
source: &str,
|
||||
destination: &str,
|
||||
options: JsValue,
|
||||
) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn createDir(dir: &str, options: JsValue) -> Result<(), JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn exists(path: &str, options: JsValue) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn readBinaryFile(filePath: &str, options: JsValue) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn readTextFile(filePath: &str, options: JsValue) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn readDir(dir: &str, options: JsValue) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn removeDir(dir: &str, options: JsValue) -> Result<(), JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn removeFile(source: &str, options: JsValue) -> Result<(), JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn renameFile(
|
||||
oldPath: &str,
|
||||
newPath: &str,
|
||||
options: JsValue,
|
||||
) -> Result<(), JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn writeBinaryFile(
|
||||
filePath: &str,
|
||||
contents: ArrayBuffer,
|
||||
options: JsValue,
|
||||
) -> Result<(), JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn writeTextFile(
|
||||
filePath: &str,
|
||||
contents: &str,
|
||||
options: JsValue,
|
||||
) -> Result<(), JsValue>;
|
||||
}
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
// 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/globalShortcut.ts
|
||||
async function register(shortcut, handler) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "GlobalShortcut",
|
||||
message: {
|
||||
cmd: "register",
|
||||
shortcut,
|
||||
handler: transformCallback(handler)
|
||||
}
|
||||
});
|
||||
}
|
||||
async function registerAll(shortcuts, handler) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "GlobalShortcut",
|
||||
message: {
|
||||
cmd: "registerAll",
|
||||
shortcuts,
|
||||
handler: transformCallback(handler)
|
||||
}
|
||||
});
|
||||
}
|
||||
async function isRegistered(shortcut) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "GlobalShortcut",
|
||||
message: {
|
||||
cmd: "isRegistered",
|
||||
shortcut
|
||||
}
|
||||
});
|
||||
}
|
||||
async function unregister(shortcut) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "GlobalShortcut",
|
||||
message: {
|
||||
cmd: "unregister",
|
||||
shortcut
|
||||
}
|
||||
});
|
||||
}
|
||||
async function unregisterAll() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "GlobalShortcut",
|
||||
message: {
|
||||
cmd: "unregisterAll"
|
||||
}
|
||||
});
|
||||
}
|
||||
export {
|
||||
isRegistered,
|
||||
register,
|
||||
registerAll,
|
||||
unregister,
|
||||
unregisterAll
|
||||
};
|
|
@ -1,199 +0,0 @@
|
|||
//! Register global shortcuts.
|
||||
//!
|
||||
//! ## Differences to the JavaScript API
|
||||
//!
|
||||
//! ## `registerAll`
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
//! let shortcuts = ["CommandOrControl+Shift+C", "Ctrl+Alt+F12"];
|
||||
//!
|
||||
//! let streams = futures::future::try_join_all(shortcuts.map(|s| async move {
|
||||
//! let stream = global_shortcut::register(s).await?;
|
||||
//!
|
||||
//! anyhow::Ok(stream.map(move |_| s))
|
||||
//! }))
|
||||
//! .await?;
|
||||
//!
|
||||
//! let mut events = futures::stream::select_all(streams);
|
||||
//!
|
||||
//! while let Some(shortcut) = events.next().await {
|
||||
//! log::debug!("Shortcut {} triggered", shortcut)
|
||||
//! }
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! The APIs must be added to tauri.allowlist.globalShortcut in tauri.conf.json:
|
||||
//!
|
||||
//! ```json
|
||||
//! {
|
||||
//! "tauri": {
|
||||
//! "allowlist": {
|
||||
//! "globalShortcut": {
|
||||
//! "all": true // enable all global shortcut APIs
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//! It is recommended to allowlist only the APIs you use for optimal bundle size and security.
|
||||
|
||||
use futures::{channel::mpsc, Stream, StreamExt};
|
||||
use wasm_bindgen::{prelude::Closure, JsValue};
|
||||
|
||||
/// Determines whether the given shortcut is registered by this application or not.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::global_shortcut::is_registered;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let registered = is_registered("CommandOrControl+P").await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub async fn is_registered(shortcut: &str) -> crate::Result<bool> {
|
||||
let raw = inner::isRegistered(shortcut).await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Register a global shortcut.
|
||||
///
|
||||
/// The returned Future will automatically clean up it's underlying event listener when dropped, so no manual unlisten function needs to be called.
|
||||
/// See [Differences to the JavaScript API](../index.html#differences-to-the-javascript-api) for details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::global_shortcut::register;
|
||||
/// use web_sys::console;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let events = register("CommandOrControl+Shift+C").await?;
|
||||
///
|
||||
/// while let Some(_) in events.next().await {
|
||||
/// console::log_1(&"Shortcut triggered".into());
|
||||
/// }
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub async fn register(shortcut: &str) -> crate::Result<impl Stream<Item = ()>> {
|
||||
let (tx, rx) = mpsc::unbounded();
|
||||
|
||||
let closure = Closure::<dyn FnMut(JsValue)>::new(move |_| {
|
||||
let _ = tx.unbounded_send(());
|
||||
});
|
||||
inner::register(shortcut, &closure).await?;
|
||||
closure.forget();
|
||||
|
||||
Ok(Listen {
|
||||
shortcut: JsValue::from_str(shortcut),
|
||||
rx,
|
||||
})
|
||||
}
|
||||
|
||||
struct Listen<T> {
|
||||
pub shortcut: JsValue,
|
||||
pub rx: mpsc::UnboundedReceiver<T>,
|
||||
}
|
||||
|
||||
impl<T> Drop for Listen<T> {
|
||||
fn drop(&mut self) {
|
||||
log::debug!("Unregistering shortcut {:?}", self.shortcut);
|
||||
inner::unregister(self.shortcut.clone());
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Stream for Listen<T> {
|
||||
type Item = T;
|
||||
|
||||
fn poll_next(
|
||||
mut self: std::pin::Pin<&mut Self>,
|
||||
cx: &mut std::task::Context<'_>,
|
||||
) -> std::task::Poll<Option<Self::Item>> {
|
||||
self.rx.poll_next_unpin(cx)
|
||||
}
|
||||
}
|
||||
|
||||
/// Register a collection of global shortcuts.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::global_shortcut::register;
|
||||
/// use web_sys::console;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let events = register_all(["CommandOrControl+Shift+C", "Ctrl+Alt+F12"]).await?;
|
||||
///
|
||||
/// while let Some(shortcut) in events.next().await {
|
||||
/// console::log_1(&format!("Shortcut {} triggered", shortcut).into());
|
||||
/// }
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
// pub async fn register_all<I>(shortcuts: impl IntoIterator<Item = &str>) -> crate::Result<impl Stream<Item = String>>
|
||||
// {
|
||||
// let shortcuts: Array = shortcuts.into_iter().map(JsValue::from_str).collect();
|
||||
// let (tx, rx) = mpsc::unbounded::<String>();
|
||||
|
||||
// let closure = Closure::<dyn FnMut(JsValue)>::new(move |raw| {
|
||||
// let _ = tx.unbounded_send(serde_wasm_bindgen::from_value(raw).unwrap());
|
||||
// });
|
||||
// inner::registerAll(shortcuts.clone(), &closure).await?;
|
||||
// closure.forget();
|
||||
|
||||
// Ok(ListenAll { shortcuts, rx })
|
||||
// }
|
||||
|
||||
// struct ListenAll<T> {
|
||||
// pub shortcuts: js_sys::Array,
|
||||
// pub rx: mpsc::UnboundedReceiver<T>,
|
||||
// }
|
||||
|
||||
// impl<T> Drop for ListenAll<T> {
|
||||
// fn drop(&mut self) {
|
||||
// for shortcut in self.shortcuts.iter() {
|
||||
// inner::unregister(shortcut);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl<T> Stream for ListenAll<T> {
|
||||
// type Item = T;
|
||||
|
||||
// fn poll_next(
|
||||
// mut self: std::pin::Pin<&mut Self>,
|
||||
// cx: &mut std::task::Context<'_>,
|
||||
// ) -> std::task::Poll<Option<Self::Item>> {
|
||||
// self.rx.poll_next_unpin(cx)
|
||||
// }
|
||||
// }
|
||||
|
||||
mod inner {
|
||||
// use js_sys::Array;
|
||||
use wasm_bindgen::{
|
||||
prelude::{wasm_bindgen, Closure},
|
||||
JsValue,
|
||||
};
|
||||
|
||||
#[wasm_bindgen(module = "/src/globalShortcut.js")]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn isRegistered(shortcut: &str) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn register(
|
||||
shortcut: &str,
|
||||
handler: &Closure<dyn FnMut(JsValue)>,
|
||||
) -> Result<(), JsValue>;
|
||||
// #[wasm_bindgen(catch)]
|
||||
// pub async fn registerAll(
|
||||
// shortcuts: Array,
|
||||
// handler: &Closure<dyn FnMut(JsValue)>,
|
||||
// ) -> Result<(), JsValue>;
|
||||
pub fn unregister(shortcut: JsValue);
|
||||
}
|
||||
}
|
229
src/http.js
229
src/http.js
|
@ -1,229 +0,0 @@
|
|||
// 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/http.ts
|
||||
var ResponseType = /* @__PURE__ */ ((ResponseType2) => {
|
||||
ResponseType2[ResponseType2["JSON"] = 1] = "JSON";
|
||||
ResponseType2[ResponseType2["Text"] = 2] = "Text";
|
||||
ResponseType2[ResponseType2["Binary"] = 3] = "Binary";
|
||||
return ResponseType2;
|
||||
})(ResponseType || {});
|
||||
async function formBody(data) {
|
||||
const form = {};
|
||||
const append = async (key, v) => {
|
||||
if (v !== null) {
|
||||
let r;
|
||||
if (typeof v === "string") {
|
||||
r = v;
|
||||
} else if (v instanceof Uint8Array || Array.isArray(v)) {
|
||||
r = Array.from(v);
|
||||
} else if (v instanceof File) {
|
||||
r = {
|
||||
file: Array.from(new Uint8Array(await v.arrayBuffer())),
|
||||
mime: v.type,
|
||||
fileName: v.name
|
||||
};
|
||||
} else if (typeof v.file === "string") {
|
||||
r = { file: v.file, mime: v.mime, fileName: v.fileName };
|
||||
} else {
|
||||
r = { file: Array.from(v.file), mime: v.mime, fileName: v.fileName };
|
||||
}
|
||||
form[String(key)] = r;
|
||||
}
|
||||
};
|
||||
if (data instanceof FormData) {
|
||||
for (const [key, value] of data) {
|
||||
await append(key, value);
|
||||
}
|
||||
} else {
|
||||
for (const [key, value] of Object.entries(data)) {
|
||||
await append(key, value);
|
||||
}
|
||||
}
|
||||
return form;
|
||||
}
|
||||
var Body = class {
|
||||
constructor(type, payload) {
|
||||
this.type = type;
|
||||
this.payload = payload;
|
||||
}
|
||||
static form(data) {
|
||||
return new Body("Form", data);
|
||||
}
|
||||
static json(data) {
|
||||
return new Body("Json", data);
|
||||
}
|
||||
static text(value) {
|
||||
return new Body("Text", value);
|
||||
}
|
||||
static bytes(bytes) {
|
||||
return new Body(
|
||||
"Bytes",
|
||||
Array.from(bytes instanceof ArrayBuffer ? new Uint8Array(bytes) : bytes)
|
||||
);
|
||||
}
|
||||
};
|
||||
var Response = class {
|
||||
constructor(response) {
|
||||
this.url = response.url;
|
||||
this.status = response.status;
|
||||
this.ok = this.status >= 200 && this.status < 300;
|
||||
this.headers = response.headers;
|
||||
this.rawHeaders = response.rawHeaders;
|
||||
this.data = response.data;
|
||||
}
|
||||
};
|
||||
var Client = class {
|
||||
constructor(id) {
|
||||
this.id = id;
|
||||
}
|
||||
async drop() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Http",
|
||||
message: {
|
||||
cmd: "dropClient",
|
||||
client: this.id
|
||||
}
|
||||
});
|
||||
}
|
||||
async request(options) {
|
||||
const jsonResponse = !options.responseType || options.responseType === 1 /* JSON */;
|
||||
if (jsonResponse) {
|
||||
options.responseType = 2 /* Text */;
|
||||
}
|
||||
if (options.body?.type === "Form") {
|
||||
options.body.payload = await formBody(options.body.payload);
|
||||
}
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Http",
|
||||
message: {
|
||||
cmd: "httpRequest",
|
||||
client: this.id,
|
||||
options
|
||||
}
|
||||
}).then((res) => {
|
||||
const response = new Response(res);
|
||||
if (jsonResponse) {
|
||||
try {
|
||||
response.data = JSON.parse(response.data);
|
||||
} catch (e) {
|
||||
if (response.ok && response.data === "") {
|
||||
response.data = {};
|
||||
} else if (response.ok) {
|
||||
throw Error(
|
||||
`Failed to parse response \`${response.data}\` as JSON: ${e};
|
||||
try setting the \`responseType\` option to \`ResponseType.Text\` or \`ResponseType.Binary\` if the API does not return a JSON response.`
|
||||
);
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
return response;
|
||||
});
|
||||
}
|
||||
async get(url, options) {
|
||||
return this.request({
|
||||
method: "GET",
|
||||
url,
|
||||
...options
|
||||
});
|
||||
}
|
||||
async post(url, body, options) {
|
||||
return this.request({
|
||||
method: "POST",
|
||||
url,
|
||||
body,
|
||||
...options
|
||||
});
|
||||
}
|
||||
async put(url, body, options) {
|
||||
return this.request({
|
||||
method: "PUT",
|
||||
url,
|
||||
body,
|
||||
...options
|
||||
});
|
||||
}
|
||||
async patch(url, options) {
|
||||
return this.request({
|
||||
method: "PATCH",
|
||||
url,
|
||||
...options
|
||||
});
|
||||
}
|
||||
async delete(url, options) {
|
||||
return this.request({
|
||||
method: "DELETE",
|
||||
url,
|
||||
...options
|
||||
});
|
||||
}
|
||||
};
|
||||
async function getClient(options) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Http",
|
||||
message: {
|
||||
cmd: "createClient",
|
||||
options
|
||||
}
|
||||
}).then((id) => new Client(id));
|
||||
}
|
||||
var defaultClient = null;
|
||||
async function fetch(url, options) {
|
||||
if (defaultClient === null) {
|
||||
defaultClient = await getClient();
|
||||
}
|
||||
return defaultClient.request({
|
||||
url,
|
||||
method: options?.method ?? "GET",
|
||||
...options
|
||||
});
|
||||
}
|
||||
export {
|
||||
Body,
|
||||
Client,
|
||||
Response,
|
||||
ResponseType,
|
||||
fetch,
|
||||
getClient
|
||||
};
|
2607
src/index.js
2607
src/index.js
File diff suppressed because it is too large
Load diff
111
src/lib.rs
111
src/lib.rs
|
@ -1,4 +1,4 @@
|
|||
//! Bindings to the [`Tauri API`](https://tauri.app/v1/api/js/) for projects using [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen)
|
||||
//! Bindings to the [`Tauri API`](https://v2.tauri.app) for projects using [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen)
|
||||
//!
|
||||
//! Tauri is a framework for building tiny, blazing fast, and secure cross-platform applications.
|
||||
//! Developers can integrate any front-end framework that compiles to HTML, JS and CSS for building their user interface.
|
||||
|
@ -13,7 +13,7 @@
|
|||
//!
|
||||
//! ## Event Listeners
|
||||
//!
|
||||
//! Event Listeners, such as [`event::listen`] module or [`window::WebviewWindow::listen`],
|
||||
//! Event Listeners, such as [`event::listen`] module,
|
||||
//! are modeled as async streams of data using the [`futures::Stream`] trait instead of using callbacks.
|
||||
//! Streams have multiple advantages over callbacks:
|
||||
//!
|
||||
|
@ -22,39 +22,6 @@
|
|||
//! Streams are essentially the async equivalent of the standard [`Iterator`] and therefore expose a very similar set of combinator functions.
|
||||
//! This means streams are much more versatile and ergonomic than simple callbacks.
|
||||
//!
|
||||
//! For example, we can use Stream combinators and various utility functions
|
||||
//! to replicate the `registerAll` function that unregisters the shortcuts after 20 seconds:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use futures::{future, stream, Stream, StreamExt};
|
||||
//! use std::time::Duration;
|
||||
//! use tauri_sys::global_shortcut;
|
||||
//!
|
||||
//! async fn register_with_shortcut<'a>(
|
||||
//! shortcut: &'a str,
|
||||
//! ) -> anyhow::Result<impl Stream<Item = &'a str>> {
|
||||
//! let stream = global_shortcut::register(shortcut).await?;
|
||||
//!
|
||||
//! Ok(stream.map(move |_| shortcut))
|
||||
//! }
|
||||
//!
|
||||
//! async fn register_all() {
|
||||
//! let shortcuts = ["CommandOrControl+Shift+C", "Ctrl+Alt+F12"];
|
||||
//!
|
||||
//! let timeout = gloo_timers::future::sleep(Duration::from_secs(20));
|
||||
//!
|
||||
//! // await the futures that creates the streams, exiting early if any future resolves with an error
|
||||
//! let streams = future::try_join_all(shortcuts.map(register_with_shortcut)).await?;
|
||||
//!
|
||||
//! // combine all streams into one
|
||||
//! let mut events = stream::select_all(streams).take_until(timeout);
|
||||
//!
|
||||
//! while let Some(shortcut) = events.next().await {
|
||||
//! log::debug!("Shortcut {} triggered", shortcut);
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! #### Automatic cleanup
|
||||
//!
|
||||
//! Streams follow Rust's RAII idiom as they automatically clean up after themselves when being dropped.
|
||||
|
@ -118,65 +85,39 @@
|
|||
//! abort_handle.abort();
|
||||
//! ```
|
||||
|
||||
#[cfg(feature = "app")]
|
||||
pub mod app;
|
||||
#[cfg(feature = "clipboard")]
|
||||
pub mod clipboard;
|
||||
#[cfg(feature = "dialog")]
|
||||
pub mod dialog;
|
||||
mod error;
|
||||
#[cfg(feature = "event")]
|
||||
pub mod event;
|
||||
#[cfg(feature = "fs")]
|
||||
pub mod fs;
|
||||
#[cfg(feature = "global_shortcut")]
|
||||
pub mod global_shortcut;
|
||||
#[cfg(feature = "mocks")]
|
||||
pub mod mocks;
|
||||
#[cfg(feature = "notification")]
|
||||
pub mod notification;
|
||||
#[cfg(feature = "os")]
|
||||
pub mod os;
|
||||
#[cfg(feature = "path")]
|
||||
pub mod path;
|
||||
#[cfg(feature = "process")]
|
||||
pub mod process;
|
||||
#[cfg(feature = "tauri")]
|
||||
pub mod tauri;
|
||||
#[cfg(feature = "updater")]
|
||||
pub mod updater;
|
||||
#[cfg(feature = "window")]
|
||||
pub mod window;
|
||||
|
||||
pub use error::Error;
|
||||
pub(crate) type Result<T> = core::result::Result<T, Error>;
|
||||
|
||||
#[cfg(any(feature = "dialog", feature = "window"))]
|
||||
pub(crate) mod utils {
|
||||
pub struct ArrayIterator {
|
||||
pos: u32,
|
||||
arr: js_sys::Array,
|
||||
}
|
||||
// #[cfg(any(feature = "window"))]
|
||||
// pub(crate) mod utils {
|
||||
// pub struct ArrayIterator {
|
||||
// pos: u32,
|
||||
// arr: js_sys::Array,
|
||||
// }
|
||||
|
||||
impl ArrayIterator {
|
||||
pub fn new(arr: js_sys::Array) -> Self {
|
||||
Self { pos: 0, arr }
|
||||
}
|
||||
}
|
||||
// impl ArrayIterator {
|
||||
// pub fn new(arr: js_sys::Array) -> Self {
|
||||
// Self { pos: 0, arr }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl Iterator for ArrayIterator {
|
||||
type Item = wasm_bindgen::JsValue;
|
||||
// impl Iterator for ArrayIterator {
|
||||
// type Item = wasm_bindgen::JsValue;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let raw = self.arr.get(self.pos);
|
||||
// fn next(&mut self) -> Option<Self::Item> {
|
||||
// let raw = self.arr.get(self.pos);
|
||||
|
||||
if raw.is_undefined() {
|
||||
None
|
||||
} else {
|
||||
self.pos += 1;
|
||||
// if raw.is_undefined() {
|
||||
// None
|
||||
// } else {
|
||||
// self.pos += 1;
|
||||
|
||||
Some(raw)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Some(raw)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
|
42
src/mocks.js
42
src/mocks.js
|
@ -1,42 +0,0 @@
|
|||
// 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 mockConvertFileSrc(osName, windowsProtocolScheme = "https") {
|
||||
window.__TAURI__ = window.__TAURI__ ?? {};
|
||||
window.__TAURI__.convertFileSrc = function(filePath, protocol = "asset") {
|
||||
const path = encodeURIComponent(filePath);
|
||||
return osName === "windows" ? `${windowsProtocolScheme}://${protocol}.localhost/${path}` : `${protocol}://localhost/${path}`;
|
||||
};
|
||||
}
|
||||
function clearMocks() {
|
||||
if (window.__TAURI__?.convertFileSrc)
|
||||
delete window.__TAURI__.convertFileSrc;
|
||||
if (window.__TAURI_IPC__)
|
||||
delete window.__TAURI_IPC__;
|
||||
if (window.__TAURI_METADATA__)
|
||||
delete window.__TAURI_METADATA__;
|
||||
}
|
||||
export {
|
||||
clearMocks,
|
||||
mockConvertFileSrc,
|
||||
mockIPC,
|
||||
mockWindows
|
||||
};
|
67
src/mocks.rs
67
src/mocks.rs
|
@ -1,67 +0,0 @@
|
|||
//!
|
||||
|
||||
use js_sys::Array;
|
||||
use wasm_bindgen::{prelude::Closure, 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<H, R, E>(mut handler: H)
|
||||
where
|
||||
H: FnMut(String, JsValue) -> Result<R, E> + 'static,
|
||||
R: Into<JsValue>,
|
||||
E: Into<JsValue>,
|
||||
{
|
||||
let closure = Closure::<dyn FnMut(String, JsValue) -> Result<JsValue, JsValue>>::new(
|
||||
move |cmd, payload| (handler)(cmd, payload).map(Into::into).map_err(Into::into),
|
||||
);
|
||||
|
||||
inner::mockIPC(&closure);
|
||||
|
||||
closure.forget();
|
||||
}
|
||||
|
||||
/// 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, Closure},
|
||||
JsValue,
|
||||
};
|
||||
|
||||
#[wasm_bindgen(module = "/src/mocks.js")]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(variadic)]
|
||||
pub fn mockWindows(current: &str, rest: JsValue);
|
||||
pub fn mockIPC(handler: &Closure<dyn FnMut(String, JsValue) -> Result<JsValue, JsValue>>);
|
||||
pub fn clearMocks();
|
||||
}
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
// 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/notification.ts
|
||||
async function isPermissionGranted() {
|
||||
if (window.Notification.permission !== "default") {
|
||||
return Promise.resolve(window.Notification.permission === "granted");
|
||||
}
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Notification",
|
||||
message: {
|
||||
cmd: "isNotificationPermissionGranted"
|
||||
}
|
||||
});
|
||||
}
|
||||
async function requestPermission() {
|
||||
return window.Notification.requestPermission();
|
||||
}
|
||||
function sendNotification(options) {
|
||||
if (typeof options === "string") {
|
||||
new window.Notification(options);
|
||||
} else {
|
||||
new window.Notification(options.title, options);
|
||||
}
|
||||
}
|
||||
export {
|
||||
isPermissionGranted,
|
||||
requestPermission,
|
||||
sendNotification
|
||||
};
|
|
@ -1,135 +0,0 @@
|
|||
//! Send toast notifications (brief auto-expiring OS window element) to your user. Can also be used with the Notification Web API.
|
||||
//!
|
||||
//! The APIs must be added to tauri.allowlist.notification in tauri.conf.json:
|
||||
//!
|
||||
//! ```json
|
||||
//! {
|
||||
//! "tauri": {
|
||||
//! "allowlist": {
|
||||
//! "notification": {
|
||||
//! "all": true // enable all notification APIs
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//! It is recommended to allowlist only the APIs you use for optimal bundle size and security.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Checks if the permission to send notifications is granted.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::notification;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let is_granted = notification::is_permission_granted().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn is_permission_granted() -> crate::Result<bool> {
|
||||
let raw = inner::isPermissionGranted().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Requests the permission to send notifications.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::notification;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let perm = notification::request_permission().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn request_permission() -> crate::Result<Permission> {
|
||||
let raw = inner::requestPermission().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Possible permission values.
|
||||
#[derive(Debug, Deserialize, Default, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Permission {
|
||||
#[default]
|
||||
#[serde(rename = "default")]
|
||||
Default,
|
||||
#[serde(rename = "granted")]
|
||||
Granted,
|
||||
#[serde(rename = "denied")]
|
||||
Denied,
|
||||
}
|
||||
|
||||
/// The desktop notification definition.
|
||||
///
|
||||
/// Allows you to construct a Notification data and send it.
|
||||
#[derive(Debug, Default, Serialize)]
|
||||
pub struct Notification<'a> {
|
||||
body: Option<&'a str>,
|
||||
title: Option<&'a str>,
|
||||
icon: Option<&'a str>,
|
||||
}
|
||||
|
||||
impl<'a> Notification<'a> {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Sets the notification title.
|
||||
pub fn set_title(&mut self, title: &'a str) {
|
||||
self.title = Some(title);
|
||||
}
|
||||
|
||||
/// Sets the notification body.
|
||||
pub fn set_body(&mut self, body: &'a str) {
|
||||
self.body = Some(body);
|
||||
}
|
||||
|
||||
/// Sets the notification icon.
|
||||
pub fn set_icon(&mut self, icon: &'a str) {
|
||||
self.icon = Some(icon);
|
||||
}
|
||||
|
||||
/// Shows the notification.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::notification::Notification;
|
||||
///
|
||||
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// Notification::new()
|
||||
/// .set_title("Tauri")
|
||||
/// .set_body("Tauri is awesome!")
|
||||
/// .show()?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn show(&self) -> crate::Result<()> {
|
||||
inner::sendNotification(serde_wasm_bindgen::to_value(&self)?)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
mod inner {
|
||||
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
|
||||
|
||||
#[wasm_bindgen(module = "/src/notification.js")]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn isPermissionGranted() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn requestPermission() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub fn sendNotification(notification: JsValue) -> Result<(), JsValue>;
|
||||
}
|
||||
}
|
107
src/os.js
107
src/os.js
|
@ -1,107 +0,0 @@
|
|||
// tauri/tooling/api/src/helpers/os-check.ts
|
||||
function isWindows() {
|
||||
return navigator.appVersion.includes("Win");
|
||||
}
|
||||
|
||||
// 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/os.ts
|
||||
var EOL = isWindows() ? "\r\n" : "\n";
|
||||
async function platform() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Os",
|
||||
message: {
|
||||
cmd: "platform"
|
||||
}
|
||||
});
|
||||
}
|
||||
async function version() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Os",
|
||||
message: {
|
||||
cmd: "version"
|
||||
}
|
||||
});
|
||||
}
|
||||
async function type() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Os",
|
||||
message: {
|
||||
cmd: "osType"
|
||||
}
|
||||
});
|
||||
}
|
||||
async function arch() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Os",
|
||||
message: {
|
||||
cmd: "arch"
|
||||
}
|
||||
});
|
||||
}
|
||||
async function tempdir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Os",
|
||||
message: {
|
||||
cmd: "tempdir"
|
||||
}
|
||||
});
|
||||
}
|
||||
async function locale() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Os",
|
||||
message: {
|
||||
cmd: "locale"
|
||||
}
|
||||
});
|
||||
}
|
||||
export {
|
||||
EOL,
|
||||
arch,
|
||||
locale,
|
||||
platform,
|
||||
tempdir,
|
||||
type,
|
||||
version
|
||||
};
|
136
src/os.rs
136
src/os.rs
|
@ -1,136 +0,0 @@
|
|||
//! Provides operating system-related utility methods and properties.
|
||||
//!
|
||||
//! The APIs must be added to tauri.allowlist.os in tauri.conf.json:
|
||||
//! ```json
|
||||
//! {
|
||||
//! "tauri": {
|
||||
//! "allowlist": {
|
||||
//! "os": {
|
||||
//! "all": true, // enable all Os APIs
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//! It is recommended to allowlist only the APIs you use for optimal bundle size and security.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub enum Arch {
|
||||
#[serde(rename = "x86")]
|
||||
X86,
|
||||
#[serde(rename = "x86_64")]
|
||||
X86_64,
|
||||
#[serde(rename = "arm")]
|
||||
Arm,
|
||||
#[serde(rename = "aarch64")]
|
||||
Aarch64,
|
||||
#[serde(rename = "mips")]
|
||||
Mips,
|
||||
#[serde(rename = "mips64")]
|
||||
Mips64,
|
||||
#[serde(rename = "powerpc")]
|
||||
Powerpc,
|
||||
#[serde(rename = "powerpc64")]
|
||||
Powerpc64,
|
||||
#[serde(rename = "riscv64")]
|
||||
Riscv64,
|
||||
#[serde(rename = "s390x")]
|
||||
S390x,
|
||||
#[serde(rename = "sparc64")]
|
||||
Sparc64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub enum Platform {
|
||||
#[serde(rename = "linux")]
|
||||
Linux,
|
||||
#[serde(rename = "darwin")]
|
||||
Darwin,
|
||||
#[serde(rename = "ios")]
|
||||
Ios,
|
||||
#[serde(rename = "freebsd")]
|
||||
Freebsd,
|
||||
#[serde(rename = "dragonfly")]
|
||||
Dragonfly,
|
||||
#[serde(rename = "netbsd")]
|
||||
Netbsd,
|
||||
#[serde(rename = "openbsd")]
|
||||
Openbsd,
|
||||
#[serde(rename = "solaris")]
|
||||
Solaris,
|
||||
#[serde(rename = "android")]
|
||||
Android,
|
||||
#[serde(rename = "win32")]
|
||||
Win32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub enum OsKind {
|
||||
#[serde(rename = "Linux")]
|
||||
Linux,
|
||||
#[serde(rename = "Darwin")]
|
||||
Darwin,
|
||||
#[serde(rename = "Windows_NT")]
|
||||
WindowsNT,
|
||||
}
|
||||
|
||||
/// Returns the operating system CPU architecture for which the tauri app was compiled.
|
||||
#[inline(always)]
|
||||
pub async fn arch() -> crate::Result<Arch> {
|
||||
let raw = inner::arch().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns a string identifying the operating system platform. The value is set at compile time.
|
||||
#[inline(always)]
|
||||
pub async fn platform() -> crate::Result<Platform> {
|
||||
let raw = inner::platform().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the operating system's default directory for temporary files.
|
||||
#[inline(always)]
|
||||
pub async fn tempdir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::tempdir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns [`OsKind::Linux`] on Linux, [`OsKind::Darwin`] on macOS, and [`OsKind::WindowsNT`] on Windows.
|
||||
#[inline(always)]
|
||||
pub async fn kind() -> crate::Result<OsKind> {
|
||||
let raw = inner::kind().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns a string identifying the kernel version.
|
||||
#[inline(always)]
|
||||
pub async fn version() -> crate::Result<String> {
|
||||
let raw = inner::version().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
mod inner {
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen(module = "/src/os.js")]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn arch() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn platform() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn tempdir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch, js_name = "type")]
|
||||
pub async fn kind() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn version() -> Result<JsValue, JsValue>;
|
||||
}
|
||||
}
|
418
src/path.js
418
src/path.js
|
@ -1,418 +0,0 @@
|
|||
// 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((resolve2, reject) => {
|
||||
const callback = transformCallback((e) => {
|
||||
resolve2(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/fs.ts
|
||||
var BaseDirectory = /* @__PURE__ */ ((BaseDirectory2) => {
|
||||
BaseDirectory2[BaseDirectory2["Audio"] = 1] = "Audio";
|
||||
BaseDirectory2[BaseDirectory2["Cache"] = 2] = "Cache";
|
||||
BaseDirectory2[BaseDirectory2["Config"] = 3] = "Config";
|
||||
BaseDirectory2[BaseDirectory2["Data"] = 4] = "Data";
|
||||
BaseDirectory2[BaseDirectory2["LocalData"] = 5] = "LocalData";
|
||||
BaseDirectory2[BaseDirectory2["Desktop"] = 6] = "Desktop";
|
||||
BaseDirectory2[BaseDirectory2["Document"] = 7] = "Document";
|
||||
BaseDirectory2[BaseDirectory2["Download"] = 8] = "Download";
|
||||
BaseDirectory2[BaseDirectory2["Executable"] = 9] = "Executable";
|
||||
BaseDirectory2[BaseDirectory2["Font"] = 10] = "Font";
|
||||
BaseDirectory2[BaseDirectory2["Home"] = 11] = "Home";
|
||||
BaseDirectory2[BaseDirectory2["Picture"] = 12] = "Picture";
|
||||
BaseDirectory2[BaseDirectory2["Public"] = 13] = "Public";
|
||||
BaseDirectory2[BaseDirectory2["Runtime"] = 14] = "Runtime";
|
||||
BaseDirectory2[BaseDirectory2["Template"] = 15] = "Template";
|
||||
BaseDirectory2[BaseDirectory2["Video"] = 16] = "Video";
|
||||
BaseDirectory2[BaseDirectory2["Resource"] = 17] = "Resource";
|
||||
BaseDirectory2[BaseDirectory2["App"] = 18] = "App";
|
||||
BaseDirectory2[BaseDirectory2["Log"] = 19] = "Log";
|
||||
BaseDirectory2[BaseDirectory2["Temp"] = 20] = "Temp";
|
||||
BaseDirectory2[BaseDirectory2["AppConfig"] = 21] = "AppConfig";
|
||||
BaseDirectory2[BaseDirectory2["AppData"] = 22] = "AppData";
|
||||
BaseDirectory2[BaseDirectory2["AppLocalData"] = 23] = "AppLocalData";
|
||||
BaseDirectory2[BaseDirectory2["AppCache"] = 24] = "AppCache";
|
||||
BaseDirectory2[BaseDirectory2["AppLog"] = 25] = "AppLog";
|
||||
return BaseDirectory2;
|
||||
})(BaseDirectory || {});
|
||||
|
||||
// tauri/tooling/api/src/helpers/os-check.ts
|
||||
function isWindows() {
|
||||
return navigator.appVersion.includes("Win");
|
||||
}
|
||||
|
||||
// tauri/tooling/api/src/path.ts
|
||||
async function appDir() {
|
||||
return appConfigDir();
|
||||
}
|
||||
async function appConfigDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 21 /* AppConfig */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function appDataDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 22 /* AppData */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function appLocalDataDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 23 /* AppLocalData */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function appCacheDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 24 /* AppCache */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function audioDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 1 /* Audio */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function cacheDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 2 /* Cache */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function configDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 3 /* Config */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function dataDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 4 /* Data */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function desktopDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 6 /* Desktop */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function documentDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 7 /* Document */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function downloadDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 8 /* Download */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function executableDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 9 /* Executable */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function fontDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 10 /* Font */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function homeDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 11 /* Home */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function localDataDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 5 /* LocalData */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function pictureDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 12 /* Picture */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function publicDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 13 /* Public */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function resourceDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 17 /* Resource */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function resolveResource(resourcePath) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: resourcePath,
|
||||
directory: 17 /* Resource */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function runtimeDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 14 /* Runtime */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function templateDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 15 /* Template */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function videoDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 16 /* Video */
|
||||
}
|
||||
});
|
||||
}
|
||||
async function logDir() {
|
||||
return appLogDir();
|
||||
}
|
||||
async function appLogDir() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolvePath",
|
||||
path: "",
|
||||
directory: 25 /* AppLog */
|
||||
}
|
||||
});
|
||||
}
|
||||
var sep = isWindows() ? "\\" : "/";
|
||||
var delimiter = isWindows() ? ";" : ":";
|
||||
async function resolve(...paths) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "resolve",
|
||||
paths
|
||||
}
|
||||
});
|
||||
}
|
||||
async function normalize(path) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "normalize",
|
||||
path
|
||||
}
|
||||
});
|
||||
}
|
||||
async function join(...paths) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "join",
|
||||
paths
|
||||
}
|
||||
});
|
||||
}
|
||||
async function dirname(path) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "dirname",
|
||||
path
|
||||
}
|
||||
});
|
||||
}
|
||||
async function extname(path) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "extname",
|
||||
path
|
||||
}
|
||||
});
|
||||
}
|
||||
async function basename(path, ext) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "basename",
|
||||
path,
|
||||
ext
|
||||
}
|
||||
});
|
||||
}
|
||||
async function isAbsolute(path) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Path",
|
||||
message: {
|
||||
cmd: "isAbsolute",
|
||||
path
|
||||
}
|
||||
});
|
||||
}
|
||||
export {
|
||||
BaseDirectory,
|
||||
appCacheDir,
|
||||
appConfigDir,
|
||||
appDataDir,
|
||||
appDir,
|
||||
appLocalDataDir,
|
||||
appLogDir,
|
||||
audioDir,
|
||||
basename,
|
||||
cacheDir,
|
||||
configDir,
|
||||
dataDir,
|
||||
delimiter,
|
||||
desktopDir,
|
||||
dirname,
|
||||
documentDir,
|
||||
downloadDir,
|
||||
executableDir,
|
||||
extname,
|
||||
fontDir,
|
||||
homeDir,
|
||||
isAbsolute,
|
||||
join,
|
||||
localDataDir,
|
||||
logDir,
|
||||
normalize,
|
||||
pictureDir,
|
||||
publicDir,
|
||||
resolve,
|
||||
resolveResource,
|
||||
resourceDir,
|
||||
runtimeDir,
|
||||
sep,
|
||||
templateDir,
|
||||
videoDir
|
||||
};
|
790
src/path.rs
790
src/path.rs
|
@ -1,790 +0,0 @@
|
|||
//! The path module provides utilities for working with file and directory paths.
|
||||
//!
|
||||
//! The APIs must be added to tauri.allowlist.path in tauri.conf.json:
|
||||
//! ```json
|
||||
//! {
|
||||
//! "tauri": {
|
||||
//! "allowlist": {
|
||||
//! "path": {
|
||||
//! "all": true, // enable all Path APIs
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//! It is recommended to allowlist only the APIs you use for optimal bundle size and security.
|
||||
|
||||
use std::path::PathBuf;
|
||||
use wasm_bindgen::JsValue;
|
||||
|
||||
/// Returns the path to the suggested directory for your app's config files.
|
||||
///
|
||||
/// Resolves to `${configDir}/${bundleIdentifier}`, where `bundleIdentifier` is the value [`tauri.bundle.identifier`](https://tauri.app/v1/api/config/#bundleconfig.identifier) is configured in `tauri.conf.json`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::app_config_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let app_config_dir_path = app_config_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn app_config_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::appConfigDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the path to the suggested directory for your app's data files.
|
||||
///
|
||||
/// Resolves to `${dataDir}/${bundleIdentifier}`, where `bundleIdentifier` is the value [`tauri.bundle.identifier`](https://tauri.app/v1/api/config/#bundleconfig.identifier) is configured in `tauri.conf.json`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::app_data_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let app_data_dir_path = app_data_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn app_data_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::appDataDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the path to the suggested directory for your app's local data files.
|
||||
///
|
||||
/// Resolves to `${localDataDir}/${bundleIdentifier}`, where `bundleIdentifier` is the value [`tauri.bundle.identifier`](https://tauri.app/v1/api/config/#bundleconfig.identifier) is configured in `tauri.conf.json`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::app_local_data_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let app_local_data_dir_path = app_local_data_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn app_local_data_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::appLocalDataDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the path to the suggested directory for your app's cache files.
|
||||
///
|
||||
/// Resolves to `${cacheDir}/${bundleIdentifier}`, where `bundleIdentifier` is the value [`tauri.bundle.identifier`](https://tauri.app/v1/api/config/#bundleconfig.identifier) is configured in `tauri.conf.json`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::app_cache_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let app_cache_dir_path = app_cache_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn app_cache_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::appCacheDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the path to the user's audio directory.
|
||||
///
|
||||
/// #### Platform-specific
|
||||
///
|
||||
/// - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_MUSIC_DIR`.
|
||||
/// - **macOS:** Resolves to `$HOME/Music`.
|
||||
/// - **Windows:** Resolves to `{FOLDERID_Music}`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::audio_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let audio_dir_path = audio_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn audio_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::audioDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the path to the user's cache directory.
|
||||
///
|
||||
/// #### Platform-specific
|
||||
///
|
||||
/// - **Linux:** Resolves to `$XDG_CACHE_HOME` or `$HOME/.cache`.
|
||||
/// - **macOS:** Resolves to `$HOME/Library/Caches`.
|
||||
/// - **Windows:** Resolves to `{FOLDERID_LocalAppData}`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::cache_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let cache_dir_path = cache_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn cache_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::cacheDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the path to the user's config directory.
|
||||
///
|
||||
/// #### Platform-specific
|
||||
///
|
||||
/// - **Linux:** Resolves to `$XDG_CONFIG_HOME` or `$HOME/.config`.
|
||||
/// - **macOS:** Resolves to `$HOME/Library/Application Support`.
|
||||
/// - **Windows:** Resolves to `{FOLDERID_RoamingAppData}`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::config_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let config_dir_path = config_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn config_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::configDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the path to the user's data directory.
|
||||
///
|
||||
/// #### Platform-specific
|
||||
///
|
||||
/// - **Linux:** Resolves to `$XDG_DATA_HOME` or `$HOME/.local/share`.
|
||||
/// - **macOS:** Resolves to `$HOME/Library/Application Support`.
|
||||
/// - **Windows:** Resolves to `{FOLDERID_RoamingAppData}`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::data_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let data_dir_path = data_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn data_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::dataDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the path to the user's desktop directory.
|
||||
///
|
||||
/// #### Platform-specific
|
||||
///
|
||||
/// - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_DESKTOP_DIR`.
|
||||
/// - **macOS:** Resolves to `$HOME/Desktop`.
|
||||
/// - **Windows:** Resolves to `{FOLDERID_Desktop}`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::desktop_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let desktop_dir_path = desktop_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn desktop_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::desktopDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the path to the user's document directory.
|
||||
///
|
||||
/// #### Platform-specific
|
||||
///
|
||||
/// - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_DOCUMENTS_DIR`.
|
||||
/// - **macOS:** Resolves to `$HOME/Documents`.
|
||||
/// - **Windows:** Resolves to `{FOLDERID_Documents}`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::document_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let document_dir_path = document_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn document_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::documentDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the path to the user's download directory.
|
||||
///
|
||||
/// #### Platform-specific
|
||||
///
|
||||
/// - **Linux**: Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_DOWNLOAD_DIR`.
|
||||
/// - **macOS**: Resolves to `$HOME/Downloads`.
|
||||
/// - **Windows**: Resolves to `{FOLDERID_Downloads}`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::download_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let download_dir_path = download_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn download_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::downloadDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the path to the user's executable directory.
|
||||
///
|
||||
/// #### Platform-specific
|
||||
///
|
||||
/// - **Linux:** Resolves to `$XDG_BIN_HOME/../bin` or `$XDG_DATA_HOME/../bin` or `$HOME/.local/bin`.
|
||||
/// - **macOS:** Not supported.
|
||||
/// - **Windows:** Not supported.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::executable_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let executable_dir_path = executable_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn executable_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::executableDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the path to the user's font directory.
|
||||
///
|
||||
/// #### Platform-specific
|
||||
///
|
||||
/// - **Linux:** Resolves to `$XDG_DATA_HOME/fonts` or `$HOME/.local/share/fonts`.
|
||||
/// - **macOS:** Resolves to `$HOME/Library/Fonts`.
|
||||
/// - **Windows:** Not supported.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::font_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let font_dir_path = font_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn font_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::fontDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the path to the user's home directory.
|
||||
///
|
||||
/// #### Platform-specific
|
||||
///
|
||||
/// - **Linux:** Resolves to `$HOME`.
|
||||
/// - **macOS:** Resolves to `$HOME`.
|
||||
/// - **Windows:** Resolves to `{FOLDERID_Profile}`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::home_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let home_dir_path = home_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn home_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::homeDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the path to the user's local data directory.
|
||||
///
|
||||
/// #### Platform-specific
|
||||
///
|
||||
/// - **Linux:** Resolves to `$XDG_DATA_HOME` or `$HOME/.local/share`.
|
||||
/// - **macOS:** Resolves to `$HOME/Library/Application Support`.
|
||||
/// - **Windows:** Resolves to `{FOLDERID_LocalAppData}`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::local_data_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let local_data_dir_path = local_data_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn local_data_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::localDataDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the path to the user's picture directory.
|
||||
///
|
||||
/// #### Platform-specific
|
||||
///
|
||||
/// - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_PICTURES_DIR`.
|
||||
/// - **macOS:** Resolves to `$HOME/Pictures`.
|
||||
/// - **Windows:** Resolves to `{FOLDERID_Pictures}`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::picture_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let picture_dir_path = picture_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn picture_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::pictureDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the path to the user's public directory.
|
||||
///
|
||||
/// #### Platform-specific
|
||||
///
|
||||
/// - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_PUBLICSHARE_DIR`.
|
||||
/// - **macOS:** Resolves to `$HOME/Public`.
|
||||
/// - **Windows:** Resolves to `{FOLDERID_Public}`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::public_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let public_dir_path = public_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn public_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::publicDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the path to the application's resource directory.
|
||||
///
|
||||
/// To resolve a resource path, see the [`resolve_resource`] function.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::resource_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let resource_dir_path = resource_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn resource_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::resourceDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Resolve the path to a resource file.
|
||||
///
|
||||
/// @param resourcePath The path to the resource.
|
||||
/// Must follow the same syntax as defined in `tauri.conf.json > tauri > bundle > resources`, i.e. keeping subfolders and parent dir components (`../`).
|
||||
/// @returns The full path to the resource.
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::resolve_resource;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let resource_path = resolve_resource("script.sh").await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn resolve_resource(resource_path: &str) -> crate::Result<PathBuf> {
|
||||
let raw = inner::resolveResource(JsValue::from_str(resource_path)).await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the path to the user's runtime directory.
|
||||
///
|
||||
/// #### Platform-specific
|
||||
///
|
||||
/// - **Linux:** Resolves to `$XDG_RUNTIME_DIR`.
|
||||
/// - **macOS:** Not supported.
|
||||
/// - **Windows:** Not supported.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::runtime_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let runtime_dir_path = runtime_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn runtime_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::runtimeDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the path to the user's template directory.
|
||||
///
|
||||
/// #### Platform-specific
|
||||
///
|
||||
/// - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_TEMPLATES_DIR`.
|
||||
/// - **macOS:** Not supported.
|
||||
/// - **Windows:** Resolves to `{FOLDERID_Templates}`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::template_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let template_dir_path = template_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn template_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::templateDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the path to the user's video directory.
|
||||
///
|
||||
/// #### Platform-specific
|
||||
///
|
||||
/// - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_VIDEOS_DIR`.
|
||||
/// - **macOS:** Resolves to `$HOME/Movies`.
|
||||
/// - **Windows:** Resolves to `{FOLDERID_Videos}`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::video_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let video_dir_path = video_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn video_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::videoDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the path to the suggested directory for your app's log files.
|
||||
///
|
||||
/// #### Platform-specific
|
||||
///
|
||||
/// - **Linux:** Resolves to `${configDir}/${bundleIdentifier}/logs`.
|
||||
/// - **macOS:** Resolves to `${homeDir}/Library/Logs/{bundleIdentifier}`
|
||||
/// - **Windows:** Resolves to `${configDir}/${bundleIdentifier}/logs`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::app_log_dir;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let app_log_dir_path = app_log_dir().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn app_log_dir() -> crate::Result<PathBuf> {
|
||||
let raw = inner::appLogDir().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Resolves a sequence of `paths` or `path` segments into an absolute path.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::{resolve, app_data_dir};
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let app_data_dir_path = app_data_dir().await?;
|
||||
///
|
||||
/// let path = resolve([app_data_dir_path, "..", "users", "tauri", "avatar.png"]).await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn resolve(paths: impl IntoIterator<Item = &str>) -> crate::Result<PathBuf> {
|
||||
let paths = paths.into_iter();
|
||||
let raw = inner::resolve(serde_wasm_bindgen::to_value(&paths.collect::<Vec<_>>())?).await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Normalizes the given `path`, resolving `'..'` and `'.'` segments and resolve symbolic links.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::{normalize, app_data_dir};
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let app_data_dir_path = app_data_dir().await?;
|
||||
///
|
||||
/// let path = normalize([app_data_dir_path, "..", "users", "tauri", "avatar.png"]).await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn normalize(path: &str) -> crate::Result<PathBuf> {
|
||||
let raw = inner::normalize(JsValue::from_str(path)).await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Joins all given `path` segments together using the platform-specific separator as a delimiter, then normalizes the resulting path.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::{join, app_data_dir};
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let app_data_dir_path = app_data_dir().await?;
|
||||
///
|
||||
/// let path = join([app_data_dir_path, "..", "users", "tauri", "avatar.png"]).await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn join(paths: impl IntoIterator<Item = &str>) -> crate::Result<PathBuf> {
|
||||
let paths = paths.into_iter();
|
||||
let raw = inner::join(serde_wasm_bindgen::to_value(&paths.collect::<Vec<_>>())?).await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the directory name of a `path`. Trailing directory separators are ignored.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::{dirname, app_data_dir};
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let app_data_dir_path = app_data_dir().await?;
|
||||
///
|
||||
/// let dir = dirname(app_data_dir_path).await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn dirname(path: &str) -> crate::Result<PathBuf> {
|
||||
let raw = inner::dirname(JsValue::from_str(path)).await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the extension of the `path`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::{extname, resolve_resource};
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let resource_path = await resolve_resource("app.conf").await?;
|
||||
/// let ext = extname(resource_path).await?;
|
||||
/// assert_eq!(ext, "conf");
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn extname(path: &str) -> crate::Result<PathBuf> {
|
||||
let raw = inner::extname(JsValue::from_str(path)).await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns the last portion of a `path`. Trailing directory separators are ignored.
|
||||
///
|
||||
/// @param ext An optional file extension to be removed from the returned path.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::{basename, resolve_resource};
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let resource_path = await resolve_resource("app.conf").await?;
|
||||
/// let ext = basename(resource_path).await?;
|
||||
/// assert_eq!(ext, "app");
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn basename(path: &str, ext: Option<&str>) -> crate::Result<PathBuf> {
|
||||
let raw = inner::basename(
|
||||
JsValue::from_str(path),
|
||||
ext.map(JsValue::from_str).unwrap_or(JsValue::null()),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Returns whether the path is absolute or not.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::path::is_absolute;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// assert!(is_absolute("/home/tauri").await?);
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn is_absolute(path: &str) -> crate::Result<bool> {
|
||||
let raw = inner::isAbsolute(JsValue::from_str(path)).await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
mod inner {
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen(module = "/src/path.js")]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn appCacheDir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn appConfigDir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn appDataDir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn appLocalDataDir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn appLogDir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn audioDir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn basename(path: JsValue, ext: JsValue) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn cacheDir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn configDir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn dataDir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn desktopDir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn dirname(path: JsValue) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn documentDir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn downloadDir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn executableDir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn extname(path: JsValue) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn fontDir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn homeDir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn isAbsolute(path: JsValue) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn join(paths: JsValue) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn localDataDir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn normalize(path: JsValue) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn pictureDir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn publicDir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn resolve(paths: JsValue) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn resolveResource(path: JsValue) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn resourceDir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn runtimeDir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn templateDir() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn videoDir() -> Result<JsValue, JsValue>;
|
||||
}
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
// 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/process.ts
|
||||
async function exit(exitCode = 0) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Process",
|
||||
message: {
|
||||
cmd: "exit",
|
||||
exitCode
|
||||
}
|
||||
});
|
||||
}
|
||||
async function relaunch() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Process",
|
||||
message: {
|
||||
cmd: "relaunch"
|
||||
}
|
||||
});
|
||||
}
|
||||
export {
|
||||
exit,
|
||||
relaunch
|
||||
};
|
|
@ -1,24 +0,0 @@
|
|||
//! Perform operations on the current process.
|
||||
|
||||
/// Exits immediately with the given `exit_code`.
|
||||
#[inline(always)]
|
||||
pub async fn exit(exit_code: i32) -> ! {
|
||||
inner::exit(exit_code).await;
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
/// Exits the current instance of the app then relaunches it.
|
||||
#[inline(always)]
|
||||
pub fn relaunch() {
|
||||
inner::relaunch();
|
||||
}
|
||||
|
||||
mod inner {
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen(module = "/src/process.js")]
|
||||
extern "C" {
|
||||
pub async fn exit(exitCode: i32);
|
||||
pub fn relaunch();
|
||||
}
|
||||
}
|
230
src/shell.js
230
src/shell.js
|
@ -1,230 +0,0 @@
|
|||
// 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/shell.ts
|
||||
async function execute(onEvent, program, args = [], options) {
|
||||
if (typeof args === "object") {
|
||||
Object.freeze(args);
|
||||
}
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Shell",
|
||||
message: {
|
||||
cmd: "execute",
|
||||
program,
|
||||
args,
|
||||
options,
|
||||
onEventFn: transformCallback(onEvent)
|
||||
}
|
||||
});
|
||||
}
|
||||
var EventEmitter = class {
|
||||
constructor() {
|
||||
this.eventListeners = /* @__PURE__ */ Object.create(null);
|
||||
}
|
||||
addListener(eventName, listener) {
|
||||
return this.on(eventName, listener);
|
||||
}
|
||||
removeListener(eventName, listener) {
|
||||
return this.off(eventName, listener);
|
||||
}
|
||||
on(eventName, listener) {
|
||||
if (eventName in this.eventListeners) {
|
||||
this.eventListeners[eventName].push(listener);
|
||||
} else {
|
||||
this.eventListeners[eventName] = [listener];
|
||||
}
|
||||
return this;
|
||||
}
|
||||
once(eventName, listener) {
|
||||
const wrapper = (...args) => {
|
||||
this.removeListener(eventName, wrapper);
|
||||
listener(...args);
|
||||
};
|
||||
return this.addListener(eventName, wrapper);
|
||||
}
|
||||
off(eventName, listener) {
|
||||
if (eventName in this.eventListeners) {
|
||||
this.eventListeners[eventName] = this.eventListeners[eventName].filter(
|
||||
(l) => l !== listener
|
||||
);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
removeAllListeners(event) {
|
||||
if (event) {
|
||||
delete this.eventListeners[event];
|
||||
} else {
|
||||
this.eventListeners = /* @__PURE__ */ Object.create(null);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
emit(eventName, ...args) {
|
||||
if (eventName in this.eventListeners) {
|
||||
const listeners = this.eventListeners[eventName];
|
||||
for (const listener of listeners)
|
||||
listener(...args);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
listenerCount(eventName) {
|
||||
if (eventName in this.eventListeners)
|
||||
return this.eventListeners[eventName].length;
|
||||
return 0;
|
||||
}
|
||||
prependListener(eventName, listener) {
|
||||
if (eventName in this.eventListeners) {
|
||||
this.eventListeners[eventName].unshift(listener);
|
||||
} else {
|
||||
this.eventListeners[eventName] = [listener];
|
||||
}
|
||||
return this;
|
||||
}
|
||||
prependOnceListener(eventName, listener) {
|
||||
const wrapper = (...args) => {
|
||||
this.removeListener(eventName, wrapper);
|
||||
listener(...args);
|
||||
};
|
||||
return this.prependListener(eventName, wrapper);
|
||||
}
|
||||
};
|
||||
var Child = class {
|
||||
constructor(pid) {
|
||||
this.pid = pid;
|
||||
}
|
||||
async write(data) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Shell",
|
||||
message: {
|
||||
cmd: "stdinWrite",
|
||||
pid: this.pid,
|
||||
buffer: typeof data === "string" ? data : Array.from(data)
|
||||
}
|
||||
});
|
||||
}
|
||||
async kill() {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Shell",
|
||||
message: {
|
||||
cmd: "killChild",
|
||||
pid: this.pid
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
var Command = class extends EventEmitter {
|
||||
constructor(program, args = [], options) {
|
||||
super();
|
||||
this.stdout = new EventEmitter();
|
||||
this.stderr = new EventEmitter();
|
||||
this.program = program;
|
||||
this.args = typeof args === "string" ? [args] : args;
|
||||
this.options = options ?? {};
|
||||
}
|
||||
static sidecar(program, args = [], options) {
|
||||
const instance = new Command(program, args, options);
|
||||
instance.options.sidecar = true;
|
||||
return instance;
|
||||
}
|
||||
async spawn() {
|
||||
return execute(
|
||||
(event) => {
|
||||
switch (event.event) {
|
||||
case "Error":
|
||||
this.emit("error", event.payload);
|
||||
break;
|
||||
case "Terminated":
|
||||
this.emit("close", event.payload);
|
||||
break;
|
||||
case "Stdout":
|
||||
this.stdout.emit("data", event.payload);
|
||||
break;
|
||||
case "Stderr":
|
||||
this.stderr.emit("data", event.payload);
|
||||
break;
|
||||
}
|
||||
},
|
||||
this.program,
|
||||
this.args,
|
||||
this.options
|
||||
).then((pid) => new Child(pid));
|
||||
}
|
||||
async execute() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.on("error", reject);
|
||||
const stdout = [];
|
||||
const stderr = [];
|
||||
this.stdout.on("data", (line) => {
|
||||
stdout.push(line);
|
||||
});
|
||||
this.stderr.on("data", (line) => {
|
||||
stderr.push(line);
|
||||
});
|
||||
this.on("close", (payload) => {
|
||||
resolve({
|
||||
code: payload.code,
|
||||
signal: payload.signal,
|
||||
stdout: stdout.join("\n"),
|
||||
stderr: stderr.join("\n")
|
||||
});
|
||||
});
|
||||
this.spawn().catch(reject);
|
||||
});
|
||||
}
|
||||
};
|
||||
async function open(path, openWith) {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: "Shell",
|
||||
message: {
|
||||
cmd: "open",
|
||||
path,
|
||||
with: openWith
|
||||
}
|
||||
});
|
||||
}
|
||||
export {
|
||||
Child,
|
||||
Command,
|
||||
EventEmitter,
|
||||
open
|
||||
};
|
45
src/tauri.js
45
src/tauri.js
|
@ -1,45 +0,0 @@
|
|||
// 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") {
|
||||
return window.__TAURI__.convertFileSrc(filePath, protocol);
|
||||
}
|
||||
export {
|
||||
convertFileSrc,
|
||||
invoke,
|
||||
transformCallback
|
||||
};
|
110
src/tauri.rs
110
src/tauri.rs
|
@ -1,110 +0,0 @@
|
|||
//! Invoke your custom commands.
|
||||
|
||||
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>) -> crate::Result<Url> {
|
||||
let js_val = inner::convertFileSrc(file_path, protocol).await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(js_val)?)
|
||||
}
|
||||
|
||||
/// 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 raw = inner::invoke(cmd, serde_wasm_bindgen::to_value(args)?).await?;
|
||||
|
||||
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,
|
||||
) -> crate::Result<f64> {
|
||||
let js_val = inner::transformCallback(
|
||||
&|raw| callback(serde_wasm_bindgen::from_value(raw).unwrap()),
|
||||
once,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(js_val)?)
|
||||
}
|
||||
|
||||
mod inner {
|
||||
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
|
||||
|
||||
#[wasm_bindgen(module = "/src/tauri.js")]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn convertFileSrc(
|
||||
filePath: &str,
|
||||
protocol: Option<&str>,
|
||||
) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn invoke(cmd: &str, args: JsValue) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn transformCallback(
|
||||
callback: &dyn Fn(JsValue),
|
||||
once: bool,
|
||||
) -> Result<JsValue, JsValue>;
|
||||
}
|
||||
}
|
187
src/updater.js
187
src/updater.js
|
@ -1,187 +0,0 @@
|
|||
// 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
|
||||
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);
|
||||
}
|
||||
|
||||
// tauri/tooling/api/src/updater.ts
|
||||
async function onUpdaterEvent(handler) {
|
||||
return listen2("tauri://update-status" /* STATUS_UPDATE */, (data) => {
|
||||
handler(data?.payload);
|
||||
});
|
||||
}
|
||||
async function installUpdate() {
|
||||
let unlistenerFn;
|
||||
function cleanListener() {
|
||||
if (unlistenerFn) {
|
||||
unlistenerFn();
|
||||
}
|
||||
unlistenerFn = void 0;
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
function onStatusChange(statusResult) {
|
||||
if (statusResult.error) {
|
||||
cleanListener();
|
||||
reject(statusResult.error);
|
||||
return;
|
||||
}
|
||||
if (statusResult.status === "DONE") {
|
||||
cleanListener();
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
onUpdaterEvent(onStatusChange).then((fn) => {
|
||||
unlistenerFn = fn;
|
||||
}).catch((e) => {
|
||||
cleanListener();
|
||||
throw e;
|
||||
});
|
||||
emit2("tauri://update-install" /* INSTALL_UPDATE */).catch((e) => {
|
||||
cleanListener();
|
||||
throw e;
|
||||
});
|
||||
});
|
||||
}
|
||||
async function checkUpdate() {
|
||||
let unlistenerFn;
|
||||
function cleanListener() {
|
||||
if (unlistenerFn) {
|
||||
unlistenerFn();
|
||||
}
|
||||
unlistenerFn = void 0;
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
function onUpdateAvailable(manifest) {
|
||||
cleanListener();
|
||||
resolve({
|
||||
manifest,
|
||||
shouldUpdate: true
|
||||
});
|
||||
}
|
||||
function onStatusChange(statusResult) {
|
||||
if (statusResult.error) {
|
||||
cleanListener();
|
||||
reject(statusResult.error);
|
||||
return;
|
||||
}
|
||||
if (statusResult.status === "UPTODATE") {
|
||||
cleanListener();
|
||||
resolve({
|
||||
shouldUpdate: false
|
||||
});
|
||||
}
|
||||
}
|
||||
once2("tauri://update-available" /* UPDATE_AVAILABLE */, (data) => {
|
||||
onUpdateAvailable(data?.payload);
|
||||
}).catch((e) => {
|
||||
cleanListener();
|
||||
throw e;
|
||||
});
|
||||
onUpdaterEvent(onStatusChange).then((fn) => {
|
||||
unlistenerFn = fn;
|
||||
}).catch((e) => {
|
||||
cleanListener();
|
||||
throw e;
|
||||
});
|
||||
emit2("tauri://update" /* CHECK_UPDATE */).catch((e) => {
|
||||
cleanListener();
|
||||
throw e;
|
||||
});
|
||||
});
|
||||
}
|
||||
export {
|
||||
checkUpdate,
|
||||
installUpdate,
|
||||
onUpdaterEvent
|
||||
};
|
139
src/updater.rs
139
src/updater.rs
|
@ -1,139 +0,0 @@
|
|||
//! Customize the auto updater flow.
|
||||
|
||||
use futures::{Stream, channel::mpsc};
|
||||
use serde::Deserialize;
|
||||
use wasm_bindgen::{prelude::Closure, JsValue};
|
||||
use crate::event::Listen;
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
pub struct UpdateManifest {
|
||||
pub body: String,
|
||||
pub date: String,
|
||||
pub version: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UpdateResult {
|
||||
pub manifest: Option<UpdateManifest>,
|
||||
pub should_update: bool,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct UpdateStatusResult {
|
||||
error: Option<String>,
|
||||
status: UpdateStatus,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub enum UpdateStatus {
|
||||
#[serde(rename = "PENDING")]
|
||||
Pending,
|
||||
#[serde(rename = "DONE")]
|
||||
Done,
|
||||
#[serde(rename = "UPTODATE")]
|
||||
UpToDate,
|
||||
}
|
||||
|
||||
/// Checks if an update is available.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::updater::check_update;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let update = check_update().await?;
|
||||
/// // now run installUpdate() if needed
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn check_update() -> crate::Result<UpdateResult> {
|
||||
let raw = inner::checkUpdate().await?;
|
||||
|
||||
Ok(serde_wasm_bindgen::from_value(raw)?)
|
||||
}
|
||||
|
||||
/// Install the update if there's one available.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::updater::{check_update, install_update};
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let update = check_update().await?;
|
||||
///
|
||||
/// if update.should_update {
|
||||
/// log::info("Installing update {:?}", update.manifest);
|
||||
/// install_update().await?;
|
||||
/// }
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn install_update() -> crate::Result<()> {
|
||||
inner::installUpdate().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Listen to an updater event.
|
||||
///
|
||||
/// The returned Future will automatically clean up it's underlying event listener when dropped, so no manual unlisten function needs to be called.
|
||||
/// See [Differences to the JavaScript API](../index.html#differences-to-the-javascript-api) for details.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_sys::updater::updater_events;
|
||||
/// use web_sys::console;
|
||||
///
|
||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let events = updater_events();
|
||||
///
|
||||
/// while let Some(event) = events.next().await {
|
||||
/// console::log_1(&format!("Updater event {:?}", event).into());
|
||||
/// }
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub async fn updater_events() -> crate::Result<impl Stream<Item = Result<UpdateStatus, String>>> {
|
||||
let (tx, rx) = mpsc::unbounded::<Result<UpdateStatus, String>>();
|
||||
|
||||
let closure = Closure::<dyn FnMut(JsValue)>::new(move |raw| {
|
||||
let raw: UpdateStatusResult = serde_wasm_bindgen::from_value(raw).unwrap();
|
||||
|
||||
let msg = if let Some(error) = raw.error {
|
||||
Err(error)
|
||||
} else {
|
||||
Ok(raw.status)
|
||||
};
|
||||
|
||||
let _ = tx.unbounded_send(msg);
|
||||
});
|
||||
let unlisten = inner::onUpdaterEvent(&closure).await?;
|
||||
closure.forget();
|
||||
|
||||
Ok(Listen {
|
||||
rx,
|
||||
unlisten: js_sys::Function::from(unlisten),
|
||||
})
|
||||
}
|
||||
|
||||
mod inner {
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen(module = "/src/updater.js")]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn checkUpdate() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn installUpdate() -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
pub async fn onUpdaterEvent(
|
||||
handler: &Closure<dyn FnMut(JsValue)>,
|
||||
) -> Result<JsValue, JsValue>;
|
||||
}
|
||||
}
|
1168
src/window.js
1168
src/window.js
File diff suppressed because it is too large
Load diff
1393
src/window.rs
1393
src/window.rs
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue