Compare commits

..
Author SHA1 Message Date
renovate[bot]andGitHub f89438e2d6 chore(deps): update dependency typescript to v7 2026-07-11 17:55:17 +00:00
144 changed files with 1417 additions and 1998 deletions
-10
View File
@@ -1,17 +1,7 @@
[advisories]
ignore = [
# rsa Marvin Attack
"RUSTSEC-2023-0071",
# time crate can't be updated in the repo because of MSRV, users are unaffected
"RUSTSEC-2026-0009",
# libflate crates can't be updated in the repo because of MSRV, users are unaffected
"RUSTSEC-2026-0105",
# quick-xml, need an update in plist, can't be updated in the repo because of MSRV, users are unaffected
# Also needs on update in wayland-scanner > arboard > tauri-plugin-clipboard-manager
"RUSTSEC-2026-0194",
# quick-xml, need an update in plist, can't be updated in the repo because of MSRV, users are unaffected
# Also needs on update in wayland-scanner > arboard > tauri-plugin-clipboard-manager
"RUSTSEC-2026-0195",
# quinn-proto, can't be updated in the repo because of MSRV, users are unaffected
"RUSTSEC-2026-0185",
]
-6
View File
@@ -1,6 +0,0 @@
---
"deep-link": patch
"deep-link-js": patch
---
adds proper Platform-specific sections to the docs for `register`, `unregister`, `isRegistered`, and `onOpenUrl`
-6
View File
@@ -1,6 +0,0 @@
---
"dialog": patch
"dialog-js": patch
---
Fix Android save dialog MIME type when a single MIME type is provided.
-30
View File
@@ -1,30 +0,0 @@
---
"dialog": patch
"dialog-js": patch
"fs": patch
"fs-js": patch
"geolocation": patch
"geolocation-js": patch
"haptics": patch
"haptics-js": patch
"http": patch
"http-js": patch
"log": patch
"log-js": patch
"persisted-scope": patch
"positioner": patch
"positioner-js": patch
"single-instance": patch
"sql": patch
"sql-js": patch
"stronghold": patch
"stronghold-js": patch
"updater": patch
"updater-js": patch
"upload": patch
"upload-js": patch
"websocket": patch
"websocket-js": patch
---
Documented Cargo feature flags in each plugin's crate-level documentation.
@@ -0,0 +1,4 @@
---
"single-instance": patch
---
Fix blocked thread on the single-instance plugin for MacOS: replace standard `UnixListener` with `tokio::net::UnixListener`, so the task can yield.
-6
View File
@@ -1,6 +0,0 @@
---
"fs": patch
"fs-js": patch
---
Fixed `deny-webview-data` has no effect
-6
View File
@@ -1,6 +0,0 @@
---
"http": minor
"http-js": minor
---
Added `system-proxy` feature to replace the old `macos-system-configuration` feature flag to match the new reqwest API.
+6
View File
@@ -0,0 +1,6 @@
---
"log": minor:feat
"log-js": minor
---
Added the `FileOpenStrategy` for log rotation. It defaults to append into existing file if any (previous behaviour), and brings a new feature to create a new file per session: `FileOpenStrategy::Rotate`.
-6
View File
@@ -1,6 +0,0 @@
---
nfc: patch
nfc-js: patch
---
Expect a `NFCTag` as input and return a `ScanResponse` in the `scan` function.
-7
View File
@@ -1,7 +0,0 @@
---
notification: minor
notification-js: minor
---
- Add Rust builders for mobile notification action types.
- Fix Android action-group entries being stored under the action type ID instead of sequential indices, causing later actions to overwrite earlier ones.
@@ -0,0 +1,6 @@
---
positioner: patch
positioner-js: patch
---
Replaced a panic in `calculate_position` with an error return when the window has no associated monitor (e.g. during display sleep or monitor reconfiguration).
+6
View File
@@ -0,0 +1,6 @@
---
"log": patch
"log-js": patch
---
Removed an unused dependency `byte-unit`.
@@ -1,6 +0,0 @@
---
"updater": patch
"updater-js": patch
---
On Windows, returns an error if failed to spawn the installer in `install` through `ShellExecuteW`
-6
View File
@@ -1,6 +0,0 @@
---
"updater": minor
"updater-js": minor
---
On Windows, add a new option `restartAfterInstall`/`restart_after_install` to install an update without the installer re-launching the app
-6
View File
@@ -1,6 +0,0 @@
---
"updater": minor
"updater-js": minor
---
Added `system-proxy` (enabled by default) feature flag to control `reqwest/system-proxy` feature (Use Windows and macOS system proxy settings automatically)
+5 -4
View File
@@ -33,19 +33,20 @@ jobs:
audit-js:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v4
- name: Cache pnpm modules
uses: actions/cache@v6
uses: actions/cache@v4
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-
- uses: actions/setup-node@v7
- uses: actions/setup-node@v4
with:
node-version: 'lts/*'
- uses: pnpm/action-setup@v6
- uses: pnpm/action-setup@v4
with:
version: 10.x.x
run_install: true
- name: audit
run: pnpm audit
+1 -1
View File
@@ -33,7 +33,7 @@ jobs:
audit-rust:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v4
- uses: rustsec/audit-check@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v4
- name: check change files end with .md
run: |
+6 -5
View File
@@ -21,7 +21,7 @@ jobs:
outputs:
packages: ${{ steps.filter.outputs.changes }}
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v2
id: filter
with:
@@ -153,20 +153,21 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v4
- name: Cache pnpm modules
uses: actions/cache@v6
uses: actions/cache@v4
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-
- uses: actions/setup-node@v7
- uses: actions/setup-node@v4
with:
node-version: 'lts/*'
- uses: pnpm/action-setup@v6
- uses: pnpm/action-setup@v4
with:
version: 10.x.x
run_install: true
- name: build api
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v2
id: filter
with:
+1 -1
View File
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v4
with:
fetch-depth: 0 # required for use of git history
- name: covector status
@@ -28,17 +28,18 @@ jobs:
successfulPublish: ${{ steps.covector.outputs.successfulPublish }}
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v4
with:
fetch-depth: 0 # required for use of git history
- uses: actions/setup-node@v7
- uses: actions/setup-node@v4
with:
node-version: 'lts/*'
registry-url: 'https://registry.npmjs.org'
- uses: pnpm/action-setup@v6
- uses: pnpm/action-setup@v4
with:
version: 10.x.x
run_install: true
- name: cargo login
@@ -73,7 +74,7 @@ jobs:
- name: Create Pull Request With Versions Bumped
id: cpr
uses: peter-evans/create-pull-request@v8.1.1
uses: peter-evans/create-pull-request@dd2324fc52d5d43c699a5636bcf19fceaa70c284 # 7.0.7
if: steps.covector.outputs.commandRan == 'version'
with:
title: 'Publish New Versions (${{ github.ref_name }})'
+7 -6
View File
@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v4
- name: install Rust stable and rustfmt
uses: dtolnay/rust-toolchain@stable
@@ -25,19 +25,20 @@ jobs:
prettier:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v4
- name: Cache pnpm modules
uses: actions/cache@v6
uses: actions/cache@v4
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-
- uses: actions/setup-node@v7
- uses: actions/setup-node@v4
with:
node-version: 'lts/*'
- uses: pnpm/action-setup@v6
- uses: pnpm/action-setup@v4
with:
version: 10.x.x
run_install: true
- run: pnpm format:check
@@ -45,7 +46,7 @@ jobs:
name: taplo (.toml files)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v4
- name: install Rust stable
uses: dtolnay/rust-toolchain@stable
+1 -1
View File
@@ -31,7 +31,7 @@ jobs:
platform: [ubuntu-22.04, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v4
with:
fetch-depth: 0
+5 -4
View File
@@ -36,19 +36,20 @@ jobs:
eslint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v4
- name: Cache pnpm modules
uses: actions/cache@v6
uses: actions/cache@v4
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-
- uses: actions/setup-node@v7
- uses: actions/setup-node@v4
with:
node-version: 'lts/*'
- uses: pnpm/action-setup@v6
- uses: pnpm/action-setup@v4
with:
version: 10.x.x
run_install: true
- name: eslint
run: pnpm lint
+2 -2
View File
@@ -36,7 +36,7 @@ jobs:
outputs:
packages: ${{ steps.filter.outputs.changes }}
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v2
id: filter
with:
@@ -136,7 +136,7 @@ jobs:
package: ${{ fromJSON(needs.changes.outputs.packages) }}
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v4
- name: install webkit2gtk
run: |
+5 -4
View File
@@ -19,25 +19,26 @@ jobs:
sync-to-mirrors:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v4
- name: Fetch git tags
run: git fetch origin 'refs/tags/*:refs/tags/*'
- name: Cache pnpm modules
uses: actions/cache@v6
uses: actions/cache@v4
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-
- uses: actions/setup-node@v7
- uses: actions/setup-node@v4
with:
node-version: 'lts/*'
- uses: pnpm/action-setup@v6
- uses: pnpm/action-setup@v4
with:
version: 10.x.x
run_install: true
- name: Build packages
+2 -2
View File
@@ -38,7 +38,7 @@ jobs:
outputs:
packages: ${{ steps.filter.outputs.changes }}
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v2
id: filter
with:
@@ -225,7 +225,7 @@ jobs:
runs-on: ${{ matrix.platform.os }}
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v4
- name: install webkit2gtk
if: contains(matrix.platform.target, 'unknown-linux')
Generated
+45 -35
View File
@@ -201,13 +201,13 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.103"
version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3"
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
[[package]]
name = "api"
version = "2.0.46"
version = "2.0.44"
dependencies = [
"log",
"serde",
@@ -300,7 +300,7 @@ dependencies = [
"objc2-foundation 0.3.0",
"parking_lot",
"percent-encoding",
"windows-sys 0.59.0",
"windows-sys 0.52.0",
"wl-clipboard-rs",
"x11rb",
]
@@ -1041,7 +1041,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c"
dependencies = [
"lazy_static",
"windows-sys 0.59.0",
"windows-sys 0.48.0",
]
[[package]]
@@ -1862,7 +1862,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e"
dependencies = [
"libc",
"windows-sys 0.59.0",
"windows-sys 0.52.0",
]
[[package]]
@@ -3463,6 +3463,9 @@ name = "log"
version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
dependencies = [
"value-bag",
]
[[package]]
name = "lru-slab"
@@ -4717,7 +4720,7 @@ dependencies = [
"once_cell",
"socket2",
"tracing",
"windows-sys 0.59.0",
"windows-sys 0.52.0",
]
[[package]]
@@ -5167,7 +5170,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys 0.4.15",
"windows-sys 0.59.0",
"windows-sys 0.52.0",
]
[[package]]
@@ -5180,7 +5183,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys 0.11.0",
"windows-sys 0.60.2",
"windows-sys 0.52.0",
]
[[package]]
@@ -5237,7 +5240,7 @@ dependencies = [
"security-framework 3.5.1",
"security-framework-sys",
"webpki-root-certs",
"windows-sys 0.60.2",
"windows-sys 0.52.0",
]
[[package]]
@@ -6309,9 +6312,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
[[package]]
name = "tauri"
version = "2.11.5"
version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "667b20e2726d572dea2de7370da16e188eb06008faf9a92fab7cdc46791190b5"
checksum = "b93bd86d231f0a8138f11a02a584769fe4b703dc36ae133d783228dbc4801405"
dependencies = [
"anyhow",
"bytes",
@@ -6364,9 +6367,9 @@ dependencies = [
[[package]]
name = "tauri-build"
version = "2.6.3"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc9ce40b16101cb6ea63d3e221567affd1c3a9205f95d7bc574941a10636b632"
checksum = "3a318b234cc2dea65f575467bafcfb76286bce228ebc3778e337d61d03213007"
dependencies = [
"anyhow",
"cargo_toml",
@@ -6387,9 +6390,9 @@ dependencies = [
[[package]]
name = "tauri-codegen"
version = "2.6.3"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08279169ff42f8fc45a1dbc9dcae888893ba95288142e5880c59b93a26d2cfc5"
checksum = "6bd11644962add2549a60b7e7c6800f17d7020156e02f516021d8103e80cc528"
dependencies = [
"base64 0.22.1",
"ico",
@@ -6413,9 +6416,9 @@ dependencies = [
[[package]]
name = "tauri-macros"
version = "2.6.3"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8b394794f399a421811d06966343e7933fcae92d59f5180b9388d1174497a45"
checksum = "fed9d3742a37a355d2e47c9af924e9fbc112abb76f9835d35d4780e318419502"
dependencies = [
"heck 0.5.0",
"proc-macro2",
@@ -6525,7 +6528,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-dialog"
version = "2.7.2"
version = "2.7.1"
dependencies = [
"log",
"raw-window-handle",
@@ -6640,7 +6643,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-log"
version = "2.9.0"
version = "2.8.0"
dependencies = [
"android_logger",
"fern",
@@ -6742,7 +6745,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-positioner"
version = "2.3.3"
version = "2.3.2"
dependencies = [
"log",
"serde",
@@ -6782,7 +6785,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-single-instance"
version = "2.4.3"
version = "2.4.2"
dependencies = [
"semver",
"serde",
@@ -6817,7 +6820,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-store"
version = "2.4.4"
version = "2.4.3"
dependencies = [
"dunce",
"serde",
@@ -6932,9 +6935,9 @@ dependencies = [
[[package]]
name = "tauri-runtime"
version = "2.11.3"
version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0b4bc95aed361b0019067d189a1174a603d460d0f6c72606512d59fc9c12ec8"
checksum = "8fef478ba1d2ac21c2d528740b24d0cb315e1e8b1111aae53fafac34804371fc"
dependencies = [
"cookie",
"dpi",
@@ -6957,9 +6960,9 @@ dependencies = [
[[package]]
name = "tauri-runtime-wry"
version = "2.11.4"
version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e6fac707727b7a2f48e4ded90976324267371073edbb415ffb73bb0458d203f"
checksum = "a3989df2ae1c476404fe0a2e8ffc4cfbde97e51efd613c2bb5355fbc9ab52cf0"
dependencies = [
"gtk",
"http",
@@ -6983,9 +6986,9 @@ dependencies = [
[[package]]
name = "tauri-utils"
version = "2.9.3"
version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e176a18e67764923c4f1ce66f25ae4abe5f688384d5eb1a0fa6c77f3d90f887"
checksum = "d57200389a2f82b4b0a40ae29ca19b6978116e8f4d4e974c3234ce40c0ffbdec"
dependencies = [
"aes-gcm",
"anyhow",
@@ -7033,10 +7036,11 @@ dependencies = [
[[package]]
name = "tauri-winrt-notification"
version = "0.7.3"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed071c670382e85fc2f48ae706492d8c338f4f89bf72520d32f8abfe880aade"
checksum = "0b1e66e07de489fe43a46678dd0b8df65e0c973909df1b60ba33874e297ba9b9"
dependencies = [
"quick-xml 0.37.4",
"thiserror 2.0.12",
"windows 0.61.1",
"windows-version",
@@ -7052,7 +7056,7 @@ dependencies = [
"getrandom 0.3.2",
"once_cell",
"rustix 1.1.3",
"windows-sys 0.60.2",
"windows-sys 0.52.0",
]
[[package]]
@@ -7467,9 +7471,9 @@ dependencies = [
[[package]]
name = "tray-icon"
version = "0.24.1"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65ba1e5f6b9ef9fd87e21b9c6f351554dbd717960089168fcfdef854686961dc"
checksum = "15edbb0d80583e85ee8df283410038e17314df5cba30da2087a54a85216c0773"
dependencies = [
"crossbeam-channel",
"dirs 6.0.0",
@@ -7741,6 +7745,12 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "value-bag"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5"
[[package]]
name = "vcpkg"
version = "0.2.15"
@@ -8186,7 +8196,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
"windows-sys 0.59.0",
"windows-sys 0.48.0",
]
[[package]]
+1 -1
View File
@@ -11,7 +11,7 @@ resolver = "2"
[workspace.dependencies]
serde = { version = "1", features = ["derive"] }
tracing = "0.1"
log = "0.4.21"
log = "0.4"
tauri = { version = "2.10", default-features = false }
tauri-build = "2.5"
tauri-plugin = "2.5"
-13
View File
@@ -1,18 +1,5 @@
# Changelog
## \[2.0.42]
### Dependencies
- Upgraded to `dialog-js@2.7.2`
- Upgraded to `store-js@2.4.4`
## \[2.0.41]
### Dependencies
- Upgraded to `log-js@2.9.0`
## \[2.0.40]
### Dependencies
+2 -3
View File
@@ -1,13 +1,12 @@
<!doctype html>
<html lang="en">
<html lang="en" theme="dark">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, viewport-fit=cover, user-scalable=0"
/>
<meta name="color-scheme" content="dark light" />
<title>API Example App</title>
<title>Svelte + Vite App</title>
</head>
<body>
+24 -24
View File
@@ -1,7 +1,7 @@
{
"name": "api",
"private": true,
"version": "2.0.42",
"version": "2.0.40",
"type": "module",
"scripts": {
"dev": "vite --clearScreen false",
@@ -11,35 +11,35 @@
},
"dependencies": {
"@tauri-apps/api": "^2.11.0",
"@tauri-apps/plugin-barcode-scanner": "workspace:*",
"@tauri-apps/plugin-biometric": "workspace:*",
"@tauri-apps/plugin-cli": "workspace:*",
"@tauri-apps/plugin-clipboard-manager": "workspace:*",
"@tauri-apps/plugin-dialog": "workspace:*",
"@tauri-apps/plugin-fs": "workspace:*",
"@tauri-apps/plugin-geolocation": "workspace:*",
"@tauri-apps/plugin-global-shortcut": "workspace:*",
"@tauri-apps/plugin-haptics": "workspace:*",
"@tauri-apps/plugin-http": "workspace:*",
"@tauri-apps/plugin-nfc": "workspace:*",
"@tauri-apps/plugin-notification": "workspace:*",
"@tauri-apps/plugin-opener": "workspace:*",
"@tauri-apps/plugin-os": "workspace:*",
"@tauri-apps/plugin-process": "workspace:*",
"@tauri-apps/plugin-shell": "workspace:*",
"@tauri-apps/plugin-store": "workspace:*",
"@tauri-apps/plugin-updater": "workspace:*",
"@tauri-apps/plugin-upload": "workspace:*",
"@zerodevx/svelte-json-view": "2.0.0"
"@tauri-apps/plugin-barcode-scanner": "^2.4.5",
"@tauri-apps/plugin-biometric": "^2.3.2",
"@tauri-apps/plugin-cli": "^2.4.1",
"@tauri-apps/plugin-clipboard-manager": "^2.3.2",
"@tauri-apps/plugin-dialog": "^2.7.1",
"@tauri-apps/plugin-fs": "^2.5.1",
"@tauri-apps/plugin-geolocation": "^2.3.2",
"@tauri-apps/plugin-global-shortcut": "^2.3.2",
"@tauri-apps/plugin-haptics": "^2.3.2",
"@tauri-apps/plugin-http": "^2.5.9",
"@tauri-apps/plugin-nfc": "^2.3.5",
"@tauri-apps/plugin-notification": "^2.3.3",
"@tauri-apps/plugin-opener": "^2.5.4",
"@tauri-apps/plugin-os": "^2.3.2",
"@tauri-apps/plugin-process": "^2.3.1",
"@tauri-apps/plugin-shell": "^2.3.5",
"@tauri-apps/plugin-store": "^2.4.3",
"@tauri-apps/plugin-updater": "^2.10.1",
"@tauri-apps/plugin-upload": "^2.4.0",
"@zerodevx/svelte-json-view": "1.0.11"
},
"devDependencies": {
"@iconify-json/codicon": "^1.2.49",
"@iconify-json/ph": "^1.2.2",
"@sveltejs/vite-plugin-svelte": "^7.0.0",
"@tauri-apps/cli": "2.11.4",
"@tauri-apps/cli": "2.11.2",
"@unocss/extractor-svelte": "^66.6.7",
"svelte": "^5.55.7",
"svelte": "^5.54.0",
"unocss": "^66.6.7",
"vite": "^8.0.16"
"vite": "^8.0.1"
}
}
-13
View File
@@ -1,18 +1,5 @@
# Changelog
## \[2.0.46]
### Dependencies
- Upgraded to `dialog@2.7.2`
- Upgraded to `store@2.4.4`
## \[2.0.45]
### Dependencies
- Upgraded to `log@2.9.0`
## \[2.0.44]
### Dependencies
+7 -4
View File
@@ -1,7 +1,7 @@
[package]
name = "api"
publish = false
version = "2.0.46"
version = "2.0.44"
description = "An example Tauri Application showcasing the api"
edition = "2021"
rust-version = { workspace = true }
@@ -20,12 +20,12 @@ serde = { workspace = true }
tiny_http = "0.12"
time = "0.3"
log = { workspace = true }
tauri-plugin-log = { path = "../../../plugins/log", version = "2.9.0" }
tauri-plugin-log = { path = "../../../plugins/log", version = "2.8.0" }
tauri-plugin-fs = { path = "../../../plugins/fs", version = "2.5.1", features = [
"watch",
] }
tauri-plugin-clipboard-manager = { path = "../../../plugins/clipboard-manager", version = "2.3.2" }
tauri-plugin-dialog = { path = "../../../plugins/dialog", version = "2.7.2" }
tauri-plugin-dialog = { path = "../../../plugins/dialog", version = "2.7.1" }
tauri-plugin-http = { path = "../../../plugins/http", features = [
"multipart",
"cookies",
@@ -37,7 +37,7 @@ tauri-plugin-os = { path = "../../../plugins/os", version = "2.3.2" }
tauri-plugin-process = { path = "../../../plugins/process", version = "2.3.1" }
tauri-plugin-opener = { path = "../../../plugins/opener", version = "2.5.4" }
tauri-plugin-shell = { path = "../../../plugins/shell", version = "2.3.5" }
tauri-plugin-store = { path = "../../../plugins/store", version = "2.4.4" }
tauri-plugin-store = { path = "../../../plugins/store", version = "2.4.3" }
tauri-plugin-upload = { path = "../../../plugins/upload", version = "2.3.0" }
[dependencies.tauri]
@@ -66,3 +66,6 @@ tauri-plugin-nfc = { path = "../../../plugins/nfc", version = "2.3.5" }
tauri-plugin-biometric = { path = "../../../plugins/biometric/", version = "2.3.2" }
tauri-plugin-geolocation = { path = "../../../plugins/geolocation/", version = "2.3.2" }
tauri-plugin-haptics = { path = "../../../plugins/haptics/", version = "2.3.2" }
[features]
prod = ["tauri/custom-protocol"]
@@ -15,10 +15,10 @@
]
},
"core:default",
"core:app:allow-set-app-theme",
"fs:default",
"core:window:allow-minimize",
"core:window:allow-toggle-maximize",
"core:window:allow-maximize",
"core:window:allow-unmaximize",
"core:window:allow-close",
"core:window:allow-start-dragging",
"notification:default",
@@ -1,11 +1,3 @@
package com.tauri.api
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
class MainActivity : TauriActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge()
super.onCreate(savedInstanceState)
}
}
class MainActivity : TauriActivity()
@@ -1,6 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.api" parent="Theme.Material3.DayNight.NoActionBar">
<style name="Theme.api" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Customize your theme here. -->
</style>
</resources>
@@ -1,6 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.api" parent="Theme.Material3.DayNight.NoActionBar">
<style name="Theme.api" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Customize your theme here. -->
</style>
</resources>
@@ -21,23 +21,7 @@ open class BuildTask : DefaultTask() {
runTauriCli(executable)
} catch (e: Exception) {
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
// Try different Windows-specific extensions
val fallbacks = listOf(
"$executable.exe",
"$executable.cmd",
"$executable.bat",
)
var lastException: Exception = e
for (fallback in fallbacks) {
try {
runTauriCli(fallback)
return
} catch (fallbackException: Exception) {
lastException = fallbackException
}
}
throw lastException
runTauriCli("$executable.cmd")
} else {
throw e;
}
@@ -1,6 +1,6 @@
#Tue May 10 19:22:52 CST 2022
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
-5
View File
@@ -77,9 +77,7 @@
},
"updater": {
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDE5QzMxNjYwNTM5OEUwNTgKUldSWTRKaFRZQmJER1h4d1ZMYVA3dnluSjdpN2RmMldJR09hUFFlZDY0SlFqckkvRUJhZDJVZXAK",
"dangerousInsecureTransportProtocol": true,
"endpoints": [
"http://localhost:5173/updater-test/updater.json",
"https://tauri-update-server.vercel.app/update/{{target}}/{{current_version}}"
]
}
@@ -101,9 +99,6 @@
"localePath": "locales/pt-BR.wxl"
}
}
},
"nsis": {
"compression": "none"
}
},
"iOS": {
+202 -135
View File
@@ -1,16 +1,7 @@
<script module lang="ts">
export type ViewProps = {
onMessage: (value: unknown) => void
}
</script>
<script lang="ts">
import { onMount, tick } from 'svelte'
<script>
import { writable } from 'svelte/store'
import { MediaQuery } from 'svelte/reactivity'
import { getCurrentWindow, type Theme } from '@tauri-apps/api/window'
import { getCurrentWindow } from '@tauri-apps/api/window'
import { getCurrentWebview } from '@tauri-apps/api/webview'
import { setTheme } from '@tauri-apps/api/app'
import * as os from '@tauri-apps/plugin-os'
import Welcome from './views/Welcome.svelte'
@@ -32,9 +23,10 @@
import Biometric from './views/Biometric.svelte'
import Geolocation from './views/Geolocation.svelte'
import Haptics from './views/Haptics.svelte'
import Nfc from './views/Nfc.svelte'
import TitleBar from './lib/TitleBar.svelte'
import { onMount, tick } from 'svelte'
import { ask } from '@tauri-apps/plugin-dialog'
import Nfc from './views/Nfc.svelte'
const appWindow = getCurrentWindow()
@@ -156,98 +148,114 @@
component: Haptics,
icon: 'i-ph-vibrate'
}
].filter(Boolean) as {
label: string
component: typeof Haptics
icon: string
}[]
let selected = $state.raw(views[0])
]
// dark/light themes
const preferDark = new MediaQuery('prefers-color-scheme: dark')
let theme = $state<Theme | 'auto'>(
(localStorage.getItem('theme') as Theme | null) || 'auto'
)
async function switchTheme() {
switch (theme) {
case 'dark':
theme = 'light'
break
case 'light':
theme = 'auto'
break
case 'auto':
theme = 'dark'
break
}
applyTheme()
let selected = views[0]
function select(view) {
selected = view
}
function applyTheme() {
const isDark = theme === 'auto' ? preferDark.current : theme === 'dark'
if (isDark) {
document.documentElement.classList.add('dark')
document.documentElement.classList.remove('light')
} else {
document.documentElement.classList.remove('dark')
document.documentElement.classList.add('light')
}
setTheme(theme === 'auto' ? null : theme)
localStorage.setItem('theme', theme)
}
$effect(() => {
applyTheme()
// Window controls
let isWindowMaximized
onMount(async () => {
isWindowMaximized = await appWindow.isMaximized()
appWindow.onResized(async () => {
isWindowMaximized = await appWindow.isMaximized()
})
})
// Console
const messages = writable<string[]>([])
let consoleTextEl: HTMLDivElement
// this function is renders HTML without sanitizing it so it's insecure
// we only use it with our own input data
async function insecureRenderHtml(html: string) {
messages.update((r) => [
...r,
`<pre><strong class="text-accent dark:text-darkAccent">[${new Date().toLocaleTimeString()}]:</strong> ${html}</pre>`
])
await tick()
consoleTextEl.scrollTop = consoleTextEl.scrollHeight
function minimize() {
appWindow.minimize()
}
async function onMessage(value: unknown) {
const valueStr =
typeof value === 'string'
? value
: JSON.stringify(
value instanceof ArrayBuffer
? Array.from(new Uint8Array(value))
: value,
null,
1
)
insecureRenderHtml(valueStr)
async function toggleMaximize() {
;(await appWindow.isMaximized())
? appWindow.unmaximize()
: appWindow.maximize()
}
let confirmed_close = false
async function close() {
if (!confirmed_close) {
confirmed_close = await ask(
'Are you sure that you want to close this window?',
{
title: 'Tauri API'
}
)
if (confirmed_close) {
appWindow.close()
}
}
}
// dark/light
let isDark
onMount(() => {
isDark = localStorage && localStorage.getItem('theme') == 'dark'
applyTheme(isDark)
})
function applyTheme(isDark) {
const html = document.querySelector('html')
isDark ? html.classList.add('dark') : html.classList.remove('dark')
localStorage && localStorage.setItem('theme', isDark ? 'dark' : '')
}
function toggleDark() {
isDark = !isDark
applyTheme(isDark)
}
// Console
let messages = writable([])
let consoleTextEl
async function onMessage(value) {
messages.update((r) => [
...r,
{
html:
`<pre><strong class="text-accent dark:text-darkAccent">[${new Date().toLocaleTimeString()}]:</strong> ` +
(typeof value === 'string' ? value : JSON.stringify(value, null, 1)) +
'</pre>'
}
])
await tick()
if (consoleTextEl) consoleTextEl.scrollTop = consoleTextEl.scrollHeight
}
// this function renders HTML without sanitizing it so it's insecure
// we only use it with our own input data
async function insecureRenderHtml(html) {
messages.update((r) => [
...r,
{
html:
`<pre><strong class="text-accent dark:text-darkAccent">[${new Date().toLocaleTimeString()}]:</strong> ` +
html +
'</pre>'
}
])
await tick()
if (consoleTextEl) consoleTextEl.scrollTop = consoleTextEl.scrollHeight
}
function clear() {
messages.update(() => [])
}
let consoleEl: HTMLDivElement
let consoleH = 0
let cStartY = 0
const minConsoleHeight = 50
function startResizingConsole(e: MouseEvent) {
let consoleEl, consoleH, cStartY
let minConsoleHeight = 50
function startResizingConsole(e) {
cStartY = e.clientY
const styles = window.getComputedStyle(consoleEl)
consoleH = parseInt(styles.height, 10)
const moveHandler = (e: MouseEvent) => {
const moveHandler = (e) => {
const dy = e.clientY - cStartY
const newH = consoleH - dy
consoleEl.style.height = `${newH < minConsoleHeight ? minConsoleHeight : newH}px`
consoleEl.style.height = `${
newH < minConsoleHeight ? minConsoleHeight : newH
}px`
}
const upHandler = () => {
document.removeEventListener('mouseup', upHandler)
@@ -257,19 +265,21 @@
document.addEventListener('mousemove', moveHandler)
}
let isWindows = os.platform() === 'windows'
let isWindows
onMount(async () => {
isWindows = (await os.platform()) === 'windows'
})
// mobile
let isSideBarOpen = $state(false)
let sidebar: HTMLElement
let sidebarToggle: HTMLElement
let isSideBarOpen = false
let sidebar
let sidebarToggle
let isDraggingSideBar = false
let draggingStartPosX = 0
let draggingEndPosX = 0
const clamp = (min: number, num: number, max: number) =>
Math.min(Math.max(num, min), max)
const clamp = (min, num, max) => Math.min(Math.max(num, min), max)
function toggleSidebar() {
function toggleSidebar(sidebar, isSideBarOpen) {
sidebar.style.setProperty(
'--translate-x',
`${isSideBarOpen ? '0' : '-18.75'}rem`
@@ -277,9 +287,10 @@
}
onMount(() => {
document.addEventListener('click', (e) => {
if (!(e.target instanceof Node)) return
sidebar = document.querySelector('#sidebar')
sidebarToggle = document.querySelector('#sidebarToggle')
document.addEventListener('click', (e) => {
if (sidebarToggle.contains(e.target)) {
isSideBarOpen = !isSideBarOpen
} else if (isSideBarOpen && !sidebar.contains(e.target)) {
@@ -288,7 +299,6 @@
})
document.addEventListener('touchstart', (e) => {
if (!(e.target instanceof Node)) return
if (sidebarToggle.contains(e.target)) return
const x = e.touches[0].clientX
@@ -320,22 +330,76 @@
})
})
$effect(() => {
toggleSidebar()
})
$: {
const sidebar = document.querySelector('#sidebar')
if (sidebar) {
toggleSidebar(sidebar, isSideBarOpen)
}
}
</script>
<!-- custom titlebar for Windows -->
{#if isWindows}
<TitleBar {appWindow} {theme} {switchTheme} />
<div
class="w-screen select-none h-8 pl-2 flex justify-between items-center absolute text-primaryText dark:text-darkPrimaryText"
data-tauri-drag-region
>
<span class="lt-sm:pl-10 text-darkPrimaryText">Tauri API Validation</span>
<span
class="
h-100%
children:h-100% children:w-12 children:inline-flex
children:items-center children:justify-center"
>
<button
aria-label="Toggle dark mode"
title={isDark ? 'Switch to Light mode' : 'Switch to Dark mode'}
class="bg-inherit border-none hover:bg-hoverOverlay active:bg-hoverOverlayDarker dark:hover:bg-darkHoverOverlay dark:active:bg-darkHoverOverlayDarker"
on:click={toggleDark}
>
{#if isDark}
<div class="i-ph-sun"></div>
{:else}
<div class="i-ph-moon"></div>
{/if}
</button>
<button
aria-label="Minimize window"
title="Minimize"
class="bg-inherit border-none hover:bg-hoverOverlay active:bg-hoverOverlayDarker dark:hover:bg-darkHoverOverlay dark:active:bg-darkHoverOverlayDarker"
on:click={minimize}
>
<div class="i-codicon-chrome-minimize"></div>
</button>
<button
aria-label="Maximize window"
title={isWindowMaximized ? 'Restore' : 'Maximize'}
class="bg-inherit border-none hover:bg-hoverOverlay active:bg-hoverOverlayDarker dark:hover:bg-darkHoverOverlay dark:active:bg-darkHoverOverlayDarker"
on:click={toggleMaximize}
>
{#if isWindowMaximized}
<div class="i-codicon-chrome-restore"></div>
{:else}
<div class="i-codicon-chrome-maximize"></div>
{/if}
</button>
<button
aria-label="Close window"
title="Close"
class="bg-inherit border-none hover:bg-red-700 dark:hover:bg-red-700 hover:text-darkPrimaryText active:bg-red-700/90 dark:active:bg-red-700/90 active:text-darkPrimaryText"
on:click={close}
>
<div class="i-codicon-chrome-close"></div>
</button>
</span>
</div>
{/if}
<!-- Sidebar toggle, only visible on small screens -->
<div
id="sidebarToggle"
bind:this={sidebarToggle}
class="z-2000 hidden lt-sm:flex justify-center absolute items-center w-8 h-8 rd-8
bg-accent dark:bg-darkAccent active:bg-accentDark dark:active:bg-darkAccentDark text-accentText dark:text-darkAccentText"
class="z-2000 sidebar-toggle hidden lt-sm:flex justify-center absolute items-center w-8 h-8 rd-8
bg-accent dark:bg-darkAccent active:bg-accentDark dark:active:bg-darkAccentDark"
>
{#if isSideBarOpen}
<span class="i-codicon-close animate-duration-300ms animate-fade-in"></span>
@@ -345,11 +409,10 @@
</div>
<div
class="flex h-screen w-screen overflow-hidden text-primaryText dark:text-darkPrimaryText"
class="flex h-screen w-screen overflow-hidden children-pt8 children-pb-2 text-primaryText dark:text-darkPrimaryText"
>
<aside
id="sidebar"
bind:this={sidebar}
class="lt-sm:h-screen lt-sm:shadow-lg lt-sm:shadow lt-sm:transition-transform lt-sm:absolute lt-sm:z-1999
bg-darkPrimaryLighter transition-colors-250 overflow-hidden grid select-none px-2"
>
@@ -357,16 +420,13 @@
<img class="p-7" src="tauri_logo.png" alt="Tauri logo" />
</a>
{#if !isWindows}
<a href="##" class="nv justify-between" onclick={switchTheme}>
{#if theme === 'auto'}
Switch to Dark mode
<div class="i-ph-circle-half-fill"></div>
{:else if theme === 'dark'}
<a href="##" class="nv justify-between h-8" on:click={toggleDark}>
{#if isDark}
Switch to Light mode
<div class="i-ph-moon"></div>
{:else if theme === 'light'}
Switch to Auto mode
<div class="i-ph-sun"></div>
{:else}
Switch to Dark mode
<div class="i-ph-moon"></div>
{/if}
</a>
<br />
@@ -375,7 +435,7 @@
{/if}
<a
class="nv justify-between"
class="nv justify-between h-8"
target="_blank"
href="https://tauri.app/v1/guides/"
>
@@ -383,7 +443,7 @@
<span class="i-codicon-link-external"></span>
</a>
<a
class="nv justify-between"
class="nv justify-between h-8"
target="_blank"
href="https://github.com/tauri-apps/tauri"
>
@@ -391,7 +451,7 @@
<span class="i-codicon-link-external"></span>
</a>
<a
class="nv justify-between"
class="nv justify-between h-8"
target="_blank"
href="https://github.com/tauri-apps/tauri/tree/dev/examples/api"
>
@@ -401,19 +461,23 @@
<br />
<div class="bg-white/5 h-2px"></div>
<br />
<div class="flex flex-col overflow-y-auto children-flex-none gap-1">
<div
class="flex flex-col overflow-y-auto children-h-10 children-flex-none gap-1"
>
{#each views as view}
<a
href="##"
class="nv {selected === view ? 'nv_selected' : ''}"
onclick={() => {
selected = view
isSideBarOpen = false
}}
>
<div class="{view.icon} mr-2"></div>
<p>{view.label}</p></a
>
{#if view}
<a
href="##"
class="nv {selected === view ? 'nv_selected' : ''}"
on:click={() => {
select(view)
isSideBarOpen = false
}}
>
<div class="{view.icon} mr-2"></div>
<p>{view.label}</p></a
>
{/if}
{/each}
</div>
</aside>
@@ -425,7 +489,11 @@
<h1>{selected.label}</h1>
<div class="overflow-y-auto">
<div class="mr-2">
<selected.component {onMessage} />
<svelte:component
this={selected.component}
{onMessage}
{insecureRenderHtml}
/>
</div>
</div>
</div>
@@ -435,21 +503,20 @@
id="console"
class="select-none h-15rem grid grid-rows-[2px_2rem_1fr] gap-1 overflow-hidden"
>
<!-- svelte-ignore a11y_no_static_element_interactions -->
<div
role="button"
tabindex="0"
onmousedown={startResizingConsole}
on:mousedown={startResizingConsole}
class="bg-black/20 h-2px cursor-ns-resize"
></div>
<div class="flex justify-between items-center px-2">
<p class="font-semibold">Console</p>
<button
aria-label="Clear Console"
class="cursor-pointer h-85% rd-1 p-1 flex justify-center items-center border-none
class="cursor-pointer h-85% rd-1 p-1 flex justify-center items-center border-none bg-inherit
hover:bg-hoverOverlay dark:hover:bg-darkHoverOverlay
active:bg-hoverOverlay/25 dark:active:bg-darkHoverOverlay/25
"
onclick={clear}
on:click={clear}
>
<div class="i-codicon-clear-all"></div>
</button>
@@ -458,8 +525,8 @@
bind:this={consoleTextEl}
class="px-2 overflow-y-auto all:font-mono code-block all:text-xs select-text mr-2"
>
{#each $messages as messageHtml}
{@html messageHtml}
{#each $messages as r}
{@html r.html}
{/each}
</div>
</div>
+9 -32
View File
@@ -1,14 +1,3 @@
:root {
line-height: 1.5;
}
:root.dark {
color-scheme: dark;
}
:root.light {
color-scheme: light;
}
*:not(h1, h2, h3, h4, h5, h6) {
margin: 0;
padding: 0;
@@ -19,11 +8,6 @@
font-family: 'Rubik', sans-serif;
}
button {
color: inherit;
background-color: inherit;
}
::-webkit-scrollbar {
width: 0.25rem;
height: 3px;
@@ -49,34 +33,27 @@ code.code-block {
width: 18.75rem;
}
@media screen and (width < 640px) {
@media screen and (max-width: 640px) {
#sidebar {
--translate-x: -18.75rem;
transform: translateX(var(--translate-x));
}
}
#sidebar,
main {
padding-top: calc(env(safe-area-inset-top) + 2rem);
.sidebar-toggle {
margin-top: 0.5rem;
margin-left: 0.5rem;
}
#sidebar {
padding-left: calc(env(safe-area-inset-left) + 0.5rem);
}
main {
padding-right: env(safe-area-inset-right);
}
#sidebarToggle {
margin-top: calc(env(safe-area-inset-top) + 0.5rem);
margin-left: calc(env(safe-area-inset-left) + 0.5rem);
body {
overflow: hidden;
padding: env(safe-area-inset-top) env(safe-area-inset-right)
env(safe-area-inset-bottom) env(safe-area-inset-left);
}
#sidebar,
#console {
padding-bottom: calc(env(safe-area-inset-bottom) + 1.5rem);
padding-bottom: calc(env(safe-area-inset-bottom) + 24px);
}
.transparent {
-103
View File
@@ -1,103 +0,0 @@
<script lang="ts">
import type { Theme, Window } from '@tauri-apps/api/window'
import { ask } from '@tauri-apps/plugin-dialog'
import { onMount } from 'svelte'
let {
appWindow,
switchTheme,
theme
}: { appWindow: Window; switchTheme: () => void; theme: Theme | 'auto' } =
$props()
// Window controls
let isWindowMaximized = $state(false)
onMount(async () => {
isWindowMaximized = await appWindow.isMaximized()
appWindow.onResized(async () => {
isWindowMaximized = await appWindow.isMaximized()
})
})
async function minimize() {
await appWindow.minimize()
}
async function toggleMaximize() {
await appWindow.toggleMaximize()
}
let confirmedClose = false
async function close() {
if (!confirmedClose) {
confirmedClose = await ask(
'Are you sure that you want to close this window?',
{
title: 'Tauri API'
}
)
if (confirmedClose) {
appWindow.close()
}
}
}
</script>
<div
class="w-screen select-none h-8 flex justify-between items-center absolute text-primaryText dark:text-darkPrimaryText"
data-tauri-drag-region
>
<span
class="h-100% pl-2 flex-1 flex items-center lt-sm:pl-10 lt-lg:text-darkPrimaryText [app-region:drag]"
>Tauri API Validation</span
>
<span
class="
h-100%
children:h-100% children:w-12 children:inline-flex
children:items-center children:justify-center"
>
<button
aria-label="Toggle dark mode"
title={theme ? 'Switch to Light mode' : 'Switch to Dark mode'}
class="border-none hover:bg-hoverOverlay active:bg-hoverOverlayDarker dark:hover:bg-darkHoverOverlay dark:active:bg-darkHoverOverlayDarker"
onclick={switchTheme}
>
{#if theme === 'auto'}
<div title="Switch to Dark mode" class="i-ph-circle-half-fill"></div>
{:else if theme === 'dark'}
<div title="Switch to Light mode" class="i-ph-moon"></div>
{:else if theme === 'light'}
<div title="Switch to Auto mode" class="i-ph-sun"></div>
{/if}
</button>
<button
aria-label="Minimize window"
title="Minimize"
class="border-none hover:bg-hoverOverlay active:bg-hoverOverlayDarker dark:hover:bg-darkHoverOverlay dark:active:bg-darkHoverOverlayDarker"
onclick={minimize}
>
<div class="i-codicon-chrome-minimize"></div>
</button>
<button
aria-label="Maximize window"
title={isWindowMaximized ? 'Restore' : 'Maximize'}
class="border-none hover:bg-hoverOverlay active:bg-hoverOverlayDarker dark:hover:bg-darkHoverOverlay dark:active:bg-darkHoverOverlayDarker"
onclick={toggleMaximize}
>
{#if isWindowMaximized}
<div class="i-codicon-chrome-restore"></div>
{:else}
<div class="i-codicon-chrome-maximize"></div>
{/if}
</button>
<button
aria-label="Close window"
title="Close"
class="border-none hover:bg-red-700 dark:hover:bg-red-700 hover:text-darkPrimaryText active:bg-red-700/90 dark:active:bg-red-700/90 active:text-darkPrimaryText"
onclick={close}
>
<div class="i-codicon-chrome-close"></div>
</button>
</span>
</div>
+2 -1
View File
@@ -5,6 +5,7 @@
import { readFile } from '@tauri-apps/plugin-fs'
export let onMessage
export let insecureRenderHtml
let text = 'clipboard message'
function writeText() {
@@ -40,7 +41,7 @@
const image = await clipboard.readImage()
arrayBufferToBase64(await image.rgba(), function (base64) {
const src = 'data:image/png;base64,' + base64
onMessage('<img src="' + src + '"></img>')
insecureRenderHtml('<img src="' + src + '"></img>')
})
return
} catch (_) {}
+77 -87
View File
@@ -1,138 +1,129 @@
<script lang="ts">
import {
open,
save,
confirm,
message,
type PickerMode,
type FileAccessMode
} from '@tauri-apps/plugin-dialog'
import { readFile } from '@tauri-apps/plugin-fs'
import type { ViewProps } from '../App.svelte'
<script>
import { open, save, confirm, message } from "@tauri-apps/plugin-dialog";
import { readFile } from "@tauri-apps/plugin-fs";
let { onMessage }: ViewProps = $props()
export let onMessage;
export let insecureRenderHtml;
let defaultPath = null;
let filter = null;
let multiple = false;
let directory = false;
let pickerMode = "document";
let fileAccessMode = "scoped";
let defaultPath: string | undefined = $state()
let filter = $state('')
let multiple = $state(false)
let directory = $state(false)
let pickerMode: PickerMode = $state('document')
let fileAccessMode: FileAccessMode = $state('scoped')
function arrayBufferToBase64(
buffer: ArrayBuffer,
callback: (base64: string) => void
) {
function arrayBufferToBase64(buffer, callback) {
var blob = new Blob([buffer], {
type: 'application/octet-binary'
})
var reader = new FileReader()
type: "application/octet-binary",
});
var reader = new FileReader();
reader.onload = function (evt) {
var dataurl = evt.target!.result as string
callback(dataurl.split(',')[1])
}
reader.readAsDataURL(blob)
var dataurl = evt.target.result;
callback(dataurl.substr(dataurl.indexOf(",") + 1));
};
reader.readAsDataURL(blob);
}
async function prompt() {
confirm('Do you want to do something?')
.then((res) => onMessage(res ? 'Yes' : 'No'))
.catch(onMessage)
confirm("Do you want to do something?")
.then((res) => onMessage(res ? "Yes" : "No"))
.catch(onMessage);
}
async function promptCustom() {
confirm('Is Tauri awesome?', {
okLabel: 'Absolutely',
cancelLabel: 'Totally'
confirm("Is Tauri awesome?", {
okLabel: "Absolutely",
cancelLabel: "Totally",
})
.then((res) =>
onMessage(
res ? 'Tauri is absolutely awesome' : 'Tauri is totally awesome'
res ? "Tauri is absolutely awesome" : "Tauri is totally awesome"
)
)
.catch(onMessage)
.catch(onMessage);
}
async function msg() {
await message('Tauri is awesome!').then((res) => onMessage(res))
await message("Tauri is awesome!").then((res) => onMessage(res));
}
async function msgCustom() {
const buttons = { yes: 'awesome', no: 'amazing', cancel: 'stunning' }
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)
.catch(onMessage);
}
async function openDialog() {
try {
const result = await open({
title: 'My wonderful open dialog',
var result = await open({
title: "My wonderful open dialog",
defaultPath,
filters: filter
? [
{
name: 'Tauri Example',
extensions: filter.split(',').map((f) => f.trim())
}
name: "Tauri Example",
extensions: filter.split(",").map((f) => f.trim()),
},
]
: [],
multiple,
directory,
pickerMode,
fileAccessMode
fileAccessMode,
})
if (Array.isArray(result)) {
onMessage(result)
} else if (result === null) {
onMessage('user cancelled the selection')
onMessage(result);
} else {
const pathToRead = result
const isFile = pathToRead.match(/\S+\.\S+$/g)
var pathToRead = result;
var isFile = pathToRead.match(/\S+\.\S+$/g);
await readFile(pathToRead).then(function (res) {
if (isFile) {
if (
pathToRead.includes('.png')
|| pathToRead.includes('.jpg')
|| pathToRead.includes('.jpeg')
) {
arrayBufferToBase64(res.buffer, function (base64) {
const src = 'data:image/png;base64,' + base64
onMessage('<img src="' + src + '"></img>')
})
await readFile(pathToRead)
.then(function (res) {
if (isFile) {
if (
pathToRead.includes(".png") ||
pathToRead.includes(".jpg") ||
pathToRead.includes(".jpeg")
) {
arrayBufferToBase64(
new Uint8Array(res),
function (base64) {
var src = "data:image/png;base64," + base64;
insecureRenderHtml('<img src="' + src + '"></img>');
}
);
} else {
// Convert byte array to UTF-8 string
const decoder = new TextDecoder('utf-8');
const text = decoder.decode(new Uint8Array(res));
onMessage(text);
}
} else {
// Convert byte array to UTF-8 string
const decoder = new TextDecoder('utf-8')
const text = decoder.decode(res)
onMessage(text)
}
} else {
onMessage(res)
onMessage(res);
}
})
}
} catch (exception) {
} catch(exception) {
onMessage(exception)
}
}
function saveDialog() {
save({
title: 'My wonderful save dialog',
title: "My wonderful save dialog",
defaultPath,
filters: filter
? [
{
name: 'Tauri Example',
extensions: filter.split(',').map((f) => f.trim())
}
name: "Tauri Example",
extensions: filter.split(",").map((f) => f.trim()),
},
]
: []
})
: [],
})
.then(onMessage)
.catch(onMessage)
.catch(onMessage);
}
</script>
@@ -180,16 +171,15 @@
<br />
<div class="flex flex-wrap flex-col md:flex-row gap-2 children:flex-shrink-0">
<button class="btn" id="open-dialog" onclick={openDialog}>Open dialog</button>
<button class="btn" id="save-dialog" onclick={saveDialog}
<button class="btn" id="open-dialog" on:click={openDialog}>Open dialog</button>
<button class="btn" id="save-dialog" on:click={saveDialog}
>Open save dialog</button
>
<button class="btn" id="prompt-dialog" onclick={prompt}>Prompt</button>
<button class="btn" id="custom-prompt-dialog" onclick={promptCustom}
<button class="btn" id="prompt-dialog" on:click={prompt}>Prompt</button>
<button class="btn" id="custom-prompt-dialog" on:click={promptCustom}
>Prompt (custom)</button
>
<button class="btn" id="message-dialog" onclick={msg}>Message</button>
<button class="btn" id="message-dialog" onclick={msgCustom}
>Message (custom)</button
>
<button class="btn" id="message-dialog" on:click={msg}>Message</button>
<button class="btn" id="message-dialog" on:click={msgCustom}>Message (custom)</button>
</div>
+3 -3
View File
@@ -5,7 +5,7 @@
import { arrayBufferToBase64 } from '../lib/utils'
import { onDestroy, onMount } from 'svelte'
const { onMessage } = $props()
const { onMessage, insecureRenderHtml } = $props()
let path = $state('')
let img
@@ -118,12 +118,12 @@
new Uint8Array(response),
function (base64) {
const src = 'data:image/png;base64,' + base64
onMessage('<img src="' + src + '"></img>')
insecureRenderHtml('<img src="' + src + '"></img>')
}
)
} else {
const value = String.fromCharCode.apply(null, response)
onMessage(
insecureRenderHtml(
'<textarea id="file-response"></textarea><button id="file-save">Save</button>'
)
setTimeout(() => {
+11 -19
View File
@@ -1,18 +1,12 @@
<script lang="ts">
import { check, Update } from '@tauri-apps/plugin-updater'
<script>
import { check } from '@tauri-apps/plugin-updater'
import { relaunch } from '@tauri-apps/plugin-process'
import { onDestroy } from 'svelte'
let { onMessage } = $props()
export let onMessage
let isChecking = $state(false)
let isInstalling = $state(false)
let newUpdate = $state<Update | undefined>()
let totalSize = $state(0)
let downloadedSize = $state(0)
let progress = $derived(
totalSize ? Math.round((downloadedSize / totalSize) * 100) : 0
)
let isChecking, isInstalling, newUpdate
let totalSize = 0,
downloadedSize = 0
async function checkUpdate() {
isChecking = true
@@ -37,10 +31,10 @@
isInstalling = true
downloadedSize = 0
try {
await newUpdate!.downloadAndInstall((downloadProgress) => {
await newUpdate.downloadAndInstall((downloadProgress) => {
switch (downloadProgress.event) {
case 'Started':
totalSize = downloadProgress.data.contentLength!
totalSize = downloadProgress.data.contentLength
break
case 'Progress':
downloadedSize += downloadProgress.data.chunkLength
@@ -60,16 +54,14 @@
}
}
onDestroy(() => {
newUpdate?.close()
})
$: progress = totalSize ? Math.round((downloadedSize / totalSize) * 100) : 0
</script>
<div class="flex children:grow children:h10">
{#if !isChecking && !newUpdate}
<button class="btn" onclick={checkUpdate}>Check update</button>
<button class="btn" on:click={checkUpdate}>Check update</button>
{:else if !isInstalling && newUpdate}
<button class="btn" onclick={install}>Install update</button>
<button class="btn" on:click={install}>Install update</button>
{:else}
<div class="progress">
<span>{progress}%</span>
-5
View File
@@ -1,5 +0,0 @@
*
!.gitignore
!README.md
!updater.json
-10
View File
@@ -1,10 +0,0 @@
To test the updater:
1. Comment out `verify_signature` inside `plugins/updater/src/updater.rs`
2. Run `pnpm tauri build --debug` to build the bundles
3. Copy the bundle you want to test to this folder (`examples/api/updater-test/`)
4. Run `pnpm tauri dev` and open the Updater tab to check
If the bundle you're testing doesn't exist in the `updater.json` yet, add it manually and welcome to open an PR
> The `updater.json` and debug bundles will be served by `vite`
-11
View File
@@ -1,11 +0,0 @@
{
"version": "2.1.0",
"notes": "Test update!",
"pub_date": "2026-03-01T14:04:20+00:00",
"platforms": {
"windows-x86_64": {
"signature": "",
"url": "http://localhost:5173/updater-test/Tauri API_2.0.0_x64_en-US.msi"
}
}
}
+1 -1
View File
@@ -27,7 +27,7 @@ export default defineConfig(async () => {
port: 5173,
strictPort: true,
fs: {
allow: ['.']
allow: ['.', '../../tooling/api/dist']
}
}
}
+13 -3
View File
@@ -19,11 +19,21 @@
"eslint-config-prettier": "10.1.8",
"eslint-plugin-security": "4.0.1",
"prettier": "3.8.3",
"rollup": "4.62.2",
"rollup": "4.60.3",
"tslib": "2.8.1",
"typescript": "6.0.3",
"typescript": "7.0.2",
"typescript-eslint": "8.58.2"
},
"minimumReleaseAge": 4320,
"packageManager": "pnpm@11.20.0"
"pnpm": {
"overrides": {
"esbuild@<0.25.0": ">=0.25.0"
},
"onlyBuiltDependencies": [
"esbuild"
]
},
"engines": {
"pnpm": "^10.16.0"
}
}
-7
View File
@@ -8,13 +8,6 @@ edition = { workspace = true }
rust-version = { workspace = true }
repository = { workspace = true }
links = "tauri-plugin-autostart"
exclude = [
"/banner.png",
"/guest-js",
"/package.json",
"/rollup.config.js",
"/tsconfig.json",
]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
+1 -1
View File
@@ -161,7 +161,7 @@ impl Builder {
///
/// ```no_run
/// Builder::new()
/// .app_name("My Custom Name")
/// .app_name("My Custom Name"))
/// .build();
/// ```
pub fn app_name<S: Into<String>>(mut self, app_name: S) -> Self {
+1 -7
View File
@@ -8,13 +8,7 @@ license = { workspace = true }
rust-version = { workspace = true }
repository = { workspace = true }
links = "tauri-plugin-barcode-scanner"
exclude = [
"/banner.png",
"/guest-js",
"/package.json",
"/rollup.config.js",
"/tsconfig.json",
]
[package.metadata.docs.rs]
targets = ["x86_64-linux-android"]
-1
View File
@@ -7,7 +7,6 @@ authors = { workspace = true }
license = { workspace = true }
repository = { workspace = true }
links = "tauri-plugin-biometric"
exclude = ["/guest-js", "/package.json", "/rollup.config.js", "/tsconfig.json"]
[package.metadata.docs.rs]
targets = ["x86_64-linux-android"]
-7
View File
@@ -8,13 +8,6 @@ license = { workspace = true }
rust-version = { workspace = true }
repository = { workspace = true }
links = "tauri-plugin-cli"
exclude = [
"/banner.png",
"/guest-js",
"/package.json",
"/rollup.config.js",
"/tsconfig.json",
]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
-7
View File
@@ -8,13 +8,6 @@ license = { workspace = true }
rust-version = { workspace = true }
repository = { workspace = true }
links = "tauri-plugin-clipboard-manager"
exclude = [
"/banner.png",
"/guest-js",
"/package.json",
"/rollup.config.js",
"/tsconfig.json",
]
[package.metadata.docs.rs]
-8
View File
@@ -8,14 +8,6 @@ edition = { workspace = true }
rust-version = { workspace = true }
repository = { workspace = true }
links = "tauri-plugin-deep-link"
exclude = [
"/banner.png",
"/examples",
"/guest-js",
"/package.json",
"/rollup.config.js",
"/tsconfig.json",
]
[package.metadata.docs.rs]
targets = ["x86_64-linux-android"]
+4 -4
View File
@@ -11,11 +11,11 @@
},
"dependencies": {
"@tauri-apps/api": "^2.11.0",
"@tauri-apps/plugin-deep-link": "workspace:*"
"@tauri-apps/plugin-deep-link": "2.4.9"
},
"devDependencies": {
"@tauri-apps/cli": "2.11.4",
"typescript": "^6.0.3",
"vite": "^8.0.16"
"@tauri-apps/cli": "2.11.2",
"typescript": "^7.0.0",
"vite": "^8.0.1"
}
}
@@ -26,3 +26,9 @@ tauri-plugin-single-instance = { path = "../../../../single-instance", features
"deep-link",
] }
log = "0.4"
[features]
# this feature is used for production builds or when `devUrl` points to the filesystem and the built-in dev server is disabled.
# If you use cargo directly instead of tauri's cli you can use this feature flag to switch between tauri's `dev` and `build` modes.
# DO NOT REMOVE!!
prod = ["tauri/custom-protocol"]
@@ -1,6 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.deep_link_example" parent="Theme.Material3.DayNight.NoActionBar">
<style name="Theme.deep_link_example" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Customize your theme here. -->
</style>
</resources>
@@ -1,6 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.deep_link_example" parent="Theme.Material3.DayNight.NoActionBar">
<style name="Theme.deep_link_example" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Customize your theme here. -->
</style>
</resources>
+7 -17
View File
@@ -14,11 +14,9 @@ import { type UnlistenFn, listen } from '@tauri-apps/api/event'
* const urls = await getCurrent();
* ```
*
* #### Platform-specific
*
* - **Windows / Linux:** This function reads the command line arguments and checks if there's only one value, which must be an URL with scheme matching one of the configured values.
* Note that you must manually check the arguments when registering deep link schemes dynamically with [`Self::register`].
* Additionally, the deep link might have been provided as a CLI argument so you should check if its format matches what you expect.
* #### - **Windows / Linux**: This function reads the command line arguments and checks if there's only one value, which must be an URL with scheme matching one of the configured values.
* Note that you must manually check the arguments when registering deep link schemes dynamically with [`Self::register`].
* Additionally, the deep link might have been provided as a CLI argument so you should check if its format matches what you expect..
*
* @since 2.0.0
*/
@@ -37,9 +35,7 @@ export async function getCurrent(): Promise<string[] | null> {
* await register("my-scheme");
* ```
*
* #### Platform-specific
*
* - **macOS / Android / iOS:** Unsupported.
* #### - **macOS / Android / iOS**: Unsupported.
*
* @since 2.0.0
*/
@@ -58,9 +54,7 @@ export async function register(protocol: string): Promise<null> {
* await unregister("my-scheme");
* ```
*
* #### Platform-specific
*
* - **macOS / Linux / Android / iOS:** Unsupported.
* #### - **macOS / Linux / Android / iOS**: Unsupported.
*
* @since 2.0.0
*/
@@ -79,9 +73,7 @@ export async function unregister(protocol: string): Promise<null> {
* await isRegistered("my-scheme");
* ```
*
* #### Platform-specific
*
* - **macOS / Android / iOS:** Unsupported.
* #### - **macOS / Android / iOS**: Unsupported.
*
* @since 2.0.0
*/
@@ -100,9 +92,7 @@ export async function isRegistered(protocol: string): Promise<boolean> {
* await onOpenUrl((urls) => { console.log(urls) });
* ```
*
* #### Platform-specific
*
* - **Windows / Linux:** Unsupported without the single-instance plugin. The OS will spawn a new app instance passing the URL as a CLI argument.
* #### - **Windows / Linux**: Unsupported without the single-instance plugin. The OS will spawn a new app instance passing the URL as a CLI argument.
*
* @since 2.0.0
*/
+1 -1
View File
@@ -28,6 +28,6 @@
"@tauri-apps/api": "^2.11.0"
},
"devDependencies": {
"@tauri-apps/cli": "2.11.4"
"@tauri-apps/cli": "2.11.2"
}
}
-4
View File
@@ -1,9 +1,5 @@
# Changelog
## \[2.7.2]
- [`40ae0a7f`](https://github.com/tauri-apps/plugins-workspace/commit/40ae0a7fa0ecc9b0cdbd952297f7a17f37308229) ([#3491](https://github.com/tauri-apps/plugins-workspace/pull/3491) by [@Legend-Master](https://github.com/tauri-apps/plugins-workspace/../../Legend-Master)) Use `com.google.android.material.dialog.MaterialAlertDialogBuilder` instead of `AlertDialog` so the dialog follows the app's theme
## \[2.7.1]
### Dependencies
+1 -9
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-dialog"
version = "2.7.2"
version = "2.7.1"
description = "Native system dialogs for opening and saving files along with message dialogs on your Tauri application."
edition = { workspace = true }
authors = { workspace = true }
@@ -8,14 +8,6 @@ license = { workspace = true }
rust-version = { workspace = true }
repository = { workspace = true }
links = "tauri-plugin-dialog"
exclude = [
"/banner.png",
"/guest-js",
"/package.json",
"/rollup.config.js",
"/test",
"/tsconfig.json",
]
[features]
default = ["gtk3"]
+2 -2
View File
@@ -35,8 +35,8 @@ android {
dependencies {
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.appcompat:appcompat:1.7.1")
implementation("com.google.android.material:material:1.13.0")
implementation("androidx.appcompat:appcompat:1.6.0")
implementation("com.google.android.material:material:1.7.0")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
@@ -5,6 +5,7 @@
package app.tauri.dialog
import android.app.Activity
import android.app.AlertDialog
import android.content.Intent
import android.net.Uri
import android.os.Handler
@@ -20,7 +21,6 @@ import app.tauri.plugin.Invoke
import app.tauri.plugin.JSArray
import app.tauri.plugin.JSObject
import app.tauri.plugin.Plugin
import com.google.android.material.dialog.MaterialAlertDialogBuilder
@InvokeArg
class Filter {
@@ -158,7 +158,7 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) {
Handler(Looper.getMainLooper())
.post {
val builder = MaterialAlertDialogBuilder(activity)
val builder = AlertDialog.Builder(activity)
if (args.title != null) {
builder.setTitle(args.title)
@@ -191,7 +191,8 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) {
}
}
builder.show()
val dialog = builder.create()
dialog.show()
}
}
@@ -204,10 +205,9 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) {
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.putExtra(Intent.EXTRA_TITLE, args.fileName ?: "")
if (parsedTypes.size == 1) {
intent.type = parsedTypes.first()
} else {
intent.type = "*/*"
intent.type = "*/*"
if (parsedTypes.isNotEmpty()) {
intent.putExtra(Intent.EXTRA_MIME_TYPES, parsedTypes)
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-dialog",
"version": "2.7.2",
"version": "2.7.1",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
-5
View File
@@ -3,11 +3,6 @@
// SPDX-License-Identifier: MIT
//! Native system dialogs for opening and saving files along with message dialogs.
//!
//! ## Cargo features
//!
//! - **gtk3** *(enabled by default)*: Uses GTK for dialogs on Linux & BSDs; has no effect on Windows and macOS
//! - **xdg-portal**: Uses XDG Desktop Portal instead of GTK on Linux & BSDs
#![doc(
html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png",
-7
View File
@@ -8,13 +8,6 @@ edition = { workspace = true }
rust-version = { workspace = true }
repository = { workspace = true }
links = "tauri-plugin-fs"
exclude = [
"/banner.png",
"/guest-js",
"/package.json",
"/rollup.config.js",
"/tsconfig.json",
]
[package.metadata.platforms.support]
windows = { level = "full", notes = "Apps installed via MSI or NSIS in `perMachine` and `both` mode require admin permissions for write access in `$RESOURCES` folder" }
@@ -6,7 +6,7 @@ description = """This denies read access to the
`$APPLOCALDATA` folder on linux as the webview data and configuration values are stored here.
Allowing access can lead to sensitive information disclosure and should be well considered."""
[[permission.scope.deny]]
[[scope.deny]]
path = "$APPLOCALDATA/**"
[[permission]]
@@ -15,5 +15,5 @@ description = """This denies read access to the
`$APPLOCALDATA/EBWebView` folder on windows as the webview data and configuration values are stored here.
Allowing access can lead to sensitive information disclosure and should be well considered."""
[[permission.scope.deny]]
[[scope.deny]]
path = "$APPLOCALDATA/EBWebView/**"
+109 -106
View File
@@ -74,7 +74,7 @@ pub type CommandResult<T> = std::result::Result<T, CommandError>;
/// Represents either a plain PathBuf or a PathHandle that manages security-scoped resources.
pub enum PathKind<R: Runtime> {
/// A plain path that doesn't manage security-scoped resources.
#[cfg(mobile)] // only used on mobile
#[allow(dead_code)] // only used on mobile
Path(PathBuf),
/// A path handle that manages security-scoped resources and will clean them up on drop.
Handle(PathHandle<R>),
@@ -84,7 +84,6 @@ impl<R: Runtime> PathKind<R> {
/// Get a reference to the underlying path.
pub fn as_path(&self) -> &Path {
match self {
#[cfg(mobile)]
PathKind::Path(p) => p.as_ref(),
PathKind::Handle(h) => h.as_ref(),
}
@@ -93,7 +92,6 @@ impl<R: Runtime> PathKind<R> {
/// Get a reference to the underlying PathBuf.
pub fn as_path_buf(&self) -> &PathBuf {
match self {
#[cfg(mobile)]
PathKind::Path(p) => p,
PathKind::Handle(h) => h,
}
@@ -116,13 +114,27 @@ impl<R: Runtime> AsRef<PathBuf> for PathKind<R> {
pub struct FileHandle<R: Runtime> {
file: File,
path: PathKind<R>,
#[cfg(target_os = "ios")]
#[allow(dead_code)] // Used in Drop implementation
path_: SafeFilePath,
#[cfg(target_os = "ios")]
#[allow(dead_code)] // Used in Drop implementation
app_handle: tauri::AppHandle<R>,
}
impl<R: Runtime> FileHandle<R> {
fn new(
file: File,
path: PathKind<R>,
path_: SafeFilePath,
app_handle: tauri::AppHandle<R>,
) -> Self {
Self {
file,
path,
path_,
app_handle,
}
}
/// Get the resolved path.
pub fn path(&self) -> &Path {
self.path.as_path()
@@ -143,39 +155,41 @@ impl<R: Runtime> DerefMut for FileHandle<R> {
}
}
#[cfg(target_os = "ios")]
impl<R: Runtime> Drop for FileHandle<R> {
fn drop(&mut self) {
// Only clean up if we have a plain PathBuf, not a PathHandle
// PathHandle will handle its own cleanup when it's dropped
if let PathKind::Path(_) = &self.path {
use crate::{FilePath, FsExt};
// Convert SafeFilePath to FilePath
let file_path: FilePath = match &self.path_ {
SafeFilePath::Url(url) => FilePath::Url(url.clone()),
SafeFilePath::Path(safe_path) => FilePath::Path(safe_path.as_ref().to_owned()),
};
#[cfg(target_os = "ios")]
{
// Only clean up if we have a plain PathBuf, not a PathHandle
// PathHandle will handle its own cleanup when it's dropped
if let PathKind::Path(_) = &self.path {
use crate::{FilePath, FsExt};
// Convert SafeFilePath to FilePath
let file_path: FilePath = match &self.path_ {
SafeFilePath::Url(url) => FilePath::Url(url.clone()),
SafeFilePath::Path(safe_path) => FilePath::Path(safe_path.as_ref().to_owned()),
};
// Only clean up if we're tracking this resource
// If start_accessing_security_scoped_resource was used, it won't be in our tracking
// and we shouldn't interfere
if let FilePath::Url(url) = file_path {
if url.scheme() == "file" {
let security_scoped_resources =
self.app_handle.state::<crate::SecurityScopedResources>();
// Only clean up if we're tracking this resource
// If start_accessing_security_scoped_resource was used, it won't be in our tracking
// and we shouldn't interfere
if let FilePath::Url(url) = file_path {
if url.scheme() == "file" {
let security_scoped_resources =
self.app_handle.state::<crate::SecurityScopedResources>();
// Only clean up if it's not tracked manually
if !security_scoped_resources.is_tracked_manually(url.as_str()) {
log::debug!(
"Stopping accessing security-scoped resource for URL: {url} on drop"
);
let _ = self
.app_handle
.fs()
.stop_accessing_security_scoped_resource(FilePath::Url(url.clone()));
security_scoped_resources.remove(url.as_str());
} else {
log::debug!("Not cleaning up security-scoped resource for URL: {url} on drop (manually tracked via start_accessing_security_scoped_resource)");
// Only clean up if it's not tracked manually
if !security_scoped_resources.is_tracked_manually(url.as_str()) {
log::debug!("Stopping accessing security-scoped resource for URL: {url} on drop");
let _ = self
.app_handle
.fs()
.stop_accessing_security_scoped_resource(FilePath::Url(
url.clone(),
));
security_scoped_resources.remove(url.as_str());
} else {
log::debug!("Not cleaning up security-scoped resource for URL: {url} on drop (manually tracked via start_accessing_security_scoped_resource)");
}
}
}
}
@@ -222,36 +236,38 @@ impl<R: Runtime> AsRef<PathBuf> for PathHandle<R> {
}
}
#[cfg(target_os = "ios")]
impl<R: Runtime> Drop for PathHandle<R> {
fn drop(&mut self) {
use crate::{FilePath, FsExt};
// Convert SafeFilePath to FilePath
let file_path: FilePath = match &self.path_ {
SafeFilePath::Url(url) => FilePath::Url(url.clone()),
SafeFilePath::Path(safe_path) => FilePath::Path(safe_path.as_ref().to_owned()),
};
#[cfg(target_os = "ios")]
{
use crate::{FilePath, FsExt};
// Convert SafeFilePath to FilePath
let file_path: FilePath = match &self.path_ {
SafeFilePath::Url(url) => FilePath::Url(url.clone()),
SafeFilePath::Path(safe_path) => FilePath::Path(safe_path.as_ref().to_owned()),
};
// Only clean up if we're tracking this resource (i.e., resolve_path started it)
// If start_accessing_security_scoped_resource was used, it won't be in our tracking
// and we shouldn't interfere
if let FilePath::Url(url) = file_path {
if url.scheme() == "file" {
let security_scoped_resources =
self.app_handle.state::<crate::SecurityScopedResources>();
// Only clean up if we're tracking this resource (i.e., resolve_path started it)
// If start_accessing_security_scoped_resource was used, it won't be in our tracking
// and we shouldn't interfere
if let FilePath::Url(url) = file_path {
if url.scheme() == "file" {
let security_scoped_resources =
self.app_handle.state::<crate::SecurityScopedResources>();
// Only clean up if it's not tracked manually
if !security_scoped_resources.is_tracked_manually(url.as_str()) {
log::debug!(
"Stopping accessing security-scoped resource for URL: {url} on drop"
);
let _ = self
.app_handle
.fs()
.stop_accessing_security_scoped_resource(FilePath::Url(url.clone()));
security_scoped_resources.remove(url.as_str());
} else {
log::debug!("Not cleaning up security-scoped resource for URL: {url} on drop (manually tracked via start_accessing_security_scoped_resource)");
// Only clean up if it's not tracked manually
if !security_scoped_resources.is_tracked_manually(url.as_str()) {
log::debug!(
"Stopping accessing security-scoped resource for URL: {url} on drop"
);
let _ = self
.app_handle
.fs()
.stop_accessing_security_scoped_resource(FilePath::Url(url.clone()));
security_scoped_resources.remove(url.as_str());
} else {
log::debug!("Not cleaning up security-scoped resource for URL: {url} on drop (manually tracked via start_accessing_security_scoped_resource)");
}
}
}
}
@@ -272,7 +288,6 @@ pub fn create<R: Runtime>(
path: SafeFilePath,
options: Option<BaseOptions>,
) -> CommandResult<ResourceId> {
#[cfg(target_os = "ios")]
let path_ = path.clone();
let resolved_path_handle = resolve_path(
"create",
@@ -288,16 +303,13 @@ pub fn create<R: Runtime>(
resolved_path_handle.display()
)
})?;
#[cfg(target_os = "ios")]
let app_handle = webview.app_handle().clone();
let file_handle = FileHandle {
let file_handle = FileHandle::new(
file,
path: PathKind::Handle(resolved_path_handle),
#[cfg(target_os = "ios")]
PathKind::Handle(resolved_path_handle),
path_,
#[cfg(target_os = "ios")]
app_handle,
};
);
let rid = webview
.resources_table()
.add(StdFileResource::new(file_handle));
@@ -1405,7 +1417,6 @@ fn resolve_file_in_fs<R: Runtime>(
path: SafeFilePath,
open_options: OpenOptions,
) -> CommandResult<FileHandle<R>> {
#[cfg(target_os = "ios")]
let path_ = path.clone();
let resolved_path_handle = resolve_path(
permission,
@@ -1425,16 +1436,13 @@ fn resolve_file_in_fs<R: Runtime>(
)
})?;
#[cfg(target_os = "ios")]
let app_handle = webview.app_handle().clone();
Ok(FileHandle {
Ok(FileHandle::new(
file,
path: PathKind::Handle(resolved_path_handle),
#[cfg(target_os = "ios")]
PathKind::Handle(resolved_path_handle),
path_,
#[cfg(target_os = "ios")]
app_handle,
})
))
}
#[cfg(mobile)]
@@ -1448,7 +1456,6 @@ pub fn resolve_file<R: Runtime>(
) -> CommandResult<FileHandle<R>> {
use crate::FsExt;
#[cfg(target_os = "ios")]
let path_ = path.clone();
match path {
SafeFilePath::Url(url) => {
@@ -1456,16 +1463,13 @@ pub fn resolve_file<R: Runtime>(
let file = webview
.fs()
.open(SafeFilePath::Url(url.clone()), open_options.options)?;
#[cfg(target_os = "ios")]
let app_handle = webview.app_handle().clone();
Ok(FileHandle {
Ok(FileHandle::new(
file,
path: PathKind::Path(resolved_path),
#[cfg(target_os = "ios")]
PathKind::Path(resolved_path),
path_,
#[cfg(target_os = "ios")]
app_handle,
})
))
}
SafeFilePath::Path(path) => resolve_file_in_fs(
permission,
@@ -1490,37 +1494,36 @@ pub fn resolve_path<R: Runtime>(
// On iOS, start accessing security-scoped resource if the path is a file URL
// Only if it hasn't been started already via start_accessing_security_scoped_resource
#[cfg(target_os = "ios")]
if let SafeFilePath::Url(url) = &path {
if url.scheme() == "file" {
use objc2_foundation::{NSString, NSURL};
{
if let SafeFilePath::Url(url) = &path {
if url.scheme() == "file" {
use objc2_foundation::{NSString, NSURL};
let security_scoped_resources = webview.state::<crate::SecurityScopedResources>();
let security_scoped_resources = webview.state::<crate::SecurityScopedResources>();
// Check if already active (started via start_accessing_security_scoped_resource)
if !security_scoped_resources.is_tracked_manually(url.as_str()) {
let url_nsstring = NSString::from_str(url.as_str());
let ns_url = unsafe { NSURL::URLWithString(&url_nsstring) };
if let Some(ns_url) = ns_url {
// Start accessing the security-scoped resource
// This is required for files outside the app's sandbox (e.g., from file picker)
unsafe {
let success = ns_url.startAccessingSecurityScopedResource();
if success {
log::debug!("Started accessing security-scoped resource for URL: {} (via resolve_path)", url.as_str());
// Track it so we know to clean it up
security_scoped_resources.track_manually(url.as_str().to_string());
} else {
log::warn!(
"Failed to start accessing security-scoped resource for URL: {}",
url.as_str()
);
// Check if already active (started via start_accessing_security_scoped_resource)
if !security_scoped_resources.is_tracked_manually(url.as_str()) {
let url_nsstring = NSString::from_str(url.as_str());
let ns_url = unsafe { NSURL::URLWithString(&url_nsstring) };
if let Some(ns_url) = ns_url {
// Start accessing the security-scoped resource
// This is required for files outside the app's sandbox (e.g., from file picker)
unsafe {
let success = ns_url.startAccessingSecurityScopedResource();
if success {
log::debug!("Started accessing security-scoped resource for URL: {} (via resolve_path)", url.as_str());
// Track it so we know to clean it up
security_scoped_resources.track_manually(url.as_str().to_string());
} else {
log::warn!("Failed to start accessing security-scoped resource for URL: {}", url.as_str());
}
}
} else {
log::debug!("Failed to create NSURL from URL: {}, ignoring security-scoped resource access request", url.as_str());
}
} else {
log::debug!("Failed to create NSURL from URL: {}, ignoring security-scoped resource access request", url.as_str());
log::debug!("Security-scoped resource already active for URL: {} (started via start_accessing_security_scoped_resource), skipping", url.as_str());
}
} else {
log::debug!("Security-scoped resource already active for URL: {} (started via start_accessing_security_scoped_resource), skipping", url.as_str());
}
}
}
-4
View File
@@ -3,10 +3,6 @@
// SPDX-License-Identifier: MIT
//! Access the file system.
//!
//! ## Cargo features
//!
//! - **watch**: Enables the `watch` command backed by [`notify`](http://crates.io/crates/notify).
// TODO(v3): consider redesign the API to implement automatic stopAccessingSecurityScopedResource on iOS
// this likely requires returning a handle to a resource so we can impl Drop for it
-1
View File
@@ -7,7 +7,6 @@ authors = { workspace = true }
license = { workspace = true }
repository = { workspace = true }
links = "tauri-plugin-geolocation"
exclude = ["/guest-js", "/package.json", "/rollup.config.js", "/tsconfig.json"]
[package.metadata.docs.rs]
targets = ["x86_64-linux-android"]
-6
View File
@@ -2,12 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
//! Access device geolocation APIs.
//!
//! ## Cargo features
//!
//! - **specta**: Add support for [`specta::specta`](https://docs.rs/specta/2.0.0-rc.25/specta/attr.specta.html) on structs like [`PermissionStatus`], [`PositionOptions`].
use tauri::{
plugin::{Builder, TauriPlugin},
Manager, Runtime,
-7
View File
@@ -8,13 +8,6 @@ license = { workspace = true }
rust-version = { workspace = true }
repository = { workspace = true }
links = "tauri-plugin-global-shortcut"
exclude = [
"/banner.png",
"/guest-js",
"/package.json",
"/rollup.config.js",
"/tsconfig.json",
]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
-1
View File
@@ -7,7 +7,6 @@ authors = { workspace = true }
license = { workspace = true }
repository = { workspace = true }
links = "tauri-plugin-haptics"
exclude = ["/guest-js", "/package.json", "/rollup.config.js", "/tsconfig.json"]
[package.metadata.docs.rs]
targets = ["x86_64-linux-android"]
-6
View File
@@ -2,12 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
//! Trigger haptic feedback on supported devices.
//!
//! ## Cargo features
//!
//! - **specta**: Add support for [`specta::specta`](https://docs.rs/specta/2.0.0-rc.25/specta/attr.specta.html) on structs like [`ImpactFeedbackStyle`], [`NotificationFeedbackType`].
use tauri::{
plugin::{Builder, TauriPlugin},
Manager, Runtime,
+8 -13
View File
@@ -8,13 +8,6 @@ license = { workspace = true }
rust-version = { workspace = true }
repository = { workspace = true }
links = "tauri-plugin-http"
exclude = [
"/banner.png",
"/guest-js",
"/package.json",
"/rollup.config.js",
"/tsconfig.json",
]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
@@ -41,8 +34,7 @@ tauri-plugin-fs = { path = "../fs", version = "2.5.1" }
urlpattern = "0.3"
regex = "1"
http = "1"
# 0.12.16 is when `system-proxy` was added
reqwest = { version = "0.13.0", default-features = false }
reqwest = { version = "0.12", default-features = false }
url = { workspace = true }
data-url = "0.3"
cookie_store = { version = "0.22", optional = true, features = ["serde"] }
@@ -50,7 +42,13 @@ bytes = { version = "1.9", optional = true }
tracing = { workspace = true, optional = true }
[features]
default = ["rustls-tls", "http2", "charset", "system-proxy", "cookies"]
default = [
"rustls-tls",
"http2",
"charset",
"macos-system-configuration",
"cookies",
]
multipart = ["reqwest/multipart"]
json = ["reqwest/json"]
stream = ["reqwest/stream"]
@@ -71,10 +69,7 @@ trust-dns = ["reqwest/trust-dns"]
socks = ["reqwest/socks"]
http2 = ["reqwest/http2"]
charset = ["reqwest/charset"]
# Deprecated, switch to system-proxy
macos-system-configuration = ["reqwest/macos-system-configuration"]
system-proxy = ["reqwest/system-proxy"]
unsafe-headers = []
tracing = ["dep:tracing"]
dangerous-settings = []
-40
View File
@@ -3,46 +3,6 @@
// SPDX-License-Identifier: MIT
//! Access the HTTP client written in Rust.
//!
//! ## Cargo features
//!
//! ### Reqwest feature forwards
//!
//! These features forwards [`reqwest`](https://docs.rs/reqwest/0.12.28/reqwest/index.html) features:
//!
//! - **http2** *(enabled by default)*: Enables HTTP/2 support.
//! - **native-tls**: Enables TLS functionality provided by native-tls.
//! - **native-tls-vendored**: Enables the vendored feature of native-tls.
//! - **native-tls-alpn**: Enables the alpn feature of native-tls.
//! - **rustls-tls** *(enabled by default)*: Enables TLS functionality provided by rustls. Equivalent to
//! rustls-tls-webpki-roots.
//! - **rustls-tls-manual-roots**: Enables TLS functionality provided by rustls, without setting any root
//! certificates. Roots have to be specified manually.
//! - **rustls-tls-webpki-roots**: Enables TLS functionality provided by rustls, while using root certificates
//! from the webpki-roots crate.
//! - **rustls-tls-native-roots**: Enables TLS functionality provided by rustls, while using root certificates
//! from the rustls-native-certs crate.
//! - **blocking**: Provides the [blocking](https://docs.rs/reqwest/0.12.28/reqwest/blocking/index.html) client API.
//! - **charset** *(enabled by default)*: Improved support for decoding text.
//! - **cookies** *(enabled by default)*: Provides cookie session support.
//! - **gzip**: Provides response body gzip decompression.
//! - **brotli**: Provides response body brotli decompression.
//! - **zstd**: Provides response body zstd decompression.
//! - **deflate**: Provides response body deflate decompression.
//! - **json**: Provides serialization and deserialization for JSON bodies.
//! - **multipart**: Provides functionality for multipart forms.
//! - **stream**: Adds support for futures::Stream.
//! - **socks**: Provides SOCKS5 proxy support.
//! - **trust-dns**: Enables a trust-dns/Hickory DNS async resolver instead of the default threadpool using
//! getaddrinfo.
//! - **macos-system-configuration** *(deprecated, use `system-proxy` instead)*: Use Windows and macOS system proxy settings automatically.
//! - **system-proxy** *(enabled by default)*: Use Windows and macOS system proxy settings automatically.
//!
//! ### tauri-plugin-http features
//!
//! - **tracing**: Adds request, response, and cookie-store diagnostics through `tracing`.
//! - **unsafe-headers**: Allows webview requests to send any headers.
//! - **dangerous-settings**: Allows dangerous client settings such as accepting invalid certificates or hostnames.
pub use reqwest;
use tauri::{
-1
View File
@@ -7,7 +7,6 @@ license = { workspace = true }
edition = { workspace = true }
rust-version = { workspace = true }
repository = { workspace = true }
exclude = ["/banner.png"]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
-6
View File
@@ -1,11 +1,5 @@
# Changelog
## \[2.9.0]
- [`f08980f1`](https://github.com/tauri-apps/plugins-workspace/commit/f08980f123f191b9505bd290acd8fff0fdefeed9) ([#3445](https://github.com/tauri-apps/plugins-workspace/pull/3445) by [@bajoca05](https://github.com/tauri-apps/plugins-workspace/../../bajoca05)) Added the `FileOpenStrategy` for log rotation. It defaults to append into existing file if any (previous behaviour), and brings a new feature to create a new file per session: `FileOpenStrategy::Rotate`.
- [`254f222e`](https://github.com/tauri-apps/plugins-workspace/commit/254f222e0e2bc79370f977855b6b39d956d3b568) ([#3477](https://github.com/tauri-apps/plugins-workspace/pull/3477) by [@bajoca05](https://github.com/tauri-apps/plugins-workspace/../../bajoca05)) Migrated from the `log` crate's `kv_unstable` feature flag to the `kv` feature flag stabilized in `0.4.21`.
- [`0c23b8ec`](https://github.com/tauri-apps/plugins-workspace/commit/0c23b8ecfe7c2aca582a81ab7339b11e350b3cac) ([#3446](https://github.com/tauri-apps/plugins-workspace/pull/3446) by [@fee1-dead](https://github.com/tauri-apps/plugins-workspace/../../fee1-dead)) Removed an unused dependency `byte-unit`.
## \[2.8.0]
- [`2a625adf`](https://github.com/tauri-apps/plugins-workspace/commit/2a625adff30238904035b86b6e2db7595597e857) ([#3065](https://github.com/tauri-apps/plugins-workspace/pull/3065) by [@BinaryMuse](https://github.com/tauri-apps/plugins-workspace/../../BinaryMuse)) Allow specifying a log formatter per target using the `format` method on `Target`.
+2 -9
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-log"
version = "2.9.0"
version = "2.8.0"
description = "Configurable logging for your Tauri app."
authors = { workspace = true }
license = { workspace = true }
@@ -8,13 +8,6 @@ edition = { workspace = true }
rust-version = { workspace = true }
repository = { workspace = true }
links = "tauri-plugin-log"
exclude = [
"/banner.png",
"/guest-js",
"/package.json",
"/rollup.config.js",
"/tsconfig.json",
]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
@@ -32,7 +25,7 @@ serde_json = { workspace = true }
tauri = { workspace = true }
thiserror = { workspace = true }
serde_repr = "0.1"
log = { workspace = true, features = ["kv"] }
log = { workspace = true, features = ["kv_unstable"] }
time = { version = "0.3", features = [
"formatting",
"local-offset",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-log",
"version": "2.9.0",
"version": "2.8.0",
"description": "Configurable logging for your Tauri app.",
"license": "MIT OR Apache-2.0",
"authors": [
+1 -12
View File
@@ -3,11 +3,6 @@
// SPDX-License-Identifier: MIT
//! Logging for Tauri applications.
//!
//! ## Cargo features
//!
//! - **colored**: Enables [`Builder::with_colors`] `fern`'s `colored` feature for ANSI-colored outputs.
//! - **tracing**: Emit both log and tracing for the JavaScript log commands.
#![doc(
html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png",
@@ -653,13 +648,7 @@ impl Builder {
/// Skip the creation and global registration of a logger
///
/// If you wish to use your own global logger, you must call `skip_logger` so that the plugin does not attempt to set a second global logger.
/// In this configuration, no logger will be created and the plugin's `log` command will rely on the result of `log::logger()`.
/// You will be responsible for configuring the logger yourself and any included targets will be ignored.
/// If ever initializing the plugin multiple times, such as if registering the plugin while testing, call this method to avoid panicking when registering multiple loggers.
/// For interacting with `tracing`, you can leverage the `tracing-log` logger to forward logs to `tracing` or enable the `tracing` feature for this plugin to emit events directly to the tracing system.
/// Both scenarios require calling this method.
///
/// If you wish to use your own global logger, you must call `skip_logger` so that the plugin does not attempt to set a second global logger. In this configuration, no logger will be created and the plugin's `log` command will rely on the result of `log::logger()`. You will be responsible for configuring the logger yourself and any included targets will be ignored. If ever initializing the plugin multiple times, such as if registering the plugin while testing, call this method to avoid panicking when registering multiple loggers. For interacting with `tracing`, you can leverage the `tracing-log` logger to forward logs to `tracing` or enable the `tracing` feature for this plugin to emit events directly to the tracing system. Both scenarios require calling this method.
/// ```rust
/// static LOGGER: SimpleLogger = SimpleLogger;
///
-1
View File
@@ -7,7 +7,6 @@ authors = { workspace = true }
license = { workspace = true }
repository = { workspace = true }
links = "tauri-plugin-nfc"
exclude = ["/guest-js", "/package.json", "/rollup.config.js", "/tsconfig.json"]
[package.metadata.docs.rs]
targets = ["x86_64-linux-android"]
-1
View File
@@ -47,7 +47,6 @@ impl<R: Runtime> Nfc<R> {
pub fn scan(&self, payload: ScanRequest) -> crate::Result<ScanResponse> {
self.0
.run_mobile_plugin("scan", payload)
.map(|v| ScanResponse { tag: v })
.map_err(Into::into)
}
-8
View File
@@ -8,14 +8,6 @@ license = { workspace = true }
rust-version = { workspace = true }
repository = { workspace = true }
links = "tauri-plugin-notification"
exclude = [
"/banner.png",
"/guest-js",
"/package.json",
"/rollup.config.js",
"/test",
"/tsconfig.json",
]
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu", "x86_64-linux-android"]
@@ -80,11 +80,11 @@ class NotificationStorage(private val context: Context, private val jsonMapper:
fun writeActionGroup(actions: List<ActionType>) {
for (type in actions) {
val i = type.id
val editor = getStorage(ACTION_TYPES_ID + type.id).edit()
editor.clear()
editor.putInt("count", type.actions.size)
for (i in 0 until type.actions.size) {
val action = type.actions[i]
for (action in type.actions) {
editor.putString("id$i", action.id)
editor.putString("title$i", action.title)
editor.putBoolean("input$i", action.input ?: false)
+1 -2
View File
@@ -73,8 +73,7 @@ interface Options {
/**
* The sound resource name or file path for the notification.
*
* ## Platform-specific behavior:
*
* Platform specific behavior:
* - On macOS: use system sounds (e.g., "Ping", "Blow") or sound files in the app bundle
* - On Linux: use XDG theme sounds (e.g., "message-new-instant") or file paths
* - On Windows: use file paths to sound files (.wav format)
-4
View File
@@ -3,10 +3,6 @@
// SPDX-License-Identifier: MIT
//! Send message notifications (brief auto-expiring OS window element) to your user. Can also be used with the Notification Web API.
//!
//! ## Cargo features
//!
//! - **windows7-compat**: Adds support for the legacy Windows 7 notification implementation and Windows-version detection.
#![doc(
html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png",
-178
View File
@@ -320,95 +320,6 @@ pub struct ActionType {
hidden_previews_show_subtitle: bool,
}
#[cfg(mobile)]
#[derive(Debug)]
pub struct ActionTypeBuilder(ActionType);
#[cfg(mobile)]
impl ActionType {
pub fn builder(id: impl Into<String>) -> ActionTypeBuilder {
ActionTypeBuilder(Self {
id: id.into(),
actions: Vec::new(),
hidden_previews_body_placeholder: None,
custom_dismiss_action: false,
allow_in_car_play: false,
hidden_previews_show_title: false,
hidden_previews_show_subtitle: false,
})
}
pub fn id(&self) -> &str {
&self.id
}
pub fn actions(&self) -> &[Action] {
&self.actions
}
pub fn hidden_previews_body_placeholder(&self) -> Option<&str> {
self.hidden_previews_body_placeholder.as_deref()
}
pub fn custom_dismiss_action(&self) -> bool {
self.custom_dismiss_action
}
pub fn allow_in_car_play(&self) -> bool {
self.allow_in_car_play
}
pub fn hidden_previews_show_title(&self) -> bool {
self.hidden_previews_show_title
}
pub fn hidden_previews_show_subtitle(&self) -> bool {
self.hidden_previews_show_subtitle
}
}
#[cfg(mobile)]
impl ActionTypeBuilder {
pub fn actions(mut self, actions: Vec<Action>) -> Self {
self.0.actions = actions;
self
}
pub fn hidden_previews_body_placeholder(
mut self,
hidden_previews_body_placeholder: impl Into<String>,
) -> Self {
self.0
.hidden_previews_body_placeholder
.replace(hidden_previews_body_placeholder.into());
self
}
pub fn custom_dismiss_action(mut self, custom_dismiss_action: bool) -> Self {
self.0.custom_dismiss_action = custom_dismiss_action;
self
}
pub fn allow_in_car_play(mut self, allow_in_car_play: bool) -> Self {
self.0.allow_in_car_play = allow_in_car_play;
self
}
pub fn hidden_previews_show_title(mut self, hidden_previews_show_title: bool) -> Self {
self.0.hidden_previews_show_title = hidden_previews_show_title;
self
}
pub fn hidden_previews_show_subtitle(mut self, hidden_previews_show_subtitle: bool) -> Self {
self.0.hidden_previews_show_subtitle = hidden_previews_show_subtitle;
self
}
pub fn build(self) -> ActionType {
self.0
}
}
#[cfg(mobile)]
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
@@ -423,95 +334,6 @@ pub struct Action {
input_placeholder: Option<String>,
}
#[cfg(mobile)]
#[derive(Debug)]
pub struct ActionBuilder(Action);
#[cfg(mobile)]
impl Action {
pub fn builder(id: impl Into<String>, title: impl Into<String>) -> ActionBuilder {
ActionBuilder(Self {
id: id.into(),
title: title.into(),
requires_authentication: false,
foreground: false,
destructive: false,
input: false,
input_button_title: None,
input_placeholder: None,
})
}
pub fn id(&self) -> &str {
&self.id
}
pub fn title(&self) -> &str {
&self.title
}
pub fn requires_authentication(&self) -> bool {
self.requires_authentication
}
pub fn foreground(&self) -> bool {
self.foreground
}
pub fn destructive(&self) -> bool {
self.destructive
}
pub fn input(&self) -> bool {
self.input
}
pub fn input_button_title(&self) -> Option<&str> {
self.input_button_title.as_deref()
}
pub fn input_placeholder(&self) -> Option<&str> {
self.input_placeholder.as_deref()
}
}
#[cfg(mobile)]
impl ActionBuilder {
pub fn requires_authentication(mut self, requires_authentication: bool) -> Self {
self.0.requires_authentication = requires_authentication;
self
}
pub fn foreground(mut self, foreground: bool) -> Self {
self.0.foreground = foreground;
self
}
pub fn destructive(mut self, destructive: bool) -> Self {
self.0.destructive = destructive;
self
}
pub fn input(mut self, input: bool) -> Self {
self.0.input = input;
self
}
pub fn input_button_title(mut self, input_button_title: impl Into<String>) -> Self {
self.0.input_button_title.replace(input_button_title.into());
self
}
pub fn input_placeholder(mut self, input_placeholder: impl Into<String>) -> Self {
self.0.input_placeholder.replace(input_placeholder.into());
self
}
pub fn build(self) -> Action {
self.0
}
}
#[cfg(target_os = "android")]
pub use android::*;
-2
View File
@@ -11,8 +11,6 @@ links = "tauri-plugin-opener"
# Platforms supported by the plugin
# Support levels are "full", "partial", "none", "unknown"
# Details of the support level are left to plugin maintainer
exclude = ["/guest-js", "/package.json", "/rollup.config.js", "/tsconfig.json"]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
linux = { level = "full", notes = "" }
-7
View File
@@ -8,13 +8,6 @@ license = { workspace = true }
rust-version = { workspace = true }
repository = { workspace = true }
links = "tauri-plugin-os"
exclude = [
"/banner.png",
"/guest-js",
"/package.json",
"/rollup.config.js",
"/tsconfig.json",
]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
-1
View File
@@ -7,7 +7,6 @@ license = { workspace = true }
edition = { workspace = true }
rust-version = { workspace = true }
repository = { workspace = true }
exclude = ["/banner.png"]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
+18 -21
View File
@@ -3,10 +3,6 @@
// SPDX-License-Identifier: MIT
//! Save filesystem and asset scopes and restore them when the app is reopened.
//!
//! ## Cargo features
//!
//! - **protocol-asset**: Enables `tauri`'s `protocol-asset` feature and adds support for persisting `asset://` protocol scopes.
#![doc(
html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png",
@@ -192,25 +188,25 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
if let Some(fs_scope) = &fs_scope {
if fs_scope_state_path.exists() {
let scope: Scope = std::fs::read(&fs_scope_state_path)
.map_err(Error::from)
.and_then(|scope| bincode::deserialize(&scope).map_err(Into::into))
.unwrap_or_default();
let scope: Scope = std::fs::read(&fs_scope_state_path)
.map_err(Error::from)
.and_then(|scope| bincode::deserialize(&scope).map_err(Into::into))
.unwrap_or_default();
for allowed in &scope.allowed_paths {
let allowed = fix_pattern(&ac, allowed);
allow_path(fs_scope, &allowed);
}
for forbidden in &scope.forbidden_patterns {
let forbidden = fix_pattern(&ac, forbidden);
forbid_path(fs_scope, &forbidden);
}
// Manually save the fixed scopes to disk once.
// This is needed to fix broken .peristed-scope files in case the app doesn't update the scope itself.
save_scopes(fs_scope, &app_dir, &fs_scope_state_path);
for allowed in &scope.allowed_paths {
let allowed = fix_pattern(&ac, allowed);
allow_path(fs_scope, &allowed);
}
for forbidden in &scope.forbidden_patterns {
let forbidden = fix_pattern(&ac, forbidden);
forbid_path(fs_scope, &forbidden);
}
// Manually save the fixed scopes to disk once.
// This is needed to fix broken .peristed-scope files in case the app doesn't update the scope itself.
save_scopes(fs_scope, &app_dir, &fs_scope_state_path);
}
}
#[cfg(feature = "protocol-asset")]
if asset_scope_state_path.exists() {
@@ -236,9 +232,10 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
let app_dir_ = app_dir.clone();
if let Some(fs_scope) = &fs_scope {
let app_ = app.clone();
fs_scope.listen(move |event| {
if let tauri::fs::Event::PathAllowed(_) = event {
save_scopes(&app.fs_scope(), &app_dir, &fs_scope_state_path);
save_scopes(&app_.fs_scope(), &app_dir, &fs_scope_state_path);
}
});
}

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