Compare commits

..

63 Commits

Author SHA1 Message Date
github-actions[bot] b40a02c525 publish new versions (#2477)
Co-authored-by: FabianLars <30730186+FabianLars@users.noreply.github.com>
2025-03-10 14:17:57 +01:00
Fabian-Lars a1b3fa27f1 fix: Re-export api structs (#2515)
* fix: Re-export api structs

* whoops
2025-03-10 13:57:17 +01:00
Tony e54cfcb261 fix(updater): should be log::debug not println (#2514) 2025-03-10 02:59:19 +02:00
renovate[bot] 22ba197b80 chore(deps): update eslint monorepo to v9.22.0 (#2508)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-09 10:42:49 +08:00
renovate[bot] 77520a3587 chore(deps): update dependency rollup to v4.35.0 (#2511)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-09 10:33:37 +08:00
renovate[bot] dbc5fe120a chore(deps): update dependency eslint-config-prettier to v10.1.1 (#2503)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-09 10:33:15 +08:00
Guilherme Oenning faefcc9fd8 feat(updater): add configure_client to UpdaterBuilder (#2430) 2025-03-09 03:53:16 +02:00
Lucas Fernandes Nogueira ac60d589ec feat(updater): improve tracing and error logging (#2513) 2025-03-09 03:24:45 +02:00
Adriel Jansen Siahaya cb38f54f4a HTTP add stream support (#2479)
* feat: add stream support

* feat: add stream support

* Revert "feat: add stream support"

This reverts commit 5edea81680.

* feat: add stream support

* Discard changes to pnpm-lock.yaml

* Discard changes to plugins/http/package.json

* fix(stream): change IPC packet

* fix: update stream message guest-js

* fix: return early when aborted

* fix: use InvokeResponseBody as packet

* fix: remove serde_bytes

* fix: remove reqwest response

* fix: content conversion bug

* fix: remove ReqwestResponses along with its implementations

* formatting and update changelog

* build api-iife.js

---------

Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-03-08 15:45:05 -03:00
Clément Fouré d37bbdef8d fix(clipboard-manager): Wayland support (#2507)
* fix(clipboard-manager): Wayland support

* style(deps): merge dependencies declaration
2025-03-07 19:53:14 +01:00
Khoshbin Ali Ahmed 3a750c7300 docs(clipboard): Fixed typo from rbga to rgba (#2499) 2025-03-06 21:28:28 +01:00
renovate[bot] 5c9cf52e75 chore(deps): update dependency typescript-eslint to v8.26.0 (#2488)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-04 10:26:23 +01:00
Tony 02df0421d6 chore(deps): update openssl in lock file (#2484) 2025-03-03 09:08:29 +01:00
Tony f7f5bbf259 Ignore vscode settings.json and tasks.json (#2482) 2025-03-03 04:39:43 +02:00
renovate[bot] 561cf39f64 chore(deps): update dependency prettier to v3.5.3 (#2480)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-03 10:06:03 +08:00
Jim 024815018f feat(log): Add skip_logger setting (#2377) 2025-03-01 16:20:18 +01:00
FabianLars e90cd9fab1 ci: Use upstream create-pull-request version 2025-03-01 14:55:23 +01:00
FabianLars 1b86af8e26 chore(deps): Small lockfile update for deduplication purposes. 2025-03-01 14:27:53 +01:00
renovate[bot] 1dba334f00 chore(deps): update dependency rollup to v4.34.9 (#2474)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-01 12:31:09 +01:00
renovate[bot] 54e7864507 chore(deps): update dependency typescript to v5.8.2 (#2472)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-01 19:03:25 +08:00
renovate[bot] 45c7848714 chore(deps): update dependency @tauri-apps/cli to v2.3.1 (#2470)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-01 11:56:59 +01:00
github-actions[bot] 393e956728 publish new versions (#2468)
Co-authored-by: FabianLars <FabianLars@users.noreply.github.com>
2025-02-27 23:57:29 +01:00
Fabian-Lars 1a9846599b chore(deps): Update objc2 to 0.6 (#2469) 2025-02-27 15:24:18 +01:00
renovate[bot] 71f95c9f05 chore(deps): update rust crate windows to 0.60 (v2) (#2445)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <github@fabianlars.de>
2025-02-27 11:45:55 +01:00
Tony 8b3cd9e827 chore(deps): update tauri to 2.3 (#2466) 2025-02-27 10:18:15 +01:00
Tony 39c022eea2 chore(deps): update js dependencies (#2467)
* chore(deps): update js dependencies

* Bump pnpm version in github actions
2025-02-27 05:24:53 +02:00
renovate[bot] 7527a3465a chore(deps): update dependency eslint-config-prettier to v10.0.2 (#2463)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-27 09:32:33 +08:00
renovate[bot] abca2ebc0d chore(deps): update tauri monorepo to v2.3.0 (v2) (#2465)
* chore(deps): update tauri monorepo to v2.3.0

* Regenerate window-state api-iife

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
2025-02-27 09:19:05 +08:00
renovate[bot] ddcfad46f9 chore(deps): update dependency typescript-eslint to v8.25.0 (#2459)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-25 11:31:58 +08:00
github-actions[bot] fbd4d28920 publish new versions (#2404)
Co-authored-by: amrbashir <amrbashir@users.noreply.github.com>
2025-02-24 16:31:28 +01:00
Amr Bashir 0af367f7d4 refactor(single-instance): improve userdata ptr handling (#2453)
* fix(single-instance): fix null pointer dereference panic on Windows

* fmt
2025-02-24 17:10:30 +02:00
Fabian-Lars 1ab5f15763 fix(single-instance): check if pointer is null (#2452) 2025-02-23 19:25:00 +02:00
renovate[bot] c10d5bfb54 chore(deps): update rust crate infer to 0.19 (v2) (#2385)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <github@fabianlars.de>
2025-02-23 13:22:51 +01:00
renovate[bot] f6838d507f chore(deps): update dependency @types/eslint__js to v9 (v2) (#2447)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <github@fabianlars.de>
2025-02-22 23:12:38 +01:00
renovate[bot] 5b3a1aaf73 chore(deps): update rust crate color-backtrace to 0.7 (#2409)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-22 22:35:05 +01:00
renovate[bot] 3276d65801 chore(deps): update rust crate windows-registry to 0.5 (#2446)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-22 18:31:57 +01:00
renovate[bot] e0900f0451 chore(deps): update eslint monorepo to v9.21.0 (#2402)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-22 17:40:04 +01:00
renovate[bot] 4d38066ef9 chore(deps): update unocss monorepo to v66 (#2436)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-22 17:37:09 +01:00
renovate[bot] 3b37ce1508 chore(deps): update dependency prettier to v3.5.2 (#2444)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-22 23:37:35 +08:00
Fabian-Lars 6f881293fc fix(updater): Propagate request error (#2439) 2025-02-20 11:47:37 +01:00
renovate[bot] 9229f991fe chore(deps): update dependency typescript-eslint to v8.24.1 (#2435)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-18 09:20:26 +08:00
renovate[bot] b3bf74212e chore(deps): update dependency rollup to v4.34.8 (#2433)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-17 19:12:19 +08:00
Tony c5da9d2579 chore: update prettier to 3.5.1 and enable experimentalOperatorPosition (#2427) 2025-02-16 10:36:53 +08:00
Tony 7a5495963b Check for generated files on pnpm lock changed (#2429) 2025-02-15 22:47:28 +08:00
Tony 7d3869ced8 Regenerate api-iife (#2428) 2025-02-15 15:10:23 +02:00
renovate[bot] fa8c544479 chore(deps): update dependency typescript-eslint to v8.24.0 (#2412)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-15 10:35:37 +08:00
renovate[bot] 14660b6230 chore(deps): update dependency rollup to v4.34.7 (#2420)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-15 10:20:15 +08:00
Seishiin 6b4c391738 fix(log): timezone_strategy overwriting LogLevels (#2401) 2025-02-08 09:41:34 +08:00
renovate[bot] d5d9f7c970 chore(deps): update dependency rollup to v4.34.6 (v2) (#2399)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-07 18:43:37 +01:00
renovate[bot] 63f9449c9a chore(deps): update dependency rollup to v4.34.4 (v2) (#2396)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-06 11:33:40 +01:00
renovate[bot] e0cff9bcf4 chore(deps): update dependency rollup to v4.34.2 (v2) (#2394)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-04 19:58:00 +01:00
Dominic Moser 5411db68a8 docs(haptics): Include permissions in readme (#2395)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-02-04 19:50:50 +01:00
github-actions[bot] 80804adc68 publish new versions (#2380)
Co-authored-by: Legend-Master <Legend-Master@users.noreply.github.com>
2025-02-04 07:27:53 -03:00
renovate[bot] 93edbd1434 chore(deps): update dependency typescript-eslint to v8.23.0 (#2390)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-04 08:45:25 +08:00
dependabot[bot] 3ebec74983 chore(deps): bump openssl from 0.10.66 to 0.10.70 in /plugins/updater/tests/updater-migration/v1-app (#2392)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-03 21:31:13 +01:00
renovate[bot] 51f5aff58a chore(deps): update dependency rollup to v4.34.1 (#2388)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-03 21:35:03 +08:00
jLynx 5369898db7 fix(macOS): Tauri V2 Update Permission Denied Error (#2067)
* WIP

* Fixed linting

* WIP

* Fixed linting

* use osakit to show actual app name on dialog

* sync versions

* lint

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-02-02 17:54:09 -03:00
renovate[bot] a7497b0aeb chore(deps): update rust crate gethostname to v1 (v2) (#2382)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-01 11:47:53 +01:00
renovate[bot] aaa88fa45f chore(deps): update dependency rollup to v4.34.0 (v2) (#2381)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-01 11:47:09 +01:00
Fabian-Lars ca7395a5ce fix(upload): Enable reqwest's rustls-tls feature by default (#2378) 2025-02-01 11:17:22 +01:00
renovate[bot] 6ae853c2e6 chore(deps): update dependency rollup to v4.32.1 (v2) (#2373)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-28 13:42:36 +01:00
renovate[bot] d5fb5337a0 chore(deps): update rust crate dirs to v6 (v2) (#2311)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <github@fabianlars.de>
2025-01-27 22:16:22 +01:00
renovate[bot] 512a188c7a chore(deps): update dependency typescript-eslint to v8.22.0 (v2) (#2363)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-27 20:09:10 +01:00
100 changed files with 2031 additions and 1864 deletions
+1 -1
View File
@@ -46,7 +46,7 @@ jobs:
node-version: 'lts/*'
- uses: pnpm/action-setup@v4
with:
version: 9.x.x
version: 10.x.x
run_install: true
- name: audit
run: pnpm audit
+25 -1
View File
@@ -8,6 +8,7 @@ on:
pull_request:
paths:
- '.github/workflows/check-generated-files.yml'
- pnpm-lock.yaml
- '**/guest-js/**'
concurrency:
@@ -27,94 +28,117 @@ jobs:
filters: |
autostart:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/autostart/guest-js/**
- plugins/autostart/src/api-iife.js
cli:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/cli/guest-js/**
- plugins/cli/src/api-iife.js
clipboard-manager:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/clipboard-manager/guest-js/**
- plugins/clipboard-manager/src/api-iife.js
dialog:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/dialog/guest-js/**
- plugins/dialog/src/api-iife.js
fs:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/fs/guest-js/**
- plugins/fs/src/api-iife.js
geolocation:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/geolocation/guest-js/**
- plugins/geolocation/src/api-iife.js
global-shortcut:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/global-shortcut/guest-js/**
- plugins/global-shortcut/src/api-iife.js
opener:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/opener/guest-js/**
- plugins/opener/src/api-iife.js
haptics:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/haptics/guest-js/**
- plugins/haptics/src/api-iife.js
http:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/http/guest-js/**
- plugins/http/src/api-iife.js
log:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/log/guest-js/**
- plugins/log/src/api-iife.js
notification:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/notification/guest-js/**
- plugins/notification/src/api-iife.js
os:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/os/guest-js/**
- plugins/os/src/api-iife.js
positioner:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/positioner/guest-js/**
- plugins/positioner/src/api-iife.js
process:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/process/guest-js/**
- plugins/process/src/api-iife.js
shell:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/shell/guest-js/**
- plugins/shell/src/api-iife.js
sql:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/sql/guest-js/**
- plugins/sql/src/api-iife.js
store:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/store/guest-js/**
- plugins/store/src/api-iife.js
stronghold:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/stronghold/guest-js/**
- plugins/stronghold/src/api-iife.js
updater:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/updater/guest-js/**
- plugins/updater/src/api-iife.js
upload:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/upload/guest-js/**
- plugins/upload/src/api-iife.js
websocket:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/websocket/guest-js/**
- plugins/websocket/src/api-iife.js
window-state:
- .github/workflows/check-generated-files.yml
- pnpm-lock.yaml
- plugins/window-state/guest-js/**
- plugins/window-state/src/api-iife.js
@@ -143,7 +167,7 @@ jobs:
node-version: 'lts/*'
- uses: pnpm/action-setup@v4
with:
version: 9.x.x
version: 10.x.x
run_install: true
- name: build api
@@ -39,7 +39,7 @@ jobs:
- uses: pnpm/action-setup@v4
with:
version: 9.x.x
version: 10.x.x
run_install: true
- name: cargo login
@@ -75,7 +75,7 @@ jobs:
- name: Create Pull Request With Versions Bumped
id: cpr
uses: tauri-apps/create-pull-request@v3
uses: peter-evans/create-pull-request@dd2324fc52d5d43c699a5636bcf19fceaa70c284 # 7.0.7
if: steps.covector.outputs.commandRan == 'version'
with:
title: 'Publish New Versions (${{ github.ref_name }})'
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
node-version: 'lts/*'
- uses: pnpm/action-setup@v4
with:
version: 9.x.x
version: 10.x.x
run_install: true
- run: pnpm format:check
+1 -1
View File
@@ -49,7 +49,7 @@ jobs:
node-version: 'lts/*'
- uses: pnpm/action-setup@v4
with:
version: 9.x.x
version: 10.x.x
run_install: true
- name: eslint
run: pnpm lint
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
- uses: pnpm/action-setup@v4
with:
version: 9.x.x
version: 10.x.x
run_install: true
- name: Build packages
+2
View File
@@ -14,6 +14,8 @@ target/
# .vscode workspace settings file
.vscode/settings.json
.vscode/launch.json
.vscode/tasks.json
# npm, yarn and bun lock files
package-lock.json
+2 -1
View File
@@ -1,5 +1,6 @@
{
"singleQuote": true,
"semi": false,
"trailingComma": "none"
"trailingComma": "none",
"experimentalOperatorPosition": "start"
}
+6 -6
View File
@@ -32,8 +32,8 @@ const ignore = [
async function checkFile(file) {
if (
extensions.some((e) => file.endsWith(e)) &&
!ignore.some((i) => file.includes(`${path.sep}${i}`))
extensions.some((e) => file.endsWith(e))
&& !ignore.some((i) => file.includes(`${path.sep}${i}`))
) {
const fileStream = fs.createReadStream(file)
const rl = readline.createInterface({
@@ -46,10 +46,10 @@ async function checkFile(file) {
for await (let line of rl) {
// ignore empty lines, allow shebang, swift-tools-version and bundler license
if (
line.length === 0 ||
line.startsWith('#!') ||
line.startsWith('// swift-tools-version:') ||
ignoredLicenses.includes(line)
line.length === 0
|| line.startsWith('#!')
|| line.startsWith('// swift-tools-version:')
|| ignoredLicenses.includes(line)
) {
continue
}
Generated
+507 -386
View File
File diff suppressed because it is too large Load Diff
+31
View File
@@ -1,5 +1,36 @@
# Changelog
## \[2.0.16]
### Dependencies
- Upgraded to `clipboard-manager-js@2.2.2`
- Upgraded to `notification-js@2.2.2`
- Upgraded to `os-js@2.2.1`
- Upgraded to `http-js@2.4.0`
- Upgraded to `log-js@2.3.0`
- Upgraded to `updater-js@2.6.0`
## \[2.0.15]
### Dependencies
- Upgraded to `log-js@2.2.3`
- Upgraded to `opener-js@2.2.6`
## \[2.0.14]
### Dependencies
- Upgraded to `log-js@2.2.2`
- Upgraded to `updater-js@2.5.1`
## \[2.0.13]
### Dependencies
- Upgraded to `updater-js@2.5.0`
## \[2.0.12]
### Dependencies
+16 -16
View File
@@ -1,7 +1,7 @@
{
"name": "api",
"private": true,
"version": "2.0.12",
"version": "2.0.16",
"type": "module",
"scripts": {
"dev": "vite --clearScreen false",
@@ -10,35 +10,35 @@
"tauri": "tauri"
},
"dependencies": {
"@tauri-apps/api": "2.2.0",
"@tauri-apps/api": "2.3.0",
"@tauri-apps/plugin-barcode-scanner": "^2.2.0",
"@tauri-apps/plugin-biometric": "^2.2.0",
"@tauri-apps/plugin-cli": "^2.2.0",
"@tauri-apps/plugin-clipboard-manager": "^2.2.1",
"@tauri-apps/plugin-clipboard-manager": "^2.2.2",
"@tauri-apps/plugin-dialog": "^2.2.0",
"@tauri-apps/plugin-fs": "^2.2.0",
"@tauri-apps/plugin-geolocation": "^2.2.0",
"@tauri-apps/plugin-global-shortcut": "^2.2.0",
"@tauri-apps/plugin-opener": "^2.2.5",
"@tauri-apps/plugin-haptics": "^2.2.0",
"@tauri-apps/plugin-http": "^2.3.0",
"@tauri-apps/plugin-http": "^2.4.0",
"@tauri-apps/plugin-nfc": "^2.2.0",
"@tauri-apps/plugin-notification": "^2.2.1",
"@tauri-apps/plugin-os": "^2.2.0",
"@tauri-apps/plugin-notification": "^2.2.2",
"@tauri-apps/plugin-opener": "^2.2.6",
"@tauri-apps/plugin-os": "^2.2.1",
"@tauri-apps/plugin-process": "^2.2.0",
"@tauri-apps/plugin-shell": "^2.2.0",
"@tauri-apps/plugin-store": "^2.2.0",
"@tauri-apps/plugin-updater": "^2.4.0",
"@tauri-apps/plugin-updater": "^2.6.0",
"@zerodevx/svelte-json-view": "1.0.11"
},
"devDependencies": {
"@iconify-json/codicon": "^1.2.6",
"@iconify-json/ph": "^1.2.1",
"@sveltejs/vite-plugin-svelte": "^5.0.1",
"@tauri-apps/cli": "2.2.7",
"@unocss/extractor-svelte": "^65.0.0",
"svelte": "^5.10.0",
"unocss": "^65.0.0",
"vite": "^6.0.3"
"@iconify-json/codicon": "^1.2.12",
"@iconify-json/ph": "^1.2.2",
"@sveltejs/vite-plugin-svelte": "^5.0.3",
"@tauri-apps/cli": "2.3.1",
"@unocss/extractor-svelte": "^66.0.0",
"svelte": "^5.20.4",
"unocss": "^66.0.0",
"vite": "^6.2.0"
}
}
+33
View File
@@ -1,5 +1,38 @@
# Changelog
## \[2.0.20]
### Dependencies
- Upgraded to `clipboard-manager@2.2.2`
- Upgraded to `geolocation@2.2.4`
- Upgraded to `haptics@2.2.4`
- Upgraded to `notification@2.2.2`
- Upgraded to `os@2.2.1`
- Upgraded to `http@2.4.0`
- Upgraded to `log@2.3.0`
- Upgraded to `updater@2.6.0`
## \[2.0.19]
### Dependencies
- Upgraded to `log@2.2.3`
- Upgraded to `opener@2.2.6`
## \[2.0.18]
### Dependencies
- Upgraded to `log@2.2.2`
- Upgraded to `updater@2.5.1`
## \[2.0.17]
### Dependencies
- Upgraded to `updater@2.5.0`
## \[2.0.16]
### Dependencies
+10 -10
View File
@@ -1,7 +1,7 @@
[package]
name = "api"
publish = false
version = "2.0.16"
version = "2.0.20"
description = "An example Tauri Application showcasing the api"
edition = "2021"
rust-version = { workspace = true }
@@ -19,21 +19,21 @@ serde_json = { workspace = true }
serde = { workspace = true }
tiny_http = "0.12"
log = { workspace = true }
tauri-plugin-log = { path = "../../../plugins/log", version = "2.2.1" }
tauri-plugin-log = { path = "../../../plugins/log", version = "2.3.0" }
tauri-plugin-fs = { path = "../../../plugins/fs", version = "2.2.0", features = [
"watch",
] }
tauri-plugin-clipboard-manager = { path = "../../../plugins/clipboard-manager", version = "2.2.1" }
tauri-plugin-clipboard-manager = { path = "../../../plugins/clipboard-manager", version = "2.2.2" }
tauri-plugin-dialog = { path = "../../../plugins/dialog", version = "2.2.0" }
tauri-plugin-http = { path = "../../../plugins/http", features = [
"multipart",
], version = "2.3.0" }
tauri-plugin-notification = { path = "../../../plugins/notification", version = "2.2.1", features = [
], version = "2.4.0" }
tauri-plugin-notification = { path = "../../../plugins/notification", version = "2.2.2", features = [
"windows7-compat",
] }
tauri-plugin-os = { path = "../../../plugins/os", version = "2.2.0" }
tauri-plugin-os = { path = "../../../plugins/os", version = "2.2.1" }
tauri-plugin-process = { path = "../../../plugins/process", version = "2.2.0" }
tauri-plugin-opener = { path = "../../../plugins/opener", version = "2.2.5" }
tauri-plugin-opener = { path = "../../../plugins/opener", version = "2.2.6" }
tauri-plugin-shell = { path = "../../../plugins/shell", version = "2.2.0" }
tauri-plugin-store = { path = "../../../plugins/store", version = "2.2.0" }
@@ -53,15 +53,15 @@ features = [
[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
tauri-plugin-cli = { path = "../../../plugins/cli", version = "2.2.0" }
tauri-plugin-global-shortcut = { path = "../../../plugins/global-shortcut", version = "2.2.0" }
tauri-plugin-updater = { path = "../../../plugins/updater", version = "2.4.0" }
tauri-plugin-updater = { path = "../../../plugins/updater", version = "2.6.0" }
tauri-plugin-window-state = { path = "../../../plugins/window-state", version = "2.2.0" }
[target."cfg(any(target_os = \"android\", target_os = \"ios\"))".dependencies]
tauri-plugin-barcode-scanner = { path = "../../../plugins/barcode-scanner/", version = "2.2.0" }
tauri-plugin-nfc = { path = "../../../plugins/nfc", version = "2.2.0" }
tauri-plugin-biometric = { path = "../../../plugins/biometric/", version = "2.2.0" }
tauri-plugin-geolocation = { path = "../../../plugins/geolocation/", version = "2.2.3" }
tauri-plugin-haptics = { path = "../../../plugins/haptics/", version = "2.2.3" }
tauri-plugin-geolocation = { path = "../../../plugins/geolocation/", version = "2.2.4" }
tauri-plugin-haptics = { path = "../../../plugins/haptics/", version = "2.2.4" }
[features]
prod = ["tauri/custom-protocol"]
+17 -14
View File
@@ -11,26 +11,29 @@
"example:api:dev": "pnpm run --filter \"api\" tauri dev"
},
"devDependencies": {
"@eslint/js": "9.19.0",
"@eslint/js": "9.22.0",
"@rollup/plugin-node-resolve": "16.0.0",
"@rollup/plugin-terser": "0.4.4",
"@rollup/plugin-typescript": "11.1.6",
"@types/eslint__js": "8.42.3",
"covector": "^0.12.3",
"eslint": "9.19.0",
"eslint-config-prettier": "10.0.1",
"@rollup/plugin-typescript": "12.1.2",
"covector": "^0.12.4",
"eslint": "9.22.0",
"eslint-config-prettier": "10.1.1",
"eslint-plugin-security": "3.0.1",
"prettier": "3.4.2",
"rollup": "4.32.0",
"prettier": "3.5.3",
"rollup": "4.35.0",
"tslib": "2.8.1",
"typescript": "5.7.3",
"typescript-eslint": "8.21.0"
"typescript": "5.8.2",
"typescript-eslint": "8.26.0"
},
"resolutions": {
"semver": ">=7.5.2",
"optionator": ">=0.9.3"
"pnpm": {
"overrides": {
"esbuild@<0.25.0": ">=0.25.0"
},
"onlyBuiltDependencies": [
"esbuild"
]
},
"engines": {
"pnpm": "^9.0.0"
"pnpm": "^10.0.0"
}
}
+6
View File
@@ -1,5 +1,11 @@
# Changelog
## \[2.2.2]
### bug
- [`d37bbdef`](https://github.com/tauri-apps/plugins-workspace/commit/d37bbdef8dc70e61e59f9fe0bb8b2a48999d0aa1) ([#2507](https://github.com/tauri-apps/plugins-workspace/pull/2507) by [@SquitchYT](https://github.com/tauri-apps/plugins-workspace/../../SquitchYT)) Fix clipboard-manager Wayland support.
## \[2.2.1]
- [`ce11079f`](https://github.com/tauri-apps/plugins-workspace/commit/ce11079f19852fbefdecf0e4c7d947af3624fee0) ([#2280](https://github.com/tauri-apps/plugins-workspace/pull/2280) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Explicitly drop `arboard::Clipboard` on exit. Add recommendation to not use read methods on the mainthread.
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-clipboard-manager"
version = "2.2.1"
version = "2.2.2"
description = "Read and write to the system clipboard."
edition = { workspace = true }
authors = { workspace = true }
@@ -36,4 +36,4 @@ thiserror = { workspace = true }
tauri = { workspace = true, features = ["wry"] }
[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
arboard = "3"
arboard = { version = "3", features = ["wayland-data-control"] }
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_CLIPBOARD_MANAGER__=function(e){"use strict";var t;async function r(e,t={},r){return window.__TAURI_INTERNALS__.invoke(e,t,r)}"function"==typeof SuppressedError&&SuppressedError;class n{get rid(){return function(e,t,r,n){if("a"===r&&!n)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!n:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?n:"a"===r?n.call(e):n?n.value:t.get(e)}(this,t,"f")}constructor(e){t.set(this,void 0),function(e,t,r){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");t.set(e,r)}(this,t,e)}async close(){return r("plugin:resources|close",{rid:this.rid})}}t=new WeakMap;class a extends n{constructor(e){super(e)}static async new(e,t,n){return r("plugin:image|new",{rgba:i(e),width:t,height:n}).then((e=>new a(e)))}static async fromBytes(e){return r("plugin:image|from_bytes",{bytes:i(e)}).then((e=>new a(e)))}static async fromPath(e){return r("plugin:image|from_path",{path:e}).then((e=>new a(e)))}async rgba(){return r("plugin:image|rgba",{rid:this.rid}).then((e=>new Uint8Array(e)))}async size(){return r("plugin:image|size",{rid:this.rid})}}function i(e){return null==e?null:"string"==typeof e?e:e instanceof a?e.rid:e}return e.clear=async function(){await r("plugin:clipboard-manager|clear")},e.readImage=async function(){return await r("plugin:clipboard-manager|read_image").then((e=>new a(e)))},e.readText=async function(){return await r("plugin:clipboard-manager|read_text")},e.writeHtml=async function(e,t){await r("plugin:clipboard-manager|write_html",{html:e,altText:t})},e.writeImage=async function(e){await r("plugin:clipboard-manager|write_image",{image:i(e)})},e.writeText=async function(e,t){await r("plugin:clipboard-manager|write_text",{label:t?.label,text:e})},e}({});Object.defineProperty(window.__TAURI__,"clipboardManager",{value:__TAURI_PLUGIN_CLIPBOARD_MANAGER__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_CLIPBOARD_MANAGER__=function(e){"use strict";var n;async function t(e,n={},t){return window.__TAURI_INTERNALS__.invoke(e,n,t)}"function"==typeof SuppressedError&&SuppressedError;class r{get rid(){return function(e,n,t,r){if("function"==typeof n||!n.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===t?r:"a"===t?r.call(e):r?r.value:n.get(e)}(this,n,"f")}constructor(e){n.set(this,void 0),function(e,n,t){if("function"==typeof n||!n.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");n.set(e,t)}(this,n,e)}async close(){return t("plugin:resources|close",{rid:this.rid})}}n=new WeakMap;class a extends r{constructor(e){super(e)}static async new(e,n,r){return t("plugin:image|new",{rgba:i(e),width:n,height:r}).then((e=>new a(e)))}static async fromBytes(e){return t("plugin:image|from_bytes",{bytes:i(e)}).then((e=>new a(e)))}static async fromPath(e){return t("plugin:image|from_path",{path:e}).then((e=>new a(e)))}async rgba(){return t("plugin:image|rgba",{rid:this.rid}).then((e=>new Uint8Array(e)))}async size(){return t("plugin:image|size",{rid:this.rid})}}function i(e){return null==e?null:"string"==typeof e?e:e instanceof a?e.rid:e}return e.clear=async function(){await t("plugin:clipboard-manager|clear")},e.readImage=async function(){return await t("plugin:clipboard-manager|read_image").then((e=>new a(e)))},e.readText=async function(){return await t("plugin:clipboard-manager|read_text")},e.writeHtml=async function(e,n){await t("plugin:clipboard-manager|write_html",{html:e,altText:n})},e.writeImage=async function(e){await t("plugin:clipboard-manager|write_image",{image:i(e)})},e.writeText=async function(e,n){await t("plugin:clipboard-manager|write_text",{label:n?.label,text:e})},e}({});Object.defineProperty(window.__TAURI__,"clipboardManager",{value:__TAURI_PLUGIN_CLIPBOARD_MANAGER__})}
+1 -1
View File
@@ -91,7 +91,7 @@ async function writeImage(
* import { readImage } from '@tauri-apps/plugin-clipboard-manager';
*
* const clipboardImage = await readImage();
* const blob = new Blob([await clipboardImage.rbga()], { type: 'image' })
* const blob = new Blob([await clipboardImage.rgba()], { type: 'image' })
* const url = URL.createObjectURL(blob)
* ```
* @since 2.0.0
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-clipboard-manager",
"version": "2.2.1",
"version": "2.2.2",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
+1 -1
View File
@@ -38,7 +38,7 @@ url = { workspace = true }
[target."cfg(windows)".dependencies]
dunce = "1"
windows-registry = "0.4"
windows-registry = "0.5"
windows-result = "0.3"
[target."cfg(target_os = \"linux\")".dependencies]
+4 -4
View File
@@ -10,12 +10,12 @@
"tauri": "tauri"
},
"dependencies": {
"@tauri-apps/api": "2.2.0",
"@tauri-apps/api": "2.3.0",
"@tauri-apps/plugin-deep-link": "2.2.0"
},
"devDependencies": {
"@tauri-apps/cli": "2.2.7",
"typescript": "^5.2.2",
"vite": "^6.0.0"
"@tauri-apps/cli": "2.3.1",
"typescript": "^5.7.3",
"vite": "^6.2.0"
}
}
+3 -6
View File
@@ -265,18 +265,15 @@ mod imp {
.to_string();
let key_reg = CURRENT_USER.create(&key_base)?;
key_reg.set_string(
"",
&format!("URL:{} protocol", self.app.config().identifier),
)?;
key_reg.set_string("", format!("URL:{} protocol", self.app.config().identifier))?;
key_reg.set_string("URL Protocol", "")?;
let icon_reg = CURRENT_USER.create(format!("{key_base}\\DefaultIcon"))?;
icon_reg.set_string("", &format!("{exe},0"))?;
icon_reg.set_string("", format!("{exe},0"))?;
let cmd_reg = CURRENT_USER.create(format!("{key_base}\\shell\\open\\command"))?;
cmd_reg.set_string("", &format!("\"{exe}\" \"%1\""))?;
cmd_reg.set_string("", format!("\"{exe}\" \"%1\""))?;
Ok(())
}
File diff suppressed because one or more lines are too long
+4 -4
View File
@@ -604,8 +604,8 @@ async function copyFile(
options?: CopyFileOptions
): Promise<void> {
if (
(fromPath instanceof URL && fromPath.protocol !== 'file:') ||
(toPath instanceof URL && toPath.protocol !== 'file:')
(fromPath instanceof URL && fromPath.protocol !== 'file:')
|| (toPath instanceof URL && toPath.protocol !== 'file:')
) {
throw new TypeError('Must be a file URL.')
}
@@ -919,8 +919,8 @@ async function rename(
options?: RenameOptions
): Promise<void> {
if (
(oldPath instanceof URL && oldPath.protocol !== 'file:') ||
(newPath instanceof URL && newPath.protocol !== 'file:')
(oldPath instanceof URL && oldPath.protocol !== 'file:')
|| (newPath instanceof URL && newPath.protocol !== 'file:')
) {
throw new TypeError('Must be a file URL.')
}
+2 -8
View File
@@ -53,10 +53,7 @@ impl FilePath {
#[inline]
pub fn into_path(self) -> Result<PathBuf> {
match self {
Self::Url(url) => url
.to_file_path()
.map(PathBuf::from)
.map_err(|_| Error::InvalidPathUrl),
Self::Url(url) => url.to_file_path().map_err(|_| Error::InvalidPathUrl),
Self::Path(p) => Ok(p),
}
}
@@ -91,10 +88,7 @@ impl SafeFilePath {
#[inline]
pub fn into_path(self) -> Result<PathBuf> {
match self {
Self::Url(url) => url
.to_file_path()
.map(PathBuf::from)
.map_err(|_| Error::InvalidPathUrl),
Self::Url(url) => url.to_file_path().map_err(|_| Error::InvalidPathUrl),
Self::Path(p) => Ok(p.as_ref().to_owned()),
}
}
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.2.4]
- [`a1b3fa27`](https://github.com/tauri-apps/plugins-workspace/commit/a1b3fa27f11022c9b6622b4fab12d93239eb05de) ([#2515](https://github.com/tauri-apps/plugins-workspace/pull/2515) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Re-exported the `Geolocation`, `Haptics`, `Notification`, and `Os` structs so that they show up on docs.rs.
## \[2.2.3]
- [`406e6f48`](https://github.com/tauri-apps/plugins-workspace/commit/406e6f484cdc13d35c50fb949f7489ca9eeccc44) ([#2323](https://github.com/tauri-apps/plugins-workspace/pull/2323) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Fixed an issue that caused build failures when the `haptics` or `geolocation` plugin was used without their `specta` feature flag enabled.
+1 -1
View File
@@ -1,7 +1,7 @@
[package]
name = "tauri-plugin-geolocation"
description = "Get and track the device's current position"
version = "2.2.3"
version = "2.2.4"
edition = { workspace = true }
authors = { workspace = true }
license = { workspace = true }
+2 -2
View File
@@ -118,8 +118,8 @@ import {
let permissions = await checkPermissions()
if (
permissions.location === 'prompt' ||
permissions.location === 'prompt-with-rationale'
permissions.location === 'prompt'
|| permissions.location === 'prompt-with-rationale'
) {
permissions = await requestPermissions(['location'])
}
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_GEOLOCATION__=function(t){"use strict";function n(t,n,e,i){if("a"===e&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof n?t!==n||!i:!n.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===e?i:"a"===e?i.call(t):i?i.value:n.get(t)}function e(t,n,e,i,s){if("function"==typeof n||!n.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return n.set(t,e),e}var i,s,o;"function"==typeof SuppressedError&&SuppressedError;const r="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),s.set(this,0),o.set(this,[]),this.id=function(t,n=!1){return window.__TAURI_INTERNALS__.transformCallback(t,n)}((({message:t,id:r})=>{if(r==n(this,s,"f"))for(n(this,i,"f").call(this,t),e(this,s,n(this,s,"f")+1);n(this,s,"f")in n(this,o,"f");){const t=n(this,o,"f")[n(this,s,"f")];n(this,i,"f").call(this,t),delete n(this,o,"f")[n(this,s,"f")],e(this,s,n(this,s,"f")+1)}else n(this,o,"f")[r]=t}))}set onmessage(t){e(this,i,t)}get onmessage(){return n(this,i,"f")}[(i=new WeakMap,s=new WeakMap,o=new WeakMap,r)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[r]()}}async function c(t,n={},e){return window.__TAURI_INTERNALS__.invoke(t,n,e)}return t.checkPermissions=async function(){return await async function(t){return c(`plugin:${t}|check_permissions`)}("geolocation")},t.clearWatch=async function(t){await c("plugin:geolocation|clear_watch",{channelId:t})},t.getCurrentPosition=async function(t){return await c("plugin:geolocation|get_current_position",{options:t})},t.requestPermissions=async function(t){return await c("plugin:geolocation|request_permissions",{permissions:t})},t.watchPosition=async function(t,n){const e=new a;return e.onmessage=t=>{"string"==typeof t?n(null,t):n(t)},await c("plugin:geolocation|watch_position",{options:t,channel:e}),e.id},t}({});Object.defineProperty(window.__TAURI__,"geolocation",{value:__TAURI_PLUGIN_GEOLOCATION__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_GEOLOCATION__=function(t){"use strict";function n(t,n,e,i){if("function"==typeof n||!n.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===e?i:"a"===e?i.call(t):i?i.value:n.get(t)}function e(t,n,e,i,s){if("function"==typeof n||!n.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return n.set(t,e),e}var i,s,o;"function"==typeof SuppressedError&&SuppressedError;const r="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),s.set(this,0),o.set(this,[]),this.id=function(t,n=!1){return window.__TAURI_INTERNALS__.transformCallback(t,n)}((({message:t,id:r})=>{if(r==n(this,s,"f"))for(n(this,i,"f").call(this,t),e(this,s,n(this,s,"f")+1);n(this,s,"f")in n(this,o,"f");){const t=n(this,o,"f")[n(this,s,"f")];n(this,i,"f").call(this,t),delete n(this,o,"f")[n(this,s,"f")],e(this,s,n(this,s,"f")+1)}else n(this,o,"f")[r]=t}))}set onmessage(t){e(this,i,t)}get onmessage(){return n(this,i,"f")}[(i=new WeakMap,s=new WeakMap,o=new WeakMap,r)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[r]()}}async function c(t,n={},e){return window.__TAURI_INTERNALS__.invoke(t,n,e)}return t.checkPermissions=async function(){return await async function(t){return c(`plugin:${t}|check_permissions`)}("geolocation")},t.clearWatch=async function(t){await c("plugin:geolocation|clear_watch",{channelId:t})},t.getCurrentPosition=async function(t){return await c("plugin:geolocation|get_current_position",{options:t})},t.requestPermissions=async function(t){return await c("plugin:geolocation|request_permissions",{permissions:t})},t.watchPosition=async function(t,n){const e=new a;return e.onmessage=t=>{"string"==typeof t?n(null,t):n(t)},await c("plugin:geolocation|watch_position",{options:t,channel:e}),e.id},t}({});Object.defineProperty(window.__TAURI__,"geolocation",{value:__TAURI_PLUGIN_GEOLOCATION__})}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-geolocation",
"version": "2.2.3",
"version": "2.2.4",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
+2 -2
View File
@@ -21,9 +21,9 @@ mod models;
pub use error::{Error, Result};
#[cfg(desktop)]
use desktop::Geolocation;
pub use desktop::Geolocation;
#[cfg(mobile)]
use mobile::Geolocation;
pub use mobile::Geolocation;
/// Extensions to [`tauri::App`], [`tauri::AppHandle`], [`tauri::WebviewWindow`], [`tauri::Webview`] and [`tauri::Window`] to access the geolocation APIs.
pub trait GeolocationExt<R: Runtime> {
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_GLOBAL_SHORTCUT__=function(t){"use strict";function e(t,e,r,s){if("a"===r&&!s)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!s:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?s:"a"===r?s.call(t):s?s.value:e.get(t)}function r(t,e,r,s,i){if("function"==typeof e||!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,r),r}var s,i,n;"function"==typeof SuppressedError&&SuppressedError;const o="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,s.set(this,(()=>{})),i.set(this,0),n.set(this,[]),this.id=function(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}((({message:t,id:o})=>{if(o==e(this,i,"f"))for(e(this,s,"f").call(this,t),r(this,i,e(this,i,"f")+1);e(this,i,"f")in e(this,n,"f");){const t=e(this,n,"f")[e(this,i,"f")];e(this,s,"f").call(this,t),delete e(this,n,"f")[e(this,i,"f")],r(this,i,e(this,i,"f")+1)}else e(this,n,"f")[o]=t}))}set onmessage(t){r(this,s,t)}get onmessage(){return e(this,s,"f")}[(s=new WeakMap,i=new WeakMap,n=new WeakMap,o)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[o]()}}async function _(t,e={},r){return window.__TAURI_INTERNALS__.invoke(t,e,r)}return t.isRegistered=async function(t){return await _("plugin:global-shortcut|is_registered",{shortcut:t})},t.register=async function(t,e){const r=new a;return r.onmessage=e,await _("plugin:global-shortcut|register",{shortcuts:Array.isArray(t)?t:[t],handler:r})},t.unregister=async function(t){return await _("plugin:global-shortcut|unregister",{shortcuts:Array.isArray(t)?t:[t]})},t.unregisterAll=async function(){return await _("plugin:global-shortcut|unregister_all",{})},t}({});Object.defineProperty(window.__TAURI__,"globalShortcut",{value:__TAURI_PLUGIN_GLOBAL_SHORTCUT__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_GLOBAL_SHORTCUT__=function(t){"use strict";function e(t,e,r,s){if("function"==typeof e||!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?s:"a"===r?s.call(t):s?s.value:e.get(t)}function r(t,e,r,s,i){if("function"==typeof e||!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,r),r}var s,i,n;"function"==typeof SuppressedError&&SuppressedError;const o="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,s.set(this,(()=>{})),i.set(this,0),n.set(this,[]),this.id=function(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}((({message:t,id:o})=>{if(o==e(this,i,"f"))for(e(this,s,"f").call(this,t),r(this,i,e(this,i,"f")+1);e(this,i,"f")in e(this,n,"f");){const t=e(this,n,"f")[e(this,i,"f")];e(this,s,"f").call(this,t),delete e(this,n,"f")[e(this,i,"f")],r(this,i,e(this,i,"f")+1)}else e(this,n,"f")[o]=t}))}set onmessage(t){r(this,s,t)}get onmessage(){return e(this,s,"f")}[(s=new WeakMap,i=new WeakMap,n=new WeakMap,o)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[o]()}}async function _(t,e={},r){return window.__TAURI_INTERNALS__.invoke(t,e,r)}return t.isRegistered=async function(t){return await _("plugin:global-shortcut|is_registered",{shortcut:t})},t.register=async function(t,e){const r=new a;return r.onmessage=e,await _("plugin:global-shortcut|register",{shortcuts:Array.isArray(t)?t:[t],handler:r})},t.unregister=async function(t){return await _("plugin:global-shortcut|unregister",{shortcuts:Array.isArray(t)?t:[t]})},t.unregisterAll=async function(){return await _("plugin:global-shortcut|unregister_all",{})},t}({});Object.defineProperty(window.__TAURI__,"globalShortcut",{value:__TAURI_PLUGIN_GLOBAL_SHORTCUT__})}
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.2.4]
- [`a1b3fa27`](https://github.com/tauri-apps/plugins-workspace/commit/a1b3fa27f11022c9b6622b4fab12d93239eb05de) ([#2515](https://github.com/tauri-apps/plugins-workspace/pull/2515) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Re-exported the `Geolocation`, `Haptics`, `Notification`, and `Os` structs so that they show up on docs.rs.
## \[2.2.3]
- [`406e6f48`](https://github.com/tauri-apps/plugins-workspace/commit/406e6f484cdc13d35c50fb949f7489ca9eeccc44) ([#2323](https://github.com/tauri-apps/plugins-workspace/pull/2323) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Fixed an issue that caused build failures when the `haptics` or `geolocation` plugin was used without their `specta` feature flag enabled.
+1 -1
View File
@@ -1,7 +1,7 @@
[package]
name = "tauri-plugin-haptics"
description = "Haptic feedback and vibrations on Android and iOS"
version = "2.2.3"
version = "2.2.4"
edition = { workspace = true }
authors = { workspace = true }
license = { workspace = true }
+13
View File
@@ -69,6 +69,19 @@ fn main() {
}
```
Second, add the required permissions in the project:
`src-tauri/capabilities/default.json`
```json
"permissions": [
"haptics:allow-impact-feedback",
"haptics:allow-notification-feedback",
"haptics:allow-selection-feedback",
"haptics:allow-vibrate"
]
```
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-haptics",
"version": "2.2.3",
"version": "2.2.4",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
+2 -2
View File
@@ -21,9 +21,9 @@ mod models;
pub use error::{Error, Result};
#[cfg(desktop)]
use desktop::Haptics;
pub use desktop::Haptics;
#[cfg(mobile)]
use mobile::Haptics;
pub use mobile::Haptics;
/// Extensions to [`tauri::App`], [`tauri::AppHandle`], [`tauri::WebviewWindow`], [`tauri::Webview`] and [`tauri::Window`] to access the haptics APIs.
pub trait HapticsExt<R: Runtime> {
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.4.0]
- [`cb38f54f`](https://github.com/tauri-apps/plugins-workspace/commit/cb38f54f4a4ef30995283cd82166c62da17bac44) ([#2479](https://github.com/tauri-apps/plugins-workspace/pull/2479) by [@adrieljss](https://github.com/tauri-apps/plugins-workspace/../../adrieljss)) Add stream support for HTTP stream responses.
## \[2.3.0]
- [`10513649`](https://github.com/tauri-apps/plugins-workspace/commit/105136494c5a5bf4b1f1cc06cc71815412d17ec8) ([#2204](https://github.com/tauri-apps/plugins-workspace/pull/2204) by [@RickeyWard](https://github.com/tauri-apps/plugins-workspace/../../RickeyWard)) Add `dangerous-settings` feature flag and new JS `danger` option to disable tls hostname/certificate validation.
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-http"
version = "2.3.0"
version = "2.4.0"
description = "Access an HTTP client written in Rust."
edition = { workspace = true }
authors = { workspace = true }
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_HTTP__=function(e){"use strict";async function t(e,t={},r){return window.__TAURI_INTERNALS__.invoke(e,t,r)}"function"==typeof SuppressedError&&SuppressedError;const r="Request canceled";return e.fetch=async function(e,n){const a=n?.signal;if(a?.aborted)throw new Error(r);const o=n?.maxRedirections,s=n?.connectTimeout,i=n?.proxy,d=n?.danger;n&&(delete n.maxRedirections,delete n.connectTimeout,delete n.proxy,delete n.danger);const c=n?.headers?n.headers instanceof Headers?n.headers:new Headers(n.headers):new Headers,u=new Request(e,n),f=await u.arrayBuffer(),_=0!==f.byteLength?Array.from(new Uint8Array(f)):null;for(const[e,t]of u.headers)c.get(e)||c.set(e,t);const h=(c instanceof Headers?Array.from(c.entries()):Array.isArray(c)?c:Object.entries(c)).map((([e,t])=>[e,"string"==typeof t?t:t.toString()]));if(a?.aborted)throw new Error(r);const l=await t("plugin:http|fetch",{clientConfig:{method:u.method,url:u.url,headers:h,data:_,maxRedirections:o,connectTimeout:s,proxy:i,danger:d}}),p=()=>t("plugin:http|fetch_cancel",{rid:l});if(a?.aborted)throw p(),new Error(r);a?.addEventListener("abort",(()=>{p()}));const{status:w,statusText:y,url:g,headers:T,rid:A}=await t("plugin:http|fetch_send",{rid:l}),R=await t("plugin:http|fetch_read_body",{rid:A}),b=new Response(R instanceof ArrayBuffer&&0!==R.byteLength?R:R instanceof Array&&R.length>0?new Uint8Array(R):null,{status:w,statusText:y});return Object.defineProperty(b,"url",{value:g}),Object.defineProperty(b,"headers",{value:new Headers(T)}),b},e}({});Object.defineProperty(window.__TAURI__,"http",{value:__TAURI_PLUGIN_HTTP__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_HTTP__=function(e){"use strict";function t(e,t,r,n){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?n:"a"===r?n.call(e):n?n.value:t.get(e)}function r(e,t,r,n,s){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(e,r),r}var n,s,a;"function"==typeof SuppressedError&&SuppressedError;const i="__TAURI_TO_IPC_KEY__";class o{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,n.set(this,(()=>{})),s.set(this,0),a.set(this,[]),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((({message:e,id:i})=>{if(i==t(this,s,"f"))for(t(this,n,"f").call(this,e),r(this,s,t(this,s,"f")+1);t(this,s,"f")in t(this,a,"f");){const e=t(this,a,"f")[t(this,s,"f")];t(this,n,"f").call(this,e),delete t(this,a,"f")[t(this,s,"f")],r(this,s,t(this,s,"f")+1)}else t(this,a,"f")[i]=e}))}set onmessage(e){r(this,n,e)}get onmessage(){return t(this,n,"f")}[(n=new WeakMap,s=new WeakMap,a=new WeakMap,i)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[i]()}}async function c(e,t={},r){return window.__TAURI_INTERNALS__.invoke(e,t,r)}const d="Request canceled";return e.fetch=async function(e,t){const r=t?.signal;if(r?.aborted)throw new Error(d);const n=t?.maxRedirections,s=t?.connectTimeout,a=t?.proxy,i=t?.danger;t&&(delete t.maxRedirections,delete t.connectTimeout,delete t.proxy,delete t.danger);const f=t?.headers?t.headers instanceof Headers?t.headers:new Headers(t.headers):new Headers,h=new Request(e,t),_=await h.arrayBuffer(),u=0!==_.byteLength?Array.from(new Uint8Array(_)):null;for(const[e,t]of h.headers)f.get(e)||f.set(e,t);const l=(f instanceof Headers?Array.from(f.entries()):Array.isArray(f)?f:Object.entries(f)).map((([e,t])=>[e,"string"==typeof t?t:t.toString()]));if(r?.aborted)throw new Error(d);const w=new o,p=new ReadableStream({start:e=>{w.onmessage=t=>{if(r?.aborted)return e.error(d),void e.close();(t instanceof ArrayBuffer?0!=t.byteLength:0!=t.length)?e.enqueue(new Uint8Array(t)):e.close()}}}),m=await c("plugin:http|fetch",{clientConfig:{method:h.method,url:h.url,headers:l,data:u,maxRedirections:n,connectTimeout:s,proxy:a,danger:i},streamChannel:w}),y=()=>c("plugin:http|fetch_cancel",{rid:m});if(r?.aborted)throw y(),new Error(d);r?.addEventListener("abort",(()=>{y()}));const{status:T,statusText:g,url:A,headers:R}=await c("plugin:http|fetch_send",{rid:m}),b=new Response(p,{status:T,statusText:g});return Object.defineProperty(b,"url",{value:A}),Object.defineProperty(b,"headers",{value:new Headers(R)}),b},e}({});Object.defineProperty(window.__TAURI__,"http",{value:__TAURI_PLUGIN_HTTP__})}
+37 -22
View File
@@ -26,7 +26,7 @@
* @module
*/
import { invoke } from '@tauri-apps/api/core'
import { Channel, invoke } from '@tauri-apps/api/core'
/**
* Configuration of a proxy that a Client should pass requests to.
@@ -186,6 +186,35 @@ export async function fetch(
throw new Error(ERROR_REQUEST_CANCELLED)
}
const streamChannel = new Channel<ArrayBuffer | number[]>()
const readableStreamBody = new ReadableStream({
start: (controller) => {
streamChannel.onmessage = (res: ArrayBuffer | number[]) => {
// close early if aborted
if (signal?.aborted) {
controller.error(ERROR_REQUEST_CANCELLED)
controller.close()
return
}
// close when the signal to close (an empty chunk)
// is sent from the IPC.
if (
res instanceof ArrayBuffer ? res.byteLength == 0 : res.length == 0
) {
controller.close()
return
}
// the content conversion (like .text(), .json(), etc.) in Response
// must have Uint8Array as its content, else it will
// have untraceable error that's hard to debug.
controller.enqueue(new Uint8Array(res))
}
}
})
const rid = await invoke<number>('plugin:http|fetch', {
clientConfig: {
method: req.method,
@@ -196,7 +225,8 @@ export async function fetch(
connectTimeout,
proxy,
danger
}
},
streamChannel
})
const abort = () => invoke('plugin:http|fetch_cancel', { rid })
@@ -223,30 +253,15 @@ export async function fetch(
status,
statusText,
url,
headers: responseHeaders,
rid: responseRid
headers: responseHeaders
} = await invoke<FetchSendResponse>('plugin:http|fetch_send', {
rid
})
const body = await invoke<ArrayBuffer | number[]>(
'plugin:http|fetch_read_body',
{
rid: responseRid
}
)
const res = new Response(
body instanceof ArrayBuffer && body.byteLength !== 0
? body
: body instanceof Array && body.length > 0
? new Uint8Array(body)
: null,
{
status,
statusText
}
)
const res = new Response(readableStreamBody, {
status,
statusText
})
// url and headers are read only properties
// but seems like we can set them like this
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-http",
"version": "2.3.0",
"version": "2.4.0",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
+17 -21
View File
@@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize};
use tauri::{
async_runtime::Mutex,
command,
ipc::{CommandScope, GlobalScope},
ipc::{Channel, CommandScope, GlobalScope},
Manager, ResourceId, ResourceTable, Runtime, State, Webview,
};
use tokio::sync::oneshot::{channel, Receiver, Sender};
@@ -22,9 +22,6 @@ use crate::{
const HTTP_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"),);
struct ReqwestResponse(reqwest::Response);
impl tauri::Resource for ReqwestResponse {}
type CancelableResponseResult = Result<reqwest::Response>;
type CancelableResponseFuture =
Pin<Box<dyn Future<Output = CancelableResponseResult> + Send + Sync>>;
@@ -181,6 +178,7 @@ pub async fn fetch<R: Runtime>(
client_config: ClientConfig,
command_scope: CommandScope<Entry>,
global_scope: GlobalScope<Entry>,
stream_channel: Channel<tauri::ipc::InvokeResponseBody>,
) -> crate::Result<ResourceId> {
let ClientConfig {
method,
@@ -314,7 +312,21 @@ pub async fn fetch<R: Runtime>(
#[cfg(feature = "tracing")]
tracing::trace!("{:?}", request);
let fut = async move { request.send().await.map_err(Into::into) };
let fut = async move {
let mut res = request.send().await?;
// send response through IPC channel
while let Some(chunk) = res.chunk().await? {
stream_channel.send(tauri::ipc::InvokeResponseBody::Raw(chunk.to_vec()))?;
}
// send empty vector when done
stream_channel.send(tauri::ipc::InvokeResponseBody::Raw(Vec::new()))?;
// return that response
Ok(res)
};
let mut resources_table = webview.resources_table();
let rid = resources_table.add_request(Box::pin(fut));
@@ -398,9 +410,6 @@ pub async fn fetch_send<R: Runtime>(
));
}
let mut resources_table = webview.resources_table();
let rid = resources_table.add(ReqwestResponse(res));
Ok(FetchResponse {
status: status.as_u16(),
status_text: status.canonical_reason().unwrap_or_default().to_string(),
@@ -410,19 +419,6 @@ pub async fn fetch_send<R: Runtime>(
})
}
#[tauri::command]
pub(crate) async fn fetch_read_body<R: Runtime>(
webview: Webview<R>,
rid: ResourceId,
) -> crate::Result<tauri::ipc::Response> {
let res = {
let mut resources_table = webview.resources_table();
resources_table.take::<ReqwestResponse>(rid)?
};
let res = Arc::into_inner(res).unwrap().0;
Ok(tauri::ipc::Response::new(res.bytes().await?.to_vec()))
}
// forbidden headers per fetch spec https://fetch.spec.whatwg.org/#terminology-headers
#[cfg(not(feature = "unsafe-headers"))]
fn is_unsafe_header(header: &HeaderName) -> bool {
+1 -2
View File
@@ -36,8 +36,7 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
.invoke_handler(tauri::generate_handler![
commands::fetch,
commands::fetch_cancel,
commands::fetch_send,
commands::fetch_read_body,
commands::fetch_send
])
.build()
}
+14
View File
@@ -1,5 +1,19 @@
# Changelog
## \[2.3.0]
### feat
- [`02481501`](https://github.com/tauri-apps/plugins-workspace/commit/024815018fbc63a37afc716796a454925aa7d25e) ([#2377](https://github.com/tauri-apps/plugins-workspace/pull/2377) by [@3lpsy](https://github.com/tauri-apps/plugins-workspace/../../3lpsy)) Add a `is_skip_logger` flag to the Log Plugin `Builder` struct, a `skip_logger()` method to the Builder, and logic to avoid acquiring (creating) a logger and attaching it to the global logger. Since acquire_logger is pub, a `LoggerNotInitialized` is added and returned if it's called when the `is_skip_looger` flag is set. Overall, this feature permits a user to avoid calling `attach_logger` which can only be called once in a program's lifetime and allows the user to control the logger returned from `logger()`. Additionally, it also will allow users to generate multiple Tauri Mock apps in test suites that run and parallel and have the `log` plugin attached (assuming they use `skip_logger()`).
## \[2.2.3]
- [`1a984659`](https://github.com/tauri-apps/plugins-workspace/commit/1a9846599b6a71faf330845847a30f6bf9735898) ([#2469](https://github.com/tauri-apps/plugins-workspace/pull/2469) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Update `objc2` crate to 0.6. No user facing changes.
## \[2.2.2]
- [`6b4c3917`](https://github.com/tauri-apps/plugins-workspace/commit/6b4c3917389f4bc489d03b48a837557ac0584175) ([#2401](https://github.com/tauri-apps/plugins-workspace/pull/2401) by [@Seishiin](https://github.com/tauri-apps/plugins-workspace/../../Seishiin)) Fix timezone_strategy overwriting previously set LogLevels.
## \[2.2.1]
- [`784a54a3`](https://github.com/tauri-apps/plugins-workspace/commit/784a54a39094dfbaaa8dd123eb083c04dc6c3bb2) ([#2344](https://github.com/tauri-apps/plugins-workspace/pull/2344) by [@madsmtm](https://github.com/tauri-apps/plugins-workspace/../../madsmtm)) Use `objc2` instead of `objc`.
+3 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-log"
version = "2.2.1"
version = "2.3.0"
description = "Configurable logging for your Tauri app."
authors = { workspace = true }
license = { workspace = true }
@@ -39,8 +39,8 @@ android_logger = "0.14"
[target."cfg(target_os = \"ios\")".dependencies]
swift-rs = "1"
objc2 = "0.5"
objc2-foundation = { version = "0.2", default-features = false, features = [
objc2 = "0.6"
objc2-foundation = { version = "0.3", default-features = false, features = [
"std",
"NSString",
] }
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-log",
"version": "2.2.1",
"version": "2.3.0",
"description": "Configurable logging for your Tauri app.",
"license": "MIT OR Apache-2.0",
"authors": [
+35 -12
View File
@@ -58,6 +58,8 @@ pub enum Error {
TimeFormat(#[from] time::error::Format),
#[error(transparent)]
InvalidFormatDescription(#[from] time::error::InvalidFormatDescription),
#[error("Internal logger disabled and cannot be acquired or attached")]
LoggerNotInitialized,
}
/// An enum representing the available verbosity levels of the logger.
@@ -230,6 +232,7 @@ pub struct Builder {
timezone_strategy: TimezoneStrategy,
max_file_size: u128,
targets: Vec<Target>,
is_skip_logger: bool,
}
impl Default for Builder {
@@ -258,6 +261,7 @@ impl Default for Builder {
timezone_strategy: DEFAULT_TIMEZONE_STRATEGY,
max_file_size: DEFAULT_MAX_FILE_SIZE,
targets: DEFAULT_LOG_TARGETS.into(),
is_skip_logger: false,
}
}
}
@@ -278,7 +282,7 @@ impl Builder {
let format =
time::format_description::parse("[[[year]-[month]-[day]][[[hour]:[minute]:[second]]")
.unwrap();
self.dispatch = fern::Dispatch::new().format(move |out, message, record| {
self.dispatch = self.dispatch.format(move |out, message, record| {
out.finish(format_args!(
"{}[{}][{}] {}",
timezone_strategy.get_now().format(&format).unwrap(),
@@ -339,6 +343,22 @@ impl Builder {
self
}
/// 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. This can also be used with `tracing-log` or if running tests in parallel that require the plugin to be registered.
/// ```rust
/// static LOGGER: SimpleLogger = SimpleLogger;
///
/// log::set_logger(&SimpleLogger)?;
/// log::set_max_level(LevelFilter::Info);
/// tauri_plugin_log::Builder::new()
/// .skip_logger();
/// ```
pub fn skip_logger(mut self) -> Self {
self.is_skip_logger = true;
self
}
/// Adds a collection of targets to the logger.
///
/// ```rust
@@ -481,6 +501,9 @@ impl Builder {
self,
app_handle: &AppHandle<R>,
) -> Result<(TauriPlugin<R>, log::LevelFilter, Box<dyn log::Log>), Error> {
if self.is_skip_logger {
return Err(Error::LoggerNotInitialized);
}
let plugin = Self::plugin_builder();
let (max_level, log) = Self::acquire_logger(
app_handle,
@@ -497,17 +520,17 @@ impl Builder {
pub fn build<R: Runtime>(self) -> TauriPlugin<R> {
Self::plugin_builder()
.setup(move |app_handle, _api| {
let (max_level, log) = Self::acquire_logger(
app_handle,
self.dispatch,
self.rotation_strategy,
self.timezone_strategy,
self.max_file_size,
self.targets,
)?;
attach_logger(max_level, log)?;
if !self.is_skip_logger {
let (max_level, log) = Self::acquire_logger(
app_handle,
self.dispatch,
self.rotation_strategy,
self.timezone_strategy,
self.max_file_size,
self.targets,
)?;
attach_logger(max_level, log)?;
}
Ok(())
})
.build()
+2 -2
View File
@@ -181,8 +181,8 @@ function encodeURI(uri: string): number[] {
protocols.slice(1).forEach(function (protocol) {
if (
(prefix.length === 0 || prefix === 'urn:') &&
uri.indexOf(protocol) === 0
(prefix.length === 0 || prefix === 'urn:')
&& uri.indexOf(protocol) === 0
) {
prefix = protocol
}
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.2.2]
- [`a1b3fa27`](https://github.com/tauri-apps/plugins-workspace/commit/a1b3fa27f11022c9b6622b4fab12d93239eb05de) ([#2515](https://github.com/tauri-apps/plugins-workspace/pull/2515) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Re-exported the `Geolocation`, `Haptics`, `Notification`, and `Os` structs so that they show up on docs.rs.
## \[2.2.1]
- [`da5c59e2`](https://github.com/tauri-apps/plugins-workspace/commit/da5c59e2fe879d177e3cfd52fcacce85440423cb) ([#2271](https://github.com/tauri-apps/plugins-workspace/pull/2271) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated `zbus` dependency to version 5. No API changes.
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-notification"
version = "2.2.1"
version = "2.2.2"
description = "Send desktop and mobile notifications on your Tauri application."
edition = { workspace = true }
authors = { workspace = true }
@@ -46,7 +46,7 @@ windows-version = { version = "0.1", optional = true }
notify-rust = "4.11"
[dev-dependencies]
color-backtrace = "0.6"
color-backtrace = "0.7"
ctor = "0.2"
maplit = "1"
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_NOTIFICATION__=function(i){"use strict";function t(i,t,n,e){if("a"===n&&!e)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?i!==t||!e:!t.has(i))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?e:"a"===n?e.call(i):e?e.value:t.get(i)}function n(i,t,n,e,a){if("function"==typeof t||!t.has(i))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(i,n),n}var e,a,o;"function"==typeof SuppressedError&&SuppressedError;const r="__TAURI_TO_IPC_KEY__";class s{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,e.set(this,(()=>{})),a.set(this,0),o.set(this,[]),this.id=function(i,t=!1){return window.__TAURI_INTERNALS__.transformCallback(i,t)}((({message:i,id:r})=>{if(r==t(this,a,"f"))for(t(this,e,"f").call(this,i),n(this,a,t(this,a,"f")+1);t(this,a,"f")in t(this,o,"f");){const i=t(this,o,"f")[t(this,a,"f")];t(this,e,"f").call(this,i),delete t(this,o,"f")[t(this,a,"f")],n(this,a,t(this,a,"f")+1)}else t(this,o,"f")[r]=i}))}set onmessage(i){n(this,e,i)}get onmessage(){return t(this,e,"f")}[(e=new WeakMap,a=new WeakMap,o=new WeakMap,r)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[r]()}}class c{constructor(i,t,n){this.plugin=i,this.event=t,this.channelId=n}async unregister(){return u(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}}async function l(i,t,n){const e=new s;return e.onmessage=n,u(`plugin:${i}|registerListener`,{event:t,handler:e}).then((()=>new c(i,t,e.id)))}async function u(i,t={},n){return window.__TAURI_INTERNALS__.invoke(i,t,n)}var f,h,d;i.ScheduleEvery=void 0,(f=i.ScheduleEvery||(i.ScheduleEvery={})).Year="year",f.Month="month",f.TwoWeeks="twoWeeks",f.Week="week",f.Day="day",f.Hour="hour",f.Minute="minute",f.Second="second";return i.Importance=void 0,(h=i.Importance||(i.Importance={}))[h.None=0]="None",h[h.Min=1]="Min",h[h.Low=2]="Low",h[h.Default=3]="Default",h[h.High=4]="High",i.Visibility=void 0,(d=i.Visibility||(i.Visibility={}))[d.Secret=-1]="Secret",d[d.Private=0]="Private",d[d.Public=1]="Public",i.Schedule=class{static at(i,t=!1,n=!1){return{at:{date:i,repeating:t,allowWhileIdle:n},interval:void 0,every:void 0}}static interval(i,t=!1){return{at:void 0,interval:{interval:i,allowWhileIdle:t},every:void 0}}static every(i,t,n=!1){return{at:void 0,interval:void 0,every:{interval:i,count:t,allowWhileIdle:n}}}},i.active=async function(){return await u("plugin:notification|get_active")},i.cancel=async function(i){await u("plugin:notification|cancel",{notifications:i})},i.cancelAll=async function(){await u("plugin:notification|cancel")},i.channels=async function(){return await u("plugin:notification|listChannels")},i.createChannel=async function(i){await u("plugin:notification|create_channel",{...i})},i.isPermissionGranted=async function(){return"default"!==window.Notification.permission?await Promise.resolve("granted"===window.Notification.permission):await u("plugin:notification|is_permission_granted")},i.onAction=async function(i){return await l("notification","actionPerformed",i)},i.onNotificationReceived=async function(i){return await l("notification","notification",i)},i.pending=async function(){return await u("plugin:notification|get_pending")},i.registerActionTypes=async function(i){await u("plugin:notification|register_action_types",{types:i})},i.removeActive=async function(i){await u("plugin:notification|remove_active",{notifications:i})},i.removeAllActive=async function(){await u("plugin:notification|remove_active")},i.removeChannel=async function(i){await u("plugin:notification|delete_channel",{id:i})},i.requestPermission=async function(){return await window.Notification.requestPermission()},i.sendNotification=function(i){"string"==typeof i?new window.Notification(i):new window.Notification(i.title,i)},i}({});Object.defineProperty(window.__TAURI__,"notification",{value:__TAURI_PLUGIN_NOTIFICATION__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_NOTIFICATION__=function(i){"use strict";function n(i,n,t,e){if("function"==typeof n||!n.has(i))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===t?e:"a"===t?e.call(i):e?e.value:n.get(i)}function t(i,n,t,e,o){if("function"==typeof n||!n.has(i))throw new TypeError("Cannot write private member to an object whose class did not declare it");return n.set(i,t),t}var e,o,a;"function"==typeof SuppressedError&&SuppressedError;const r="__TAURI_TO_IPC_KEY__";class c{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,e.set(this,(()=>{})),o.set(this,0),a.set(this,[]),this.id=function(i,n=!1){return window.__TAURI_INTERNALS__.transformCallback(i,n)}((({message:i,id:r})=>{if(r==n(this,o,"f"))for(n(this,e,"f").call(this,i),t(this,o,n(this,o,"f")+1);n(this,o,"f")in n(this,a,"f");){const i=n(this,a,"f")[n(this,o,"f")];n(this,e,"f").call(this,i),delete n(this,a,"f")[n(this,o,"f")],t(this,o,n(this,o,"f")+1)}else n(this,a,"f")[r]=i}))}set onmessage(i){t(this,e,i)}get onmessage(){return n(this,e,"f")}[(e=new WeakMap,o=new WeakMap,a=new WeakMap,r)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[r]()}}class s{constructor(i,n,t){this.plugin=i,this.event=n,this.channelId=t}async unregister(){return u(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}}async function l(i,n,t){const e=new c;return e.onmessage=t,u(`plugin:${i}|registerListener`,{event:n,handler:e}).then((()=>new s(i,n,e.id)))}async function u(i,n={},t){return window.__TAURI_INTERNALS__.invoke(i,n,t)}var f,h,d;i.ScheduleEvery=void 0,(f=i.ScheduleEvery||(i.ScheduleEvery={})).Year="year",f.Month="month",f.TwoWeeks="twoWeeks",f.Week="week",f.Day="day",f.Hour="hour",f.Minute="minute",f.Second="second";return i.Importance=void 0,(h=i.Importance||(i.Importance={}))[h.None=0]="None",h[h.Min=1]="Min",h[h.Low=2]="Low",h[h.Default=3]="Default",h[h.High=4]="High",i.Visibility=void 0,(d=i.Visibility||(i.Visibility={}))[d.Secret=-1]="Secret",d[d.Private=0]="Private",d[d.Public=1]="Public",i.Schedule=class{static at(i,n=!1,t=!1){return{at:{date:i,repeating:n,allowWhileIdle:t},interval:void 0,every:void 0}}static interval(i,n=!1){return{at:void 0,interval:{interval:i,allowWhileIdle:n},every:void 0}}static every(i,n,t=!1){return{at:void 0,interval:void 0,every:{interval:i,count:n,allowWhileIdle:t}}}},i.active=async function(){return await u("plugin:notification|get_active")},i.cancel=async function(i){await u("plugin:notification|cancel",{notifications:i})},i.cancelAll=async function(){await u("plugin:notification|cancel")},i.channels=async function(){return await u("plugin:notification|listChannels")},i.createChannel=async function(i){await u("plugin:notification|create_channel",{...i})},i.isPermissionGranted=async function(){return"default"!==window.Notification.permission?await Promise.resolve("granted"===window.Notification.permission):await u("plugin:notification|is_permission_granted")},i.onAction=async function(i){return await l("notification","actionPerformed",i)},i.onNotificationReceived=async function(i){return await l("notification","notification",i)},i.pending=async function(){return await u("plugin:notification|get_pending")},i.registerActionTypes=async function(i){await u("plugin:notification|register_action_types",{types:i})},i.removeActive=async function(i){await u("plugin:notification|remove_active",{notifications:i})},i.removeAllActive=async function(){await u("plugin:notification|remove_active")},i.removeChannel=async function(i){await u("plugin:notification|delete_channel",{id:i})},i.requestPermission=async function(){return await window.Notification.requestPermission()},i.sendNotification=function(i){"string"==typeof i?new window.Notification(i):new window.Notification(i.title,i)},i}({});Object.defineProperty(window.__TAURI__,"notification",{value:__TAURI_PLUGIN_NOTIFICATION__})}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-notification",
"version": "2.2.1",
"version": "2.2.2",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
+2
View File
@@ -18,6 +18,8 @@ pub fn init<R: Runtime, C: DeserializeOwned>(
}
/// Access to the notification APIs.
///
/// You can get an instance of this type via [`NotificationExt`](crate::NotificationExt)
pub struct Notification<R: Runtime>(AppHandle<R>);
impl<R: Runtime> crate::NotificationBuilder<R> {
+3 -3
View File
@@ -34,9 +34,9 @@ mod models;
pub use error::{Error, Result};
#[cfg(desktop)]
use desktop::Notification;
pub use desktop::Notification;
#[cfg(mobile)]
use mobile::Notification;
pub use mobile::Notification;
/// The notification builder.
#[derive(Debug)]
@@ -120,7 +120,7 @@ impl<R: Runtime> NotificationBuilder<R> {
/// Identifier used to group multiple notifications.
///
/// https://developer.apple.com/documentation/usernotifications/unmutablenotificationcontent/1649872-threadidentifier
/// <https://developer.apple.com/documentation/usernotifications/unmutablenotificationcontent/1649872-threadidentifier>
pub fn group(mut self, group: impl Into<String>) -> Self {
self.data.group.replace(group.into());
self
+2
View File
@@ -40,6 +40,8 @@ impl<R: Runtime> crate::NotificationBuilder<R> {
}
/// Access to the notification APIs.
///
/// You can get an instance of this type via [`NotificationExt`](crate::NotificationExt)
pub struct Notification<R: Runtime>(PluginHandle<R>);
impl<R: Runtime> Notification<R> {
+5
View File
@@ -1,5 +1,10 @@
# Changelog
## \[2.2.6]
- [`1a984659`](https://github.com/tauri-apps/plugins-workspace/commit/1a9846599b6a71faf330845847a30f6bf9735898) ([#2469](https://github.com/tauri-apps/plugins-workspace/pull/2469) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Update `objc2` crate to 0.6. No user facing changes.
- [`71f95c9f`](https://github.com/tauri-apps/plugins-workspace/commit/71f95c9f05b29cf1be586849614c0b007757c15d) ([#2445](https://github.com/tauri-apps/plugins-workspace/pull/2445) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated `windows` crate to 0.60 to match Tauri 2.3.0. No user facing changes.
## \[2.2.5]
- [`5b821181`](https://github.com/tauri-apps/plugins-workspace/commit/5b8211815825ddae2dcc0c00520e0cfdff002763) ([#2332](https://github.com/tauri-apps/plugins-workspace/pull/2332) by [@betamos](https://github.com/tauri-apps/plugins-workspace/../../betamos)) Fix broken JS commands `opener.openPath` and `opener.openUrl` on mobile.
+4 -4
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-opener"
version = "2.2.5"
version = "2.2.6"
description = "Open files and URLs using their default application."
edition = { workspace = true }
authors = { workspace = true }
@@ -40,7 +40,7 @@ glob = { workspace = true }
dunce = { workspace = true }
[target."cfg(windows)".dependencies.windows]
version = "0.58"
version = "0.60"
features = [
"Win32_Foundation",
"Win32_UI_Shell_Common",
@@ -54,12 +54,12 @@ zbus = { workspace = true }
url = { workspace = true }
[target."cfg(target_os = \"macos\")".dependencies.objc2-app-kit]
version = "0.2"
version = "0.3"
default-features = false
features = ["std", "NSWorkspace"]
[target."cfg(target_os = \"macos\")".dependencies.objc2-foundation]
version = "0.2"
version = "0.3"
default-features = false
features = ["std", "NSURL", "NSArray", "NSString"]
+12 -12
View File
@@ -9,13 +9,13 @@ window.addEventListener('click', function (evt) {
// return early if
if (
// event was prevented
evt.defaultPrevented ||
evt.defaultPrevented
// or not a left click
evt.button !== 0 ||
|| evt.button !== 0
// or meta key pressed
evt.metaKey ||
|| evt.metaKey
// or al key pressed
evt.altKey
|| evt.altKey
)
return
@@ -28,16 +28,16 @@ window.addEventListener('click', function (evt) {
// return early if
if (
// not tirggered from <a> element
!a ||
!a
// or doesn't have a href
!a.href ||
|| !a.href
// or not supposed to be open in a new tab
!(
a.target === '_blank' ||
|| !(
a.target === '_blank'
// or ctrl key pressed
evt.ctrlKey ||
|| evt.ctrlKey
// or shift key pressed
evt.shiftKey
|| evt.shiftKey
)
)
return
@@ -47,9 +47,9 @@ window.addEventListener('click', function (evt) {
// return early if
if (
// same origin (internal navigation)
url.origin === window.location.origin ||
url.origin === window.location.origin
// not default protocols
['http:', 'https:', 'mailto:', 'tel:'].every((p) => url.protocol !== p)
|| ['http:', 'https:', 'mailto:', 'tel:'].every((p) => url.protocol !== p)
)
return
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-opener",
"version": "2.2.5",
"version": "2.2.6",
"description": "Open files and URLs using their default application.",
"license": "MIT OR Apache-2.0",
"authors": [
+2 -2
View File
@@ -56,7 +56,7 @@ impl<R: Runtime> Opener<R> {
/// - **Android / iOS**: Always opens using default program.
#[cfg(desktop)]
pub fn open_url(&self, url: impl Into<String>, with: Option<impl Into<String>>) -> Result<()> {
crate::open::open(url.into(), with.map(Into::into)).map_err(Into::into)
crate::open::open(url.into(), with.map(Into::into))
}
/// Open a url with a default or specific program.
@@ -108,7 +108,7 @@ impl<R: Runtime> Opener<R> {
path: impl Into<String>,
with: Option<impl Into<String>>,
) -> Result<()> {
crate::open::open(path.into(), with.map(Into::into)).map_err(Into::into)
crate::open::open(path.into(), with.map(Into::into))
}
/// Open a path with a default or specific program.
+1 -1
View File
@@ -185,7 +185,7 @@ mod imp {
let path = path.to_string_lossy();
let path = NSString::from_str(&path);
let urls = vec![NSURL::fileURLWithPath(&path)];
let urls = NSArray::from_vec(urls);
let urls = NSArray::from_retained_slice(&urls);
let workspace = NSWorkspace::new();
workspace.activateFileViewerSelectingURLs(&urls);
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.2.1]
- [`a1b3fa27`](https://github.com/tauri-apps/plugins-workspace/commit/a1b3fa27f11022c9b6622b4fab12d93239eb05de) ([#2515](https://github.com/tauri-apps/plugins-workspace/pull/2515) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Re-exported the `Geolocation`, `Haptics`, `Notification`, and `Os` structs so that they show up on docs.rs.
## \[2.2.0]
- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-os"
version = "2.2.0"
version = "2.2.1"
description = "Read information about the operating system."
edition = { workspace = true }
authors = { workspace = true }
@@ -31,5 +31,5 @@ log = { workspace = true }
thiserror = { workspace = true }
os_info = "3"
sys-locale = "0.3"
gethostname = "0.5"
gethostname = "1.0"
serialize-to-javascript = "=0.1.1"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-os",
"version": "2.2.0",
"version": "2.2.1",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
+1 -1
View File
@@ -88,7 +88,7 @@ pub fn exe_extension() -> &'static str {
std::env::consts::EXE_EXTENSION
}
/// Returns the current operating system locale with the `BCP-47` language tag. If the locale couldnt be obtained, `None` is returned instead.
/// Returns the current operating system locale with the `BCP-47` language tag. If the locale couldn't be obtained, `None` is returned instead.
pub fn locale() -> Option<String> {
sys_locale::get_locale()
}
@@ -322,4 +322,4 @@
]
}
}
}
}
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_SHELL__=function(e){"use strict";function t(e,t,s,i){if("a"===s&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!i:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===s?i:"a"===s?i.call(e):i?i.value:t.get(e)}function s(e,t,s,i,n){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(e,s),s}var i,n,r;"function"==typeof SuppressedError&&SuppressedError;const o="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),n.set(this,0),r.set(this,[]),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((({message:e,id:o})=>{if(o==t(this,n,"f"))for(t(this,i,"f").call(this,e),s(this,n,t(this,n,"f")+1);t(this,n,"f")in t(this,r,"f");){const e=t(this,r,"f")[t(this,n,"f")];t(this,i,"f").call(this,e),delete t(this,r,"f")[t(this,n,"f")],s(this,n,t(this,n,"f")+1)}else t(this,r,"f")[o]=e}))}set onmessage(e){s(this,i,e)}get onmessage(){return t(this,i,"f")}[(i=new WeakMap,n=new WeakMap,r=new WeakMap,o)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[o]()}}async function h(e,t={},s){return window.__TAURI_INTERNALS__.invoke(e,t,s)}class c{constructor(){this.eventListeners=Object.create(null)}addListener(e,t){return this.on(e,t)}removeListener(e,t){return this.off(e,t)}on(e,t){return e in this.eventListeners?this.eventListeners[e].push(t):this.eventListeners[e]=[t],this}once(e,t){const s=i=>{this.removeListener(e,s),t(i)};return this.addListener(e,s)}off(e,t){return e in this.eventListeners&&(this.eventListeners[e]=this.eventListeners[e].filter((e=>e!==t))),this}removeAllListeners(e){return e?delete this.eventListeners[e]:this.eventListeners=Object.create(null),this}emit(e,t){if(e in this.eventListeners){const s=this.eventListeners[e];for(const e of s)e(t);return!0}return!1}listenerCount(e){return e in this.eventListeners?this.eventListeners[e].length:0}prependListener(e,t){return e in this.eventListeners?this.eventListeners[e].unshift(t):this.eventListeners[e]=[t],this}prependOnceListener(e,t){const s=i=>{this.removeListener(e,s),t(i)};return this.prependListener(e,s)}}class l{constructor(e){this.pid=e}async write(e){await h("plugin:shell|stdin_write",{pid:this.pid,buffer:e})}async kill(){await h("plugin:shell|kill",{cmd:"killChild",pid:this.pid})}}class u extends c{constructor(e,t=[],s){super(),this.stdout=new c,this.stderr=new c,this.program=e,this.args="string"==typeof t?[t]:t,this.options=s??{}}static create(e,t=[],s){return new u(e,t,s)}static sidecar(e,t=[],s){const i=new u(e,t,s);return i.options.sidecar=!0,i}async spawn(){const e=this.program,t=this.args,s=this.options;"object"==typeof t&&Object.freeze(t);const i=new a;return i.onmessage=e=>{switch(e.event){case"Error":this.emit("error",e.payload);break;case"Terminated":this.emit("close",e.payload);break;case"Stdout":this.stdout.emit("data",e.payload);break;case"Stderr":this.stderr.emit("data",e.payload)}},await h("plugin:shell|spawn",{program:e,args:t,options:s,onEvent:i}).then((e=>new l(e)))}async execute(){const e=this.program,t=this.args,s=this.options;return"object"==typeof t&&Object.freeze(t),await h("plugin:shell|execute",{program:e,args:t,options:s})}}return e.Child=l,e.Command=u,e.EventEmitter=c,e.open=async function(e,t){await h("plugin:shell|open",{path:e,with:t})},e}({});Object.defineProperty(window.__TAURI__,"shell",{value:__TAURI_PLUGIN_SHELL__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_SHELL__=function(e){"use strict";function t(e,t,s,i){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===s?i:"a"===s?i.call(e):i?i.value:t.get(e)}function s(e,t,s,i,n){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(e,s),s}var i,n,r;"function"==typeof SuppressedError&&SuppressedError;const o="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),n.set(this,0),r.set(this,[]),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((({message:e,id:o})=>{if(o==t(this,n,"f"))for(t(this,i,"f").call(this,e),s(this,n,t(this,n,"f")+1);t(this,n,"f")in t(this,r,"f");){const e=t(this,r,"f")[t(this,n,"f")];t(this,i,"f").call(this,e),delete t(this,r,"f")[t(this,n,"f")],s(this,n,t(this,n,"f")+1)}else t(this,r,"f")[o]=e}))}set onmessage(e){s(this,i,e)}get onmessage(){return t(this,i,"f")}[(i=new WeakMap,n=new WeakMap,r=new WeakMap,o)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[o]()}}async function h(e,t={},s){return window.__TAURI_INTERNALS__.invoke(e,t,s)}class c{constructor(){this.eventListeners=Object.create(null)}addListener(e,t){return this.on(e,t)}removeListener(e,t){return this.off(e,t)}on(e,t){return e in this.eventListeners?this.eventListeners[e].push(t):this.eventListeners[e]=[t],this}once(e,t){const s=i=>{this.removeListener(e,s),t(i)};return this.addListener(e,s)}off(e,t){return e in this.eventListeners&&(this.eventListeners[e]=this.eventListeners[e].filter((e=>e!==t))),this}removeAllListeners(e){return e?delete this.eventListeners[e]:this.eventListeners=Object.create(null),this}emit(e,t){if(e in this.eventListeners){const s=this.eventListeners[e];for(const e of s)e(t);return!0}return!1}listenerCount(e){return e in this.eventListeners?this.eventListeners[e].length:0}prependListener(e,t){return e in this.eventListeners?this.eventListeners[e].unshift(t):this.eventListeners[e]=[t],this}prependOnceListener(e,t){const s=i=>{this.removeListener(e,s),t(i)};return this.prependListener(e,s)}}class l{constructor(e){this.pid=e}async write(e){await h("plugin:shell|stdin_write",{pid:this.pid,buffer:e})}async kill(){await h("plugin:shell|kill",{cmd:"killChild",pid:this.pid})}}class u extends c{constructor(e,t=[],s){super(),this.stdout=new c,this.stderr=new c,this.program=e,this.args="string"==typeof t?[t]:t,this.options=s??{}}static create(e,t=[],s){return new u(e,t,s)}static sidecar(e,t=[],s){const i=new u(e,t,s);return i.options.sidecar=!0,i}async spawn(){const e=this.program,t=this.args,s=this.options;"object"==typeof t&&Object.freeze(t);const i=new a;return i.onmessage=e=>{switch(e.event){case"Error":this.emit("error",e.payload);break;case"Terminated":this.emit("close",e.payload);break;case"Stdout":this.stdout.emit("data",e.payload);break;case"Stderr":this.stderr.emit("data",e.payload)}},await h("plugin:shell|spawn",{program:e,args:t,options:s,onEvent:i}).then((e=>new l(e)))}async execute(){const e=this.program,t=this.args,s=this.options;return"object"==typeof t&&Object.freeze(t),await h("plugin:shell|execute",{program:e,args:t,options:s})}}return e.Child=l,e.Command=u,e.EventEmitter=c,e.open=async function(e,t){await h("plugin:shell|open",{path:e,with:t})},e}({});Object.defineProperty(window.__TAURI__,"shell",{value:__TAURI_PLUGIN_SHELL__})}
+6 -6
View File
@@ -12,11 +12,11 @@ function openLinks(): void {
if (target.matches('a')) {
const t = target as HTMLAnchorElement
if (
t.href !== '' &&
['http://', 'https://', 'mailto:', 'tel:'].some((v) =>
t.href !== ''
&& ['http://', 'https://', 'mailto:', 'tel:'].some((v) =>
t.href.startsWith(v)
) &&
t.target === '_blank'
)
&& t.target === '_blank'
) {
void invoke('plugin:shell|open', {
path: t.href
@@ -31,8 +31,8 @@ function openLinks(): void {
}
if (
document.readyState === 'complete' ||
document.readyState === 'interactive'
document.readyState === 'complete'
|| document.readyState === 'interactive'
) {
openLinks()
} else {
+1 -1
View File
@@ -75,7 +75,7 @@ impl<R: Runtime> Shell<R> {
#[deprecated(since = "2.1.0", note = "Use tauri-plugin-opener instead.")]
#[allow(deprecated)]
pub fn open(&self, path: impl Into<String>, with: Option<open::Program>) -> Result<()> {
open::open(&self.open_scope, path.into(), with).map_err(Into::into)
open::open(&self.open_scope, path.into(), with)
}
/// Open a (url) path with a default or specific browser opening program.
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.2.2]
- [`1ab5f157`](https://github.com/tauri-apps/plugins-workspace/commit/1ab5f1576333174095bc7dad4bef7a8576bb29ab) ([#2452](https://github.com/tauri-apps/plugins-workspace/pull/2452) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Fixed `null pointer dereference` panic on rust nightly on Windows.
## \[2.2.1]
- [`da5c59e2`](https://github.com/tauri-apps/plugins-workspace/commit/da5c59e2fe879d177e3cfd52fcacce85440423cb) ([#2271](https://github.com/tauri-apps/plugins-workspace/pull/2271) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated `zbus` dependency to version 5. No API changes.
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-single-instance"
version = "2.2.1"
version = "2.2.2"
description = "Ensure a single instance of your tauri app is running."
authors = { workspace = true }
license = { workspace = true }
@@ -9,6 +9,6 @@
"author": "",
"license": "MIT",
"devDependencies": {
"@tauri-apps/cli": "2.2.7"
"@tauri-apps/cli": "2.3.1"
}
}
@@ -3,5 +3,5 @@
// SPDX-License-Identifier: MIT
fn main() {
tauri_build::build()
tauri_build::build()
}
@@ -1,14 +0,0 @@
max_width = 100
hard_tabs = false
tab_spaces = 2
newline_style = "Auto"
use_small_heuristics = "Default"
reorder_imports = true
reorder_modules = true
remove_nested_parens = true
edition = "2021"
merge_derives = true
use_try_shorthand = false
use_field_init_shorthand = false
force_explicit_abi = true
imports_granularity = "Crate"
@@ -3,16 +3,15 @@
// SPDX-License-Identifier: MIT
#![cfg_attr(
all(not(debug_assertions), target_os = "windows"),
windows_subsystem = "windows"
all(not(debug_assertions), target_os = "windows"),
windows_subsystem = "windows"
)]
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_cli::init())
.plugin(tauri_plugin_single_instance::init(|app, argv, cwd| {
println!("{}, {argv:?}, {cwd}", app.package_info().name);
}))
.run(tauri::generate_context!())
.expect("error while running tauri application");
tauri::Builder::default()
.plugin(tauri_plugin_single_instance::init(|app, argv, cwd| {
println!("{}, {argv:?}, {cwd}", app.package_info().name);
}))
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
@@ -20,18 +20,38 @@ use windows_sys::Win32::{
},
UI::WindowsAndMessaging::{
self as w32wm, CreateWindowExW, DefWindowProcW, DestroyWindow, FindWindowW,
RegisterClassExW, SendMessageW, GWL_STYLE, GWL_USERDATA, WINDOW_LONG_PTR_INDEX,
WM_COPYDATA, WM_DESTROY, WNDCLASSEXW, WS_EX_LAYERED, WS_EX_NOACTIVATE, WS_EX_TOOLWINDOW,
WS_EX_TRANSPARENT, WS_OVERLAPPED, WS_POPUP, WS_VISIBLE,
RegisterClassExW, SendMessageW, CREATESTRUCTW, GWLP_USERDATA, GWL_STYLE,
WINDOW_LONG_PTR_INDEX, WM_COPYDATA, WM_CREATE, WM_DESTROY, WNDCLASSEXW, WS_EX_LAYERED,
WS_EX_NOACTIVATE, WS_EX_TOOLWINDOW, WS_EX_TRANSPARENT, WS_OVERLAPPED, WS_POPUP, WS_VISIBLE,
},
};
struct MutexHandle(isize);
struct TargetWindowHandle(isize);
const WMCOPYDATA_SINGLE_INSTANCE_DATA: usize = 1542;
pub fn init<R: Runtime>(f: Box<SingleInstanceCallback<R>>) -> TauriPlugin<R> {
struct MutexHandle(isize);
struct TargetWindowHandle(isize);
struct UserData<R: Runtime> {
app: AppHandle<R>,
callback: Box<SingleInstanceCallback<R>>,
}
impl<R: Runtime> UserData<R> {
unsafe fn from_hwnd_raw(hwnd: HWND) -> *mut Self {
GetWindowLongPtrW(hwnd, GWLP_USERDATA) as *mut Self
}
unsafe fn from_hwnd<'a>(hwnd: HWND) -> &'a mut Self {
&mut *Self::from_hwnd_raw(hwnd)
}
fn run_callback(&mut self, args: Vec<String>, cwd: String) {
(self.callback)(&self.app, args, cwd)
}
}
pub fn init<R: Runtime>(callback: Box<SingleInstanceCallback<R>>) -> TauriPlugin<R> {
plugin::Builder::new("single-instance")
.setup(|app, _api| {
#[allow(unused_mut)]
@@ -54,21 +74,22 @@ pub fn init<R: Runtime>(f: Box<SingleInstanceCallback<R>>) -> TauriPlugin<R> {
let hwnd = FindWindowW(class_name.as_ptr(), window_name.as_ptr());
if !hwnd.is_null() {
let data = format!(
"{}|{}\0",
std::env::current_dir()
.unwrap_or_default()
.to_str()
.unwrap_or_default(),
std::env::args().collect::<Vec<String>>().join("|")
);
let cwd = std::env::current_dir().unwrap_or_default();
let cwd = cwd.to_str().unwrap_or_default();
let args = std::env::args().collect::<Vec<String>>().join("|");
let data = format!("{cwd}|{args}\0",);
let bytes = data.as_bytes();
let cds = COPYDATASTRUCT {
dwData: WMCOPYDATA_SINGLE_INSTANCE_DATA,
cbData: bytes.len() as _,
lpData: bytes.as_ptr() as _,
};
SendMessageW(hwnd, WM_COPYDATA, 0, &cds as *const _ as _);
app.cleanup_before_exit();
std::process::exit(0);
}
@@ -76,15 +97,12 @@ pub fn init<R: Runtime>(f: Box<SingleInstanceCallback<R>>) -> TauriPlugin<R> {
} else {
app.manage(MutexHandle(hmutex as _));
let hwnd = create_event_target_window::<R>(&class_name, &window_name);
unsafe {
SetWindowLongPtrW(
hwnd,
GWL_USERDATA,
Box::into_raw(Box::new((app.clone(), f))) as _,
)
let userdata = UserData {
app: app.clone(),
callback,
};
let userdata = Box::into_raw(Box::new(userdata));
let hwnd = create_event_target_window::<R>(&class_name, &window_name, userdata);
app.manage(TargetWindowHandle(hwnd as _));
}
@@ -116,32 +134,43 @@ unsafe extern "system" fn single_instance_window_proc<R: Runtime>(
wparam: WPARAM,
lparam: LPARAM,
) -> LRESULT {
let data_ptr = GetWindowLongPtrW(hwnd, GWL_USERDATA)
as *mut (AppHandle<R>, Box<SingleInstanceCallback<R>>);
let (app_handle, callback) = &mut *data_ptr;
match msg {
WM_CREATE => {
let create_struct = &*(lparam as *const CREATESTRUCTW);
let userdata = create_struct.lpCreateParams as *const UserData<R>;
SetWindowLongPtrW(hwnd, GWLP_USERDATA, userdata as _);
0
}
WM_COPYDATA => {
let cds_ptr = lparam as *const COPYDATASTRUCT;
if (*cds_ptr).dwData == WMCOPYDATA_SINGLE_INSTANCE_DATA {
let userdata = UserData::<R>::from_hwnd(hwnd);
let data = CStr::from_ptr((*cds_ptr).lpData as _).to_string_lossy();
let mut s = data.split('|');
let cwd = s.next().unwrap();
let args = s.map(|s| s.to_string()).collect();
callback(app_handle, args, cwd.to_string());
userdata.run_callback(args, cwd.to_string());
}
1
}
WM_DESTROY => {
let _ = Box::from_raw(data_ptr);
let userdata = UserData::<R>::from_hwnd_raw(hwnd);
drop(Box::from_raw(userdata));
0
}
_ => DefWindowProcW(hwnd, msg, wparam, lparam),
}
}
fn create_event_target_window<R: Runtime>(class_name: &[u16], window_name: &[u16]) -> HWND {
fn create_event_target_window<R: Runtime>(
class_name: &[u16],
window_name: &[u16],
userdata: *const UserData<R>,
) -> HWND {
unsafe {
let class = WNDCLASSEXW {
cbSize: std::mem::size_of::<WNDCLASSEXW>() as u32,
@@ -182,7 +211,7 @@ fn create_event_target_window<R: Runtime>(class_name: &[u16], window_name: &[u16
std::ptr::null_mut(),
std::ptr::null_mut(),
GetModuleHandleW(std::ptr::null()),
std::ptr::null(),
userdata as _,
);
SetWindowLongPtrW(
hwnd,
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_STORE__=function(t){"use strict";var e,a;function r(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}async function s(t,e={},a){return window.__TAURI_INTERNALS__.invoke(t,e,a)}"function"==typeof SuppressedError&&SuppressedError;class i{get rid(){return function(t,e,a,r){if("a"===a&&!r)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!r:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===a?r:"a"===a?r.call(t):r?r.value:e.get(t)}(this,e,"f")}constructor(t){e.set(this,void 0),function(t,e,a){if("function"==typeof e||!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");e.set(t,a)}(this,e,t)}async close(){return s("plugin:resources|close",{rid:this.rid})}}async function n(t,e,a){const i={kind:"Any"};return s("plugin:event|listen",{event:t,target:i,handler:r(e)}).then((e=>async()=>async function(t,e){await s("plugin:event|unlisten",{event:t,eventId:e})}(t,e)))}async function o(t,e){return await u.load(t,e)}e=new WeakMap,function(t){t.WINDOW_RESIZED="tauri://resize",t.WINDOW_MOVED="tauri://move",t.WINDOW_CLOSE_REQUESTED="tauri://close-requested",t.WINDOW_DESTROYED="tauri://destroyed",t.WINDOW_FOCUS="tauri://focus",t.WINDOW_BLUR="tauri://blur",t.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",t.WINDOW_THEME_CHANGED="tauri://theme-changed",t.WINDOW_CREATED="tauri://window-created",t.WEBVIEW_CREATED="tauri://webview-created",t.DRAG_ENTER="tauri://drag-enter",t.DRAG_OVER="tauri://drag-over",t.DRAG_DROP="tauri://drag-drop",t.DRAG_LEAVE="tauri://drag-leave"}(a||(a={}));class u extends i{constructor(t){super(t)}static async load(t,e){const a=await s("plugin:store|load",{path:t,...e});return new u(a)}static async get(t){return await s("plugin:store|get_store",{path:t}).then((t=>t?new u(t):null))}async set(t,e){await s("plugin:store|set",{rid:this.rid,key:t,value:e})}async get(t){const[e,a]=await s("plugin:store|get",{rid:this.rid,key:t});return a?e:void 0}async has(t){return await s("plugin:store|has",{rid:this.rid,key:t})}async delete(t){return await s("plugin:store|delete",{rid:this.rid,key:t})}async clear(){await s("plugin:store|clear",{rid:this.rid})}async reset(){await s("plugin:store|reset",{rid:this.rid})}async keys(){return await s("plugin:store|keys",{rid:this.rid})}async values(){return await s("plugin:store|values",{rid:this.rid})}async entries(){return await s("plugin:store|entries",{rid:this.rid})}async length(){return await s("plugin:store|length",{rid:this.rid})}async reload(){await s("plugin:store|reload",{rid:this.rid})}async save(){await s("plugin:store|save",{rid:this.rid})}async onKeyChange(t,e){return await n("store://change",(a=>{a.payload.resourceId===this.rid&&a.payload.key===t&&e(a.payload.exists?a.payload.value:void 0)}))}async onChange(t){return await n("store://change",(e=>{e.payload.resourceId===this.rid&&t(e.payload.key,e.payload.exists?e.payload.value:void 0)}))}}return t.LazyStore=class{get store(){return this._store||(this._store=o(this.path,this.options)),this._store}constructor(t,e){this.path=t,this.options=e}async init(){await this.store}async set(t,e){return(await this.store).set(t,e)}async get(t){return(await this.store).get(t)}async has(t){return(await this.store).has(t)}async delete(t){return(await this.store).delete(t)}async clear(){await(await this.store).clear()}async reset(){await(await this.store).reset()}async keys(){return(await this.store).keys()}async values(){return(await this.store).values()}async entries(){return(await this.store).entries()}async length(){return(await this.store).length()}async reload(){await(await this.store).reload()}async save(){await(await this.store).save()}async onKeyChange(t,e){return(await this.store).onKeyChange(t,e)}async onChange(t){return(await this.store).onChange(t)}async close(){this._store&&await(await this._store).close()}},t.Store=u,t.getStore=async function(t){return await u.get(t)},t.load=o,t}({});Object.defineProperty(window.__TAURI__,"store",{value:__TAURI_PLUGIN_STORE__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_STORE__=function(t){"use strict";var e,a;function r(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}async function s(t,e={},a){return window.__TAURI_INTERNALS__.invoke(t,e,a)}"function"==typeof SuppressedError&&SuppressedError;class i{get rid(){return function(t,e,a,r){if("function"==typeof e||!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===a?r:"a"===a?r.call(t):r?r.value:e.get(t)}(this,e,"f")}constructor(t){e.set(this,void 0),function(t,e,a){if("function"==typeof e||!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");e.set(t,a)}(this,e,t)}async close(){return s("plugin:resources|close",{rid:this.rid})}}async function n(t,e,a){const i={kind:"Any"};return s("plugin:event|listen",{event:t,target:i,handler:r(e)}).then((e=>async()=>async function(t,e){await s("plugin:event|unlisten",{event:t,eventId:e})}(t,e)))}async function o(t,e){return await u.load(t,e)}e=new WeakMap,function(t){t.WINDOW_RESIZED="tauri://resize",t.WINDOW_MOVED="tauri://move",t.WINDOW_CLOSE_REQUESTED="tauri://close-requested",t.WINDOW_DESTROYED="tauri://destroyed",t.WINDOW_FOCUS="tauri://focus",t.WINDOW_BLUR="tauri://blur",t.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",t.WINDOW_THEME_CHANGED="tauri://theme-changed",t.WINDOW_CREATED="tauri://window-created",t.WEBVIEW_CREATED="tauri://webview-created",t.DRAG_ENTER="tauri://drag-enter",t.DRAG_OVER="tauri://drag-over",t.DRAG_DROP="tauri://drag-drop",t.DRAG_LEAVE="tauri://drag-leave"}(a||(a={}));class u extends i{constructor(t){super(t)}static async load(t,e){const a=await s("plugin:store|load",{path:t,...e});return new u(a)}static async get(t){return await s("plugin:store|get_store",{path:t}).then((t=>t?new u(t):null))}async set(t,e){await s("plugin:store|set",{rid:this.rid,key:t,value:e})}async get(t){const[e,a]=await s("plugin:store|get",{rid:this.rid,key:t});return a?e:void 0}async has(t){return await s("plugin:store|has",{rid:this.rid,key:t})}async delete(t){return await s("plugin:store|delete",{rid:this.rid,key:t})}async clear(){await s("plugin:store|clear",{rid:this.rid})}async reset(){await s("plugin:store|reset",{rid:this.rid})}async keys(){return await s("plugin:store|keys",{rid:this.rid})}async values(){return await s("plugin:store|values",{rid:this.rid})}async entries(){return await s("plugin:store|entries",{rid:this.rid})}async length(){return await s("plugin:store|length",{rid:this.rid})}async reload(){await s("plugin:store|reload",{rid:this.rid})}async save(){await s("plugin:store|save",{rid:this.rid})}async onKeyChange(t,e){return await n("store://change",(a=>{a.payload.resourceId===this.rid&&a.payload.key===t&&e(a.payload.exists?a.payload.value:void 0)}))}async onChange(t){return await n("store://change",(e=>{e.payload.resourceId===this.rid&&t(e.payload.key,e.payload.exists?e.payload.value:void 0)}))}}return t.LazyStore=class{get store(){return this._store||(this._store=o(this.path,this.options)),this._store}constructor(t,e){this.path=t,this.options=e}async init(){await this.store}async set(t,e){return(await this.store).set(t,e)}async get(t){return(await this.store).get(t)}async has(t){return(await this.store).has(t)}async delete(t){return(await this.store).delete(t)}async clear(){await(await this.store).clear()}async reset(){await(await this.store).reset()}async keys(){return(await this.store).keys()}async values(){return(await this.store).values()}async entries(){return(await this.store).entries()}async length(){return(await this.store).length()}async reload(){await(await this.store).reload()}async save(){await(await this.store).save()}async onKeyChange(t,e){return(await this.store).onKeyChange(t,e)}async onChange(t){return(await this.store).onChange(t)}async close(){this._store&&await(await this._store).close()}},t.Store=u,t.getStore=async function(t){return await u.get(t)},t.load=o,t}({});Object.defineProperty(window.__TAURI__,"store",{value:__TAURI_PLUGIN_STORE__})}
@@ -8,8 +8,8 @@
"tauri": "tauri"
},
"devDependencies": {
"@tauri-apps/cli": "2.2.7",
"vite": "^6.0.0",
"typescript": "^5.4.7"
"@tauri-apps/cli": "2.3.1",
"typescript": "^5.7.3",
"vite": "^6.2.0"
}
}
+14
View File
@@ -1,5 +1,19 @@
# Changelog
## \[2.6.0]
- [`faefcc9f`](https://github.com/tauri-apps/plugins-workspace/commit/faefcc9fd8c61f709d491649e255a7fcac82c09a) ([#2430](https://github.com/tauri-apps/plugins-workspace/pull/2430) by [@goenning](https://github.com/tauri-apps/plugins-workspace/../../goenning)) Add `UpdaterBuilder::configure_client` method on Rust side, to configure the `reqwest` client used to check and download the update.
- [`ac60d589`](https://github.com/tauri-apps/plugins-workspace/commit/ac60d589eca2bbc4aed040feb18da148e66ec171) ([#2513](https://github.com/tauri-apps/plugins-workspace/pull/2513) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Enhance error logging.
## \[2.5.1]
- [`6f881293`](https://github.com/tauri-apps/plugins-workspace/commit/6f881293fcd67838f6f3f8063f536292431dd1f7) ([#2439](https://github.com/tauri-apps/plugins-workspace/pull/2439) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Fixed an issue that caused the plugin to emit a `ReleaseNotFound` error instead of a `Reqwest` error when the http request in `check()` failed.
## \[2.5.0]
- [`5369898d`](https://github.com/tauri-apps/plugins-workspace/commit/5369898db7a6098e3e2f43436100ea556d405628) ([#2067](https://github.com/tauri-apps/plugins-workspace/pull/2067) by [@jLynx](https://github.com/tauri-apps/plugins-workspace/../../jLynx)) Fix update installation on macOS when using an user without admin privileges.
- [`5369898d`](https://github.com/tauri-apps/plugins-workspace/commit/5369898db7a6098e3e2f43436100ea556d405628) ([#2067](https://github.com/tauri-apps/plugins-workspace/pull/2067) by [@jLynx](https://github.com/tauri-apps/plugins-workspace/../../jLynx)) Remove the `UpdaterBuilder::new` function, use `UpdaterExt::updater_builder` instead.
## \[2.4.0]
- [`0afc9b6b`](https://github.com/tauri-apps/plugins-workspace/commit/0afc9b6be07bee1077f05a86285d977e57810ed9) ([#2325](https://github.com/tauri-apps/plugins-workspace/pull/2325) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) The `Update` struct/object will now contain a `raw_json`/`rawJson` property to be able to read parts of server's json response that are not handled by the plugin.
+5 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-updater"
version = "2.4.0"
version = "2.6.0"
description = "In-app updates for Tauri applications."
edition = { workspace = true }
authors = { workspace = true }
@@ -30,6 +30,7 @@ tauri = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
thiserror = { workspace = true }
log = { workspace = true }
tokio = "1"
reqwest = { version = "0.12", default-features = false, features = [
"json",
@@ -43,7 +44,7 @@ base64 = "0.22"
semver = { version = "1", features = ["serde"] }
futures-util = "0.3"
tempfile = "3"
infer = "0.16"
infer = "0.19"
percent-encoding = "2.3"
[target."cfg(target_os = \"windows\")".dependencies]
@@ -55,13 +56,14 @@ windows-sys = { version = "0.59.0", features = [
] }
[target."cfg(target_os = \"linux\")".dependencies]
dirs = "5"
dirs = "6"
tar = { version = "0.4", optional = true }
flate2 = { version = "1", optional = true }
[target."cfg(target_os = \"macos\")".dependencies]
tar = "0.4"
flate2 = "1"
osakit = { version = "0.3", features = ["full"] }
[features]
default = ["rustls-tls", "zip"]
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_UPDATER__=function(e){"use strict";function t(e,t,s,i){if("a"===s&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!i:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===s?i:"a"===s?i.call(e):i?i.value:t.get(e)}function s(e,t,s,i,n){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(e,s),s}var i,n,r,a;"function"==typeof SuppressedError&&SuppressedError;const o="__TAURI_TO_IPC_KEY__";class d{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),n.set(this,0),r.set(this,[]),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((({message:e,id:a})=>{if(a==t(this,n,"f"))for(t(this,i,"f").call(this,e),s(this,n,t(this,n,"f")+1);t(this,n,"f")in t(this,r,"f");){const e=t(this,r,"f")[t(this,n,"f")];t(this,i,"f").call(this,e),delete t(this,r,"f")[t(this,n,"f")],s(this,n,t(this,n,"f")+1)}else t(this,r,"f")[a]=e}))}set onmessage(e){s(this,i,e)}get onmessage(){return t(this,i,"f")}[(i=new WeakMap,n=new WeakMap,r=new WeakMap,o)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[o]()}}async function l(e,t={},s){return window.__TAURI_INTERNALS__.invoke(e,t,s)}class h{get rid(){return t(this,a,"f")}constructor(e){a.set(this,void 0),s(this,a,e)}async close(){return l("plugin:resources|close",{rid:this.rid})}}a=new WeakMap;class c extends h{constructor(e){super(e.rid),this.available=e.available,this.currentVersion=e.currentVersion,this.version=e.version,this.date=e.date,this.body=e.body,this.rawJson=e.rawJson}async download(e,t){const s=new d;e&&(s.onmessage=e);const i=await l("plugin:updater|download",{onEvent:s,rid:this.rid,...t});this.downloadedBytes=new h(i)}async install(){if(!this.downloadedBytes)throw new Error("Update.install called before Update.download");await l("plugin:updater|install",{updateRid:this.rid,bytesRid:this.downloadedBytes.rid}),this.downloadedBytes=void 0}async downloadAndInstall(e,t){const s=new d;e&&(s.onmessage=e),await l("plugin:updater|download_and_install",{onEvent:s,rid:this.rid,...t})}async close(){await(this.downloadedBytes?.close()),await super.close()}}return e.Update=c,e.check=async function(e){return e?.headers&&(e.headers=Array.from(new Headers(e.headers).entries())),await l("plugin:updater|check",{...e}).then((e=>e.available?new c(e):null))},e}({});Object.defineProperty(window.__TAURI__,"updater",{value:__TAURI_PLUGIN_UPDATER__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_UPDATER__=function(e){"use strict";function t(e,t,s,n){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===s?n:"a"===s?n.call(e):n?n.value:t.get(e)}function s(e,t,s,n,i){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(e,s),s}var n,i,a,r;"function"==typeof SuppressedError&&SuppressedError;const o="__TAURI_TO_IPC_KEY__";class d{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,n.set(this,(()=>{})),i.set(this,0),a.set(this,[]),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((({message:e,id:r})=>{if(r==t(this,i,"f"))for(t(this,n,"f").call(this,e),s(this,i,t(this,i,"f")+1);t(this,i,"f")in t(this,a,"f");){const e=t(this,a,"f")[t(this,i,"f")];t(this,n,"f").call(this,e),delete t(this,a,"f")[t(this,i,"f")],s(this,i,t(this,i,"f")+1)}else t(this,a,"f")[r]=e}))}set onmessage(e){s(this,n,e)}get onmessage(){return t(this,n,"f")}[(n=new WeakMap,i=new WeakMap,a=new WeakMap,o)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[o]()}}async function l(e,t={},s){return window.__TAURI_INTERNALS__.invoke(e,t,s)}class h{get rid(){return t(this,r,"f")}constructor(e){r.set(this,void 0),s(this,r,e)}async close(){return l("plugin:resources|close",{rid:this.rid})}}r=new WeakMap;class c extends h{constructor(e){super(e.rid),this.available=e.available,this.currentVersion=e.currentVersion,this.version=e.version,this.date=e.date,this.body=e.body,this.rawJson=e.rawJson}async download(e,t){const s=new d;e&&(s.onmessage=e);const n=await l("plugin:updater|download",{onEvent:s,rid:this.rid,...t});this.downloadedBytes=new h(n)}async install(){if(!this.downloadedBytes)throw new Error("Update.install called before Update.download");await l("plugin:updater|install",{updateRid:this.rid,bytesRid:this.downloadedBytes.rid}),this.downloadedBytes=void 0}async downloadAndInstall(e,t){const s=new d;e&&(s.onmessage=e),await l("plugin:updater|download_and_install",{onEvent:s,rid:this.rid,...t})}async close(){await(this.downloadedBytes?.close()),await super.close()}}return e.Update=c,e.check=async function(e){return e?.headers&&(e.headers=Array.from(new Headers(e.headers).entries())),await l("plugin:updater|check",{...e}).then((e=>e.available?new c(e):null))},e}({});Object.defineProperty(window.__TAURI__,"updater",{value:__TAURI_PLUGIN_UPDATER__})}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-updater",
"version": "2.4.0",
"version": "2.6.0",
"license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
+1 -7
View File
@@ -70,7 +70,6 @@ pub trait UpdaterExt<R: Runtime> {
impl<R: Runtime, T: Manager<R>> UpdaterExt<R> for T {
fn updater_builder(&self) -> UpdaterBuilder {
let app = self.app_handle();
let package_info = app.package_info();
let UpdaterState {
config,
target,
@@ -78,12 +77,7 @@ impl<R: Runtime, T: Manager<R>> UpdaterExt<R> for T {
headers,
} = self.state::<UpdaterState>().inner();
let mut builder = UpdaterBuilder::new(
package_info.name.clone(),
package_info.version.clone(),
config.clone(),
)
.headers(headers.clone());
let mut builder = UpdaterBuilder::new(app, config.clone()).headers(headers.clone());
if let Some(target) = target {
builder = builder.target(target);
+161 -46
View File
@@ -4,7 +4,7 @@
use std::{
collections::HashMap,
ffi::{OsStr, OsString},
ffi::OsString,
io::Cursor,
path::{Path, PathBuf},
str::FromStr,
@@ -12,6 +12,9 @@ use std::{
time::Duration,
};
#[cfg(not(target_os = "macos"))]
use std::ffi::OsStr;
use base64::Engine;
use futures_util::StreamExt;
use http::HeaderName;
@@ -23,7 +26,7 @@ use reqwest::{
};
use semver::Version;
use serde::{de::Error as DeError, Deserialize, Deserializer, Serialize};
use tauri::{utils::platform::current_exe, Resource};
use tauri::{utils::platform::current_exe, AppHandle, Resource, Runtime};
use time::OffsetDateTime;
use url::Url;
@@ -93,9 +96,15 @@ impl RemoteRelease {
}
pub type OnBeforeExit = Arc<dyn Fn() + Send + Sync + 'static>;
pub type OnBeforeRequest = Arc<dyn Fn(ClientBuilder) -> ClientBuilder + Send + Sync + 'static>;
pub type VersionComparator = Arc<dyn Fn(Version, RemoteRelease) -> bool + Send + Sync>;
type MainThreadClosure = Box<dyn FnOnce() + Send + Sync + 'static>;
type RunOnMainThread =
Box<dyn Fn(MainThreadClosure) -> std::result::Result<(), tauri::Error> + Send + Sync + 'static>;
pub struct UpdaterBuilder {
#[allow(dead_code)]
run_on_main_thread: RunOnMainThread,
app_name: String,
current_version: Version,
config: Config,
@@ -109,21 +118,24 @@ pub struct UpdaterBuilder {
installer_args: Vec<OsString>,
current_exe_args: Vec<OsString>,
on_before_exit: Option<OnBeforeExit>,
configure_client: Option<OnBeforeRequest>,
}
impl UpdaterBuilder {
/// It's prefered to use [`crate::UpdaterExt::updater_builder`] instead of
/// constructing a [`UpdaterBuilder`] with this function yourself
pub fn new(app_name: String, current_version: Version, config: crate::Config) -> Self {
pub(crate) fn new<R: Runtime>(app: &AppHandle<R>, config: crate::Config) -> Self {
let app_ = app.clone();
let run_on_main_thread =
move |f: Box<dyn FnOnce() + Send + Sync + 'static>| app_.run_on_main_thread(f);
Self {
run_on_main_thread: Box::new(run_on_main_thread),
installer_args: config
.windows
.as_ref()
.map(|w| w.installer_args.clone())
.unwrap_or_default(),
current_exe_args: Vec::new(),
app_name,
current_version,
app_name: app.package_info().name.clone(),
current_version: app.package_info().version.clone(),
config,
version_comparator: None,
executable_path: None,
@@ -133,6 +145,7 @@ impl UpdaterBuilder {
timeout: None,
proxy: None,
on_before_exit: None,
configure_client: None,
}
}
@@ -232,6 +245,19 @@ impl UpdaterBuilder {
self
}
/// Allows you to modify the `reqwest` client builder before the HTTP request is sent.
///
/// Note that `reqwest` crate may be updated in minor releases of tauri-plugin-updater.
/// Therefore it's recommended to pin the plugin to at least a minor version when you're using `configure_client`.
///
pub fn configure_client<F: Fn(ClientBuilder) -> ClientBuilder + Send + Sync + 'static>(
mut self,
f: F,
) -> Self {
self.configure_client.replace(Arc::new(f));
self
}
pub fn build(self) -> Result<Updater> {
let endpoints = self
.endpoints
@@ -259,6 +285,7 @@ impl UpdaterBuilder {
};
Ok(Updater {
run_on_main_thread: Arc::new(self.run_on_main_thread),
config: self.config,
app_name: self.app_name,
current_version: self.current_version,
@@ -274,6 +301,7 @@ impl UpdaterBuilder {
headers: self.headers,
extract_path,
on_before_exit: self.on_before_exit,
configure_client: self.configure_client,
})
}
}
@@ -291,6 +319,8 @@ impl UpdaterBuilder {
}
pub struct Updater {
#[allow(dead_code)]
run_on_main_thread: Arc<RunOnMainThread>,
config: Config,
app_name: String,
current_version: Version,
@@ -306,6 +336,7 @@ pub struct Updater {
headers: HeaderMap,
extract_path: PathBuf,
on_before_exit: Option<OnBeforeExit>,
configure_client: Option<OnBeforeRequest>,
#[allow(unused)]
installer_args: Vec<OsString>,
#[allow(unused)]
@@ -358,14 +389,22 @@ impl Updater {
.replace("{{arch}}", self.arch)
.parse()?;
log::debug!("checking for updates {url}");
let mut request = ClientBuilder::new().user_agent(UPDATER_USER_AGENT);
if let Some(timeout) = self.timeout {
request = request.timeout(timeout);
}
if let Some(ref proxy) = self.proxy {
log::debug!("using proxy {proxy}");
let proxy = reqwest::Proxy::all(proxy.as_str())?;
request = request.proxy(proxy);
}
if let Some(ref configure_client) = self.configure_client {
request = configure_client(request);
}
let response = request
.build()?
.get(url)
@@ -373,26 +412,43 @@ impl Updater {
.send()
.await;
if let Ok(res) = response {
if res.status().is_success() {
// no updates found!
if StatusCode::NO_CONTENT == res.status() {
return Ok(None);
};
match response {
Ok(res) => {
if res.status().is_success() {
// no updates found!
if StatusCode::NO_CONTENT == res.status() {
log::debug!("update endpoint returned 204 No Content");
return Ok(None);
};
raw_json = Some(res.json().await?);
match serde_json::from_value::<RemoteRelease>(raw_json.clone().unwrap())
.map_err(Into::into)
{
Ok(release) => {
last_error = None;
remote_release = Some(release);
// we found a relase, break the loop
break;
let update_response: serde_json::Value = res.json().await?;
log::debug!("update response: {update_response:?}");
raw_json = Some(update_response.clone());
match serde_json::from_value::<RemoteRelease>(update_response)
.map_err(Into::into)
{
Ok(release) => {
log::debug!("parsed release response {release:?}");
last_error = None;
remote_release = Some(release);
// we found a release, break the loop
break;
}
Err(err) => {
log::error!("failed to deserialize update response: {err}");
last_error = Some(err)
}
}
Err(err) => last_error = Some(err),
} else {
log::error!(
"update endpoint did not respond with a successful status code"
);
}
}
Err(err) => {
log::error!("failed to check for updates: {err}");
last_error = Some(err.into())
}
}
}
@@ -412,6 +468,7 @@ impl Updater {
let update = if should_update {
Some(Update {
run_on_main_thread: self.run_on_main_thread.clone(),
config: self.config.clone(),
on_before_exit: self.on_before_exit.clone(),
app_name: self.app_name.clone(),
@@ -429,6 +486,7 @@ impl Updater {
headers: self.headers.clone(),
installer_args: self.installer_args.clone(),
current_exe_args: self.current_exe_args.clone(),
configure_client: self.configure_client.clone(),
})
} else {
None
@@ -440,6 +498,8 @@ impl Updater {
#[derive(Clone)]
pub struct Update {
#[allow(dead_code)]
run_on_main_thread: Arc<RunOnMainThread>,
config: Config,
#[allow(unused)]
on_before_exit: Option<OnBeforeExit>,
@@ -475,6 +535,7 @@ pub struct Update {
installer_args: Vec<OsString>,
#[allow(unused)]
current_exe_args: Vec<OsString>,
configure_client: Option<OnBeforeRequest>,
}
impl Resource for Update {}
@@ -503,6 +564,9 @@ impl Update {
let proxy = reqwest::Proxy::all(proxy.as_str())?;
request = request.proxy(proxy);
}
if let Some(ref configure_client) = self.configure_client {
request = configure_client(request);
}
let response = request
.build()?
.get(self.download_url.clone())
@@ -651,6 +715,7 @@ impl Update {
};
if let Some(on_before_exit) = self.on_before_exit.as_ref() {
log::debug!("running on_before_exit hook");
on_before_exit();
}
@@ -819,6 +884,7 @@ impl Update {
#[cfg(feature = "zip")]
if infer::archive::is_gz(bytes) {
log::debug!("extracting AppImage");
// extract the buffer to the tmp_dir
// we extract our signed archive into our final directory without any temp file
let archive = Cursor::new(bytes);
@@ -842,6 +908,7 @@ impl Update {
return Err(Error::BinaryNotFoundInArchive);
}
log::debug!("rewriting AppImage");
return match std::fs::write(&self.extract_path, bytes)
.and_then(|_| std::fs::set_permissions(&self.extract_path, permissions))
{
@@ -895,6 +962,7 @@ impl Update {
fn install_deb(&self, bytes: &[u8]) -> Result<()> {
// First verify the bytes are actually a .deb package
if !infer::archive::is_deb(bytes) {
log::warn!("update is not a valid deb package");
return Err(Error::InvalidUpdaterFormat);
}
@@ -937,6 +1005,7 @@ impl Update {
.status()
{
if status.success() {
log::debug!("installed deb with pkexec");
return Ok(());
}
}
@@ -944,6 +1013,7 @@ impl Update {
// 2. Try zenity or kdialog for a graphical sudo experience
if let Ok(password) = self.get_password_graphically() {
if self.install_with_sudo(deb_path, &password)? {
log::debug!("installed deb with GUI sudo");
return Ok(());
}
}
@@ -956,6 +1026,7 @@ impl Update {
.status()?;
if status.success() {
log::debug!("installed deb with sudo");
Ok(())
} else {
Err(Error::DebInstallFailed)
@@ -1031,42 +1102,86 @@ impl Update {
let cursor = Cursor::new(bytes);
let mut extracted_files: Vec<PathBuf> = Vec::new();
// the first file in the tar.gz will always be
// <app_name>/Contents
let tmp_dir = tempfile::Builder::new()
// Create temp directories for backup and extraction
let tmp_backup_dir = tempfile::Builder::new()
.prefix("tauri_current_app")
.tempdir()?;
// create backup of our current app
std::fs::rename(&self.extract_path, tmp_dir.path())?;
let tmp_extract_dir = tempfile::Builder::new()
.prefix("tauri_updated_app")
.tempdir()?;
let decoder = GzDecoder::new(cursor);
let mut archive = tar::Archive::new(decoder);
std::fs::create_dir(&self.extract_path)?;
// Extract files to temporary directory
for entry in archive.entries()? {
let mut entry = entry?;
// skip the first folder (should be the app name)
let collected_path: PathBuf = entry.path()?.iter().skip(1).collect();
let extraction_path = &self.extract_path.join(collected_path);
let extraction_path = tmp_extract_dir.path().join(&collected_path);
// if something went wrong during the extraction, we should restore previous app
if let Err(err) = entry.unpack(extraction_path) {
for file in extracted_files.iter().rev() {
// delete all the files we extracted
if file.is_dir() {
std::fs::remove_dir(file)?;
} else {
std::fs::remove_file(file)?;
}
}
std::fs::rename(tmp_dir.path(), &self.extract_path)?;
return Err(err.into());
// Ensure parent directories exist
if let Some(parent) = extraction_path.parent() {
std::fs::create_dir_all(parent)?;
}
extracted_files.push(extraction_path.to_path_buf());
if let Err(err) = entry.unpack(&extraction_path) {
// Cleanup on error
std::fs::remove_dir_all(tmp_extract_dir.path()).ok();
return Err(err.into());
}
extracted_files.push(extraction_path);
}
// Try to move the current app to backup
let move_result = std::fs::rename(
&self.extract_path,
tmp_backup_dir.path().join("current_app"),
);
let need_authorization = if let Err(err) = move_result {
if err.kind() == std::io::ErrorKind::PermissionDenied {
true
} else {
std::fs::remove_dir_all(tmp_extract_dir.path()).ok();
return Err(err.into());
}
} else {
false
};
if need_authorization {
log::debug!("app installation needs admin privileges");
// Use AppleScript to perform moves with admin privileges
let apple_script = format!(
"do shell script \"rm -rf '{src}' && mv -f '{new}' '{src}'\" with administrator privileges",
src = self.extract_path.display(),
new = tmp_extract_dir.path().display()
);
let (tx, rx) = std::sync::mpsc::channel();
let res = (self.run_on_main_thread)(Box::new(move || {
let mut script =
osakit::Script::new_from_source(osakit::Language::AppleScript, &apple_script);
script.compile().expect("invalid AppleScript");
let r = script.execute();
tx.send(r).unwrap();
}));
let result = rx.recv().unwrap();
if res.is_err() || result.is_err() {
std::fs::remove_dir_all(tmp_extract_dir.path()).ok();
return Err(Error::Io(std::io::Error::new(
std::io::ErrorKind::PermissionDenied,
"Failed to move the new app into place",
)));
}
} else {
// Remove existing directory if it exists
if self.extract_path.exists() {
std::fs::remove_dir_all(&self.extract_path)?;
}
// Move the new app to the target path
std::fs::rename(tmp_extract_dir.path(), &self.extract_path)?;
}
let _ = std::process::Command::new("touch")
@@ -63,8 +63,6 @@ fn build_app(cwd: &Path, config: &Config, bundle_updater: bool, target: BundleTa
if bundle_updater {
#[cfg(windows)]
command.args(["--bundles", "msi", "nsis"]);
command.args(["--bundles", "updater"]);
} else {
#[cfg(windows)]
command.args(["--bundles", target.name()]);
@@ -67,8 +67,6 @@ mod v1 {
if bundle_updater {
#[cfg(windows)]
command.args(["--bundles", "msi", "nsis"]);
command.args(["--bundles", "updater"]);
} else {
#[cfg(windows)]
command.args(["--bundles", target.name()]);
@@ -173,8 +171,6 @@ mod v2 {
if bundle_updater {
#[cfg(windows)]
command.args(["--bundles", "msi", "nsis"]);
command.args(["--bundles", "updater"]);
} else {
#[cfg(windows)]
command.args(["--bundles", target.name()]);
+4 -4
View File
@@ -1822,9 +1822,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "openssl"
version = "0.10.66"
version = "0.10.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1"
checksum = "61cfb4e166a8bb8c9b55c500bc2308550148ece889be90f609377e58140f42c6"
dependencies = [
"bitflags 2.6.0",
"cfg-if",
@@ -1854,9 +1854,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
version = "0.9.103"
version = "0.9.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6"
checksum = "8b22d5b84be05a8d6947c7cb71f7c849aa0f112acd4bf51c2a7c1c988ac0a9dc"
dependencies = [
"cc",
"libc",
+4
View File
@@ -2,6 +2,10 @@
## \[2.2.1]
- [`ca7395a5`](https://github.com/tauri-apps/plugins-workspace/commit/ca7395a5ce971cbac25fb54285056edf3dd84e1f) ([#2378](https://github.com/tauri-apps/plugins-workspace/pull/2378) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) the `rustls-tls` feature is now enabled by default
## \[2.2.1]
- [`05c62d73`](https://github.com/tauri-apps/plugins-workspace/commit/05c62d731fa48fd06b8cb3694a962d8cb0db8619) ([#1523](https://github.com/tauri-apps/plugins-workspace/pull/1523) by [@enri90](https://github.com/tauri-apps/plugins-workspace/../../enri90)) Added post request on download function
## \[2.2.0]
+3 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-upload"
version = "2.2.0"
version = "2.2.1"
description = "Upload files from disk to a remote server over HTTP."
authors = { workspace = true }
license = { workspace = true }
@@ -32,6 +32,7 @@ thiserror = { workspace = true }
tokio = { version = "1", features = ["fs"] }
tokio-util = { version = "0.7", features = ["codec"] }
reqwest = { version = "0.12", default-features = false, features = [
"macos-system-configuration",
"json",
"stream",
] }
@@ -39,6 +40,7 @@ futures-util = "0.3"
read-progress-stream = "1.0.0"
[features]
default = ["rustls-tls"]
native-tls = ["reqwest/native-tls"]
native-tls-vendored = ["reqwest/native-tls-vendored"]
rustls-tls = ["reqwest/rustls-tls"]
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_UPLOAD__=function(t){"use strict";function e(t,e,n,s){if("a"===n&&!s)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!s:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?s:"a"===n?s.call(t):s?s.value:e.get(t)}function n(t,e,n,s,i){if("function"==typeof e||!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,n),n}var s,i,o;"function"==typeof SuppressedError&&SuppressedError;const r="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,s.set(this,(()=>{})),i.set(this,0),o.set(this,[]),this.id=function(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}((({message:t,id:r})=>{if(r==e(this,i,"f"))for(e(this,s,"f").call(this,t),n(this,i,e(this,i,"f")+1);e(this,i,"f")in e(this,o,"f");){const t=e(this,o,"f")[e(this,i,"f")];e(this,s,"f").call(this,t),delete e(this,o,"f")[e(this,i,"f")],n(this,i,e(this,i,"f")+1)}else e(this,o,"f")[r]=t}))}set onmessage(t){n(this,s,t)}get onmessage(){return e(this,s,"f")}[(s=new WeakMap,i=new WeakMap,o=new WeakMap,r)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[r]()}}async function _(t,e={},n){return window.__TAURI_INTERNALS__.invoke(t,e,n)}return t.download=async function(t,e,n,s,i){const o=new Uint32Array(1);window.crypto.getRandomValues(o);const r=o[0],c=new a;n&&(c.onmessage=n),await _("plugin:upload|download",{id:r,url:t,filePath:e,headers:s??{},onProgress:c,body:i})},t.upload=async function(t,e,n,s){const i=new Uint32Array(1);window.crypto.getRandomValues(i);const o=i[0],r=new a;return n&&(r.onmessage=n),await _("plugin:upload|upload",{id:o,url:t,filePath:e,headers:s??{},onProgress:r})},t}({});Object.defineProperty(window.__TAURI__,"upload",{value:__TAURI_PLUGIN_UPLOAD__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_UPLOAD__=function(t){"use strict";function e(t,e,n,s){if("function"==typeof e||!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?s:"a"===n?s.call(t):s?s.value:e.get(t)}function n(t,e,n,s,i){if("function"==typeof e||!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,n),n}var s,i,o;"function"==typeof SuppressedError&&SuppressedError;const r="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,s.set(this,(()=>{})),i.set(this,0),o.set(this,[]),this.id=function(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}((({message:t,id:r})=>{if(r==e(this,i,"f"))for(e(this,s,"f").call(this,t),n(this,i,e(this,i,"f")+1);e(this,i,"f")in e(this,o,"f");){const t=e(this,o,"f")[e(this,i,"f")];e(this,s,"f").call(this,t),delete e(this,o,"f")[e(this,i,"f")],n(this,i,e(this,i,"f")+1)}else e(this,o,"f")[r]=t}))}set onmessage(t){n(this,s,t)}get onmessage(){return e(this,s,"f")}[(s=new WeakMap,i=new WeakMap,o=new WeakMap,r)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[r]()}}async function _(t,e={},n){return window.__TAURI_INTERNALS__.invoke(t,e,n)}return t.download=async function(t,e,n,s,i){const o=new Uint32Array(1);window.crypto.getRandomValues(o);const r=o[0],c=new a;n&&(c.onmessage=n),await _("plugin:upload|download",{id:r,url:t,filePath:e,headers:s??{},onProgress:c,body:i})},t.upload=async function(t,e,n,s){const i=new Uint32Array(1);window.crypto.getRandomValues(i);const o=i[0],r=new a;return n&&(r.onmessage=n),await _("plugin:upload|upload",{id:o,url:t,filePath:e,headers:s??{},onProgress:r})},t}({});Object.defineProperty(window.__TAURI__,"upload",{value:__TAURI_PLUGIN_UPLOAD__})}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-upload",
"version": "2.2.0",
"version": "2.2.1",
"description": "Upload files from disk to a remote server over HTTP.",
"license": "MIT OR Apache-2.0",
"authors": [
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_WEBSOCKET__=function(){"use strict";function e(e,t,s,n){if("a"===s&&!n)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!n:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===s?n:"a"===s?n.call(e):n?n.value:t.get(e)}function t(e,t,s,n,i){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(e,s),s}var s,n,i;"function"==typeof SuppressedError&&SuppressedError;const r="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,s.set(this,(()=>{})),n.set(this,0),i.set(this,[]),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((({message:r,id:a})=>{if(a==e(this,n,"f"))for(e(this,s,"f").call(this,r),t(this,n,e(this,n,"f")+1);e(this,n,"f")in e(this,i,"f");){const r=e(this,i,"f")[e(this,n,"f")];e(this,s,"f").call(this,r),delete e(this,i,"f")[e(this,n,"f")],t(this,n,e(this,n,"f")+1)}else e(this,i,"f")[a]=r}))}set onmessage(e){t(this,s,e)}get onmessage(){return e(this,s,"f")}[(s=new WeakMap,n=new WeakMap,i=new WeakMap,r)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[r]()}}async function o(e,t={},s){return window.__TAURI_INTERNALS__.invoke(e,t,s)}class c{constructor(e,t){this.id=e,this.listeners=t}static async connect(e,t){const s=new Set,n=new a;return n.onmessage=e=>{s.forEach((t=>{t(e)}))},t?.headers&&(t.headers=Array.from(new Headers(t.headers).entries())),await o("plugin:websocket|connect",{url:e,onMessage:n,config:t}).then((e=>new c(e,s)))}addListener(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}async send(e){let t;if("string"==typeof e)t={type:"Text",data:e};else if("object"==typeof e&&"type"in e)t=e;else{if(!Array.isArray(e))throw new Error("invalid `message` type, expected a `{ type: string, data: any }` object, a string or a numeric array");t={type:"Binary",data:e}}await o("plugin:websocket|send",{id:this.id,message:t})}async disconnect(){await this.send({type:"Close",data:{code:1e3,reason:"Disconnected by client"}})}}return c}();Object.defineProperty(window.__TAURI__,"websocket",{value:__TAURI_PLUGIN_WEBSOCKET__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_WEBSOCKET__=function(){"use strict";function e(e,t,s,n){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===s?n:"a"===s?n.call(e):n?n.value:t.get(e)}function t(e,t,s,n,i){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(e,s),s}var s,n,i;"function"==typeof SuppressedError&&SuppressedError;const r="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,s.set(this,(()=>{})),n.set(this,0),i.set(this,[]),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((({message:r,id:a})=>{if(a==e(this,n,"f"))for(e(this,s,"f").call(this,r),t(this,n,e(this,n,"f")+1);e(this,n,"f")in e(this,i,"f");){const r=e(this,i,"f")[e(this,n,"f")];e(this,s,"f").call(this,r),delete e(this,i,"f")[e(this,n,"f")],t(this,n,e(this,n,"f")+1)}else e(this,i,"f")[a]=r}))}set onmessage(e){t(this,s,e)}get onmessage(){return e(this,s,"f")}[(s=new WeakMap,n=new WeakMap,i=new WeakMap,r)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[r]()}}async function o(e,t={},s){return window.__TAURI_INTERNALS__.invoke(e,t,s)}class c{constructor(e,t){this.id=e,this.listeners=t}static async connect(e,t){const s=new Set,n=new a;return n.onmessage=e=>{s.forEach((t=>{t(e)}))},t?.headers&&(t.headers=Array.from(new Headers(t.headers).entries())),await o("plugin:websocket|connect",{url:e,onMessage:n,config:t}).then((e=>new c(e,s)))}addListener(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}async send(e){let t;if("string"==typeof e)t={type:"Text",data:e};else if("object"==typeof e&&"type"in e)t=e;else{if(!Array.isArray(e))throw new Error("invalid `message` type, expected a `{ type: string, data: any }` object, a string or a numeric array");t={type:"Binary",data:e}}await o("plugin:websocket|send",{id:this.id,message:t})}async disconnect(){await this.send({type:"Close",data:{code:1e3,reason:"Disconnected by client"}})}}return c}();Object.defineProperty(window.__TAURI__,"websocket",{value:__TAURI_PLUGIN_WEBSOCKET__})}
@@ -9,9 +9,9 @@
"preview": "vite preview"
},
"devDependencies": {
"@tauri-apps/cli": "2.2.7",
"typescript": "^5.3.3",
"vite": "^6.0.0"
"@tauri-apps/cli": "2.3.1",
"typescript": "^5.7.3",
"vite": "^6.2.0"
},
"dependencies": {
"tauri-plugin-websocket-api": "link:..\\.."
@@ -10,8 +10,9 @@ body {
margin: 0;
padding: 8px;
box-sizing: border-box;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;
font-family:
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu,
Cantarell, 'Helvetica Neue', sans-serif;
}
a {
File diff suppressed because one or more lines are too long
+854 -1132
View File
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -2,9 +2,9 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
import { readFileSync } from 'fs'
import { join } from 'path'
import { cwd } from 'process'
import { readFileSync } from 'node:fs'
import { dirname, join } from 'node:path'
import { cwd } from 'node:process'
import { nodeResolve } from '@rollup/plugin-node-resolve'
import typescript from '@rollup/plugin-typescript'
import terser from '@rollup/plugin-terser'
@@ -53,7 +53,7 @@ export function createConfig(options = {}) {
plugins: [
typescript({
declaration: true,
declarationDir: `./${pkg.exports.import.split('/')[0]}`
declarationDir: dirname(pkg.exports.import)
})
],
external: [
+2 -2
View File
@@ -21,9 +21,9 @@ mod models;
pub use error::{Error, Result};
#[cfg(desktop)]
use desktop::{{ plugin_name_pascal_case }};
pub use desktop::{{ plugin_name_pascal_case }};
#[cfg(mobile)]
use mobile::{{ plugin_name_pascal_case }};
pub use mobile::{{ plugin_name_pascal_case }};
/// Extensions to [`tauri::App`], [`tauri::AppHandle`], [`tauri::WebviewWindow`], [`tauri::Webview`] and [`tauri::Window`] to access the {{ plugin_name }} APIs.
pub trait {{ plugin_name_pascal_case }}Ext<R: Runtime> {