mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-05-03 12:15:11 +02:00
Compare commits
131 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b40a02c525 | |||
| a1b3fa27f1 | |||
| e54cfcb261 | |||
| 22ba197b80 | |||
| 77520a3587 | |||
| dbc5fe120a | |||
| faefcc9fd8 | |||
| ac60d589ec | |||
| cb38f54f4a | |||
| d37bbdef8d | |||
| 3a750c7300 | |||
| 5c9cf52e75 | |||
| 02df0421d6 | |||
| f7f5bbf259 | |||
| 561cf39f64 | |||
| 024815018f | |||
| e90cd9fab1 | |||
| 1b86af8e26 | |||
| 1dba334f00 | |||
| 54e7864507 | |||
| 45c7848714 | |||
| 393e956728 | |||
| 1a9846599b | |||
| 71f95c9f05 | |||
| 8b3cd9e827 | |||
| 39c022eea2 | |||
| 7527a3465a | |||
| abca2ebc0d | |||
| ddcfad46f9 | |||
| fbd4d28920 | |||
| 0af367f7d4 | |||
| 1ab5f15763 | |||
| c10d5bfb54 | |||
| f6838d507f | |||
| 5b3a1aaf73 | |||
| 3276d65801 | |||
| e0900f0451 | |||
| 4d38066ef9 | |||
| 3b37ce1508 | |||
| 6f881293fc | |||
| 9229f991fe | |||
| b3bf74212e | |||
| c5da9d2579 | |||
| 7a5495963b | |||
| 7d3869ced8 | |||
| fa8c544479 | |||
| 14660b6230 | |||
| 6b4c391738 | |||
| d5d9f7c970 | |||
| 63f9449c9a | |||
| e0cff9bcf4 | |||
| 5411db68a8 | |||
| 80804adc68 | |||
| 93edbd1434 | |||
| 3ebec74983 | |||
| 51f5aff58a | |||
| 5369898db7 | |||
| a7497b0aeb | |||
| aaa88fa45f | |||
| ca7395a5ce | |||
| 6ae853c2e6 | |||
| d5fb5337a0 | |||
| 512a188c7a | |||
| ad17266273 | |||
| 78acfa456f | |||
| 0b3b3a22d2 | |||
| 384b598fcf | |||
| b2fe305a84 | |||
| 68d8f3be38 | |||
| 9ac2aa88e6 | |||
| 18700f1e82 | |||
| 0afc9b6be0 | |||
| bda803fbdd | |||
| 105136494c | |||
| ce11079f19 | |||
| 784a54a390 | |||
| bdb7febf9c | |||
| e76272b619 | |||
| cf0dff049b | |||
| 28f5c33d65 | |||
| 5b82118158 | |||
| 125ec1dbcf | |||
| c545fcf896 | |||
| 0ec895c378 | |||
| 406e6f484c | |||
| b63d724e85 | |||
| c73b773724 | |||
| d467313d0c | |||
| efc7bb19a8 | |||
| c9c13a0fe7 | |||
| da5c59e2fe | |||
| f555d2981d | |||
| 4c7cb96bbd | |||
| 0ad53785ab | |||
| e2203b760f | |||
| b0d9b3b4eb | |||
| 8a5813940c | |||
| ba6d0f1a63 | |||
| a431d63b96 | |||
| 5ab167f419 | |||
| fb67ab2b92 | |||
| ec548035ff | |||
| 6112867735 | |||
| c21eda24a9 | |||
| 05cca602d9 | |||
| 3a826fb6bf | |||
| 86bae64a52 | |||
| 8d4c925a62 | |||
| 6149e70916 | |||
| a9ac1e3c93 | |||
| 3461a7ae2c | |||
| 7a83d4f7e1 | |||
| 1fe70dc61c | |||
| b21915938f | |||
| 57efb47c11 | |||
| c4d50aa9ec | |||
| 768b72acf8 | |||
| 8d6c992661 | |||
| 83b6507269 | |||
| da64d9b665 | |||
| aa2f2bfba0 | |||
| 51919fb26c | |||
| ee0f65de5c | |||
| 319ef556cd | |||
| 802399a969 | |||
| c9acff99c6 | |||
| 18dffc9dfe | |||
| 829b632650 | |||
| 501eae173b | |||
| 3ff5ccd8fb | |||
| eb94dda28a |
@@ -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
|
||||
|
||||
@@ -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 }})'
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"semi": false,
|
||||
"trailingComma": "none"
|
||||
"trailingComma": "none",
|
||||
"experimentalOperatorPosition": "start"
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
+2
-1
@@ -1 +1,2 @@
|
||||
plugins/*/permissions/autogenerated/
|
||||
plugins/*/permissions/autogenerated/
|
||||
plugins/*/android/.tauri/tauri-api/build/
|
||||
|
||||
Generated
+634
-543
File diff suppressed because it is too large
Load Diff
+2
-3
@@ -21,10 +21,9 @@ thiserror = "2"
|
||||
url = "2"
|
||||
schemars = "0.8"
|
||||
dunce = "1"
|
||||
specta = "=2.0.0-rc.20"
|
||||
specta = "^2.0.0-rc.16"
|
||||
glob = "0.3"
|
||||
zbus = "4"
|
||||
#tauri-specta = "=2.0.0-rc.11"
|
||||
zbus = "5"
|
||||
|
||||
[workspace.package]
|
||||
edition = "2021"
|
||||
|
||||
@@ -29,7 +29,7 @@ This repo and all plugins require a Rust version of at least **1.77.2**
|
||||
| [process](plugins/process) | This plugin provides APIs to access the current process. To spawn child processes, see the [`shell`](https://github.com/tauri-apps/tauri-plugin-shell) plugin. | ✅ | ✅ | ✅ | ? | ? |
|
||||
| [shell](plugins/shell) | Access the system shell. Allows you to spawn child processes and manage files and URLs using their default application. | ✅ | ✅ | ✅ | ? | ? |
|
||||
| [single-instance](plugins/single-instance) | Ensure a single instance of your tauri app is running. | ✅ | ✅ | ✅ | ❌ | ❌ |
|
||||
| [sql](plugins/sql) | Interface with SQL databases. | ✅ | ✅ | ✅ | ? | ✅ |
|
||||
| [sql](plugins/sql) | Interface with SQL databases. | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| [store](plugins/store) | Persistent key value storage. | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| [stronghold](plugins/stronghold) | Encrypted, secure database. | ✅ | ✅ | ✅ | ? | ? |
|
||||
| [updater](plugins/updater) | In-app updates for Tauri applications. | ✅ | ✅ | ✅ | ❌ | ❌ |
|
||||
|
||||
@@ -1,5 +1,78 @@
|
||||
# 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
|
||||
|
||||
- Upgraded to `clipboard-manager-js@2.2.1`
|
||||
- Upgraded to `http-js@2.3.0`
|
||||
- Upgraded to `log-js@2.2.1`
|
||||
- Upgraded to `updater-js@2.4.0`
|
||||
|
||||
## \[2.0.11]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `opener-js@2.2.5`
|
||||
|
||||
## \[2.0.10]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `notification-js@2.2.1`
|
||||
- Upgraded to `opener-js@2.2.4`
|
||||
|
||||
## \[2.0.9]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `opener-js@2.2.3`
|
||||
- Upgraded to `updater-js@2.3.1`
|
||||
|
||||
## \[2.0.8]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `opener-js@2.2.2`
|
||||
|
||||
## \[2.0.7]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `updater-js@2.3.0`
|
||||
- Upgraded to `opener-js@2.2.1`
|
||||
|
||||
## \[2.0.6]
|
||||
|
||||
### Dependencies
|
||||
|
||||
+28
-28
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "api",
|
||||
"private": true,
|
||||
"version": "2.0.6",
|
||||
"version": "2.0.16",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite --clearScreen false",
|
||||
@@ -10,35 +10,35 @@
|
||||
"tauri": "tauri"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "2.1.1",
|
||||
"@tauri-apps/plugin-barcode-scanner": "2.1.0",
|
||||
"@tauri-apps/plugin-biometric": "2.1.0",
|
||||
"@tauri-apps/plugin-cli": "2.1.0",
|
||||
"@tauri-apps/plugin-clipboard-manager": "2.1.0",
|
||||
"@tauri-apps/plugin-dialog": "2.1.0",
|
||||
"@tauri-apps/plugin-fs": "2.1.0",
|
||||
"@tauri-apps/plugin-geolocation": "2.0.0",
|
||||
"@tauri-apps/plugin-global-shortcut": "2.1.0",
|
||||
"@tauri-apps/plugin-opener": "2.1.0",
|
||||
"@tauri-apps/plugin-haptics": "2.0.0",
|
||||
"@tauri-apps/plugin-http": "2.1.0",
|
||||
"@tauri-apps/plugin-nfc": "2.1.0",
|
||||
"@tauri-apps/plugin-notification": "2.1.0",
|
||||
"@tauri-apps/plugin-os": "2.1.0",
|
||||
"@tauri-apps/plugin-process": "2.1.0",
|
||||
"@tauri-apps/plugin-shell": "2.1.0",
|
||||
"@tauri-apps/plugin-store": "2.2.0",
|
||||
"@tauri-apps/plugin-updater": "2.1.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.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-haptics": "^2.2.0",
|
||||
"@tauri-apps/plugin-http": "^2.4.0",
|
||||
"@tauri-apps/plugin-nfc": "^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.6.0",
|
||||
"@zerodevx/svelte-json-view": "1.0.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iconify-json/codicon": "^1.1.37",
|
||||
"@iconify-json/ph": "^1.1.8",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
||||
"@tauri-apps/cli": "2.1.0",
|
||||
"@unocss/extractor-svelte": "^0.65.0",
|
||||
"svelte": "^5.0.0",
|
||||
"unocss": "^0.65.0",
|
||||
"vite": "^6.0.0"
|
||||
"@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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,91 @@
|
||||
# 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
|
||||
|
||||
- Upgraded to `clipboard-manager@2.2.1`
|
||||
- Upgraded to `http@2.3.0`
|
||||
- Upgraded to `log@2.2.1`
|
||||
- Upgraded to `updater@2.4.0`
|
||||
|
||||
## \[2.0.15]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `haptics@2.2.3`
|
||||
- Upgraded to `geolocation@2.2.3`
|
||||
- Upgraded to `opener@2.2.5`
|
||||
|
||||
## \[2.0.14]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `geolocation@2.2.2`
|
||||
- Upgraded to `haptics@2.2.2`
|
||||
- Upgraded to `notification@2.2.1`
|
||||
- Upgraded to `opener@2.2.4`
|
||||
|
||||
## \[2.0.13]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `geolocation@2.2.1`
|
||||
- Upgraded to `haptics@2.2.1`
|
||||
|
||||
## \[2.0.12]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `opener@2.2.3`
|
||||
- Upgraded to `updater@2.3.1`
|
||||
|
||||
## \[2.0.11]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `opener@2.2.2`
|
||||
|
||||
## \[2.0.10]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `updater@2.3.0`
|
||||
- Upgraded to `opener@2.2.1`
|
||||
|
||||
## \[2.0.9]
|
||||
|
||||
### Dependencies
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "api"
|
||||
publish = false
|
||||
version = "2.0.9"
|
||||
version = "2.0.20"
|
||||
description = "An example Tauri Application showcasing the api"
|
||||
edition = "2021"
|
||||
rust-version = { workspace = true }
|
||||
@@ -19,22 +19,22 @@ serde_json = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
tiny_http = "0.12"
|
||||
log = { workspace = true }
|
||||
tauri-plugin-log = { path = "../../../plugins/log", version = "2.1.0" }
|
||||
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.1.0" }
|
||||
tauri-plugin-dialog = { path = "../../../plugins/dialog", version = "2.1.0" }
|
||||
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.1.0" }
|
||||
tauri-plugin-notification = { path = "../../../plugins/notification", version = "2.1.0", 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.1.0" }
|
||||
tauri-plugin-process = { path = "../../../plugins/process", version = "2.1.0" }
|
||||
tauri-plugin-opener = { path = "../../../plugins/opener", version = "2.1.0" }
|
||||
tauri-plugin-shell = { path = "../../../plugins/shell", version = "2.1.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.6" }
|
||||
tauri-plugin-shell = { path = "../../../plugins/shell", version = "2.2.0" }
|
||||
tauri-plugin-store = { path = "../../../plugins/store", version = "2.2.0" }
|
||||
|
||||
[dependencies.tauri]
|
||||
@@ -51,17 +51,17 @@ features = [
|
||||
]
|
||||
|
||||
[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
|
||||
tauri-plugin-cli = { path = "../../../plugins/cli", version = "2.1.0" }
|
||||
tauri-plugin-global-shortcut = { path = "../../../plugins/global-shortcut", version = "2.1.0" }
|
||||
tauri-plugin-updater = { path = "../../../plugins/updater", version = "2.2.0" }
|
||||
tauri-plugin-window-state = { path = "../../../plugins/window-state", version = "2.0.0" }
|
||||
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.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.1.0" }
|
||||
tauri-plugin-nfc = { path = "../../../plugins/nfc", version = "2.1.0" }
|
||||
tauri-plugin-biometric = { path = "../../../plugins/biometric/", version = "2.1.0" }
|
||||
tauri-plugin-geolocation = { path = "../../../plugins/geolocation/", version = "2.1.0" }
|
||||
tauri-plugin-haptics = { path = "../../../plugins/haptics/", version = "2.1.0" }
|
||||
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.4" }
|
||||
tauri-plugin-haptics = { path = "../../../plugins/haptics/", version = "2.2.4" }
|
||||
|
||||
[features]
|
||||
prod = ["tauri/custom-protocol"]
|
||||
|
||||
@@ -45,7 +45,7 @@ pub fn create_tray<R: Runtime>(app: &tauri::AppHandle<R>) -> tauri::Result<()> {
|
||||
.tooltip("Tauri")
|
||||
.icon(app.default_window_icon().unwrap().clone())
|
||||
.menu(&menu1)
|
||||
.menu_on_left_click(false)
|
||||
.show_menu_on_left_click(false)
|
||||
.on_menu_event(move |app, event| match event.id.as_ref() {
|
||||
"quit" => {
|
||||
app.exit(0);
|
||||
|
||||
+18
-15
@@ -11,26 +11,29 @@
|
||||
"example:api:dev": "pnpm run --filter \"api\" tauri dev"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "9.16.0",
|
||||
"@rollup/plugin-node-resolve": "15.3.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.16.0",
|
||||
"eslint-config-prettier": "9.1.0",
|
||||
"@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.28.1",
|
||||
"prettier": "3.5.3",
|
||||
"rollup": "4.35.0",
|
||||
"tslib": "2.8.1",
|
||||
"typescript": "5.7.2",
|
||||
"typescript-eslint": "8.17.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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# 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.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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-plugin-clipboard-manager"
|
||||
version = "2.2.0"
|
||||
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"] }
|
||||
|
||||
@@ -72,7 +72,6 @@ import {
|
||||
writeText,
|
||||
readText,
|
||||
writeHtml,
|
||||
readHtml,
|
||||
clear
|
||||
} from '@tauri-apps/plugin-clipboard-manager'
|
||||
await writeText('Tauri is awesome!')
|
||||
|
||||
@@ -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,n,a){if("function"==typeof t?e!==t||!a:!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__})}
|
||||
|
||||
@@ -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
|
||||
@@ -111,9 +111,11 @@ async function readImage(): Promise<Image> {
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { writeHtml, readHtml } from '@tauri-apps/plugin-clipboard-manager';
|
||||
* import { writeHtml } from '@tauri-apps/plugin-clipboard-manager';
|
||||
* await writeHtml('<h1>Tauri is awesome!</h1>', 'plaintext');
|
||||
* await writeHtml('<h1>Tauri is awesome!</h1>', '<h1>Tauri is awesome</h1>'); // Will write "<h1>Tauri is awesome</h1>" as plain text
|
||||
* // The following will write "<h1>Tauri is awesome</h1>" as plain text
|
||||
* await writeHtml('<h1>Tauri is awesome!</h1>', '<h1>Tauri is awesome</h1>');
|
||||
* // we can read html data only as a string so there's just readText(), no readHtml()
|
||||
* assert(await readText(), '<h1>Tauri is awesome!</h1>');
|
||||
* ```
|
||||
*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-clipboard-manager",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.2",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
"Tauri Programme within The Commons Conservancy"
|
||||
|
||||
@@ -14,7 +14,7 @@ pub fn init<R: Runtime, C: DeserializeOwned>(
|
||||
) -> crate::Result<Clipboard<R>> {
|
||||
Ok(Clipboard {
|
||||
app: app.clone(),
|
||||
clipboard: arboard::Clipboard::new().map(Mutex::new),
|
||||
clipboard: arboard::Clipboard::new().map(|c| Mutex::new(Some(c))),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -22,13 +22,21 @@ pub fn init<R: Runtime, C: DeserializeOwned>(
|
||||
pub struct Clipboard<R: Runtime> {
|
||||
#[allow(dead_code)]
|
||||
app: AppHandle<R>,
|
||||
clipboard: Result<Mutex<arboard::Clipboard>, arboard::Error>,
|
||||
// According to arboard docs the clipboard must be dropped before exit.
|
||||
// Since tauri doesn't call drop on exit we'll use an Option to take() on RunEvent::Exit.
|
||||
clipboard: Result<Mutex<Option<arboard::Clipboard>>, arboard::Error>,
|
||||
}
|
||||
|
||||
impl<R: Runtime> Clipboard<R> {
|
||||
pub fn write_text<'a, T: Into<Cow<'a, str>>>(&self, text: T) -> crate::Result<()> {
|
||||
match &self.clipboard {
|
||||
Ok(clipboard) => clipboard.lock().unwrap().set_text(text).map_err(Into::into),
|
||||
Ok(clipboard) => clipboard
|
||||
.lock()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.set_text(text)
|
||||
.map_err(Into::into),
|
||||
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
|
||||
}
|
||||
}
|
||||
@@ -38,6 +46,8 @@ impl<R: Runtime> Clipboard<R> {
|
||||
Ok(clipboard) => clipboard
|
||||
.lock()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.set_image(ImageData {
|
||||
bytes: Cow::Borrowed(image.rgba()),
|
||||
width: image.width() as usize,
|
||||
@@ -48,10 +58,11 @@ impl<R: Runtime> Clipboard<R> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Warning: This method should not be used on the main thread! Otherwise the underlying libraries may deadlock on Linux, freezing the whole app, when trying to copy data copied from this app, for example if the user copies text from the WebView.
|
||||
pub fn read_text(&self) -> crate::Result<String> {
|
||||
match &self.clipboard {
|
||||
Ok(clipboard) => {
|
||||
let text = clipboard.lock().unwrap().get_text()?;
|
||||
let text = clipboard.lock().unwrap().as_mut().unwrap().get_text()?;
|
||||
Ok(text)
|
||||
}
|
||||
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
|
||||
@@ -67,6 +78,8 @@ impl<R: Runtime> Clipboard<R> {
|
||||
Ok(clipboard) => clipboard
|
||||
.lock()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.set_html(html, alt_text)
|
||||
.map_err(Into::into),
|
||||
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
|
||||
@@ -75,15 +88,22 @@ impl<R: Runtime> Clipboard<R> {
|
||||
|
||||
pub fn clear(&self) -> crate::Result<()> {
|
||||
match &self.clipboard {
|
||||
Ok(clipboard) => clipboard.lock().unwrap().clear().map_err(Into::into),
|
||||
Ok(clipboard) => clipboard
|
||||
.lock()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.clear()
|
||||
.map_err(Into::into),
|
||||
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Warning: This method should not be used on the main thread! Otherwise the underlying libraries may deadlock on Linux, freezing the whole app, when trying to copy data copied from this app, for example if the user copies text from the WebView.
|
||||
pub fn read_image(&self) -> crate::Result<Image<'_>> {
|
||||
match &self.clipboard {
|
||||
Ok(clipboard) => {
|
||||
let image = clipboard.lock().unwrap().get_image()?;
|
||||
let image = clipboard.lock().unwrap().as_mut().unwrap().get_image()?;
|
||||
let image = Image::new_owned(
|
||||
image.bytes.to_vec(),
|
||||
image.width as u32,
|
||||
@@ -94,4 +114,10 @@ impl<R: Runtime> Clipboard<R> {
|
||||
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn cleanup(&self) {
|
||||
if let Ok(clipboard) = &self.clipboard {
|
||||
clipboard.lock().unwrap().take();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
use tauri::{
|
||||
plugin::{Builder, TauriPlugin},
|
||||
Manager, Runtime,
|
||||
Manager, RunEvent, Runtime,
|
||||
};
|
||||
|
||||
#[cfg(desktop)]
|
||||
@@ -59,5 +59,11 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
app.manage(clipboard);
|
||||
Ok(())
|
||||
})
|
||||
.on_event(|_app, _event| {
|
||||
#[cfg(desktop)]
|
||||
if let RunEvent::Exit = _event {
|
||||
_app.clipboard().cleanup();
|
||||
}
|
||||
})
|
||||
.build()
|
||||
}
|
||||
|
||||
@@ -38,8 +38,8 @@ url = { workspace = true }
|
||||
|
||||
[target."cfg(windows)".dependencies]
|
||||
dunce = "1"
|
||||
windows-registry = "0.3"
|
||||
windows-result = "0.2"
|
||||
windows-registry = "0.5"
|
||||
windows-result = "0.3"
|
||||
|
||||
[target."cfg(target_os = \"linux\")".dependencies]
|
||||
rust-ini = "0.21"
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
"tauri": "tauri"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "2.1.1",
|
||||
"@tauri-apps/plugin-deep-link": "2.1.0"
|
||||
"@tauri-apps/api": "2.3.0",
|
||||
"@tauri-apps/plugin-deep-link": "2.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "2.1.0",
|
||||
"typescript": "^5.2.2",
|
||||
"vite": "^6.0.0"
|
||||
"@tauri-apps/cli": "2.3.1",
|
||||
"typescript": "^5.7.3",
|
||||
"vite": "^6.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -38,11 +38,11 @@ anyhow = "1"
|
||||
uuid = { version = "1", features = ["v4"] }
|
||||
glob = { workspace = true }
|
||||
# TODO: Remove `serialization-compat-6` in v3
|
||||
notify = { version = "7", optional = true, features = [
|
||||
notify = { version = "8", optional = true, features = [
|
||||
"serde",
|
||||
"serialization-compat-6",
|
||||
] }
|
||||
notify-debouncer-full = { version = "0.4", optional = true }
|
||||
notify-debouncer-full = { version = "0.5", optional = true }
|
||||
dunce = { workspace = true }
|
||||
percent-encoding = "2"
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -10,7 +10,7 @@
|
||||
* This module prevents path traversal, not allowing parent directory accessors to be used
|
||||
* (i.e. "/usr/path/to/../file" or "../path/to/file" paths are not allowed).
|
||||
* Paths accessed with this API must be either relative to one of the {@link BaseDirectory | base directories}
|
||||
* or created with the {@link https://v2.tauri.app/reference/javascript/api/namespacepath | path API}.
|
||||
* or created with the {@link https://v2.tauri.app/reference/javascript/api/namespacepath/ | path API}.
|
||||
*
|
||||
* The API has a scope configuration that forces you to restrict the paths that can be accessed using glob patterns.
|
||||
*
|
||||
@@ -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.')
|
||||
}
|
||||
|
||||
@@ -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()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# 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.
|
||||
|
||||
## \[2.2.2]
|
||||
|
||||
- [`c9c13a0f`](https://github.com/tauri-apps/plugins-workspace/commit/c9c13a0fe7cdaac223843f5ba33176252f8e22f5) ([#2316](https://github.com/tauri-apps/plugins-workspace/pull/2316) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) **Breaking change:** `specta` integration is now behind a `specta` feature flag like in Tauri.
|
||||
- [`c9c13a0f`](https://github.com/tauri-apps/plugins-workspace/commit/c9c13a0fe7cdaac223843f5ba33176252f8e22f5) ([#2316](https://github.com/tauri-apps/plugins-workspace/pull/2316) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Unlock and widen `specta` version range to match Tauri. No API changes.
|
||||
|
||||
## \[2.2.1]
|
||||
|
||||
- [`fb67ab2b`](https://github.com/tauri-apps/plugins-workspace/commit/fb67ab2b926502bfc20d6b43fbdd156691ea8526) ([#2281](https://github.com/tauri-apps/plugins-workspace/pull/2281) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Added `specta-util` to fix a "dependency not found" compilation error.
|
||||
|
||||
## \[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.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "tauri-plugin-geolocation"
|
||||
description = "Get and track the device's current position"
|
||||
version = "2.2.0"
|
||||
version = "2.2.4"
|
||||
edition = { workspace = true }
|
||||
authors = { workspace = true }
|
||||
license = { workspace = true }
|
||||
@@ -26,10 +26,13 @@ tauri-plugin = { workspace = true, features = ["build"] }
|
||||
[dependencies]
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
tauri = { workspace = true, features = ["specta"] }
|
||||
tauri = { workspace = true }
|
||||
log = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
specta = { workspace = true }
|
||||
specta = { workspace = true, optional = true }
|
||||
|
||||
[target.'cfg(target_os = "ios")'.dependencies]
|
||||
tauri = { workspace = true, features = ["wry"] }
|
||||
|
||||
[features]
|
||||
specta = ["dep:specta", "tauri/specta"]
|
||||
|
||||
@@ -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 @@
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_GEOLOCATION__=function(t){"use strict";function e(t,e,n,i){if("a"===n&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!i:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?i:"a"===n?i.call(t):i?i.value:e.get(t)}function n(t,e,n,i,o){if("function"==typeof e?t!==e||!o:!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 i,o,s;"function"==typeof SuppressedError&&SuppressedError;const r="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),o.set(this,0),s.set(this,{}),this.id=function(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}((({message:t,id:r})=>{if(r===e(this,o,"f")){n(this,o,r+1),e(this,i,"f").call(this,t);const a=Object.keys(e(this,s,"f"));if(a.length>0){let t=r+1;for(const n of a.sort()){if(parseInt(n)!==t)break;{const o=e(this,s,"f")[n];delete e(this,s,"f")[n],e(this,i,"f").call(this,o),t+=1}}n(this,o,t)}}else e(this,s,"f")[r.toString()]=t}))}set onmessage(t){n(this,i,t)}get onmessage(){return e(this,i,"f")}[(i=new WeakMap,o=new WeakMap,s=new WeakMap,r)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[r]()}}async function c(t,e={},n){return window.__TAURI_INTERNALS__.invoke(t,e,n)}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,e){const n=new a;return n.onmessage=t=>{"string"==typeof t?e(null,t):e(t)},await c("plugin:geolocation|watch_position",{options:t,channel:n}),n.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,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-geolocation",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.4",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
"Tauri Programme within The Commons Conservancy"
|
||||
|
||||
@@ -7,7 +7,6 @@ use tauri::{command, ipc::Channel, AppHandle, Runtime};
|
||||
use crate::{GeolocationExt, PermissionStatus, PermissionType, Position, PositionOptions, Result};
|
||||
|
||||
#[command]
|
||||
#[specta::specta]
|
||||
pub(crate) async fn get_current_position<R: Runtime>(
|
||||
app: AppHandle<R>,
|
||||
options: Option<PositionOptions>,
|
||||
@@ -16,7 +15,6 @@ pub(crate) async fn get_current_position<R: Runtime>(
|
||||
}
|
||||
|
||||
#[command]
|
||||
#[specta::specta]
|
||||
pub(crate) async fn watch_position<R: Runtime>(
|
||||
app: AppHandle<R>,
|
||||
options: PositionOptions,
|
||||
@@ -26,19 +24,16 @@ pub(crate) async fn watch_position<R: Runtime>(
|
||||
}
|
||||
|
||||
#[command]
|
||||
#[specta::specta]
|
||||
pub(crate) async fn clear_watch<R: Runtime>(app: AppHandle<R>, channel_id: u32) -> Result<()> {
|
||||
app.geolocation().clear_watch(channel_id)
|
||||
}
|
||||
|
||||
#[command]
|
||||
#[specta::specta]
|
||||
pub(crate) async fn check_permissions<R: Runtime>(app: AppHandle<R>) -> Result<PermissionStatus> {
|
||||
app.geolocation().check_permissions()
|
||||
}
|
||||
|
||||
#[command]
|
||||
#[specta::specta]
|
||||
pub(crate) async fn request_permissions<R: Runtime>(
|
||||
app: AppHandle<R>,
|
||||
permissions: Option<Vec<PermissionType>>,
|
||||
|
||||
@@ -3,18 +3,18 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use serde::{ser::Serializer, Serialize};
|
||||
use specta::Type;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
// TODO: Improve Error handling (different typed errors instead of one (stringified) PluginInvokeError for all mobile errors)
|
||||
|
||||
#[derive(Debug, thiserror::Error, Type)]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[cfg_attr(feature = "specta", derive(specta::Type))]
|
||||
pub enum Error {
|
||||
#[cfg(mobile)]
|
||||
#[error(transparent)]
|
||||
PluginInvoke(
|
||||
#[serde(skip)]
|
||||
#[cfg_attr(feature = "specta", serde(skip))]
|
||||
#[from]
|
||||
tauri::plugin::mobile::PluginInvokeError,
|
||||
),
|
||||
|
||||
@@ -7,8 +7,6 @@ use tauri::{
|
||||
Manager, Runtime,
|
||||
};
|
||||
|
||||
//use tauri_specta::*;
|
||||
|
||||
pub use models::*;
|
||||
|
||||
#[cfg(desktop)]
|
||||
@@ -23,27 +21,9 @@ mod models;
|
||||
pub use error::{Error, Result};
|
||||
|
||||
#[cfg(desktop)]
|
||||
use desktop::Geolocation;
|
||||
pub use desktop::Geolocation;
|
||||
#[cfg(mobile)]
|
||||
use mobile::Geolocation;
|
||||
|
||||
/* macro_rules! specta_builder {
|
||||
() => {
|
||||
ts::builder()
|
||||
.commands(collect_commands![
|
||||
commands::get_current_position,
|
||||
commands::watch_position,
|
||||
commands::clear_watch,
|
||||
commands::check_permissions,
|
||||
commands::request_permissions
|
||||
])
|
||||
.header("// @ts-nocheck")
|
||||
.config(
|
||||
specta::ts::ExportConfig::default()
|
||||
.bigint(specta::ts::BigIntExportBehavior::Number),
|
||||
)
|
||||
};
|
||||
} */
|
||||
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> {
|
||||
@@ -58,9 +38,6 @@ impl<R: Runtime, T: Manager<R>> crate::GeolocationExt<R> for T {
|
||||
|
||||
/// Initializes the plugin.
|
||||
pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
/* let (invoke_handler, register_events) =
|
||||
specta_builder!().build_plugin_utils("geolocation").unwrap(); */
|
||||
|
||||
Builder::new("geolocation")
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
commands::get_current_position,
|
||||
@@ -79,22 +56,3 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
})
|
||||
.build()
|
||||
}
|
||||
|
||||
/* #[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn export_types() {
|
||||
specta_builder!()
|
||||
.path("./guest-js/bindings.ts")
|
||||
.config(
|
||||
specta::ts::ExportConfig::default()
|
||||
.formatter(specta::ts::formatter::prettier)
|
||||
.bigint(specta::ts::BigIntExportBehavior::Number),
|
||||
)
|
||||
.export_for_plugin("geolocation")
|
||||
.expect("failed to export specta types");
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specta::Type;
|
||||
use tauri::plugin::PermissionState;
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, Type)]
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "specta", derive(specta::Type))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PermissionStatus {
|
||||
/// Permission state for the location alias.
|
||||
@@ -25,7 +25,8 @@ pub struct PermissionStatus {
|
||||
pub coarse_location: PermissionState,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, Type)]
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "specta", derive(specta::Type))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PositionOptions {
|
||||
/// High accuracy mode (such as GPS, if available)
|
||||
@@ -46,14 +47,16 @@ pub struct PositionOptions {
|
||||
pub maximum_age: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Type)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "specta", derive(specta::Type))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum PermissionType {
|
||||
Location,
|
||||
CoarseLocation,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, Type)]
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "specta", derive(specta::Type))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Coordinates {
|
||||
/// Latitude in decimal degrees.
|
||||
@@ -73,7 +76,8 @@ pub struct Coordinates {
|
||||
pub heading: Option<f64>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, Type)]
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "specta", derive(specta::Type))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Position {
|
||||
/// Creation time for these coordinates.
|
||||
@@ -83,7 +87,8 @@ pub struct Position {
|
||||
pub coords: Coordinates,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Type)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "specta", derive(specta::Type))]
|
||||
#[serde(untagged)]
|
||||
pub enum WatchEvent {
|
||||
Position(Position),
|
||||
|
||||
@@ -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,n){if("function"==typeof e?t!==e||!n:!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,n,i;"function"==typeof SuppressedError&&SuppressedError;const o="__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(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}((({message:t,id:o})=>{if(o===e(this,n,"f")){r(this,n,o+1),e(this,s,"f").call(this,t);const a=Object.keys(e(this,i,"f"));if(a.length>0){let t=o+1;for(const r of a.sort()){if(parseInt(r)!==t)break;{const n=e(this,i,"f")[r];delete e(this,i,"f")[r],e(this,s,"f").call(this,n),t+=1}}r(this,n,t)}}else e(this,i,"f")[o.toString()]=t}))}set onmessage(t){r(this,s,t)}get onmessage(){return e(this,s,"f")}[(s=new WeakMap,n=new WeakMap,i=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__})}
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# 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.
|
||||
|
||||
## \[2.2.2]
|
||||
|
||||
- [`c9c13a0f`](https://github.com/tauri-apps/plugins-workspace/commit/c9c13a0fe7cdaac223843f5ba33176252f8e22f5) ([#2316](https://github.com/tauri-apps/plugins-workspace/pull/2316) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) **Breaking change:** `specta` integration is now behind a `specta` feature flag like in Tauri.
|
||||
- [`c9c13a0f`](https://github.com/tauri-apps/plugins-workspace/commit/c9c13a0fe7cdaac223843f5ba33176252f8e22f5) ([#2316](https://github.com/tauri-apps/plugins-workspace/pull/2316) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Unlock and widen `specta` version range to match Tauri. No API changes.
|
||||
|
||||
## \[2.2.1]
|
||||
|
||||
- [`fb67ab2b`](https://github.com/tauri-apps/plugins-workspace/commit/fb67ab2b926502bfc20d6b43fbdd156691ea8526) ([#2281](https://github.com/tauri-apps/plugins-workspace/pull/2281) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Added `specta-util` to fix a "dependency not found" compilation error.
|
||||
|
||||
## \[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.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "tauri-plugin-haptics"
|
||||
description = "Haptic feedback and vibrations on Android and iOS"
|
||||
version = "2.2.0"
|
||||
version = "2.2.4"
|
||||
edition = { workspace = true }
|
||||
authors = { workspace = true }
|
||||
license = { workspace = true }
|
||||
@@ -26,10 +26,13 @@ tauri-plugin = { workspace = true, features = ["build"] }
|
||||
[dependencies]
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
tauri = { workspace = true, features = ["specta"] }
|
||||
tauri = { workspace = true }
|
||||
log = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
specta = { workspace = true }
|
||||
specta = { workspace = true, optional = true }
|
||||
|
||||
[target.'cfg(target_os = "ios")'.dependencies]
|
||||
tauri = { workspace = true, features = ["wry"] }
|
||||
|
||||
[features]
|
||||
specta = ["dep:specta", "tauri/specta"]
|
||||
|
||||
@@ -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,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-haptics",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.4",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
"Tauri Programme within The Commons Conservancy"
|
||||
|
||||
@@ -7,13 +7,11 @@ use tauri::{command, AppHandle, Runtime};
|
||||
use crate::{HapticsExt, ImpactFeedbackStyle, NotificationFeedbackType, Result};
|
||||
|
||||
#[command]
|
||||
#[specta::specta]
|
||||
pub(crate) async fn vibrate<R: Runtime>(app: AppHandle<R>, duration: u32) -> Result<()> {
|
||||
app.haptics().vibrate(duration)
|
||||
}
|
||||
|
||||
#[command]
|
||||
#[specta::specta]
|
||||
pub(crate) async fn impact_feedback<R: Runtime>(
|
||||
app: AppHandle<R>,
|
||||
style: ImpactFeedbackStyle,
|
||||
@@ -22,7 +20,6 @@ pub(crate) async fn impact_feedback<R: Runtime>(
|
||||
}
|
||||
|
||||
#[command]
|
||||
#[specta::specta]
|
||||
pub(crate) async fn notification_feedback<R: Runtime>(
|
||||
app: AppHandle<R>,
|
||||
r#type: NotificationFeedbackType,
|
||||
@@ -31,7 +28,6 @@ pub(crate) async fn notification_feedback<R: Runtime>(
|
||||
}
|
||||
|
||||
#[command]
|
||||
#[specta::specta]
|
||||
pub(crate) async fn selection_feedback<R: Runtime>(app: AppHandle<R>) -> Result<()> {
|
||||
app.haptics().selection_feedback()
|
||||
}
|
||||
|
||||
@@ -3,18 +3,18 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use serde::{ser::Serializer, Serialize};
|
||||
use specta::Type;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
// TODO: Improve Error handling (different typed errors instead of one (stringified) PluginInvokeError for all mobile errors)
|
||||
|
||||
#[derive(Debug, thiserror::Error, Type)]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[cfg_attr(feature = "specta", derive(specta::Type))]
|
||||
pub enum Error {
|
||||
#[cfg(mobile)]
|
||||
#[error(transparent)]
|
||||
PluginInvoke(
|
||||
#[serde(skip)]
|
||||
#[cfg_attr(feature = "specta", serde(skip))]
|
||||
#[from]
|
||||
tauri::plugin::mobile::PluginInvokeError,
|
||||
),
|
||||
|
||||
@@ -7,8 +7,6 @@ use tauri::{
|
||||
Manager, Runtime,
|
||||
};
|
||||
|
||||
//use tauri_specta::*;
|
||||
|
||||
pub use models::*;
|
||||
|
||||
#[cfg(desktop)]
|
||||
@@ -23,26 +21,9 @@ mod models;
|
||||
pub use error::{Error, Result};
|
||||
|
||||
#[cfg(desktop)]
|
||||
use desktop::Haptics;
|
||||
pub use desktop::Haptics;
|
||||
#[cfg(mobile)]
|
||||
use mobile::Haptics;
|
||||
|
||||
/* macro_rules! specta_builder {
|
||||
() => {
|
||||
ts::builder()
|
||||
.commands(collect_commands![
|
||||
commands::vibrate,
|
||||
commands::impact_feedback,
|
||||
commands::notification_feedback,
|
||||
commands::selection_feedback
|
||||
])
|
||||
.header("// @ts-nocheck")
|
||||
.config(
|
||||
specta::ts::ExportConfig::default()
|
||||
.bigint(specta::ts::BigIntExportBehavior::Number),
|
||||
)
|
||||
};
|
||||
} */
|
||||
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> {
|
||||
@@ -57,9 +38,6 @@ impl<R: Runtime, T: Manager<R>> crate::HapticsExt<R> for T {
|
||||
|
||||
/// Initializes the plugin.
|
||||
pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
/* let (invoke_handler, register_events) =
|
||||
specta_builder!().build_plugin_utils("haptics").unwrap(); */
|
||||
|
||||
Builder::new("haptics")
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
commands::vibrate,
|
||||
@@ -77,22 +55,3 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
})
|
||||
.build()
|
||||
}
|
||||
|
||||
/* #[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn export_types() {
|
||||
specta_builder!()
|
||||
.path("./guest-js/bindings.ts")
|
||||
.config(
|
||||
specta::ts::ExportConfig::default()
|
||||
.formatter(specta::ts::formatter::prettier)
|
||||
.bigint(specta::ts::BigIntExportBehavior::Number),
|
||||
)
|
||||
.export_for_plugin("haptics")
|
||||
.expect("failed to export specta types");
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specta::Type;
|
||||
/*
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, Type)]
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "specta", derive(specta::Type))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct HapticsOptions {
|
||||
// TODO: support array to match web api
|
||||
@@ -13,7 +13,8 @@ pub struct HapticsOptions {
|
||||
}
|
||||
*/
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, Type)]
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "specta", derive(specta::Type))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum ImpactFeedbackStyle {
|
||||
Light,
|
||||
@@ -24,7 +25,8 @@ pub enum ImpactFeedbackStyle {
|
||||
Rigid,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, Type)]
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "specta", derive(specta::Type))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum NotificationFeedbackType {
|
||||
#[default]
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# 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.
|
||||
|
||||
## \[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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-plugin-http"
|
||||
version = "2.2.0"
|
||||
version = "2.4.0"
|
||||
description = "Access an HTTP client written in Rust."
|
||||
edition = { workspace = true }
|
||||
authors = { workspace = true }
|
||||
@@ -73,3 +73,4 @@ charset = ["reqwest/charset"]
|
||||
macos-system-configuration = ["reqwest/macos-system-configuration"]
|
||||
unsafe-headers = []
|
||||
tracing = ["dep:tracing"]
|
||||
dangerous-settings = []
|
||||
|
||||
@@ -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;n&&(delete n.maxRedirections,delete n.connectTimeout,delete n.proxy);const d=n?.headers?n.headers instanceof Headers?n.headers:new Headers(n.headers):new Headers,c=new Request(e,n),u=await c.arrayBuffer(),f=0!==u.byteLength?Array.from(new Uint8Array(u)):null;for(const[e,t]of c.headers)d.get(e)||d.set(e,t);const _=(d instanceof Headers?Array.from(d.entries()):Array.isArray(d)?d:Object.entries(d)).map((([e,t])=>[e,"string"==typeof t?t:t.toString()]));if(a?.aborted)throw new Error(r);const h=await t("plugin:http|fetch",{clientConfig:{method:c.method,url:c.url,headers:_,data:f,maxRedirections:o,connectTimeout:s,proxy:i}}),l=()=>t("plugin:http|fetch_cancel",{rid:h});if(a?.aborted)throw l(),new Error(r);a?.addEventListener("abort",(()=>{l()}));const{status:p,statusText:w,url:y,headers:T,rid:A}=await t("plugin:http|fetch_send",{rid:h}),g=await t("plugin:http|fetch_read_body",{rid:A}),R=new Response(g instanceof ArrayBuffer&&0!==g.byteLength?g:g instanceof Array&&g.length>0?new Uint8Array(g):null,{status:p,statusText:w});return Object.defineProperty(R,"url",{value:y}),Object.defineProperty(R,"headers",{value:new Headers(T)}),R},e}({});Object.defineProperty(window.__TAURI__,"http",{value:__TAURI_PLUGIN_HTTP__})}
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_HTTP__=function(e){"use strict";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__})}
|
||||
|
||||
@@ -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.
|
||||
@@ -84,6 +84,26 @@ export interface ClientOptions {
|
||||
* Configuration of a proxy that a Client should pass requests to.
|
||||
*/
|
||||
proxy?: Proxy
|
||||
/**
|
||||
* Configuration for dangerous settings on the client such as disabling SSL verification.
|
||||
*/
|
||||
danger?: DangerousSettings
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration for dangerous settings on the client such as disabling SSL verification.
|
||||
*
|
||||
* @since 2.3.0
|
||||
*/
|
||||
export interface DangerousSettings {
|
||||
/**
|
||||
* Disables SSL verification.
|
||||
*/
|
||||
acceptInvalidCerts?: boolean
|
||||
/**
|
||||
* Disables hostname verification.
|
||||
*/
|
||||
acceptInvalidHostnames?: boolean
|
||||
}
|
||||
|
||||
const ERROR_REQUEST_CANCELLED = 'Request canceled'
|
||||
@@ -115,12 +135,14 @@ export async function fetch(
|
||||
const maxRedirections = init?.maxRedirections
|
||||
const connectTimeout = init?.connectTimeout
|
||||
const proxy = init?.proxy
|
||||
const danger = init?.danger
|
||||
|
||||
// Remove these fields before creating the request
|
||||
if (init) {
|
||||
delete init.maxRedirections
|
||||
delete init.connectTimeout
|
||||
delete init.proxy
|
||||
delete init.danger
|
||||
}
|
||||
|
||||
const headers = init?.headers
|
||||
@@ -164,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,
|
||||
@@ -172,8 +223,10 @@ export async function fetch(
|
||||
data,
|
||||
maxRedirections,
|
||||
connectTimeout,
|
||||
proxy
|
||||
}
|
||||
proxy,
|
||||
danger
|
||||
},
|
||||
streamChannel
|
||||
})
|
||||
|
||||
const abort = () => invoke('plugin:http|fetch_cancel', { rid })
|
||||
@@ -200,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,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-http",
|
||||
"version": "2.2.0",
|
||||
"version": "2.4.0",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
"Tauri Programme within The Commons Conservancy"
|
||||
|
||||
@@ -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>>;
|
||||
@@ -75,6 +72,14 @@ pub struct FetchResponse {
|
||||
rid: ResourceId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[allow(dead_code)] //feature flags shoudln't affect api
|
||||
pub struct DangerousSettings {
|
||||
accept_invalid_certs: bool,
|
||||
accept_invalid_hostnames: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ClientConfig {
|
||||
@@ -85,6 +90,7 @@ pub struct ClientConfig {
|
||||
connect_timeout: Option<u64>,
|
||||
max_redirections: Option<usize>,
|
||||
proxy: Option<Proxy>,
|
||||
danger: Option<DangerousSettings>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
@@ -172,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,
|
||||
@@ -181,6 +188,7 @@ pub async fn fetch<R: Runtime>(
|
||||
connect_timeout,
|
||||
max_redirections,
|
||||
proxy,
|
||||
danger,
|
||||
} = client_config;
|
||||
|
||||
let scheme = url.scheme();
|
||||
@@ -220,6 +228,24 @@ pub async fn fetch<R: Runtime>(
|
||||
{
|
||||
let mut builder = reqwest::ClientBuilder::new();
|
||||
|
||||
if let Some(danger_config) = danger {
|
||||
#[cfg(not(feature = "dangerous-settings"))]
|
||||
{
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
eprintln!("[\x1b[33mWARNING\x1b[0m] using dangerous settings requires `dangerous-settings` feature flag in your Cargo.toml");
|
||||
}
|
||||
let _ = danger_config;
|
||||
return Err(Error::DangerousSettings);
|
||||
}
|
||||
#[cfg(feature = "dangerous-settings")]
|
||||
{
|
||||
builder = builder
|
||||
.danger_accept_invalid_certs(danger_config.accept_invalid_certs)
|
||||
.danger_accept_invalid_hostnames(danger_config.accept_invalid_hostnames)
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(timeout) = connect_timeout {
|
||||
builder = builder.connect_timeout(Duration::from_millis(timeout));
|
||||
}
|
||||
@@ -286,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));
|
||||
|
||||
@@ -370,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(),
|
||||
@@ -382,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 {
|
||||
|
||||
@@ -41,6 +41,8 @@ pub enum Error {
|
||||
Tauri(#[from] tauri::Error),
|
||||
#[error(transparent)]
|
||||
Utf8(#[from] std::string::FromUtf8Error),
|
||||
#[error("dangerous settings used but are not enabled")]
|
||||
DangerousSettings,
|
||||
}
|
||||
|
||||
impl Serialize for Error {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
# 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`.
|
||||
|
||||
## \[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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-plugin-log"
|
||||
version = "2.2.0"
|
||||
version = "2.3.0"
|
||||
description = "Configurable logging for your Tauri app."
|
||||
authors = { workspace = true }
|
||||
license = { workspace = true }
|
||||
@@ -17,8 +17,8 @@ rustdoc-args = ["--cfg", "docsrs"]
|
||||
windows = { level = "full", notes = "" }
|
||||
linux = { level = "full", notes = "" }
|
||||
macos = { level = "full", notes = "" }
|
||||
android = { level = "unknown", notes = "" }
|
||||
ios = { level = "unknown", notes = "" }
|
||||
android = { level = "full", notes = "" }
|
||||
ios = { level = "full", notes = "" }
|
||||
|
||||
[build-dependencies]
|
||||
tauri-plugin = { workspace = true, features = ["build"] }
|
||||
@@ -39,8 +39,11 @@ android_logger = "0.14"
|
||||
|
||||
[target."cfg(target_os = \"ios\")".dependencies]
|
||||
swift-rs = "1"
|
||||
objc = "0.2"
|
||||
cocoa = "0.26"
|
||||
objc2 = "0.6"
|
||||
objc2-foundation = { version = "0.3", default-features = false, features = [
|
||||
"std",
|
||||
"NSString",
|
||||
] }
|
||||
|
||||
[features]
|
||||
colored = ["fern/colored"]
|
||||
|
||||
+17
-1
@@ -54,7 +54,23 @@ yarn add https://github.com/tauri-apps/tauri-plugin-log#v2
|
||||
|
||||
## Usage
|
||||
|
||||
First you need to register the core plugin with Tauri:
|
||||
First, you should enable the `log:default` capability:
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "default",
|
||||
"description": "Capability for the main window",
|
||||
"windows": ["main"],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"opener:default",
|
||||
"log:default" # add this!
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Then, you need to register the core plugin with Tauri:
|
||||
|
||||
`src-tauri/src/lib.rs`
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-log",
|
||||
"version": "2.2.0",
|
||||
"version": "2.3.0",
|
||||
"description": "Configurable logging for your Tauri app.",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
|
||||
+41
-38
@@ -35,31 +35,6 @@ pub const WEBVIEW_TARGET: &str = "webview";
|
||||
|
||||
#[cfg(target_os = "ios")]
|
||||
mod ios {
|
||||
use cocoa::base::id;
|
||||
use objc::*;
|
||||
|
||||
const UTF8_ENCODING: usize = 4;
|
||||
pub struct NSString(pub id);
|
||||
|
||||
impl NSString {
|
||||
pub fn new(s: &str) -> Self {
|
||||
// Safety: objc runtime calls are unsafe
|
||||
NSString(unsafe {
|
||||
let ns_string: id = msg_send![class!(NSString), alloc];
|
||||
let ns_string: id = msg_send![ns_string,
|
||||
initWithBytes:s.as_ptr()
|
||||
length:s.len()
|
||||
encoding:UTF8_ENCODING];
|
||||
|
||||
// The thing is allocated in rust, the thing must be set to autorelease in rust to relinquish control
|
||||
// or it can not be released correctly in OC runtime
|
||||
let _: () = msg_send![ns_string, autorelease];
|
||||
|
||||
ns_string
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
swift_rs::swift!(pub fn tauri_log(
|
||||
level: u8, message: *const std::ffi::c_void
|
||||
));
|
||||
@@ -83,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.
|
||||
@@ -255,6 +232,7 @@ pub struct Builder {
|
||||
timezone_strategy: TimezoneStrategy,
|
||||
max_file_size: u128,
|
||||
targets: Vec<Target>,
|
||||
is_skip_logger: bool,
|
||||
}
|
||||
|
||||
impl Default for Builder {
|
||||
@@ -283,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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -303,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(),
|
||||
@@ -364,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
|
||||
@@ -429,7 +424,12 @@ impl Builder {
|
||||
log::Level::Info => 2,
|
||||
log::Level::Warn | log::Level::Error => 3,
|
||||
},
|
||||
ios::NSString::new(message.as_str()).0 as _,
|
||||
// The string is allocated in rust, so we must
|
||||
// autorelease it rust to give it to the Swift
|
||||
// runtime.
|
||||
objc2::rc::Retained::autorelease_ptr(
|
||||
objc2_foundation::NSString::from_str(message.as_str()),
|
||||
) as _,
|
||||
);
|
||||
}
|
||||
}),
|
||||
@@ -501,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,
|
||||
@@ -517,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()
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# 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.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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-plugin-notification"
|
||||
version = "2.2.0"
|
||||
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 @@
|
||||
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,o){if("function"==typeof t?i!==t||!o:!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,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,t=!1){return window.__TAURI_INTERNALS__.transformCallback(i,t)}((({message:i,id:r})=>{if(r===t(this,o,"f")){n(this,o,r+1),t(this,e,"f").call(this,i);const c=Object.keys(t(this,a,"f"));if(c.length>0){let i=r+1;for(const n of c.sort()){if(parseInt(n)!==i)break;{const o=t(this,a,"f")[n];delete t(this,a,"f")[n],t(this,e,"f").call(this,o),i+=1}}n(this,o,i)}}else t(this,a,"f")[r.toString()]=i}))}set onmessage(i){n(this,e,i)}get onmessage(){return t(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,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 c;return e.onmessage=n,u(`plugin:${i}|registerListener`,{event:t,handler:e}).then((()=>new s(i,t,e.id)))}async function u(i,t={},n){return window.__TAURI_INTERNALS__.invoke(i,t,n)}var f,d,w;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,(d=i.Importance||(i.Importance={}))[d.None=0]="None",d[d.Min=1]="Min",d[d.Low=2]="Low",d[d.Default=3]="Default",d[d.High=4]="High",i.Visibility=void 0,(w=i.Visibility||(i.Visibility={}))[w.Secret=-1]="Secret",w[w.Private=0]="Private",w[w.Public=1]="Public",i.Schedule=class{static at(i,t=!1,n=!1){return{at:{date:i,repeating:t,allowWhileIdle:n},interval:void 0,every:void 0}}static interval(i,t=!1){return{at:void 0,interval:{interval:i,allowWhileIdle:t},every:void 0}}static every(i,t,n=!1){return{at:void 0,interval:void 0,every:{interval:i,count:t,allowWhileIdle:n}}}},i.active=async function(){return await 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,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-notification",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.2",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
"Tauri Programme within The Commons Conservancy"
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -1,5 +1,30 @@
|
||||
# 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.
|
||||
|
||||
## \[2.2.4]
|
||||
|
||||
- [`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.3]
|
||||
|
||||
- [`a9ac1e3c`](https://github.com/tauri-apps/plugins-workspace/commit/a9ac1e3c939cec4338a9422ef02323c1d4dde6cd) ([#2253](https://github.com/tauri-apps/plugins-workspace/pull/2253) by [@betamos](https://github.com/tauri-apps/plugins-workspace/../../betamos)) Return an error in `open_path` if the file does not exist when opening with default application.
|
||||
|
||||
## \[2.2.2]
|
||||
|
||||
- [`ee0f65de`](https://github.com/tauri-apps/plugins-workspace/commit/ee0f65de5c645c244c5f0b638e0e0aab687cb9bf) ([#2207](https://github.com/tauri-apps/plugins-workspace/pull/2207) by [@universalappfactory](https://github.com/tauri-apps/plugins-workspace/../../universalappfactory)) Fixed OpenerPlugin packagename for android
|
||||
|
||||
## \[2.2.1]
|
||||
|
||||
- [`18dffc9d`](https://github.com/tauri-apps/plugins-workspace/commit/18dffc9dfecaf0c900e233e041d9ca36c92834b5) ([#2189](https://github.com/tauri-apps/plugins-workspace/pull/2189) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Fix usage on iOS.
|
||||
|
||||
## \[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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-plugin-opener"
|
||||
version = "2.2.0"
|
||||
version = "2.2.6"
|
||||
description = "Open files and URLs using their default application."
|
||||
edition = { workspace = true }
|
||||
authors = { workspace = true }
|
||||
@@ -15,7 +15,7 @@ rustdoc-args = ["--cfg", "docsrs"]
|
||||
# Platforms supported by the plugin
|
||||
# Support levels are "full", "partial", "none", "unknown"
|
||||
# Details of the support level are left to plugin maintainer
|
||||
[package.metadata.platforms]
|
||||
[package.metadata.platforms.support]
|
||||
windows = { level = "full", notes = "" }
|
||||
linux = { level = "full", notes = "" }
|
||||
macos = { level = "full", notes = "" }
|
||||
@@ -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,14 @@ zbus = { workspace = true }
|
||||
url = { workspace = true }
|
||||
|
||||
[target."cfg(target_os = \"macos\")".dependencies.objc2-app-kit]
|
||||
version = "0.2"
|
||||
features = ["NSWorkspace"]
|
||||
version = "0.3"
|
||||
default-features = false
|
||||
features = ["std", "NSWorkspace"]
|
||||
|
||||
[target."cfg(target_os = \"macos\")".dependencies.objc2-foundation]
|
||||
version = "0.2"
|
||||
features = ["NSURL", "NSArray", "NSString"]
|
||||
version = "0.3"
|
||||
default-features = false
|
||||
features = ["std", "NSURL", "NSArray", "NSString"]
|
||||
|
||||
[target.'cfg(target_os = "ios")'.dependencies]
|
||||
tauri = { workspace = true, features = ["wry"] }
|
||||
|
||||
@@ -98,8 +98,18 @@ fn main() {
|
||||
.plugin(tauri_plugin_opener::init())
|
||||
.setup(|app| {
|
||||
let opener = app.opener();
|
||||
|
||||
// Opens the URL in the default browser
|
||||
opener.open_url("https://example.com", None::<&str>)?;
|
||||
// Or with a specific browser/app
|
||||
opener.open_url("https://example.com", Some("firefox"))?;
|
||||
|
||||
// Opens the path with the system's default app
|
||||
opener.open_path("/path/to/file", None::<&str>)?;
|
||||
// Or with a specific app
|
||||
opener.open_path("/path/to/file", Some("firefox"))?;
|
||||
|
||||
// Reveal a path with the system's default explorer
|
||||
opener.reveal_item_in_dir("/path/to/file")?;
|
||||
Ok(())
|
||||
})
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package app.tauri.shell
|
||||
package app.tauri.opener
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
@@ -27,4 +27,4 @@ class OpenerPlugin(private val activity: Activity) : Plugin(activity) {
|
||||
invoke.reject(ex.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -3,32 +3,30 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import Foundation
|
||||
|
||||
import SwiftRs
|
||||
import Tauri
|
||||
import UIKit
|
||||
import WebKit
|
||||
|
||||
class OpenerPlugin: Plugin {
|
||||
|
||||
@objc public func open(_ invoke: Invoke) throws {
|
||||
do {
|
||||
let urlString = try invoke.parseArgs(String.self)
|
||||
if let url = URL(string: urlString) {
|
||||
if #available(iOS 10, *) {
|
||||
UIApplication.shared.open(url, options: [:])
|
||||
} else {
|
||||
UIApplication.shared.openURL(url)
|
||||
}
|
||||
}
|
||||
invoke.resolve()
|
||||
} catch {
|
||||
invoke.reject(error.localizedDescription)
|
||||
@objc public func open(_ invoke: Invoke) throws {
|
||||
do {
|
||||
let urlString = try invoke.parseArgs(String.self)
|
||||
if let url = URL(string: urlString) {
|
||||
if #available(iOS 10, *) {
|
||||
UIApplication.shared.open(url, options: [:])
|
||||
} else {
|
||||
UIApplication.shared.openURL(url)
|
||||
}
|
||||
}
|
||||
invoke.resolve()
|
||||
} catch {
|
||||
invoke.reject(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@_cdecl("init_plugin_shell")
|
||||
@_cdecl("init_plugin_opener")
|
||||
func initPlugin() -> Plugin {
|
||||
return OpenerPlugin()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-opener",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.6",
|
||||
"description": "Open files and URLs using their default application.",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
|
||||
@@ -9,7 +9,7 @@ use tauri::{
|
||||
AppHandle, Runtime,
|
||||
};
|
||||
|
||||
use crate::{scope::Scope, Error};
|
||||
use crate::{scope::Scope, Error, OpenerExt};
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn open_url<R: Runtime>(
|
||||
@@ -34,7 +34,7 @@ pub async fn open_url<R: Runtime>(
|
||||
);
|
||||
|
||||
if scope.is_url_allowed(&url, with.as_deref()) {
|
||||
crate::open_url(url, with)
|
||||
app.opener().open_url(url, with)
|
||||
} else {
|
||||
Err(Error::ForbiddenUrl { url, with })
|
||||
}
|
||||
@@ -63,7 +63,7 @@ pub async fn open_path<R: Runtime>(
|
||||
);
|
||||
|
||||
if scope.is_path_allowed(Path::new(&path), with.as_deref())? {
|
||||
crate::open_path(path, with)
|
||||
app.opener().open_path(path, with)
|
||||
} else {
|
||||
Err(Error::ForbiddenPath { path, with })
|
||||
}
|
||||
|
||||
@@ -38,16 +38,42 @@ pub struct Opener<R: Runtime> {
|
||||
impl<R: Runtime> Opener<R> {
|
||||
/// Open a url with a default or specific program.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_plugin_opener::OpenerExt;
|
||||
///
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// // open the given URL on the system default browser
|
||||
/// app.opener().open_url("https://github.com/tauri-apps/tauri", None::<&str>)?;
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// ```
|
||||
///
|
||||
/// ## Platform-specific:
|
||||
///
|
||||
/// - **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.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_plugin_opener::OpenerExt;
|
||||
///
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// // open the given URL on the system default browser
|
||||
/// app.opener().open_url("https://github.com/tauri-apps/tauri", None::<&str>)?;
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// ```
|
||||
///
|
||||
/// ## Platform-specific:
|
||||
///
|
||||
/// - **Android / iOS**: Always opens using default program.
|
||||
@@ -60,6 +86,19 @@ impl<R: Runtime> Opener<R> {
|
||||
|
||||
/// Open a path with a default or specific program.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_plugin_opener::OpenerExt;
|
||||
///
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// // open the given path on the system default explorer
|
||||
/// app.opener().open_path("/path/to/file", None::<&str>)?;
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// ```
|
||||
///
|
||||
/// ## Platform-specific:
|
||||
///
|
||||
/// - **Android / iOS**: Always opens using default program.
|
||||
@@ -69,11 +108,24 @@ 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.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri_plugin_opener::OpenerExt;
|
||||
///
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// // open the given path on the system default explorer
|
||||
/// app.opener().open_path("/path/to/file", None::<&str>)?;
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// ```
|
||||
///
|
||||
/// ## Platform-specific:
|
||||
///
|
||||
/// - **Android / iOS**: Always opens using default program.
|
||||
@@ -98,7 +150,7 @@ pub trait OpenerExt<R: Runtime> {
|
||||
fn opener(&self) -> &Opener<R>;
|
||||
}
|
||||
|
||||
impl<R: Runtime, T: Manager<R>> crate::OpenerExt<R> for T {
|
||||
impl<R: Runtime, T: Manager<R>> OpenerExt<R> for T {
|
||||
fn opener(&self) -> &Opener<R> {
|
||||
self.state::<Opener<R>>().inner()
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ pub(crate) fn open<P: AsRef<OsStr>, S: AsRef<str>>(path: P, with: Option<S>) ->
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// // open the given URL on the system default browser
|
||||
/// tauri_plugin_opener::open_url("https://github.com/tauri-apps/tauri", None)?;
|
||||
/// tauri_plugin_opener::open_url("https://github.com/tauri-apps/tauri", None::<&str>)?;
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// ```
|
||||
@@ -46,12 +46,16 @@ pub fn open_url<P: AsRef<str>, S: AsRef<str>>(url: P, with: Option<S>) -> crate:
|
||||
/// ```rust,no_run
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// // open the given URL on the system default browser
|
||||
/// tauri_plugin_opener::open_path("/path/to/file", None)?;
|
||||
/// // open the given URL on the system default explorer
|
||||
/// tauri_plugin_opener::open_path("/path/to/file", None::<&str>)?;
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// ```
|
||||
pub fn open_path<P: AsRef<Path>, S: AsRef<str>>(path: P, with: Option<S>) -> crate::Result<()> {
|
||||
let path = path.as_ref();
|
||||
if with.is_none() {
|
||||
// Returns an IO error if not exists, and besides `exists()` is a shorthand for `metadata()`
|
||||
_ = path.metadata()?;
|
||||
}
|
||||
open(path, with)
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,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"
|
||||
|
||||
@@ -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 couldn’t 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()
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
## Default Permission
|
||||
|
||||
This permission set configures which
|
||||
process feeatures are by default exposed.
|
||||
process features are by default exposed.
|
||||
|
||||
#### Granted Permissions
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
[default]
|
||||
description = """
|
||||
This permission set configures which
|
||||
process feeatures are by default exposed.
|
||||
process features are by default exposed.
|
||||
|
||||
#### Granted Permissions
|
||||
|
||||
|
||||
@@ -315,7 +315,7 @@
|
||||
"const": "deny-restart"
|
||||
},
|
||||
{
|
||||
"description": "This permission set configures which\nprocess feeatures are by default exposed.\n\n#### Granted Permissions\n\nThis enables to quit via `allow-exit` and restart via `allow-restart`\nthe application.\n",
|
||||
"description": "This permission set configures which\nprocess features are by default exposed.\n\n#### Granted Permissions\n\nThis enables to quit via `allow-exit` and restart via `allow-restart`\nthe application.\n",
|
||||
"type": "string",
|
||||
"const": "default"
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_SHELL__=function(e){"use strict";function t(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 s(e,t,s,n,i){if("function"==typeof t?e!==t||!i:!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,r;"function"==typeof SuppressedError&&SuppressedError;const o="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,n.set(this,(()=>{})),i.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,i,"f")){s(this,i,o+1),t(this,n,"f").call(this,e);const a=Object.keys(t(this,r,"f"));if(a.length>0){let e=o+1;for(const s of a.sort()){if(parseInt(s)!==e)break;{const i=t(this,r,"f")[s];delete t(this,r,"f")[s],t(this,n,"f").call(this,i),e+=1}}s(this,i,e)}}else t(this,r,"f")[o.toString()]=e}))}set onmessage(e){s(this,n,e)}get onmessage(){return t(this,n,"f")}[(n=new WeakMap,i=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=n=>{this.removeListener(e,s),t(n)};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=n=>{this.removeListener(e,s),t(n)};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 n=new u(e,t,s);return n.options.sidecar=!0,n}async spawn(){const e=this.program,t=this.args,s=this.options;"object"==typeof t&&Object.freeze(t);const n=new a;return n.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:n}).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__})}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# 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.
|
||||
|
||||
## \[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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-plugin-single-instance"
|
||||
version = "2.2.0"
|
||||
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.1.0"
|
||||
"@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");
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user