Compare commits

..

1 Commits

Author SHA1 Message Date
FabianLars 14381190e7 chore: Apply clippy suggestions 2025-07-23 12:44:36 +02:00
293 changed files with 2410 additions and 5767 deletions
@@ -1,6 +0,0 @@
---
"dialog-js": minor:feat
"dialog": minor:feat
---
Add `xdg-portal` as an optional feature for `rfd`
@@ -1,6 +0,0 @@
---
"log": "minor"
"log-js": "minor"
---
Allow specifying a log formatter per target using the `format` method on `Target`.
-10
View File
@@ -78,7 +78,6 @@
"notification", "notification",
"os", "os",
"process", "process",
"secure-storage",
"shell", "shell",
"store", "store",
"updater", "updater",
@@ -105,7 +104,6 @@
"notification-js", "notification-js",
"os-js", "os-js",
"process-js", "process-js",
"secure-storage-js",
"shell-js", "shell-js",
"store-js", "store-js",
"updater-js" "updater-js"
@@ -284,14 +282,6 @@
"path": "./plugins/process", "path": "./plugins/process",
"manager": "javascript" "manager": "javascript"
}, },
"secure-storage": {
"path": "./plugins/secure-storage",
"manager": "rust"
},
"secure-storage-js": {
"path": "./plugins/secure-storage",
"manager": "javascript"
},
"shell": { "shell": {
"path": "./plugins/shell", "path": "./plugins/shell",
"manager": "rust" "manager": "rust"
-6
View File
@@ -1,6 +0,0 @@
---
stronghold: patch
stronghold-js: patch
---
The `stronghold` plugin is now deprecated and will be removed in v3. The `secure-storage` plugin should be a replacement for most use-cases.
-6
View File
@@ -1,6 +0,0 @@
---
"dialog": minor
"dialog-js": minor
---
Add `pickerMode` option to file picker (currently only used on iOS)
@@ -1,5 +0,0 @@
---
"localhost": patch
---
Disable caching on responses.
@@ -1,6 +0,0 @@
---
"barcode-scanner": patch
"barcode-scanner-js": patch
---
Fix the `cameraView` is not removed after scanning in iOS.
-6
View File
@@ -1,6 +0,0 @@
---
"log": patch
"log-js": patch
---
Fix log file rotation when exceeding `max_file_size`.
-6
View File
@@ -1,6 +0,0 @@
---
"nfc": "patch"
"nfc-js": "patch"
---
Update return value of `isAvailable` to match TypeScript function signature
-6
View File
@@ -1,6 +0,0 @@
---
"updater": minor
"updater-js": minor
---
Updater plugin now supports all bundle types: Deb, Rpm and AppImage for Linux; NSiS, MSI for Windows. This was added in https://github.com/tauri-apps/plugins-workspace/pull/2624
-6
View File
@@ -1,6 +0,0 @@
---
"upload": minor
"upload-js": minor
---
Upload plugin now supports specifying an HTTP method i.e. POST, PUT etc.
@@ -101,11 +101,6 @@ jobs:
- pnpm-lock.yaml - pnpm-lock.yaml
- plugins/process/guest-js/** - plugins/process/guest-js/**
- plugins/process/src/api-iife.js - plugins/process/src/api-iife.js
secure-storage:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/secure-storage/guest-js/**
- plugins/secure-storage/src/api-iife.js
shell: shell:
- .github/workflows/check-generated-files.yml - .github/workflows/check-generated-files.yml
- pnpm-lock.yaml - pnpm-lock.yaml
@@ -11,7 +11,7 @@ on:
- v2 - v2
permissions: permissions:
# required for oidc token # required for npm provenance
id-token: write id-token: write
# required to create the GitHub Release # required to create the GitHub Release
contents: write contents: write
@@ -62,6 +62,7 @@ jobs:
id: covector id: covector
env: env:
CARGO_TARGET_DIR: /mnt/target CARGO_TARGET_DIR: /mnt/target
NODE_AUTH_TOKEN: ${{ secrets.ORG_NPM_TOKEN }}
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
command: 'version-or-publish' command: 'version-or-publish'
-4
View File
@@ -98,9 +98,6 @@ jobs:
tauri-plugin-process: tauri-plugin-process:
- .github/workflows/lint-rust.yml - .github/workflows/lint-rust.yml
- plugins/process/** - plugins/process/**
tauri-plugin-secure-storage:
- .github/workflows/lint-rust.yml
- plugins/secure-storage/**
tauri-plugin-shell: tauri-plugin-shell:
- .github/workflows/lint-rust.yml - .github/workflows/lint-rust.yml
- plugins/shell/** - plugins/shell/**
@@ -157,5 +154,4 @@ jobs:
run: cargo clippy --package ${{ matrix.package }} --all-targets -- -D warnings run: cargo clippy --package ${{ matrix.package }} --all-targets -- -D warnings
- name: clippy ${{ matrix.package }} --all-features - name: clippy ${{ matrix.package }} --all-features
if: matrix.package != 'tauri-plugin-dialog'
run: cargo clippy --package ${{ matrix.package }} --all-targets --all-features -- -D warnings run: cargo clippy --package ${{ matrix.package }} --all-targets --all-features -- -D warnings
+4 -9
View File
@@ -137,11 +137,6 @@ jobs:
- Cargo.toml - Cargo.toml
- Cargo.lock - Cargo.lock
- plugins/process/** - plugins/process/**
tauri-plugin-secure-storage:
- .github/workflows/test-rust.yml
- Cargo.toml
- Cargo.lock
- plugins/secure-storage/**
tauri-plugin-shell: tauri-plugin-shell:
- .github/workflows/test-rust.yml - .github/workflows/test-rust.yml
- Cargo.toml - Cargo.toml
@@ -224,7 +219,7 @@ jobs:
target: aarch64-linux-android, target: aarch64-linux-android,
os: ubuntu-latest, os: ubuntu-latest,
runner: 'cross', runner: 'cross',
command: 'build --verbose' command: 'build'
} }
runs-on: ${{ matrix.platform.os }} runs-on: ${{ matrix.platform.os }}
@@ -238,7 +233,7 @@ jobs:
sudo apt-get update sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.0-dev libwebkit2gtk-4.1-dev sudo apt-get install -y libwebkit2gtk-4.0-dev libwebkit2gtk-4.1-dev
- uses: dtolnay/rust-toolchain@1.85 - uses: dtolnay/rust-toolchain@1.77.2
with: with:
targets: ${{ matrix.platform.target }} targets: ${{ matrix.platform.target }}
@@ -251,9 +246,9 @@ jobs:
run: cargo +stable install cross --git https://github.com/cross-rs/cross run: cargo +stable install cross --git https://github.com/cross-rs/cross
- name: test ${{ matrix.package }} - name: test ${{ matrix.package }}
if: matrix.package != 'tauri-plugin-http' && matrix.package != 'tauri-plugin-secure-storage' && matrix.package != 'tauri-plugin-dialog' if: matrix.package != 'tauri-plugin-http'
run: ${{ matrix.platform.runner }} ${{ matrix.platform.command }} --package ${{ matrix.package }} --target ${{ matrix.platform.target }} --all-targets --all-features run: ${{ matrix.platform.runner }} ${{ matrix.platform.command }} --package ${{ matrix.package }} --target ${{ matrix.platform.target }} --all-targets --all-features
- name: test ${{ matrix.package }} - 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 run: ${{ matrix.platform.runner }} ${{ matrix.platform.command }} --package ${{ matrix.package }} --target ${{ matrix.platform.target }} --all-targets
+1 -1
View File
@@ -58,4 +58,4 @@ pids
.idea .idea
debug.log debug.log
TODO.md TODO.md
.aider.* .aider*
-1
View File
@@ -1,3 +1,2 @@
plugins/*/permissions/autogenerated/ plugins/*/permissions/autogenerated/
plugins/*/android/.tauri/tauri-api/build/ plugins/*/android/.tauri/tauri-api/build/
plugins/*/android/build/intermediates/
Generated
+125 -368
View File
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -12,10 +12,10 @@ resolver = "2"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
tracing = "0.1" tracing = "0.1"
log = "0.4" log = "0.4"
tauri = { version = "2.8.2", default-features = false } tauri = { version = "2.6", default-features = false }
tauri-build = "2.4" tauri-build = "2.3"
tauri-plugin = "2.4" tauri-plugin = "2.3"
tauri-utils = "2.7" tauri-utils = "2.5"
serde_json = "1" serde_json = "1"
thiserror = "2" thiserror = "2"
url = "2" url = "2"
+1 -2
View File
@@ -3,12 +3,11 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import eslint from '@eslint/js' import eslint from '@eslint/js'
import { defineConfig } from 'eslint/config'
import eslintConfigPrettier from 'eslint-config-prettier' import eslintConfigPrettier from 'eslint-config-prettier'
import eslintPluginSecurity from 'eslint-plugin-security' import eslintPluginSecurity from 'eslint-plugin-security'
import tseslint from 'typescript-eslint' import tseslint from 'typescript-eslint'
export default defineConfig( export default tseslint.config(
{ {
ignores: [ ignores: [
'**/target', '**/target',
-73
View File
@@ -1,78 +1,5 @@
# Changelog # Changelog
## \[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
- Upgraded to `dialog-js@2.3.2`
## \[2.0.27] ## \[2.0.27]
### Dependencies ### Dependencies
+1 -1
View File
@@ -4,7 +4,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta <meta
name="viewport" 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> <title>Svelte + Vite App</title>
</head> </head>
+19 -20
View File
@@ -1,7 +1,7 @@
{ {
"name": "api", "name": "api",
"private": true, "private": true,
"version": "2.0.34", "version": "2.0.27",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite --clearScreen false", "dev": "vite --clearScreen false",
@@ -10,25 +10,24 @@
"tauri": "tauri" "tauri": "tauri"
}, },
"dependencies": { "dependencies": {
"@tauri-apps/api": "2.9.0", "@tauri-apps/api": "2.7.0",
"@tauri-apps/plugin-barcode-scanner": "^2.4.2", "@tauri-apps/plugin-barcode-scanner": "^2.4.0",
"@tauri-apps/plugin-biometric": "^2.3.2", "@tauri-apps/plugin-biometric": "^2.3.0",
"@tauri-apps/plugin-cli": "^2.4.1", "@tauri-apps/plugin-cli": "^2.4.0",
"@tauri-apps/plugin-clipboard-manager": "^2.3.2", "@tauri-apps/plugin-clipboard-manager": "^2.3.0",
"@tauri-apps/plugin-dialog": "^2.4.2", "@tauri-apps/plugin-dialog": "^2.3.1",
"@tauri-apps/plugin-fs": "^2.4.4", "@tauri-apps/plugin-fs": "^2.4.1",
"@tauri-apps/plugin-geolocation": "^2.2.0", "@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-haptics": "^2.2.0",
"@tauri-apps/plugin-http": "^2.5.4", "@tauri-apps/plugin-http": "^2.5.1",
"@tauri-apps/plugin-nfc": "^2.3.3", "@tauri-apps/plugin-nfc": "^2.3.0",
"@tauri-apps/plugin-notification": "^2.3.3", "@tauri-apps/plugin-notification": "^2.3.0",
"@tauri-apps/plugin-opener": "^2.5.2", "@tauri-apps/plugin-opener": "^2.4.0",
"@tauri-apps/plugin-os": "^2.3.2", "@tauri-apps/plugin-os": "^2.3.0",
"@tauri-apps/plugin-process": "^2.3.1", "@tauri-apps/plugin-process": "^2.3.0",
"@tauri-apps/plugin-secure-storage": "file:../../plugins/secure-storage", "@tauri-apps/plugin-shell": "^2.3.0",
"@tauri-apps/plugin-shell": "^2.3.3", "@tauri-apps/plugin-store": "^2.3.0",
"@tauri-apps/plugin-store": "^2.4.1",
"@tauri-apps/plugin-updater": "^2.9.0", "@tauri-apps/plugin-updater": "^2.9.0",
"@tauri-apps/plugin-upload": "^2.3.0", "@tauri-apps/plugin-upload": "^2.3.0",
"@zerodevx/svelte-json-view": "1.0.11" "@zerodevx/svelte-json-view": "1.0.11"
@@ -37,10 +36,10 @@
"@iconify-json/codicon": "^1.2.12", "@iconify-json/codicon": "^1.2.12",
"@iconify-json/ph": "^1.2.2", "@iconify-json/ph": "^1.2.2",
"@sveltejs/vite-plugin-svelte": "^6.0.0", "@sveltejs/vite-plugin-svelte": "^6.0.0",
"@tauri-apps/cli": "2.9.4", "@tauri-apps/cli": "2.7.1",
"@unocss/extractor-svelte": "^66.3.3", "@unocss/extractor-svelte": "^66.3.3",
"svelte": "^5.20.4", "svelte": "^5.20.4",
"unocss": "^66.3.3", "unocss": "^66.3.3",
"vite": "^7.0.7" "vite": "^7.0.4"
} }
} }
-77
View File
@@ -1,82 +1,5 @@
# Changelog # Changelog
## \[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
- Upgraded to `dialog@2.3.2`
## \[2.0.31] ## \[2.0.31]
### Dependencies ### Dependencies
+19 -20
View File
@@ -1,7 +1,7 @@
[package] [package]
name = "api" name = "api"
publish = false publish = false
version = "2.0.38" version = "2.0.31"
description = "An example Tauri Application showcasing the api" description = "An example Tauri Application showcasing the api"
edition = "2021" edition = "2021"
rust-version = { workspace = true } rust-version = { workspace = true }
@@ -20,25 +20,24 @@ serde = { workspace = true }
tiny_http = "0.12" tiny_http = "0.12"
time = "0.3" time = "0.3"
log = { workspace = true } log = { workspace = true }
tauri-plugin-log = { path = "../../../plugins/log", version = "2.7.1" } tauri-plugin-log = { path = "../../../plugins/log", version = "2.6.0" }
tauri-plugin-fs = { path = "../../../plugins/fs", version = "2.4.4", features = [ tauri-plugin-fs = { path = "../../../plugins/fs", version = "2.4.1", features = [
"watch", "watch",
] } ] }
tauri-plugin-clipboard-manager = { path = "../../../plugins/clipboard-manager", version = "2.3.2" } tauri-plugin-clipboard-manager = { path = "../../../plugins/clipboard-manager", version = "2.3.0" }
tauri-plugin-dialog = { path = "../../../plugins/dialog", version = "2.4.2" } tauri-plugin-dialog = { path = "../../../plugins/dialog", version = "2.3.1" }
tauri-plugin-http = { path = "../../../plugins/http", features = [ tauri-plugin-http = { path = "../../../plugins/http", features = [
"multipart", "multipart",
"cookies", "cookies",
], version = "2.5.4" } ], version = "2.5.1" }
tauri-plugin-notification = { path = "../../../plugins/notification", version = "2.3.3", features = [ tauri-plugin-notification = { path = "../../../plugins/notification", version = "2.3.0", features = [
"windows7-compat", "windows7-compat",
] } ] }
tauri-plugin-os = { path = "../../../plugins/os", version = "2.3.2" } tauri-plugin-os = { path = "../../../plugins/os", version = "2.3.0" }
tauri-plugin-process = { path = "../../../plugins/process", version = "2.3.1" } tauri-plugin-process = { path = "../../../plugins/process", version = "2.3.0" }
tauri-plugin-opener = { path = "../../../plugins/opener", version = "2.5.2" } tauri-plugin-opener = { path = "../../../plugins/opener", version = "2.4.0" }
tauri-plugin-secure-storage = { path = "../../../plugins/secure-storage" } tauri-plugin-shell = { path = "../../../plugins/shell", version = "2.3.0" }
tauri-plugin-shell = { path = "../../../plugins/shell", version = "2.3.3" } tauri-plugin-store = { path = "../../../plugins/store", version = "2.3.0" }
tauri-plugin-store = { path = "../../../plugins/store", version = "2.4.1" }
tauri-plugin-upload = { path = "../../../plugins/upload", version = "2.3.0" } tauri-plugin-upload = { path = "../../../plugins/upload", version = "2.3.0" }
[dependencies.tauri] [dependencies.tauri]
@@ -56,17 +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] [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-cli = { path = "../../../plugins/cli", version = "2.4.0" }
tauri-plugin-global-shortcut = { path = "../../../plugins/global-shortcut", version = "2.3.1" } tauri-plugin-global-shortcut = { path = "../../../plugins/global-shortcut", version = "2.3.0" }
tauri-plugin-updater = { path = "../../../plugins/updater", version = "2.9.0" } tauri-plugin-updater = { path = "../../../plugins/updater", version = "2.9.0" }
tauri-plugin-window-state = { path = "../../../plugins/window-state", version = "2.2.0" } tauri-plugin-window-state = { path = "../../../plugins/window-state", version = "2.2.0" }
[target."cfg(any(target_os = \"android\", target_os = \"ios\"))".dependencies] [target."cfg(any(target_os = \"android\", target_os = \"ios\"))".dependencies]
tauri-plugin-barcode-scanner = { path = "../../../plugins/barcode-scanner/", version = "2.4.2" } tauri-plugin-barcode-scanner = { path = "../../../plugins/barcode-scanner/", version = "2.4.0" }
tauri-plugin-nfc = { path = "../../../plugins/nfc", version = "2.3.3" } tauri-plugin-nfc = { path = "../../../plugins/nfc", version = "2.3.0" }
tauri-plugin-biometric = { path = "../../../plugins/biometric/", version = "2.3.2" } tauri-plugin-biometric = { path = "../../../plugins/biometric/", version = "2.3.0" }
tauri-plugin-geolocation = { path = "../../../plugins/geolocation/", version = "2.3.2" } tauri-plugin-geolocation = { path = "../../../plugins/geolocation/", version = "2.3.0" }
tauri-plugin-haptics = { path = "../../../plugins/haptics/", version = "2.3.2" } tauri-plugin-haptics = { path = "../../../plugins/haptics/", version = "2.3.0" }
[features] [features]
prod = ["tauri/custom-protocol"] prod = ["tauri/custom-protocol"]
+1 -11
View File
@@ -68,9 +68,6 @@
"fs:allow-rename", "fs:allow-rename",
"fs:allow-mkdir", "fs:allow-mkdir",
"fs:allow-remove", "fs:allow-remove",
"fs:allow-stat",
"fs:allow-fstat",
"fs:allow-lstat",
"fs:allow-write-text-file", "fs:allow-write-text-file",
"fs:read-meta", "fs:read-meta",
"fs:scope-download-recursive", "fs:scope-download-recursive",
@@ -78,9 +75,6 @@
{ {
"identifier": "fs:scope-appdata-recursive", "identifier": "fs:scope-appdata-recursive",
"allow": [ "allow": [
{
"path": "$APPDATA/db/"
},
{ {
"path": "$APPDATA/db/**" "path": "$APPDATA/db/**"
} }
@@ -102,10 +96,6 @@
"identifier": "opener:allow-open-path", "identifier": "opener:allow-open-path",
"allow": [{ "path": "$APPDATA" }, { "path": "$APPDATA/**" }] "allow": [{ "path": "$APPDATA" }, { "path": "$APPDATA/**" }]
}, },
"upload:default", "upload:default"
"secure-storage:allow-get-string",
"secure-storage:allow-set-string",
"secure-storage:allow-get-binary",
"secure-storage:allow-set-binary"
] ]
} }
@@ -14,13 +14,13 @@ val tauriProperties = Properties().apply {
} }
android { android {
compileSdk = 36 compileSdk = 34
namespace = "com.tauri.api" namespace = "com.tauri.api"
defaultConfig { defaultConfig {
manifestPlaceholders["usesCleartextTraffic"] = "false" manifestPlaceholders["usesCleartextTraffic"] = "false"
applicationId = "com.tauri.api" applicationId = "com.tauri.api"
minSdk = 24 minSdk = 24
targetSdk = 36 targetSdk = 34
versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt() versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt()
versionName = tauriProperties.getProperty("tauri.android.versionName", "1.0") versionName = tauriProperties.getProperty("tauri.android.versionName", "1.0")
} }
@@ -4,7 +4,7 @@ buildscript {
mavenCentral() mavenCentral()
} }
dependencies { 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") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.25")
} }
} }
@@ -18,6 +18,6 @@ repositories {
dependencies { dependencies {
compileOnly(gradleApi()) compileOnly(gradleApi())
implementation("com.android.tools.build:gradle:8.11.0") implementation("com.android.tools.build:gradle:8.5.1")
} }
+1 -2
View File
@@ -38,7 +38,6 @@ pub fn run() {
.plugin(tauri_plugin_process::init()) .plugin(tauri_plugin_process::init())
.plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_opener::init())
.plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_shell::init())
.plugin(tauri_plugin_secure_storage::init())
.plugin(tauri_plugin_store::Builder::default().build()) .plugin(tauri_plugin_store::Builder::default().build())
.plugin(tauri_plugin_upload::init()) .plugin(tauri_plugin_upload::init())
.setup(move |app| { .setup(move |app| {
@@ -96,7 +95,7 @@ pub fn run() {
let server = match tiny_http::Server::http("localhost:3003") { let server = match tiny_http::Server::http("localhost:3003") {
Ok(s) => s, Ok(s) => s,
Err(e) => { Err(e) => {
eprintln!("{}", e); eprintln!("{e}");
std::process::exit(1); std::process::exit(1);
} }
}; };
+6 -12
View File
@@ -23,7 +23,6 @@
import Biometric from './views/Biometric.svelte' import Biometric from './views/Biometric.svelte'
import Geolocation from './views/Geolocation.svelte' import Geolocation from './views/Geolocation.svelte'
import Haptics from './views/Haptics.svelte' import Haptics from './views/Haptics.svelte'
import SecureStorage from './views/SecureStorage.svelte'
import { onMount, tick } from 'svelte' import { onMount, tick } from 'svelte'
import { ask } from '@tauri-apps/plugin-dialog' import { ask } from '@tauri-apps/plugin-dialog'
@@ -104,11 +103,6 @@
component: Store, component: Store,
icon: 'i-codicon-file-code' icon: 'i-codicon-file-code'
}, },
{
label: 'SecureStorage',
component: SecureStorage,
icon: 'i-codicon-file-code'
},
!isMobile && { !isMobile && {
label: 'Updater', label: 'Updater',
component: Updater, component: Updater,
@@ -219,9 +213,9 @@
...r, ...r,
{ {
html: html:
`<pre><strong class="text-accent dark:text-darkAccent">[${new Date().toLocaleTimeString()}]:</strong> ` `<pre><strong class="text-accent dark:text-darkAccent">[${new Date().toLocaleTimeString()}]:</strong> ` +
+ (typeof value === 'string' ? value : JSON.stringify(value, null, 1)) (typeof value === 'string' ? value : JSON.stringify(value, null, 1)) +
+ '</pre>' '</pre>'
} }
]) ])
await tick() await tick()
@@ -235,9 +229,9 @@
...r, ...r,
{ {
html: html:
`<pre><strong class="text-accent dark:text-darkAccent">[${new Date().toLocaleTimeString()}]:</strong> ` `<pre><strong class="text-accent dark:text-darkAccent">[${new Date().toLocaleTimeString()}]:</strong> ` +
+ html html +
+ '</pre>' '</pre>'
} }
]) ])
await tick() await tick()
+11 -35
View File
@@ -8,7 +8,6 @@
let filter = null; let filter = null;
let multiple = false; let multiple = false;
let directory = false; let directory = false;
let pickerMode = "";
function arrayBufferToBase64(buffer, callback) { function arrayBufferToBase64(buffer, callback) {
var blob = new Blob([buffer], { var blob = new Blob([buffer], {
@@ -45,13 +44,6 @@
await message("Tauri is awesome!"); 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);
}
function openDialog() { function openDialog() {
open({ open({
title: "My wonderful open dialog", title: "My wonderful open dialog",
@@ -66,7 +58,6 @@
: [], : [],
multiple, multiple,
directory, directory,
pickerMode: pickerMode === "" ? undefined : pickerMode,
}) })
.then(function (res) { .then(function (res) {
if (Array.isArray(res)) { if (Array.isArray(res)) {
@@ -96,7 +87,7 @@
onMessage(res); onMessage(res);
} }
}) })
.catch(onMessage); .catch(onMessage(res));
} }
}) })
.catch(onMessage); .catch(onMessage);
@@ -114,7 +105,7 @@
}, },
] ]
: [], : [],
}) })
.then(onMessage) .then(onMessage)
.catch(onMessage); .catch(onMessage);
} }
@@ -144,28 +135,13 @@
<input type="checkbox" id="dialog-directory" bind:checked={directory} /> <input type="checkbox" id="dialog-directory" bind:checked={directory} />
<label for="dialog-directory">Directory</label> <label for="dialog-directory">Directory</label>
</div> </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>
<br /> <br />
<button class="btn" id="open-dialog" on:click={openDialog}>Open dialog</button>
<div class="flex flex-wrap flex-col md:flex-row gap-2 children:flex-shrink-0"> <button class="btn" id="save-dialog" on:click={saveDialog}
<button class="btn" id="open-dialog" on:click={openDialog}>Open dialog</button> >Open save 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}
<button class="btn" id="prompt-dialog" on:click={prompt}>Prompt</button> >Prompt (custom)</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={msg}>Message</button>
<button class="btn" id="message-dialog" on:click={msgCustom}>Message (custom)</button>
</div>
+93 -114
View File
@@ -1,214 +1,194 @@
<script> <script>
import * as fs from '@tauri-apps/plugin-fs' import * as fs from "@tauri-apps/plugin-fs";
import * as os from '@tauri-apps/plugin-os' import { convertFileSrc } from "@tauri-apps/api/core";
import { convertFileSrc } from '@tauri-apps/api/core' import { arrayBufferToBase64 } from "../lib/utils";
import { arrayBufferToBase64 } from '../lib/utils' import { onDestroy } from "svelte";
import { onDestroy, onMount } from 'svelte'
const { onMessage, insecureRenderHtml } = $props() export let onMessage;
export let insecureRenderHtml;
let path = $state('') let path = "";
let img let img;
/** @type {fs.FileHandle} */ /** @type {fs.FileHandle} */
let file = $state() let file;
let renameTo = $state() let renameTo;
let watchPath = $state('') let watchPath = "";
let watchDebounceDelay = $state(0) let watchDebounceDelay = "0";
let watchRecursive = $state(false) let watchRecursive = false;
/** @type {fs.BaseDirectory | undefined} */ let unwatchFn;
let baseDir = $state() let unwatchPath = "";
let unwatchFn
let unwatchPath = ''
let isMobile = $state(false)
onMount(() => { function getDir() {
let platform = os.platform() const dirSelect = document.getElementById("dir");
isMobile = platform === 'android' || platform === 'ios' return dirSelect.value ? parseInt(dir.value) : null;
}) }
const dirOptions = Object.keys(fs.BaseDirectory).filter((key) => const DirOptions = Object.keys(fs.BaseDirectory)
isNaN(parseInt(key)) .filter((key) => isNaN(parseInt(key)))
) .map((dir) => [dir, fs.BaseDirectory[dir]]);
function open() { function open() {
fs.open(path, { fs.open(path, {
baseDir, baseDir: getDir(),
read: true, read: true,
write: true, write: true,
create: true create: true,
}) })
.then((f) => { .then((f) => {
file = f file = f;
onMessage(`Opened ${path}`) onMessage(`Opened ${path}`);
}) })
.catch(onMessage) .catch(onMessage);
} }
function mkdir() { function mkdir() {
fs.mkdir(path, { baseDir, recursive: true }) fs.mkdir(path, { baseDir: getDir() })
.then(() => { .then(() => {
onMessage(`Created dir ${path}`) onMessage(`Created dir ${path}`);
}) })
.catch(onMessage) .catch(onMessage);
} }
function remove() { function remove() {
fs.remove(path, { baseDir }) fs.remove(path, { baseDir: getDir() })
.then(() => { .then(() => {
onMessage(`Removed ${path}`) onMessage(`Removed ${path}`);
}) })
.catch(onMessage) .catch(onMessage);
} }
function rename() { function rename() {
fs.rename(path, renameTo, { fs.rename(path, renameTo, {
oldPathBaseDir, oldPathBaseDir: getDir(),
newPathBaseDir newPathBaseDir: getDir(),
}) })
.then(() => { .then(() => {
onMessage(`Renamed ${path} to ${renameTo}`) onMessage(`Renamed ${path} to ${renameTo}`);
}) })
.catch(onMessage) .catch(onMessage);
} }
function truncate() { function truncate() {
file file
.truncate(0) .truncate(0)
.then(() => { .then(() => {
onMessage(`Truncated file`) onMessage(`Truncated file`);
}) })
.catch(onMessage) .catch(onMessage);
}
function write() {
const encoder = new TextEncoder()
file
.write(encoder.encode('Hello from Tauri :)'))
.then(() => {
onMessage(`wrote to file`)
})
.catch(onMessage)
} }
function stat() { function stat() {
file file
.stat() .stat()
.then((stat) => { .then((stat) => {
onMessage(`File stat ${JSON.stringify(stat)}`) onMessage(`File stat ${JSON.stringify(stat)}`);
}) })
.catch(onMessage) .catch(onMessage);
} }
function read() { function read() {
const opts = { const opts = {
baseDir baseDir: getDir(),
} };
fs.stat(path, opts) fs.stat(path, opts)
.then((stat) => { .then((stat) => {
const isFile = stat.isFile const isFile = stat.isFile;
const promise = isFile const promise = isFile
? fs.readFile(path, opts) ? fs.readFile(path, opts)
: fs.readDir(path, opts) : fs.readDir(path, opts);
promise promise
.then(function (response) { .then(function (response) {
if (isFile) { if (isFile) {
if (path.includes('.png') || path.includes('.jpg')) { if (path.includes(".png") || path.includes(".jpg")) {
arrayBufferToBase64( arrayBufferToBase64(
new Uint8Array(response), new Uint8Array(response),
function (base64) { function (base64) {
const src = 'data:image/png;base64,' + base64 const src = "data:image/png;base64," + base64;
insecureRenderHtml('<img src="' + src + '"></img>') insecureRenderHtml('<img src="' + src + '"></img>');
} }
) );
} else { } else {
const value = String.fromCharCode.apply(null, response) const value = String.fromCharCode.apply(null, response);
insecureRenderHtml( insecureRenderHtml(
'<textarea id="file-response"></textarea><button id="file-save">Save</button>' '<textarea id="file-response"></textarea><button id="file-save">Save</button>'
) );
setTimeout(() => { setTimeout(() => {
const fileInput = document.getElementById('file-response') const fileInput = document.getElementById("file-response");
fileInput.value = value fileInput.value = value;
document document
.getElementById('file-save') .getElementById("file-save")
.addEventListener('click', function () { .addEventListener("click", function () {
fs.writeTextFile(path, fileInput.value, { fs.writeTextFile(path, fileInput.value, {
baseDir baseDir: getDir(),
}).catch(onMessage) }).catch(onMessage);
}) });
}) });
} }
} else { } else {
onMessage(response) onMessage(response);
} }
}) })
.catch(onMessage) .catch(onMessage);
}) })
.catch(onMessage) .catch(onMessage);
} }
function setSrc() { function setSrc() {
img.src = convertFileSrc(path) img.src = convertFileSrc(path);
} }
function watch() { function watch() {
unwatch() unwatch();
if (watchPath) { if (watchPath) {
onMessage(`Watching ${watchPath} for changes`) onMessage(`Watching ${watchPath} for changes`);
let options = { let options = {
recursive: watchRecursive, recursive: watchRecursive,
delayMs: watchDebounceDelay delayMs: parseInt(watchDebounceDelay),
} };
if (options.delayMs === 0) { if (options.delayMs === 0) {
fs.watchImmediate(watchPath, onMessage, options) fs.watchImmediate(watchPath, onMessage, options)
.then((fn) => { .then((fn) => {
unwatchFn = fn unwatchFn = fn;
unwatchPath = watchPath unwatchPath = watchPath;
}) })
.catch(onMessage) .catch(onMessage);
} else { } else {
fs.watch(watchPath, onMessage, options) fs.watch(watchPath, onMessage, options)
.then((fn) => { .then((fn) => {
unwatchFn = fn unwatchFn = fn;
unwatchPath = watchPath unwatchPath = watchPath;
}) })
.catch(onMessage) .catch(onMessage);
} }
} }
} }
function unwatch() { function unwatch() {
if (unwatchFn) { if (unwatchFn) {
onMessage(`Stopped watching ${unwatchPath} for changes`) onMessage(`Stopped watching ${unwatchPath} for changes`);
unwatchFn() unwatchFn();
} }
unwatchFn = undefined unwatchFn = undefined;
unwatchPath = undefined unwatchPath = undefined;
} }
onDestroy(() => { onDestroy(() => {
if (file) { if (file) {
file.close() file.close();
} }
if (unwatchFn) { if (unwatchFn) {
unwatchFn() unwatchFn();
} }
}) })
</script> </script>
<div class="flex flex-col"> <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"> <div class="flex gap-1">
<select class="input" bind:value={baseDir}> <select class="input" id="dir">
<option value={undefined} selected>None</option> <option value="">None</option>
{#each dirOptions as dir} {#each DirOptions as dir}
<option value={fs.BaseDirectory[dir]}>{dir}</option> <option value={dir[1]}>{dir[0]}</option>
{/each} {/each}
</select> </select>
<input <input
@@ -219,21 +199,20 @@
</div> </div>
<br /> <br />
<div> <div>
<button class="btn" onclick={open}>Open</button> <button class="btn" on:click={open}>Open</button>
<button class="btn" onclick={read}>Read</button> <button class="btn" on:click={read}>Read</button>
<button class="btn" onclick={mkdir}>Mkdir</button> <button class="btn" on:click={mkdir}>Mkdir</button>
<button class="btn" onclick={remove}>Remove</button> <button class="btn" on:click={remove}>Remove</button>
<div class="flex flex-row"> <div class="flex flex-row">
<button class="btn" onclick={rename}>Rename</button> <button class="btn" on:click={rename}>Rename</button>
<input class="input" bind:value={renameTo} placeholder="To" /> <input class="input" bind:value={renameTo} placeholder="To" />
</div> </div>
<button class="btn" type="button" onclick={setSrc}>Use as img src</button> <button class="btn" type="button" on:click={setSrc}>Use as img src</button>
</div> </div>
{#if file} {#if file}
<div> <div>
<button class="btn" onclick={write}>Write</button> <button class="btn" on:click={truncate}>Truncate</button>
<button class="btn" onclick={truncate}>Truncate</button> <button class="btn" on:click={stat}>Stat</button>
<button class="btn" onclick={stat}>Stat</button>
</div> </div>
{/if} {/if}
@@ -262,8 +241,8 @@
</div> </div>
<br /> <br />
<div> <div>
<button class="btn" onclick={watch}>Watch</button> <button class="btn" on:click={watch}>Watch</button>
<button class="btn" onclick={unwatch}>Unwatch</button> <button class="btn" on:click={unwatch}>Unwatch</button>
</div> </div>
</div> </div>
+4 -14
View File
@@ -1,21 +1,16 @@
<script> <script>
import { sendNotification } from '@tauri-apps/plugin-notification'
export let onMessage export let onMessage
let sound = ''
// send the notification directly // send the notification directly
// the backend is responsible for checking the permission // the backend is responsible for checking the permission
function _sendNotification() { function _sendNotification() {
sendNotification({ new Notification('Notification title', {
title: 'Notification title', body: 'This is the notification body'
body: 'This is the notification body',
sound: sound || null
}) })
} }
// alternatively, check the permission ourselves // alternatively, check the permission ourselves
function triggerNotification() { function sendNotification() {
if (Notification.permission === 'default') { if (Notification.permission === 'default') {
Notification.requestPermission() Notification.requestPermission()
.then(function (response) { .then(function (response) {
@@ -34,11 +29,6 @@
} }
</script> </script>
<input <button class="btn" id="notification" on:click={sendNotification}>
class="input grow"
placeholder="Notification sound..."
bind:value={sound}
/>
<button class="btn" id="notification" on:click={triggerNotification}>
Send test notification Send test notification
</button> </button>
@@ -1,54 +0,0 @@
<script>
import { onMount } from 'svelte'
import { getString, setString } from '@tauri-apps/plugin-secure-storage'
export let onMessage
let key
let value
let output
async function read(key) {
try {
output = await getString(key)
} catch (error) {
onMessage(error)
}
}
async function write(key, value) {
try {
await setString(key, value)
} catch (error) {
onMessage(error)
}
}
function reset() {
output = ''
}
</script>
<div class="flex flex-col childre:grow gap-1">
<div class="flex flex-col flex-row-md gap-4">
<div class="flex items-center gap-1">
Key:
<input class="grow input" bind:value={key} />
</div>
<div class="flex items-center gap-1">
Value:
<input class="grow input" bind:value />
</div>
<div>
<button class="btn" on:click={() => write(key, value)}>Write</button>
<button class="btn" on:click={() => read(key)}>Read</button>
<button class="btn" on:click={() => reset()}>Reset Output</button>
</div>
</div>
<div>
Output: {output}
</div>
</div>
+32 -49
View File
@@ -1,85 +1,71 @@
<script> <script>
import { appDataDir, resolve } from '@tauri-apps/api/path' import { LazyStore } from "@tauri-apps/plugin-store";
import { LazyStore } from '@tauri-apps/plugin-store' import { onMount } from "svelte";
import { onMount } from 'svelte'
let { onMessage } = $props() export let onMessage;
let key = $state() let key;
let value = $state() let value;
const storeName = 'cache.json' let store = new LazyStore("cache.json");
let cache = {};
let store = new LazyStore(storeName)
let path = $state('')
let cache = $state({})
async function refreshEntries() { async function refreshEntries() {
try { try {
const values = await store.entries() const values = await store.entries();
cache = {} cache = {};
for (const [key, value] of values) { for (const [key, value] of values) {
cache[key] = value cache[key] = value;
} }
} catch (error) { } catch (error) {
onMessage(error) onMessage(error);
} }
} }
onMount(async () => { onMount(async () => {
path = await resolve(await appDataDir(), storeName) await refreshEntries();
await refreshEntries() });
})
async function write(key, value) { async function write(key, value) {
try { try {
if (value) { if (value) {
await store.set(key, value) await store.set(key, value);
} else { } else {
await store.delete(key) await store.delete(key);
} }
const v = await store.get(key) const v = await store.get(key);
if (v === undefined) { if (v === undefined) {
delete cache[key] delete cache[key];
cache = cache cache = cache;
} else { } else {
cache[key] = v cache[key] = v;
} }
} catch (error) { } catch (error) {
onMessage(error) onMessage(error);
} }
} }
async function reset() { async function reset() {
try { try {
await store.reset() await store.reset();
} catch (error) { } catch (error) {
onMessage(error) onMessage(error);
} }
await refreshEntries() await refreshEntries();
}
async function reload() {
try {
await store.reload({ overrideDefaults: true })
} catch (error) {
onMessage(error)
}
await refreshEntries()
} }
async function close() { async function close() {
try { try {
await store.close() await store.close();
onMessage('Store is now closed, any new operations will error out') onMessage("Store is now closed, any new operations will error out");
} catch (error) { } catch (error) {
onMessage(error) onMessage(error);
} }
} }
function reopen() { function reopen() {
store = new LazyStore(storeName) store = new LazyStore("cache.json");
onMessage('We made a new `LazyStore` instance, operations will now work') onMessage("We made a new `LazyStore` instance, operations will now work");
} }
</script> </script>
@@ -96,17 +82,14 @@
</div> </div>
<div> <div>
<button class="btn" onclick={() => write(key, value)}>Write</button> <button class="btn" on:click={() => write(key, value)}>Write</button>
<button class="btn" onclick={() => reset()}>Reset</button> <button class="btn" on:click={() => reset()}>Reset</button>
<button class="btn" onclick={() => reload()}>Reload</button> <button class="btn" on:click={() => close()}>Close</button>
<button class="btn" onclick={() => close()}>Close</button> <button class="btn" on:click={() => reopen()}>Re-open</button>
<button class="btn" onclick={() => reopen()}>Re-open</button>
</div> </div>
<div>Store at <code>{path}</code> on disk</div>
</div> </div>
<div> <div>
<h2>Store Values</h2>
{#each Object.entries(cache) as [k, v]} {#each Object.entries(cache) as [k, v]}
<div>{k} = {v}</div> <div>{k} = {v}</div>
{/each} {/each}
+3 -44
View File
@@ -1,5 +1,5 @@
<script> <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 { open } from '@tauri-apps/plugin-dialog'
import { JsonView } from '@zerodevx/svelte-json-view' import { JsonView } from '@zerodevx/svelte-json-view'
import { appDataDir } from '@tauri-apps/api/path' import { appDataDir } from '@tauri-apps/api/path'
@@ -16,22 +16,6 @@
let uploadUrl = 'https://httpbin.org/post' let uploadUrl = 'https://httpbin.org/post'
let uploadFilePath = '' 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 uploadProgress = null
let uploadResult = null let uploadResult = null
let isUploading = false let isUploading = false
@@ -213,8 +197,7 @@
}, },
new Map([ new Map([
['User-Agent', 'Tauri Upload Plugin Demo'] ['User-Agent', 'Tauri Upload Plugin Demo']
]), ])
uploadMethod
) )
uploadResult = { uploadResult = {
@@ -357,36 +340,12 @@
</div> </div>
</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 <button
on:click={startUpload} 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" 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} disabled={isUploading || !uploadUrl || !uploadFilePath}
> >
{isUploading ? `Uploading (${uploadMethod})...` : `Upload File (${uploadMethod})`} {isUploading ? 'Uploading...' : 'Upload File'}
</button> </button>
{#if uploadProgress} {#if uploadProgress}
+8 -9
View File
@@ -11,21 +11,20 @@
"example:api:dev": "pnpm run --filter \"api\" tauri dev" "example:api:dev": "pnpm run --filter \"api\" tauri dev"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "9.39.1", "@eslint/js": "9.31.0",
"@rollup/plugin-node-resolve": "16.0.3", "@rollup/plugin-node-resolve": "16.0.1",
"@rollup/plugin-terser": "0.4.4", "@rollup/plugin-terser": "0.4.4",
"@rollup/plugin-typescript": "12.3.0", "@rollup/plugin-typescript": "12.1.4",
"covector": "^0.12.4", "covector": "^0.12.4",
"eslint": "9.39.1", "eslint": "9.31.0",
"eslint-config-prettier": "10.1.8", "eslint-config-prettier": "10.1.8",
"eslint-plugin-security": "3.0.1", "eslint-plugin-security": "3.0.1",
"prettier": "3.6.2", "prettier": "3.6.2",
"rollup": "4.53.2", "rollup": "4.45.1",
"tslib": "2.8.1", "tslib": "2.8.1",
"typescript": "5.9.3", "typescript": "5.8.3",
"typescript-eslint": "8.47.0" "typescript-eslint": "8.38.0"
}, },
"minimumReleaseAge": 4320,
"pnpm": { "pnpm": {
"overrides": { "overrides": {
"esbuild@<0.25.0": ">=0.25.0" "esbuild@<0.25.0": ">=0.25.0"
@@ -35,6 +34,6 @@
] ]
}, },
"engines": { "engines": {
"pnpm": "^10.16.0" "pnpm": "^10.0.0"
} }
} }
-4
View File
@@ -1,9 +1,5 @@
# Changelog # 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] ## \[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 - [`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] [package]
name = "tauri-plugin-autostart" name = "tauri-plugin-autostart"
version = "2.5.1" version = "2.5.0"
description = "Automatically launch your application at startup." description = "Automatically launch your application at startup."
authors = { workspace = true } authors = { workspace = true }
license = { workspace = true } license = { workspace = true }
@@ -9,6 +9,10 @@ rust-version = { workspace = true }
repository = { workspace = true } repository = { workspace = true }
links = "tauri-plugin-autostart" links = "tauri-plugin-autostart"
[package.metadata.docs.rs]
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
[package.metadata.platforms.support] [package.metadata.platforms.support]
windows = { level = "full", notes = "" } windows = { level = "full", notes = "" }
linux = { level = "full", notes = "" } linux = { level = "full", notes = "" }
+9
View File
@@ -33,12 +33,21 @@ tauri-plugin-autostart = { git = "https://github.com/tauri-apps/plugins-workspac
You can install the JavaScript Guest bindings using your preferred JavaScript package manager: You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh ```sh
pnpm add @tauri-apps/plugin-autostart pnpm add @tauri-apps/plugin-autostart
# or # or
npm add @tauri-apps/plugin-autostart npm add @tauri-apps/plugin-autostart
# or # or
yarn add @tauri-apps/plugin-autostart yarn add @tauri-apps/plugin-autostart
# alternatively with Git:
pnpm add https://github.com/tauri-apps/tauri-plugin-autostart#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-autostart#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-autostart#v2
``` ```
## Usage ## Usage
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "@tauri-apps/plugin-autostart", "name": "@tauri-apps/plugin-autostart",
"version": "2.5.1", "version": "2.5.0",
"license": "MIT OR Apache-2.0", "license": "MIT OR Apache-2.0",
"authors": [ "authors": [
"Tauri Programme within The Commons Conservancy" "Tauri Programme within The Commons Conservancy"
@@ -24,6 +24,6 @@
"LICENSE" "LICENSE"
], ],
"dependencies": { "dependencies": {
"@tauri-apps/api": "^2.8.0" "@tauri-apps/api": "^2.6.0"
} }
} }
@@ -331,10 +331,10 @@
"markdownDescription": "Denies the is_enabled command without any pre-configured scope." "markdownDescription": "Denies the is_enabled command without any pre-configured scope."
}, },
{ {
"description": "This permission set configures if your\r\napplication can enable or disable auto\r\nstarting the application on boot.\r\n\r\n#### Granted Permissions\r\n\r\nIt allows all to check, enable and\r\ndisable the automatic start on boot.\r\n\r\n\n#### This default permission set includes:\n\n- `allow-enable`\n- `allow-disable`\n- `allow-is-enabled`", "description": "This permission set configures if your\napplication can enable or disable auto\nstarting the application on boot.\n\n#### Granted Permissions\n\nIt allows all to check, enable and\ndisable the automatic start on boot.\n\n\n#### This default permission set includes:\n\n- `allow-enable`\n- `allow-disable`\n- `allow-is-enabled`",
"type": "string", "type": "string",
"const": "default", "const": "default",
"markdownDescription": "This permission set configures if your\r\napplication can enable or disable auto\r\nstarting the application on boot.\r\n\r\n#### Granted Permissions\r\n\r\nIt allows all to check, enable and\r\ndisable the automatic start on boot.\r\n\r\n\n#### This default permission set includes:\n\n- `allow-enable`\n- `allow-disable`\n- `allow-is-enabled`" "markdownDescription": "This permission set configures if your\napplication can enable or disable auto\nstarting the application on boot.\n\n#### Granted Permissions\n\nIt allows all to check, enable and\ndisable the automatic start on boot.\n\n\n#### This default permission set includes:\n\n- `allow-enable`\n- `allow-disable`\n- `allow-is-enabled`"
} }
] ]
} }
-9
View File
@@ -1,14 +1,5 @@
# Changelog # Changelog
## \[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] ## \[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+ - [`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+
+3 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "tauri-plugin-barcode-scanner" name = "tauri-plugin-barcode-scanner"
version = "2.4.2" version = "2.4.0"
description = "Scan QR codes, EAN-13 and other kinds of barcodes on Android and iOS" description = "Scan QR codes, EAN-13 and other kinds of barcodes on Android and iOS"
edition = { workspace = true } edition = { workspace = true }
authors = { workspace = true } authors = { workspace = true }
@@ -10,6 +10,8 @@ repository = { workspace = true }
links = "tauri-plugin-barcode-scanner" links = "tauri-plugin-barcode-scanner"
[package.metadata.docs.rs] [package.metadata.docs.rs]
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
targets = ["x86_64-linux-android"] targets = ["x86_64-linux-android"]
[package.metadata.platforms.support] [package.metadata.platforms.support]
+9
View File
@@ -33,12 +33,21 @@ tauri-plugin-barcode-scanner = { git = "https://github.com/tauri-apps/plugins-wo
You can install the JavaScript Guest bindings using your preferred JavaScript package manager: You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh ```sh
pnpm add @tauri-apps/plugin-barcode-scanner pnpm add @tauri-apps/plugin-barcode-scanner
# or # or
npm add @tauri-apps/plugin-barcode-scanner npm add @tauri-apps/plugin-barcode-scanner
# or # or
yarn add @tauri-apps/plugin-barcode-scanner yarn add @tauri-apps/plugin-barcode-scanner
# alternatively with Git:
pnpm add https://github.com/tauri-apps/tauri-plugin-barcode-scanner#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-barcode-scanner#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-barcode-scanner#v2
``` ```
## Usage ## Usage
@@ -5,10 +5,10 @@ plugins {
android { android {
namespace = "app.tauri.barcodescanner" namespace = "app.tauri.barcodescanner"
compileSdk = 36 compileSdk = 34
defaultConfig { defaultConfig {
minSdk = 24 minSdk = 24
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro") consumerProguardFiles("consumer-rules.pro")
@@ -33,14 +33,16 @@ android {
} }
dependencies { dependencies {
val camerax_version = "1.5.1"
implementation("androidx.core:core-ktx:1.9.0") implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.appcompat:appcompat:1.6.0") implementation("androidx.appcompat:appcompat:1.6.0")
implementation("com.google.android.material:material:1.7.0") implementation("com.google.android.material:material:1.7.0")
implementation("androidx.camera:camera-core:${camerax_version}") implementation("androidx.camera:camera-core:1.1.0")
implementation("androidx.camera:camera-camera2:${camerax_version}") implementation("androidx.camera:camera-view:1.1.0")
implementation("androidx.camera:camera-lifecycle:${camerax_version}") implementation("androidx.camera:camera-lifecycle:1.1.0")
implementation("androidx.camera:camera-view:${camerax_version}") 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") implementation("com.google.android.gms:play-services-mlkit-barcode-scanning:18.1.0")
testImplementation("junit:junit:4.13.2") testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5") androidTestImplementation("androidx.test.ext:junit:1.1.5")
@@ -191,7 +191,6 @@ class BarcodeScannerPlugin: Plugin, AVCaptureMetadataOutputObjectsDelegate {
if self.captureSession != nil { if self.captureSession != nil {
self.captureSession!.stopRunning() self.captureSession!.stopRunning()
self.cameraView.removePreviewLayer() self.cameraView.removePreviewLayer()
self.cameraView.removeFromSuperview()
self.captureVideoPreviewLayer = nil self.captureVideoPreviewLayer = nil
self.metaOutput = nil self.metaOutput = nil
self.captureSession = nil self.captureSession = nil
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "@tauri-apps/plugin-barcode-scanner", "name": "@tauri-apps/plugin-barcode-scanner",
"version": "2.4.2", "version": "2.4.0",
"description": "Scan QR codes, EAN-13 and other kinds of barcodes on Android and iOS", "description": "Scan QR codes, EAN-13 and other kinds of barcodes on Android and iOS",
"license": "MIT OR Apache-2.0", "license": "MIT OR Apache-2.0",
"authors": [ "authors": [
@@ -25,6 +25,6 @@
"LICENSE" "LICENSE"
], ],
"dependencies": { "dependencies": {
"@tauri-apps/api": "^2.8.0" "@tauri-apps/api": "^2.6.0"
} }
} }
-8
View File
@@ -1,13 +1,5 @@
# Changelog # 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] ## \[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 - [`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] [package]
name = "tauri-plugin-biometric" name = "tauri-plugin-biometric"
version = "2.3.2" version = "2.3.0"
description = "Prompt the user for biometric authentication on Android and iOS." description = "Prompt the user for biometric authentication on Android and iOS."
edition = { workspace = true } edition = { workspace = true }
authors = { workspace = true } authors = { workspace = true }
@@ -9,6 +9,8 @@ repository = { workspace = true }
links = "tauri-plugin-biometric" links = "tauri-plugin-biometric"
[package.metadata.docs.rs] [package.metadata.docs.rs]
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
targets = ["x86_64-linux-android"] targets = ["x86_64-linux-android"]
[package.metadata.platforms.support] [package.metadata.platforms.support]
+9
View File
@@ -33,6 +33,8 @@ tauri-plugin-biometric = { git = "https://github.com/tauri-apps/plugins-workspac
You can install the JavaScript Guest bindings using your preferred JavaScript package manager: You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
<!-- Add the branch for installations using git! --> <!-- Add the branch for installations using git! -->
```sh ```sh
@@ -41,6 +43,13 @@ pnpm add @tauri-apps/plugin-biometric
npm add @tauri-apps/plugin-biometric npm add @tauri-apps/plugin-biometric
# or # or
yarn add @tauri-apps/plugin-biometric yarn add @tauri-apps/plugin-biometric
# alternatively with Git:
pnpm add https://github.com/tauri-apps/tauri-plugin-biometric#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-biometric#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-biometric#v2
``` ```
## Usage ## Usage
+2 -2
View File
@@ -5,10 +5,10 @@ plugins {
android { android {
namespace = "app.tauri.biometric" namespace = "app.tauri.biometric"
compileSdk = 36 compileSdk = 34
defaultConfig { defaultConfig {
minSdk = 24 minSdk = 24
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro") consumerProguardFiles("consumer-rules.pro")
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "@tauri-apps/plugin-biometric", "name": "@tauri-apps/plugin-biometric",
"version": "2.3.2", "version": "2.3.0",
"license": "MIT OR Apache-2.0", "license": "MIT OR Apache-2.0",
"authors": [ "authors": [
"Tauri Programme within The Commons Conservancy" "Tauri Programme within The Commons Conservancy"
@@ -25,6 +25,6 @@
"LICENSE" "LICENSE"
], ],
"dependencies": { "dependencies": {
"@tauri-apps/api": "^2.8.0" "@tauri-apps/api": "^2.6.0"
} }
} }
@@ -319,10 +319,10 @@
"markdownDescription": "Denies the status command without any pre-configured scope." "markdownDescription": "Denies the status command without any pre-configured scope."
}, },
{ {
"description": "This permission set configures which\r\nbiometric features are by default exposed.\r\n\r\n#### Granted Permissions\r\n\r\nIt allows acccess to all biometric commands.\r\n\r\n\n#### This default permission set includes:\n\n- `allow-authenticate`\n- `allow-status`", "description": "This permission set configures which\nbiometric features are by default exposed.\n\n#### Granted Permissions\n\nIt allows acccess to all biometric commands.\n\n\n#### This default permission set includes:\n\n- `allow-authenticate`\n- `allow-status`",
"type": "string", "type": "string",
"const": "default", "const": "default",
"markdownDescription": "This permission set configures which\r\nbiometric features are by default exposed.\r\n\r\n#### Granted Permissions\r\n\r\nIt allows acccess to all biometric commands.\r\n\r\n\n#### This default permission set includes:\n\n- `allow-authenticate`\n- `allow-status`" "markdownDescription": "This permission set configures which\nbiometric features are by default exposed.\n\n#### Granted Permissions\n\nIt allows acccess to all biometric commands.\n\n\n#### This default permission set includes:\n\n- `allow-authenticate`\n- `allow-status`"
} }
] ]
} }
-4
View File
@@ -1,9 +1,5 @@
# Changelog # 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] ## \[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 - [`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] [package]
name = "tauri-plugin-cli" name = "tauri-plugin-cli"
version = "2.4.1" version = "2.4.0"
description = "Parse arguments from your Tauri application's command line interface." description = "Parse arguments from your Tauri application's command line interface."
edition = { workspace = true } edition = { workspace = true }
authors = { workspace = true } authors = { workspace = true }
@@ -9,6 +9,10 @@ rust-version = { workspace = true }
repository = { workspace = true } repository = { workspace = true }
links = "tauri-plugin-cli" links = "tauri-plugin-cli"
[package.metadata.docs.rs]
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
[package.metadata.platforms.support] [package.metadata.platforms.support]
windows = { level = "full", notes = "" } windows = { level = "full", notes = "" }
linux = { level = "full", notes = "" } linux = { level = "full", notes = "" }
+9
View File
@@ -34,12 +34,21 @@ tauri-plugin-cli = { git = "https://github.com/tauri-apps/plugins-workspace", br
You can install the JavaScript Guest bindings using your preferred JavaScript package manager: You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh ```sh
pnpm add @tauri-apps/plugin-cli pnpm add @tauri-apps/plugin-cli
# or # or
npm add @tauri-apps/plugin-cli npm add @tauri-apps/plugin-cli
# or # or
yarn add @tauri-apps/plugin-cli yarn add @tauri-apps/plugin-cli
# alternatively with Git:
pnpm add https://github.com/tauri-apps/tauri-plugin-cli#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-cli#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-cli#v2
``` ```
## Usage ## Usage
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "@tauri-apps/plugin-cli", "name": "@tauri-apps/plugin-cli",
"version": "2.4.1", "version": "2.4.0",
"license": "MIT OR Apache-2.0", "license": "MIT OR Apache-2.0",
"authors": [ "authors": [
"Tauri Programme within The Commons Conservancy" "Tauri Programme within The Commons Conservancy"
@@ -24,6 +24,6 @@
"LICENSE" "LICENSE"
], ],
"dependencies": { "dependencies": {
"@tauri-apps/api": "^2.8.0" "@tauri-apps/api": "^2.6.0"
} }
} }
-8
View File
@@ -1,13 +1,5 @@
# Changelog # 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] ## \[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 - [`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 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "tauri-plugin-clipboard-manager" name = "tauri-plugin-clipboard-manager"
version = "2.3.2" version = "2.3.0"
description = "Read and write to the system clipboard." description = "Read and write to the system clipboard."
edition = { workspace = true } edition = { workspace = true }
authors = { workspace = true } authors = { workspace = true }
@@ -10,7 +10,8 @@ repository = { workspace = true }
links = "tauri-plugin-clipboard-manager" links = "tauri-plugin-clipboard-manager"
[package.metadata.docs.rs] [package.metadata.docs.rs]
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
targets = ["x86_64-unknown-linux-gnu", "x86_64-linux-android"] targets = ["x86_64-unknown-linux-gnu", "x86_64-linux-android"]
[package.metadata.platforms.support] [package.metadata.platforms.support]
+9
View File
@@ -33,12 +33,21 @@ tauri-plugin-clipboard-manager = { git = "https://github.com/tauri-apps/plugins-
You can install the JavaScript Guest bindings using your preferred JavaScript package manager: You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh ```sh
pnpm add @tauri-apps/plugin-clipboard-manager pnpm add @tauri-apps/plugin-clipboard-manager
# or # or
npm add @tauri-apps/plugin-clipboard-manager npm add @tauri-apps/plugin-clipboard-manager
# or # or
yarn add @tauri-apps/plugin-clipboard-manager yarn add @tauri-apps/plugin-clipboard-manager
# alternatively with Git:
pnpm add https://github.com/tauri-apps/tauri-plugin-clipboard-manager#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-clipboard-manager#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-clipboard-manager#v2
``` ```
## Usage ## Usage
@@ -5,10 +5,10 @@ plugins {
android { android {
namespace = "app.tauri.clipboard" namespace = "app.tauri.clipboard"
compileSdk = 36 compileSdk = 34
defaultConfig { defaultConfig {
minSdk = 24 minSdk = 24
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro") consumerProguardFiles("consumer-rules.pro")
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "@tauri-apps/plugin-clipboard-manager", "name": "@tauri-apps/plugin-clipboard-manager",
"version": "2.3.2", "version": "2.3.0",
"license": "MIT OR Apache-2.0", "license": "MIT OR Apache-2.0",
"authors": [ "authors": [
"Tauri Programme within The Commons Conservancy" "Tauri Programme within The Commons Conservancy"
@@ -24,6 +24,6 @@
"LICENSE" "LICENSE"
], ],
"dependencies": { "dependencies": {
"@tauri-apps/api": "^2.8.0" "@tauri-apps/api": "^2.6.0"
} }
} }
@@ -1,7 +1,7 @@
## Default Permission ## Default Permission
No features are enabled by default, as we believe No features are enabled by default, as we believe
the clipboard can be inherently dangerous and it is the clipboard can be inherently dangerous and it is
application specific if read and/or write access is needed. application specific if read and/or write access is needed.
Clipboard interaction needs to be explicitly enabled. Clipboard interaction needs to be explicitly enabled.
@@ -2,7 +2,7 @@
[default] [default]
description = """ description = """
No features are enabled by default, as we believe No features are enabled by default, as we believe
the clipboard can be inherently dangerous and it is the clipboard can be inherently dangerous and it is
application specific if read and/or write access is needed. application specific if read and/or write access is needed.
Clipboard interaction needs to be explicitly enabled. Clipboard interaction needs to be explicitly enabled.
@@ -367,10 +367,10 @@
"markdownDescription": "Denies the write_text command without any pre-configured scope." "markdownDescription": "Denies the write_text command without any pre-configured scope."
}, },
{ {
"description": "No features are enabled by default, as we believe\r\nthe clipboard can be inherently dangerous and it is\r\napplication specific if read and/or write access is needed.\r\n\r\nClipboard interaction needs to be explicitly enabled.\r\n", "description": "No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n",
"type": "string", "type": "string",
"const": "default", "const": "default",
"markdownDescription": "No features are enabled by default, as we believe\r\nthe clipboard can be inherently dangerous and it is\r\napplication specific if read and/or write access is needed.\r\n\r\nClipboard interaction needs to be explicitly enabled.\r\n" "markdownDescription": "No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n"
} }
] ]
} }
-17
View File
@@ -1,22 +1,5 @@
# Changelog # Changelog
## \[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] ## \[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 - [`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] [package]
name = "tauri-plugin-deep-link" name = "tauri-plugin-deep-link"
version = "2.4.5" version = "2.4.1"
description = "Set your Tauri application as the default handler for an URL" description = "Set your Tauri application as the default handler for an URL"
authors = { workspace = true } authors = { workspace = true }
license = { workspace = true } license = { workspace = true }
@@ -10,6 +10,8 @@ repository = { workspace = true }
links = "tauri-plugin-deep-link" links = "tauri-plugin-deep-link"
[package.metadata.docs.rs] [package.metadata.docs.rs]
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
targets = ["x86_64-linux-android"] targets = ["x86_64-linux-android"]
[package.metadata.platforms.support] [package.metadata.platforms.support]
@@ -25,9 +27,6 @@ serde_json = { workspace = true }
tauri-utils = { workspace = true } tauri-utils = { workspace = true }
tauri-plugin = { workspace = true, features = ["build"] } tauri-plugin = { workspace = true, features = ["build"] }
[target."cfg(target_os = \"macos\")".build-dependencies]
plist = "1"
[dependencies] [dependencies]
serde = { workspace = true } serde = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
+9
View File
@@ -33,12 +33,21 @@ tauri-plugin-deep-link = { git = "https://github.com/tauri-apps/plugins-workspac
You can install the JavaScript Guest bindings using your preferred JavaScript package manager: You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh ```sh
pnpm add @tauri-apps/plugin-deep-link pnpm add @tauri-apps/plugin-deep-link
# or # or
npm add @tauri-apps/plugin-deep-link npm add @tauri-apps/plugin-deep-link
# or # or
yarn add @tauri-apps/plugin-deep-link yarn add @tauri-apps/plugin-deep-link
# alternatively with Git:
pnpm add https://github.com/tauri-apps/tauri-plugin-deep-link#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-deep-link#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-deep-link#v2
``` ```
## Setting up ## Setting up
+2 -2
View File
@@ -5,10 +5,10 @@ plugins {
android { android {
namespace = "app.tauri.deep_link" namespace = "app.tauri.deep_link"
compileSdk = 36 compileSdk = 34
defaultConfig { defaultConfig {
minSdk = 24 minSdk = 24
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro") consumerProguardFiles("consumer-rules.pro")
+26 -119
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. // TODO: Consider using activity-alias in case users may have multiple activities in their app.
fn intent_filter(domain: &AssociatedDomain) -> String { 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!( format!(
r#"<intent-filter {auto_verify}> r#"<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
{schemes} {}
{host} <data android:host="{}" />
{domains} {}
{path_patterns} {}
{path_prefixes} {}
{path_suffixes} {}
</intent-filter>"#, </intent-filter>"#,
schemes = domain domain
.scheme .scheme
.iter() .iter()
.map(|scheme| format!(r#"<data android:scheme="{scheme}" />"#)) .map(|scheme| format!(r#"<data android:scheme="{scheme}" />"#))
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join("\n "), .join("\n "),
host = host, domain.host,
domains = domain domain
.path .path
.iter() .iter()
.map(|path| format!(r#"<data android:path="{path}" />"#)) .map(|path| format!(r#"<data android:path="{path}" />"#))
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join("\n "), .join("\n "),
path_patterns = domain domain
.path_pattern .path_pattern
.iter() .iter()
.map(|pattern| format!(r#"<data android:pathPattern="{pattern}" />"#)) .map(|pattern| format!(r#"<data android:pathPattern="{pattern}" />"#))
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join("\n "), .join("\n "),
path_prefixes = domain domain
.path_prefix .path_prefix
.iter() .iter()
.map(|prefix| format!(r#"<data android:pathPrefix="{prefix}" />"#)) .map(|prefix| format!(r#"<data android:pathPrefix="{prefix}" />"#))
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join("\n "), .join("\n "),
path_suffixes = domain domain
.path_suffix .path_suffix
.iter() .iter()
.map(|suffix| format!(r#"<data android:pathSuffix="{suffix}" />"#)) .map(|suffix| format!(r#"<data android:pathSuffix="{suffix}" />"#))
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join("\n "), .join("\n "),
) )
.trim()
.to_string()
} }
fn main() { fn main() {
@@ -82,16 +68,6 @@ fn main() {
} }
if let Some(config) = tauri_plugin::plugin_config::<Config>("deep-link") { 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( tauri_plugin::mobile::update_android_manifest(
"DEEP LINK PLUGIN", "DEEP LINK PLUGIN",
"activity", "activity",
@@ -104,89 +80,20 @@ fn main() {
) )
.expect("failed to rewrite AndroidManifest.xml"); .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 tauri_plugin::mobile::update_entitlements(|entitlements| {
// generated for explicit app links and not entitlements.insert(
// other deep links because then they "com.apple.developer.associated-domains".into(),
// are just going to complain and not be built or signed config
let has_app_links = config.mobile.iter().any(|d| d.is_app_link()); .mobile
.into_iter()
if !has_app_links { .map(|d| format!("applinks:{}", d.host).into())
tauri_plugin::mobile::update_entitlements(|entitlements| { .collect::<Vec<_>>()
entitlements.remove("com.apple.developer.associated-domains"); .into(),
}) );
.expect("failed to update entitlements"); })
} else { .expect("failed to update entitlements");
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_map(|domain| {
if domain.is_app_link() {
return None;
}
Some(domain)
})
.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(),
format!("{}", domain.scheme[0]).into(),
);
plist::Value::Dictionary(dict)
})
.collect::<Vec<_>>()
.into(),
);
})
.expect("failed to update Info.plist");
}
} }
} }
} }
@@ -1,29 +1,5 @@
# Changelog # Changelog
## \[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] ## \[2.2.4]
### Dependencies ### Dependencies
+5 -5
View File
@@ -1,7 +1,7 @@
{ {
"name": "deep-link-example", "name": "deep-link-example",
"private": true, "private": true,
"version": "2.2.8", "version": "2.2.4",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
@@ -10,12 +10,12 @@
"tauri": "tauri" "tauri": "tauri"
}, },
"dependencies": { "dependencies": {
"@tauri-apps/api": "2.9.0", "@tauri-apps/api": "2.7.0",
"@tauri-apps/plugin-deep-link": "2.4.5" "@tauri-apps/plugin-deep-link": "2.4.1"
}, },
"devDependencies": { "devDependencies": {
"@tauri-apps/cli": "2.9.4", "@tauri-apps/cli": "2.7.1",
"typescript": "^5.7.3", "typescript": "^5.7.3",
"vite": "^7.0.7" "vite": "^7.0.4"
} }
} }
@@ -14,13 +14,13 @@ val tauriProperties = Properties().apply {
} }
android { android {
compileSdk = 36 compileSdk = 34
namespace = "com.tauri.deep_link_example" namespace = "com.tauri.deep_link_example"
defaultConfig { defaultConfig {
manifestPlaceholders["usesCleartextTraffic"] = "false" manifestPlaceholders["usesCleartextTraffic"] = "false"
applicationId = "com.tauri.deep_link_example" applicationId = "com.tauri.deep_link_example"
minSdk = 24 minSdk = 24
targetSdk = 36 targetSdk = 34
versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt() versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt()
versionName = tauriProperties.getProperty("tauri.android.versionName", "1.0") versionName = tauriProperties.getProperty("tauri.android.versionName", "1.0")
} }
@@ -58,10 +58,9 @@ rust {
} }
dependencies { dependencies {
implementation("androidx.webkit:webkit:1.14.0") implementation("androidx.webkit:webkit:1.6.1")
implementation("androidx.appcompat:appcompat:1.7.1") implementation("androidx.appcompat:appcompat:1.6.1")
implementation("androidx.activity:activity-ktx:1.10.1") implementation("com.google.android.material:material:1.8.0")
implementation("com.google.android.material:material:1.12.0")
testImplementation("junit:junit:4.13.2") testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.4") androidTestImplementation("androidx.test.ext:junit:1.1.4")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.0") androidTestImplementation("androidx.test.espresso:espresso-core:3.5.0")
@@ -23,40 +23,23 @@
<category android:name="android.intent.category.LEANBACK_LAUNCHER" /> <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter> </intent-filter>
<!-- DEEP LINK PLUGIN. AUTO-GENERATED. DO NOT REMOVE. --> <!-- 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" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:scheme="http" /> <data android:scheme="http" />
<data android:scheme="https" />
<data android:host="fabianlars.de" /> <data android:host="fabianlars.de" />
<data android:pathPrefix="/intent" /> <data android:pathPrefix="/intent" />
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true" > <intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:scheme="http" /> <data android:scheme="http" />
<data android:scheme="https" />
<data android:host="tauri.app" /> <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> </intent-filter>
<!-- DEEP LINK PLUGIN. AUTO-GENERATED. DO NOT REMOVE. --> <!-- DEEP LINK PLUGIN. AUTO-GENERATED. DO NOT REMOVE. -->
</activity> </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 package com.tauri.deep_link_example
import android.os.Bundle class MainActivity : TauriActivity()
import androidx.activity.enableEdgeToEdge
class MainActivity : TauriActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge()
super.onCreate(savedInstanceState)
}
}
@@ -4,7 +4,7 @@ buildscript {
mavenCentral() mavenCentral()
} }
dependencies { 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") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.25")
} }
} }
@@ -18,6 +18,6 @@ repositories {
dependencies { dependencies {
compileOnly(gradleApi()) 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 #Tue May 10 19:22:52 CST 2022
distributionBase=GRADLE_USER_HOME 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 distributionPath=wrapper/dists
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
@@ -1,116 +1,116 @@
{ {
"images" : [ "images": [
{ {
"size" : "20x20", "size": "20x20",
"idiom" : "iphone", "idiom": "iphone",
"filename" : "AppIcon-20x20@2x.png", "filename": "AppIcon-20x20@2x.png",
"scale" : "2x" "scale": "2x"
}, },
{ {
"size" : "20x20", "size": "20x20",
"idiom" : "iphone", "idiom": "iphone",
"filename" : "AppIcon-20x20@3x.png", "filename": "AppIcon-20x20@3x.png",
"scale" : "3x" "scale": "3x"
}, },
{ {
"size" : "29x29", "size": "29x29",
"idiom" : "iphone", "idiom": "iphone",
"filename" : "AppIcon-29x29@2x-1.png", "filename": "AppIcon-29x29@2x-1.png",
"scale" : "2x" "scale": "2x"
}, },
{ {
"size" : "29x29", "size": "29x29",
"idiom" : "iphone", "idiom": "iphone",
"filename" : "AppIcon-29x29@3x.png", "filename": "AppIcon-29x29@3x.png",
"scale" : "3x" "scale": "3x"
}, },
{ {
"size" : "40x40", "size": "40x40",
"idiom" : "iphone", "idiom": "iphone",
"filename" : "AppIcon-40x40@2x.png", "filename": "AppIcon-40x40@2x.png",
"scale" : "2x" "scale": "2x"
}, },
{ {
"size" : "40x40", "size": "40x40",
"idiom" : "iphone", "idiom": "iphone",
"filename" : "AppIcon-40x40@3x.png", "filename": "AppIcon-40x40@3x.png",
"scale" : "3x" "scale": "3x"
}, },
{ {
"size" : "60x60", "size": "60x60",
"idiom" : "iphone", "idiom": "iphone",
"filename" : "AppIcon-60x60@2x.png", "filename": "AppIcon-60x60@2x.png",
"scale" : "2x" "scale": "2x"
}, },
{ {
"size" : "60x60", "size": "60x60",
"idiom" : "iphone", "idiom": "iphone",
"filename" : "AppIcon-60x60@3x.png", "filename": "AppIcon-60x60@3x.png",
"scale" : "3x" "scale": "3x"
}, },
{ {
"size" : "20x20", "size": "20x20",
"idiom" : "ipad", "idiom": "ipad",
"filename" : "AppIcon-20x20@1x.png", "filename": "AppIcon-20x20@1x.png",
"scale" : "1x" "scale": "1x"
}, },
{ {
"size" : "20x20", "size": "20x20",
"idiom" : "ipad", "idiom": "ipad",
"filename" : "AppIcon-20x20@2x-1.png", "filename": "AppIcon-20x20@2x-1.png",
"scale" : "2x" "scale": "2x"
}, },
{ {
"size" : "29x29", "size": "29x29",
"idiom" : "ipad", "idiom": "ipad",
"filename" : "AppIcon-29x29@1x.png", "filename": "AppIcon-29x29@1x.png",
"scale" : "1x" "scale": "1x"
}, },
{ {
"size" : "29x29", "size": "29x29",
"idiom" : "ipad", "idiom": "ipad",
"filename" : "AppIcon-29x29@2x.png", "filename": "AppIcon-29x29@2x.png",
"scale" : "2x" "scale": "2x"
}, },
{ {
"size" : "40x40", "size": "40x40",
"idiom" : "ipad", "idiom": "ipad",
"filename" : "AppIcon-40x40@1x.png", "filename": "AppIcon-40x40@1x.png",
"scale" : "1x" "scale": "1x"
}, },
{ {
"size" : "40x40", "size": "40x40",
"idiom" : "ipad", "idiom": "ipad",
"filename" : "AppIcon-40x40@2x-1.png", "filename": "AppIcon-40x40@2x-1.png",
"scale" : "2x" "scale": "2x"
}, },
{ {
"size" : "76x76", "size": "76x76",
"idiom" : "ipad", "idiom": "ipad",
"filename" : "AppIcon-76x76@1x.png", "filename": "AppIcon-76x76@1x.png",
"scale" : "1x" "scale": "1x"
}, },
{ {
"size" : "76x76", "size": "76x76",
"idiom" : "ipad", "idiom": "ipad",
"filename" : "AppIcon-76x76@2x.png", "filename": "AppIcon-76x76@2x.png",
"scale" : "2x" "scale": "2x"
}, },
{ {
"size" : "83.5x83.5", "size": "83.5x83.5",
"idiom" : "ipad", "idiom": "ipad",
"filename" : "AppIcon-83.5x83.5@2x.png", "filename": "AppIcon-83.5x83.5@2x.png",
"scale" : "2x" "scale": "2x"
}, },
{ {
"size" : "1024x1024", "size": "1024x1024",
"idiom" : "ios-marketing", "idiom": "ios-marketing",
"filename" : "AppIcon-512@2x.png", "filename": "AppIcon-512@2x.png",
"scale" : "1x" "scale": "1x"
} }
], ],
"info" : { "info": {
"version" : 1, "version": 1,
"author" : "xcode" "author": "xcode"
} }
} }
@@ -1,6 +1,6 @@
{ {
"info" : { "info": {
"version" : 1, "version": 1,
"author" : "xcode" "author": "xcode"
} }
} }
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?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> <dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17122"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17122"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/> <capability name="Safe area layout guides" minToolsVersion="9.0"/>
@@ -3,7 +3,7 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 63; objectVersion = 56;
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
@@ -167,8 +167,6 @@
dependencies = ( dependencies = (
); );
name = "deep-link-example_iOS"; name = "deep-link-example_iOS";
packageProductDependencies = (
);
productName = "deep-link-example_iOS"; productName = "deep-link-example_iOS";
productReference = 1CAAFA750FD735A285DC1238 /* deep-link-example.app */; productReference = 1CAAFA750FD735A285DC1238 /* deep-link-example.app */;
productType = "com.apple.product-type.application"; productType = "com.apple.product-type.application";
@@ -191,7 +189,6 @@
en, en,
); );
mainGroup = 1DC58B1705AA3ECC6B887FE7; mainGroup = 1DC58B1705AA3ECC6B887FE7;
minimizedProjectReferenceProxies = 1;
projectDirPath = ""; projectDirPath = "";
projectRoot = ""; projectRoot = "";
targets = ( targets = (
@@ -230,6 +227,7 @@
outputPaths = ( outputPaths = (
"$(SRCROOT)/Externals/x86_64/${CONFIGURATION}/libapp.a", "$(SRCROOT)/Externals/x86_64/${CONFIGURATION}/libapp.a",
"$(SRCROOT)/Externals/arm64/${CONFIGURATION}/libapp.a", "$(SRCROOT)/Externals/arm64/${CONFIGURATION}/libapp.a",
"$(SRCROOT)/Externals/arm64-sim/${CONFIGURATION}/libapp.a",
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
@@ -316,13 +314,18 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ARCHS = arm64; ARCHS = (
arm64,
"arm64-sim",
);
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = "deep-link-example_iOS/deep-link-example_iOS.entitlements"; CODE_SIGN_ENTITLEMENTS = "deep-link-example_iOS/deep-link-example_iOS.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_IDENTITY = "iPhone Developer";
DEVELOPMENT_TEAM = "Q93MBH6S2F"; CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = Q93MBH6S2F;
ENABLE_BITCODE = NO; 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 = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"\".\"", "\".\"",
@@ -332,6 +335,13 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@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]" = ( "LIBRARY_SEARCH_PATHS[arch=arm64]" = (
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION)", "$(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION)",
@@ -350,7 +360,7 @@
PRODUCT_NAME = "deep-link-example"; PRODUCT_NAME = "deep-link-example";
SDKROOT = iphoneos; SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = arm64; VALID_ARCHS = "arm64 arm64-sim";
}; };
name = debug; name = debug;
}; };
@@ -414,13 +424,18 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ARCHS = arm64; ARCHS = (
arm64,
"arm64-sim",
);
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = "deep-link-example_iOS/deep-link-example_iOS.entitlements"; CODE_SIGN_ENTITLEMENTS = "deep-link-example_iOS/deep-link-example_iOS.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_IDENTITY = "iPhone Developer";
DEVELOPMENT_TEAM = "Q93MBH6S2F"; CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = Q93MBH6S2F;
ENABLE_BITCODE = NO; 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 = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"\".\"", "\".\"",
@@ -430,6 +445,13 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@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]" = ( "LIBRARY_SEARCH_PATHS[arch=arm64]" = (
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION)", "$(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION)",
@@ -448,7 +470,7 @@
PRODUCT_NAME = "deep-link-example"; PRODUCT_NAME = "deep-link-example";
SDKROOT = iphoneos; SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = arm64; VALID_ARCHS = "arm64 arm64-sim";
}; };
name = release; 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> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>0.1.0</string> <string>0.0.0</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>0.1.0</string> <string>0.1.0</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
@@ -40,16 +40,5 @@
<string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string> <string>UIInterfaceOrientationLandscapeRight</string>
</array> </array>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>taurideeplink</string>
</array>
<key>CFBundleURLName</key>
<string>taurideeplink</string>
</dict>
</array>
</dict> </dict>
</plist> </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 name: deep-link-example
options: options:
bundleIdPrefix: com.tauri.deep-link-example bundleIdPrefix: com.tauri.deep-link-example
@@ -12,6 +16,7 @@ settingGroups:
base: base:
PRODUCT_NAME: deep-link-example PRODUCT_NAME: deep-link-example
PRODUCT_BUNDLE_IDENTIFIER: com.tauri.deep-link-example PRODUCT_BUNDLE_IDENTIFIER: com.tauri.deep-link-example
DEVELOPMENT_TEAM: Q93MBH6S2F
targetTemplates: targetTemplates:
app: app:
type: application type: application
@@ -51,8 +56,8 @@ targets:
- UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationPortraitUpsideDown
- UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight - UIInterfaceOrientationLandscapeRight
CFBundleShortVersionString: 0.1.0 CFBundleShortVersionString: 0.0.0
CFBundleVersion: '0.1.0' CFBundleVersion: 0.0.0
entitlements: entitlements:
path: deep-link-example_iOS/deep-link-example_iOS.entitlements path: deep-link-example_iOS/deep-link-example_iOS.entitlements
scheme: scheme:
@@ -62,12 +67,14 @@ targets:
settings: settings:
base: base:
ENABLE_BITCODE: false ENABLE_BITCODE: false
ARCHS: [arm64] ARCHS: [arm64, arm64-sim]
VALID_ARCHS: arm64 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=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]: $(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 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] groups: [app]
dependencies: dependencies:
- framework: libapp.a - framework: libapp.a
@@ -86,3 +93,4 @@ targets:
outputFiles: outputFiles:
- $(SRCROOT)/Externals/x86_64/${CONFIGURATION}/libapp.a - $(SRCROOT)/Externals/x86_64/${CONFIGURATION}/libapp.a
- $(SRCROOT)/Externals/arm64/${CONFIGURATION}/libapp.a - $(SRCROOT)/Externals/arm64/${CONFIGURATION}/libapp.a
- $(SRCROOT)/Externals/arm64-sim/${CONFIGURATION}/libapp.a
@@ -35,9 +35,6 @@
}, },
{ {
"host": "tauri.app" "host": "tauri.app"
},
{
"scheme": ["taurideeplink"]
} }
], ],
"desktop": { "desktop": {
+2 -5
View File
@@ -1,6 +1,6 @@
{ {
"name": "@tauri-apps/plugin-deep-link", "name": "@tauri-apps/plugin-deep-link",
"version": "2.4.5", "version": "2.4.1",
"description": "Set your Tauri application as the default handler for an URL", "description": "Set your Tauri application as the default handler for an URL",
"license": "MIT OR Apache-2.0", "license": "MIT OR Apache-2.0",
"authors": [ "authors": [
@@ -25,9 +25,6 @@
"LICENSE" "LICENSE"
], ],
"dependencies": { "dependencies": {
"@tauri-apps/api": "^2.8.0" "@tauri-apps/api": "^2.6.0"
},
"devDependencies": {
"@tauri-apps/cli": "2.9.4"
} }
} }
+12 -46
View File
@@ -11,8 +11,10 @@ use tauri_utils::config::DeepLinkProtocol;
pub struct AssociatedDomain { pub struct AssociatedDomain {
#[serde(default = "default_schemes")] #[serde(default = "default_schemes")]
pub scheme: Vec<String>, 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)] #[serde(default)]
pub path: Vec<String>, pub path: Vec<String>,
#[serde(default, alias = "path-pattern", rename = "pathPattern")] #[serde(default, alias = "path-pattern", rename = "pathPattern")]
@@ -21,41 +23,6 @@ pub struct AssociatedDomain {
pub path_prefix: Vec<String>, pub path_prefix: Vec<String>,
#[serde(default, alias = "path-suffix", rename = "pathSuffix")] #[serde(default, alias = "path-suffix", rename = "pathSuffix")]
pub path_suffix: Vec<String>, 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 // TODO: Consider removing this in v3
@@ -63,19 +30,18 @@ fn default_schemes() -> Vec<String> {
vec!["https".to_string(), "http".to_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 where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
let opt = Option::<String>::deserialize(deserializer)?; let host = String::deserialize(deserializer)?;
if let Some(ref host) = opt { if let Some((scheme, _host)) = host.split_once("://") {
if let Some((scheme, _)) = host.split_once("://") { Err(serde::de::Error::custom(format!(
return Err(serde::de::Error::custom(format!( "host `{host}` cannot start with a scheme, please remove the `{scheme}://` prefix"
"host `{host}` cannot start with a scheme, please remove the `{scheme}://` prefix" )))
))); } else {
} Ok(host)
} }
Ok(opt)
} }
#[derive(Deserialize, Clone)] #[derive(Deserialize, Clone)]
-10
View File
@@ -28,16 +28,6 @@ pub enum Error {
PluginInvoke(#[from] tauri::plugin::mobile::PluginInvokeError), 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 { impl Serialize for Error {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where where
+6 -30
View File
@@ -254,7 +254,6 @@ mod imp {
/// ///
/// ## Platform-specific: /// ## 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`). /// - **macOS / Android / iOS**: Unsupported, will return [`Error::UnsupportedPlatform`](`crate::Error::UnsupportedPlatform`).
pub fn register<S: AsRef<str>>(&self, _protocol: S) -> crate::Result<()> { pub fn register<S: AsRef<str>>(&self, _protocol: S) -> crate::Result<()> {
#[cfg(windows)] #[cfg(windows)]
@@ -293,7 +292,6 @@ mod imp {
.unwrap_or_else(|| bin.into_os_string()) .unwrap_or_else(|| bin.into_os_string())
.to_string_lossy() .to_string_lossy()
.to_string(); .to_string();
let qualified_exec = format!("{} %u", exec);
let target = self.app.path().data_dir()?.join("applications"); 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 Ok(mut desktop_file) = ini::Ini::load_from_file(&target_file) {
if let Some(section) = desktop_file.section_mut(Some("Desktop Entry")) { 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 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) { if !old_mimes.split(';').any(|mime| mime == mime_type) {
section.append("MimeType", format!("{mime_type};{old_mimes}")); 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)?; desktop_file.write_to_file(&target_file)?;
} }
} }
@@ -341,7 +323,7 @@ mod imp {
.product_name .product_name
.clone() .clone()
.unwrap_or_else(|| file_name.clone()), .unwrap_or_else(|| file_name.clone()),
qualified_exec = qualified_exec, exec = exec,
mime_type = mime_type mime_type = mime_type
) )
.as_bytes(), .as_bytes(),
@@ -350,15 +332,11 @@ mod imp {
Command::new("update-desktop-database") Command::new("update-desktop-database")
.arg(target) .arg(target)
.status() .status()?;
.inspect_err(crate::error::inspect_command_error(
"update-desktop-database",
))?;
Command::new("xdg-mime") Command::new("xdg-mime")
.args(["default", &file_name, mime_type.as_str()]) .args(["default", &file_name, mime_type.as_str()])
.status() .status()?;
.inspect_err(crate::error::inspect_command_error("xdg-mime"))?;
Ok(()) Ok(())
} }
@@ -427,7 +405,6 @@ mod imp {
/// ///
/// ## Platform-specific: /// ## Platform-specific:
/// ///
/// - **Linux**: Needs the `xdg-mime` command available on the system.
/// - **macOS / Android / iOS**: Unsupported, will return [`Error::UnsupportedPlatform`](`crate::Error::UnsupportedPlatform`). /// - **macOS / Android / iOS**: Unsupported, will return [`Error::UnsupportedPlatform`](`crate::Error::UnsupportedPlatform`).
pub fn is_registered<S: AsRef<str>>(&self, _protocol: S) -> crate::Result<bool> { pub fn is_registered<S: AsRef<str>>(&self, _protocol: S) -> crate::Result<bool> {
#[cfg(windows)] #[cfg(windows)]
@@ -462,8 +439,7 @@ mod imp {
"default", "default",
&format!("x-scheme-handler/{}", _protocol.as_ref()), &format!("x-scheme-handler/{}", _protocol.as_ref()),
]) ])
.output() .output()?;
.inspect_err(crate::error::inspect_command_error("xdg-mime"))?;
Ok(String::from_utf8_lossy(&output.stdout).contains(&file_name)) Ok(String::from_utf8_lossy(&output.stdout).contains(&file_name))
} }
+2 -2
View File
@@ -1,7 +1,7 @@
[Desktop Entry] [Desktop Entry]
Type=Application Type=Application
Name={name} Name={name}
Exec={qualified_exec} Exec={exec} %u
Terminal=false Terminal=false
MimeType={mime_type} MimeType={mime_type}
NoDisplay=true NoDisplay=true
-30
View File
@@ -1,35 +1,5 @@
# Changelog # Changelog
## \[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.
## \[2.3.1] ## \[2.3.1]
### Dependencies ### Dependencies
+5 -8
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "tauri-plugin-dialog" name = "tauri-plugin-dialog"
version = "2.4.2" version = "2.3.1"
description = "Native system dialogs for opening and saving files along with message dialogs on your Tauri application." description = "Native system dialogs for opening and saving files along with message dialogs on your Tauri application."
edition = { workspace = true } edition = { workspace = true }
authors = { workspace = true } authors = { workspace = true }
@@ -9,12 +9,9 @@ rust-version = { workspace = true }
repository = { workspace = true } repository = { workspace = true }
links = "tauri-plugin-dialog" links = "tauri-plugin-dialog"
[features]
default = ["gtk3"]
xdg-portal = ["rfd/xdg-portal"]
gtk3 = ["rfd/gtk3"]
[package.metadata.docs.rs] [package.metadata.docs.rs]
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
targets = ["x86_64-unknown-linux-gnu", "x86_64-linux-android"] targets = ["x86_64-unknown-linux-gnu", "x86_64-linux-android"]
[package.metadata.platforms.support] [package.metadata.platforms.support]
@@ -37,7 +34,7 @@ tauri = { workspace = true }
log = { workspace = true } log = { workspace = true }
thiserror = { workspace = true } thiserror = { workspace = true }
url = { workspace = true } url = { workspace = true }
tauri-plugin-fs = { path = "../fs", version = "2.4.4" } tauri-plugin-fs = { path = "../fs", version = "2.4.1" }
[target.'cfg(target_os = "ios")'.dependencies] [target.'cfg(target_os = "ios")'.dependencies]
tauri = { workspace = true, features = ["wry"] } tauri = { workspace = true, features = ["wry"] }
@@ -45,7 +42,7 @@ 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] [target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
rfd = { version = "0.15", default-features = false, features = [ rfd = { version = "0.15", default-features = false, features = [
"tokio", "tokio",
"gtk3",
"common-controls-v6", "common-controls-v6",
] } ] }
raw-window-handle = "0.6" raw-window-handle = "0.6"
+9 -18
View File
@@ -31,32 +31,23 @@ tauri-plugin-dialog = "2.0.0"
tauri-plugin-dialog = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } 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: You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh ```sh
pnpm add @tauri-apps/plugin-dialog pnpm add @tauri-apps/plugin-dialog
# or # or
npm add @tauri-apps/plugin-dialog npm add @tauri-apps/plugin-dialog
# or # or
yarn add @tauri-apps/plugin-dialog yarn add @tauri-apps/plugin-dialog
# alternatively with Git:
pnpm add https://github.com/tauri-apps/tauri-plugin-dialog#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-dialog#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-dialog#v2
``` ```
## Usage ## Usage
+2 -2
View File
@@ -5,10 +5,10 @@ plugins {
android { android {
namespace = "app.tauri.dialog" namespace = "app.tauri.dialog"
compileSdk = 36 compileSdk = 34
defaultConfig { defaultConfig {
minSdk = 24 minSdk = 24
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro") consumerProguardFiles("consumer-rules.pro")
@@ -31,7 +31,6 @@ class Filter {
class FilePickerOptions { class FilePickerOptions {
lateinit var filters: Array<Filter> lateinit var filters: Array<Filter>
var multiple: Boolean? = null var multiple: Boolean? = null
var pickerMode: String? = null
} }
@InvokeArg @InvokeArg
@@ -39,7 +38,6 @@ class MessageOptions {
var title: String? = null var title: String? = null
lateinit var message: String lateinit var message: String
var okButtonLabel: String? = null var okButtonLabel: String? = null
var noButtonLabel: String? = null
var cancelButtonLabel: String? = null var cancelButtonLabel: String? = null
} }
@@ -58,27 +56,20 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) {
try { try {
val args = invoke.parseArgs(FilePickerOptions::class.java) val args = invoke.parseArgs(FilePickerOptions::class.java)
val parsedTypes = parseFiltersOption(args.filters) val parsedTypes = parseFiltersOption(args.filters)
// TODO: ACTION_OPEN_DOCUMENT ?? val intent = if (parsedTypes.isNotEmpty()) {
val intent = Intent(Intent.ACTION_GET_CONTENT) val intent = Intent(Intent.ACTION_PICK)
intent.addCategory(Intent.CATEGORY_OPENABLE) setIntentMimeTypes(intent, parsedTypes)
intent
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 = "*/*"
intent.putExtra(Intent.EXTRA_MIME_TYPES, parsedTypes)
} else { } else {
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "*/*" intent.type = "*/*"
intent
} }
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, args.multiple ?: false) intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, args.multiple ?: false)
startActivityForResult(invoke, intent, "filePickerResult") startActivityForResult(invoke, intent, "filePickerResult")
} catch (ex: Exception) { } catch (ex: Exception) {
val message = ex.message ?: "Failed to pick file" val message = ex.message ?: "Failed to pick file"
@@ -124,7 +115,7 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) {
callResult.put("files", JSArray.from(uris.toTypedArray())) callResult.put("files", JSArray.from(uris.toTypedArray()))
return callResult return callResult
} }
private fun parseFiltersOption(filters: Array<Filter>): Array<String> { private fun parseFiltersOption(filters: Array<Filter>): Array<String> {
val mimeTypes = mutableListOf<String>() val mimeTypes = mutableListOf<String>()
for (filter in filters) { for (filter in filters) {
@@ -141,17 +132,46 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) {
return mimeTypes.toTypedArray() return mimeTypes.toTypedArray()
} }
private fun setIntentMimeTypes(intent: Intent, mimeTypes: Array<String>) {
if (mimeTypes.isNotEmpty()) {
var uniqueMimeKind = true
var mimeKind: String? = null
for (mime in mimeTypes) {
val kind = mime.split("/")[0]
if (mimeKind == null) {
mimeKind = kind
} else if (mimeKind != kind) {
uniqueMimeKind = false
}
}
if (uniqueMimeKind) {
if (mimeTypes.size > 1) {
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes)
intent.type = Intent.normalizeMimeType("$mimeKind/*")
} else {
intent.type = mimeTypes[0]
}
} else {
intent.type = "*/*"
}
} else {
intent.type = "*/*"
}
}
@Command @Command
fun showMessageDialog(invoke: Invoke) { fun showMessageDialog(invoke: Invoke) {
val args = invoke.parseArgs(MessageOptions::class.java) val args = invoke.parseArgs(MessageOptions::class.java)
if (activity.isFinishing) { if (activity.isFinishing) {
invoke.reject("App is finishing") invoke.reject("App is finishing")
return return
} }
val handler = { value: String -> val handler = { cancelled: Boolean, value: Boolean ->
val ret = JSObject() val ret = JSObject()
ret.put("cancelled", cancelled)
ret.put("value", value) ret.put("value", value)
invoke.resolve(ret) invoke.resolve(ret)
} }
@@ -159,38 +179,28 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) {
Handler(Looper.getMainLooper()) Handler(Looper.getMainLooper())
.post { .post {
val builder = AlertDialog.Builder(activity) val builder = AlertDialog.Builder(activity)
if (args.title != null) { if (args.title != null) {
builder.setTitle(args.title) builder.setTitle(args.title)
} }
val okButtonLabel = args.okButtonLabel ?: "Ok"
builder builder
.setMessage(args.message) .setMessage(args.message)
.setPositiveButton(okButtonLabel) { dialog, _ -> .setPositiveButton(
args.okButtonLabel ?: "OK"
) { dialog, _ ->
dialog.dismiss() dialog.dismiss()
handler(okButtonLabel) handler(false, true)
} }
.setOnCancelListener { dialog -> .setOnCancelListener { dialog ->
dialog.dismiss() 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) { if (args.cancelButtonLabel != null) {
builder.setNegativeButton( args.cancelButtonLabel) { dialog, _ -> builder.setNegativeButton( args.cancelButtonLabel) { dialog, _ ->
dialog.dismiss() dialog.dismiss()
handler(args.cancelButtonLabel!!) handler(false, false)
} }
} }
val dialog = builder.create() val dialog = builder.create()
dialog.show() dialog.show()
} }
@@ -203,14 +213,10 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) {
val parsedTypes = parseFiltersOption(args.filters) val parsedTypes = parseFiltersOption(args.filters)
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT) val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
setIntentMimeTypes(intent, parsedTypes)
intent.addCategory(Intent.CATEGORY_OPENABLE) intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.putExtra(Intent.EXTRA_TITLE, args.fileName ?: "") intent.putExtra(Intent.EXTRA_TITLE, args.fileName ?: "")
intent.type = "*/*"
if (parsedTypes.isNotEmpty()) {
intent.putExtra(Intent.EXTRA_MIME_TYPES, parsedTypes)
}
startActivityForResult(invoke, intent, "saveFileDialogResult") startActivityForResult(invoke, intent, "saveFileDialogResult")
} catch (ex: Exception) { } catch (ex: Exception) {
val message = ex.message ?: "Failed to pick save file" val message = ex.message ?: "Failed to pick save file"
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_DIALOG__=function(t){"use strict";async function n(t,n={},e){return window.__TAURI_INTERNALS__.invoke(t,n,e)}function e(t){if(void 0!==t)return"string"==typeof t?t:"ok"in t&&"cancel"in t?{OkCancelCustom:[t.ok,t.cancel]}:"yes"in t&&"no"in t&&"cancel"in t?{YesNoCancelCustom:[t.yes,t.no,t.cancel]}:"ok"in t?{OkCustom:t.ok}:void 0}return"function"==typeof SuppressedError&&SuppressedError,t.ask=async function(t,e){const o="string"==typeof e?{title:e}:e;return await n("plugin:dialog|ask",{message:t.toString(),title:o?.title?.toString(),kind:o?.kind,yesButtonLabel:o?.okLabel?.toString(),noButtonLabel:o?.cancelLabel?.toString()})},t.confirm=async function(t,e){const o="string"==typeof e?{title:e}:e;return await n("plugin:dialog|confirm",{message:t.toString(),title:o?.title?.toString(),kind:o?.kind,okButtonLabel:o?.okLabel?.toString(),cancelButtonLabel:o?.cancelLabel?.toString()})},t.message=async function(t,o){const i="string"==typeof o?{title:o}:o;return n("plugin:dialog|message",{message:t.toString(),title:i?.title?.toString(),kind:i?.kind,okButtonLabel:i?.okLabel?.toString(),buttons:e(i?.buttons)})},t.open=async function(t={}){return"object"==typeof t&&Object.freeze(t),await n("plugin:dialog|open",{options:t})},t.save=async function(t={}){return"object"==typeof t&&Object.freeze(t),await n("plugin:dialog|save",{options:t})},t}({});Object.defineProperty(window.__TAURI__,"dialog",{value:__TAURI_PLUGIN_DIALOG__})} if("__TAURI__"in window){var __TAURI_PLUGIN_DIALOG__=function(t){"use strict";async function n(t,n={},e){return window.__TAURI_INTERNALS__.invoke(t,n,e)}return"function"==typeof SuppressedError&&SuppressedError,t.ask=async function(t,e){const i="string"==typeof e?{title:e}:e;return await n("plugin:dialog|ask",{message:t.toString(),title:i?.title?.toString(),kind:i?.kind,yesButtonLabel:i?.okLabel?.toString(),noButtonLabel:i?.cancelLabel?.toString()})},t.confirm=async function(t,e){const i="string"==typeof e?{title:e}:e;return await n("plugin:dialog|confirm",{message:t.toString(),title:i?.title?.toString(),kind:i?.kind,okButtonLabel:i?.okLabel?.toString(),cancelButtonLabel:i?.cancelLabel?.toString()})},t.message=async function(t,e){const i="string"==typeof e?{title:e}:e;await n("plugin:dialog|message",{message:t.toString(),title:i?.title?.toString(),kind:i?.kind,okButtonLabel:i?.okLabel?.toString()})},t.open=async function(t={}){return"object"==typeof t&&Object.freeze(t),await n("plugin:dialog|open",{options:t})},t.save=async function(t={}){return"object"==typeof t&&Object.freeze(t),await n("plugin:dialog|save",{options:t})},t}({});Object.defineProperty(window.__TAURI__,"dialog",{value:__TAURI_PLUGIN_DIALOG__})}
+5 -175
View File
@@ -14,16 +14,6 @@ interface DialogFilter {
name: string name: string
/** /**
* Extensions to filter, without a `.` prefix. * Extensions to filter, without a `.` prefix.
*
* **Note:** Mobile platforms have different APIs for filtering that may not support extensions.
* iOS: Extensions are supported in the document picker, but not in the media picker.
* Android: Extensions are not supported.
*
* For these platforms, MIME types are the primary way to filter files, as opposed to extensions.
* This means the string values here labeled as `extensions` may also be a MIME type.
* This property name of `extensions` is being kept for backwards compatibility, but this may be revisited to
* specify the difference between extension or MIME type filtering.
*
* @example * @example
* ```typescript * ```typescript
* extensions: ['svg', 'png'] * extensions: ['svg', 'png']
@@ -40,14 +30,7 @@ interface DialogFilter {
interface OpenDialogOptions { interface OpenDialogOptions {
/** The title of the dialog window (desktop only). */ /** The title of the dialog window (desktop only). */
title?: string title?: string
/** /** The filters of the dialog. */
* The filters of the dialog.
* On mobile platforms, if either:
* A) the {@linkcode pickerMode} is set to `media`, `image`, or `video`
* -- or --
* B) the filters include **only** either image or video mime types, the media picker will be displayed.
* Otherwise, the document picker will be displayed.
*/
filters?: DialogFilter[] filters?: DialogFilter[]
/** /**
* Initial directory or file path. * Initial directory or file path.
@@ -69,13 +52,6 @@ interface OpenDialogOptions {
recursive?: boolean recursive?: boolean
/** Whether to allow creating directories in the dialog. Enabled by default. **macOS Only** */ /** Whether to allow creating directories in the dialog. Enabled by default. **macOS Only** */
canCreateDirectories?: boolean canCreateDirectories?: boolean
/**
* The preferred mode of the dialog.
* This is meant for mobile platforms (iOS and Android) which have distinct file and media pickers.
* If not provided, the dialog will automatically choose the best mode based on the MIME types or extensions of the {@linkcode filters}.
* On desktop, this option is ignored.
*/
pickerMode?: PickerMode
} }
/** /**
@@ -101,90 +77,6 @@ interface SaveDialogOptions {
canCreateDirectories?: boolean canCreateDirectories?: boolean
} }
/**
* The preferred mode of the dialog.
* This is meant for mobile platforms (iOS and Android) which have distinct file and media pickers.
* On desktop, this option is ignored.
* If not provided, the dialog will automatically choose the best mode based on the MIME types or extensions of the {@linkcode filters}.
*
* **Note:** This option is only supported on iOS 14 and above. This parameter is ignored on iOS 13 and below.
*/
export type PickerMode = 'document' | 'media' | 'image' | 'video'
/**
* Default buttons for a message dialog.
*
* @since 2.4.0
*/
export type MessageDialogDefaultButtons =
| 'Ok'
| 'OkCancel'
| 'YesNo'
| 'YesNoCancel'
/** All possible button keys. */
type ButtonKey = 'ok' | 'cancel' | 'yes' | 'no'
/** Ban everything except a set of keys. */
type BanExcept<Allowed extends ButtonKey> = Partial<
Record<Exclude<ButtonKey, Allowed>, never>
>
/**
* The Yes, No and Cancel buttons of a message dialog.
*
* @since 2.4.0
*/
export type MessageDialogButtonsYesNoCancel = {
/** The Yes button. */
yes: string
/** The No button. */
no: string
/** The Cancel button. */
cancel: string
} & BanExcept<'yes' | 'no' | 'cancel'>
/**
* The Ok and Cancel buttons of a message dialog.
*
* @since 2.4.0
*/
export type MessageDialogButtonsOkCancel = {
/** The Ok button. */
ok: string
/** The Cancel button. */
cancel: string
} & BanExcept<'ok' | 'cancel'>
/**
* The Ok button of a message dialog.
*
* @since 2.4.0
*/
export type MessageDialogButtonsOk = {
/** The Ok button. */
ok: string
} & BanExcept<'ok'>
/**
* Custom buttons for a message dialog.
*
* @since 2.4.0
*/
export type MessageDialogCustomButtons =
| MessageDialogButtonsYesNoCancel
| MessageDialogButtonsOkCancel
| MessageDialogButtonsOk
/**
* The buttons of a message dialog.
*
* @since 2.4.0
*/
export type MessageDialogButtons =
| MessageDialogDefaultButtons
| MessageDialogCustomButtons
/** /**
* @since 2.0.0 * @since 2.0.0
*/ */
@@ -193,58 +85,8 @@ interface MessageDialogOptions {
title?: string title?: string
/** The kind of the dialog. Defaults to `info`. */ /** The kind of the dialog. Defaults to `info`. */
kind?: 'info' | 'warning' | 'error' kind?: 'info' | 'warning' | 'error'
/** /** The label of the confirm button. */
* The label of the Ok button.
*
* @deprecated Use {@linkcode MessageDialogOptions.buttons} instead.
*/
okLabel?: string okLabel?: string
/**
* The buttons of the dialog.
*
* @example
*
* ```ts
* // Use system default buttons texts
* await message('Hello World!', { buttons: 'Ok' })
* await message('Hello World!', { buttons: 'OkCancel' })
*
* // Or with custom button texts
* await message('Hello World!', { buttons: { ok: 'Yes!' } })
* await message('Take on the task?', {
* buttons: { ok: 'Accept', cancel: 'Cancel' }
* })
* await message('Show the file content?', {
* buttons: { yes: 'Show content', no: 'Show in folder', cancel: 'Cancel' }
* })
* ```
*
* @since 2.4.0
*/
buttons?: MessageDialogButtons
}
/**
* Internal function to convert the buttons to the Rust type.
*/
function buttonsToRust(buttons: MessageDialogButtons | undefined) {
if (buttons === undefined) {
return undefined
}
if (typeof buttons === 'string') {
return buttons
} else if ('ok' in buttons && 'cancel' in buttons) {
return { OkCancelCustom: [buttons.ok, buttons.cancel] }
} else if ('yes' in buttons && 'no' in buttons && 'cancel' in buttons) {
return {
YesNoCancelCustom: [buttons.yes, buttons.no, buttons.cancel]
}
} else if ('ok' in buttons) {
return { OkCustom: buttons.ok }
}
return undefined
} }
interface ConfirmDialogOptions { interface ConfirmDialogOptions {
@@ -360,16 +202,6 @@ async function save(options: SaveDialogOptions = {}): Promise<string | null> {
return await invoke('plugin:dialog|save', { options }) return await invoke('plugin:dialog|save', { options })
} }
/**
* The result of a message dialog.
*
* The result is a string if the dialog has custom buttons,
* otherwise it is one of the default buttons.
*
* @since 2.4.0
*/
export type MessageDialogResult = 'Yes' | 'No' | 'Ok' | 'Cancel' | (string & {})
/** /**
* Shows a message dialog with an `Ok` button. * Shows a message dialog with an `Ok` button.
* @example * @example
@@ -390,15 +222,13 @@ export type MessageDialogResult = 'Yes' | 'No' | 'Ok' | 'Cancel' | (string & {})
async function message( async function message(
message: string, message: string,
options?: string | MessageDialogOptions options?: string | MessageDialogOptions
): Promise<MessageDialogResult> { ): Promise<void> {
const opts = typeof options === 'string' ? { title: options } : options const opts = typeof options === 'string' ? { title: options } : options
await invoke('plugin:dialog|message', {
return invoke<MessageDialogResult>('plugin:dialog|message', {
message: message.toString(), message: message.toString(),
title: opts?.title?.toString(), title: opts?.title?.toString(),
kind: opts?.kind, kind: opts?.kind,
okButtonLabel: opts?.okLabel?.toString(), okButtonLabel: opts?.okLabel?.toString()
buttons: buttonsToRust(opts?.buttons)
}) })
} }

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