Compare commits

...

68 Commits

Author SHA1 Message Date
github-actions[bot] ad17266273 Publish New Versions (v2) (#2348)
Co-authored-by: FabianLars <FabianLars@users.noreply.github.com>
2025-01-27 19:34:40 +01:00
Twilight 78acfa456f feat(websocket): add ability to remove listener (#2027) 2025-01-27 15:18:24 +01:00
renovate[bot] 0b3b3a22d2 chore(deps): update dependency @tauri-apps/cli to v2.2.7 (v2) (#2359)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-25 22:14:17 +01:00
renovate[bot] 384b598fcf chore(deps): update dependency eslint to v9.19.0 (v2) (#2356)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-24 22:25:43 +01:00
renovate[bot] b2fe305a84 chore(deps): update dependency @eslint/js to v9.19.0 (v2) (#2352)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-24 19:59:26 +01:00
Joban 68d8f3be38 docs(process): fix typo in Default Permission section (#2351) 2025-01-24 19:57:07 +01:00
renovate[bot] 9ac2aa88e6 chore(deps): update dependency rollup to v4.32.0 (v2) (#2349)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-24 16:49:22 +01:00
Fabian-Lars 18700f1e82 docs(log): Update mobile support matrix
fixes https://github.com/tauri-apps/tauri-docs/issues/2840
2025-01-24 16:47:10 +01:00
Fabian-Lars 0afc9b6be0 feat(updater): Collect unknown response fields (#2325) 2025-01-23 02:54:02 +02:00
renovate[bot] bda803fbdd chore(deps): update dependency vite to v6.0.9 [security] (#2346)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-22 09:59:59 +08:00
DiamondDrake 105136494c feat(http): add dangerous settings / disable ssl verification - issue #518 (#2204) 2025-01-22 02:23:37 +02:00
Fabian-Lars ce11079f19 fix(clipboard-manager): Drop on exit (#2280)
* fix(clipboard-manager): Drop on exit

ref https://docs.rs/arboard/latest/arboard/struct.Clipboard.html
ref https://github.com/tauri-apps/plugins-workspace/issues/2267

* more specific
2025-01-22 02:15:01 +02:00
Mads Marquart 784a54a390 [log] Use objc2 (#2344) 2025-01-21 22:57:35 +02:00
Mads Marquart bdb7febf9c [opener] Prepare for objc2 frameworks v0.3 (#2343)
These will have a bunch of default features enabled, so let's
preemptively disable them.
2025-01-21 22:26:26 +02:00
renovate[bot] e76272b619 chore(deps): update dependency typescript-eslint to v8.21.0 (v2) (#2337)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-20 22:28:43 +01:00
Anthony Oleinik cf0dff049b [log] add mention of cability to log plugin README.md (#2339) 2025-01-20 21:56:13 +01:00
github-actions[bot] 28f5c33d65 Publish New Versions (v2) (#2324)
Co-authored-by: FabianLars <FabianLars@users.noreply.github.com>
2025-01-19 19:28:26 +01:00
Didrik Nordström 5b82118158 fix(opener): invoke the mobile plugin in the commands too (#2234) (#2332)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-01-19 18:47:14 +01:00
renovate[bot] 125ec1dbcf chore(deps): update dependency rollup to v4.31.0 (v2) (#2333)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-19 15:51:03 +01:00
renovate[bot] c545fcf896 chore(deps): update dependency @tauri-apps/cli to v2.2.5 (#2331)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-18 20:38:04 +08:00
thewh1teagle 0ec895c378 feat(window-state): add filter callback for excluding windows from tracking (#2330)
* feat(window-state): Add glob pattern support to denylist for flexible window management

* changefile

fix(window-state): Remove unnecessary reference in denylist pattern processing

chore(changes): Update window-state and window-state-js versioning for glob pattern support

docs(window-state): Update glob pattern denylist documentation for clarity

* refactor(window-state): Simplify denylist handling and error management in with_denylist method

* feat: add with_denylist_glob

* feat(window-state): Add filter callback for excluding windows from tracking

* refactor(window-state): Remove unused Glob error variant from Error enum

* refactor(window-state): Change filter_callback from Arc<Mutex<FilterCallbackFn>> to Box<FilterCallbackFn>

* refactor(window-state): Remove glob dependency from Cargo.toml and Cargo.lock

* feat(window-state): Introduce filter callback for dynamic window exclusion

* Update .changes/window-state-filter-callback.md
2025-01-18 09:31:20 +08:00
Fabian-Lars 406e6f484c fix(geo/haptics): Fix serde import error with specta feature disabled (#2323) 2025-01-15 13:28:40 +01:00
Fabian-Lars b63d724e85 chore(opener): Fix Cargo.toml property name for tauri-docs generator 2025-01-14 11:57:14 +01:00
renovate[bot] c73b773724 chore(deps): update dependency typescript-eslint to v8.20.0 (#2320)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-14 12:46:26 +08:00
renovate[bot] d467313d0c chore(deps): update dependency eslint-config-prettier to v10 (v2) (#2318)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-13 17:01:20 +01:00
github-actions[bot] efc7bb19a8 Publish New Versions (v2) (#2317)
Co-authored-by: FabianLars <FabianLars@users.noreply.github.com>
2025-01-13 15:59:32 +01:00
Fabian-Lars c9c13a0fe7 fix(geo/haptics)!: specta version and feature flag (#2316) 2025-01-13 15:36:54 +01:00
renovate[bot] da5c59e2fe chore(deps): update rust crate zbus to v5 (v2) (#2271)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <fabianlars@fabianlars.de>
2025-01-13 13:58:09 +01:00
renovate[bot] f555d2981d chore(deps): update dependency @tauri-apps/cli to v2.2.4 (v2) (#2308)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-11 20:25:38 +01:00
renovate[bot] 4c7cb96bbd chore(deps): update eslint monorepo to v9.18.0 (v2) (#2304)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: fabianlars <fabianlars@fabianlars.de>
2025-01-11 11:54:46 +01:00
renovate[bot] 0ad53785ab chore(deps): update rust crate notify to v8 (v2) (#2300)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <fabianlars@fabianlars.de>
2025-01-10 23:02:20 +01:00
github-actions[bot] e2203b760f Publish New Versions (v2) (#2285)
Co-authored-by: FabianLars <FabianLars@users.noreply.github.com>
2025-01-10 21:01:30 +01:00
renovate[bot] b0d9b3b4eb chore(deps): update dependency @tauri-apps/cli to v2.2.3 (v2) (#2298)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-10 17:18:23 +01:00
renovate[bot] 8a5813940c chore(deps): update unocss monorepo to v65 (v2) (major) (#2297)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-10 14:51:23 +01:00
Trevor Fitzgerald ba6d0f1a63 docs(fs): fix link to path API (#2292) 2025-01-09 11:17:24 +01:00
renovate[bot] a431d63b96 chore(deps): update dependency typescript to v5.7.3 (v2) (#2290)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-08 21:29:42 +01:00
renovate[bot] 5ab167f419 chore(deps): update rust crate windows-registry to 0.4 (v2) (#2286)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <fabianlars@fabianlars.de>
2025-01-08 19:19:00 +01:00
Fabian-Lars fb67ab2b92 fix(geo/haptics): Add specta_util (#2281) 2025-01-08 17:01:52 +01:00
renovate[bot] ec548035ff chore(deps): update dependency rollup to v4.30.1 (v2) (#2282)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-08 14:54:45 +01:00
github-actions[bot] 6112867735 Publish New Versions (v2) (#2269)
Co-authored-by: FabianLars <FabianLars@users.noreply.github.com>
2025-01-06 23:44:31 +01:00
renovate[bot] c21eda24a9 chore(deps): update dependency typescript-eslint to v8.19.1 (v2) (#2270)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-06 23:23:27 +01:00
renovate[bot] 05cca602d9 chore(deps): update rust crate tokio-tungstenite to 0.26 (v2) (#2210)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <fabianlars@fabianlars.de>
2025-01-06 13:38:40 +01:00
github-actions[bot] 3a826fb6bf Publish New Versions (v2) (#2237)
Co-authored-by: FabianLars <FabianLars@users.noreply.github.com>
2025-01-06 11:09:06 +01:00
renovate[bot] 86bae64a52 chore(deps): update dependency rollup to v4.30.0 (v2) (#2263)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-06 11:05:22 +01:00
renovate[bot] 8d4c925a62 chore(deps): update dependency rollup to v4.29.2 (v2) (#2260)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-05 21:12:22 +01:00
renovate[bot] 6149e70916 chore(deps): update dependency @tauri-apps/cli to v2.2.2 (#2259)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-04 12:10:03 +08:00
Didrik Nordström a9ac1e3c93 fix(opener): return error if path not exists (#2253) 2025-01-04 01:27:01 +02:00
renovate[bot] 3461a7ae2c chore(deps): update dependency @tauri-apps/cli to v2.2.1 (v2) (#2257)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-03 16:55:11 +01:00
renovate[bot] 7a83d4f7e1 chore(deps): update tauri monorepo to v2.2.0 (v2) (#2252)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-02 23:37:34 +01:00
Fabian-Lars 1fe70dc61c ci(renovate): Overwrite semantic type 2025-01-01 23:42:33 +01:00
renovate[bot] b21915938f chore(deps): update dependency typescript-eslint to v8.19.0 (#2243)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-31 10:37:14 +08:00
Amr Bashir 57efb47c11 feat(updater): add Builder::header and Builder::headers (#2235) 2024-12-24 17:00:12 +02:00
renovate[bot] c4d50aa9ec chore(deps): update dependency typescript-eslint to v8.18.2 (#2232)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-24 10:56:30 +08:00
Fabian-Lars 768b72acf8 docs(sql): iOS seems to work (#2233) 2024-12-23 20:08:05 +01:00
renovate[bot] 8d6c992661 chore(deps): update dependency rollup to v4.29.1 (#2227)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-21 21:01:09 +08:00
renovate[bot] 83b6507269 chore(deps): update dependency typescript-eslint to v8.18.1 (#2219)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-18 14:36:21 +08:00
renovate[bot] da64d9b665 fix(deps): update rust crate tauri-plugin-window-state to 2.2.0 (#2217)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-16 20:30:03 +08:00
renovate[bot] aa2f2bfba0 chore(deps): update dependency @rollup/plugin-node-resolve to v16 (#2213)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-16 10:56:31 +08:00
github-actions[bot] 51919fb26c publish new versions (#2209)
Co-authored-by: amrbashir <amrbashir@users.noreply.github.com>
2024-12-15 08:44:54 +01:00
universalappfactory ee0f65de5c fix(opener): use the correct packagename in OpenerPlugin.kt (#2207) 2024-12-14 18:58:48 +02:00
renovate[bot] 319ef556cd chore(deps): update eslint monorepo to v9.17.0 (#2205)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-14 12:09:17 +08:00
Amr Bashir 802399a969 docs(opener): add examples for None::<&str> (#2202)
closes #2200
2024-12-13 04:22:35 +02:00
github-actions[bot] c9acff99c6 publish new versions (#2188)
Co-authored-by: lucasfernog <lucasfernog@users.noreply.github.com>
2024-12-10 14:24:04 -03:00
Lucas Fernandes Nogueira 18dffc9dfe fix(opener): iOS build (#2189)
* fix(opener): iOS build

* fix covector
2024-12-10 14:21:11 -03:00
Night_Hunter 829b632650 feat(updater): add Builder::default_version_comparator (#1919) 2024-12-10 15:11:43 +02:00
renovate[bot] 501eae173b chore(deps): update dependency typescript-eslint to v8.18.0 (v2) (#2175)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-10 11:25:28 +01:00
FabianLars 3ff5ccd8fb chore(deps): Update examples 2024-12-10 11:13:15 +01:00
FabianLars eb94dda28a docs(clipboard): Remove readHtml mention 2024-12-09 23:10:17 +01:00
98 changed files with 1708 additions and 1351 deletions
+2 -1
View File
@@ -1 +1,2 @@
plugins/*/permissions/autogenerated/
plugins/*/permissions/autogenerated/
plugins/*/android/.tauri/tauri-api/build/
Generated
+245 -275
View File
File diff suppressed because it is too large Load Diff
+2 -3
View File
@@ -21,10 +21,9 @@ thiserror = "2"
url = "2"
schemars = "0.8"
dunce = "1"
specta = "=2.0.0-rc.20"
specta = "^2.0.0-rc.16"
glob = "0.3"
zbus = "4"
#tauri-specta = "=2.0.0-rc.11"
zbus = "5"
[workspace.package]
edition = "2021"
+1 -1
View File
@@ -29,7 +29,7 @@ This repo and all plugins require a Rust version of at least **1.77.2**
| [process](plugins/process) | This plugin provides APIs to access the current process. To spawn child processes, see the [`shell`](https://github.com/tauri-apps/tauri-plugin-shell) plugin. | ✅ | ✅ | ✅ | ? | ? |
| [shell](plugins/shell) | Access the system shell. Allows you to spawn child processes and manage files and URLs using their default application. | ✅ | ✅ | ✅ | ? | ? |
| [single-instance](plugins/single-instance) | Ensure a single instance of your tauri app is running. | ✅ | ✅ | ✅ | ❌ | ❌ |
| [sql](plugins/sql) | Interface with SQL databases. | ✅ | ✅ | ✅ | ? | ✅ |
| [sql](plugins/sql) | Interface with SQL databases. | ✅ | ✅ | ✅ | | ✅ |
| [store](plugins/store) | Persistent key value storage. | ✅ | ✅ | ✅ | ✅ | ✅ |
| [stronghold](plugins/stronghold) | Encrypted, secure database. | ✅ | ✅ | ✅ | ? | ? |
| [updater](plugins/updater) | In-app updates for Tauri applications. | ✅ | ✅ | ✅ | ❌ | ❌ |
+42
View File
@@ -1,5 +1,47 @@
# Changelog
## \[2.0.12]
### Dependencies
- Upgraded to `clipboard-manager-js@2.2.1`
- Upgraded to `http-js@2.3.0`
- Upgraded to `log-js@2.2.1`
- Upgraded to `updater-js@2.4.0`
## \[2.0.11]
### Dependencies
- Upgraded to `opener-js@2.2.5`
## \[2.0.10]
### Dependencies
- Upgraded to `notification-js@2.2.1`
- Upgraded to `opener-js@2.2.4`
## \[2.0.9]
### Dependencies
- Upgraded to `opener-js@2.2.3`
- Upgraded to `updater-js@2.3.1`
## \[2.0.8]
### Dependencies
- Upgraded to `opener-js@2.2.2`
## \[2.0.7]
### Dependencies
- Upgraded to `updater-js@2.3.0`
- Upgraded to `opener-js@2.2.1`
## \[2.0.6]
### Dependencies
+28 -28
View File
@@ -1,7 +1,7 @@
{
"name": "api",
"private": true,
"version": "2.0.6",
"version": "2.0.12",
"type": "module",
"scripts": {
"dev": "vite --clearScreen false",
@@ -10,35 +10,35 @@
"tauri": "tauri"
},
"dependencies": {
"@tauri-apps/api": "2.1.1",
"@tauri-apps/plugin-barcode-scanner": "2.1.0",
"@tauri-apps/plugin-biometric": "2.1.0",
"@tauri-apps/plugin-cli": "2.1.0",
"@tauri-apps/plugin-clipboard-manager": "2.1.0",
"@tauri-apps/plugin-dialog": "2.1.0",
"@tauri-apps/plugin-fs": "2.1.0",
"@tauri-apps/plugin-geolocation": "2.0.0",
"@tauri-apps/plugin-global-shortcut": "2.1.0",
"@tauri-apps/plugin-opener": "2.1.0",
"@tauri-apps/plugin-haptics": "2.0.0",
"@tauri-apps/plugin-http": "2.1.0",
"@tauri-apps/plugin-nfc": "2.1.0",
"@tauri-apps/plugin-notification": "2.1.0",
"@tauri-apps/plugin-os": "2.1.0",
"@tauri-apps/plugin-process": "2.1.0",
"@tauri-apps/plugin-shell": "2.1.0",
"@tauri-apps/plugin-store": "2.2.0",
"@tauri-apps/plugin-updater": "2.1.0",
"@tauri-apps/api": "2.2.0",
"@tauri-apps/plugin-barcode-scanner": "^2.2.0",
"@tauri-apps/plugin-biometric": "^2.2.0",
"@tauri-apps/plugin-cli": "^2.2.0",
"@tauri-apps/plugin-clipboard-manager": "^2.2.1",
"@tauri-apps/plugin-dialog": "^2.2.0",
"@tauri-apps/plugin-fs": "^2.2.0",
"@tauri-apps/plugin-geolocation": "^2.2.0",
"@tauri-apps/plugin-global-shortcut": "^2.2.0",
"@tauri-apps/plugin-opener": "^2.2.5",
"@tauri-apps/plugin-haptics": "^2.2.0",
"@tauri-apps/plugin-http": "^2.3.0",
"@tauri-apps/plugin-nfc": "^2.2.0",
"@tauri-apps/plugin-notification": "^2.2.1",
"@tauri-apps/plugin-os": "^2.2.0",
"@tauri-apps/plugin-process": "^2.2.0",
"@tauri-apps/plugin-shell": "^2.2.0",
"@tauri-apps/plugin-store": "^2.2.0",
"@tauri-apps/plugin-updater": "^2.4.0",
"@zerodevx/svelte-json-view": "1.0.11"
},
"devDependencies": {
"@iconify-json/codicon": "^1.1.37",
"@iconify-json/ph": "^1.1.8",
"@sveltejs/vite-plugin-svelte": "^5.0.0",
"@tauri-apps/cli": "2.1.0",
"@unocss/extractor-svelte": "^0.65.0",
"svelte": "^5.0.0",
"unocss": "^0.65.0",
"vite": "^6.0.0"
"@iconify-json/codicon": "^1.2.6",
"@iconify-json/ph": "^1.2.1",
"@sveltejs/vite-plugin-svelte": "^5.0.1",
"@tauri-apps/cli": "2.2.7",
"@unocss/extractor-svelte": "^65.0.0",
"svelte": "^5.10.0",
"unocss": "^65.0.0",
"vite": "^6.0.3"
}
}
+53
View File
@@ -1,5 +1,58 @@
# Changelog
## \[2.0.16]
### Dependencies
- Upgraded to `clipboard-manager@2.2.1`
- Upgraded to `http@2.3.0`
- Upgraded to `log@2.2.1`
- Upgraded to `updater@2.4.0`
## \[2.0.15]
### Dependencies
- Upgraded to `haptics@2.2.3`
- Upgraded to `geolocation@2.2.3`
- Upgraded to `opener@2.2.5`
## \[2.0.14]
### Dependencies
- Upgraded to `geolocation@2.2.2`
- Upgraded to `haptics@2.2.2`
- Upgraded to `notification@2.2.1`
- Upgraded to `opener@2.2.4`
## \[2.0.13]
### Dependencies
- Upgraded to `geolocation@2.2.1`
- Upgraded to `haptics@2.2.1`
## \[2.0.12]
### Dependencies
- Upgraded to `opener@2.2.3`
- Upgraded to `updater@2.3.1`
## \[2.0.11]
### Dependencies
- Upgraded to `opener@2.2.2`
## \[2.0.10]
### Dependencies
- Upgraded to `updater@2.3.0`
- Upgraded to `opener@2.2.1`
## \[2.0.9]
### Dependencies
+19 -19
View File
@@ -1,7 +1,7 @@
[package]
name = "api"
publish = false
version = "2.0.9"
version = "2.0.16"
description = "An example Tauri Application showcasing the api"
edition = "2021"
rust-version = { workspace = true }
@@ -19,22 +19,22 @@ serde_json = { workspace = true }
serde = { workspace = true }
tiny_http = "0.12"
log = { workspace = true }
tauri-plugin-log = { path = "../../../plugins/log", version = "2.1.0" }
tauri-plugin-log = { path = "../../../plugins/log", version = "2.2.1" }
tauri-plugin-fs = { path = "../../../plugins/fs", version = "2.2.0", features = [
"watch",
] }
tauri-plugin-clipboard-manager = { path = "../../../plugins/clipboard-manager", version = "2.1.0" }
tauri-plugin-dialog = { path = "../../../plugins/dialog", version = "2.1.0" }
tauri-plugin-clipboard-manager = { path = "../../../plugins/clipboard-manager", version = "2.2.1" }
tauri-plugin-dialog = { path = "../../../plugins/dialog", version = "2.2.0" }
tauri-plugin-http = { path = "../../../plugins/http", features = [
"multipart",
], version = "2.1.0" }
tauri-plugin-notification = { path = "../../../plugins/notification", version = "2.1.0", features = [
], version = "2.3.0" }
tauri-plugin-notification = { path = "../../../plugins/notification", version = "2.2.1", features = [
"windows7-compat",
] }
tauri-plugin-os = { path = "../../../plugins/os", version = "2.1.0" }
tauri-plugin-process = { path = "../../../plugins/process", version = "2.1.0" }
tauri-plugin-opener = { path = "../../../plugins/opener", version = "2.1.0" }
tauri-plugin-shell = { path = "../../../plugins/shell", version = "2.1.0" }
tauri-plugin-os = { path = "../../../plugins/os", version = "2.2.0" }
tauri-plugin-process = { path = "../../../plugins/process", version = "2.2.0" }
tauri-plugin-opener = { path = "../../../plugins/opener", version = "2.2.5" }
tauri-plugin-shell = { path = "../../../plugins/shell", version = "2.2.0" }
tauri-plugin-store = { path = "../../../plugins/store", version = "2.2.0" }
[dependencies.tauri]
@@ -51,17 +51,17 @@ features = [
]
[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
tauri-plugin-cli = { path = "../../../plugins/cli", version = "2.1.0" }
tauri-plugin-global-shortcut = { path = "../../../plugins/global-shortcut", version = "2.1.0" }
tauri-plugin-updater = { path = "../../../plugins/updater", version = "2.2.0" }
tauri-plugin-window-state = { path = "../../../plugins/window-state", version = "2.0.0" }
tauri-plugin-cli = { path = "../../../plugins/cli", version = "2.2.0" }
tauri-plugin-global-shortcut = { path = "../../../plugins/global-shortcut", version = "2.2.0" }
tauri-plugin-updater = { path = "../../../plugins/updater", version = "2.4.0" }
tauri-plugin-window-state = { path = "../../../plugins/window-state", version = "2.2.0" }
[target."cfg(any(target_os = \"android\", target_os = \"ios\"))".dependencies]
tauri-plugin-barcode-scanner = { path = "../../../plugins/barcode-scanner/", version = "2.1.0" }
tauri-plugin-nfc = { path = "../../../plugins/nfc", version = "2.1.0" }
tauri-plugin-biometric = { path = "../../../plugins/biometric/", version = "2.1.0" }
tauri-plugin-geolocation = { path = "../../../plugins/geolocation/", version = "2.1.0" }
tauri-plugin-haptics = { path = "../../../plugins/haptics/", version = "2.1.0" }
tauri-plugin-barcode-scanner = { path = "../../../plugins/barcode-scanner/", version = "2.2.0" }
tauri-plugin-nfc = { path = "../../../plugins/nfc", version = "2.2.0" }
tauri-plugin-biometric = { path = "../../../plugins/biometric/", version = "2.2.0" }
tauri-plugin-geolocation = { path = "../../../plugins/geolocation/", version = "2.2.3" }
tauri-plugin-haptics = { path = "../../../plugins/haptics/", version = "2.2.3" }
[features]
prod = ["tauri/custom-protocol"]
+1 -1
View File
@@ -45,7 +45,7 @@ pub fn create_tray<R: Runtime>(app: &tauri::AppHandle<R>) -> tauri::Result<()> {
.tooltip("Tauri")
.icon(app.default_window_icon().unwrap().clone())
.menu(&menu1)
.menu_on_left_click(false)
.show_menu_on_left_click(false)
.on_menu_event(move |app, event| match event.id.as_ref() {
"quit" => {
app.exit(0);
+7 -7
View File
@@ -11,20 +11,20 @@
"example:api:dev": "pnpm run --filter \"api\" tauri dev"
},
"devDependencies": {
"@eslint/js": "9.16.0",
"@rollup/plugin-node-resolve": "15.3.0",
"@eslint/js": "9.19.0",
"@rollup/plugin-node-resolve": "16.0.0",
"@rollup/plugin-terser": "0.4.4",
"@rollup/plugin-typescript": "11.1.6",
"@types/eslint__js": "8.42.3",
"covector": "^0.12.3",
"eslint": "9.16.0",
"eslint-config-prettier": "9.1.0",
"eslint": "9.19.0",
"eslint-config-prettier": "10.0.1",
"eslint-plugin-security": "3.0.1",
"prettier": "3.4.2",
"rollup": "4.28.1",
"rollup": "4.32.0",
"tslib": "2.8.1",
"typescript": "5.7.2",
"typescript-eslint": "8.17.0"
"typescript": "5.7.3",
"typescript-eslint": "8.21.0"
},
"resolutions": {
"semver": ">=7.5.2",
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.2.1]
- [`ce11079f`](https://github.com/tauri-apps/plugins-workspace/commit/ce11079f19852fbefdecf0e4c7d947af3624fee0) ([#2280](https://github.com/tauri-apps/plugins-workspace/pull/2280) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Explicitly drop `arboard::Clipboard` on exit. Add recommendation to not use read methods on the mainthread.
## \[2.2.0]
- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-clipboard-manager"
version = "2.2.0"
version = "2.2.1"
description = "Read and write to the system clipboard."
edition = { workspace = true }
authors = { workspace = true }
-1
View File
@@ -72,7 +72,6 @@ import {
writeText,
readText,
writeHtml,
readHtml,
clear
} from '@tauri-apps/plugin-clipboard-manager'
await writeText('Tauri is awesome!')
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_CLIPBOARD_MANAGER__=function(e){"use strict";var t;async function r(e,t={},r){return window.__TAURI_INTERNALS__.invoke(e,t,r)}"function"==typeof SuppressedError&&SuppressedError;class n{get rid(){return function(e,t,r,n){if("a"===r&&!n)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!n:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?n:"a"===r?n.call(e):n?n.value:t.get(e)}(this,t,"f")}constructor(e){t.set(this,void 0),function(e,t,r,n,a){if("function"==typeof t?e!==t||!a:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");t.set(e,r)}(this,t,e)}async close(){return r("plugin:resources|close",{rid:this.rid})}}t=new WeakMap;class a extends n{constructor(e){super(e)}static async new(e,t,n){return r("plugin:image|new",{rgba:i(e),width:t,height:n}).then((e=>new a(e)))}static async fromBytes(e){return r("plugin:image|from_bytes",{bytes:i(e)}).then((e=>new a(e)))}static async fromPath(e){return r("plugin:image|from_path",{path:e}).then((e=>new a(e)))}async rgba(){return r("plugin:image|rgba",{rid:this.rid}).then((e=>new Uint8Array(e)))}async size(){return r("plugin:image|size",{rid:this.rid})}}function i(e){return null==e?null:"string"==typeof e?e:e instanceof a?e.rid:e}return e.clear=async function(){await r("plugin:clipboard-manager|clear")},e.readImage=async function(){return await r("plugin:clipboard-manager|read_image").then((e=>new a(e)))},e.readText=async function(){return await r("plugin:clipboard-manager|read_text")},e.writeHtml=async function(e,t){await r("plugin:clipboard-manager|write_html",{html:e,altText:t})},e.writeImage=async function(e){await r("plugin:clipboard-manager|write_image",{image:i(e)})},e.writeText=async function(e,t){await r("plugin:clipboard-manager|write_text",{label:t?.label,text:e})},e}({});Object.defineProperty(window.__TAURI__,"clipboardManager",{value:__TAURI_PLUGIN_CLIPBOARD_MANAGER__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_CLIPBOARD_MANAGER__=function(e){"use strict";var t;async function r(e,t={},r){return window.__TAURI_INTERNALS__.invoke(e,t,r)}"function"==typeof SuppressedError&&SuppressedError;class n{get rid(){return function(e,t,r,n){if("a"===r&&!n)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!n:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?n:"a"===r?n.call(e):n?n.value:t.get(e)}(this,t,"f")}constructor(e){t.set(this,void 0),function(e,t,r){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");t.set(e,r)}(this,t,e)}async close(){return r("plugin:resources|close",{rid:this.rid})}}t=new WeakMap;class a extends n{constructor(e){super(e)}static async new(e,t,n){return r("plugin:image|new",{rgba:i(e),width:t,height:n}).then((e=>new a(e)))}static async fromBytes(e){return r("plugin:image|from_bytes",{bytes:i(e)}).then((e=>new a(e)))}static async fromPath(e){return r("plugin:image|from_path",{path:e}).then((e=>new a(e)))}async rgba(){return r("plugin:image|rgba",{rid:this.rid}).then((e=>new Uint8Array(e)))}async size(){return r("plugin:image|size",{rid:this.rid})}}function i(e){return null==e?null:"string"==typeof e?e:e instanceof a?e.rid:e}return e.clear=async function(){await r("plugin:clipboard-manager|clear")},e.readImage=async function(){return await r("plugin:clipboard-manager|read_image").then((e=>new a(e)))},e.readText=async function(){return await r("plugin:clipboard-manager|read_text")},e.writeHtml=async function(e,t){await r("plugin:clipboard-manager|write_html",{html:e,altText:t})},e.writeImage=async function(e){await r("plugin:clipboard-manager|write_image",{image:i(e)})},e.writeText=async function(e,t){await r("plugin:clipboard-manager|write_text",{label:t?.label,text:e})},e}({});Object.defineProperty(window.__TAURI__,"clipboardManager",{value:__TAURI_PLUGIN_CLIPBOARD_MANAGER__})}
+4 -2
View File
@@ -111,9 +111,11 @@ async function readImage(): Promise<Image> {
*
* @example
* ```typescript
* import { writeHtml, readHtml } from '@tauri-apps/plugin-clipboard-manager';
* import { writeHtml } from '@tauri-apps/plugin-clipboard-manager';
* await writeHtml('<h1>Tauri is awesome!</h1>', 'plaintext');
* await writeHtml('<h1>Tauri is awesome!</h1>', '<h1>Tauri is awesome</h1>'); // Will write "<h1>Tauri is awesome</h1>" as plain text
* // The following will write "<h1>Tauri is awesome</h1>" as plain text
* await writeHtml('<h1>Tauri is awesome!</h1>', '<h1>Tauri is awesome</h1>');
* // we can read html data only as a string so there's just readText(), no readHtml()
* assert(await readText(), '<h1>Tauri is awesome!</h1>');
* ```
*
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-clipboard-manager",
"version": "2.2.0",
"version": "2.2.1",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
+32 -6
View File
@@ -14,7 +14,7 @@ pub fn init<R: Runtime, C: DeserializeOwned>(
) -> crate::Result<Clipboard<R>> {
Ok(Clipboard {
app: app.clone(),
clipboard: arboard::Clipboard::new().map(Mutex::new),
clipboard: arboard::Clipboard::new().map(|c| Mutex::new(Some(c))),
})
}
@@ -22,13 +22,21 @@ pub fn init<R: Runtime, C: DeserializeOwned>(
pub struct Clipboard<R: Runtime> {
#[allow(dead_code)]
app: AppHandle<R>,
clipboard: Result<Mutex<arboard::Clipboard>, arboard::Error>,
// According to arboard docs the clipboard must be dropped before exit.
// Since tauri doesn't call drop on exit we'll use an Option to take() on RunEvent::Exit.
clipboard: Result<Mutex<Option<arboard::Clipboard>>, arboard::Error>,
}
impl<R: Runtime> Clipboard<R> {
pub fn write_text<'a, T: Into<Cow<'a, str>>>(&self, text: T) -> crate::Result<()> {
match &self.clipboard {
Ok(clipboard) => clipboard.lock().unwrap().set_text(text).map_err(Into::into),
Ok(clipboard) => clipboard
.lock()
.unwrap()
.as_mut()
.unwrap()
.set_text(text)
.map_err(Into::into),
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
}
}
@@ -38,6 +46,8 @@ impl<R: Runtime> Clipboard<R> {
Ok(clipboard) => clipboard
.lock()
.unwrap()
.as_mut()
.unwrap()
.set_image(ImageData {
bytes: Cow::Borrowed(image.rgba()),
width: image.width() as usize,
@@ -48,10 +58,11 @@ impl<R: Runtime> Clipboard<R> {
}
}
/// Warning: This method should not be used on the main thread! Otherwise the underlying libraries may deadlock on Linux, freezing the whole app, when trying to copy data copied from this app, for example if the user copies text from the WebView.
pub fn read_text(&self) -> crate::Result<String> {
match &self.clipboard {
Ok(clipboard) => {
let text = clipboard.lock().unwrap().get_text()?;
let text = clipboard.lock().unwrap().as_mut().unwrap().get_text()?;
Ok(text)
}
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
@@ -67,6 +78,8 @@ impl<R: Runtime> Clipboard<R> {
Ok(clipboard) => clipboard
.lock()
.unwrap()
.as_mut()
.unwrap()
.set_html(html, alt_text)
.map_err(Into::into),
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
@@ -75,15 +88,22 @@ impl<R: Runtime> Clipboard<R> {
pub fn clear(&self) -> crate::Result<()> {
match &self.clipboard {
Ok(clipboard) => clipboard.lock().unwrap().clear().map_err(Into::into),
Ok(clipboard) => clipboard
.lock()
.unwrap()
.as_mut()
.unwrap()
.clear()
.map_err(Into::into),
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
}
}
/// Warning: This method should not be used on the main thread! Otherwise the underlying libraries may deadlock on Linux, freezing the whole app, when trying to copy data copied from this app, for example if the user copies text from the WebView.
pub fn read_image(&self) -> crate::Result<Image<'_>> {
match &self.clipboard {
Ok(clipboard) => {
let image = clipboard.lock().unwrap().get_image()?;
let image = clipboard.lock().unwrap().as_mut().unwrap().get_image()?;
let image = Image::new_owned(
image.bytes.to_vec(),
image.width as u32,
@@ -94,4 +114,10 @@ impl<R: Runtime> Clipboard<R> {
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
}
}
pub(crate) fn cleanup(&self) {
if let Ok(clipboard) = &self.clipboard {
clipboard.lock().unwrap().take();
}
}
}
+7 -1
View File
@@ -11,7 +11,7 @@
use tauri::{
plugin::{Builder, TauriPlugin},
Manager, Runtime,
Manager, RunEvent, Runtime,
};
#[cfg(desktop)]
@@ -59,5 +59,11 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
app.manage(clipboard);
Ok(())
})
.on_event(|_app, _event| {
#[cfg(desktop)]
if let RunEvent::Exit = _event {
_app.clipboard().cleanup();
}
})
.build()
}
+2 -2
View File
@@ -38,8 +38,8 @@ url = { workspace = true }
[target."cfg(windows)".dependencies]
dunce = "1"
windows-registry = "0.3"
windows-result = "0.2"
windows-registry = "0.4"
windows-result = "0.3"
[target."cfg(target_os = \"linux\")".dependencies]
rust-ini = "0.21"
+3 -3
View File
@@ -10,11 +10,11 @@
"tauri": "tauri"
},
"dependencies": {
"@tauri-apps/api": "2.1.1",
"@tauri-apps/plugin-deep-link": "2.1.0"
"@tauri-apps/api": "2.2.0",
"@tauri-apps/plugin-deep-link": "2.2.0"
},
"devDependencies": {
"@tauri-apps/cli": "2.1.0",
"@tauri-apps/cli": "2.2.7",
"typescript": "^5.2.2",
"vite": "^6.0.0"
}
+2 -2
View File
@@ -38,11 +38,11 @@ anyhow = "1"
uuid = { version = "1", features = ["v4"] }
glob = { workspace = true }
# TODO: Remove `serialization-compat-6` in v3
notify = { version = "7", optional = true, features = [
notify = { version = "8", optional = true, features = [
"serde",
"serialization-compat-6",
] }
notify-debouncer-full = { version = "0.4", optional = true }
notify-debouncer-full = { version = "0.5", optional = true }
dunce = { workspace = true }
percent-encoding = "2"
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -10,7 +10,7 @@
* This module prevents path traversal, not allowing parent directory accessors to be used
* (i.e. "/usr/path/to/../file" or "../path/to/file" paths are not allowed).
* Paths accessed with this API must be either relative to one of the {@link BaseDirectory | base directories}
* or created with the {@link https://v2.tauri.app/reference/javascript/api/namespacepath | path API}.
* or created with the {@link https://v2.tauri.app/reference/javascript/api/namespacepath/ | path API}.
*
* The API has a scope configuration that forces you to restrict the paths that can be accessed using glob patterns.
*
+13
View File
@@ -1,5 +1,18 @@
# Changelog
## \[2.2.3]
- [`406e6f48`](https://github.com/tauri-apps/plugins-workspace/commit/406e6f484cdc13d35c50fb949f7489ca9eeccc44) ([#2323](https://github.com/tauri-apps/plugins-workspace/pull/2323) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Fixed an issue that caused build failures when the `haptics` or `geolocation` plugin was used without their `specta` feature flag enabled.
## \[2.2.2]
- [`c9c13a0f`](https://github.com/tauri-apps/plugins-workspace/commit/c9c13a0fe7cdaac223843f5ba33176252f8e22f5) ([#2316](https://github.com/tauri-apps/plugins-workspace/pull/2316) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) **Breaking change:** `specta` integration is now behind a `specta` feature flag like in Tauri.
- [`c9c13a0f`](https://github.com/tauri-apps/plugins-workspace/commit/c9c13a0fe7cdaac223843f5ba33176252f8e22f5) ([#2316](https://github.com/tauri-apps/plugins-workspace/pull/2316) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Unlock and widen `specta` version range to match Tauri. No API changes.
## \[2.2.1]
- [`fb67ab2b`](https://github.com/tauri-apps/plugins-workspace/commit/fb67ab2b926502bfc20d6b43fbdd156691ea8526) ([#2281](https://github.com/tauri-apps/plugins-workspace/pull/2281) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Added `specta-util` to fix a "dependency not found" compilation error.
## \[2.2.0]
- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+6 -3
View File
@@ -1,7 +1,7 @@
[package]
name = "tauri-plugin-geolocation"
description = "Get and track the device's current position"
version = "2.2.0"
version = "2.2.3"
edition = { workspace = true }
authors = { workspace = true }
license = { workspace = true }
@@ -26,10 +26,13 @@ tauri-plugin = { workspace = true, features = ["build"] }
[dependencies]
serde = { workspace = true }
serde_json = { workspace = true }
tauri = { workspace = true, features = ["specta"] }
tauri = { workspace = true }
log = { workspace = true }
thiserror = { workspace = true }
specta = { workspace = true }
specta = { workspace = true, optional = true }
[target.'cfg(target_os = "ios")'.dependencies]
tauri = { workspace = true, features = ["wry"] }
[features]
specta = ["dep:specta", "tauri/specta"]
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_GEOLOCATION__=function(t){"use strict";function e(t,e,n,i){if("a"===n&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!i:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?i:"a"===n?i.call(t):i?i.value:e.get(t)}function n(t,e,n,i,o){if("function"==typeof e?t!==e||!o:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,n),n}var i,o,s;"function"==typeof SuppressedError&&SuppressedError;const r="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),o.set(this,0),s.set(this,{}),this.id=function(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}((({message:t,id:r})=>{if(r===e(this,o,"f")){n(this,o,r+1),e(this,i,"f").call(this,t);const a=Object.keys(e(this,s,"f"));if(a.length>0){let t=r+1;for(const n of a.sort()){if(parseInt(n)!==t)break;{const o=e(this,s,"f")[n];delete e(this,s,"f")[n],e(this,i,"f").call(this,o),t+=1}}n(this,o,t)}}else e(this,s,"f")[r.toString()]=t}))}set onmessage(t){n(this,i,t)}get onmessage(){return e(this,i,"f")}[(i=new WeakMap,o=new WeakMap,s=new WeakMap,r)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[r]()}}async function c(t,e={},n){return window.__TAURI_INTERNALS__.invoke(t,e,n)}return t.checkPermissions=async function(){return await async function(t){return c(`plugin:${t}|check_permissions`)}("geolocation")},t.clearWatch=async function(t){await c("plugin:geolocation|clear_watch",{channelId:t})},t.getCurrentPosition=async function(t){return await c("plugin:geolocation|get_current_position",{options:t})},t.requestPermissions=async function(t){return await c("plugin:geolocation|request_permissions",{permissions:t})},t.watchPosition=async function(t,e){const n=new a;return n.onmessage=t=>{"string"==typeof t?e(null,t):e(t)},await c("plugin:geolocation|watch_position",{options:t,channel:n}),n.id},t}({});Object.defineProperty(window.__TAURI__,"geolocation",{value:__TAURI_PLUGIN_GEOLOCATION__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_GEOLOCATION__=function(t){"use strict";function n(t,n,e,i){if("a"===e&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof n?t!==n||!i:!n.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===e?i:"a"===e?i.call(t):i?i.value:n.get(t)}function e(t,n,e,i,s){if("function"==typeof n||!n.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return n.set(t,e),e}var i,s,o;"function"==typeof SuppressedError&&SuppressedError;const r="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),s.set(this,0),o.set(this,[]),this.id=function(t,n=!1){return window.__TAURI_INTERNALS__.transformCallback(t,n)}((({message:t,id:r})=>{if(r==n(this,s,"f"))for(n(this,i,"f").call(this,t),e(this,s,n(this,s,"f")+1);n(this,s,"f")in n(this,o,"f");){const t=n(this,o,"f")[n(this,s,"f")];n(this,i,"f").call(this,t),delete n(this,o,"f")[n(this,s,"f")],e(this,s,n(this,s,"f")+1)}else n(this,o,"f")[r]=t}))}set onmessage(t){e(this,i,t)}get onmessage(){return n(this,i,"f")}[(i=new WeakMap,s=new WeakMap,o=new WeakMap,r)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[r]()}}async function c(t,n={},e){return window.__TAURI_INTERNALS__.invoke(t,n,e)}return t.checkPermissions=async function(){return await async function(t){return c(`plugin:${t}|check_permissions`)}("geolocation")},t.clearWatch=async function(t){await c("plugin:geolocation|clear_watch",{channelId:t})},t.getCurrentPosition=async function(t){return await c("plugin:geolocation|get_current_position",{options:t})},t.requestPermissions=async function(t){return await c("plugin:geolocation|request_permissions",{permissions:t})},t.watchPosition=async function(t,n){const e=new a;return e.onmessage=t=>{"string"==typeof t?n(null,t):n(t)},await c("plugin:geolocation|watch_position",{options:t,channel:e}),e.id},t}({});Object.defineProperty(window.__TAURI__,"geolocation",{value:__TAURI_PLUGIN_GEOLOCATION__})}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-geolocation",
"version": "2.2.0",
"version": "2.2.3",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
-5
View File
@@ -7,7 +7,6 @@ use tauri::{command, ipc::Channel, AppHandle, Runtime};
use crate::{GeolocationExt, PermissionStatus, PermissionType, Position, PositionOptions, Result};
#[command]
#[specta::specta]
pub(crate) async fn get_current_position<R: Runtime>(
app: AppHandle<R>,
options: Option<PositionOptions>,
@@ -16,7 +15,6 @@ pub(crate) async fn get_current_position<R: Runtime>(
}
#[command]
#[specta::specta]
pub(crate) async fn watch_position<R: Runtime>(
app: AppHandle<R>,
options: PositionOptions,
@@ -26,19 +24,16 @@ pub(crate) async fn watch_position<R: Runtime>(
}
#[command]
#[specta::specta]
pub(crate) async fn clear_watch<R: Runtime>(app: AppHandle<R>, channel_id: u32) -> Result<()> {
app.geolocation().clear_watch(channel_id)
}
#[command]
#[specta::specta]
pub(crate) async fn check_permissions<R: Runtime>(app: AppHandle<R>) -> Result<PermissionStatus> {
app.geolocation().check_permissions()
}
#[command]
#[specta::specta]
pub(crate) async fn request_permissions<R: Runtime>(
app: AppHandle<R>,
permissions: Option<Vec<PermissionType>>,
+3 -3
View File
@@ -3,18 +3,18 @@
// SPDX-License-Identifier: MIT
use serde::{ser::Serializer, Serialize};
use specta::Type;
pub type Result<T> = std::result::Result<T, Error>;
// TODO: Improve Error handling (different typed errors instead of one (stringified) PluginInvokeError for all mobile errors)
#[derive(Debug, thiserror::Error, Type)]
#[derive(Debug, thiserror::Error)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
pub enum Error {
#[cfg(mobile)]
#[error(transparent)]
PluginInvoke(
#[serde(skip)]
#[cfg_attr(feature = "specta", serde(skip))]
#[from]
tauri::plugin::mobile::PluginInvokeError,
),
-42
View File
@@ -7,8 +7,6 @@ use tauri::{
Manager, Runtime,
};
//use tauri_specta::*;
pub use models::*;
#[cfg(desktop)]
@@ -27,24 +25,6 @@ use desktop::Geolocation;
#[cfg(mobile)]
use mobile::Geolocation;
/* macro_rules! specta_builder {
() => {
ts::builder()
.commands(collect_commands![
commands::get_current_position,
commands::watch_position,
commands::clear_watch,
commands::check_permissions,
commands::request_permissions
])
.header("// @ts-nocheck")
.config(
specta::ts::ExportConfig::default()
.bigint(specta::ts::BigIntExportBehavior::Number),
)
};
} */
/// Extensions to [`tauri::App`], [`tauri::AppHandle`], [`tauri::WebviewWindow`], [`tauri::Webview`] and [`tauri::Window`] to access the geolocation APIs.
pub trait GeolocationExt<R: Runtime> {
fn geolocation(&self) -> &Geolocation<R>;
@@ -58,9 +38,6 @@ impl<R: Runtime, T: Manager<R>> crate::GeolocationExt<R> for T {
/// Initializes the plugin.
pub fn init<R: Runtime>() -> TauriPlugin<R> {
/* let (invoke_handler, register_events) =
specta_builder!().build_plugin_utils("geolocation").unwrap(); */
Builder::new("geolocation")
.invoke_handler(tauri::generate_handler![
commands::get_current_position,
@@ -79,22 +56,3 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
})
.build()
}
/* #[cfg(test)]
mod test {
use super::*;
#[test]
fn export_types() {
specta_builder!()
.path("./guest-js/bindings.ts")
.config(
specta::ts::ExportConfig::default()
.formatter(specta::ts::formatter::prettier)
.bigint(specta::ts::BigIntExportBehavior::Number),
)
.export_for_plugin("geolocation")
.expect("failed to export specta types");
}
}
*/
+12 -7
View File
@@ -3,10 +3,10 @@
// SPDX-License-Identifier: MIT
use serde::{Deserialize, Serialize};
use specta::Type;
use tauri::plugin::PermissionState;
#[derive(Debug, Clone, Default, Serialize, Deserialize, Type)]
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct PermissionStatus {
/// Permission state for the location alias.
@@ -25,7 +25,8 @@ pub struct PermissionStatus {
pub coarse_location: PermissionState,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, Type)]
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct PositionOptions {
/// High accuracy mode (such as GPS, if available)
@@ -46,14 +47,16 @@ pub struct PositionOptions {
pub maximum_age: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize, Type)]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub enum PermissionType {
Location,
CoarseLocation,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, Type)]
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct Coordinates {
/// Latitude in decimal degrees.
@@ -73,7 +76,8 @@ pub struct Coordinates {
pub heading: Option<f64>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, Type)]
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct Position {
/// Creation time for these coordinates.
@@ -83,7 +87,8 @@ pub struct Position {
pub coords: Coordinates,
}
#[derive(Debug, Clone, Serialize, Deserialize, Type)]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(untagged)]
pub enum WatchEvent {
Position(Position),
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_GLOBAL_SHORTCUT__=function(t){"use strict";function e(t,e,r,s){if("a"===r&&!s)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!s:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?s:"a"===r?s.call(t):s?s.value:e.get(t)}function r(t,e,r,s,n){if("function"==typeof e?t!==e||!n:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,r),r}var s,n,i;"function"==typeof SuppressedError&&SuppressedError;const o="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,s.set(this,(()=>{})),n.set(this,0),i.set(this,{}),this.id=function(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}((({message:t,id:o})=>{if(o===e(this,n,"f")){r(this,n,o+1),e(this,s,"f").call(this,t);const a=Object.keys(e(this,i,"f"));if(a.length>0){let t=o+1;for(const r of a.sort()){if(parseInt(r)!==t)break;{const n=e(this,i,"f")[r];delete e(this,i,"f")[r],e(this,s,"f").call(this,n),t+=1}}r(this,n,t)}}else e(this,i,"f")[o.toString()]=t}))}set onmessage(t){r(this,s,t)}get onmessage(){return e(this,s,"f")}[(s=new WeakMap,n=new WeakMap,i=new WeakMap,o)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[o]()}}async function _(t,e={},r){return window.__TAURI_INTERNALS__.invoke(t,e,r)}return t.isRegistered=async function(t){return await _("plugin:global-shortcut|is_registered",{shortcut:t})},t.register=async function(t,e){const r=new a;return r.onmessage=e,await _("plugin:global-shortcut|register",{shortcuts:Array.isArray(t)?t:[t],handler:r})},t.unregister=async function(t){return await _("plugin:global-shortcut|unregister",{shortcuts:Array.isArray(t)?t:[t]})},t.unregisterAll=async function(){return await _("plugin:global-shortcut|unregister_all",{})},t}({});Object.defineProperty(window.__TAURI__,"globalShortcut",{value:__TAURI_PLUGIN_GLOBAL_SHORTCUT__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_GLOBAL_SHORTCUT__=function(t){"use strict";function e(t,e,r,s){if("a"===r&&!s)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!s:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?s:"a"===r?s.call(t):s?s.value:e.get(t)}function r(t,e,r,s,i){if("function"==typeof e||!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,r),r}var s,i,n;"function"==typeof SuppressedError&&SuppressedError;const o="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,s.set(this,(()=>{})),i.set(this,0),n.set(this,[]),this.id=function(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}((({message:t,id:o})=>{if(o==e(this,i,"f"))for(e(this,s,"f").call(this,t),r(this,i,e(this,i,"f")+1);e(this,i,"f")in e(this,n,"f");){const t=e(this,n,"f")[e(this,i,"f")];e(this,s,"f").call(this,t),delete e(this,n,"f")[e(this,i,"f")],r(this,i,e(this,i,"f")+1)}else e(this,n,"f")[o]=t}))}set onmessage(t){r(this,s,t)}get onmessage(){return e(this,s,"f")}[(s=new WeakMap,i=new WeakMap,n=new WeakMap,o)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[o]()}}async function _(t,e={},r){return window.__TAURI_INTERNALS__.invoke(t,e,r)}return t.isRegistered=async function(t){return await _("plugin:global-shortcut|is_registered",{shortcut:t})},t.register=async function(t,e){const r=new a;return r.onmessage=e,await _("plugin:global-shortcut|register",{shortcuts:Array.isArray(t)?t:[t],handler:r})},t.unregister=async function(t){return await _("plugin:global-shortcut|unregister",{shortcuts:Array.isArray(t)?t:[t]})},t.unregisterAll=async function(){return await _("plugin:global-shortcut|unregister_all",{})},t}({});Object.defineProperty(window.__TAURI__,"globalShortcut",{value:__TAURI_PLUGIN_GLOBAL_SHORTCUT__})}
+13
View File
@@ -1,5 +1,18 @@
# Changelog
## \[2.2.3]
- [`406e6f48`](https://github.com/tauri-apps/plugins-workspace/commit/406e6f484cdc13d35c50fb949f7489ca9eeccc44) ([#2323](https://github.com/tauri-apps/plugins-workspace/pull/2323) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Fixed an issue that caused build failures when the `haptics` or `geolocation` plugin was used without their `specta` feature flag enabled.
## \[2.2.2]
- [`c9c13a0f`](https://github.com/tauri-apps/plugins-workspace/commit/c9c13a0fe7cdaac223843f5ba33176252f8e22f5) ([#2316](https://github.com/tauri-apps/plugins-workspace/pull/2316) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) **Breaking change:** `specta` integration is now behind a `specta` feature flag like in Tauri.
- [`c9c13a0f`](https://github.com/tauri-apps/plugins-workspace/commit/c9c13a0fe7cdaac223843f5ba33176252f8e22f5) ([#2316](https://github.com/tauri-apps/plugins-workspace/pull/2316) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Unlock and widen `specta` version range to match Tauri. No API changes.
## \[2.2.1]
- [`fb67ab2b`](https://github.com/tauri-apps/plugins-workspace/commit/fb67ab2b926502bfc20d6b43fbdd156691ea8526) ([#2281](https://github.com/tauri-apps/plugins-workspace/pull/2281) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Added `specta-util` to fix a "dependency not found" compilation error.
## \[2.2.0]
- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+6 -3
View File
@@ -1,7 +1,7 @@
[package]
name = "tauri-plugin-haptics"
description = "Haptic feedback and vibrations on Android and iOS"
version = "2.2.0"
version = "2.2.3"
edition = { workspace = true }
authors = { workspace = true }
license = { workspace = true }
@@ -26,10 +26,13 @@ tauri-plugin = { workspace = true, features = ["build"] }
[dependencies]
serde = { workspace = true }
serde_json = { workspace = true }
tauri = { workspace = true, features = ["specta"] }
tauri = { workspace = true }
log = { workspace = true }
thiserror = { workspace = true }
specta = { workspace = true }
specta = { workspace = true, optional = true }
[target.'cfg(target_os = "ios")'.dependencies]
tauri = { workspace = true, features = ["wry"] }
[features]
specta = ["dep:specta", "tauri/specta"]
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-haptics",
"version": "2.2.0",
"version": "2.2.3",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
-4
View File
@@ -7,13 +7,11 @@ use tauri::{command, AppHandle, Runtime};
use crate::{HapticsExt, ImpactFeedbackStyle, NotificationFeedbackType, Result};
#[command]
#[specta::specta]
pub(crate) async fn vibrate<R: Runtime>(app: AppHandle<R>, duration: u32) -> Result<()> {
app.haptics().vibrate(duration)
}
#[command]
#[specta::specta]
pub(crate) async fn impact_feedback<R: Runtime>(
app: AppHandle<R>,
style: ImpactFeedbackStyle,
@@ -22,7 +20,6 @@ pub(crate) async fn impact_feedback<R: Runtime>(
}
#[command]
#[specta::specta]
pub(crate) async fn notification_feedback<R: Runtime>(
app: AppHandle<R>,
r#type: NotificationFeedbackType,
@@ -31,7 +28,6 @@ pub(crate) async fn notification_feedback<R: Runtime>(
}
#[command]
#[specta::specta]
pub(crate) async fn selection_feedback<R: Runtime>(app: AppHandle<R>) -> Result<()> {
app.haptics().selection_feedback()
}
+3 -3
View File
@@ -3,18 +3,18 @@
// SPDX-License-Identifier: MIT
use serde::{ser::Serializer, Serialize};
use specta::Type;
pub type Result<T> = std::result::Result<T, Error>;
// TODO: Improve Error handling (different typed errors instead of one (stringified) PluginInvokeError for all mobile errors)
#[derive(Debug, thiserror::Error, Type)]
#[derive(Debug, thiserror::Error)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
pub enum Error {
#[cfg(mobile)]
#[error(transparent)]
PluginInvoke(
#[serde(skip)]
#[cfg_attr(feature = "specta", serde(skip))]
#[from]
tauri::plugin::mobile::PluginInvokeError,
),
-41
View File
@@ -7,8 +7,6 @@ use tauri::{
Manager, Runtime,
};
//use tauri_specta::*;
pub use models::*;
#[cfg(desktop)]
@@ -27,23 +25,6 @@ use desktop::Haptics;
#[cfg(mobile)]
use mobile::Haptics;
/* macro_rules! specta_builder {
() => {
ts::builder()
.commands(collect_commands![
commands::vibrate,
commands::impact_feedback,
commands::notification_feedback,
commands::selection_feedback
])
.header("// @ts-nocheck")
.config(
specta::ts::ExportConfig::default()
.bigint(specta::ts::BigIntExportBehavior::Number),
)
};
} */
/// Extensions to [`tauri::App`], [`tauri::AppHandle`], [`tauri::WebviewWindow`], [`tauri::Webview`] and [`tauri::Window`] to access the haptics APIs.
pub trait HapticsExt<R: Runtime> {
fn haptics(&self) -> &Haptics<R>;
@@ -57,9 +38,6 @@ impl<R: Runtime, T: Manager<R>> crate::HapticsExt<R> for T {
/// Initializes the plugin.
pub fn init<R: Runtime>() -> TauriPlugin<R> {
/* let (invoke_handler, register_events) =
specta_builder!().build_plugin_utils("haptics").unwrap(); */
Builder::new("haptics")
.invoke_handler(tauri::generate_handler![
commands::vibrate,
@@ -77,22 +55,3 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
})
.build()
}
/* #[cfg(test)]
mod test {
use super::*;
#[test]
fn export_types() {
specta_builder!()
.path("./guest-js/bindings.ts")
.config(
specta::ts::ExportConfig::default()
.formatter(specta::ts::formatter::prettier)
.bigint(specta::ts::BigIntExportBehavior::Number),
)
.export_for_plugin("haptics")
.expect("failed to export specta types");
}
}
*/
+6 -4
View File
@@ -3,9 +3,9 @@
// SPDX-License-Identifier: MIT
use serde::{Deserialize, Serialize};
use specta::Type;
/*
#[derive(Debug, Clone, Default, Serialize, Deserialize, Type)]
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub struct HapticsOptions {
// TODO: support array to match web api
@@ -13,7 +13,8 @@ pub struct HapticsOptions {
}
*/
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, Type)]
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub enum ImpactFeedbackStyle {
Light,
@@ -24,7 +25,8 @@ pub enum ImpactFeedbackStyle {
Rigid,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, Type)]
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[serde(rename_all = "camelCase")]
pub enum NotificationFeedbackType {
#[default]
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.3.0]
- [`10513649`](https://github.com/tauri-apps/plugins-workspace/commit/105136494c5a5bf4b1f1cc06cc71815412d17ec8) ([#2204](https://github.com/tauri-apps/plugins-workspace/pull/2204) by [@RickeyWard](https://github.com/tauri-apps/plugins-workspace/../../RickeyWard)) Add `dangerous-settings` feature flag and new JS `danger` option to disable tls hostname/certificate validation.
## \[2.2.0]
- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+2 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-http"
version = "2.2.0"
version = "2.3.0"
description = "Access an HTTP client written in Rust."
edition = { workspace = true }
authors = { workspace = true }
@@ -73,3 +73,4 @@ charset = ["reqwest/charset"]
macos-system-configuration = ["reqwest/macos-system-configuration"]
unsafe-headers = []
tracing = ["dep:tracing"]
dangerous-settings = []
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_HTTP__=function(e){"use strict";async function t(e,t={},r){return window.__TAURI_INTERNALS__.invoke(e,t,r)}"function"==typeof SuppressedError&&SuppressedError;const r="Request canceled";return e.fetch=async function(e,n){const a=n?.signal;if(a?.aborted)throw new Error(r);const o=n?.maxRedirections,s=n?.connectTimeout,i=n?.proxy;n&&(delete n.maxRedirections,delete n.connectTimeout,delete n.proxy);const d=n?.headers?n.headers instanceof Headers?n.headers:new Headers(n.headers):new Headers,c=new Request(e,n),u=await c.arrayBuffer(),f=0!==u.byteLength?Array.from(new Uint8Array(u)):null;for(const[e,t]of c.headers)d.get(e)||d.set(e,t);const _=(d instanceof Headers?Array.from(d.entries()):Array.isArray(d)?d:Object.entries(d)).map((([e,t])=>[e,"string"==typeof t?t:t.toString()]));if(a?.aborted)throw new Error(r);const h=await t("plugin:http|fetch",{clientConfig:{method:c.method,url:c.url,headers:_,data:f,maxRedirections:o,connectTimeout:s,proxy:i}}),l=()=>t("plugin:http|fetch_cancel",{rid:h});if(a?.aborted)throw l(),new Error(r);a?.addEventListener("abort",(()=>{l()}));const{status:p,statusText:w,url:y,headers:T,rid:A}=await t("plugin:http|fetch_send",{rid:h}),g=await t("plugin:http|fetch_read_body",{rid:A}),R=new Response(g instanceof ArrayBuffer&&0!==g.byteLength?g:g instanceof Array&&g.length>0?new Uint8Array(g):null,{status:p,statusText:w});return Object.defineProperty(R,"url",{value:y}),Object.defineProperty(R,"headers",{value:new Headers(T)}),R},e}({});Object.defineProperty(window.__TAURI__,"http",{value:__TAURI_PLUGIN_HTTP__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_HTTP__=function(e){"use strict";async function t(e,t={},r){return window.__TAURI_INTERNALS__.invoke(e,t,r)}"function"==typeof SuppressedError&&SuppressedError;const r="Request canceled";return e.fetch=async function(e,n){const a=n?.signal;if(a?.aborted)throw new Error(r);const o=n?.maxRedirections,s=n?.connectTimeout,i=n?.proxy,d=n?.danger;n&&(delete n.maxRedirections,delete n.connectTimeout,delete n.proxy,delete n.danger);const c=n?.headers?n.headers instanceof Headers?n.headers:new Headers(n.headers):new Headers,u=new Request(e,n),f=await u.arrayBuffer(),_=0!==f.byteLength?Array.from(new Uint8Array(f)):null;for(const[e,t]of u.headers)c.get(e)||c.set(e,t);const h=(c instanceof Headers?Array.from(c.entries()):Array.isArray(c)?c:Object.entries(c)).map((([e,t])=>[e,"string"==typeof t?t:t.toString()]));if(a?.aborted)throw new Error(r);const l=await t("plugin:http|fetch",{clientConfig:{method:u.method,url:u.url,headers:h,data:_,maxRedirections:o,connectTimeout:s,proxy:i,danger:d}}),p=()=>t("plugin:http|fetch_cancel",{rid:l});if(a?.aborted)throw p(),new Error(r);a?.addEventListener("abort",(()=>{p()}));const{status:w,statusText:y,url:g,headers:T,rid:A}=await t("plugin:http|fetch_send",{rid:l}),R=await t("plugin:http|fetch_read_body",{rid:A}),b=new Response(R instanceof ArrayBuffer&&0!==R.byteLength?R:R instanceof Array&&R.length>0?new Uint8Array(R):null,{status:w,statusText:y});return Object.defineProperty(b,"url",{value:g}),Object.defineProperty(b,"headers",{value:new Headers(T)}),b},e}({});Object.defineProperty(window.__TAURI__,"http",{value:__TAURI_PLUGIN_HTTP__})}
+24 -1
View File
@@ -84,6 +84,26 @@ export interface ClientOptions {
* Configuration of a proxy that a Client should pass requests to.
*/
proxy?: Proxy
/**
* Configuration for dangerous settings on the client such as disabling SSL verification.
*/
danger?: DangerousSettings
}
/**
* Configuration for dangerous settings on the client such as disabling SSL verification.
*
* @since 2.3.0
*/
export interface DangerousSettings {
/**
* Disables SSL verification.
*/
acceptInvalidCerts?: boolean
/**
* Disables hostname verification.
*/
acceptInvalidHostnames?: boolean
}
const ERROR_REQUEST_CANCELLED = 'Request canceled'
@@ -115,12 +135,14 @@ export async function fetch(
const maxRedirections = init?.maxRedirections
const connectTimeout = init?.connectTimeout
const proxy = init?.proxy
const danger = init?.danger
// Remove these fields before creating the request
if (init) {
delete init.maxRedirections
delete init.connectTimeout
delete init.proxy
delete init.danger
}
const headers = init?.headers
@@ -172,7 +194,8 @@ export async function fetch(
data,
maxRedirections,
connectTimeout,
proxy
proxy,
danger
}
})
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-http",
"version": "2.2.0",
"version": "2.3.0",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
+28
View File
@@ -75,6 +75,14 @@ pub struct FetchResponse {
rid: ResourceId,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
#[allow(dead_code)] //feature flags shoudln't affect api
pub struct DangerousSettings {
accept_invalid_certs: bool,
accept_invalid_hostnames: bool,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ClientConfig {
@@ -85,6 +93,7 @@ pub struct ClientConfig {
connect_timeout: Option<u64>,
max_redirections: Option<usize>,
proxy: Option<Proxy>,
danger: Option<DangerousSettings>,
}
#[derive(Debug, Deserialize)]
@@ -181,6 +190,7 @@ pub async fn fetch<R: Runtime>(
connect_timeout,
max_redirections,
proxy,
danger,
} = client_config;
let scheme = url.scheme();
@@ -220,6 +230,24 @@ pub async fn fetch<R: Runtime>(
{
let mut builder = reqwest::ClientBuilder::new();
if let Some(danger_config) = danger {
#[cfg(not(feature = "dangerous-settings"))]
{
#[cfg(debug_assertions)]
{
eprintln!("[\x1b[33mWARNING\x1b[0m] using dangerous settings requires `dangerous-settings` feature flag in your Cargo.toml");
}
let _ = danger_config;
return Err(Error::DangerousSettings);
}
#[cfg(feature = "dangerous-settings")]
{
builder = builder
.danger_accept_invalid_certs(danger_config.accept_invalid_certs)
.danger_accept_invalid_hostnames(danger_config.accept_invalid_hostnames)
}
}
if let Some(timeout) = connect_timeout {
builder = builder.connect_timeout(Duration::from_millis(timeout));
}
+2
View File
@@ -41,6 +41,8 @@ pub enum Error {
Tauri(#[from] tauri::Error),
#[error(transparent)]
Utf8(#[from] std::string::FromUtf8Error),
#[error("dangerous settings used but are not enabled")]
DangerousSettings,
}
impl Serialize for Error {
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.2.1]
- [`784a54a3`](https://github.com/tauri-apps/plugins-workspace/commit/784a54a39094dfbaaa8dd123eb083c04dc6c3bb2) ([#2344](https://github.com/tauri-apps/plugins-workspace/pull/2344) by [@madsmtm](https://github.com/tauri-apps/plugins-workspace/../../madsmtm)) Use `objc2` instead of `objc`.
## \[2.2.0]
- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+8 -5
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-log"
version = "2.2.0"
version = "2.2.1"
description = "Configurable logging for your Tauri app."
authors = { workspace = true }
license = { workspace = true }
@@ -17,8 +17,8 @@ rustdoc-args = ["--cfg", "docsrs"]
windows = { level = "full", notes = "" }
linux = { level = "full", notes = "" }
macos = { level = "full", notes = "" }
android = { level = "unknown", notes = "" }
ios = { level = "unknown", notes = "" }
android = { level = "full", notes = "" }
ios = { level = "full", notes = "" }
[build-dependencies]
tauri-plugin = { workspace = true, features = ["build"] }
@@ -39,8 +39,11 @@ android_logger = "0.14"
[target."cfg(target_os = \"ios\")".dependencies]
swift-rs = "1"
objc = "0.2"
cocoa = "0.26"
objc2 = "0.5"
objc2-foundation = { version = "0.2", default-features = false, features = [
"std",
"NSString",
] }
[features]
colored = ["fern/colored"]
+17 -1
View File
@@ -54,7 +54,23 @@ yarn add https://github.com/tauri-apps/tauri-plugin-log#v2
## Usage
First you need to register the core plugin with Tauri:
First, you should enable the `log:default` capability:
```json
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "Capability for the main window",
"windows": ["main"],
"permissions": [
"core:default",
"opener:default",
"log:default" # add this!
]
}
```
Then, you need to register the core plugin with Tauri:
`src-tauri/src/lib.rs`
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-log",
"version": "2.2.0",
"version": "2.2.1",
"description": "Configurable logging for your Tauri app.",
"license": "MIT OR Apache-2.0",
"authors": [
+6 -26
View File
@@ -35,31 +35,6 @@ pub const WEBVIEW_TARGET: &str = "webview";
#[cfg(target_os = "ios")]
mod ios {
use cocoa::base::id;
use objc::*;
const UTF8_ENCODING: usize = 4;
pub struct NSString(pub id);
impl NSString {
pub fn new(s: &str) -> Self {
// Safety: objc runtime calls are unsafe
NSString(unsafe {
let ns_string: id = msg_send![class!(NSString), alloc];
let ns_string: id = msg_send![ns_string,
initWithBytes:s.as_ptr()
length:s.len()
encoding:UTF8_ENCODING];
// The thing is allocated in rust, the thing must be set to autorelease in rust to relinquish control
// or it can not be released correctly in OC runtime
let _: () = msg_send![ns_string, autorelease];
ns_string
})
}
}
swift_rs::swift!(pub fn tauri_log(
level: u8, message: *const std::ffi::c_void
));
@@ -429,7 +404,12 @@ impl Builder {
log::Level::Info => 2,
log::Level::Warn | log::Level::Error => 3,
},
ios::NSString::new(message.as_str()).0 as _,
// The string is allocated in rust, so we must
// autorelease it rust to give it to the Swift
// runtime.
objc2::rc::Retained::autorelease_ptr(
objc2_foundation::NSString::from_str(message.as_str()),
) as _,
);
}
}),
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.2.1]
- [`da5c59e2`](https://github.com/tauri-apps/plugins-workspace/commit/da5c59e2fe879d177e3cfd52fcacce85440423cb) ([#2271](https://github.com/tauri-apps/plugins-workspace/pull/2271) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated `zbus` dependency to version 5. No API changes.
## \[2.2.0]
- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-notification"
version = "2.2.0"
version = "2.2.1"
description = "Send desktop and mobile notifications on your Tauri application."
edition = { workspace = true }
authors = { workspace = true }
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_NOTIFICATION__=function(i){"use strict";function t(i,t,n,e){if("a"===n&&!e)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?i!==t||!e:!t.has(i))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?e:"a"===n?e.call(i):e?e.value:t.get(i)}function n(i,t,n,e,o){if("function"==typeof t?i!==t||!o:!t.has(i))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(i,n),n}var e,o,a;"function"==typeof SuppressedError&&SuppressedError;const r="__TAURI_TO_IPC_KEY__";class c{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,e.set(this,(()=>{})),o.set(this,0),a.set(this,{}),this.id=function(i,t=!1){return window.__TAURI_INTERNALS__.transformCallback(i,t)}((({message:i,id:r})=>{if(r===t(this,o,"f")){n(this,o,r+1),t(this,e,"f").call(this,i);const c=Object.keys(t(this,a,"f"));if(c.length>0){let i=r+1;for(const n of c.sort()){if(parseInt(n)!==i)break;{const o=t(this,a,"f")[n];delete t(this,a,"f")[n],t(this,e,"f").call(this,o),i+=1}}n(this,o,i)}}else t(this,a,"f")[r.toString()]=i}))}set onmessage(i){n(this,e,i)}get onmessage(){return t(this,e,"f")}[(e=new WeakMap,o=new WeakMap,a=new WeakMap,r)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[r]()}}class s{constructor(i,t,n){this.plugin=i,this.event=t,this.channelId=n}async unregister(){return u(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}}async function l(i,t,n){const e=new c;return e.onmessage=n,u(`plugin:${i}|registerListener`,{event:t,handler:e}).then((()=>new s(i,t,e.id)))}async function u(i,t={},n){return window.__TAURI_INTERNALS__.invoke(i,t,n)}var f,d,w;i.ScheduleEvery=void 0,(f=i.ScheduleEvery||(i.ScheduleEvery={})).Year="year",f.Month="month",f.TwoWeeks="twoWeeks",f.Week="week",f.Day="day",f.Hour="hour",f.Minute="minute",f.Second="second";return i.Importance=void 0,(d=i.Importance||(i.Importance={}))[d.None=0]="None",d[d.Min=1]="Min",d[d.Low=2]="Low",d[d.Default=3]="Default",d[d.High=4]="High",i.Visibility=void 0,(w=i.Visibility||(i.Visibility={}))[w.Secret=-1]="Secret",w[w.Private=0]="Private",w[w.Public=1]="Public",i.Schedule=class{static at(i,t=!1,n=!1){return{at:{date:i,repeating:t,allowWhileIdle:n},interval:void 0,every:void 0}}static interval(i,t=!1){return{at:void 0,interval:{interval:i,allowWhileIdle:t},every:void 0}}static every(i,t,n=!1){return{at:void 0,interval:void 0,every:{interval:i,count:t,allowWhileIdle:n}}}},i.active=async function(){return await u("plugin:notification|get_active")},i.cancel=async function(i){await u("plugin:notification|cancel",{notifications:i})},i.cancelAll=async function(){await u("plugin:notification|cancel")},i.channels=async function(){return await u("plugin:notification|listChannels")},i.createChannel=async function(i){await u("plugin:notification|create_channel",{...i})},i.isPermissionGranted=async function(){return"default"!==window.Notification.permission?await Promise.resolve("granted"===window.Notification.permission):await u("plugin:notification|is_permission_granted")},i.onAction=async function(i){return await l("notification","actionPerformed",i)},i.onNotificationReceived=async function(i){return await l("notification","notification",i)},i.pending=async function(){return await u("plugin:notification|get_pending")},i.registerActionTypes=async function(i){await u("plugin:notification|register_action_types",{types:i})},i.removeActive=async function(i){await u("plugin:notification|remove_active",{notifications:i})},i.removeAllActive=async function(){await u("plugin:notification|remove_active")},i.removeChannel=async function(i){await u("plugin:notification|delete_channel",{id:i})},i.requestPermission=async function(){return await window.Notification.requestPermission()},i.sendNotification=function(i){"string"==typeof i?new window.Notification(i):new window.Notification(i.title,i)},i}({});Object.defineProperty(window.__TAURI__,"notification",{value:__TAURI_PLUGIN_NOTIFICATION__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_NOTIFICATION__=function(i){"use strict";function t(i,t,n,e){if("a"===n&&!e)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?i!==t||!e:!t.has(i))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?e:"a"===n?e.call(i):e?e.value:t.get(i)}function n(i,t,n,e,a){if("function"==typeof t||!t.has(i))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(i,n),n}var e,a,o;"function"==typeof SuppressedError&&SuppressedError;const r="__TAURI_TO_IPC_KEY__";class s{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,e.set(this,(()=>{})),a.set(this,0),o.set(this,[]),this.id=function(i,t=!1){return window.__TAURI_INTERNALS__.transformCallback(i,t)}((({message:i,id:r})=>{if(r==t(this,a,"f"))for(t(this,e,"f").call(this,i),n(this,a,t(this,a,"f")+1);t(this,a,"f")in t(this,o,"f");){const i=t(this,o,"f")[t(this,a,"f")];t(this,e,"f").call(this,i),delete t(this,o,"f")[t(this,a,"f")],n(this,a,t(this,a,"f")+1)}else t(this,o,"f")[r]=i}))}set onmessage(i){n(this,e,i)}get onmessage(){return t(this,e,"f")}[(e=new WeakMap,a=new WeakMap,o=new WeakMap,r)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[r]()}}class c{constructor(i,t,n){this.plugin=i,this.event=t,this.channelId=n}async unregister(){return u(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}}async function l(i,t,n){const e=new s;return e.onmessage=n,u(`plugin:${i}|registerListener`,{event:t,handler:e}).then((()=>new c(i,t,e.id)))}async function u(i,t={},n){return window.__TAURI_INTERNALS__.invoke(i,t,n)}var f,h,d;i.ScheduleEvery=void 0,(f=i.ScheduleEvery||(i.ScheduleEvery={})).Year="year",f.Month="month",f.TwoWeeks="twoWeeks",f.Week="week",f.Day="day",f.Hour="hour",f.Minute="minute",f.Second="second";return i.Importance=void 0,(h=i.Importance||(i.Importance={}))[h.None=0]="None",h[h.Min=1]="Min",h[h.Low=2]="Low",h[h.Default=3]="Default",h[h.High=4]="High",i.Visibility=void 0,(d=i.Visibility||(i.Visibility={}))[d.Secret=-1]="Secret",d[d.Private=0]="Private",d[d.Public=1]="Public",i.Schedule=class{static at(i,t=!1,n=!1){return{at:{date:i,repeating:t,allowWhileIdle:n},interval:void 0,every:void 0}}static interval(i,t=!1){return{at:void 0,interval:{interval:i,allowWhileIdle:t},every:void 0}}static every(i,t,n=!1){return{at:void 0,interval:void 0,every:{interval:i,count:t,allowWhileIdle:n}}}},i.active=async function(){return await u("plugin:notification|get_active")},i.cancel=async function(i){await u("plugin:notification|cancel",{notifications:i})},i.cancelAll=async function(){await u("plugin:notification|cancel")},i.channels=async function(){return await u("plugin:notification|listChannels")},i.createChannel=async function(i){await u("plugin:notification|create_channel",{...i})},i.isPermissionGranted=async function(){return"default"!==window.Notification.permission?await Promise.resolve("granted"===window.Notification.permission):await u("plugin:notification|is_permission_granted")},i.onAction=async function(i){return await l("notification","actionPerformed",i)},i.onNotificationReceived=async function(i){return await l("notification","notification",i)},i.pending=async function(){return await u("plugin:notification|get_pending")},i.registerActionTypes=async function(i){await u("plugin:notification|register_action_types",{types:i})},i.removeActive=async function(i){await u("plugin:notification|remove_active",{notifications:i})},i.removeAllActive=async function(){await u("plugin:notification|remove_active")},i.removeChannel=async function(i){await u("plugin:notification|delete_channel",{id:i})},i.requestPermission=async function(){return await window.Notification.requestPermission()},i.sendNotification=function(i){"string"==typeof i?new window.Notification(i):new window.Notification(i.title,i)},i}({});Object.defineProperty(window.__TAURI__,"notification",{value:__TAURI_PLUGIN_NOTIFICATION__})}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-notification",
"version": "2.2.0",
"version": "2.2.1",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
+20
View File
@@ -1,5 +1,25 @@
# Changelog
## \[2.2.5]
- [`5b821181`](https://github.com/tauri-apps/plugins-workspace/commit/5b8211815825ddae2dcc0c00520e0cfdff002763) ([#2332](https://github.com/tauri-apps/plugins-workspace/pull/2332) by [@betamos](https://github.com/tauri-apps/plugins-workspace/../../betamos)) Fix broken JS commands `opener.openPath` and `opener.openUrl` on mobile.
## \[2.2.4]
- [`da5c59e2`](https://github.com/tauri-apps/plugins-workspace/commit/da5c59e2fe879d177e3cfd52fcacce85440423cb) ([#2271](https://github.com/tauri-apps/plugins-workspace/pull/2271) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated `zbus` dependency to version 5. No API changes.
## \[2.2.3]
- [`a9ac1e3c`](https://github.com/tauri-apps/plugins-workspace/commit/a9ac1e3c939cec4338a9422ef02323c1d4dde6cd) ([#2253](https://github.com/tauri-apps/plugins-workspace/pull/2253) by [@betamos](https://github.com/tauri-apps/plugins-workspace/../../betamos)) Return an error in `open_path` if the file does not exist when opening with default application.
## \[2.2.2]
- [`ee0f65de`](https://github.com/tauri-apps/plugins-workspace/commit/ee0f65de5c645c244c5f0b638e0e0aab687cb9bf) ([#2207](https://github.com/tauri-apps/plugins-workspace/pull/2207) by [@universalappfactory](https://github.com/tauri-apps/plugins-workspace/../../universalappfactory)) Fixed OpenerPlugin packagename for android
## \[2.2.1]
- [`18dffc9d`](https://github.com/tauri-apps/plugins-workspace/commit/18dffc9dfecaf0c900e233e041d9ca36c92834b5) ([#2189](https://github.com/tauri-apps/plugins-workspace/pull/2189) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Fix usage on iOS.
## \[2.2.0]
- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+6 -4
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-opener"
version = "2.2.0"
version = "2.2.5"
description = "Open files and URLs using their default application."
edition = { workspace = true }
authors = { workspace = true }
@@ -15,7 +15,7 @@ rustdoc-args = ["--cfg", "docsrs"]
# Platforms supported by the plugin
# Support levels are "full", "partial", "none", "unknown"
# Details of the support level are left to plugin maintainer
[package.metadata.platforms]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
linux = { level = "full", notes = "" }
macos = { level = "full", notes = "" }
@@ -55,11 +55,13 @@ url = { workspace = true }
[target."cfg(target_os = \"macos\")".dependencies.objc2-app-kit]
version = "0.2"
features = ["NSWorkspace"]
default-features = false
features = ["std", "NSWorkspace"]
[target."cfg(target_os = \"macos\")".dependencies.objc2-foundation]
version = "0.2"
features = ["NSURL", "NSArray", "NSString"]
default-features = false
features = ["std", "NSURL", "NSArray", "NSString"]
[target.'cfg(target_os = "ios")'.dependencies]
tauri = { workspace = true, features = ["wry"] }
+10
View File
@@ -98,8 +98,18 @@ fn main() {
.plugin(tauri_plugin_opener::init())
.setup(|app| {
let opener = app.opener();
// Opens the URL in the default browser
opener.open_url("https://example.com", None::<&str>)?;
// Or with a specific browser/app
opener.open_url("https://example.com", Some("firefox"))?;
// Opens the path with the system's default app
opener.open_path("/path/to/file", None::<&str>)?;
// Or with a specific app
opener.open_path("/path/to/file", Some("firefox"))?;
// Reveal a path with the system's default explorer
opener.reveal_item_in_dir("/path/to/file")?;
Ok(())
})
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
package app.tauri.shell
package app.tauri.opener
import android.app.Activity
import android.content.Intent
@@ -27,4 +27,4 @@ class OpenerPlugin(private val activity: Activity) : Plugin(activity) {
invoke.reject(ex.message)
}
}
}
}
+14 -16
View File
@@ -3,32 +3,30 @@
// SPDX-License-Identifier: MIT
import Foundation
import SwiftRs
import Tauri
import UIKit
import WebKit
class OpenerPlugin: Plugin {
@objc public func open(_ invoke: Invoke) throws {
do {
let urlString = try invoke.parseArgs(String.self)
if let url = URL(string: urlString) {
if #available(iOS 10, *) {
UIApplication.shared.open(url, options: [:])
} else {
UIApplication.shared.openURL(url)
}
}
invoke.resolve()
} catch {
invoke.reject(error.localizedDescription)
@objc public func open(_ invoke: Invoke) throws {
do {
let urlString = try invoke.parseArgs(String.self)
if let url = URL(string: urlString) {
if #available(iOS 10, *) {
UIApplication.shared.open(url, options: [:])
} else {
UIApplication.shared.openURL(url)
}
}
invoke.resolve()
} catch {
invoke.reject(error.localizedDescription)
}
}
}
@_cdecl("init_plugin_shell")
@_cdecl("init_plugin_opener")
func initPlugin() -> Plugin {
return OpenerPlugin()
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-opener",
"version": "2.2.0",
"version": "2.2.5",
"description": "Open files and URLs using their default application.",
"license": "MIT OR Apache-2.0",
"authors": [
+3 -3
View File
@@ -9,7 +9,7 @@ use tauri::{
AppHandle, Runtime,
};
use crate::{scope::Scope, Error};
use crate::{scope::Scope, Error, OpenerExt};
#[tauri::command]
pub async fn open_url<R: Runtime>(
@@ -34,7 +34,7 @@ pub async fn open_url<R: Runtime>(
);
if scope.is_url_allowed(&url, with.as_deref()) {
crate::open_url(url, with)
app.opener().open_url(url, with)
} else {
Err(Error::ForbiddenUrl { url, with })
}
@@ -63,7 +63,7 @@ pub async fn open_path<R: Runtime>(
);
if scope.is_path_allowed(Path::new(&path), with.as_deref())? {
crate::open_path(path, with)
app.opener().open_path(path, with)
} else {
Err(Error::ForbiddenPath { path, with })
}
+53 -1
View File
@@ -38,6 +38,19 @@ pub struct Opener<R: Runtime> {
impl<R: Runtime> Opener<R> {
/// Open a url with a default or specific program.
///
/// # Examples
///
/// ```rust,no_run
/// use tauri_plugin_opener::OpenerExt;
///
/// tauri::Builder::default()
/// .setup(|app| {
/// // open the given URL on the system default browser
/// app.opener().open_url("https://github.com/tauri-apps/tauri", None::<&str>)?;
/// Ok(())
/// });
/// ```
///
/// ## Platform-specific:
///
/// - **Android / iOS**: Always opens using default program.
@@ -48,6 +61,19 @@ impl<R: Runtime> Opener<R> {
/// Open a url with a default or specific program.
///
/// # Examples
///
/// ```rust,no_run
/// use tauri_plugin_opener::OpenerExt;
///
/// tauri::Builder::default()
/// .setup(|app| {
/// // open the given URL on the system default browser
/// app.opener().open_url("https://github.com/tauri-apps/tauri", None::<&str>)?;
/// Ok(())
/// });
/// ```
///
/// ## Platform-specific:
///
/// - **Android / iOS**: Always opens using default program.
@@ -60,6 +86,19 @@ impl<R: Runtime> Opener<R> {
/// Open a path with a default or specific program.
///
/// # Examples
///
/// ```rust,no_run
/// use tauri_plugin_opener::OpenerExt;
///
/// tauri::Builder::default()
/// .setup(|app| {
/// // open the given path on the system default explorer
/// app.opener().open_path("/path/to/file", None::<&str>)?;
/// Ok(())
/// });
/// ```
///
/// ## Platform-specific:
///
/// - **Android / iOS**: Always opens using default program.
@@ -74,6 +113,19 @@ impl<R: Runtime> Opener<R> {
/// Open a path with a default or specific program.
///
/// # Examples
///
/// ```rust,no_run
/// use tauri_plugin_opener::OpenerExt;
///
/// tauri::Builder::default()
/// .setup(|app| {
/// // open the given path on the system default explorer
/// app.opener().open_path("/path/to/file", None::<&str>)?;
/// Ok(())
/// });
/// ```
///
/// ## Platform-specific:
///
/// - **Android / iOS**: Always opens using default program.
@@ -98,7 +150,7 @@ pub trait OpenerExt<R: Runtime> {
fn opener(&self) -> &Opener<R>;
}
impl<R: Runtime, T: Manager<R>> crate::OpenerExt<R> for T {
impl<R: Runtime, T: Manager<R>> OpenerExt<R> for T {
fn opener(&self) -> &Opener<R> {
self.state::<Opener<R>>().inner()
}
+7 -3
View File
@@ -26,7 +26,7 @@ pub(crate) fn open<P: AsRef<OsStr>, S: AsRef<str>>(path: P, with: Option<S>) ->
/// tauri::Builder::default()
/// .setup(|app| {
/// // open the given URL on the system default browser
/// tauri_plugin_opener::open_url("https://github.com/tauri-apps/tauri", None)?;
/// tauri_plugin_opener::open_url("https://github.com/tauri-apps/tauri", None::<&str>)?;
/// Ok(())
/// });
/// ```
@@ -46,12 +46,16 @@ pub fn open_url<P: AsRef<str>, S: AsRef<str>>(url: P, with: Option<S>) -> crate:
/// ```rust,no_run
/// tauri::Builder::default()
/// .setup(|app| {
/// // open the given URL on the system default browser
/// tauri_plugin_opener::open_path("/path/to/file", None)?;
/// // open the given URL on the system default explorer
/// tauri_plugin_opener::open_path("/path/to/file", None::<&str>)?;
/// Ok(())
/// });
/// ```
pub fn open_path<P: AsRef<Path>, S: AsRef<str>>(path: P, with: Option<S>) -> crate::Result<()> {
let path = path.as_ref();
if with.is_none() {
// Returns an IO error if not exists, and besides `exists()` is a shorthand for `metadata()`
_ = path.metadata()?;
}
open(path, with)
}
@@ -1,7 +1,7 @@
## Default Permission
This permission set configures which
process feeatures are by default exposed.
process features are by default exposed.
#### Granted Permissions
+1 -1
View File
@@ -3,7 +3,7 @@
[default]
description = """
This permission set configures which
process feeatures are by default exposed.
process features are by default exposed.
#### Granted Permissions
@@ -315,11 +315,11 @@
"const": "deny-restart"
},
{
"description": "This permission set configures which\nprocess feeatures are by default exposed.\n\n#### Granted Permissions\n\nThis enables to quit via `allow-exit` and restart via `allow-restart`\nthe application.\n",
"description": "This permission set configures which\nprocess features are by default exposed.\n\n#### Granted Permissions\n\nThis enables to quit via `allow-exit` and restart via `allow-restart`\nthe application.\n",
"type": "string",
"const": "default"
}
]
}
}
}
}
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_SHELL__=function(e){"use strict";function t(e,t,s,n){if("a"===s&&!n)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!n:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===s?n:"a"===s?n.call(e):n?n.value:t.get(e)}function s(e,t,s,n,i){if("function"==typeof t?e!==t||!i:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(e,s),s}var n,i,r;"function"==typeof SuppressedError&&SuppressedError;const o="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,n.set(this,(()=>{})),i.set(this,0),r.set(this,{}),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((({message:e,id:o})=>{if(o===t(this,i,"f")){s(this,i,o+1),t(this,n,"f").call(this,e);const a=Object.keys(t(this,r,"f"));if(a.length>0){let e=o+1;for(const s of a.sort()){if(parseInt(s)!==e)break;{const i=t(this,r,"f")[s];delete t(this,r,"f")[s],t(this,n,"f").call(this,i),e+=1}}s(this,i,e)}}else t(this,r,"f")[o.toString()]=e}))}set onmessage(e){s(this,n,e)}get onmessage(){return t(this,n,"f")}[(n=new WeakMap,i=new WeakMap,r=new WeakMap,o)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[o]()}}async function h(e,t={},s){return window.__TAURI_INTERNALS__.invoke(e,t,s)}class c{constructor(){this.eventListeners=Object.create(null)}addListener(e,t){return this.on(e,t)}removeListener(e,t){return this.off(e,t)}on(e,t){return e in this.eventListeners?this.eventListeners[e].push(t):this.eventListeners[e]=[t],this}once(e,t){const s=n=>{this.removeListener(e,s),t(n)};return this.addListener(e,s)}off(e,t){return e in this.eventListeners&&(this.eventListeners[e]=this.eventListeners[e].filter((e=>e!==t))),this}removeAllListeners(e){return e?delete this.eventListeners[e]:this.eventListeners=Object.create(null),this}emit(e,t){if(e in this.eventListeners){const s=this.eventListeners[e];for(const e of s)e(t);return!0}return!1}listenerCount(e){return e in this.eventListeners?this.eventListeners[e].length:0}prependListener(e,t){return e in this.eventListeners?this.eventListeners[e].unshift(t):this.eventListeners[e]=[t],this}prependOnceListener(e,t){const s=n=>{this.removeListener(e,s),t(n)};return this.prependListener(e,s)}}class l{constructor(e){this.pid=e}async write(e){await h("plugin:shell|stdin_write",{pid:this.pid,buffer:e})}async kill(){await h("plugin:shell|kill",{cmd:"killChild",pid:this.pid})}}class u extends c{constructor(e,t=[],s){super(),this.stdout=new c,this.stderr=new c,this.program=e,this.args="string"==typeof t?[t]:t,this.options=s??{}}static create(e,t=[],s){return new u(e,t,s)}static sidecar(e,t=[],s){const n=new u(e,t,s);return n.options.sidecar=!0,n}async spawn(){const e=this.program,t=this.args,s=this.options;"object"==typeof t&&Object.freeze(t);const n=new a;return n.onmessage=e=>{switch(e.event){case"Error":this.emit("error",e.payload);break;case"Terminated":this.emit("close",e.payload);break;case"Stdout":this.stdout.emit("data",e.payload);break;case"Stderr":this.stderr.emit("data",e.payload)}},await h("plugin:shell|spawn",{program:e,args:t,options:s,onEvent:n}).then((e=>new l(e)))}async execute(){const e=this.program,t=this.args,s=this.options;return"object"==typeof t&&Object.freeze(t),await h("plugin:shell|execute",{program:e,args:t,options:s})}}return e.Child=l,e.Command=u,e.EventEmitter=c,e.open=async function(e,t){await h("plugin:shell|open",{path:e,with:t})},e}({});Object.defineProperty(window.__TAURI__,"shell",{value:__TAURI_PLUGIN_SHELL__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_SHELL__=function(e){"use strict";function t(e,t,s,i){if("a"===s&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!i:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===s?i:"a"===s?i.call(e):i?i.value:t.get(e)}function s(e,t,s,i,n){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(e,s),s}var i,n,r;"function"==typeof SuppressedError&&SuppressedError;const o="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),n.set(this,0),r.set(this,[]),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((({message:e,id:o})=>{if(o==t(this,n,"f"))for(t(this,i,"f").call(this,e),s(this,n,t(this,n,"f")+1);t(this,n,"f")in t(this,r,"f");){const e=t(this,r,"f")[t(this,n,"f")];t(this,i,"f").call(this,e),delete t(this,r,"f")[t(this,n,"f")],s(this,n,t(this,n,"f")+1)}else t(this,r,"f")[o]=e}))}set onmessage(e){s(this,i,e)}get onmessage(){return t(this,i,"f")}[(i=new WeakMap,n=new WeakMap,r=new WeakMap,o)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[o]()}}async function h(e,t={},s){return window.__TAURI_INTERNALS__.invoke(e,t,s)}class c{constructor(){this.eventListeners=Object.create(null)}addListener(e,t){return this.on(e,t)}removeListener(e,t){return this.off(e,t)}on(e,t){return e in this.eventListeners?this.eventListeners[e].push(t):this.eventListeners[e]=[t],this}once(e,t){const s=i=>{this.removeListener(e,s),t(i)};return this.addListener(e,s)}off(e,t){return e in this.eventListeners&&(this.eventListeners[e]=this.eventListeners[e].filter((e=>e!==t))),this}removeAllListeners(e){return e?delete this.eventListeners[e]:this.eventListeners=Object.create(null),this}emit(e,t){if(e in this.eventListeners){const s=this.eventListeners[e];for(const e of s)e(t);return!0}return!1}listenerCount(e){return e in this.eventListeners?this.eventListeners[e].length:0}prependListener(e,t){return e in this.eventListeners?this.eventListeners[e].unshift(t):this.eventListeners[e]=[t],this}prependOnceListener(e,t){const s=i=>{this.removeListener(e,s),t(i)};return this.prependListener(e,s)}}class l{constructor(e){this.pid=e}async write(e){await h("plugin:shell|stdin_write",{pid:this.pid,buffer:e})}async kill(){await h("plugin:shell|kill",{cmd:"killChild",pid:this.pid})}}class u extends c{constructor(e,t=[],s){super(),this.stdout=new c,this.stderr=new c,this.program=e,this.args="string"==typeof t?[t]:t,this.options=s??{}}static create(e,t=[],s){return new u(e,t,s)}static sidecar(e,t=[],s){const i=new u(e,t,s);return i.options.sidecar=!0,i}async spawn(){const e=this.program,t=this.args,s=this.options;"object"==typeof t&&Object.freeze(t);const i=new a;return i.onmessage=e=>{switch(e.event){case"Error":this.emit("error",e.payload);break;case"Terminated":this.emit("close",e.payload);break;case"Stdout":this.stdout.emit("data",e.payload);break;case"Stderr":this.stderr.emit("data",e.payload)}},await h("plugin:shell|spawn",{program:e,args:t,options:s,onEvent:i}).then((e=>new l(e)))}async execute(){const e=this.program,t=this.args,s=this.options;return"object"==typeof t&&Object.freeze(t),await h("plugin:shell|execute",{program:e,args:t,options:s})}}return e.Child=l,e.Command=u,e.EventEmitter=c,e.open=async function(e,t){await h("plugin:shell|open",{path:e,with:t})},e}({});Object.defineProperty(window.__TAURI__,"shell",{value:__TAURI_PLUGIN_SHELL__})}
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.2.1]
- [`da5c59e2`](https://github.com/tauri-apps/plugins-workspace/commit/da5c59e2fe879d177e3cfd52fcacce85440423cb) ([#2271](https://github.com/tauri-apps/plugins-workspace/pull/2271) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated `zbus` dependency to version 5. No API changes.
## \[2.2.0]
- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-single-instance"
version = "2.2.0"
version = "2.2.1"
description = "Ensure a single instance of your tauri app is running."
authors = { workspace = true }
license = { workspace = true }
@@ -9,6 +9,6 @@
"author": "",
"license": "MIT",
"devDependencies": {
"@tauri-apps/cli": "2.1.0"
"@tauri-apps/cli": "2.2.7"
}
}
+1 -1
View File
@@ -19,7 +19,7 @@ windows = { level = "full", notes = "" }
linux = { level = "full", notes = "" }
macos = { level = "full", notes = "" }
android = { level = "full", notes = "" }
ios = { level = "none", notes = "" }
ios = { level = "full", notes = "" }
[build-dependencies]
tauri-plugin = { workspace = true, features = ["build"] }
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_STORE__=function(t){"use strict";var e,a;function r(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}async function s(t,e={},a){return window.__TAURI_INTERNALS__.invoke(t,e,a)}"function"==typeof SuppressedError&&SuppressedError;class i{get rid(){return function(t,e,a,r){if("a"===a&&!r)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!r:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===a?r:"a"===a?r.call(t):r?r.value:e.get(t)}(this,e,"f")}constructor(t){e.set(this,void 0),function(t,e,a,r,s){if("function"==typeof e?t!==e||!s:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");e.set(t,a)}(this,e,t)}async close(){return s("plugin:resources|close",{rid:this.rid})}}async function n(t,e,a){const i={kind:"Any"};return s("plugin:event|listen",{event:t,target:i,handler:r(e)}).then((e=>async()=>async function(t,e){await s("plugin:event|unlisten",{event:t,eventId:e})}(t,e)))}async function o(t,e){return await u.load(t,e)}e=new WeakMap,function(t){t.WINDOW_RESIZED="tauri://resize",t.WINDOW_MOVED="tauri://move",t.WINDOW_CLOSE_REQUESTED="tauri://close-requested",t.WINDOW_DESTROYED="tauri://destroyed",t.WINDOW_FOCUS="tauri://focus",t.WINDOW_BLUR="tauri://blur",t.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",t.WINDOW_THEME_CHANGED="tauri://theme-changed",t.WINDOW_CREATED="tauri://window-created",t.WEBVIEW_CREATED="tauri://webview-created",t.DRAG_ENTER="tauri://drag-enter",t.DRAG_OVER="tauri://drag-over",t.DRAG_DROP="tauri://drag-drop",t.DRAG_LEAVE="tauri://drag-leave"}(a||(a={}));class u extends i{constructor(t){super(t)}static async load(t,e){const a=await s("plugin:store|load",{path:t,...e});return new u(a)}static async get(t){return await s("plugin:store|get_store",{path:t}).then((t=>t?new u(t):null))}async set(t,e){await s("plugin:store|set",{rid:this.rid,key:t,value:e})}async get(t){const[e,a]=await s("plugin:store|get",{rid:this.rid,key:t});return a?e:void 0}async has(t){return await s("plugin:store|has",{rid:this.rid,key:t})}async delete(t){return await s("plugin:store|delete",{rid:this.rid,key:t})}async clear(){await s("plugin:store|clear",{rid:this.rid})}async reset(){await s("plugin:store|reset",{rid:this.rid})}async keys(){return await s("plugin:store|keys",{rid:this.rid})}async values(){return await s("plugin:store|values",{rid:this.rid})}async entries(){return await s("plugin:store|entries",{rid:this.rid})}async length(){return await s("plugin:store|length",{rid:this.rid})}async reload(){await s("plugin:store|reload",{rid:this.rid})}async save(){await s("plugin:store|save",{rid:this.rid})}async onKeyChange(t,e){return await n("store://change",(a=>{a.payload.resourceId===this.rid&&a.payload.key===t&&e(a.payload.exists?a.payload.value:void 0)}))}async onChange(t){return await n("store://change",(e=>{e.payload.resourceId===this.rid&&t(e.payload.key,e.payload.exists?e.payload.value:void 0)}))}}return t.LazyStore=class{get store(){return this._store||(this._store=o(this.path,this.options)),this._store}constructor(t,e){this.path=t,this.options=e}async init(){await this.store}async set(t,e){return(await this.store).set(t,e)}async get(t){return(await this.store).get(t)}async has(t){return(await this.store).has(t)}async delete(t){return(await this.store).delete(t)}async clear(){await(await this.store).clear()}async reset(){await(await this.store).reset()}async keys(){return(await this.store).keys()}async values(){return(await this.store).values()}async entries(){return(await this.store).entries()}async length(){return(await this.store).length()}async reload(){await(await this.store).reload()}async save(){await(await this.store).save()}async onKeyChange(t,e){return(await this.store).onKeyChange(t,e)}async onChange(t){return(await this.store).onChange(t)}async close(){this._store&&await(await this._store).close()}},t.Store=u,t.getStore=async function(t){return await u.get(t)},t.load=o,t}({});Object.defineProperty(window.__TAURI__,"store",{value:__TAURI_PLUGIN_STORE__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_STORE__=function(t){"use strict";var e,a;function r(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}async function s(t,e={},a){return window.__TAURI_INTERNALS__.invoke(t,e,a)}"function"==typeof SuppressedError&&SuppressedError;class i{get rid(){return function(t,e,a,r){if("a"===a&&!r)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!r:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===a?r:"a"===a?r.call(t):r?r.value:e.get(t)}(this,e,"f")}constructor(t){e.set(this,void 0),function(t,e,a){if("function"==typeof e||!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");e.set(t,a)}(this,e,t)}async close(){return s("plugin:resources|close",{rid:this.rid})}}async function n(t,e,a){const i={kind:"Any"};return s("plugin:event|listen",{event:t,target:i,handler:r(e)}).then((e=>async()=>async function(t,e){await s("plugin:event|unlisten",{event:t,eventId:e})}(t,e)))}async function o(t,e){return await u.load(t,e)}e=new WeakMap,function(t){t.WINDOW_RESIZED="tauri://resize",t.WINDOW_MOVED="tauri://move",t.WINDOW_CLOSE_REQUESTED="tauri://close-requested",t.WINDOW_DESTROYED="tauri://destroyed",t.WINDOW_FOCUS="tauri://focus",t.WINDOW_BLUR="tauri://blur",t.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",t.WINDOW_THEME_CHANGED="tauri://theme-changed",t.WINDOW_CREATED="tauri://window-created",t.WEBVIEW_CREATED="tauri://webview-created",t.DRAG_ENTER="tauri://drag-enter",t.DRAG_OVER="tauri://drag-over",t.DRAG_DROP="tauri://drag-drop",t.DRAG_LEAVE="tauri://drag-leave"}(a||(a={}));class u extends i{constructor(t){super(t)}static async load(t,e){const a=await s("plugin:store|load",{path:t,...e});return new u(a)}static async get(t){return await s("plugin:store|get_store",{path:t}).then((t=>t?new u(t):null))}async set(t,e){await s("plugin:store|set",{rid:this.rid,key:t,value:e})}async get(t){const[e,a]=await s("plugin:store|get",{rid:this.rid,key:t});return a?e:void 0}async has(t){return await s("plugin:store|has",{rid:this.rid,key:t})}async delete(t){return await s("plugin:store|delete",{rid:this.rid,key:t})}async clear(){await s("plugin:store|clear",{rid:this.rid})}async reset(){await s("plugin:store|reset",{rid:this.rid})}async keys(){return await s("plugin:store|keys",{rid:this.rid})}async values(){return await s("plugin:store|values",{rid:this.rid})}async entries(){return await s("plugin:store|entries",{rid:this.rid})}async length(){return await s("plugin:store|length",{rid:this.rid})}async reload(){await s("plugin:store|reload",{rid:this.rid})}async save(){await s("plugin:store|save",{rid:this.rid})}async onKeyChange(t,e){return await n("store://change",(a=>{a.payload.resourceId===this.rid&&a.payload.key===t&&e(a.payload.exists?a.payload.value:void 0)}))}async onChange(t){return await n("store://change",(e=>{e.payload.resourceId===this.rid&&t(e.payload.key,e.payload.exists?e.payload.value:void 0)}))}}return t.LazyStore=class{get store(){return this._store||(this._store=o(this.path,this.options)),this._store}constructor(t,e){this.path=t,this.options=e}async init(){await this.store}async set(t,e){return(await this.store).set(t,e)}async get(t){return(await this.store).get(t)}async has(t){return(await this.store).has(t)}async delete(t){return(await this.store).delete(t)}async clear(){await(await this.store).clear()}async reset(){await(await this.store).reset()}async keys(){return(await this.store).keys()}async values(){return(await this.store).values()}async entries(){return(await this.store).entries()}async length(){return(await this.store).length()}async reload(){await(await this.store).reload()}async save(){await(await this.store).save()}async onKeyChange(t,e){return(await this.store).onKeyChange(t,e)}async onChange(t){return(await this.store).onChange(t)}async close(){this._store&&await(await this._store).close()}},t.Store=u,t.getStore=async function(t){return await u.get(t)},t.load=o,t}({});Object.defineProperty(window.__TAURI__,"store",{value:__TAURI_PLUGIN_STORE__})}
@@ -8,7 +8,7 @@
"tauri": "tauri"
},
"devDependencies": {
"@tauri-apps/cli": "2.1.0",
"@tauri-apps/cli": "2.2.7",
"vite": "^6.0.0",
"typescript": "^5.4.7"
}
+12
View File
@@ -1,5 +1,17 @@
# Changelog
## \[2.4.0]
- [`0afc9b6b`](https://github.com/tauri-apps/plugins-workspace/commit/0afc9b6be07bee1077f05a86285d977e57810ed9) ([#2325](https://github.com/tauri-apps/plugins-workspace/pull/2325) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) The `Update` struct/object will now contain a `raw_json`/`rawJson` property to be able to read parts of server's json response that are not handled by the plugin.
## \[2.3.1]
- [`57efb47c`](https://github.com/tauri-apps/plugins-workspace/commit/57efb47c116f880477f72f02a8e4239e88007d44) ([#2235](https://github.com/tauri-apps/plugins-workspace/pull/2235) by [@amrbashir](https://github.com/tauri-apps/plugins-workspace/../../amrbashir)) Add `Builder::header` and `Builder::headers` method to configure default headers for updater.
## \[2.3.0]
- [`829b6326`](https://github.com/tauri-apps/plugins-workspace/commit/829b63265030bc9c61d1738c4eaca0ffb3178677) ([#1919](https://github.com/tauri-apps/plugins-workspace/pull/1919) by [@n1ght-hunter](https://github.com/tauri-apps/plugins-workspace/../../n1ght-hunter)) Add `tauri_plugin_updater::Builder::default_version_comparator` method to set the default version comparator for the updater.
## \[2.2.0]
- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-updater"
version = "2.2.0"
version = "2.4.0"
description = "In-app updates for Tauri applications."
edition = { workspace = true }
authors = { workspace = true }
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_UPDATER__=function(e){"use strict";function t(e,t,s,n){if("a"===s&&!n)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!n:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===s?n:"a"===s?n.call(e):n?n.value:t.get(e)}function s(e,t,s,n,i){if("function"==typeof t?e!==t||!i:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(e,s),s}var n,i,r,a;"function"==typeof SuppressedError&&SuppressedError;const o="__TAURI_TO_IPC_KEY__";class d{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,n.set(this,(()=>{})),i.set(this,0),r.set(this,{}),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((({message:e,id:a})=>{if(a===t(this,i,"f")){s(this,i,a+1),t(this,n,"f").call(this,e);const o=Object.keys(t(this,r,"f"));if(o.length>0){let e=a+1;for(const s of o.sort()){if(parseInt(s)!==e)break;{const i=t(this,r,"f")[s];delete t(this,r,"f")[s],t(this,n,"f").call(this,i),e+=1}}s(this,i,e)}}else t(this,r,"f")[a.toString()]=e}))}set onmessage(e){s(this,n,e)}get onmessage(){return t(this,n,"f")}[(n=new WeakMap,i=new WeakMap,r=new WeakMap,o)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[o]()}}async function l(e,t={},s){return window.__TAURI_INTERNALS__.invoke(e,t,s)}class c{get rid(){return t(this,a,"f")}constructor(e){a.set(this,void 0),s(this,a,e)}async close(){return l("plugin:resources|close",{rid:this.rid})}}a=new WeakMap;class h extends c{constructor(e){super(e.rid),this.available=e.available,this.currentVersion=e.currentVersion,this.version=e.version,this.date=e.date,this.body=e.body}async download(e,t){const s=new d;e&&(s.onmessage=e);const n=await l("plugin:updater|download",{onEvent:s,rid:this.rid,...t});this.downloadedBytes=new c(n)}async install(){if(!this.downloadedBytes)throw new Error("Update.install called before Update.download");await l("plugin:updater|install",{updateRid:this.rid,bytesRid:this.downloadedBytes.rid}),this.downloadedBytes=void 0}async downloadAndInstall(e,t){const s=new d;e&&(s.onmessage=e),await l("plugin:updater|download_and_install",{onEvent:s,rid:this.rid,...t})}async close(){await(this.downloadedBytes?.close()),await super.close()}}return e.Update=h,e.check=async function(e){return e?.headers&&(e.headers=Array.from(new Headers(e.headers).entries())),await l("plugin:updater|check",{...e}).then((e=>e.available?new h(e):null))},e}({});Object.defineProperty(window.__TAURI__,"updater",{value:__TAURI_PLUGIN_UPDATER__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_UPDATER__=function(e){"use strict";function t(e,t,s,i){if("a"===s&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!i:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===s?i:"a"===s?i.call(e):i?i.value:t.get(e)}function s(e,t,s,i,n){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(e,s),s}var i,n,r,a;"function"==typeof SuppressedError&&SuppressedError;const o="__TAURI_TO_IPC_KEY__";class d{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),n.set(this,0),r.set(this,[]),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((({message:e,id:a})=>{if(a==t(this,n,"f"))for(t(this,i,"f").call(this,e),s(this,n,t(this,n,"f")+1);t(this,n,"f")in t(this,r,"f");){const e=t(this,r,"f")[t(this,n,"f")];t(this,i,"f").call(this,e),delete t(this,r,"f")[t(this,n,"f")],s(this,n,t(this,n,"f")+1)}else t(this,r,"f")[a]=e}))}set onmessage(e){s(this,i,e)}get onmessage(){return t(this,i,"f")}[(i=new WeakMap,n=new WeakMap,r=new WeakMap,o)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[o]()}}async function l(e,t={},s){return window.__TAURI_INTERNALS__.invoke(e,t,s)}class h{get rid(){return t(this,a,"f")}constructor(e){a.set(this,void 0),s(this,a,e)}async close(){return l("plugin:resources|close",{rid:this.rid})}}a=new WeakMap;class c extends h{constructor(e){super(e.rid),this.available=e.available,this.currentVersion=e.currentVersion,this.version=e.version,this.date=e.date,this.body=e.body,this.rawJson=e.rawJson}async download(e,t){const s=new d;e&&(s.onmessage=e);const i=await l("plugin:updater|download",{onEvent:s,rid:this.rid,...t});this.downloadedBytes=new h(i)}async install(){if(!this.downloadedBytes)throw new Error("Update.install called before Update.download");await l("plugin:updater|install",{updateRid:this.rid,bytesRid:this.downloadedBytes.rid}),this.downloadedBytes=void 0}async downloadAndInstall(e,t){const s=new d;e&&(s.onmessage=e),await l("plugin:updater|download_and_install",{onEvent:s,rid:this.rid,...t})}async close(){await(this.downloadedBytes?.close()),await super.close()}}return e.Update=c,e.check=async function(e){return e?.headers&&(e.headers=Array.from(new Headers(e.headers).entries())),await l("plugin:updater|check",{...e}).then((e=>e.available?new c(e):null))},e}({});Object.defineProperty(window.__TAURI__,"updater",{value:__TAURI_PLUGIN_UPDATER__})}
+3
View File
@@ -43,6 +43,7 @@ interface UpdateMetadata {
version: string
date?: string
body?: string
rawJson: Record<string, unknown>
}
/** Updater download event */
@@ -57,6 +58,7 @@ class Update extends Resource {
version: string
date?: string
body?: string
rawJson: Record<string, unknown>
private downloadedBytes?: Resource
constructor(metadata: UpdateMetadata) {
@@ -66,6 +68,7 @@ class Update extends Resource {
this.version = metadata.version
this.date = metadata.date
this.body = metadata.body
this.rawJson = metadata.rawJson
}
/** Download the updater package */
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-updater",
"version": "2.2.0",
"version": "2.4.0",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
+2
View File
@@ -34,6 +34,7 @@ pub(crate) struct Metadata {
version: String,
date: Option<String>,
body: Option<String>,
raw_json: serde_json::Value,
}
struct DownloadedBytes(pub Vec<u8>);
@@ -73,6 +74,7 @@ pub(crate) async fn check<R: Runtime>(
metadata.version.clone_from(&update.version);
metadata.date = update.date.map(|d| d.to_string());
metadata.body.clone_from(&update.body);
metadata.raw_json.clone_from(&update.raw_json);
metadata.rid = Some(webview.resources_table().add(update));
}
+55 -4
View File
@@ -11,8 +11,10 @@
html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png"
)]
use std::ffi::OsString;
use std::{ffi::OsString, sync::Arc};
use http::{HeaderMap, HeaderName, HeaderValue};
use semver::Version;
use tauri::{
plugin::{Builder as PluginBuilder, TauriPlugin},
Manager, Runtime,
@@ -69,13 +71,19 @@ impl<R: Runtime, T: Manager<R>> UpdaterExt<R> for T {
fn updater_builder(&self) -> UpdaterBuilder {
let app = self.app_handle();
let package_info = app.package_info();
let UpdaterState { config, target } = self.state::<UpdaterState>().inner();
let UpdaterState {
config,
target,
version_comparator,
headers,
} = self.state::<UpdaterState>().inner();
let mut builder = UpdaterBuilder::new(
package_info.name.clone(),
package_info.version.clone(),
config.clone(),
);
)
.headers(headers.clone());
if let Some(target) = target {
builder = builder.target(target);
@@ -86,6 +94,8 @@ impl<R: Runtime, T: Manager<R>> UpdaterExt<R> for T {
builder = builder.current_exe_args(args);
}
builder.version_comparator = version_comparator.clone();
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
@@ -116,6 +126,8 @@ impl<R: Runtime, T: Manager<R>> UpdaterExt<R> for T {
struct UpdaterState {
target: Option<String>,
config: Config,
version_comparator: Option<VersionComparator>,
headers: HeaderMap,
}
#[derive(Default)]
@@ -123,6 +135,8 @@ pub struct Builder {
target: Option<String>,
pubkey: Option<String>,
installer_args: Vec<OsString>,
headers: HeaderMap,
default_version_comparator: Option<VersionComparator>,
}
impl Builder {
@@ -163,10 +177,42 @@ impl Builder {
self
}
pub fn header<K, V>(mut self, key: K, value: V) -> Result<Self>
where
HeaderName: TryFrom<K>,
<HeaderName as TryFrom<K>>::Error: Into<http::Error>,
HeaderValue: TryFrom<V>,
<HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
{
let key: std::result::Result<HeaderName, http::Error> = key.try_into().map_err(Into::into);
let value: std::result::Result<HeaderValue, http::Error> =
value.try_into().map_err(Into::into);
self.headers.insert(key?, value?);
Ok(self)
}
pub fn headers(mut self, headers: HeaderMap) -> Self {
self.headers = headers;
self
}
pub fn default_version_comparator<
F: Fn(Version, RemoteRelease) -> bool + Send + Sync + 'static,
>(
mut self,
f: F,
) -> Self {
self.default_version_comparator.replace(Arc::new(f));
self
}
pub fn build<R: Runtime>(self) -> TauriPlugin<R, Config> {
let pubkey = self.pubkey;
let target = self.target;
let version_comparator = self.default_version_comparator;
let installer_args = self.installer_args;
let headers = self.headers;
PluginBuilder::<R, Config>::new("updater")
.setup(move |app, api| {
let mut config = api.config().clone();
@@ -176,7 +222,12 @@ impl Builder {
if let Some(windows) = &mut config.windows {
windows.installer_args.extend_from_slice(&installer_args);
}
app.manage(UpdaterState { target, config });
app.manage(UpdaterState {
target,
config,
version_comparator,
headers,
});
Ok(())
})
.invoke_handler(tauri::generate_handler![
+20 -4
View File
@@ -93,12 +93,13 @@ impl RemoteRelease {
}
pub type OnBeforeExit = Arc<dyn Fn() + Send + Sync + 'static>;
pub type VersionComparator = Arc<dyn Fn(Version, RemoteRelease) -> bool + Send + Sync>;
pub struct UpdaterBuilder {
app_name: String,
current_version: Version,
config: Config,
version_comparator: Option<Box<dyn Fn(Version, RemoteRelease) -> bool + Send + Sync>>,
pub(crate) version_comparator: Option<VersionComparator>,
executable_path: Option<PathBuf>,
target: Option<String>,
endpoints: Option<Vec<Url>>,
@@ -139,7 +140,7 @@ impl UpdaterBuilder {
mut self,
f: F,
) -> Self {
self.version_comparator = Some(Box::new(f));
self.version_comparator = Some(Arc::new(f));
self
}
@@ -178,6 +179,16 @@ impl UpdaterBuilder {
Ok(self)
}
pub fn headers(mut self, headers: HeaderMap) -> Self {
self.headers = headers;
self
}
pub fn clear_headers(mut self) -> Self {
self.headers.clear();
self
}
pub fn timeout(mut self, timeout: Duration) -> Self {
self.timeout = Some(timeout);
self
@@ -283,7 +294,7 @@ pub struct Updater {
config: Config,
app_name: String,
current_version: Version,
version_comparator: Option<Box<dyn Fn(Version, RemoteRelease) -> bool + Send + Sync>>,
version_comparator: Option<VersionComparator>,
timeout: Option<Duration>,
proxy: Option<Url>,
endpoints: Vec<Url>,
@@ -319,6 +330,7 @@ impl Updater {
}
let mut remote_release: Option<RemoteRelease> = None;
let mut raw_json: Option<serde_json::Value> = None;
let mut last_error: Option<Error> = None;
for url in &self.endpoints {
// replace {{current_version}}, {{target}} and {{arch}} in the provided URL
@@ -368,7 +380,8 @@ impl Updater {
return Ok(None);
};
match serde_json::from_value::<RemoteRelease>(res.json().await?)
raw_json = Some(res.json().await?);
match serde_json::from_value::<RemoteRelease>(raw_json.clone().unwrap())
.map_err(Into::into)
{
Ok(release) => {
@@ -410,6 +423,7 @@ impl Updater {
download_url: release.download_url(&self.json_target)?.to_owned(),
body: release.notes.clone(),
signature: release.signature(&self.json_target)?.to_owned(),
raw_json: raw_json.unwrap(),
timeout: self.timeout,
proxy: self.proxy.clone(),
headers: self.headers.clone(),
@@ -443,6 +457,8 @@ pub struct Update {
pub download_url: Url,
/// Signature announced
pub signature: String,
/// The raw version of server's JSON response. Useful if the response contains additional fields that the updater doesn't handle.
pub raw_json: serde_json::Value,
/// Request timeout
pub timeout: Option<Duration>,
/// Request proxy
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_UPLOAD__=function(t){"use strict";function e(t,e,n,o){if("a"===n&&!o)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!o:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?o:"a"===n?o.call(t):o?o.value:e.get(t)}function n(t,e,n,o,s){if("function"==typeof e?t!==e||!s:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,n),n}var o,s,r;"function"==typeof SuppressedError&&SuppressedError;const i="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,o.set(this,(()=>{})),s.set(this,0),r.set(this,{}),this.id=function(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}((({message:t,id:i})=>{if(i===e(this,s,"f")){n(this,s,i+1),e(this,o,"f").call(this,t);const a=Object.keys(e(this,r,"f"));if(a.length>0){let t=i+1;for(const n of a.sort()){if(parseInt(n)!==t)break;{const s=e(this,r,"f")[n];delete e(this,r,"f")[n],e(this,o,"f").call(this,s),t+=1}}n(this,s,t)}}else e(this,r,"f")[i.toString()]=t}))}set onmessage(t){n(this,o,t)}get onmessage(){return e(this,o,"f")}[(o=new WeakMap,s=new WeakMap,r=new WeakMap,i)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[i]()}}async function _(t,e={},n){return window.__TAURI_INTERNALS__.invoke(t,e,n)}return t.download=async function(t,e,n,o,s){const r=new Uint32Array(1);window.crypto.getRandomValues(r);const i=r[0],c=new a;n&&(c.onmessage=n),await _("plugin:upload|download",{id:i,url:t,filePath:e,headers:o??{},onProgress:c,body:s})},t.upload=async function(t,e,n,o){const s=new Uint32Array(1);window.crypto.getRandomValues(s);const r=s[0],i=new a;return n&&(i.onmessage=n),await _("plugin:upload|upload",{id:r,url:t,filePath:e,headers:o??{},onProgress:i})},t}({});Object.defineProperty(window.__TAURI__,"upload",{value:__TAURI_PLUGIN_UPLOAD__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_UPLOAD__=function(t){"use strict";function e(t,e,n,s){if("a"===n&&!s)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!s:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?s:"a"===n?s.call(t):s?s.value:e.get(t)}function n(t,e,n,s,i){if("function"==typeof e||!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,n),n}var s,i,o;"function"==typeof SuppressedError&&SuppressedError;const r="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,s.set(this,(()=>{})),i.set(this,0),o.set(this,[]),this.id=function(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}((({message:t,id:r})=>{if(r==e(this,i,"f"))for(e(this,s,"f").call(this,t),n(this,i,e(this,i,"f")+1);e(this,i,"f")in e(this,o,"f");){const t=e(this,o,"f")[e(this,i,"f")];e(this,s,"f").call(this,t),delete e(this,o,"f")[e(this,i,"f")],n(this,i,e(this,i,"f")+1)}else e(this,o,"f")[r]=t}))}set onmessage(t){n(this,s,t)}get onmessage(){return e(this,s,"f")}[(s=new WeakMap,i=new WeakMap,o=new WeakMap,r)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[r]()}}async function _(t,e={},n){return window.__TAURI_INTERNALS__.invoke(t,e,n)}return t.download=async function(t,e,n,s,i){const o=new Uint32Array(1);window.crypto.getRandomValues(o);const r=o[0],c=new a;n&&(c.onmessage=n),await _("plugin:upload|download",{id:r,url:t,filePath:e,headers:s??{},onProgress:c,body:i})},t.upload=async function(t,e,n,s){const i=new Uint32Array(1);window.crypto.getRandomValues(i);const o=i[0],r=new a;return n&&(r.onmessage=n),await _("plugin:upload|upload",{id:o,url:t,filePath:e,headers:s??{},onProgress:r})},t}({});Object.defineProperty(window.__TAURI__,"upload",{value:__TAURI_PLUGIN_UPLOAD__})}
+9
View File
@@ -1,5 +1,14 @@
# Changelog
## \[2.3.0]
- [`78acfa45`](https://github.com/tauri-apps/plugins-workspace/commit/78acfa456f343c0af5fbf35660802d14ff7a5eca) ([#2027](https://github.com/tauri-apps/plugins-workspace/pull/2027) by [@twlite](https://github.com/tauri-apps/plugins-workspace/../../twlite)) `addListener` now returns a cleanup function instead of `void` to remove the listener.
## \[2.2.1]
- [`05cca602`](https://github.com/tauri-apps/plugins-workspace/commit/05cca602d927c30014d3892438ca28d99bc4e1d3) ([#2210](https://github.com/tauri-apps/plugins-workspace/pull/2210) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) **Breaking change:** Updated tokio_tungstenite to `0.26`. This may be a breaking change if you use the `tls_connector` Builder method in Rust.
**Breaking change:** Removed the accidental `ConnectionConfig` struct re-export (in rust). This should not affect anyone since the Config was not used in any public API.
## \[2.2.0]
- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-websocket"
version = "2.2.0"
version = "2.3.0"
description = "Expose a WebSocket server to your Tauri frontend."
authors = { workspace = true }
license = { workspace = true }
@@ -34,7 +34,7 @@ http = "1"
rand = "0.8"
futures-util = "0.3"
tokio = { version = "1", features = ["net", "sync"] }
tokio-tungstenite = { version = "0.24" }
tokio-tungstenite = { version = "0.26" }
[features]
default = ["rustls-tls"]
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_WEBSOCKET__=function(){"use strict";function e(e,t,s,n){if("a"===s&&!n)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!n:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===s?n:"a"===s?n.call(e):n?n.value:t.get(e)}function t(e,t,s,n,r){if("function"==typeof t?e!==t||!r:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(e,s),s}var s,n,r;"function"==typeof SuppressedError&&SuppressedError;const i="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,s.set(this,(()=>{})),n.set(this,0),r.set(this,{}),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((({message:i,id:a})=>{if(a===e(this,n,"f")){t(this,n,a+1),e(this,s,"f").call(this,i);const o=Object.keys(e(this,r,"f"));if(o.length>0){let i=a+1;for(const t of o.sort()){if(parseInt(t)!==i)break;{const n=e(this,r,"f")[t];delete e(this,r,"f")[t],e(this,s,"f").call(this,n),i+=1}}t(this,n,i)}}else e(this,r,"f")[a.toString()]=i}))}set onmessage(e){t(this,s,e)}get onmessage(){return e(this,s,"f")}[(s=new WeakMap,n=new WeakMap,r=new WeakMap,i)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[i]()}}async function o(e,t={},s){return window.__TAURI_INTERNALS__.invoke(e,t,s)}class c{constructor(e,t){this.id=e,this.listeners=t}static async connect(e,t){const s=[],n=new a;return n.onmessage=e=>{s.forEach((t=>{t(e)}))},t?.headers&&(t.headers=Array.from(new Headers(t.headers).entries())),await o("plugin:websocket|connect",{url:e,onMessage:n,config:t}).then((e=>new c(e,s)))}addListener(e){this.listeners.push(e)}async send(e){let t;if("string"==typeof e)t={type:"Text",data:e};else if("object"==typeof e&&"type"in e)t=e;else{if(!Array.isArray(e))throw new Error("invalid `message` type, expected a `{ type: string, data: any }` object, a string or a numeric array");t={type:"Binary",data:e}}await o("plugin:websocket|send",{id:this.id,message:t})}async disconnect(){await this.send({type:"Close",data:{code:1e3,reason:"Disconnected by client"}})}}return c}();Object.defineProperty(window.__TAURI__,"websocket",{value:__TAURI_PLUGIN_WEBSOCKET__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_WEBSOCKET__=function(){"use strict";function e(e,t,s,n){if("a"===s&&!n)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!n:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===s?n:"a"===s?n.call(e):n?n.value:t.get(e)}function t(e,t,s,n,i){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(e,s),s}var s,n,i;"function"==typeof SuppressedError&&SuppressedError;const r="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,s.set(this,(()=>{})),n.set(this,0),i.set(this,[]),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((({message:r,id:a})=>{if(a==e(this,n,"f"))for(e(this,s,"f").call(this,r),t(this,n,e(this,n,"f")+1);e(this,n,"f")in e(this,i,"f");){const r=e(this,i,"f")[e(this,n,"f")];e(this,s,"f").call(this,r),delete e(this,i,"f")[e(this,n,"f")],t(this,n,e(this,n,"f")+1)}else e(this,i,"f")[a]=r}))}set onmessage(e){t(this,s,e)}get onmessage(){return e(this,s,"f")}[(s=new WeakMap,n=new WeakMap,i=new WeakMap,r)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[r]()}}async function o(e,t={},s){return window.__TAURI_INTERNALS__.invoke(e,t,s)}class c{constructor(e,t){this.id=e,this.listeners=t}static async connect(e,t){const s=new Set,n=new a;return n.onmessage=e=>{s.forEach((t=>{t(e)}))},t?.headers&&(t.headers=Array.from(new Headers(t.headers).entries())),await o("plugin:websocket|connect",{url:e,onMessage:n,config:t}).then((e=>new c(e,s)))}addListener(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}async send(e){let t;if("string"==typeof e)t={type:"Text",data:e};else if("object"==typeof e&&"type"in e)t=e;else{if(!Array.isArray(e))throw new Error("invalid `message` type, expected a `{ type: string, data: any }` object, a string or a numeric array");t={type:"Binary",data:e}}await o("plugin:websocket|send",{id:this.id,message:t})}async disconnect(){await this.send({type:"Close",data:{code:1e3,reason:"Disconnected by client"}})}}return c}();Object.defineProperty(window.__TAURI__,"websocket",{value:__TAURI_PLUGIN_WEBSOCKET__})}
@@ -9,7 +9,7 @@
"preview": "vite preview"
},
"devDependencies": {
"@tauri-apps/cli": "2.1.0",
"@tauri-apps/cli": "2.2.7",
"typescript": "^5.3.3",
"vite": "^6.0.0"
},
@@ -11,7 +11,7 @@ tauri = { workspace = true, features = ["wry", "compression"] }
tokio = { version = "1", features = ["net"] }
futures-util = "0.3"
tauri-plugin-websocket = { path = "../../../" }
tokio-tungstenite = "0.24"
tokio-tungstenite = "0.26"
[build-dependencies]
tauri-build = { workspace = true }
+37 -7
View File
@@ -5,11 +5,37 @@
import { invoke, Channel } from '@tauri-apps/api/core'
export interface ConnectionConfig {
/**
* Read buffer capacity. The default value is 128 KiB.
*/
readBufferSize?: number
/** The target minimum size of the write buffer to reach before writing the data to the underlying stream. The default value is 128 KiB.
*
* If set to 0 each message will be eagerly written to the underlying stream. It is often more optimal to allow them to buffer a little, hence the default value.
*/
writeBufferSize?: number
/** The max size of the write buffer in bytes. Setting this can provide backpressure in the case the write buffer is filling up due to write errors. The default value is unlimited.
*
* Note: The write buffer only builds up past write_buffer_size when writes to the underlying stream are failing. So the write buffer can not fill up if you are not observing write errors.
*
* Note: Should always be at least write_buffer_size + 1 message and probably a little more depending on error handling strategy.
*/
maxWriteBufferSize?: number
maxMessageSize?: number
maxFrameSize?: number
/**
* The maximum size of an incoming message. The string "none" means no size limit. The default value is 64 MiB which should be reasonably big for all normal use-cases but small enough to prevent memory eating by a malicious user.
*/
maxMessageSize?: number | 'none'
/**
* The maximum size of a single incoming message frame. The string "none" means no size limit. The limit is for frame payload NOT including the frame header. The default value is 16 MiB which should be reasonably big for all normal use-cases but small enough to prevent memory eating by a malicious user.
*/
maxFrameSize?: number | 'none'
/**
* When set to true, the server will accept and handle unmasked frames from the client. According to the RFC 6455, the server must close the connection to the client in such cases, however it seems like there are some popular libraries that are sending unmasked frames, ignoring the RFC. By default this option is set to false, i.e. according to RFC 6455.
*/
acceptUnmaskedFrames?: boolean
/**
* Additional connect request headers.
*/
headers?: HeadersInit
}
@@ -32,9 +58,9 @@ export type Message =
export default class WebSocket {
id: number
private readonly listeners: Array<(arg: Message) => void>
private readonly listeners: Set<(arg: Message) => void>
constructor(id: number, listeners: Array<(arg: Message) => void>) {
constructor(id: number, listeners: Set<(arg: Message) => void>) {
this.id = id
this.listeners = listeners
}
@@ -43,7 +69,7 @@ export default class WebSocket {
url: string,
config?: ConnectionConfig
): Promise<WebSocket> {
const listeners: Array<(arg: Message) => void> = []
const listeners: Set<(arg: Message) => void> = new Set()
const onMessage = new Channel<Message>()
onMessage.onmessage = (message: Message): void => {
@@ -63,8 +89,12 @@ export default class WebSocket {
}).then((id) => new WebSocket(id, listeners))
}
addListener(cb: (arg: Message) => void): void {
this.listeners.push(cb)
addListener(cb: (arg: Message) => void): () => void {
this.listeners.add(cb)
return () => {
this.listeners.delete(cb)
}
}
async send(message: Message | string | number[]): Promise<void> {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-websocket",
"version": "2.2.0",
"version": "2.3.0",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
+52 -24
View File
@@ -66,13 +66,21 @@ struct ConnectionManager(Mutex<HashMap<Id, WebSocketWriter>>);
#[cfg(any(feature = "rustls-tls", feature = "native-tls"))]
struct TlsConnector(Mutex<Option<Connector>>);
#[derive(Deserialize)]
#[serde(untagged, rename_all = "camelCase")]
enum Max {
None,
Number(usize),
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ConnectionConfig {
pub(crate) struct ConnectionConfig {
pub read_buffer_size: Option<usize>,
pub write_buffer_size: Option<usize>,
pub max_write_buffer_size: Option<usize>,
pub max_message_size: Option<usize>,
pub max_frame_size: Option<usize>,
pub max_message_size: Option<Max>,
pub max_frame_size: Option<Max>,
#[serde(default)]
pub accept_unmasked_frames: bool,
pub headers: Option<Vec<(String, String)>>,
@@ -80,18 +88,38 @@ pub struct ConnectionConfig {
impl From<ConnectionConfig> for WebSocketConfig {
fn from(config: ConnectionConfig) -> Self {
// Disabling the warning on max_send_queue which we don't use anymore since it was deprecated.
#[allow(deprecated)]
Self {
max_send_queue: None,
write_buffer_size: config.write_buffer_size.unwrap_or(128 * 1024),
max_write_buffer_size: config.max_write_buffer_size.unwrap_or(usize::MAX),
// This may be harmful since if it's not provided from js we're overwriting the default value with None, meaning no size limit.
max_message_size: config.max_message_size,
// This may be harmful since if it's not provided from js we're overwriting the default value with None, meaning no size limit.
max_frame_size: config.max_frame_size,
accept_unmasked_frames: config.accept_unmasked_frames,
let mut builder =
WebSocketConfig::default().accept_unmasked_frames(config.accept_unmasked_frames);
if let Some(read_buffer_size) = config.read_buffer_size {
builder = builder.read_buffer_size(read_buffer_size)
}
if let Some(write_buffer_size) = config.write_buffer_size {
builder = builder.write_buffer_size(write_buffer_size)
}
if let Some(max_write_buffer_size) = config.max_write_buffer_size {
builder = builder.max_write_buffer_size(max_write_buffer_size)
}
if let Some(max_message_size) = config.max_message_size {
let max_size = match max_message_size {
Max::None => Option::None,
Max::Number(n) => Some(n),
};
builder = builder.max_message_size(max_size);
}
if let Some(max_frame_size) = config.max_frame_size {
let max_size = match max_frame_size {
Max::None => Option::None,
Max::Number(n) => Some(n),
};
builder = builder.max_frame_size(max_size);
}
builder
}
}
@@ -157,21 +185,21 @@ async fn connect<R: Runtime>(
let response = match message {
Ok(Message::Text(t)) => {
serde_json::to_value(WebSocketMessage::Text(t)).unwrap()
serde_json::to_value(WebSocketMessage::Text(t.to_string())).unwrap()
}
Ok(Message::Binary(t)) => {
serde_json::to_value(WebSocketMessage::Binary(t)).unwrap()
serde_json::to_value(WebSocketMessage::Binary(t.to_vec())).unwrap()
}
Ok(Message::Ping(t)) => {
serde_json::to_value(WebSocketMessage::Ping(t)).unwrap()
serde_json::to_value(WebSocketMessage::Ping(t.to_vec())).unwrap()
}
Ok(Message::Pong(t)) => {
serde_json::to_value(WebSocketMessage::Pong(t)).unwrap()
serde_json::to_value(WebSocketMessage::Pong(t.to_vec())).unwrap()
}
Ok(Message::Close(t)) => {
serde_json::to_value(WebSocketMessage::Close(t.map(|v| CloseFrame {
code: v.code.into(),
reason: v.reason.into_owned(),
reason: v.reason.to_string(),
})))
.unwrap()
}
@@ -197,13 +225,13 @@ async fn send(
if let Some(write) = manager.0.lock().await.get_mut(&id) {
write
.send(match message {
WebSocketMessage::Text(t) => Message::Text(t),
WebSocketMessage::Binary(t) => Message::Binary(t),
WebSocketMessage::Ping(t) => Message::Ping(t),
WebSocketMessage::Pong(t) => Message::Pong(t),
WebSocketMessage::Text(t) => Message::Text(t.into()),
WebSocketMessage::Binary(t) => Message::Binary(t.into()),
WebSocketMessage::Ping(t) => Message::Ping(t.into()),
WebSocketMessage::Pong(t) => Message::Pong(t.into()),
WebSocketMessage::Close(t) => Message::Close(t.map(|v| ProtocolCloseFrame {
code: v.code.into(),
reason: std::borrow::Cow::Owned(v.reason),
reason: v.reason.into(),
})),
})
.await?;
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.2.1]
- [`0ec895c3`](https://github.com/tauri-apps/plugins-workspace/commit/0ec895c378d4700cf8d7a002c6d9829f3c015b9f) ([#2330](https://github.com/tauri-apps/plugins-workspace/pull/2330) by [@thewh1teagle](https://github.com/tauri-apps/plugins-workspace/../../thewh1teagle)) Add `Builder::with_filter` callback to exclude specific windows from saving their state. This allows for more flexibility by enabling dynamic exclusion of windows based on custom logic.
## \[2.2.0]
- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-window-state"
version = "2.2.0"
version = "2.2.1"
description = "Save window positions and sizes and restore them when the app is reopened."
authors = { workspace = true }
license = { workspace = true }
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-window-state",
"version": "2.2.0",
"version": "2.2.1",
"description": "Save window positions and sizes and restore them when the app is reopened.",
"license": "MIT OR Apache-2.0",
"authors": [
+22 -1
View File
@@ -27,6 +27,7 @@ use std::{
mod cmd;
type LabelMapperFn = dyn Fn(&str) -> &str + Send + Sync;
type FilterCallbackFn = dyn Fn(&str) -> bool + Send + Sync;
/// Default filename used to store window state.
///
@@ -320,6 +321,7 @@ impl<R: Runtime> WindowExtInternal for Window<R> {
#[derive(Default)]
pub struct Builder {
denylist: HashSet<String>,
filter_callback: Option<Box<FilterCallbackFn>>,
skip_initial_state: HashSet<String>,
state_flags: StateFlags,
map_label: Option<Box<LabelMapperFn>>,
@@ -344,12 +346,22 @@ impl Builder {
}
/// Sets a list of windows that shouldn't be tracked and managed by this plugin
/// for example splash screen windows.
/// For example, splash screen windows.
pub fn with_denylist(mut self, denylist: &[&str]) -> Self {
self.denylist = denylist.iter().map(|l| l.to_string()).collect();
self
}
/// Sets a filter callback to exclude specific windows from being tracked.
/// Return `true` to save the state, or `false` to skip and not save it.
pub fn with_filter<F>(mut self, filter_callback: F) -> Self
where
F: Fn(&str) -> bool + Send + Sync + 'static,
{
self.filter_callback = Some(Box::new(filter_callback));
self
}
/// Adds the given window label to a list of windows to skip initial state restore.
pub fn skip_initial_state(mut self, label: &str) -> Self {
self.skip_initial_state.insert(label.into());
@@ -413,10 +425,19 @@ impl Builder {
.map(|map| map(window.label()))
.unwrap_or_else(|| window.label());
// Check deny list names
if self.denylist.contains(label) {
return;
}
// Check deny list callback
if let Some(filter_callback) = &self.filter_callback {
// Don't save the state if the callback returns false
if !filter_callback(label) {
return;
}
}
if !self.skip_initial_state.contains(label) {
let _ = window.restore_state(self.state_flags);
}
+714 -740
View File
File diff suppressed because it is too large Load Diff
+5 -2
View File
@@ -1,8 +1,7 @@
{
"extends": ["config:base"],
"extends": ["config:recommended"],
"baseBranches": ["v2", "v1"],
"enabledManagers": ["cargo", "npm"],
"semanticCommitType": "chore",
"labels": ["dependencies"],
"ignorePaths": [
"**/node_modules/**",
@@ -16,6 +15,10 @@
],
"rangeStrategy": "replace",
"packageRules": [
{
"semanticCommitType": "chore",
"matchPackageNames": ["*"]
},
{
"description": "Disable node/pnpm version updates",
"matchPackageNames": ["node", "pnpm"],