Compare commits

..

59 Commits

Author SHA1 Message Date
github-actions[bot] 50b159f668 Publish New Versions (v2) (#3211)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-03 12:18:37 +01:00
Fabian-Lars 305c4f6b4e ci: add workflow_dipatch trigger to integration tests 2026-02-03 10:55:10 +01:00
Lucas Fernandes Nogueira 89f3e17952 chore: bump tauri to 2.10 (#3246)
* chore: bump tauri to 2.10

* pnpm i

* audit fix
2026-02-02 21:48:08 -03:00
Ale Sanchez d4613ff002 fix(shell): Make sidecars work in tests (fix #13767) (#3234) 2026-01-26 17:12:42 +01:00
Tony 69a9d5771c chore(updater): use keep from tempfile 3.20 (#3229) 2026-01-22 11:40:43 +08:00
Del 61e9b0ab64 fix(http): ensure body resources are released on stream cancellation (#3228)
Co-authored-by: Amr Bashir <github@amrbashir.me>
2026-01-22 05:20:29 +02:00
dependabot[bot] 25ad21beff chore(deps): bump diff from 5.2.0 to 5.2.2 (#3226)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <github@fabianlars.de>
2026-01-20 20:30:35 +01:00
Madhusudhan 2dc3f3f039 fix(sql): uuid columns returning null in postgres query results (#2039) (#3144)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2026-01-19 17:30:28 +01:00
Lucas Fernandes Nogueira c27af9128d fix(barcode-scanner): check if iOS platform supports scanning (#3222) 2026-01-19 13:16:31 -03:00
Lucas Fernandes Nogueira b60dd88702 fix(barcode-scanner): start capture session on a separate thread (#3223)
fixes the given warning:

Thread Performance Checker: -[AVCaptureSession startRunning] should be called from background thread. Calling it on the main thread can lead to UI unresponsiveness

which might cause a UI freeze
2026-01-19 13:16:16 -03:00
renovate[bot] a97033bcd9 chore(deps): update dependency rollup to v4.55.1 (#3201)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-19 16:44:07 +01:00
miaoshengkun 4375c98bed feat(updater): add no_proxy config to disable system proxy (#3073)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2026-01-19 16:17:37 +01:00
Fabian-Lars 82fbb0c790 fix(barcode-scanner): early return scanner if missing permissions (#3221) 2026-01-19 10:21:33 -03:00
Tony de6bf68585 docs(store): fix outdated fn link (#3220) 2026-01-19 12:21:55 +01:00
renovate[bot] 734c627084 chore(deps): update dependency prettier to v3.8.0 (#3217) 2026-01-18 10:54:16 +08:00
Tony 05c5da072b chore(deps): update reqwest to 0.13 for updater (#3213) 2026-01-16 18:37:20 +08:00
renovate[bot] 0d126ff0ad chore(deps): update dependency typescript-eslint to v8.53.0 (v2) (#3189)
* chore(deps): update dependency typescript-eslint to v8.53.0

* Update api-iife.js
2026-01-16 18:36:41 +08:00
FabianLars f122ee98c6 Revert "temp: delete updater changefiles"
This reverts commit 82c404635b.
2026-01-14 20:48:59 +01:00
github-actions[bot] 2308f2299d publish new versions (#3203)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-01-14 20:48:22 +01:00
FabianLars 82c404635b temp: delete updater changefiles 2026-01-14 20:30:54 +01:00
Fabian-Lars b1dbee2c55 fix(http): manually set origin header to tauri://localhost (#3210) 2026-01-14 20:26:17 +01:00
Andrew de Waal d7a0bb325d feat(dialog) - Support fileAccessMode for open dialog (#3030) (#3136)
* feat(dialog) - Support fileAccessMode for open dialog (#3030)

On iOS, when trying to access a file that exists outside of the app sandbox, one of 2 things need to happen to be able to perform any operations on said file:

* A copy of the file needs to be made to the internal app sandbox
* The method startAccessingSecurityScopedResource needs to be called.

Previously, a copy of the file was always being made when a file was selected through the picker dialog.

While this did ensure there were no file access exceptions when reading from the file, it does not scale well for large files.

To resolve this, we now support `fileAccessMode`, which allows a file handle to be returned without copying the file to the app sandbox.

This MR only supports this change for iOS; MacOS has a different set of needs for security scoped resources.

See discussion in #3716 for more discussion of the difference between iOS and MacOS.
See MR #3185 to see how these scoped files will be accessible using security scoping.

* fmt, clippy

* use enum

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2026-01-14 08:35:06 -03:00
FabianLars f3d75f7abb Revert "temp: remove updater changefiles"
This reverts commit 9a2c98f450.
2026-01-08 15:54:33 +01:00
github-actions[bot] 6e2e7e48c3 publish new versions (#3070)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-01-08 15:34:17 +01:00
FabianLars 9a2c98f450 temp: remove updater changefiles 2026-01-08 15:17:30 +01:00
FabianLars 4a2ecb6287 chore(deps): update rkyv, closes #3196 2026-01-06 11:05:04 +01:00
Tunglies 31415effdf docs(shell): update example to include Encoding usage in Command::spawn (#3183)
* docs(shell): update example to include Encoding usage in `Command::spawn`

* docs(shell): update patch level to minor for Encoding usage in `Command::spawn` documentation

* Update .changes/doc-to-Encoding-usage-in-shell.md

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>

* docs(shell): update examples to demonstrate manual Encoding usage in command output

* Update plugins/shell/src/process/mod.rs

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>

* docs(shell): update example to use 'windows-1252' encoding in command output

* Update plugins/shell/src/process/mod.rs

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>

* docs(shell): update example command in documentation to use 'some-program' with 'some-arg'

* Bump shell-js in change file

* Fix indent
2025-12-29 10:58:55 +08:00
renovate[bot] 04b33ea0b0 chore(deps): update dependency typescript-eslint to v8.50.1 (#3181)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-27 22:30:26 +08:00
renovate[bot] 54e21f142b chore(deps): update dependency rollup to v4.54.0 (#3179)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-23 22:50:36 +08:00
renovate[bot] d528c88b4f chore(deps): update dependency rollup to v4.53.5 (#3172)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-19 19:16:32 +08:00
renovate[bot] 69146fa852 chore(deps): update dependency rollup to v4.53.4 (#3167)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-19 11:20:50 +08:00
renovate[bot] 9f68f2d827 chore(deps): update dependency typescript-eslint to v8.50.0 (#3170)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-19 10:58:03 +08:00
Fabian-Lars 3d0d2e041b fix(opener): ignore inAppBrowser on desktop (#3163) 2025-12-16 07:07:15 -03:00
renovate[bot] 1e3d7ef16e chore(deps): update eslint monorepo to v9.39.2 (#3164)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-16 12:36:13 +08:00
renovate[bot] ce6835d50f chore(deps): update dependency @tauri-apps/cli to v2.9.6 (#3162)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-12 22:13:33 +08:00
renovate[bot] 1d9f47c882 chore(deps): update dependency typescript-eslint to v8.49.0 (#3160)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-12 10:39:11 +08:00
Fabian-Lars e221a04ef4 docs(stronghold): add scrypt opt-level recommendation, closes #2048 2025-12-09 11:50:09 +01:00
Tony eebfd2ed3e fix(store): error instead of panic on invalid rid (#3157) 2025-12-09 18:02:23 +08:00
Elias* 521cd8b372 fix(fs): off by one error in readTextFileLines (#3155)
* fix: off by one error in readTextFileLines (#3154)

Signed-off-by: EliasStar <31409841+EliasStar@users.noreply.github.com>

* Format and regenerate `api-iife.js`

---------

Signed-off-by: EliasStar <31409841+EliasStar@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
2025-12-09 11:48:18 +08:00
renovate[bot] e4a40f4423 chore(deps): update tauri monorepo (v2) (#3142)
* chore(deps): update tauri monorepo

* Build

* Bump rust tauri

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
2025-12-07 00:03:50 +08:00
renovate[bot] fa8b11f19d chore(deps): update dependency prettier to v3.7.4 (#3150)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-06 13:10:40 +08:00
renovate[bot] baefd761e0 chore(deps): update dependency typescript-eslint to v8.48.1 (#3146)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-05 18:35:15 +08:00
Tunglies 2804803949 fix: deep-link clippy warnings (#3143)
* Update build.rs

* fix: address clippy warnings in deep-link module

* fix: add deep-link-js patch to address clippy warnings
2025-12-04 20:04:56 +08:00
renovate[bot] d9d51eb8ea chore(deps): update dependency prettier to v3.7.3 (#3140)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-03 09:58:49 +08:00
renovate[bot] 1483c63101 chore(deps): update dependency prettier to v3.7.2 (#3137)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-02 10:31:13 +08:00
renovate[bot] 26ed78989a chore(deps): update dependency prettier to v3.7.1 (#3134)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-30 20:01:16 +08:00
renovate[bot] f1564e58b6 chore(deps): update dependency prettier to v3.7.0 (#3132)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-30 19:53:50 +08:00
Fabian-Lars f2d4abb9e2 fix(dialog): rfd feature flags (#3129) 2025-11-28 15:25:58 +01:00
renovate[bot] 3dcf7522b1 chore(deps): update dependency typescript-eslint to v8.48.0 (#3126)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-28 14:45:59 +08:00
renovate[bot] 02068550e8 chore(deps): update rust crate rfd to 0.16 (#3128)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-28 13:47:22 +08:00
Fabian-Lars 66a75ece27 fix(websocket): install crypto provider if needed (#3124) 2025-11-25 20:02:47 +01:00
Christian Leingang fa601e8754 feat(updater): allow accepting invalid TLS certs/hostnames via config (#3057)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-11-24 14:56:59 +01:00
Niccolò Gnani d8bfe61f20 fix(barcode-scanner): remove unnecessary permission checks on Android (fix #2312) (#3121) 2025-11-24 14:27:46 +01:00
Amr Bashir e8915f17e4 fix(http): fix aborting a streaming response (#2562) 2025-11-24 13:55:11 +01:00
Lucas Fernandes Nogueira 6de61f854b chore(log): remove iOS simulator workarounds (#3113) 2025-11-24 13:35:19 +01:00
renovate[bot] ad7a8d3e42 chore(deps): update dependency rollup to v4.53.3 (#3119)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-24 16:25:46 +08:00
FabianLars d5509a9ac8 chore: add docs issue template and enable blank issues 2025-11-23 13:55:52 +01:00
FabianLars 06727b19c1 chore: fix issue templates 2025-11-23 13:51:01 +01:00
Fabian-Lars 2f9fa79747 chore: add issue templates (#3122) 2025-11-23 13:42:24 +01:00
170 changed files with 1901 additions and 2618 deletions
@@ -1,6 +0,0 @@
---
"dialog-js": minor:feat
"dialog": minor:feat
---
Add `xdg-portal` as an optional feature for `rfd`
@@ -1,6 +0,0 @@
---
"log": "minor"
"log-js": "minor"
---
Allow specifying a log formatter per target using the `format` method on `Target`.
-10
View File
@@ -78,7 +78,6 @@
"notification",
"os",
"process",
"secure-storage",
"shell",
"store",
"updater",
@@ -105,7 +104,6 @@
"notification-js",
"os-js",
"process-js",
"secure-storage-js",
"shell-js",
"store-js",
"updater-js"
@@ -284,14 +282,6 @@
"path": "./plugins/process",
"manager": "javascript"
},
"secure-storage": {
"path": "./plugins/secure-storage",
"manager": "rust"
},
"secure-storage-js": {
"path": "./plugins/secure-storage",
"manager": "javascript"
},
"shell": {
"path": "./plugins/shell",
"manager": "rust"
-6
View File
@@ -1,6 +0,0 @@
---
stronghold: patch
stronghold-js: patch
---
The `stronghold` plugin is now deprecated and will be removed in v3. The `secure-storage` plugin should be a replacement for most use-cases.
-6
View File
@@ -1,6 +0,0 @@
---
"dialog": minor
"dialog-js": minor
---
Add `pickerMode` option to file picker (currently only used on iOS)
@@ -1,5 +0,0 @@
---
"localhost": patch
---
Disable caching on responses.
@@ -1,6 +0,0 @@
---
"barcode-scanner": patch
"barcode-scanner-js": patch
---
Fix the `cameraView` is not removed after scanning in iOS.
-6
View File
@@ -1,6 +0,0 @@
---
"log": patch
"log-js": patch
---
Fix log file rotation when exceeding `max_file_size`.
-6
View File
@@ -1,6 +0,0 @@
---
"nfc": "patch"
"nfc-js": "patch"
---
Update return value of `isAvailable` to match TypeScript function signature
-6
View File
@@ -1,6 +0,0 @@
---
"updater": minor
"updater-js": minor
---
Updater plugin now supports all bundle types: Deb, Rpm and AppImage for Linux; NSiS, MSI for Windows. This was added in https://github.com/tauri-apps/plugins-workspace/pull/2624
-6
View File
@@ -1,6 +0,0 @@
---
"upload": minor
"upload-js": minor
---
Upload plugin now supports specifying an HTTP method i.e. POST, PUT etc.
+63
View File
@@ -0,0 +1,63 @@
# Copyright 2019-2023 Tauri Programme within The Commons Conservancy
# SPDX-License-Identifier: Apache-2.0
# SPDX-License-Identifier: MIT
name: 🐞 Bug Report
description: Report a bug
labels: ['type: bug']
body:
- type: markdown
attributes:
value: |
## First of all
1. Please search for [existing issues](https://github.com/tauri-apps/plugins-workspace/issues?q=is%3Aissue) about this problem first.
2. Make sure `rustc` and all relevant Tauri packages are up to date.
3. Make sure it's an issue with a tauri plugin and not something else you are using.
4. Remember to follow our community guidelines and be friendly.
- type: textarea
id: description
attributes:
label: Describe the bug
description: A clear description of what the bug is. Include screenshots if applicable.
placeholder: Bug description
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: Reproduction
description: A link to a reproduction repo or steps to reproduce the behaviour.
placeholder: |
Please provide a minimal reproduction or steps to reproduce, see this guide https://stackoverflow.com/help/minimal-reproducible-example
Why reproduction is required? see this article https://antfu.me/posts/why-reproductions-are-required
- type: textarea
id: expected-behavior
attributes:
label: Expected behavior
description: A clear description of what you expected to happen.
- type: textarea
id: info
attributes:
label: Full `tauri info` output
description: 'Output of `npm run tauri info` or `cargo tauri info`. Issues without this will be closed!'
render: text
validations:
required: true
- type: textarea
id: logs
attributes:
label: Stack trace
description: A stack trace or ANY error messages you may see.
render: text
- type: textarea
id: context
attributes:
label: Additional context
description: Add any other context about the problem here. For example a link to a Discord discussion.
+12
View File
@@ -0,0 +1,12 @@
# Copyright 2019-2023 Tauri Programme within The Commons Conservancy
# SPDX-License-Identifier: Apache-2.0
# SPDX-License-Identifier: MIT
#blank_issues_enabled: false
contact_links:
- name: 💡 Request a new plugin
url: https://github.com/orgs/tauri-apps/discussions/new?category=plugin-requests
about: Propose a new Plugin to the community or the Tauri org.
- name: 💬 Discord Chat
url: https://discord.com/invite/tauri
about: Ask questions and talk to other Tauri users and the maintainers
+5
View File
@@ -0,0 +1,5 @@
---
name: 📚 Docs Report
about: Create a report to help us improve the docs
labels: 'type: documentation'
---
@@ -0,0 +1,46 @@
# Copyright 2019-2023 Tauri Programme within The Commons Conservancy
# SPDX-License-Identifier: Apache-2.0
# SPDX-License-Identifier: MIT
name: 💡 Feature Request
description: Request a feature or enhancement for an existing plugin
labels: ['type: feature request']
body:
- type: markdown
attributes:
value: |
## First of all
- Please search for [existing issues](https://github.com/tauri-apps/plugins-workspace/issues?q=is%3Aissue) for this request first.
- Only requests for plugins that exist in this repo are allowed.
- You can request new plugins [here](https://github.com/orgs/tauri-apps/discussions/new?category=plugin-requests)
- type: textarea
id: problem
attributes:
label: Describe the problem
description: A clear description of the problem this feature would solve
placeholder: "I'm always frustrated when..."
validations:
required: true
- type: textarea
id: solution
attributes:
label: "Describe the solution you'd like"
description: A clear description of what change you would like
placeholder: 'I would like to...'
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives considered
description: "Any alternative solutions you've considered"
- type: textarea
id: context
attributes:
label: Additional context
description: Add any other context about the problem here.
@@ -101,11 +101,6 @@ jobs:
- pnpm-lock.yaml
- plugins/process/guest-js/**
- plugins/process/src/api-iife.js
secure-storage:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/secure-storage/guest-js/**
- plugins/secure-storage/src/api-iife.js
shell:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
+1
View File
@@ -5,6 +5,7 @@
name: integration tests
on:
workflow_dispatch:
push:
branches:
- v1
-3
View File
@@ -98,9 +98,6 @@ jobs:
tauri-plugin-process:
- .github/workflows/lint-rust.yml
- plugins/process/**
tauri-plugin-secure-storage:
- .github/workflows/lint-rust.yml
- plugins/secure-storage/**
tauri-plugin-shell:
- .github/workflows/lint-rust.yml
- plugins/shell/**
+3 -8
View File
@@ -137,11 +137,6 @@ jobs:
- Cargo.toml
- Cargo.lock
- plugins/process/**
tauri-plugin-secure-storage:
- .github/workflows/test-rust.yml
- Cargo.toml
- Cargo.lock
- plugins/secure-storage/**
tauri-plugin-shell:
- .github/workflows/test-rust.yml
- Cargo.toml
@@ -224,7 +219,7 @@ jobs:
target: aarch64-linux-android,
os: ubuntu-latest,
runner: 'cross',
command: 'build --verbose'
command: 'build'
}
runs-on: ${{ matrix.platform.os }}
@@ -238,7 +233,7 @@ jobs:
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.0-dev libwebkit2gtk-4.1-dev
- uses: dtolnay/rust-toolchain@1.85
- uses: dtolnay/rust-toolchain@1.77.2
with:
targets: ${{ matrix.platform.target }}
@@ -251,7 +246,7 @@ jobs:
run: cargo +stable install cross --git https://github.com/cross-rs/cross
- name: test ${{ matrix.package }}
if: matrix.package != 'tauri-plugin-http' && matrix.package != 'tauri-plugin-secure-storage' && matrix.package != 'tauri-plugin-dialog'
if: ${{ matrix.package != 'tauri-plugin-http' && matrix.package != 'tauri-plugin-dialog' }}
run: ${{ matrix.platform.runner }} ${{ matrix.platform.command }} --package ${{ matrix.package }} --target ${{ matrix.platform.target }} --all-targets --all-features
- name: test ${{ matrix.package }}
-1
View File
@@ -1,3 +1,2 @@
plugins/*/permissions/autogenerated/
plugins/*/android/.tauri/tauri-api/build/
plugins/*/android/build/intermediates/
Generated
+296 -307
View File
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -12,10 +12,10 @@ resolver = "2"
serde = { version = "1", features = ["derive"] }
tracing = "0.1"
log = "0.4"
tauri = { version = "2.8.2", default-features = false }
tauri-build = "2.4"
tauri-plugin = "2.4"
tauri-utils = "2.7"
tauri = { version = "2.10", default-features = false }
tauri-build = "2.5"
tauri-plugin = "2.5"
tauri-utils = "2.8"
serde_json = "1"
thiserror = "2"
url = "2"
+30
View File
@@ -1,5 +1,35 @@
# Changelog
## \[2.0.37]
### Dependencies
- Upgraded to `updater-js@2.10.0`
- Upgraded to `barcode-scanner-js@2.4.4`
- Upgraded to `http-js@2.5.7`
- Upgraded to `shell-js@2.3.5`
## \[2.0.36]
### Dependencies
- Upgraded to `http-js@2.5.6`
- Upgraded to `dialog-js@2.6.0`
## \[2.0.35]
### Dependencies
- Upgraded to `dialog-js@2.5.0`
- Upgraded to `log-js@2.8.0`
- Upgraded to `shell-js@2.3.4`
- Upgraded to `barcode-scanner-js@2.4.3`
- Upgraded to `fs-js@2.4.5`
- Upgraded to `http-js@2.5.5`
- Upgraded to `nfc-js@2.3.4`
- Upgraded to `opener-js@2.5.3`
- Upgraded to `store-js@2.4.2`
## \[2.0.34]
### Dependencies
+12 -13
View File
@@ -1,7 +1,7 @@
{
"name": "api",
"private": true,
"version": "2.0.34",
"version": "2.0.37",
"type": "module",
"scripts": {
"dev": "vite --clearScreen false",
@@ -10,26 +10,25 @@
"tauri": "tauri"
},
"dependencies": {
"@tauri-apps/api": "2.9.0",
"@tauri-apps/plugin-barcode-scanner": "^2.4.2",
"@tauri-apps/api": "^2.10.1",
"@tauri-apps/plugin-barcode-scanner": "^2.4.4",
"@tauri-apps/plugin-biometric": "^2.3.2",
"@tauri-apps/plugin-cli": "^2.4.1",
"@tauri-apps/plugin-clipboard-manager": "^2.3.2",
"@tauri-apps/plugin-dialog": "^2.4.2",
"@tauri-apps/plugin-fs": "^2.4.4",
"@tauri-apps/plugin-dialog": "^2.6.0",
"@tauri-apps/plugin-fs": "^2.4.5",
"@tauri-apps/plugin-geolocation": "^2.2.0",
"@tauri-apps/plugin-global-shortcut": "^2.3.1",
"@tauri-apps/plugin-haptics": "^2.2.0",
"@tauri-apps/plugin-http": "^2.5.4",
"@tauri-apps/plugin-nfc": "^2.3.3",
"@tauri-apps/plugin-http": "^2.5.7",
"@tauri-apps/plugin-nfc": "^2.3.4",
"@tauri-apps/plugin-notification": "^2.3.3",
"@tauri-apps/plugin-opener": "^2.5.2",
"@tauri-apps/plugin-opener": "^2.5.3",
"@tauri-apps/plugin-os": "^2.3.2",
"@tauri-apps/plugin-process": "^2.3.1",
"@tauri-apps/plugin-secure-storage": "file:../../plugins/secure-storage",
"@tauri-apps/plugin-shell": "^2.3.3",
"@tauri-apps/plugin-store": "^2.4.1",
"@tauri-apps/plugin-updater": "^2.9.0",
"@tauri-apps/plugin-shell": "^2.3.5",
"@tauri-apps/plugin-store": "^2.4.2",
"@tauri-apps/plugin-updater": "^2.10.0",
"@tauri-apps/plugin-upload": "^2.3.0",
"@zerodevx/svelte-json-view": "1.0.11"
},
@@ -37,7 +36,7 @@
"@iconify-json/codicon": "^1.2.12",
"@iconify-json/ph": "^1.2.2",
"@sveltejs/vite-plugin-svelte": "^6.0.0",
"@tauri-apps/cli": "2.9.4",
"@tauri-apps/cli": "2.10.0",
"@unocss/extractor-svelte": "^66.3.3",
"svelte": "^5.20.4",
"unocss": "^66.3.3",
+30
View File
@@ -1,5 +1,35 @@
# Changelog
## \[2.0.41]
### Dependencies
- Upgraded to `updater@2.10.0`
- Upgraded to `barcode-scanner@2.4.4`
- Upgraded to `http@2.5.7`
- Upgraded to `shell@2.3.5`
## \[2.0.40]
### Dependencies
- Upgraded to `http@2.5.6`
- Upgraded to `dialog@2.6.0`
## \[2.0.39]
### Dependencies
- Upgraded to `dialog@2.5.0`
- Upgraded to `log@2.8.0`
- Upgraded to `shell@2.3.4`
- Upgraded to `barcode-scanner@2.4.3`
- Upgraded to `fs@2.4.5`
- Upgraded to `http@2.5.5`
- Upgraded to `nfc@2.3.4`
- Upgraded to `opener@2.5.3`
- Upgraded to `store@2.4.2`
## \[2.0.38]
### Dependencies
+11 -12
View File
@@ -1,7 +1,7 @@
[package]
name = "api"
publish = false
version = "2.0.38"
version = "2.0.41"
description = "An example Tauri Application showcasing the api"
edition = "2021"
rust-version = { workspace = true }
@@ -20,25 +20,24 @@ serde = { workspace = true }
tiny_http = "0.12"
time = "0.3"
log = { workspace = true }
tauri-plugin-log = { path = "../../../plugins/log", version = "2.7.1" }
tauri-plugin-fs = { path = "../../../plugins/fs", version = "2.4.4", features = [
tauri-plugin-log = { path = "../../../plugins/log", version = "2.8.0" }
tauri-plugin-fs = { path = "../../../plugins/fs", version = "2.4.5", features = [
"watch",
] }
tauri-plugin-clipboard-manager = { path = "../../../plugins/clipboard-manager", version = "2.3.2" }
tauri-plugin-dialog = { path = "../../../plugins/dialog", version = "2.4.2" }
tauri-plugin-dialog = { path = "../../../plugins/dialog", version = "2.6.0" }
tauri-plugin-http = { path = "../../../plugins/http", features = [
"multipart",
"cookies",
], version = "2.5.4" }
], version = "2.5.7" }
tauri-plugin-notification = { path = "../../../plugins/notification", version = "2.3.3", features = [
"windows7-compat",
] }
tauri-plugin-os = { path = "../../../plugins/os", version = "2.3.2" }
tauri-plugin-process = { path = "../../../plugins/process", version = "2.3.1" }
tauri-plugin-opener = { path = "../../../plugins/opener", version = "2.5.2" }
tauri-plugin-secure-storage = { path = "../../../plugins/secure-storage" }
tauri-plugin-shell = { path = "../../../plugins/shell", version = "2.3.3" }
tauri-plugin-store = { path = "../../../plugins/store", version = "2.4.1" }
tauri-plugin-opener = { path = "../../../plugins/opener", version = "2.5.3" }
tauri-plugin-shell = { path = "../../../plugins/shell", version = "2.3.5" }
tauri-plugin-store = { path = "../../../plugins/store", version = "2.4.2" }
tauri-plugin-upload = { path = "../../../plugins/upload", version = "2.3.0" }
[dependencies.tauri]
@@ -58,12 +57,12 @@ 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.4.1" }
tauri-plugin-global-shortcut = { path = "../../../plugins/global-shortcut", version = "2.3.1" }
tauri-plugin-updater = { path = "../../../plugins/updater", version = "2.9.0" }
tauri-plugin-updater = { path = "../../../plugins/updater", version = "2.10.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.4.2" }
tauri-plugin-nfc = { path = "../../../plugins/nfc", version = "2.3.3" }
tauri-plugin-barcode-scanner = { path = "../../../plugins/barcode-scanner/", version = "2.4.4" }
tauri-plugin-nfc = { path = "../../../plugins/nfc", version = "2.3.4" }
tauri-plugin-biometric = { path = "../../../plugins/biometric/", version = "2.3.2" }
tauri-plugin-geolocation = { path = "../../../plugins/geolocation/", version = "2.3.2" }
tauri-plugin-haptics = { path = "../../../plugins/haptics/", version = "2.3.2" }
@@ -102,10 +102,6 @@
"identifier": "opener:allow-open-path",
"allow": [{ "path": "$APPDATA" }, { "path": "$APPDATA/**" }]
},
"upload:default",
"secure-storage:allow-get-string",
"secure-storage:allow-set-string",
"secure-storage:allow-get-binary",
"secure-storage:allow-set-binary"
"upload:default"
]
}
+2 -2
View File
@@ -14,11 +14,11 @@ pub struct RequestBody {
#[command]
pub fn log_operation(event: String, payload: Option<String>) {
log::info!("{event} {payload:?}");
log::info!("{} {:?}", event, payload);
}
#[command]
pub fn perform_request(endpoint: String, body: RequestBody) -> String {
println!("{endpoint} {body:?}");
println!("{} {:?}", endpoint, body);
"message response".into()
}
-1
View File
@@ -38,7 +38,6 @@ pub fn run() {
.plugin(tauri_plugin_process::init())
.plugin(tauri_plugin_opener::init())
.plugin(tauri_plugin_shell::init())
.plugin(tauri_plugin_secure_storage::init())
.plugin(tauri_plugin_store::Builder::default().build())
.plugin(tauri_plugin_upload::init())
.setup(move |app| {
+6 -12
View File
@@ -23,7 +23,6 @@
import Biometric from './views/Biometric.svelte'
import Geolocation from './views/Geolocation.svelte'
import Haptics from './views/Haptics.svelte'
import SecureStorage from './views/SecureStorage.svelte'
import { onMount, tick } from 'svelte'
import { ask } from '@tauri-apps/plugin-dialog'
@@ -104,11 +103,6 @@
component: Store,
icon: 'i-codicon-file-code'
},
{
label: 'SecureStorage',
component: SecureStorage,
icon: 'i-codicon-file-code'
},
!isMobile && {
label: 'Updater',
component: Updater,
@@ -219,9 +213,9 @@
...r,
{
html:
`<pre><strong class="text-accent dark:text-darkAccent">[${new Date().toLocaleTimeString()}]:</strong> `
+ (typeof value === 'string' ? value : JSON.stringify(value, null, 1))
+ '</pre>'
`<pre><strong class="text-accent dark:text-darkAccent">[${new Date().toLocaleTimeString()}]:</strong> ` +
(typeof value === 'string' ? value : JSON.stringify(value, null, 1)) +
'</pre>'
}
])
await tick()
@@ -235,9 +229,9 @@
...r,
{
html:
`<pre><strong class="text-accent dark:text-darkAccent">[${new Date().toLocaleTimeString()}]:</strong> `
+ html
+ '</pre>'
`<pre><strong class="text-accent dark:text-darkAccent">[${new Date().toLocaleTimeString()}]:</strong> ` +
html +
'</pre>'
}
])
await tick()
+62 -48
View File
@@ -8,7 +8,8 @@
let filter = null;
let multiple = false;
let directory = false;
let pickerMode = "";
let pickerMode = "document";
let fileAccessMode = "scoped";
function arrayBufferToBase64(buffer, callback) {
var blob = new Blob([buffer], {
@@ -52,54 +53,60 @@
.catch(onMessage);
}
function openDialog() {
open({
title: "My wonderful open dialog",
defaultPath,
filters: filter
? [
{
name: "Tauri Example",
extensions: filter.split(",").map((f) => f.trim()),
},
]
: [],
multiple,
directory,
pickerMode: pickerMode === "" ? undefined : pickerMode,
})
.then(function (res) {
if (Array.isArray(res)) {
onMessage(res);
} else {
var pathToRead = res;
var isFile = pathToRead.match(/\S+\.\S+$/g);
readFile(pathToRead)
.then(function (response) {
if (isFile) {
if (
pathToRead.includes(".png") ||
pathToRead.includes(".jpg") ||
pathToRead.includes(".jpeg")
) {
arrayBufferToBase64(
new Uint8Array(response),
function (base64) {
var src = "data:image/png;base64," + base64;
insecureRenderHtml('<img src="' + src + '"></img>');
}
);
} else {
onMessage(res);
}
} else {
onMessage(res);
}
})
.catch(onMessage);
}
async function openDialog() {
try {
var result = await open({
title: "My wonderful open dialog",
defaultPath,
filters: filter
? [
{
name: "Tauri Example",
extensions: filter.split(",").map((f) => f.trim()),
},
]
: [],
multiple,
directory,
pickerMode,
fileAccessMode,
})
.catch(onMessage);
if (Array.isArray(result)) {
onMessage(result);
} else {
var pathToRead = result;
var isFile = pathToRead.match(/\S+\.\S+$/g);
await readFile(pathToRead)
.then(function (res) {
if (isFile) {
if (
pathToRead.includes(".png") ||
pathToRead.includes(".jpg") ||
pathToRead.includes(".jpeg")
) {
arrayBufferToBase64(
new Uint8Array(res),
function (base64) {
var src = "data:image/png;base64," + base64;
insecureRenderHtml('<img src="' + src + '"></img>');
}
);
} else {
// Convert byte array to UTF-8 string
const decoder = new TextDecoder('utf-8');
const text = decoder.decode(new Uint8Array(res));
onMessage(text);
}
} else {
onMessage(res);
}
})
}
} catch(exception) {
onMessage(exception)
}
}
function saveDialog() {
@@ -154,6 +161,13 @@
<option value="document">Document</option>
</select>
</div>
<div>
<label for="dialog-file-access-mode">File Access Mode:</label>
<select id="dialog-file-access-mode" bind:value={fileAccessMode}>
<option value="copy">Copy</option>
<option value="scoped">Scoped</option>
</select>
</div>
<br />
<div class="flex flex-wrap flex-col md:flex-row gap-2 children:flex-shrink-0">
@@ -1,54 +0,0 @@
<script>
import { onMount } from 'svelte'
import { getString, setString } from '@tauri-apps/plugin-secure-storage'
export let onMessage
let key
let value
let output
async function read(key) {
try {
output = await getString(key)
} catch (error) {
onMessage(error)
}
}
async function write(key, value) {
try {
await setString(key, value)
} catch (error) {
onMessage(error)
}
}
function reset() {
output = ''
}
</script>
<div class="flex flex-col childre:grow gap-1">
<div class="flex flex-col flex-row-md gap-4">
<div class="flex items-center gap-1">
Key:
<input class="grow input" bind:value={key} />
</div>
<div class="flex items-center gap-1">
Value:
<input class="grow input" bind:value />
</div>
<div>
<button class="btn" on:click={() => write(key, value)}>Write</button>
<button class="btn" on:click={() => read(key)}>Read</button>
<button class="btn" on:click={() => reset()}>Reset Output</button>
</div>
</div>
<div>
Output: {output}
</div>
</div>
+7 -6
View File
@@ -11,24 +11,25 @@
"example:api:dev": "pnpm run --filter \"api\" tauri dev"
},
"devDependencies": {
"@eslint/js": "9.39.1",
"@eslint/js": "9.39.2",
"@rollup/plugin-node-resolve": "16.0.3",
"@rollup/plugin-terser": "0.4.4",
"@rollup/plugin-typescript": "12.3.0",
"covector": "^0.12.4",
"eslint": "9.39.1",
"eslint": "9.39.2",
"eslint-config-prettier": "10.1.8",
"eslint-plugin-security": "3.0.1",
"prettier": "3.6.2",
"rollup": "4.53.2",
"prettier": "3.8.0",
"rollup": "4.55.1",
"tslib": "2.8.1",
"typescript": "5.9.3",
"typescript-eslint": "8.47.0"
"typescript-eslint": "8.53.0"
},
"minimumReleaseAge": 4320,
"pnpm": {
"overrides": {
"esbuild@<0.25.0": ">=0.25.0"
"esbuild@<0.25.0": ">=0.25.0",
"lodash@>=4.0.0 <=4.17.22": ">=4.17.23"
},
"onlyBuiltDependencies": [
"esbuild"
+1 -1
View File
@@ -24,6 +24,6 @@
"LICENSE"
],
"dependencies": {
"@tauri-apps/api": "^2.8.0"
"@tauri-apps/api": "^2.10.1"
}
}
@@ -331,10 +331,10 @@
"markdownDescription": "Denies the is_enabled command without any pre-configured scope."
},
{
"description": "This permission set configures if your\r\napplication can enable or disable auto\r\nstarting the application on boot.\r\n\r\n#### Granted Permissions\r\n\r\nIt allows all to check, enable and\r\ndisable the automatic start on boot.\r\n\r\n\n#### This default permission set includes:\n\n- `allow-enable`\n- `allow-disable`\n- `allow-is-enabled`",
"description": "This permission set configures if your\napplication can enable or disable auto\nstarting the application on boot.\n\n#### Granted Permissions\n\nIt allows all to check, enable and\ndisable the automatic start on boot.\n\n\n#### This default permission set includes:\n\n- `allow-enable`\n- `allow-disable`\n- `allow-is-enabled`",
"type": "string",
"const": "default",
"markdownDescription": "This permission set configures if your\r\napplication can enable or disable auto\r\nstarting the application on boot.\r\n\r\n#### Granted Permissions\r\n\r\nIt allows all to check, enable and\r\ndisable the automatic start on boot.\r\n\r\n\n#### This default permission set includes:\n\n- `allow-enable`\n- `allow-disable`\n- `allow-is-enabled`"
"markdownDescription": "This permission set configures if your\napplication can enable or disable auto\nstarting the application on boot.\n\n#### Granted Permissions\n\nIt allows all to check, enable and\ndisable the automatic start on boot.\n\n\n#### This default permission set includes:\n\n- `allow-enable`\n- `allow-disable`\n- `allow-is-enabled`"
}
]
}
+11
View File
@@ -1,5 +1,16 @@
# Changelog
## \[2.4.4]
- [`82fbb0c7`](https://github.com/tauri-apps/plugins-workspace/commit/82fbb0c790288eca72af9ade13828ded7700ff90) ([#3221](https://github.com/tauri-apps/plugins-workspace/pull/3221)) On iOS, fixed an application crash happening when the scanner was started when user denied permission before.
- [`b60dd887`](https://github.com/tauri-apps/plugins-workspace/commit/b60dd88702a2be2af942a3d104d728970a4c42d6) ([#3223](https://github.com/tauri-apps/plugins-workspace/pull/3223)) On iOS, start the scanning session on a separate thread to fix performance issues.
- [`c27af912`](https://github.com/tauri-apps/plugins-workspace/commit/c27af9128d6cc7a2424ec49e98005e68b2d0eb1a) ([#3222](https://github.com/tauri-apps/plugins-workspace/pull/3222)) On iOS, fixed an application crash happening when the scanner was started on the iOS Simulator (no camera available).
## \[2.4.3]
- [`d8bfe61f`](https://github.com/tauri-apps/plugins-workspace/commit/d8bfe61f20f235314bad93a9c50d8b7f3eade734) ([#3121](https://github.com/tauri-apps/plugins-workspace/pull/3121) by [@NKIPSC](https://github.com/tauri-apps/plugins-workspace/../../NKIPSC)) Remove unnecessary checks on Android when requesting camera permission.
- [`631d0e25`](https://github.com/tauri-apps/plugins-workspace/commit/631d0e256a37946b6a9102ca35511abfbebb92c5) ([#2440](https://github.com/tauri-apps/plugins-workspace/pull/2440) by [@kingsword09](https://github.com/tauri-apps/plugins-workspace/../../kingsword09)) Fix the `cameraView` is not removed after scanning in iOS.
## \[2.4.2]
- [`93426f85`](https://github.com/tauri-apps/plugins-workspace/commit/93426f85120f49beb9f40222bff45185a32d54a9) Fixed an issue that caused docs.rs builds to fail. No user facing changes.
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-barcode-scanner"
version = "2.4.2"
version = "2.4.4"
description = "Scan QR codes, EAN-13 and other kinds of barcodes on Android and iOS"
edition = { workspace = true }
authors = { workspace = true }
@@ -54,7 +54,6 @@ import java.util.concurrent.ExecutionException
private const val PERMISSION_ALIAS_CAMERA = "camera"
private const val PERMISSION_NAME = Manifest.permission.CAMERA
private const val PREFS_PERMISSION_FIRST_TIME_ASKING = "PREFS_PERMISSION_FIRST_TIME_ASKING"
@InvokeArg
class ScanOptions {
@@ -354,17 +353,6 @@ class BarcodeScannerPlugin(private val activity: Activity) : Plugin(activity),
}
}
private fun markFirstPermissionRequest() {
val sharedPreference: SharedPreferences =
activity.getSharedPreferences(PREFS_PERMISSION_FIRST_TIME_ASKING, MODE_PRIVATE)
sharedPreference.edit().putBoolean(PERMISSION_NAME, false).apply()
}
private fun firstPermissionRequest(): Boolean {
return activity.getSharedPreferences(PREFS_PERMISSION_FIRST_TIME_ASKING, MODE_PRIVATE)
.getBoolean(PERMISSION_NAME, true)
}
@SuppressLint("ObsoleteSdkInt")
@PermissionCallback
fun cameraPermissionCallback(invoke: Invoke) {
@@ -380,9 +368,7 @@ class BarcodeScannerPlugin(private val activity: Activity) : Plugin(activity),
requestPermissionResponse.put(PERMISSION_ALIAS_CAMERA, PermissionState.GRANTED)
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!activity.shouldShowRequestPermissionRationale(PERMISSION_NAME)) {
requestPermissionResponse.put(PERMISSION_ALIAS_CAMERA, PermissionState.DENIED)
}
requestPermissionResponse.put(PERMISSION_ALIAS_CAMERA, PermissionState.DENIED)
} else {
requestPermissionResponse.put(PERMISSION_ALIAS_CAMERA, PermissionState.GRANTED)
}
@@ -401,20 +387,12 @@ class BarcodeScannerPlugin(private val activity: Activity) : Plugin(activity),
requestPermissionResponse.put(PERMISSION_ALIAS_CAMERA, PermissionState.GRANTED)
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (firstPermissionRequest() || activity.shouldShowRequestPermissionRationale(
PERMISSION_NAME
)
) {
markFirstPermissionRequest()
requestPermissionForAlias(
PERMISSION_ALIAS_CAMERA,
invoke,
"cameraPermissionCallback"
)
return
} else {
requestPermissionResponse.put(PERMISSION_ALIAS_CAMERA, PermissionState.DENIED)
}
requestPermissionForAlias(
PERMISSION_ALIAS_CAMERA,
invoke,
"cameraPermissionCallback"
)
return
} else {
requestPermissionResponse.put(PERMISSION_ALIAS_CAMERA, PermissionState.GRANTED)
}
@@ -261,27 +261,34 @@ class BarcodeScannerPlugin: Plugin, AVCaptureMetadataOutputObjectsDelegate {
}
private func runScanner(_ invoke: Invoke, args: ScanOptions) {
if getPermissionState() != "granted" {
invoke.reject("Camera permission denied or not yet requested")
return
}
scanFormats = [AVMetadataObject.ObjectType]()
(args.formats ?? []).forEach { format in
if let formatValue = format.value {
scanFormats.append(formatValue)
} else {
invoke.reject("Unsupported barcode format on this iOS version: \(format)")
return
}
if let formatValue = format.value {
scanFormats.append(formatValue)
} else {
invoke.reject("Unsupported barcode format on this iOS version: \(format)")
return
}
}
if scanFormats.isEmpty {
for supportedFormat in SupportedFormat.allCases {
if let formatValue = supportedFormat.value {
scanFormats.append(formatValue)
}
for supportedFormat in SupportedFormat.allCases {
if let formatValue = supportedFormat.value {
scanFormats.append(formatValue)
}
}
}
self.metaOutput!.metadataObjectTypes = self.scanFormats
self.captureSession!.startRunning()
DispatchQueue.main.async {
self.captureSession!.startRunning()
}
self.isScanning = true
}
@@ -298,6 +305,13 @@ class BarcodeScannerPlugin: Plugin, AVCaptureMetadataOutputObjectsDelegate {
return
}
// Check if camera is available on this platform (iOS simulator doesn't have cameras)
let availableVideoDevices = discoverCaptureDevices()
if availableVideoDevices.isEmpty {
invoke.reject("No camera available on this device (e.g., iOS Simulator)")
return
}
var iOS14min: Bool = false
if #available(iOS 14.0, *) { iOS14min = true }
if !iOS14min && self.getPermissionState() != "granted" {
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-barcode-scanner",
"version": "2.4.2",
"version": "2.4.4",
"description": "Scan QR codes, EAN-13 and other kinds of barcodes on Android and iOS",
"license": "MIT OR Apache-2.0",
"authors": [
@@ -25,6 +25,6 @@
"LICENSE"
],
"dependencies": {
"@tauri-apps/api": "^2.8.0"
"@tauri-apps/api": "^2.10.1"
}
}
+1 -1
View File
@@ -25,6 +25,6 @@
"LICENSE"
],
"dependencies": {
"@tauri-apps/api": "^2.8.0"
"@tauri-apps/api": "^2.10.1"
}
}
@@ -319,10 +319,10 @@
"markdownDescription": "Denies the status command without any pre-configured scope."
},
{
"description": "This permission set configures which\r\nbiometric features are by default exposed.\r\n\r\n#### Granted Permissions\r\n\r\nIt allows acccess to all biometric commands.\r\n\r\n\n#### This default permission set includes:\n\n- `allow-authenticate`\n- `allow-status`",
"description": "This permission set configures which\nbiometric features are by default exposed.\n\n#### Granted Permissions\n\nIt allows acccess to all biometric commands.\n\n\n#### This default permission set includes:\n\n- `allow-authenticate`\n- `allow-status`",
"type": "string",
"const": "default",
"markdownDescription": "This permission set configures which\r\nbiometric features are by default exposed.\r\n\r\n#### Granted Permissions\r\n\r\nIt allows acccess to all biometric commands.\r\n\r\n\n#### This default permission set includes:\n\n- `allow-authenticate`\n- `allow-status`"
"markdownDescription": "This permission set configures which\nbiometric features are by default exposed.\n\n#### Granted Permissions\n\nIt allows acccess to all biometric commands.\n\n\n#### This default permission set includes:\n\n- `allow-authenticate`\n- `allow-status`"
}
]
}
+1 -1
View File
@@ -24,6 +24,6 @@
"LICENSE"
],
"dependencies": {
"@tauri-apps/api": "^2.8.0"
"@tauri-apps/api": "^2.10.1"
}
}
+1 -1
View File
@@ -24,6 +24,6 @@
"LICENSE"
],
"dependencies": {
"@tauri-apps/api": "^2.8.0"
"@tauri-apps/api": "^2.10.1"
}
}
@@ -1,7 +1,7 @@
## Default Permission
No features are enabled by default, as we believe
the clipboard can be inherently dangerous and it is
the clipboard can be inherently dangerous and it is
application specific if read and/or write access is needed.
Clipboard interaction needs to be explicitly enabled.
@@ -2,7 +2,7 @@
[default]
description = """
No features are enabled by default, as we believe
the clipboard can be inherently dangerous and it is
the clipboard can be inherently dangerous and it is
application specific if read and/or write access is needed.
Clipboard interaction needs to be explicitly enabled.
@@ -367,10 +367,10 @@
"markdownDescription": "Denies the write_text command without any pre-configured scope."
},
{
"description": "No features are enabled by default, as we believe\r\nthe clipboard can be inherently dangerous and it is\r\napplication specific if read and/or write access is needed.\r\n\r\nClipboard interaction needs to be explicitly enabled.\r\n",
"description": "No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n",
"type": "string",
"const": "default",
"markdownDescription": "No features are enabled by default, as we believe\r\nthe clipboard can be inherently dangerous and it is\r\napplication specific if read and/or write access is needed.\r\n\r\nClipboard interaction needs to be explicitly enabled.\r\n"
"markdownDescription": "No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n"
}
]
}
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.4.6]
- [`28048039`](https://github.com/tauri-apps/plugins-workspace/commit/28048039496e84b46847c008416d341f1349e30e) ([#3143](https://github.com/tauri-apps/plugins-workspace/pull/3143) by [@Tunglies](https://github.com/tauri-apps/plugins-workspace/../../Tunglies)) Fix clippy warnings. No user facing changes.
## \[2.4.5]
- [`93426f85`](https://github.com/tauri-apps/plugins-workspace/commit/93426f85120f49beb9f40222bff45185a32d54a9) Fixed an issue that caused docs.rs builds to fail. No user facing changes.
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-deep-link"
version = "2.4.5"
version = "2.4.6"
description = "Set your Tauri application as the default handler for an URL"
authors = { workspace = true }
license = { workspace = true }
+2 -8
View File
@@ -137,13 +137,7 @@ fn main() {
let deep_link_domains = config
.mobile
.iter()
.filter_map(|domain| {
if domain.is_app_link() {
return None;
}
Some(domain)
})
.filter(|domain| domain.is_app_link())
.collect::<Vec<_>>();
if deep_link_domains.is_empty() {
@@ -177,7 +171,7 @@ fn main() {
);
dict.insert(
"CFBundleURLName".into(),
format!("{}", domain.scheme[0]).into(),
domain.scheme[0].clone().into(),
);
plist::Value::Dictionary(dict)
})
@@ -1,5 +1,11 @@
# Changelog
## \[2.2.9]
### Dependencies
- Upgraded to `deep-link-js@2.4.6`
## \[2.2.8]
### Dependencies
+5 -5
View File
@@ -1,7 +1,7 @@
{
"name": "deep-link-example",
"private": true,
"version": "2.2.8",
"version": "2.2.9",
"type": "module",
"scripts": {
"dev": "vite",
@@ -10,12 +10,12 @@
"tauri": "tauri"
},
"dependencies": {
"@tauri-apps/api": "2.9.0",
"@tauri-apps/plugin-deep-link": "2.4.5"
"@tauri-apps/api": "^2.10.1",
"@tauri-apps/plugin-deep-link": "2.4.6"
},
"devDependencies": {
"@tauri-apps/cli": "2.9.4",
"@tauri-apps/cli": "2.10.0",
"typescript": "^5.7.3",
"vite": "^7.0.7"
"vite": "^7.3.1"
}
}
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-deep-link",
"version": "2.4.5",
"version": "2.4.6",
"description": "Set your Tauri application as the default handler for an URL",
"license": "MIT OR Apache-2.0",
"authors": [
@@ -25,9 +25,9 @@
"LICENSE"
],
"dependencies": {
"@tauri-apps/api": "^2.8.0"
"@tauri-apps/api": "^2.10.1"
},
"devDependencies": {
"@tauri-apps/cli": "2.9.4"
"@tauri-apps/cli": "2.10.0"
}
}
+16
View File
@@ -1,5 +1,21 @@
# Changelog
## \[2.6.0]
- [`d7a0bb32`](https://github.com/tauri-apps/plugins-workspace/commit/d7a0bb325dad919d6cc132eb3898c33540de77c4) ([#3136](https://github.com/tauri-apps/plugins-workspace/pull/3136) by [@onehumandev](https://github.com/tauri-apps/plugins-workspace/../../onehumandev)) Add `fileAccessMode` option to file picker.
## \[2.5.0]
- [`dff6fa98`](https://github.com/tauri-apps/plugins-workspace/commit/dff6fa986a9a05ba98b6ca660fea78ae97251fc2) ([#3034](https://github.com/tauri-apps/plugins-workspace/pull/3034) by [@onehumandev](https://github.com/tauri-apps/plugins-workspace/../../onehumandev)) Add `pickerMode` option to file picker (currently only used on iOS)
### Dependencies
- Upgraded to `fs-js@2.4.5`
### feat
- [`c23fa03f`](https://github.com/tauri-apps/plugins-workspace/commit/c23fa03f07d5c1c220bcf0bca482364513e3f754) ([#3098](https://github.com/tauri-apps/plugins-workspace/pull/3098) by [@Lepidopteran](https://github.com/tauri-apps/plugins-workspace/../../Lepidopteran)) Add `xdg-portal` as an optional feature for `rfd`
## \[2.4.2]
- [`93426f85`](https://github.com/tauri-apps/plugins-workspace/commit/93426f85120f49beb9f40222bff45185a32d54a9) Fixed an issue that caused docs.rs builds to fail. No user facing changes.
+4 -5
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-dialog"
version = "2.4.2"
version = "2.6.0"
description = "Native system dialogs for opening and saving files along with message dialogs on your Tauri application."
edition = { workspace = true }
authors = { workspace = true }
@@ -11,7 +11,7 @@ links = "tauri-plugin-dialog"
[features]
default = ["gtk3"]
xdg-portal = ["rfd/xdg-portal"]
xdg-portal = ["rfd/xdg-portal", "rfd/tokio", "rfd/wayland"]
gtk3 = ["rfd/gtk3"]
[package.metadata.docs.rs]
@@ -37,14 +37,13 @@ tauri = { workspace = true }
log = { workspace = true }
thiserror = { workspace = true }
url = { workspace = true }
tauri-plugin-fs = { path = "../fs", version = "2.4.4" }
tauri-plugin-fs = { path = "../fs", version = "2.4.5" }
[target.'cfg(target_os = "ios")'.dependencies]
tauri = { workspace = true, features = ["wry"] }
[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
rfd = { version = "0.15", default-features = false, features = [
"tokio",
rfd = { version = "0.16", default-features = false, features = [
"common-controls-v6",
] }
+35
View File
@@ -76,6 +76,31 @@ interface OpenDialogOptions {
* On desktop, this option is ignored.
*/
pickerMode?: PickerMode
/**
* The file access mode of the dialog.
* If not provided, `copy` is used, which matches the behavior of the {@linkcode open} method before the introduction of this option.
*
* **Usage**
* If a file is opened with {@linkcode fileAccessMode: 'copy'}, it will be copied to the app's sandbox.
* This means the file can be read, edited, deleted, copied, or any other operation without any issues, since the file
* now belongs to the app.
* This also means that the caller has responsibility of deleting the file if this file is not meant to be retained
* in the app sandbox.
*
* If a file is opened with {@linkcode fileAccessMode: 'scoped'}, the file will remain in its original location
* and security-scoped access will be automatically managed by the system.
*
* **Note**
* This is specifically meant for document pickers on iOS or MacOS, in conjunction with [security scoped resources](https://developer.apple.com/documentation/foundation/nsurl/startaccessingsecurityscopedresource()).
*
* Why only document pickers, and not image or video pickers?
* The image and video pickers on iOS behave differently from the document pickers, and return [NSItemProvider](https://developer.apple.com/documentation/foundation/nsitemprovider) objects instead of file URLs.
* These are meant to be ephemeral (only available within the callback of the picker), and are not accessible outside of the callback.
* So for image and video pickers, the only way to access the file is to copy it to the app's sandbox, and this is the URL that is returned from this API.
* This means there is no provision for using `scoped` mode with image or video pickers.
* If an image or video picker is used, `copy` is always used.
*/
fileAccessMode?: FileAccessMode
}
/**
@@ -111,6 +136,16 @@ interface SaveDialogOptions {
*/
export type PickerMode = 'document' | 'media' | 'image' | 'video'
/**
* The file access mode of the dialog.
*
* - `copy`: copy/move the picked file to the app sandbox; no scoped access required.
* - `scoped`: keep file in place; security-scoped access is automatically managed.
*
* **Note:** This option is only supported on iOS 14 and above. This parameter is ignored on iOS 13 and below.
*/
export type FileAccessMode = 'copy' | 'scoped'
/**
* Default buttons for a message dialog.
*
+26 -13
View File
@@ -34,6 +34,7 @@ struct FilePickerOptions: Decodable {
var filters: [Filter]?
var defaultPath: String?
var pickerMode: PickerMode?
var fileAccessMode: FileAccessMode?
}
struct SaveFileDialogOptions: Decodable {
@@ -41,6 +42,11 @@ struct SaveFileDialogOptions: Decodable {
var defaultPath: String?
}
enum FileAccessMode: String, Decodable {
case copy
case scoped
}
enum PickerMode: String, Decodable {
case document
case media
@@ -56,6 +62,7 @@ class DialogPlugin: Plugin {
override init() {
super.init()
filePickerController = FilePickerController(self)
}
@objc public func showFilePicker(_ invoke: Invoke) throws {
@@ -70,12 +77,13 @@ class DialogPlugin: Plugin {
case .error(let error):
invoke.reject(error)
}
}
}
if #available(iOS 14, *) {
let parsedTypes = parseFiltersOption(args.filters ?? [])
let mimeKinds = Set(parsedTypes.compactMap { $0.preferredMIMEType?.components(separatedBy: "/")[0] })
let mimeKinds = Set(
parsedTypes.compactMap { $0.preferredMIMEType?.components(separatedBy: "/")[0] })
let filtersIncludeImage = mimeKinds.contains("image")
let filtersIncludeVideo = mimeKinds.contains("video")
let filtersIncludeNonMedia = mimeKinds.contains(where: { $0 != "image" && $0 != "video" })
@@ -85,7 +93,8 @@ class DialogPlugin: Plugin {
if args.pickerMode == .media
|| args.pickerMode == .image
|| args.pickerMode == .video
|| (!filtersIncludeNonMedia && (filtersIncludeImage || filtersIncludeVideo)) {
|| (!filtersIncludeNonMedia && (filtersIncludeImage || filtersIncludeVideo))
{
DispatchQueue.main.async {
var configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
configuration.selectionLimit = (args.multiple ?? false) ? 0 : 1
@@ -107,8 +116,10 @@ class DialogPlugin: Plugin {
DispatchQueue.main.async {
// The UTType.item is the catch-all, allowing for any file type to be selected.
let contentTypes = parsedTypes.isEmpty ? [UTType.item] : parsedTypes
let picker: UIDocumentPickerViewController = UIDocumentPickerViewController(forOpeningContentTypes: contentTypes, asCopy: true)
let picker: UIDocumentPickerViewController = UIDocumentPickerViewController(
forOpeningContentTypes: contentTypes,
asCopy: args.fileAccessMode == .scoped ? false : true)
if let defaultPath = args.defaultPath {
picker.directoryURL = URL(string: defaultPath)
}
@@ -181,7 +192,7 @@ class DialogPlugin: Plugin {
}
}
}
return parsedTypes
}
@@ -203,14 +214,14 @@ class DialogPlugin: Plugin {
if !filtersIncludeNonMedia && (filtersIncludeImage || filtersIncludeVideo) {
DispatchQueue.main.async {
let picker = UIImagePickerController()
picker.delegate = self.filePickerController
picker.delegate = self.filePickerController
if filtersIncludeImage && !filtersIncludeVideo {
picker.sourceType = .photoLibrary
}
if filtersIncludeImage && !filtersIncludeVideo {
picker.sourceType = .photoLibrary
}
picker.modalPresentationStyle = .fullScreen
self.presentViewController(picker)
picker.modalPresentationStyle = .fullScreen
self.presentViewController(picker)
}
} else {
let documentTypes = parsedTypes.isEmpty ? ["public.data"] : parsedTypes
@@ -234,7 +245,8 @@ class DialogPlugin: Plugin {
for filter in filters {
for ext in filter.extensions ?? [] {
guard
let utType: String = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, ext as CFString, nil)?.takeRetainedValue() as String?
let utType: String = UTTypeCreatePreferredIdentifierForTag(
kUTTagClassMIMEType, ext as CFString, nil)?.takeRetainedValue() as String?
else {
continue
}
@@ -292,6 +304,7 @@ class DialogPlugin: Plugin {
manager.viewController?.present(alert, animated: true, completion: nil)
}
}
}
@_cdecl("init_plugin_dialog")
@@ -95,16 +95,33 @@ public class FilePickerController: NSObject {
return nil
}
}
/// ## In which cases do we need to save a copy of a file selected by a user to the app sandbox?
/// In short, only when the file is **not** selected using UIDocumentPickerDelegate.
/// For the rest of the cases, we need to write a copy of the file to the app sandbox.
///
/// For PHPicker (used for photos and videos), `NSItemProvider.loadFileRepresentation` returns a temporary file URL that is deleted after the completion handler.
/// The recommendation is to [Persist](https://developer.apple.com/documentation/foundation/nsitemprovider/2888338-loadfilerepresentation) the file by moving/copying
/// it to your apps directory within the completion handler.
///
/// If available, `loadInPlaceFileRepresentation` can open a file in place; Photos assets typically do not support true in-place access,
/// so fall back to persisting a local file.
/// Ref: https://developer.apple.com/documentation/foundation/nsitemprovider/2888335-loadinplacefilerepresentation
///
/// For UIDocumentPicker, prefer "open in place" and avoid copying when possible.
/// Ref: https://developer.apple.com/documentation/uikit/uidocumentpickerviewcontroller
private func saveTemporaryFile(_ sourceUrl: URL) throws -> URL {
var directory = URL(fileURLWithPath: NSTemporaryDirectory())
if let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first {
directory = cachesDirectory
}
let targetUrl = directory.appendingPathComponent(sourceUrl.lastPathComponent)
do {
try deleteFile(targetUrl)
}
try FileManager.default.copyItem(at: sourceUrl, to: targetUrl)
return targetUrl
}
@@ -119,8 +136,7 @@ public class FilePickerController: NSObject {
extension FilePickerController: UIDocumentPickerDelegate {
public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
do {
let temporaryUrls = try urls.map { try saveTemporaryFile($0) }
self.plugin.onFilePickerEvent(.selected(temporaryUrls))
self.plugin.onFilePickerEvent(.selected(urls))
} catch {
self.plugin.onFilePickerEvent(.error("Failed to create a temporary copy of the file"))
}
@@ -191,6 +207,8 @@ extension FilePickerController: PHPickerViewControllerDelegate {
return
}
do {
// We have to make a copy of the file to the app sandbox here, as PHPicker returns an NSItemProvider with either an ephemeral file URL or content that is deleted after the completion handler.
// This is a different behavior from UIDocumentPicker, where the file can either be copied to the app sandbox or opened in place, and then accessed with `startAccessingSecurityScopedResource`.
let temporaryUrl = try self.saveTemporaryFile(url)
temporaryUrls.append(temporaryUrl)
} catch {
@@ -212,6 +230,8 @@ extension FilePickerController: PHPickerViewControllerDelegate {
return
}
do {
// We have to make a copy of the file to the app sandbox here, as PHPicker returns an NSItemProvider with either an ephemeral file URL or content that is deleted after the completion handler.
// This is a different behavior from UIDocumentPicker, where the file can either be copied to the app sandbox or opened in place, and then accessed with `startAccessingSecurityScopedResource`.
let temporaryUrl = try self.saveTemporaryFile(url)
temporaryUrls.append(temporaryUrl)
} catch {
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-dialog",
"version": "2.4.2",
"version": "2.6.0",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
@@ -24,6 +24,6 @@
"LICENSE"
],
"dependencies": {
"@tauri-apps/api": "^2.8.0"
"@tauri-apps/api": "^2.10.1"
}
}
+10 -2
View File
@@ -9,8 +9,9 @@ use tauri::{command, Manager, Runtime, State, Window};
use tauri_plugin_fs::FsExt;
use crate::{
Dialog, FileDialogBuilder, FilePath, MessageDialogBuilder, MessageDialogButtons,
MessageDialogKind, MessageDialogResult, PickerMode, Result, CANCEL, NO, OK, YES,
Dialog, FileAccessMode, FileDialogBuilder, FilePath, MessageDialogBuilder,
MessageDialogButtons, MessageDialogKind, MessageDialogResult, PickerMode, Result, CANCEL, NO,
OK, YES,
};
#[derive(Serialize)]
@@ -63,6 +64,10 @@ pub struct OpenDialogOptions {
#[serde(default)]
#[cfg_attr(mobile, allow(dead_code))]
picker_mode: Option<PickerMode>,
/// The file access mode of the dialog.
#[serde(default)]
#[cfg_attr(mobile, allow(dead_code))]
file_access_mode: Option<FileAccessMode>,
}
/// The options for the save dialog API.
@@ -141,6 +146,9 @@ pub(crate) async fn open<R: Runtime>(
let extensions: Vec<&str> = filter.extensions.iter().map(|s| &**s).collect();
dialog_builder = dialog_builder.add_filter(filter.name, &extensions);
}
if let Some(file_access_mode) = options.file_access_mode {
dialog_builder = dialog_builder.set_file_access_mode(file_access_mode);
}
let res = if options.directory {
#[cfg(desktop)]
+20 -1
View File
@@ -53,6 +53,13 @@ pub enum PickerMode {
Video,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "lowercase")]
pub enum FileAccessMode {
Copy,
Scoped,
}
pub(crate) const OK: &str = "Ok";
pub(crate) const CANCEL: &str = "Cancel";
pub(crate) const YES: &str = "Yes";
@@ -191,7 +198,7 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
commands::save,
commands::message,
commands::ask,
commands::confirm
commands::confirm,
])
.setup(|app, api| {
#[cfg(mobile)]
@@ -379,6 +386,7 @@ pub struct FileDialogBuilder<R: Runtime> {
pub(crate) title: Option<String>,
pub(crate) can_create_directories: Option<bool>,
pub(crate) picker_mode: Option<PickerMode>,
pub(crate) file_access_mode: Option<FileAccessMode>,
#[cfg(desktop)]
pub(crate) parent: Option<crate::desktop::WindowHandle>,
}
@@ -391,6 +399,7 @@ pub(crate) struct FileDialogPayload<'a> {
filters: &'a Vec<Filter>,
multiple: bool,
picker_mode: &'a Option<PickerMode>,
file_access_mode: &'a Option<FileAccessMode>,
}
// raw window handle :(
@@ -407,6 +416,7 @@ impl<R: Runtime> FileDialogBuilder<R> {
title: None,
can_create_directories: None,
picker_mode: None,
file_access_mode: None,
#[cfg(desktop)]
parent: None,
}
@@ -419,6 +429,7 @@ impl<R: Runtime> FileDialogBuilder<R> {
filters: &self.filters,
multiple,
picker_mode: &self.picker_mode,
file_access_mode: &self.file_access_mode,
}
}
@@ -488,6 +499,14 @@ impl<R: Runtime> FileDialogBuilder<R> {
self
}
/// Set the file access mode of the dialog.
/// This is only used on iOS.
/// On desktop and Android, this option is ignored.
pub fn set_file_access_mode(mut self, mode: FileAccessMode) -> Self {
self.file_access_mode.replace(mode);
self
}
/// Shows the dialog to select a single file.
///
/// This is not a blocking operation,
+6
View File
@@ -1,5 +1,11 @@
# Changelog
## \[2.4.5]
- [`521cd8b3`](https://github.com/tauri-apps/plugins-workspace/commit/521cd8b372c862d96b1637775710e4d7cf2443e2) ([#3155](https://github.com/tauri-apps/plugins-workspace/pull/3155) by [@EliasStar](https://github.com/tauri-apps/plugins-workspace/../../EliasStar)) Fix off by one error in the implementation of readTextFileLines causing all lines to end with an (additional) null byte.
Issue: [#3154](https://github.com/tauri-apps/plugins-workspace/issues/3154)
PR: [#3155](https://github.com/tauri-apps/plugins-workspace/pull/3155)
## \[2.4.4]
- [`93426f85`](https://github.com/tauri-apps/plugins-workspace/commit/93426f85120f49beb9f40222bff45185a32d54a9) Fixed an issue that caused docs.rs builds to fail. No user facing changes.
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-fs"
version = "2.4.4"
version = "2.4.5"
description = "Access the file system."
authors = { workspace = true }
license = { workspace = true }
File diff suppressed because one or more lines are too long
+3 -1
View File
@@ -838,7 +838,9 @@ async function readTextFileLines(
return { value: null, done }
}
const line = new TextDecoder().decode(bytes.slice(0, bytes.byteLength))
const line = new TextDecoder().decode(
bytes.slice(0, bytes.byteLength - 1)
)
return {
value: line,
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-fs",
"version": "2.4.4",
"version": "2.4.5",
"description": "Access the file system.",
"license": "MIT OR Apache-2.0",
"authors": [
@@ -25,6 +25,6 @@
"LICENSE"
],
"dependencies": {
"@tauri-apps/api": "^2.8.0"
"@tauri-apps/api": "^2.10.1"
}
}
@@ -1,6 +1,6 @@
## Default Permission
This set of permissions describes what kind of
This set of permissions describes the what kind of
file system access the `fs` plugin has enabled or denied by default.
#### Granted Permissions
+1 -1
View File
@@ -2,7 +2,7 @@
[default]
description = """
This set of permissions describes what kind of
This set of permissions describes the what kind of
file system access the `fs` plugin has enabled or denied by default.
#### Granted Permissions
+12 -12
View File
@@ -1945,16 +1945,16 @@
"markdownDescription": "Denies the write_text_file command without any pre-configured scope."
},
{
"description": "This permissions allows to create the application specific directories.\r\n",
"description": "This permissions allows to create the application specific directories.\n",
"type": "string",
"const": "create-app-specific-dirs",
"markdownDescription": "This permissions allows to create the application specific directories.\r\n"
"markdownDescription": "This permissions allows to create the application specific directories.\n"
},
{
"description": "This set of permissions describes what kind of\r\nfile system access the `fs` plugin has enabled or denied by default.\r\n\r\n#### Granted Permissions\r\n\r\nThis default permission set enables read access to the\r\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\r\nAppLog) and all files and sub directories created in it.\r\nThe location of these directories depends on the operating system,\r\nwhere the application is run.\r\n\r\nIn general these directories need to be manually created\r\nby the application at runtime, before accessing files or folders\r\nin it is possible.\r\n\r\nTherefore, it is also allowed to create all of these folders via\r\nthe `mkdir` command.\r\n\r\n#### Denied Permissions\r\n\r\nThis default permission set prevents access to critical components\r\nof the Tauri application by default.\r\nOn Windows the webview data folder access is denied.\r\n\n#### This default permission set includes:\n\n- `create-app-specific-dirs`\n- `read-app-specific-dirs-recursive`\n- `deny-default`",
"description": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n#### This default permission set includes:\n\n- `create-app-specific-dirs`\n- `read-app-specific-dirs-recursive`\n- `deny-default`",
"type": "string",
"const": "default",
"markdownDescription": "This set of permissions describes what kind of\r\nfile system access the `fs` plugin has enabled or denied by default.\r\n\r\n#### Granted Permissions\r\n\r\nThis default permission set enables read access to the\r\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\r\nAppLog) and all files and sub directories created in it.\r\nThe location of these directories depends on the operating system,\r\nwhere the application is run.\r\n\r\nIn general these directories need to be manually created\r\nby the application at runtime, before accessing files or folders\r\nin it is possible.\r\n\r\nTherefore, it is also allowed to create all of these folders via\r\nthe `mkdir` command.\r\n\r\n#### Denied Permissions\r\n\r\nThis default permission set prevents access to critical components\r\nof the Tauri application by default.\r\nOn Windows the webview data folder access is denied.\r\n\n#### This default permission set includes:\n\n- `create-app-specific-dirs`\n- `read-app-specific-dirs-recursive`\n- `deny-default`"
"markdownDescription": "This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n#### This default permission set includes:\n\n- `create-app-specific-dirs`\n- `read-app-specific-dirs-recursive`\n- `deny-default`"
},
{
"description": "This denies access to dangerous Tauri relevant files and folders by default.\n#### This permission set includes:\n\n- `deny-webview-data-linux`\n- `deny-webview-data-windows`",
@@ -1963,16 +1963,16 @@
"markdownDescription": "This denies access to dangerous Tauri relevant files and folders by default.\n#### This permission set includes:\n\n- `deny-webview-data-linux`\n- `deny-webview-data-windows`"
},
{
"description": "This denies read access to the\r\n`$APPLOCALDATA` folder on linux as the webview data and configuration values are stored here.\r\nAllowing access can lead to sensitive information disclosure and should be well considered.",
"description": "This denies read access to the\n`$APPLOCALDATA` folder on linux as the webview data and configuration values are stored here.\nAllowing access can lead to sensitive information disclosure and should be well considered.",
"type": "string",
"const": "deny-webview-data-linux",
"markdownDescription": "This denies read access to the\r\n`$APPLOCALDATA` folder on linux as the webview data and configuration values are stored here.\r\nAllowing access can lead to sensitive information disclosure and should be well considered."
"markdownDescription": "This denies read access to the\n`$APPLOCALDATA` folder on linux as the webview data and configuration values are stored here.\nAllowing access can lead to sensitive information disclosure and should be well considered."
},
{
"description": "This denies read access to the\r\n`$APPLOCALDATA/EBWebView` folder on windows as the webview data and configuration values are stored here.\r\nAllowing access can lead to sensitive information disclosure and should be well considered.",
"description": "This denies read access to the\n`$APPLOCALDATA/EBWebView` folder on windows as the webview data and configuration values are stored here.\nAllowing access can lead to sensitive information disclosure and should be well considered.",
"type": "string",
"const": "deny-webview-data-windows",
"markdownDescription": "This denies read access to the\r\n`$APPLOCALDATA/EBWebView` folder on windows as the webview data and configuration values are stored here.\r\nAllowing access can lead to sensitive information disclosure and should be well considered."
"markdownDescription": "This denies read access to the\n`$APPLOCALDATA/EBWebView` folder on windows as the webview data and configuration values are stored here.\nAllowing access can lead to sensitive information disclosure and should be well considered."
},
{
"description": "This enables all read related commands without any pre-configured accessible paths.",
@@ -1981,10 +1981,10 @@
"markdownDescription": "This enables all read related commands without any pre-configured accessible paths."
},
{
"description": "This permission allows recursive read functionality on the application\r\nspecific base directories. \r\n",
"description": "This permission allows recursive read functionality on the application\nspecific base directories. \n",
"type": "string",
"const": "read-app-specific-dirs-recursive",
"markdownDescription": "This permission allows recursive read functionality on the application\r\nspecific base directories. \r\n"
"markdownDescription": "This permission allows recursive read functionality on the application\nspecific base directories. \n"
},
{
"description": "This enables directory read and file metadata related commands without any pre-configured accessible paths.",
@@ -2005,10 +2005,10 @@
"markdownDescription": "This enables all index or metadata related commands without any pre-configured accessible paths."
},
{
"description": "An empty permission you can use to modify the global scope.\r\n\r\n## Example\r\n\r\n```json\r\n{\r\n \"identifier\": \"read-documents\",\r\n \"windows\": [\"main\"],\r\n \"permissions\": [\r\n \"fs:allow-read\",\r\n {\r\n \"identifier\": \"fs:scope\",\r\n \"allow\": [\r\n \"$APPDATA/documents/**/*\"\r\n ],\r\n \"deny\": [\r\n \"$APPDATA/documents/secret.txt\"\r\n ]\r\n }\r\n ]\r\n}\r\n```\r\n",
"description": "An empty permission you can use to modify the global scope.\n\n## Example\n\n```json\n{\n \"identifier\": \"read-documents\",\n \"windows\": [\"main\"],\n \"permissions\": [\n \"fs:allow-read\",\n {\n \"identifier\": \"fs:scope\",\n \"allow\": [\n \"$APPDATA/documents/**/*\"\n ],\n \"deny\": [\n \"$APPDATA/documents/secret.txt\"\n ]\n }\n ]\n}\n```\n",
"type": "string",
"const": "scope",
"markdownDescription": "An empty permission you can use to modify the global scope.\r\n\r\n## Example\r\n\r\n```json\r\n{\r\n \"identifier\": \"read-documents\",\r\n \"windows\": [\"main\"],\r\n \"permissions\": [\r\n \"fs:allow-read\",\r\n {\r\n \"identifier\": \"fs:scope\",\r\n \"allow\": [\r\n \"$APPDATA/documents/**/*\"\r\n ],\r\n \"deny\": [\r\n \"$APPDATA/documents/secret.txt\"\r\n ]\r\n }\r\n ]\r\n}\r\n```\r\n"
"markdownDescription": "An empty permission you can use to modify the global scope.\n\n## Example\n\n```json\n{\n \"identifier\": \"read-documents\",\n \"windows\": [\"main\"],\n \"permissions\": [\n \"fs:allow-read\",\n {\n \"identifier\": \"fs:scope\",\n \"allow\": [\n \"$APPDATA/documents/**/*\"\n ],\n \"deny\": [\n \"$APPDATA/documents/secret.txt\"\n ]\n }\n ]\n}\n```\n"
},
{
"description": "This enables all write related commands without any pre-configured accessible paths.",
+1 -1
View File
@@ -24,6 +24,6 @@
"LICENSE"
],
"dependencies": {
"@tauri-apps/api": "^2.8.0"
"@tauri-apps/api": "^2.10.1"
}
}
+1 -1
View File
@@ -24,6 +24,6 @@
"LICENSE"
],
"dependencies": {
"@tauri-apps/api": "^2.8.0"
"@tauri-apps/api": "^2.10.1"
}
}
+1 -1
View File
@@ -24,6 +24,6 @@
"LICENSE"
],
"dependencies": {
"@tauri-apps/api": "^2.8.0"
"@tauri-apps/api": "^2.10.1"
}
}
+16
View File
@@ -1,5 +1,21 @@
# Changelog
## \[2.5.7]
- [`61e9b0ab`](https://github.com/tauri-apps/plugins-workspace/commit/61e9b0ab64c56cc5f7a5cb3b92b386671da6e0a2) ([#3228](https://github.com/tauri-apps/plugins-workspace/pull/3228)) Cleanup resource when the returned `ReadableStream.cancel` is called to avoid memory leaks
## \[2.5.6]
- [`b1dbee2c`](https://github.com/tauri-apps/plugins-workspace/commit/b1dbee2c55c1aa7b64732c4cc9f8cb20520b8666) ([#3210](https://github.com/tauri-apps/plugins-workspace/pull/3210) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Fixed an issue that caused the Origin header to always be `null` on macOS, iOS and Linux.
## \[2.5.5]
- [`e8915f17`](https://github.com/tauri-apps/plugins-workspace/commit/e8915f17e418138f0776870353cd6ce7254b0473) ([#2562](https://github.com/tauri-apps/plugins-workspace/pull/2562) by [@amrbashir](https://github.com/tauri-apps/plugins-workspace/../../amrbashir)) Fix aborting a request in the middle of a streaming response.
### Dependencies
- Upgraded to `fs-js@2.4.5`
## \[2.5.4]
- [`93426f85`](https://github.com/tauri-apps/plugins-workspace/commit/93426f85120f49beb9f40222bff45185a32d54a9) Fixed an issue that caused docs.rs builds to fail. No user facing changes.
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-http"
version = "2.5.4"
version = "2.5.7"
description = "Access an HTTP client written in Rust."
edition = { workspace = true }
authors = { workspace = true }
@@ -30,7 +30,7 @@ serde_json = { workspace = true }
tauri = { workspace = true }
thiserror = { workspace = true }
tokio = { version = "1", features = ["sync", "macros"] }
tauri-plugin-fs = { path = "../fs", version = "2.4.4" }
tauri-plugin-fs = { path = "../fs", version = "2.4.5" }
urlpattern = "0.3"
regex = "1"
http = "1"
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_HTTP__=function(e){"use strict";function t(e,t,r,n){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)}function r(e,t,r,n,s){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,r),r}var n,s,i,a;"function"==typeof SuppressedError&&SuppressedError;const o="__TAURI_TO_IPC_KEY__";class c{constructor(e){n.set(this,void 0),s.set(this,0),i.set(this,[]),a.set(this,void 0),r(this,n,e||(()=>{})),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((e=>{const o=e.index;if("end"in e)return void(o==t(this,s,"f")?this.cleanupCallback():r(this,a,o));const c=e.message;if(o==t(this,s,"f")){for(t(this,n,"f").call(this,c),r(this,s,t(this,s,"f")+1);t(this,s,"f")in t(this,i,"f");){const e=t(this,i,"f")[t(this,s,"f")];t(this,n,"f").call(this,e),delete t(this,i,"f")[t(this,s,"f")],r(this,s,t(this,s,"f")+1)}t(this,s,"f")===t(this,a,"f")&&this.cleanupCallback()}else t(this,i,"f")[o]=c}))}cleanupCallback(){window.__TAURI_INTERNALS__.unregisterCallback(this.id)}set onmessage(e){r(this,n,e)}get onmessage(){return t(this,n,"f")}[(n=new WeakMap,s=new WeakMap,i=new WeakMap,a=new WeakMap,o)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[o]()}}async function d(e,t={},r){return window.__TAURI_INTERNALS__.invoke(e,t,r)}const h="Request cancelled";return e.fetch=async function(e,t){const r=t?.signal;if(r?.aborted)throw new Error(h);const n=t?.maxRedirections,s=t?.connectTimeout,i=t?.proxy,a=t?.danger;t&&(delete t.maxRedirections,delete t.connectTimeout,delete t.proxy,delete t.danger);const o=t?.headers?t.headers instanceof Headers?t.headers:new Headers(t.headers):new Headers,f=new Request(e,t),l=await f.arrayBuffer(),u=0!==l.byteLength?Array.from(new Uint8Array(l)):null;for(const[e,t]of f.headers)o.get(e)||o.set(e,t);const _=(o instanceof Headers?Array.from(o.entries()):Array.isArray(o)?o:Object.entries(o)).map((([e,t])=>[e,"string"==typeof t?t:t.toString()]));if(r?.aborted)throw new Error(h);const w=await d("plugin:http|fetch",{clientConfig:{method:f.method,url:f.url,headers:_,data:u,maxRedirections:n,connectTimeout:s,proxy:i,danger:a}}),p=()=>d("plugin:http|fetch_cancel",{rid:w});if(r?.aborted)throw p(),new Error(h);r?.addEventListener("abort",(()=>{p()}));const{status:y,statusText:m,url:b,headers:T,rid:g}=await d("plugin:http|fetch_send",{rid:w}),A=[101,103,204,205,304].includes(y)?null:new ReadableStream({start:e=>{const t=new c;t.onmessage=t=>{if(r?.aborted)return void e.error(h);const n=new Uint8Array(t),s=n[n.byteLength-1],i=n.slice(0,n.byteLength-1);1!=s?e.enqueue(i):e.close()},d("plugin:http|fetch_read_body",{rid:g,streamChannel:t}).catch((t=>{e.error(t)}))}}),R=new Response(A,{status:y,statusText:m});return Object.defineProperty(R,"url",{value:b}),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 cancelled";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),l=await u.arrayBuffer(),_=0!==l.byteLength?Array.from(new Uint8Array(l)):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 f=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:f});if(a?.aborted)throw p(),new Error(r);a?.addEventListener("abort",(()=>{p()}));const{status:w,statusText:y,url:g,headers:b,rid:T}=await t("plugin:http|fetch_send",{rid:f}),R=()=>t("plugin:http|fetch_cancel_body",{rid:T}),m=[101,103,204,205,304].includes(w)?null:new ReadableStream({start:e=>{a?.addEventListener("abort",(()=>{e.error(r),R()}))},pull:e=>(async e=>{let r;try{r=await t("plugin:http|fetch_read_body",{rid:T})}catch(t){return e.error(t),void R()}const n=new Uint8Array(r),a=n[n.byteLength-1],o=n.slice(0,n.byteLength-1);1!==a?e.enqueue(o):e.close()})(e),cancel:()=>{R()}}),A=new Response(m,{status:w,statusText:y});return Object.defineProperty(A,"url",{value:g}),Object.defineProperty(A,"headers",{value:new Headers(b)}),A},e}({});Object.defineProperty(window.__TAURI__,"http",{value:__TAURI_PLUGIN_HTTP__})}
+7 -1
View File
@@ -6,7 +6,13 @@
#[allow(dead_code)]
mod scope;
const COMMANDS: &[&str] = &["fetch", "fetch_cancel", "fetch_send", "fetch_read_body"];
const COMMANDS: &[&str] = &[
"fetch",
"fetch_cancel",
"fetch_send",
"fetch_read_body",
"fetch_cancel_body",
];
/// HTTP scope entry.
#[derive(schemars::JsonSchema)]
+48 -32
View File
@@ -26,7 +26,7 @@
* @module
*/
import { Channel, invoke } from '@tauri-apps/api/core'
import { invoke } from '@tauri-apps/api/core'
/**
* Configuration of a proxy that a Client should pass requests to.
@@ -126,7 +126,7 @@ export async function fetch(
input: URL | Request | string,
init?: RequestInit & ClientOptions
): Promise<Response> {
// abort early here if needed
// Optimistically check for abort signal and avoid doing any work
const signal = init?.signal
if (signal?.aborted) {
throw new Error(ERROR_REQUEST_CANCELLED)
@@ -181,7 +181,7 @@ export async function fetch(
]
)
// abort early here if needed
// Optimistically check for abort signal and avoid doing any work on the Rust side
if (signal?.aborted) {
throw new Error(ERROR_REQUEST_CANCELLED)
}
@@ -201,7 +201,8 @@ export async function fetch(
const abort = () => invoke('plugin:http|fetch_cancel', { rid })
// abort early here if needed
// Optimistically check for abort signal
// and avoid doing any work after doing intial work on the Rust side
if (signal?.aborted) {
// we don't care about the result of this proimse
// eslint-disable-next-line @typescript-eslint/no-floating-promises
@@ -229,40 +230,55 @@ export async function fetch(
rid
})
const dropBody = () => {
return invoke('plugin:http|fetch_cancel_body', { rid: responseRid })
}
const readChunk = async (
controller: ReadableStreamDefaultController<Uint8Array>
) => {
let data: ArrayBuffer
try {
data = await invoke('plugin:http|fetch_read_body', {
rid: responseRid
})
} catch (e) {
// close the stream if an error occurs
// and drop the body on Rust side
controller.error(e)
void dropBody()
return
}
const dataUint8 = new Uint8Array(data)
const lastByte = dataUint8[dataUint8.byteLength - 1]
const actualData = dataUint8.slice(0, dataUint8.byteLength - 1)
// close when the signal to close (last byte is 1) is sent from the IPC.
if (lastByte === 1) {
controller.close()
return
}
controller.enqueue(actualData)
}
// no body for 101, 103, 204, 205 and 304
// see https://fetch.spec.whatwg.org/#null-body-status
const body = [101, 103, 204, 205, 304].includes(status)
? null
: new ReadableStream({
: new ReadableStream<Uint8Array>({
start: (controller) => {
const streamChannel = new Channel<ArrayBuffer | number[]>()
streamChannel.onmessage = (res: ArrayBuffer | number[]) => {
// close early if aborted
if (signal?.aborted) {
controller.error(ERROR_REQUEST_CANCELLED)
return
}
const resUint8 = new Uint8Array(res)
const lastByte = resUint8[resUint8.byteLength - 1]
const actualRes = resUint8.slice(0, resUint8.byteLength - 1)
// close when the signal to close (last byte is 1) is sent from the IPC.
if (lastByte == 1) {
controller.close()
return
}
controller.enqueue(actualRes)
}
// run a non-blocking body stream fetch
invoke('plugin:http|fetch_read_body', {
rid: responseRid,
streamChannel
}).catch((e) => {
controller.error(e)
// listen for abort events to cancel reading
signal?.addEventListener('abort', () => {
controller.error(ERROR_REQUEST_CANCELLED)
void dropBody()
})
},
pull: (controller) => readChunk(controller),
cancel: () => {
// Ensure body resources are released on stream cancellation
void dropBody()
}
})
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-http",
"version": "2.5.4",
"version": "2.5.7",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
@@ -24,6 +24,6 @@
"LICENSE"
],
"dependencies": {
"@tauri-apps/api": "^2.8.0"
"@tauri-apps/api": "^2.10.1"
}
}
@@ -0,0 +1,13 @@
# Automatically generated - DO NOT EDIT!
"$schema" = "../../schemas/schema.json"
[[permission]]
identifier = "allow-fetch-cancel-body"
description = "Enables the fetch_cancel_body command without any pre-configured scope."
commands.allow = ["fetch_cancel_body"]
[[permission]]
identifier = "deny-fetch-cancel-body"
description = "Denies the fetch_cancel_body command without any pre-configured scope."
commands.deny = ["fetch_cancel_body"]
@@ -15,8 +15,9 @@ All fetch operations are enabled.
- `allow-fetch`
- `allow-fetch-cancel`
- `allow-fetch-read-body`
- `allow-fetch-send`
- `allow-fetch-read-body`
- `allow-fetch-cancel-body`
## Permission Table
@@ -82,6 +83,32 @@ Denies the fetch_cancel command without any pre-configured scope.
<tr>
<td>
`http:allow-fetch-cancel-body`
</td>
<td>
Enables the fetch_cancel_body command without any pre-configured scope.
</td>
</tr>
<tr>
<td>
`http:deny-fetch-cancel-body`
</td>
<td>
Denies the fetch_cancel_body command without any pre-configured scope.
</td>
</tr>
<tr>
<td>
`http:allow-fetch-read-body`
</td>
+2 -1
View File
@@ -17,6 +17,7 @@ All fetch operations are enabled.
permissions = [
"allow-fetch",
"allow-fetch-cancel",
"allow-fetch-read-body",
"allow-fetch-send",
"allow-fetch-read-body",
"allow-fetch-cancel-body",
]
+14 -2
View File
@@ -318,6 +318,18 @@
"const": "deny-fetch-cancel",
"markdownDescription": "Denies the fetch_cancel command without any pre-configured scope."
},
{
"description": "Enables the fetch_cancel_body command without any pre-configured scope.",
"type": "string",
"const": "allow-fetch-cancel-body",
"markdownDescription": "Enables the fetch_cancel_body command without any pre-configured scope."
},
{
"description": "Denies the fetch_cancel_body command without any pre-configured scope.",
"type": "string",
"const": "deny-fetch-cancel-body",
"markdownDescription": "Denies the fetch_cancel_body command without any pre-configured scope."
},
{
"description": "Enables the fetch_read_body command without any pre-configured scope.",
"type": "string",
@@ -343,10 +355,10 @@
"markdownDescription": "Denies the fetch_send command without any pre-configured scope."
},
{
"description": "This permission set configures what kind of\r\nfetch operations are available from the http plugin.\r\n\r\nThis enables all fetch operations but does not\r\nallow explicitly any origins to be fetched. This needs to\r\nbe manually configured before usage.\r\n\r\n#### Granted Permissions\r\n\r\nAll fetch operations are enabled.\r\n\r\n\n#### This default permission set includes:\n\n- `allow-fetch`\n- `allow-fetch-cancel`\n- `allow-fetch-read-body`\n- `allow-fetch-send`",
"description": "This permission set configures what kind of\nfetch operations are available from the http plugin.\n\nThis enables all fetch operations but does not\nallow explicitly any origins to be fetched. This needs to\nbe manually configured before usage.\n\n#### Granted Permissions\n\nAll fetch operations are enabled.\n\n\n#### This default permission set includes:\n\n- `allow-fetch`\n- `allow-fetch-cancel`\n- `allow-fetch-send`\n- `allow-fetch-read-body`\n- `allow-fetch-cancel-body`",
"type": "string",
"const": "default",
"markdownDescription": "This permission set configures what kind of\r\nfetch operations are available from the http plugin.\r\n\r\nThis enables all fetch operations but does not\r\nallow explicitly any origins to be fetched. This needs to\r\nbe manually configured before usage.\r\n\r\n#### Granted Permissions\r\n\r\nAll fetch operations are enabled.\r\n\r\n\n#### This default permission set includes:\n\n- `allow-fetch`\n- `allow-fetch-cancel`\n- `allow-fetch-read-body`\n- `allow-fetch-send`"
"markdownDescription": "This permission set configures what kind of\nfetch operations are available from the http plugin.\n\nThis enables all fetch operations but does not\nallow explicitly any origins to be fetched. This needs to\nbe manually configured before usage.\n\n#### Granted Permissions\n\nAll fetch operations are enabled.\n\n\n#### This default permission set includes:\n\n- `allow-fetch`\n- `allow-fetch-cancel`\n- `allow-fetch-send`\n- `allow-fetch-read-body`\n- `allow-fetch-cancel-body`"
}
]
}
+39 -20
View File
@@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize};
use tauri::{
async_runtime::Mutex,
command,
ipc::{Channel, CommandScope, GlobalScope},
ipc::{CommandScope, GlobalScope},
Manager, ResourceId, ResourceTable, Runtime, State, Webview,
};
use tokio::sync::oneshot::{channel, Receiver, Sender};
@@ -279,7 +279,7 @@ pub async fn fetch<R: Runtime>(
if headers.contains_key(header::RANGE) {
// https://fetch.spec.whatwg.org/#http-network-or-cache-fetch step 18
// If httpRequests header list contains `Range`, then append (`Accept-Encoding`, `identity`)
// If httpRequest's header list contains `Range`, then append (`Accept-Encoding`, `identity`)
headers.append(header::ACCEPT_ENCODING, HeaderValue::from_str("identity")?);
}
@@ -290,10 +290,13 @@ pub async fn fetch<R: Runtime>(
// ensure we have an Origin header set
if cfg!(not(feature = "unsafe-headers")) || !headers.contains_key(header::ORIGIN) {
if let Ok(url) = webview.url() {
headers.append(
header::ORIGIN,
HeaderValue::from_str(&url.origin().ascii_serialization())?,
);
// The url crate returns OpaqueOrigin for tauri://localhost which serializes to "null"
let origin = if url.scheme() == "tauri" {
"tauri://localhost".to_string()
} else {
url.origin().ascii_serialization()
};
headers.append(header::ORIGIN, HeaderValue::from_str(&origin)?);
}
}
@@ -415,26 +418,42 @@ pub async fn fetch_send<R: Runtime>(
pub async fn fetch_read_body<R: Runtime>(
webview: Webview<R>,
rid: ResourceId,
stream_channel: Channel<tauri::ipc::InvokeResponseBody>,
) -> crate::Result<()> {
) -> crate::Result<tauri::ipc::Response> {
let res = {
let mut resources_table = webview.resources_table();
resources_table.take::<ReqwestResponse>(rid)?
let resources_table = webview.resources_table();
resources_table.get::<ReqwestResponse>(rid)?
};
let mut res = Arc::into_inner(res).unwrap().0;
// SAFETY: we can access the inner value mutably
// because we are the only ones with a reference to it
// and we don't want to use `Arc::into_inner` because we want to keep the value in the table
// for potential future calls to `fetch_cancel_body`
let res_ptr = Arc::as_ptr(&res) as *mut ReqwestResponse;
let res = unsafe { &mut *res_ptr };
let res = &mut res.0;
// send response through IPC channel
while let Some(chunk) = res.chunk().await? {
let mut chunk = chunk.to_vec();
// append 0 to indicate we are not done yet
chunk.push(0);
stream_channel.send(tauri::ipc::InvokeResponseBody::Raw(chunk))?;
}
let Some(chunk) = res.chunk().await? else {
let mut resources_table = webview.resources_table();
resources_table.close(rid)?;
// send 1 to indicate we are done
stream_channel.send(tauri::ipc::InvokeResponseBody::Raw(vec![1]))?;
// return a response with a single byte to indicate that the body is empty
return Ok(tauri::ipc::Response::new(vec![1]));
};
let mut chunk = chunk.to_vec();
// append a 0 byte to indicate that the body is not empty
chunk.push(0);
Ok(tauri::ipc::Response::new(chunk))
}
#[command]
pub async fn fetch_cancel_body<R: Runtime>(
webview: Webview<R>,
rid: ResourceId,
) -> crate::Result<()> {
let mut resources_table = webview.resources_table();
resources_table.close(rid)?;
Ok(())
}
+2 -1
View File
@@ -84,7 +84,8 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
commands::fetch,
commands::fetch_cancel,
commands::fetch_send,
commands::fetch_read_body
commands::fetch_read_body,
commands::fetch_cancel_body,
])
.build()
}
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.3.2]
- [`8bfa4450`](https://github.com/tauri-apps/plugins-workspace/commit/8bfa4450230d6a00f836bd27944c34cd7fe43e08) ([#3112](https://github.com/tauri-apps/plugins-workspace/pull/3112) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Disable caching on responses.
## \[2.3.1]
- [`93426f85`](https://github.com/tauri-apps/plugins-workspace/commit/93426f85120f49beb9f40222bff45185a32d54a9) Fixed an issue that caused docs.rs builds to fail. No user facing changes.
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-localhost"
version = "2.3.1"
version = "2.3.2"
description = "Expose your apps assets through a localhost server instead of the default custom protocol."
authors = { workspace = true }
license = { workspace = true }
+6
View File
@@ -1,5 +1,11 @@
# Changelog
## \[2.8.0]
- [`2a625adf`](https://github.com/tauri-apps/plugins-workspace/commit/2a625adff30238904035b86b6e2db7595597e857) ([#3065](https://github.com/tauri-apps/plugins-workspace/pull/3065) by [@BinaryMuse](https://github.com/tauri-apps/plugins-workspace/../../BinaryMuse)) Allow specifying a log formatter per target using the `format` method on `Target`.
- [`ae278ddf`](https://github.com/tauri-apps/plugins-workspace/commit/ae278ddf60203da183fe2266c06a5bdeb909285c) ([#3110](https://github.com/tauri-apps/plugins-workspace/pull/3110) by [@liuzhch1](https://github.com/tauri-apps/plugins-workspace/../../liuzhch1)) Fix log file rotation when exceeding `max_file_size`.
- [`6de61f85`](https://github.com/tauri-apps/plugins-workspace/commit/6de61f854bee0c1d39e4ce5890b12754b931c163) ([#3113](https://github.com/tauri-apps/plugins-workspace/pull/3113) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Remove log delays for iOS simulators that are no longer necessary.
## \[2.7.1]
- [`93426f85`](https://github.com/tauri-apps/plugins-workspace/commit/93426f85120f49beb9f40222bff45185a32d54a9) Fixed an issue that caused docs.rs builds to fail. No user facing changes.
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-log"
version = "2.7.1"
version = "2.8.0"
description = "Configurable logging for your Tauri app."
authors = { workspace = true }
license = { workspace = true }
-40
View File
@@ -7,48 +7,8 @@ import Tauri
import UIKit
import os.log
#if targetEnvironment(simulator)
var logReady = false
#else
var logReady = true
#endif
var pendingLogs: [(Int, NSString)] = []
var elapsedTime: TimeInterval = 0
var logFlushScheduled = false
@_cdecl("tauri_log")
func log(level: Int, message: NSString) {
if logReady {
os_log(level, message)
} else {
pendingLogs.append((level, message))
scheduleLogFlush()
}
}
// delay logging when the logger isn't immediately available
// in some cases when using the simulator the app would hang when calling os_log too soon
// better be safe here and wait a few seconds than actually freeze the app in dev mode
// in production this isn't a problem
func scheduleLogFlush() {
guard !logFlushScheduled else { return }
logFlushScheduled = true
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
logReady = true
flushLogs()
}
}
func flushLogs() {
for (level, message) in pendingLogs {
os_log(level, message)
}
pendingLogs.removeAll()
}
func os_log(_ level: Int, _ message: NSString) {
switch level {
case 1: Logger.debug(message as String)
case 2: Logger.info(message as String)
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-log",
"version": "2.7.1",
"version": "2.8.0",
"description": "Configurable logging for your Tauri app.",
"license": "MIT OR Apache-2.0",
"authors": [
@@ -25,6 +25,6 @@
"LICENSE"
],
"dependencies": {
"@tauri-apps/api": "^2.8.0"
"@tauri-apps/api": "^2.10.1"
}
}
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.3.4]
- [`b4348cee`](https://github.com/tauri-apps/plugins-workspace/commit/b4348cee926ee3d1db151bc831cdb9049bee717f) ([#3101](https://github.com/tauri-apps/plugins-workspace/pull/3101) by [@bclarke123](https://github.com/tauri-apps/plugins-workspace/../../bclarke123)) Update return value of `isAvailable` to match TypeScript function signature
## \[2.3.3]
- [`93426f85`](https://github.com/tauri-apps/plugins-workspace/commit/93426f85120f49beb9f40222bff45185a32d54a9) Fixed an issue that caused docs.rs builds to fail. No user facing changes.
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-nfc"
version = "2.3.3"
version = "2.3.4"
description = "Read and write NFC tags on Android and iOS."
edition = { workspace = true }
authors = { workspace = true }
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_NFC__=function(n){"use strict";async function e(n,e={},t){return window.__TAURI_INTERNALS__.invoke(n,e,t)}"function"==typeof SuppressedError&&SuppressedError;const t=[84],r=[85];var o,c;function a(n,e,t,r){return{format:n,kind:"string"==typeof e?Array.from((new TextEncoder).encode(e)):e,id:"string"==typeof t?Array.from((new TextEncoder).encode(t)):t,payload:"string"==typeof r?Array.from((new TextEncoder).encode(r)):r}}n.TechKind=void 0,(o=n.TechKind||(n.TechKind={}))[o.IsoDep=0]="IsoDep",o[o.MifareClassic=1]="MifareClassic",o[o.MifareUltralight=2]="MifareUltralight",o[o.Ndef=3]="Ndef",o[o.NdefFormatable=4]="NdefFormatable",o[o.NfcA=5]="NfcA",o[o.NfcB=6]="NfcB",o[o.NfcBarcode=7]="NfcBarcode",o[o.NfcF=8]="NfcF",o[o.NfcV=9]="NfcV",n.NFCTypeNameFormat=void 0,(c=n.NFCTypeNameFormat||(n.NFCTypeNameFormat={}))[c.Empty=0]="Empty",c[c.NfcWellKnown=1]="NfcWellKnown",c[c.Media=2]="Media",c[c.AbsoluteURI=3]="AbsoluteURI",c[c.NfcExternal=4]="NfcExternal",c[c.Unknown=5]="Unknown",c[c.Unchanged=6]="Unchanged";const i=["","http://www.","https://www.","http://","https://","tel:","mailto:","ftp://anonymous:anonymous@","ftp://ftp.","ftps://","sftp://","smb://","nfs://","ftp://","dav://","news:","telnet://","imap:","rtsp://","urn:","pop:","sip:","sips:","tftp:","btspp://","btl2cap://","btgoep://","tcpobex://","irdaobex://","file://","urn:epc:id:","urn:epc:tag:","urn:epc:pat:","urn:epc:raw:","urn:epc:","urn:nfc:"];function f(n){const{type:e,...t}=n;return{[e]:t}}return n.RTD_TEXT=t,n.RTD_URI=r,n.isAvailable=async function(){return await e("plugin:nfc|is_available")},n.record=a,n.scan=async function(n,t){return await e("plugin:nfc|scan",{kind:f(n),...t})},n.textRecord=function(e,r,o="en"){const c=Array.from((new TextEncoder).encode(o+e));return c.unshift(o.length),a(n.NFCTypeNameFormat.NfcWellKnown,t,r??[],c)},n.uriRecord=function(e,t){return a(n.NFCTypeNameFormat.NfcWellKnown,r,t??[],function(n){let e="";i.slice(1).forEach((function(t){0!==e.length&&"urn:"!==e||0!==n.indexOf(t)||(e=t)})),0===e.length&&(e="");const t=Array.from((new TextEncoder).encode(n.slice(e.length))),r=i.indexOf(e);return t.unshift(r),t}(e))},n.write=async function(n,t){const{kind:r,...o}=t??{};r&&(o.kind=f(r)),await e("plugin:nfc|write",{records:n,...o})},n}({});Object.defineProperty(window.__TAURI__,"nfc",{value:__TAURI_PLUGIN_NFC__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_NFC__=function(n){"use strict";async function e(n,e={},t){return window.__TAURI_INTERNALS__.invoke(n,e,t)}"function"==typeof SuppressedError&&SuppressedError;const t=[84],r=[85];var o,c;function a(n,e,t,r){return{format:n,kind:"string"==typeof e?Array.from((new TextEncoder).encode(e)):e,id:"string"==typeof t?Array.from((new TextEncoder).encode(t)):t,payload:"string"==typeof r?Array.from((new TextEncoder).encode(r)):r}}n.TechKind=void 0,(o=n.TechKind||(n.TechKind={}))[o.IsoDep=0]="IsoDep",o[o.MifareClassic=1]="MifareClassic",o[o.MifareUltralight=2]="MifareUltralight",o[o.Ndef=3]="Ndef",o[o.NdefFormatable=4]="NdefFormatable",o[o.NfcA=5]="NfcA",o[o.NfcB=6]="NfcB",o[o.NfcBarcode=7]="NfcBarcode",o[o.NfcF=8]="NfcF",o[o.NfcV=9]="NfcV",n.NFCTypeNameFormat=void 0,(c=n.NFCTypeNameFormat||(n.NFCTypeNameFormat={}))[c.Empty=0]="Empty",c[c.NfcWellKnown=1]="NfcWellKnown",c[c.Media=2]="Media",c[c.AbsoluteURI=3]="AbsoluteURI",c[c.NfcExternal=4]="NfcExternal",c[c.Unknown=5]="Unknown",c[c.Unchanged=6]="Unchanged";const i=["","http://www.","https://www.","http://","https://","tel:","mailto:","ftp://anonymous:anonymous@","ftp://ftp.","ftps://","sftp://","smb://","nfs://","ftp://","dav://","news:","telnet://","imap:","rtsp://","urn:","pop:","sip:","sips:","tftp:","btspp://","btl2cap://","btgoep://","tcpobex://","irdaobex://","file://","urn:epc:id:","urn:epc:tag:","urn:epc:pat:","urn:epc:raw:","urn:epc:","urn:nfc:"];function f(n){const{type:e,...t}=n;return{[e]:t}}return n.RTD_TEXT=t,n.RTD_URI=r,n.isAvailable=async function(){const{available:n}=await e("plugin:nfc|is_available");return n},n.record=a,n.scan=async function(n,t){return await e("plugin:nfc|scan",{kind:f(n),...t})},n.textRecord=function(e,r,o="en"){const c=Array.from((new TextEncoder).encode(o+e));return c.unshift(o.length),a(n.NFCTypeNameFormat.NfcWellKnown,t,r??[],c)},n.uriRecord=function(e,t){return a(n.NFCTypeNameFormat.NfcWellKnown,r,t??[],function(n){let e="";i.slice(1).forEach((function(t){0!==e.length&&"urn:"!==e||0!==n.indexOf(t)||(e=t)})),0===e.length&&(e="");const t=Array.from((new TextEncoder).encode(n.slice(e.length))),r=i.indexOf(e);return t.unshift(r),t}(e))},n.write=async function(n,t){const{kind:r,...o}=t??{};r&&(o.kind=f(r)),await e("plugin:nfc|write",{records:n,...o})},n}({});Object.defineProperty(window.__TAURI__,"nfc",{value:__TAURI_PLUGIN_NFC__})}
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-nfc",
"version": "2.3.3",
"version": "2.3.4",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
@@ -25,6 +25,6 @@
"LICENSE"
],
"dependencies": {
"@tauri-apps/api": "^2.8.0"
"@tauri-apps/api": "^2.10.1"
}
}
+2 -2
View File
@@ -331,10 +331,10 @@
"markdownDescription": "Denies the write command without any pre-configured scope."
},
{
"description": "This permission set configures what kind of\r\noperations are available from the nfc plugin.\r\n\r\n#### Granted Permissions\r\n\r\nChecking if the NFC functionality is available\r\nand scanning nearby tags is allowed.\r\nWriting to tags needs to be manually enabled.\r\n\r\n\n#### This default permission set includes:\n\n- `allow-is-available`\n- `allow-scan`",
"description": "This permission set configures what kind of\noperations are available from the nfc plugin.\n\n#### Granted Permissions\n\nChecking if the NFC functionality is available\nand scanning nearby tags is allowed.\nWriting to tags needs to be manually enabled.\n\n\n#### This default permission set includes:\n\n- `allow-is-available`\n- `allow-scan`",
"type": "string",
"const": "default",
"markdownDescription": "This permission set configures what kind of\r\noperations are available from the nfc plugin.\r\n\r\n#### Granted Permissions\r\n\r\nChecking if the NFC functionality is available\r\nand scanning nearby tags is allowed.\r\nWriting to tags needs to be manually enabled.\r\n\r\n\n#### This default permission set includes:\n\n- `allow-is-available`\n- `allow-scan`"
"markdownDescription": "This permission set configures what kind of\noperations are available from the nfc plugin.\n\n#### Granted Permissions\n\nChecking if the NFC functionality is available\nand scanning nearby tags is allowed.\nWriting to tags needs to be manually enabled.\n\n\n#### This default permission set includes:\n\n- `allow-is-available`\n- `allow-scan`"
}
]
}
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_NOTIFICATION__=function(i){"use strict";function n(i,n,t,e){if("function"==typeof n?i!==n||!e:!n.has(i))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===t?e:"a"===t?e.call(i):e?e.value:n.get(i)}function t(i,n,t,e,a){if("function"==typeof n||!n.has(i))throw new TypeError("Cannot write private member to an object whose class did not declare it");return n.set(i,t),t}var e,a,o,r;"function"==typeof SuppressedError&&SuppressedError;const s="__TAURI_TO_IPC_KEY__";class c{constructor(i){e.set(this,void 0),a.set(this,0),o.set(this,[]),r.set(this,void 0),t(this,e,i||(()=>{})),this.id=function(i,n=!1){return window.__TAURI_INTERNALS__.transformCallback(i,n)}((i=>{const s=i.index;if("end"in i)return void(s==n(this,a,"f")?this.cleanupCallback():t(this,r,s));const c=i.message;if(s==n(this,a,"f")){for(n(this,e,"f").call(this,c),t(this,a,n(this,a,"f")+1);n(this,a,"f")in n(this,o,"f");){const i=n(this,o,"f")[n(this,a,"f")];n(this,e,"f").call(this,i),delete n(this,o,"f")[n(this,a,"f")],t(this,a,n(this,a,"f")+1)}n(this,a,"f")===n(this,r,"f")&&this.cleanupCallback()}else n(this,o,"f")[s]=c}))}cleanupCallback(){window.__TAURI_INTERNALS__.unregisterCallback(this.id)}set onmessage(i){t(this,e,i)}get onmessage(){return n(this,e,"f")}[(e=new WeakMap,a=new WeakMap,o=new WeakMap,r=new WeakMap,s)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[s]()}}class l{constructor(i,n,t){this.plugin=i,this.event=n,this.channelId=t}async unregister(){return f(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}}async function u(i,n,t){const e=new c(t);try{return f(`plugin:${i}|register_listener`,{event:n,handler:e}).then((()=>new l(i,n,e.id)))}catch{return f(`plugin:${i}|registerListener`,{event:n,handler:e}).then((()=>new l(i,n,e.id)))}}async function f(i,n={},t){return window.__TAURI_INTERNALS__.invoke(i,n,t)}var h,d,w;i.ScheduleEvery=void 0,(h=i.ScheduleEvery||(i.ScheduleEvery={})).Year="year",h.Month="month",h.TwoWeeks="twoWeeks",h.Week="week",h.Day="day",h.Hour="hour",h.Minute="minute",h.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,n=!1,t=!1){return{at:{date:i,repeating:n,allowWhileIdle:t},interval:void 0,every:void 0}}static interval(i,n=!1){return{at:void 0,interval:{interval:i,allowWhileIdle:n},every:void 0}}static every(i,n,t=!1){return{at:void 0,interval:void 0,every:{interval:i,count:n,allowWhileIdle:t}}}},i.active=async function(){return await f("plugin:notification|get_active")},i.cancel=async function(i){await f("plugin:notification|cancel",{notifications:i})},i.cancelAll=async function(){await f("plugin:notification|cancel")},i.channels=async function(){return await f("plugin:notification|listChannels")},i.createChannel=async function(i){await f("plugin:notification|create_channel",{...i})},i.isPermissionGranted=async function(){return"default"!==window.Notification.permission?await Promise.resolve("granted"===window.Notification.permission):await f("plugin:notification|is_permission_granted")},i.onAction=async function(i){return await u("notification","actionPerformed",i)},i.onNotificationReceived=async function(i){return await u("notification","notification",i)},i.pending=async function(){return await f("plugin:notification|get_pending")},i.registerActionTypes=async function(i){await f("plugin:notification|register_action_types",{types:i})},i.removeActive=async function(i){await f("plugin:notification|remove_active",{notifications:i})},i.removeAllActive=async function(){await f("plugin:notification|remove_active")},i.removeChannel=async function(i){await f("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("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,r;"function"==typeof SuppressedError&&SuppressedError;const s="__TAURI_TO_IPC_KEY__";class c{constructor(i){e.set(this,void 0),a.set(this,0),o.set(this,[]),r.set(this,void 0),n(this,e,i||(()=>{})),this.id=function(i,t=!1){return window.__TAURI_INTERNALS__.transformCallback(i,t)}((i=>{const s=i.index;if("end"in i)return void(s==t(this,a,"f")?this.cleanupCallback():n(this,r,s));const c=i.message;if(s==t(this,a,"f")){for(t(this,e,"f").call(this,c),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)}t(this,a,"f")===t(this,r,"f")&&this.cleanupCallback()}else t(this,o,"f")[s]=c}))}cleanupCallback(){window.__TAURI_INTERNALS__.unregisterCallback(this.id)}set onmessage(i){n(this,e,i)}get onmessage(){return t(this,e,"f")}[(e=new WeakMap,a=new WeakMap,o=new WeakMap,r=new WeakMap,s)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[s]()}}class l{constructor(i,t,n){this.plugin=i,this.event=t,this.channelId=n}async unregister(){return f(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}}async function u(i,t,n){const e=new c(n);try{return await f(`plugin:${i}|register_listener`,{event:t,handler:e}),new l(i,t,e.id)}catch{return await f(`plugin:${i}|registerListener`,{event:t,handler:e}),new l(i,t,e.id)}}async function f(i,t={},n){return window.__TAURI_INTERNALS__.invoke(i,t,n)}var h,d,w;i.ScheduleEvery=void 0,(h=i.ScheduleEvery||(i.ScheduleEvery={})).Year="year",h.Month="month",h.TwoWeeks="twoWeeks",h.Week="week",h.Day="day",h.Hour="hour",h.Minute="minute",h.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 f("plugin:notification|get_active")},i.cancel=async function(i){await f("plugin:notification|cancel",{notifications:i})},i.cancelAll=async function(){await f("plugin:notification|cancel")},i.channels=async function(){return await f("plugin:notification|listChannels")},i.createChannel=async function(i){await f("plugin:notification|create_channel",{...i})},i.isPermissionGranted=async function(){return"default"!==window.Notification.permission?await Promise.resolve("granted"===window.Notification.permission):await f("plugin:notification|is_permission_granted")},i.onAction=async function(i){return await u("notification","actionPerformed",i)},i.onNotificationReceived=async function(i){return await u("notification","notification",i)},i.pending=async function(){return await f("plugin:notification|get_pending")},i.registerActionTypes=async function(i){await f("plugin:notification|register_action_types",{types:i})},i.removeActive=async function(i){await f("plugin:notification|remove_active",{notifications:i})},i.removeAllActive=async function(){await f("plugin:notification|remove_active")},i.removeChannel=async function(i){await f("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
@@ -24,6 +24,6 @@
"LICENSE"
],
"dependencies": {
"@tauri-apps/api": "^2.8.0"
"@tauri-apps/api": "^2.10.1"
}
}
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.5.3]
- [`3d0d2e04`](https://github.com/tauri-apps/plugins-workspace/commit/3d0d2e041bbad9766aebecaeba291a28d8d7bf5c) ([#3163](https://github.com/tauri-apps/plugins-workspace/pull/3163) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Properly ignore `with: inAppBrowser` on desktop. This prevents an issue were `open_url` seamingly did nothing on desktop.
## \[2.5.2]
- [`93426f85`](https://github.com/tauri-apps/plugins-workspace/commit/93426f85120f49beb9f40222bff45185a32d54a9) Fixed an issue that caused docs.rs builds to fail. No user facing changes.
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-opener"
version = "2.5.2"
version = "2.5.3"
description = "Open files and URLs using their default application."
edition = { workspace = true }
authors = { workspace = true }
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-opener",
"version": "2.5.2",
"version": "2.5.3",
"description": "Open files and URLs using their default application.",
"license": "MIT OR Apache-2.0",
"authors": [
@@ -25,6 +25,6 @@
"LICENSE"
],
"dependencies": {
"@tauri-apps/api": "^2.8.0"
"@tauri-apps/api": "^2.10.1"
}
}

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