Compare commits

..

45 Commits

Author SHA1 Message Date
github-actions[bot] fb62d03f73 publish new versions (#1807)
Co-authored-by: lucasfernog <lucasfernog@users.noreply.github.com>
2024-10-02 07:02:42 -03:00
Tony 7e5e34420b Cancel auto save on save (#1859) 2024-10-01 23:13:20 -03:00
Tony f12d35609a feat(store)!: fully rework and add auto save (#1550)
* Add auto save to store plugin

* Put jsdoc at constructor instead of class level

* Clippy

* Use enum instead of bool

* Some(AutoSaveMessage::Cancel) | None

* from_millis

* u64

* Add change file

* Rename to emit_on_change

* should use Duration in `with_store`

* Add breaking change notice to change file

* Emit change event for inserts by reset

* Update readme example

* Update example

* Remove extra line

* Make description clear it only works with managed

* Fix links in docstring

* Fix doc string closing

* get_mut

* Proof of concept

* fmt

* Load store on create

* cargo fmt

* Fix merge conflits

* Format

* small cleanup

* update docs, use `impl Into<JsonValue>`

* fix doctests, further simplification of api

* add store options

---------

Co-authored-by: Tillmann <28728469+tweidinger@users.noreply.github.com>
Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2024-10-01 15:10:40 -03:00
Amr Bashir 44273b9889 fix(shell): fix schema requiring sidecar property even though it is optional (#1839)
* fix(shell): fix schema requiring `sidecar` property even though it is optional

* fix clippy

* make `cmd` and `sidecar` exclusive

* make args optional

* cleanup

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2024-10-01 10:16:14 -03:00
Jacob Bolda 2f7e32b5e0 [positioner] handleIconState in JS (#1822)
* [positioner] handleIconState in JS

* update readme

* fix change file version

* fixes

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2024-10-01 10:15:22 -03:00
Fabian-Lars 30bcf5dcc2 refactor(sql): Allow multiple drivers at the same time (#1838)
* refactor(sql): Allow multiple drivers at the same time

* fmt

* remove default feature comment [skip ci]

* what was that doing there [skip ci]

* disable public methods for now
2024-10-01 09:47:08 -03:00
Amr Bashir 68579934c9 fix(cli): expose hidden structs (#1856)
closes  #1843
2024-10-01 09:35:13 -03:00
Tony 04459afbb6 refactor(dialog)!: use enum instead of label for buttons (#1842)
* refactor(dialog)!: use enum instead of label

* Add change file

* Fix doc comment typo

* Move ok and cancel to lib.rs
2024-10-01 09:34:20 -03:00
Tillmann 3b2bd3065d fix sql heading 2024-09-30 14:11:44 +02:00
renovate[bot] f930505de4 chore(deps): lock file maintenance (#1852)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-30 10:19:10 +08:00
renovate[bot] 34319bd977 chore(deps): update unocss monorepo to ^0.63.0 (#1848)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-29 16:18:56 +08:00
Tony 34737186fe chore: re-generate reference.md (#1847) 2024-09-28 20:50:57 +03:00
renovate[bot] 4bd1f15bb9 fix(deps): update tauri monorepo (#1846)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-28 14:44:24 +08:00
Tillmann aabc4d3a24 Add Metadata for Plugin Compatibility (#1836)
Co-authored-by: Tillmann <112912081+tillmann-crabnebula@users.noreply.github.com>
Co-authored-by: Tillmann <28728469+tweidinger@users.noreply.github.com>
2024-09-26 14:21:25 +02:00
Fabian-Lars fc9b189e83 fix(fs): ignore OS specific paths in scope deserialization (#1837) 2024-09-26 02:43:33 +03:00
renovate[bot] b7ff3a6bdb fix(deps): update rust crate windows-registry to 0.3 (v2) (#1841)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <fabianlars@fabianlars.de>
2024-09-25 15:44:41 +02:00
Amr Bashir 04a0aea0ab feat(updater)!: add option to use insecure transport protocol (#1814) 2024-09-24 18:38:53 +03:00
renovate[bot] e564e2aa91 chore(deps): update dependency typescript-eslint to v8.7.0 (#1832)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-23 23:25:24 +02:00
renovate[bot] 118f6b4334 chore(deps): update dependency @rollup/plugin-node-resolve to v15.3.0 (#1831)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-23 23:11:01 +02:00
renovate[bot] fd0a52aa86 chore(deps): update eslint monorepo to v9.11.1 (#1829)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-23 22:49:03 +02:00
renovate[bot] 52e3bdab26 fix(deps): update dependency @zerodevx/svelte-json-view to v1.0.11 (v2) (#1830)
* fix(deps): update dependency @zerodevx/svelte-json-view to v1.0.11

* audit fix

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: fabianlars <fabianlars@fabianlars.de>
2024-09-23 22:45:24 +02:00
renovate[bot] dd09e3c3f4 chore(deps): update dependency @rollup/plugin-node-resolve to v15.2.4 (#1824)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-23 16:13:16 +08:00
renovate[bot] 2797954799 chore(deps): update dependency rollup to v4.22.4 (#1818)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-23 16:08:15 +08:00
renovate[bot] 025210be28 chore(deps): update eslint monorepo to v9.11.0 (#1820)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-23 16:07:35 +08:00
Amr Bashir 221f50f53b fix(updater): encode version when making requests (#1816)
* fix(updater): encode version when making requests

ref: https://github.com/tauri-apps/tauri/issues/10908

* Update .changes/updater-endpoint-version-encoded.md

* only skip `+`

* fmt

* use normal const
2024-09-20 07:57:40 -03:00
renovate[bot] 6bf1bd8d44 fix(deps): update rust crate rfd to 0.15 (v2) (#1805)
* fix(deps): update rust crate rfd to 0.15

* Fix compilation

* Add change file

* Remove platform specific note

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
2024-09-19 20:04:02 +08:00
Tony 41fe9053a0 fix(deep-link): is_registered check on windows 2024-09-19 19:58:13 +08:00
renovate[bot] 27bb5d9a27 chore(deps): update dependency rollup to v4.22.0 (v2) (#1810)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-19 12:40:55 +02:00
Austin Bennett 3168e17603 Added quotes for cmd (#1806)
* Added quotes for cmd

* Add change file

---------

Co-authored-by: Tony <legendmastertony@gmail.com>
2024-09-19 09:59:54 +08:00
Jaken Herman dd514e7a88 Docs: contaiend -> contained typos (#1802) 2024-09-17 19:31:55 +03:00
renovate[bot] 6e142b4230 fix(deps): update tauri monorepo (v2) (#1801)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-17 17:24:18 +02:00
renovate[bot] fd1c7c8dbb fix(deps): update dependency @tauri-apps/plugin-geolocation to v2.0.0-rc.2 (v2) (#1799)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-17 11:09:53 +02:00
renovate[bot] 59c63f31cc chore(deps): update dependency typescript-eslint to v8.6.0 (v2) (#1798)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-16 21:39:26 +02:00
github-actions[bot] 3cbb55aa7b publish new versions (#1796) 2024-09-16 16:29:07 -03:00
Lucas Fernandes Nogueira 60765694f5 refactor(geolocation): simplify API, defer permission checks (#1773) 2024-09-16 17:01:13 +03:00
renovate[bot] fd75401aee fix(deps): update rust crate image to 0.25 (v2) (#1418)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <fabianlars@fabianlars.de>
2024-09-16 13:20:08 +02:00
renovate[bot] ca34972266 fix(deps): update rust crate tokio-tungstenite to 0.24 (v2) (#1781)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-16 13:13:15 +02:00
renovate[bot] 179184326b chore(deps): update tauri monorepo (v2) (#1789)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-16 12:08:42 +02:00
github-actions[bot] d8efd3cd20 Publish New Versions (v2) (#1794)
Co-authored-by: amrbashir <amrbashir@users.noreply.github.com>
2024-09-16 07:00:22 -03:00
renovate[bot] 5d39ddcf22 chore(deps): lock file maintenance (#1791)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-16 10:21:19 +08:00
Tony 2050a3bea2 fix(upload): change tokio version to 1 instead of * (#1793) 2024-09-16 05:20:52 +03:00
Tony c078f57a09 Revert "Publish New Versions (v2)" (#1792)
This reverts commit dc5721ac13.
2024-09-16 05:20:21 +03:00
github-actions[bot] dc5721ac13 Publish New Versions (v2) (#1788)
Co-authored-by: lucasfernog <lucasfernog@users.noreply.github.com>
2024-09-15 18:37:58 -03:00
Felix Salazar 1d9741b52b [upload - http-extra] fix: download content to file when unsuccessful response (and test) #1750 (#1783)
* fix and test

* Update Cargo.toml

Co-authored-by: Fabian-Lars <fabianlars@fabianlars.de>

* Update Cargo.toml

Co-authored-by: Fabian-Lars <fabianlars@fabianlars.de>

* add .change log

* clippy fixes

* print test error

* fix tests

---------

Co-authored-by: Fabian-Lars <fabianlars@fabianlars.de>
Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
2024-09-15 18:37:02 -03:00
Tony 7a37355e17 fix(window-state): deadlock when trying to restore window states on initial load (#1787)
* Fix deadlock when trying to restore window the size on initial load

* Typo
2024-09-15 18:01:27 -03:00
182 changed files with 4008 additions and 16511 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"cli": patch
---
Expose `Matches`, `SubcommandMatches` and `ArgData` structs.
+5
View File
@@ -0,0 +1,5 @@
---
"deep-link": patch
---
Fix fails to start when having spaces in the main binary path on Windows
+5
View File
@@ -0,0 +1,5 @@
---
"dialog": patch
---
Update rfd to 0.15
+5
View File
@@ -0,0 +1,5 @@
---
sql: patch
---
It is now possible to enable multiple SQL backends at the same time. There will be no compile error anymore if no backends are enabled!
+5
View File
@@ -0,0 +1,5 @@
---
fs: patch
---
Fix failing to deserialize capability file when using an OS specific path in the scope that is not available on the current OS.
@@ -0,0 +1,5 @@
---
"window-state": patch
---
Fix deadlock when trying to restore window states on initial load
@@ -0,0 +1,5 @@
---
"upload": 'patch:bug'
---
fix download content to file when unsuccessful response
@@ -0,0 +1,5 @@
---
"geolocation": patch
---
No longer request permission automatically and leave to the user how to handle the `checkPermissions` and `requestPermissions` APIs.
+5
View File
@@ -0,0 +1,5 @@
---
"dialog": patch:breaking
---
Changed `MessageDialogBuilder::ok_button_label` and `MessageDialogBuilder::cancel_button_label` to `MessageDialogBuilder::buttons` which takes an enum now
@@ -0,0 +1,6 @@
---
"positioner": patch
"positioner-js": patch
---
`handleIconState` function for use in JavaScript event handlers. This allows one to update the TrayIcon state through JavaScript and fully create and handle the TrayIcon without requiring Rust (and the side-effect of creating a TrayIcon).
+17
View File
@@ -4,24 +4,31 @@
".changes/android-dialog-save.md",
".changes/barcode-dependencies.md",
".changes/barcode-scanner-validate-plist.md",
".changes/cli-hidden-structs.md",
".changes/consolidate-permission-state.md",
".changes/deep-link-event.md",
".changes/deep-link-get-current-desktop.md",
".changes/deep-link-on-new-url.md",
".changes/deep-link-register-all.md",
".changes/deep-link-space-in-path.md",
".changes/dialog-asset-scope.md",
".changes/dialog-file-response-non-exhaustive.md",
".changes/dialog-return-path.md",
".changes/dialog-rfd-015.md",
".changes/feat-multiple-sql-backends.md",
".changes/fix-barcodae-scanner-imports.md",
".changes/fix-clipboard-warnings-sdk.md",
".changes/fix-deep-link-config.md",
".changes/fix-fs-app-scopes.md",
".changes/fix-fs-scope-unknown-path.md",
".changes/fix-fs-write-file-android.md",
".changes/fix-http-plugin-abort.md",
".changes/fix-ios-file-dialog-default-mode.md",
".changes/fix-linux-updater-permission-error.md",
".changes/fix-restore-minimized-window-position.md",
".changes/fix-restore-minimized-window-state.md",
".changes/fix-restore-window-state-deadlock.md",
".changes/fix-upload-handle-non-success-download.md",
".changes/fs-dialog-file-path-methods.md",
".changes/fs-dialog-file-path-traits.md",
".changes/fs-dialog-non-exhaustive-error.md",
@@ -29,28 +36,38 @@
".changes/fs-scope-recursive-allow-read-dir.md",
".changes/fs-windows-path.md",
".changes/fs-write-file-utf8-chars.md",
".changes/geolocation-permission-refactor.md",
".changes/geolocation-release.md",
".changes/global-shortcut-0.6.md",
".changes/haptics-release.md",
".changes/iife-varname-spacing.md",
".changes/ios-dialog-save.md",
".changes/native-dialog-button-text.md",
".changes/notification-body-optional-ios.md",
".changes/notification-permission-type-change.md",
".changes/positioner-v2-handleIconState.md",
".changes/rc.md",
".changes/remove-target-sdk.md",
".changes/resolve-content-uris.md",
".changes/shell-open-regex-match-string.md",
".changes/shell-regex-match-string.md",
".changes/shell-schema-required-sidcar.md",
".changes/single-instance-deep-link.md",
".changes/single-instance-optional-deep-link.md",
".changes/single-instance-windows-sys.0.59.md",
".changes/sql-uuid-type.md",
".changes/store-api-refactor.md",
".changes/store-auto-save.md",
".changes/store-remove-mobile-plugin.md",
".changes/swift-build-older-versions.md",
".changes/tauri-rc-8.md",
".changes/update-fs-api-docs.md",
".changes/update-geolocation-api.md",
".changes/update-tauri-rc-12.md",
".changes/update-tauri-rc-3.md",
".changes/updater-endpoint-version-encoded.md",
".changes/updater-endpoints-result.md",
".changes/updater-insecure-transport-protocol.md",
".changes/updater-js-headers-download-crate.md",
".changes/updater-js-headers-download.md",
".changes/window-state-physical-size.md"
+6
View File
@@ -0,0 +1,6 @@
---
"shell": "patch"
---
Fix the plugin schema requiring to set `sidecar` property when it is in fact optional.
+5
View File
@@ -0,0 +1,5 @@
---
"store-js": patch
---
**Breaking change**: Removed the `Store` constructor and added the `createStore` API.
+7
View File
@@ -0,0 +1,7 @@
---
"store": patch
---
Add a setting `auto_save` to enable a store to debounce save on modification (on calls like set, clear, delete, reset)
**Breaking change**: Removed the `with_store` API and added `StoreExt::store_builder`.
+5
View File
@@ -0,0 +1,5 @@
---
"geolocation-js": patch
---
Update API to match other plugins.
@@ -0,0 +1,5 @@
---
'updater': 'patch'
---
Encode `+` when making updater requests which can be cause incorrectly interpolating the endpoint when using `{{current_version}}` in the endpoint where the current version contains a build number, for example `1.8.0+1`.
+5
View File
@@ -0,0 +1,5 @@
---
"updater": patch
---
**Breaking change**, Changed `UpdaterBuilder::endpoints` method to return a `Result`.
@@ -0,0 +1,5 @@
---
"updater": patch
---
Add `dangerousInsecureTransportProtocol` config option to allow using insecure transport protocols, like `http`
+2 -8
View File
@@ -148,13 +148,7 @@ jobs:
- uses: Swatinem/rust-cache@v2
- name: clippy ${{ matrix.package }}
if: matrix.package != 'tauri-plugin-sql'
run: cargo clippy --package ${{ matrix.package }} --all-targets -- -D warnings
- name: clippy ${{ matrix.package }} mysql
if: matrix.package == 'tauri-plugin-sql'
run: cargo clippy --package ${{ matrix.package }} --all-targets --no-default-features --features mysql -- -D warnings
- name: clippy ${{ matrix.package }} postgres
if: matrix.package == 'tauri-plugin-sql'
run: cargo clippy --package ${{ matrix.package }} --all-targets --no-default-features --features postgres -- -D warnings
- name: clippy ${{ matrix.package }} --all-features
run: cargo clippy --package ${{ matrix.package }} --all-targets --all-features -- -D warnings
+1 -13
View File
@@ -215,21 +215,9 @@ jobs:
run: cargo +stable install cross --git https://github.com/cross-rs/cross
- name: test ${{ matrix.package }}
if: matrix.package != 'tauri-plugin-sql' && matrix.package != 'tauri-plugin-http'
if: matrix.package != 'tauri-plugin-http'
run: ${{ matrix.platform.runner }} ${{ matrix.platform.command }} --package ${{ matrix.package }} --target ${{ matrix.platform.target }} --all-targets --all-features
- name: test ${{ matrix.package }}
if: matrix.package == 'tauri-plugin-http'
run: ${{ matrix.platform.runner }} ${{ matrix.platform.command }} --package ${{ matrix.package }} --target ${{ matrix.platform.target }} --all-targets
- name: test ${{ matrix.package }} sqlite
if: matrix.package == 'tauri-plugin-sql'
run: ${{ matrix.platform.runner }} ${{ matrix.platform.command }} --package ${{ matrix.package }} --target ${{ matrix.platform.target }} --all-targets --features sqlite
- name: test ${{ matrix.package }} mysql
if: matrix.package == 'tauri-plugin-sql'
run: ${{ matrix.platform.runner }} ${{ matrix.platform.command }} --package ${{ matrix.package }} --target ${{ matrix.platform.target }} --all-targets --features mysql
- name: test ${{ matrix.package }} postgres
if: matrix.package == 'tauri-plugin-sql'
run: ${{ matrix.platform.runner }} ${{ matrix.platform.command }} --package ${{ matrix.package }} --target ${{ matrix.platform.target }} --all-targets --features postgres
+7 -1
View File
@@ -26,9 +26,15 @@ target/
# compiled plugins
dist-js/
# plugins .tauri director
# plugins .tauri directory
/plugins/*/.tauri
# examples
examples/*/dist
plugins/*/examples/*/dist
examples/*/src-tauri/gen/schemas
plugins/*/examples/*/src-tauri/gen/schemas
# logs
logs
*.log
+1
View File
@@ -24,3 +24,4 @@ CHANGELOG.md
# mobile build
**/ios/.build
**/.tauri
plugins/*/android/build
Generated
+685 -412
View File
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -11,10 +11,10 @@ resolver = "2"
[workspace.dependencies]
serde = { version = "1", features = ["derive"] }
log = "0.4"
tauri = { version = "2.0.0-rc.12", default-features = false }
tauri-build = "2.0.0-rc.11"
tauri-plugin = "2.0.0-rc.11"
tauri-utils = "2.0.0-rc.11"
tauri = { version = "2.0.0-rc.16", default-features = false }
tauri-build = "2.0.0-rc.13"
tauri-plugin = "2.0.0-rc.13"
tauri-utils = "2.0.0-rc.13"
serde_json = "1"
thiserror = "1"
url = "2"
-2
View File
@@ -1,2 +0,0 @@
/dist/*
!/dist/.gitkeep
+6
View File
@@ -1,5 +1,11 @@
# Changelog
## \[2.0.0-rc.5]
### Dependencies
- Upgraded to `store-js@2.0.0-rc.2`
## \[2.0.0-rc.4]
### Dependencies
View File
+10 -8
View File
@@ -1,7 +1,7 @@
{
"name": "svelte-app",
"private": true,
"version": "2.0.0-rc.4",
"version": "2.0.0-rc.5",
"type": "module",
"scripts": {
"dev": "vite --clearScreen false",
@@ -9,32 +9,34 @@
"serve": "vite preview"
},
"dependencies": {
"@tauri-apps/api": "2.0.0-rc.4",
"@tauri-apps/api": "2.0.0-rc.6",
"@tauri-apps/plugin-barcode-scanner": "2.0.0-rc.2",
"@tauri-apps/plugin-biometric": "2.0.0-rc.1",
"@tauri-apps/plugin-cli": "2.0.0-rc.1",
"@tauri-apps/plugin-clipboard-manager": "2.0.0-rc.2",
"@tauri-apps/plugin-dialog": "2.0.0-rc.1",
"@tauri-apps/plugin-fs": "2.0.0-rc.2",
"@tauri-apps/plugin-geolocation": "2.0.0-rc.2",
"@tauri-apps/plugin-global-shortcut": "2.0.0-rc.1",
"@tauri-apps/plugin-haptics": "2.0.0-rc.1",
"@tauri-apps/plugin-http": "2.0.0-rc.2",
"@tauri-apps/plugin-nfc": "2.0.0-rc.1",
"@tauri-apps/plugin-notification": "2.0.0-rc.1",
"@tauri-apps/plugin-os": "2.0.0-rc.1",
"@tauri-apps/plugin-process": "2.0.0-rc.1",
"@tauri-apps/plugin-shell": "2.0.0-rc.1",
"@tauri-apps/plugin-store": "2.0.0-rc.1",
"@tauri-apps/plugin-store": "2.0.0-rc.2",
"@tauri-apps/plugin-updater": "2.0.0-rc.2",
"@zerodevx/svelte-json-view": "1.0.10"
"@zerodevx/svelte-json-view": "1.0.11"
},
"devDependencies": {
"@iconify-json/codicon": "^1.1.37",
"@iconify-json/ph": "^1.1.8",
"@sveltejs/vite-plugin-svelte": "^3.0.1",
"@tauri-apps/cli": "2.0.0-rc.14",
"@unocss/extractor-svelte": "^0.62.0",
"@tauri-apps/cli": "2.0.0-rc.17",
"@unocss/extractor-svelte": "^0.63.0",
"svelte": "^4.2.19",
"unocss": "^0.62.0",
"vite": "^5.0.13"
"unocss": "^0.63.0",
"vite": "^5.4.7"
}
}
+12
View File
@@ -1,5 +1,17 @@
# Changelog
## \[2.0.0-rc.8]
### Dependencies
- Upgraded to `cli@2.0.0-rc.2`
- Upgraded to `dialog@2.0.0-rc.8`
- Upgraded to `fs@2.0.0-rc.6`
- Upgraded to `shell@2.0.0-rc.4`
- Upgraded to `store@2.0.0-rc.4`
- Upgraded to `updater@2.0.0-rc.4`
- Upgraded to `http@2.0.0-rc.6`
## \[2.0.0-rc.7]
### Dependencies
+10 -8
View File
@@ -1,7 +1,7 @@
[package]
name = "api"
publish = false
version = "2.0.0-rc.7"
version = "2.0.0-rc.8"
description = "An example Tauri Application showcasing the api"
edition = "2021"
rust-version = { workspace = true }
@@ -20,21 +20,21 @@ serde = { workspace = true }
tiny_http = "0.12"
log = { workspace = true }
tauri-plugin-log = { path = "../../../plugins/log", version = "2.0.0-rc.2" }
tauri-plugin-fs = { path = "../../../plugins/fs", version = "2.0.0-rc.5", features = [
tauri-plugin-fs = { path = "../../../plugins/fs", version = "2.0.0-rc.6", features = [
"watch",
] }
tauri-plugin-clipboard-manager = { path = "../../../plugins/clipboard-manager", version = "2.0.0-rc.4" }
tauri-plugin-dialog = { path = "../../../plugins/dialog", version = "2.0.0-rc.7" }
tauri-plugin-dialog = { path = "../../../plugins/dialog", version = "2.0.0-rc.8" }
tauri-plugin-http = { path = "../../../plugins/http", features = [
"multipart",
], version = "2.0.0-rc.5" }
], version = "2.0.0-rc.6" }
tauri-plugin-notification = { path = "../../../plugins/notification", version = "2.0.0-rc.5", features = [
"windows7-compat",
] }
tauri-plugin-os = { path = "../../../plugins/os", version = "2.0.0-rc.1" }
tauri-plugin-process = { path = "../../../plugins/process", version = "2.0.0-rc.1" }
tauri-plugin-shell = { path = "../../../plugins/shell", version = "2.0.0-rc.3" }
tauri-plugin-store = { path = "../../../plugins/store", version = "2.0.0-rc.3" }
tauri-plugin-shell = { path = "../../../plugins/shell", version = "2.0.0-rc.4" }
tauri-plugin-store = { path = "../../../plugins/store", version = "2.0.0-rc.4" }
[dependencies.tauri]
workspace = true
@@ -50,15 +50,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.0.0-rc.1" }
tauri-plugin-cli = { path = "../../../plugins/cli", version = "2.0.0-rc.2" }
tauri-plugin-global-shortcut = { path = "../../../plugins/global-shortcut", version = "2.0.0-rc.2" }
tauri-plugin-updater = { path = "../../../plugins/updater", version = "2.0.0-rc.3" }
tauri-plugin-updater = { path = "../../../plugins/updater", version = "2.0.0-rc.4" }
tauri-plugin-window-state = { path = "../../../plugins/window-state", version = "2.0.0-rc.3" }
[target."cfg(any(target_os = \"android\", target_os = \"ios\"))".dependencies]
tauri-plugin-barcode-scanner = { path = "../../../plugins/barcode-scanner/", version = "2.0.0-rc.4" }
tauri-plugin-nfc = { path = "../../../plugins/nfc", version = "2.0.0-rc.3" }
tauri-plugin-biometric = { path = "../../../plugins/biometric/", version = "2.0.0-rc.3" }
tauri-plugin-geolocation = { path = "../../../plugins/geolocation/", version = "2.0.0-rc.3" }
tauri-plugin-haptics = { path = "../../../plugins/haptics/", version = "2.0.0-rc.3" }
[features]
prod = ["tauri/custom-protocol"]
@@ -11,6 +11,10 @@
"barcode-scanner:allow-scan",
"barcode-scanner:allow-cancel",
"barcode-scanner:allow-request-permissions",
"barcode-scanner:allow-check-permissions"
"barcode-scanner:allow-check-permissions",
"geolocation:allow-check-permissions",
"geolocation:allow-request-permissions",
"geolocation:allow-watch-position",
"geolocation:allow-get-current-position"
]
}
-1
View File
@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+2
View File
@@ -55,6 +55,8 @@ pub fn run() {
app.handle().plugin(tauri_plugin_barcode_scanner::init())?;
app.handle().plugin(tauri_plugin_nfc::init())?;
app.handle().plugin(tauri_plugin_biometric::init())?;
app.handle().plugin(tauri_plugin_geolocation::init())?;
app.handle().plugin(tauri_plugin_haptics::init())?;
}
let mut webview_window_builder =
+168 -165
View File
@@ -1,203 +1,208 @@
<script>
import { writable } from "svelte/store";
import { open } from "@tauri-apps/plugin-shell";
import { getCurrentWindow } from "@tauri-apps/api/window";
import { getCurrentWebview } from "@tauri-apps/api/webview";
import * as os from "@tauri-apps/plugin-os";
import { writable } from 'svelte/store'
import { open } from '@tauri-apps/plugin-shell'
import { getCurrentWindow } from '@tauri-apps/api/window'
import { getCurrentWebview } from '@tauri-apps/api/webview'
import * as os from '@tauri-apps/plugin-os'
import Welcome from "./views/Welcome.svelte";
import Cli from "./views/Cli.svelte";
import Communication from "./views/Communication.svelte";
import Dialog from "./views/Dialog.svelte";
import FileSystem from "./views/FileSystem.svelte";
import Http from "./views/Http.svelte";
import Notifications from "./views/Notifications.svelte";
import Shortcuts from "./views/Shortcuts.svelte";
import Shell from "./views/Shell.svelte";
import Store from "./views/Store.svelte";
import Updater from "./views/Updater.svelte";
import Clipboard from "./views/Clipboard.svelte";
import WebRTC from "./views/WebRTC.svelte";
import Scanner from "./views/Scanner.svelte";
import Biometric from "./views/Biometric.svelte";
import Welcome from './views/Welcome.svelte'
import Cli from './views/Cli.svelte'
import Communication from './views/Communication.svelte'
import Dialog from './views/Dialog.svelte'
import FileSystem from './views/FileSystem.svelte'
import Http from './views/Http.svelte'
import Notifications from './views/Notifications.svelte'
import Shortcuts from './views/Shortcuts.svelte'
import Shell from './views/Shell.svelte'
import Store from './views/Store.svelte'
import Updater from './views/Updater.svelte'
import Clipboard from './views/Clipboard.svelte'
import WebRTC from './views/WebRTC.svelte'
import Scanner from './views/Scanner.svelte'
import Biometric from './views/Biometric.svelte'
import Geolocation from './views/Geolocation.svelte'
import { onMount, tick } from "svelte";
import { ask } from "@tauri-apps/plugin-dialog";
import Nfc from "./views/Nfc.svelte";
import { onMount, tick } from 'svelte'
import { ask } from '@tauri-apps/plugin-dialog'
import Nfc from './views/Nfc.svelte'
const appWindow = getCurrentWindow();
const appWindow = getCurrentWindow()
if (appWindow.label !== "main") {
if (appWindow.label !== 'main') {
appWindow.onCloseRequested(async (event) => {
const confirmed = await confirm("Are you sure?");
const confirmed = await confirm('Are you sure?')
if (!confirmed) {
// user did not confirm closing the window; let's prevent it
event.preventDefault();
event.preventDefault()
}
});
})
}
getCurrentWebview().onDragDropEvent((event) => {
onMessage(`File drop: ${JSON.stringify(event.payload)}`);
});
onMessage(`File drop: ${JSON.stringify(event.payload)}`)
})
const userAgent = navigator.userAgent.toLowerCase();
const isMobile =
userAgent.includes("android") || userAgent.includes("iphone");
const userAgent = navigator.userAgent.toLowerCase()
const isMobile = userAgent.includes('android') || userAgent.includes('iphone')
const views = [
{
label: "Welcome",
label: 'Welcome',
component: Welcome,
icon: "i-ph-hand-waving",
icon: 'i-ph-hand-waving'
},
{
label: "Communication",
label: 'Communication',
component: Communication,
icon: "i-codicon-radio-tower",
icon: 'i-codicon-radio-tower'
},
!isMobile && {
label: "CLI",
label: 'CLI',
component: Cli,
icon: "i-codicon-terminal",
icon: 'i-codicon-terminal'
},
{
label: "Dialog",
label: 'Dialog',
component: Dialog,
icon: "i-codicon-multiple-windows",
icon: 'i-codicon-multiple-windows'
},
{
label: "File system",
label: 'File system',
component: FileSystem,
icon: "i-codicon-files",
icon: 'i-codicon-files'
},
{
label: "HTTP",
label: 'HTTP',
component: Http,
icon: "i-ph-globe-hemisphere-west",
icon: 'i-ph-globe-hemisphere-west'
},
{
label: "Notifications",
label: 'Notifications',
component: Notifications,
icon: "i-codicon-bell-dot",
icon: 'i-codicon-bell-dot'
},
!isMobile && {
label: "Shortcuts",
label: 'Shortcuts',
component: Shortcuts,
icon: "i-codicon-record-keys",
icon: 'i-codicon-record-keys'
},
{
label: "Shell",
label: 'Shell',
component: Shell,
icon: "i-codicon-terminal-bash",
icon: 'i-codicon-terminal-bash'
},
{
label: "Store",
label: 'Store',
component: Store,
icon: "i-codicon-file-code",
icon: 'i-codicon-file-code'
},
!isMobile && {
label: "Updater",
label: 'Updater',
component: Updater,
icon: "i-codicon-cloud-download",
icon: 'i-codicon-cloud-download'
},
{
label: "Clipboard",
label: 'Clipboard',
component: Clipboard,
icon: "i-codicon-clippy",
icon: 'i-codicon-clippy'
},
{
label: "WebRTC",
label: 'WebRTC',
component: WebRTC,
icon: "i-ph-broadcast",
icon: 'i-ph-broadcast'
},
isMobile && {
label: "Scanner",
label: 'Scanner',
component: Scanner,
icon: "i-ph-scan",
icon: 'i-ph-scan'
},
isMobile && {
label: "NFC",
label: 'NFC',
component: Nfc,
icon: "i-ph-nfc",
icon: 'i-ph-nfc'
},
isMobile && {
label: "Biometric",
label: 'Biometric',
component: Biometric,
icon: "i-ph-scan",
icon: 'i-ph-scan'
},
];
isMobile && {
label: 'Geolocation',
component: Geolocation,
icon: 'i-ph-map-pin'
}
]
let selected = views[0];
let selected = views[0]
function select(view) {
selected = view;
selected = view
}
// Window controls
let isWindowMaximized;
let isWindowMaximized
onMount(async () => {
isWindowMaximized = await appWindow.isMaximized();
isWindowMaximized = await appWindow.isMaximized()
appWindow.onResized(async () => {
isWindowMaximized = await appWindow.isMaximized();
});
});
isWindowMaximized = await appWindow.isMaximized()
})
})
function minimize() {
appWindow.minimize();
appWindow.minimize()
}
async function toggleMaximize() {
(await appWindow.isMaximized())
;(await appWindow.isMaximized())
? appWindow.unmaximize()
: appWindow.maximize();
: appWindow.maximize()
}
let confirmed_close = false;
let confirmed_close = false
async function close() {
if (!confirmed_close) {
confirmed_close = await ask(
"Are you sure that you want to close this window?",
'Are you sure that you want to close this window?',
{
title: "Tauri API",
title: 'Tauri API'
}
);
)
if (confirmed_close) {
appWindow.close();
appWindow.close()
}
}
}
// dark/light
let isDark;
let isDark
onMount(() => {
isDark = localStorage && localStorage.getItem("theme") == "dark";
applyTheme(isDark);
});
isDark = localStorage && localStorage.getItem('theme') == 'dark'
applyTheme(isDark)
})
function applyTheme(isDark) {
const html = document.querySelector("html");
isDark ? html.classList.add("dark") : html.classList.remove("dark");
localStorage && localStorage.setItem("theme", isDark ? "dark" : "");
const html = document.querySelector('html')
isDark ? html.classList.add('dark') : html.classList.remove('dark')
localStorage && localStorage.setItem('theme', isDark ? 'dark' : '')
}
function toggleDark() {
isDark = !isDark;
applyTheme(isDark);
isDark = !isDark
applyTheme(isDark)
}
// Console
let messages = writable([]);
let consoleTextEl;
let messages = writable([])
let consoleTextEl
async function onMessage(value) {
messages.update((r) => [
...r,
{
html:
`<pre><strong class="text-accent dark:text-darkAccent">[${new Date().toLocaleTimeString()}]:</strong> ` +
(typeof value === "string" ? value : JSON.stringify(value, null, 1)) +
"</pre>",
},
]);
await tick();
if (consoleTextEl) consoleTextEl.scrollTop = consoleTextEl.scrollHeight;
(typeof value === 'string' ? value : JSON.stringify(value, null, 1)) +
'</pre>'
}
])
await tick()
if (consoleTextEl) consoleTextEl.scrollTop = consoleTextEl.scrollHeight
}
// this function is renders HTML without sanitizing it so it's insecure
@@ -209,111 +214,109 @@
html:
`<pre><strong class="text-accent dark:text-darkAccent">[${new Date().toLocaleTimeString()}]:</strong> ` +
html +
"</pre>",
},
]);
await tick();
if (consoleTextEl) consoleTextEl.scrollTop = consoleTextEl.scrollHeight;
'</pre>'
}
])
await tick()
if (consoleTextEl) consoleTextEl.scrollTop = consoleTextEl.scrollHeight
}
function clear() {
messages.update(() => []);
messages.update(() => [])
}
let consoleEl, consoleH, cStartY;
let minConsoleHeight = 50;
let consoleEl, consoleH, cStartY
let minConsoleHeight = 50
function startResizingConsole(e) {
cStartY = e.clientY;
cStartY = e.clientY
const styles = window.getComputedStyle(consoleEl);
consoleH = parseInt(styles.height, 10);
const styles = window.getComputedStyle(consoleEl)
consoleH = parseInt(styles.height, 10)
const moveHandler = (e) => {
const dy = e.clientY - cStartY;
const newH = consoleH - dy;
const dy = e.clientY - cStartY
const newH = consoleH - dy
consoleEl.style.height = `${
newH < minConsoleHeight ? minConsoleHeight : newH
}px`;
};
}px`
}
const upHandler = () => {
document.removeEventListener("mouseup", upHandler);
document.removeEventListener("mousemove", moveHandler);
};
document.addEventListener("mouseup", upHandler);
document.addEventListener("mousemove", moveHandler);
document.removeEventListener('mouseup', upHandler)
document.removeEventListener('mousemove', moveHandler)
}
document.addEventListener('mouseup', upHandler)
document.addEventListener('mousemove', moveHandler)
}
let isWindows;
let isWindows
onMount(async () => {
isWindows = (await os.platform()) === "windows";
});
isWindows = (await os.platform()) === 'windows'
})
// mobile
let isSideBarOpen = false;
let sidebar;
let sidebarToggle;
let isDraggingSideBar = false;
let draggingStartPosX = 0;
let draggingEndPosX = 0;
const clamp = (min, num, max) => Math.min(Math.max(num, min), max);
let isSideBarOpen = false
let sidebar
let sidebarToggle
let isDraggingSideBar = false
let draggingStartPosX = 0
let draggingEndPosX = 0
const clamp = (min, num, max) => Math.min(Math.max(num, min), max)
function toggleSidebar(sidebar, isSideBarOpen) {
sidebar.style.setProperty(
"--translate-x",
`${isSideBarOpen ? "0" : "-18.75"}rem`
);
'--translate-x',
`${isSideBarOpen ? '0' : '-18.75'}rem`
)
}
onMount(() => {
sidebar = document.querySelector("#sidebar");
sidebarToggle = document.querySelector("#sidebarToggle");
sidebar = document.querySelector('#sidebar')
sidebarToggle = document.querySelector('#sidebarToggle')
document.addEventListener("click", (e) => {
document.addEventListener('click', (e) => {
if (sidebarToggle.contains(e.target)) {
isSideBarOpen = !isSideBarOpen;
isSideBarOpen = !isSideBarOpen
} else if (isSideBarOpen && !sidebar.contains(e.target)) {
isSideBarOpen = false;
isSideBarOpen = false
}
});
})
document.addEventListener("touchstart", (e) => {
if (sidebarToggle.contains(e.target)) return;
document.addEventListener('touchstart', (e) => {
if (sidebarToggle.contains(e.target)) return
const x = e.touches[0].clientX;
const x = e.touches[0].clientX
if ((0 < x && x < 20 && !isSideBarOpen) || isSideBarOpen) {
isDraggingSideBar = true;
draggingStartPosX = x;
isDraggingSideBar = true
draggingStartPosX = x
}
});
})
document.addEventListener("touchmove", (e) => {
document.addEventListener('touchmove', (e) => {
if (isDraggingSideBar) {
const x = e.touches[0].clientX;
draggingEndPosX = x;
const delta = (x - draggingStartPosX) / 10;
const x = e.touches[0].clientX
draggingEndPosX = x
const delta = (x - draggingStartPosX) / 10
sidebar.style.setProperty(
"--translate-x",
'--translate-x',
`-${clamp(0, isSideBarOpen ? 0 - delta : 18.75 - delta, 18.75)}rem`
);
)
}
});
})
document.addEventListener("touchend", () => {
document.addEventListener('touchend', () => {
if (isDraggingSideBar) {
const delta = (draggingEndPosX - draggingStartPosX) / 10;
isSideBarOpen = isSideBarOpen
? delta > -(18.75 / 2)
: delta > 18.75 / 2;
const delta = (draggingEndPosX - draggingStartPosX) / 10
isSideBarOpen = isSideBarOpen ? delta > -(18.75 / 2) : delta > 18.75 / 2
}
isDraggingSideBar = false;
});
});
isDraggingSideBar = false
})
})
$: {
const sidebar = document.querySelector("#sidebar");
const sidebar = document.querySelector('#sidebar')
if (sidebar) {
toggleSidebar(sidebar, isSideBarOpen);
toggleSidebar(sidebar, isSideBarOpen)
}
}
</script>
@@ -332,7 +335,7 @@
children:items-center children:justify-center"
>
<span
title={isDark ? "Switch to Light mode" : "Switch to Dark mode"}
title={isDark ? 'Switch to Light mode' : 'Switch to Dark mode'}
class="hover:bg-hoverOverlay active:bg-hoverOverlayDarker dark:hover:bg-darkHoverOverlay dark:active:bg-darkHoverOverlayDarker"
on:click={toggleDark}
>
@@ -350,7 +353,7 @@
<div class="i-codicon-chrome-minimize" />
</span>
<span
title={isWindowMaximized ? "Restore" : "Maximize"}
title={isWindowMaximized ? 'Restore' : 'Maximize'}
class="hover:bg-hoverOverlay active:bg-hoverOverlayDarker dark:hover:bg-darkHoverOverlay dark:active:bg-darkHoverOverlayDarker"
on:click={toggleMaximize}
>
@@ -393,7 +396,7 @@
bg-darkPrimaryLighter transition-colors-250 overflow-hidden grid select-none px-2"
>
<img
on:click={() => open("https://tauri.app/")}
on:click={() => open('https://tauri.app/')}
class="self-center p-7 cursor-pointer"
src="tauri_logo.png"
alt="Tauri logo"
@@ -449,8 +452,8 @@
href="##"
class="nv {selected === view ? 'nv_selected' : ''}"
on:click={() => {
select(view);
isSideBarOpen = false;
select(view)
isSideBarOpen = false
}}
>
<div class="{view.icon} mr-2" />
+29
View File
@@ -0,0 +1,29 @@
<script>
import {
checkPermissions,
requestPermissions,
getCurrentPosition
} from '@tauri-apps/plugin-geolocation'
export let onMessage
async function getPosition() {
let permissions = await checkPermissions()
if (
permissions.location === 'prompt' ||
permissions.location === 'prompt-with-rationale'
) {
permissions = await requestPermissions(['location'])
}
if (permissions.location === 'granted') {
getCurrentPosition().then(onMessage).catch(onMessage)
} else {
onMessage('permission denied')
}
}
</script>
<button class="btn" id="cli-matches" on:click={getPosition}>
Get Position
</button>
+6 -6
View File
@@ -10,20 +10,20 @@
"format:check": "prettier --check ."
},
"devDependencies": {
"@eslint/js": "9.10.0",
"@rollup/plugin-node-resolve": "15.2.3",
"@eslint/js": "9.11.1",
"@rollup/plugin-node-resolve": "15.3.0",
"@rollup/plugin-terser": "0.4.4",
"@rollup/plugin-typescript": "11.1.6",
"@types/eslint__js": "8.42.3",
"covector": "^0.12.0",
"eslint": "9.10.0",
"covector": "^0.12.3",
"eslint": "9.11.1",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-security": "3.0.1",
"prettier": "3.3.3",
"rollup": "4.21.3",
"rollup": "4.22.4",
"tslib": "2.7.0",
"typescript": "5.6.2",
"typescript-eslint": "8.5.0"
"typescript-eslint": "8.7.0"
},
"resolutions": {
"semver": ">=7.5.2",
+7
View File
@@ -13,6 +13,13 @@ links = "tauri-plugin-autostart"
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
linux = { level = "full", notes = "" }
macos = { level = "full", notes = "" }
android = { level = "none", notes = "" }
ios = { level = "none", notes = "" }
[build-dependencies]
tauri-plugin = { workspace = true, features = ["build"] }
@@ -15,7 +15,7 @@ disable the automatic start on boot.
- `allow-disable`
- `allow-is-enabled`
## Permission Table
## Permission Table
<table>
<tr>
+8
View File
@@ -14,6 +14,14 @@ rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
targets = ["x86_64-linux-android"]
[package.metadata.platforms.support]
windows = { level = "none", notes = "" }
linux = { level = "none", notes = "" }
macos = { level = "none", notes = "" }
android = { level = "full", notes = "" }
ios = { level = "full", notes = "" }
[build-dependencies]
tauri-plugin = { workspace = true, features = ["build"] }
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_BARCODE_SCANNER__=function(n){"use strict";async function e(n,e={},r){return window.__TAURI_INTERNALS__.invoke(n,e,r)}var r;return"function"==typeof SuppressedError&&SuppressedError,n.Format=void 0,(r=n.Format||(n.Format={})).QRCode="QR_CODE",r.UPC_A="UPC_A",r.UPC_E="UPC_E",r.EAN8="EAN_8",r.EAN13="EAN_13",r.Code39="CODE_39",r.Code93="CODE_93",r.Code128="CODE_128",r.Codabar="CODABAR",r.ITF="ITF",r.Aztec="AZTEC",r.DataMatrix="DATA_MATRIX",r.PDF417="PDF_417",n.cancel=async function(){await e("plugin:barcode-scanner|cancel")},n.checkPermissions=async function(){return await async function(n){return e(`plugin:${n}|request_permissions`)}("barcode-scanner").then((n=>n.camera))},n.openAppSettings=async function(){await e("plugin:barcode-scanner|open_app_settings")},n.requestPermissions=async function(){return await async function(n){return e(`plugin:${n}|check_permissions`)}("barcode-scanner").then((n=>n.camera))},n.scan=async function(n){return await e("plugin:barcode-scanner|scan",{...n})},n}({});Object.defineProperty(window.__TAURI__,"barcodeScanner",{value:__TAURI_PLUGIN_BARCODE_SCANNER__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_BARCODE_SCANNER__=function(n){"use strict";async function e(n,e={},r){return window.__TAURI_INTERNALS__.invoke(n,e,r)}var r;return"function"==typeof SuppressedError&&SuppressedError,n.Format=void 0,(r=n.Format||(n.Format={})).QRCode="QR_CODE",r.UPC_A="UPC_A",r.UPC_E="UPC_E",r.EAN8="EAN_8",r.EAN13="EAN_13",r.Code39="CODE_39",r.Code93="CODE_93",r.Code128="CODE_128",r.Codabar="CODABAR",r.ITF="ITF",r.Aztec="AZTEC",r.DataMatrix="DATA_MATRIX",r.PDF417="PDF_417",n.cancel=async function(){await e("plugin:barcode-scanner|cancel")},n.checkPermissions=async function(){return await async function(n){return e(`plugin:${n}|check_permissions`)}("barcode-scanner").then((n=>n.camera))},n.openAppSettings=async function(){await e("plugin:barcode-scanner|open_app_settings")},n.requestPermissions=async function(){return await async function(n){return e(`plugin:${n}|request_permissions`)}("barcode-scanner").then((n=>n.camera))},n.scan=async function(n){return await e("plugin:barcode-scanner|scan",{...n})},n}({});Object.defineProperty(window.__TAURI__,"barcodeScanner",{value:__TAURI_PLUGIN_BARCODE_SCANNER__})}
@@ -16,7 +16,7 @@ It allows all barcode related features.
- `allow-scan`
- `allow-vibrate`
## Permission Table
## Permission Table
<table>
<tr>
+8
View File
@@ -13,6 +13,14 @@ rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
targets = ["x86_64-linux-android"]
[package.metadata.platforms.support]
windows = { level = "none", notes = "" }
linux = { level = "none", notes = "" }
macos = { level = "none", notes = "" }
android = { level = "full", notes = "" }
ios = { level = "full", notes = "" }
[build-dependencies]
tauri-plugin = { workspace = true, features = ["build"] }
@@ -12,7 +12,7 @@ It allows acccess to all biometric commands.
- `allow-authenticate`
- `allow-status`
## Permission Table
## Permission Table
<table>
<tr>
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.0.0-rc.2]
- [`68579934`](https://github.com/tauri-apps/plugins-workspace/commit/68579934c93f6ed2edbc97474560d6a8a00e8f70) ([#1856](https://github.com/tauri-apps/plugins-workspace/pull/1856) by [@amrbashir](https://github.com/tauri-apps/plugins-workspace/../../amrbashir)) Expose `Matches`, `SubcommandMatches` and `ArgData` structs.
## \[2.0.0-rc.1]
- [`e2e97db5`](https://github.com/tauri-apps/plugins-workspace/commit/e2e97db51983267f5be84d4f6f0278d58834d1f5) ([#1701](https://github.com/tauri-apps/plugins-workspace/pull/1701) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Update to tauri 2.0.0-rc.8
+9 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-cli"
version = "2.0.0-rc.1"
version = "2.0.0-rc.2"
description = "Parse arguments from your Tauri application's command line interface."
edition = { workspace = true }
authors = { workspace = true }
@@ -13,6 +13,14 @@ links = "tauri-plugin-cli"
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
linux = { level = "full", notes = "" }
macos = { level = "full", notes = "" }
android = { level = "none", notes = "" }
ios = { level = "none", notes = "" }
[build-dependencies]
tauri-plugin = { workspace = true, features = ["build"] }
@@ -4,7 +4,7 @@ Allows reading the CLI matches
- `allow-cli-matches`
## Permission Table
## Permission Table
<table>
<tr>
+2
View File
@@ -18,3 +18,5 @@ impl Serialize for Error {
serializer.serialize_str(self.to_string().as_ref())
}
}
pub type Result<T> = std::result::Result<T, Error>;
+3 -2
View File
@@ -23,8 +23,9 @@ mod error;
mod parser;
use config::{Arg, Config};
pub use error::Error;
type Result<T> = std::result::Result<T, Error>;
pub use error::{Error, Result};
pub use parser::{ArgData, Matches, SubcommandMatches};
pub struct Cli<R: Runtime>(PluginApi<R, Config>);
+9 -1
View File
@@ -14,6 +14,14 @@ rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
targets = ["x86_64-unknown-linux-gnu", "x86_64-linux-android"]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
linux = { level = "full", notes = "" }
macos = { level = "full", notes = "" }
android = { level = "partial", notes = "Only plain-text content support" }
ios = { level = "partial", notes = "Only plain-text content support" }
[build-dependencies]
tauri-plugin = { workspace = true, features = ["build"] }
@@ -29,4 +37,4 @@ 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"
image = "0.24"
image = "0.25"
@@ -8,7 +8,7 @@ Clipboard interaction needs to be explicitly enabled.
## Permission Table
## Permission Table
<table>
<tr>
+1 -1
View File
@@ -91,7 +91,7 @@ impl<R: Runtime> Clipboard<R> {
&image.bytes,
image.width as u32,
image.height as u32,
image::ColorType::Rgba8,
image::ExtendedColorType::Rgba8,
)?;
let image = Image::new_owned(buffer, image.width as u32, image.height as u32);
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.0.0-rc.7]
- [`3168e176`](https://github.com/tauri-apps/plugins-workspace/commit/3168e176031a61215be542595ba90ca51f8f2d97) ([#1806](https://github.com/tauri-apps/plugins-workspace/pull/1806) by [@auggiebennett](https://github.com/tauri-apps/plugins-workspace/../../auggiebennett)) Fix fails to start when having spaces in the main binary path on Windows
## \[2.0.0-rc.6]
- [`6f3f6679`](https://github.com/tauri-apps/plugins-workspace/commit/6f3f66794a87ef9d1c16667c425d5ad7091a9c2f) ([#1780](https://github.com/tauri-apps/plugins-workspace/pull/1780)) Added `DeepLink::on_open_url` function to match the JavaScript API implementation,
+9 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-deep-link"
version = "2.0.0-rc.6"
version = "2.0.0-rc.7"
description = "Set your Tauri application as the default handler for an URL"
authors = { workspace = true }
license = { workspace = true }
@@ -14,6 +14,13 @@ rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
targets = ["x86_64-linux-android"]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
linux = { level = "full", notes = "" }
macos = { level = "partial", notes = "Runtime deep link registration is not supported" }
android = { level = "partial", notes = "Runtime deep link registration is not supported" }
ios = { level = "partial", notes = "Runtime deep link registration is not supported" }
[build-dependencies]
serde = { workspace = true }
serde_json = { workspace = true }
@@ -31,7 +38,7 @@ url = { workspace = true }
[target."cfg(windows)".dependencies]
dunce = "1"
windows-registry = "0.2"
windows-registry = "0.3"
windows-result = "0.2"
[target."cfg(target_os = \"linux\")".dependencies]
+3 -3
View File
@@ -10,12 +10,12 @@
"tauri": "tauri"
},
"dependencies": {
"@tauri-apps/api": "2.0.0-rc.4",
"@tauri-apps/api": "2.0.0-rc.6",
"@tauri-apps/plugin-deep-link": "2.0.0-rc.2"
},
"devDependencies": {
"@tauri-apps/cli": "2.0.0-rc.14",
"@tauri-apps/cli": "2.0.0-rc.17",
"typescript": "^5.2.2",
"vite": "^5.0.13"
"vite": "^5.4.7"
}
}
@@ -4,7 +4,7 @@ Allows reading the opened deep link via the get_current command
- `allow-get-current`
## Permission Table
## Permission Table
<table>
<tr>
+4 -4
View File
@@ -274,11 +274,11 @@ mod imp {
key_reg.set_string("URL Protocol", "")?;
let icon_reg = CURRENT_USER.create(format!("{key_base}\\DefaultIcon"))?;
icon_reg.set_string("", &format!("{},0", &exe))?;
icon_reg.set_string("", &format!("{exe},0"))?;
let cmd_reg = CURRENT_USER.create(format!("{key_base}\\shell\\open\\command"))?;
cmd_reg.set_string("", &format!("{} \"%1\"", &exe))?;
cmd_reg.set_string("", &format!("\"{exe}\" \"%1\""))?;
Ok(())
}
@@ -408,13 +408,13 @@ mod imp {
_protocol.as_ref()
))?;
let registered_cmd: String = cmd_reg.get_string("")?;
let registered_cmd = cmd_reg.get_string("")?;
let exe = dunce::simplified(&tauri::utils::platform::current_exe()?)
.display()
.to_string();
Ok(registered_cmd == format!("{} \"%1\"", &exe))
Ok(registered_cmd == format!("\"{exe}\" \"%1\""))
}
#[cfg(target_os = "linux")]
{
+12
View File
@@ -1,5 +1,17 @@
# Changelog
## \[2.0.0-rc.8]
- [`6bf1bd8d`](https://github.com/tauri-apps/plugins-workspace/commit/6bf1bd8d44bb95618590aa066e638509b014e0f9) ([#1805](https://github.com/tauri-apps/plugins-workspace/pull/1805) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Update rfd to 0.15
### Dependencies
- Upgraded to `fs@2.0.0-rc.6`
### breaking
- [`04459afb`](https://github.com/tauri-apps/plugins-workspace/commit/04459afbb67aafa5cd57e6a148c2beb0a8d3e04a) ([#1842](https://github.com/tauri-apps/plugins-workspace/pull/1842) by [@Legend-Master](https://github.com/tauri-apps/plugins-workspace/../../Legend-Master)) Changed `MessageDialogBuilder::ok_button_label` and `MessageDialogBuilder::cancel_button_label` to `MessageDialogBuilder::buttons` which takes an enum now
## \[2.0.0-rc.7]
### Dependencies
+10 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-dialog"
version = "2.0.0-rc.7"
version = "2.0.0-rc.8"
description = "Native system dialogs for opening and saving files along with message dialogs on your Tauri application."
edition = { workspace = true }
authors = { workspace = true }
@@ -14,6 +14,13 @@ rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
targets = ["x86_64-unknown-linux-gnu", "x86_64-linux-android"]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
linux = { level = "full", notes = "" }
macos = { level = "full", notes = "" }
android = { level = "partial", notes = "Does not support folder picker" }
ios = { level = "partial", notes = "Does not support folder picker" }
[build-dependencies]
tauri-plugin = { workspace = true, features = ["build"] }
@@ -27,13 +34,13 @@ tauri = { workspace = true }
log = { workspace = true }
thiserror = { workspace = true }
url = { workspace = true }
tauri-plugin-fs = { path = "../fs", version = "2.0.0-rc.5" }
tauri-plugin-fs = { path = "../fs", version = "2.0.0-rc.6" }
[target.'cfg(target_os = "ios")'.dependencies]
tauri = { workspace = true, features = ["wry"] }
[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
rfd = { version = "0.14", default-features = false, features = [
rfd = { version = "0.15", default-features = false, features = [
"tokio",
"gtk3",
"common-controls-v6",
@@ -16,7 +16,7 @@ All dialog types are enabled.
- `allow-save`
- `allow-open`
## Permission Table
## Permission Table
<table>
<tr>
+32 -19
View File
@@ -8,7 +8,10 @@ use serde::{Deserialize, Serialize};
use tauri::{command, Manager, Runtime, State, Window};
use tauri_plugin_fs::FsExt;
use crate::{Dialog, FileDialogBuilder, FilePath, MessageDialogKind, Result};
use crate::{
Dialog, FileDialogBuilder, FilePath, MessageDialogButtons, MessageDialogKind, Result, CANCEL,
OK,
};
#[derive(Serialize)]
#[serde(untagged)]
@@ -205,7 +208,7 @@ pub(crate) async fn save<R: Runtime>(
options: SaveDialogOptions,
) -> Result<Option<FilePath>> {
let mut dialog_builder = dialog.file();
#[cfg(any(windows, target_os = "macos"))]
#[cfg(desktop)]
{
dialog_builder = dialog_builder.set_parent(&window);
}
@@ -244,16 +247,17 @@ fn message_dialog<R: Runtime>(
title: Option<String>,
message: String,
kind: Option<MessageDialogKind>,
ok_button_label: Option<String>,
cancel_button_label: Option<String>,
buttons: MessageDialogButtons,
) -> bool {
let mut builder = dialog.message(message);
builder = builder.buttons(buttons);
if let Some(title) = title {
builder = builder.title(title);
}
#[cfg(any(windows, target_os = "macos"))]
#[cfg(desktop)]
{
builder = builder.parent(&window);
}
@@ -262,14 +266,6 @@ fn message_dialog<R: Runtime>(
builder = builder.kind(kind);
}
if let Some(ok) = ok_button_label {
builder = builder.ok_button_label(ok);
}
if let Some(cancel) = cancel_button_label {
builder = builder.cancel_button_label(cancel);
}
builder.blocking_show()
}
@@ -288,8 +284,11 @@ pub(crate) async fn message<R: Runtime>(
title,
message,
kind,
ok_button_label,
None,
if let Some(ok_button_label) = ok_button_label {
MessageDialogButtons::OkCustom(ok_button_label)
} else {
MessageDialogButtons::Ok
},
))
}
@@ -309,8 +308,7 @@ pub(crate) async fn ask<R: Runtime>(
title,
message,
kind,
Some(ok_button_label.unwrap_or_else(|| "Yes".into())),
Some(cancel_button_label.unwrap_or_else(|| "No".into())),
get_ok_cancel_type(ok_button_label, cancel_button_label),
))
}
@@ -330,7 +328,22 @@ pub(crate) async fn confirm<R: Runtime>(
title,
message,
kind,
Some(ok_button_label.unwrap_or_else(|| "Ok".into())),
Some(cancel_button_label.unwrap_or_else(|| "Cancel".into())),
get_ok_cancel_type(ok_button_label, cancel_button_label),
))
}
fn get_ok_cancel_type(
ok_button_label: Option<String>,
cancel_button_label: Option<String>,
) -> MessageDialogButtons {
if let Some(ok_button_label) = ok_button_label {
MessageDialogButtons::OkCancelCustom(
ok_button_label,
cancel_button_label.unwrap_or(CANCEL.to_string()),
)
} else if let Some(cancel_button_label) = cancel_button_label {
MessageDialogButtons::OkCancelCustom(OK.to_string(), cancel_button_label)
} else {
MessageDialogButtons::OkCancel
}
}
+45 -20
View File
@@ -8,14 +8,12 @@
//! to give results back. This is particularly useful when running dialogs from the main thread.
//! When using on asynchronous contexts such as async commands, the [`blocking`] APIs are recommended.
use raw_window_handle::{HasWindowHandle, RawWindowHandle};
use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle};
use rfd::{AsyncFileDialog, AsyncMessageDialog};
use serde::de::DeserializeOwned;
use tauri::{plugin::PluginApi, AppHandle, Runtime};
use crate::{models::*, FileDialogBuilder, FilePath, MessageDialogBuilder};
const OK: &str = "Ok";
use crate::{models::*, FileDialogBuilder, FilePath, MessageDialogBuilder, OK};
pub fn init<R: Runtime, C: DeserializeOwned>(
app: &AppHandle<R>,
@@ -50,13 +48,34 @@ impl From<MessageDialogKind> for rfd::MessageLevel {
}
}
struct WindowHandle(RawWindowHandle);
#[derive(Debug)]
pub(crate) struct WindowHandle {
window_handle: RawWindowHandle,
display_handle: RawDisplayHandle,
}
impl WindowHandle {
pub(crate) fn new(window_handle: RawWindowHandle, display_handle: RawDisplayHandle) -> Self {
Self {
window_handle,
display_handle,
}
}
}
impl HasWindowHandle for WindowHandle {
fn window_handle(
&self,
) -> Result<raw_window_handle::WindowHandle<'_>, raw_window_handle::HandleError> {
Ok(unsafe { raw_window_handle::WindowHandle::borrow_raw(self.0) })
Ok(unsafe { raw_window_handle::WindowHandle::borrow_raw(self.window_handle) })
}
}
impl HasDisplayHandle for WindowHandle {
fn display_handle(
&self,
) -> Result<raw_window_handle::DisplayHandle<'_>, raw_window_handle::HandleError> {
Ok(unsafe { raw_window_handle::DisplayHandle::borrow_raw(self.display_handle) })
}
}
@@ -79,7 +98,7 @@ impl<R: Runtime> From<FileDialogBuilder<R>> for AsyncFileDialog {
}
#[cfg(desktop)]
if let Some(parent) = d.parent {
builder = builder.set_parent(&WindowHandle(parent));
builder = builder.set_parent(&parent);
}
builder = builder.set_can_create_directories(d.can_create_directories.unwrap_or(true));
@@ -88,25 +107,27 @@ impl<R: Runtime> From<FileDialogBuilder<R>> for AsyncFileDialog {
}
}
impl From<MessageDialogButtons> for rfd::MessageButtons {
fn from(value: MessageDialogButtons) -> Self {
match value {
MessageDialogButtons::Ok => Self::Ok,
MessageDialogButtons::OkCancel => Self::OkCancel,
MessageDialogButtons::OkCustom(ok) => Self::OkCustom(ok),
MessageDialogButtons::OkCancelCustom(ok, cancel) => Self::OkCancelCustom(ok, cancel),
}
}
}
impl<R: Runtime> From<MessageDialogBuilder<R>> for AsyncMessageDialog {
fn from(d: MessageDialogBuilder<R>) -> Self {
let mut dialog = AsyncMessageDialog::new()
.set_title(&d.title)
.set_description(&d.message)
.set_level(d.kind.into());
let buttons = match (d.ok_button_label, d.cancel_button_label) {
(Some(ok), Some(cancel)) => Some(rfd::MessageButtons::OkCancelCustom(ok, cancel)),
(Some(ok), None) => Some(rfd::MessageButtons::OkCustom(ok)),
(None, Some(cancel)) => Some(rfd::MessageButtons::OkCancelCustom(OK.into(), cancel)),
(None, None) => None,
};
if let Some(buttons) = buttons {
dialog = dialog.set_buttons(buttons);
}
.set_level(d.kind.into())
.set_buttons(d.buttons.into());
if let Some(parent) = d.parent {
dialog = dialog.set_parent(&WindowHandle(parent));
dialog = dialog.set_parent(&parent);
}
dialog
@@ -192,7 +213,11 @@ pub fn show_message_dialog<R: Runtime, F: FnOnce(bool) + Send + 'static>(
) {
use rfd::MessageDialogResult;
let ok_label = dialog.ok_button_label.clone();
let ok_label = match &dialog.buttons {
MessageDialogButtons::OkCustom(ok) => Some(ok.clone()),
MessageDialogButtons::OkCancelCustom(ok, _) => Some(ok.clone()),
_ => None,
};
let f = move |res| {
f(match res {
MessageDialogResult::Ok | MessageDialogResult::Yes => true,
+52 -37
View File
@@ -41,6 +41,9 @@ use desktop::*;
#[cfg(mobile)]
use mobile::*;
pub(crate) const OK: &str = "Ok";
pub(crate) const CANCEL: &str = "Cancel";
macro_rules! blocking_fn {
($self:ident, $fn:ident) => {{
let (tx, rx) = sync_channel(0);
@@ -89,14 +92,13 @@ impl<R: Runtime> Dialog<R> {
/// - Ask dialog:
///
/// ```
/// use tauri_plugin_dialog::DialogExt;
/// use tauri_plugin_dialog::{DialogExt, MessageDialogButtons};
///
/// tauri::Builder::default()
/// .setup(|app| {
/// app.dialog()
/// .message("Are you sure?")
/// .ok_button_label("Yes")
/// .cancel_button_label("No")
/// .buttons(MessageDialogButtons::OkCancelCustom("Yes", "No"))
/// .show(|yes| {
/// println!("user said {}", if yes { "yes" } else { "no" });
/// });
@@ -107,13 +109,13 @@ impl<R: Runtime> Dialog<R> {
/// - Message dialog with OK button:
///
/// ```
/// use tauri_plugin_dialog::DialogExt;
/// use tauri_plugin_dialog::{DialogExt, MessageDialogButtons};
///
/// tauri::Builder::default()
/// .setup(|app| {
/// app.dialog()
/// .message("Job completed successfully")
/// .ok_button_label("Ok")
/// .buttons(MessageDialogButtons::Ok)
/// .show(|_| {
/// println!("dialog closed");
/// });
@@ -129,7 +131,7 @@ impl<R: Runtime> Dialog<R> {
/// but note that it cannot be executed on the main thread as it will freeze your application.
///
/// ```
/// use tauri_plugin_dialog::DialogExt;
/// use tauri_plugin_dialog::{DialogExt, MessageDialogButtons};
///
/// tauri::Builder::default()
/// .setup(|app| {
@@ -137,8 +139,7 @@ impl<R: Runtime> Dialog<R> {
/// std::thread::spawn(move || {
/// let yes = handle.dialog()
/// .message("Are you sure?")
/// .ok_button_label("Yes")
/// .cancel_button_label("No")
/// .buttons(MessageDialogButtons::OkCancelCustom("Yes", "No"))
/// .blocking_show();
/// });
///
@@ -196,10 +197,9 @@ pub struct MessageDialogBuilder<R: Runtime> {
pub(crate) title: String,
pub(crate) message: String,
pub(crate) kind: MessageDialogKind,
pub(crate) ok_button_label: Option<String>,
pub(crate) cancel_button_label: Option<String>,
pub(crate) buttons: MessageDialogButtons,
#[cfg(desktop)]
pub(crate) parent: Option<raw_window_handle::RawWindowHandle>,
pub(crate) parent: Option<crate::desktop::WindowHandle>,
}
/// Payload for the message dialog mobile API.
@@ -210,8 +210,8 @@ pub(crate) struct MessageDialogPayload<'a> {
title: &'a String,
message: &'a String,
kind: &'a MessageDialogKind,
ok_button_label: &'a Option<String>,
cancel_button_label: &'a Option<String>,
ok_button_label: Option<&'a str>,
cancel_button_label: Option<&'a str>,
}
// raw window handle :(
@@ -225,8 +225,7 @@ impl<R: Runtime> MessageDialogBuilder<R> {
title: title.into(),
message: message.into(),
kind: Default::default(),
ok_button_label: None,
cancel_button_label: None,
buttons: Default::default(),
#[cfg(desktop)]
parent: None,
}
@@ -234,12 +233,20 @@ impl<R: Runtime> MessageDialogBuilder<R> {
#[cfg(mobile)]
pub(crate) fn payload(&self) -> MessageDialogPayload<'_> {
let (ok_button_label, cancel_button_label) = match &self.buttons {
MessageDialogButtons::Ok => (Some(OK), None),
MessageDialogButtons::OkCancel => (Some(OK), Some(CANCEL)),
MessageDialogButtons::OkCustom(ok) => (Some(ok.as_str()), Some(CANCEL)),
MessageDialogButtons::OkCancelCustom(ok, cancel) => {
(Some(ok.as_str()), Some(cancel.as_str()))
}
};
MessageDialogPayload {
title: &self.title,
message: &self.message,
kind: &self.kind,
ok_button_label: &self.ok_button_label,
cancel_button_label: &self.cancel_button_label,
ok_button_label,
cancel_button_label,
}
}
@@ -250,27 +257,25 @@ impl<R: Runtime> MessageDialogBuilder<R> {
}
/// Set parent windows explicitly (optional)
///
/// ## Platform-specific
///
/// - **Linux:** Unsupported.
#[cfg(desktop)]
pub fn parent<W: raw_window_handle::HasWindowHandle>(mut self, parent: &W) -> Self {
if let Ok(h) = parent.window_handle() {
self.parent.replace(h.as_raw());
pub fn parent<W: raw_window_handle::HasWindowHandle + raw_window_handle::HasDisplayHandle>(
mut self,
parent: &W,
) -> Self {
if let (Ok(window_handle), Ok(display_handle)) =
(parent.window_handle(), parent.display_handle())
{
self.parent.replace(crate::desktop::WindowHandle::new(
window_handle.as_raw(),
display_handle.as_raw(),
));
}
self
}
/// Sets the label for the OK button.
pub fn ok_button_label(mut self, label: impl Into<String>) -> Self {
self.ok_button_label.replace(label.into());
self
}
/// Sets the label for the Cancel button.
pub fn cancel_button_label(mut self, label: impl Into<String>) -> Self {
self.cancel_button_label.replace(label.into());
/// Sets the dialog buttons.
pub fn buttons(mut self, buttons: MessageDialogButtons) -> Self {
self.buttons = buttons;
self
}
@@ -314,7 +319,7 @@ pub struct FileDialogBuilder<R: Runtime> {
pub(crate) title: Option<String>,
pub(crate) can_create_directories: Option<bool>,
#[cfg(desktop)]
pub(crate) parent: Option<raw_window_handle::RawWindowHandle>,
pub(crate) parent: Option<crate::desktop::WindowHandle>,
}
#[cfg(mobile)]
@@ -380,9 +385,19 @@ impl<R: Runtime> FileDialogBuilder<R> {
/// Sets the parent window of the dialog.
#[cfg(desktop)]
#[must_use]
pub fn set_parent<W: raw_window_handle::HasWindowHandle>(mut self, parent: &W) -> Self {
if let Ok(h) = parent.window_handle() {
self.parent.replace(h.as_raw());
pub fn set_parent<
W: raw_window_handle::HasWindowHandle + raw_window_handle::HasDisplayHandle,
>(
mut self,
parent: &W,
) -> Self {
if let (Ok(window_handle), Ok(display_handle)) =
(parent.window_handle(), parent.display_handle())
{
self.parent.replace(crate::desktop::WindowHandle::new(
window_handle.as_raw(),
display_handle.as_raw(),
));
}
self
}
+15
View File
@@ -49,3 +49,18 @@ impl Serialize for MessageDialogKind {
}
}
}
/// Set of button that will be displayed on the dialog
#[non_exhaustive]
#[derive(Debug, Default, Clone)]
pub enum MessageDialogButtons {
#[default]
/// A single `Ok` button with OS default dialog text
Ok,
/// 2 buttons `Ok` and `Cancel` with OS default dialog texts
OkCancel,
/// A single `Ok` button with custom text
OkCustom(String),
/// 2 buttons `Ok` and `Cancel` with custom texts
OkCancelCustom(String, String),
}
+4
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.0.0-rc.6]
- [`fc9b189e`](https://github.com/tauri-apps/plugins-workspace/commit/fc9b189e83a29bd750714ec6336133c6eabdfa20) ([#1837](https://github.com/tauri-apps/plugins-workspace/pull/1837) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Fix failing to deserialize capability file when using an OS specific path in the scope that is not available on the current OS.
## \[2.0.0-rc.5]
- [`cc03ccf5`](https://github.com/tauri-apps/plugins-workspace/commit/cc03ccf5e0e4be8bbf50bbdebe957c84be7f779b) ([#1774](https://github.com/tauri-apps/plugins-workspace/pull/1774)) Fix `scope-app`, `scope-app-recursive` and `scope-index` not properly enabling the application paths.
+8 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-fs"
version = "2.0.0-rc.5"
version = "2.0.0-rc.6"
description = "Access the file system."
authors = { workspace = true }
license = { workspace = true }
@@ -13,6 +13,13 @@ links = "tauri-plugin-fs"
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
linux = { level = "full", notes = "No write access to `$RESOURCES` folder" }
macos = { level = "full", notes = "No write access to `$RESOURCES` folder" }
android = { level = "partial", notes = "Access is restricted to Application folder by default" }
ios = { level = "partial", notes = "Access is restricted to Application folder by default" }
[build-dependencies]
tauri-plugin = { workspace = true, features = ["build"] }
schemars = { workspace = true }
+10 -8
View File
@@ -24,14 +24,16 @@ enum FsScopeEntry {
},
}
// Ensure scope entry is kept up to date
impl From<FsScopeEntry> for scope::EntryRaw {
fn from(value: FsScopeEntry) -> Self {
match value {
FsScopeEntry::Value(path) => scope::EntryRaw::Value(path),
FsScopeEntry::Object { path } => scope::EntryRaw::Object { path },
}
}
// Ensure `FsScopeEntry` and `scope::EntryRaw` is kept in sync
fn _f() {
match scope::EntryRaw::Value(PathBuf::new()) {
scope::EntryRaw::Value(path) => FsScopeEntry::Value(path),
scope::EntryRaw::Object { path } => FsScopeEntry::Object { path },
};
match FsScopeEntry::Value(PathBuf::new()) {
FsScopeEntry::Value(path) => scope::EntryRaw::Value(path),
FsScopeEntry::Object { path } => scope::EntryRaw::Object { path },
};
}
const BASE_DIR_VARS: &[&str] = &[
@@ -30,7 +30,7 @@ On Windows the webview data folder access is denied.
- `read-app-specific-dirs-recursive`
- `deny-default`
## Permission Table
## Permission Table
<table>
<tr>
+4 -4
View File
@@ -993,8 +993,8 @@ pub fn resolve_path<R: Runtime>(
.unwrap()
.clone()
.into_iter()
.chain(global_scope.allows().iter().map(|e| e.path.clone()))
.chain(command_scope.allows().iter().map(|e| e.path.clone()))
.chain(global_scope.allows().iter().filter_map(|e| e.path.clone()))
.chain(command_scope.allows().iter().filter_map(|e| e.path.clone()))
.collect(),
deny: webview
.fs_scope()
@@ -1003,8 +1003,8 @@ pub fn resolve_path<R: Runtime>(
.unwrap()
.clone()
.into_iter()
.chain(global_scope.denies().iter().map(|e| e.path.clone()))
.chain(command_scope.denies().iter().map(|e| e.path.clone()))
.chain(global_scope.denies().iter().filter_map(|e| e.path.clone()))
.chain(command_scope.denies().iter().filter_map(|e| e.path.clone()))
.collect(),
require_literal_leading_dot: webview.fs_scope().require_literal_leading_dot,
},
+2 -2
View File
@@ -35,7 +35,7 @@ pub enum SafeFilePath {
}
impl FilePath {
/// Get a reference to the contaiend [`Path`] if the variant is [`FilePath::Path`].
/// Get a reference to the contained [`Path`] if the variant is [`FilePath::Path`].
///
/// Use [`FilePath::into_path`] to try to convert the [`FilePath::Url`] variant as well.
#[inline]
@@ -73,7 +73,7 @@ impl FilePath {
}
impl SafeFilePath {
/// Get a reference to the contaiend [`Path`] if the variant is [`SafeFilePath::Path`].
/// Get a reference to the contained [`Path`] if the variant is [`SafeFilePath::Path`].
///
/// Use [`SafeFilePath::into_path`] to try to convert the [`SafeFilePath::Url`] variant as well.
#[inline]
+9 -9
View File
@@ -353,17 +353,17 @@ impl ScopeObject for scope::Entry {
app: &AppHandle<R>,
raw: Value,
) -> std::result::Result<Self, Self::Error> {
let entry = serde_json::from_value(raw.into()).map(|raw| {
let path = match raw {
scope::EntryRaw::Value(path) => path,
scope::EntryRaw::Object { path } => path,
};
Self { path }
let path = serde_json::from_value(raw.into()).map(|raw| match raw {
scope::EntryRaw::Value(path) => path,
scope::EntryRaw::Object { path } => path,
})?;
Ok(Self {
path: app.path().parse(entry.path)?,
})
match app.path().parse(path) {
Ok(path) => Ok(Self { path: Some(path) }),
#[cfg(not(target_os = "android"))]
Err(tauri::Error::UnknownPath) => Ok(Self { path: None }),
Err(err) => Err(err.into()),
}
}
}
+2 -3
View File
@@ -13,17 +13,16 @@ use std::{
use serde::Deserialize;
#[doc(hidden)]
#[derive(Deserialize)]
#[serde(untagged)]
pub enum EntryRaw {
pub(crate) enum EntryRaw {
Value(PathBuf),
Object { path: PathBuf },
}
#[derive(Debug)]
pub struct Entry {
pub path: PathBuf,
pub path: Option<PathBuf>,
}
pub type EventId = u32;
+5
View File
@@ -1,5 +1,9 @@
# Changelog
## \[2.0.0-rc.2]
- [`60765694`](https://github.com/tauri-apps/plugins-workspace/commit/60765694f54875e22b8eb70b1d2e32dbf0c585c7) ([#1773](https://github.com/tauri-apps/plugins-workspace/pull/1773) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Update API to match other plugins.
## \[2.0.0-rc.1]
- [`e2e97db5`](https://github.com/tauri-apps/plugins-workspace/commit/e2e97db51983267f5be84d4f6f0278d58834d1f5) ([#1701](https://github.com/tauri-apps/plugins-workspace/pull/1701) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Use `PermissionState` from the `tauri` crate, which now also includes a "prompt with rationale" variant for Android (returned when your app must explain to the user why it needs the permission).
@@ -21,3 +25,4 @@
- [`9606089b`](https://github.com/tauri-apps/plugins-workspace/commit/9606089b2add4a17f80ed5a09d59ce94824bd672) ([#1599](https://github.com/tauri-apps/plugins-workspace/pull/1599)) Initial release.
- [`9887d1`](https://github.com/tauri-apps/plugins-workspace/commit/9887d14bd0e971c4c0f5c1188fc4005d3fc2e29e) Update to tauri RC.
tauri-apps/plugins-workspace/commit/9887d14bd0e971c4c0f5c1188fc4005d3fc2e29e) Update to tauri RC.
+8 -1
View File
@@ -1,7 +1,7 @@
[package]
name = "tauri-plugin-geolocation"
description = "Get and track the device's current position"
version = "2.0.0-rc.3"
version = "2.0.0-rc.4"
edition = { workspace = true }
authors = { workspace = true }
license = { workspace = true }
@@ -13,6 +13,13 @@ rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
targets = ["x86_64-linux-android"]
[package.metadata.platforms.support]
windows = { level = "none", notes = "" }
linux = { level = "none", notes = "" }
macos = { level = "none", notes = "" }
android = { level = "full", notes = "" }
ios = { level = "full", notes = "" }
[build-dependencies]
tauri-plugin = { workspace = true, features = ["build"] }
+23 -8
View File
@@ -87,16 +87,31 @@ fn main() {
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
import { getCurrentPosition, watchPosition } from '@tauri-apps/plugin-log'
import {
checkPermissions,
requestPermissions,
getCurrentPosition,
watchPosition
} from '@tauri-apps/plugin-log'
const pos = await getCurrentPosition()
let permissions = await checkPermissions()
if (
permissions.location === 'prompt' ||
permissions.location === 'prompt-with-rationale'
) {
permissions = await requestPermissions(['location'])
}
await watchPosition(
{ enableHighAccuracy: true, timeout: 10000, maximumAge: 0 },
(pos) => {
console.log(pos)
}
)
if (permissions.location === 'granted') {
const pos = await getCurrentPosition()
await watchPosition(
{ enableHighAccuracy: true, timeout: 10000, maximumAge: 0 },
(pos) => {
console.log(pos)
}
)
}
```
## Contributing
@@ -60,18 +60,8 @@ private const val ALIAS_COARSE_LOCATION: String = "coarseLocation"
]
)
class GeolocationPlugin(private val activity: Activity): Plugin(activity) {
private lateinit var implementation: Geolocation// = Geolocation(activity.applicationContext)
private var watchers = hashMapOf<Long, Invoke>()
// If multiple permissions get requested in quick succession not all callbacks will be fired,
// So we'll store all requests ourselves instead of using the callback argument.
private var positionRequests = mutableListOf<Invoke>()
private var watchRequests = mutableListOf<Invoke>()
// If getCurrentPosition or watchPosition are called before a prior call is done requesting permission,
// the callback will be called with denied for the prior call(s) so we keep track of them to make sure
// to only run the logic on the last request.
// TODO: Find a better solution after switching to explicit requestPermissions call - likely needs changes in Tauri
private var ongoingPermissionRequests = 0;
private lateinit var implementation: Geolocation
private var watchers = hashMapOf<Long, Pair<Invoke, WatchArgs>>()
override fun load(webView: WebView) {
super.load(webView)
@@ -86,8 +76,9 @@ class GeolocationPlugin(private val activity: Activity): Plugin(activity) {
override fun onResume() {
super.onResume()
for (watcher in watchers.values) {
startWatch(watcher)
// resume watchers
for ((watcher, args) in watchers.values) {
startWatch(watcher, args)
}
}
@@ -112,83 +103,39 @@ class GeolocationPlugin(private val activity: Activity): Plugin(activity) {
@Command
fun getCurrentPosition(invoke: Invoke) {
val args = invoke.parseArgs(PositionOptions::class.java)
val alias = getAlias(args.enableHighAccuracy)
if (getPermissionState(alias) != PermissionState.GRANTED) {
Logger.error("NOT GRANTED");
this.positionRequests.add(invoke)
this.ongoingPermissionRequests += 1
requestPermissionForAlias(alias, invoke, "positionPermissionCallback")
val location = implementation.getLastLocation(args.maximumAge)
if (location != null) {
invoke.resolve(convertLocation(location))
} else {
Logger.error("GRANTED");
getPosition(invoke, args)
implementation.sendLocation(args.enableHighAccuracy,
{ loc -> invoke.resolve(convertLocation(loc)) },
{ error -> invoke.reject(error) })
}
}
@PermissionCallback
private fun positionPermissionCallback(invoke: Invoke) {
Logger.error("positionPermissionCallback - ongoingRequests: " + this.ongoingPermissionRequests.toString())
this.ongoingPermissionRequests -= 1
if (this.ongoingPermissionRequests > 0) {
return
}
val pRequests = this.positionRequests.toTypedArray()
val wRequests = this.watchRequests.toTypedArray()
this.positionRequests.clear()
this.watchRequests.clear()
// TODO: capacitor only checks for coarse here
val permissionGranted = getPermissionState(ALIAS_COARSE_LOCATION) == PermissionState.GRANTED;
Logger.error("positionPermissionCallback - permissionGranted: $permissionGranted");
for (inv in pRequests) {
if (permissionGranted) {
val args = inv.parseArgs(PositionOptions::class.java)
implementation.sendLocation(args.enableHighAccuracy,
{ location -> inv.resolve(convertLocation(location)) },
{ error -> inv.reject(error) })
} else {
inv.reject("Location permission was denied.")
}
}
for (inv in wRequests) {
if (permissionGranted) {
startWatch(invoke)
} else {
inv.reject("Location permission was denied.")
}
}
val permissionsResultJSON = JSObject()
permissionsResultJSON.put("location", getPermissionState(ALIAS_LOCATION))
permissionsResultJSON.put("coarseLocation", getPermissionState(ALIAS_COARSE_LOCATION))
invoke.resolve(permissionsResultJSON)
}
@Command
fun watchPosition(invoke: Invoke) {
val args = invoke.parseArgs(WatchArgs::class.java)
val alias = getAlias(args.options.enableHighAccuracy)
if (getPermissionState(alias) != PermissionState.GRANTED) {
this.watchRequests.add(invoke)
this.ongoingPermissionRequests += 1
requestPermissionForAlias(alias, invoke, "positionPermissionCallback")
} else {
startWatch(invoke)
}
startWatch(invoke, args)
}
private fun startWatch(invoke: Invoke) {
val args = invoke.parseArgs(WatchArgs::class.java)
private fun startWatch(invoke: Invoke, args: WatchArgs) {
implementation.requestLocationUpdates(
args.options.enableHighAccuracy,
args.options.timeout,
{ location -> args.channel.send(convertLocation(location)) },
{ error -> args.channel.sendObject(error) })
watchers[args.channel.id] = invoke
watchers[args.channel.id] = Pair(invoke, args)
}
@Command
@@ -204,19 +151,6 @@ class GeolocationPlugin(private val activity: Activity): Plugin(activity) {
invoke.resolve()
}
private fun getPosition(invoke: Invoke, options: PositionOptions) {
val location = implementation.getLastLocation(options.maximumAge)
if (location != null) {
Logger.error("getPosition location non-null")
invoke.resolve(convertLocation(location))
} else {
Logger.error("getPosition location null")
implementation.sendLocation(options.enableHighAccuracy,
{ loc -> invoke.resolve(convertLocation(loc)) },
{ error -> invoke.reject(error) })
}
}
private fun convertLocation(location: Location): JSObject {
val ret = JSObject()
val coords = JSObject()
@@ -235,14 +169,4 @@ class GeolocationPlugin(private val activity: Activity): Plugin(activity) {
return ret
}
private fun getAlias(enableHighAccuracy: Boolean): String {
var alias = ALIAS_LOCATION;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
if (!enableHighAccuracy) {
alias = ALIAS_COARSE_LOCATION;
}
}
return alias
}
}
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_PLUGIN_GEOLOCATION__=function(t){"use strict";function r(t,r,e,s){if("a"===e&&!s)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof r?t!==r||!s:!r.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===e?s:"a"===e?s.call(t):s?s.value:r.get(t)}function e(t,r,e,s,o){if("function"==typeof r?t!==r||!o:!r.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return r.set(t,e),e}var s,o,i,a;"function"==typeof SuppressedError&&SuppressedError;class n{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,s.set(this,(()=>{})),o.set(this,0),i.set(this,{}),this.id=function(t,r=!1){return window.__TAURI_INTERNALS__.transformCallback(t,r)}((({message:t,id:a})=>{if(a===r(this,o,"f")){e(this,o,a+1),r(this,s,"f").call(this,t);const n=Object.keys(r(this,i,"f"));if(n.length>0){let t=a+1;for(const e of n.sort()){if(parseInt(e)!==t)break;{const o=r(this,i,"f")[e];delete r(this,i,"f")[e],r(this,s,"f").call(this,o),t+=1}}e(this,o,t)}}else r(this,i,"f")[a.toString()]=t}))}set onmessage(t){e(this,s,t)}get onmessage(){return r(this,s,"f")}toJSON(){return`__CHANNEL__:${this.id}`}}async function c(t,r={},e){return window.__TAURI_INTERNALS__.invoke(t,r,e)}s=new WeakMap,o=new WeakMap,i=new WeakMap,function(t){t.WINDOW_RESIZED="tauri://resize",t.WINDOW_MOVED="tauri://move",t.WINDOW_CLOSE_REQUESTED="tauri://close-requested",t.WINDOW_DESTROYED="tauri://destroyed",t.WINDOW_FOCUS="tauri://focus",t.WINDOW_BLUR="tauri://blur",t.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",t.WINDOW_THEME_CHANGED="tauri://theme-changed",t.WINDOW_CREATED="tauri://window-created",t.WEBVIEW_CREATED="tauri://webview-created",t.DRAG_ENTER="tauri://drag-enter",t.DRAG_OVER="tauri://drag-over",t.DRAG_DROP="tauri://drag-drop",t.DRAG_LEAVE="tauri://drag-leave"}(a||(a={}));const u={async getCurrentPosition(t){try{return{status:"ok",data:await c("plugin:geolocation|get_current_position",{options:t})}}catch(t){if(t instanceof Error)throw t;return{status:"error",error:t}}},async watchPosition(t,r){try{return{status:"ok",data:await c("plugin:geolocation|watch_position",{options:t,channel:r})}}catch(t){if(t instanceof Error)throw t;return{status:"error",error:t}}},async clearWatch(t){try{return{status:"ok",data:await c("plugin:geolocation|clear_watch",{channelId:t})}}catch(t){if(t instanceof Error)throw t;return{status:"error",error:t}}},async checkPermissions(){try{return{status:"ok",data:await c("plugin:geolocation|check_permissions")}}catch(t){if(t instanceof Error)throw t;return{status:"error",error:t}}},async requestPermissions(t){try{return{status:"ok",data:await c("plugin:geolocation|request_permissions",{permissions:t})}}catch(t){if(t instanceof Error)throw t;return{status:"error",error:t}}}};const{getCurrentPosition:_,clearWatch:h,checkPermissions:f,requestPermissions:w}=u;return t.checkPermissions=f,t.clearWatch=h,t.getCurrentPosition=_,t.requestPermissions=w,t.watchPosition=async function(t,r){const e=new n;return e.onmessage=r,await u.watchPosition(t,e),e.id},t}({});Object.defineProperty(window.__TAURI__,"geolocation",{value:__TAURI_PLUGIN_GEOLOCATION__})}
if("__TAURI__"in window){var __TAURI_PLUGIN_GEOLOCATION__=function(t){"use strict";function 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;class r{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")}toJSON(){return`__CHANNEL__:${this.id}`}}async function a(t,e={},n){return window.__TAURI_INTERNALS__.invoke(t,e,n)}return i=new WeakMap,o=new WeakMap,s=new WeakMap,t.checkPermissions=async function(){return await async function(t){return a(`plugin:${t}|check_permissions`)}("geolocation")},t.clearWatch=async function(t){await a("plugin:geolocation|clear_watch",{channelId:t})},t.getCurrentPosition=async function(t){return await a("plugin:geolocation|get_current_position",{options:t})},t.requestPermissions=async function(t){return await a("plugin:geolocation|request_permissions",{permissions:t})},t.watchPosition=async function(t,e){const n=new r;return n.onmessage=t=>{"string"==typeof t?e(null,t):e(t)},await a("plugin:geolocation|watch_position",{options:t,channel:n}),n.id},t}({});Object.defineProperty(window.__TAURI__,"geolocation",{value:__TAURI_PLUGIN_GEOLOCATION__})}
+1 -1
View File
@@ -7,7 +7,7 @@ const COMMANDS: &[&str] = &[
"watch_position",
"clear_watch",
"check_permissions",
"clear_permissions",
"request_permissions",
];
fn main() {
-248
View File
@@ -1,248 +0,0 @@
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
// @ts-nocheck
// This file was generated by [tauri-specta](https://github.com/oscartbeaumont/tauri-specta). Do not edit this file manually.
/** user-defined commands **/
export const commands = {
async getCurrentPosition(
options: PositionOptions | null
): Promise<Result<Position, Error>> {
try {
return {
status: 'ok',
data: await TAURI_INVOKE('plugin:geolocation|get_current_position', {
options
})
}
} catch (e) {
if (e instanceof Error) throw e
else return { status: 'error', error: e as any }
}
},
async watchPosition(
options: PositionOptions,
channel: any
): Promise<Result<null, Error>> {
try {
return {
status: 'ok',
data: await TAURI_INVOKE('plugin:geolocation|watch_position', {
options,
channel
})
}
} catch (e) {
if (e instanceof Error) throw e
else return { status: 'error', error: e as any }
}
},
async clearWatch(channelId: number): Promise<Result<null, Error>> {
try {
return {
status: 'ok',
data: await TAURI_INVOKE('plugin:geolocation|clear_watch', {
channelId
})
}
} catch (e) {
if (e instanceof Error) throw e
else return { status: 'error', error: e as any }
}
},
async checkPermissions(): Promise<Result<PermissionStatus, Error>> {
try {
return {
status: 'ok',
data: await TAURI_INVOKE('plugin:geolocation|check_permissions')
}
} catch (e) {
if (e instanceof Error) throw e
else return { status: 'error', error: e as any }
}
},
async requestPermissions(
permissions: PermissionType[] | null
): Promise<Result<PermissionStatus, Error>> {
try {
return {
status: 'ok',
data: await TAURI_INVOKE('plugin:geolocation|request_permissions', {
permissions
})
}
} catch (e) {
if (e instanceof Error) throw e
else return { status: 'error', error: e as any }
}
}
}
/** user-defined events **/
/* export const events = __makeEvents__<{
randomNumber: RandomNumber;
}>({
randomNumber: "plugin:geolocation:random-number",
}); */
/** user-defined statics **/
/** user-defined types **/
export type Coordinates = {
/**
* Latitude in decimal degrees.
*/
latitude: number
/**
* Longitude in decimal degrees.
*/
longitude: number
/**
* Accuracy level of the latitude and longitude coordinates in meters.
*/
accuracy: number
/**
* Accuracy level of the altitude coordinate in meters, if available.
* Available on all iOS versions and on Android 8 and above.
*/
altitudeAccuracy: number | null
/**
* The altitude the user is at, if available.
*/
altitude: number | null
speed: number | null
/**
* The heading the user is facing, if available.
*/
heading: number | null
}
export type Error = never
/**
* Permission state.
*/
export type PermissionState =
/**
* Permission access has been granted.
*/
| 'granted'
/**
* Permission access has been denied.
*/
| 'denied'
/**
* The end user should be prompted for permission.
*/
| 'prompt'
export type PermissionStatus = {
/**
* Permission state for the location alias.
*
* On Android it requests/checks both ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION permissions.
*
* On iOS it requests/checks location permissions.
*/
location: PermissionState
/**
* Permissions state for the coarseLoaction alias.
*
* On Android it requests/checks ACCESS_COARSE_LOCATION.
*
* On Android 12+, users can choose between Approximate location (ACCESS_COARSE_LOCATION) and Precise location (ACCESS_FINE_LOCATION).
*
* On iOS it will have the same value as the `location` alias.
*/
coarseLocation: PermissionState
}
export type PermissionType = 'location' | 'coarseLocation'
export type Position = {
/**
* Creation time for these coordinates.
*/
timestamp: number
/**
* The GPD coordinates along with the accuracy of the data.
*/
coords: Coordinates
}
export type PositionOptions = {
/**
* High accuracy mode (such as GPS, if available)
* Will be ignored on Android 12+ if users didn't grant the ACCESS_FINE_LOCATION permission.
*/
enableHighAccuracy: boolean
/**
* The maximum wait time in milliseconds for location updates.
* On Android the timeout gets ignored for getCurrentPosition.
* Ignored on iOS
*/
timeout: number
/**
* The maximum age in milliseconds of a possible cached position that is acceptable to return.
* Default: 0
* Ignored on iOS
*/
maximumAge: number
}
//export type RandomNumber = number;
/** tauri-specta globals **/
import { invoke as TAURI_INVOKE } from '@tauri-apps/api/core'
import * as TAURI_API_EVENT from '@tauri-apps/api/event'
import { type WebviewWindow as __WebviewWindow__ } from '@tauri-apps/api/webviewWindow'
type __EventObj__<T> = {
listen: (
cb: TAURI_API_EVENT.EventCallback<T>
) => ReturnType<typeof TAURI_API_EVENT.listen<T>>
once: (
cb: TAURI_API_EVENT.EventCallback<T>
) => ReturnType<typeof TAURI_API_EVENT.once<T>>
emit: T extends null
? (payload?: T) => ReturnType<typeof TAURI_API_EVENT.emit>
: (payload: T) => ReturnType<typeof TAURI_API_EVENT.emit>
}
export type Result<T, E> =
| { status: 'ok'; data: T }
| { status: 'error'; error: E }
function __makeEvents__<T extends Record<string, any>>(
mappings: Record<keyof T, string>
) {
return new Proxy(
{} as unknown as {
[K in keyof T]: __EventObj__<T[K]> & {
(handle: __WebviewWindow__): __EventObj__<T[K]>
}
},
{
get: (_, event) => {
const name = mappings[event as keyof T]
return new Proxy((() => {}) as any, {
apply: (_, __, [window]: [__WebviewWindow__]) => ({
listen: (arg: any) => window.listen(name, arg),
once: (arg: any) => window.once(name, arg),
emit: (arg: any) => window.emit(name, arg)
}),
get: (_, command: keyof __EventObj__<any>) => {
switch (command) {
case 'listen':
return (arg: any) => TAURI_API_EVENT.listen(name, arg)
case 'once':
return (arg: any) => TAURI_API_EVENT.once(name, arg)
case 'emit':
return (arg: any) => TAURI_API_EVENT.emit(name, arg)
}
}
})
}
}
)
}
+124 -23
View File
@@ -2,36 +2,137 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
/* eslint-disable @typescript-eslint/unbound-method */
import {
Channel,
invoke,
PermissionState,
checkPermissions as checkPluginPermissions
} from '@tauri-apps/api/core'
import { Channel } from '@tauri-apps/api/core'
import { commands, type PositionOptions, type Position } from './bindings'
export type Coordinates = {
/**
* Latitude in decimal degrees.
*/
latitude: number
/**
* Longitude in decimal degrees.
*/
longitude: number
/**
* Accuracy level of the latitude and longitude coordinates in meters.
*/
accuracy: number
/**
* Accuracy level of the altitude coordinate in meters, if available.
* Available on all iOS versions and on Android 8 and above.
*/
altitudeAccuracy: number | null
/**
* The altitude the user is at, if available.
*/
altitude: number | null
speed: number | null
/**
* The heading the user is facing, if available.
*/
heading: number | null
}
export type PermissionStatus = {
/**
* Permission state for the location alias.
*
* On Android it requests/checks both ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION permissions.
*
* On iOS it requests/checks location permissions.
*/
location: PermissionState
/**
* Permissions state for the coarseLoaction alias.
*
* On Android it requests/checks ACCESS_COARSE_LOCATION.
*
* On Android 12+, users can choose between Approximate location (ACCESS_COARSE_LOCATION) and Precise location (ACCESS_FINE_LOCATION).
*
* On iOS it will have the same value as the `location` alias.
*/
coarseLocation: PermissionState
}
export type PermissionType = 'location' | 'coarseLocation'
export type Position = {
/**
* Creation time for these coordinates.
*/
timestamp: number
/**
* The GPD coordinates along with the accuracy of the data.
*/
coords: Coordinates
}
export type PositionOptions = {
/**
* High accuracy mode (such as GPS, if available)
* Will be ignored on Android 12+ if users didn't grant the ACCESS_FINE_LOCATION permission (`coarseLocation` permission).
*/
enableHighAccuracy: boolean
/**
* The maximum wait time in milliseconds for location updates.
* On Android the timeout gets ignored for getCurrentPosition.
* Ignored on iOS
*/
timeout: number
/**
* The maximum age in milliseconds of a possible cached position that is acceptable to return.
* Default: 0
* Ignored on iOS
*/
maximumAge: number
}
export async function watchPosition(
options: PositionOptions,
// TODO: This can receive errors too
cb: (location: Position | string) => void
cb: (location: Position | null, error?: string) => void
): Promise<number> {
const channel = new Channel<Position>()
channel.onmessage = cb
await commands.watchPosition(options, channel)
const channel = new Channel<Position | string>()
channel.onmessage = (message) => {
if (typeof message === 'string') {
cb(null, message)
} else {
cb(message)
}
}
await invoke('plugin:geolocation|watch_position', {
options,
channel
})
return channel.id
}
export const {
getCurrentPosition,
clearWatch,
checkPermissions,
requestPermissions
} = commands
export async function getCurrentPosition(
options?: PositionOptions
): Promise<Position> {
return await invoke('plugin:geolocation|get_current_position', {
options
})
}
export type {
PermissionState,
PermissionStatus,
PermissionType,
Position,
PositionOptions,
Coordinates
} from './bindings'
export async function clearWatch(channelId: number): Promise<void> {
await invoke('plugin:geolocation|clear_watch', {
channelId
})
}
// export { events };
export async function checkPermissions(): Promise<PermissionStatus> {
return await checkPluginPermissions('geolocation')
}
export async function requestPermissions(
permissions: PermissionType[] | null
): Promise<PermissionStatus> {
return await invoke('plugin:geolocation|request_permissions', {
permissions
})
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@tauri-apps/plugin-geolocation",
"version": "2.0.0-rc.1",
"version": "2.0.0-rc.2",
"license": "MIT or APACHE-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
@@ -1,13 +0,0 @@
# Automatically generated - DO NOT EDIT!
"$schema" = "../../schemas/schema.json"
[[permission]]
identifier = "allow-clear-positions"
description = "Enables the clear_positions command without any pre-configured scope."
commands.allow = ["clear_positions"]
[[permission]]
identifier = "deny-clear-positions"
description = "Denies the clear_positions command without any pre-configured scope."
commands.deny = ["clear_positions"]
@@ -0,0 +1,13 @@
# Automatically generated - DO NOT EDIT!
"$schema" = "../../schemas/schema.json"
[[permission]]
identifier = "allow-request-permissions"
description = "Enables the request_permissions command without any pre-configured scope."
commands.allow = ["request_permissions"]
[[permission]]
identifier = "deny-request-permissions"
description = "Denies the request_permissions command without any pre-configured scope."
commands.deny = ["request_permissions"]
@@ -1,5 +1,5 @@
## Permission Table
## Permission Table
<table>
<tr>
@@ -63,32 +63,6 @@ Denies the clear_permissions command without any pre-configured scope.
<tr>
<td>
`geolocation:allow-clear-positions`
</td>
<td>
Enables the clear_positions command without any pre-configured scope.
</td>
</tr>
<tr>
<td>
`geolocation:deny-clear-positions`
</td>
<td>
Denies the clear_positions command without any pre-configured scope.
</td>
</tr>
<tr>
<td>
`geolocation:allow-clear-watch`
</td>
@@ -141,6 +115,32 @@ Denies the get_current_position command without any pre-configured scope.
<tr>
<td>
`geolocation:allow-request-permissions`
</td>
<td>
Enables the request_permissions command without any pre-configured scope.
</td>
</tr>
<tr>
<td>
`geolocation:deny-request-permissions`
</td>
<td>
Denies the request_permissions command without any pre-configured scope.
</td>
</tr>
<tr>
<td>
`geolocation:allow-watch-position`
</td>
@@ -314,16 +314,6 @@
"type": "string",
"const": "deny-clear-permissions"
},
{
"description": "Enables the clear_positions command without any pre-configured scope.",
"type": "string",
"const": "allow-clear-positions"
},
{
"description": "Denies the clear_positions command without any pre-configured scope.",
"type": "string",
"const": "deny-clear-positions"
},
{
"description": "Enables the clear_watch command without any pre-configured scope.",
"type": "string",
@@ -344,6 +334,16 @@
"type": "string",
"const": "deny-get-current-position"
},
{
"description": "Enables the request_permissions command without any pre-configured scope.",
"type": "string",
"const": "allow-request-permissions"
},
{
"description": "Denies the request_permissions command without any pre-configured scope.",
"type": "string",
"const": "deny-request-permissions"
},
{
"description": "Enables the watch_position command without any pre-configured scope.",
"type": "string",
+4 -1
View File
@@ -98,7 +98,10 @@ impl<R: Runtime> Geolocation<R> {
permissions: Option<Vec<PermissionType>>,
) -> crate::Result<PermissionStatus> {
self.0
.run_mobile_plugin("requestPermissions", permissions)
.run_mobile_plugin(
"requestPermissions",
serde_json::json!({ "permissions": permissions }),
)
.map_err(Into::into)
}
}
+7
View File
@@ -13,6 +13,13 @@ links = "tauri-plugin-global-shortcut"
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
linux = { level = "full", notes = "" }
macos = { level = "full", notes = "" }
android = { level = "none", notes = "" }
ios = { level = "none", notes = "" }
[build-dependencies]
tauri-plugin = { workspace = true, features = ["build"] }
@@ -7,7 +7,7 @@ registered or unregistered.
## Permission Table
## Permission Table
<table>
<tr>
+7
View File
@@ -13,6 +13,13 @@ rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
targets = ["x86_64-linux-android"]
[package.metadata.platforms.support]
windows = { level = "none", notes = "" }
linux = { level = "none", notes = "" }
macos = { level = "none", notes = "" }
android = { level = "full", notes = "" }
ios = { level = "full", notes = "" }
[build-dependencies]
tauri-plugin = { workspace = true, features = ["build"] }
@@ -1,5 +1,5 @@
## Permission Table
## Permission Table
<table>
<tr>
+6
View File
@@ -1,5 +1,11 @@
# Changelog
## \[2.0.0-rc.6]
### Dependencies
- Upgraded to `fs@2.0.0-rc.6`
## \[2.0.0-rc.5]
### Dependencies
+9 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "tauri-plugin-http"
version = "2.0.0-rc.5"
version = "2.0.0-rc.6"
description = "Access an HTTP client written in Rust."
edition = { workspace = true }
authors = { workspace = true }
@@ -13,6 +13,13 @@ links = "tauri-plugin-http"
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
linux = { level = "full", notes = "" }
macos = { level = "full", notes = "" }
android = { level = "none", notes = "" }
ios = { level = "none", notes = "" }
[build-dependencies]
tauri-plugin = { workspace = true, features = ["build"] }
schemars = { workspace = true }
@@ -27,7 +34,7 @@ serde_json = { workspace = true }
tauri = { workspace = true }
thiserror = { workspace = true }
tokio = { version = "1", features = ["sync", "macros"] }
tauri-plugin-fs = { path = "../fs", version = "2.0.0-rc.5" }
tauri-plugin-fs = { path = "../fs", version = "2.0.0-rc.6" }
urlpattern = "0.3"
regex = "1"
http = "1"
+10 -17
View File
@@ -47,23 +47,16 @@ enum HttpScopeEntry {
},
}
// Ensure scope entry is kept up to date
impl From<HttpScopeEntry> for scope::Entry {
fn from(value: HttpScopeEntry) -> Self {
let url = match value {
HttpScopeEntry::Value(url) => url,
HttpScopeEntry::Object { url } => url,
};
scope::Entry {
url: urlpattern::UrlPattern::parse(
urlpattern::UrlPatternInit::parse_constructor_string::<regex::Regex>(&url, None)
.unwrap(),
Default::default(),
)
.unwrap(),
}
}
// Ensure `HttpScopeEntry` and `scope::EntryRaw` is kept in sync
fn _f() {
match scope::EntryRaw::Value(String::new()) {
scope::EntryRaw::Value(url) => HttpScopeEntry::Value(url),
scope::EntryRaw::Object { url } => HttpScopeEntry::Object { url },
};
match HttpScopeEntry::Value(String::new()) {
HttpScopeEntry::Value(url) => scope::EntryRaw::Value(url),
HttpScopeEntry::Object { url } => scope::EntryRaw::Object { url },
};
}
fn main() {
@@ -18,7 +18,7 @@ All fetch operations are enabled.
- `allow-fetch-read-body`
- `allow-fetch-send`
## Permission Table
## Permission Table
<table>
<tr>
+7 -7
View File
@@ -33,18 +33,18 @@ fn parse_url_pattern(s: &str) -> Result<UrlPattern, urlpattern::quirks::Error> {
UrlPattern::parse(init, Default::default())
}
#[derive(Deserialize)]
#[serde(untagged)]
pub(crate) enum EntryRaw {
Value(String),
Object { url: String },
}
impl<'de> Deserialize<'de> for Entry {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
#[serde(untagged)]
enum EntryRaw {
Value(String),
Object { url: String },
}
EntryRaw::deserialize(deserializer).and_then(|raw| {
let url = match raw {
EntryRaw::Value(url) => url,
+7
View File
@@ -12,6 +12,13 @@ repository = { workspace = true }
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
linux = { level = "full", notes = "" }
macos = { level = "full", notes = "" }
android = { level = "none", notes = "" }
ios = { level = "none", notes = "" }
[dependencies]
serde = { workspace = true }
serde_json = { workspace = true }
+1 -1
View File
@@ -74,7 +74,7 @@ impl Builder {
let asset_resolver = app.asset_resolver();
std::thread::spawn(move || {
let server =
Server::http(&format!("localhost:{port}")).expect("Unable to spawn server");
Server::http(format!("localhost:{port}")).expect("Unable to spawn server");
for req in server.incoming_requests() {
let path = req
.url()
+7
View File
@@ -13,6 +13,13 @@ links = "tauri-plugin-log"
rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]
[package.metadata.platforms.support]
windows = { level = "full", notes = "" }
linux = { level = "full", notes = "" }
macos = { level = "full", notes = "" }
android = { level = "unknown", notes = "" }
ios = { level = "unknown", notes = "" }
[build-dependencies]
tauri-plugin = { workspace = true, features = ["build"] }
@@ -4,7 +4,7 @@ Allows the log command
- `allow-log`
## Permission Table
## Permission Table
<table>
<tr>

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