Compare commits

..

2 Commits

Author SHA1 Message Date
FabianLars 15fc071773 add corenfc framework 2025-08-11 22:21:03 +02:00
FabianLars 73c6047b78 fix(nfc): use xcode project instead of swift package 2025-08-11 22:08:58 +02:00
316 changed files with 9689 additions and 7871 deletions
+8 -2
View File
@@ -1,5 +1,11 @@
[advisories]
ignore = [
# time crate can't be updated in the repo because of MSRV, users are unaffected
"RUSTSEC-2026-0009",
# time 0.1
"RUSTSEC-2020-0071",
# needs sqlx 0.7 (still in alpha)
"RUSTSEC-2022-0090",
# wry needs kuchiki on Android
"RUSTSEC-2023-0019",
# atty is only used when the `colored` feature is enabled on tauri-plugin-log
"RUSTSEC-2021-0145",
]
@@ -1,6 +0,0 @@
---
"sql": minor
"sql-js": minor
---
Add support for Postgres `NUMERIC` and custom data types.
-6
View File
@@ -1,6 +0,0 @@
---
"fs": minor
"fs-js": minor
---
Add `encoding` option for `readTextFile` and `readTextFileLines`
-6
View File
@@ -1,6 +0,0 @@
---
"http": patch
"http-js": patch
---
Correct Response header initialization to support cloning and ensure Set-Cookie visibility.
-6
View File
@@ -1,6 +0,0 @@
---
"updater": patch
"updater-js": patch
---
fix: preserve file extension of updater package, otherwise users may get confused when presented with a sudo dialog suggesting to install a file with the extension `.rpm` using `dpkg -i`
+6
View File
@@ -0,0 +1,6 @@
---
fs: patch
fs-js: patch
---
Fixed calling `writeFile` with `data: ReadableStream` throws `Invalid argument`
+6
View File
@@ -0,0 +1,6 @@
---
nfc: patch
nfc-js: patch
---
On iOS, the reader session will now get closed properly on errors, preventing dangling invalid sessions that could prevent subsequent write attempts.
+6
View File
@@ -0,0 +1,6 @@
---
"opener": 'minor:enhance'
"opener-js": 'minor:enhance'
---
Allow reveal multiple items in the file explorer.
@@ -1,6 +0,0 @@
---
"dialog": minor
"dialog-js": minor
---
Re-use `message` command in Rust side for `ask` and `confirm` commands, `allow-ask` and `allow-confirm` permissions are now aliases to `allow-message`
-6
View File
@@ -1,6 +0,0 @@
---
"fs": minor
"fs-js": minor
---
Enable access for security-scoped resources on iOS by automatically calling `NSURL::startAccessingSecurityScopedResource` on resource access and adding the `stopAccessingSecurityScopedResource` API.
+6
View File
@@ -0,0 +1,6 @@
---
store: minor
store-js: minor
---
Allow setting defaults from the JavaScript API
+6
View File
@@ -0,0 +1,6 @@
---
store: minor
store-js: minor
---
Add an new option `overrideDefaults` for creating/loading and reloading the store that overrides the store with the on-disk state, ignoring defaults
-6
View File
@@ -1,6 +0,0 @@
---
"deep-link": patch
"deep-link-js": patch
---
Validate Android new intent is actually a deep link before triggering the onOpenUrl event.
-63
View File
@@ -1,63 +0,0 @@
# 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
@@ -1,12 +0,0 @@
# 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
@@ -1,5 +0,0 @@
---
name: 📚 Docs Report
about: Create a report to help us improve the docs
labels: 'type: documentation'
---
@@ -1,46 +0,0 @@
# 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.
+1 -1
View File
@@ -34,7 +34,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: rustsec/audit-check@v2
- uses: rustsec/audit-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
# https://github.com/tauri-apps/plugins-workspace/issues/774
@@ -11,7 +11,7 @@ on:
- v2
permissions:
# required for oidc token
# required for npm provenance
id-token: write
# required to create the GitHub Release
contents: write
@@ -62,6 +62,7 @@ jobs:
id: covector
env:
CARGO_TARGET_DIR: /mnt/target
NODE_AUTH_TOKEN: ${{ secrets.ORG_NPM_TOKEN }}
with:
token: ${{ secrets.GITHUB_TOKEN }}
command: 'version-or-publish'
-1
View File
@@ -5,7 +5,6 @@
name: integration tests
on:
workflow_dispatch:
push:
branches:
- v1
-1
View File
@@ -154,5 +154,4 @@ jobs:
run: cargo clippy --package ${{ matrix.package }} --all-targets -- -D warnings
- name: clippy ${{ matrix.package }} --all-features
if: matrix.package != 'tauri-plugin-dialog'
run: cargo clippy --package ${{ matrix.package }} --all-targets --all-features -- -D warnings
+2 -2
View File
@@ -246,9 +246,9 @@ 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-dialog' }}
if: matrix.package != 'tauri-plugin-http'
run: ${{ matrix.platform.runner }} ${{ matrix.platform.command }} --package ${{ matrix.package }} --target ${{ matrix.platform.target }} --all-targets --all-features
- name: test ${{ matrix.package }}
if: ${{ matrix.package == 'tauri-plugin-http' || matrix.package == 'tauri-plugin-dialog' }}
if: matrix.package == 'tauri-plugin-http'
run: ${{ matrix.platform.runner }} ${{ matrix.platform.command }} --package ${{ matrix.package }} --target ${{ matrix.platform.target }} --all-targets
+1 -2
View File
@@ -21,7 +21,6 @@ target/
package-lock.json
yarn.lock
bun.lockb
bun.lock
# rust compiled folders
target/
@@ -59,4 +58,4 @@ pids
.idea
debug.log
TODO.md
.aider.*
.aider*
Generated
+287 -841
View File
File diff suppressed because it is too large Load Diff
+5 -13
View File
@@ -12,16 +12,14 @@ resolver = "2"
serde = { version = "1", features = ["derive"] }
tracing = "0.1"
log = "0.4"
tauri = { version = "2.10", default-features = false }
tauri-runtime-wry = "2"
tauri-runtime-cef = { git = "https://github.com/tauri-apps/tauri.git", branch = "refactor/runtime-feature-flag" }
tauri-build = "2.5"
tauri-plugin = "2.5"
tauri-utils = "2.8"
tauri = { version = "2.6", default-features = false }
tauri-build = "2.3"
tauri-plugin = "2.3"
tauri-utils = "2.5"
serde_json = "1"
thiserror = "2"
url = "2"
schemars = "1"
schemars = "0.8"
dunce = "1"
specta = "^2.0.0-rc.16"
glob = "0.3"
@@ -41,9 +39,3 @@ codegen-units = 1
lto = true
incremental = false
opt-level = "s"
[patch.crates-io]
tauri = { git = "https://github.com/tauri-apps/tauri.git", branch = "refactor/runtime-feature-flag" }
tauri-utils = { git = "https://github.com/tauri-apps/tauri.git", branch = "refactor/runtime-feature-flag" }
tauri-plugin = { git = "https://github.com/tauri-apps/tauri.git", branch = "refactor/runtime-feature-flag" }
tauri-runtime-wry = { git = "https://github.com/tauri-apps/tauri.git", branch = "refactor/runtime-feature-flag" }
+1 -2
View File
@@ -3,12 +3,11 @@
// SPDX-License-Identifier: MIT
import eslint from '@eslint/js'
import { defineConfig } from 'eslint/config'
import eslintConfigPrettier from 'eslint-config-prettier'
import eslintPluginSecurity from 'eslint-plugin-security'
import tseslint from 'typescript-eslint'
export default defineConfig(
export default tseslint.config(
{
ignores: [
'**/target',
-97
View File
@@ -1,102 +1,5 @@
# 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
- Upgraded to `barcode-scanner-js@2.4.2`
- Upgraded to `biometric-js@2.3.2`
- Upgraded to `cli-js@2.4.1`
- Upgraded to `clipboard-manager-js@2.3.2`
- Upgraded to `dialog-js@2.4.2`
- Upgraded to `fs-js@2.4.4`
- Upgraded to `global-shortcut-js@2.3.1`
- Upgraded to `http-js@2.5.4`
- Upgraded to `log-js@2.7.1`
- Upgraded to `nfc-js@2.3.3`
- Upgraded to `notification-js@2.3.3`
- Upgraded to `opener-js@2.5.2`
- Upgraded to `os-js@2.3.2`
- Upgraded to `process-js@2.3.1`
- Upgraded to `shell-js@2.3.3`
- Upgraded to `store-js@2.4.1`
## \[2.0.33]
### Dependencies
- Upgraded to `barcode-scanner-js@2.4.1`
- Upgraded to `biometric-js@2.3.1`
- Upgraded to `clipboard-manager-js@2.3.1`
- Upgraded to `dialog-js@2.4.1`
- Upgraded to `fs-js@2.4.3`
- Upgraded to `nfc-js@2.3.2`
- Upgraded to `notification-js@2.3.2`
- Upgraded to `opener-js@2.5.1`
- Upgraded to `shell-js@2.3.2`
- Upgraded to `http-js@2.5.3`
## \[2.0.32]
### Dependencies
- Upgraded to `dialog-js@2.4.0`
- Upgraded to `log-js@2.7.0`
## \[2.0.31]
### Dependencies
- Upgraded to `shell-js@2.3.1`
## \[2.0.30]
### Dependencies
- Upgraded to `notification-js@2.3.1`
## \[2.0.29]
### Dependencies
- Upgraded to `fs-js@2.4.2`
- Upgraded to `nfc-js@2.3.1`
- Upgraded to `opener-js@2.5.0`
- Upgraded to `os-js@2.3.1`
- Upgraded to `store-js@2.4.0`
- Upgraded to `dialog-js@2.3.3`
- Upgraded to `http-js@2.5.2`
## \[2.0.28]
### Dependencies
+1 -1
View File
@@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, viewport-fit=cover, user-scalable=0"
content="width=device-width, initial-scale=1.0, viewport-fit=cover"
/>
<title>Svelte + Vite App</title>
</head>
+20 -20
View File
@@ -1,7 +1,7 @@
{
"name": "api",
"private": true,
"version": "2.0.37",
"version": "2.0.28",
"type": "module",
"scripts": {
"dev": "vite --clearScreen false",
@@ -10,25 +10,25 @@
"tauri": "tauri"
},
"dependencies": {
"@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.6.0",
"@tauri-apps/plugin-fs": "^2.4.5",
"@tauri-apps/api": "2.7.0",
"@tauri-apps/plugin-barcode-scanner": "^2.4.0",
"@tauri-apps/plugin-biometric": "^2.3.0",
"@tauri-apps/plugin-cli": "^2.4.0",
"@tauri-apps/plugin-clipboard-manager": "^2.3.0",
"@tauri-apps/plugin-dialog": "^2.3.2",
"@tauri-apps/plugin-fs": "^2.4.1",
"@tauri-apps/plugin-geolocation": "^2.2.0",
"@tauri-apps/plugin-global-shortcut": "^2.3.1",
"@tauri-apps/plugin-global-shortcut": "^2.3.0",
"@tauri-apps/plugin-haptics": "^2.2.0",
"@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.3",
"@tauri-apps/plugin-os": "^2.3.2",
"@tauri-apps/plugin-process": "^2.3.1",
"@tauri-apps/plugin-shell": "^2.3.5",
"@tauri-apps/plugin-store": "^2.4.2",
"@tauri-apps/plugin-updater": "^2.10.0",
"@tauri-apps/plugin-http": "^2.5.1",
"@tauri-apps/plugin-nfc": "^2.3.0",
"@tauri-apps/plugin-notification": "^2.3.0",
"@tauri-apps/plugin-opener": "^2.4.0",
"@tauri-apps/plugin-os": "^2.3.0",
"@tauri-apps/plugin-process": "^2.3.0",
"@tauri-apps/plugin-shell": "^2.3.0",
"@tauri-apps/plugin-store": "^2.3.0",
"@tauri-apps/plugin-updater": "^2.9.0",
"@tauri-apps/plugin-upload": "^2.3.0",
"@zerodevx/svelte-json-view": "1.0.11"
},
@@ -36,10 +36,10 @@
"@iconify-json/codicon": "^1.2.12",
"@iconify-json/ph": "^1.2.2",
"@sveltejs/vite-plugin-svelte": "^6.0.0",
"@tauri-apps/cli": "2.10.1",
"@tauri-apps/cli": "2.7.1",
"@unocss/extractor-svelte": "^66.3.3",
"svelte": "^5.20.4",
"unocss": "^66.3.3",
"vite": "^7.0.7"
"vite": "^7.0.4"
}
}
-101
View File
@@ -1,106 +1,5 @@
# 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
- Upgraded to `barcode-scanner@2.4.2`
- Upgraded to `biometric@2.3.2`
- Upgraded to `cli@2.4.1`
- Upgraded to `clipboard-manager@2.3.2`
- Upgraded to `dialog@2.4.2`
- Upgraded to `fs@2.4.4`
- Upgraded to `geolocation@2.3.2`
- Upgraded to `global-shortcut@2.3.1`
- Upgraded to `haptics@2.3.2`
- Upgraded to `http@2.5.4`
- Upgraded to `log@2.7.1`
- Upgraded to `nfc@2.3.3`
- Upgraded to `notification@2.3.3`
- Upgraded to `opener@2.5.2`
- Upgraded to `os@2.3.2`
- Upgraded to `process@2.3.1`
- Upgraded to `shell@2.3.3`
- Upgraded to `store@2.4.1`
## \[2.0.37]
### Dependencies
- Upgraded to `barcode-scanner@2.4.1`
- Upgraded to `biometric@2.3.1`
- Upgraded to `clipboard-manager@2.3.1`
- Upgraded to `dialog@2.4.1`
- Upgraded to `fs@2.4.3`
- Upgraded to `geolocation@2.3.1`
- Upgraded to `haptics@2.3.1`
- Upgraded to `nfc@2.3.2`
- Upgraded to `notification@2.3.2`
- Upgraded to `opener@2.5.1`
- Upgraded to `shell@2.3.2`
- Upgraded to `http@2.5.3`
## \[2.0.36]
### Dependencies
- Upgraded to `dialog@2.4.0`
- Upgraded to `log@2.7.0`
## \[2.0.35]
### Dependencies
- Upgraded to `shell@2.3.1`
## \[2.0.34]
### Dependencies
- Upgraded to `notification@2.3.1`
## \[2.0.33]
### Dependencies
- Upgraded to `fs@2.4.2`
- Upgraded to `nfc@2.3.1`
- Upgraded to `opener@2.5.0`
- Upgraded to `os@2.3.1`
- Upgraded to `store@2.4.0`
- Upgraded to `dialog@2.3.3`
- Upgraded to `http@2.5.2`
## \[2.0.32]
### Dependencies
+23 -27
View File
@@ -1,7 +1,7 @@
[package]
name = "api"
publish = false
version = "2.0.41"
version = "2.0.32"
description = "An example Tauri Application showcasing the api"
edition = "2021"
rust-version = { workspace = true }
@@ -20,33 +20,32 @@ serde = { workspace = true }
tiny_http = "0.12"
time = "0.3"
log = { workspace = true }
tauri-plugin-log = { path = "../../../plugins/log", version = "2.8.0" }
tauri-plugin-fs = { path = "../../../plugins/fs", version = "2.4.5", features = [
tauri-plugin-log = { path = "../../../plugins/log", version = "2.6.0" }
tauri-plugin-fs = { path = "../../../plugins/fs", version = "2.4.1", features = [
"watch",
] }
tauri-plugin-clipboard-manager = { path = "../../../plugins/clipboard-manager", version = "2.3.2" }
tauri-plugin-dialog = { path = "../../../plugins/dialog", version = "2.6.0" }
tauri-plugin-clipboard-manager = { path = "../../../plugins/clipboard-manager", version = "2.3.0" }
tauri-plugin-dialog = { path = "../../../plugins/dialog", version = "2.3.2" }
tauri-plugin-http = { path = "../../../plugins/http", features = [
"multipart",
"cookies",
], version = "2.5.7" }
tauri-plugin-notification = { path = "../../../plugins/notification", version = "2.3.3", features = [
], version = "2.5.1" }
tauri-plugin-notification = { path = "../../../plugins/notification", version = "2.3.0", 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.3" }
tauri-plugin-shell = { path = "../../../plugins/shell", version = "2.3.5" }
tauri-plugin-store = { path = "../../../plugins/store", version = "2.4.2" }
tauri-plugin-os = { path = "../../../plugins/os", version = "2.3.0" }
tauri-plugin-process = { path = "../../../plugins/process", version = "2.3.0" }
tauri-plugin-opener = { path = "../../../plugins/opener", version = "2.4.0" }
tauri-plugin-shell = { path = "../../../plugins/shell", version = "2.3.0" }
tauri-plugin-store = { path = "../../../plugins/store", version = "2.3.0" }
tauri-plugin-upload = { path = "../../../plugins/upload", version = "2.3.0" }
tauri-runtime-wry = { workspace = true, optional = true, features = [
"macos-private-api",
] }
tauri-runtime-cef = { workspace = true, optional = true }
[dependencies.tauri]
workspace = true
features = [
"wry",
"common-controls-v6",
"x11",
"image-ico",
"image-png",
"isolation",
@@ -56,20 +55,17 @@ features = [
]
[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
tauri-plugin-cli = { path = "../../../plugins/cli", version = "2.4.1" }
tauri-plugin-global-shortcut = { path = "../../../plugins/global-shortcut", version = "2.3.1" }
tauri-plugin-updater = { path = "../../../plugins/updater", version = "2.10.0" }
tauri-plugin-cli = { path = "../../../plugins/cli", version = "2.4.0" }
tauri-plugin-global-shortcut = { path = "../../../plugins/global-shortcut", version = "2.3.0" }
tauri-plugin-updater = { path = "../../../plugins/updater", version = "2.9.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.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" }
tauri-plugin-barcode-scanner = { path = "../../../plugins/barcode-scanner/", version = "2.4.0" }
tauri-plugin-nfc = { path = "../../../plugins/nfc", version = "2.3.0" }
tauri-plugin-biometric = { path = "../../../plugins/biometric/", version = "2.3.0" }
tauri-plugin-geolocation = { path = "../../../plugins/geolocation/", version = "2.3.0" }
tauri-plugin-haptics = { path = "../../../plugins/haptics/", version = "2.3.0" }
[features]
default = ["wry"]
wry = ["dep:tauri-runtime-wry"]
cef = ["dep:tauri-runtime-cef"]
prod = ["tauri/custom-protocol"]
@@ -23,7 +23,11 @@
"core:window:allow-start-dragging",
"notification:default",
"os:allow-platform",
"dialog:default",
"dialog:allow-open",
"dialog:allow-ask",
"dialog:allow-save",
"dialog:allow-confirm",
"dialog:allow-message",
{
"identifier": "shell:allow-spawn",
"allow": [
@@ -64,9 +68,6 @@
"fs:allow-rename",
"fs:allow-mkdir",
"fs:allow-remove",
"fs:allow-stat",
"fs:allow-fstat",
"fs:allow-lstat",
"fs:allow-write-text-file",
"fs:read-meta",
"fs:scope-download-recursive",
@@ -74,9 +75,6 @@
{
"identifier": "fs:scope-appdata-recursive",
"allow": [
{
"path": "$APPDATA/db/"
},
{
"path": "$APPDATA/db/**"
}
@@ -14,13 +14,13 @@ val tauriProperties = Properties().apply {
}
android {
compileSdk = 36
compileSdk = 34
namespace = "com.tauri.api"
defaultConfig {
manifestPlaceholders["usesCleartextTraffic"] = "false"
applicationId = "com.tauri.api"
minSdk = 24
targetSdk = 36
targetSdk = 34
versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt()
versionName = tauriProperties.getProperty("tauri.android.versionName", "1.0")
}
@@ -4,7 +4,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:8.11.0")
classpath("com.android.tools.build:gradle:8.5.1")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.25")
}
}
@@ -18,6 +18,6 @@ repositories {
dependencies {
compileOnly(gradleApi())
implementation("com.android.tools.build:gradle:8.11.0")
implementation("com.android.tools.build:gradle:8.5.1")
}
+3 -8
View File
@@ -6,11 +6,6 @@ mod cmd;
#[cfg(desktop)]
mod tray;
#[cfg(feature = "cef")]
type TauriRuntime = tauri_runtime_cef::CefRuntime<tauri::EventLoopMessage>;
#[cfg(feature = "wry")]
type TauriRuntime = tauri_runtime_wry::Wry<tauri::EventLoopMessage>;
use serde::Serialize;
use tauri::{
webview::{PageLoadEvent, WebviewWindowBuilder},
@@ -22,13 +17,13 @@ struct Reply {
data: String,
}
pub type SetupHook<R> = Box<dyn FnOnce(&mut App<R>) -> Result<(), Box<dyn std::error::Error>> + Send>;
pub type OnEvent<R> = Box<dyn FnMut(&AppHandle<R>, RunEvent)>;
pub type SetupHook = Box<dyn FnOnce(&mut App) -> Result<(), Box<dyn std::error::Error>> + Send>;
pub type OnEvent = Box<dyn FnMut(&AppHandle, RunEvent)>;
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
#[allow(unused_mut)]
let mut builder = tauri::Builder::<TauriRuntime>::new()
let mut builder = tauri::Builder::default()
.plugin(
tauri_plugin_log::Builder::default()
.level(log::LevelFilter::Info)
+56 -94
View File
@@ -8,8 +8,6 @@
let filter = null;
let multiple = false;
let directory = false;
let pickerMode = "document";
let fileAccessMode = "scoped";
function arrayBufferToBase64(buffer, callback) {
var blob = new Blob([buffer], {
@@ -43,70 +41,56 @@
}
async function msg() {
await message("Tauri is awesome!").then((res) => onMessage(res));
await message("Tauri is awesome!");
}
async function msgCustom(result) {
const buttons = { yes: "awesome", no: "amazing", cancel: "stunning" };
await message(`Tauri is: `, { buttons })
.then((res) => onMessage(`Tauri is ${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,
})
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>');
}
);
function openDialog() {
open({
title: "My wonderful open dialog",
defaultPath,
filters: filter
? [
{
name: "Tauri Example",
extensions: filter.split(",").map((f) => f.trim()),
},
]
: [],
multiple,
directory,
})
.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 {
// Convert byte array to UTF-8 string
const decoder = new TextDecoder('utf-8');
const text = decoder.decode(new Uint8Array(res));
onMessage(text);
onMessage(res);
}
} else {
onMessage(res);
}
})
}
} catch(exception) {
onMessage(exception)
}
})
.catch(onMessage(res));
}
})
.catch(onMessage);
}
function saveDialog() {
@@ -121,7 +105,7 @@
},
]
: [],
})
})
.then(onMessage)
.catch(onMessage);
}
@@ -151,35 +135,13 @@
<input type="checkbox" id="dialog-directory" bind:checked={directory} />
<label for="dialog-directory">Directory</label>
</div>
<div>
<label for="dialog-picker-mode">Picker Mode:</label>
<select id="dialog-picker-mode" bind:value={pickerMode}>
<option value="">None</option>
<option value="media">Media</option>
<option value="image">Image</option>
<option value="video">Video</option>
<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">
<button class="btn" id="open-dialog" on:click={openDialog}>Open dialog</button>
<button class="btn" id="save-dialog" on:click={saveDialog}
>Open save dialog</button
>
<button class="btn" id="prompt-dialog" on:click={prompt}>Prompt</button>
<button class="btn" id="custom-prompt-dialog" on:click={promptCustom}
>Prompt (custom)</button
>
<button class="btn" id="message-dialog" on:click={msg}>Message</button>
<button class="btn" id="message-dialog" on:click={msgCustom}>Message (custom)</button>
</div>
<button class="btn" id="open-dialog" on:click={openDialog}>Open dialog</button>
<button class="btn" id="save-dialog" on:click={saveDialog}
>Open save dialog</button
>
<button class="btn" id="prompt-dialog" on:click={prompt}>Prompt</button>
<button class="btn" id="custom-prompt-dialog" on:click={promptCustom}
>Prompt (custom)</button
>
<button class="btn" id="message-dialog" on:click={msg}>Message</button>
+2 -27
View File
@@ -1,9 +1,8 @@
<script>
import * as fs from '@tauri-apps/plugin-fs'
import * as os from '@tauri-apps/plugin-os'
import { convertFileSrc } from '@tauri-apps/api/core'
import { arrayBufferToBase64 } from '../lib/utils'
import { onDestroy, onMount } from 'svelte'
import { onDestroy } from 'svelte'
const { onMessage, insecureRenderHtml } = $props()
@@ -19,12 +18,6 @@
let baseDir = $state()
let unwatchFn
let unwatchPath = ''
let isMobile = $state(false)
onMount(() => {
let platform = os.platform()
isMobile = platform === 'android' || platform === 'ios'
})
const dirOptions = Object.keys(fs.BaseDirectory).filter((key) =>
isNaN(parseInt(key))
@@ -45,7 +38,7 @@
}
function mkdir() {
fs.mkdir(path, { baseDir, recursive: true })
fs.mkdir(path, { baseDir })
.then(() => {
onMessage(`Created dir ${path}`)
})
@@ -80,16 +73,6 @@
.catch(onMessage)
}
function write() {
const encoder = new TextEncoder()
file
.write(encoder.encode('Hello from Tauri :)'))
.then(() => {
onMessage(`wrote to file`)
})
.catch(onMessage)
}
function stat() {
file
.stat()
@@ -197,13 +180,6 @@
</script>
<div class="flex flex-col">
{#if isMobile}
<div>
On mobile, paths outside of App* paths require the use of dialogs
regardless of Tauri's scope mechanism.
</div>
<br />
{/if}
<div class="flex gap-1">
<select class="input" bind:value={baseDir}>
<option value={undefined} selected>None</option>
@@ -231,7 +207,6 @@
</div>
{#if file}
<div>
<button class="btn" onclick={write}>Write</button>
<button class="btn" onclick={truncate}>Truncate</button>
<button class="btn" onclick={stat}>Stat</button>
</div>
+4 -14
View File
@@ -1,21 +1,16 @@
<script>
import { sendNotification } from '@tauri-apps/plugin-notification'
export let onMessage
let sound = ''
// send the notification directly
// the backend is responsible for checking the permission
function _sendNotification() {
sendNotification({
title: 'Notification title',
body: 'This is the notification body',
sound: sound || null
new Notification('Notification title', {
body: 'This is the notification body'
})
}
// alternatively, check the permission ourselves
function triggerNotification() {
function sendNotification() {
if (Notification.permission === 'default') {
Notification.requestPermission()
.then(function (response) {
@@ -34,11 +29,6 @@
}
</script>
<input
class="input grow"
placeholder="Notification sound..."
bind:value={sound}
/>
<button class="btn" id="notification" on:click={triggerNotification}>
<button class="btn" id="notification" on:click={sendNotification}>
Send test notification
</button>
+3 -44
View File
@@ -1,5 +1,5 @@
<script>
import { download, upload, HttpMethod } from '@tauri-apps/plugin-upload'
import { download, upload } from '@tauri-apps/plugin-upload'
import { open } from '@tauri-apps/plugin-dialog'
import { JsonView } from '@zerodevx/svelte-json-view'
import { appDataDir } from '@tauri-apps/api/path'
@@ -16,22 +16,6 @@
let uploadUrl = 'https://httpbin.org/post'
let uploadFilePath = ''
let uploadMethod = HttpMethod.Post
// Update URL when method changes
$: {
switch (uploadMethod) {
case HttpMethod.Post:
uploadUrl = 'https://httpbin.org/post'
break
case HttpMethod.Put:
uploadUrl = 'https://httpbin.org/put'
break
case HttpMethod.Patch:
uploadUrl = 'https://httpbin.org/patch'
break
}
}
let uploadProgress = null
let uploadResult = null
let isUploading = false
@@ -213,8 +197,7 @@
},
new Map([
['User-Agent', 'Tauri Upload Plugin Demo']
]),
uploadMethod
])
)
uploadResult = {
@@ -357,36 +340,12 @@
</div>
</div>
<div>
<label for="upload-method" class="block text-sm font-medium text-gray-700 mb-1">HTTP Method:</label>
<select
id="upload-method"
bind:value={uploadMethod}
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500"
disabled={isUploading}
>
<option value={HttpMethod.Post}>POST</option>
<option value={HttpMethod.Put}>PUT</option>
<option value={HttpMethod.Patch}>PATCH</option>
</select>
<p class="text-xs text-gray-500 mt-1">Choose the HTTP method for the upload request</p>
</div>
<div class="bg-blue-50 border border-blue-200 p-3 rounded-md">
<div class="text-sm text-blue-800">
<strong>Upload Configuration:</strong>
<div class="font-mono text-xs mt-1">
Method: {uploadMethod} | URL: {uploadUrl || 'Not set'}
</div>
</div>
</div>
<button
on:click={startUpload}
class="w-full px-4 py-2 bg-green-500 text-white rounded-md hover:bg-green-600 disabled:opacity-50 disabled:cursor-not-allowed"
disabled={isUploading || !uploadUrl || !uploadFilePath}
>
{isUploading ? `Uploading (${uploadMethod})...` : `Upload File (${uploadMethod})`}
{isUploading ? 'Uploading...' : 'Upload File'}
</button>
{#if uploadProgress}
+12 -12
View File
@@ -11,20 +11,20 @@
"example:api:dev": "pnpm run --filter \"api\" tauri dev"
},
"devDependencies": {
"@eslint/js": "10.0.1",
"@rollup/plugin-node-resolve": "16.0.3",
"@rollup/plugin-terser": "1.0.0",
"@rollup/plugin-typescript": "12.3.0",
"eslint": "10.0.2",
"@eslint/js": "9.32.0",
"@rollup/plugin-node-resolve": "16.0.1",
"@rollup/plugin-terser": "0.4.4",
"@rollup/plugin-typescript": "12.1.4",
"covector": "^0.12.4",
"eslint": "9.32.0",
"eslint-config-prettier": "10.1.8",
"eslint-plugin-security": "4.0.0",
"prettier": "3.8.1",
"rollup": "4.59.0",
"eslint-plugin-security": "3.0.1",
"prettier": "3.6.2",
"rollup": "4.46.2",
"tslib": "2.8.1",
"typescript": "5.9.3",
"typescript-eslint": "8.56.1"
"typescript": "5.9.2",
"typescript-eslint": "8.39.0"
},
"minimumReleaseAge": 4320,
"pnpm": {
"overrides": {
"esbuild@<0.25.0": ">=0.25.0"
@@ -34,6 +34,6 @@
]
},
"engines": {
"pnpm": "^10.16.0"
"pnpm": "^10.0.0"
}
}
-4
View File
@@ -1,9 +1,5 @@
# Changelog
## \[2.5.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.
## \[2.5.0]
- [`f209b2f2`](https://github.com/tauri-apps/plugins-workspace/commit/f209b2f23cb29133c97ad5961fb46ef794dbe063) ([#2804](https://github.com/tauri-apps/plugins-workspace/pull/2804) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated tauri to 2.6
+5 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-autostart"
version = "2.5.1"
version = "2.5.0"
description = "Automatically launch your application at startup."
authors = { workspace = true }
license = { workspace = true }
@@ -9,6 +9,10 @@ rust-version = { workspace = true }
repository = { workspace = true }
links = "tauri-plugin-autostart"
[package.metadata.docs.rs]
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
linux = { level = "full", notes = "" }
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-autostart",
"version": "2.5.1",
"version": "2.5.0",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
@@ -24,6 +24,6 @@
"LICENSE"
],
"dependencies": {
"@tauri-apps/api": "^2.10.1"
"@tauri-apps/api": "^2.6.0"
}
}
@@ -24,17 +24,20 @@
},
"permission": {
"description": "A list of inlined permissions",
"default": [],
"type": "array",
"items": {
"$ref": "#/definitions/Permission"
},
"default": []
}
}
},
"definitions": {
"DefaultPermission": {
"description": "The default permission set of the plugin.\n\nWorks similarly to a permission with the \"default\" identifier.",
"type": "object",
"required": [
"permissions"
],
"properties": {
"version": {
"description": "The version of the permission.",
@@ -43,10 +46,10 @@
"null"
],
"format": "uint64",
"minimum": 1
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does.\nTauri convention is to use `<h4>` headings in markdown content\nfor Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -59,14 +62,16 @@
"type": "string"
}
}
},
"required": [
"permissions"
]
}
},
"PermissionSet": {
"description": "A set of direct permissions grouped together under a new name.",
"type": "object",
"required": [
"description",
"identifier",
"permissions"
],
"properties": {
"identifier": {
"description": "A unique identifier for the permission.",
@@ -80,19 +85,17 @@
"description": "All permissions this set contains.",
"type": "array",
"items": {
"type": "string"
"$ref": "#/definitions/PermissionKind"
}
}
},
"required": [
"identifier",
"description",
"permissions"
]
}
},
"Permission": {
"description": "Descriptions of explicit privileges of commands.\n\nIt can enable commands to be accessible in the frontend of the application.\n\nIf the scope is defined it can be used to fine grain control the access of individual or multiple commands.",
"type": "object",
"required": [
"identifier"
],
"properties": {
"version": {
"description": "The version of the permission.",
@@ -101,14 +104,14 @@
"null"
],
"format": "uint64",
"minimum": 1
"minimum": 1.0
},
"identifier": {
"description": "A unique identifier for the permission.",
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does.\nTauri internal convention is to use `<h4>` headings in markdown content\nfor Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -144,10 +147,7 @@
"$ref": "#/definitions/Target"
}
}
},
"required": [
"identifier"
]
}
},
"Commands": {
"description": "Allowed and denied commands inside a permission.\n\nIf two commands clash inside of `allow` and `deny`, it should be denied by default.",
@@ -155,24 +155,24 @@
"properties": {
"allow": {
"description": "Allowed command.",
"default": [],
"type": "array",
"items": {
"type": "string"
},
"default": []
}
},
"deny": {
"description": "Denied command, which takes priority.",
"default": [],
"type": "array",
"items": {
"type": "string"
},
"default": []
}
}
}
},
"Scopes": {
"description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command.\nThe configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json\n{\n \"allow\": [{ \"path\": \"$HOME/**\" }],\n \"deny\": [{ \"path\": \"$HOME/secret.txt\" }]\n}\n```",
"description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command. The configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json { \"allow\": [{ \"path\": \"$HOME/**\" }], \"deny\": [{ \"path\": \"$HOME/secret.txt\" }] } ```",
"type": "object",
"properties": {
"allow": {
@@ -257,27 +257,84 @@
{
"description": "MacOS.",
"type": "string",
"const": "macOS"
"enum": [
"macOS"
]
},
{
"description": "Windows.",
"type": "string",
"const": "windows"
"enum": [
"windows"
]
},
{
"description": "Linux.",
"type": "string",
"const": "linux"
"enum": [
"linux"
]
},
{
"description": "Android.",
"type": "string",
"const": "android"
"enum": [
"android"
]
},
{
"description": "iOS.",
"type": "string",
"const": "iOS"
"enum": [
"iOS"
]
}
]
},
"PermissionKind": {
"type": "string",
"oneOf": [
{
"description": "Enables the disable command without any pre-configured scope.",
"type": "string",
"const": "allow-disable",
"markdownDescription": "Enables the disable command without any pre-configured scope."
},
{
"description": "Denies the disable command without any pre-configured scope.",
"type": "string",
"const": "deny-disable",
"markdownDescription": "Denies the disable command without any pre-configured scope."
},
{
"description": "Enables the enable command without any pre-configured scope.",
"type": "string",
"const": "allow-enable",
"markdownDescription": "Enables the enable command without any pre-configured scope."
},
{
"description": "Denies the enable command without any pre-configured scope.",
"type": "string",
"const": "deny-enable",
"markdownDescription": "Denies the enable command without any pre-configured scope."
},
{
"description": "Enables the is_enabled command without any pre-configured scope.",
"type": "string",
"const": "allow-is-enabled",
"markdownDescription": "Enables the is_enabled command without any pre-configured scope."
},
{
"description": "Denies the is_enabled command without any pre-configured scope.",
"type": "string",
"const": "deny-is-enabled",
"markdownDescription": "Denies the is_enabled command without any pre-configured scope."
},
{
"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\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`"
}
]
}
-20
View File
@@ -1,25 +1,5 @@
# 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.
## \[2.4.1]
- [`654bf489`](https://github.com/tauri-apps/plugins-workspace/commit/654bf4891a35769f7e82971641d3ad99974b2dfe) ([#3038](https://github.com/tauri-apps/plugins-workspace/pull/3038) by [@daniel-mader](https://github.com/tauri-apps/plugins-workspace/../../daniel-mader)) Update `androidx.camera` from `1.1.0` to `1.5.1` to support 16 KB memory page sizes.
- [`6c9b61fb`](https://github.com/tauri-apps/plugins-workspace/commit/6c9b61fb658145d13893626112fc489f7458aa17) ([#3039](https://github.com/tauri-apps/plugins-workspace/pull/3039) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) On Android, updated compileSdk to 36.
## \[2.4.0]
- [`aa9140e1`](https://github.com/tauri-apps/plugins-workspace/commit/aa9140e1ac239ab9f015f92b2ed52bbf0eda7c12) ([#2437](https://github.com/tauri-apps/plugins-workspace/pull/2437) by [@enkhjile](https://github.com/tauri-apps/plugins-workspace/../../enkhjile)) Added support for GS1 DataBar on iOS 15.4+
+4 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-barcode-scanner"
version = "2.4.4"
version = "2.4.0"
description = "Scan QR codes, EAN-13 and other kinds of barcodes on Android and iOS"
edition = { workspace = true }
authors = { workspace = true }
@@ -10,6 +10,8 @@ repository = { workspace = true }
links = "tauri-plugin-barcode-scanner"
[package.metadata.docs.rs]
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
targets = ["x86_64-linux-android"]
[package.metadata.platforms.support]
@@ -31,4 +33,4 @@ log = { workspace = true }
thiserror = { workspace = true }
[target.'cfg(target_os = "ios")'.dependencies]
tauri = { workspace = true }
tauri = { workspace = true, features = ["wry"] }
@@ -5,10 +5,10 @@ plugins {
android {
namespace = "app.tauri.barcodescanner"
compileSdk = 36
compileSdk = 34
defaultConfig {
minSdk = 24
minSdk = 24
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
@@ -33,14 +33,16 @@ android {
}
dependencies {
val camerax_version = "1.5.1"
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.appcompat:appcompat:1.6.0")
implementation("com.google.android.material:material:1.7.0")
implementation("androidx.camera:camera-core:${camerax_version}")
implementation("androidx.camera:camera-camera2:${camerax_version}")
implementation("androidx.camera:camera-lifecycle:${camerax_version}")
implementation("androidx.camera:camera-view:${camerax_version}")
implementation("androidx.camera:camera-core:1.1.0")
implementation("androidx.camera:camera-view:1.1.0")
implementation("androidx.camera:camera-lifecycle:1.1.0")
implementation("androidx.camera:camera-camera2:1.1.0")
implementation("androidx.camera:camera-lifecycle:1.1.0")
implementation("androidx.camera:camera-view:1.1.0")
implementation("com.google.android.gms:play-services-mlkit-barcode-scanning:18.1.0")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
@@ -54,6 +54,7 @@ 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 {
@@ -353,6 +354,17 @@ 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) {
@@ -368,7 +380,9 @@ 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) {
requestPermissionResponse.put(PERMISSION_ALIAS_CAMERA, PermissionState.DENIED)
if (!activity.shouldShowRequestPermissionRationale(PERMISSION_NAME)) {
requestPermissionResponse.put(PERMISSION_ALIAS_CAMERA, PermissionState.DENIED)
}
} else {
requestPermissionResponse.put(PERMISSION_ALIAS_CAMERA, PermissionState.GRANTED)
}
@@ -387,12 +401,20 @@ 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) {
requestPermissionForAlias(
PERMISSION_ALIAS_CAMERA,
invoke,
"cameraPermissionCallback"
)
return
if (firstPermissionRequest() || activity.shouldShowRequestPermissionRationale(
PERMISSION_NAME
)
) {
markFirstPermissionRequest()
requestPermissionForAlias(
PERMISSION_ALIAS_CAMERA,
invoke,
"cameraPermissionCallback"
)
return
} else {
requestPermissionResponse.put(PERMISSION_ALIAS_CAMERA, PermissionState.DENIED)
}
} else {
requestPermissionResponse.put(PERMISSION_ALIAS_CAMERA, PermissionState.GRANTED)
}
@@ -191,7 +191,6 @@ class BarcodeScannerPlugin: Plugin, AVCaptureMetadataOutputObjectsDelegate {
if self.captureSession != nil {
self.captureSession!.stopRunning()
self.cameraView.removePreviewLayer()
self.cameraView.removeFromSuperview()
self.captureVideoPreviewLayer = nil
self.metaOutput = nil
self.captureSession = nil
@@ -261,34 +260,27 @@ 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
DispatchQueue.main.async {
self.captureSession!.startRunning()
}
self.captureSession!.startRunning()
self.isScanning = true
}
@@ -305,13 +297,6 @@ 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.4",
"version": "2.4.0",
"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.10.1"
"@tauri-apps/api": "^2.6.0"
}
}
@@ -24,17 +24,20 @@
},
"permission": {
"description": "A list of inlined permissions",
"default": [],
"type": "array",
"items": {
"$ref": "#/definitions/Permission"
},
"default": []
}
}
},
"definitions": {
"DefaultPermission": {
"description": "The default permission set of the plugin.\n\nWorks similarly to a permission with the \"default\" identifier.",
"type": "object",
"required": [
"permissions"
],
"properties": {
"version": {
"description": "The version of the permission.",
@@ -43,10 +46,10 @@
"null"
],
"format": "uint64",
"minimum": 1
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does.\nTauri convention is to use `<h4>` headings in markdown content\nfor Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -59,14 +62,16 @@
"type": "string"
}
}
},
"required": [
"permissions"
]
}
},
"PermissionSet": {
"description": "A set of direct permissions grouped together under a new name.",
"type": "object",
"required": [
"description",
"identifier",
"permissions"
],
"properties": {
"identifier": {
"description": "A unique identifier for the permission.",
@@ -80,19 +85,17 @@
"description": "All permissions this set contains.",
"type": "array",
"items": {
"type": "string"
"$ref": "#/definitions/PermissionKind"
}
}
},
"required": [
"identifier",
"description",
"permissions"
]
}
},
"Permission": {
"description": "Descriptions of explicit privileges of commands.\n\nIt can enable commands to be accessible in the frontend of the application.\n\nIf the scope is defined it can be used to fine grain control the access of individual or multiple commands.",
"type": "object",
"required": [
"identifier"
],
"properties": {
"version": {
"description": "The version of the permission.",
@@ -101,14 +104,14 @@
"null"
],
"format": "uint64",
"minimum": 1
"minimum": 1.0
},
"identifier": {
"description": "A unique identifier for the permission.",
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does.\nTauri internal convention is to use `<h4>` headings in markdown content\nfor Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -144,10 +147,7 @@
"$ref": "#/definitions/Target"
}
}
},
"required": [
"identifier"
]
}
},
"Commands": {
"description": "Allowed and denied commands inside a permission.\n\nIf two commands clash inside of `allow` and `deny`, it should be denied by default.",
@@ -155,24 +155,24 @@
"properties": {
"allow": {
"description": "Allowed command.",
"default": [],
"type": "array",
"items": {
"type": "string"
},
"default": []
}
},
"deny": {
"description": "Denied command, which takes priority.",
"default": [],
"type": "array",
"items": {
"type": "string"
},
"default": []
}
}
}
},
"Scopes": {
"description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command.\nThe configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json\n{\n \"allow\": [{ \"path\": \"$HOME/**\" }],\n \"deny\": [{ \"path\": \"$HOME/secret.txt\" }]\n}\n```",
"description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command. The configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json { \"allow\": [{ \"path\": \"$HOME/**\" }], \"deny\": [{ \"path\": \"$HOME/secret.txt\" }] } ```",
"type": "object",
"properties": {
"allow": {
@@ -257,27 +257,120 @@
{
"description": "MacOS.",
"type": "string",
"const": "macOS"
"enum": [
"macOS"
]
},
{
"description": "Windows.",
"type": "string",
"const": "windows"
"enum": [
"windows"
]
},
{
"description": "Linux.",
"type": "string",
"const": "linux"
"enum": [
"linux"
]
},
{
"description": "Android.",
"type": "string",
"const": "android"
"enum": [
"android"
]
},
{
"description": "iOS.",
"type": "string",
"const": "iOS"
"enum": [
"iOS"
]
}
]
},
"PermissionKind": {
"type": "string",
"oneOf": [
{
"description": "Enables the cancel command without any pre-configured scope.",
"type": "string",
"const": "allow-cancel",
"markdownDescription": "Enables the cancel command without any pre-configured scope."
},
{
"description": "Denies the cancel command without any pre-configured scope.",
"type": "string",
"const": "deny-cancel",
"markdownDescription": "Denies the cancel command without any pre-configured scope."
},
{
"description": "Enables the check_permissions command without any pre-configured scope.",
"type": "string",
"const": "allow-check-permissions",
"markdownDescription": "Enables the check_permissions command without any pre-configured scope."
},
{
"description": "Denies the check_permissions command without any pre-configured scope.",
"type": "string",
"const": "deny-check-permissions",
"markdownDescription": "Denies the check_permissions command without any pre-configured scope."
},
{
"description": "Enables the open_app_settings command without any pre-configured scope.",
"type": "string",
"const": "allow-open-app-settings",
"markdownDescription": "Enables the open_app_settings command without any pre-configured scope."
},
{
"description": "Denies the open_app_settings command without any pre-configured scope.",
"type": "string",
"const": "deny-open-app-settings",
"markdownDescription": "Denies the open_app_settings command without any pre-configured scope."
},
{
"description": "Enables the request_permissions command without any pre-configured scope.",
"type": "string",
"const": "allow-request-permissions",
"markdownDescription": "Enables the request_permissions command without any pre-configured scope."
},
{
"description": "Denies the request_permissions command without any pre-configured scope.",
"type": "string",
"const": "deny-request-permissions",
"markdownDescription": "Denies the request_permissions command without any pre-configured scope."
},
{
"description": "Enables the scan command without any pre-configured scope.",
"type": "string",
"const": "allow-scan",
"markdownDescription": "Enables the scan command without any pre-configured scope."
},
{
"description": "Denies the scan command without any pre-configured scope.",
"type": "string",
"const": "deny-scan",
"markdownDescription": "Denies the scan command without any pre-configured scope."
},
{
"description": "Enables the vibrate command without any pre-configured scope.",
"type": "string",
"const": "allow-vibrate",
"markdownDescription": "Enables the vibrate command without any pre-configured scope."
},
{
"description": "Denies the vibrate command without any pre-configured scope.",
"type": "string",
"const": "deny-vibrate",
"markdownDescription": "Denies the vibrate command without any pre-configured scope."
},
{
"description": "This permission set configures which\nbarcode scanning features are by default exposed.\n\n#### Granted Permissions\n\nIt allows all barcode related features.\n\n\n#### This default permission set includes:\n\n- `allow-cancel`\n- `allow-check-permissions`\n- `allow-open-app-settings`\n- `allow-request-permissions`\n- `allow-scan`\n- `allow-vibrate`",
"type": "string",
"const": "default",
"markdownDescription": "This permission set configures which\nbarcode scanning features are by default exposed.\n\n#### Granted Permissions\n\nIt allows all barcode related features.\n\n\n#### This default permission set includes:\n\n- `allow-cancel`\n- `allow-check-permissions`\n- `allow-open-app-settings`\n- `allow-request-permissions`\n- `allow-scan`\n- `allow-vibrate`"
}
]
}
-8
View File
@@ -1,13 +1,5 @@
# Changelog
## \[2.3.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.
## \[2.3.1]
- [`6c9b61fb`](https://github.com/tauri-apps/plugins-workspace/commit/6c9b61fb658145d13893626112fc489f7458aa17) ([#3039](https://github.com/tauri-apps/plugins-workspace/pull/3039) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) On Android, updated compileSdk to 36.
## \[2.3.0]
- [`f209b2f2`](https://github.com/tauri-apps/plugins-workspace/commit/f209b2f23cb29133c97ad5961fb46ef794dbe063) ([#2804](https://github.com/tauri-apps/plugins-workspace/pull/2804) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated tauri to 2.6
+3 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-biometric"
version = "2.3.2"
version = "2.3.0"
description = "Prompt the user for biometric authentication on Android and iOS."
edition = { workspace = true }
authors = { workspace = true }
@@ -9,6 +9,8 @@ repository = { workspace = true }
links = "tauri-plugin-biometric"
[package.metadata.docs.rs]
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
targets = ["x86_64-linux-android"]
[package.metadata.platforms.support]
+2 -2
View File
@@ -5,10 +5,10 @@ plugins {
android {
namespace = "app.tauri.biometric"
compileSdk = 36
compileSdk = 34
defaultConfig {
minSdk = 24
minSdk = 24
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-biometric",
"version": "2.3.2",
"version": "2.3.0",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
@@ -25,6 +25,6 @@
"LICENSE"
],
"dependencies": {
"@tauri-apps/api": "^2.10.1"
"@tauri-apps/api": "^2.6.0"
}
}
@@ -24,17 +24,20 @@
},
"permission": {
"description": "A list of inlined permissions",
"default": [],
"type": "array",
"items": {
"$ref": "#/definitions/Permission"
},
"default": []
}
}
},
"definitions": {
"DefaultPermission": {
"description": "The default permission set of the plugin.\n\nWorks similarly to a permission with the \"default\" identifier.",
"type": "object",
"required": [
"permissions"
],
"properties": {
"version": {
"description": "The version of the permission.",
@@ -43,10 +46,10 @@
"null"
],
"format": "uint64",
"minimum": 1
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does.\nTauri convention is to use `<h4>` headings in markdown content\nfor Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -59,14 +62,16 @@
"type": "string"
}
}
},
"required": [
"permissions"
]
}
},
"PermissionSet": {
"description": "A set of direct permissions grouped together under a new name.",
"type": "object",
"required": [
"description",
"identifier",
"permissions"
],
"properties": {
"identifier": {
"description": "A unique identifier for the permission.",
@@ -80,19 +85,17 @@
"description": "All permissions this set contains.",
"type": "array",
"items": {
"type": "string"
"$ref": "#/definitions/PermissionKind"
}
}
},
"required": [
"identifier",
"description",
"permissions"
]
}
},
"Permission": {
"description": "Descriptions of explicit privileges of commands.\n\nIt can enable commands to be accessible in the frontend of the application.\n\nIf the scope is defined it can be used to fine grain control the access of individual or multiple commands.",
"type": "object",
"required": [
"identifier"
],
"properties": {
"version": {
"description": "The version of the permission.",
@@ -101,14 +104,14 @@
"null"
],
"format": "uint64",
"minimum": 1
"minimum": 1.0
},
"identifier": {
"description": "A unique identifier for the permission.",
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does.\nTauri internal convention is to use `<h4>` headings in markdown content\nfor Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -144,10 +147,7 @@
"$ref": "#/definitions/Target"
}
}
},
"required": [
"identifier"
]
}
},
"Commands": {
"description": "Allowed and denied commands inside a permission.\n\nIf two commands clash inside of `allow` and `deny`, it should be denied by default.",
@@ -155,24 +155,24 @@
"properties": {
"allow": {
"description": "Allowed command.",
"default": [],
"type": "array",
"items": {
"type": "string"
},
"default": []
}
},
"deny": {
"description": "Denied command, which takes priority.",
"default": [],
"type": "array",
"items": {
"type": "string"
},
"default": []
}
}
}
},
"Scopes": {
"description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command.\nThe configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json\n{\n \"allow\": [{ \"path\": \"$HOME/**\" }],\n \"deny\": [{ \"path\": \"$HOME/secret.txt\" }]\n}\n```",
"description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command. The configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json { \"allow\": [{ \"path\": \"$HOME/**\" }], \"deny\": [{ \"path\": \"$HOME/secret.txt\" }] } ```",
"type": "object",
"properties": {
"allow": {
@@ -257,27 +257,72 @@
{
"description": "MacOS.",
"type": "string",
"const": "macOS"
"enum": [
"macOS"
]
},
{
"description": "Windows.",
"type": "string",
"const": "windows"
"enum": [
"windows"
]
},
{
"description": "Linux.",
"type": "string",
"const": "linux"
"enum": [
"linux"
]
},
{
"description": "Android.",
"type": "string",
"const": "android"
"enum": [
"android"
]
},
{
"description": "iOS.",
"type": "string",
"const": "iOS"
"enum": [
"iOS"
]
}
]
},
"PermissionKind": {
"type": "string",
"oneOf": [
{
"description": "Enables the authenticate command without any pre-configured scope.",
"type": "string",
"const": "allow-authenticate",
"markdownDescription": "Enables the authenticate command without any pre-configured scope."
},
{
"description": "Denies the authenticate command without any pre-configured scope.",
"type": "string",
"const": "deny-authenticate",
"markdownDescription": "Denies the authenticate command without any pre-configured scope."
},
{
"description": "Enables the status command without any pre-configured scope.",
"type": "string",
"const": "allow-status",
"markdownDescription": "Enables the status command without any pre-configured scope."
},
{
"description": "Denies the status command without any pre-configured scope.",
"type": "string",
"const": "deny-status",
"markdownDescription": "Denies the status command without any pre-configured scope."
},
{
"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\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`"
}
]
}
-4
View File
@@ -1,9 +1,5 @@
# Changelog
## \[2.4.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.
## \[2.4.0]
- [`f209b2f2`](https://github.com/tauri-apps/plugins-workspace/commit/f209b2f23cb29133c97ad5961fb46ef794dbe063) ([#2804](https://github.com/tauri-apps/plugins-workspace/pull/2804) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated tauri to 2.6
+5 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-cli"
version = "2.4.1"
version = "2.4.0"
description = "Parse arguments from your Tauri application's command line interface."
edition = { workspace = true }
authors = { workspace = true }
@@ -9,6 +9,10 @@ rust-version = { workspace = true }
repository = { workspace = true }
links = "tauri-plugin-cli"
[package.metadata.docs.rs]
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
linux = { level = "full", notes = "" }
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-cli",
"version": "2.4.1",
"version": "2.4.0",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
@@ -24,6 +24,6 @@
"LICENSE"
],
"dependencies": {
"@tauri-apps/api": "^2.10.1"
"@tauri-apps/api": "^2.6.0"
}
}
+64 -31
View File
@@ -24,17 +24,20 @@
},
"permission": {
"description": "A list of inlined permissions",
"default": [],
"type": "array",
"items": {
"$ref": "#/definitions/Permission"
},
"default": []
}
}
},
"definitions": {
"DefaultPermission": {
"description": "The default permission set of the plugin.\n\nWorks similarly to a permission with the \"default\" identifier.",
"type": "object",
"required": [
"permissions"
],
"properties": {
"version": {
"description": "The version of the permission.",
@@ -43,10 +46,10 @@
"null"
],
"format": "uint64",
"minimum": 1
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does.\nTauri convention is to use `<h4>` headings in markdown content\nfor Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -59,14 +62,16 @@
"type": "string"
}
}
},
"required": [
"permissions"
]
}
},
"PermissionSet": {
"description": "A set of direct permissions grouped together under a new name.",
"type": "object",
"required": [
"description",
"identifier",
"permissions"
],
"properties": {
"identifier": {
"description": "A unique identifier for the permission.",
@@ -80,19 +85,17 @@
"description": "All permissions this set contains.",
"type": "array",
"items": {
"type": "string"
"$ref": "#/definitions/PermissionKind"
}
}
},
"required": [
"identifier",
"description",
"permissions"
]
}
},
"Permission": {
"description": "Descriptions of explicit privileges of commands.\n\nIt can enable commands to be accessible in the frontend of the application.\n\nIf the scope is defined it can be used to fine grain control the access of individual or multiple commands.",
"type": "object",
"required": [
"identifier"
],
"properties": {
"version": {
"description": "The version of the permission.",
@@ -101,14 +104,14 @@
"null"
],
"format": "uint64",
"minimum": 1
"minimum": 1.0
},
"identifier": {
"description": "A unique identifier for the permission.",
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does.\nTauri internal convention is to use `<h4>` headings in markdown content\nfor Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -144,10 +147,7 @@
"$ref": "#/definitions/Target"
}
}
},
"required": [
"identifier"
]
}
},
"Commands": {
"description": "Allowed and denied commands inside a permission.\n\nIf two commands clash inside of `allow` and `deny`, it should be denied by default.",
@@ -155,24 +155,24 @@
"properties": {
"allow": {
"description": "Allowed command.",
"default": [],
"type": "array",
"items": {
"type": "string"
},
"default": []
}
},
"deny": {
"description": "Denied command, which takes priority.",
"default": [],
"type": "array",
"items": {
"type": "string"
},
"default": []
}
}
}
},
"Scopes": {
"description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command.\nThe configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json\n{\n \"allow\": [{ \"path\": \"$HOME/**\" }],\n \"deny\": [{ \"path\": \"$HOME/secret.txt\" }]\n}\n```",
"description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command. The configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json { \"allow\": [{ \"path\": \"$HOME/**\" }], \"deny\": [{ \"path\": \"$HOME/secret.txt\" }] } ```",
"type": "object",
"properties": {
"allow": {
@@ -257,27 +257,60 @@
{
"description": "MacOS.",
"type": "string",
"const": "macOS"
"enum": [
"macOS"
]
},
{
"description": "Windows.",
"type": "string",
"const": "windows"
"enum": [
"windows"
]
},
{
"description": "Linux.",
"type": "string",
"const": "linux"
"enum": [
"linux"
]
},
{
"description": "Android.",
"type": "string",
"const": "android"
"enum": [
"android"
]
},
{
"description": "iOS.",
"type": "string",
"const": "iOS"
"enum": [
"iOS"
]
}
]
},
"PermissionKind": {
"type": "string",
"oneOf": [
{
"description": "Enables the cli_matches command without any pre-configured scope.",
"type": "string",
"const": "allow-cli-matches",
"markdownDescription": "Enables the cli_matches command without any pre-configured scope."
},
{
"description": "Denies the cli_matches command without any pre-configured scope.",
"type": "string",
"const": "deny-cli-matches",
"markdownDescription": "Denies the cli_matches command without any pre-configured scope."
},
{
"description": "Allows reading the CLI matches\n#### This default permission set includes:\n\n- `allow-cli-matches`",
"type": "string",
"const": "default",
"markdownDescription": "Allows reading the CLI matches\n#### This default permission set includes:\n\n- `allow-cli-matches`"
}
]
}
-8
View File
@@ -1,13 +1,5 @@
# Changelog
## \[2.3.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.
## \[2.3.1]
- [`6c9b61fb`](https://github.com/tauri-apps/plugins-workspace/commit/6c9b61fb658145d13893626112fc489f7458aa17) ([#3039](https://github.com/tauri-apps/plugins-workspace/pull/3039) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) On Android, updated compileSdk to 36.
## \[2.3.0]
- [`f209b2f2`](https://github.com/tauri-apps/plugins-workspace/commit/f209b2f23cb29133c97ad5961fb46ef794dbe063) ([#2804](https://github.com/tauri-apps/plugins-workspace/pull/2804) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated tauri to 2.6
+4 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-clipboard-manager"
version = "2.3.2"
version = "2.3.0"
description = "Read and write to the system clipboard."
edition = { workspace = true }
authors = { workspace = true }
@@ -10,7 +10,8 @@ repository = { workspace = true }
links = "tauri-plugin-clipboard-manager"
[package.metadata.docs.rs]
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
targets = ["x86_64-unknown-linux-gnu", "x86_64-linux-android"]
[package.metadata.platforms.support]
@@ -32,7 +33,7 @@ log = { workspace = true }
thiserror = { workspace = true }
[target.'cfg(target_os = "ios")'.dependencies]
tauri = { workspace = true }
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]
arboard = { version = "3", features = ["wayland-data-control"] }
@@ -5,10 +5,10 @@ plugins {
android {
namespace = "app.tauri.clipboard"
compileSdk = 36
compileSdk = 34
defaultConfig {
minSdk = 24
minSdk = 24
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-clipboard-manager",
"version": "2.3.2",
"version": "2.3.0",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
@@ -24,6 +24,6 @@
"LICENSE"
],
"dependencies": {
"@tauri-apps/api": "^2.10.1"
"@tauri-apps/api": "^2.6.0"
}
}
@@ -24,17 +24,20 @@
},
"permission": {
"description": "A list of inlined permissions",
"default": [],
"type": "array",
"items": {
"$ref": "#/definitions/Permission"
},
"default": []
}
}
},
"definitions": {
"DefaultPermission": {
"description": "The default permission set of the plugin.\n\nWorks similarly to a permission with the \"default\" identifier.",
"type": "object",
"required": [
"permissions"
],
"properties": {
"version": {
"description": "The version of the permission.",
@@ -43,10 +46,10 @@
"null"
],
"format": "uint64",
"minimum": 1
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does.\nTauri convention is to use `<h4>` headings in markdown content\nfor Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -59,14 +62,16 @@
"type": "string"
}
}
},
"required": [
"permissions"
]
}
},
"PermissionSet": {
"description": "A set of direct permissions grouped together under a new name.",
"type": "object",
"required": [
"description",
"identifier",
"permissions"
],
"properties": {
"identifier": {
"description": "A unique identifier for the permission.",
@@ -80,19 +85,17 @@
"description": "All permissions this set contains.",
"type": "array",
"items": {
"type": "string"
"$ref": "#/definitions/PermissionKind"
}
}
},
"required": [
"identifier",
"description",
"permissions"
]
}
},
"Permission": {
"description": "Descriptions of explicit privileges of commands.\n\nIt can enable commands to be accessible in the frontend of the application.\n\nIf the scope is defined it can be used to fine grain control the access of individual or multiple commands.",
"type": "object",
"required": [
"identifier"
],
"properties": {
"version": {
"description": "The version of the permission.",
@@ -101,14 +104,14 @@
"null"
],
"format": "uint64",
"minimum": 1
"minimum": 1.0
},
"identifier": {
"description": "A unique identifier for the permission.",
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does.\nTauri internal convention is to use `<h4>` headings in markdown content\nfor Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -144,10 +147,7 @@
"$ref": "#/definitions/Target"
}
}
},
"required": [
"identifier"
]
}
},
"Commands": {
"description": "Allowed and denied commands inside a permission.\n\nIf two commands clash inside of `allow` and `deny`, it should be denied by default.",
@@ -155,24 +155,24 @@
"properties": {
"allow": {
"description": "Allowed command.",
"default": [],
"type": "array",
"items": {
"type": "string"
},
"default": []
}
},
"deny": {
"description": "Denied command, which takes priority.",
"default": [],
"type": "array",
"items": {
"type": "string"
},
"default": []
}
}
}
},
"Scopes": {
"description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command.\nThe configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json\n{\n \"allow\": [{ \"path\": \"$HOME/**\" }],\n \"deny\": [{ \"path\": \"$HOME/secret.txt\" }]\n}\n```",
"description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command. The configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json { \"allow\": [{ \"path\": \"$HOME/**\" }], \"deny\": [{ \"path\": \"$HOME/secret.txt\" }] } ```",
"type": "object",
"properties": {
"allow": {
@@ -257,27 +257,120 @@
{
"description": "MacOS.",
"type": "string",
"const": "macOS"
"enum": [
"macOS"
]
},
{
"description": "Windows.",
"type": "string",
"const": "windows"
"enum": [
"windows"
]
},
{
"description": "Linux.",
"type": "string",
"const": "linux"
"enum": [
"linux"
]
},
{
"description": "Android.",
"type": "string",
"const": "android"
"enum": [
"android"
]
},
{
"description": "iOS.",
"type": "string",
"const": "iOS"
"enum": [
"iOS"
]
}
]
},
"PermissionKind": {
"type": "string",
"oneOf": [
{
"description": "Enables the clear command without any pre-configured scope.",
"type": "string",
"const": "allow-clear",
"markdownDescription": "Enables the clear command without any pre-configured scope."
},
{
"description": "Denies the clear command without any pre-configured scope.",
"type": "string",
"const": "deny-clear",
"markdownDescription": "Denies the clear command without any pre-configured scope."
},
{
"description": "Enables the read_image command without any pre-configured scope.",
"type": "string",
"const": "allow-read-image",
"markdownDescription": "Enables the read_image command without any pre-configured scope."
},
{
"description": "Denies the read_image command without any pre-configured scope.",
"type": "string",
"const": "deny-read-image",
"markdownDescription": "Denies the read_image command without any pre-configured scope."
},
{
"description": "Enables the read_text command without any pre-configured scope.",
"type": "string",
"const": "allow-read-text",
"markdownDescription": "Enables the read_text command without any pre-configured scope."
},
{
"description": "Denies the read_text command without any pre-configured scope.",
"type": "string",
"const": "deny-read-text",
"markdownDescription": "Denies the read_text command without any pre-configured scope."
},
{
"description": "Enables the write_html command without any pre-configured scope.",
"type": "string",
"const": "allow-write-html",
"markdownDescription": "Enables the write_html command without any pre-configured scope."
},
{
"description": "Denies the write_html command without any pre-configured scope.",
"type": "string",
"const": "deny-write-html",
"markdownDescription": "Denies the write_html command without any pre-configured scope."
},
{
"description": "Enables the write_image command without any pre-configured scope.",
"type": "string",
"const": "allow-write-image",
"markdownDescription": "Enables the write_image command without any pre-configured scope."
},
{
"description": "Denies the write_image command without any pre-configured scope.",
"type": "string",
"const": "deny-write-image",
"markdownDescription": "Denies the write_image command without any pre-configured scope."
},
{
"description": "Enables the write_text command without any pre-configured scope.",
"type": "string",
"const": "allow-write-text",
"markdownDescription": "Enables the write_text command without any pre-configured scope."
},
{
"description": "Denies the write_text command without any pre-configured scope.",
"type": "string",
"const": "deny-write-text",
"markdownDescription": "Denies the write_text command without any pre-configured scope."
},
{
"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\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"
}
]
}
-25
View File
@@ -1,30 +1,5 @@
# Changelog
## \[2.4.7]
- [`8374e997`](https://github.com/tauri-apps/plugins-workspace/commit/8374e997b82c95516fc0c1f6d665d9fc3b52edf8) ([#3258](https://github.com/tauri-apps/plugins-workspace/pull/3258) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Fix runtime deep link registration failing on Linux when the app path has spaces.
## \[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.
## \[2.4.4]
- [`6c9b61fb`](https://github.com/tauri-apps/plugins-workspace/commit/6c9b61fb658145d13893626112fc489f7458aa17) ([#3039](https://github.com/tauri-apps/plugins-workspace/pull/3039) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) On Android, updated compileSdk to 36.
- [`e25a9339`](https://github.com/tauri-apps/plugins-workspace/commit/e25a9339f46268f70dc9afd0c5ab3decbf79b330) ([#3019](https://github.com/tauri-apps/plugins-workspace/pull/3019) by [@kevinschoonover](https://github.com/tauri-apps/plugins-workspace/../../kevinschoonover)) Fix Exec= field in desktop handler if executable path changes
## \[2.4.3]
- [`2522b71f`](https://github.com/tauri-apps/plugins-workspace/commit/2522b71f6bcae65c03b24415eb9295c9e7c84ffc) ([#2970](https://github.com/tauri-apps/plugins-workspace/pull/2970) by [@WSH032](https://github.com/tauri-apps/plugins-workspace/../../WSH032)) Revert the breaking change introduced by [#2928](https://github.com/tauri-apps/plugins-workspace/pull/2928).
## \[2.4.2]
- [`21d721a0`](https://github.com/tauri-apps/plugins-workspace/commit/21d721a0c2731fc201872f5b99ea8bbdc61b0b60) ([#2928](https://github.com/tauri-apps/plugins-workspace/pull/2928) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) On Linux, improved error messages when OS commands fail.
## \[2.4.1]
- [`d4f8299b`](https://github.com/tauri-apps/plugins-workspace/commit/d4f8299b12f107718c70692840a63768d65baaf9) ([#2844](https://github.com/tauri-apps/plugins-workspace/pull/2844) by [@yobson1](https://github.com/tauri-apps/plugins-workspace/../../yobson1)) Fix deep link protocol handler not set as default on linux
+3 -4
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-deep-link"
version = "2.4.7"
version = "2.4.1"
description = "Set your Tauri application as the default handler for an URL"
authors = { workspace = true }
license = { workspace = true }
@@ -10,6 +10,8 @@ repository = { workspace = true }
links = "tauri-plugin-deep-link"
[package.metadata.docs.rs]
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
targets = ["x86_64-linux-android"]
[package.metadata.platforms.support]
@@ -25,9 +27,6 @@ serde_json = { workspace = true }
tauri-utils = { workspace = true }
tauri-plugin = { workspace = true, features = ["build"] }
[target."cfg(target_os = \"macos\")".build-dependencies]
plist = "1"
[dependencies]
serde = { workspace = true }
serde_json = { workspace = true }
+2 -2
View File
@@ -5,10 +5,10 @@ plugins {
android {
namespace = "app.tauri.deep_link"
compileSdk = 36
compileSdk = 34
defaultConfig {
minSdk = 24
minSdk = 24
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
@@ -6,8 +6,9 @@ package app.tauri.deep_link
import android.app.Activity
import android.content.Intent
import android.os.PatternMatcher
import android.os.Bundle
import android.webkit.WebView
import app.tauri.Logger
import app.tauri.annotation.InvokeArg
import app.tauri.annotation.Command
import app.tauri.annotation.TauriPlugin
@@ -15,35 +16,18 @@ import app.tauri.plugin.Channel
import app.tauri.plugin.JSObject
import app.tauri.plugin.Plugin
import app.tauri.plugin.Invoke
import androidx.core.net.toUri
@InvokeArg
class SetEventHandlerArgs {
lateinit var handler: Channel
}
@InvokeArg
class AssociatedDomain {
var scheme: List<String> = listOf("https", "http")
var host: String? = null
var path: List<String> = listOf()
var pathPattern: List<String> = listOf()
var pathPrefix: List<String> = listOf()
var pathSuffix: List<String> = listOf()
}
@InvokeArg
class PluginConfig {
var mobile: List<AssociatedDomain> = listOf()
}
@TauriPlugin
class DeepLinkPlugin(private val activity: Activity): Plugin(activity) {
//private val implementation = Example()
private var webView: WebView? = null
private var currentUrl: String? = null
private var channel: Channel? = null
private var config: PluginConfig? = null
companion object {
var instance: DeepLinkPlugin? = null
@@ -67,105 +51,27 @@ class DeepLinkPlugin(private val activity: Activity): Plugin(activity) {
override fun load(webView: WebView) {
instance = this
config = getConfig(PluginConfig::class.java)
super.load(webView)
this.webView = webView
val intent = activity.intent
if (intent.action == Intent.ACTION_VIEW && intent.data != null) {
val url = intent.data.toString()
if (isDeepLink(url)) {
// TODO: check if it makes sense to split up init url and last url
this.currentUrl = url
val event = JSObject()
event.put("url", this.currentUrl)
this.channel?.send(event)
}
if (intent.action == Intent.ACTION_VIEW) {
// TODO: check if it makes sense to split up init url and last url
this.currentUrl = intent.data.toString()
val event = JSObject()
event.put("url", this.currentUrl)
this.channel?.send(event)
}
super.load(webView)
this.webView = webView
}
override fun onNewIntent(intent: Intent) {
if (intent.action == Intent.ACTION_VIEW && intent.data != null) {
val url = intent.data.toString()
if (isDeepLink(url)) {
this.currentUrl = url
val event = JSObject()
event.put("url", this.currentUrl)
this.channel?.send(event)
}
if (intent.action == Intent.ACTION_VIEW) {
this.currentUrl = intent.data.toString()
val event = JSObject()
event.put("url", this.currentUrl)
this.channel?.send(event)
}
}
private fun isDeepLink(url: String): Boolean {
val config = this.config ?: return false
if (config.mobile.isEmpty()) {
return false
}
val uri = try {
url.toUri()
} catch (_: Exception) {
// not a URL
return false
}
val scheme = uri.scheme ?: return false
val host = uri.host
val path = uri.path ?: ""
// Check if URL matches any configured mobile deep link
for (domain in config.mobile) {
// Check scheme
if (!domain.scheme.any { it.equals(scheme, ignoreCase = true) }) {
continue
}
// Check host (if configured)
if (domain.host != null) {
if (!host.equals(domain.host, ignoreCase = true)) {
continue
}
}
// Check path constraints
// According to Android docs:
// - path: exact match, must begin with /
// - pathPrefix: matches initial part of path
// - pathSuffix: matches ending part, doesn't need to begin with /
// - pathPattern: simple glob pattern (., *, .*)
val pathMatches = when {
// Exact path match (must begin with /)
domain.path.isNotEmpty() && domain.path.any { it == path } -> true
// Path pattern match (simple glob: ., *, .*)
domain.pathPattern.isNotEmpty() && domain.pathPattern.any { pattern ->
try {
PatternMatcher(pattern, PatternMatcher.PATTERN_SIMPLE_GLOB).match(path)
} catch (e: Exception) {
false
}
} -> true
// Path prefix match
domain.pathPrefix.isNotEmpty() && domain.pathPrefix.any { prefix ->
path.startsWith(prefix)
} -> true
// Path suffix match
domain.pathSuffix.isNotEmpty() && domain.pathSuffix.any { suffix ->
path.endsWith(suffix)
} -> true
// If no path constraints, any path is allowed
domain.path.isEmpty() && domain.pathPattern.isEmpty() &&
domain.pathPrefix.isEmpty() && domain.pathSuffix.isEmpty() -> true
else -> false
}
if (pathMatches) {
return true
}
}
return false
}
}
+26 -113
View File
@@ -10,64 +10,50 @@ const COMMANDS: &[&str] = &["get_current", "register", "unregister", "is_registe
// TODO: Consider using activity-alias in case users may have multiple activities in their app.
fn intent_filter(domain: &AssociatedDomain) -> String {
let host = domain
.host
.as_ref()
.map(|h| format!(r#"<data android:host="{h}" />"#))
.unwrap_or_default();
let auto_verify = if domain.is_app_link() {
r#"android:autoVerify="true" "#.to_string()
} else {
String::new()
};
format!(
r#"<intent-filter {auto_verify}>
r#"<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
{schemes}
{host}
{domains}
{path_patterns}
{path_prefixes}
{path_suffixes}
{}
<data android:host="{}" />
{}
{}
{}
{}
</intent-filter>"#,
schemes = domain
domain
.scheme
.iter()
.map(|scheme| format!(r#"<data android:scheme="{scheme}" />"#))
.collect::<Vec<_>>()
.join("\n "),
host = host,
domains = domain
domain.host,
domain
.path
.iter()
.map(|path| format!(r#"<data android:path="{path}" />"#))
.collect::<Vec<_>>()
.join("\n "),
path_patterns = domain
domain
.path_pattern
.iter()
.map(|pattern| format!(r#"<data android:pathPattern="{pattern}" />"#))
.collect::<Vec<_>>()
.join("\n "),
path_prefixes = domain
domain
.path_prefix
.iter()
.map(|prefix| format!(r#"<data android:pathPrefix="{prefix}" />"#))
.collect::<Vec<_>>()
.join("\n "),
path_suffixes = domain
domain
.path_suffix
.iter()
.map(|suffix| format!(r#"<data android:pathSuffix="{suffix}" />"#))
.collect::<Vec<_>>()
.join("\n "),
)
.trim()
.to_string()
}
fn main() {
@@ -82,16 +68,6 @@ fn main() {
}
if let Some(config) = tauri_plugin::plugin_config::<Config>("deep-link") {
let errors: Vec<String> = config
.mobile
.iter()
.filter_map(|d| d.validate().err())
.collect();
if !errors.is_empty() {
panic!("Deep link config validation failed:\n{}", errors.join("\n"));
}
tauri_plugin::mobile::update_android_manifest(
"DEEP LINK PLUGIN",
"activity",
@@ -104,83 +80,20 @@ fn main() {
)
.expect("failed to rewrite AndroidManifest.xml");
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[cfg(target_os = "macos")]
{
// we need to ensure that the entitlements are only
// generated for explicit app links and not
// other deep links because then they
// are just going to complain and not be built or signed
let has_app_links = config.mobile.iter().any(|d| d.is_app_link());
if !has_app_links {
tauri_plugin::mobile::update_entitlements(|entitlements| {
entitlements.remove("com.apple.developer.associated-domains");
})
.expect("failed to update entitlements");
} else {
tauri_plugin::mobile::update_entitlements(|entitlements| {
entitlements.insert(
"com.apple.developer.associated-domains".into(),
config
.mobile
.iter()
.filter(|d| d.is_app_link())
.filter_map(|d| d.host.as_ref())
.map(|host| format!("applinks:{}", host).into())
.collect::<Vec<_>>()
.into(),
);
})
.expect("failed to update entitlements");
}
let deep_link_domains = config
.mobile
.iter()
.filter(|domain| domain.is_app_link())
.collect::<Vec<_>>();
if deep_link_domains.is_empty() {
tauri_plugin::mobile::update_info_plist(|info_plist| {
info_plist.remove("CFBundleURLTypes");
})
.expect("failed to update Info.plist");
} else {
tauri_plugin::mobile::update_info_plist(|info_plist| {
info_plist.insert(
"CFBundleURLTypes".into(),
deep_link_domains
.iter()
.map(|domain| {
let schemes = domain
.scheme
.iter()
.filter(|scheme| {
scheme.as_str() != "https" && scheme.as_str() != "http"
})
.collect::<Vec<_>>();
let mut dict = plist::Dictionary::new();
dict.insert(
"CFBundleURLSchemes".into(),
schemes
.iter()
.map(|s| s.to_string().into())
.collect::<Vec<_>>()
.into(),
);
dict.insert(
"CFBundleURLName".into(),
domain.scheme[0].clone().into(),
);
plist::Value::Dictionary(dict)
})
.collect::<Vec<_>>()
.into(),
);
})
.expect("failed to update Info.plist");
}
tauri_plugin::mobile::update_entitlements(|entitlements| {
entitlements.insert(
"com.apple.developer.associated-domains".into(),
config
.mobile
.into_iter()
.map(|d| format!("applinks:{}", d.host).into())
.collect::<Vec<_>>()
.into(),
);
})
.expect("failed to update entitlements");
}
}
}
@@ -1,41 +1,5 @@
# Changelog
## \[2.2.10]
### Dependencies
- Upgraded to `deep-link-js@2.4.7`
## \[2.2.9]
### Dependencies
- Upgraded to `deep-link-js@2.4.6`
## \[2.2.8]
### Dependencies
- Upgraded to `deep-link-js@2.4.5`
## \[2.2.7]
### Dependencies
- Upgraded to `deep-link-js@2.4.4`
## \[2.2.6]
### Dependencies
- Upgraded to `deep-link-js@2.4.3`
## \[2.2.5]
### Dependencies
- Upgraded to `deep-link-js@2.4.2`
## \[2.2.4]
### Dependencies
+5 -5
View File
@@ -1,7 +1,7 @@
{
"name": "deep-link-example",
"private": true,
"version": "2.2.10",
"version": "2.2.4",
"type": "module",
"scripts": {
"dev": "vite",
@@ -10,12 +10,12 @@
"tauri": "tauri"
},
"dependencies": {
"@tauri-apps/api": "^2.10.1",
"@tauri-apps/plugin-deep-link": "2.4.7"
"@tauri-apps/api": "2.7.0",
"@tauri-apps/plugin-deep-link": "2.4.1"
},
"devDependencies": {
"@tauri-apps/cli": "2.10.1",
"@tauri-apps/cli": "2.7.1",
"typescript": "^5.7.3",
"vite": "^7.3.1"
"vite": "^7.0.4"
}
}
@@ -19,9 +19,7 @@ tauri-build = { workspace = true }
[dependencies]
serde = { workspace = true }
serde_json = { workspace = true }
tauri = { workspace = true }
tauri-runtime-wry = { workspace = true, optional = true }
tauri-runtime-cef = { workspace = true, optional = true }
tauri = { workspace = true, features = ["wry", "common-controls-v6", "x11"] }
tauri-plugin-deep-link = { path = "../../../" }
tauri-plugin-log = { path = "../../../../log" }
tauri-plugin-single-instance = { path = "../../../../single-instance", features = [
@@ -30,9 +28,6 @@ tauri-plugin-single-instance = { path = "../../../../single-instance", features
log = "0.4"
[features]
default = ["wry"]
wry = ["dep:tauri-runtime-wry"]
cef = ["dep:tauri-runtime-cef"]
# this feature is used for production builds or when `devUrl` points to the filesystem and the built-in dev server is disabled.
# If you use cargo directly instead of tauri's cli you can use this feature flag to switch between tauri's `dev` and `build` modes.
# DO NOT REMOVE!!
@@ -14,13 +14,13 @@ val tauriProperties = Properties().apply {
}
android {
compileSdk = 36
compileSdk = 34
namespace = "com.tauri.deep_link_example"
defaultConfig {
manifestPlaceholders["usesCleartextTraffic"] = "false"
applicationId = "com.tauri.deep_link_example"
minSdk = 24
targetSdk = 36
targetSdk = 34
versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt()
versionName = tauriProperties.getProperty("tauri.android.versionName", "1.0")
}
@@ -58,10 +58,9 @@ rust {
}
dependencies {
implementation("androidx.webkit:webkit:1.14.0")
implementation("androidx.appcompat:appcompat:1.7.1")
implementation("androidx.activity:activity-ktx:1.10.1")
implementation("com.google.android.material:material:1.12.0")
implementation("androidx.webkit:webkit:1.6.1")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.8.0")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.4")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.0")
@@ -23,40 +23,23 @@
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
<!-- DEEP LINK PLUGIN. AUTO-GENERATED. DO NOT REMOVE. -->
<intent-filter android:autoVerify="true" >
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="fabianlars.de" />
<data android:pathPrefix="/intent" />
</intent-filter>
<intent-filter android:autoVerify="true" >
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="tauri.app" />
</intent-filter>
<intent-filter >
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="taurideeplink" />
</intent-filter>
<!-- DEEP LINK PLUGIN. AUTO-GENERATED. DO NOT REMOVE. -->
</activity>
@@ -1,11 +1,7 @@
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
package com.tauri.deep_link_example
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
class MainActivity : TauriActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge()
super.onCreate(savedInstanceState)
}
}
class MainActivity : TauriActivity()
@@ -4,7 +4,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:8.11.0")
classpath("com.android.tools.build:gradle:8.5.1")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.25")
}
}
@@ -18,6 +18,6 @@ repositories {
dependencies {
compileOnly(gradleApi())
implementation("com.android.tools.build:gradle:8.11.0")
implementation("com.android.tools.build:gradle:8.5.1")
}
@@ -1,6 +1,6 @@
#Tue May 10 19:22:52 CST 2022
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
@@ -1,116 +1,116 @@
{
"images" : [
"images": [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "AppIcon-20x20@2x.png",
"scale" : "2x"
"size": "20x20",
"idiom": "iphone",
"filename": "AppIcon-20x20@2x.png",
"scale": "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "AppIcon-20x20@3x.png",
"scale" : "3x"
"size": "20x20",
"idiom": "iphone",
"filename": "AppIcon-20x20@3x.png",
"scale": "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "AppIcon-29x29@2x-1.png",
"scale" : "2x"
"size": "29x29",
"idiom": "iphone",
"filename": "AppIcon-29x29@2x-1.png",
"scale": "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "AppIcon-29x29@3x.png",
"scale" : "3x"
"size": "29x29",
"idiom": "iphone",
"filename": "AppIcon-29x29@3x.png",
"scale": "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "AppIcon-40x40@2x.png",
"scale" : "2x"
"size": "40x40",
"idiom": "iphone",
"filename": "AppIcon-40x40@2x.png",
"scale": "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "AppIcon-40x40@3x.png",
"scale" : "3x"
"size": "40x40",
"idiom": "iphone",
"filename": "AppIcon-40x40@3x.png",
"scale": "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "AppIcon-60x60@2x.png",
"scale" : "2x"
"size": "60x60",
"idiom": "iphone",
"filename": "AppIcon-60x60@2x.png",
"scale": "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "AppIcon-60x60@3x.png",
"scale" : "3x"
"size": "60x60",
"idiom": "iphone",
"filename": "AppIcon-60x60@3x.png",
"scale": "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "AppIcon-20x20@1x.png",
"scale" : "1x"
"size": "20x20",
"idiom": "ipad",
"filename": "AppIcon-20x20@1x.png",
"scale": "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "AppIcon-20x20@2x-1.png",
"scale" : "2x"
"size": "20x20",
"idiom": "ipad",
"filename": "AppIcon-20x20@2x-1.png",
"scale": "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "AppIcon-29x29@1x.png",
"scale" : "1x"
"size": "29x29",
"idiom": "ipad",
"filename": "AppIcon-29x29@1x.png",
"scale": "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "AppIcon-29x29@2x.png",
"scale" : "2x"
"size": "29x29",
"idiom": "ipad",
"filename": "AppIcon-29x29@2x.png",
"scale": "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "AppIcon-40x40@1x.png",
"scale" : "1x"
"size": "40x40",
"idiom": "ipad",
"filename": "AppIcon-40x40@1x.png",
"scale": "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "AppIcon-40x40@2x-1.png",
"scale" : "2x"
"size": "40x40",
"idiom": "ipad",
"filename": "AppIcon-40x40@2x-1.png",
"scale": "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "AppIcon-76x76@1x.png",
"scale" : "1x"
"size": "76x76",
"idiom": "ipad",
"filename": "AppIcon-76x76@1x.png",
"scale": "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "AppIcon-76x76@2x.png",
"scale" : "2x"
"size": "76x76",
"idiom": "ipad",
"filename": "AppIcon-76x76@2x.png",
"scale": "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "AppIcon-83.5x83.5@2x.png",
"scale" : "2x"
"size": "83.5x83.5",
"idiom": "ipad",
"filename": "AppIcon-83.5x83.5@2x.png",
"scale": "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "AppIcon-512@2x.png",
"scale" : "1x"
"size": "1024x1024",
"idiom": "ios-marketing",
"filename": "AppIcon-512@2x.png",
"scale": "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"info": {
"version": 1,
"author": "xcode"
}
}
}
@@ -1,6 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
"info": {
"version": 1,
"author": "xcode"
}
}
}
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17150" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Y6W-OH-hqX">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17150" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17122"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 63;
objectVersion = 56;
objects = {
/* Begin PBXBuildFile section */
@@ -167,8 +167,6 @@
dependencies = (
);
name = "deep-link-example_iOS";
packageProductDependencies = (
);
productName = "deep-link-example_iOS";
productReference = 1CAAFA750FD735A285DC1238 /* deep-link-example.app */;
productType = "com.apple.product-type.application";
@@ -191,7 +189,6 @@
en,
);
mainGroup = 1DC58B1705AA3ECC6B887FE7;
minimizedProjectReferenceProxies = 1;
projectDirPath = "";
projectRoot = "";
targets = (
@@ -230,6 +227,7 @@
outputPaths = (
"$(SRCROOT)/Externals/x86_64/${CONFIGURATION}/libapp.a",
"$(SRCROOT)/Externals/arm64/${CONFIGURATION}/libapp.a",
"$(SRCROOT)/Externals/arm64-sim/${CONFIGURATION}/libapp.a",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@@ -316,13 +314,18 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ARCHS = arm64;
ARCHS = (
arm64,
"arm64-sim",
);
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = "deep-link-example_iOS/deep-link-example_iOS.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
DEVELOPMENT_TEAM = "Q93MBH6S2F";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = Q93MBH6S2F;
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphoneos*]" = x86_64;
"EXCLUDED_ARCHS[sdk=iphoneos*]" = "arm64-sim x86_64";
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\".\"",
@@ -332,6 +335,13 @@
"$(inherited)",
"@executable_path/Frameworks",
);
"LIBRARY_SEARCH_PATHS[arch=arm64-sim]" = (
"$(inherited)",
"$(PROJECT_DIR)/Externals/arm64-sim/$(CONFIGURATION)",
"$(SDKROOT)/usr/lib/swift",
"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)",
"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)",
);
"LIBRARY_SEARCH_PATHS[arch=arm64]" = (
"$(inherited)",
"$(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION)",
@@ -350,7 +360,7 @@
PRODUCT_NAME = "deep-link-example";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = arm64;
VALID_ARCHS = "arm64 arm64-sim";
};
name = debug;
};
@@ -414,13 +424,18 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ARCHS = arm64;
ARCHS = (
arm64,
"arm64-sim",
);
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = "deep-link-example_iOS/deep-link-example_iOS.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
DEVELOPMENT_TEAM = "Q93MBH6S2F";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = Q93MBH6S2F;
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphoneos*]" = x86_64;
"EXCLUDED_ARCHS[sdk=iphoneos*]" = "arm64-sim x86_64";
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\".\"",
@@ -430,6 +445,13 @@
"$(inherited)",
"@executable_path/Frameworks",
);
"LIBRARY_SEARCH_PATHS[arch=arm64-sim]" = (
"$(inherited)",
"$(PROJECT_DIR)/Externals/arm64-sim/$(CONFIGURATION)",
"$(SDKROOT)/usr/lib/swift",
"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)",
"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)",
);
"LIBRARY_SEARCH_PATHS[arch=arm64]" = (
"$(inherited)",
"$(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION)",
@@ -448,7 +470,7 @@
PRODUCT_NAME = "deep-link-example";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = arm64;
VALID_ARCHS = "arm64 arm64-sim";
};
name = release;
};
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.1.0</string>
<string>0.0.0</string>
<key>CFBundleVersion</key>
<string>0.1.0</string>
<key>LSRequiresIPhoneOS</key>
@@ -40,16 +40,5 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>taurideeplink</string>
</array>
<key>CFBundleURLName</key>
<string>taurideeplink</string>
</dict>
</array>
</dict>
</plist>
@@ -1,3 +1,7 @@
# Copyright 2019-2023 Tauri Programme within The Commons Conservancy
# SPDX-License-Identifier: Apache-2.0
# SPDX-License-Identifier: MIT
name: deep-link-example
options:
bundleIdPrefix: com.tauri.deep-link-example
@@ -12,6 +16,7 @@ settingGroups:
base:
PRODUCT_NAME: deep-link-example
PRODUCT_BUNDLE_IDENTIFIER: com.tauri.deep-link-example
DEVELOPMENT_TEAM: Q93MBH6S2F
targetTemplates:
app:
type: application
@@ -51,8 +56,8 @@ targets:
- UIInterfaceOrientationPortraitUpsideDown
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
CFBundleShortVersionString: 0.1.0
CFBundleVersion: '0.1.0'
CFBundleShortVersionString: 0.0.0
CFBundleVersion: 0.0.0
entitlements:
path: deep-link-example_iOS/deep-link-example_iOS.entitlements
scheme:
@@ -62,12 +67,14 @@ targets:
settings:
base:
ENABLE_BITCODE: false
ARCHS: [arm64]
VALID_ARCHS: arm64
ARCHS: [arm64, arm64-sim]
VALID_ARCHS: arm64 arm64-sim
LIBRARY_SEARCH_PATHS[arch=x86_64]: $(inherited) $(PROJECT_DIR)/Externals/x86_64/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)
LIBRARY_SEARCH_PATHS[arch=arm64]: $(inherited) $(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)
LIBRARY_SEARCH_PATHS[arch=arm64-sim]: $(inherited) $(PROJECT_DIR)/Externals/arm64-sim/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES: true
EXCLUDED_ARCHS[sdk=iphoneos*]: x86_64
EXCLUDED_ARCHS[sdk=iphonesimulator*]: arm64
EXCLUDED_ARCHS[sdk=iphoneos*]: arm64-sim x86_64
groups: [app]
dependencies:
- framework: libapp.a
@@ -86,3 +93,4 @@ targets:
outputFiles:
- $(SRCROOT)/Externals/x86_64/${CONFIGURATION}/libapp.a
- $(SRCROOT)/Externals/arm64/${CONFIGURATION}/libapp.a
- $(SRCROOT)/Externals/arm64-sim/${CONFIGURATION}/libapp.a
@@ -2,11 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
#[cfg(feature = "cef")]
type TauriRuntime = tauri_runtime_cef::CefRuntime<tauri::EventLoopMessage>;
#[cfg(feature = "wry")]
type TauriRuntime = tauri_runtime_wry::Wry<tauri::EventLoopMessage>;
use tauri_plugin_deep_link::DeepLinkExt;
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
@@ -18,7 +13,7 @@ fn greet(name: &str) -> String {
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
#[allow(unused_mut)]
let mut builder = tauri::Builder::<TauriRuntime>::new();
let mut builder = tauri::Builder::default();
#[cfg(desktop)]
{
@@ -35,9 +35,6 @@
},
{
"host": "tauri.app"
},
{
"scheme": ["taurideeplink"]
}
],
"desktop": {
+2 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-deep-link",
"version": "2.4.7",
"version": "2.4.1",
"description": "Set your Tauri application as the default handler for an URL",
"license": "MIT OR Apache-2.0",
"authors": [
@@ -25,9 +25,6 @@
"LICENSE"
],
"dependencies": {
"@tauri-apps/api": "^2.10.1"
},
"devDependencies": {
"@tauri-apps/cli": "2.10.1"
"@tauri-apps/api": "^2.6.0"
}
}
+100 -31
View File
@@ -24,17 +24,20 @@
},
"permission": {
"description": "A list of inlined permissions",
"default": [],
"type": "array",
"items": {
"$ref": "#/definitions/Permission"
},
"default": []
}
}
},
"definitions": {
"DefaultPermission": {
"description": "The default permission set of the plugin.\n\nWorks similarly to a permission with the \"default\" identifier.",
"type": "object",
"required": [
"permissions"
],
"properties": {
"version": {
"description": "The version of the permission.",
@@ -43,10 +46,10 @@
"null"
],
"format": "uint64",
"minimum": 1
"minimum": 1.0
},
"description": {
"description": "Human-readable description of what the permission does.\nTauri convention is to use `<h4>` headings in markdown content\nfor Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -59,14 +62,16 @@
"type": "string"
}
}
},
"required": [
"permissions"
]
}
},
"PermissionSet": {
"description": "A set of direct permissions grouped together under a new name.",
"type": "object",
"required": [
"description",
"identifier",
"permissions"
],
"properties": {
"identifier": {
"description": "A unique identifier for the permission.",
@@ -80,19 +85,17 @@
"description": "All permissions this set contains.",
"type": "array",
"items": {
"type": "string"
"$ref": "#/definitions/PermissionKind"
}
}
},
"required": [
"identifier",
"description",
"permissions"
]
}
},
"Permission": {
"description": "Descriptions of explicit privileges of commands.\n\nIt can enable commands to be accessible in the frontend of the application.\n\nIf the scope is defined it can be used to fine grain control the access of individual or multiple commands.",
"type": "object",
"required": [
"identifier"
],
"properties": {
"version": {
"description": "The version of the permission.",
@@ -101,14 +104,14 @@
"null"
],
"format": "uint64",
"minimum": 1
"minimum": 1.0
},
"identifier": {
"description": "A unique identifier for the permission.",
"type": "string"
},
"description": {
"description": "Human-readable description of what the permission does.\nTauri internal convention is to use `<h4>` headings in markdown content\nfor Tauri documentation generation purposes.",
"description": "Human-readable description of what the permission does. Tauri internal convention is to use `<h4>` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -144,10 +147,7 @@
"$ref": "#/definitions/Target"
}
}
},
"required": [
"identifier"
]
}
},
"Commands": {
"description": "Allowed and denied commands inside a permission.\n\nIf two commands clash inside of `allow` and `deny`, it should be denied by default.",
@@ -155,24 +155,24 @@
"properties": {
"allow": {
"description": "Allowed command.",
"default": [],
"type": "array",
"items": {
"type": "string"
},
"default": []
}
},
"deny": {
"description": "Denied command, which takes priority.",
"default": [],
"type": "array",
"items": {
"type": "string"
},
"default": []
}
}
}
},
"Scopes": {
"description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command.\nThe configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json\n{\n \"allow\": [{ \"path\": \"$HOME/**\" }],\n \"deny\": [{ \"path\": \"$HOME/secret.txt\" }]\n}\n```",
"description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command. The configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json { \"allow\": [{ \"path\": \"$HOME/**\" }], \"deny\": [{ \"path\": \"$HOME/secret.txt\" }] } ```",
"type": "object",
"properties": {
"allow": {
@@ -257,27 +257,96 @@
{
"description": "MacOS.",
"type": "string",
"const": "macOS"
"enum": [
"macOS"
]
},
{
"description": "Windows.",
"type": "string",
"const": "windows"
"enum": [
"windows"
]
},
{
"description": "Linux.",
"type": "string",
"const": "linux"
"enum": [
"linux"
]
},
{
"description": "Android.",
"type": "string",
"const": "android"
"enum": [
"android"
]
},
{
"description": "iOS.",
"type": "string",
"const": "iOS"
"enum": [
"iOS"
]
}
]
},
"PermissionKind": {
"type": "string",
"oneOf": [
{
"description": "Enables the get_current command without any pre-configured scope.",
"type": "string",
"const": "allow-get-current",
"markdownDescription": "Enables the get_current command without any pre-configured scope."
},
{
"description": "Denies the get_current command without any pre-configured scope.",
"type": "string",
"const": "deny-get-current",
"markdownDescription": "Denies the get_current command without any pre-configured scope."
},
{
"description": "Enables the is_registered command without any pre-configured scope.",
"type": "string",
"const": "allow-is-registered",
"markdownDescription": "Enables the is_registered command without any pre-configured scope."
},
{
"description": "Denies the is_registered command without any pre-configured scope.",
"type": "string",
"const": "deny-is-registered",
"markdownDescription": "Denies the is_registered command without any pre-configured scope."
},
{
"description": "Enables the register command without any pre-configured scope.",
"type": "string",
"const": "allow-register",
"markdownDescription": "Enables the register command without any pre-configured scope."
},
{
"description": "Denies the register command without any pre-configured scope.",
"type": "string",
"const": "deny-register",
"markdownDescription": "Denies the register command without any pre-configured scope."
},
{
"description": "Enables the unregister command without any pre-configured scope.",
"type": "string",
"const": "allow-unregister",
"markdownDescription": "Enables the unregister command without any pre-configured scope."
},
{
"description": "Denies the unregister command without any pre-configured scope.",
"type": "string",
"const": "deny-unregister",
"markdownDescription": "Denies the unregister command without any pre-configured scope."
},
{
"description": "Allows reading the opened deep link via the get_current command\n#### This default permission set includes:\n\n- `allow-get-current`",
"type": "string",
"const": "default",
"markdownDescription": "Allows reading the opened deep link via the get_current command\n#### This default permission set includes:\n\n- `allow-get-current`"
}
]
}
+12 -46
View File
@@ -11,8 +11,10 @@ use tauri_utils::config::DeepLinkProtocol;
pub struct AssociatedDomain {
#[serde(default = "default_schemes")]
pub scheme: Vec<String>,
#[serde(default, deserialize_with = "deserialize_associated_host")]
pub host: Option<String>, // Optional custom uri schemes dont NEED a host (may have one still), but required for https/http schemes
#[serde(deserialize_with = "deserialize_associated_host")]
pub host: String,
#[serde(default)]
pub path: Vec<String>,
#[serde(default, alias = "path-pattern", rename = "pathPattern")]
@@ -21,41 +23,6 @@ pub struct AssociatedDomain {
pub path_prefix: Vec<String>,
#[serde(default, alias = "path-suffix", rename = "pathSuffix")]
pub path_suffix: Vec<String>,
#[serde(default, alias = "app-link", rename = "appLink")]
pub app_link: Option<bool>,
}
impl AssociatedDomain {
/// Returns true if the domain uses http or https scheme.
pub fn is_web_link(&self) -> bool {
self.scheme.iter().any(|s| s == "https" || s == "http")
}
/// Returns true if the domain uses http or https scheme and has proper host configuration.
pub fn is_app_link(&self) -> bool {
self.app_link
.unwrap_or_else(|| self.is_web_link() && self.host.is_some())
}
pub fn validate(&self) -> Result<(), String> {
// Rule 1: All web links require a host.
if self.is_web_link() && self.host.is_none() {
return Err("Web link requires a host".into());
}
// Rule 2: If it's an App Link, ensure http(s) and host.
if self.is_app_link() {
if !self.is_web_link() {
return Err("AppLink must be a valid web link (https/http + host)".into());
}
if self.scheme.iter().any(|s| s == "http") && !self.scheme.iter().any(|s| s == "https")
{
eprintln!("Warning: AppLink uses only 'http' — allowed on Android but not secure for production.");
}
}
Ok(())
}
}
// TODO: Consider removing this in v3
@@ -63,19 +30,18 @@ fn default_schemes() -> Vec<String> {
vec!["https".to_string(), "http".to_string()]
}
fn deserialize_associated_host<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
fn deserialize_associated_host<'de, D>(deserializer: D) -> Result<String, D::Error>
where
D: Deserializer<'de>,
{
let opt = Option::<String>::deserialize(deserializer)?;
if let Some(ref host) = opt {
if let Some((scheme, _)) = host.split_once("://") {
return Err(serde::de::Error::custom(format!(
"host `{host}` cannot start with a scheme, please remove the `{scheme}://` prefix"
)));
}
let host = String::deserialize(deserializer)?;
if let Some((scheme, _host)) = host.split_once("://") {
Err(serde::de::Error::custom(format!(
"host `{host}` cannot start with a scheme, please remove the `{scheme}://` prefix"
)))
} else {
Ok(host)
}
Ok(opt)
}
#[derive(Deserialize, Clone)]
-10
View File
@@ -28,16 +28,6 @@ pub enum Error {
PluginInvoke(#[from] tauri::plugin::mobile::PluginInvokeError),
}
// TODO(v3): change this into an error in v3,
// see <https://github.com/tauri-apps/plugins-workspace/pull/2970#issuecomment-3244660138>.
#[inline]
#[cfg(target_os = "linux")]
pub(crate) fn inspect_command_error<'a>(command: &'a str) -> impl Fn(&std::io::Error) + 'a {
move |e| {
tracing::error!("Failed to run OS command `{command}`: {e}");
}
}
impl Serialize for Error {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
+7 -31
View File
@@ -254,7 +254,6 @@ mod imp {
///
/// ## Platform-specific:
///
/// - **Linux**: Needs the `xdg-mime` and `update-desktop-database` commands available on the system.
/// - **macOS / Android / iOS**: Unsupported, will return [`Error::UnsupportedPlatform`](`crate::Error::UnsupportedPlatform`).
pub fn register<S: AsRef<str>>(&self, _protocol: S) -> crate::Result<()> {
#[cfg(windows)]
@@ -293,7 +292,6 @@ mod imp {
.unwrap_or_else(|| bin.into_os_string())
.to_string_lossy()
.to_string();
let qualified_exec = format!("\"{}\" %u", exec);
let target = self.app.path().data_dir()?.join("applications");
@@ -305,28 +303,12 @@ mod imp {
if let Ok(mut desktop_file) = ini::Ini::load_from_file(&target_file) {
if let Some(section) = desktop_file.section_mut(Some("Desktop Entry")) {
// it's ok to remove it - we only write to the file if it's missing
// and in that case we include old_mimes
let old_mimes = section.remove("MimeType").unwrap_or_default();
let mut change = false;
// if the mime type is not present, append it to the list
if !old_mimes.split(';').any(|mime| mime == mime_type) {
section.append("MimeType", format!("{mime_type};{old_mimes}"));
change = true;
} else {
section.insert("MimeType".to_string(), old_mimes);
}
// if the exec command doesnt match, update to the new one
let old_exec = section.remove("Exec").unwrap_or_default();
if old_exec != qualified_exec {
section.append("Exec", qualified_exec);
change = true;
} else {
section.insert("Exec".to_string(), old_exec.to_string());
}
// if any property has changed, rewrite the .desktop file
if change {
desktop_file.write_to_file(&target_file)?;
}
}
@@ -341,7 +323,7 @@ mod imp {
.product_name
.clone()
.unwrap_or_else(|| file_name.clone()),
qualified_exec = qualified_exec,
exec = exec,
mime_type = mime_type
)
.as_bytes(),
@@ -350,15 +332,11 @@ mod imp {
Command::new("update-desktop-database")
.arg(target)
.status()
.inspect_err(crate::error::inspect_command_error(
"update-desktop-database",
))?;
.status()?;
Command::new("xdg-mime")
.args(["default", &file_name, mime_type.as_str()])
.status()
.inspect_err(crate::error::inspect_command_error("xdg-mime"))?;
.status()?;
Ok(())
}
@@ -427,7 +405,6 @@ mod imp {
///
/// ## Platform-specific:
///
/// - **Linux**: Needs the `xdg-mime` command available on the system.
/// - **macOS / Android / iOS**: Unsupported, will return [`Error::UnsupportedPlatform`](`crate::Error::UnsupportedPlatform`).
pub fn is_registered<S: AsRef<str>>(&self, _protocol: S) -> crate::Result<bool> {
#[cfg(windows)]
@@ -462,8 +439,7 @@ mod imp {
"default",
&format!("x-scheme-handler/{}", _protocol.as_ref()),
])
.output()
.inspect_err(crate::error::inspect_command_error("xdg-mime"))?;
.output()?;
Ok(String::from_utf8_lossy(&output.stdout).contains(&file_name))
}
@@ -540,7 +516,7 @@ pub fn init<R: Runtime>() -> TauriPlugin<R, Option<config::Config>> {
Ok(())
})
.on_event(|_app, _event| {
#[cfg(desktop)]
#[cfg(any(target_os = "macos", target_os = "ios"))]
if let tauri::RunEvent::Opened { urls } = _event {
use tauri::Emitter;
+2 -2
View File
@@ -1,7 +1,7 @@
[Desktop Entry]
Type=Application
Name={name}
Exec={qualified_exec}
Exec={exec} %u
Terminal=false
MimeType={mime_type}
NoDisplay=true
NoDisplay=true
-42
View File
@@ -1,47 +1,5 @@
# 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.
### Dependencies
- Upgraded to `fs-js@2.4.4`
## \[2.4.1]
- [`6c9b61fb`](https://github.com/tauri-apps/plugins-workspace/commit/6c9b61fb658145d13893626112fc489f7458aa17) ([#3039](https://github.com/tauri-apps/plugins-workspace/pull/3039) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) On Android, updated compileSdk to 36.
### Dependencies
- Upgraded to `fs-js@2.4.3`
## \[2.4.0]
- [`509eba8d`](https://github.com/tauri-apps/plugins-workspace/commit/509eba8d441c4f6ecf0af77b572cb2afd69a752d) ([#2641](https://github.com/tauri-apps/plugins-workspace/pull/2641) by [@amrbashir](https://github.com/tauri-apps/plugins-workspace/../../amrbashir)) Add support for showing a message dialog with 3 buttons.
## \[2.3.3]
### Dependencies
- Upgraded to `fs-js@2.4.2`
## \[2.3.2]
- [`af08c66f`](https://github.com/tauri-apps/plugins-workspace/commit/af08c66faafe0dffc4b0a80aef030cd3f0f89a9c) ([#2871](https://github.com/tauri-apps/plugins-workspace/pull/2871) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Fixed an issue that caused the file picker not to open on Android when extension filters were set.
+9 -11
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-dialog"
version = "2.6.0"
version = "2.3.2"
description = "Native system dialogs for opening and saving files along with message dialogs on your Tauri application."
edition = { workspace = true }
authors = { workspace = true }
@@ -9,12 +9,9 @@ rust-version = { workspace = true }
repository = { workspace = true }
links = "tauri-plugin-dialog"
[features]
default = ["gtk3"]
xdg-portal = ["rfd/xdg-portal", "rfd/tokio", "rfd/wayland"]
gtk3 = ["rfd/gtk3"]
[package.metadata.docs.rs]
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
targets = ["x86_64-unknown-linux-gnu", "x86_64-linux-android"]
[package.metadata.platforms.support]
@@ -28,7 +25,7 @@ ios = { level = "partial", notes = "Does not support folder picker" }
tauri-plugin = { workspace = true, features = ["build"] }
[dev-dependencies]
tauri = { workspace = true }
tauri = { workspace = true, features = ["wry"] }
[dependencies]
serde = { workspace = true }
@@ -37,14 +34,15 @@ tauri = { workspace = true }
log = { workspace = true }
thiserror = { workspace = true }
url = { workspace = true }
tauri-plugin-fs = { path = "../fs", version = "2.4.5" }
tauri-plugin-fs = { path = "../fs", version = "2.4.1" }
[target.'cfg(target_os = "ios")'.dependencies]
tauri = { workspace = true }
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.16", default-features = false, features = [
rfd = { version = "0.15", default-features = false, features = [
"tokio",
"gtk3",
"common-controls-v6",
] }
raw-window-handle = "0.6"
-18
View File
@@ -31,24 +31,6 @@ tauri-plugin-dialog = "2.0.0"
tauri-plugin-dialog = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
### Linux XDG Desktop Portal Support
By default, this plugin uses gtk to show dialogs, however since `v2.5.0` you can switch to using [XDG Desktop Portal](https://flatpak.github.io/xdg-desktop-portal/) by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
tauri-plugin-dialog = { version = "2.5.0", default-features = false, features = ["xdg-portal"] }
# alternatively with Git:
tauri-plugin-dialog = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2", default-features = false, features = ["xdg-portal"] }
```
Do note if you use the `xdg-portal` feature, you need to ensure that [`zenity`](https://gitlab.gnome.org/GNOME/zenity) and an [XDG Desktop Portal backend](https://flatpak.github.io/xdg-desktop-portal#using-portals) is installed with your program.
For more information, see [XDG Desktop Portal documentation](https://flatpak.github.io/xdg-desktop-portal/) and [`rfd` documentation](https://docs.rs/rfd/latest/rfd#xdg-desktop-portal-backend).
### JavaScript
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
```sh
+2 -2
View File
@@ -5,10 +5,10 @@ plugins {
android {
namespace = "app.tauri.dialog"
compileSdk = 36
compileSdk = 34
defaultConfig {
minSdk = 24
minSdk = 24
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
@@ -31,7 +31,6 @@ class Filter {
class FilePickerOptions {
lateinit var filters: Array<Filter>
var multiple: Boolean? = null
var pickerMode: String? = null
}
@InvokeArg
@@ -39,7 +38,6 @@ class MessageOptions {
var title: String? = null
lateinit var message: String
var okButtonLabel: String? = null
var noButtonLabel: String? = null
var cancelButtonLabel: String? = null
}
@@ -62,19 +60,10 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) {
// TODO: ACTION_OPEN_DOCUMENT ??
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "*/*"
if (args.pickerMode == "image") {
intent.type = "image/*"
} else if (args.pickerMode == "video") {
intent.type = "video/*"
} else if (args.pickerMode == "media") {
intent.type = "*/*"
intent.putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("video/*", "image/*"))
} else if (parsedTypes.isNotEmpty()) {
intent.type = "*/*"
if (parsedTypes.isNotEmpty()) {
intent.putExtra(Intent.EXTRA_MIME_TYPES, parsedTypes)
} else {
intent.type = "*/*"
}
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, args.multiple ?: false)
@@ -150,8 +139,9 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) {
return
}
val handler = { value: String ->
val handler = { cancelled: Boolean, value: Boolean ->
val ret = JSObject()
ret.put("cancelled", cancelled)
ret.put("value", value)
invoke.resolve(ret)
}
@@ -163,34 +153,24 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) {
if (args.title != null) {
builder.setTitle(args.title)
}
val okButtonLabel = args.okButtonLabel ?: "Ok"
builder
.setMessage(args.message)
.setPositiveButton(okButtonLabel) { dialog, _ ->
.setPositiveButton(
args.okButtonLabel ?: "OK"
) { dialog, _ ->
dialog.dismiss()
handler(okButtonLabel)
handler(false, true)
}
.setOnCancelListener { dialog ->
dialog.dismiss()
handler(args.cancelButtonLabel ?: "Cancel")
handler(true, false)
}
if (args.noButtonLabel != null) {
builder.setNeutralButton(args.noButtonLabel) { dialog, _ ->
dialog.dismiss()
handler(args.noButtonLabel!!)
}
}
if (args.cancelButtonLabel != null) {
builder.setNegativeButton( args.cancelButtonLabel) { dialog, _ ->
dialog.dismiss()
handler(args.cancelButtonLabel!!)
handler(false, false)
}
}
val dialog = builder.create()
dialog.show()
}

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