diff --git a/.changes/UriSchemeResponder-export.md b/.changes/UriSchemeResponder-export.md deleted file mode 100644 index 92c3e1db4..000000000 --- a/.changes/UriSchemeResponder-export.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": "patch:bug" ---- - -Export `tauri::UriSchemeResponder`. diff --git a/.changes/acl-default-permission-verification.md b/.changes/acl-default-permission-verification.md deleted file mode 100644 index 478b48a52..000000000 --- a/.changes/acl-default-permission-verification.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-build": patch:enhance -"tauri-utils": patch:enhance ---- - -Fallback to an empty permission set if the plugin did not define its `default` permissions. diff --git a/.changes/acl-platform-refactor.md b/.changes/acl-platform-refactor.md deleted file mode 100644 index a465a0e6f..000000000 --- a/.changes/acl-platform-refactor.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"tauri-utils": patch:enhance -"tauri": patch:enhance -"tauri-cli": patch:enhance -"@tauri-apps/cli": patch:enhance ---- - -Changed the permission and capability platforms to be optional. diff --git a/.changes/acl-scope-refactor.md b/.changes/acl-scope-refactor.md deleted file mode 100644 index 7781a67fc..000000000 --- a/.changes/acl-scope-refactor.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:breaking ---- - -Removed the lifetime parameter from `ipc::GlobalScope` and `ipc::CommandScope`. diff --git a/.changes/acl-urlpattern.md b/.changes/acl-urlpattern.md deleted file mode 100644 index 3a2a6b4c1..000000000 --- a/.changes/acl-urlpattern.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri": patch:breaking -"tauri-utils": patch:breaking ---- - -The ACL configuration for remote URLs now uses the URLPattern standard instead of glob patterns. diff --git a/.changes/allow-recursive-asset-scope-on-file-drop-directory.md b/.changes/allow-recursive-asset-scope-on-file-drop-directory.md deleted file mode 100644 index 9f7ad5f40..000000000 --- a/.changes/allow-recursive-asset-scope-on-file-drop-directory.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": 'patch:enhance' ---- - -A file-drop now allows sub-directories recursively when the path is a directory. diff --git a/.changes/mobile-watcher.md b/.changes/android-dev-open-adb-fix.md similarity index 62% rename from .changes/mobile-watcher.md rename to .changes/android-dev-open-adb-fix.md index 2402e4f8f..a2e398a05 100644 --- a/.changes/mobile-watcher.md +++ b/.changes/android-dev-open-adb-fix.md @@ -1,6 +1,6 @@ --- -"@tauri-apps/cli": patch:bug "tauri-cli": patch:bug +"@tauri-apps/cli": patch:bug --- -Fixes dev watcher on mobile dev. +Fixes running `android dev --open`. diff --git a/.changes/android-warning.md b/.changes/android-warning.md deleted file mode 100644 index 1bb320407..000000000 --- a/.changes/android-warning.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-cli": patch:changes -"@tauri-apps/cli": patch:changes ---- - -Migrate to new Android buildFeatures.buildConfig format. diff --git a/.changes/api-app-defaultWindowIcon.md b/.changes/api-app-defaultWindowIcon.md deleted file mode 100644 index 11e82acf3..000000000 --- a/.changes/api-app-defaultWindowIcon.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"tauri": "patch:feat" -"@tauri-apps/api": "patch:feat" ---- - -Add `defaultWindowIcon` to the JS `app` module to retrieve the default window icon in JS. - diff --git a/.changes/api-isTauri-type.md b/.changes/api-isTauri-type.md deleted file mode 100644 index 22422f0c6..000000000 --- a/.changes/api-isTauri-type.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@tauri-apps/api": "patch:bug" ---- - -Fix `isTauri` incorrect return type. \ No newline at end of file diff --git a/.changes/api-isTauri.md b/.changes/api-isTauri.md deleted file mode 100644 index 0982c7b83..000000000 --- a/.changes/api-isTauri.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@tauri-apps/api": "patch:feat" ---- - -Add `isTauri` function in `core` module to check whether running inside tauri or not. - diff --git a/.changes/api-position-size-args.md b/.changes/api-position-size-args.md deleted file mode 100644 index 66f45aa2f..000000000 --- a/.changes/api-position-size-args.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@tauri-apps/api": "patch:bug" ---- - -Fix `Window/Webview/WebviewWindow.setSize`, `Window/Webview/WebviewWindow.setPostion`, `Window/WebviewWindow.setMinSize`, `Window/WebviewWindow.setMaxSize`, `Window/WebviewWindow.setCursorPosition` and `Menu/Submenu.popup` methods failing with invalid args. diff --git a/.changes/api-readd-window-created-event.md b/.changes/api-readd-window-created-event.md deleted file mode 100644 index a0e52ad91..000000000 --- a/.changes/api-readd-window-created-event.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@tauri-apps/api': 'patch:bug' ---- - -Re-added the `TauriEvent.WINDOW_CREATED` (`tauri://window-created`) event. diff --git a/.changes/api-simplify-unc-paths.md b/.changes/api-simplify-unc-paths.md deleted file mode 100644 index f3edca194..000000000 --- a/.changes/api-simplify-unc-paths.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -tauri: patch:enhance ---- - -Tauri's built-in commands for the JS api will now return simplified paths on Windows, removing the `\\?\` prefix. diff --git a/.changes/api-tauri-event-file-drop-rename.md b/.changes/api-tauri-event-file-drop-rename.md deleted file mode 100644 index f7e9d4f80..000000000 --- a/.changes/api-tauri-event-file-drop-rename.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@tauri-apps/api': 'patch:breaking' ---- - -Renamed the following enum variants of `TauriEvent` enum: - -- `TauriEvent.WEBVIEW_FILE_DROP` -> `TauriEvent.FILE_DROP` -- `TauriEvent.WEBVIEW_FILE_DROP_HOVER` -> `TauriEvent.FILE_DROP_HOVER` -- `TauriEvent.WEBVIEW_FILE_DROP_CANCELLED` -> `TauriEvent.FILE_DROP_CANCELLED` diff --git a/.changes/api-tray-by-id.md b/.changes/api-tray-by-id.md deleted file mode 100644 index f1e9b621c..000000000 --- a/.changes/api-tray-by-id.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@tauri-apps/api': 'patch:feat' ---- - -Add `TrayIcon.getById` and `TrayIcon.removeById` static methods. diff --git a/.changes/api-type-definitions.md b/.changes/api-type-definitions.md deleted file mode 100644 index 1ce3b3872..000000000 --- a/.changes/api-type-definitions.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@tauri-apps/api": patch:bug ---- - -Set the `exports > types` package.json field. diff --git a/.changes/api-webview-window-new-methods.md b/.changes/api-webview-window-new-methods.md deleted file mode 100644 index 063c15f7a..000000000 --- a/.changes/api-webview-window-new-methods.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@tauri-apps/api': 'patch:feat' ---- - -Add a new `webviewWindow` module that exports `WebviewWindow` class and related methods such as `getCurrent` and `getAll`. diff --git a/.changes/api-webview-window.md b/.changes/api-webview-window.md deleted file mode 100644 index d2fd15e5e..000000000 --- a/.changes/api-webview-window.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@tauri-apps/api': 'patch:breaking' ---- - -Move `WebviewWindow` class from `webview` module to a new `webviewWindow` module. diff --git a/.changes/api-window-on-filedrop.md b/.changes/api-window-on-filedrop.md deleted file mode 100644 index 12ff6b77a..000000000 --- a/.changes/api-window-on-filedrop.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@tauri-apps/api': 'patch:feat' ---- - -Add `Window.onFileDropEvent` method. diff --git a/.changes/app-handle-set-activation-policy.md b/.changes/app-handle-set-activation-policy.md deleted file mode 100644 index 4cc03b2ba..000000000 --- a/.changes/app-handle-set-activation-policy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:enhance ---- - -Added `AppHandle::set_activation_policy` for macOS. diff --git a/.changes/app-manifest.md b/.changes/app-manifest.md deleted file mode 100644 index d7afeab8e..000000000 --- a/.changes/app-manifest.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"tauri": patch:enhance -"tauri-build": patch:breaking -"tauri-utils": patch:breaking -"tauri-plugin": patch:breaking -"tauri-codegen": patch:breaking ---- - -Allow defining permissions for the application commands via `tauri_build::Attributes::app_manifest`. diff --git a/.changes/app-region-drag.md b/.changes/app-region-drag.md deleted file mode 100644 index 0cbb45e47..000000000 --- a/.changes/app-region-drag.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:feat ---- - -Add `app-region: drag` to HTML elements with `data-tauri-drag-region` on Windows, only WebView2 123+, which should fix dragging using touch. diff --git a/.changes/appimage-duplicate-desktop-file.md b/.changes/appimage-duplicate-desktop-file.md deleted file mode 100644 index ca6d19e5c..000000000 --- a/.changes/appimage-duplicate-desktop-file.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-bundler": "patch:bug" ---- - -Fixed an issue that caused the AppImage to segfault on start due to an incorrect .desktop file. diff --git a/.changes/asset-resolver-dev-fallback.md b/.changes/asset-resolver-dev-fallback.md new file mode 100644 index 000000000..fc9b5069d --- /dev/null +++ b/.changes/asset-resolver-dev-fallback.md @@ -0,0 +1,6 @@ +--- +"tauri": patch:enhance +"tauri-codegen": patch:enhance +--- + +Enhance `AssetResolver::get` in development mode by reading distDir directly as a fallback to the embedded assets. diff --git a/.changes/assets-setup.md b/.changes/assets-setup.md deleted file mode 100644 index 5d107aae9..000000000 --- a/.changes/assets-setup.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:feat ---- - -The `Assets` trait now include a `setup` method that lets you run initialization code for your custom asset provider. diff --git a/.changes/beta.md b/.changes/beta.md deleted file mode 100644 index 915ca5663..000000000 --- a/.changes/beta.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -"tauri": major:feat -"tauri-plugin": major:feat -"tauri-build": major:feat -"tauri-utils": major:feat -"tauri-codegen": major:feat -"tauri-macros": major:feat -"tauri-runtime": major:feat -"tauri-runtime-wry": major:feat -"tauri-cli": major:feat -"@tauri-apps/api": major:feat -"@tauri-apps/cli": major:feat ---- - -Move to beta! diff --git a/.changes/better-error-for-invalid-plugin-config.md b/.changes/better-error-for-invalid-plugin-config.md deleted file mode 100644 index c61806d0e..000000000 --- a/.changes/better-error-for-invalid-plugin-config.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri': patch:enhance ---- - -Improve the error message that is shown when deserializing the Tauri plugin config. diff --git a/.changes/build-android-version-check.md b/.changes/build-android-version-check.md deleted file mode 100644 index d160ecb3d..000000000 --- a/.changes/build-android-version-check.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-build": patch:enhance ---- - -Check for Android version code before building the package in release mode. diff --git a/.changes/build-resource-target-same-src.md b/.changes/build-resource-target-same-src.md deleted file mode 100644 index a394a7083..000000000 --- a/.changes/build-resource-target-same-src.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-build": "patch:bug" ---- - -Avoid copying resources if the target path is the same as source. - diff --git a/.changes/build-schema-generation.md b/.changes/build-schema-generation.md deleted file mode 100644 index cbcfb2bea..000000000 --- a/.changes/build-schema-generation.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-build": patch:bug ---- - -Fixed generation of capability schema for permissions field which previously disallowed mixed (strings and objects) permission definition. \ No newline at end of file diff --git a/.changes/bunderl-installer-hooks.md b/.changes/bunderl-installer-hooks.md deleted file mode 100644 index 02e0faa4e..000000000 --- a/.changes/bunderl-installer-hooks.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-bundler": "patch:feat" ---- - -Add support for NSIS installer hooks providing a path to a `.nsh` file in `bundle > windows > nsis > installer_hooks` key in `tauri.conf.json`. - diff --git a/.changes/bundler-compression-option.md b/.changes/bundler-compression-option.md deleted file mode 100644 index 301dbc6ad..000000000 --- a/.changes/bundler-compression-option.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-utils": patch:breaking ---- - -Changed `NsisSettings::compression` field from `Option` to just `NsisCompression` \ No newline at end of file diff --git a/.changes/bundler-deep-link-reg-path.md b/.changes/bundler-deep-link-reg-path.md deleted file mode 100644 index bbbf9ee24..000000000 --- a/.changes/bundler-deep-link-reg-path.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri-bundler': 'patch:bug' ---- - -Fixed an issue that caused the msi bundler to crash when deep link schemes were configured. diff --git a/.changes/bundler-homepage-url.md b/.changes/bundler-homepage-url.md deleted file mode 100644 index 5ef84d66e..000000000 --- a/.changes/bundler-homepage-url.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"tauri-utils": "minor:feat" -"tauri-bundler": "minor:feat" ---- - -Add `bundle > homepage` option, if unset, it will fallback to `homepage` defined in `Cargo.toml`. - diff --git a/.changes/bundler-license.md b/.changes/bundler-license.md deleted file mode 100644 index d71414cd2..000000000 --- a/.changes/bundler-license.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri-bundler': 'patch:bug' ---- - -Fix NSIS installer always containing a license page even though `licenseFile` option is not set in the config. diff --git a/.changes/bundler-long_description.md b/.changes/bundler-long_description.md deleted file mode 100644 index 82172d0ad..000000000 --- a/.changes/bundler-long_description.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-bundler": "patch:feat" ---- - -Expose `{{long_description}}` variable for custom templates. - diff --git a/.changes/bundler-nsis-deep-links.md b/.changes/bundler-nsis-deep-links.md deleted file mode 100644 index 762a7fd64..000000000 --- a/.changes/bundler-nsis-deep-links.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-bundler": "patch:bug" ---- - -Fix NSIS installer deep links registration. diff --git a/.changes/bundler-nsis-license-file-bom.md b/.changes/bundler-nsis-license-file-bom.md deleted file mode 100644 index 544661f9e..000000000 --- a/.changes/bundler-nsis-license-file-bom.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri-bundler': 'patch:bug' ---- - -Fix encoding of NSIS license page when using a license file without a BOM. diff --git a/.changes/bundler-nsis-tauri-utils.md b/.changes/bundler-nsis-tauri-utils.md deleted file mode 100644 index 27fd690ec..000000000 --- a/.changes/bundler-nsis-tauri-utils.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri-bundler': 'patch:enhance' ---- - -Update `nsis_tauri_utils` plugin to `0.3` and use the built-in NSIS download plugin, which reduces the NSIS installer size by 775kb. diff --git a/.changes/bundler-r-flag.md b/.changes/bundler-r-flag.md deleted file mode 100644 index 01bb177a0..000000000 --- a/.changes/bundler-r-flag.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri-bundler': 'patch:bug' ---- - -The NSIS uninstaller now won't mindlessly try to remove the whole installation folder when the "Remove application data" checkbox was ticked. This prevents data loss when the app was installed in a folder which contained other files. diff --git a/.changes/bundler-resources-unix.md b/.changes/bundler-resources-unix.md deleted file mode 100644 index 5c9561848..000000000 --- a/.changes/bundler-resources-unix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri-bundler': 'patch:bug' ---- - -Fixed an issue causing the NSIS bundler to install resources incorrectly when the installer was built on a non-Windows system. diff --git a/.changes/bundler-rpm-filename.md b/.changes/bundler-rpm-filename.md deleted file mode 100644 index d922e4e44..000000000 --- a/.changes/bundler-rpm-filename.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-bundler": "patch:bug" ---- - -Use the `productName` for `rpm` package name instead of main binary name, to be consistent with other bundle types. - diff --git a/.changes/bundler-rpm-license.md b/.changes/bundler-rpm-license.md deleted file mode 100644 index f8152363b..000000000 --- a/.changes/bundler-rpm-license.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-bundler": patch:bug ---- - -Don't fallback to `licenseFile` and use only `license` field when building RPM. \ No newline at end of file diff --git a/.changes/bundler-shortcuts-updating.md b/.changes/bundler-shortcuts-updating.md deleted file mode 100644 index 79a3e6652..000000000 --- a/.changes/bundler-shortcuts-updating.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-bundler": "patch:enhance" ---- - -Added `/UPDATE` flag for NSIS installer which will make the installer avoid deleting app data and re-creating shortcuts. - diff --git a/.changes/capabilities-multiwebview.md b/.changes/capabilities-multiwebview.md deleted file mode 100644 index 1fc9aa9e6..000000000 --- a/.changes/capabilities-multiwebview.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri": patch:enhance -"tauri-utils": patch:enhance ---- - -Add `webviews` array on the capability for usage on multiwebview contexts. diff --git a/.changes/capabilities-tauri-conf.md b/.changes/capabilities-tauri-conf.md deleted file mode 100644 index 83dc6f786..000000000 --- a/.changes/capabilities-tauri-conf.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"tauri-build": patch:breaking -"tauri-utils": patch:enhance -"tauri-codegen": patch:enhance ---- - -Added a new configuration option `tauri.conf.json > app > security > capabilities` to reference existing capabilities and inline new ones. If it is empty, all capabilities are still included preserving the current behavior. diff --git a/.changes/capability-builder-platform.md b/.changes/capability-builder-platform.md deleted file mode 100644 index c4684ce10..000000000 --- a/.changes/capability-builder-platform.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:feat ---- - -Added `CapabilityBuilder::platform` to link the runtime capability with a specific platform. diff --git a/.changes/capability-context-refactor.md b/.changes/capability-context-refactor.md deleted file mode 100644 index 62d1c9a7e..000000000 --- a/.changes/capability-context-refactor.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"tauri-utils": patch:breaking -"tauri-cli": patch:breaking -"@tauri-apps/cli": patch:breaking ---- - -Changed the capability format to allow configuring both `remote: { urls: Vec }` and `local: bool (default: true)` instead of choosing one on the `context` field. diff --git a/.changes/change-pr-10435.md b/.changes/change-pr-10435.md new file mode 100644 index 000000000..7df501a25 --- /dev/null +++ b/.changes/change-pr-10435.md @@ -0,0 +1,5 @@ +--- +"tauri": patch:bug +--- + +Fix Specta remote implementation target for `Channel`. diff --git a/.changes/change-pr-10498.md b/.changes/change-pr-10498.md new file mode 100644 index 000000000..92c9274cf --- /dev/null +++ b/.changes/change-pr-10498.md @@ -0,0 +1,5 @@ +--- +"tauri-bundler": patch:bug +--- + +Correct nsis pre-uninstall hook to post-uninstall diff --git a/.changes/check-android-lib-symbols.md b/.changes/check-android-lib-symbols.md new file mode 100644 index 000000000..7afbfcf41 --- /dev/null +++ b/.changes/check-android-lib-symbols.md @@ -0,0 +1,6 @@ +--- +"tauri-cli": patch:enhance +"@tauri-apps/cli": patch:enhance +--- + +Check if the Rust library contains the symbols required at runtime for Android and iOS apps. diff --git a/.changes/cleanup-resource-table.md b/.changes/cleanup-resource-table.md deleted file mode 100644 index 07396fe65..000000000 --- a/.changes/cleanup-resource-table.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -tauri: patch:bug ---- - -Fix resource tables not cleaned up on exit which causes tray icon inside resource tables not cleaned up on exit diff --git a/.changes/cli-acl-subcommands.md b/.changes/cli-acl-subcommands.md deleted file mode 100644 index 44895acfc..000000000 --- a/.changes/cli-acl-subcommands.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -'tauri-cli': 'patch:feat' -'@tauri-apps/cli': 'patch:feat' ---- - -Add new subcommands for managing permissions and cababilities: - -- `tauri permission new` -- `tauri permission add` -- `tauri permission rm` -- `tauri permission ls` -- `tauri capability new` diff --git a/.changes/cli-add-@-spec.md b/.changes/cli-add-@-spec.md deleted file mode 100644 index 66ecdcac5..000000000 --- a/.changes/cli-add-@-spec.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-cli": "minor:feat" -"@tauri-apps/cli": "minor:feat" ---- - -Support specifying a version for `tauri add` subcommand, for example: `tauri add window-state@2.0.0-beta.2` diff --git a/.changes/cli-add-launchscreen-storyboard.md b/.changes/cli-add-launchscreen-storyboard.md deleted file mode 100644 index 8819530a8..000000000 --- a/.changes/cli-add-launchscreen-storyboard.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'tauri-cli': 'patch:enhance' -'@tauri-apps/cli': 'patch:enhance' ---- - -Add a blank LaunchScreen.storyboard to the iOS project init template to pass the App Store validation. diff --git a/.changes/cli-allow-kotlin-keyword-as-ident.md b/.changes/cli-allow-kotlin-keyword-as-ident.md deleted file mode 100644 index a26d9a881..000000000 --- a/.changes/cli-allow-kotlin-keyword-as-ident.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-cli": "patch:enhance" ---- - -On Android, allow using Kotlin keywords as identifiers and escape them in templates. diff --git a/.changes/cli-build-no-bundle.md b/.changes/cli-build-no-bundle.md deleted file mode 100644 index bbcdd1437..000000000 --- a/.changes/cli-build-no-bundle.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'tauri-cli': 'patch:enhance' -'@tauri-apps/cli': 'patch:enhance' ---- - -Add `--no-bundle` flag for `tauri build` command to skip bundling. Previously `none` was used to skip bundling, it will now be treated as invalid format and a warning will be emitted instead. diff --git a/.changes/cli-chinese-product-name.md b/.changes/cli-chinese-product-name.md deleted file mode 100644 index cc036ead8..000000000 --- a/.changes/cli-chinese-product-name.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'tauri-cli': 'patch:bug' -'@tauri-apps/cli': 'patch:bug' ---- - -Upgrade `heck` to v0.5 to better support Chinese and Japanese product name, because Chinese do not have word separation. diff --git a/.changes/cli-desktop-port-exposure.md b/.changes/cli-desktop-port-exposure.md new file mode 100644 index 000000000..94d834275 --- /dev/null +++ b/.changes/cli-desktop-port-exposure.md @@ -0,0 +1,6 @@ +--- +"tauri-cli": "patch:enhance" +"@tauri-apps/cli": "patch:enhance" +--- + +Changes the default behavior of the `dev` command to only expose to localhost (`127.0.0.1`) instead of the default system interface. \ No newline at end of file diff --git a/.changes/cli-ds-store-dev-watch.md b/.changes/cli-ds-store-dev-watch.md deleted file mode 100644 index 84a5e7e12..000000000 --- a/.changes/cli-ds-store-dev-watch.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-cli": "patch:enhance" -"@tauri-apps/cli": "patch:enhance" ---- - -Ignore `.DS_Store` by default for `tauri dev` hot reloads. diff --git a/.changes/cli-empty-responses.md b/.changes/cli-empty-responses.md deleted file mode 100644 index d5a4ee4eb..000000000 --- a/.changes/cli-empty-responses.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'tauri-cli': 'patch:enhance' -'@tauri-apps/cli': 'patch:enhance' ---- - -Allow empty responses for `devUrl`, `beforeDevCommand` and `beforeBuildCommands` questions in `tauri init`. diff --git a/.changes/cli-frontend-dist-expected-path.md b/.changes/cli-frontend-dist-expected-path.md deleted file mode 100644 index 80b85c913..000000000 --- a/.changes/cli-frontend-dist-expected-path.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-cli": patch -"@tauri-apps/cli": patch ---- - -Show full expected path of `frontendDist` when if can't be found. \ No newline at end of file diff --git a/.changes/cli-icon-non-0-exit.md b/.changes/cli-icon-non-0-exit.md deleted file mode 100644 index 8b9826cea..000000000 --- a/.changes/cli-icon-non-0-exit.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-cli": "patch:bug" -"@tauri-apps/cli": "patch:bug" ---- - -Exit `tauri icon` with non-zero code when it fails. diff --git a/.changes/cli-include-dir-cargo-manifest-dir.md b/.changes/cli-include-dir-cargo-manifest-dir.md deleted file mode 100644 index 7b3679496..000000000 --- a/.changes/cli-include-dir-cargo-manifest-dir.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-cli": patch:enhance ---- - -Use `$CARGO_MANIFEST_DIR` when including templates at build-time. \ No newline at end of file diff --git a/.changes/cli-migrate-clipboard-globalShortcut.md b/.changes/cli-migrate-clipboard-globalShortcut.md deleted file mode 100644 index b4964c453..000000000 --- a/.changes/cli-migrate-clipboard-globalShortcut.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'tauri-cli': 'patch:bug' -'@tauri-apps/cli': 'patch:bug' ---- - -Fix wrong migration of `clipboard` and `globalShortcut` modules diff --git a/.changes/cli-migrate-non-utf8.md b/.changes/cli-migrate-non-utf8.md deleted file mode 100644 index 5d36cc18b..000000000 --- a/.changes/cli-migrate-non-utf8.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'tauri-cli': 'patch:bug' -'@tauri-apps/cli': 'patch:bug' ---- - -Gracefully handle Non-UTF8 files when using `tauri migrate` \ No newline at end of file diff --git a/.changes/cli-migrate-unknown-plugins.md b/.changes/cli-migrate-unknown-plugins.md deleted file mode 100644 index afa03f525..000000000 --- a/.changes/cli-migrate-unknown-plugins.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"tauri-cli": "patch:bug" -"@tauri-apps/cli": "patch:bug" ---- - -Fix `tauri migrate` trying to migrate to a non-existing plugin. - diff --git a/.changes/cli-mobile-checks.md b/.changes/cli-mobile-checks.md new file mode 100644 index 000000000..420ac28dd --- /dev/null +++ b/.changes/cli-mobile-checks.md @@ -0,0 +1,6 @@ +--- +"tauri-cli": patch:enhance +"@tauri-apps/cli": patch:enhance +--- + +Check if identifier or lib name changed when running mobile commands. diff --git a/.changes/cli-mobile-init-partition.md b/.changes/cli-mobile-init-partition.md deleted file mode 100644 index fd414f26e..000000000 --- a/.changes/cli-mobile-init-partition.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'tauri-cli': 'patch:bug' -'@tauri-apps/cli': 'patch:bug' ---- - -Fixes Android and iOS project initialization when the Tauri CLI is on a different disk partition. diff --git a/.changes/cli-openssl-cargo-mobile2-removal.md b/.changes/cli-openssl-cargo-mobile2-removal.md deleted file mode 100644 index f6ae732e4..000000000 --- a/.changes/cli-openssl-cargo-mobile2-removal.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@tauri-apps/cli": patch:enhance -"tauri-cli": patch:enhance ---- - -`openssl` is no longer a required dependency on macOS. diff --git a/.changes/cli-perserve-cargo-bin-name.md b/.changes/cli-perserve-cargo-bin-name.md deleted file mode 100644 index a991e3eea..000000000 --- a/.changes/cli-perserve-cargo-bin-name.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"tauri-cli": "patch:breaking" -"@tauri-apps/cli": "patch:breaking" ---- - -Avoid renaming main binary to product name and perserve the name generated by cargo. - diff --git a/.changes/cli-plugin-android-init.md b/.changes/cli-plugin-android-init.md deleted file mode 100644 index 631ecf352..000000000 --- a/.changes/cli-plugin-android-init.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-cli": patch:bug -"@tauri-apps/cli": patch:bug ---- - -Fix `tauri plugin android init` printing invalid code that has a missing closing `"`. \ No newline at end of file diff --git a/.changes/cli-plugin-template-updates.md b/.changes/cli-plugin-template-updates.md deleted file mode 100644 index de98339e1..000000000 --- a/.changes/cli-plugin-template-updates.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-cli": "patch:enhance" -"@tauri-apps/cli": "patch:enhance" ---- - -Enhance the plugin template to include `permissions/default.toml` and default capabilities file for the example application. diff --git a/.changes/cli-plugins-migrate.md b/.changes/cli-plugins-migrate.md deleted file mode 100644 index be41341fa..000000000 --- a/.changes/cli-plugins-migrate.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'tauri-cli': 'patch:enhance' -'@tauri-apps/cli': 'patch:enhance' ---- - -Add plugins to `Cargo.toml` when using `tauri migrate` diff --git a/.changes/cli-profile-parse-syntax.md b/.changes/cli-profile-parse-syntax.md deleted file mode 100644 index 592527877..000000000 --- a/.changes/cli-profile-parse-syntax.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-cli": "patch:bug" -"@tauri-apps/cli": "patch:bug" ---- - -Fix parsing of cargo profile when using `--profile=` syntax. diff --git a/.changes/cli-update-deps-fix-log.md b/.changes/cli-update-deps-fix-log.md deleted file mode 100644 index e8d158d6e..000000000 --- a/.changes/cli-update-deps-fix-log.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-cli": patch:deps ---- - -Update dependencies, fix `log` compilation issue. diff --git a/.changes/cli-updater-unkown-fields.md b/.changes/cli-updater-unkown-fields.md deleted file mode 100644 index 077d19af0..000000000 --- a/.changes/cli-updater-unkown-fields.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-cli": patch:bug -"@tauri-apps/cli": patch:bug ---- - -Fix bundling when `plugins > updater > windows > installerArgs` are set in `tauri.conf.json` \ No newline at end of file diff --git a/.changes/cli-windows-build-tools-detect-utf8.md b/.changes/cli-windows-build-tools-detect-utf8.md deleted file mode 100644 index 235c70076..000000000 --- a/.changes/cli-windows-build-tools-detect-utf8.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-cli": patch:bug -"@tauri-apps/cli": patch:bug ---- - -On Windows, fixed `tauri info` fails to detect the build tool when the system language is CJK. diff --git a/.changes/cli-windows-sys.md b/.changes/cli-windows-sys.md deleted file mode 100644 index 0db7f9348..000000000 --- a/.changes/cli-windows-sys.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-cli": "patch:bug" ---- - -Use `windows-sys` crate instead of `winapi` which fixes installing the published cli from crates.io using `cargo install tauri-cli --version "^2.0.0-beta"`. diff --git a/.changes/closeable-maximizable.md b/.changes/closeable-maximizable.md deleted file mode 100644 index 8a9990a37..000000000 --- a/.changes/closeable-maximizable.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri": "patch:bug" -"tauri-runtime-wry": "patch" ---- - -Fix `closable`, `maximizable` and `minimizable` options not taking effect when used in tauri.conf.json or from JS APIs. diff --git a/.changes/codegen-capabilities-attribute.md b/.changes/codegen-capabilities-attribute.md deleted file mode 100644 index c96d47141..000000000 --- a/.changes/codegen-capabilities-attribute.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-macros": patch:enhance -"tauri-codegen": patch:enhance ---- - -The `generate_context` proc macro now accepts a `capabilities` attribute where the value is an array of file paths that can be [conditionally compiled](https://doc.rust-lang.org/reference/conditional-compilation.html). These capabilities are added to the application along the capabilities defined in the Tauri configuration file. diff --git a/.changes/codegen-set-assets.md b/.changes/codegen-set-assets.md deleted file mode 100644 index efa70d526..000000000 --- a/.changes/codegen-set-assets.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-macros": patch:feat -"tauri-codegen": patch:feat ---- - -The `Context` codegen now accepts a `assets` input to define a custom `tauri::Assets` implementation. diff --git a/.changes/color-context-generation.md b/.changes/color-context-generation.md deleted file mode 100644 index 68eb29eb1..000000000 --- a/.changes/color-context-generation.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'tauri-utils': 'patch:bug' -'tauri': 'patch:bug' ---- - -Fix compile time error in context generation when using `app.windows.windowEffects.color` diff --git a/.changes/config.json b/.changes/config.json index 0450e266c..1121c00a0 100644 --- a/.changes/config.json +++ b/.changes/config.json @@ -188,10 +188,14 @@ "path": "./core/tauri-utils", "manager": "rust" }, + "tauri-macos-sign": { + "path": "./tooling/macos-sign", + "manager": "rust" + }, "tauri-bundler": { "path": "./tooling/bundler", "manager": "rust", - "dependencies": ["tauri-utils"] + "dependencies": ["tauri-utils", "tauri-macos-sign"] }, "tauri-runtime": { "path": "./core/tauri-runtime", @@ -262,7 +266,7 @@ "tauri-cli": { "path": "./tooling/cli", "manager": "rust", - "dependencies": ["tauri-bundler", "tauri-utils"], + "dependencies": ["tauri-bundler", "tauri-utils", "tauri-macos-sign"], "postversion": [ "cargo check", "cargo build --manifest-path ../../core/tauri-config-schema/Cargo.toml" diff --git a/.changes/context-assets-runtime-generic.md b/.changes/context-assets-runtime-generic.md deleted file mode 100644 index c9c65519d..000000000 --- a/.changes/context-assets-runtime-generic.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:breaking ---- - -The `Context` struct and the `Assets` trait now takes a `R: Runtime` generic. diff --git a/.changes/context-assets-unbox.md b/.changes/context-assets-unbox.md deleted file mode 100644 index 489bf9b49..000000000 --- a/.changes/context-assets-unbox.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:breaking ---- - -`Context::assets` now returns `&dyn Assets` instead of `&A` generic. diff --git a/.changes/context-remove-assets-generics.md b/.changes/context-remove-assets-generics.md deleted file mode 100644 index 3fc550477..000000000 --- a/.changes/context-remove-assets-generics.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:breaking ---- - -The `Context` type no longer uses the `` generic so the assets implementation can be swapped with `Context::assets_mut`. diff --git a/.changes/context-remove-assets-mut.md b/.changes/context-remove-assets-mut.md deleted file mode 100644 index 84db6b346..000000000 --- a/.changes/context-remove-assets-mut.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:breaking ---- - -Removed `Context::assets_mut` and added `Context::set_assets`. diff --git a/.changes/context-runtime-authority.md b/.changes/context-runtime-authority.md deleted file mode 100644 index 4d2a65e5c..000000000 --- a/.changes/context-runtime-authority.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-utils": patch:enhance ---- - -The `Context` struct now includes the runtime authority instead of the resolved ACL. This does not impact most applications. diff --git a/.changes/core-always-rebuilds-due-to-permissions-dir.md b/.changes/core-always-rebuilds-due-to-permissions-dir.md deleted file mode 100644 index d59930c69..000000000 --- a/.changes/core-always-rebuilds-due-to-permissions-dir.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-build": "patch:bug" ---- - -Fix tauri always rebuilding even if source code didn't change. - diff --git a/.changes/core-app-tray-remove-tray-apis-removed.md b/.changes/core-app-tray-remove-tray-apis-removed.md deleted file mode 100644 index b0289051a..000000000 --- a/.changes/core-app-tray-remove-tray-apis-removed.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri': 'patch:breaking' ---- - -Removed `App/AppHandle::tray` and `App/AppHandle::remove_tray`, use `App/AppHandle::tray_by_id` and `App/AppHandle::remove_tray_by_id` instead. If these APIs were used to access tray icon configured in `tauri.conf.json`, you can use `App/AppHandle::tray_by_id` with ID `main` or the configured value. diff --git a/.changes/core-center-window.md b/.changes/core-center-window.md deleted file mode 100644 index f6993db82..000000000 --- a/.changes/core-center-window.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'tauri': 'patch:enhance' -'tauri-runtime-wry': 'patch' ---- - -Enhance centering a newly created window, it will no longer jump to center after being visible. diff --git a/.changes/core-emit-created-events.md b/.changes/core-emit-created-events.md deleted file mode 100644 index 3215c1dc7..000000000 --- a/.changes/core-emit-created-events.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -tauri: 'patch:bug' ---- - -Fixed an issue preventing webview/window creation events to not be emitted. This also fixed the `getByLabel` and `getAll` JavaScript functions. diff --git a/.changes/core-emit-js-all-targets.md b/.changes/core-emit-js-all-targets.md deleted file mode 100644 index 6a62a35c5..000000000 --- a/.changes/core-emit-js-all-targets.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri': 'patch:bug' ---- - -Fix `emit` and `emit_to` (when used with `EventTarget::Any`) always skipping the webview listeners. diff --git a/.changes/core-env-args.md b/.changes/core-env-args.md deleted file mode 100644 index fbb2cef53..000000000 --- a/.changes/core-env-args.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri": "patch:breaking" ---- - -Include binary path in `Env.args_os`, previously it was skipped. - diff --git a/.changes/core-isTauri.md b/.changes/core-isTauri.md deleted file mode 100644 index 2c110effd..000000000 --- a/.changes/core-isTauri.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri": "patch:feat" ---- - -Add `window.isTauri` to check whether running inside tauri or not. - diff --git a/.changes/core-js-event-anytarget.md b/.changes/core-js-event-anytarget.md deleted file mode 100644 index 3d55b2c6a..000000000 --- a/.changes/core-js-event-anytarget.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri': 'patch:bug' ---- - -Fix JS event listeners registered using JS `listen` api with `EventTarget::Any` never fired. diff --git a/.changes/core-jsimage-intoimg.md b/.changes/core-jsimage-intoimg.md deleted file mode 100644 index 3f4fae5db..000000000 --- a/.changes/core-jsimage-intoimg.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": "patch:breaking" ---- - -Changed `JsImage::into_img` to take a reference to a `ResourceTable` instead of a `Manager`. diff --git a/.changes/core-menu-resources-deadlock.md b/.changes/core-menu-resources-deadlock.md deleted file mode 100644 index 5d9924747..000000000 --- a/.changes/core-menu-resources-deadlock.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": "patch:bug" ---- - -Fix deadlock when using the menu/tray/image JS APIs. diff --git a/.changes/core-once-event-return-event-id.md b/.changes/core-once-event-return-event-id.md deleted file mode 100644 index aa9e13b31..000000000 --- a/.changes/core-once-event-return-event-id.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri': 'patch:enhance' ---- - -Return an id when using from `Manager::once_any`, `App::once`, `Window::once`, `Webview::once`, `WebviewWindow::once` and `fs::Scope::once`. diff --git a/.changes/core-path-basename-replace.md b/.changes/core-path-basename-replace.md deleted file mode 100644 index 4f2b51328..000000000 --- a/.changes/core-path-basename-replace.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'tauri': 'patch:bug' -'@tauri-apps/api': patch:bug ---- - -Fix `basename(path, 'ext')` JS API when removing all occurances of `ext` where it should only remove the last one. diff --git a/.changes/core-plugin-namespace.md b/.changes/core-plugin-namespace.md new file mode 100644 index 000000000..82936cb5c --- /dev/null +++ b/.changes/core-plugin-namespace.md @@ -0,0 +1,9 @@ +--- +"tauri": patch:breaking +"tauri-plugin": patch:breaking +"@tauri-apps/cli": patch:breaking +"tauri-cli": patch:breaking +--- + +Core plugin permissions are now prefixed with `core:`, the `core:default` permission set can now be used and the `core` plugin name is reserved. +The `tauri migrate` tool will automate the migration process, which involves prefixing all `app`, `event`, `image`, `menu`, `path`, `resources`, `tray`, `webview` and `window` permissions with `core:`. diff --git a/.changes/core-specta-integration.md b/.changes/core-specta-integration.md deleted file mode 100644 index f72c6abbc..000000000 --- a/.changes/core-specta-integration.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:feat ---- - -Add `specta` feature flag which adds `specta` support for `AppHandle`, `State`, `Window`, `Webview` and `WebviewWindow` types. \ No newline at end of file diff --git a/.changes/core-start-resize-permission.md b/.changes/core-start-resize-permission.md deleted file mode 100644 index b0f4a43d1..000000000 --- a/.changes/core-start-resize-permission.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": "patch:bug" ---- - -Add missing permission for `window.start_resize_dragging` diff --git a/.changes/core-window-hasdisplayhandle.md b/.changes/core-window-hasdisplayhandle.md deleted file mode 100644 index a2b1346d3..000000000 --- a/.changes/core-window-hasdisplayhandle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -tauri: 'patch:enhance' ---- - -`tauri::Window` and `tauri::WebviewWindow` now implement `raw_window_handle::HasDisplayHandle`. diff --git a/.changes/core-windows-menubar-theme.md b/.changes/core-windows-menubar-theme.md deleted file mode 100644 index 6614fe8b9..000000000 --- a/.changes/core-windows-menubar-theme.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri": "patch:bug" ---- - -On Windows, fix wrong menubar theme when window is using an explicit theme. - diff --git a/.changes/csp-header-linux.md b/.changes/csp-header-linux.md deleted file mode 100644 index 4ca673cc3..000000000 --- a/.changes/csp-header-linux.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"tauri": patch:enhance -"tauri-utils": patch:enhance -"tauri-codegen": patch:enhance ---- - -Do not include a CSP tag in the application HTML and rely on the custom protocol response header instead. diff --git a/.changes/cursor_position.md b/.changes/cursor_position.md deleted file mode 100644 index d1b4156e0..000000000 --- a/.changes/cursor_position.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'tauri': 'patch:feat' -'tauri-runtime': 'patch:feat' -'tauri-runtime-wry': 'patch:feat' ---- - -Add `App/AppHandle/Window/Webview/WebviewWindow::cursor_position` getter to get the current cursor position. diff --git a/.changes/cursor_position_js.md b/.changes/cursor_position_js.md deleted file mode 100644 index 0eebd13bc..000000000 --- a/.changes/cursor_position_js.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@tauri-apps/api': 'patch:feat' ---- - -Add `cursorPosition` function in `window` module to get the current cursor position. diff --git a/.changes/custom-sign-command.md b/.changes/custom-sign-command.md deleted file mode 100644 index 606ac05b9..000000000 --- a/.changes/custom-sign-command.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-bundler": "patch:feat" ---- - -On Windows, add option to specify a custom signing command to be used. This opens an endless possibilities, for example use `osslsigncode` on non-Windows or use hardware tokens and HSM or even using Azure Trusted Signing. diff --git a/.changes/deb-rpm-post-pre-scripts-bundler.md b/.changes/deb-rpm-post-pre-scripts-bundler.md deleted file mode 100644 index 2a7f5b942..000000000 --- a/.changes/deb-rpm-post-pre-scripts-bundler.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri-bundler': 'minor:feat' ---- - -Add suport for include `preinstall`, `postinstall`, `preremove` and `postremove` scripts into Debian and RPM packages. diff --git a/.changes/deb-rpm-post-pre-scripts-config.md b/.changes/deb-rpm-post-pre-scripts-config.md deleted file mode 100644 index 0723d7301..000000000 --- a/.changes/deb-rpm-post-pre-scripts-config.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri-utils': 'minor:feat' ---- - -Added `preInstallScript`, `postInstallScript`, `preRemoveScript` and `postRemoveScript` options for `bundler > deb` and `bundler > rpm` configs. diff --git a/.changes/deb-rpm-provides-conflicts-replaces.md b/.changes/deb-rpm-provides-conflicts-replaces.md deleted file mode 100644 index 8b6fd7473..000000000 --- a/.changes/deb-rpm-provides-conflicts-replaces.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'tauri-bundler': 'minor:feat' -'tauri-utils': 'minor:feat' ---- - -Added support for `provides`, `conflicts` and `replaces` (`obsoletes` for RPM) options for `bundler > deb` and `bundler > rpm` configs. diff --git a/.changes/default-generic-for-menu.md b/.changes/default-generic-for-menu.md deleted file mode 100644 index 3e42d4bde..000000000 --- a/.changes/default-generic-for-menu.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri': patch:enhance ---- - -Provide a default for the runtime generic on `Menu`, `MenuItem`, `Submenu`, `PredefinedMenuItem`, `CheckMenuItem` and `IconMenuItem`. diff --git a/.changes/default-generic-for-tray.md b/.changes/default-generic-for-tray.md deleted file mode 100644 index ca29a89fa..000000000 --- a/.changes/default-generic-for-tray.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri': patch:enhance ---- - -Provide a default for the runtime generic on `TrayIcon`. diff --git a/.changes/dev-fn.md b/.changes/dev-fn.md deleted file mode 100644 index 7b0b12901..000000000 --- a/.changes/dev-fn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:enhance ---- - -Added `tauri::dev()` to determine whether we are running in development mode or not. diff --git a/.changes/dev-url-localhost-mobile.md b/.changes/dev-url-localhost-mobile.md new file mode 100644 index 000000000..f4a37061f --- /dev/null +++ b/.changes/dev-url-localhost-mobile.md @@ -0,0 +1,9 @@ +--- +"tauri-cli": patch:breaking +"@tauri-apps/cli": patch:breaking +--- + +`ios dev` and `android dev` now uses localhost for the development server unless running on an iOS device, +which still requires connecting to the public network address. To conditionally check this on your frontend +framework's configuration you can check for the existence of the `TAURI_DEV_HOST` +environment variable instead of checking if the target is iOS or Android (previous recommendation). diff --git a/.changes/dirs-next-dirs.md b/.changes/dirs-next-dirs.md deleted file mode 100644 index 5ac2f0bca..000000000 --- a/.changes/dirs-next-dirs.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"tauri": patch:deps -"tauri-build": patch:deps -"tauri-bundler": patch:deps -"tauri-cli": patch:deps -"@tauri-apps/cli": patch:deps ---- - -Switch from `dirs_next` to `dirs` as `dirs_next` is now unmaintained while `dirs` is diff --git a/.changes/downgrade-minisign.md b/.changes/downgrade-minisign.md deleted file mode 100644 index 918440a6b..000000000 --- a/.changes/downgrade-minisign.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-cli": patch:bug -"@tauri-apps/cli": patch:bug ---- - -Downgrade minisign dependency fixing updater signing key bug and prevent it from happening in the future. diff --git a/.changes/drop-nsis-applicationid.md b/.changes/drop-nsis-applicationid.md deleted file mode 100644 index 55be7e96c..000000000 --- a/.changes/drop-nsis-applicationid.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri-bundler': 'patch:enhance' ---- - -Use nsis's built-in COM plugin instead of `ApplicationID` plugin, this reduces the installer size by 100 KB, and also fixes pinned shortcut not getting cleaned up on uninstall. diff --git a/.changes/enhance-event-emit.md b/.changes/enhance-event-emit.md deleted file mode 100644 index 492e208b7..000000000 --- a/.changes/enhance-event-emit.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:enhance ---- - -Improve and optimize event emit calls. diff --git a/.changes/enhance-ipc-url-check.md b/.changes/enhance-ipc-url-check.md deleted file mode 100644 index 834b2c2f5..000000000 --- a/.changes/enhance-ipc-url-check.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:enhance ---- - -Enhance the IPC URL check by using the Origin header on the custom protocol IPC and the new request URI field on the postMessage IPC instead of using `Webview::url()` which only returns the URL of the main frame and is not suitable for iframes (iframe URL fetch is still not supported on Android and on Linux when using the postMessage IPC). diff --git a/.changes/enhance-resource-dir-resolution.md b/.changes/enhance-resource-dir-resolution.md deleted file mode 100644 index 2d0edc5e3..000000000 --- a/.changes/enhance-resource-dir-resolution.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-utils": patch:enhance ---- - -Enhance resource directory resolution on development. diff --git a/.changes/event-reopen.md b/.changes/event-reopen.md deleted file mode 100644 index 484929df3..000000000 --- a/.changes/event-reopen.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'tauri': 'minor:feat' -'tauri-runtime': 'minor:feat' -'tauri-runtime-wry': 'minor:feat' ---- - -Add `RunEvent::Reopen` for handle click on dock icon on macOS. diff --git a/.changes/expose-image-constructor.md b/.changes/expose-image-constructor.md deleted file mode 100644 index 07b03cbc3..000000000 --- a/.changes/expose-image-constructor.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@tauri-apps/api": patch:enhance ---- - -The `Image` constructor is now public (for internal use only). diff --git a/.changes/expose-js-image.md b/.changes/expose-js-image.md deleted file mode 100644 index 19b187ef1..000000000 --- a/.changes/expose-js-image.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri": patch:breaking -"tauri-codegen": patch:breaking ---- - -Expose `tauri::image` module to export the `JsImage` type and removed the `Image` root re-export. diff --git a/.changes/fix-acl-webview-check.md b/.changes/fix-acl-webview-check.md deleted file mode 100644 index 0aa74c0ce..000000000 --- a/.changes/fix-acl-webview-check.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:bug ---- - -Fixes capability webview label check. diff --git a/.changes/fix-ios-dev-logs.md b/.changes/fix-adb.md similarity index 55% rename from .changes/fix-ios-dev-logs.md rename to .changes/fix-adb.md index eaa22703a..f292a4d1f 100644 --- a/.changes/fix-ios-dev-logs.md +++ b/.changes/fix-adb.md @@ -1,6 +1,6 @@ --- -"@tauri-apps/cli": patch:bug "tauri-cli": patch:bug +"@tauri-apps/cli": patch:bug --- -Fixes process logs not showing on `ios dev`. +Fixes running `adb reverse` in Node.js context. diff --git a/.changes/fix-add-child-deadlock.md b/.changes/fix-add-child-deadlock.md deleted file mode 100644 index 2f3c9db12..000000000 --- a/.changes/fix-add-child-deadlock.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:bug ---- - -Fixes `Window::add_child` deadlock. diff --git a/.changes/fix-api-export-mocks-module.md b/.changes/fix-api-export-mocks-module.md deleted file mode 100644 index 5978127c2..000000000 --- a/.changes/fix-api-export-mocks-module.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@tauri-apps/api": "patch:bug" ---- - -Export `mocks` module in `@tauri-apps/api` npm package. diff --git a/.changes/fix-build-script-rerun-macos.md b/.changes/fix-build-script-rerun-macos.md deleted file mode 100644 index 187d7e748..000000000 --- a/.changes/fix-build-script-rerun-macos.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-codegen": patch:bug ---- - -Fixes Info.plist rewriting always triggering build to rerun. \ No newline at end of file diff --git a/.changes/fix-capability-schema-definitions.md b/.changes/fix-capability-schema-definitions.md deleted file mode 100644 index 2935b5039..000000000 --- a/.changes/fix-capability-schema-definitions.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-build": patch:bug ---- - -Fixes the capability schema not resolving inner definitions. diff --git a/.changes/fix-capability-totokens.md b/.changes/fix-capability-totokens.md deleted file mode 100644 index 00e735dc2..000000000 --- a/.changes/fix-capability-totokens.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-utils": patch:bug ---- - -Fixes the `ToTokens` implementation for `Capability`. diff --git a/.changes/fix-channel-buffer-processing.md b/.changes/fix-channel-buffer-processing.md deleted file mode 100644 index be4625218..000000000 --- a/.changes/fix-channel-buffer-processing.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@tauri-apps/api": patch:bug ---- - -Fixes a bug when processing channel messages out of order. diff --git a/.changes/fix-channel-ipc-response.md b/.changes/fix-channel-ipc-response.md deleted file mode 100644 index 1ab50f088..000000000 --- a/.changes/fix-channel-ipc-response.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:bug ---- - -Fix regression on IPC response when using a channel to return objects. diff --git a/.changes/fix-clear-residual-listeners.md b/.changes/fix-clear-residual-listeners.md deleted file mode 100644 index d08ed8452..000000000 --- a/.changes/fix-clear-residual-listeners.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:bug ---- - -Clear JS event listeneres on page load, which fixes zombie listeners when the page reloads. diff --git a/.changes/fix-cli-add-more-plugins.md b/.changes/fix-cli-add-more-plugins.md deleted file mode 100644 index 1fa8fde95..000000000 --- a/.changes/fix-cli-add-more-plugins.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-cli": "patch:bug" -"@tauri-apps/cli": "patch:bug" ---- - -Fixed an issue that caused `tauri add` to fail for multiple rust-only and platform-specific plugins. diff --git a/.changes/fix-cli-icon-svg-render-text.md b/.changes/fix-cli-icon-svg-render-text.md deleted file mode 100644 index 40cb6a425..000000000 --- a/.changes/fix-cli-icon-svg-render-text.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"tauri-cli": "patch:bug" -"@tauri-apps/cli": "patch:bug" ---- - -Fixed an issue that prevented `tauri icon` from rendering `` nodes in SVG files. - diff --git a/.changes/fix-cli-migration-http-acl.md b/.changes/fix-cli-migration-http-acl.md deleted file mode 100644 index 8956b9c77..000000000 --- a/.changes/fix-cli-migration-http-acl.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:bug ---- - -Fix `tauri migrate` for http plugin ACL. diff --git a/.changes/fix-codegen-rerun-if-changed.md b/.changes/fix-codegen-rerun-if-changed.md deleted file mode 100644 index 193678760..000000000 --- a/.changes/fix-codegen-rerun-if-changed.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-build": patch:bug ---- - -Do not trigger build script to rerun if the frontendDist directory does not exist. diff --git a/.changes/fix-colon-in-file-path.md b/.changes/fix-colon-in-file-path.md new file mode 100644 index 000000000..76abf745a --- /dev/null +++ b/.changes/fix-colon-in-file-path.md @@ -0,0 +1,5 @@ +--- +"tauri-utils": "patch:bug" +--- + +Fixed an issue where permission files will be generated with ':' in the file path. diff --git a/.changes/fix-conf-parsing-error-filepath.md b/.changes/fix-conf-parsing-error-filepath.md new file mode 100644 index 000000000..468ec892e --- /dev/null +++ b/.changes/fix-conf-parsing-error-filepath.md @@ -0,0 +1,7 @@ +--- +"tauri-utils": "patch:bug" +--- + +Fixed an issue where configuration parsing errors always displayed 'tauri.conf.json' as the file path, even when using 'Tauri.toml' or 'tauri.conf.json5'. + +The error messages now correctly shows the actual config file being used. diff --git a/.changes/fix-config-arg.md b/.changes/fix-config-arg.md deleted file mode 100644 index 88b47bf32..000000000 --- a/.changes/fix-config-arg.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-cli": patch:bug -"@tauri-apps/cli": patch:bug ---- - -Fixes a regression on the `--config` argument not accepting file paths. diff --git a/.changes/fix-draw-tracing.md b/.changes/fix-draw-tracing.md deleted file mode 100644 index fca8a8b55..000000000 --- a/.changes/fix-draw-tracing.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-runtime-wry": patch:bug ---- - -Fixes redraw tracing span not closing. diff --git a/.changes/fix-fs-scope-check-symlink.md b/.changes/fix-fs-scope-check-symlink.md deleted file mode 100644 index 7804412d4..000000000 --- a/.changes/fix-fs-scope-check-symlink.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:bug ---- - -Resolve symlinks on the filesystem scope check. diff --git a/.changes/fix-incompatible-ipc-field-postmessage.md b/.changes/fix-incompatible-ipc-field-postmessage.md deleted file mode 100644 index 3aa5f1599..000000000 --- a/.changes/fix-incompatible-ipc-field-postmessage.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:bug ---- - -Fix IPC tracing format incompatible between the custom protocol and the postMessage implementations. diff --git a/.changes/fix-inner-size.md b/.changes/fix-inner-size.md deleted file mode 100644 index 83d2191bf..000000000 --- a/.changes/fix-inner-size.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-runtime-wry": patch:bug ---- - -Fix window inner size evaluation on macOS. diff --git a/.changes/fix-invoke-devtools-by-hotkey.md b/.changes/fix-invoke-devtools-by-hotkey.md deleted file mode 100644 index 33fb31311..000000000 --- a/.changes/fix-invoke-devtools-by-hotkey.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:bug ---- - -Fix invoking toggle devtools by hotkey. diff --git a/.changes/fix-ios-plugin-xcode-deployment-target.md b/.changes/fix-ios-plugin-xcode-deployment-target.md deleted file mode 100644 index 2477395c1..000000000 --- a/.changes/fix-ios-plugin-xcode-deployment-target.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-cli": patch:bug -"@tauri-apps/cli": patch:bug ---- - -Changed the deployment target of plugin iOS Xcode project to 13.0 so it works on older iOS releases. diff --git a/.changes/fix-ipc-error-json.md b/.changes/fix-ipc-error-json.md deleted file mode 100644 index 2e5e5f756..000000000 --- a/.changes/fix-ipc-error-json.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -tauri: 'patch:bug' ---- - -Fixed an issue where errors where returned as strings instead of objects from commands. diff --git a/.changes/fix-macos-deep-link-cfbundleurlname.md b/.changes/fix-macos-deep-link-cfbundleurlname.md deleted file mode 100644 index 86c32d891..000000000 --- a/.changes/fix-macos-deep-link-cfbundleurlname.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -tauri-bundler: "patch:bug" ---- - -Fixed an issue causing the deep link feature to create invalid `Info.plist` values on macOS. diff --git a/.changes/fix-menu-remove-api.md b/.changes/fix-menu-remove-api.md deleted file mode 100644 index 81b738aeb..000000000 --- a/.changes/fix-menu-remove-api.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:bug ---- - -Fixes the menu plugin `remove` command signature. diff --git a/.changes/fix-metadata-on-close.md b/.changes/fix-metadata-on-close.md deleted file mode 100644 index 7208e19ef..000000000 --- a/.changes/fix-metadata-on-close.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:bug ---- - -Fixes an issue causing `getAll()` to list webviews that were already destroyed. diff --git a/.changes/fix-migrate-updater.md b/.changes/fix-migrate-updater.md deleted file mode 100644 index eec5c5b49..000000000 --- a/.changes/fix-migrate-updater.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@tauri-apps/cli": patch:bug -"tauri-cli": patch:bug ---- - -Do not migrate updater configuration if the active flag is set to false. diff --git a/.changes/fix-missing-depends.md b/.changes/fix-missing-depends.md deleted file mode 100644 index 77ef8a79a..000000000 --- a/.changes/fix-missing-depends.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-cli": "patch:bug" -"@tauri-apps/cli": "patch:bug" ---- - -Add missing dependency `libayatana-appindicator3.so.1` for rpm package. \ No newline at end of file diff --git a/.changes/fix-mobile-cmd-case.md b/.changes/fix-mobile-cmd-case.md deleted file mode 100644 index 653e2c007..000000000 --- a/.changes/fix-mobile-cmd-case.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:bug ---- - -Convert the command name to camelCase when executing a mobile plugin command. diff --git a/.changes/fix-mobile-process-spawn.md b/.changes/fix-mobile-process-spawn.md deleted file mode 100644 index 776868528..000000000 --- a/.changes/fix-mobile-process-spawn.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-cli": patch:bug -"@tauri-apps/cli": patch:bug ---- - -Fixes android and iOS process spawning not working on Node.js. diff --git a/.changes/fix-pnpm-check.md b/.changes/fix-pnpm-check.md deleted file mode 100644 index ae4ea9609..000000000 --- a/.changes/fix-pnpm-check.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-cli": patch:bug -"@tauri-apps/cli": patch:bug ---- - -Fixes `pnpm` detection when initializing and running a mobile project. diff --git a/.changes/fix-process-ipc-message-fn.md b/.changes/fix-process-ipc-message-fn.md deleted file mode 100644 index 334d8ccf3..000000000 --- a/.changes/fix-process-ipc-message-fn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:bug ---- - -Fix regression on the JavaScript code that processes the IPC message. diff --git a/.changes/fix-proxy-url-totokens-impl.md b/.changes/fix-proxy-url-totokens-impl.md deleted file mode 100644 index 43a7c2dc5..000000000 --- a/.changes/fix-proxy-url-totokens-impl.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-utils": patch:bug ---- - -Fixes the ToTokens implementation of the window configuration `proxy_url` field. diff --git a/.changes/fix-remote-domain-url.md b/.changes/fix-remote-domain-url.md deleted file mode 100644 index d21f99c67..000000000 --- a/.changes/fix-remote-domain-url.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:bug ---- - -Fixes capability remote domain not allowing subpaths, query parameters and hash when those values are empty. diff --git a/.changes/fix-reparent.md b/.changes/fix-reparent.md deleted file mode 100644 index 04ee7756b..000000000 --- a/.changes/fix-reparent.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:bug ---- - -Fixes `Webview::reparent` not updating the webview parent window reference. diff --git a/.changes/fix-rewrite-schema.md b/.changes/fix-rewrite-schema.md deleted file mode 100644 index eec0c0c8a..000000000 --- a/.changes/fix-rewrite-schema.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-build": patch:bug ---- - -Do not rewrite capability JSON schema if it did not change. diff --git a/.changes/fix-runtime-wry-32bit.md b/.changes/fix-runtime-wry-32bit.md deleted file mode 100644 index 712cf1ec7..000000000 --- a/.changes/fix-runtime-wry-32bit.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -tauri-runtime-wry: patch:bug ---- - -Fixes an issue causing compilation to fail for i686 and armv7 32-bit targets. \ No newline at end of file diff --git a/.changes/fix-schemars-compatibility.md b/.changes/fix-schemars-compatibility.md deleted file mode 100644 index 37576c896..000000000 --- a/.changes/fix-schemars-compatibility.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -tauri-utils: "patch:bug" ---- - -Fixes `schemars` compilation issue. \ No newline at end of file diff --git a/.changes/fix-scope-resolution.md b/.changes/fix-scope-resolution.md deleted file mode 100644 index 911699347..000000000 --- a/.changes/fix-scope-resolution.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri": patch:bug -"tauri-utils": patch:bug ---- - -Fixes scope resolution grouping scopes for all windows. diff --git a/.changes/fix-tauri-build-license-field.md b/.changes/fix-tauri-build-license-field.md deleted file mode 100644 index 48e9d4374..000000000 --- a/.changes/fix-tauri-build-license-field.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-utils": patch:bug ---- - -Fix compile error when `tauri.conf.json` had `bundle > license` set. diff --git a/.changes/fix-tauri-build-unix.md b/.changes/fix-tauri-build-unix.md deleted file mode 100644 index b9d0de876..000000000 --- a/.changes/fix-tauri-build-unix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:bug ---- - -Workaround for zbus not enabling the proper Cargo features for its nix dependency. diff --git a/.changes/fix-temp-permission-file-name.md b/.changes/fix-temp-permission-file-name.md deleted file mode 100644 index acf9420b5..000000000 --- a/.changes/fix-temp-permission-file-name.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-utils": "patch:bug" ---- - -Replace `tauri:` prefix with `tauri-` for temporary permission file names diff --git a/.changes/fix-usage-without-compression.md b/.changes/fix-usage-without-compression.md new file mode 100644 index 000000000..0e6bf6154 --- /dev/null +++ b/.changes/fix-usage-without-compression.md @@ -0,0 +1,6 @@ +--- +"tauri": patch:bug +"tauri-codegen": patch:bug +--- + +Fixes asset resolving when not using the `compression` feature. diff --git a/.changes/fix-visibility-change.md b/.changes/fix-visibility-change.md deleted file mode 100644 index 024cda8e7..000000000 --- a/.changes/fix-visibility-change.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-runtime-wry": patch:bug ---- - -Fix webview's visibility doesn't change with the app window diff --git a/.changes/fix-webview-close.md b/.changes/fix-webview-close.md deleted file mode 100644 index 9d7a62078..000000000 --- a/.changes/fix-webview-close.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:bug ---- - -When using the multiwebview mode, properly remove the webview from memory on `Webview::close`. diff --git a/.changes/fix-window-center-monitor-scale.md b/.changes/fix-window-center-monitor-scale.md deleted file mode 100644 index 0d967f138..000000000 --- a/.changes/fix-window-center-monitor-scale.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-runtime-wry": patch:bug ---- - -Fix window centering not taking monitor scale into account diff --git a/.changes/fix-window-center-work-area.md b/.changes/fix-window-center-work-area.md deleted file mode 100644 index 78d1596c4..000000000 --- a/.changes/fix-window-center-work-area.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-runtime-wry": patch:bug ---- - -Fix window centering not taking taskbar into account on Windows diff --git a/.changes/fix-window-destroy-deadlock.md b/.changes/fix-window-destroy-deadlock.md deleted file mode 100644 index 014ca46c1..000000000 --- a/.changes/fix-window-destroy-deadlock.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:bug ---- - -Fixes a deadlock when the window is destroyed. diff --git a/.changes/fix-window-inner-size-crash.md b/.changes/fix-window-inner-size-crash.md deleted file mode 100644 index dc8d6af1e..000000000 --- a/.changes/fix-window-inner-size-crash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-runtime-wry": patch:bug ---- - -Fixes `inner_size` crash when the window has no webviews. diff --git a/.changes/fix-wix-autostart-after-update.md b/.changes/fix-wix-autostart-after-update.md deleted file mode 100644 index 242443260..000000000 --- a/.changes/fix-wix-autostart-after-update.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -tauri-bundler: patch:enhance ---- - -Added a public property to the msi to tell the installer to launch the app after installation. This was added for the updater plugin. diff --git a/.changes/global-api-script-path-plugins.md b/.changes/global-api-script-path-plugins.md deleted file mode 100644 index 2de6c03a0..000000000 --- a/.changes/global-api-script-path-plugins.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"tauri": patch:feat -"tauri-codegen": patch:feat -"tauri-build": patch:feat -"tauri-plugin": patch:feat ---- - -Allow plugins to define (at compile time) JavaScript that are initialized when `withGlobalTauri` is true. diff --git a/.changes/handle-empty-permissions.md b/.changes/handle-empty-permissions.md deleted file mode 100644 index 5e47234fe..000000000 --- a/.changes/handle-empty-permissions.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-plugin": patch:enhance -"tauri-utils": patch:enhance ---- - -Do not generate JSON schema and markdown reference file if the plugin does not define any permissions and delete those files if they exist. diff --git a/.changes/hardened-runtime-option.md b/.changes/hardened-runtime-option.md deleted file mode 100644 index fbae7bd2a..000000000 --- a/.changes/hardened-runtime-option.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"tauri-bundler": patch:feat -"@tauri-apps/cli": patch:feat -"tauri-cli": patch:feat -"tauri-utils": patch:feat ---- - -Added a configuration option to disable hardened runtime on macOS codesign. diff --git a/.changes/hide-windows-on-cleanup.md b/.changes/hide-windows-on-cleanup.md deleted file mode 100644 index 9a798987b..000000000 --- a/.changes/hide-windows-on-cleanup.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": "patch:bug" ---- - -Fix window white flashing on exit on Windows diff --git a/.changes/http-v1.md b/.changes/http-v1.md deleted file mode 100644 index 646717162..000000000 --- a/.changes/http-v1.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'tauri': 'patch:deps' -'tauri-runtime': 'patch' -'tauri-runtime-wry': 'patch' ---- - -Updated `http` crate to `1.1` diff --git a/.changes/ico-featrue-flags.md b/.changes/ico-featrue-flags.md deleted file mode 100644 index bf488fe43..000000000 --- a/.changes/ico-featrue-flags.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri': 'major:breaking' ---- - -Renamed `icon-ico` and `icon-png` feature flags to `image-ico` and `image-png` respectively diff --git a/.changes/image-crate.md b/.changes/image-crate.md deleted file mode 100644 index e4a89d724..000000000 --- a/.changes/image-crate.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:breaking ---- - -Use the image crate for `tauri::image::Image` and remove the `from_png_bytes` and `from_ico_bytes` APIs. diff --git a/.changes/image-rgba-uint8array.md b/.changes/image-rgba-uint8array.md deleted file mode 100644 index b57acab3d..000000000 --- a/.changes/image-rgba-uint8array.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@tauri-apps/api": patch:breaking ---- - -`Image::rgba()` now returns `Promise`. diff --git a/.changes/image-size-refactor.md b/.changes/image-size-refactor.md deleted file mode 100644 index 5de4791d1..000000000 --- a/.changes/image-size-refactor.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@tauri-apps/api": patch:breaking -"tauri": patch:breaking ---- - -Removed `width` and `height` methods on the JS `Image` class, use `size` instead. diff --git a/.changes/improve-errors-for-missing-links-property.md b/.changes/improve-errors-for-missing-links-property.md deleted file mode 100644 index 24a59a46d..000000000 --- a/.changes/improve-errors-for-missing-links-property.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'tauri-plugin': patch:enhance ---- - -Improve the error message that is shown when the `links` property is missing from a Tauri Plugin. - diff --git a/.changes/include-image-macro-codegen.md b/.changes/include-image-macro-codegen.md deleted file mode 100644 index cff5f71ff..000000000 --- a/.changes/include-image-macro-codegen.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-codegen": "patch:feat" ---- - -Add `include_image_codegen` function to help embedding instances of `Image` struct at compile-time in rust to be used with window, menu or tray icons. diff --git a/.changes/include-image-macro.md b/.changes/include-image-macro.md deleted file mode 100644 index f68052710..000000000 --- a/.changes/include-image-macro.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"tauri": "patch:feat" -"tauri-utils": "patch:feat" -"tauri-macros": "patch:feat" ---- - -Add `include_image` macro to help embedding instances of `Image` struct at compile-time in rust to be used with window, menu or tray icons. diff --git a/.changes/inline-plugins.md b/.changes/inline-plugins.md deleted file mode 100644 index b2d7f52cc..000000000 --- a/.changes/inline-plugins.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri-build': patch:enhance ---- - -Added `Attributes::plugin()` to register a plugin that is inlined in the application crate. diff --git a/.changes/invoke-body-raw-deserialization.md b/.changes/invoke-body-raw-deserialization.md deleted file mode 100644 index d74493fec..000000000 --- a/.changes/invoke-body-raw-deserialization.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": "patch:bug" ---- - -Fix `InvokeBody::deserialize` method deserialization for `InvokeBody::Raw` variant diff --git a/.changes/ios-custom-project-template.md b/.changes/ios-custom-project-template.md new file mode 100644 index 000000000..2788ec0e7 --- /dev/null +++ b/.changes/ios-custom-project-template.md @@ -0,0 +1,7 @@ +--- +"tauri-utils": patch:feat +"tauri-cli": patch:feat +"@tauri-apps/cli": patch:feat +--- + +Added `bundle > ios > template` configuration option for custom Xcode project YML Handlebars template using XcodeGen. diff --git a/.changes/ios-frameworks.md b/.changes/ios-frameworks.md new file mode 100644 index 000000000..fb42a61c9 --- /dev/null +++ b/.changes/ios-frameworks.md @@ -0,0 +1,7 @@ +--- +"tauri-utils": patch:feat +"@tauri-apps/cli": patch:feat +"tauri-cli": patch:feat +--- + +Added `bundle > iOS > frameworks` configuration to define a list of frameworks that are linked to the Xcode project when it is generated. diff --git a/.changes/ios-non-transparent-icons.md b/.changes/ios-non-transparent-icons.md deleted file mode 100644 index 0c8e07226..000000000 --- a/.changes/ios-non-transparent-icons.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"@tauri-apps/cli": patch:bug -"tauri-cli": patch:bug ---- - -Removed alpha channel from default icons in iOS template to comply with Apple's human interface guideline -(https://developer.apple.com/design/human-interface-guidelines/app-icons), because -transparent icons with alpha channel are not allowed, and will be rejected -upon upload to Apple appstore. diff --git a/.changes/ios-signing-optional.md b/.changes/ios-signing-optional.md deleted file mode 100644 index 420ca2882..000000000 --- a/.changes/ios-signing-optional.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@tauri-apps/cli": patch:enhance -"tauri-cli": patch:enhance ---- - -Setting up code signing is no longer required on iOS when using the simulator. diff --git a/.changes/ipc-allow-headers.md b/.changes/ipc-allow-headers.md deleted file mode 100644 index 4501500cf..000000000 --- a/.changes/ipc-allow-headers.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:bug ---- - -Allow any headers on the IPC custom protocol. diff --git a/.changes/ipc-only-main-frame.md b/.changes/ipc-only-main-frame.md deleted file mode 100644 index 52e04c4eb..000000000 --- a/.changes/ipc-only-main-frame.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'tauri': patch:sec -'tauri-runtime-wry': patch:sec ---- - -Only process IPC commands from the main frame. diff --git a/.changes/ipc-post-message-fallback.md b/.changes/ipc-post-message-fallback.md deleted file mode 100644 index b271d945f..000000000 --- a/.changes/ipc-post-message-fallback.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:enhance ---- - -Fallback to the postMessage IPC interface if we cannot reach the IPC custom protocol. diff --git a/.changes/ipc-request-param-refactor.md b/.changes/ipc-request-param-refactor.md deleted file mode 100644 index 6562c2f88..000000000 --- a/.changes/ipc-request-param-refactor.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-runtime": patch:breaking -"tauri-runtime-wry": patch:breaking ---- - -The IPC handler closure now receives a `http::Request` instead of a String representing the request body. diff --git a/.changes/isolation-main-frame-origin.md b/.changes/isolation-main-frame-origin.md new file mode 100644 index 000000000..46c6a7856 --- /dev/null +++ b/.changes/isolation-main-frame-origin.md @@ -0,0 +1,6 @@ +--- +"tauri": "patch:sec" +"tauri-utils": "patch:sec" +--- + +Explicitly check that the main frame's origin is the sender of Isolation Payloads diff --git a/.changes/isolation-pattern-key-extractable.md b/.changes/isolation-pattern-key-extractable.md deleted file mode 100644 index ef79d5adc..000000000 --- a/.changes/isolation-pattern-key-extractable.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-utils": patch:enhance ---- - -Make the isolation pattern encrypt key unextractable. diff --git a/.changes/isolation-script-remove-itself.md b/.changes/isolation-script-remove-itself.md deleted file mode 100644 index f7b0888df..000000000 --- a/.changes/isolation-script-remove-itself.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-utils": patch:enhance ---- - -The isolation iframe script now removes itself after execution. diff --git a/.changes/linux-gtk-app-id.md b/.changes/linux-gtk-app-id.md deleted file mode 100644 index 59933cc2d..000000000 --- a/.changes/linux-gtk-app-id.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"tauri": "patch:enhance" -"tauri-runtime-wry": "patch" ---- - -Set the gtk application to the identifier defined in `tauri.conf.json` to ensure the app uniqueness. - diff --git a/.changes/linux-option-gtk-app-id.md b/.changes/linux-option-gtk-app-id.md new file mode 100644 index 000000000..f050fd6a7 --- /dev/null +++ b/.changes/linux-option-gtk-app-id.md @@ -0,0 +1,6 @@ +--- +"tauri-utils": "patch:enhance" +"tauri": "patch:enhance" +--- + +Make the set of gtk application id optional, to allow more then one instance of the app running at the same time. diff --git a/.changes/min-ios-version.md b/.changes/min-ios-version.md new file mode 100644 index 000000000..f2755a770 --- /dev/null +++ b/.changes/min-ios-version.md @@ -0,0 +1,7 @@ +--- +"tauri-utils": patch:feat +"tauri-cli": patch:feat +"@tauri-apps/cli": patch:feat +--- + +Added `bundle > ios > minimumSystemVersion` configuration option. diff --git a/.changes/mobile-use-identifier-as-id.md b/.changes/mobile-use-identifier-as-id.md deleted file mode 100644 index 1e3e4a7cb..000000000 --- a/.changes/mobile-use-identifier-as-id.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"tauri": patch:breaking -"tauri-build": patch:breaking -"tauri-cli": patch:breaking -"@tauri-apps/cli": patch:breaking -"tauri-macros": patch:breaking ---- - -Use `tauri.conf.json > identifier` to set the `PackageName` in Android and `BundleId` in iOS. diff --git a/.changes/monitor-from-point-js.md b/.changes/monitor-from-point-js.md deleted file mode 100644 index f14971a9c..000000000 --- a/.changes/monitor-from-point-js.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@tauri-apps/api': 'patch:feat' ---- - -Add `monitorFromPoint` function in `window` module to get the monitor from a given point. \ No newline at end of file diff --git a/.changes/monitor-from-point.md b/.changes/monitor-from-point.md deleted file mode 100644 index 797d47e67..000000000 --- a/.changes/monitor-from-point.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri': 'patch:feat' ---- - -Add `App/AppHandle/Window/Webview/WebviewWindow::monitor_from_point(x, y)` getter to get the monitor from a given point. \ No newline at end of file diff --git a/.changes/multiwebview-bounds-fixes.md b/.changes/multiwebview-bounds-fixes.md deleted file mode 100644 index 9080a90b8..000000000 --- a/.changes/multiwebview-bounds-fixes.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-runtime-wry": patch:bug ---- - -Fixes auto resize and positioning when using the multiwebview mode. diff --git a/.changes/nsis-append-product-name.md b/.changes/nsis-append-product-name.md deleted file mode 100644 index 176131f27..000000000 --- a/.changes/nsis-append-product-name.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri-bundler': 'patch:enhance' ---- - -Append product name automatically when choosing a new install path using browse for nsis installer diff --git a/.changes/nsis-deep-link-uninstall.md b/.changes/nsis-deep-link-uninstall.md deleted file mode 100644 index f58017567..000000000 --- a/.changes/nsis-deep-link-uninstall.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-bundler": "patch:bug" ---- - -Fix NSIS uninstaller failing to clean up deep links diff --git a/.changes/nsis-delete-data-button-dpi.md b/.changes/nsis-delete-data-button-dpi.md deleted file mode 100644 index e91d2d6bd..000000000 --- a/.changes/nsis-delete-data-button-dpi.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-build": "patch:enhance" ---- - -Fix delete app data button gone on higher scaling (>= 1.5) diff --git a/.changes/nsis-dpi-aware.md b/.changes/nsis-dpi-aware.md deleted file mode 100644 index 0fb75afb3..000000000 --- a/.changes/nsis-dpi-aware.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri-build': 'patch:enhance' ---- - -Enable Hight DPI awareness for NSIS installer so it is not blurry on some systems. diff --git a/.changes/nsis-esitimated-size-unit.md b/.changes/nsis-esitimated-size-unit.md deleted file mode 100644 index 411bed048..000000000 --- a/.changes/nsis-esitimated-size-unit.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-bundler": "patch:bug" ---- - -Fix NSIS esitmated size unit being in kB (1000 bytes) not KB (1024 bytes) diff --git a/.changes/nsis-migrate-shortcut.md b/.changes/nsis-migrate-shortcut.md deleted file mode 100644 index a6cc84d27..000000000 --- a/.changes/nsis-migrate-shortcut.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-bundler": "patch:enhance" ---- - -For NSIS installer, migrate old shortcuts by setting the path only instead of re-creating a new one diff --git a/.changes/nsis-no-compression.md b/.changes/nsis-no-compression.md deleted file mode 100644 index 6e4f33e3e..000000000 --- a/.changes/nsis-no-compression.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-utils": patch:feat -"tauri-bundler": patch:feat ---- - -Add an option to disable NSIS compression `bundle > nsis > compression: "none"` diff --git a/.changes/nsis-run-as-user.md b/.changes/nsis-run-as-user.md deleted file mode 100644 index 2ca63383e..000000000 --- a/.changes/nsis-run-as-user.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-bundler": patch:bug ---- - -Fix NSIS installer runs the app as admin when using `perMachine` install mode diff --git a/.changes/nsis-shortcuts-regression.md b/.changes/nsis-shortcuts-regression.md deleted file mode 100644 index b3c55eece..000000000 --- a/.changes/nsis-shortcuts-regression.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-bundler": "patch:bug" ---- - -Fix regression in NSIS where it created shortcuts that point to non-existent files. - diff --git a/.changes/nsis-start-menu-folder-breaking.md b/.changes/nsis-start-menu-folder-breaking.md deleted file mode 100644 index 324f4e350..000000000 --- a/.changes/nsis-start-menu-folder-breaking.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-bundler": "patch:breaking" ---- - -Changed NSIS start menu shortcut to be placed directly inside `%AppData%\Microsoft\Windows\Start Menu\Programs` without an additional folder. You can get the old behavior by setting `bundle > nsis > startMenuFolder` to the same value as your `productName` diff --git a/.changes/nsis-start-menu-folder.md b/.changes/nsis-start-menu-folder.md deleted file mode 100644 index f7fa40bcc..000000000 --- a/.changes/nsis-start-menu-folder.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-utils": "patch:feat" -"tauri-bundler": "patch:feat" ---- - -Add `bundle > nsis > startMenuFolder` option to customize start menu folder for NSIS installer diff --git a/.changes/path-result-error-rexport.md b/.changes/path-result-error-rexport.md deleted file mode 100644 index 6783b717f..000000000 --- a/.changes/path-result-error-rexport.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri': 'major:breaking' ---- - -Removed `tauri::path::Result` and `tauri::path::Error` which were merely an unintentional re-export of `tauri::Result` and `tauri::Error` so use those instead. diff --git a/.changes/permission-platforms.md b/.changes/permission-platforms.md deleted file mode 100644 index 575e8b48a..000000000 --- a/.changes/permission-platforms.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri": patch:feat -"tauri-utils": patch:feat ---- - -Allow defining a permission that only applies to a set of target platforms via the `platforms` configuration option. diff --git a/.changes/permission-schema-unique-item.md b/.changes/permission-schema-unique-item.md deleted file mode 100644 index e670face0..000000000 --- a/.changes/permission-schema-unique-item.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-utils": patch:enhance ---- - -Mark ACL `permissions` array with unique items diff --git a/.changes/permission-table.md b/.changes/permission-table.md deleted file mode 100644 index d31dadd9e..000000000 --- a/.changes/permission-table.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-utils": patch:enhance ---- - -Changed plugin markdown docs generation to table format. diff --git a/.changes/plugin-builder-failable.md b/.changes/plugin-builder-failable.md new file mode 100644 index 000000000..f3c675374 --- /dev/null +++ b/.changes/plugin-builder-failable.md @@ -0,0 +1,5 @@ +--- +"tauri": "patch:enhance" +--- + +Add `tauri::plugin::Builder::try_build` to allow plugins to check if their `TauriPlugin` initialization is valid. diff --git a/.changes/plugin-global-api-script.md b/.changes/plugin-global-api-script.md deleted file mode 100644 index 299385d6e..000000000 --- a/.changes/plugin-global-api-script.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-plugin": patch:feat ---- - -Added `Builder::global_api_script_path` to define a JavaScript file containing the initialization script for the plugin API bindings when `withGlobalTauri` is used. diff --git a/.changes/plugin-init-script-context.md b/.changes/plugin-init-script-context.md deleted file mode 100644 index ba3f59bd3..000000000 --- a/.changes/plugin-init-script-context.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:enhance ---- - -Run each plugin initialization script on its own context so they do not interfere with each other or the Tauri init script. diff --git a/.changes/plugin-ios-xcode-project.md b/.changes/plugin-ios-xcode-project.md deleted file mode 100644 index ecfc3afd8..000000000 --- a/.changes/plugin-ios-xcode-project.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"tauri-cli": patch:feat -"@tauri-apps/cli": patch:feat -"tauri-plugin": patch:feat -"tauri-utils": patch:feat -"tauri": patch:feat ---- - -Added an option to use a Xcode project for the iOS plugin instead of a plain SwiftPM project. diff --git a/.changes/pre.json b/.changes/pre.json index 167f3ea53..300964945 100644 --- a/.changes/pre.json +++ b/.changes/pre.json @@ -1,263 +1,28 @@ { - "tag": "beta", + "tag": "rc", "changes": [ - ".changes/UriSchemeResponder-export.md", - ".changes/acl-default-permission-verification.md", - ".changes/acl-platform-refactor.md", - ".changes/acl-scope-refactor.md", - ".changes/acl-urlpattern.md", - ".changes/allow-recursive-asset-scope-on-file-drop-directory.md", - ".changes/api-isTauri-type.md", - ".changes/api-isTauri.md", - ".changes/api-position-size-args.md", - ".changes/api-readd-window-created-event.md", - ".changes/api-simplify-unc-paths.md", - ".changes/api-tauri-event-file-drop-rename.md", - ".changes/api-tray-by-id.md", - ".changes/api-type-definitions.md", - ".changes/api-webview-window-new-methods.md", - ".changes/api-webview-window.md", - ".changes/api-window-on-filedrop.md", - ".changes/app-handle-set-activation-policy.md", - ".changes/app-manifest.md", - ".changes/app-region-drag.md", - ".changes/assets-setup.md", - ".changes/beta.md", - ".changes/better-error-for-invalid-plugin-config.md", - ".changes/build-android-version-check.md", - ".changes/build-resource-target-same-src.md", - ".changes/build-schema-generation.md", - ".changes/bunderl-installer-hooks.md", - ".changes/bundler-deep-link-reg-path.md", - ".changes/bundler-license.md", - ".changes/bundler-long_description.md", - ".changes/bundler-nsis-deep-links.md", - ".changes/bundler-nsis-tauri-utils.md", - ".changes/bundler-r-flag.md", - ".changes/bundler-resources-unix.md", - ".changes/bundler-rpm-license.md", - ".changes/bundler-shortcuts-updating.md", - ".changes/capabilities-multiwebview.md", - ".changes/capabilities-tauri-conf.md", - ".changes/capability-builder-platform.md", - ".changes/capability-context-refactor.md", - ".changes/cleanup-resource-table.md", - ".changes/cli-acl-subcommands.md", - ".changes/cli-add-@-spec.md", - ".changes/cli-add-launchscreen-storyboard.md", - ".changes/cli-allow-kotlin-keyword-as-ident.md", - ".changes/cli-build-no-bundle.md", - ".changes/cli-chinese-product-name.md", - ".changes/cli-ds-store-dev-watch.md", - ".changes/cli-empty-responses.md", - ".changes/cli-frontend-dist-expected-path.md", - ".changes/cli-icon-non-0-exit.md", - ".changes/cli-include-dir-cargo-manifest-dir.md", - ".changes/cli-migrate-non-utf8.md", - ".changes/cli-migrate-unknown-plugins.md", - ".changes/cli-mobile-init-partition.md", - ".changes/cli-openssl-cargo-mobile2-removal.md", - ".changes/cli-perserve-cargo-bin-name.md", - ".changes/cli-plugin-android-init.md", - ".changes/cli-plugins-migrate.md", - ".changes/cli-update-deps-fix-log.md", - ".changes/cli-updater-unkown-fields.md", - ".changes/cli-windows-build-tools-detect-utf8.md", - ".changes/cli-windows-sys.md", - ".changes/closeable-maximizable.md", - ".changes/codegen-capabilities-attribute.md", - ".changes/codegen-set-assets.md", - ".changes/color-context-generation.md", - ".changes/context-assets-runtime-generic.md", - ".changes/context-assets-unbox.md", - ".changes/context-remove-assets-generics.md", - ".changes/context-remove-assets-mut.md", - ".changes/context-runtime-authority.md", - ".changes/core-always-rebuilds-due-to-permissions-dir.md", - ".changes/core-app-tray-remove-tray-apis-removed.md", - ".changes/core-center-window.md", - ".changes/core-emit-created-events.md", - ".changes/core-emit-js-all-targets.md", - ".changes/core-env-args.md", - ".changes/core-isTauri.md", - ".changes/core-js-event-anytarget.md", - ".changes/core-jsimage-intoimg.md", - ".changes/core-menu-resources-deadlock.md", - ".changes/core-once-event-return-event-id.md", - ".changes/core-path-basename-replace.md", - ".changes/core-specta-integration.md", - ".changes/core-start-resize-permission.md", - ".changes/core-window-hasdisplayhandle.md", - ".changes/core-windows-menubar-theme.md", - ".changes/csp-header-linux.md", - ".changes/cursor_position.md", - ".changes/cursor_position_js.md", - ".changes/custom-sign-command.md", - ".changes/deb-rpm-post-pre-scripts-bundler.md", - ".changes/deb-rpm-post-pre-scripts-config.md", - ".changes/deb-rpm-provides-conflicts-replaces.md", - ".changes/default-generic-for-menu.md", - ".changes/default-generic-for-tray.md", - ".changes/dev-fn.md", - ".changes/downgrade-minisign.md", - ".changes/drop-nsis-applicationid.md", - ".changes/enhance-event-emit.md", - ".changes/enhance-ipc-url-check.md", - ".changes/enhance-resource-dir-resolution.md", - ".changes/event-reopen.md", - ".changes/expose-image-constructor.md", - ".changes/expose-js-image.md", - ".changes/fix-acl-webview-check.md", - ".changes/fix-add-child-deadlock.md", - ".changes/fix-capability-schema-definitions.md", - ".changes/fix-capability-totokens.md", - ".changes/fix-channel-buffer-processing.md", - ".changes/fix-channel-ipc-response.md", - ".changes/fix-clear-residual-listeners.md", - ".changes/fix-cli-add-more-plugins.md", - ".changes/fix-cli-migration-http-acl.md", - ".changes/fix-codegen-rerun-if-changed.md", - ".changes/fix-config-arg.md", - ".changes/fix-draw-tracing.md", - ".changes/fix-fs-scope-check-symlink.md", - ".changes/fix-incompatible-ipc-field-postmessage.md", - ".changes/fix-inner-size.md", - ".changes/fix-invoke-devtools-by-hotkey.md", - ".changes/fix-ios-dev-logs.md", - ".changes/fix-ipc-error-json.md", - ".changes/fix-macos-deep-link-cfbundleurlname.md", - ".changes/fix-menu-remove-api.md", - ".changes/fix-metadata-on-close.md", - ".changes/fix-migrate-updater.md", - ".changes/fix-mobile-cmd-case.md", - ".changes/fix-mobile-process-spawn.md", - ".changes/fix-pnpm-check.md", - ".changes/fix-process-ipc-message-fn.md", - ".changes/fix-proxy-url-totokens-impl.md", - ".changes/fix-remote-domain-url.md", - ".changes/fix-reparent.md", - ".changes/fix-rewrite-schema.md", - ".changes/fix-runtime-wry-32bit.md", - ".changes/fix-schemars-compatibility.md", - ".changes/fix-scope-resolution.md", - ".changes/fix-tauri-build-license-field.md", - ".changes/fix-tauri-build-unix.md", - ".changes/fix-temp-permission-file-name.md", - ".changes/fix-visibility-change.md", - ".changes/fix-webview-close.md", - ".changes/fix-window-center-monitor-scale.md", - ".changes/fix-window-center-work-area.md", - ".changes/fix-window-destroy-deadlock.md", - ".changes/fix-window-inner-size-crash.md", - ".changes/global-api-script-path-plugins.md", - ".changes/handle-empty-permissions.md", - ".changes/hide-windows-on-cleanup.md", - ".changes/http-v1.md", - ".changes/ico-featrue-flags.md", - ".changes/image-crate.md", - ".changes/image-rgba-uint8array.md", - ".changes/image-size-refactor.md", - ".changes/improve-errors-for-missing-links-property.md", - ".changes/inline-plugins.md", - ".changes/ios-signing-optional.md", - ".changes/ipc-allow-headers.md", - ".changes/ipc-only-main-frame.md", - ".changes/ipc-post-message-fallback.md", - ".changes/ipc-request-param-refactor.md", - ".changes/isolation-pattern-key-extractable.md", - ".changes/isolation-script-remove-itself.md", - ".changes/mobile-use-identifier-as-id.md", - ".changes/mobile-watcher.md", - ".changes/monitor-from-point-js.md", - ".changes/monitor-from-point.md", - ".changes/multiwebview-bounds-fixes.md", - ".changes/nsis-append-product-name.md", - ".changes/nsis-dpi-aware.md", - ".changes/nsis-shortcuts-regression.md", - ".changes/path-result-error-rexport.md", - ".changes/permission-platforms.md", - ".changes/permission-table.md", - ".changes/plugin-global-api-script.md", - ".changes/plugin-init-script-context.md", - ".changes/plugin-ios-xcode-project.md", - ".changes/preserve-channel-order.md", - ".changes/progress-bar-state-refactor.md", - ".changes/re-export-progress-bar-status.md", - ".changes/rect-strcut.md", - ".changes/refactor-capabilities-schema.md", - ".changes/refactor-capability-remote-option.md", - ".changes/refactor-scope-ret-value.md", - ".changes/remove-app-custom-protocol-feature.md", - ".changes/remove-from-format-image.md", - ".changes/remove-unit-uri.md", - ".changes/rename-file-drop.md", - ".changes/reparent.md", - ".changes/rerun-if-permission-created.md", - ".changes/resources_table_access.md", - ".changes/revert-app-region-drag.md", - ".changes/revert-fix-visibility-change.md", - ".changes/rpm-compression-level.md", - ".changes/runner-config.md", - ".changes/runtime-add-capability.md", - ".changes/runtime-capability-dynamic.md", - ".changes/runtime-dpi-mod-moved.md", - ".changes/runtime-icon-lifetime.md", - ".changes/runtime-window-builder-get-theme.md", - ".changes/rustc-check-cfg.md", - ".changes/rwh-06.md", - ".changes/schema_str.md", - ".changes/script-older-os.md", - ".changes/set-auto-resize.md", - ".changes/set-zoom.md", - ".changes/skip-webview-install-mod.md", - ".changes/strict-csp-isolation-frame.md", - ".changes/tauri-build-codegen-capabilities.md", - ".changes/tauri-build-dev-changes.md", - ".changes/tauri-build-dev-fn.md", - ".changes/tauri-bundle-command.md", - ".changes/tauri-cli-add-default-perm.md", - ".changes/tauri-close-requested-target-specific.md", - ".changes/tauri-codegen-use-correct-env.md", - ".changes/tauri-context-icon-methods.md", - ".changes/tauri-correct-platform-file.md", - ".changes/tauri-dev-fn-const.md", - ".changes/tauri-error-sync.md", - ".changes/tauri-icon-removed.md", - ".changes/tauri-image-codegen.md", - ".changes/tauri-image.md", - ".changes/tauri-info-no-node.md", - ".changes/tauri-plugin-identifier-alphanumeric.md", - ".changes/tauri-runtime-webview-events.md", - ".changes/tauri-scope-object-error-sync.md", - ".changes/tauri-utils-capability-refactor.md", - ".changes/tauri-utils-package-name-removed.md", - ".changes/tauri-utils-plugin-module.md", - ".changes/tauri-webview-events.md", - ".changes/tauri-window-origin-default-to-null.md", - ".changes/tray-icon-event.md", - ".changes/tray-icon-rect.md", - ".changes/tray-rect.md", - ".changes/truncate-before-write-buildtask.md", - ".changes/unstable-child-webview.md", - ".changes/update-acl-paths-cli.md", - ".changes/update-app-template-capabilities-conf.md", - ".changes/update-gradle.md", - ".changes/update-plugin-template.md", - ".changes/update-target-sdk.md", - ".changes/url-result-runtime.md", - ".changes/url-result.md", - ".changes/utils-bundle-target-all.md", - ".changes/utils-bundle-type-all.md", - ".changes/utils-debug-eprintln.md", - ".changes/utils-installer-hooks.md", - ".changes/utils-named-capability-file.md", - ".changes/utils-remove-asset-trait.md", - ".changes/utils-sign-command.md", - ".changes/webview-bounds.md", - ".changes/wry-0.36.md", - ".changes/wry-0.37.md", - ".changes/wry-0.38.md", - ".changes/zoom-hotkeys-enabled.md", - ".changes/zoom-polyfill.md" + ".changes/android-dev-open-adb-fix.md", + ".changes/asset-resolver-dev-fallback.md", + ".changes/change-pr-10435.md", + ".changes/change-pr-10498.md", + ".changes/check-android-lib-symbols.md", + ".changes/cli-desktop-port-exposure.md", + ".changes/cli-mobile-checks.md", + ".changes/core-plugin-namespace.md", + ".changes/dev-url-localhost-mobile.md", + ".changes/fix-adb.md", + ".changes/fix-colon-in-file-path.md", + ".changes/fix-conf-parsing-error-filepath.md", + ".changes/fix-usage-without-compression.md", + ".changes/ios-custom-project-template.md", + ".changes/ios-frameworks.md", + ".changes/isolation-main-frame-origin.md", + ".changes/linux-option-gtk-app-id.md", + ".changes/min-ios-version.md", + ".changes/plugin-builder-failable.md", + ".changes/rc-migration.md", + ".changes/remove-open-command.md", + ".changes/remove-unsecure-configs.md", + ".changes/v1-migrate-updater.md" ] } diff --git a/.changes/preserve-channel-order.md b/.changes/preserve-channel-order.md deleted file mode 100644 index 59b4595fa..000000000 --- a/.changes/preserve-channel-order.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri": patch:enhance -"@tauri-apps/api": patch:enhance ---- - -Added a mechanism to preserve channel message order. diff --git a/.changes/progress-bar-state-refactor.md b/.changes/progress-bar-state-refactor.md deleted file mode 100644 index 3c65c686e..000000000 --- a/.changes/progress-bar-state-refactor.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri": patch:breaking -"tauri-utils": patch:breaking ---- - -Moved `ProgressBarState` from `tauri-utils` to the `tauri::window` module and removed the `unity_uri` field. diff --git a/.changes/raw-window-handle-std.md b/.changes/raw-window-handle-std.md deleted file mode 100644 index 356832906..000000000 --- a/.changes/raw-window-handle-std.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:bug ---- - -Add `std` feature to `raw-window-handle` crate so that using `default-features = false` on `tauri` crate can work diff --git a/.changes/rc-migration.md b/.changes/rc-migration.md new file mode 100644 index 000000000..3e117a741 --- /dev/null +++ b/.changes/rc-migration.md @@ -0,0 +1,6 @@ +--- +"tauri-cli": patch:feat +"@tauri-apps/cli": patch:feat +--- + +Added migration from `2.0.0-beta` to `2.0.0-rc`. diff --git a/.changes/re-export-progress-bar-status.md b/.changes/re-export-progress-bar-status.md deleted file mode 100644 index edec293a2..000000000 --- a/.changes/re-export-progress-bar-status.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri': 'patch:bug' ---- - -Export `ProgressBarStatus`, regression introduced in `2.0.0-beta.4` diff --git a/.changes/rect-strcut.md b/.changes/rect-strcut.md deleted file mode 100644 index 923f7777b..000000000 --- a/.changes/rect-strcut.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri': 'patch:feat' ---- - -Added `Rect` struct. diff --git a/.changes/refactor-capabilities-schema.md b/.changes/refactor-capabilities-schema.md deleted file mode 100644 index ee1d56a39..000000000 --- a/.changes/refactor-capabilities-schema.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"@tauri-apps/cli": patch:enhance -"tauri-cli": patch:enhance -"tauri-build": patch:enhance -"tauri-utils": patch:enhance ---- - -Moved the capability JSON schema to the `src-tauri/gen` folder so it's easier to track changes on the `capabilities` folder. diff --git a/.changes/refactor-capability-remote-option.md b/.changes/refactor-capability-remote-option.md deleted file mode 100644 index 2572cc10a..000000000 --- a/.changes/refactor-capability-remote-option.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-utils": patch:breaking -"tauri": patch:breaking ---- - -Changed the capability `remote` configuration to take a list of `urls` instead of `domains` for more flexibility. diff --git a/.changes/refactor-scope-ret-value.md b/.changes/refactor-scope-ret-value.md deleted file mode 100644 index 63112d4e7..000000000 --- a/.changes/refactor-scope-ret-value.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:breaking ---- - -The `allows` and `denies` methods from `ipc::ScopeValue`, `ipc::CommandScope` and `ipc::GlobalScope` now returns `&Vec>` instead of `&Vec`. diff --git a/.changes/remove-app-custom-protocol-feature.md b/.changes/remove-app-custom-protocol-feature.md deleted file mode 100644 index ffd7353aa..000000000 --- a/.changes/remove-app-custom-protocol-feature.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"@tauri-apps/cli": patch:breaking -"tauri-cli": patch:breaking -"tauri": patch:breaking -"tauri-build": patch:breaking ---- - -The `custom-protocol` Cargo feature is no longer required on your application and is now ignored. To check if running on production, use `#[cfg(not(dev))]` instead of `#[cfg(feature = "custom-protocol")]`. diff --git a/.changes/remove-from-format-image.md b/.changes/remove-from-format-image.md deleted file mode 100644 index 7fbde64f8..000000000 --- a/.changes/remove-from-format-image.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@tauri-apps/api": patch:breaking ---- - -Remove the `Image.fromPngBytes` and `Image.fromIcoBytes` APIs. Use `Image.fromBytes` instead. diff --git a/.changes/remove-open-command.md b/.changes/remove-open-command.md new file mode 100644 index 000000000..29210b0b4 --- /dev/null +++ b/.changes/remove-open-command.md @@ -0,0 +1,6 @@ +--- +"tauri-cli": patch:changes +"@tauri-apps/cli": patch:changes +--- + +Removed the `[android|ios] open` command. It is recommended to use `[android|ios] dev --open` or `[android|ios] build --open` instead. diff --git a/.changes/remove-unit-uri.md b/.changes/remove-unit-uri.md deleted file mode 100644 index 7ddb6fcaf..000000000 --- a/.changes/remove-unit-uri.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@tauri-apps/api": patch:breaking ---- - -Removed the `unityUri` option from the progress bar state, no longer required. diff --git a/.changes/remove-unsecure-configs.md b/.changes/remove-unsecure-configs.md new file mode 100644 index 000000000..2385ec55b --- /dev/null +++ b/.changes/remove-unsecure-configs.md @@ -0,0 +1,8 @@ +--- +"tauri-cli": patch:sec +"@tauri-apps/cli": patch:sec +"tauri": patch:sec +--- + +Re-enable TLS checks that were previously disabled to support an insecure HTTPS custom protocol on Android which is no longer used. + diff --git a/.changes/rename-file-drop.md b/.changes/rename-file-drop.md deleted file mode 100644 index 26fd3bd0c..000000000 --- a/.changes/rename-file-drop.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"tauri": patch:breaking -"tauri-runtime": patch:breaking -"tauri-utils": patch:breaking -"tauri-runtime-wry": patch:breaking -"@tauri-apps/api": patch:breaking ---- - -Rename `FileDrop` to `DragDrop` on structs, enums and enum variants. Also renamed `file_drop` to `drag_drop` on fields and function names. diff --git a/.changes/reparent.md b/.changes/reparent.md deleted file mode 100644 index 318162aa5..000000000 --- a/.changes/reparent.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"@tauri-apps/api": patch:feat -"tauri": patch:feat -"tauri-runtime": patch:feat -"tauri-runtime-wry": patch:feat ---- - -Added the `reparent` function to the webview API. diff --git a/.changes/rerun-if-permission-created.md b/.changes/rerun-if-permission-created.md deleted file mode 100644 index e0f9e83fe..000000000 --- a/.changes/rerun-if-permission-created.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-plugin": patch:bug -"tauri-utils": patch:bug ---- - -Rerun build script when a new permission is added. diff --git a/.changes/resources_table_access.md b/.changes/resources_table_access.md deleted file mode 100644 index 649badeeb..000000000 --- a/.changes/resources_table_access.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri': 'patch:breaking' ---- - -`Manager::resources_table` is now scoped so each `App/AppHandle/Window/Webview/WebviewWindow` has its own resource collection. diff --git a/.changes/revert-app-region-drag.md b/.changes/revert-app-region-drag.md deleted file mode 100644 index 6827c2ebc..000000000 --- a/.changes/revert-app-region-drag.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"tauri": patch:bug ---- - -Revert adding `app-region: drag` to HTML elements with `data-tauri-drag-region` on Windows as it has a few issues: -- Doesn't allow right click, as it will always show the system context menu on right click. -- `data-tauri-drag-region` works only if the click was on an element that has it, this allows buttons in the custom titlebar to work, however `app-region: drag` will treat the whole area as a titlebar won't even allow clicks on buttons. diff --git a/.changes/revert-fix-visibility-change.md b/.changes/revert-fix-visibility-change.md deleted file mode 100644 index 71dd87e8d..000000000 --- a/.changes/revert-fix-visibility-change.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-runtime-wry": patch:bug ---- - -Revert the [fix](https://github.com/tauri-apps/tauri/pull/9246) for webview's visibility doesn't change with the app window on Windows as it caused white flashes on show/restore. diff --git a/.changes/rpm-compression-level.md b/.changes/rpm-compression-level.md deleted file mode 100644 index 93feb3c34..000000000 --- a/.changes/rpm-compression-level.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -tauri-bundler: patch:enhance ---- - -Reduced the compression level for rpm bundles from 9 (max) to 6. This has almost no effect on file size but should reduce build time by roughly 25%. diff --git a/.changes/runner-config.md b/.changes/runner-config.md deleted file mode 100644 index c810ccfbb..000000000 --- a/.changes/runner-config.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'tauri-cli': 'patch:bug' -'@tauri-apps/cli': 'patch:bug' ---- - -Fixed an issue causing the `build.runner` and `build.features` configs to not take effect. diff --git a/.changes/runtime-add-capability.md b/.changes/runtime-add-capability.md deleted file mode 100644 index 851d11801..000000000 --- a/.changes/runtime-add-capability.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:enhance ---- - -Added `Manager::add_capability` to add a capability file at runtime. diff --git a/.changes/runtime-capability-dynamic.md b/.changes/runtime-capability-dynamic.md deleted file mode 100644 index 404c76579..000000000 --- a/.changes/runtime-capability-dynamic.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:enhance ---- - -`Manager::add_capability` now allows adding a dynamically defined capability instead of only relying on static strings. diff --git a/.changes/runtime-dpi-mod-moved.md b/.changes/runtime-dpi-mod-moved.md deleted file mode 100644 index 51629e345..000000000 --- a/.changes/runtime-dpi-mod-moved.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri-runtime': 'major:breaking' ---- - -Moved `window::dpi` module to the root of the crate. diff --git a/.changes/runtime-icon-lifetime.md b/.changes/runtime-icon-lifetime.md deleted file mode 100644 index 664ff1e78..000000000 --- a/.changes/runtime-icon-lifetime.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri-runtime': 'major:breaking' ---- - -Add a lifetime parameter for `Icon` type. Also changed `rgba` field to be `Cow<'a, [u8]>` diff --git a/.changes/runtime-window-builder-get-theme.md b/.changes/runtime-window-builder-get-theme.md deleted file mode 100644 index b40f03962..000000000 --- a/.changes/runtime-window-builder-get-theme.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-runtime": patch:enhance -"tauri-runtime-wry": patch:enhance ---- - -Added `WindowBuilder::get_theme`. diff --git a/.changes/rustc-check-cfg.md b/.changes/rustc-check-cfg.md deleted file mode 100644 index 6bb9a2bce..000000000 --- a/.changes/rustc-check-cfg.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"tauri": patch:changes -"tauri-build": patch:changes -"tauri-runtime": patch:changes -"tauri-runtime-wry": patch:changes -"tauri-plugin": patch:changes ---- - -Emit `cargo:rustc-check-cfg` instruction so Cargo validates custom cfg attributes on Rust 1.80 (or nightly-2024-05-05). diff --git a/.changes/rwh-06.md b/.changes/rwh-06.md deleted file mode 100644 index a2b6e5f1b..000000000 --- a/.changes/rwh-06.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"tauri": patch:breaking -"tauri-runtime": patch:breaking -"tauri-runtime-wry": patch:breaking ---- - -Update raw-window-handle to 0.6. diff --git a/.changes/schema_str.md b/.changes/schema_str.md deleted file mode 100644 index f9088ac49..000000000 --- a/.changes/schema_str.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri-build': 'patch:bug' ---- - -Fix generating invalid schema files. diff --git a/.changes/script-older-os.md b/.changes/script-older-os.md deleted file mode 100644 index 8c37afcc2..000000000 --- a/.changes/script-older-os.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@tauri-apps/api": patch:bug -"tauri": patch:bug ---- - -Do not use JS optional chaining to prevent script errors on older webviews such as macOS 10.14. diff --git a/.changes/separate-updater-field.md b/.changes/separate-updater-field.md deleted file mode 100644 index 2bc80f9d5..000000000 --- a/.changes/separate-updater-field.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"tauri-utils": patch:breaking -"tauri-bundler": patch:breaking -"tauri-cli": patch:breaking -"@tauri-apps/cli": patch:breaking ---- - -Move updater target from `bundle > targets` to a separate field `bundle > createUpdaterArtifacts` diff --git a/.changes/set-auto-resize.md b/.changes/set-auto-resize.md deleted file mode 100644 index 454f44ecd..000000000 --- a/.changes/set-auto-resize.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"tauri": patch:feat -"tauri-runtime": patch:feat -"tauri-runtime-wry": patch:feat ---- - -Added `set_auto_resize` method for the webview. diff --git a/.changes/set-zoom.md b/.changes/set-zoom.md deleted file mode 100644 index d095b4918..000000000 --- a/.changes/set-zoom.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"@tauri-apps/api": minor:feat -"tauri": minor:feat -"tauri-runtime": minor:feat -"tauri-runtime-wry": minor:feat ---- - -Added the `set_zoom` function to the webview API. diff --git a/.changes/skip-webview-install-mod.md b/.changes/skip-webview-install-mod.md deleted file mode 100644 index 86fc8b639..000000000 --- a/.changes/skip-webview-install-mod.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"tauri-utils": "major:breaking" -"tauri-bundler": "major:breaking" ---- - -Removed `skip_webview_install` (`skipWebviewInstall`) option from config, which has been deprecated for a while now and planned to be removed in v2. Use `webview_install_mode` (`webviewInstallMode`) instead. - diff --git a/.changes/strict-csp-isolation-frame.md b/.changes/strict-csp-isolation-frame.md deleted file mode 100644 index c01271311..000000000 --- a/.changes/strict-csp-isolation-frame.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": patch:enhance ---- - -Use a strict content security policy on the isolation pattern iframe. diff --git a/.changes/tauri-build-codegen-capabilities.md b/.changes/tauri-build-codegen-capabilities.md deleted file mode 100644 index cc767345a..000000000 --- a/.changes/tauri-build-codegen-capabilities.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-build": patch:enhance ---- - -Added `CodegenContext::capability` to include a capability file dynamically. diff --git a/.changes/tauri-build-dev-changes.md b/.changes/tauri-build-dev-changes.md deleted file mode 100644 index bcf4204f6..000000000 --- a/.changes/tauri-build-dev-changes.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-build": patch:breaking ---- - -Removed `tauri_build::CodegenContext::dev()` and added `tauri_build::dev()`. diff --git a/.changes/tauri-build-dev-fn.md b/.changes/tauri-build-dev-fn.md deleted file mode 100644 index 580437e97..000000000 --- a/.changes/tauri-build-dev-fn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-build": "patch:breaking" ---- - -Renamed `dev` function to `is_dev` \ No newline at end of file diff --git a/.changes/tauri-bundle-command.md b/.changes/tauri-bundle-command.md deleted file mode 100644 index 8d586dcc2..000000000 --- a/.changes/tauri-bundle-command.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"tauri-cli": "patch:feat" -"@tauri-apps/cli": "patch:feat" ---- - -Add `tauri bundle` subcommand which runs the bundle phase only, best paired with `tauri build --no-bundle` - diff --git a/.changes/tauri-cli-add-default-perm.md b/.changes/tauri-cli-add-default-perm.md deleted file mode 100644 index 814a6d26b..000000000 --- a/.changes/tauri-cli-add-default-perm.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'tauri-cli': 'patch:feat' -'@tauri-apps/cli': 'patch:feat' ---- - -Add default permission for a plugin to capabilities when using `tauri add `. diff --git a/.changes/tauri-close-requested-target-specific.md b/.changes/tauri-close-requested-target-specific.md deleted file mode 100644 index bbe08852e..000000000 --- a/.changes/tauri-close-requested-target-specific.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri': 'patch:bug' ---- - -Fix JS `onCloseRequested` catching close event from other windows. diff --git a/.changes/tauri-codegen-use-correct-env.md b/.changes/tauri-codegen-use-correct-env.md deleted file mode 100644 index 5f0b66582..000000000 --- a/.changes/tauri-codegen-use-correct-env.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-codegen": "patch" ---- - -Use `TAURI_ENV_TARGET_TRIPLE` (which is set by `tauri-build`) to determine the target when reading the config file. diff --git a/.changes/tauri-context-icon-methods.md b/.changes/tauri-context-icon-methods.md deleted file mode 100644 index 0f8cdbaef..000000000 --- a/.changes/tauri-context-icon-methods.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri': 'major:breaking' ---- - -Removed `Context::default_window_icon_mut` and `Context::tray_icon_mut`, use `Context::set_default_window_icon` and `Context::set_tray_icon` instead. Also changed `Context::set_tray_icon` to accept `Option`. diff --git a/.changes/tauri-correct-platform-file.md b/.changes/tauri-correct-platform-file.md deleted file mode 100644 index 5cccf70cf..000000000 --- a/.changes/tauri-correct-platform-file.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri": "patch:bug" ---- - -Parse the correct platform `tauri..conf.json` config file when building or developing for mobile. - diff --git a/.changes/tauri-dev-fn-const.md b/.changes/tauri-dev-fn-const.md deleted file mode 100644 index eafb464ac..000000000 --- a/.changes/tauri-dev-fn-const.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": "patch:breaking" ---- - -Renamed `dev` function to `is_dev` and marked it as `const fn` \ No newline at end of file diff --git a/.changes/tauri-error-sync.md b/.changes/tauri-error-sync.md deleted file mode 100644 index 3fb1c3e88..000000000 --- a/.changes/tauri-error-sync.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri': 'patch:bug' ---- - -Fix regression in `tauri::Error` not being `Sync`. diff --git a/.changes/tauri-icon-removed.md b/.changes/tauri-icon-removed.md deleted file mode 100644 index 5be02ecf0..000000000 --- a/.changes/tauri-icon-removed.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri': 'major:breaking' ---- - -Removed `Icon` enum, use the new `Image` type instead. All APIs that previously accepted `Icon` have changed to accept `Image` instead. diff --git a/.changes/tauri-image-codegen.md b/.changes/tauri-image-codegen.md deleted file mode 100644 index ce4e64afb..000000000 --- a/.changes/tauri-image-codegen.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri-codegen': 'major:breaking' ---- - -Change the generated context code to use the new `Image` type in tauri. diff --git a/.changes/tauri-image.md b/.changes/tauri-image.md deleted file mode 100644 index 0b72a4306..000000000 --- a/.changes/tauri-image.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'tauri': 'minor:feat' -'@tauri-apps/api': 'minor:feat' ---- - -Add a new `Image` type in Rust and JS. diff --git a/.changes/tauri-info-no-node.md b/.changes/tauri-info-no-node.md deleted file mode 100644 index 67a00a955..000000000 --- a/.changes/tauri-info-no-node.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-cli": "patch:bug" -"@tauri-apps/cli": "patch:bug" ---- - -Fix `tauri info` crashing when Node.js is not installed. diff --git a/.changes/tauri-plugin-identifier-alphanumeric.md b/.changes/tauri-plugin-identifier-alphanumeric.md deleted file mode 100644 index d6cbbc36d..000000000 --- a/.changes/tauri-plugin-identifier-alphanumeric.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'tauri': 'patch:enhance' -'tauri-utils': 'patch:enhance' ---- - -Relax requirements on plugin's identifiers to be alphanumeric and `-` instead of only lower alpha and `-`. diff --git a/.changes/tauri-runtime-webview-events.md b/.changes/tauri-runtime-webview-events.md deleted file mode 100644 index b021ab1d1..000000000 --- a/.changes/tauri-runtime-webview-events.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'tauri-runtime': 'patch' -'tauri-runtime-wry': 'patch' ---- - -Add `WebviewEvent`, `RunEvent::WebviewEvent` and `WebviewDispatch::on_webview_event`. diff --git a/.changes/tauri-scope-object-error-sync.md b/.changes/tauri-scope-object-error-sync.md deleted file mode 100644 index 8af76397d..000000000 --- a/.changes/tauri-scope-object-error-sync.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri': 'patch:breaking' ---- - -Require `ScopeObject::Error` to be `Sync` as well. diff --git a/.changes/tauri-utils-capability-refactor.md b/.changes/tauri-utils-capability-refactor.md deleted file mode 100644 index c1fa7873f..000000000 --- a/.changes/tauri-utils-capability-refactor.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-utils": patch:enhance ---- - -Refactored the capability types and resolution algorithm. diff --git a/.changes/tauri-utils-package-name-removed.md b/.changes/tauri-utils-package-name-removed.md deleted file mode 100644 index bbb4ae146..000000000 --- a/.changes/tauri-utils-package-name-removed.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-utils": "patch:breaking" ---- - -Removed `Config::binary_name` and `PackageInfo::package_name` - diff --git a/.changes/tauri-utils-plugin-module.md b/.changes/tauri-utils-plugin-module.md deleted file mode 100644 index 033ed9f23..000000000 --- a/.changes/tauri-utils-plugin-module.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-utils": patch:feat ---- - -Added the `plugin` module. diff --git a/.changes/tauri-webview-events.md b/.changes/tauri-webview-events.md deleted file mode 100644 index 7a4aa10ef..000000000 --- a/.changes/tauri-webview-events.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'tauri': 'patch:feat' ---- - -Add webview-specific events for multi-webview windows: - -- Add `WebviewEvent` enum -- Add `RunEvent::WebviewEvent` variant. -- Add `Builder::on_webview_event` and `Webview::on_webview_event` methods. diff --git a/.changes/tauri-window-origin-default-to-null.md b/.changes/tauri-window-origin-default-to-null.md deleted file mode 100644 index 748932cd7..000000000 --- a/.changes/tauri-window-origin-default-to-null.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri': 'patch:bug' ---- - -Set default window origin to `null`. Prevent window crash when loading `about:blank`. diff --git a/.changes/tray-icon-event.md b/.changes/tray-icon-event.md deleted file mode 100644 index eae9fc890..000000000 --- a/.changes/tray-icon-event.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -"tauri": "patch:breaking" -"@tauri-apps/api": "patch:breaking" ---- - -This release contains breaking changes to the tray event structure because of newly added events: -- Changed `TrayIconEvent` to be an enum instead of a struct. -- Added `MouseButtonState` and `MouseButton` enums. -- Removed `ClickType` enum and replaced it with `MouseButton` enum. -- Added `MouseButtonState` enum. diff --git a/.changes/tray-icon-rect.md b/.changes/tray-icon-rect.md deleted file mode 100644 index 1eae30d7f..000000000 --- a/.changes/tray-icon-rect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": "minor:feat" ---- - -Add `TrayIcon::rect` method to retrieve the tray icon rectangle \ No newline at end of file diff --git a/.changes/tray-menu-default-permission.md b/.changes/tray-menu-default-permission.md deleted file mode 100644 index d1cd740fd..000000000 --- a/.changes/tray-menu-default-permission.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": "patch:enhance" ---- - -Make `tray:default` and `menu:default` include all tray and menu permissions diff --git a/.changes/tray-rect.md b/.changes/tray-rect.md deleted file mode 100644 index 28f8528cd..000000000 --- a/.changes/tray-rect.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'tauri': 'patch:breaking' ---- - -Refactored the tray icon event struct: - -- Changed `TrayIconEvent.icon_rect` type to use the new `tauri::Rect` type. -- Removed `TrayIconEvent.x` and `TrayIconEvent.y` fields and combined them into `TrayIconEvent.position` field. -- Removed `tauri::tray::Rectangle` struct. diff --git a/.changes/truncate-before-write-buildtask.md b/.changes/truncate-before-write-buildtask.md deleted file mode 100644 index 0897545c0..000000000 --- a/.changes/truncate-before-write-buildtask.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-cli": patch:bug -"@tauri-apps/cli": patch:bug ---- - -Fixes truncation of existing BuildTask.kt when running `tauri android init`. diff --git a/.changes/undecorated-resizing.md b/.changes/undecorated-resizing.md deleted file mode 100644 index e13e22073..000000000 --- a/.changes/undecorated-resizing.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -"tauri": "patch:bug" -"tauri-runtime-wry": "patch:bug" ---- - -On Windows, handle resizing undecorated windows natively which improves performance and fixes a couple of annoyances with previous JS implementation: -- No more cursor flickering when moving the cursor across an edge. -- Can resize from top even when `data-tauri-drag-region` element exists there. -- Upon starting rezing, clicks don't go through elements behind it so no longer accidental clicks. - diff --git a/.changes/unstable-child-webview.md b/.changes/unstable-child-webview.md deleted file mode 100644 index bebc812d1..000000000 --- a/.changes/unstable-child-webview.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri": patch:enhance -"tauri-runtime-wry": patch:enhance ---- - -When using the `unstable` feature flag, `WebviewWindow` will internally use the child webview interface for flexibility. diff --git a/.changes/update-acl-paths-cli.md b/.changes/update-acl-paths-cli.md deleted file mode 100644 index 19a4e7b55..000000000 --- a/.changes/update-acl-paths-cli.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-cli": patch:changes -"@tauri-apps/cli": patch:changes ---- - -Updates to new ACL manifest path. diff --git a/.changes/update-app-template-capabilities-conf.md b/.changes/update-app-template-capabilities-conf.md deleted file mode 100644 index ebfe18dd2..000000000 --- a/.changes/update-app-template-capabilities-conf.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@tauri-apps/cli": patch:enhance -"tauri-cli": patch:enhance ---- - -Update app template following capabilities configuration change. diff --git a/.changes/update-gradle.md b/.changes/update-gradle.md deleted file mode 100644 index fd66b47f9..000000000 --- a/.changes/update-gradle.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-cli": patch:enhance -"@tauri-apps/cli": patch:enhance ---- - -Update to latest gradle. diff --git a/.changes/update-plugin-template.md b/.changes/update-plugin-template.md deleted file mode 100644 index d6ca22f44..000000000 --- a/.changes/update-plugin-template.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@tauri-apps/cli": patch:enhance -"tauri-cli": patch:enhance ---- - -Update app and plugin templates following generated files change from tauri-build and tauri-plugin. diff --git a/.changes/update-target-sdk.md b/.changes/update-target-sdk.md deleted file mode 100644 index fa052fdeb..000000000 --- a/.changes/update-target-sdk.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"tauri-cli": patch:changes -"@tauri-apps/cli": patch:changes -"tauri": patch:changes ---- - -Updated Android target SDK to 34. diff --git a/.changes/url-result-runtime.md b/.changes/url-result-runtime.md deleted file mode 100644 index 4407a349b..000000000 --- a/.changes/url-result-runtime.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri-runtime": "patch" -"tauri-runtime-wry": "patch" ---- - -Changed `WebviewDispatch::url` getter to return a result. diff --git a/.changes/url-result.md b/.changes/url-result.md deleted file mode 100644 index 978d2cc81..000000000 --- a/.changes/url-result.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": "patch:breaking" ---- - -Changed `WebviewWindow::url` and `Webview::url` getter to return a result. diff --git a/.changes/utils-bundle-target-all.md b/.changes/utils-bundle-target-all.md deleted file mode 100644 index 3a3e98a4e..000000000 --- a/.changes/utils-bundle-target-all.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri-utils': 'patch:bug' ---- - -Fix `BundleTarget::to_vec` returning an empty vec for `BundleTarget::All` variant. diff --git a/.changes/utils-bundle-type-all.md b/.changes/utils-bundle-type-all.md deleted file mode 100644 index 07906a628..000000000 --- a/.changes/utils-bundle-type-all.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri-utils': 'patch:bug' ---- - -Add `BundleType::all` method to return all possible `BundleType` variants. diff --git a/.changes/utils-compression-option.md b/.changes/utils-compression-option.md deleted file mode 100644 index 9757842eb..000000000 --- a/.changes/utils-compression-option.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-utils": patch:breaking ---- - -Changed `NsisConfig::compression` field from `Option` to just `NsisCompression` \ No newline at end of file diff --git a/.changes/utils-debug-eprintln.md b/.changes/utils-debug-eprintln.md deleted file mode 100644 index 8f1f275fe..000000000 --- a/.changes/utils-debug-eprintln.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri-utils': 'major:breaking' ---- - -Removed `debug_eprintln!` and `consume_unused_variable` macros. diff --git a/.changes/utils-installer-hooks.md b/.changes/utils-installer-hooks.md deleted file mode 100644 index 80988dcdb..000000000 --- a/.changes/utils-installer-hooks.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-utils": "patch:feat" ---- - -Add `installer_hooks` NSIS configuration field diff --git a/.changes/utils-named-capability-file.md b/.changes/utils-named-capability-file.md deleted file mode 100644 index 4510542a0..000000000 --- a/.changes/utils-named-capability-file.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-utils": major:breaking ---- - -Changed `CapabiltyFile::List` enum variant to be a tuple-struct and added `CapabiltyFile::NamedList`. This allows more flexibility when parsing capabilties from JSON files. \ No newline at end of file diff --git a/.changes/utils-remove-asset-trait.md b/.changes/utils-remove-asset-trait.md deleted file mode 100644 index c37e15ae2..000000000 --- a/.changes/utils-remove-asset-trait.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-utils": patch:breaking ---- - -Removed the `assets::Assets` trait which is now part of the `tauri` crate. diff --git a/.changes/utils-sign-command.md b/.changes/utils-sign-command.md deleted file mode 100644 index 67b0e39d7..000000000 --- a/.changes/utils-sign-command.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-utils": "patch:feat" ---- - -Add `sign_command` in `WindowsConfig` diff --git a/.changes/v1-migrate-updater.md b/.changes/v1-migrate-updater.md new file mode 100644 index 000000000..74af5344b --- /dev/null +++ b/.changes/v1-migrate-updater.md @@ -0,0 +1,6 @@ +--- +"tauri-cli": patch:bug +"@tauri-apps/cli": patch:bug +--- + +Migration from v1 to v2 now adds the updater plugin when it is active. diff --git a/.changes/webview-bounds.md b/.changes/webview-bounds.md deleted file mode 100644 index eb0c4db25..000000000 --- a/.changes/webview-bounds.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'tauri': 'minor:feat' ---- - -Add `Webview::bounds` and `Webview::set_bounds` APIs. diff --git a/.changes/webview-builder-on-download.md b/.changes/webview-builder-on-download.md deleted file mode 100644 index b84649bcc..000000000 --- a/.changes/webview-builder-on-download.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": "patch:feat" ---- - -Add `WebviewWindowBuilder::on_download`. diff --git a/.changes/webview-navigate-result.md b/.changes/webview-navigate-result.md deleted file mode 100644 index bf7b1784f..000000000 --- a/.changes/webview-navigate-result.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri": "patch:breaking" ---- - -Changed `WebviewWindow::navigate` and `Webview::navigate` method signature to return a `Result` diff --git a/.changes/windows-rs-0.57.md b/.changes/windows-rs-0.57.md deleted file mode 100644 index ba4898092..000000000 --- a/.changes/windows-rs-0.57.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'tauri': 'patch:deps' -'tauri-runtime': 'patch:deps' -'tauri-runtime-wry': 'patch:deps' ---- - -Update `windows` crate to version `0.57` and `webview2-com` crate to version `0.31` diff --git a/.changes/wry-0.36.md b/.changes/wry-0.36.md deleted file mode 100644 index 7d69500ef..000000000 --- a/.changes/wry-0.36.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-runtime-wry": patch:deps ---- - -Update `wry` to 0.36. diff --git a/.changes/wry-0.37.md b/.changes/wry-0.37.md deleted file mode 100644 index d31f4f498..000000000 --- a/.changes/wry-0.37.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-runtime-wry": patch:deps ---- - -Upgraded to `wry@0.37.0` diff --git a/.changes/wry-0.38.md b/.changes/wry-0.38.md deleted file mode 100644 index dd35e9dee..000000000 --- a/.changes/wry-0.38.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"tauri-runtime-wry": patch:deps ---- - -Upgraded to `wry@0.38.0` diff --git a/.changes/zoom-hotkeys-enabled.md b/.changes/zoom-hotkeys-enabled.md deleted file mode 100644 index ac7a4447f..000000000 --- a/.changes/zoom-hotkeys-enabled.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"@tauri-apps/api": minor:feat -"tauri": minor:feat -"tauri-runtime": minor:feat -"tauri-runtime-wry": minor:feat ---- - -Add `zoom_hotkeys_enabled` to enable browser native zoom controls on creating webviews. diff --git a/.changes/zoom-polyfill.md b/.changes/zoom-polyfill.md deleted file mode 100644 index 88dad403f..000000000 --- a/.changes/zoom-polyfill.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"tauri": minor:feat -"tauri-runtime": minor:feat ---- - -Provide a basic zoom hotkey polyfill for non-Windows platforms diff --git a/.github/workflows/covector-comment-on-fork.yml b/.github/workflows/covector-comment-on-fork.yml new file mode 100644 index 000000000..8995bf030 --- /dev/null +++ b/.github/workflows/covector-comment-on-fork.yml @@ -0,0 +1,30 @@ +# Copyright 2019-2024 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT + +name: covector comment +on: + workflow_run: + workflows: [covector status] # the `name` of the workflow run on `pull_request` running `status` with `comment: true` + types: + - completed + +# note all other permissions are set to none if not specified +# and these set the permissions for `secrets.GITHUB_TOKEN` +permissions: + # to read the action artifacts on `covector status` workflows + actions: read + # to write the comment + pull-requests: write + +jobs: + comment: + runs-on: ubuntu-latest + if: github.event.workflow_run.conclusion == 'success' && + (github.event.workflow_run.head_repository.full_name != github.repository || github.actor == 'dependabot[bot]') + steps: + - name: covector status + uses: jbolda/covector/packages/action@covector-v0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + command: "status" diff --git a/.github/workflows/covector-status.yml b/.github/workflows/covector-status.yml index ea3b84a2b..9b13dc221 100644 --- a/.github/workflows/covector-status.yml +++ b/.github/workflows/covector-status.yml @@ -18,3 +18,5 @@ jobs: id: covector with: command: 'status' + token: ${{ secrets.GITHUB_TOKEN }} + comment: true diff --git a/.github/workflows/covector-version-or-publish.yml b/.github/workflows/covector-version-or-publish.yml index 1add9377b..98149b357 100644 --- a/.github/workflows/covector-version-or-publish.yml +++ b/.github/workflows/covector-version-or-publish.yml @@ -55,6 +55,9 @@ jobs: version-or-publish: runs-on: ubuntu-latest timeout-minutes: 65 + permissions: + contents: write # required for workflow_dispatch + pull-requests: write outputs: change: ${{ steps.covector.outputs.change }} commandRan: ${{ steps.covector.outputs.commandRan }} @@ -87,9 +90,10 @@ jobs: NODE_AUTH_TOKEN: ${{ secrets.ORG_NPM_TOKEN }} CARGO_AUDIT_OPTIONS: ${{ secrets.CARGO_AUDIT_OPTIONS }} with: - token: ${{ secrets.GITHUB_TOKEN }} command: 'version-or-publish' + token: ${{ secrets.GITHUB_TOKEN }} createRelease: true + recognizeContributors: true - name: Create Pull Request With Versions Bumped if: steps.covector.outputs.commandRan == 'version' @@ -116,18 +120,14 @@ jobs: if: | steps.covector.outputs.successfulPublish == 'true' && contains(steps.covector.outputs.packagesPublished, '@tauri-apps/cli') - uses: peter-evans/repository-dispatch@v1 - with: - token: ${{ secrets.ORG_TAURI_BOT_PAT }} - event-type: publish-js-cli - client-payload: >- - {"releaseId": "${{ steps.covector.outputs['-tauri-apps-cli-releaseId'] }}" } + run: gh workflow run 31554138 -r dev -f releaseId=${{ steps.covector.outputs['-tauri-apps-cli-releaseId'] }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Trigger `tauri-cli` publishing workflow if: | steps.covector.outputs.successfulPublish == 'true' && contains(steps.covector.outputs.packagesPublished, 'tauri-cli') - uses: peter-evans/repository-dispatch@v1 - with: - token: ${{ secrets.ORG_TAURI_BOT_PAT }} - event-type: publish-clirs + run: gh workflow run 31554139 -r dev + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.scripts/covector/sync-cli-metadata.js b/.scripts/covector/sync-cli-metadata.js index a8c4a53c2..a490bb8c3 100644 --- a/.scripts/covector/sync-cli-metadata.js +++ b/.scripts/covector/sync-cli-metadata.js @@ -34,6 +34,7 @@ switch (bump) { index = 2 break case 'prerelease': + case 'prepatch': index = 3 break default: diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index bf4b5dd93..fd904023d 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -1,8 +1,8 @@ # The Tauri Architecture -https://tauri.app + -https://github.com/tauri-apps/tauri + ## Introduction @@ -113,9 +113,9 @@ Generally speaking, plugins are authored by third parties (even though there may Here are several examples of Tauri Plugins: -- https://github.com/tauri-apps/tauri-plugin-sql -- https://github.com/tauri-apps/tauri-plugin-stronghold -- https://github.com/tauri-apps/tauri-plugin-authenticator +- +- +- # Workflows diff --git a/Cargo.lock b/Cargo.lock index 7ddbb2b41..b1f709487 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -577,7 +577,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -587,7 +587,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" dependencies = [ "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -620,7 +620,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -631,7 +631,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -729,7 +729,7 @@ checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -898,7 +898,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -972,7 +972,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -1239,7 +1239,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -1318,7 +1318,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -1821,12 +1821,6 @@ dependencies = [ "x11", ] -[[package]] -name = "line-wrap" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd1bc4d24ad230d21fb898d1116b1801d7adfc449d42026475862ab48b11e70e" - [[package]] name = "linked-hash-map" version = "0.5.6" @@ -2241,9 +2235,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.64" +version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ "bitflags 2.5.0", "cfg-if", @@ -2262,7 +2256,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -2282,9 +2276,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.102" +version = "0.9.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" dependencies = [ "cc", "libc", @@ -2396,7 +2390,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -2514,7 +2508,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -2561,7 +2555,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -2584,13 +2578,12 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "plist" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9d34169e64b3c7a80c8621a48adaf44e0cf62c78a9b25dd9dd35f1881a17cf9" +checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "indexmap 2.2.6", - "line-wrap", "quick-xml", "serde", "time", @@ -2691,9 +2684,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -2726,9 +2719,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quick-xml" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" dependencies = [ "memchr", ] @@ -2888,9 +2881,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.5" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -3127,12 +3120,12 @@ dependencies = [ [[package]] name = "schemars_derive" version = "0.8.21" -source = "git+https://github.com/chippers/schemars.git?branch=feat/preserve-description-newlines#8c5441c0f045ff7ae2ccc83fefb9e6f70173bd1b" +source = "git+https://github.com/tauri-apps/schemars.git?branch=feat/preserve-description-newlines#c30f98480e6e4742aa72202d55d5264c6b2e6476" dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -3201,9 +3194,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] @@ -3221,13 +3214,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -3238,16 +3231,17 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" dependencies = [ "itoa 1.0.11", + "memchr", "ryu", "serde", ] @@ -3260,7 +3254,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -3311,7 +3305,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -3470,27 +3464,25 @@ dependencies = [ [[package]] name = "specta" -version = "2.0.0-rc.12" +version = "2.0.0-rc.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3624a07cbde326fdf1ec37cbd39d06a224660fa0199b7db7316f2349583df981" +checksum = "5fd9fd8ec58ec895d2e947a7b431b5c8d2218956a1e378bbfdc3b7414109e2c5" dependencies = [ - "once_cell", "paste", - "serde", "specta-macros", "thiserror", ] [[package]] name = "specta-macros" -version = "2.0.0-rc.10" +version = "2.0.0-rc.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef33e9678ae36993fcbfc46aa29568ef10d32fd54428808759c6a450998c43ec" +checksum = "649713524bd94bb77336b3d2924e3686a88de3cea780a57d45051923d5a5add4" dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.72", ] [[package]] @@ -3576,9 +3568,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -3662,7 +3654,7 @@ checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "tauri" -version = "2.0.0-beta.22" +version = "2.0.0-rc.1" dependencies = [ "anyhow", "bytes", @@ -3731,7 +3723,7 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.0.0-beta.17" +version = "2.0.0-rc.1" dependencies = [ "anyhow", "cargo_toml", @@ -3753,7 +3745,7 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "2.0.0-beta.17" +version = "2.0.0-rc.1" dependencies = [ "base64 0.22.1", "brotli", @@ -3768,7 +3760,7 @@ dependencies = [ "serde", "serde_json", "sha2", - "syn 2.0.66", + "syn 2.0.72", "tauri-utils", "thiserror", "time", @@ -3790,19 +3782,19 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.0.0-beta.17" +version = "2.0.0-rc.1" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", "tauri-codegen", "tauri-utils", ] [[package]] name = "tauri-plugin" -version = "2.0.0-beta.17" +version = "2.0.0-rc.1" dependencies = [ "anyhow", "glob", @@ -3817,7 +3809,7 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.0.0-beta.18" +version = "2.0.0-rc.1" dependencies = [ "dpi", "gtk", @@ -3834,7 +3826,7 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "2.0.0-beta.18" +version = "2.0.0-rc.1" dependencies = [ "cocoa", "gtk", @@ -3857,7 +3849,7 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.0.0-beta.17" +version = "2.0.0-rc.1" dependencies = [ "aes-gcm", "brotli", @@ -3933,22 +3925,22 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -4034,7 +4026,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -4176,7 +4168,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -4354,9 +4346,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -4385,9 +4377,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "uuid" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "getrandom 0.2.15", ] @@ -4497,7 +4489,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", "wasm-bindgen-shared", ] @@ -4531,7 +4523,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4651,7 +4643,7 @@ checksum = "ac1345798ecd8122468840bcdf1b95e5dc6d2206c5e4b0eafa078d061f59c9bc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -4757,7 +4749,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -4768,7 +4760,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 28f3d88c7..fffb35a73 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,4 +48,4 @@ opt-level = "s" # Temporary patch to schemars to preserve newlines in docstrings for our reference docs schemas # See https://github.com/GREsau/schemars/issues/120 for reference [patch.crates-io] -schemars_derive = { git = 'https://github.com/chippers/schemars.git', branch = 'feat/preserve-description-newlines' } \ No newline at end of file +schemars_derive = { git = 'https://github.com/tauri-apps/schemars.git', branch = 'feat/preserve-description-newlines' } diff --git a/README.md b/README.md index 1c02b27ac..b9424065b 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ Thank you to everyone contributing to Tauri! ### Documentation -Documentation in a polyglot system is a tricky proposition. To this end, we prefer to use inline documentation in the Rust & JS source code as much as possible. Check out the hosting repository for the documentation site for further information: https://github.com/tauri-apps/tauri-docs +Documentation in a polyglot system is a tricky proposition. To this end, we prefer to use inline documentation in the Rust & JS source code as much as possible. Check out the hosting repository for the documentation site for further information: ## Partners diff --git a/core/tauri-acl-schema/build.rs b/core/tauri-acl-schema/build.rs index e5f40f80b..8a2f3d1bb 100644 --- a/core/tauri-acl-schema/build.rs +++ b/core/tauri-acl-schema/build.rs @@ -2,33 +2,33 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -use std::{ - error::Error, - fs::File, - io::{BufWriter, Write}, - path::PathBuf, +use std::{error::Error, path::PathBuf}; + +use schemars::schema_for; +use tauri_utils::{ + acl::capability::Capability, + acl::{Permission, Scopes}, + write_if_changed, }; -use schemars::schema::RootSchema; +macro_rules! schema { + ($name:literal, $path:ty) => { + (concat!($name, "-schema.json"), schema_for!($path)) + }; +} pub fn main() -> Result<(), Box> { - let cap_schema = schemars::schema_for!(tauri_utils::acl::capability::Capability); - let perm_schema = schemars::schema_for!(tauri_utils::acl::Permission); - let scope_schema = schemars::schema_for!(tauri_utils::acl::Scopes); + let schemas = [ + schema!("capability", Capability), + schema!("permission", Permission), + schema!("scope", Scopes), + ]; - let crate_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR")?); - - write_schema_file(cap_schema, crate_dir.join("capability-schema.json"))?; - write_schema_file(perm_schema, crate_dir.join("permission-schema.json"))?; - write_schema_file(scope_schema, crate_dir.join("scope-schema.json"))?; - - Ok(()) -} - -fn write_schema_file(schema: RootSchema, outpath: PathBuf) -> Result<(), Box> { - let schema_str = serde_json::to_string_pretty(&schema).unwrap(); - let mut schema_file = BufWriter::new(File::create(outpath)?); - write!(schema_file, "{schema_str}")?; + let out = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR")?); + for (filename, schema) in schemas { + let schema = serde_json::to_string_pretty(&schema)?; + write_if_changed(out.join(filename), schema)?; + } Ok(()) } diff --git a/core/tauri-acl-schema/capability-schema.json b/core/tauri-acl-schema/capability-schema.json index 4f3301c1d..850d4b528 100644 --- a/core/tauri-acl-schema/capability-schema.json +++ b/core/tauri-acl-schema/capability-schema.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Capability", - "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"path:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```", + "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```", "type": "object", "required": [ "identifier", @@ -48,7 +48,7 @@ } }, "permissions": { - "description": "List of permissions attached to this capability.\n\n Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.\n For commands directly implemented in the application itself only `${permission-name}`\n is required.\n\n ## Example\n\n ```json\n [\n \"path:default\",\n \"event:default\",\n \"window:default\",\n \"app:default\",\n \"image:default\",\n \"resources:default\",\n \"menu:default\",\n \"tray:default\",\n \"shell:allow-open\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n }\n ```", + "description": "List of permissions attached to this capability.\n\n Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.\n For commands directly implemented in the application itself only `${permission-name}`\n is required.\n\n ## Example\n\n ```json\n [\n \"core:default\",\n \"shell:allow-open\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n }\n ```", "type": "array", "items": { "$ref": "#/definitions/PermissionEntry" diff --git a/core/tauri-build/CHANGELOG.md b/core/tauri-build/CHANGELOG.md index 8dcfe268b..0a94c8557 100644 --- a/core/tauri-build/CHANGELOG.md +++ b/core/tauri-build/CHANGELOG.md @@ -1,5 +1,42 @@ # Changelog +## \[2.0.0-rc.1] + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-rc.1` +- Upgraded to `tauri-codegen@2.0.0-rc.1` + +## \[2.0.0-rc.0] + +### Dependencies + +- Upgraded to `tauri-codegen@2.0.0-rc.0` +- Upgraded to `tauri-utils@2.0.0-rc.0` + +## \[2.0.0-beta.19] + +### Bug Fixes + +- [`69dcfdfe0`](https://www.github.com/tauri-apps/tauri/commit/69dcfdfe0f3b0570fcf5997267a7200087d5341b) ([#10267](https://www.github.com/tauri-apps/tauri/pull/10267) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix build script rerun-if-changed instruction if Info.plist do not exist next to tauri.conf.json. + +### Dependencies + +- Upgraded to `tauri-codegen@2.0.0-beta.19` +- Upgraded to `tauri-utils@2.0.0-beta.19` + +## \[2.0.0-beta.18] + +### Enhancements + +- [`35110dba2`](https://www.github.com/tauri-apps/tauri/commit/35110dba21d7db0f155c45da58b41c9ca4d5853c) ([#10106](https://www.github.com/tauri-apps/tauri/pull/10106)) Fix delete app data button gone on higher scaling (>= 1.5) + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-beta.18` +- Upgraded to `tauri-codegen@2.0.0-beta.18` +- [`f955f7b49`](https://www.github.com/tauri-apps/tauri/commit/f955f7b4903bcea376c0a8b430736f66c8cebf56) ([#9929](https://www.github.com/tauri-apps/tauri/pull/9929)) Switch from `dirs_next` to `dirs` as `dirs_next` is now unmaintained while `dirs` is + ## \[2.0.0-beta.17] ### Enhancements @@ -374,7 +411,7 @@ - [`52474e47`](https://www.github.com/tauri-apps/tauri/commit/52474e479d695865299d8c8d868fb98b99731020)([#7141](https://www.github.com/tauri-apps/tauri/pull/7141)) Enhance Cargo features check. - [`af937290`](https://www.github.com/tauri-apps/tauri/commit/af93729031565a69d1fde6cf16bea3b9b6e43a65)([#6676](https://www.github.com/tauri-apps/tauri/pull/6676)) On Windows, set `LegalCopyright` and `FileDescription` file properties on the executable from `tauri.bundle.copyright` and `tauri.bundle.shortDescription`, -- [`d2710e9d`](https://www.github.com/tauri-apps/tauri/commit/d2710e9d2e8fd93975ef6494512370faa8cb3b7e)([#6944](https://www.github.com/tauri-apps/tauri/pull/6944)) Unpin `time`, `ignore`, and `winnow` crate versions. Developers now have to pin crates if needed themselves. A list of crates that need pinning to adhere to Tauri's MSRV will be visible in Tauri's GitHub workflow: https://github.com/tauri-apps/tauri/blob/dev/.github/workflows/test-core.yml#L85. +- [`d2710e9d`](https://www.github.com/tauri-apps/tauri/commit/d2710e9d2e8fd93975ef6494512370faa8cb3b7e)([#6944](https://www.github.com/tauri-apps/tauri/pull/6944)) Unpin `time`, `ignore`, and `winnow` crate versions. Developers now have to pin crates if needed themselves. A list of crates that need pinning to adhere to Tauri's MSRV will be visible in Tauri's GitHub workflow: . ## \[1.3.0] diff --git a/core/tauri-build/Cargo.toml b/core/tauri-build/Cargo.toml index ba140d810..e5332127c 100644 --- a/core/tauri-build/Cargo.toml +++ b/core/tauri-build/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tauri-build" -version = "2.0.0-beta.17" +version = "2.0.0-rc.1" description = "build time code to pair with https://crates.io/crates/tauri" exclude = [ "CHANGELOG.md", "/target" ] readme = "README.md" @@ -28,8 +28,8 @@ rustdoc-args = [ "--cfg", "docsrs" ] [dependencies] anyhow = "1" quote = { version = "1", optional = true } -tauri-codegen = { version = "2.0.0-beta.17", path = "../tauri-codegen", optional = true } -tauri-utils = { version = "2.0.0-beta.17", path = "../tauri-utils", features = [ "build", "resources" ] } +tauri-codegen = { version = "2.0.0-rc.1", path = "../tauri-codegen", optional = true } +tauri-utils = { version = "2.0.0-rc.1", path = "../tauri-utils", features = [ "build", "resources" ] } cargo_toml = "0.17" serde = "1" serde_json = "1" diff --git a/core/tauri-build/src/acl.rs b/core/tauri-build/src/acl.rs index 593b41783..219b542d5 100644 --- a/core/tauri-build/src/acl.rs +++ b/core/tauri-build/src/acl.rs @@ -473,10 +473,13 @@ pub fn validate_capabilities( for permission_entry in &capability.permissions { let permission_id = permission_entry.identifier(); - let (key, permission_name) = permission_id - .get() - .split_once(':') - .unwrap_or_else(|| (APP_ACL_KEY, permission_id.get())); + + let key = permission_id.get_prefix().unwrap_or(APP_ACL_KEY); + let permission_name = permission_id.get_base(); + + if key == "core" && permission_name == "default" { + continue; + } let permission_exists = acl_manifests .get(key) diff --git a/core/tauri-build/src/codegen/context.rs b/core/tauri-build/src/codegen/context.rs index 695e8ed73..224857e10 100644 --- a/core/tauri-build/src/codegen/context.rs +++ b/core/tauri-build/src/codegen/context.rs @@ -115,10 +115,12 @@ impl CodegenContext { } #[cfg(target_os = "macos")] - println!( - "cargo:rerun-if-changed={}", - config_parent.join("Info.plist").display() - ); + { + let info_plist_path = config_parent.join("Info.plist"); + if info_plist_path.exists() { + println!("cargo:rerun-if-changed={}", info_plist_path.display()); + } + } let code = context_codegen(ContextData { dev: crate::is_dev(), @@ -129,6 +131,7 @@ impl CodegenContext { root: quote::quote!(::tauri), capabilities: self.capabilities, assets: None, + test: false, })?; // get the full output file path diff --git a/core/tauri-build/src/lib.rs b/core/tauri-build/src/lib.rs index 961f54f57..b29c7baa9 100644 --- a/core/tauri-build/src/lib.rs +++ b/core/tauri-build/src/lib.rs @@ -156,7 +156,7 @@ fn copy_dir(from: &Path, to: &Path) -> Result<()> { // Copies the framework under `{src_dir}/{framework}.framework` to `{dest_dir}/{framework}.framework`. fn copy_framework_from(src_dir: &Path, framework: &str, dest_dir: &Path) -> Result { - let src_name = format!("{}.framework", framework); + let src_name = format!("{framework}.framework"); let src_path = src_dir.join(&src_name); if src_path.exists() { copy_dir(&src_path, &dest_dir.join(&src_name))?; @@ -168,12 +168,8 @@ fn copy_framework_from(src_dir: &Path, framework: &str, dest_dir: &Path) -> Resu // Copies the macOS application bundle frameworks to the target folder fn copy_frameworks(dest_dir: &Path, frameworks: &[String]) -> Result<()> { - std::fs::create_dir_all(dest_dir).with_context(|| { - format!( - "Failed to create frameworks output directory at {:?}", - dest_dir - ) - })?; + std::fs::create_dir_all(dest_dir) + .with_context(|| format!("Failed to create frameworks output directory at {dest_dir:?}"))?; for framework in frameworks.iter() { if framework.ends_with(".framework") { let src_path = PathBuf::from(framework); @@ -469,7 +465,7 @@ pub fn try_build(attributes: Attributes) -> Result<()> { let mut android_package_prefix = String::new(); for (i, w) in s.enumerate() { if i == last { - println!("cargo:rustc-env=TAURI_ANDROID_PACKAGE_NAME_APP_NAME={}", w); + println!("cargo:rustc-env=TAURI_ANDROID_PACKAGE_NAME_APP_NAME={w}"); } else { android_package_prefix.push_str(w); android_package_prefix.push('_'); @@ -605,6 +601,13 @@ pub fn try_build(attributes: Attributes) -> Result<()> { } } + if target_triple.contains("ios") { + println!( + "cargo:rustc-env=IPHONEOS_DEPLOYMENT_TARGET={}", + config.bundle.ios.minimum_system_version + ); + } + if target_triple.contains("windows") { use semver::Version; use tauri_winres::{VersionInfo, WindowsResource}; diff --git a/core/tauri-build/src/mobile.rs b/core/tauri-build/src/mobile.rs index 548de42b7..3c8e7c1cb 100644 --- a/core/tauri-build/src/mobile.rs +++ b/core/tauri-build/src/mobile.rs @@ -55,9 +55,9 @@ dependencies {" app_build_gradle.push_str("\n}"); if let Some(version) = config.version.as_ref() { - app_tauri_properties.push(format!("tauri.android.versionName={}", version)); + app_tauri_properties.push(format!("tauri.android.versionName={version}")); if let Some(version_code) = config.bundle.android.version_code.as_ref() { - app_tauri_properties.push(format!("tauri.android.versionCode={}", version_code)); + app_tauri_properties.push(format!("tauri.android.versionCode={version_code}")); } else if let Ok(version) = Version::parse(version) { let mut version_code = version.major * 1000000 + version.minor * 1000 + version.patch; @@ -76,7 +76,7 @@ dependencies {" )); } - app_tauri_properties.push(format!("tauri.android.versionCode={}", version_code)); + app_tauri_properties.push(format!("tauri.android.versionCode={version_code}")); } } diff --git a/core/tauri-build/src/static_vcruntime.rs b/core/tauri-build/src/static_vcruntime.rs index 833c7d227..e5bc7429c 100644 --- a/core/tauri-build/src/static_vcruntime.rs +++ b/core/tauri-build/src/static_vcruntime.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -// taken from https://github.com/ChrisDenton/static_vcruntime/ +// taken from // we're not using static_vcruntime directly because we want this for debug builds too use std::{env, fs, io::Write, path::Path}; diff --git a/core/tauri-codegen/CHANGELOG.md b/core/tauri-codegen/CHANGELOG.md index 617e0f80b..6cb6ff750 100644 --- a/core/tauri-codegen/CHANGELOG.md +++ b/core/tauri-codegen/CHANGELOG.md @@ -1,5 +1,53 @@ # Changelog +## \[2.0.0-rc.1] + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-rc.1` + +## \[2.0.0-rc.0] + +### Enhancements + +- [`1e0793b68`](https://www.github.com/tauri-apps/tauri/commit/1e0793b6821799829e380c88066b3415cc9006df) ([#10357](https://www.github.com/tauri-apps/tauri/pull/10357)) Enhance `AssetResolver::get` in development mode by reading distDir directly as a fallback to the embedded assets. + +### Bug Fixes + +- [`24445d71d`](https://www.github.com/tauri-apps/tauri/commit/24445d71de92d526d0ccaecb54f13003ddc6f6b4)([#10432](https://www.github.com/tauri-apps/tauri/pull/10432)) Fixes asset resolving when not using the `compression` feature. + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-rc.0` + +## \[2.0.0-beta.19] + +### Bug Fixes + +- [`5d2922985`](https://www.github.com/tauri-apps/tauri/commit/5d2922985801908e4b929a7a0e387806ff02ab89) ([#10268](https://www.github.com/tauri-apps/tauri/pull/10268) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix icon rewriting always triggering build to rerun due to conflicts between file names. + +### What's Changed + +- [`4c239729c`](https://www.github.com/tauri-apps/tauri/commit/4c239729c3e1b899ecbc6793c3682848e8de1729) ([#10167](https://www.github.com/tauri-apps/tauri/pull/10167) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add support for `test = true` in `generate_context!` macro to skip some code generation that could affect some tests, for now it only skips empedding a plist on macOS. + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-beta.19` + +## \[2.0.0-beta.18] + +### New Features + +- [`5b769948a`](https://www.github.com/tauri-apps/tauri/commit/5b769948a81cac333f64c870a470ba6525bd5cd3) ([#9959](https://www.github.com/tauri-apps/tauri/pull/9959)) Add `include_image_codegen` function to help embedding instances of `Image` struct at compile-time in rust to be used with window, menu or tray icons. + +### Bug Fixes + +- [`1f6e478c8`](https://www.github.com/tauri-apps/tauri/commit/1f6e478c842a16219798b9962718e9ddb969c041) ([#9878](https://www.github.com/tauri-apps/tauri/pull/9878)) Fixes Info.plist rewriting always triggering build to rerun. + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-beta.18` + ## \[2.0.0-beta.17] ### What's Changed diff --git a/core/tauri-codegen/Cargo.toml b/core/tauri-codegen/Cargo.toml index 8eefeac91..5dd4d5bab 100644 --- a/core/tauri-codegen/Cargo.toml +++ b/core/tauri-codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tauri-codegen" -version = "2.0.0-beta.17" +version = "2.0.0-rc.1" description = "code generation meant to be consumed inside of `tauri` through `tauri-build` or `tauri-macros`" exclude = [ "CHANGELOG.md", "/target" ] readme = "README.md" @@ -20,7 +20,7 @@ quote = "1" syn = "2" serde = { version = "1", features = [ "derive" ] } serde_json = "1" -tauri-utils = { version = "2.0.0-beta.17", path = "../tauri-utils", features = [ "build" ] } +tauri-utils = { version = "2.0.0-rc.1", path = "../tauri-utils", features = [ "build" ] } thiserror = "1" walkdir = "2" brotli = { version = "3", optional = true, default-features = false, features = [ "std" ] } @@ -37,7 +37,6 @@ plist = "1" time = { version = "0.3", features = [ "parsing", "formatting" ] } [features] -default = [ "compression" ] compression = [ "brotli", "tauri-utils/compression" ] isolation = [ "tauri-utils/isolation" ] config-json5 = [ "tauri-utils/config-json5" ] diff --git a/core/tauri-codegen/src/context.rs b/core/tauri-codegen/src/context.rs index f49d9356a..fd06092f3 100644 --- a/core/tauri-codegen/src/context.rs +++ b/core/tauri-codegen/src/context.rs @@ -7,28 +7,28 @@ use std::convert::identity; use std::path::{Path, PathBuf}; use std::{ffi::OsStr, str::FromStr}; +use crate::{ + embedded_assets::{ + ensure_out_dir, AssetOptions, CspHashes, EmbeddedAssets, EmbeddedAssetsResult, + }, + image::CachedIcon, +}; use base64::Engine; use proc_macro2::TokenStream; use quote::quote; use sha2::{Digest, Sha256}; - use syn::Expr; -use tauri_utils::acl::capability::{Capability, CapabilityFile}; -use tauri_utils::acl::manifest::Manifest; -use tauri_utils::acl::resolved::Resolved; -use tauri_utils::assets::AssetKey; -use tauri_utils::config::{CapabilityEntry, Config, FrontendDist, PatternKind}; -use tauri_utils::html::{ - inject_nonce_token, parse as parse_html, serialize_node as serialize_html_node, NodeRef, +use tauri_utils::{ + acl::capability::{Capability, CapabilityFile}, + acl::manifest::Manifest, + acl::resolved::Resolved, + assets::AssetKey, + config::{CapabilityEntry, Config, FrontendDist, PatternKind}, + html::{inject_nonce_token, parse as parse_html, serialize_node as serialize_html_node, NodeRef}, + platform::Target, + plugin::GLOBAL_API_SCRIPT_FILE_LIST_PATH, + tokens::{map_lit, str_lit}, }; -use tauri_utils::platform::Target; -use tauri_utils::plugin::GLOBAL_API_SCRIPT_FILE_LIST_PATH; -use tauri_utils::tokens::{map_lit, str_lit}; - -use crate::embedded_assets::{ - ensure_out_dir, AssetOptions, CspHashes, EmbeddedAssets, EmbeddedAssetsResult, -}; -use crate::image::{ico_icon, image_icon, png_icon, raw_icon}; const ACL_MANIFESTS_FILE_NAME: &str = "acl-manifests.json"; const CAPABILITIES_FILE_NAME: &str = "capabilities.json"; @@ -43,6 +43,8 @@ pub struct ContextData { pub capabilities: Option>, /// The custom assets implementation pub assets: Option, + /// Skip runtime-only types generation for tests (e.g. embed-plist usage). + pub test: bool, } fn inject_script_hashes(document: &NodeRef, key: &AssetKey, csp_hashes: &mut CspHashes) { @@ -140,8 +142,12 @@ pub fn context_codegen(data: ContextData) -> EmbeddedAssetsResult { root, capabilities: additional_capabilities, assets, + test, } = data; + #[allow(unused_variables)] + let running_tests = test; + let target = std::env::var("TAURI_ENV_TARGET_TRIPLE") .as_deref() .map(Target::from_triple) @@ -183,8 +189,7 @@ pub fn context_codegen(data: ContextData) -> EmbeddedAssetsResult { let assets_path = config_parent.join(path); if !assets_path.exists() { panic!( - "The `frontendDist` configuration is set to `{:?}` but this path doesn't exist", - path + "The `frontendDist` configuration is set to `{path:?}` but this path doesn't exist" ) } EmbeddedAssets::new(assets_path, &options, map_core_assets(&options))? @@ -216,7 +221,8 @@ pub fn context_codegen(data: ContextData) -> EmbeddedAssetsResult { "icons/icon.ico", ); if icon_path.exists() { - ico_icon(&root, &out_dir, &icon_path).map(|i| quote!(::std::option::Option::Some(#i)))? + let icon = CachedIcon::new(&root, &icon_path)?; + quote!(::std::option::Option::Some(#icon)) } else { let icon_path = find_icon( &config, @@ -224,7 +230,8 @@ pub fn context_codegen(data: ContextData) -> EmbeddedAssetsResult { |i| i.ends_with(".png"), "icons/icon.png", ); - png_icon(&root, &out_dir, &icon_path).map(|i| quote!(::std::option::Option::Some(#i)))? + let icon = CachedIcon::new(&root, &icon_path)?; + quote!(::std::option::Option::Some(#icon)) } } else { // handle default window icons for Unix targets @@ -234,7 +241,8 @@ pub fn context_codegen(data: ContextData) -> EmbeddedAssetsResult { |i| i.ends_with(".png"), "icons/icon.png", ); - png_icon(&root, &out_dir, &icon_path).map(|i| quote!(::std::option::Option::Some(#i)))? + let icon = CachedIcon::new(&root, &icon_path)?; + quote!(::std::option::Option::Some(#icon)) } }; @@ -253,7 +261,9 @@ pub fn context_codegen(data: ContextData) -> EmbeddedAssetsResult { "icons/icon.png", ); } - raw_icon(&out_dir, &icon_path)? + + let icon = CachedIcon::new_raw(&root, &icon_path)?; + quote!(::std::option::Option::Some(#icon.to_vec())) } else { quote!(::std::option::Option::None) }; @@ -282,8 +292,8 @@ pub fn context_codegen(data: ContextData) -> EmbeddedAssetsResult { let with_tray_icon_code = if target.is_desktop() { if let Some(tray) = &config.app.tray_icon { let tray_icon_icon_path = config_parent.join(&tray.icon_path); - image_icon(&root, &out_dir, &tray_icon_icon_path) - .map(|i| quote!(context.set_tray_icon(Some(#i));))? + let icon = CachedIcon::new(&root, &tray_icon_icon_path)?; + quote!(context.set_tray_icon(::std::option::Option::Some(#icon));) } else { quote!() } @@ -292,7 +302,7 @@ pub fn context_codegen(data: ContextData) -> EmbeddedAssetsResult { }; #[cfg(target_os = "macos")] - let info_plist = if target == Target::MacOS && dev { + let info_plist = if target == Target::MacOS && dev && !running_tests { let info_plist_path = config_parent.join("Info.plist"); let mut info_plist = if info_plist_path.exists() { plist::Value::from_file(&info_plist_path) @@ -311,8 +321,6 @@ pub fn context_codegen(data: ContextData) -> EmbeddedAssetsResult { } } - let plist_file = out_dir.join("Info.plist"); - let mut plist_contents = std::io::BufWriter::new(Vec::new()); info_plist .to_writer_xml(&mut plist_contents) @@ -320,12 +328,9 @@ pub fn context_codegen(data: ContextData) -> EmbeddedAssetsResult { let plist_contents = String::from_utf8_lossy(&plist_contents.into_inner().unwrap()).into_owned(); - if plist_contents != std::fs::read_to_string(&plist_file).unwrap_or_default() { - std::fs::write(&plist_file, &plist_contents).expect("failed to write Info.plist"); - } - + let plist = crate::Cached::try_from(plist_contents)?; quote!({ - tauri::embed_plist::embed_info_plist!(concat!(std::env!("OUT_DIR"), "/Info.plist")); + tauri::embed_plist::embed_info_plist!(#plist); }) } else { quote!(()) @@ -475,6 +480,15 @@ pub fn context_codegen(data: ContextData) -> EmbeddedAssetsResult { quote!(::std::option::Option::None) }; + let maybe_config_parent_setter = if dev { + let config_parent = config_parent.to_string_lossy(); + quote!({ + context.with_config_parent(#config_parent); + }) + } else { + quote!() + }; + Ok(quote!({ #[allow(unused_mut, clippy::let_and_return)] let mut context = #root::Context::new( @@ -488,7 +502,10 @@ pub fn context_codegen(data: ContextData) -> EmbeddedAssetsResult { #runtime_authority, #plugin_global_api_script ); + #with_tray_icon_code + #maybe_config_parent_setter + context })) } diff --git a/core/tauri-codegen/src/embedded_assets.rs b/core/tauri-codegen/src/embedded_assets.rs index 868635ae2..20b00a105 100644 --- a/core/tauri-codegen/src/embedded_assets.rs +++ b/core/tauri-codegen/src/embedded_assets.rs @@ -8,7 +8,6 @@ use quote::{quote, ToTokens, TokenStreamExt}; use sha2::{Digest, Sha256}; use std::{ collections::HashMap, - fmt::Write, fs::File, path::{Path, PathBuf}, }; @@ -48,7 +47,7 @@ pub enum EmbeddedAssetsError { #[error("invalid prefix {prefix} used while including path {path}")] PrefixInvalid { prefix: PathBuf, path: PathBuf }, - #[error("invalid extension {extension} used for image {path}, must be `ico` or `png`")] + #[error("invalid extension `{extension}` used for image {path}, must be `ico` or `png`")] InvalidImageExtension { extension: PathBuf, path: PathBuf }, #[error("failed to walk directory {path} because {error}")] @@ -341,19 +340,7 @@ impl EmbeddedAssets { std::fs::create_dir_all(&out_dir).map_err(|_| EmbeddedAssetsError::OutDir)?; // get a hash of the input - allows for caching existing files - let hash = { - let mut hasher = crate::vendor::blake3_reference::Hasher::default(); - hasher.update(&input); - - let mut bytes = [0u8; 32]; - hasher.finalize(&mut bytes); - - let mut hex = String::with_capacity(2 * bytes.len()); - for b in bytes { - write!(hex, "{b:02x}").map_err(EmbeddedAssetsError::Hex)?; - } - hex - }; + let hash = crate::checksum(&input).map_err(EmbeddedAssetsError::Hex)?; // use the content hash to determine filename, keep extensions that exist let out_path = if let Some(ext) = path.extension().and_then(|e| e.to_str()) { diff --git a/core/tauri-codegen/src/image.rs b/core/tauri-codegen/src/image.rs index 62adbbca8..49546082a 100644 --- a/core/tauri-codegen/src/image.rs +++ b/core/tauri-codegen/src/image.rs @@ -2,135 +2,117 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -use crate::embedded_assets::{ensure_out_dir, EmbeddedAssetsError, EmbeddedAssetsResult}; -use proc_macro2::{Span, TokenStream}; -use quote::{quote, ToTokens}; -use std::path::Path; -use syn::{punctuated::Punctuated, Ident, PathArguments, PathSegment, Token}; +use crate::{ + embedded_assets::{EmbeddedAssetsError, EmbeddedAssetsResult}, + Cached, +}; +use proc_macro2::TokenStream; +use quote::{quote, ToTokens, TokenStreamExt}; +use std::{ffi::OsStr, io::Cursor, path::Path}; -pub fn include_image_codegen(path: &Path) -> EmbeddedAssetsResult { - let out_dir = ensure_out_dir()?; +/// The format the Icon is consumed as. +pub(crate) enum IconFormat { + /// The image, completely unmodified. + Raw, - let mut segments = Punctuated::new(); - segments.push(PathSegment { - ident: Ident::new("tauri", Span::call_site()), - arguments: PathArguments::None, - }); - let root = syn::Path { - leading_colon: Some(Token![::](Span::call_site())), - segments, - }; - - image_icon(&root.to_token_stream(), &out_dir, path) + /// RGBA raw data, meant to be consumed by [`tauri::image::Image`]. + Image { width: u32, height: u32 }, } -pub(crate) fn image_icon( - root: &TokenStream, - out_dir: &Path, - path: &Path, -) -> EmbeddedAssetsResult { - let extension = path.extension().unwrap_or_default(); - if extension == "ico" { - ico_icon(root, out_dir, path) - } else if extension == "png" { - png_icon(root, out_dir, path) - } else { - Err(EmbeddedAssetsError::InvalidImageExtension { - extension: extension.into(), - path: path.to_path_buf(), +pub struct CachedIcon { + cache: Cached, + format: IconFormat, + root: TokenStream, +} + +impl CachedIcon { + pub fn new(root: &TokenStream, icon: &Path) -> EmbeddedAssetsResult { + match icon.extension().map(OsStr::to_string_lossy).as_deref() { + Some("png") => Self::new_png(root, icon), + Some("ico") => Self::new_ico(root, icon), + unknown => Err(EmbeddedAssetsError::InvalidImageExtension { + extension: unknown.unwrap_or_default().into(), + path: icon.to_path_buf(), + }), + } + } + + /// Cache the icon without any manipulation. + pub fn new_raw(root: &TokenStream, icon: &Path) -> EmbeddedAssetsResult { + let buf = Self::open(icon); + Cached::try_from(buf).map(|cache| Self { + cache, + root: root.clone(), + format: IconFormat::Raw, + }) + } + + /// Cache an ICO icon as RGBA data, see [`ImageFormat::Image`]. + pub fn new_ico(root: &TokenStream, icon: &Path) -> EmbeddedAssetsResult { + let buf = Self::open(icon); + + let icon_dir = ico::IconDir::read(Cursor::new(&buf)) + .unwrap_or_else(|e| panic!("failed to parse icon {}: {}", icon.display(), e)); + + let entry = &icon_dir.entries()[0]; + let rgba = entry + .decode() + .unwrap_or_else(|e| panic!("failed to decode icon {}: {}", icon.display(), e)) + .rgba_data() + .to_vec(); + + Cached::try_from(rgba).map(|cache| Self { + cache, + root: root.clone(), + format: IconFormat::Image { + width: entry.width(), + height: entry.height(), + }, + }) + } + + /// Cache a PNG icon as RGBA data, see [`ImageFormat::Image`]. + pub fn new_png(root: &TokenStream, icon: &Path) -> EmbeddedAssetsResult { + let buf = Self::open(icon); + let decoder = png::Decoder::new(Cursor::new(&buf)); + let mut reader = decoder + .read_info() + .unwrap_or_else(|e| panic!("failed to read icon {}: {}", icon.display(), e)); + + if reader.output_color_type().0 != png::ColorType::Rgba { + panic!("icon {} is not RGBA", icon.display()); + } + + let mut rgba = Vec::with_capacity(reader.output_buffer_size()); + while let Ok(Some(row)) = reader.next_row() { + rgba.extend(row.data()); + } + + Cached::try_from(rgba).map(|cache| Self { + cache, + root: root.clone(), + format: IconFormat::Image { + width: reader.info().width, + height: reader.info().height, + }, + }) + } + + fn open(path: &Path) -> Vec { + std::fs::read(path).unwrap_or_else(|e| panic!("failed to open icon {}: {}", path.display(), e)) + } +} + +impl ToTokens for CachedIcon { + fn to_tokens(&self, tokens: &mut TokenStream) { + let root = &self.root; + let cache = &self.cache; + let raw = quote!(::std::include_bytes!(#cache)); + tokens.append_all(match self.format { + IconFormat::Raw => raw, + IconFormat::Image { width, height } => { + quote!(#root::image::Image::new(#raw, #width, #height)) + } }) } } - -pub(crate) fn raw_icon(out_dir: &Path, path: &Path) -> EmbeddedAssetsResult { - let bytes = - std::fs::read(path).unwrap_or_else(|e| panic!("failed to read icon {}: {}", path.display(), e)); - - let out_path = out_dir.join(path.file_name().unwrap()); - write_if_changed(&out_path, &bytes).map_err(|error| EmbeddedAssetsError::AssetWrite { - path: path.to_owned(), - error, - })?; - - let icon_path = path.file_name().unwrap().to_str().unwrap().to_string(); - let icon = quote!(::std::option::Option::Some( - include_bytes!(concat!(std::env!("OUT_DIR"), "/", #icon_path)).to_vec() - )); - Ok(icon) -} - -pub(crate) fn ico_icon( - root: &TokenStream, - out_dir: &Path, - path: &Path, -) -> EmbeddedAssetsResult { - let file = std::fs::File::open(path) - .unwrap_or_else(|e| panic!("failed to open icon {}: {}", path.display(), e)); - let icon_dir = ico::IconDir::read(file) - .unwrap_or_else(|e| panic!("failed to parse icon {}: {}", path.display(), e)); - let entry = &icon_dir.entries()[0]; - let rgba = entry - .decode() - .unwrap_or_else(|e| panic!("failed to decode icon {}: {}", path.display(), e)) - .rgba_data() - .to_vec(); - let width = entry.width(); - let height = entry.height(); - - let icon_file_name = path.file_name().unwrap(); - let out_path = out_dir.join(icon_file_name); - write_if_changed(&out_path, &rgba).map_err(|error| EmbeddedAssetsError::AssetWrite { - path: path.to_owned(), - error, - })?; - - let icon_file_name = icon_file_name.to_str().unwrap(); - let icon = quote!(#root::image::Image::new(include_bytes!(concat!(std::env!("OUT_DIR"), "/", #icon_file_name)), #width, #height)); - Ok(icon) -} - -pub(crate) fn png_icon( - root: &TokenStream, - out_dir: &Path, - path: &Path, -) -> EmbeddedAssetsResult { - let file = std::fs::File::open(path) - .unwrap_or_else(|e| panic!("failed to open icon {}: {}", path.display(), e)); - let decoder = png::Decoder::new(file); - let mut reader = decoder - .read_info() - .unwrap_or_else(|e| panic!("failed to read icon {}: {}", path.display(), e)); - - let (color_type, _) = reader.output_color_type(); - - if color_type != png::ColorType::Rgba { - panic!("icon {} is not RGBA", path.display()); - } - - let mut buffer: Vec = Vec::new(); - while let Ok(Some(row)) = reader.next_row() { - buffer.extend(row.data()); - } - let width = reader.info().width; - let height = reader.info().height; - - let icon_file_name = path.file_name().unwrap(); - let out_path = out_dir.join(icon_file_name); - write_if_changed(&out_path, &buffer).map_err(|error| EmbeddedAssetsError::AssetWrite { - path: path.to_owned(), - error, - })?; - - let icon_file_name = icon_file_name.to_str().unwrap(); - let icon = quote!(#root::image::Image::new(include_bytes!(concat!(std::env!("OUT_DIR"), "/", #icon_file_name)), #width, #height)); - Ok(icon) -} - -pub(crate) fn write_if_changed(out_path: &Path, data: &[u8]) -> std::io::Result<()> { - if let Ok(curr) = std::fs::read(out_path) { - if curr == data { - return Ok(()); - } - } - std::fs::write(out_path, data) -} diff --git a/core/tauri-codegen/src/lib.rs b/core/tauri-codegen/src/lib.rs index 48a3033fd..67bff21ef 100644 --- a/core/tauri-codegen/src/lib.rs +++ b/core/tauri-codegen/src/lib.rs @@ -13,17 +13,21 @@ )] pub use self::context::{context_codegen, ContextData}; -pub use self::image::include_image_codegen; +use crate::embedded_assets::{ensure_out_dir, EmbeddedAssetsError}; +use proc_macro2::TokenStream; +use quote::{quote, ToTokens, TokenStreamExt}; use std::{ borrow::Cow, + fmt::{self, Write}, path::{Path, PathBuf}, }; pub use tauri_utils::config::{parse::ConfigError, Config}; use tauri_utils::platform::Target; +use tauri_utils::write_if_changed; mod context; pub mod embedded_assets; -mod image; +pub mod image; #[doc(hidden)] pub mod vendor; @@ -97,3 +101,54 @@ pub fn get_config(path: &Path) -> Result<(Config, PathBuf), CodegenConfigError> Ok((config, parent)) } + +/// Create a blake3 checksum of the passed bytes. +fn checksum(bytes: &[u8]) -> Result { + let mut hasher = vendor::blake3_reference::Hasher::default(); + hasher.update(bytes); + + let mut bytes = [0u8; 32]; + hasher.finalize(&mut bytes); + + let mut hex = String::with_capacity(2 * bytes.len()); + for b in bytes { + write!(hex, "{b:02x}")?; + } + Ok(hex) +} + +/// Cache the data to `$OUT_DIR`, only if it does not already exist. +/// +/// Due to using a checksum as the filename, an existing file should be the exact same content +/// as the data being checked. +struct Cached { + checksum: String, +} + +impl TryFrom for Cached { + type Error = EmbeddedAssetsError; + + fn try_from(value: String) -> Result { + Self::try_from(Vec::from(value)) + } +} + +impl TryFrom> for Cached { + type Error = EmbeddedAssetsError; + + fn try_from(content: Vec) -> Result { + let checksum = checksum(content.as_ref()).map_err(EmbeddedAssetsError::Hex)?; + let path = ensure_out_dir()?.join(&checksum); + + write_if_changed(&path, &content) + .map(|_| Self { checksum }) + .map_err(|error| EmbeddedAssetsError::AssetWrite { path, error }) + } +} + +impl ToTokens for Cached { + fn to_tokens(&self, tokens: &mut TokenStream) { + let path = &self.checksum; + tokens.append_all(quote!(::std::concat!(::std::env!("OUT_DIR"), "/", #path))) + } +} diff --git a/core/tauri-config-schema/build.rs b/core/tauri-config-schema/build.rs index cfb52844c..d9afa67a9 100644 --- a/core/tauri-config-schema/build.rs +++ b/core/tauri-config-schema/build.rs @@ -2,23 +2,15 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -use std::{ - error::Error, - fs::File, - io::{BufWriter, Write}, - path::PathBuf, -}; +use std::{error::Error, path::PathBuf}; +use tauri_utils::{config::Config, write_if_changed}; pub fn main() -> Result<(), Box> { - let schema = schemars::schema_for!(tauri_utils::config::Config); - let schema_str = serde_json::to_string_pretty(&schema).unwrap(); - let crate_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR")?); - for file in [ - crate_dir.join("schema.json"), - crate_dir.join("../../tooling/cli/schema.json"), - ] { - let mut schema_file = BufWriter::new(File::create(file)?); - write!(schema_file, "{schema_str}")?; + let schema = schemars::schema_for!(Config); + let schema = serde_json::to_string_pretty(&schema)?; + let out = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR")?); + for path in ["schema.json", "../../tooling/cli/schema.json"] { + write_if_changed(out.join(path), &schema)?; } Ok(()) diff --git a/core/tauri-config-schema/schema.json b/core/tauri-config-schema/schema.json index 4c0b2b26d..e5cdd19ab 100644 --- a/core/tauri-config-schema/schema.json +++ b/core/tauri-config-schema/schema.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Config", - "description": "The Tauri configuration object.\n It is read from a file where you can define your frontend assets,\n configure the bundler and define a tray icon.\n\n The configuration file is generated by the\n [`tauri init`](https://tauri.app/v1/api/cli#init) command that lives in\n your Tauri application source directory (src-tauri).\n\n Once generated, you may modify it at will to customize your Tauri application.\n\n ## File Formats\n\n By default, the configuration is defined as a JSON file named `tauri.conf.json`.\n\n Tauri also supports JSON5 and TOML files via the `config-json5` and `config-toml` Cargo features, respectively.\n The JSON5 file name must be either `tauri.conf.json` or `tauri.conf.json5`.\n The TOML file name is `Tauri.toml`.\n\n ## Platform-Specific Configuration\n\n In addition to the default configuration file, Tauri can\n read a platform-specific configuration from `tauri.linux.conf.json`,\n `tauri.windows.conf.json`, `tauri.macos.conf.json`, `tauri.android.conf.json` and `tauri.ios.conf.json`\n (or `Tauri.linux.toml`, `Tauri.windows.toml`, `Tauri.macos.toml`, `Tauri.android.toml` and `Tauri.ios.toml` if the `Tauri.toml` format is used),\n which gets merged with the main configuration object.\n\n ## Configuration Structure\n\n The configuration is composed of the following objects:\n\n - [`app`](#appconfig): The Tauri configuration\n - [`build`](#buildconfig): The build configuration\n - [`bundle`](#bundleconfig): The bundle configurations\n - [`plugins`](#pluginconfig): The plugins configuration\n\n ```json title=\"Example tauri.config.json file\"\n {\n \"productName\": \"tauri-app\",\n \"version\": \"0.1.0\"\n \"build\": {\n \"beforeBuildCommand\": \"\",\n \"beforeDevCommand\": \"\",\n \"devUrl\": \"../dist\",\n \"frontendDist\": \"../dist\"\n },\n \"app\": {\n \"security\": {\n \"csp\": null\n },\n \"windows\": [\n {\n \"fullscreen\": false,\n \"height\": 600,\n \"resizable\": true,\n \"title\": \"Tauri App\",\n \"width\": 800\n }\n ]\n },\n \"bundle\": {},\n \"plugins\": {}\n }\n ```", + "description": "The Tauri configuration object.\n It is read from a file where you can define your frontend assets,\n configure the bundler and define a tray icon.\n\n The configuration file is generated by the\n [`tauri init`](https://tauri.app/v1/api/cli#init) command that lives in\n your Tauri application source directory (src-tauri).\n\n Once generated, you may modify it at will to customize your Tauri application.\n\n ## File Formats\n\n By default, the configuration is defined as a JSON file named `tauri.conf.json`.\n\n Tauri also supports JSON5 and TOML files via the `config-json5` and `config-toml` Cargo features, respectively.\n The JSON5 file name must be either `tauri.conf.json` or `tauri.conf.json5`.\n The TOML file name is `Tauri.toml`.\n\n ## Platform-Specific Configuration\n\n In addition to the default configuration file, Tauri can\n read a platform-specific configuration from `tauri.linux.conf.json`,\n `tauri.windows.conf.json`, `tauri.macos.conf.json`, `tauri.android.conf.json` and `tauri.ios.conf.json`\n (or `Tauri.linux.toml`, `Tauri.windows.toml`, `Tauri.macos.toml`, `Tauri.android.toml` and `Tauri.ios.toml` if the `Tauri.toml` format is used),\n which gets merged with the main configuration object.\n\n ## Configuration Structure\n\n The configuration is composed of the following objects:\n\n - [`app`](#appconfig): The Tauri configuration\n - [`build`](#buildconfig): The build configuration\n - [`bundle`](#bundleconfig): The bundle configurations\n - [`plugins`](#pluginconfig): The plugins configuration\n\n ```json title=\"Example tauri.config.json file\"\n {\n \"productName\": \"tauri-app\",\n \"version\": \"0.1.0\",\n \"build\": {\n \"beforeBuildCommand\": \"\",\n \"beforeDevCommand\": \"\",\n \"devUrl\": \"../dist\",\n \"frontendDist\": \"../dist\"\n },\n \"app\": {\n \"security\": {\n \"csp\": null\n },\n \"windows\": [\n {\n \"fullscreen\": false,\n \"height\": 600,\n \"resizable\": true,\n \"title\": \"Tauri App\",\n \"width\": 800\n }\n ]\n },\n \"bundle\": {},\n \"plugins\": {}\n }\n ```", "type": "object", "properties": { "$schema": { @@ -34,6 +34,7 @@ "app": { "description": "The App configuration.", "default": { + "enableGTKAppId": false, "macOSPrivateApi": false, "security": { "assetProtocol": { @@ -73,7 +74,9 @@ "minSdkVersion": 24 }, "createUpdaterArtifacts": false, - "iOS": {}, + "iOS": { + "minimumSystemVersion": "" + }, "icon": [], "linux": { "appimage": { @@ -195,6 +198,11 @@ "description": "Whether we should inject the Tauri API on `window.__TAURI__` or not.", "default": false, "type": "boolean" + }, + "enableGTKAppId": { + "description": "If set to true \"identifier\" will be set as GTK app ID (on systems that use GTK).", + "default": false, + "type": "boolean" } }, "additionalProperties": false @@ -430,7 +438,7 @@ ] }, "shadow": { - "description": "Whether or not the window has shadow.\n\n ## Platform-specific\n\n - **Windows:**\n - `false` has no effect on decorated window, shadow are always ON.\n - `true` will make ndecorated window have a 1px white border,\n and on Windows 11, it will have a rounded corners.\n - **Linux:** Unsupported.", + "description": "Whether or not the window has shadow.\n\n ## Platform-specific\n\n - **Windows:**\n - `false` has no effect on decorated window, shadow are always ON.\n - `true` will make undecorated window have a 1px white border,\n and on Windows 11, it will have a rounded corners.\n - **Linux:** Unsupported.", "default": true, "type": "boolean" }, @@ -1127,7 +1135,7 @@ ] }, "Capability": { - "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"path:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```", + "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```", "type": "object", "required": [ "identifier", @@ -1174,7 +1182,7 @@ } }, "permissions": { - "description": "List of permissions attached to this capability.\n\n Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.\n For commands directly implemented in the application itself only `${permission-name}`\n is required.\n\n ## Example\n\n ```json\n [\n \"path:default\",\n \"event:default\",\n \"window:default\",\n \"app:default\",\n \"image:default\",\n \"resources:default\",\n \"menu:default\",\n \"tray:default\",\n \"shell:allow-open\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n }\n ```", + "description": "List of permissions attached to this capability.\n\n Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.\n For commands directly implemented in the application itself only `${permission-name}`\n is required.\n\n ## Example\n\n ```json\n [\n \"core:default\",\n \"shell:allow-open\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n }\n ```", "type": "array", "items": { "$ref": "#/definitions/PermissionEntry" @@ -1757,7 +1765,9 @@ }, "iOS": { "description": "iOS configuration.", - "default": {}, + "default": { + "minimumSystemVersion": "" + }, "allOf": [ { "$ref": "#/definitions/IosConfig" @@ -2398,7 +2408,7 @@ ] }, "installerHooks": { - "description": "A path to a `.nsh` file that contains special NSIS macros to be hooked into the\n main installer.nsi script.\n\n Supported hooks are:\n - `NSIS_HOOK_PREINSTALL`: This hook runs before copying files, setting registry key values and creating shortcuts.\n - `NSIS_HOOK_POSTINSTALL`: This hook runs after the installer has finished copying all files, setting the registry keys and created shortcuts.\n - `NSIS_HOOK_PREUNINSTALL`: This hook runs before removing any files, registry keys and shortcuts.\n - `NSIS_HOOK_POSTUNINSTALL`: This hook runs after files, registry keys and shortcuts have been removed.\n\n\n ### Example\n\n ```nsh\n !define NSIS_HOOK_PREINSTALL \"NSIS_HOOK_PREINSTALL_\"\n !macro NSIS_HOOK_PREINSTALL_\n MessageBox MB_OK \"PreInstall\"\n !macroend\n\n !define NSIS_HOOK_POSTINSTALL \"NSIS_HOOK_POSTINSTALL_\"\n !macro NSIS_HOOK_POSTINSTALL_\n MessageBox MB_OK \"PostInstall\"\n !macroend\n\n !define NSIS_HOOK_PREUNINSTALL \"NSIS_HOOK_PREUNINSTALL_\"\n !macro NSIS_HOOK_PREUNINSTALL_\n MessageBox MB_OK \"PreUnInstall\"\n !macroend\n\n !define NSIS_HOOK_POSTUNINSTALL \"NSIS_HOOK_POSTUNINSTALL_\"\n !macro NSIS_HOOK_POSTUNINSTALL_\n MessageBox MB_OK \"PostUninstall\"\n !macroend\n\n ```", + "description": "A path to a `.nsh` file that contains special NSIS macros to be hooked into the\n main installer.nsi script.\n\n Supported hooks are:\n - `NSIS_HOOK_PREINSTALL`: This hook runs before copying files, setting registry key values and creating shortcuts.\n - `NSIS_HOOK_POSTINSTALL`: This hook runs after the installer has finished copying all files, setting the registry keys and created shortcuts.\n - `NSIS_HOOK_PREUNINSTALL`: This hook runs before removing any files, registry keys and shortcuts.\n - `NSIS_HOOK_POSTUNINSTALL`: This hook runs after files, registry keys and shortcuts have been removed.\n\n\n ### Example\n\n ```nsh\n !macro NSIS_HOOK_PREINSTALL\n MessageBox MB_OK \"PreInstall\"\n !macroend\n\n !macro NSIS_HOOK_POSTINSTALL\n MessageBox MB_OK \"PostInstall\"\n !macroend\n\n !macro NSIS_HOOK_PREUNINSTALL\n MessageBox MB_OK \"PreUnInstall\"\n !macroend\n\n !macro NSIS_HOOK_POSTUNINSTALL\n MessageBox MB_OK \"PostUninstall\"\n !macroend\n\n ```", "type": [ "string", "null" @@ -2596,7 +2606,7 @@ ] }, "changelog": { - "description": "Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See\n https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes", + "description": "Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See\n ", "type": [ "string", "null" @@ -2610,28 +2620,28 @@ ] }, "preInstallScript": { - "description": "Path to script that will be executed before the package is unpacked. See\n https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html", + "description": "Path to script that will be executed before the package is unpacked. See\n ", "type": [ "string", "null" ] }, "postInstallScript": { - "description": "Path to script that will be executed after the package is unpacked. See\n https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html", + "description": "Path to script that will be executed after the package is unpacked. See\n ", "type": [ "string", "null" ] }, "preRemoveScript": { - "description": "Path to script that will be executed before the package is removed. See\n https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html", + "description": "Path to script that will be executed before the package is removed. See\n ", "type": [ "string", "null" ] }, "postRemoveScript": { - "description": "Path to script that will be executed after the package is removed. See\n https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html", + "description": "Path to script that will be executed after the package is removed. See\n ", "type": [ "string", "null" @@ -2712,28 +2722,28 @@ ] }, "preInstallScript": { - "description": "Path to script that will be executed before the package is unpacked. See\n http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html", + "description": "Path to script that will be executed before the package is unpacked. See\n ", "type": [ "string", "null" ] }, "postInstallScript": { - "description": "Path to script that will be executed after the package is unpacked. See\n http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html", + "description": "Path to script that will be executed after the package is unpacked. See\n ", "type": [ "string", "null" ] }, "preRemoveScript": { - "description": "Path to script that will be executed before the package is removed. See\n http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html", + "description": "Path to script that will be executed before the package is removed. See\n ", "type": [ "string", "null" ] }, "postRemoveScript": { - "description": "Path to script that will be executed after the package is removed. See\n http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html", + "description": "Path to script that will be executed after the package is removed. See\n ", "type": [ "string", "null" @@ -2941,12 +2951,34 @@ "description": "General configuration for the iOS target.", "type": "object", "properties": { + "template": { + "description": "A custom [XcodeGen] project.yml template to use.\n\n [XcodeGen]: ", + "type": [ + "string", + "null" + ] + }, + "frameworks": { + "description": "A list of strings indicating any iOS frameworks that need to be bundled with the application.\n\n Note that you need to recreate the iOS project for the changes to be applied.", + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, "developmentTeam": { "description": "The development team. This value is required for iOS development because code signing is enforced.\n The `APPLE_DEVELOPMENT_TEAM` environment variable can be set to overwrite it.", "type": [ "string", "null" ] + }, + "minimumSystemVersion": { + "description": "A version string indicating the minimum iOS version that the bundled application supports. Defaults to `13.0`.\n\n Maps to the IPHONEOS_DEPLOYMENT_TARGET value.", + "default": "13.0", + "type": "string" } }, "additionalProperties": false diff --git a/core/tauri-macros/CHANGELOG.md b/core/tauri-macros/CHANGELOG.md index b64048ab2..e50b78fb7 100644 --- a/core/tauri-macros/CHANGELOG.md +++ b/core/tauri-macros/CHANGELOG.md @@ -1,5 +1,41 @@ # Changelog +## \[2.0.0-rc.1] + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-rc.1` +- Upgraded to `tauri-codegen@2.0.0-rc.1` + +## \[2.0.0-rc.0] + +### Dependencies + +- Upgraded to `tauri-codegen@2.0.0-rc.0` +- Upgraded to `tauri-utils@2.0.0-rc.0` + +## \[2.0.0-beta.19] + +### What's Changed + +- [`4c239729c`](https://www.github.com/tauri-apps/tauri/commit/4c239729c3e1b899ecbc6793c3682848e8de1729) ([#10167](https://www.github.com/tauri-apps/tauri/pull/10167) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add support for `test = true` in `generate_context!` macro to skip some code generation that could affect some tests, for now it only skips empedding a plist on macOS. + +### Dependencies + +- Upgraded to `tauri-codegen@2.0.0-beta.19` +- Upgraded to `tauri-utils@2.0.0-beta.19` + +## \[2.0.0-beta.18] + +### New Features + +- [`5b769948a`](https://www.github.com/tauri-apps/tauri/commit/5b769948a81cac333f64c870a470ba6525bd5cd3) ([#9959](https://www.github.com/tauri-apps/tauri/pull/9959)) Add `include_image` macro to help embedding instances of `Image` struct at compile-time in rust to be used with window, menu or tray icons. + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-beta.18` +- Upgraded to `tauri-codegen@2.0.0-beta.18` + ## \[2.0.0-beta.17] ### Dependencies @@ -405,7 +441,7 @@ - `ring` -> `getrandom` -See https://github.com/tauri-apps/tauri/pull/3773 for more information about +See for more information about these specific choices. - [8661e3e2](https://www.github.com/tauri-apps/tauri/commit/8661e3e24d96c399bfbcdee5d8e9d6beba2265a7) replace dependencies with long build times when used together (closes [#3571](https://www.github.com/tauri-apps/tauri/pull/3571)) ([#3773](https://www.github.com/tauri-apps/tauri/pull/3773)) on 2022-03-27 diff --git a/core/tauri-macros/Cargo.toml b/core/tauri-macros/Cargo.toml index 42c68b0eb..645e5d31a 100644 --- a/core/tauri-macros/Cargo.toml +++ b/core/tauri-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tauri-macros" -version = "2.0.0-beta.17" +version = "2.0.0-rc.1" description = "Macros for the tauri crate." exclude = [ "CHANGELOG.md", "/target" ] readme = "README.md" @@ -20,8 +20,8 @@ proc-macro2 = { version = "1", features = [ "span-locations" ] } quote = "1" syn = { version = "2", features = [ "full" ] } heck = "0.5" -tauri-codegen = { version = "2.0.0-beta.17", default-features = false, path = "../tauri-codegen" } -tauri-utils = { version = "2.0.0-beta.17", path = "../tauri-utils" } +tauri-codegen = { version = "2.0.0-rc.1", default-features = false, path = "../tauri-codegen" } +tauri-utils = { version = "2.0.0-rc.1", path = "../tauri-utils" } [features] custom-protocol = [ ] diff --git a/core/tauri-macros/src/context.rs b/core/tauri-macros/src/context.rs index 9b166919b..9469ea17f 100644 --- a/core/tauri-macros/src/context.rs +++ b/core/tauri-macros/src/context.rs @@ -8,7 +8,7 @@ use std::path::PathBuf; use syn::{ parse::{Parse, ParseBuffer}, punctuated::Punctuated, - Expr, ExprLit, Lit, LitStr, Meta, PathArguments, PathSegment, Token, + Expr, ExprLit, Lit, LitBool, LitStr, Meta, PathArguments, PathSegment, Token, }; use tauri_codegen::{context_codegen, get_config, ContextData}; use tauri_utils::{config::parse::does_supported_file_name_exist, platform::Target}; @@ -18,6 +18,7 @@ pub(crate) struct ContextItems { root: syn::Path, capabilities: Option>, assets: Option, + test: bool, } impl Parse for ContextItems { @@ -31,6 +32,7 @@ impl Parse for ContextItems { let mut root = None; let mut capabilities = None; let mut assets = None; + let mut test = false; let config_file = input.parse::().ok().map(|raw| { let _ = input.parse::(); let path = PathBuf::from(raw.value()); @@ -93,6 +95,17 @@ impl Parse for ContextItems { "assets" => { assets.replace(v.value); } + "test" => { + if let Expr::Lit(ExprLit { + lit: Lit::Bool(LitBool { value, .. }), + .. + }) = v.value + { + test = value; + } else { + return Err(syn::Error::new(input.span(), "unexpected value for test")); + } + } name => { return Err(syn::Error::new( input.span(), @@ -105,6 +118,8 @@ impl Parse for ContextItems { return Err(syn::Error::new(input.span(), "unexpected list input")); } } + + let _ = input.parse::(); } Ok(Self { @@ -128,6 +143,7 @@ impl Parse for ContextItems { }), capabilities, assets, + test, }) } } @@ -142,6 +158,7 @@ pub(crate) fn generate_context(context: ContextItems) -> TokenStream { root: context.root.to_token_stream(), capabilities: context.capabilities, assets: context.assets, + test: context.test, }) .and_then(|data| context_codegen(data).map_err(|e| e.to_string())); diff --git a/core/tauri-macros/src/lib.rs b/core/tauri-macros/src/lib.rs index a8b9585e5..89e5b83fe 100644 --- a/core/tauri-macros/src/lib.rs +++ b/core/tauri-macros/src/lib.rs @@ -15,8 +15,9 @@ use std::path::PathBuf; use crate::context::ContextItems; use proc_macro::TokenStream; -use quote::quote; +use quote::{quote, ToTokens}; use syn::{parse2, parse_macro_input, LitStr}; +use tauri_codegen::image::CachedIcon; mod command; mod menu; @@ -109,7 +110,7 @@ pub fn default_runtime(attributes: TokenStream, input: TokenStream) -> TokenStre /// ``` /// but you can't have mixed negations and positive kinds. /// ```ignore -/// do_menu_item!(resources_table, rid, kind, |i| i.set_text(text), !Check | Submeun); +/// do_menu_item!(resources_table, rid, kind, |i| i.set_text(text), !Check | Submenu); /// ``` /// /// #### Example @@ -203,8 +204,9 @@ pub fn include_image(tokens: TokenStream) -> TokenStream { ); return quote!(compile_error!(#error_string)).into(); } - match tauri_codegen::include_image_codegen(&resolved_path).map_err(|error| error.to_string()) { - Ok(output) => output, + + match CachedIcon::new("e!(::tauri), &resolved_path).map_err(|error| error.to_string()) { + Ok(icon) => icon.into_token_stream(), Err(error) => quote!(compile_error!(#error)), } .into() diff --git a/core/tauri-macros/src/mobile.rs b/core/tauri-macros/src/mobile.rs index 99d1e0c77..09e9af1f0 100644 --- a/core/tauri-macros/src/mobile.rs +++ b/core/tauri-macros/src/mobile.rs @@ -76,6 +76,7 @@ pub fn entry_point(_attributes: TokenStream, item: TokenStream) -> TokenStream { stop_unwind(#function_name); } + // be careful when renaming this, the `start_app` symbol is checked by the CLI #[cfg(not(target_os = "android"))] #[no_mangle] #[inline(never)] diff --git a/core/tauri-plugin/CHANGELOG.md b/core/tauri-plugin/CHANGELOG.md index f9b7a0caf..ecb75ae3a 100644 --- a/core/tauri-plugin/CHANGELOG.md +++ b/core/tauri-plugin/CHANGELOG.md @@ -1,5 +1,34 @@ # Changelog +## \[2.0.0-rc.1] + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-rc.1` + +## \[2.0.0-rc.0] + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-rc.0` + +### Breaking Changes + +- [`758d28c8a`](https://www.github.com/tauri-apps/tauri/commit/758d28c8a2d5c9567158e339326b765f72da983e) ([#10390](https://www.github.com/tauri-apps/tauri/pull/10390)) Core plugin permissions are now prefixed with `core:`, the `core:default` permission set can now be used and the `core` plugin name is reserved. + The `tauri migrate` tool will automate the migration process, which involves prefixing all `app`, `event`, `image`, `menu`, `path`, `resources`, `tray`, `webview` and `window` permissions with `core:`. + +## \[2.0.0-beta.19] + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-beta.19` + +## \[2.0.0-beta.18] + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-beta.18` + ## \[2.0.0-beta.17] ### New Features diff --git a/core/tauri-plugin/Cargo.toml b/core/tauri-plugin/Cargo.toml index eac3c53b8..d3ded6790 100644 --- a/core/tauri-plugin/Cargo.toml +++ b/core/tauri-plugin/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tauri-plugin" -version = "2.0.0-beta.17" +version = "2.0.0-rc.1" description = "Build script and runtime Tauri plugin definitions" authors = { workspace = true } homepage = { workspace = true } @@ -30,7 +30,7 @@ runtime = [ ] [dependencies] anyhow = { version = "1", optional = true } serde = { version = "1", optional = true } -tauri-utils = { version = "2.0.0-beta.17", default-features = false, features = [ "build" ], path = "../tauri-utils" } +tauri-utils = { version = "2.0.0-rc.1", default-features = false, features = [ "build" ], path = "../tauri-utils" } serde_json = { version = "1", optional = true } glob = { version = "0.3", optional = true } toml = { version = "0.8", optional = true } diff --git a/core/tauri-plugin/src/build/mod.rs b/core/tauri-plugin/src/build/mod.rs index a9e498f27..fda9eb5f5 100644 --- a/core/tauri-plugin/src/build/mod.rs +++ b/core/tauri-plugin/src/build/mod.rs @@ -13,6 +13,8 @@ use serde::de::DeserializeOwned; use std::{env::var, io::Cursor}; +const RESERVED_PLUGIN_NAMES: &[&str] = &["core", "tauri"]; + pub fn plugin_config(name: &str) -> Option { let config_env_var_name = format!( "TAURI_{}_PLUGIN_CONFIG", @@ -93,6 +95,9 @@ impl<'a> Builder<'a> { if name.contains('_') { anyhow::bail!("plugin names cannot contain underscores"); } + if RESERVED_PLUGIN_NAMES.contains(&name.as_str()) { + anyhow::bail!("plugin name `{name}` is reserved"); + } let out_dir = PathBuf::from(build_var("OUT_DIR")?); @@ -124,7 +129,7 @@ impl<'a> Builder<'a> { acl::build::generate_docs( &permissions, &autogenerated, - &name.strip_prefix("tauri-plugin-").unwrap_or(&name), + name.strip_prefix("tauri-plugin-").unwrap_or(&name), )?; } diff --git a/core/tauri-runtime-wry/CHANGELOG.md b/core/tauri-runtime-wry/CHANGELOG.md index 336da4263..0e7fd809c 100644 --- a/core/tauri-runtime-wry/CHANGELOG.md +++ b/core/tauri-runtime-wry/CHANGELOG.md @@ -1,5 +1,61 @@ # Changelog +## \[2.0.0-rc.1] + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-rc.1` +- Upgraded to `tauri-runtime@2.0.0-rc.1` + +## \[2.0.0-rc.0] + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-rc.0` +- Upgraded to `tauri-runtime@2.0.0-rc.0` + +## \[2.0.0-beta.21] + +### What's Changed + +- [`9546548ec`](https://www.github.com/tauri-apps/tauri/commit/9546548ec0c83ba620b1bc9d1d424a7009d0b423) ([#10297](https://www.github.com/tauri-apps/tauri/pull/10297) by [@pewsheen](https://www.github.com/tauri-apps/tauri/../../pewsheen)) On macOS, set default titlebar style to `Visible` to prevent webview move out of the view. +- [`da25f7353`](https://www.github.com/tauri-apps/tauri/commit/da25f7353070477ba969851e974379d7666d6806) ([#10242](https://www.github.com/tauri-apps/tauri/pull/10242) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `inner_size_constraints` method on `WindowBuilder` trait and `set_size_constraints` method on `WindowDispatch` trait. + +### Dependencies + +- Upgraded to `tauri-runtime@2.0.0-beta.21` + +## \[2.0.0-beta.20] + +### Bug Fixes + +- [`afb102c59`](https://www.github.com/tauri-apps/tauri/commit/afb102c59ba0de27e330589269001e0d2a01576d) ([#10211](https://www.github.com/tauri-apps/tauri/pull/10211) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix window edge not working after setting resizable false and decorated false dynamically + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-beta.19` +- Upgraded to `tauri-runtime@2.0.0-beta.20` + +## \[2.0.0-beta.19] + +### Bug Fixes + +- [`f29b78811`](https://www.github.com/tauri-apps/tauri/commit/f29b78811080bc8313459f34545152d939c62bf6) ([#9862](https://www.github.com/tauri-apps/tauri/pull/9862)) On Windows, handle resizing undecorated windows natively which improves performance and fixes a couple of annoyances with previous JS implementation: + + - No more cursor flickering when moving the cursor across an edge. + - Can resize from top even when `data-tauri-drag-region` element exists there. + - Upon starting rezing, clicks don't go through elements behind it so no longer accidental clicks. + +### What's Changed + +- [`669b9c6b5`](https://www.github.com/tauri-apps/tauri/commit/669b9c6b5af791129b77ee440dacaa98288c906b) ([#9621](https://www.github.com/tauri-apps/tauri/pull/9621)) Set the gtk application to the identifier defined in `tauri.conf.json` to ensure the app uniqueness. + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-beta.18` +- Upgraded to `tauri-runtime@2.0.0-beta.19` +- [`d4c908cfb`](https://www.github.com/tauri-apps/tauri/commit/d4c908cfb8c567abdaf99b85f65f482ea81967e5) ([#10048](https://www.github.com/tauri-apps/tauri/pull/10048)) Update `windows` crate to version `0.57` and `webview2-com` crate to version `0.31` + ## \[2.0.0-beta.18] ### Enhancements diff --git a/core/tauri-runtime-wry/Cargo.toml b/core/tauri-runtime-wry/Cargo.toml index efebd6757..c3090c7f9 100644 --- a/core/tauri-runtime-wry/Cargo.toml +++ b/core/tauri-runtime-wry/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tauri-runtime-wry" -version = "2.0.0-beta.18" +version = "2.0.0-rc.1" description = "Wry bindings to the Tauri runtime" exclude = [ "CHANGELOG.md", "/target" ] readme = "README.md" @@ -15,8 +15,8 @@ rust-version = { workspace = true } [dependencies] wry = { version = "0.41", default-features = false, features = [ "drag-drop", "protocol", "os-webview" ] } tao = { version = "0.28.1", default-features = false, features = [ "rwh_06" ] } -tauri-runtime = { version = "2.0.0-beta.18", path = "../tauri-runtime" } -tauri-utils = { version = "2.0.0-beta.17", path = "../tauri-utils" } +tauri-runtime = { version = "2.0.0-rc.1", path = "../tauri-runtime" } +tauri-utils = { version = "2.0.0-rc.1", path = "../tauri-utils" } raw-window-handle = "0.6" http = "1.1" url = "2" diff --git a/core/tauri-runtime-wry/README.md b/core/tauri-runtime-wry/README.md index 3b0e7cae8..afc8fe20f 100644 --- a/core/tauri-runtime-wry/README.md +++ b/core/tauri-runtime-wry/README.md @@ -24,6 +24,8 @@ Tauri apps can have custom menus and have tray-type interfaces. They can be upda ## This module This crate opens up direct systems-level interactions specifically for WRY, such as printing, monitor detection, and other windowing related tasks. `tauri-runtime` implementation for WRY. +None of the exposed API of this crate is stable, and it may break semver +compatibility in the future. The major version only signifies the intended Tauri version. To learn more about the details of how all of these pieces fit together, please consult this [ARCHITECTURE.md](https://github.com/tauri-apps/tauri/blob/dev/ARCHITECTURE.md) document. diff --git a/core/tauri-runtime-wry/src/lib.rs b/core/tauri-runtime-wry/src/lib.rs index ca460d327..66fd64e7a 100644 --- a/core/tauri-runtime-wry/src/lib.rs +++ b/core/tauri-runtime-wry/src/lib.rs @@ -5,6 +5,9 @@ //! [![](https://github.com/tauri-apps/tauri/raw/dev/.github/splash.png)](https://tauri.app) //! //! The [`wry`] Tauri [`Runtime`]. +//! +//! None of the exposed API of this crate is stable, and it may break semver +//! compatibility in the future. The major version only signifies the intended Tauri version. #![doc( html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png", @@ -20,7 +23,7 @@ use tauri_runtime::{ webview::{DetachedWebview, DownloadEvent, PendingWebview, WebviewIpcHandler}, window::{ CursorIcon, DetachedWindow, DragDropEvent, PendingWindow, RawWindow, WebviewEvent, - WindowBuilder, WindowBuilderBase, WindowEvent, WindowId, + WindowBuilder, WindowBuilderBase, WindowEvent, WindowId, WindowSizeConstraints, }, DeviceEventFilter, Error, EventLoopProxy, ExitRequestedEventAction, Icon, ProgressBarState, ProgressBarStatus, Result, RunEvent, Runtime, RuntimeHandle, RuntimeInitArgs, UserAttentionType, @@ -43,8 +46,8 @@ use wry::WebViewBuilderExtWindows; use tao::{ dpi::{ LogicalPosition as TaoLogicalPosition, LogicalSize as TaoLogicalSize, - PhysicalPosition as TaoPhysicalPosition, PhysicalSize as TaoPhysicalSize, - Position as TaoPosition, Size as TaoSize, + LogicalUnit as ToaLogicalUnit, PhysicalPosition as TaoPhysicalPosition, + PhysicalSize as TaoPhysicalSize, Position as TaoPosition, Size as TaoSize, }, event::{Event, StartCause, WindowEvent as TaoWindowEvent}, event_loop::{ @@ -733,7 +736,20 @@ unsafe impl Send for WindowBuilderWrapper {} impl WindowBuilderBase for WindowBuilderWrapper {} impl WindowBuilder for WindowBuilderWrapper { fn new() -> Self { - Self::default().focused(true) + #[allow(unused_mut)] + let mut builder = Self::default().focused(true); + + #[cfg(target_os = "macos")] + { + // TODO: find a proper way to prevent webview being pushed out of the window. + // Workround for issue: https://github.com/tauri-apps/tauri/issues/10225 + // The window requies `NSFullSizeContentViewWindowMask` flag to prevent devtools + // pushing the content view out of the window. + // By setting the default style to `TitleBarStyle::Visible` should fix the issue for most of the users. + builder = builder.title_bar_style(TitleBarStyle::Visible); + } + + builder } fn with_config(config: &WindowConfig) -> Self { @@ -792,12 +808,22 @@ impl WindowBuilder for WindowBuilderWrapper { .minimizable(config.minimizable) .shadow(config.shadow); - if let (Some(min_width), Some(min_height)) = (config.min_width, config.min_height) { - window = window.min_inner_size(min_width, min_height); + let mut constraints = WindowSizeConstraints::default(); + + if let Some(min_width) = config.min_width { + constraints.min_width = Some(ToaLogicalUnit::new(min_width).into()); } - if let (Some(max_width), Some(max_height)) = (config.max_width, config.max_height) { - window = window.max_inner_size(max_width, max_height); + if let Some(min_height) = config.min_height { + constraints.min_height = Some(ToaLogicalUnit::new(min_height).into()); } + if let Some(max_width) = config.max_width { + constraints.max_width = Some(ToaLogicalUnit::new(max_width).into()); + } + if let Some(max_height) = config.max_height { + constraints.max_height = Some(ToaLogicalUnit::new(max_height).into()); + } + window = window.inner_size_constraints(constraints); + if let (Some(x), Some(y)) = (config.x, config.y) { window = window.position(x, y); } @@ -851,6 +877,16 @@ impl WindowBuilder for WindowBuilderWrapper { self } + fn inner_size_constraints(mut self, constraints: WindowSizeConstraints) -> Self { + self.inner.window.inner_size_constraints = tao::window::WindowSizeConstraints { + min_width: constraints.min_width, + min_height: constraints.min_height, + max_width: constraints.max_width, + max_height: constraints.max_height, + }; + self + } + /// Prevent the window from overflowing the working area (e.g. monitor size - taskbar size) on creation #[must_use] fn prevent_overflow(mut self, margin: Option) -> Self { @@ -1006,6 +1042,13 @@ impl WindowBuilder for WindowBuilderWrapper { self.inner = self.inner.with_titlebar_transparent(true); self.inner = self.inner.with_fullsize_content_view(true); } + unknown => { + #[cfg(feature = "tracing")] + tracing::warn!("unknown title bar style applied: {unknown}"); + + #[cfg(not(feature = "tracing"))] + eprintln!("unknown title bar style applied: {unknown}"); + } } self } @@ -1179,6 +1222,7 @@ pub enum WindowMessage { SetSize(Size), SetMinSize(Option), SetMaxSize(Option), + SetSizeConstraints(WindowSizeConstraints), SetPosition(Position), SetFullscreen(bool), SetFocus, @@ -1190,6 +1234,7 @@ pub enum WindowMessage { SetCursorPosition(Position), SetIgnoreCursorEvents(bool), SetProgressBar(ProgressBarState), + SetTitleBarStyle(tauri_utils::TitleBarStyle), DragWindow, ResizeDragWindow(tauri_runtime::ResizeDirection), RequestRedraw, @@ -1884,6 +1929,16 @@ impl WindowDispatch for WryWindowDispatcher { ) } + fn set_size_constraints(&self, constraints: WindowSizeConstraints) -> Result<()> { + send_user_message( + &self.context, + Message::Window( + self.window_id, + WindowMessage::SetSizeConstraints(constraints), + ), + ) + } + fn set_position(&self, position: Position) -> Result<()> { send_user_message( &self.context, @@ -1983,6 +2038,13 @@ impl WindowDispatch for WryWindowDispatcher { ), ) } + + fn set_title_bar_style(&self, style: tauri_utils::TitleBarStyle) -> Result<()> { + send_user_message( + &self.context, + Message::Window(self.window_id, WindowMessage::SetTitleBarStyle(style)), + ) + } } #[derive(Clone)] @@ -2801,7 +2863,15 @@ fn handle_user_message( WindowMessage::RequestUserAttention(request_type) => { window.request_user_attention(request_type.map(|r| r.0)); } - WindowMessage::SetResizable(resizable) => window.set_resizable(resizable), + WindowMessage::SetResizable(resizable) => { + window.set_resizable(resizable); + #[cfg(windows)] + if !resizable { + undecorated_resizing::detach_resize_handler(window.hwnd()); + } else if !window.is_decorated() { + undecorated_resizing::attach_resize_handler(window.hwnd()); + } + } WindowMessage::SetMaximizable(maximizable) => window.set_maximizable(maximizable), WindowMessage::SetMinimizable(minimizable) => window.set_minimizable(minimizable), WindowMessage::SetClosable(closable) => window.set_closable(closable), @@ -2823,7 +2893,7 @@ fn handle_user_message( #[cfg(windows)] if decorations { undecorated_resizing::detach_resize_handler(window.hwnd()); - } else { + } else if window.is_resizable() { undecorated_resizing::attach_resize_handler(window.hwnd()); } } @@ -2850,6 +2920,14 @@ fn handle_user_message( WindowMessage::SetMaxSize(size) => { window.set_max_inner_size(size.map(|s| SizeWrapper::from(s).0)); } + WindowMessage::SetSizeConstraints(constraints) => { + window.set_inner_size_constraints(tao::window::WindowSizeConstraints { + min_width: constraints.min_width, + min_height: constraints.min_height, + max_width: constraints.max_width, + max_height: constraints.max_height, + }); + } WindowMessage::SetPosition(position) => { window.set_outer_position(PositionWrapper::from(position).0) } @@ -2907,6 +2985,30 @@ fn handle_user_message( WindowMessage::SetProgressBar(progress_state) => { window.set_progress_bar(ProgressBarStateWrapper::from(progress_state).0); } + WindowMessage::SetTitleBarStyle(_style) => { + #[cfg(target_os = "macos")] + match _style { + TitleBarStyle::Visible => { + window.set_titlebar_transparent(false); + window.set_fullsize_content_view(true); + } + TitleBarStyle::Transparent => { + window.set_titlebar_transparent(true); + window.set_fullsize_content_view(false); + } + TitleBarStyle::Overlay => { + window.set_titlebar_transparent(true); + window.set_fullsize_content_view(true); + } + unknown => { + #[cfg(feature = "tracing")] + tracing::warn!("unknown title bar style applied: {unknown}"); + + #[cfg(not(feature = "tracing"))] + eprintln!("unknown title bar style applied: {unknown}"); + } + }; + } } } } @@ -3893,21 +3995,21 @@ fn create_webview( WryDragDropEvent::Enter { paths, position: (x, y), - } => DragDropEvent::Dragged { + } => DragDropEvent::Enter { paths, position: PhysicalPosition::new(x as _, y as _), }, - WryDragDropEvent::Over { position: (x, y) } => DragDropEvent::DragOver { + WryDragDropEvent::Over { position: (x, y) } => DragDropEvent::Over { position: PhysicalPosition::new(x as _, y as _), }, WryDragDropEvent::Drop { paths, position: (x, y), - } => DragDropEvent::Dropped { + } => DragDropEvent::Drop { paths, position: PhysicalPosition::new(x as _, y as _), }, - WryDragDropEvent::Leave => DragDropEvent::Cancelled, + WryDragDropEvent::Leave => DragDropEvent::Leave, _ => unimplemented!(), }; diff --git a/core/tauri-runtime/CHANGELOG.md b/core/tauri-runtime/CHANGELOG.md index 336086d32..7e1b2a344 100644 --- a/core/tauri-runtime/CHANGELOG.md +++ b/core/tauri-runtime/CHANGELOG.md @@ -1,5 +1,36 @@ # Changelog +## \[2.0.0-rc.1] + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-rc.1` + +## \[2.0.0-rc.0] + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-rc.0` + +## \[2.0.0-beta.21] + +### What's Changed + +- [`da25f7353`](https://www.github.com/tauri-apps/tauri/commit/da25f7353070477ba969851e974379d7666d6806) ([#10242](https://www.github.com/tauri-apps/tauri/pull/10242) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `inner_size_constraints` method on `WindowBuilder` trait and `set_size_constraints` method on `WindowDispatch` trait. + +## \[2.0.0-beta.20] + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-beta.19` + +## \[2.0.0-beta.19] + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-beta.18` +- [`d4c908cfb`](https://www.github.com/tauri-apps/tauri/commit/d4c908cfb8c567abdaf99b85f65f482ea81967e5) ([#10048](https://www.github.com/tauri-apps/tauri/pull/10048)) Update `windows` crate to version `0.57` and `webview2-com` crate to version `0.31` + ## \[2.0.0-beta.18] ### Enhancements diff --git a/core/tauri-runtime/Cargo.toml b/core/tauri-runtime/Cargo.toml index 8cd2163c3..b094ba159 100644 --- a/core/tauri-runtime/Cargo.toml +++ b/core/tauri-runtime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tauri-runtime" -version = "2.0.0-beta.18" +version = "2.0.0-rc.1" description = "Runtime for Tauri applications" exclude = [ "CHANGELOG.md", "/target" ] readme = "README.md" @@ -29,7 +29,7 @@ targets = [ serde = { version = "1.0", features = [ "derive" ] } serde_json = "1.0" thiserror = "1.0" -tauri-utils = { version = "2.0.0-beta.17", path = "../tauri-utils" } +tauri-utils = { version = "2.0.0-rc.1", path = "../tauri-utils" } http = "1.1" raw-window-handle = "0.6" url = { version = "2" } diff --git a/core/tauri-runtime/README.md b/core/tauri-runtime/README.md index 8de890db7..531c845bc 100644 --- a/core/tauri-runtime/README.md +++ b/core/tauri-runtime/README.md @@ -24,6 +24,8 @@ Tauri apps can have custom menus and have tray-type interfaces. They can be upda ## This module This is the glue layer between tauri itself and lower level webview libraries. +None of the exposed API of this crate is stable, and it may break semver +compatibility in the future. The major version only signifies the intended Tauri version. To learn more about the details of how all of these pieces fit together, please consult this [ARCHITECTURE.md](https://github.com/tauri-apps/tauri/blob/dev/ARCHITECTURE.md) document. diff --git a/core/tauri-runtime/src/lib.rs b/core/tauri-runtime/src/lib.rs index 47fa96f37..a69bb5b2f 100644 --- a/core/tauri-runtime/src/lib.rs +++ b/core/tauri-runtime/src/lib.rs @@ -5,6 +5,9 @@ //! [![](https://github.com/tauri-apps/tauri/raw/dev/.github/splash.png)](https://tauri.app) //! //! Internal runtime between Tauri and the underlying webview runtime. +//! +//! None of the exposed API of this crate is stable, and it may break semver +//! compatibility in the future. The major version only signifies the intended Tauri version. #![doc( html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png", @@ -26,7 +29,10 @@ pub mod window; use dpi::{PhysicalPosition, PhysicalSize, Position, Size}; use monitor::Monitor; -use window::{CursorIcon, DetachedWindow, PendingWindow, RawWindow, WebviewEvent, WindowEvent}; +use window::{ + CursorIcon, DetachedWindow, PendingWindow, RawWindow, WebviewEvent, WindowEvent, + WindowSizeConstraints, +}; use window::{WindowBuilder, WindowId}; use http::{ @@ -735,6 +741,9 @@ pub trait WindowDispatch: Debug + Clone + Send + Sync + Sized + 's /// Updates the window max inner size. fn set_max_size(&self, size: Option) -> Result<()>; + /// Sets this window's minimum inner width. + fn set_size_constraints(&self, constraints: WindowSizeConstraints) -> Result<()>; + /// Updates the window position. fn set_position(&self, position: Position) -> Result<()>; @@ -783,4 +792,11 @@ pub trait WindowDispatch: Debug + Clone + Send + Sync + Sized + 's /// - **Linux / macOS**: Progress bar is app-wide and not specific to this window. Only supported desktop environments with `libunity` (e.g. GNOME). /// - **iOS / Android:** Unsupported. fn set_progress_bar(&self, progress_state: ProgressBarState) -> Result<()>; + + /// Sets the title bar style. Available on macOS only. + /// + /// ## Platform-specific + /// + /// - **Linux / Windows / iOS / Android:** Unsupported. + fn set_title_bar_style(&self, style: tauri_utils::TitleBarStyle) -> Result<()>; } diff --git a/core/tauri-runtime/src/webview.rs b/core/tauri-runtime/src/webview.rs index f286ab237..f11cab630 100644 --- a/core/tauri-runtime/src/webview.rs +++ b/core/tauri-runtime/src/webview.rs @@ -355,7 +355,7 @@ impl WebviewAttributes { /// /// - **Windows**: Controls WebView2's [`IsZoomControlEnabled`](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/microsoft_web_webview2_core/corewebview2settings?view=webview2-winrt-1.0.2420.47#iszoomcontrolenabled) setting. /// - **MacOS / Linux**: Injects a polyfill that zooms in and out with `ctrl/command` + `-/=`, - /// 20% in each step, ranging from 20% to 1000%. Requires `webview:allow-set-webview-zoom` permission + /// 20% in each step, ranging from 20% to 1000%. Requires `webview:allow-set-webview-zoom` permission /// /// - **Android / iOS**: Unsupported. #[must_use] diff --git a/core/tauri-runtime/src/window.rs b/core/tauri-runtime/src/window.rs index 0cf16949b..afca9abbe 100644 --- a/core/tauri-runtime/src/window.rs +++ b/core/tauri-runtime/src/window.rs @@ -9,7 +9,8 @@ use crate::{ Icon, Runtime, UserEvent, WindowDispatch, }; -use serde::{Deserialize, Deserializer}; +use dpi::PixelUnit; +use serde::{Deserialize, Deserializer, Serialize}; use tauri_utils::{config::WindowConfig, Theme}; #[cfg(windows)] use windows::Win32::Foundation::HWND; @@ -71,27 +72,27 @@ pub enum WebviewEvent { #[derive(Debug, Clone)] #[non_exhaustive] pub enum DragDropEvent { - /// A drag operation started. - Dragged { - /// Paths of the files that are being dragged. + /// A drag operation has entered the webview. + Enter { + /// List of paths that are being dragged onto the webview. paths: Vec, /// The position of the mouse cursor. position: dpi::PhysicalPosition, }, - /// The files have been dragged onto the window, but have not been dropped yet. - DragOver { + /// A drag operation is moving over the webview. + Over { /// The position of the mouse cursor. position: dpi::PhysicalPosition, }, - /// The user dropped the operation. - Dropped { - /// Path of the files that were dropped. + /// The file(s) have been dropped onto the webview. + Drop { + /// List of paths that are being dropped onto the window. paths: Vec, /// The position of the mouse cursor. position: dpi::PhysicalPosition, }, - /// The drag operation was cancelled. - Cancelled, + /// The drag operation has been cancelled or left the window. + Leave, } /// Describes the appearance of the mouse cursor. @@ -201,6 +202,28 @@ impl<'de> Deserialize<'de> for CursorIcon { } } +/// Window size constraints +#[derive(Clone, Copy, PartialEq, Debug, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct WindowSizeConstraints { + /// The minimum width a window can be, If this is `None`, the window will have no minimum width. + /// + /// The default is `None`. + pub min_width: Option, + /// The minimum height a window can be, If this is `None`, the window will have no minimum height. + /// + /// The default is `None`. + pub min_height: Option, + /// The maximum width a window can be, If this is `None`, the window will have no maximum width. + /// + /// The default is `None`. + pub max_width: Option, + /// The maximum height a window can be, If this is `None`, the window will have no maximum height. + /// + /// The default is `None`. + pub max_height: Option, +} + /// Do **NOT** implement this trait except for use in a custom [`Runtime`] /// /// This trait is separate from [`WindowBuilder`] to prevent "accidental" implementation. @@ -237,6 +260,10 @@ pub trait WindowBuilder: WindowBuilderBase { #[must_use] fn max_inner_size(self, max_width: f64, max_height: f64) -> Self; + /// Window inner size constraints. + #[must_use] + fn inner_size_constraints(self, constraints: WindowSizeConstraints) -> Self; + /// Window max inner size. #[must_use] fn prevent_overflow(self, margin: Option) -> Self; @@ -337,8 +364,8 @@ pub trait WindowBuilder: WindowBuilderBase { /// /// - **Windows:** /// - `false` has no effect on decorated window, shadows are always ON. - /// - `true` will make ndecorated window have a 1px white border, - /// and on Windows 11, it will have a rounded corners. + /// - `true` will make undecorated window have a 1px white border, + /// and on Windows 11, it will have a rounded corners. /// - **Linux:** Unsupported. #[must_use] fn shadow(self, enable: bool) -> Self; diff --git a/core/tauri-utils/CHANGELOG.md b/core/tauri-utils/CHANGELOG.md index 2e4367465..2783a83bc 100644 --- a/core/tauri-utils/CHANGELOG.md +++ b/core/tauri-utils/CHANGELOG.md @@ -1,5 +1,62 @@ # Changelog +## \[2.0.0-rc.1] + +### New Features + +- [`8dc81b6cc`](https://www.github.com/tauri-apps/tauri/commit/8dc81b6cc2b8235b11f74a971d6aa3a5df5e9f68) ([#10496](https://www.github.com/tauri-apps/tauri/pull/10496) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Added `bundle > ios > template` configuration option for custom Xcode project YML Handlebars template using XcodeGen. +- [`02c00abc6`](https://www.github.com/tauri-apps/tauri/commit/02c00abc63cf86e9bf9179cbb143d5145a9397b6) ([#10495](https://www.github.com/tauri-apps/tauri/pull/10495) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Added `bundle > ios > minimumSystemVersion` configuration option. + +### Bug Fixes + +- [`7e810cb2a`](https://www.github.com/tauri-apps/tauri/commit/7e810cb2a3fd934017ae973e737864dfa4bdf64e) ([#10485](https://www.github.com/tauri-apps/tauri/pull/10485) by [@anatawa12](https://www.github.com/tauri-apps/tauri/../../anatawa12)) Fixed an issue where permission files will be generated with ':' in the file path. + +## \[2.0.0-rc.0] + +### New Features + +- [`a5bfbaa62`](https://www.github.com/tauri-apps/tauri/commit/a5bfbaa62b8cd0aacbb33f730d4e30b43c461fe1)([#9962](https://www.github.com/tauri-apps/tauri/pull/9962)) Added `bundle > iOS > frameworks` configuration to define a list of frameworks that are linked to the Xcode project when it is generated. + +### Enhancements + +- [`7aeac39e7`](https://www.github.com/tauri-apps/tauri/commit/7aeac39e7fb97dc57ca278f1c097058275c20aa2) ([#10397](https://www.github.com/tauri-apps/tauri/pull/10397)) Make the set of gtk application id optional, to allow more then one instance of the app running at the same time. + +### Bug Fixes + +- [`498f405ca`](https://www.github.com/tauri-apps/tauri/commit/498f405ca80440447823dd3c9cd53c0f79d655b5) ([#10404](https://www.github.com/tauri-apps/tauri/pull/10404)) Fixed an issue where configuration parsing errors always displayed 'tauri.conf.json' as the file path, even when using 'Tauri.toml' or 'tauri.conf.json5'. + + The error messages now correctly shows the actual config file being used. + +### Security fixes + +- [`426d14bb4`](https://www.github.com/tauri-apps/tauri/commit/426d14bb4164290d93b5a0f61e925cb2dfc4aafa) ([#10423](https://www.github.com/tauri-apps/tauri/pull/10423)) Explicitly check that the main frame's origin is the sender of Isolation Payloads + +## \[2.0.0-beta.19] + +### New Features + +- [`4c239729c`](https://www.github.com/tauri-apps/tauri/commit/4c239729c3e1b899ecbc6793c3682848e8de1729) ([#10167](https://www.github.com/tauri-apps/tauri/pull/10167) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `RawIsolationPayload::content_type` method. + +## \[2.0.0-beta.18] + +### New Features + +- [`fafc238f7`](https://www.github.com/tauri-apps/tauri/commit/fafc238f7288548975ca7d3e5207b925c0295c91) ([#9977](https://www.github.com/tauri-apps/tauri/pull/9977)) Add `bundle > homepage` option, if unset, it will fallback to `homepage` defined in `Cargo.toml`. +- [`656a64974`](https://www.github.com/tauri-apps/tauri/commit/656a64974468bc207bf39537e02ae179bdee9b83) ([#9318](https://www.github.com/tauri-apps/tauri/pull/9318)) Added a configuration option to disable hardened runtime on macOS codesign. +- [`5b769948a`](https://www.github.com/tauri-apps/tauri/commit/5b769948a81cac333f64c870a470ba6525bd5cd3) ([#9959](https://www.github.com/tauri-apps/tauri/pull/9959)) Add `include_image` macro to help embedding instances of `Image` struct at compile-time in rust to be used with window, menu or tray icons. +- [`3ab170917`](https://www.github.com/tauri-apps/tauri/commit/3ab170917ed535fc9013f0a9255631fb34493e18) ([#9932](https://www.github.com/tauri-apps/tauri/pull/9932)) Add an option to disable NSIS compression `bundle > nsis > compression: "none"` +- [`f21029b1b`](https://www.github.com/tauri-apps/tauri/commit/f21029b1bc25f5cb987e1a25de94c2d364e3e462) ([#9994](https://www.github.com/tauri-apps/tauri/pull/9994)) Add `bundle > nsis > startMenuFolder` option to customize start menu folder for NSIS installer + +### Enhancements + +- [`878198777`](https://www.github.com/tauri-apps/tauri/commit/878198777ef693efdbd394cb4be4b234e8a7ed3d) ([#9999](https://www.github.com/tauri-apps/tauri/pull/9999)) Mark ACL `permissions` array with unique items + +### Breaking Changes + +- [`3ab170917`](https://www.github.com/tauri-apps/tauri/commit/3ab170917ed535fc9013f0a9255631fb34493e18) ([#9932](https://www.github.com/tauri-apps/tauri/pull/9932)) Changed `NsisSettings::compression` field from `Option` to just `NsisCompression` +- [`911242f09`](https://www.github.com/tauri-apps/tauri/commit/911242f0928e0a2add3595fa9de27850fb875fa6) ([#9883](https://www.github.com/tauri-apps/tauri/pull/9883)) Move updater target from `bundle > targets` to a separate field `bundle > createUpdaterArtifacts` +- [`3ab170917`](https://www.github.com/tauri-apps/tauri/commit/3ab170917ed535fc9013f0a9255631fb34493e18) ([#9932](https://www.github.com/tauri-apps/tauri/pull/9932)) Changed `NsisConfig::compression` field from `Option` to just `NsisCompression` + ## \[2.0.0-beta.17] ### New Features diff --git a/core/tauri-utils/Cargo.toml b/core/tauri-utils/Cargo.toml index 1694c0d20..ef0881779 100644 --- a/core/tauri-utils/Cargo.toml +++ b/core/tauri-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tauri-utils" -version = "2.0.0-beta.17" +version = "2.0.0-rc.1" description = "Utilities for Tauri" exclude = [ "CHANGELOG.md", "/target" ] readme = "README.md" diff --git a/core/tauri-utils/src/acl/build.rs b/core/tauri-utils/src/acl/build.rs index 582c8016c..637dfc3be 100644 --- a/core/tauri-utils/src/acl/build.rs +++ b/core/tauri-utils/src/acl/build.rs @@ -71,10 +71,8 @@ pub fn define_permissions bool>( .filter(|p| p.parent().unwrap().file_name().unwrap() != PERMISSION_SCHEMAS_FOLDER_NAME) .collect::>(); - let permission_files_path = out_dir.join(format!( - "{}-permission-files", - pkg_name.replace("tauri:", "tauri-") - )); + let permission_files_path = + out_dir.join(format!("{}-permission-files", pkg_name.replace(':', "-"))); std::fs::write( &permission_files_path, serde_json::to_string(&permission_files)?, @@ -435,8 +433,6 @@ identifier = "deny-{slugified_command}" description = "Denies the {command} command without any pre-configured scope." commands.deny = ["{command}"] "###, - command = command, - slugified_command = slugified_command, ); let out_path = path.join(format!("{command}.toml")); diff --git a/core/tauri-utils/src/acl/capability.rs b/core/tauri-utils/src/acl/capability.rs index a84b9b017..ebfdba33b 100644 --- a/core/tauri-utils/src/acl/capability.rs +++ b/core/tauri-utils/src/acl/capability.rs @@ -94,7 +94,7 @@ impl<'de> Deserialize<'de> for PermissionEntry { /// "main" /// ], /// "permissions": [ -/// "path:default", +/// "core:default", /// "dialog:open", /// { /// "identifier": "fs:allow-write-text-file", @@ -174,14 +174,7 @@ pub struct Capability { /// /// ```json /// [ - /// "path:default", - /// "event:default", - /// "window:default", - /// "app:default", - /// "image:default", - /// "resources:default", - /// "menu:default", - /// "tray:default", + /// "core:default", /// "shell:allow-open", /// "dialog:open", /// { diff --git a/core/tauri-utils/src/acl/identifier.rs b/core/tauri-utils/src/acl/identifier.rs index 92d210aa8..64df0ed27 100644 --- a/core/tauri-utils/src/acl/identifier.rs +++ b/core/tauri-utils/src/acl/identifier.rs @@ -10,8 +10,9 @@ use thiserror::Error; const IDENTIFIER_SEPARATOR: u8 = b':'; const PLUGIN_PREFIX: &str = "tauri-plugin-"; +const CORE_PLUGIN_IDENTIFIER_PREFIX: &str = "core:"; -// https://doc.rust-lang.org/cargo/reference/manifest.html#the-name-field +// const MAX_LEN_PREFIX: usize = 64 - PLUGIN_PREFIX.len(); const MAX_LEN_BASE: usize = 64; const MAX_LEN_IDENTIFIER: usize = MAX_LEN_PREFIX + 1 + MAX_LEN_BASE; @@ -156,11 +157,14 @@ impl TryFrom for Identifier { return Err(Self::Error::Empty); } - let mut bytes = value.bytes(); - if bytes.len() > MAX_LEN_IDENTIFIER { - return Err(Self::Error::Humongous(bytes.len())); + if value.len() > MAX_LEN_IDENTIFIER { + return Err(Self::Error::Humongous(value.len())); } + let is_core_identifier = value.starts_with(CORE_PLUGIN_IDENTIFIER_PREFIX); + + let mut bytes = value.bytes(); + // grab the first byte only before parsing the rest let mut prev = bytes .next() @@ -175,7 +179,7 @@ impl TryFrom for Identifier { None => return Err(Self::Error::InvalidFormat), Some(next @ ValidByte::Byte(_)) => prev = next, Some(ValidByte::Separator) => { - if separator.is_none() { + if separator.is_none() || is_core_identifier { // safe to unwrap because idx starts at 1 and cannot go over MAX_IDENTIFIER_LEN separator = Some(idx.try_into().unwrap()); prev = ValidByte::Separator diff --git a/core/tauri-utils/src/acl/mod.rs b/core/tauri-utils/src/acl/mod.rs index 0016a4682..6d574263d 100644 --- a/core/tauri-utils/src/acl/mod.rs +++ b/core/tauri-utils/src/acl/mod.rs @@ -3,6 +3,23 @@ // SPDX-License-Identifier: MIT //! Access Control List types. +//! +//! # Stability +//! +//! This is a core functionality that is not considered part of the stable API. +//! If you use it, note that it may include breaking changes in the future. +//! +//! These items are intended to be non-breaking from a de/serialization standpoint only. +//! Using and modifying existing config values will try to avoid breaking changes, but they are +//! free to add fields in the future - causing breaking changes for creating and full destructuring. +//! +//! To avoid this, [ignore unknown fields when destructuring] with the `{my, config, ..}` pattern. +//! If you need to create the Rust config directly without deserializing, then create the struct +//! the [Struct Update Syntax] with `..Default::default()`, which may need a +//! `#[allow(clippy::needless_update)]` attribute if you are declaring all fields. +//! +//! [ignore unknown fields when destructuring]: https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html#ignoring-remaining-parts-of-a-value-with- +//! [Struct Update Syntax]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax use serde::{Deserialize, Serialize}; use std::{num::NonZeroU64, str::FromStr, sync::Arc}; diff --git a/core/tauri-utils/src/acl/resolved.rs b/core/tauri-utils/src/acl/resolved.rs index 57c71e991..7bf841b4f 100644 --- a/core/tauri-utils/src/acl/resolved.rs +++ b/core/tauri-utils/src/acl/resolved.rs @@ -17,6 +17,18 @@ use super::{ /// A key for a scope, used to link a [`ResolvedCommand#structfield.scope`] to the store [`Resolved#structfield.scopes`]. pub type ScopeKey = u64; +const CORE_PLUGINS: &[&str] = &[ + "core:app", + "core:event", + "core:image", + "core:menu", + "core:path", + "core:resources", + "core:tray", + "core:webview", + "core:window", +]; + /// Metadata for what referenced a [`ResolvedCommand`]. #[cfg(debug_assertions)] #[derive(Default, Clone, PartialEq, Eq)] @@ -80,7 +92,7 @@ impl Resolved { /// Resolves the ACL for the given plugin permissions and app capabilities. pub fn resolve( acl: &BTreeMap, - capabilities: BTreeMap, + mut capabilities: BTreeMap, target: Target, ) -> Result { let mut allowed_commands = BTreeMap::new(); @@ -91,7 +103,7 @@ impl Resolved { let mut global_scope: BTreeMap> = BTreeMap::new(); // resolve commands - for capability in capabilities.values() { + for capability in capabilities.values_mut() { if !capability .platforms .as_ref() @@ -101,6 +113,20 @@ impl Resolved { continue; } + if let Some(core_default_index) = capability.permissions.iter().position(|permission| { + matches!( + permission, + PermissionEntry::PermissionRef(i) if i.get() == "core:default" + ) + }) { + capability.permissions.remove(core_default_index); + for plugin in CORE_PLUGINS { + capability.permissions.push(PermissionEntry::PermissionRef( + format!("{plugin}:default").try_into().unwrap(), + )); + } + } + with_resolved_permissions( capability, acl, @@ -134,6 +160,8 @@ impl Resolved { &mut allowed_commands, if key == APP_ACL_KEY { allowed_command.to_string() + } else if let Some(core_plugin_name) = key.strip_prefix("core:") { + format!("plugin:{core_plugin_name}|{allowed_command}") } else { format!("plugin:{key}|{allowed_command}") }, @@ -149,6 +177,8 @@ impl Resolved { &mut denied_commands, if key == APP_ACL_KEY { denied_command.to_string() + } else if let Some(core_plugin_name) = key.strip_prefix("core:") { + format!("plugin:{core_plugin_name}|{denied_command}") } else { format!("plugin:{key}|{denied_command}") }, diff --git a/core/tauri-utils/src/config.rs b/core/tauri-utils/src/config.rs index eca654b3e..32bcc6ee5 100644 --- a/core/tauri-utils/src/config.rs +++ b/core/tauri-utils/src/config.rs @@ -7,8 +7,21 @@ //! It is pulled from a `tauri.conf.json` file and the [`Config`] struct is generated at compile time. //! //! # Stability +//! //! This is a core functionality that is not considered part of the stable API. //! If you use it, note that it may include breaking changes in the future. +//! +//! These items are intended to be non-breaking from a de/serialization standpoint only. +//! Using and modifying existing config values will try to avoid breaking changes, but they are +//! free to add fields in the future - causing breaking changes for creating and full destructuring. +//! +//! To avoid this, [ignore unknown fields when destructuring] with the `{my, config, ..}` pattern. +//! If you need to create the Rust config directly without deserializing, then create the struct +//! the [Struct Update Syntax] with `..Default::default()`, which may need a +//! `#[allow(clippy::needless_update)]` attribute if you are declaring all fields. +//! +//! [ignore unknown fields when destructuring]: https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html#ignoring-remaining-parts-of-a-value-with- +//! [Struct Update Syntax]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax #[cfg(feature = "schema")] use schemars::JsonSchema; @@ -333,7 +346,7 @@ pub struct DebConfig { /// Recognized Priorities as of now are : `required`, `important`, `standard`, `optional`, `extra` pub priority: Option, /// Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See - /// https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes + /// pub changelog: Option, /// Path to a custom desktop file Handlebars template. /// @@ -341,19 +354,19 @@ pub struct DebConfig { #[serde(alias = "desktop-template")] pub desktop_template: Option, /// Path to script that will be executed before the package is unpacked. See - /// https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html + /// #[serde(alias = "pre-install-script")] pub pre_install_script: Option, /// Path to script that will be executed after the package is unpacked. See - /// https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html + /// #[serde(alias = "post-install-script")] pub post_install_script: Option, /// Path to script that will be executed before the package is removed. See - /// https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html + /// #[serde(alias = "pre-remove-script")] pub pre_remove_script: Option, /// Path to script that will be executed after the package is removed. See - /// https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html + /// #[serde(alias = "post-remove-script")] pub post_remove_script: Option, } @@ -408,19 +421,19 @@ pub struct RpmConfig { #[serde(alias = "desktop-template")] pub desktop_template: Option, /// Path to script that will be executed before the package is unpacked. See - /// http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html + /// #[serde(alias = "pre-install-script")] pub pre_install_script: Option, /// Path to script that will be executed after the package is unpacked. See - /// http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html + /// #[serde(alias = "post-install-script")] pub post_install_script: Option, /// Path to script that will be executed before the package is removed. See - /// http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html + /// #[serde(alias = "pre-remove-script")] pub pre_remove_script: Option, /// Path to script that will be executed after the package is removed. See - /// http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html + /// #[serde(alias = "post-remove-script")] pub post_remove_script: Option, } @@ -523,13 +536,13 @@ fn dmg_application_folder_position() -> Position { Position { x: 480, y: 170 } } -fn de_minimum_system_version<'de, D>(deserializer: D) -> Result, D::Error> +fn de_macos_minimum_system_version<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { let version = Option::::deserialize(deserializer)?; match version { - Some(v) if v.is_empty() => Ok(minimum_system_version()), + Some(v) if v.is_empty() => Ok(macos_minimum_system_version()), e => Ok(e), } } @@ -556,8 +569,8 @@ pub struct MacConfig { /// /// An empty string is considered an invalid value so the default value is used. #[serde( - deserialize_with = "de_minimum_system_version", - default = "minimum_system_version", + deserialize_with = "de_macos_minimum_system_version", + default = "macos_minimum_system_version", alias = "minimum-system-version" )] pub minimum_system_version: Option, @@ -588,7 +601,7 @@ impl Default for MacConfig { Self { frameworks: None, files: HashMap::new(), - minimum_system_version: minimum_system_version(), + minimum_system_version: macos_minimum_system_version(), exception_domain: None, signing_identity: None, hardened_runtime: true, @@ -599,10 +612,14 @@ impl Default for MacConfig { } } -fn minimum_system_version() -> Option { +fn macos_minimum_system_version() -> Option { Some("10.13".into()) } +fn ios_minimum_system_version() -> String { + "13.0".into() +} + /// Configuration for a target language for the WiX build. /// /// See more: @@ -802,23 +819,19 @@ pub struct NsisConfig { /// ### Example /// /// ```nsh - /// !define NSIS_HOOK_PREINSTALL "NSIS_HOOK_PREINSTALL_" - /// !macro NSIS_HOOK_PREINSTALL_ + /// !macro NSIS_HOOK_PREINSTALL /// MessageBox MB_OK "PreInstall" /// !macroend /// - /// !define NSIS_HOOK_POSTINSTALL "NSIS_HOOK_POSTINSTALL_" - /// !macro NSIS_HOOK_POSTINSTALL_ + /// !macro NSIS_HOOK_POSTINSTALL /// MessageBox MB_OK "PostInstall" /// !macroend /// - /// !define NSIS_HOOK_PREUNINSTALL "NSIS_HOOK_PREUNINSTALL_" - /// !macro NSIS_HOOK_PREUNINSTALL_ + /// !macro NSIS_HOOK_PREUNINSTALL /// MessageBox MB_OK "PreUnInstall" /// !macroend /// - /// !define NSIS_HOOK_POSTUNINSTALL "NSIS_HOOK_POSTUNINSTALL_" - /// !macro NSIS_HOOK_POSTUNINSTALL_ + /// !macro NSIS_HOOK_POSTUNINSTALL /// MessageBox MB_OK "PostUninstall" /// !macroend /// @@ -1383,7 +1396,7 @@ pub struct WindowConfig { /// /// - **Windows:** /// - `false` has no effect on decorated window, shadow are always ON. - /// - `true` will make ndecorated window have a 1px white border, + /// - `true` will make undecorated window have a 1px white border, /// and on Windows 11, it will have a rounded corners. /// - **Linux:** Unsupported. #[serde(default = "default_true")] @@ -1839,6 +1852,9 @@ pub struct AppConfig { /// Whether we should inject the Tauri API on `window.__TAURI__` or not. #[serde(default, alias = "with-global-tauri")] pub with_global_tauri: bool, + /// If set to true "identifier" will be set as GTK app ID (on systems that use GTK). + #[serde(rename = "enableGTKAppId", alias = "enable-gtk-app-id", default)] + pub enable_gtk_app_id: bool, } impl AppConfig { @@ -1909,10 +1925,26 @@ pub struct TrayIconConfig { #[cfg_attr(feature = "schema", derive(JsonSchema))] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct IosConfig { + /// A custom [XcodeGen] project.yml template to use. + /// + /// [XcodeGen]: + pub template: Option, + /// A list of strings indicating any iOS frameworks that need to be bundled with the application. + /// + /// Note that you need to recreate the iOS project for the changes to be applied. + pub frameworks: Option>, /// The development team. This value is required for iOS development because code signing is enforced. /// The `APPLE_DEVELOPMENT_TEAM` environment variable can be set to overwrite it. #[serde(alias = "development-team")] pub development_team: Option, + /// A version string indicating the minimum iOS version that the bundled application supports. Defaults to `13.0`. + /// + /// Maps to the IPHONEOS_DEPLOYMENT_TARGET value. + #[serde( + alias = "minimum-system-version", + default = "ios_minimum_system_version" + )] + pub minimum_system_version: String, } /// General configuration for the iOS target. @@ -2162,7 +2194,7 @@ where /// ```json title="Example tauri.config.json file" /// { /// "productName": "tauri-app", -/// "version": "0.1.0" +/// "version": "0.1.0", /// "build": { /// "beforeBuildCommand": "", /// "beforeDevCommand": "", @@ -2796,6 +2828,7 @@ mod build { let tray_icon = opt_lit(self.tray_icon.as_ref()); let macos_private_api = self.macos_private_api; let with_global_tauri = self.with_global_tauri; + let enable_gtk_app_id = self.enable_gtk_app_id; literal_struct!( tokens, @@ -2804,7 +2837,8 @@ mod build { security, tray_icon, macos_private_api, - with_global_tauri + with_global_tauri, + enable_gtk_app_id ); } } @@ -2881,6 +2915,7 @@ mod test { tray_icon: None, macos_private_api: false, with_global_tauri: false, + enable_gtk_app_id: false, }; // create a build config diff --git a/core/tauri-utils/src/config/parse.rs b/core/tauri-utils/src/config/parse.rs index ccf6ad536..39431a7b0 100644 --- a/core/tauri-utils/src/config/parse.rs +++ b/core/tauri-utils/src/config/parse.rs @@ -172,7 +172,7 @@ pub fn is_configuration_file(target: Target, path: &Path) -> bool { /// - `tauri.windows.conf.json[5]` or `Tauri.windows.toml` on Windows /// - `tauri.android.conf.json[5]` or `Tauri.android.toml` on Android /// - `tauri.ios.conf.json[5]` or `Tauri.ios.toml` on iOS -/// Merging the configurations using [JSON Merge Patch (RFC 7396)]. +/// Merging the configurations using [JSON Merge Patch (RFC 7396)]. /// /// [JSON Merge Patch (RFC 7396)]: https://datatracker.ietf.org/doc/html/rfc7396. pub fn read_from(target: Target, root_dir: PathBuf) -> Result { @@ -224,15 +224,15 @@ pub fn does_supported_file_name_exist(target: Target, path: impl Into) /// /// Hierarchy: /// 1. Check if `tauri.conf.json` exists -/// a. Parse it with `serde_json` -/// b. Parse it with `json5` if `serde_json` fails -/// c. Return original `serde_json` error if all above steps failed +/// a. Parse it with `serde_json` +/// b. Parse it with `json5` if `serde_json` fails +/// c. Return original `serde_json` error if all above steps failed /// 2. Check if `tauri.conf.json5` exists -/// a. Parse it with `json5` -/// b. Return error if all above steps failed +/// a. Parse it with `json5` +/// b. Return error if all above steps failed /// 3. Check if `Tauri.json` exists -/// a. Parse it with `toml` -/// b. Return error if all above steps failed +/// a. Parse it with `toml` +/// b. Return error if all above steps failed /// 4. Return error if all above steps failed pub fn parse(target: Target, path: impl Into) -> Result<(Config, PathBuf), ConfigError> { do_parse(target, path.into()) @@ -300,7 +300,7 @@ fn do_parse( #[cfg(feature = "config-json5")] { let raw = read_to_string(&json5)?; - do_parse_json5(&raw, &path).map(|config| (config, json5)) + do_parse_json5(&raw, &json5).map(|config| (config, json5)) } #[cfg(not(feature = "config-json5"))] @@ -312,7 +312,7 @@ fn do_parse( #[cfg(feature = "config-toml")] { let raw = read_to_string(&toml)?; - do_parse_toml(&raw, &path).map(|config| (config, toml)) + do_parse_toml(&raw, &toml).map(|config| (config, toml)) } #[cfg(not(feature = "config-toml"))] diff --git a/core/tauri-utils/src/html.rs b/core/tauri-utils/src/html.rs index 97c83e2a3..a42f4e8c4 100644 --- a/core/tauri-utils/src/html.rs +++ b/core/tauri-utils/src/html.rs @@ -28,7 +28,7 @@ pub const SCRIPT_NONCE_TOKEN: &str = "__TAURI_SCRIPT_NONCE__"; /// The token used for style nonces. pub const STYLE_NONCE_TOKEN: &str = "__TAURI_STYLE_NONCE__"; -// taken from https://github.com/kuchiki-rs/kuchiki/blob/57ee6920d835315a498e748ba4b07a851ae5e498/src/serializer.rs#L12 +// taken from fn serialize_node_ref_internal( node: &NodeRef, serializer: &mut S, diff --git a/core/tauri-utils/src/lib.rs b/core/tauri-utils/src/lib.rs index c8e363391..08434064b 100644 --- a/core/tauri-utils/src/lib.rs +++ b/core/tauri-utils/src/lib.rs @@ -159,6 +159,7 @@ pub use window_effects::{WindowEffect, WindowEffectState}; /// How the window title bar should be displayed on macOS. #[derive(Debug, Clone, PartialEq, Eq, Copy)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] +#[non_exhaustive] pub enum TitleBarStyle { /// A normal title bar. Visible, @@ -294,7 +295,7 @@ impl Default for Env { if env.appimage.is_some() || env.appdir.is_some() { // validate that we're actually running on an AppImage // an AppImage is mounted to `/$TEMPDIR/.mount_${appPrefix}${hash}` - // see https://github.com/AppImage/AppImageKit/blob/1681fd84dbe09c7d9b22e13cdb16ea601aa0ec47/src/runtime.c#L501 + // see // note that it is safe to use `std::env::current_exe` here since we just loaded an AppImage. let is_temp = std::env::current_exe() .map(|p| { @@ -379,3 +380,20 @@ pub fn display_path>(p: P) -> String { .display() .to_string() } + +/// Write the file only if the content of the existing file (if any) is different. +/// +/// This will always write unless the file exists with identical content. +pub fn write_if_changed(path: P, content: C) -> std::io::Result<()> +where + P: AsRef, + C: AsRef<[u8]>, +{ + if let Ok(existing) = std::fs::read(&path) { + if existing == content.as_ref() { + return Ok(()); + } + } + + std::fs::write(path, content) +} diff --git a/core/tauri-utils/src/mime_type.rs b/core/tauri-utils/src/mime_type.rs index e78cdd90d..61b64147d 100644 --- a/core/tauri-utils/src/mime_type.rs +++ b/core/tauri-utils/src/mime_type.rs @@ -71,7 +71,7 @@ impl MimeType { // Assume HTML when a TLD is found for eg. `wry:://tauri.app` | `wry://hello.com` Some(_) => fallback, // using octet stream according to this: - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types + // None => Self::OctetStream, } } diff --git a/core/tauri-utils/src/pattern/isolation.js b/core/tauri-utils/src/pattern/isolation.js index f1908bffc..d929308e0 100644 --- a/core/tauri-utils/src/pattern/isolation.js +++ b/core/tauri-utils/src/pattern/isolation.js @@ -17,6 +17,11 @@ window.parent.postMessage(message, '*') } + /** + * @type {string} - The main frame origin. + */ + const origin = __TEMPLATE_origin__ + /** * @type {Uint8Array} - Injected by Tauri during runtime */ @@ -37,20 +42,27 @@ * @param {object} data * @return {Promise<{nonce: number[], payload: number[]}>} */ - async function encrypt(data) { + async function encrypt(payload) { const algorithm = Object.create(null) algorithm.name = 'AES-GCM' algorithm.iv = window.crypto.getRandomValues(new Uint8Array(12)) - const encoder = new TextEncoder() - const encoded = encoder.encode(__RAW_process_ipc_message_fn__(data).data) + const {contentType, data} = __RAW_process_ipc_message_fn__(payload) + + const message = + typeof data === 'string' + ? new TextEncoder().encode(data) + : ArrayBuffer.isView(data) || data instanceof ArrayBuffer + ? data + : new Uint8Array(data) return window.crypto.subtle - .encrypt(algorithm, aesGcmKey, encoded) + .encrypt(algorithm, aesGcmKey, message) .then((payload) => { const result = Object.create(null) result.nonce = Array.from(new Uint8Array(algorithm.iv)) result.payload = Array.from(new Uint8Array(payload)) + result.contentType = contentType return result }) } @@ -66,7 +78,9 @@ const keys = data.payload ? Object.keys(data.payload) : [] return ( keys.length > 0 && - keys.every((key) => key === 'nonce' || key === 'payload') + keys.every( + (key) => key === 'nonce' || key === 'payload' || key === 'contentType' + ) ) } return false @@ -92,7 +106,7 @@ * @param {MessageEvent} event */ async function payloadHandler(event) { - if (!isIsolationPayload(event.data)) { + if (event.origin !== origin || !isIsolationPayload(event.data)) { return } diff --git a/core/tauri-utils/src/pattern/isolation.rs b/core/tauri-utils/src/pattern/isolation.rs index afffdf487..64fa8beba 100644 --- a/core/tauri-utils/src/pattern/isolation.rs +++ b/core/tauri-utils/src/pattern/isolation.rs @@ -73,6 +73,14 @@ impl AesGcmPair { pub fn key(&self) -> &Aes256Gcm { &self.key } + + #[doc(hidden)] + pub fn encrypt(&self, nonce: &[u8; 12], payload: &[u8]) -> Result, Error> { + self + .key + .encrypt(nonce.into(), payload) + .map_err(|_| self::Error::Aes) + } } /// All cryptographic keys required for Isolation encryption @@ -97,7 +105,7 @@ impl Keys { /// Decrypts a message using the generated keys. pub fn decrypt(&self, raw: RawIsolationPayload<'_>) -> Result, Error> { - let RawIsolationPayload { nonce, payload } = raw; + let RawIsolationPayload { nonce, payload, .. } = raw; let nonce: [u8; 12] = nonce.as_ref().try_into()?; self .aes_gcm @@ -109,9 +117,18 @@ impl Keys { /// Raw representation of #[derive(Debug, serde::Deserialize)] +#[serde(rename_all = "camelCase")] pub struct RawIsolationPayload<'a> { nonce: Cow<'a, [u8]>, payload: Cow<'a, [u8]>, + content_type: Cow<'a, str>, +} + +impl<'a> RawIsolationPayload<'a> { + /// Content type of this payload. + pub fn content_type(&self) -> &Cow<'a, str> { + &self.content_type + } } impl<'a> TryFrom<&'a Vec> for RawIsolationPayload<'a> { @@ -139,6 +156,8 @@ pub struct IsolationJavascriptCodegen { pub struct IsolationJavascriptRuntime<'a> { /// The key used on the Rust backend and the Isolation Javascript pub runtime_aes_gcm_key: &'a [u8; 32], + /// The origin the isolation application is expecting messages from. + pub origin: String, /// The function that processes the IPC message. #[raw] pub process_ipc_message_fn: &'a str, diff --git a/core/tauri-utils/src/platform.rs b/core/tauri-utils/src/platform.rs index 29bfcc222..5b0040264 100644 --- a/core/tauri-utils/src/platform.rs +++ b/core/tauri-utils/src/platform.rs @@ -19,6 +19,7 @@ mod starting_binary; #[derive(PartialEq, Eq, Copy, Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] #[serde(rename_all = "camelCase")] +#[non_exhaustive] pub enum Target { /// MacOS. #[serde(rename = "macOS")] diff --git a/core/tauri-utils/src/tokens.rs b/core/tauri-utils/src/tokens.rs index 238d8df2f..c02fb1fdc 100644 --- a/core/tauri-utils/src/tokens.rs +++ b/core/tauri-utils/src/tokens.rs @@ -131,7 +131,7 @@ where /// Create a `serde_json::Value` variant `TokenStream` for a number pub fn json_value_number_lit(num: &serde_json::Number) -> TokenStream { - // See https://docs.rs/serde_json/1/serde_json/struct.Number.html for guarantees + // See for guarantees let prefix = quote! { ::serde_json::Value }; if num.is_u64() { // guaranteed u64 diff --git a/core/tauri/CHANGELOG.md b/core/tauri/CHANGELOG.md index b5ed9f76b..b27718ae6 100644 --- a/core/tauri/CHANGELOG.md +++ b/core/tauri/CHANGELOG.md @@ -1,5 +1,169 @@ # Changelog +## \[2.0.0-rc.1] + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-rc.1` +- Upgraded to `tauri-runtime@2.0.0-rc.1` +- Upgraded to `tauri-runtime-wry@2.0.0-rc.1` +- Upgraded to `tauri-macros@2.0.0-rc.1` +- Upgraded to `tauri-build@2.0.0-rc.1` + +## \[2.0.0-rc.0] + +### Bug Fixes + +- [`6755af230`](https://www.github.com/tauri-apps/tauri/commit/6755af23021a254cff98c07aa7711545771097a6)([#10435](https://www.github.com/tauri-apps/tauri/pull/10435)) Fix Specta remote implementation target for `Channel`. +- [`24445d71d`](https://www.github.com/tauri-apps/tauri/commit/24445d71de92d526d0ccaecb54f13003ddc6f6b4)([#10432](https://www.github.com/tauri-apps/tauri/pull/10432)) Fixes asset resolving when not using the `compression` feature. + +### Enhancements + +- [`1e0793b68`](https://www.github.com/tauri-apps/tauri/commit/1e0793b6821799829e380c88066b3415cc9006df) ([#10357](https://www.github.com/tauri-apps/tauri/pull/10357)) Enhance `AssetResolver::get` in development mode by reading distDir directly as a fallback to the embedded assets. +- [`7aeac39e7`](https://www.github.com/tauri-apps/tauri/commit/7aeac39e7fb97dc57ca278f1c097058275c20aa2) ([#10397](https://www.github.com/tauri-apps/tauri/pull/10397)) Make the set of gtk application id optional, to allow more then one instance of the app running at the same time. +- [`cf994a6bb`](https://www.github.com/tauri-apps/tauri/commit/cf994a6bb064a50d3e5aef67e9a25903ee17a1e2) ([#10405](https://www.github.com/tauri-apps/tauri/pull/10405)) Add `tauri::plugin::Builder::try_build` to allow plugins to check if their `TauriPlugin` initialization is valid. + +### Security fixes + +- [`426d14bb4`](https://www.github.com/tauri-apps/tauri/commit/426d14bb4164290d93b5a0f61e925cb2dfc4aafa) ([#10423](https://www.github.com/tauri-apps/tauri/pull/10423)) Explicitly check that the main frame's origin is the sender of Isolation Payloads +- [`289ae5555`](https://www.github.com/tauri-apps/tauri/commit/289ae5555da3802741018015bfe4927729a2eb33) ([#10386](https://www.github.com/tauri-apps/tauri/pull/10386)) Re-enable TLS checks that were previously disabled to support an insecure HTTPS custom protocol on Android which is no longer used. + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-rc.0` +- Upgraded to `tauri-macros@2.0.0-rc.0` +- Upgraded to `tauri-build@2.0.0-rc.0` +- Upgraded to `tauri-runtime@2.0.0-rc.0` +- Upgraded to `tauri-runtime-wry@2.0.0-rc.0` + +### Breaking Changes + +- [`758d28c8a`](https://www.github.com/tauri-apps/tauri/commit/758d28c8a2d5c9567158e339326b765f72da983e) ([#10390](https://www.github.com/tauri-apps/tauri/pull/10390)) Core plugin permissions are now prefixed with `core:`, the `core:default` permission set can now be used and the `core` plugin name is reserved. + The `tauri migrate` tool will automate the migration process, which involves prefixing all `app`, `event`, `image`, `menu`, `path`, `resources`, `tray`, `webview` and `window` permissions with `core:`. + +## \[2.0.0-beta.25] + +### New Features + +- [`da25f7353`](https://www.github.com/tauri-apps/tauri/commit/da25f7353070477ba969851e974379d7666d6806) ([#10242](https://www.github.com/tauri-apps/tauri/pull/10242) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add APIs to enable setting window size constraints separately: + + - Added `WindowBuilder::inner_size_constraints` and `WebviewWindowBuilder::inner_size_constraints` which can be used for setting granular constraints. + - Added `WindowSizeConstraints` struct + - Added `Window::set_size_constraints` and `WebviewWindow::set_size_constraints` + +### Bug Fixes + +- [`e1776946a`](https://www.github.com/tauri-apps/tauri/commit/e1776946ad034d7a6e005834a754773671d9f7ef) ([#10362](https://www.github.com/tauri-apps/tauri/pull/10362) by [@Brendonovich](https://www.github.com/tauri-apps/tauri/../../Brendonovich)) Use ` specta rc.15's `derive\` feature which fixes build issues in docs.rs. +- [`da25f7353`](https://www.github.com/tauri-apps/tauri/commit/da25f7353070477ba969851e974379d7666d6806) ([#10242](https://www.github.com/tauri-apps/tauri/pull/10242) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Apply `minWidth`, `minHieght`, `maxWidth` and `maxHeight` constraints separately, which fixes a long standing bug where these constraints were never applied unless width and height were constrained together. + +### What's Changed + +- [`9546548ec`](https://www.github.com/tauri-apps/tauri/commit/9546548ec0c83ba620b1bc9d1d424a7009d0b423) ([#10297](https://www.github.com/tauri-apps/tauri/pull/10297) by [@pewsheen](https://www.github.com/tauri-apps/tauri/../../pewsheen)) On macOS, set default titlebar style to `Visible` to prevent webview move out of the view. + +### Dependencies + +- Upgraded to `tauri-runtime-wry@2.0.0-beta.21` +- Upgraded to `tauri-runtime@2.0.0-beta.21` + +## \[2.0.0-beta.24] + +### New Features + +- [`7bc6a2a1d`](https://www.github.com/tauri-apps/tauri/commit/7bc6a2a1d6d2c5406d91cac94d33bce76443c28f) ([#9788](https://www.github.com/tauri-apps/tauri/pull/9788) by [@pewsheen](https://www.github.com/tauri-apps/tauri/../../pewsheen)) Add a new method to set title bar style dynamically on macOS. + +### Enhancements + +- [`a7354f9a8`](https://www.github.com/tauri-apps/tauri/commit/a7354f9a81d4db83ff3d34b29617717117ad64d2) ([#10171](https://www.github.com/tauri-apps/tauri/pull/10171) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Mark `AppHandle::restart` and `process::restart` as [diverging functions](https://doc.rust-lang.org/rust-by-example/fn/diverging.html). + +### Bug Fixes + +- [`4c239729c`](https://www.github.com/tauri-apps/tauri/commit/4c239729c3e1b899ecbc6793c3682848e8de1729) ([#10167](https://www.github.com/tauri-apps/tauri/pull/10167) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix deserialization of raw invoke requests when using `isolation` pattern. +- [`55733aba9`](https://www.github.com/tauri-apps/tauri/commit/55733aba9c5a5c8d664afea0c83d9337bc99387d) ([#10176](https://www.github.com/tauri-apps/tauri/pull/10176) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Move `PluginApi::register_ios_plugin` behind the `wry` Cargo feature as `Webview::with_webview` is only available when that feature is enabled. + +### Dependencies + +- Upgraded to `tauri-macros@2.0.0-beta.19` +- Upgraded to `tauri-build@2.0.0-beta.19` +- Upgraded to `tauri-runtime-wry@2.0.0-beta.20` +- Upgraded to `tauri-utils@2.0.0-beta.19` +- Upgraded to `tauri-runtime@2.0.0-beta.20` + +### Breaking Changes + +- [`ba9590aa9`](https://www.github.com/tauri-apps/tauri/commit/ba9590aa92a67a11fa1e559e506d87b7e643cc24) ([#9640](https://www.github.com/tauri-apps/tauri/pull/9640) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Added `Emitter` and `Listener` traits that defines what an emitter or a listener can do, this however comes with a few breaking changes: + + - Removed `Manager::listen_any`, use `Listener::listen_any` instead. + - Removed `Manager::once_any`, use `Listener::once_any` instead. + - Removed `Manager::unlisten`, use `Listener::unlisten` instead. + - Removed `Manager::emit`, use `Emitter::emit` instead. + - Removed `Manager::emit_to`, use `Emitter::emit_to` instead. + - Removed `Manager::emit_filter`, use `Emitter::emit_filter` instead. + - Removed `App/AppHandle::listen`, `WebviewWindow::listen`, `Window::listen` and `Webview::listen`, use `Listener::listen` instead. + - Removed `App/AppHandle::once`, `WebviewWindow::once`, `Window::once` and `Webview::once`, use `Listener::once` instead. + - Removed `App/AppHandle::unlisten`, `WebviewWindow::unlisten`, `Window::unlisten` and `Webview::unlisten`, use `Listener::unlisten` instead. +- [`261c9f942`](https://www.github.com/tauri-apps/tauri/commit/261c9f942de9a598b5c6cc504de6bddd1306113b) ([#10170](https://www.github.com/tauri-apps/tauri/pull/10170) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Renamed `DragDropEvent` enum variants to better convey when they are triggered: + + - `DragDropEvent::Dragged` -> `DragDropEvent::Enter` + - `DragDropEvent::DragOver` -> `DragDropEvent::Over` + - `DragDropEvent::Dropped` -> `DragDropEvent::Drop` + - `DragDropEvent::Cancelled` -> `DragDropEvent::Leave` + + This also comes with a change in the events being emitted to JS and Rust event listeners: + + - `tauri://drag` -> `tauri://drag-enter` + - `tauri://drop-over` -> `tauri://drag-over` + - `tauri://drop` -> `tauri://drag-drop` + - `tauri://drag-cancelled` -> `tauri://drag-leave` +- [`2b1ceb40d`](https://www.github.com/tauri-apps/tauri/commit/2b1ceb40d345aef42dd79438fa69ca7989ee0194) ([#10229](https://www.github.com/tauri-apps/tauri/pull/10229) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Renamed the JS `getCurrent` and `getAll` functions to a clearer name to avoid ambiguity: + + - `getCurrent` in `window` module has been renamed to `getCurrentWindow` + - `getCurrent` in `webview` module has been renamed to `getCurrentWebview` + - `getCurrent` in `webviewWindow` module has been renamed to `getCurrentWebviewWindow` + - `getAll` in `window` module has been renamed to `getAllWindows` + - `getAll` in `webview` module has been renamed to `getAllWebviews` + - `getAll` in `webviewWindow` module has been renamed to `getAllWebviewWindows` +- [`57612ab24`](https://www.github.com/tauri-apps/tauri/commit/57612ab24963b02d769ce408b0283ef552fb7b0d) ([#10139](https://www.github.com/tauri-apps/tauri/pull/10139) by [@Brendonovich](https://www.github.com/tauri-apps/tauri/../../Brendonovich)) Add `TSend` generic to `ipc::Channel` for typesafe `send` calls and type inspection in `tauri-specta` + +## \[2.0.0-beta.23] + +### New Features + +- [`148f04887`](https://www.github.com/tauri-apps/tauri/commit/148f048871caee21498b236c058b8890f2b66cc7) ([#9979](https://www.github.com/tauri-apps/tauri/pull/9979)) Add `defaultWindowIcon` to the JS `app` module to retrieve the default window icon in JS. +- [`5b769948a`](https://www.github.com/tauri-apps/tauri/commit/5b769948a81cac333f64c870a470ba6525bd5cd3) ([#9959](https://www.github.com/tauri-apps/tauri/pull/9959)) Add `include_image` macro to help embedding instances of `Image` struct at compile-time in rust to be used with window, menu or tray icons. +- [`ddaabda36`](https://www.github.com/tauri-apps/tauri/commit/ddaabda365ed5dc0780925049473989cbd1d7ea3) ([#9922](https://www.github.com/tauri-apps/tauri/pull/9922)) Add `WebviewWindowBuilder::on_download`. + +### Enhancements + +- [`cee0bfcd6`](https://www.github.com/tauri-apps/tauri/commit/cee0bfcd6c03c2a6794abca8f4fde700f3f818ba) ([#10092](https://www.github.com/tauri-apps/tauri/pull/10092)) Make `tray:default` and `menu:default` include all tray and menu permissions + +### Bug Fixes + +- [`e93ca1df3`](https://www.github.com/tauri-apps/tauri/commit/e93ca1df3b3948647f501f9f958e894ade6a27fb) ([#10138](https://www.github.com/tauri-apps/tauri/pull/10138)) Fix `InvokeBody::deserialize` method deserialization for `InvokeBody::Raw` variant +- [`e6e17ad1c`](https://www.github.com/tauri-apps/tauri/commit/e6e17ad1c8a6b53463946c407a354c250bd7e701) ([#9954](https://www.github.com/tauri-apps/tauri/pull/9954)) Add `std` feature to `raw-window-handle` crate so that using `default-features = false` on `tauri` crate can work +- [`f29b78811`](https://www.github.com/tauri-apps/tauri/commit/f29b78811080bc8313459f34545152d939c62bf6) ([#9862](https://www.github.com/tauri-apps/tauri/pull/9862)) On Windows, handle resizing undecorated windows natively which improves performance and fixes a couple of annoyances with previous JS implementation: + + - No more cursor flickering when moving the cursor across an edge. + - Can resize from top even when `data-tauri-drag-region` element exists there. + - Upon starting rezing, clicks don't go through elements behind it so no longer accidental clicks. + +### What's Changed + +- [`669b9c6b5`](https://www.github.com/tauri-apps/tauri/commit/669b9c6b5af791129b77ee440dacaa98288c906b) ([#9621](https://www.github.com/tauri-apps/tauri/pull/9621)) Set the gtk application to the identifier defined in `tauri.conf.json` to ensure the app uniqueness. + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-beta.18` +- Upgraded to `tauri-build@2.0.0-beta.18` +- Upgraded to `tauri-macros@2.0.0-beta.18` +- Upgraded to `tauri-runtime-wry@2.0.0-beta.19` +- Upgraded to `tauri-runtime@2.0.0-beta.19` +- [`f955f7b49`](https://www.github.com/tauri-apps/tauri/commit/f955f7b4903bcea376c0a8b430736f66c8cebf56) ([#9929](https://www.github.com/tauri-apps/tauri/pull/9929)) Switch from `dirs_next` to `dirs` as `dirs_next` is now unmaintained while `dirs` is +- [`d4c908cfb`](https://www.github.com/tauri-apps/tauri/commit/d4c908cfb8c567abdaf99b85f65f482ea81967e5) ([#10048](https://www.github.com/tauri-apps/tauri/pull/10048)) Update `windows` crate to version `0.57` and `webview2-com` crate to version `0.31` + +### Breaking Changes + +- [`3afe82894`](https://www.github.com/tauri-apps/tauri/commit/3afe8289407b53791e761764964a42207a7f7881) ([#10134](https://www.github.com/tauri-apps/tauri/pull/10134)) Changed `WebviewWindow::navigate` and `Webview::navigate` method signature to return a `Result` + ## \[2.0.0-beta.22] ### Bug Fixes diff --git a/core/tauri/Cargo.toml b/core/tauri/Cargo.toml index f8ab5215a..244d8450c 100644 --- a/core/tauri/Cargo.toml +++ b/core/tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tauri" -version = "2.0.0-beta.22" +version = "2.0.0-rc.1" description = "Make tiny, secure apps for all desktop platforms with Tauri" exclude = [ "/test", "/.scripts", "CHANGELOG.md", "/target" ] readme = "README.md" @@ -51,10 +51,10 @@ uuid = { version = "1", features = [ "v4" ], optional = true } url = "2" anyhow = "1.0" thiserror = "1.0" -tauri-runtime = { version = "2.0.0-beta.18", path = "../tauri-runtime" } -tauri-macros = { version = "2.0.0-beta.17", path = "../tauri-macros" } -tauri-utils = { version = "2.0.0-beta.17", features = [ "resources" ], path = "../tauri-utils" } -tauri-runtime-wry = { version = "2.0.0-beta.18", path = "../tauri-runtime-wry", optional = true } +tauri-runtime = { version = "2.0.0-rc.1", path = "../tauri-runtime" } +tauri-macros = { version = "2.0.0-rc.1", path = "../tauri-macros" } +tauri-utils = { version = "2.0.0-rc.1", features = [ "resources" ], path = "../tauri-utils" } +tauri-runtime-wry = { version = "2.0.0-rc.1", path = "../tauri-runtime-wry", optional = true } getrandom = "0.2" serde_repr = "0.1" state = "0.6" @@ -75,7 +75,7 @@ tracing = { version = "0.1", optional = true } heck = "0.5" log = "0.4" dunce = "1" -specta = { version = "^2.0.0-rc.9", optional = true, default-features = false, features = [ "function" ] } +specta = { version = "^2.0.0-rc.16", optional = true, default-features = false, features = [ "function", "derive" ] } [target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\", target_os = \"windows\", target_os = \"macos\"))".dependencies] muda = { version = "0.13.4", default-features = false, features = [ "serde" ] } @@ -110,8 +110,8 @@ swift-rs = "1.0.6" [build-dependencies] heck = "0.5" -tauri-build = { path = "../tauri-build/", default-features = false, version = "2.0.0-beta.17" } -tauri-utils = { path = "../tauri-utils/", version = "2.0.0-beta.17", features = [ "build" ] } +tauri-build = { path = "../tauri-build/", default-features = false, version = "2.0.0-rc.1" } +tauri-utils = { path = "../tauri-utils/", version = "2.0.0-rc.1", features = [ "build" ] } [dev-dependencies] proptest = "1.4.0" diff --git a/core/tauri/build.rs b/core/tauri/build.rs index 25990c02f..8169f2f68 100644 --- a/core/tauri/build.rs +++ b/core/tauri/build.rs @@ -18,8 +18,9 @@ use std::{ static CHECKED_FEATURES: OnceLock>> = OnceLock::new(); const PLUGINS: &[(&str, &[(&str, bool)])] = &[ // (plugin_name, &[(command, enabled-by_default)]) + // note that when adding new core plugins, they must be added to the ACL resolver aswell ( - "path", + "core:path", &[ ("resolve_directory", true), ("resolve", true), @@ -32,7 +33,7 @@ const PLUGINS: &[(&str, &[(&str, bool)])] = &[ ], ), ( - "event", + "core:event", &[ ("listen", true), ("unlisten", true), @@ -41,7 +42,7 @@ const PLUGINS: &[(&str, &[(&str, bool)])] = &[ ], ), ( - "window", + "core:window", &[ ("create", false), // getters @@ -92,6 +93,7 @@ const PLUGINS: &[(&str, &[(&str, bool)])] = &[ ("set_content_protected", false), ("set_size", false), ("set_min_size", false), + ("set_size_constraints", false), ("set_max_size", false), ("set_position", false), ("set_fullscreen", false), @@ -106,13 +108,14 @@ const PLUGINS: &[(&str, &[(&str, bool)])] = &[ ("start_resize_dragging", false), ("set_progress_bar", false), ("set_icon", false), + ("set_title_bar_style", false), ("toggle_maximize", false), // internal ("internal_toggle_maximize", true), ], ), ( - "webview", + "core:webview", &[ ("create_webview", false), ("create_webview_window", false), @@ -132,7 +135,7 @@ const PLUGINS: &[(&str, &[(&str, bool)])] = &[ ], ), ( - "app", + "core:app", &[ ("version", true), ("name", true), @@ -143,7 +146,7 @@ const PLUGINS: &[(&str, &[(&str, bool)])] = &[ ], ), ( - "image", + "core:image", &[ ("new", true), ("from_bytes", true), @@ -152,9 +155,9 @@ const PLUGINS: &[(&str, &[(&str, bool)])] = &[ ("size", true), ], ), - ("resources", &[("close", true)]), + ("core:resources", &[("close", true)]), ( - "menu", + "core:menu", &[ ("new", true), ("append", true), @@ -181,7 +184,7 @@ const PLUGINS: &[(&str, &[(&str, bool)])] = &[ ], ), ( - "tray", + "core:tray", &[ ("new", true), ("get_by_id", true), @@ -207,7 +210,7 @@ fn has_feature(feature: &str) -> bool { .push(feature.to_string()); // when a feature is enabled, Cargo sets the `CARGO_FEATURE_` env var to 1 - // https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts + // std::env::var(format!("CARGO_FEATURE_{}", AsShoutySnakeCase(feature))) .map(|x| x == "1") .unwrap_or(false) @@ -228,7 +231,7 @@ fn main() { alias("custom_protocol", custom_protocol); alias("dev", dev); - println!("cargo:dev={}", dev); + println!("cargo:dev={dev}"); let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap(); let mobile = target_os == "ios" || target_os == "android"; @@ -256,10 +259,7 @@ fn main() { if let Ok(kotlin_out_dir) = std::env::var("WRY_ANDROID_KOTLIN_FILES_OUT_DIR") { fn env_var(var: &str) -> String { std::env::var(var).unwrap_or_else(|_| { - panic!( - "`{}` is not set, which is needed to generate the kotlin files for android.", - var - ) + panic!("`{var}` is not set, which is needed to generate the kotlin files for android.") }) } @@ -323,13 +323,14 @@ fn main() { } fn define_permissions(out_dir: &Path) { - let license_header = r#"# Copyright 2019-2024 Tauri Programme within The Commons Conservancy + let license_header = r"# Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT -"#; +"; for (plugin, commands) in PLUGINS { - let permissions_out_dir = out_dir.join("permissions").join(plugin); + let plugin_directory_name = plugin.strip_prefix("core:").unwrap_or(plugin); + let permissions_out_dir = out_dir.join("permissions").join(plugin_directory_name); let autogenerated = permissions_out_dir.join(tauri_utils::acl::build::AUTOGENERATED_FOLDER_NAME); let commands_dir = autogenerated.join("commands"); @@ -345,7 +346,7 @@ fn define_permissions(out_dir: &Path) { .filter(|(_cmd, default)| *default) .map(|(cmd, _)| { let slugified_command = cmd.replace('_', "-"); - format!("\"allow-{}\"", slugified_command) + format!("\"allow-{slugified_command}\"") }) .collect::>() .join(", "); @@ -376,7 +377,9 @@ permissions = [{default_permissions}] ) .unwrap_or_else(|e| panic!("failed to define permissions for {plugin}: {e}")); - let docs_out_dir = Path::new("permissions").join(plugin).join("autogenerated"); + let docs_out_dir = Path::new("permissions") + .join(plugin_directory_name) + .join("autogenerated"); create_dir_all(&docs_out_dir).expect("failed to create plugin documentation directory"); tauri_utils::acl::build::generate_docs( &permissions, diff --git a/core/tauri/permissions/app/autogenerated/reference.md b/core/tauri/permissions/app/autogenerated/reference.md index 8991c7203..93e6e66d3 100644 --- a/core/tauri/permissions/app/autogenerated/reference.md +++ b/core/tauri/permissions/app/autogenerated/reference.md @@ -18,7 +18,7 @@ Default permissions for the plugin. -`app:allow-app-hide` +`core:app:allow-app-hide` @@ -31,7 +31,7 @@ Enables the app_hide command without any pre-configured scope. -`app:deny-app-hide` +`core:app:deny-app-hide` @@ -44,7 +44,7 @@ Denies the app_hide command without any pre-configured scope. -`app:allow-app-show` +`core:app:allow-app-show` @@ -57,7 +57,7 @@ Enables the app_show command without any pre-configured scope. -`app:deny-app-show` +`core:app:deny-app-show` @@ -70,7 +70,7 @@ Denies the app_show command without any pre-configured scope. -`app:allow-default-window-icon` +`core:app:allow-default-window-icon` @@ -83,7 +83,7 @@ Enables the default_window_icon command without any pre-configured scope. -`app:deny-default-window-icon` +`core:app:deny-default-window-icon` @@ -96,7 +96,7 @@ Denies the default_window_icon command without any pre-configured scope. -`app:allow-name` +`core:app:allow-name` @@ -109,7 +109,7 @@ Enables the name command without any pre-configured scope. -`app:deny-name` +`core:app:deny-name` @@ -122,7 +122,7 @@ Denies the name command without any pre-configured scope. -`app:allow-tauri-version` +`core:app:allow-tauri-version` @@ -135,7 +135,7 @@ Enables the tauri_version command without any pre-configured scope. -`app:deny-tauri-version` +`core:app:deny-tauri-version` @@ -148,7 +148,7 @@ Denies the tauri_version command without any pre-configured scope. -`app:allow-version` +`core:app:allow-version` @@ -161,7 +161,7 @@ Enables the version command without any pre-configured scope. -`app:deny-version` +`core:app:deny-version` diff --git a/core/tauri/permissions/event/autogenerated/reference.md b/core/tauri/permissions/event/autogenerated/reference.md index e5a3ef8cd..b541931a3 100644 --- a/core/tauri/permissions/event/autogenerated/reference.md +++ b/core/tauri/permissions/event/autogenerated/reference.md @@ -19,7 +19,7 @@ Default permissions for the plugin. -`event:allow-emit` +`core:event:allow-emit` @@ -32,7 +32,7 @@ Enables the emit command without any pre-configured scope. -`event:deny-emit` +`core:event:deny-emit` @@ -45,7 +45,7 @@ Denies the emit command without any pre-configured scope. -`event:allow-emit-to` +`core:event:allow-emit-to` @@ -58,7 +58,7 @@ Enables the emit_to command without any pre-configured scope. -`event:deny-emit-to` +`core:event:deny-emit-to` @@ -71,7 +71,7 @@ Denies the emit_to command without any pre-configured scope. -`event:allow-listen` +`core:event:allow-listen` @@ -84,7 +84,7 @@ Enables the listen command without any pre-configured scope. -`event:deny-listen` +`core:event:deny-listen` @@ -97,7 +97,7 @@ Denies the listen command without any pre-configured scope. -`event:allow-unlisten` +`core:event:allow-unlisten` @@ -110,7 +110,7 @@ Enables the unlisten command without any pre-configured scope. -`event:deny-unlisten` +`core:event:deny-unlisten` diff --git a/core/tauri/permissions/image/autogenerated/reference.md b/core/tauri/permissions/image/autogenerated/reference.md index ea4eaf480..b38fd327a 100644 --- a/core/tauri/permissions/image/autogenerated/reference.md +++ b/core/tauri/permissions/image/autogenerated/reference.md @@ -20,7 +20,7 @@ Default permissions for the plugin. -`image:allow-from-bytes` +`core:image:allow-from-bytes` @@ -33,7 +33,7 @@ Enables the from_bytes command without any pre-configured scope. -`image:deny-from-bytes` +`core:image:deny-from-bytes` @@ -46,7 +46,7 @@ Denies the from_bytes command without any pre-configured scope. -`image:allow-from-path` +`core:image:allow-from-path` @@ -59,7 +59,7 @@ Enables the from_path command without any pre-configured scope. -`image:deny-from-path` +`core:image:deny-from-path` @@ -72,7 +72,7 @@ Denies the from_path command without any pre-configured scope. -`image:allow-new` +`core:image:allow-new` @@ -85,7 +85,7 @@ Enables the new command without any pre-configured scope. -`image:deny-new` +`core:image:deny-new` @@ -98,7 +98,7 @@ Denies the new command without any pre-configured scope. -`image:allow-rgba` +`core:image:allow-rgba` @@ -111,7 +111,7 @@ Enables the rgba command without any pre-configured scope. -`image:deny-rgba` +`core:image:deny-rgba` @@ -124,7 +124,7 @@ Denies the rgba command without any pre-configured scope. -`image:allow-size` +`core:image:allow-size` @@ -137,7 +137,7 @@ Enables the size command without any pre-configured scope. -`image:deny-size` +`core:image:deny-size` diff --git a/core/tauri/permissions/menu/autogenerated/reference.md b/core/tauri/permissions/menu/autogenerated/reference.md index 9fb194e43..4f1f1a3a4 100644 --- a/core/tauri/permissions/menu/autogenerated/reference.md +++ b/core/tauri/permissions/menu/autogenerated/reference.md @@ -37,7 +37,7 @@ Default permissions for the plugin. -`menu:allow-append` +`core:menu:allow-append` @@ -50,7 +50,7 @@ Enables the append command without any pre-configured scope. -`menu:deny-append` +`core:menu:deny-append` @@ -63,7 +63,7 @@ Denies the append command without any pre-configured scope. -`menu:allow-create-default` +`core:menu:allow-create-default` @@ -76,7 +76,7 @@ Enables the create_default command without any pre-configured scope. -`menu:deny-create-default` +`core:menu:deny-create-default` @@ -89,7 +89,7 @@ Denies the create_default command without any pre-configured scope. -`menu:allow-get` +`core:menu:allow-get` @@ -102,7 +102,7 @@ Enables the get command without any pre-configured scope. -`menu:deny-get` +`core:menu:deny-get` @@ -115,7 +115,7 @@ Denies the get command without any pre-configured scope. -`menu:allow-insert` +`core:menu:allow-insert` @@ -128,7 +128,7 @@ Enables the insert command without any pre-configured scope. -`menu:deny-insert` +`core:menu:deny-insert` @@ -141,7 +141,7 @@ Denies the insert command without any pre-configured scope. -`menu:allow-is-checked` +`core:menu:allow-is-checked` @@ -154,7 +154,7 @@ Enables the is_checked command without any pre-configured scope. -`menu:deny-is-checked` +`core:menu:deny-is-checked` @@ -167,7 +167,7 @@ Denies the is_checked command without any pre-configured scope. -`menu:allow-is-enabled` +`core:menu:allow-is-enabled` @@ -180,7 +180,7 @@ Enables the is_enabled command without any pre-configured scope. -`menu:deny-is-enabled` +`core:menu:deny-is-enabled` @@ -193,7 +193,7 @@ Denies the is_enabled command without any pre-configured scope. -`menu:allow-items` +`core:menu:allow-items` @@ -206,7 +206,7 @@ Enables the items command without any pre-configured scope. -`menu:deny-items` +`core:menu:deny-items` @@ -219,7 +219,7 @@ Denies the items command without any pre-configured scope. -`menu:allow-new` +`core:menu:allow-new` @@ -232,7 +232,7 @@ Enables the new command without any pre-configured scope. -`menu:deny-new` +`core:menu:deny-new` @@ -245,7 +245,7 @@ Denies the new command without any pre-configured scope. -`menu:allow-popup` +`core:menu:allow-popup` @@ -258,7 +258,7 @@ Enables the popup command without any pre-configured scope. -`menu:deny-popup` +`core:menu:deny-popup` @@ -271,7 +271,7 @@ Denies the popup command without any pre-configured scope. -`menu:allow-prepend` +`core:menu:allow-prepend` @@ -284,7 +284,7 @@ Enables the prepend command without any pre-configured scope. -`menu:deny-prepend` +`core:menu:deny-prepend` @@ -297,7 +297,7 @@ Denies the prepend command without any pre-configured scope. -`menu:allow-remove` +`core:menu:allow-remove` @@ -310,7 +310,7 @@ Enables the remove command without any pre-configured scope. -`menu:deny-remove` +`core:menu:deny-remove` @@ -323,7 +323,7 @@ Denies the remove command without any pre-configured scope. -`menu:allow-remove-at` +`core:menu:allow-remove-at` @@ -336,7 +336,7 @@ Enables the remove_at command without any pre-configured scope. -`menu:deny-remove-at` +`core:menu:deny-remove-at` @@ -349,7 +349,7 @@ Denies the remove_at command without any pre-configured scope. -`menu:allow-set-accelerator` +`core:menu:allow-set-accelerator` @@ -362,7 +362,7 @@ Enables the set_accelerator command without any pre-configured scope. -`menu:deny-set-accelerator` +`core:menu:deny-set-accelerator` @@ -375,7 +375,7 @@ Denies the set_accelerator command without any pre-configured scope. -`menu:allow-set-as-app-menu` +`core:menu:allow-set-as-app-menu` @@ -388,7 +388,7 @@ Enables the set_as_app_menu command without any pre-configured scope. -`menu:deny-set-as-app-menu` +`core:menu:deny-set-as-app-menu` @@ -401,7 +401,7 @@ Denies the set_as_app_menu command without any pre-configured scope. -`menu:allow-set-as-help-menu-for-nsapp` +`core:menu:allow-set-as-help-menu-for-nsapp` @@ -414,7 +414,7 @@ Enables the set_as_help_menu_for_nsapp command without any pre-configured scope. -`menu:deny-set-as-help-menu-for-nsapp` +`core:menu:deny-set-as-help-menu-for-nsapp` @@ -427,7 +427,7 @@ Denies the set_as_help_menu_for_nsapp command without any pre-configured scope. -`menu:allow-set-as-window-menu` +`core:menu:allow-set-as-window-menu` @@ -440,7 +440,7 @@ Enables the set_as_window_menu command without any pre-configured scope. -`menu:deny-set-as-window-menu` +`core:menu:deny-set-as-window-menu` @@ -453,7 +453,7 @@ Denies the set_as_window_menu command without any pre-configured scope. -`menu:allow-set-as-windows-menu-for-nsapp` +`core:menu:allow-set-as-windows-menu-for-nsapp` @@ -466,7 +466,7 @@ Enables the set_as_windows_menu_for_nsapp command without any pre-configured sco -`menu:deny-set-as-windows-menu-for-nsapp` +`core:menu:deny-set-as-windows-menu-for-nsapp` @@ -479,7 +479,7 @@ Denies the set_as_windows_menu_for_nsapp command without any pre-configured scop -`menu:allow-set-checked` +`core:menu:allow-set-checked` @@ -492,7 +492,7 @@ Enables the set_checked command without any pre-configured scope. -`menu:deny-set-checked` +`core:menu:deny-set-checked` @@ -505,7 +505,7 @@ Denies the set_checked command without any pre-configured scope. -`menu:allow-set-enabled` +`core:menu:allow-set-enabled` @@ -518,7 +518,7 @@ Enables the set_enabled command without any pre-configured scope. -`menu:deny-set-enabled` +`core:menu:deny-set-enabled` @@ -531,7 +531,7 @@ Denies the set_enabled command without any pre-configured scope. -`menu:allow-set-icon` +`core:menu:allow-set-icon` @@ -544,7 +544,7 @@ Enables the set_icon command without any pre-configured scope. -`menu:deny-set-icon` +`core:menu:deny-set-icon` @@ -557,7 +557,7 @@ Denies the set_icon command without any pre-configured scope. -`menu:allow-set-text` +`core:menu:allow-set-text` @@ -570,7 +570,7 @@ Enables the set_text command without any pre-configured scope. -`menu:deny-set-text` +`core:menu:deny-set-text` @@ -583,7 +583,7 @@ Denies the set_text command without any pre-configured scope. -`menu:allow-text` +`core:menu:allow-text` @@ -596,7 +596,7 @@ Enables the text command without any pre-configured scope. -`menu:deny-text` +`core:menu:deny-text` diff --git a/core/tauri/permissions/path/autogenerated/reference.md b/core/tauri/permissions/path/autogenerated/reference.md index 3765933bc..36a9c8ade 100644 --- a/core/tauri/permissions/path/autogenerated/reference.md +++ b/core/tauri/permissions/path/autogenerated/reference.md @@ -23,7 +23,7 @@ Default permissions for the plugin. -`path:allow-basename` +`core:path:allow-basename` @@ -36,7 +36,7 @@ Enables the basename command without any pre-configured scope. -`path:deny-basename` +`core:path:deny-basename` @@ -49,7 +49,7 @@ Denies the basename command without any pre-configured scope. -`path:allow-dirname` +`core:path:allow-dirname` @@ -62,7 +62,7 @@ Enables the dirname command without any pre-configured scope. -`path:deny-dirname` +`core:path:deny-dirname` @@ -75,7 +75,7 @@ Denies the dirname command without any pre-configured scope. -`path:allow-extname` +`core:path:allow-extname` @@ -88,7 +88,7 @@ Enables the extname command without any pre-configured scope. -`path:deny-extname` +`core:path:deny-extname` @@ -101,7 +101,7 @@ Denies the extname command without any pre-configured scope. -`path:allow-is-absolute` +`core:path:allow-is-absolute` @@ -114,7 +114,7 @@ Enables the is_absolute command without any pre-configured scope. -`path:deny-is-absolute` +`core:path:deny-is-absolute` @@ -127,7 +127,7 @@ Denies the is_absolute command without any pre-configured scope. -`path:allow-join` +`core:path:allow-join` @@ -140,7 +140,7 @@ Enables the join command without any pre-configured scope. -`path:deny-join` +`core:path:deny-join` @@ -153,7 +153,7 @@ Denies the join command without any pre-configured scope. -`path:allow-normalize` +`core:path:allow-normalize` @@ -166,7 +166,7 @@ Enables the normalize command without any pre-configured scope. -`path:deny-normalize` +`core:path:deny-normalize` @@ -179,7 +179,7 @@ Denies the normalize command without any pre-configured scope. -`path:allow-resolve` +`core:path:allow-resolve` @@ -192,7 +192,7 @@ Enables the resolve command without any pre-configured scope. -`path:deny-resolve` +`core:path:deny-resolve` @@ -205,7 +205,7 @@ Denies the resolve command without any pre-configured scope. -`path:allow-resolve-directory` +`core:path:allow-resolve-directory` @@ -218,7 +218,7 @@ Enables the resolve_directory command without any pre-configured scope. -`path:deny-resolve-directory` +`core:path:deny-resolve-directory` diff --git a/core/tauri/permissions/resources/autogenerated/reference.md b/core/tauri/permissions/resources/autogenerated/reference.md index 2a41e9a2b..247d70287 100644 --- a/core/tauri/permissions/resources/autogenerated/reference.md +++ b/core/tauri/permissions/resources/autogenerated/reference.md @@ -16,7 +16,7 @@ Default permissions for the plugin. -`resources:allow-close` +`core:resources:allow-close` @@ -29,7 +29,7 @@ Enables the close command without any pre-configured scope. -`resources:deny-close` +`core:resources:deny-close` diff --git a/core/tauri/permissions/tray/autogenerated/reference.md b/core/tauri/permissions/tray/autogenerated/reference.md index 1e7d1185e..a1cb0eb01 100644 --- a/core/tauri/permissions/tray/autogenerated/reference.md +++ b/core/tauri/permissions/tray/autogenerated/reference.md @@ -26,7 +26,7 @@ Default permissions for the plugin. -`tray:allow-get-by-id` +`core:tray:allow-get-by-id` @@ -39,7 +39,7 @@ Enables the get_by_id command without any pre-configured scope. -`tray:deny-get-by-id` +`core:tray:deny-get-by-id` @@ -52,7 +52,7 @@ Denies the get_by_id command without any pre-configured scope. -`tray:allow-new` +`core:tray:allow-new` @@ -65,7 +65,7 @@ Enables the new command without any pre-configured scope. -`tray:deny-new` +`core:tray:deny-new` @@ -78,7 +78,7 @@ Denies the new command without any pre-configured scope. -`tray:allow-remove-by-id` +`core:tray:allow-remove-by-id` @@ -91,7 +91,7 @@ Enables the remove_by_id command without any pre-configured scope. -`tray:deny-remove-by-id` +`core:tray:deny-remove-by-id` @@ -104,7 +104,7 @@ Denies the remove_by_id command without any pre-configured scope. -`tray:allow-set-icon` +`core:tray:allow-set-icon` @@ -117,7 +117,7 @@ Enables the set_icon command without any pre-configured scope. -`tray:deny-set-icon` +`core:tray:deny-set-icon` @@ -130,7 +130,7 @@ Denies the set_icon command without any pre-configured scope. -`tray:allow-set-icon-as-template` +`core:tray:allow-set-icon-as-template` @@ -143,7 +143,7 @@ Enables the set_icon_as_template command without any pre-configured scope. -`tray:deny-set-icon-as-template` +`core:tray:deny-set-icon-as-template` @@ -156,7 +156,7 @@ Denies the set_icon_as_template command without any pre-configured scope. -`tray:allow-set-menu` +`core:tray:allow-set-menu` @@ -169,7 +169,7 @@ Enables the set_menu command without any pre-configured scope. -`tray:deny-set-menu` +`core:tray:deny-set-menu` @@ -182,7 +182,7 @@ Denies the set_menu command without any pre-configured scope. -`tray:allow-set-show-menu-on-left-click` +`core:tray:allow-set-show-menu-on-left-click` @@ -195,7 +195,7 @@ Enables the set_show_menu_on_left_click command without any pre-configured scope -`tray:deny-set-show-menu-on-left-click` +`core:tray:deny-set-show-menu-on-left-click` @@ -208,7 +208,7 @@ Denies the set_show_menu_on_left_click command without any pre-configured scope. -`tray:allow-set-temp-dir-path` +`core:tray:allow-set-temp-dir-path` @@ -221,7 +221,7 @@ Enables the set_temp_dir_path command without any pre-configured scope. -`tray:deny-set-temp-dir-path` +`core:tray:deny-set-temp-dir-path` @@ -234,7 +234,7 @@ Denies the set_temp_dir_path command without any pre-configured scope. -`tray:allow-set-title` +`core:tray:allow-set-title` @@ -247,7 +247,7 @@ Enables the set_title command without any pre-configured scope. -`tray:deny-set-title` +`core:tray:deny-set-title` @@ -260,7 +260,7 @@ Denies the set_title command without any pre-configured scope. -`tray:allow-set-tooltip` +`core:tray:allow-set-tooltip` @@ -273,7 +273,7 @@ Enables the set_tooltip command without any pre-configured scope. -`tray:deny-set-tooltip` +`core:tray:deny-set-tooltip` @@ -286,7 +286,7 @@ Denies the set_tooltip command without any pre-configured scope. -`tray:allow-set-visible` +`core:tray:allow-set-visible` @@ -299,7 +299,7 @@ Enables the set_visible command without any pre-configured scope. -`tray:deny-set-visible` +`core:tray:deny-set-visible` diff --git a/core/tauri/permissions/webview/autogenerated/reference.md b/core/tauri/permissions/webview/autogenerated/reference.md index 2f994373a..1b47019a8 100644 --- a/core/tauri/permissions/webview/autogenerated/reference.md +++ b/core/tauri/permissions/webview/autogenerated/reference.md @@ -18,7 +18,7 @@ Default permissions for the plugin. -`webview:allow-create-webview` +`core:webview:allow-create-webview` @@ -31,7 +31,7 @@ Enables the create_webview command without any pre-configured scope. -`webview:deny-create-webview` +`core:webview:deny-create-webview` @@ -44,7 +44,7 @@ Denies the create_webview command without any pre-configured scope. -`webview:allow-create-webview-window` +`core:webview:allow-create-webview-window` @@ -57,7 +57,7 @@ Enables the create_webview_window command without any pre-configured scope. -`webview:deny-create-webview-window` +`core:webview:deny-create-webview-window` @@ -70,7 +70,7 @@ Denies the create_webview_window command without any pre-configured scope. -`webview:allow-internal-toggle-devtools` +`core:webview:allow-internal-toggle-devtools` @@ -83,7 +83,7 @@ Enables the internal_toggle_devtools command without any pre-configured scope. -`webview:deny-internal-toggle-devtools` +`core:webview:deny-internal-toggle-devtools` @@ -96,7 +96,7 @@ Denies the internal_toggle_devtools command without any pre-configured scope. -`webview:allow-print` +`core:webview:allow-print` @@ -109,7 +109,7 @@ Enables the print command without any pre-configured scope. -`webview:deny-print` +`core:webview:deny-print` @@ -122,7 +122,7 @@ Denies the print command without any pre-configured scope. -`webview:allow-reparent` +`core:webview:allow-reparent` @@ -135,7 +135,7 @@ Enables the reparent command without any pre-configured scope. -`webview:deny-reparent` +`core:webview:deny-reparent` @@ -148,7 +148,7 @@ Denies the reparent command without any pre-configured scope. -`webview:allow-set-webview-focus` +`core:webview:allow-set-webview-focus` @@ -161,7 +161,7 @@ Enables the set_webview_focus command without any pre-configured scope. -`webview:deny-set-webview-focus` +`core:webview:deny-set-webview-focus` @@ -174,7 +174,7 @@ Denies the set_webview_focus command without any pre-configured scope. -`webview:allow-set-webview-position` +`core:webview:allow-set-webview-position` @@ -187,7 +187,7 @@ Enables the set_webview_position command without any pre-configured scope. -`webview:deny-set-webview-position` +`core:webview:deny-set-webview-position` @@ -200,7 +200,7 @@ Denies the set_webview_position command without any pre-configured scope. -`webview:allow-set-webview-size` +`core:webview:allow-set-webview-size` @@ -213,7 +213,7 @@ Enables the set_webview_size command without any pre-configured scope. -`webview:deny-set-webview-size` +`core:webview:deny-set-webview-size` @@ -226,7 +226,7 @@ Denies the set_webview_size command without any pre-configured scope. -`webview:allow-set-webview-zoom` +`core:webview:allow-set-webview-zoom` @@ -239,7 +239,7 @@ Enables the set_webview_zoom command without any pre-configured scope. -`webview:deny-set-webview-zoom` +`core:webview:deny-set-webview-zoom` @@ -252,7 +252,7 @@ Denies the set_webview_zoom command without any pre-configured scope. -`webview:allow-webview-close` +`core:webview:allow-webview-close` @@ -265,7 +265,7 @@ Enables the webview_close command without any pre-configured scope. -`webview:deny-webview-close` +`core:webview:deny-webview-close` @@ -278,7 +278,7 @@ Denies the webview_close command without any pre-configured scope. -`webview:allow-webview-position` +`core:webview:allow-webview-position` @@ -291,7 +291,7 @@ Enables the webview_position command without any pre-configured scope. -`webview:deny-webview-position` +`core:webview:deny-webview-position` @@ -304,7 +304,7 @@ Denies the webview_position command without any pre-configured scope. -`webview:allow-webview-size` +`core:webview:allow-webview-size` @@ -317,7 +317,7 @@ Enables the webview_size command without any pre-configured scope. -`webview:deny-webview-size` +`core:webview:deny-webview-size` diff --git a/core/tauri/permissions/window/autogenerated/reference.md b/core/tauri/permissions/window/autogenerated/reference.md index eaf0910fd..d77549a26 100644 --- a/core/tauri/permissions/window/autogenerated/reference.md +++ b/core/tauri/permissions/window/autogenerated/reference.md @@ -38,7 +38,7 @@ Default permissions for the plugin. -`window:allow-available-monitors` +`core:window:allow-available-monitors` @@ -51,7 +51,7 @@ Enables the available_monitors command without any pre-configured scope. -`window:deny-available-monitors` +`core:window:deny-available-monitors` @@ -64,7 +64,7 @@ Denies the available_monitors command without any pre-configured scope. -`window:allow-center` +`core:window:allow-center` @@ -77,7 +77,7 @@ Enables the center command without any pre-configured scope. -`window:deny-center` +`core:window:deny-center` @@ -90,7 +90,7 @@ Denies the center command without any pre-configured scope. -`window:allow-close` +`core:window:allow-close` @@ -103,7 +103,7 @@ Enables the close command without any pre-configured scope. -`window:deny-close` +`core:window:deny-close` @@ -116,7 +116,7 @@ Denies the close command without any pre-configured scope. -`window:allow-create` +`core:window:allow-create` @@ -129,7 +129,7 @@ Enables the create command without any pre-configured scope. -`window:deny-create` +`core:window:deny-create` @@ -142,7 +142,7 @@ Denies the create command without any pre-configured scope. -`window:allow-current-monitor` +`core:window:allow-current-monitor` @@ -155,7 +155,7 @@ Enables the current_monitor command without any pre-configured scope. -`window:deny-current-monitor` +`core:window:deny-current-monitor` @@ -168,7 +168,7 @@ Denies the current_monitor command without any pre-configured scope. -`window:allow-cursor-position` +`core:window:allow-cursor-position` @@ -181,7 +181,7 @@ Enables the cursor_position command without any pre-configured scope. -`window:deny-cursor-position` +`core:window:deny-cursor-position` @@ -194,7 +194,7 @@ Denies the cursor_position command without any pre-configured scope. -`window:allow-destroy` +`core:window:allow-destroy` @@ -207,7 +207,7 @@ Enables the destroy command without any pre-configured scope. -`window:deny-destroy` +`core:window:deny-destroy` @@ -220,7 +220,7 @@ Denies the destroy command without any pre-configured scope. -`window:allow-hide` +`core:window:allow-hide` @@ -233,7 +233,7 @@ Enables the hide command without any pre-configured scope. -`window:deny-hide` +`core:window:deny-hide` @@ -246,7 +246,7 @@ Denies the hide command without any pre-configured scope. -`window:allow-inner-position` +`core:window:allow-inner-position` @@ -259,7 +259,7 @@ Enables the inner_position command without any pre-configured scope. -`window:deny-inner-position` +`core:window:deny-inner-position` @@ -272,7 +272,7 @@ Denies the inner_position command without any pre-configured scope. -`window:allow-inner-size` +`core:window:allow-inner-size` @@ -285,7 +285,7 @@ Enables the inner_size command without any pre-configured scope. -`window:deny-inner-size` +`core:window:deny-inner-size` @@ -298,7 +298,7 @@ Denies the inner_size command without any pre-configured scope. -`window:allow-internal-toggle-maximize` +`core:window:allow-internal-toggle-maximize` @@ -311,7 +311,7 @@ Enables the internal_toggle_maximize command without any pre-configured scope. -`window:deny-internal-toggle-maximize` +`core:window:deny-internal-toggle-maximize` @@ -324,7 +324,7 @@ Denies the internal_toggle_maximize command without any pre-configured scope. -`window:allow-is-closable` +`core:window:allow-is-closable` @@ -337,7 +337,7 @@ Enables the is_closable command without any pre-configured scope. -`window:deny-is-closable` +`core:window:deny-is-closable` @@ -350,7 +350,7 @@ Denies the is_closable command without any pre-configured scope. -`window:allow-is-decorated` +`core:window:allow-is-decorated` @@ -363,7 +363,7 @@ Enables the is_decorated command without any pre-configured scope. -`window:deny-is-decorated` +`core:window:deny-is-decorated` @@ -376,7 +376,7 @@ Denies the is_decorated command without any pre-configured scope. -`window:allow-is-focused` +`core:window:allow-is-focused` @@ -389,7 +389,7 @@ Enables the is_focused command without any pre-configured scope. -`window:deny-is-focused` +`core:window:deny-is-focused` @@ -402,7 +402,7 @@ Denies the is_focused command without any pre-configured scope. -`window:allow-is-fullscreen` +`core:window:allow-is-fullscreen` @@ -415,7 +415,7 @@ Enables the is_fullscreen command without any pre-configured scope. -`window:deny-is-fullscreen` +`core:window:deny-is-fullscreen` @@ -428,7 +428,7 @@ Denies the is_fullscreen command without any pre-configured scope. -`window:allow-is-maximizable` +`core:window:allow-is-maximizable` @@ -441,7 +441,7 @@ Enables the is_maximizable command without any pre-configured scope. -`window:deny-is-maximizable` +`core:window:deny-is-maximizable` @@ -454,7 +454,7 @@ Denies the is_maximizable command without any pre-configured scope. -`window:allow-is-maximized` +`core:window:allow-is-maximized` @@ -467,7 +467,7 @@ Enables the is_maximized command without any pre-configured scope. -`window:deny-is-maximized` +`core:window:deny-is-maximized` @@ -480,7 +480,7 @@ Denies the is_maximized command without any pre-configured scope. -`window:allow-is-minimizable` +`core:window:allow-is-minimizable` @@ -493,7 +493,7 @@ Enables the is_minimizable command without any pre-configured scope. -`window:deny-is-minimizable` +`core:window:deny-is-minimizable` @@ -506,7 +506,7 @@ Denies the is_minimizable command without any pre-configured scope. -`window:allow-is-minimized` +`core:window:allow-is-minimized` @@ -519,7 +519,7 @@ Enables the is_minimized command without any pre-configured scope. -`window:deny-is-minimized` +`core:window:deny-is-minimized` @@ -532,7 +532,7 @@ Denies the is_minimized command without any pre-configured scope. -`window:allow-is-resizable` +`core:window:allow-is-resizable` @@ -545,7 +545,7 @@ Enables the is_resizable command without any pre-configured scope. -`window:deny-is-resizable` +`core:window:deny-is-resizable` @@ -558,7 +558,7 @@ Denies the is_resizable command without any pre-configured scope. -`window:allow-is-visible` +`core:window:allow-is-visible` @@ -571,7 +571,7 @@ Enables the is_visible command without any pre-configured scope. -`window:deny-is-visible` +`core:window:deny-is-visible` @@ -584,7 +584,7 @@ Denies the is_visible command without any pre-configured scope. -`window:allow-maximize` +`core:window:allow-maximize` @@ -597,7 +597,7 @@ Enables the maximize command without any pre-configured scope. -`window:deny-maximize` +`core:window:deny-maximize` @@ -610,7 +610,7 @@ Denies the maximize command without any pre-configured scope. -`window:allow-minimize` +`core:window:allow-minimize` @@ -623,7 +623,7 @@ Enables the minimize command without any pre-configured scope. -`window:deny-minimize` +`core:window:deny-minimize` @@ -636,7 +636,7 @@ Denies the minimize command without any pre-configured scope. -`window:allow-monitor-from-point` +`core:window:allow-monitor-from-point` @@ -649,7 +649,7 @@ Enables the monitor_from_point command without any pre-configured scope. -`window:deny-monitor-from-point` +`core:window:deny-monitor-from-point` @@ -662,7 +662,7 @@ Denies the monitor_from_point command without any pre-configured scope. -`window:allow-outer-position` +`core:window:allow-outer-position` @@ -675,7 +675,7 @@ Enables the outer_position command without any pre-configured scope. -`window:deny-outer-position` +`core:window:deny-outer-position` @@ -688,7 +688,7 @@ Denies the outer_position command without any pre-configured scope. -`window:allow-outer-size` +`core:window:allow-outer-size` @@ -701,7 +701,7 @@ Enables the outer_size command without any pre-configured scope. -`window:deny-outer-size` +`core:window:deny-outer-size` @@ -714,7 +714,7 @@ Denies the outer_size command without any pre-configured scope. -`window:allow-primary-monitor` +`core:window:allow-primary-monitor` @@ -727,7 +727,7 @@ Enables the primary_monitor command without any pre-configured scope. -`window:deny-primary-monitor` +`core:window:deny-primary-monitor` @@ -740,7 +740,7 @@ Denies the primary_monitor command without any pre-configured scope. -`window:allow-request-user-attention` +`core:window:allow-request-user-attention` @@ -753,7 +753,7 @@ Enables the request_user_attention command without any pre-configured scope. -`window:deny-request-user-attention` +`core:window:deny-request-user-attention` @@ -766,7 +766,7 @@ Denies the request_user_attention command without any pre-configured scope. -`window:allow-scale-factor` +`core:window:allow-scale-factor` @@ -779,7 +779,7 @@ Enables the scale_factor command without any pre-configured scope. -`window:deny-scale-factor` +`core:window:deny-scale-factor` @@ -792,7 +792,7 @@ Denies the scale_factor command without any pre-configured scope. -`window:allow-set-always-on-bottom` +`core:window:allow-set-always-on-bottom` @@ -805,7 +805,7 @@ Enables the set_always_on_bottom command without any pre-configured scope. -`window:deny-set-always-on-bottom` +`core:window:deny-set-always-on-bottom` @@ -818,7 +818,7 @@ Denies the set_always_on_bottom command without any pre-configured scope. -`window:allow-set-always-on-top` +`core:window:allow-set-always-on-top` @@ -831,7 +831,7 @@ Enables the set_always_on_top command without any pre-configured scope. -`window:deny-set-always-on-top` +`core:window:deny-set-always-on-top` @@ -844,7 +844,7 @@ Denies the set_always_on_top command without any pre-configured scope. -`window:allow-set-closable` +`core:window:allow-set-closable` @@ -857,7 +857,7 @@ Enables the set_closable command without any pre-configured scope. -`window:deny-set-closable` +`core:window:deny-set-closable` @@ -870,7 +870,7 @@ Denies the set_closable command without any pre-configured scope. -`window:allow-set-content-protected` +`core:window:allow-set-content-protected` @@ -883,7 +883,7 @@ Enables the set_content_protected command without any pre-configured scope. -`window:deny-set-content-protected` +`core:window:deny-set-content-protected` @@ -896,7 +896,7 @@ Denies the set_content_protected command without any pre-configured scope. -`window:allow-set-cursor-grab` +`core:window:allow-set-cursor-grab` @@ -909,7 +909,7 @@ Enables the set_cursor_grab command without any pre-configured scope. -`window:deny-set-cursor-grab` +`core:window:deny-set-cursor-grab` @@ -922,7 +922,7 @@ Denies the set_cursor_grab command without any pre-configured scope. -`window:allow-set-cursor-icon` +`core:window:allow-set-cursor-icon` @@ -935,7 +935,7 @@ Enables the set_cursor_icon command without any pre-configured scope. -`window:deny-set-cursor-icon` +`core:window:deny-set-cursor-icon` @@ -948,7 +948,7 @@ Denies the set_cursor_icon command without any pre-configured scope. -`window:allow-set-cursor-position` +`core:window:allow-set-cursor-position` @@ -961,7 +961,7 @@ Enables the set_cursor_position command without any pre-configured scope. -`window:deny-set-cursor-position` +`core:window:deny-set-cursor-position` @@ -974,7 +974,7 @@ Denies the set_cursor_position command without any pre-configured scope. -`window:allow-set-cursor-visible` +`core:window:allow-set-cursor-visible` @@ -987,7 +987,7 @@ Enables the set_cursor_visible command without any pre-configured scope. -`window:deny-set-cursor-visible` +`core:window:deny-set-cursor-visible` @@ -1000,7 +1000,7 @@ Denies the set_cursor_visible command without any pre-configured scope. -`window:allow-set-decorations` +`core:window:allow-set-decorations` @@ -1013,7 +1013,7 @@ Enables the set_decorations command without any pre-configured scope. -`window:deny-set-decorations` +`core:window:deny-set-decorations` @@ -1026,7 +1026,7 @@ Denies the set_decorations command without any pre-configured scope. -`window:allow-set-effects` +`core:window:allow-set-effects` @@ -1039,7 +1039,7 @@ Enables the set_effects command without any pre-configured scope. -`window:deny-set-effects` +`core:window:deny-set-effects` @@ -1052,7 +1052,7 @@ Denies the set_effects command without any pre-configured scope. -`window:allow-set-focus` +`core:window:allow-set-focus` @@ -1065,7 +1065,7 @@ Enables the set_focus command without any pre-configured scope. -`window:deny-set-focus` +`core:window:deny-set-focus` @@ -1078,7 +1078,7 @@ Denies the set_focus command without any pre-configured scope. -`window:allow-set-fullscreen` +`core:window:allow-set-fullscreen` @@ -1091,7 +1091,7 @@ Enables the set_fullscreen command without any pre-configured scope. -`window:deny-set-fullscreen` +`core:window:deny-set-fullscreen` @@ -1104,7 +1104,7 @@ Denies the set_fullscreen command without any pre-configured scope. -`window:allow-set-icon` +`core:window:allow-set-icon` @@ -1117,7 +1117,7 @@ Enables the set_icon command without any pre-configured scope. -`window:deny-set-icon` +`core:window:deny-set-icon` @@ -1130,7 +1130,7 @@ Denies the set_icon command without any pre-configured scope. -`window:allow-set-ignore-cursor-events` +`core:window:allow-set-ignore-cursor-events` @@ -1143,7 +1143,7 @@ Enables the set_ignore_cursor_events command without any pre-configured scope. -`window:deny-set-ignore-cursor-events` +`core:window:deny-set-ignore-cursor-events` @@ -1156,7 +1156,7 @@ Denies the set_ignore_cursor_events command without any pre-configured scope. -`window:allow-set-max-size` +`core:window:allow-set-max-size` @@ -1169,7 +1169,7 @@ Enables the set_max_size command without any pre-configured scope. -`window:deny-set-max-size` +`core:window:deny-set-max-size` @@ -1182,7 +1182,7 @@ Denies the set_max_size command without any pre-configured scope. -`window:allow-set-maximizable` +`core:window:allow-set-maximizable` @@ -1195,7 +1195,7 @@ Enables the set_maximizable command without any pre-configured scope. -`window:deny-set-maximizable` +`core:window:deny-set-maximizable` @@ -1208,7 +1208,7 @@ Denies the set_maximizable command without any pre-configured scope. -`window:allow-set-min-size` +`core:window:allow-set-min-size` @@ -1221,7 +1221,7 @@ Enables the set_min_size command without any pre-configured scope. -`window:deny-set-min-size` +`core:window:deny-set-min-size` @@ -1234,7 +1234,7 @@ Denies the set_min_size command without any pre-configured scope. -`window:allow-set-minimizable` +`core:window:allow-set-minimizable` @@ -1247,7 +1247,7 @@ Enables the set_minimizable command without any pre-configured scope. -`window:deny-set-minimizable` +`core:window:deny-set-minimizable` @@ -1260,7 +1260,7 @@ Denies the set_minimizable command without any pre-configured scope. -`window:allow-set-position` +`core:window:allow-set-position` @@ -1273,7 +1273,7 @@ Enables the set_position command without any pre-configured scope. -`window:deny-set-position` +`core:window:deny-set-position` @@ -1286,7 +1286,7 @@ Denies the set_position command without any pre-configured scope. -`window:allow-set-progress-bar` +`core:window:allow-set-progress-bar` @@ -1299,7 +1299,7 @@ Enables the set_progress_bar command without any pre-configured scope. -`window:deny-set-progress-bar` +`core:window:deny-set-progress-bar` @@ -1312,7 +1312,7 @@ Denies the set_progress_bar command without any pre-configured scope. -`window:allow-set-resizable` +`core:window:allow-set-resizable` @@ -1325,7 +1325,7 @@ Enables the set_resizable command without any pre-configured scope. -`window:deny-set-resizable` +`core:window:deny-set-resizable` @@ -1338,7 +1338,7 @@ Denies the set_resizable command without any pre-configured scope. -`window:allow-set-shadow` +`core:window:allow-set-shadow` @@ -1351,7 +1351,7 @@ Enables the set_shadow command without any pre-configured scope. -`window:deny-set-shadow` +`core:window:deny-set-shadow` @@ -1364,7 +1364,7 @@ Denies the set_shadow command without any pre-configured scope. -`window:allow-set-size` +`core:window:allow-set-size` @@ -1377,7 +1377,7 @@ Enables the set_size command without any pre-configured scope. -`window:deny-set-size` +`core:window:deny-set-size` @@ -1390,7 +1390,33 @@ Denies the set_size command without any pre-configured scope. -`window:allow-set-skip-taskbar` +`core:window:allow-set-size-constraints` + + + + +Enables the set_size_constraints command without any pre-configured scope. + + + + + + + +`core:window:deny-set-size-constraints` + + + + +Denies the set_size_constraints command without any pre-configured scope. + + + + + + + +`core:window:allow-set-skip-taskbar` @@ -1403,7 +1429,7 @@ Enables the set_skip_taskbar command without any pre-configured scope. -`window:deny-set-skip-taskbar` +`core:window:deny-set-skip-taskbar` @@ -1416,7 +1442,7 @@ Denies the set_skip_taskbar command without any pre-configured scope. -`window:allow-set-title` +`core:window:allow-set-title` @@ -1429,7 +1455,7 @@ Enables the set_title command without any pre-configured scope. -`window:deny-set-title` +`core:window:deny-set-title` @@ -1442,7 +1468,33 @@ Denies the set_title command without any pre-configured scope. -`window:allow-set-visible-on-all-workspaces` +`core:window:allow-set-title-bar-style` + + + + +Enables the set_title_bar_style command without any pre-configured scope. + + + + + + + +`core:window:deny-set-title-bar-style` + + + + +Denies the set_title_bar_style command without any pre-configured scope. + + + + + + + +`core:window:allow-set-visible-on-all-workspaces` @@ -1455,7 +1507,7 @@ Enables the set_visible_on_all_workspaces command without any pre-configured sco -`window:deny-set-visible-on-all-workspaces` +`core:window:deny-set-visible-on-all-workspaces` @@ -1468,7 +1520,7 @@ Denies the set_visible_on_all_workspaces command without any pre-configured scop -`window:allow-show` +`core:window:allow-show` @@ -1481,7 +1533,7 @@ Enables the show command without any pre-configured scope. -`window:deny-show` +`core:window:deny-show` @@ -1494,7 +1546,7 @@ Denies the show command without any pre-configured scope. -`window:allow-start-dragging` +`core:window:allow-start-dragging` @@ -1507,7 +1559,7 @@ Enables the start_dragging command without any pre-configured scope. -`window:deny-start-dragging` +`core:window:deny-start-dragging` @@ -1520,7 +1572,7 @@ Denies the start_dragging command without any pre-configured scope. -`window:allow-start-resize-dragging` +`core:window:allow-start-resize-dragging` @@ -1533,7 +1585,7 @@ Enables the start_resize_dragging command without any pre-configured scope. -`window:deny-start-resize-dragging` +`core:window:deny-start-resize-dragging` @@ -1546,7 +1598,7 @@ Denies the start_resize_dragging command without any pre-configured scope. -`window:allow-theme` +`core:window:allow-theme` @@ -1559,7 +1611,7 @@ Enables the theme command without any pre-configured scope. -`window:deny-theme` +`core:window:deny-theme` @@ -1572,7 +1624,7 @@ Denies the theme command without any pre-configured scope. -`window:allow-title` +`core:window:allow-title` @@ -1585,7 +1637,7 @@ Enables the title command without any pre-configured scope. -`window:deny-title` +`core:window:deny-title` @@ -1598,7 +1650,7 @@ Denies the title command without any pre-configured scope. -`window:allow-toggle-maximize` +`core:window:allow-toggle-maximize` @@ -1611,7 +1663,7 @@ Enables the toggle_maximize command without any pre-configured scope. -`window:deny-toggle-maximize` +`core:window:deny-toggle-maximize` @@ -1624,7 +1676,7 @@ Denies the toggle_maximize command without any pre-configured scope. -`window:allow-unmaximize` +`core:window:allow-unmaximize` @@ -1637,7 +1689,7 @@ Enables the unmaximize command without any pre-configured scope. -`window:deny-unmaximize` +`core:window:deny-unmaximize` @@ -1650,7 +1702,7 @@ Denies the unmaximize command without any pre-configured scope. -`window:allow-unminimize` +`core:window:allow-unminimize` @@ -1663,7 +1715,7 @@ Enables the unminimize command without any pre-configured scope. -`window:deny-unminimize` +`core:window:deny-unminimize` diff --git a/core/tauri/scripts/bundle.global.js b/core/tauri/scripts/bundle.global.js index 1362ad774..06a954704 100644 --- a/core/tauri/scripts/bundle.global.js +++ b/core/tauri/scripts/bundle.global.js @@ -1 +1 @@ -var __TAURI_IIFE__=function(e){"use strict";function t(e,t,n,i){if("a"===n&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!i:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?i:"a"===n?i.call(e):i?i.value:t.get(e)}function n(e,t,n,i,r){if("m"===i)throw new TypeError("Private method is not writable");if("a"===i&&!r)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof t?e!==t||!r:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===i?r.call(e,n):r?r.value=n:t.set(e,n),n}var i,r,a,s;function l(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}"function"==typeof SuppressedError&&SuppressedError;class o{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),r.set(this,0),a.set(this,{}),this.id=l((({message:e,id:s})=>{if(s===t(this,r,"f")){n(this,r,s+1,"f"),t(this,i,"f").call(this,e);const l=Object.keys(t(this,a,"f"));if(l.length>0){let e=s+1;for(const n of l.sort()){if(parseInt(n)!==e)break;{const r=t(this,a,"f")[n];delete t(this,a,"f")[n],t(this,i,"f").call(this,r),e+=1}}n(this,r,e,"f")}}else t(this,a,"f")[s.toString()]=e}))}set onmessage(e){n(this,i,e,"f")}get onmessage(){return t(this,i,"f")}toJSON(){return`__CHANNEL__:${this.id}`}}i=new WeakMap,r=new WeakMap,a=new WeakMap;class u{constructor(e,t,n){this.plugin=e,this.event=t,this.channelId=n}async unregister(){return c(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}}async function c(e,t={},n){return window.__TAURI_INTERNALS__.invoke(e,t,n)}class d{get rid(){return t(this,s,"f")}constructor(e){s.set(this,void 0),n(this,s,e,"f")}async close(){return c("plugin:resources|close",{rid:this.rid})}}s=new WeakMap;var p=Object.freeze({__proto__:null,Channel:o,PluginListener:u,Resource:d,addPluginListener:async function(e,t,n){const i=new o;return i.onmessage=n,c(`plugin:${e}|register_listener`,{event:t,handler:i}).then((()=>new u(e,t,i.id)))},convertFileSrc:function(e,t="asset"){return window.__TAURI_INTERNALS__.convertFileSrc(e,t)},invoke:c,isTauri:function(){return"isTauri"in window&&!!window.isTauri},transformCallback:l});class h extends d{constructor(e){super(e)}static async new(e,t,n){return c("plugin:image|new",{rgba:w(e),width:t,height:n}).then((e=>new h(e)))}static async fromBytes(e){return c("plugin:image|from_bytes",{bytes:w(e)}).then((e=>new h(e)))}static async fromPath(e){return c("plugin:image|from_path",{path:e}).then((e=>new h(e)))}async rgba(){return c("plugin:image|rgba",{rid:this.rid}).then((e=>new Uint8Array(e)))}async size(){return c("plugin:image|size",{rid:this.rid})}}function w(e){return null==e?null:"string"==typeof e?e:e instanceof Uint8Array?Array.from(e):e instanceof ArrayBuffer?Array.from(new Uint8Array(e)):e instanceof h?e.rid:e}var y=Object.freeze({__proto__:null,Image:h,transformImage:w});var _=Object.freeze({__proto__:null,defaultWindowIcon:async function(){return c("plugin:app|default_window_icon").then((e=>e?new h(e):null))},getName:async function(){return c("plugin:app|name")},getTauriVersion:async function(){return c("plugin:app|tauri_version")},getVersion:async function(){return c("plugin:app|version")},hide:async function(){return c("plugin:app|app_hide")},show:async function(){return c("plugin:app|app_show")}});class g{constructor(e,t){this.type="Logical",this.width=e,this.height=t}}class b{constructor(e,t){this.type="Physical",this.width=e,this.height=t}toLogical(e){return new g(this.width/e,this.height/e)}}class m{constructor(e,t){this.type="Logical",this.x=e,this.y=t}}class v{constructor(e,t){this.type="Physical",this.x=e,this.y=t}toLogical(e){return new m(this.x/e,this.y/e)}}var f,k=Object.freeze({__proto__:null,LogicalPosition:m,LogicalSize:g,PhysicalPosition:v,PhysicalSize:b});async function A(e,t){await c("plugin:event|unlisten",{event:e,eventId:t})}async function E(e,t,n){var i;const r="string"==typeof(null==n?void 0:n.target)?{kind:"AnyLabel",label:n.target}:null!==(i=null==n?void 0:n.target)&&void 0!==i?i:{kind:"Any"};return c("plugin:event|listen",{event:e,target:r,handler:l(t)}).then((t=>async()=>A(e,t)))}async function D(e,t,n){return E(e,(n=>{t(n),A(e,n.id).catch((()=>{}))}),n)}async function I(e,t){await c("plugin:event|emit",{event:e,payload:t})}async function T(e,t,n){const i="string"==typeof e?{kind:"AnyLabel",label:e}:e;await c("plugin:event|emit_to",{target:i,event:t,payload:n})}!function(e){e.WINDOW_RESIZED="tauri://resize",e.WINDOW_MOVED="tauri://move",e.WINDOW_CLOSE_REQUESTED="tauri://close-requested",e.WINDOW_DESTROYED="tauri://destroyed",e.WINDOW_FOCUS="tauri://focus",e.WINDOW_BLUR="tauri://blur",e.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",e.WINDOW_THEME_CHANGED="tauri://theme-changed",e.WINDOW_CREATED="tauri://window-created",e.WEBVIEW_CREATED="tauri://webview-created",e.DRAG="tauri://drag",e.DROP="tauri://drop",e.DROP_OVER="tauri://drop-over",e.DROP_CANCELLED="tauri://drag-cancelled"}(f||(f={}));var L,S,R,P,C,N=Object.freeze({__proto__:null,get TauriEvent(){return f},emit:I,emitTo:T,listen:E,once:D});function x(e){var t;if("items"in e)e.items=null===(t=e.items)||void 0===t?void 0:t.map((e=>"rid"in e?e:x(e)));else if("action"in e&&e.action){const t=new o;return t.onmessage=e.action,delete e.action,{...e,handler:t}}return e}async function z(e,t){const n=new o;let i=null;return t&&"object"==typeof t&&("action"in t&&t.action&&(n.onmessage=t.action,delete t.action),"items"in t&&t.items&&(i=t.items.map((e=>{var t;return"rid"in e?[e.rid,e.kind]:("item"in e&&"object"==typeof e.item&&(null===(t=e.item.About)||void 0===t?void 0:t.icon)&&(e.item.About.icon=w(e.item.About.icon)),"icon"in e&&e.icon&&(e.icon=w(e.icon)),x(e))})))),c("plugin:menu|new",{kind:e,options:t?{...t,items:i}:void 0,handler:n})}class O extends d{get id(){return t(this,L,"f")}get kind(){return t(this,S,"f")}constructor(e,t,i){super(e),L.set(this,void 0),S.set(this,void 0),n(this,L,t,"f"),n(this,S,i,"f")}}L=new WeakMap,S=new WeakMap;class W extends O{constructor(e,t){super(e,t,"MenuItem")}static async new(e){return z("MenuItem",e).then((([e,t])=>new W(e,t)))}async text(){return c("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return c("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return c("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return c("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return c("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}}class F extends O{constructor(e,t){super(e,t,"Check")}static async new(e){return z("Check",e).then((([e,t])=>new F(e,t)))}async text(){return c("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return c("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return c("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return c("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return c("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async isChecked(){return c("plugin:menu|is_checked",{rid:this.rid})}async setChecked(e){return c("plugin:menu|set_checked",{rid:this.rid,checked:e})}}!function(e){e.Add="Add",e.Advanced="Advanced",e.Bluetooth="Bluetooth",e.Bookmarks="Bookmarks",e.Caution="Caution",e.ColorPanel="ColorPanel",e.ColumnView="ColumnView",e.Computer="Computer",e.EnterFullScreen="EnterFullScreen",e.Everyone="Everyone",e.ExitFullScreen="ExitFullScreen",e.FlowView="FlowView",e.Folder="Folder",e.FolderBurnable="FolderBurnable",e.FolderSmart="FolderSmart",e.FollowLinkFreestanding="FollowLinkFreestanding",e.FontPanel="FontPanel",e.GoLeft="GoLeft",e.GoRight="GoRight",e.Home="Home",e.IChatTheater="IChatTheater",e.IconView="IconView",e.Info="Info",e.InvalidDataFreestanding="InvalidDataFreestanding",e.LeftFacingTriangle="LeftFacingTriangle",e.ListView="ListView",e.LockLocked="LockLocked",e.LockUnlocked="LockUnlocked",e.MenuMixedState="MenuMixedState",e.MenuOnState="MenuOnState",e.MobileMe="MobileMe",e.MultipleDocuments="MultipleDocuments",e.Network="Network",e.Path="Path",e.PreferencesGeneral="PreferencesGeneral",e.QuickLook="QuickLook",e.RefreshFreestanding="RefreshFreestanding",e.Refresh="Refresh",e.Remove="Remove",e.RevealFreestanding="RevealFreestanding",e.RightFacingTriangle="RightFacingTriangle",e.Share="Share",e.Slideshow="Slideshow",e.SmartBadge="SmartBadge",e.StatusAvailable="StatusAvailable",e.StatusNone="StatusNone",e.StatusPartiallyAvailable="StatusPartiallyAvailable",e.StatusUnavailable="StatusUnavailable",e.StopProgressFreestanding="StopProgressFreestanding",e.StopProgress="StopProgress",e.TrashEmpty="TrashEmpty",e.TrashFull="TrashFull",e.User="User",e.UserAccounts="UserAccounts",e.UserGroup="UserGroup",e.UserGuest="UserGuest"}(R||(R={}));class U extends O{constructor(e,t){super(e,t,"Icon")}static async new(e){return z("Icon",e).then((([e,t])=>new U(e,t)))}async text(){return c("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return c("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return c("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return c("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return c("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async setIcon(e){return c("plugin:menu|set_icon",{rid:this.rid,icon:w(e)})}}class M extends O{constructor(e,t){super(e,t,"Predefined")}static async new(e){return z("Predefined",e).then((([e,t])=>new M(e,t)))}async text(){return c("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return c("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}}!function(e){e[e.Critical=1]="Critical",e[e.Informational=2]="Informational"}(P||(P={}));class B{constructor(e){this._preventDefault=!1,this.event=e.event,this.id=e.id}preventDefault(){this._preventDefault=!0}isPreventDefault(){return this._preventDefault}}function j(){return new H(window.__TAURI_INTERNALS__.metadata.currentWindow.label,{skip:!0})}function V(){return window.__TAURI_INTERNALS__.metadata.windows.map((e=>new H(e.label,{skip:!0})))}!function(e){e.None="none",e.Normal="normal",e.Indeterminate="indeterminate",e.Paused="paused",e.Error="error"}(C||(C={}));const G=["tauri://created","tauri://error"];class H{constructor(e,t={}){var n;this.label=e,this.listeners=Object.create(null),(null==t?void 0:t.skip)||c("plugin:window|create",{options:{...t,parent:"string"==typeof t.parent?t.parent:null===(n=t.parent)||void 0===n?void 0:n.label,label:e}}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static getByLabel(e){var t;return null!==(t=V().find((t=>t.label===e)))&&void 0!==t?t:null}static getCurrent(){return j()}static getAll(){return V()}static async getFocusedWindow(){for(const e of V())if(await e.isFocused())return e;return null}async listen(e,t){return this._handleTauriEvent(e,t)?Promise.resolve((()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)})):E(e,t,{target:{kind:"Window",label:this.label}})}async once(e,t){return this._handleTauriEvent(e,t)?Promise.resolve((()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)})):D(e,t,{target:{kind:"Window",label:this.label}})}async emit(e,t){if(G.includes(e)){for(const n of this.listeners[e]||[])n({event:e,id:-1,payload:t});return Promise.resolve()}return I(e,t)}async emitTo(e,t,n){if(G.includes(t)){for(const e of this.listeners[t]||[])e({event:t,id:-1,payload:n});return Promise.resolve()}return T(e,t,n)}_handleTauriEvent(e,t){return!!G.includes(e)&&(e in this.listeners?this.listeners[e].push(t):this.listeners[e]=[t],!0)}async scaleFactor(){return c("plugin:window|scale_factor",{label:this.label})}async innerPosition(){return c("plugin:window|inner_position",{label:this.label}).then((({x:e,y:t})=>new v(e,t)))}async outerPosition(){return c("plugin:window|outer_position",{label:this.label}).then((({x:e,y:t})=>new v(e,t)))}async innerSize(){return c("plugin:window|inner_size",{label:this.label}).then((({width:e,height:t})=>new b(e,t)))}async outerSize(){return c("plugin:window|outer_size",{label:this.label}).then((({width:e,height:t})=>new b(e,t)))}async isFullscreen(){return c("plugin:window|is_fullscreen",{label:this.label})}async isMinimized(){return c("plugin:window|is_minimized",{label:this.label})}async isMaximized(){return c("plugin:window|is_maximized",{label:this.label})}async isFocused(){return c("plugin:window|is_focused",{label:this.label})}async isDecorated(){return c("plugin:window|is_decorated",{label:this.label})}async isResizable(){return c("plugin:window|is_resizable",{label:this.label})}async isMaximizable(){return c("plugin:window|is_maximizable",{label:this.label})}async isMinimizable(){return c("plugin:window|is_minimizable",{label:this.label})}async isClosable(){return c("plugin:window|is_closable",{label:this.label})}async isVisible(){return c("plugin:window|is_visible",{label:this.label})}async title(){return c("plugin:window|title",{label:this.label})}async theme(){return c("plugin:window|theme",{label:this.label})}async center(){return c("plugin:window|center",{label:this.label})}async requestUserAttention(e){let t=null;return e&&(t=e===P.Critical?{type:"Critical"}:{type:"Informational"}),c("plugin:window|request_user_attention",{label:this.label,value:t})}async setResizable(e){return c("plugin:window|set_resizable",{label:this.label,value:e})}async setMaximizable(e){return c("plugin:window|set_maximizable",{label:this.label,value:e})}async setMinimizable(e){return c("plugin:window|set_minimizable",{label:this.label,value:e})}async setClosable(e){return c("plugin:window|set_closable",{label:this.label,value:e})}async setTitle(e){return c("plugin:window|set_title",{label:this.label,value:e})}async maximize(){return c("plugin:window|maximize",{label:this.label})}async unmaximize(){return c("plugin:window|unmaximize",{label:this.label})}async toggleMaximize(){return c("plugin:window|toggle_maximize",{label:this.label})}async minimize(){return c("plugin:window|minimize",{label:this.label})}async unminimize(){return c("plugin:window|unminimize",{label:this.label})}async show(){return c("plugin:window|show",{label:this.label})}async hide(){return c("plugin:window|hide",{label:this.label})}async close(){return c("plugin:window|close",{label:this.label})}async destroy(){return c("plugin:window|destroy",{label:this.label})}async setDecorations(e){return c("plugin:window|set_decorations",{label:this.label,value:e})}async setShadow(e){return c("plugin:window|set_shadow",{label:this.label,value:e})}async setEffects(e){return c("plugin:window|set_effects",{label:this.label,value:e})}async clearEffects(){return c("plugin:window|set_effects",{label:this.label,value:null})}async setAlwaysOnTop(e){return c("plugin:window|set_always_on_top",{label:this.label,value:e})}async setAlwaysOnBottom(e){return c("plugin:window|set_always_on_bottom",{label:this.label,value:e})}async setContentProtected(e){return c("plugin:window|set_content_protected",{label:this.label,value:e})}async setSize(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");const t={};return t[`${e.type}`]={width:e.width,height:e.height},c("plugin:window|set_size",{label:this.label,value:t})}async setMinSize(e){if(e&&"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");let t=null;return e&&(t={},t[`${e.type}`]={width:e.width,height:e.height}),c("plugin:window|set_min_size",{label:this.label,value:t})}async setMaxSize(e){if(e&&"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");let t=null;return e&&(t={},t[`${e.type}`]={width:e.width,height:e.height}),c("plugin:window|set_max_size",{label:this.label,value:t})}async setPosition(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");const t={};return t[`${e.type}`]={x:e.x,y:e.y},c("plugin:window|set_position",{label:this.label,value:t})}async setFullscreen(e){return c("plugin:window|set_fullscreen",{label:this.label,value:e})}async setFocus(){return c("plugin:window|set_focus",{label:this.label})}async setIcon(e){return c("plugin:window|set_icon",{label:this.label,value:w(e)})}async setSkipTaskbar(e){return c("plugin:window|set_skip_taskbar",{label:this.label,value:e})}async setCursorGrab(e){return c("plugin:window|set_cursor_grab",{label:this.label,value:e})}async setCursorVisible(e){return c("plugin:window|set_cursor_visible",{label:this.label,value:e})}async setCursorIcon(e){return c("plugin:window|set_cursor_icon",{label:this.label,value:e})}async setCursorPosition(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");const t={};return t[`${e.type}`]={x:e.x,y:e.y},c("plugin:window|set_cursor_position",{label:this.label,value:t})}async setIgnoreCursorEvents(e){return c("plugin:window|set_ignore_cursor_events",{label:this.label,value:e})}async startDragging(){return c("plugin:window|start_dragging",{label:this.label})}async startResizeDragging(e){return c("plugin:window|start_resize_dragging",{label:this.label,value:e})}async setProgressBar(e){return c("plugin:window|set_progress_bar",{label:this.label,value:e})}async setVisibleOnAllWorkspaces(e){return c("plugin:window|set_visible_on_all_workspaces",{label:this.label,value:e})}async onResized(e){return this.listen(f.WINDOW_RESIZED,(t=>{t.payload=J(t.payload),e(t)}))}async onMoved(e){return this.listen(f.WINDOW_MOVED,(t=>{t.payload=Z(t.payload),e(t)}))}async onCloseRequested(e){return this.listen(f.WINDOW_CLOSE_REQUESTED,(t=>{const n=new B(t);Promise.resolve(e(n)).then((()=>{if(!n.isPreventDefault())return this.destroy()}))}))}async onDragDropEvent(e){const t=await this.listen(f.DRAG,(t=>{e({...t,payload:{type:"dragged",paths:t.payload.paths,position:Z(t.payload.position)}})})),n=await this.listen(f.DROP,(t=>{e({...t,payload:{type:"dropped",paths:t.payload.paths,position:Z(t.payload.position)}})})),i=await this.listen(f.DROP_OVER,(t=>{e({...t,payload:{type:"dragOver",position:Z(t.payload.position)}})})),r=await this.listen(f.DROP_CANCELLED,(t=>{e({...t,payload:{type:"cancelled"}})}));return()=>{t(),n(),i(),r()}}async onFocusChanged(e){const t=await this.listen(f.WINDOW_FOCUS,(t=>{e({...t,payload:!0})})),n=await this.listen(f.WINDOW_BLUR,(t=>{e({...t,payload:!1})}));return()=>{t(),n()}}async onScaleChanged(e){return this.listen(f.WINDOW_SCALE_FACTOR_CHANGED,e)}async onThemeChanged(e){return this.listen(f.WINDOW_THEME_CHANGED,e)}}var $,q;function Q(e){return null===e?null:{name:e.name,scaleFactor:e.scaleFactor,position:Z(e.position),size:J(e.size)}}function Z(e){return new v(e.x,e.y)}function J(e){return new b(e.width,e.height)}!function(e){e.AppearanceBased="appearanceBased",e.Light="light",e.Dark="dark",e.MediumLight="mediumLight",e.UltraDark="ultraDark",e.Titlebar="titlebar",e.Selection="selection",e.Menu="menu",e.Popover="popover",e.Sidebar="sidebar",e.HeaderView="headerView",e.Sheet="sheet",e.WindowBackground="windowBackground",e.HudWindow="hudWindow",e.FullScreenUI="fullScreenUI",e.Tooltip="tooltip",e.ContentBackground="contentBackground",e.UnderWindowBackground="underWindowBackground",e.UnderPageBackground="underPageBackground",e.Mica="mica",e.Blur="blur",e.Acrylic="acrylic",e.Tabbed="tabbed",e.TabbedDark="tabbedDark",e.TabbedLight="tabbedLight"}($||($={})),function(e){e.FollowsWindowActiveState="followsWindowActiveState",e.Active="active",e.Inactive="inactive"}(q||(q={}));var K=Object.freeze({__proto__:null,CloseRequestedEvent:B,get Effect(){return $},get EffectState(){return q},LogicalPosition:m,LogicalSize:g,PhysicalPosition:v,PhysicalSize:b,get ProgressBarStatus(){return C},get UserAttentionType(){return P},Window:H,availableMonitors:async function(){return c("plugin:window|available_monitors").then((e=>e.map(Q)))},currentMonitor:async function(){return c("plugin:window|current_monitor").then(Q)},cursorPosition:async function(){return c("plugin:window|cursor_position").then(Z)},getAll:V,getCurrent:j,monitorFromPoint:async function(e,t){return c("plugin:window|monitor_from_point",{x:e,y:t}).then(Q)},primaryMonitor:async function(){return c("plugin:window|primary_monitor").then(Q)}});function Y([e,t,n]){switch(n){case"Submenu":return new X(e,t);case"Predefined":return new M(e,t);case"Check":return new F(e,t);case"Icon":return new U(e,t);default:return new W(e,t)}}class X extends O{constructor(e,t){super(e,t,"Submenu")}static async new(e){return z("Submenu",e).then((([e,t])=>new X(e,t)))}async text(){return c("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return c("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return c("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return c("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async append(e){return c("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async prepend(e){return c("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async insert(e,t){return c("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e)),position:t})}async remove(e){return c("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return c("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(Y)}async items(){return c("plugin:menu|items",{rid:this.rid,kind:this.kind}).then((e=>e.map(Y)))}async get(e){return c("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then((e=>e?Y(e):null))}async popup(e,t){var n;let i=null;return e&&(i={},i[""+(e instanceof v?"Physical":"Logical")]={x:e.x,y:e.y}),c("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:null!==(n=null==t?void 0:t.label)&&void 0!==n?n:null,at:i})}async setAsWindowsMenuForNSApp(){return c("plugin:menu|set_as_windows_menu_for_nsapp",{rid:this.rid})}async setAsHelpMenuForNSApp(){return c("plugin:menu|set_as_help_menu_for_nsapp",{rid:this.rid})}}function ee([e,t,n]){switch(n){case"Submenu":return new X(e,t);case"Predefined":return new M(e,t);case"Check":return new F(e,t);case"Icon":return new U(e,t);default:return new W(e,t)}}class te extends O{constructor(e,t){super(e,t,"Menu")}static async new(e){return z("Menu",e).then((([e,t])=>new te(e,t)))}static async default(){return c("plugin:menu|create_default").then((([e,t])=>new te(e,t)))}async append(e){return c("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async prepend(e){return c("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async insert(e,t){return c("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e)),position:t})}async remove(e){return c("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return c("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(ee)}async items(){return c("plugin:menu|items",{rid:this.rid,kind:this.kind}).then((e=>e.map(ee)))}async get(e){return c("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then((e=>e?ee(e):null))}async popup(e,t){var n;let i=null;return e&&(i={},i[""+(e instanceof v?"Physical":"Logical")]={x:e.x,y:e.y}),c("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:null!==(n=null==t?void 0:t.label)&&void 0!==n?n:null,at:i})}async setAsAppMenu(){return c("plugin:menu|set_as_app_menu",{rid:this.rid}).then((e=>e?new te(e[0],e[1]):null))}async setAsWindowMenu(e){var t;return c("plugin:menu|set_as_window_menu",{rid:this.rid,window:null!==(t=null==e?void 0:e.label)&&void 0!==t?t:null}).then((e=>e?new te(e[0],e[1]):null))}}var ne=Object.freeze({__proto__:null,CheckMenuItem:F,IconMenuItem:U,Menu:te,MenuItem:W,get NativeIcon(){return R},PredefinedMenuItem:M,Submenu:X});function ie(){var e;window.__TAURI_INTERNALS__=null!==(e=window.__TAURI_INTERNALS__)&&void 0!==e?e:{}}var re,ae=Object.freeze({__proto__:null,clearMocks:function(){var e,t,n;"object"==typeof window.__TAURI_INTERNALS__&&((null===(e=window.__TAURI_INTERNALS__)||void 0===e?void 0:e.convertFileSrc)&&delete window.__TAURI_INTERNALS__.convertFileSrc,(null===(t=window.__TAURI_INTERNALS__)||void 0===t?void 0:t.invoke)&&delete window.__TAURI_INTERNALS__.invoke,(null===(n=window.__TAURI_INTERNALS__)||void 0===n?void 0:n.metadata)&&delete window.__TAURI_INTERNALS__.metadata)},mockConvertFileSrc:function(e){ie(),window.__TAURI_INTERNALS__.convertFileSrc=function(t,n="asset"){const i=encodeURIComponent(t);return"windows"===e?`http://${n}.localhost/${i}`:`${n}://localhost/${i}`}},mockIPC:function(e){ie(),window.__TAURI_INTERNALS__.transformCallback=function(e,t=!1){const n=window.crypto.getRandomValues(new Uint32Array(1))[0],i=`_${n}`;return Object.defineProperty(window,i,{value:n=>(t&&Reflect.deleteProperty(window,i),e&&e(n)),writable:!1,configurable:!0}),n},window.__TAURI_INTERNALS__.invoke=function(t,n,i){return e(t,n)}},mockWindows:function(e,...t){ie(),window.__TAURI_INTERNALS__.metadata={windows:[e,...t].map((e=>({label:e}))),currentWindow:{label:e},webviews:[e,...t].map((e=>({windowLabel:e,label:e}))),currentWebview:{windowLabel:e,label:e}}}});!function(e){e[e.Audio=1]="Audio",e[e.Cache=2]="Cache",e[e.Config=3]="Config",e[e.Data=4]="Data",e[e.LocalData=5]="LocalData",e[e.Document=6]="Document",e[e.Download=7]="Download",e[e.Picture=8]="Picture",e[e.Public=9]="Public",e[e.Video=10]="Video",e[e.Resource=11]="Resource",e[e.Temp=12]="Temp",e[e.AppConfig=13]="AppConfig",e[e.AppData=14]="AppData",e[e.AppLocalData=15]="AppLocalData",e[e.AppCache=16]="AppCache",e[e.AppLog=17]="AppLog",e[e.Desktop=18]="Desktop",e[e.Executable=19]="Executable",e[e.Font=20]="Font",e[e.Home=21]="Home",e[e.Runtime=22]="Runtime",e[e.Template=23]="Template"}(re||(re={}));var se=Object.freeze({__proto__:null,get BaseDirectory(){return re},appCacheDir:async function(){return c("plugin:path|resolve_directory",{directory:re.AppCache})},appConfigDir:async function(){return c("plugin:path|resolve_directory",{directory:re.AppConfig})},appDataDir:async function(){return c("plugin:path|resolve_directory",{directory:re.AppData})},appLocalDataDir:async function(){return c("plugin:path|resolve_directory",{directory:re.AppLocalData})},appLogDir:async function(){return c("plugin:path|resolve_directory",{directory:re.AppLog})},audioDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Audio})},basename:async function(e,t){return c("plugin:path|basename",{path:e,ext:t})},cacheDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Cache})},configDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Config})},dataDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Data})},delimiter:function(){return window.__TAURI_INTERNALS__.plugins.path.delimiter},desktopDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Desktop})},dirname:async function(e){return c("plugin:path|dirname",{path:e})},documentDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Document})},downloadDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Download})},executableDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Executable})},extname:async function(e){return c("plugin:path|extname",{path:e})},fontDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Font})},homeDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Home})},isAbsolute:async function(e){return c("plugin:path|isAbsolute",{path:e})},join:async function(...e){return c("plugin:path|join",{paths:e})},localDataDir:async function(){return c("plugin:path|resolve_directory",{directory:re.LocalData})},normalize:async function(e){return c("plugin:path|normalize",{path:e})},pictureDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Picture})},publicDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Public})},resolve:async function(...e){return c("plugin:path|resolve",{paths:e})},resolveResource:async function(e){return c("plugin:path|resolve_directory",{directory:re.Resource,path:e})},resourceDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Resource})},runtimeDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Runtime})},sep:function(){return window.__TAURI_INTERNALS__.plugins.path.sep},tempDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Temp})},templateDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Template})},videoDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Video})}});class le extends d{constructor(e,t){super(e),this.id=t}static async getById(e){return c("plugin:tray|get_by_id",{id:e}).then((t=>t?new le(t,e):null))}static async removeById(e){return c("plugin:tray|remove_by_id",{id:e})}static async new(e){(null==e?void 0:e.menu)&&(e.menu=[e.menu.rid,e.menu.kind]),(null==e?void 0:e.icon)&&(e.icon=w(e.icon));const t=new o;return(null==e?void 0:e.action)&&(t.onmessage=e.action,delete e.action),c("plugin:tray|new",{options:null!=e?e:{},handler:t}).then((([e,t])=>new le(e,t)))}async setIcon(e){let t=null;return e&&(t=w(e)),c("plugin:tray|set_icon",{rid:this.rid,icon:t})}async setMenu(e){return e&&(e=[e.rid,e.kind]),c("plugin:tray|set_menu",{rid:this.rid,menu:e})}async setTooltip(e){return c("plugin:tray|set_tooltip",{rid:this.rid,tooltip:e})}async setTitle(e){return c("plugin:tray|set_title",{rid:this.rid,title:e})}async setVisible(e){return c("plugin:tray|set_visible",{rid:this.rid,visible:e})}async setTempDirPath(e){return c("plugin:tray|set_temp_dir_path",{rid:this.rid,path:e})}async setIconAsTemplate(e){return c("plugin:tray|set_icon_as_template",{rid:this.rid,asTemplate:e})}async setMenuOnLeftClick(e){return c("plugin:tray|set_show_menu_on_left_click",{rid:this.rid,onLeft:e})}}var oe=Object.freeze({__proto__:null,TrayIcon:le});function ue(){return new pe(j(),window.__TAURI_INTERNALS__.metadata.currentWebview.label,{skip:!0})}function ce(){return window.__TAURI_INTERNALS__.metadata.webviews.map((e=>new pe(H.getByLabel(e.windowLabel),e.label,{skip:!0})))}const de=["tauri://created","tauri://error"];class pe{constructor(e,t,n){this.window=e,this.label=t,this.listeners=Object.create(null),(null==n?void 0:n.skip)||c("plugin:webview|create_webview",{windowLabel:e.label,label:t,options:n}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static getByLabel(e){var t;return null!==(t=ce().find((t=>t.label===e)))&&void 0!==t?t:null}static getCurrent(){return ue()}static getAll(){return ce()}async listen(e,t){return this._handleTauriEvent(e,t)?Promise.resolve((()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)})):E(e,t,{target:{kind:"Webview",label:this.label}})}async once(e,t){return this._handleTauriEvent(e,t)?Promise.resolve((()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)})):D(e,t,{target:{kind:"Webview",label:this.label}})}async emit(e,t){if(de.includes(e)){for(const n of this.listeners[e]||[])n({event:e,id:-1,payload:t});return Promise.resolve()}return I(e,t)}async emitTo(e,t,n){if(de.includes(t)){for(const e of this.listeners[t]||[])e({event:t,id:-1,payload:n});return Promise.resolve()}return T(e,t,n)}_handleTauriEvent(e,t){return!!de.includes(e)&&(e in this.listeners?this.listeners[e].push(t):this.listeners[e]=[t],!0)}async position(){return c("plugin:webview|webview_position",{label:this.label}).then((({x:e,y:t})=>new v(e,t)))}async size(){return c("plugin:webview|webview_size",{label:this.label}).then((({width:e,height:t})=>new b(e,t)))}async close(){return c("plugin:webview|close",{label:this.label})}async setSize(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");const t={};return t[`${e.type}`]={width:e.width,height:e.height},c("plugin:webview|set_webview_size",{label:this.label,value:t})}async setPosition(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");const t={};return t[`${e.type}`]={x:e.x,y:e.y},c("plugin:webview|set_webview_position",{label:this.label,value:t})}async setFocus(){return c("plugin:webview|set_webview_focus",{label:this.label})}async setZoom(e){return c("plugin:webview|set_webview_zoom",{label:this.label,value:e})}async reparent(e){return c("plugin:webview|set_webview_focus",{label:this.label,window:"string"==typeof e?e:e.label})}async onDragDropEvent(e){const t=await this.listen(f.DRAG,(t=>{e({...t,payload:{type:"dragged",paths:t.payload.paths,position:he(t.payload.position)}})})),n=await this.listen(f.DROP,(t=>{e({...t,payload:{type:"dropped",paths:t.payload.paths,position:he(t.payload.position)}})})),i=await this.listen(f.DROP_CANCELLED,(t=>{e({...t,payload:{type:"dragOver",position:he(t.payload.position)}})})),r=await this.listen(f.DROP_CANCELLED,(t=>{e({...t,payload:{type:"cancelled"}})}));return()=>{t(),n(),i(),r()}}}function he(e){return new v(e.x,e.y)}var we,ye,_e=Object.freeze({__proto__:null,Webview:pe,getAll:ce,getCurrent:ue});function ge(){const e=ue();return new me(e.label,{skip:!0})}function be(){return window.__TAURI_INTERNALS__.metadata.webviews.map((e=>new me(e.label,{skip:!0})))}class me{constructor(e,t={}){var n;this.label=e,this.listeners=Object.create(null),(null==t?void 0:t.skip)||c("plugin:webview|create_webview_window",{options:{...t,parent:"string"==typeof t.parent?t.parent:null===(n=t.parent)||void 0===n?void 0:n.label,label:e}}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static getByLabel(e){var t;const n=null!==(t=be().find((t=>t.label===e)))&&void 0!==t?t:null;return n?new me(n.label,{skip:!0}):null}static getCurrent(){return ge()}static getAll(){return be().map((e=>new me(e.label,{skip:!0})))}async listen(e,t){return this._handleTauriEvent(e,t)?Promise.resolve((()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)})):E(e,t,{target:{kind:"WebviewWindow",label:this.label}})}async once(e,t){return this._handleTauriEvent(e,t)?Promise.resolve((()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)})):D(e,t,{target:{kind:"WebviewWindow",label:this.label}})}}we=me,ye=[H,pe],(Array.isArray(ye)?ye:[ye]).forEach((e=>{Object.getOwnPropertyNames(e.prototype).forEach((t=>{var n;"object"==typeof we.prototype&&we.prototype&&t in we.prototype||Object.defineProperty(we.prototype,t,null!==(n=Object.getOwnPropertyDescriptor(e.prototype,t))&&void 0!==n?n:Object.create(null))}))}));var ve=Object.freeze({__proto__:null,WebviewWindow:me,getAll:be,getCurrent:ge});return e.app=_,e.core=p,e.dpi=k,e.event=N,e.image=y,e.menu=ne,e.mocks=ae,e.path=se,e.tray=oe,e.webview=_e,e.webviewWindow=ve,e.window=K,e}({});window.__TAURI__=__TAURI_IIFE__; +var __TAURI_IIFE__=function(e){"use strict";function t(e,t,n,i){if("a"===n&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!i:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?i:"a"===n?i.call(e):i?i.value:t.get(e)}function n(e,t,n,i,r){if("m"===i)throw new TypeError("Private method is not writable");if("a"===i&&!r)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof t?e!==t||!r:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===i?r.call(e,n):r?r.value=n:t.set(e,n),n}var i,r,a,s;function l(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}"function"==typeof SuppressedError&&SuppressedError;class o{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),r.set(this,0),a.set(this,{}),this.id=l((({message:e,id:s})=>{if(s===t(this,r,"f")){n(this,r,s+1,"f"),t(this,i,"f").call(this,e);const l=Object.keys(t(this,a,"f"));if(l.length>0){let e=s+1;for(const n of l.sort()){if(parseInt(n)!==e)break;{const r=t(this,a,"f")[n];delete t(this,a,"f")[n],t(this,i,"f").call(this,r),e+=1}}n(this,r,e,"f")}}else t(this,a,"f")[s.toString()]=e}))}set onmessage(e){n(this,i,e,"f")}get onmessage(){return t(this,i,"f")}toJSON(){return`__CHANNEL__:${this.id}`}}i=new WeakMap,r=new WeakMap,a=new WeakMap;class u{constructor(e,t,n){this.plugin=e,this.event=t,this.channelId=n}async unregister(){return c(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}}async function c(e,t={},n){return window.__TAURI_INTERNALS__.invoke(e,t,n)}class d{get rid(){return t(this,s,"f")}constructor(e){s.set(this,void 0),n(this,s,e,"f")}async close(){return c("plugin:resources|close",{rid:this.rid})}}s=new WeakMap;var p=Object.freeze({__proto__:null,Channel:o,PluginListener:u,Resource:d,addPluginListener:async function(e,t,n){const i=new o;return i.onmessage=n,c(`plugin:${e}|register_listener`,{event:t,handler:i}).then((()=>new u(e,t,i.id)))},convertFileSrc:function(e,t="asset"){return window.__TAURI_INTERNALS__.convertFileSrc(e,t)},invoke:c,isTauri:function(){return"isTauri"in window&&!!window.isTauri},transformCallback:l});class h extends d{constructor(e){super(e)}static async new(e,t,n){return c("plugin:image|new",{rgba:w(e),width:t,height:n}).then((e=>new h(e)))}static async fromBytes(e){return c("plugin:image|from_bytes",{bytes:w(e)}).then((e=>new h(e)))}static async fromPath(e){return c("plugin:image|from_path",{path:e}).then((e=>new h(e)))}async rgba(){return c("plugin:image|rgba",{rid:this.rid}).then((e=>new Uint8Array(e)))}async size(){return c("plugin:image|size",{rid:this.rid})}}function w(e){return null==e?null:"string"==typeof e?e:e instanceof Uint8Array?Array.from(e):e instanceof ArrayBuffer?Array.from(new Uint8Array(e)):e instanceof h?e.rid:e}var y=Object.freeze({__proto__:null,Image:h,transformImage:w});var _=Object.freeze({__proto__:null,defaultWindowIcon:async function(){return c("plugin:app|default_window_icon").then((e=>e?new h(e):null))},getName:async function(){return c("plugin:app|name")},getTauriVersion:async function(){return c("plugin:app|tauri_version")},getVersion:async function(){return c("plugin:app|version")},hide:async function(){return c("plugin:app|app_hide")},show:async function(){return c("plugin:app|app_show")}});class g{constructor(e,t){this.type="Logical",this.width=e,this.height=t}}class b{constructor(e,t){this.type="Physical",this.width=e,this.height=t}toLogical(e){return new g(this.width/e,this.height/e)}}class m{constructor(e,t){this.type="Logical",this.x=e,this.y=t}}class v{constructor(e,t){this.type="Physical",this.x=e,this.y=t}toLogical(e){return new m(this.x/e,this.y/e)}}var f,k=Object.freeze({__proto__:null,LogicalPosition:m,LogicalSize:g,PhysicalPosition:v,PhysicalSize:b});async function A(e,t){await c("plugin:event|unlisten",{event:e,eventId:t})}async function E(e,t,n){var i;const r="string"==typeof(null==n?void 0:n.target)?{kind:"AnyLabel",label:n.target}:null!==(i=null==n?void 0:n.target)&&void 0!==i?i:{kind:"Any"};return c("plugin:event|listen",{event:e,target:r,handler:l(t)}).then((t=>async()=>A(e,t)))}async function T(e,t,n){return E(e,(n=>{A(e,n.id),t(n)}),n)}async function I(e,t){await c("plugin:event|emit",{event:e,payload:t})}async function D(e,t,n){const i="string"==typeof e?{kind:"AnyLabel",label:e}:e;await c("plugin:event|emit_to",{target:i,event:t,payload:n})}!function(e){e.WINDOW_RESIZED="tauri://resize",e.WINDOW_MOVED="tauri://move",e.WINDOW_CLOSE_REQUESTED="tauri://close-requested",e.WINDOW_DESTROYED="tauri://destroyed",e.WINDOW_FOCUS="tauri://focus",e.WINDOW_BLUR="tauri://blur",e.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",e.WINDOW_THEME_CHANGED="tauri://theme-changed",e.WINDOW_CREATED="tauri://window-created",e.WEBVIEW_CREATED="tauri://webview-created",e.DRAG_ENTER="tauri://drag-enter",e.DRAG_OVER="tauri://drag-over",e.DRAG_DROP="tauri://drag-drop",e.DRAG_LEAVE="tauri://drag-leave"}(f||(f={}));var R,S,L,P,x,N=Object.freeze({__proto__:null,get TauriEvent(){return f},emit:I,emitTo:D,listen:E,once:T});function C(e){var t;if("items"in e)e.items=null===(t=e.items)||void 0===t?void 0:t.map((e=>"rid"in e?e:C(e)));else if("action"in e&&e.action){const t=new o;return t.onmessage=e.action,delete e.action,{...e,handler:t}}return e}async function W(e,t){const n=new o;let i=null;return t&&"object"==typeof t&&("action"in t&&t.action&&(n.onmessage=t.action,delete t.action),"items"in t&&t.items&&(i=t.items.map((e=>{var t;return"rid"in e?[e.rid,e.kind]:("item"in e&&"object"==typeof e.item&&(null===(t=e.item.About)||void 0===t?void 0:t.icon)&&(e.item.About.icon=w(e.item.About.icon)),"icon"in e&&e.icon&&(e.icon=w(e.icon)),C(e))})))),c("plugin:menu|new",{kind:e,options:t?{...t,items:i}:void 0,handler:n})}class z extends d{get id(){return t(this,R,"f")}get kind(){return t(this,S,"f")}constructor(e,t,i){super(e),R.set(this,void 0),S.set(this,void 0),n(this,R,t,"f"),n(this,S,i,"f")}}R=new WeakMap,S=new WeakMap;class O extends z{constructor(e,t){super(e,t,"MenuItem")}static async new(e){return W("MenuItem",e).then((([e,t])=>new O(e,t)))}async text(){return c("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return c("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return c("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return c("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return c("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}}class F extends z{constructor(e,t){super(e,t,"Check")}static async new(e){return W("Check",e).then((([e,t])=>new F(e,t)))}async text(){return c("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return c("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return c("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return c("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return c("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async isChecked(){return c("plugin:menu|is_checked",{rid:this.rid})}async setChecked(e){return c("plugin:menu|set_checked",{rid:this.rid,checked:e})}}!function(e){e.Add="Add",e.Advanced="Advanced",e.Bluetooth="Bluetooth",e.Bookmarks="Bookmarks",e.Caution="Caution",e.ColorPanel="ColorPanel",e.ColumnView="ColumnView",e.Computer="Computer",e.EnterFullScreen="EnterFullScreen",e.Everyone="Everyone",e.ExitFullScreen="ExitFullScreen",e.FlowView="FlowView",e.Folder="Folder",e.FolderBurnable="FolderBurnable",e.FolderSmart="FolderSmart",e.FollowLinkFreestanding="FollowLinkFreestanding",e.FontPanel="FontPanel",e.GoLeft="GoLeft",e.GoRight="GoRight",e.Home="Home",e.IChatTheater="IChatTheater",e.IconView="IconView",e.Info="Info",e.InvalidDataFreestanding="InvalidDataFreestanding",e.LeftFacingTriangle="LeftFacingTriangle",e.ListView="ListView",e.LockLocked="LockLocked",e.LockUnlocked="LockUnlocked",e.MenuMixedState="MenuMixedState",e.MenuOnState="MenuOnState",e.MobileMe="MobileMe",e.MultipleDocuments="MultipleDocuments",e.Network="Network",e.Path="Path",e.PreferencesGeneral="PreferencesGeneral",e.QuickLook="QuickLook",e.RefreshFreestanding="RefreshFreestanding",e.Refresh="Refresh",e.Remove="Remove",e.RevealFreestanding="RevealFreestanding",e.RightFacingTriangle="RightFacingTriangle",e.Share="Share",e.Slideshow="Slideshow",e.SmartBadge="SmartBadge",e.StatusAvailable="StatusAvailable",e.StatusNone="StatusNone",e.StatusPartiallyAvailable="StatusPartiallyAvailable",e.StatusUnavailable="StatusUnavailable",e.StopProgressFreestanding="StopProgressFreestanding",e.StopProgress="StopProgress",e.TrashEmpty="TrashEmpty",e.TrashFull="TrashFull",e.User="User",e.UserAccounts="UserAccounts",e.UserGroup="UserGroup",e.UserGuest="UserGuest"}(L||(L={}));class U extends z{constructor(e,t){super(e,t,"Icon")}static async new(e){return W("Icon",e).then((([e,t])=>new U(e,t)))}async text(){return c("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return c("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return c("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return c("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return c("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async setIcon(e){return c("plugin:menu|set_icon",{rid:this.rid,icon:w(e)})}}class M extends z{constructor(e,t){super(e,t,"Predefined")}static async new(e){return W("Predefined",e).then((([e,t])=>new M(e,t)))}async text(){return c("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return c("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}}!function(e){e[e.Critical=1]="Critical",e[e.Informational=2]="Informational"}(P||(P={}));class B{constructor(e){this._preventDefault=!1,this.event=e.event,this.id=e.id}preventDefault(){this._preventDefault=!0}isPreventDefault(){return this._preventDefault}}function j(){return new H(window.__TAURI_INTERNALS__.metadata.currentWindow.label,{skip:!0})}function V(){return window.__TAURI_INTERNALS__.metadata.windows.map((e=>new H(e.label,{skip:!0})))}!function(e){e.None="none",e.Normal="normal",e.Indeterminate="indeterminate",e.Paused="paused",e.Error="error"}(x||(x={}));const G=["tauri://created","tauri://error"];class H{constructor(e,t={}){var n;this.label=e,this.listeners=Object.create(null),(null==t?void 0:t.skip)||c("plugin:window|create",{options:{...t,parent:"string"==typeof t.parent?t.parent:null===(n=t.parent)||void 0===n?void 0:n.label,label:e}}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static getByLabel(e){var t;return null!==(t=V().find((t=>t.label===e)))&&void 0!==t?t:null}static getCurrent(){return j()}static getAll(){return V()}static async getFocusedWindow(){for(const e of V())if(await e.isFocused())return e;return null}async listen(e,t){return this._handleTauriEvent(e,t)?()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)}:E(e,t,{target:{kind:"Window",label:this.label}})}async once(e,t){return this._handleTauriEvent(e,t)?()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)}:T(e,t,{target:{kind:"Window",label:this.label}})}async emit(e,t){if(!G.includes(e))return I(e,t);for(const n of this.listeners[e]||[])n({event:e,id:-1,payload:t})}async emitTo(e,t,n){if(!G.includes(t))return D(e,t,n);for(const e of this.listeners[t]||[])e({event:t,id:-1,payload:n})}_handleTauriEvent(e,t){return!!G.includes(e)&&(e in this.listeners?this.listeners[e].push(t):this.listeners[e]=[t],!0)}async scaleFactor(){return c("plugin:window|scale_factor",{label:this.label})}async innerPosition(){return c("plugin:window|inner_position",{label:this.label}).then((({x:e,y:t})=>new v(e,t)))}async outerPosition(){return c("plugin:window|outer_position",{label:this.label}).then((({x:e,y:t})=>new v(e,t)))}async innerSize(){return c("plugin:window|inner_size",{label:this.label}).then((({width:e,height:t})=>new b(e,t)))}async outerSize(){return c("plugin:window|outer_size",{label:this.label}).then((({width:e,height:t})=>new b(e,t)))}async isFullscreen(){return c("plugin:window|is_fullscreen",{label:this.label})}async isMinimized(){return c("plugin:window|is_minimized",{label:this.label})}async isMaximized(){return c("plugin:window|is_maximized",{label:this.label})}async isFocused(){return c("plugin:window|is_focused",{label:this.label})}async isDecorated(){return c("plugin:window|is_decorated",{label:this.label})}async isResizable(){return c("plugin:window|is_resizable",{label:this.label})}async isMaximizable(){return c("plugin:window|is_maximizable",{label:this.label})}async isMinimizable(){return c("plugin:window|is_minimizable",{label:this.label})}async isClosable(){return c("plugin:window|is_closable",{label:this.label})}async isVisible(){return c("plugin:window|is_visible",{label:this.label})}async title(){return c("plugin:window|title",{label:this.label})}async theme(){return c("plugin:window|theme",{label:this.label})}async center(){return c("plugin:window|center",{label:this.label})}async requestUserAttention(e){let t=null;return e&&(t=e===P.Critical?{type:"Critical"}:{type:"Informational"}),c("plugin:window|request_user_attention",{label:this.label,value:t})}async setResizable(e){return c("plugin:window|set_resizable",{label:this.label,value:e})}async setMaximizable(e){return c("plugin:window|set_maximizable",{label:this.label,value:e})}async setMinimizable(e){return c("plugin:window|set_minimizable",{label:this.label,value:e})}async setClosable(e){return c("plugin:window|set_closable",{label:this.label,value:e})}async setTitle(e){return c("plugin:window|set_title",{label:this.label,value:e})}async maximize(){return c("plugin:window|maximize",{label:this.label})}async unmaximize(){return c("plugin:window|unmaximize",{label:this.label})}async toggleMaximize(){return c("plugin:window|toggle_maximize",{label:this.label})}async minimize(){return c("plugin:window|minimize",{label:this.label})}async unminimize(){return c("plugin:window|unminimize",{label:this.label})}async show(){return c("plugin:window|show",{label:this.label})}async hide(){return c("plugin:window|hide",{label:this.label})}async close(){return c("plugin:window|close",{label:this.label})}async destroy(){return c("plugin:window|destroy",{label:this.label})}async setDecorations(e){return c("plugin:window|set_decorations",{label:this.label,value:e})}async setShadow(e){return c("plugin:window|set_shadow",{label:this.label,value:e})}async setEffects(e){return c("plugin:window|set_effects",{label:this.label,value:e})}async clearEffects(){return c("plugin:window|set_effects",{label:this.label,value:null})}async setAlwaysOnTop(e){return c("plugin:window|set_always_on_top",{label:this.label,value:e})}async setAlwaysOnBottom(e){return c("plugin:window|set_always_on_bottom",{label:this.label,value:e})}async setContentProtected(e){return c("plugin:window|set_content_protected",{label:this.label,value:e})}async setSize(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");const t={};return t[`${e.type}`]={width:e.width,height:e.height},c("plugin:window|set_size",{label:this.label,value:t})}async setMinSize(e){if(e&&"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");let t=null;return e&&(t={},t[`${e.type}`]={width:e.width,height:e.height}),c("plugin:window|set_min_size",{label:this.label,value:t})}async setMaxSize(e){if(e&&"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");let t=null;return e&&(t={},t[`${e.type}`]={width:e.width,height:e.height}),c("plugin:window|set_max_size",{label:this.label,value:t})}async setSizeConstraints(e){function t(e){return e?{Logical:e}:null}return c("plugin:window|set_size_constraints",{label:this.label,value:{minWidth:t(null==e?void 0:e.minWidth),minHeight:t(null==e?void 0:e.minHeight),maxWidth:t(null==e?void 0:e.maxWidth),maxHeight:t(null==e?void 0:e.maxHeight)}})}async setPosition(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");const t={};return t[`${e.type}`]={x:e.x,y:e.y},c("plugin:window|set_position",{label:this.label,value:t})}async setFullscreen(e){return c("plugin:window|set_fullscreen",{label:this.label,value:e})}async setFocus(){return c("plugin:window|set_focus",{label:this.label})}async setIcon(e){return c("plugin:window|set_icon",{label:this.label,value:w(e)})}async setSkipTaskbar(e){return c("plugin:window|set_skip_taskbar",{label:this.label,value:e})}async setCursorGrab(e){return c("plugin:window|set_cursor_grab",{label:this.label,value:e})}async setCursorVisible(e){return c("plugin:window|set_cursor_visible",{label:this.label,value:e})}async setCursorIcon(e){return c("plugin:window|set_cursor_icon",{label:this.label,value:e})}async setCursorPosition(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");const t={};return t[`${e.type}`]={x:e.x,y:e.y},c("plugin:window|set_cursor_position",{label:this.label,value:t})}async setIgnoreCursorEvents(e){return c("plugin:window|set_ignore_cursor_events",{label:this.label,value:e})}async startDragging(){return c("plugin:window|start_dragging",{label:this.label})}async startResizeDragging(e){return c("plugin:window|start_resize_dragging",{label:this.label,value:e})}async setProgressBar(e){return c("plugin:window|set_progress_bar",{label:this.label,value:e})}async setVisibleOnAllWorkspaces(e){return c("plugin:window|set_visible_on_all_workspaces",{label:this.label,value:e})}async setTitleBarStyle(e){return c("plugin:window|set_title_bar_style",{label:this.label,value:e})}async onResized(e){return this.listen(f.WINDOW_RESIZED,(t=>{t.payload=J(t.payload),e(t)}))}async onMoved(e){return this.listen(f.WINDOW_MOVED,(t=>{t.payload=Z(t.payload),e(t)}))}async onCloseRequested(e){return this.listen(f.WINDOW_CLOSE_REQUESTED,(async t=>{const n=new B(t);await e(n),n.isPreventDefault()||await this.destroy()}))}async onDragDropEvent(e){const t=await this.listen(f.DRAG_ENTER,(t=>{e({...t,payload:{type:"enter",paths:t.payload.paths,position:Z(t.payload.position)}})})),n=await this.listen(f.DRAG_OVER,(t=>{e({...t,payload:{type:"over",position:Z(t.payload.position)}})})),i=await this.listen(f.DRAG_DROP,(t=>{e({...t,payload:{type:"drop",paths:t.payload.paths,position:Z(t.payload.position)}})})),r=await this.listen(f.DRAG_LEAVE,(t=>{e({...t,payload:{type:"leave"}})}));return()=>{t(),i(),n(),r()}}async onFocusChanged(e){const t=await this.listen(f.WINDOW_FOCUS,(t=>{e({...t,payload:!0})})),n=await this.listen(f.WINDOW_BLUR,(t=>{e({...t,payload:!1})}));return()=>{t(),n()}}async onScaleChanged(e){return this.listen(f.WINDOW_SCALE_FACTOR_CHANGED,e)}async onThemeChanged(e){return this.listen(f.WINDOW_THEME_CHANGED,e)}}var $,q;function Q(e){return null===e?null:{name:e.name,scaleFactor:e.scaleFactor,position:Z(e.position),size:J(e.size)}}function Z(e){return new v(e.x,e.y)}function J(e){return new b(e.width,e.height)}!function(e){e.AppearanceBased="appearanceBased",e.Light="light",e.Dark="dark",e.MediumLight="mediumLight",e.UltraDark="ultraDark",e.Titlebar="titlebar",e.Selection="selection",e.Menu="menu",e.Popover="popover",e.Sidebar="sidebar",e.HeaderView="headerView",e.Sheet="sheet",e.WindowBackground="windowBackground",e.HudWindow="hudWindow",e.FullScreenUI="fullScreenUI",e.Tooltip="tooltip",e.ContentBackground="contentBackground",e.UnderWindowBackground="underWindowBackground",e.UnderPageBackground="underPageBackground",e.Mica="mica",e.Blur="blur",e.Acrylic="acrylic",e.Tabbed="tabbed",e.TabbedDark="tabbedDark",e.TabbedLight="tabbedLight"}($||($={})),function(e){e.FollowsWindowActiveState="followsWindowActiveState",e.Active="active",e.Inactive="inactive"}(q||(q={}));var K=Object.freeze({__proto__:null,CloseRequestedEvent:B,get Effect(){return $},get EffectState(){return q},LogicalPosition:m,LogicalSize:g,PhysicalPosition:v,PhysicalSize:b,get ProgressBarStatus(){return x},get UserAttentionType(){return P},Window:H,availableMonitors:async function(){return c("plugin:window|available_monitors").then((e=>e.map(Q)))},currentMonitor:async function(){return c("plugin:window|current_monitor").then(Q)},cursorPosition:async function(){return c("plugin:window|cursor_position").then(Z)},getAllWindows:V,getCurrentWindow:j,monitorFromPoint:async function(e,t){return c("plugin:window|monitor_from_point",{x:e,y:t}).then(Q)},primaryMonitor:async function(){return c("plugin:window|primary_monitor").then(Q)}});function Y([e,t,n]){switch(n){case"Submenu":return new X(e,t);case"Predefined":return new M(e,t);case"Check":return new F(e,t);case"Icon":return new U(e,t);default:return new O(e,t)}}class X extends z{constructor(e,t){super(e,t,"Submenu")}static async new(e){return W("Submenu",e).then((([e,t])=>new X(e,t)))}async text(){return c("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return c("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return c("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return c("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async append(e){return c("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async prepend(e){return c("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async insert(e,t){return c("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e)),position:t})}async remove(e){return c("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return c("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(Y)}async items(){return c("plugin:menu|items",{rid:this.rid,kind:this.kind}).then((e=>e.map(Y)))}async get(e){return c("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then((e=>e?Y(e):null))}async popup(e,t){var n;let i=null;return e&&(i={},i[""+(e instanceof v?"Physical":"Logical")]={x:e.x,y:e.y}),c("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:null!==(n=null==t?void 0:t.label)&&void 0!==n?n:null,at:i})}async setAsWindowsMenuForNSApp(){return c("plugin:menu|set_as_windows_menu_for_nsapp",{rid:this.rid})}async setAsHelpMenuForNSApp(){return c("plugin:menu|set_as_help_menu_for_nsapp",{rid:this.rid})}}function ee([e,t,n]){switch(n){case"Submenu":return new X(e,t);case"Predefined":return new M(e,t);case"Check":return new F(e,t);case"Icon":return new U(e,t);default:return new O(e,t)}}class te extends z{constructor(e,t){super(e,t,"Menu")}static async new(e){return W("Menu",e).then((([e,t])=>new te(e,t)))}static async default(){return c("plugin:menu|create_default").then((([e,t])=>new te(e,t)))}async append(e){return c("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async prepend(e){return c("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async insert(e,t){return c("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e)),position:t})}async remove(e){return c("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return c("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(ee)}async items(){return c("plugin:menu|items",{rid:this.rid,kind:this.kind}).then((e=>e.map(ee)))}async get(e){return c("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then((e=>e?ee(e):null))}async popup(e,t){var n;let i=null;return e&&(i={},i[""+(e instanceof v?"Physical":"Logical")]={x:e.x,y:e.y}),c("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:null!==(n=null==t?void 0:t.label)&&void 0!==n?n:null,at:i})}async setAsAppMenu(){return c("plugin:menu|set_as_app_menu",{rid:this.rid}).then((e=>e?new te(e[0],e[1]):null))}async setAsWindowMenu(e){var t;return c("plugin:menu|set_as_window_menu",{rid:this.rid,window:null!==(t=null==e?void 0:e.label)&&void 0!==t?t:null}).then((e=>e?new te(e[0],e[1]):null))}}var ne=Object.freeze({__proto__:null,CheckMenuItem:F,IconMenuItem:U,Menu:te,MenuItem:O,get NativeIcon(){return L},PredefinedMenuItem:M,Submenu:X});function ie(){var e;window.__TAURI_INTERNALS__=null!==(e=window.__TAURI_INTERNALS__)&&void 0!==e?e:{}}var re,ae=Object.freeze({__proto__:null,clearMocks:function(){var e,t,n;"object"==typeof window.__TAURI_INTERNALS__&&((null===(e=window.__TAURI_INTERNALS__)||void 0===e?void 0:e.convertFileSrc)&&delete window.__TAURI_INTERNALS__.convertFileSrc,(null===(t=window.__TAURI_INTERNALS__)||void 0===t?void 0:t.invoke)&&delete window.__TAURI_INTERNALS__.invoke,(null===(n=window.__TAURI_INTERNALS__)||void 0===n?void 0:n.metadata)&&delete window.__TAURI_INTERNALS__.metadata)},mockConvertFileSrc:function(e){ie(),window.__TAURI_INTERNALS__.convertFileSrc=function(t,n="asset"){const i=encodeURIComponent(t);return"windows"===e?`http://${n}.localhost/${i}`:`${n}://localhost/${i}`}},mockIPC:function(e){ie(),window.__TAURI_INTERNALS__.transformCallback=function(e,t=!1){const n=window.crypto.getRandomValues(new Uint32Array(1))[0],i=`_${n}`;return Object.defineProperty(window,i,{value:n=>(t&&Reflect.deleteProperty(window,i),e&&e(n)),writable:!1,configurable:!0}),n},window.__TAURI_INTERNALS__.invoke=function(t,n,i){return e(t,n)}},mockWindows:function(e,...t){ie(),window.__TAURI_INTERNALS__.metadata={windows:[e,...t].map((e=>({label:e}))),currentWindow:{label:e},webviews:[e,...t].map((e=>({windowLabel:e,label:e}))),currentWebview:{windowLabel:e,label:e}}}});!function(e){e[e.Audio=1]="Audio",e[e.Cache=2]="Cache",e[e.Config=3]="Config",e[e.Data=4]="Data",e[e.LocalData=5]="LocalData",e[e.Document=6]="Document",e[e.Download=7]="Download",e[e.Picture=8]="Picture",e[e.Public=9]="Public",e[e.Video=10]="Video",e[e.Resource=11]="Resource",e[e.Temp=12]="Temp",e[e.AppConfig=13]="AppConfig",e[e.AppData=14]="AppData",e[e.AppLocalData=15]="AppLocalData",e[e.AppCache=16]="AppCache",e[e.AppLog=17]="AppLog",e[e.Desktop=18]="Desktop",e[e.Executable=19]="Executable",e[e.Font=20]="Font",e[e.Home=21]="Home",e[e.Runtime=22]="Runtime",e[e.Template=23]="Template"}(re||(re={}));var se=Object.freeze({__proto__:null,get BaseDirectory(){return re},appCacheDir:async function(){return c("plugin:path|resolve_directory",{directory:re.AppCache})},appConfigDir:async function(){return c("plugin:path|resolve_directory",{directory:re.AppConfig})},appDataDir:async function(){return c("plugin:path|resolve_directory",{directory:re.AppData})},appLocalDataDir:async function(){return c("plugin:path|resolve_directory",{directory:re.AppLocalData})},appLogDir:async function(){return c("plugin:path|resolve_directory",{directory:re.AppLog})},audioDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Audio})},basename:async function(e,t){return c("plugin:path|basename",{path:e,ext:t})},cacheDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Cache})},configDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Config})},dataDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Data})},delimiter:function(){return window.__TAURI_INTERNALS__.plugins.path.delimiter},desktopDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Desktop})},dirname:async function(e){return c("plugin:path|dirname",{path:e})},documentDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Document})},downloadDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Download})},executableDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Executable})},extname:async function(e){return c("plugin:path|extname",{path:e})},fontDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Font})},homeDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Home})},isAbsolute:async function(e){return c("plugin:path|isAbsolute",{path:e})},join:async function(...e){return c("plugin:path|join",{paths:e})},localDataDir:async function(){return c("plugin:path|resolve_directory",{directory:re.LocalData})},normalize:async function(e){return c("plugin:path|normalize",{path:e})},pictureDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Picture})},publicDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Public})},resolve:async function(...e){return c("plugin:path|resolve",{paths:e})},resolveResource:async function(e){return c("plugin:path|resolve_directory",{directory:re.Resource,path:e})},resourceDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Resource})},runtimeDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Runtime})},sep:function(){return window.__TAURI_INTERNALS__.plugins.path.sep},tempDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Temp})},templateDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Template})},videoDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Video})}});class le extends d{constructor(e,t){super(e),this.id=t}static async getById(e){return c("plugin:tray|get_by_id",{id:e}).then((t=>t?new le(t,e):null))}static async removeById(e){return c("plugin:tray|remove_by_id",{id:e})}static async new(e){(null==e?void 0:e.menu)&&(e.menu=[e.menu.rid,e.menu.kind]),(null==e?void 0:e.icon)&&(e.icon=w(e.icon));const t=new o;return(null==e?void 0:e.action)&&(t.onmessage=e.action,delete e.action),c("plugin:tray|new",{options:null!=e?e:{},handler:t}).then((([e,t])=>new le(e,t)))}async setIcon(e){let t=null;return e&&(t=w(e)),c("plugin:tray|set_icon",{rid:this.rid,icon:t})}async setMenu(e){return e&&(e=[e.rid,e.kind]),c("plugin:tray|set_menu",{rid:this.rid,menu:e})}async setTooltip(e){return c("plugin:tray|set_tooltip",{rid:this.rid,tooltip:e})}async setTitle(e){return c("plugin:tray|set_title",{rid:this.rid,title:e})}async setVisible(e){return c("plugin:tray|set_visible",{rid:this.rid,visible:e})}async setTempDirPath(e){return c("plugin:tray|set_temp_dir_path",{rid:this.rid,path:e})}async setIconAsTemplate(e){return c("plugin:tray|set_icon_as_template",{rid:this.rid,asTemplate:e})}async setMenuOnLeftClick(e){return c("plugin:tray|set_show_menu_on_left_click",{rid:this.rid,onLeft:e})}}var oe=Object.freeze({__proto__:null,TrayIcon:le});function ue(){return new pe(j(),window.__TAURI_INTERNALS__.metadata.currentWebview.label,{skip:!0})}function ce(){return window.__TAURI_INTERNALS__.metadata.webviews.map((e=>new pe(H.getByLabel(e.windowLabel),e.label,{skip:!0})))}const de=["tauri://created","tauri://error"];class pe{constructor(e,t,n){this.window=e,this.label=t,this.listeners=Object.create(null),(null==n?void 0:n.skip)||c("plugin:webview|create_webview",{windowLabel:e.label,label:t,options:n}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static getByLabel(e){var t;return null!==(t=ce().find((t=>t.label===e)))&&void 0!==t?t:null}static getCurrent(){return ue()}static getAll(){return ce()}async listen(e,t){return this._handleTauriEvent(e,t)?()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)}:E(e,t,{target:{kind:"Webview",label:this.label}})}async once(e,t){return this._handleTauriEvent(e,t)?()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)}:T(e,t,{target:{kind:"Webview",label:this.label}})}async emit(e,t){if(!de.includes(e))return I(e,t);for(const n of this.listeners[e]||[])n({event:e,id:-1,payload:t})}async emitTo(e,t,n){if(!de.includes(t))return D(e,t,n);for(const e of this.listeners[t]||[])e({event:t,id:-1,payload:n})}_handleTauriEvent(e,t){return!!de.includes(e)&&(e in this.listeners?this.listeners[e].push(t):this.listeners[e]=[t],!0)}async position(){return c("plugin:webview|webview_position",{label:this.label}).then((({x:e,y:t})=>new v(e,t)))}async size(){return c("plugin:webview|webview_size",{label:this.label}).then((({width:e,height:t})=>new b(e,t)))}async close(){return c("plugin:webview|close",{label:this.label})}async setSize(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");const t={};return t[`${e.type}`]={width:e.width,height:e.height},c("plugin:webview|set_webview_size",{label:this.label,value:t})}async setPosition(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");const t={};return t[`${e.type}`]={x:e.x,y:e.y},c("plugin:webview|set_webview_position",{label:this.label,value:t})}async setFocus(){return c("plugin:webview|set_webview_focus",{label:this.label})}async setZoom(e){return c("plugin:webview|set_webview_zoom",{label:this.label,value:e})}async reparent(e){return c("plugin:webview|reparent",{label:this.label,window:"string"==typeof e?e:e.label})}async onDragDropEvent(e){const t=await this.listen(f.DRAG_ENTER,(t=>{e({...t,payload:{type:"enter",paths:t.payload.paths,position:he(t.payload.position)}})})),n=await this.listen(f.DRAG_OVER,(t=>{e({...t,payload:{type:"over",position:he(t.payload.position)}})})),i=await this.listen(f.DRAG_DROP,(t=>{e({...t,payload:{type:"drop",paths:t.payload.paths,position:he(t.payload.position)}})})),r=await this.listen(f.DRAG_LEAVE,(t=>{e({...t,payload:{type:"leave"}})}));return()=>{t(),i(),n(),r()}}}function he(e){return new v(e.x,e.y)}var we,ye,_e=Object.freeze({__proto__:null,Webview:pe,getAllWebviews:ce,getCurrentWebview:ue});function ge(){const e=ue();return new me(e.label,{skip:!0})}function be(){return window.__TAURI_INTERNALS__.metadata.webviews.map((e=>new me(e.label,{skip:!0})))}class me{constructor(e,t={}){var n;this.label=e,this.listeners=Object.create(null),(null==t?void 0:t.skip)||c("plugin:webview|create_webview_window",{options:{...t,parent:"string"==typeof t.parent?t.parent:null===(n=t.parent)||void 0===n?void 0:n.label,label:e}}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static getByLabel(e){var t;const n=null!==(t=be().find((t=>t.label===e)))&&void 0!==t?t:null;return n?new me(n.label,{skip:!0}):null}static getCurrent(){return ge()}static getAll(){return be().map((e=>new me(e.label,{skip:!0})))}async listen(e,t){return this._handleTauriEvent(e,t)?()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)}:E(e,t,{target:{kind:"WebviewWindow",label:this.label}})}async once(e,t){return this._handleTauriEvent(e,t)?()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)}:T(e,t,{target:{kind:"WebviewWindow",label:this.label}})}}we=me,ye=[H,pe],(Array.isArray(ye)?ye:[ye]).forEach((e=>{Object.getOwnPropertyNames(e.prototype).forEach((t=>{var n;"object"==typeof we.prototype&&we.prototype&&t in we.prototype||Object.defineProperty(we.prototype,t,null!==(n=Object.getOwnPropertyDescriptor(e.prototype,t))&&void 0!==n?n:Object.create(null))}))}));var ve=Object.freeze({__proto__:null,WebviewWindow:me,getAllWebviewWindows:be,getCurrentWebviewWindow:ge});return e.app=_,e.core=p,e.dpi=k,e.event=N,e.image=y,e.menu=ne,e.mocks=ae,e.path=se,e.tray=oe,e.webview=_e,e.webviewWindow=ve,e.window=K,e}({});window.__TAURI__=__TAURI_IIFE__; diff --git a/core/tauri/scripts/ipc.js b/core/tauri/scripts/ipc.js index 77b21f5d3..28cf33150 100644 --- a/core/tauri/scripts/ipc.js +++ b/core/tauri/scripts/ipc.js @@ -39,7 +39,9 @@ const keys = Object.keys(event.data.payload || {}) return ( keys.length > 0 && - keys.every((key) => key === 'nonce' || key === 'payload') + keys.every( + (key) => key === 'contentType' || key === 'nonce' || key === 'payload' + ) ) } return false diff --git a/core/tauri/src/app.rs b/core/tauri/src/app.rs index 3d1b2158b..314a9120d 100644 --- a/core/tauri/src/app.rs +++ b/core/tauri/src/app.rs @@ -22,8 +22,8 @@ use crate::{ utils::config::Config, utils::Env, webview::PageLoadPayload, - Context, DeviceEventFilter, EventLoopMessage, Manager, Monitor, Runtime, Scopes, StateManager, - Theme, Webview, WebviewWindowBuilder, Window, + Context, DeviceEventFilter, Emitter, EventLoopMessage, Listener, Manager, Monitor, Result, + Runtime, Scopes, StateManager, Theme, Webview, WebviewWindowBuilder, Window, }; #[cfg(desktop)] @@ -42,6 +42,7 @@ use tauri_runtime::{ }; use tauri_utils::PackageInfo; +use serde::Serialize; use std::{ borrow::Cow, collections::HashMap, @@ -66,7 +67,7 @@ pub(crate) type GlobalWebviewEventListener = Box, &WebviewEvent) + Send + Sync>; /// A closure that is run when the Tauri application is setting up. pub type SetupHook = - Box) -> Result<(), Box> + Send>; + Box) -> std::result::Result<(), Box> + Send>; /// A closure that is run every time a page starts or finishes loading. pub type OnPageLoad = dyn Fn(&Webview, &PageLoadPayload<'_>) + Send + Sync + 'static; @@ -268,7 +269,45 @@ pub struct AssetResolver { impl AssetResolver { /// Gets the app asset associated with the given path. + /// + /// Resolves to the embedded asset that is part of the app + /// in dev when [`devPath`](https://tauri.app/v1/api/config/#buildconfig.devpath) points to a folder in your filesystem + /// or in production when [`distDir`](https://tauri.app/v1/api/config/#buildconfig.distdir) + /// points to your frontend assets. + /// + /// Fallbacks to reading the asset from the [distDir] folder so the behavior is consistent in development. + /// Note that the dist directory must exist so you might need to build your frontend assets first. pub fn get(&self, path: String) -> Option { + #[cfg(dev)] + { + // on dev if the devPath is a path to a directory we have the embedded assets + // so we can use get_asset() directly + // we only fallback to reading from distDir directly if we're using an external URL (which is likely) + if let (Some(_), Some(crate::utils::config::FrontendDist::Directory(dist_path))) = ( + &self.manager.config().build.dev_url, + &self.manager.config().build.frontend_dist, + ) { + let asset_path = std::path::PathBuf::from(&path) + .components() + .filter(|c| !matches!(c, std::path::Component::RootDir)) + .collect::(); + + let asset_path = self + .manager + .config_parent() + .map(|p| p.join(dist_path).join(&asset_path)) + .unwrap_or_else(|| dist_path.join(&asset_path)); + return std::fs::read(asset_path).ok().map(|bytes| { + let mime_type = crate::utils::mime_type::MimeType::parse(&bytes, &path); + Asset { + bytes, + mime_type, + csp_header: None, + } + }); + } + } + self.manager.get_asset(path).ok() } @@ -328,7 +367,7 @@ impl Clone for AppHandle { impl<'de, R: Runtime> CommandArg<'de, R> for AppHandle { /// Grabs the [`Window`] from the [`CommandItem`] and returns the associated [`AppHandle`]. This will never fail. - fn from_command(command: CommandItem<'de, R>) -> Result { + fn from_command(command: CommandItem<'de, R>) -> std::result::Result { Ok(command.message.webview().window().app_handle) } } @@ -417,7 +456,7 @@ impl AppHandle { } /// Restarts the app by triggering [`RunEvent::ExitRequested`] with code [`RESTART_EXIT_CODE`] and [`RunEvent::Exit`].. - pub fn restart(&self) { + pub fn restart(&self) -> ! { if self.runtime_handle.request_exit(RESTART_EXIT_CODE).is_err() { self.cleanup_before_exit(); } @@ -820,14 +859,13 @@ macro_rules! shared_app_impl { } } - /// Event system APIs. - impl $app { + impl Listener for $app { /// Listen to an event on this app. /// /// # Examples /// /// ``` - /// use tauri::Manager; + /// use tauri::Listener; /// /// tauri::Builder::default() /// .setup(|app| { @@ -838,19 +876,29 @@ macro_rules! shared_app_impl { /// Ok(()) /// }); /// ``` - pub fn listen(&self, event: impl Into, handler: F) -> EventId + fn listen(&self, event: impl Into, handler: F) -> EventId where F: Fn(Event) + Send + 'static, { self.manager.listen(event.into(), EventTarget::App, handler) } + /// Listen to an event on this app only once. + /// + /// See [`Self::listen`] for more information. + fn once(&self, event: impl Into, handler: F) -> EventId + where + F: FnOnce(Event) + Send + 'static, + { + self.manager.once(event.into(), EventTarget::App, handler) + } + /// Unlisten to an event on this app. /// /// # Examples /// /// ``` - /// use tauri::Manager; + /// use tauri::Listener; /// /// tauri::Builder::default() /// .setup(|app| { @@ -864,18 +912,82 @@ macro_rules! shared_app_impl { /// Ok(()) /// }); /// ``` - pub fn unlisten(&self, id: EventId) { + fn unlisten(&self, id: EventId) { self.manager.unlisten(id) } + } - /// Listen to an event on this app only once. + impl Emitter for $app { + /// Emits an event to all [targets](EventTarget). /// - /// See [`Self::listen`] for more information. - pub fn once(&self, event: impl Into, handler: F) -> EventId + /// # Examples + /// ``` + /// use tauri::Emitter; + /// + /// #[tauri::command] + /// fn synchronize(app: tauri::AppHandle) { + /// // emits the synchronized event to all webviews + /// app.emit("synchronized", ()); + /// } + /// ``` + fn emit(&self, event: &str, payload: S) -> Result<()> { + self.manager.emit(event, payload) + } + + /// Emits an event to all [targets](EventTarget) matching the given target. + /// + /// # Examples + /// ``` + /// use tauri::{Emitter, EventTarget}; + /// + /// #[tauri::command] + /// fn download(app: tauri::AppHandle) { + /// for i in 1..100 { + /// std::thread::sleep(std::time::Duration::from_millis(150)); + /// // emit a download progress event to all listeners + /// app.emit_to(EventTarget::any(), "download-progress", i); + /// // emit an event to listeners that used App::listen or AppHandle::listen + /// app.emit_to(EventTarget::app(), "download-progress", i); + /// // emit an event to any webview/window/webviewWindow matching the given label + /// app.emit_to("updater", "download-progress", i); // similar to using EventTarget::labeled + /// app.emit_to(EventTarget::labeled("updater"), "download-progress", i); + /// // emit an event to listeners that used WebviewWindow::listen + /// app.emit_to(EventTarget::webview_window("updater"), "download-progress", i); + /// } + /// } + /// ``` + fn emit_to(&self, target: I, event: &str, payload: S) -> Result<()> where - F: FnOnce(Event) + Send + 'static, + I: Into, + S: Serialize + Clone, { - self.manager.once(event.into(), EventTarget::App, handler) + self.manager.emit_to(target, event, payload) + } + + /// Emits an event to all [targets](EventTarget) based on the given filter. + /// + /// # Examples + /// ``` + /// use tauri::{Emitter, EventTarget}; + /// + /// #[tauri::command] + /// fn download(app: tauri::AppHandle) { + /// for i in 1..100 { + /// std::thread::sleep(std::time::Duration::from_millis(150)); + /// // emit a download progress event to the updater window + /// app.emit_filter("download-progress", i, |t| match t { + /// EventTarget::WebviewWindow { label } => label == "main", + /// _ => false, + /// }); + /// } + /// } + /// ``` + fn emit_filter(&self, event: &str, payload: S, filter: F) -> Result<()> + where + S: Serialize + Clone, + F: Fn(&EventTarget) -> bool, + { + self.manager.emit_filter(event, payload, filter) } } }; @@ -1230,7 +1342,7 @@ use tauri::Manager; tauri::Builder::default() .setup(|app| { let main_window = app.get_window("main").unwrap(); - main_window.set_title("Tauri!"); + main_window.set_title("Tauri!")?; Ok(()) }); ``` @@ -1239,7 +1351,7 @@ tauri::Builder::default() #[must_use] pub fn setup(mut self, setup: F) -> Self where - F: FnOnce(&mut App) -> Result<(), Box> + Send + 'static, + F: FnOnce(&mut App) -> std::result::Result<(), Box> + Send + 'static, { self.setup = Box::new(setup); self @@ -1632,6 +1744,12 @@ tauri::Builder::default() self.invoke_key, )); + let app_id = if manager.config.app.enable_gtk_app_id { + Some(manager.config.identifier.clone()) + } else { + None + }; + let runtime_args = RuntimeInitArgs { #[cfg(any( target_os = "linux", @@ -1640,7 +1758,7 @@ tauri::Builder::default() target_os = "netbsd", target_os = "openbsd" ))] - app_id: Some(manager.config.identifier.clone()), + app_id, #[cfg(windows)] msg_hook: { diff --git a/core/tauri/src/event/mod.rs b/core/tauri/src/event/mod.rs index 2086a7d62..5338bfeb3 100644 --- a/core/tauri/src/event/mod.rs +++ b/core/tauri/src/event/mod.rs @@ -175,22 +175,20 @@ pub fn listen_js_script( ) -> String { format!( "(function () {{ - if (window['{listeners}'] === void 0) {{ - Object.defineProperty(window, '{listeners}', {{ value: Object.create(null) }}); + if (window['{listeners_object_name}'] === void 0) {{ + Object.defineProperty(window, '{listeners_object_name}', {{ value: Object.create(null) }}); }} - if (window['{listeners}']['{event}'] === void 0) {{ - Object.defineProperty(window['{listeners}'], '{event}', {{ value: Object.create(null) }}); + if (window['{listeners_object_name}']['{event}'] === void 0) {{ + Object.defineProperty(window['{listeners_object_name}'], '{event}', {{ value: Object.create(null) }}); }} - const eventListeners = window['{listeners}']['{event}'] + const eventListeners = window['{listeners_object_name}']['{event}'] const listener = {{ - target: {target}, + target: {serialized_target}, handler: {handler} }}; Object.defineProperty(eventListeners, '{event_id}', {{ value: listener, configurable: true }}); }})() ", - listeners = listeners_object_name, - target = serialized_target, ) } diff --git a/core/tauri/src/event/plugin.rs b/core/tauri/src/event/plugin.rs index 34b404a4d..3857b0c74 100644 --- a/core/tauri/src/event/plugin.rs +++ b/core/tauri/src/event/plugin.rs @@ -9,8 +9,8 @@ use serde_json::Value as JsonValue; use tauri_runtime::window::is_label_valid; use crate::plugin::{Builder, TauriPlugin}; -use crate::{command, ipc::CallbackFn, EventId, Manager, Result, Runtime}; -use crate::{AppHandle, Webview}; +use crate::{command, ipc::CallbackFn, EventId, Result, Runtime}; +use crate::{AppHandle, Emitter, Webview}; use super::{is_event_name_valid, EventTarget}; diff --git a/core/tauri/src/ipc/authority.rs b/core/tauri/src/ipc/authority.rs index 662fa48a1..ca528caf6 100644 --- a/core/tauri/src/ipc/authority.rs +++ b/core/tauri/src/ipc/authority.rs @@ -426,7 +426,11 @@ impl RuntimeAuthority { ) } } else { - let permission_error_detail = if let Some(manifest) = self.acl.get(key) { + let permission_error_detail = if let Some(manifest) = self + .acl + .get(key) + .or_else(|| self.acl.get(&format!("core:{key}"))) + { let mut permissions_referencing_command = Vec::new(); if let Some(default) = &manifest.default_permission { diff --git a/core/tauri/src/ipc/channel.rs b/core/tauri/src/ipc/channel.rs index 609039eb5..922186fc4 100644 --- a/core/tauri/src/ipc/channel.rs +++ b/core/tauri/src/ipc/channel.rs @@ -37,12 +37,20 @@ pub struct ChannelDataIpcQueue(pub(crate) Arc>>); /// An IPC channel. #[derive(Clone)] -pub struct Channel { +pub struct Channel { id: u32, on_message: Arc crate::Result<()> + Send + Sync>, + phantom: std::marker::PhantomData, } -impl Serialize for Channel { +#[cfg(feature = "specta")] +const _: () = { + #[derive(specta::Type)] + #[specta(remote = super::Channel, rename = "TAURI_CHANNEL")] + struct Channel(std::marker::PhantomData); +}; + +impl Serialize for Channel { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -88,7 +96,7 @@ impl FromStr for JavaScriptChannelId { impl JavaScriptChannelId { /// Gets a [`Channel`] for this channel ID on the given [`Webview`]. - pub fn channel_on(&self, webview: Webview) -> Channel { + pub fn channel_on(&self, webview: Webview) -> Channel { let callback_id = self.0; let counter = AtomicUsize::new(0); @@ -128,7 +136,7 @@ impl<'de> Deserialize<'de> for JavaScriptChannelId { } } -impl Channel { +impl Channel { /// Creates a new channel with the given message handler. pub fn new crate::Result<()> + Send + Sync + 'static>( on_message: F, @@ -144,10 +152,15 @@ impl Channel { let channel = Self { id, on_message: Arc::new(on_message), + phantom: Default::default(), }; #[cfg(mobile)] - crate::plugin::mobile::register_channel(channel.clone()); + crate::plugin::mobile::register_channel(Channel { + id, + on_message: channel.on_message.clone(), + phantom: Default::default(), + }); channel } @@ -178,13 +191,16 @@ impl Channel { } /// Sends the given data through the channel. - pub fn send(&self, data: T) -> crate::Result<()> { + pub fn send(&self, data: TSend) -> crate::Result<()> + where + TSend: IpcResponse, + { let body = data.body()?; (self.on_message)(body) } } -impl<'de, R: Runtime> CommandArg<'de, R> for Channel { +impl<'de, R: Runtime, TSend: Clone> CommandArg<'de, R> for Channel { /// Grabs the [`Webview`] from the [`CommandItem`] and returns the associated [`Channel`]. fn from_command(command: CommandItem<'de, R>) -> Result { let name = command.name; @@ -195,9 +211,9 @@ impl<'de, R: Runtime> CommandArg<'de, R> for Channel { JavaScriptChannelId::from_str(&value) .map(|id| id.channel_on(webview)) .map_err(|_| { - InvokeError::from_anyhow(anyhow::anyhow!( - "invalid channel value `{value}`, expected a string in the `{IPC_PAYLOAD_PREFIX}ID` format" - )) + InvokeError::from(format!( + "invalid channel value `{value}`, expected a string in the `{IPC_PAYLOAD_PREFIX}ID` format" + )) }) } } diff --git a/core/tauri/src/ipc/mod.rs b/core/tauri/src/ipc/mod.rs index 1c02986e3..ca23f1829 100644 --- a/core/tauri/src/ipc/mod.rs +++ b/core/tauri/src/ipc/mod.rs @@ -46,6 +46,7 @@ pub type OwnedInvokeResponder = /// Possible values of an IPC payload. #[derive(Debug, Clone)] +#[cfg_attr(test, derive(PartialEq))] pub enum InvokeBody { /// Json payload. Json(JsonValue), @@ -159,6 +160,9 @@ impl Response { } /// The message and resolver given to a custom command. +/// +/// This struct is used internally by macros and is explicitly **NOT** stable. +#[doc(hidden)] #[default_runtime(crate::Wry, wry)] pub struct Invoke { /// The message passed. diff --git a/core/tauri/src/ipc/protocol.rs b/core/tauri/src/ipc/protocol.rs index 3d06ecd44..ad67d70b2 100644 --- a/core/tauri/src/ipc/protocol.rs +++ b/core/tauri/src/ipc/protocol.rs @@ -388,6 +388,15 @@ fn parse_invoke_request( // so we must ignore it because some commands use the IPC for faster response let has_payload = !body.is_empty(); + #[allow(unused_mut)] + let mut content_type = parts + .headers + .get(http::header::CONTENT_TYPE) + .and_then(|h| h.to_str().ok()) + .map(|mime| mime.parse()) + .unwrap_or(Ok(mime::APPLICATION_OCTET_STREAM)) + .map_err(|_| "unknown content type")?; + #[cfg(feature = "isolation")] if let crate::Pattern::Isolation { crypto_keys, .. } = &*manager.pattern { // if the platform does not support request body, we ignore it @@ -395,8 +404,18 @@ fn parse_invoke_request( #[cfg(feature = "tracing")] let _span = tracing::trace_span!("ipc::request::decrypt_isolation_payload").entered(); - body = crate::utils::pattern::isolation::RawIsolationPayload::try_from(&body) - .and_then(|raw| crypto_keys.decrypt(raw)) + (body, content_type) = crate::utils::pattern::isolation::RawIsolationPayload::try_from(&body) + .and_then(|raw| { + let content_type = raw.content_type().clone(); + crypto_keys.decrypt(raw).map(|decrypted| { + ( + decrypted, + content_type + .parse() + .unwrap_or(mime::APPLICATION_OCTET_STREAM), + ) + }) + }) .map_err(|e| e.to_string())?; } } @@ -440,14 +459,6 @@ fn parse_invoke_request( .map_err(|_| "Tauri error header value must be a numeric string")?, ); - let content_type = parts - .headers - .get(http::header::CONTENT_TYPE) - .and_then(|h| h.to_str().ok()) - .map(|mime| mime.parse()) - .unwrap_or(Ok(mime::APPLICATION_OCTET_STREAM)) - .map_err(|_| "unknown content type")?; - #[cfg(feature = "tracing")] let span = tracing::trace_span!("ipc::request::deserialize").entered(); @@ -481,3 +492,194 @@ fn parse_invoke_request( Ok(payload) } + +#[cfg(test)] +mod tests { + use std::str::FromStr; + + use super::*; + use crate::{manager::AppManager, plugin::PluginStore, StateManager, Wry}; + use http::header::*; + use serde_json::json; + use tauri_macros::generate_context; + + #[test] + fn parse_invoke_request() { + let context = generate_context!("test/fixture/src-tauri/tauri.conf.json", crate, test = true); + let manager: AppManager = AppManager::with_handlers( + context, + PluginStore::default(), + Box::new(|_| false), + None, + Default::default(), + StateManager::new(), + Default::default(), + Default::default(), + Default::default(), + (None, "".into()), + crate::generate_invoke_key().unwrap(), + ); + + let cmd = "write_something"; + let url = "tauri://localhost"; + let invoke_key = "1234ahdsjkl123"; + let callback = 12378123; + let error = 6243; + let headers = HeaderMap::from_iter(vec![ + ( + CONTENT_TYPE, + HeaderValue::from_str(mime::APPLICATION_OCTET_STREAM.as_ref()).unwrap(), + ), + ( + HeaderName::from_str(TAURI_INVOKE_KEY_HEADER_NAME).unwrap(), + HeaderValue::from_str(invoke_key).unwrap(), + ), + ( + HeaderName::from_str(TAURI_CALLBACK_HEADER_NAME).unwrap(), + HeaderValue::from_str(&callback.to_string()).unwrap(), + ), + ( + HeaderName::from_str(TAURI_ERROR_HEADER_NAME).unwrap(), + HeaderValue::from_str(&error.to_string()).unwrap(), + ), + (ORIGIN, HeaderValue::from_str("tauri://localhost").unwrap()), + ]); + + let mut request = Request::builder().uri(format!("ipc://localhost/{cmd}")); + *request.headers_mut().unwrap() = headers.clone(); + + let body = vec![123, 31, 45]; + let request = request.body(body.clone()).unwrap(); + let invoke_request = super::parse_invoke_request(&manager, request).unwrap(); + + assert_eq!(invoke_request.cmd, cmd); + assert_eq!(invoke_request.callback.0, callback); + assert_eq!(invoke_request.error.0, error); + assert_eq!(invoke_request.invoke_key, invoke_key); + assert_eq!(invoke_request.url, url.parse().unwrap()); + assert_eq!(invoke_request.headers, headers); + assert_eq!(invoke_request.body, InvokeBody::Raw(body)); + + let body = json!({ + "key": 1, + "anotherKey": "asda", + }); + + let mut headers = headers.clone(); + headers.insert( + CONTENT_TYPE, + HeaderValue::from_str(mime::APPLICATION_JSON.as_ref()).unwrap(), + ); + + let mut request = Request::builder().uri(format!("ipc://localhost/{cmd}")); + *request.headers_mut().unwrap() = headers.clone(); + + let request = request.body(serde_json::to_vec(&body).unwrap()).unwrap(); + let invoke_request = super::parse_invoke_request(&manager, request).unwrap(); + + assert_eq!(invoke_request.headers, headers); + assert_eq!(invoke_request.body, InvokeBody::Json(body)); + } + + #[test] + #[cfg(feature = "isolation")] + fn parse_invoke_request_isolation() { + let context = generate_context!( + "test/fixture/isolation/src-tauri/tauri.conf.json", + crate, + test = false + ); + + let crate::pattern::Pattern::Isolation { crypto_keys, .. } = &context.pattern else { + unreachable!() + }; + + let mut nonce = [0u8; 12]; + getrandom::getrandom(&mut nonce).unwrap(); + + let body_raw = vec![1, 41, 65, 12, 78]; + let body_bytes = crypto_keys.aes_gcm().encrypt(&nonce, &body_raw).unwrap(); + let isolation_payload_raw = json!({ + "nonce": nonce, + "payload": body_bytes, + "contentType": mime::APPLICATION_OCTET_STREAM.to_string(), + }); + + let body_json = json!({ + "key": 1, + "anotherKey": "string" + }); + let body_bytes = crypto_keys + .aes_gcm() + .encrypt(&nonce, &serde_json::to_vec(&body_json).unwrap()) + .unwrap(); + let isolation_payload_json = json!({ + "nonce": nonce, + "payload": body_bytes, + "contentType": mime::APPLICATION_JSON.to_string(), + }); + + let manager: AppManager = AppManager::with_handlers( + context, + PluginStore::default(), + Box::new(|_| false), + None, + Default::default(), + StateManager::new(), + Default::default(), + Default::default(), + Default::default(), + (None, "".into()), + crate::generate_invoke_key().unwrap(), + ); + + let cmd = "write_something"; + let url = "tauri://localhost"; + let invoke_key = "1234ahdsjkl123"; + let callback = 12378123; + let error = 6243; + + let headers = HeaderMap::from_iter(vec![ + ( + CONTENT_TYPE, + HeaderValue::from_str(mime::APPLICATION_JSON.as_ref()).unwrap(), + ), + ( + HeaderName::from_str(TAURI_INVOKE_KEY_HEADER_NAME).unwrap(), + HeaderValue::from_str(invoke_key).unwrap(), + ), + ( + HeaderName::from_str(TAURI_CALLBACK_HEADER_NAME).unwrap(), + HeaderValue::from_str(&callback.to_string()).unwrap(), + ), + ( + HeaderName::from_str(TAURI_ERROR_HEADER_NAME).unwrap(), + HeaderValue::from_str(&error.to_string()).unwrap(), + ), + (ORIGIN, HeaderValue::from_str("tauri://localhost").unwrap()), + ]); + + let mut request = Request::builder().uri(format!("ipc://localhost/{cmd}")); + *request.headers_mut().unwrap() = headers.clone(); + let body = serde_json::to_vec(&isolation_payload_raw).unwrap(); + let request = request.body(body).unwrap(); + let invoke_request = super::parse_invoke_request(&manager, request).unwrap(); + + assert_eq!(invoke_request.cmd, cmd); + assert_eq!(invoke_request.callback.0, callback); + assert_eq!(invoke_request.error.0, error); + assert_eq!(invoke_request.invoke_key, invoke_key); + assert_eq!(invoke_request.url, url.parse().unwrap()); + assert_eq!(invoke_request.headers, headers); + assert_eq!(invoke_request.body, InvokeBody::Raw(body_raw)); + + let mut request = Request::builder().uri(format!("ipc://localhost/{cmd}")); + *request.headers_mut().unwrap() = headers.clone(); + let body = serde_json::to_vec(&isolation_payload_json).unwrap(); + let request = request.body(body).unwrap(); + let invoke_request = super::parse_invoke_request(&manager, request).unwrap(); + + assert_eq!(invoke_request.headers, headers); + assert_eq!(invoke_request.body, InvokeBody::Json(body_json)); + } +} diff --git a/core/tauri/src/lib.rs b/core/tauri/src/lib.rs index eabb02d9d..10cc5b1c2 100644 --- a/core/tauri/src/lib.rs +++ b/core/tauri/src/lib.rs @@ -23,7 +23,7 @@ //! - **isolation**: Enables the isolation pattern. Enabled by default if the `app > security > pattern > use` config option is set to `isolation` on the `tauri.conf.json` file. //! - **custom-protocol**: Feature managed by the Tauri CLI. When enabled, Tauri assumes a production environment instead of a development one. //! - **devtools**: Enables the developer tools (Web inspector) and [`window::Window#method.open_devtools`]. Enabled by default on debug builds. -//! On macOS it uses private APIs, so you can't enable it if your app will be published to the App Store. +//! On macOS it uses private APIs, so you can't enable it if your app will be published to the App Store. //! - **native-tls**: Provides TLS support to connect over HTTPS. //! - **native-tls-vendored**: Compile and statically link to a vendored copy of OpenSSL. //! - **rustls-tls**: Provides TLS support to connect over HTTPS using rustls. @@ -147,6 +147,7 @@ macro_rules! android_binding { ::tauri::tao ); + // be careful when renaming this, the `Java_app_tauri_plugin_PluginManager_handlePluginResponse` symbol is checked by the CLI ::tauri::tao::platform::android::prelude::android_fn!( app_tauri, plugin, @@ -222,7 +223,7 @@ pub use { self::runtime::{ dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Pixel, Position, Size}, webview::WebviewAttributes, - window::{CursorIcon, DragDropEvent}, + window::{CursorIcon, DragDropEvent, WindowSizeConstraints}, DeviceEventFilter, Rect, UserAttentionType, }, self::state::{State, StateManager}, @@ -379,6 +380,8 @@ impl Assets for EmbeddedAssets { #[tauri_macros::default_runtime(Wry, wry)] pub struct Context { pub(crate) config: Config, + #[cfg(dev)] + pub(crate) config_parent: Option, /// Asset provider. pub assets: Box>, pub(crate) default_window_icon: Option>, @@ -507,6 +510,8 @@ impl Context { ) -> Self { Self { config, + #[cfg(dev)] + config_parent: None, assets, default_window_icon, app_icon, @@ -519,6 +524,14 @@ impl Context { plugin_global_api_scripts, } } + + #[cfg(dev)] + #[doc(hidden)] + pub fn with_config_parent(&mut self, config_parent: impl AsRef) { + self + .config_parent + .replace(config_parent.as_ref().to_owned()); + } } // TODO: expand these docs @@ -539,178 +552,6 @@ pub trait Manager: sealed::ManagerBase { self.manager().package_info() } - /// Listen to an emitted event to any [target](EventTarget). - /// - /// # Examples - /// ``` - /// use tauri::Manager; - /// - /// #[tauri::command] - /// fn synchronize(window: tauri::Window) { - /// // emits the synchronized event to all windows - /// window.emit("synchronized", ()); - /// } - /// - /// tauri::Builder::default() - /// .setup(|app| { - /// app.listen_any("synchronized", |event| { - /// println!("app is in sync"); - /// }); - /// Ok(()) - /// }) - /// .invoke_handler(tauri::generate_handler![synchronize]); - /// ``` - fn listen_any(&self, event: impl Into, handler: F) -> EventId - where - F: Fn(Event) + Send + 'static, - { - self - .manager() - .listen(event.into(), EventTarget::Any, handler) - } - - /// Remove an event listener. - /// - /// # Examples - /// ``` - /// use tauri::Manager; - /// - /// tauri::Builder::default() - /// .setup(|app| { - /// let handle = app.handle().clone(); - /// let handler = app.listen_any("ready", move |event| { - /// println!("app is ready"); - /// - /// // we no longer need to listen to the event - /// // we also could have used `app.once_global` instead - /// handle.unlisten(event.id()); - /// }); - /// - /// // stop listening to the event when you do not need it anymore - /// app.unlisten(handler); - /// - /// - /// Ok(()) - /// }); - /// ``` - fn unlisten(&self, id: EventId) { - self.manager().unlisten(id) - } - - /// Listens once to an emitted event to any [target](EventTarget) . - /// - /// See [`Self::listen_any`] for more information. - fn once_any(&self, event: impl Into, handler: F) -> EventId - where - F: FnOnce(Event) + Send + 'static, - { - self.manager().once(event.into(), EventTarget::Any, handler) - } - - /// Emits an event to all [targets](EventTarget). - /// - /// # Examples - /// ``` - /// use tauri::Manager; - /// - /// #[tauri::command] - /// fn synchronize(app: tauri::AppHandle) { - /// // emits the synchronized event to all webviews - /// app.emit("synchronized", ()); - /// } - /// ``` - #[cfg_attr( - feature = "tracing", - tracing::instrument("app::emit", skip(self, payload)) - )] - fn emit(&self, event: &str, payload: S) -> Result<()> { - self.manager().emit(event, payload) - } - - /// Emits an event to all [targets](EventTarget) matching the given target. - /// - /// # Examples - /// ``` - /// use tauri::{Manager, EventTarget}; - /// - /// #[tauri::command] - /// fn download(app: tauri::AppHandle) { - /// for i in 1..100 { - /// std::thread::sleep(std::time::Duration::from_millis(150)); - /// // emit a download progress event to all listeners - /// app.emit_to(EventTarget::any(), "download-progress", i); - /// // emit an event to listeners that used App::listen or AppHandle::listen - /// app.emit_to(EventTarget::app(), "download-progress", i); - /// // emit an event to any webview/window/webviewWindow matching the given label - /// app.emit_to("updater", "download-progress", i); // similar to using EventTarget::labeled - /// app.emit_to(EventTarget::labeled("updater"), "download-progress", i); - /// // emit an event to listeners that used WebviewWindow::listen - /// app.emit_to(EventTarget::webview_window("updater"), "download-progress", i); - /// } - /// } - /// ``` - #[cfg_attr( - feature = "tracing", - tracing::instrument("app::emit::to", skip(self, target, payload), fields(target)) - )] - fn emit_to(&self, target: I, event: &str, payload: S) -> Result<()> - where - I: Into, - S: Serialize + Clone, - { - let target = target.into(); - #[cfg(feature = "tracing")] - tracing::Span::current().record("target", format!("{target:?}")); - - match target { - // if targeting all, emit to all using emit without filter - EventTarget::Any => self.manager().emit(event, payload), - - // if targeting any label, emit using emit_filter and filter labels - EventTarget::AnyLabel { - label: target_label, - } => self.manager().emit_filter(event, payload, |t| match t { - EventTarget::Window { label } - | EventTarget::Webview { label } - | EventTarget::WebviewWindow { label } => label == &target_label, - _ => false, - }), - - // otherwise match same target - _ => self.manager().emit_filter(event, payload, |t| t == &target), - } - } - - /// Emits an event to all [targets](EventTarget) based on the given filter. - /// - /// # Examples - /// ``` - /// use tauri::{Manager, EventTarget}; - /// - /// #[tauri::command] - /// fn download(app: tauri::AppHandle) { - /// for i in 1..100 { - /// std::thread::sleep(std::time::Duration::from_millis(150)); - /// // emit a download progress event to the updater window - /// app.emit_filter("download-progress", i, |t| match t { - /// EventTarget::WebviewWindow { label } => label == "main", - /// _ => false, - /// }); - /// } - /// } - /// ``` - #[cfg_attr( - feature = "tracing", - tracing::instrument("app::emit::filter", skip(self, payload, filter)) - )] - fn emit_filter(&self, event: &str, payload: S, filter: F) -> Result<()> - where - S: Serialize + Clone, - F: Fn(&EventTarget) -> bool, - { - self.manager().emit_filter(event, payload, filter) - } - /// Fetch a single window from the manager. #[cfg(feature = "unstable")] #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] @@ -933,6 +774,174 @@ pub trait Manager: sealed::ManagerBase { } } +/// Listen to events. +pub trait Listener: sealed::ManagerBase { + /// Listen to an emitted event on this manager. + /// + /// # Examples + /// ``` + /// use tauri::{Manager, Listener, Emitter}; + /// + /// #[tauri::command] + /// fn synchronize(window: tauri::Window) { + /// // emits the synchronized event to all windows + /// window.emit("synchronized", ()); + /// } + /// + /// tauri::Builder::default() + /// .setup(|app| { + /// app.listen("synchronized", |event| { + /// println!("app is in sync"); + /// }); + /// Ok(()) + /// }) + /// .invoke_handler(tauri::generate_handler![synchronize]); + /// ``` + fn listen(&self, event: impl Into, handler: F) -> EventId + where + F: Fn(Event) + Send + 'static; + + /// Listen to an event on this manager only once. + /// + /// See [`Self::listen`] for more information. + fn once(&self, event: impl Into, handler: F) -> EventId + where + F: FnOnce(Event) + Send + 'static; + + /// Remove an event listener. + /// + /// # Examples + /// ``` + /// use tauri::{Manager, Listener}; + /// + /// tauri::Builder::default() + /// .setup(|app| { + /// let handle = app.handle().clone(); + /// let handler = app.listen_any("ready", move |event| { + /// println!("app is ready"); + /// + /// // we no longer need to listen to the event + /// // we also could have used `app.once_global` instead + /// handle.unlisten(event.id()); + /// }); + /// + /// // stop listening to the event when you do not need it anymore + /// app.unlisten(handler); + /// + /// + /// Ok(()) + /// }); + /// ``` + fn unlisten(&self, id: EventId); + + /// Listen to an emitted event to any [target](EventTarget). + /// + /// # Examples + /// ``` + /// use tauri::{Manager, Emitter, Listener}; + /// + /// #[tauri::command] + /// fn synchronize(window: tauri::Window) { + /// // emits the synchronized event to all windows + /// window.emit("synchronized", ()); + /// } + /// + /// tauri::Builder::default() + /// .setup(|app| { + /// app.listen_any("synchronized", |event| { + /// println!("app is in sync"); + /// }); + /// Ok(()) + /// }) + /// .invoke_handler(tauri::generate_handler![synchronize]); + /// ``` + fn listen_any(&self, event: impl Into, handler: F) -> EventId + where + F: Fn(Event) + Send + 'static, + { + self + .manager() + .listen(event.into(), EventTarget::Any, handler) + } + + /// Listens once to an emitted event to any [target](EventTarget) . + /// + /// See [`Self::listen_any`] for more information. + fn once_any(&self, event: impl Into, handler: F) -> EventId + where + F: FnOnce(Event) + Send + 'static, + { + self.manager().once(event.into(), EventTarget::Any, handler) + } +} + +/// Emit events. +pub trait Emitter: sealed::ManagerBase { + /// Emits an event to all [targets](EventTarget). + /// + /// # Examples + /// ``` + /// use tauri::Emitter; + /// + /// #[tauri::command] + /// fn synchronize(app: tauri::AppHandle) { + /// // emits the synchronized event to all webviews + /// app.emit("synchronized", ()); + /// } + /// ``` + fn emit(&self, event: &str, payload: S) -> Result<()>; + + /// Emits an event to all [targets](EventTarget) matching the given target. + /// + /// # Examples + /// ``` + /// use tauri::{Emitter, EventTarget}; + /// + /// #[tauri::command] + /// fn download(app: tauri::AppHandle) { + /// for i in 1..100 { + /// std::thread::sleep(std::time::Duration::from_millis(150)); + /// // emit a download progress event to all listeners + /// app.emit_to(EventTarget::any(), "download-progress", i); + /// // emit an event to listeners that used App::listen or AppHandle::listen + /// app.emit_to(EventTarget::app(), "download-progress", i); + /// // emit an event to any webview/window/webviewWindow matching the given label + /// app.emit_to("updater", "download-progress", i); // similar to using EventTarget::labeled + /// app.emit_to(EventTarget::labeled("updater"), "download-progress", i); + /// // emit an event to listeners that used WebviewWindow::listen + /// app.emit_to(EventTarget::webview_window("updater"), "download-progress", i); + /// } + /// } + /// ``` + fn emit_to(&self, target: I, event: &str, payload: S) -> Result<()> + where + I: Into, + S: Serialize + Clone; + + /// Emits an event to all [targets](EventTarget) based on the given filter. + /// + /// # Examples + /// ``` + /// use tauri::{Emitter, EventTarget}; + /// + /// #[tauri::command] + /// fn download(app: tauri::AppHandle) { + /// for i in 1..100 { + /// std::thread::sleep(std::time::Duration::from_millis(150)); + /// // emit a download progress event to the updater window + /// app.emit_filter("download-progress", i, |t| match t { + /// EventTarget::WebviewWindow { label } => label == "main", + /// _ => false, + /// }); + /// } + /// } + /// ``` + fn emit_filter(&self, event: &str, payload: S, filter: F) -> Result<()> + where + S: Serialize + Clone, + F: Fn(&EventTarget) -> bool; +} + /// Prevent implementation details from leaking out of the [`Manager`] trait. pub(crate) mod sealed { use super::Runtime; @@ -984,7 +993,7 @@ pub mod test; #[cfg(feature = "specta")] const _: () = { - use specta::{function::FunctionArg, DataType, TypeMap}; + use specta::{datatype::DataType, function::FunctionArg, TypeMap}; impl<'r, T: Send + Sync + 'static> FunctionArg for crate::State<'r, T> { fn to_datatype(_: &mut TypeMap) -> Option { diff --git a/core/tauri/src/manager/mod.rs b/core/tauri/src/manager/mod.rs index f16d2bba0..8210706d9 100644 --- a/core/tauri/src/manager/mod.rs +++ b/core/tauri/src/manager/mod.rs @@ -102,7 +102,7 @@ pub(crate) fn set_csp( csp } -// inspired by https://github.com/rust-lang/rust/blob/1be5c8f90912c446ecbdc405cbc4a89f9acd20fd/library/alloc/src/str.rs#L260-L297 +// inspired by fn replace_with_callback String>( original: &str, pattern: &str, @@ -156,6 +156,7 @@ fn replace_csp_nonce( } /// A resolved asset. +#[non_exhaustive] pub struct Asset { /// The asset bytes. pub bytes: Vec, @@ -165,6 +166,23 @@ pub struct Asset { pub csp_header: Option, } +impl Asset { + /// The asset bytes. + pub fn bytes(&self) -> &[u8] { + &self.bytes + } + + /// The asset's mime type. + pub fn mime_type(&self) -> &str { + &self.mime_type + } + + /// The `Content-Security-Policy` header value. + pub fn csp_header(&self) -> Option<&str> { + self.csp_header.as_deref() + } +} + #[default_runtime(crate::Wry, wry)] pub struct AppManager { pub runtime_authority: Mutex, @@ -179,6 +197,8 @@ pub struct AppManager { pub listeners: Listeners, pub state: Arc, pub config: Config, + #[cfg(dev)] + pub config_parent: Option, pub assets: Box>, pub app_icon: Option>, @@ -278,6 +298,8 @@ impl AppManager { listeners: Listeners::default(), state: Arc::new(state), config: context.config, + #[cfg(dev)] + config_parent: context.config_parent, assets: context.assets, app_icon: context.app_icon, package_info: context.package_info, @@ -458,6 +480,11 @@ impl AppManager { &self.config } + #[cfg(dev)] + pub fn config_parent(&self) -> Option<&std::path::PathBuf> { + self.config_parent.as_ref() + } + pub fn package_info(&self) -> &PackageInfo { &self.package_info } @@ -472,10 +499,6 @@ impl AppManager { self.listeners().listen(event, target, handler) } - pub fn unlisten(&self, id: EventId) { - self.listeners().unlisten(id) - } - pub fn once( &self, event: String, @@ -486,6 +509,33 @@ impl AppManager { self.listeners().once(event, target, handler) } + pub fn unlisten(&self, id: EventId) { + self.listeners().unlisten(id) + } + + #[cfg_attr( + feature = "tracing", + tracing::instrument("app::emit", skip(self, payload)) + )] + pub fn emit(&self, event: &str, payload: S) -> crate::Result<()> { + assert_event_name_is_valid(event); + + #[cfg(feature = "tracing")] + let _span = tracing::debug_span!("emit::run").entered(); + let emit_args = EmitArgs::new(event, payload)?; + + let listeners = self.listeners(); + + listeners.emit_js(self.webview.webviews_lock().values(), event, &emit_args)?; + listeners.emit(emit_args)?; + + Ok(()) + } + + #[cfg_attr( + feature = "tracing", + tracing::instrument("app::emit::filter", skip(self, payload, filter)) + )] pub fn emit_filter(&self, event: &str, payload: S, filter: F) -> crate::Result<()> where S: Serialize + Clone, @@ -511,19 +561,36 @@ impl AppManager { Ok(()) } - pub fn emit(&self, event: &str, payload: S) -> crate::Result<()> { - assert_event_name_is_valid(event); - + #[cfg_attr( + feature = "tracing", + tracing::instrument("app::emit::to", skip(self, target, payload), fields(target)) + )] + pub fn emit_to(&self, target: I, event: &str, payload: S) -> crate::Result<()> + where + I: Into, + S: Serialize + Clone, + { + let target = target.into(); #[cfg(feature = "tracing")] - let _span = tracing::debug_span!("emit::run").entered(); - let emit_args = EmitArgs::new(event, payload)?; + tracing::Span::current().record("target", format!("{target:?}")); - let listeners = self.listeners(); + match target { + // if targeting all, emit to all using emit without filter + EventTarget::Any => self.emit(event, payload), - listeners.emit_js(self.webview.webviews_lock().values(), event, &emit_args)?; - listeners.emit(emit_args)?; + // if targeting any label, emit using emit_filter and filter labels + EventTarget::AnyLabel { + label: target_label, + } => self.emit_filter(event, payload, |t| match t { + EventTarget::Window { label } + | EventTarget::Webview { label } + | EventTarget::WebviewWindow { label } => label == &target_label, + _ => false, + }), - Ok(()) + // otherwise match same target + _ => self.emit_filter(event, payload, |t| t == &target), + } } pub fn get_window(&self, label: &str) -> Option> { @@ -634,7 +701,8 @@ mod test { test::{mock_app, MockRuntime}, webview::WebviewBuilder, window::WindowBuilder, - App, Manager, StateManager, Webview, WebviewWindow, WebviewWindowBuilder, Window, Wry, + App, Emitter, Listener, Manager, StateManager, Webview, WebviewWindow, WebviewWindowBuilder, + Window, Wry, }; use super::AppManager; @@ -651,7 +719,7 @@ mod test { #[test] fn check_get_url() { - let context = generate_context!("test/fixture/src-tauri/tauri.conf.json", crate); + let context = generate_context!("test/fixture/src-tauri/tauri.conf.json", crate, test = true); let manager: AppManager = AppManager::with_handlers( context, PluginStore::default(), @@ -759,9 +827,7 @@ mod test { assert_eq!( received.len(), expected.len(), - "received {:?} `{kind}` events but expected {:?}", - received, - expected + "received {received:?} `{kind}` events but expected {expected:?}" ); } @@ -782,7 +848,11 @@ mod test { run_emit_test("emit (webview_window)", webview_window, &rx); } - fn run_emit_test>(kind: &str, m: M, rx: &Receiver<(&str, String)>) { + fn run_emit_test + Emitter>( + kind: &str, + m: M, + rx: &Receiver<(&str, String)>, + ) { let mut received = Vec::new(); let payload = "global-payload"; m.emit(TEST_EVENT_NAME, payload).unwrap(); @@ -855,7 +925,7 @@ mod test { ); } - fn run_emit_to_test>( + fn run_emit_to_test + Emitter>( kind: &str, m: &M, window: &Window, diff --git a/core/tauri/src/manager/webview.rs b/core/tauri/src/manager/webview.rs index c7b2e100c..c19aedaed 100644 --- a/core/tauri/src/manager/webview.rs +++ b/core/tauri/src/manager/webview.rs @@ -25,14 +25,11 @@ use crate::{ pattern::PatternJavascript, sealed::ManagerBase, webview::PageLoadPayload, - AppHandle, EventLoopMessage, EventTarget, Manager, Runtime, Scopes, Webview, Window, + AppHandle, Emitter, EventLoopMessage, EventTarget, Manager, Runtime, Scopes, Webview, Window, }; use super::{ - window::{ - DragDropPayload, DragOverPayload, DRAG_EVENT, DROP_CANCELLED_EVENT, DROP_EVENT, - DROP_HOVER_EVENT, - }, + window::{DragDropPayload, DRAG_DROP_EVENT, DRAG_ENTER_EVENT, DRAG_LEAVE_EVENT, DRAG_OVER_EVENT}, AppManager, }; @@ -168,7 +165,7 @@ impl WebviewManager { } webview_attributes = webview_attributes .initialization_script( - r#" + r" Object.defineProperty(window, 'isTauri', { value: true, }); @@ -180,7 +177,7 @@ impl WebviewManager { } }) } - "#, + ", ) .initialization_script(&self.invoke_initialization_script) .initialization_script(&format!( @@ -339,6 +336,7 @@ impl WebviewManager { schema, assets.clone(), *crypto_keys.aes_gcm().raw(), + window_origin, ); pending.register_uri_scheme_protocol(schema, move |request, responder| { protocol(request, UriSchemeResponder(responder)) @@ -631,7 +629,7 @@ impl WebviewManager { .webview_created(webview_); }); - #[cfg(target_os = "ios")] + #[cfg(all(target_os = "ios", feature = "wry"))] { webview .with_webview(|w| { @@ -689,15 +687,21 @@ impl Webview { fn on_webview_event(webview: &Webview, event: &WebviewEvent) -> crate::Result<()> { match event { WebviewEvent::DragDrop(event) => match event { - DragDropEvent::Dragged { paths, position } => { - let payload = DragDropPayload { paths, position }; - webview.emit_to_webview(DRAG_EVENT, payload)? + DragDropEvent::Enter { paths, position } => { + let payload = DragDropPayload { + paths: Some(paths), + position, + }; + webview.emit_to_webview(DRAG_ENTER_EVENT, payload)? } - DragDropEvent::DragOver { position } => { - let payload = DragOverPayload { position }; - webview.emit_to_webview(DROP_HOVER_EVENT, payload)? + DragDropEvent::Over { position } => { + let payload = DragDropPayload { + position, + paths: None, + }; + webview.emit_to_webview(DRAG_OVER_EVENT, payload)? } - DragDropEvent::Dropped { paths, position } => { + DragDropEvent::Drop { paths, position } => { let scopes = webview.state::(); for path in paths { if path.is_file() { @@ -706,10 +710,13 @@ fn on_webview_event(webview: &Webview, event: &WebviewEvent) -> c let _ = scopes.allow_directory(path, false); } } - let payload = DragDropPayload { paths, position }; - webview.emit_to_webview(DROP_EVENT, payload)? + let payload = DragDropPayload { + paths: Some(paths), + position, + }; + webview.emit_to_webview(DRAG_DROP_EVENT, payload)? } - DragDropEvent::Cancelled => webview.emit_to_webview(DROP_CANCELLED_EVENT, ())?, + DragDropEvent::Leave => webview.emit_to_webview(DRAG_LEAVE_EVENT, ())?, _ => unimplemented!(), }, } diff --git a/core/tauri/src/manager/window.rs b/core/tauri/src/manager/window.rs index 17c8e3ea7..dd6cfa786 100644 --- a/core/tauri/src/manager/window.rs +++ b/core/tauri/src/manager/window.rs @@ -17,8 +17,8 @@ use tauri_runtime::{ }; use crate::{ - app::GlobalWindowEventListener, image::Image, sealed::ManagerBase, AppHandle, EventLoopMessage, - EventTarget, Manager, Runtime, Scopes, Window, WindowEvent, + app::GlobalWindowEventListener, image::Image, sealed::ManagerBase, AppHandle, Emitter, + EventLoopMessage, EventTarget, Manager, Runtime, Scopes, Window, WindowEvent, }; const WINDOW_RESIZED_EVENT: &str = "tauri://resize"; @@ -29,10 +29,10 @@ const WINDOW_FOCUS_EVENT: &str = "tauri://focus"; const WINDOW_BLUR_EVENT: &str = "tauri://blur"; const WINDOW_SCALE_FACTOR_CHANGED_EVENT: &str = "tauri://scale-change"; const WINDOW_THEME_CHANGED: &str = "tauri://theme-changed"; -pub const DRAG_EVENT: &str = "tauri://drag"; -pub const DROP_EVENT: &str = "tauri://drop"; -pub const DROP_HOVER_EVENT: &str = "tauri://drop-over"; -pub const DROP_CANCELLED_EVENT: &str = "tauri://drag-cancelled"; +pub(crate) const DRAG_ENTER_EVENT: &str = "tauri://drag-enter"; +pub(crate) const DRAG_OVER_EVENT: &str = "tauri://drag-over"; +pub(crate) const DRAG_DROP_EVENT: &str = "tauri://drag-drop"; +pub(crate) const DRAG_LEAVE_EVENT: &str = "tauri://drag-leave"; pub struct WindowManager { pub windows: Mutex>>, @@ -144,13 +144,9 @@ impl Window { } #[derive(Serialize, Clone)] -pub struct DragDropPayload<'a> { - pub paths: &'a Vec, - pub position: &'a PhysicalPosition, -} - -#[derive(Serialize, Clone)] -pub struct DragOverPayload<'a> { +pub(crate) struct DragDropPayload<'a> { + #[serde(skip_serializing_if = "Option::is_none")] + pub paths: Option<&'a Vec>, pub position: &'a PhysicalPosition, } @@ -194,28 +190,38 @@ fn on_window_event(window: &Window, event: &WindowEvent) -> crate }, )?, WindowEvent::DragDrop(event) => match event { - DragDropEvent::Dragged { paths, position } => { - let payload = DragDropPayload { paths, position }; + DragDropEvent::Enter { paths, position } => { + let payload = DragDropPayload { + paths: Some(paths), + position, + }; - if window.is_webview_window() { - window.emit_to(EventTarget::labeled(window.label()), DRAG_EVENT, payload)? - } else { - window.emit_to_window(DRAG_EVENT, payload)? - } - } - DragDropEvent::DragOver { position } => { - let payload = DragOverPayload { position }; if window.is_webview_window() { window.emit_to( EventTarget::labeled(window.label()), - DROP_HOVER_EVENT, + DRAG_ENTER_EVENT, payload, )? } else { - window.emit_to_window(DROP_HOVER_EVENT, payload)? + window.emit_to_window(DRAG_ENTER_EVENT, payload)? } } - DragDropEvent::Dropped { paths, position } => { + DragDropEvent::Over { position } => { + let payload = DragDropPayload { + position, + paths: None, + }; + if window.is_webview_window() { + window.emit_to( + EventTarget::labeled(window.label()), + DRAG_OVER_EVENT, + payload, + )? + } else { + window.emit_to_window(DRAG_OVER_EVENT, payload)? + } + } + DragDropEvent::Drop { paths, position } => { let scopes = window.state::(); for path in paths { if path.is_file() { @@ -224,23 +230,26 @@ fn on_window_event(window: &Window, event: &WindowEvent) -> crate let _ = scopes.allow_directory(path, true); } } - let payload = DragDropPayload { paths, position }; + let payload = DragDropPayload { + paths: Some(paths), + position, + }; - if window.is_webview_window() { - window.emit_to(EventTarget::labeled(window.label()), DROP_EVENT, payload)? - } else { - window.emit_to_window(DROP_EVENT, payload)? - } - } - DragDropEvent::Cancelled => { if window.is_webview_window() { window.emit_to( EventTarget::labeled(window.label()), - DROP_CANCELLED_EVENT, - (), + DRAG_DROP_EVENT, + payload, )? } else { - window.emit_to_window(DROP_CANCELLED_EVENT, ())? + window.emit_to_window(DRAG_DROP_EVENT, payload)? + } + } + DragDropEvent::Leave => { + if window.is_webview_window() { + window.emit_to(EventTarget::labeled(window.label()), DRAG_LEAVE_EVENT, ())? + } else { + window.emit_to_window(DRAG_LEAVE_EVENT, ())? } } _ => unimplemented!(), diff --git a/core/tauri/src/menu/builders/check.rs b/core/tauri/src/menu/builders/check.rs index 4120a1a1a..01bfbd59b 100644 --- a/core/tauri/src/menu/builders/check.rs +++ b/core/tauri/src/menu/builders/check.rs @@ -17,7 +17,7 @@ impl CheckMenuItemBuilder { /// Create a new menu item builder. /// /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic - /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. + /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. pub fn new>(text: S) -> Self { Self { id: None, @@ -31,7 +31,7 @@ impl CheckMenuItemBuilder { /// Create a new menu item builder with the specified id. /// /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic - /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. + /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. pub fn with_id, S: AsRef>(id: I, text: S) -> Self { Self { id: Some(id.into()), diff --git a/core/tauri/src/menu/builders/icon.rs b/core/tauri/src/menu/builders/icon.rs index fea7e00cd..275990cbe 100644 --- a/core/tauri/src/menu/builders/icon.rs +++ b/core/tauri/src/menu/builders/icon.rs @@ -22,7 +22,7 @@ impl<'a> IconMenuItemBuilder<'a> { /// Create a new menu item builder. /// /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic - /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. + /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. pub fn new>(text: S) -> Self { Self { id: None, @@ -37,7 +37,7 @@ impl<'a> IconMenuItemBuilder<'a> { /// Create a new menu item builder with the specified id. /// /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic - /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. + /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. pub fn with_id, S: AsRef>(id: I, text: S) -> Self { Self { id: Some(id.into()), diff --git a/core/tauri/src/menu/builders/normal.rs b/core/tauri/src/menu/builders/normal.rs index 7297e5a2d..f9f94fd92 100644 --- a/core/tauri/src/menu/builders/normal.rs +++ b/core/tauri/src/menu/builders/normal.rs @@ -16,7 +16,7 @@ impl MenuItemBuilder { /// Create a new menu item builder. /// /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic - /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. + /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. pub fn new>(text: S) -> Self { Self { id: None, @@ -29,7 +29,7 @@ impl MenuItemBuilder { /// Create a new menu item builder with the specified id. /// /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic - /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. + /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. pub fn with_id, S: AsRef>(id: I, text: S) -> Self { Self { id: Some(id.into()), diff --git a/core/tauri/src/menu/builders/submenu.rs b/core/tauri/src/menu/builders/submenu.rs index f86258d2c..c9ef2d5ee 100644 --- a/core/tauri/src/menu/builders/submenu.rs +++ b/core/tauri/src/menu/builders/submenu.rs @@ -48,7 +48,7 @@ impl<'m, R: Runtime, M: Manager> SubmenuBuilder<'m, R, M> { /// Create a new submenu builder. /// /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic - /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. + /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. pub fn new>(manager: &'m M, text: S) -> Self { Self { id: None, @@ -62,7 +62,7 @@ impl<'m, R: Runtime, M: Manager> SubmenuBuilder<'m, R, M> { /// Create a new submenu builder with the specified id. /// /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic - /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. + /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. pub fn with_id, S: AsRef>(manager: &'m M, id: I, text: S) -> Self { Self { id: Some(id.into()), diff --git a/core/tauri/src/menu/check.rs b/core/tauri/src/menu/check.rs index e19d2d0af..f0f20b802 100644 --- a/core/tauri/src/menu/check.rs +++ b/core/tauri/src/menu/check.rs @@ -15,7 +15,7 @@ impl CheckMenuItem { /// Create a new menu item. /// /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic - /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. + /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. pub fn new( manager: &M, text: T, @@ -49,7 +49,7 @@ impl CheckMenuItem { /// Create a new menu item with the specified id. /// /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic - /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. + /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. pub fn with_id( manager: &M, id: I, diff --git a/core/tauri/src/menu/icon.rs b/core/tauri/src/menu/icon.rs index 1ae9176b1..dd22975fc 100644 --- a/core/tauri/src/menu/icon.rs +++ b/core/tauri/src/menu/icon.rs @@ -14,7 +14,7 @@ impl IconMenuItem { /// Create a new menu item. /// /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic - /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. + /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. pub fn new( manager: &M, text: T, @@ -52,7 +52,7 @@ impl IconMenuItem { /// Create a new menu item with the specified id. /// /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic - /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. + /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. pub fn with_id( manager: &M, id: I, diff --git a/core/tauri/src/menu/normal.rs b/core/tauri/src/menu/normal.rs index be85bf73e..deaaae758 100644 --- a/core/tauri/src/menu/normal.rs +++ b/core/tauri/src/menu/normal.rs @@ -15,7 +15,7 @@ impl MenuItem { /// Create a new menu item. /// /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic - /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. + /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. pub fn new( manager: &M, text: T, @@ -48,7 +48,7 @@ impl MenuItem { /// Create a new menu item with the specified id. /// /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic - /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. + /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. pub fn with_id( manager: &M, id: I, diff --git a/core/tauri/src/menu/plugin.rs b/core/tauri/src/menu/plugin.rs index fa969bb50..c46aec5d4 100644 --- a/core/tauri/src/menu/plugin.rs +++ b/core/tauri/src/menu/plugin.rs @@ -350,7 +350,7 @@ fn new( kind: ItemKind, options: Option, channels: State<'_, MenuChannels>, - handler: Channel, + handler: Channel, ) -> crate::Result<(ResourceId, MenuId)> { let options = options.unwrap_or_default(); let mut resources_table = app.resources_table(); @@ -866,7 +866,7 @@ fn set_icon( } } -struct MenuChannels(Mutex>); +struct MenuChannels(Mutex>>); pub(crate) fn init() -> TauriPlugin { Builder::new("menu") @@ -877,7 +877,7 @@ pub(crate) fn init() -> TauriPlugin { .on_event(|app, e| { if let RunEvent::MenuEvent(e) = e { if let Some(channel) = app.state::().0.lock().unwrap().get(&e.id) { - let _ = channel.send(&e.id); + let _ = channel.send(e.id.clone()); } } }) diff --git a/core/tauri/src/path/plugin.rs b/core/tauri/src/path/plugin.rs index fded281d9..834393505 100644 --- a/core/tauri/src/path/plugin.rs +++ b/core/tauri/src/path/plugin.rs @@ -14,7 +14,7 @@ use crate::{ }; /// Normalize a path, removing things like `.` and `..`, this snippet is taken from cargo's paths util. -/// https://github.com/rust-lang/cargo/blob/46fa867ff7043e3a0545bf3def7be904e1497afd/crates/cargo-util/src/paths.rs#L73-L106 +/// fn normalize_path(path: &Path) -> PathBuf { let mut components = path.components().peekable(); let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() { @@ -44,7 +44,7 @@ fn normalize_path(path: &Path) -> PathBuf { /// Normalize a path, removing things like `.` and `..`, this snippet is taken from cargo's paths util but /// slightly modified to not resolve absolute paths. -/// https://github.com/rust-lang/cargo/blob/46fa867ff7043e3a0545bf3def7be904e1497afd/crates/cargo-util/src/paths.rs#L73-L106 +/// fn normalize_path_no_absolute(path: &Path) -> PathBuf { let mut components = path.components().peekable(); let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() { diff --git a/core/tauri/src/plugin.rs b/core/tauri/src/plugin.rs index 68875cb33..3bef88e73 100644 --- a/core/tauri/src/plugin.rs +++ b/core/tauri/src/plugin.rs @@ -15,6 +15,7 @@ use crate::{ use serde::de::DeserializeOwned; use serde_json::Value as JsonValue; use tauri_macros::default_runtime; +use thiserror::Error; use url::Url; use std::{ @@ -151,6 +152,17 @@ impl PluginApi { } } +/// Errors that can happen during [`Builder`]. +#[derive(Debug, Clone, Hash, PartialEq, Error)] +#[non_exhaustive] +pub enum BuilderError { + /// Plugin attempted to use a reserved name. + #[error("plugin uses reserved name: {0}")] + ReservedName(String), +} + +const RESERVED_PLUGIN_NAMES: &[&str] = &["core", "tauri"]; + /// Builds a [`TauriPlugin`]. /// /// This Builder offers a more concise way to construct Tauri plugins than implementing the Plugin trait directly. @@ -616,9 +628,13 @@ impl Builder { self } - /// Builds the [TauriPlugin]. - pub fn build(self) -> TauriPlugin { - TauriPlugin { + /// Builds the [`TauriPlugin`]. + pub fn try_build(self) -> Result, BuilderError> { + if let Some(&reserved) = RESERVED_PLUGIN_NAMES.iter().find(|&r| r == &self.name) { + return Err(BuilderError::ReservedName(reserved.into())); + } + + Ok(TauriPlugin { name: self.name, app: None, invoke_handler: self.invoke_handler, @@ -631,7 +647,16 @@ impl Builder { on_event: self.on_event, on_drop: self.on_drop, uri_scheme_protocols: self.uri_scheme_protocols, - } + }) + } + + /// Builds the [`TauriPlugin`]. + /// + /// # Panics + /// + /// If the builder returns an error during [`Self::try_build`], then this method will panic. + pub fn build(self) -> TauriPlugin { + self.try_build().expect("valid plugin") } } diff --git a/core/tauri/src/plugin/mobile.rs b/core/tauri/src/plugin/mobile.rs index e5ecd4951..689be85fd 100644 --- a/core/tauri/src/plugin/mobile.rs +++ b/core/tauri/src/plugin/mobile.rs @@ -30,7 +30,7 @@ type PendingPluginCallHandler = Box static PENDING_PLUGIN_CALLS_ID: AtomicI32 = AtomicI32::new(0); static PENDING_PLUGIN_CALLS: OnceLock>> = OnceLock::new(); -static CHANNELS: OnceLock>> = OnceLock::new(); +static CHANNELS: OnceLock>>> = OnceLock::new(); /// Possible errors when invoking a plugin. #[derive(Debug, thiserror::Error)] @@ -53,7 +53,7 @@ pub enum PluginInvokeError { CannotSerializePayload(serde_json::Error), } -pub(crate) fn register_channel(channel: Channel) { +pub(crate) fn register_channel(channel: Channel) { CHANNELS .get_or_init(Default::default) .lock() @@ -152,7 +152,7 @@ impl fmt::Display for ErrorResponse { impl PluginApi { /// Registers an iOS plugin. - #[cfg(target_os = "ios")] + #[cfg(all(target_os = "ios", feature = "wry"))] pub fn register_ios_plugin( &self, init_fn: unsafe fn() -> *const std::ffi::c_void, diff --git a/core/tauri/src/process.rs b/core/tauri/src/process.rs index 90660d4fe..5fb3c44e7 100644 --- a/core/tauri/src/process.rs +++ b/core/tauri/src/process.rs @@ -71,7 +71,7 @@ pub fn current_binary(_env: &Env) -> std::io::Result { /// Ok(()) /// }); /// ``` -pub fn restart(env: &Env) { +pub fn restart(env: &Env) -> ! { use std::process::{exit, Command}; if let Ok(path) = current_binary(env) { diff --git a/core/tauri/src/protocol/isolation.rs b/core/tauri/src/protocol/isolation.rs index 62206a87e..e31a4a6e2 100644 --- a/core/tauri/src/protocol/isolation.rs +++ b/core/tauri/src/protocol/isolation.rs @@ -20,6 +20,7 @@ pub fn get( schema: &str, assets: Arc, aes_gcm_key: [u8; 32], + window_origin: String, ) -> UriSchemeProtocolHandler { let frame_src = if cfg!(any(windows, target_os = "android")) { format!("http://{schema}.localhost") @@ -45,6 +46,7 @@ pub fn get( let template = tauri_utils::pattern::isolation::IsolationJavascriptRuntime { runtime_aes_gcm_key: &aes_gcm_key, + origin: window_origin.clone(), process_ipc_message_fn: PROCESS_IPC_MESSAGE_FN, }; match template.render(asset.as_ref(), &Default::default()) { diff --git a/core/tauri/src/protocol/tauri.rs b/core/tauri/src/protocol/tauri.rs index dc025805f..fd89b954c 100644 --- a/core/tauri/src/protocol/tauri.rs +++ b/core/tauri/src/protocol/tauri.rs @@ -103,13 +103,8 @@ fn get_response( .decode_utf8_lossy() .to_string(); let url = format!("{url}{decoded_path}"); - #[allow(unused_mut)] - let mut client_builder = reqwest::ClientBuilder::new(); - #[cfg(any(feature = "native-tls", feature = "rustls-tls"))] - { - client_builder = client_builder.danger_accept_invalid_certs(true); - } - let mut proxy_builder = client_builder + + let mut proxy_builder = reqwest::ClientBuilder::new() .build() .unwrap() .request(request.method().clone(), &url); diff --git a/core/tauri/src/scope/fs.rs b/core/tauri/src/scope/fs.rs index 35930a5a0..e01235129 100644 --- a/core/tauri/src/scope/fs.rs +++ b/core/tauri/src/scope/fs.rs @@ -171,7 +171,7 @@ impl Scope { next_event_id: Default::default(), match_options: glob::MatchOptions { // this is needed so `/dir/*` doesn't match files within subdirectories such as `/dir/subdir/file.txt` - // see: https://github.com/tauri-apps/tauri/security/advisories/GHSA-6mv3-wm7j-h4w5 + // see: require_literal_separator: true, require_literal_leading_dot, ..Default::default() @@ -362,7 +362,7 @@ mod tests { next_event_id: Default::default(), match_options: glob::MatchOptions { // this is needed so `/dir/*` doesn't match files within subdirectories such as `/dir/subdir/file.txt` - // see: https://github.com/tauri-apps/tauri/security/advisories/GHSA-6mv3-wm7j-h4w5 + // see: require_literal_separator: true, // dotfiles are not supposed to be exposed by default on unix #[cfg(unix)] diff --git a/core/tauri/src/test/mock_runtime.rs b/core/tauri/src/test/mock_runtime.rs index a90a5e2c7..fefbf10f9 100644 --- a/core/tauri/src/test/mock_runtime.rs +++ b/core/tauri/src/test/mock_runtime.rs @@ -332,6 +332,13 @@ impl WindowBuilder for MockWindowBuilder { self } + fn inner_size_constraints( + self, + constraints: tauri_runtime::window::WindowSizeConstraints, + ) -> Self { + self + } + fn prevent_overflow(self, margin: Option) -> Self { self } @@ -937,6 +944,17 @@ impl WindowDispatch for MockWindowDispatcher { fn set_progress_bar(&self, progress_state: ProgressBarState) -> Result<()> { Ok(()) } + + fn set_title_bar_style(&self, style: tauri_utils::TitleBarStyle) -> Result<()> { + Ok(()) + } + + fn set_size_constraints( + &self, + constraints: tauri_runtime::window::WindowSizeConstraints, + ) -> Result<()> { + Ok(()) + } } #[derive(Debug, Clone)] diff --git a/core/tauri/src/test/mod.rs b/core/tauri/src/test/mod.rs index 2fa7a141a..c05109652 100644 --- a/core/tauri/src/test/mod.rs +++ b/core/tauri/src/test/mod.rs @@ -113,6 +113,7 @@ pub fn mock_context>(assets: A) -> crate::Context { security: Default::default(), tray_icon: None, macos_private_api: false, + enable_gtk_app_id: false, }, bundle: Default::default(), build: Default::default(), @@ -134,6 +135,9 @@ pub fn mock_context>(assets: A) -> crate::Context { pattern: Pattern::Brownfield, runtime_authority: RuntimeAuthority::new(Default::default(), Resolved::default()), plugin_global_api_scripts: None, + + #[cfg(dev)] + config_parent: None, } } @@ -314,7 +318,7 @@ mod tests { }); app.run(|_app, event| { - println!("{:?}", event); + println!("{event:?}"); }); } } diff --git a/core/tauri/src/tray/mod.rs b/core/tauri/src/tray/mod.rs index 8e08fd8d0..3363192d8 100644 --- a/core/tauri/src/tray/mod.rs +++ b/core/tauri/src/tray/mod.rs @@ -73,7 +73,7 @@ impl From for MouseButton { /// ## Platform-specific: /// /// - **Linux**: Unsupported. The event is not emmited even though the icon is shown -/// and will still show a context menu on right click. +/// and will still show a context menu on right click. #[derive(Debug, Clone, Serialize)] #[serde(rename_all = "camelCase")] #[non_exhaustive] @@ -194,7 +194,7 @@ impl TrayIconBuilder { /// ## Platform-specific: /// /// - **Linux:** Sometimes the icon won't be visible unless a menu is set. - /// Setting an empty [`Menu`](crate::menu::Menu) is enough. + /// Setting an empty [`Menu`](crate::menu::Menu) is enough. pub fn new() -> Self { Self { inner: tray_icon::TrayIconBuilder::new(), @@ -208,7 +208,7 @@ impl TrayIconBuilder { /// ## Platform-specific: /// /// - **Linux:** Sometimes the icon won't be visible unless a menu is set. - /// Setting an empty [`Menu`](crate::menu::Menu) is enough. + /// Setting an empty [`Menu`](crate::menu::Menu) is enough. pub fn with_id>(id: I) -> Self { let mut builder = Self::new(); builder.inner = builder.inner.with_id(id); @@ -230,7 +230,7 @@ impl TrayIconBuilder { /// ## Platform-specific: /// /// - **Linux:** Sometimes the icon won't be visible unless a menu is set. - /// Setting an empty [`Menu`](crate::menu::Menu) is enough. + /// Setting an empty [`Menu`](crate::menu::Menu) is enough. pub fn icon(mut self, icon: Image<'_>) -> Self { let icon = icon.try_into().ok(); if let Some(icon) = icon { @@ -254,10 +254,10 @@ impl TrayIconBuilder { /// ## Platform-specific /// /// - **Linux:** The title will not be shown unless there is an icon - /// as well. The title is useful for numerical and other frequently - /// updated information. In general, it shouldn't be shown unless a - /// user requests it as it can take up a significant amount of space - /// on the user's panel. This may not be shown in all visualizations. + /// as well. The title is useful for numerical and other frequently + /// updated information. In general, it shouldn't be shown unless a + /// user requests it as it can take up a significant amount of space + /// on the user's panel. This may not be shown in all visualizations. /// - **Windows:** Unsupported. pub fn title>(mut self, title: S) -> Self { self.inner = self.inner.with_title(title); @@ -471,10 +471,10 @@ impl TrayIcon { /// ## Platform-specific: /// /// - **Linux:** The title will not be shown unless there is an icon - /// as well. The title is useful for numerical and other frequently - /// updated information. In general, it shouldn't be shown unless a - /// user requests it as it can take up a significant amount of space - /// on the user's panel. This may not be shown in all visualizations. + /// as well. The title is useful for numerical and other frequently + /// updated information. In general, it shouldn't be shown unless a + /// user requests it as it can take up a significant amount of space + /// on the user's panel. This may not be shown in all visualizations. /// - **Windows:** Unsupported pub fn set_title>(&self, title: Option) -> crate::Result<()> { let s = title.map(|s| s.as_ref().to_string()); diff --git a/core/tauri/src/tray/plugin.rs b/core/tauri/src/tray/plugin.rs index ad335e3f5..99bcb90f0 100644 --- a/core/tauri/src/tray/plugin.rs +++ b/core/tauri/src/tray/plugin.rs @@ -17,7 +17,7 @@ use crate::{ AppHandle, Manager, Runtime, Webview, }; -use super::TrayIcon; +use super::{TrayIcon, TrayIconEvent}; #[derive(Deserialize)] #[serde(rename_all = "camelCase")] @@ -36,7 +36,7 @@ struct TrayIconOptions { fn new( webview: Webview, options: TrayIconOptions, - handler: Channel, + handler: Channel, ) -> crate::Result<(ResourceId, String)> { let mut builder = if let Some(id) = options.id { TrayIconBuilder::::with_id(id) diff --git a/core/tauri/src/vibrancy/macos.rs b/core/tauri/src/vibrancy/macos.rs index d1305718c..1af3f44ff 100644 --- a/core/tauri/src/vibrancy/macos.rs +++ b/core/tauri/src/vibrancy/macos.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -#![cfg(target_os = "macos")] #![allow(deprecated)] use crate::utils::config::WindowEffectsConfig; diff --git a/core/tauri/src/webview/mod.rs b/core/tauri/src/webview/mod.rs index 12210d460..ff990e4dd 100644 --- a/core/tauri/src/webview/mod.rs +++ b/core/tauri/src/webview/mod.rs @@ -34,7 +34,8 @@ use crate::{ }, manager::{webview::WebviewLabelDef, AppManager}, sealed::{ManagerBase, RuntimeOrDispatch}, - AppHandle, Event, EventId, EventLoopMessage, Manager, ResourceTable, Runtime, Window, + AppHandle, Emitter, Event, EventId, EventLoopMessage, Listener, Manager, ResourceTable, Runtime, + Window, }; use std::{ @@ -83,7 +84,7 @@ pub enum DownloadEvent<'a> { /// ## Platform-specific: /// /// - **macOS**: The second parameter indicating the path the file was saved to is always empty, due to API - /// limitations. + /// limitations. path: Option, /// Indicates if the download succeeded or not. success: bool, @@ -110,7 +111,14 @@ impl<'a> PageLoadPayload<'a> { } /// The IPC invoke request. +/// +/// # Stability +/// +/// This struct is **NOT** part of the public stable API and is only meant to be used +/// by internal code and external testing/fuzzing tools. If not used with feature `unstable`, this +/// struct is marked `#[non_exhaustive]` and is non-constructable externally. #[derive(Debug)] +#[cfg_attr(not(feature = "unstable"), non_exhaustive)] pub struct InvokeRequest { /// The invoke command. pub cmd: String, @@ -784,7 +792,7 @@ fn main() { /// /// - **Windows**: Controls WebView2's [`IsZoomControlEnabled`](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/microsoft_web_webview2_core/corewebview2settings?view=webview2-winrt-1.0.2420.47#iszoomcontrolenabled) setting. /// - **MacOS / Linux**: Injects a polyfill that zooms in and out with `ctrl/command` + `-/=`, - /// 20% in each step, ranging from 20% to 1000%. Requires `webview:allow-set-webview-zoom` permission + /// 20% in each step, ranging from 20% to 1000%. Requires `webview:allow-set-webview-zoom` permission /// /// - **Android / iOS**: Unsupported. #[must_use] @@ -1027,8 +1035,8 @@ fn main() { main_webview.with_webview(|webview| { #[cfg(target_os = "linux")] { - // see https://docs.rs/webkit2gtk/2.0.0/webkit2gtk/struct.WebView.html - // and https://docs.rs/webkit2gtk/2.0.0/webkit2gtk/trait.WebViewExt.html + // see + // and use webkit2gtk::WebViewExt; webview.inner().set_zoom_level(4.); } @@ -1268,7 +1276,7 @@ fn main() { for v in map.values() { if let serde_json::Value::String(s) = v { let _ = crate::ipc::JavaScriptChannelId::from_str(s) - .map(|id| id.channel_on(webview.clone())); + .map(|id| id.channel_on::(webview.clone())); } } } @@ -1366,7 +1374,7 @@ fn main() { /// ## Platform-specific /// /// - **macOS:** Only supported on macOS 10.15+. - /// This is a private API on macOS, so you cannot use this if your application will be published on the App Store. + /// This is a private API on macOS, so you cannot use this if your application will be published on the App Store. /// /// # Examples /// @@ -1396,7 +1404,7 @@ tauri::Builder::default() /// ## Platform-specific /// /// - **macOS:** Only supported on macOS 10.15+. - /// This is a private API on macOS, so you cannot use this if your application will be published on the App Store. + /// This is a private API on macOS, so you cannot use this if your application will be published on the App Store. /// - **Windows:** Unsupported. /// /// # Examples @@ -1434,7 +1442,7 @@ tauri::Builder::default() /// ## Platform-specific /// /// - **macOS:** Only supported on macOS 10.15+. - /// This is a private API on macOS, so you cannot use this if your application will be published on the App Store. + /// This is a private API on macOS, so you cannot use this if your application will be published on the App Store. /// - **Windows:** Unsupported. /// /// # Examples @@ -1484,8 +1492,7 @@ tauri::Builder::default() } } -/// Event system APIs. -impl Webview { +impl Listener for Webview { /// Listen to an event on this webview. /// /// # Examples @@ -1493,13 +1500,13 @@ impl Webview { feature = "unstable", doc = r####" ``` -use tauri::Manager; +use tauri::{Manager, Listener}; tauri::Builder::default() .setup(|app| { let webview = app.get_webview("main").unwrap(); webview.listen("component-loaded", move |event| { - println!("window just loaded a component"); + println!("webview just loaded a component"); }); Ok(()) @@ -1507,7 +1514,7 @@ tauri::Builder::default() ``` "#### )] - pub fn listen(&self, event: impl Into, handler: F) -> EventId + fn listen(&self, event: impl Into, handler: F) -> EventId where F: Fn(Event) + Send + 'static, { @@ -1520,6 +1527,22 @@ tauri::Builder::default() ) } + /// Listen to an event on this webview only once. + /// + /// See [`Self::listen`] for more information. + fn once(&self, event: impl Into, handler: F) -> EventId + where + F: FnOnce(Event) + Send + 'static, + { + self.manager.once( + event.into(), + EventTarget::Webview { + label: self.label().to_string(), + }, + handler, + ) + } + /// Unlisten to an event on this webview. /// /// # Examples @@ -1527,7 +1550,7 @@ tauri::Builder::default() feature = "unstable", doc = r####" ``` -use tauri::Manager; +use tauri::{Manager, Listener}; tauri::Builder::default() .setup(|app| { @@ -1549,24 +1572,97 @@ tauri::Builder::default() ``` "#### )] - pub fn unlisten(&self, id: EventId) { + fn unlisten(&self, id: EventId) { self.manager.unlisten(id) } +} - /// Listen to an event on this webview only once. +impl Emitter for Webview { + /// Emits an event to all [targets](EventTarget). /// - /// See [`Self::listen`] for more information. - pub fn once(&self, event: impl Into, handler: F) -> EventId + /// # Examples + #[cfg_attr( + feature = "unstable", + doc = r####" +``` +use tauri::Emitter; + +#[tauri::command] +fn synchronize(webview: tauri::Webview) { + // emits the synchronized event to all webviews + webview.emit("synchronized", ()); +} + ``` + "#### + )] + fn emit(&self, event: &str, payload: S) -> crate::Result<()> { + self.manager.emit(event, payload) + } + + /// Emits an event to all [targets](EventTarget) matching the given target. + /// + /// # Examples + #[cfg_attr( + feature = "unstable", + doc = r####" +``` +use tauri::{Emitter, EventTarget}; + +#[tauri::command] +fn download(webview: tauri::Webview) { + for i in 1..100 { + std::thread::sleep(std::time::Duration::from_millis(150)); + // emit a download progress event to all listeners + webview.emit_to(EventTarget::any(), "download-progress", i); + // emit an event to listeners that used App::listen or AppHandle::listen + webview.emit_to(EventTarget::app(), "download-progress", i); + // emit an event to any webview/window/webviewWindow matching the given label + webview.emit_to("updater", "download-progress", i); // similar to using EventTarget::labeled + webview.emit_to(EventTarget::labeled("updater"), "download-progress", i); + // emit an event to listeners that used WebviewWindow::listen + webview.emit_to(EventTarget::webview_window("updater"), "download-progress", i); + } +} +``` +"#### + )] + fn emit_to(&self, target: I, event: &str, payload: S) -> crate::Result<()> where - F: FnOnce(Event) + Send + 'static, + I: Into, + S: Serialize + Clone, { - self.manager.once( - event.into(), - EventTarget::Webview { - label: self.label().to_string(), - }, - handler, - ) + self.manager.emit_to(target, event, payload) + } + + /// Emits an event to all [targets](EventTarget) based on the given filter. + /// + /// # Examples + #[cfg_attr( + feature = "unstable", + doc = r####" +``` +use tauri::{Emitter, EventTarget}; + +#[tauri::command] +fn download(webview: tauri::Webview) { + for i in 1..100 { + std::thread::sleep(std::time::Duration::from_millis(150)); + // emit a download progress event to the updater window + webview.emit_filter("download-progress", i, |t| match t { + EventTarget::WebviewWindow { label } => label == "main", + _ => false, + }); + } +} + ``` + "#### + )] + fn emit_filter(&self, event: &str, payload: S, filter: F) -> crate::Result<()> + where + S: Serialize + Clone, + F: Fn(&EventTarget) -> bool, + { + self.manager.emit_filter(event, payload, filter) } } diff --git a/core/tauri/src/webview/webview_window.rs b/core/tauri/src/webview/webview_window.rs index 8151954b4..2189992f3 100644 --- a/core/tauri/src/webview/webview_window.rs +++ b/core/tauri/src/webview/webview_window.rs @@ -14,7 +14,7 @@ use crate::{ event::EventTarget, runtime::dpi::{PhysicalPosition, PhysicalSize}, window::Monitor, - ResourceTable, + Emitter, Listener, ResourceTable, }; #[cfg(desktop)] use crate::{ @@ -26,6 +26,8 @@ use crate::{ UserAttentionType, }, }; +use serde::Serialize; +use tauri_runtime::window::WindowSizeConstraints; use tauri_utils::config::{WebviewUrl, WindowConfig}; use url::Url; @@ -189,40 +191,34 @@ impl<'a, R: Runtime, M: Manager> WebviewWindowBuilder<'a, R, M> { /// but it might be implemented in the future. **Always** check the request URL. /// /// # Examples - #[cfg_attr( - feature = "unstable", - doc = r####" -```rust,no_run -use tauri::{ - utils::config::{Csp, CspDirectiveSources, WebviewUrl}, - window::WindowBuilder, - webview::WebviewWindowBuilder, -}; -use http::header::HeaderValue; -use std::collections::HashMap; -tauri::Builder::default() - .setup(|app| { - let webview_window = WebviewWindowBuilder::new(app, "core", WebviewUrl::App("index.html".into())) - .on_web_resource_request(|request, response| { - if request.uri().scheme_str() == Some("tauri") { - // if we have a CSP header, Tauri is loading an HTML file - // for this example, let's dynamically change the CSP - if let Some(csp) = response.headers_mut().get_mut("Content-Security-Policy") { - // use the tauri helper to parse the CSP policy to a map - let mut csp_map: HashMap = Csp::Policy(csp.to_str().unwrap().to_string()).into(); - csp_map.entry("script-src".to_string()).or_insert_with(Default::default).push("'unsafe-inline'"); - // use the tauri helper to get a CSP string from the map - let csp_string = Csp::from(csp_map).to_string(); - *csp = HeaderValue::from_str(&csp_string).unwrap(); - } - } - }) - .build()?; - Ok(()) - }); -``` - "#### - )] + /// ```rust,no_run + /// use tauri::{ + /// utils::config::{Csp, CspDirectiveSources, WebviewUrl}, + /// webview::WebviewWindowBuilder, + /// }; + /// use http::header::HeaderValue; + /// use std::collections::HashMap; + /// tauri::Builder::default() + /// .setup(|app| { + /// let webview_window = WebviewWindowBuilder::new(app, "core", WebviewUrl::App("index.html".into())) + /// .on_web_resource_request(|request, response| { + /// if request.uri().scheme_str() == Some("tauri") { + /// // if we have a CSP header, Tauri is loading an HTML file + /// // for this example, let's dynamically change the CSP + /// if let Some(csp) = response.headers_mut().get_mut("Content-Security-Policy") { + /// // use the tauri helper to parse the CSP policy to a map + /// let mut csp_map: HashMap = Csp::Policy(csp.to_str().unwrap().to_string()).into(); + /// csp_map.entry("script-src".to_string()).or_insert_with(Default::default).push("'unsafe-inline'"); + /// // use the tauri helper to get a CSP string from the map + /// let csp_string = Csp::from(csp_map).to_string(); + /// *csp = HeaderValue::from_str(&csp_string).unwrap(); + /// } + /// } + /// }) + /// .build()?; + /// Ok(()) + /// }); + /// ``` pub fn on_web_resource_request< F: Fn(http::Request>, &mut http::Response>) + Send + Sync + 'static, >( @@ -236,30 +232,24 @@ tauri::Builder::default() /// Defines a closure to be executed when the webview navigates to a URL. Returning `false` cancels the navigation. /// /// # Examples - #[cfg_attr( - feature = "unstable", - doc = r####" -```rust,no_run -use tauri::{ - utils::config::{Csp, CspDirectiveSources, WebviewUrl}, - window::WindowBuilder, - webview::WebviewWindowBuilder, -}; -use http::header::HeaderValue; -use std::collections::HashMap; -tauri::Builder::default() - .setup(|app| { - let webview_window = WebviewWindowBuilder::new(app, "core", WebviewUrl::App("index.html".into())) - .on_navigation(|url| { - // allow the production URL or localhost on dev - url.scheme() == "tauri" || (cfg!(dev) && url.host_str() == Some("localhost")) - }) - .build()?; - Ok(()) - }); -``` - "#### - )] + /// ```rust,no_run + /// use tauri::{ + /// utils::config::{Csp, CspDirectiveSources, WebviewUrl}, + /// webview::WebviewWindowBuilder, + /// }; + /// use http::header::HeaderValue; + /// use std::collections::HashMap; + /// tauri::Builder::default() + /// .setup(|app| { + /// let webview_window = WebviewWindowBuilder::new(app, "core", WebviewUrl::App("index.html".into())) + /// .on_navigation(|url| { + /// // allow the production URL or localhost on dev + /// url.scheme() == "tauri" || (cfg!(dev) && url.host_str() == Some("localhost")) + /// }) + /// .build()?; + /// Ok(()) + /// }); + /// ``` pub fn on_navigation bool + Send + 'static>(mut self, f: F) -> Self { self.webview_builder = self.webview_builder.on_navigation(f); self @@ -318,36 +308,30 @@ tauri::Builder::default() /// or [`tauri_runtime::webview::PageLoadEvent::Finished`] when the page finishes loading. /// /// # Examples - #[cfg_attr( - feature = "unstable", - doc = r####" -```rust,no_run -use tauri::{ - utils::config::{Csp, CspDirectiveSources, WebviewUrl}, - window::WindowBuilder, - webview::{PageLoadEvent, WebviewWindowBuilder}, -}; -use http::header::HeaderValue; -use std::collections::HashMap; -tauri::Builder::default() - .setup(|app| { - let webview_window = WebviewWindowBuilder::new(app, "core", WebviewUrl::App("index.html".into())) - .on_page_load(|window, payload| { - match payload.event() { - PageLoadEvent::Started => { - println!("{} finished loading", payload.url()); - } - PageLoadEvent::Finished => { - println!("{} finished loading", payload.url()); - } - } - }) - .build()?; - Ok(()) - }); -``` - "#### - )] + /// ```rust,no_run + /// use tauri::{ + /// utils::config::{Csp, CspDirectiveSources, WebviewUrl}, + /// webview::{PageLoadEvent, WebviewWindowBuilder}, + /// }; + /// use http::header::HeaderValue; + /// use std::collections::HashMap; + /// tauri::Builder::default() + /// .setup(|app| { + /// let webview_window = WebviewWindowBuilder::new(app, "core", WebviewUrl::App("index.html".into())) + /// .on_page_load(|window, payload| { + /// match payload.event() { + /// PageLoadEvent::Started => { + /// println!("{} finished loading", payload.url()); + /// } + /// PageLoadEvent::Finished => { + /// println!("{} finished loading", payload.url()); + /// } + /// } + /// }) + /// .build()?; + /// Ok(()) + /// }); + /// ``` pub fn on_page_load, PageLoadPayload<'_>) + Send + Sync + 'static>( mut self, f: F, @@ -423,10 +407,10 @@ impl<'a, R: Runtime, M: Manager> WebviewWindowBuilder<'a, R, M> { self } - /// Prevent the window from overflowing the working area (e.g. monitor size - taskbar size) on creation + /// Window inner size constraints. #[must_use] - pub fn prevent_overflow(mut self, margin: Option) -> Self { - self.window_builder = self.window_builder.prevent_overflow(margin); + pub fn inner_size_constraints(mut self, constraints: WindowSizeConstraints) -> Self { + self.window_builder = self.window_builder.inner_size_constraints(constraints); self } @@ -606,8 +590,8 @@ impl<'a, R: Runtime, M: Manager> WebviewWindowBuilder<'a, R, M> { /// /// - **Windows:** /// - `false` has no effect on decorated window, shadows are always ON. - /// - `true` will make ndecorated window have a 1px white border, - /// and on Windows 11, it will have a rounded corners. + /// - `true` will make undecorated window have a 1px white border, + /// and on Windows 11, it will have a rounded corners. /// - **Linux:** Unsupported. #[must_use] pub fn shadow(mut self, enable: bool) -> Self { @@ -783,32 +767,27 @@ impl<'a, R: Runtime, M: Manager> WebviewWindowBuilder<'a, R, M> { /// /// # Examples /// - #[cfg_attr( - feature = "unstable", - doc = r####" -```rust -use tauri::{WindowBuilder, Runtime}; - -const INIT_SCRIPT: &str = r#" - if (window.location.origin === 'https://tauri.app') { - console.log("hello world from js init script"); - - window.__MY_CUSTOM_PROPERTY__ = { foo: 'bar' }; - } -"#; - -fn main() { - tauri::Builder::default() - .setup(|app| { - let webview = tauri::WebviewWindowBuilder::new(app, "label", tauri::WebviewUrl::App("index.html".into())) - .initialization_script(INIT_SCRIPT) - .build()?; - Ok(()) - }); -} -``` - "#### - )] + /// ```rust + /// use tauri::{WebviewWindowBuilder, Runtime}; + /// + /// const INIT_SCRIPT: &str = r#" + /// if (window.location.origin === 'https://tauri.app') { + /// console.log("hello world from js init script"); + /// + /// window.__MY_CUSTOM_PROPERTY__ = { foo: 'bar' }; + /// } + /// "#; + /// + /// fn main() { + /// tauri::Builder::default() + /// .setup(|app| { + /// let webview = tauri::WebviewWindowBuilder::new(app, "label", tauri::WebviewUrl::App("index.html".into())) + /// .initialization_script(INIT_SCRIPT) + /// .build()?; + /// Ok(()) + /// }); + /// } + /// ``` #[must_use] pub fn initialization_script(mut self, script: &str) -> Self { self.webview_builder = self.webview_builder.initialization_script(script); @@ -897,7 +876,7 @@ fn main() { /// /// - **Windows**: Controls WebView2's [`IsZoomControlEnabled`](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/microsoft_web_webview2_core/corewebview2settings?view=webview2-winrt-1.0.2420.47#iszoomcontrolenabled) setting. /// - **MacOS / Linux**: Injects a polyfill that zooms in and out with `ctrl/command` + `-/=`, - /// 20% in each step, ranging from 20% to 1000%. Requires `webview:allow-set-webview-zoom` permission + /// 20% in each step, ranging from 20% to 1000%. Requires `webview:allow-set-webview-zoom` permission /// /// - **Android / iOS**: Unsupported. #[must_use] @@ -961,9 +940,7 @@ impl<'de, R: Runtime> CommandArg<'de, R> for WebviewWindow { if webview.window().is_webview_window() { Ok(Self { webview }) } else { - Err(InvokeError::from_anyhow(anyhow::anyhow!( - "current webview is not a WebviewWindow" - ))) + Err(InvokeError::from("current webview is not a WebviewWindow")) } } } @@ -1010,36 +987,33 @@ impl WebviewWindow { /// /// # Examples /// - #[cfg_attr( - feature = "unstable", - doc = r####" -``` -use tauri::menu::{Menu, Submenu, MenuItem}; -tauri::Builder::default() - .setup(|app| { - let handle = app.handle(); - let save_menu_item = MenuItem::new(handle, "Save", true, None::<&str>)?; - let menu = Menu::with_items(handle, &[ - &Submenu::with_items(handle, "File", true, &[ - &save_menu_item, - ])?, - ])?; - let webview_window = tauri::window::WindowBuilder::new(app, "editor") - .menu(menu) - .build() - .unwrap(); - - webview_window.on_menu_event(move |window, event| { - if event.id == save_menu_item.id() { - // save menu item - } - }); - - Ok(()) - }); -``` - "#### - )] + /// ``` + /// use tauri::menu::{Menu, Submenu, MenuItem}; + /// use tauri::{WebviewWindowBuilder, WebviewUrl}; + /// + /// tauri::Builder::default() + /// .setup(|app| { + /// let handle = app.handle(); + /// let save_menu_item = MenuItem::new(handle, "Save", true, None::<&str>)?; + /// let menu = Menu::with_items(handle, &[ + /// &Submenu::with_items(handle, "File", true, &[ + /// &save_menu_item, + /// ])?, + /// ])?; + /// let webview_window = WebviewWindowBuilder::new(app, "editor", WebviewUrl::default()) + /// .menu(menu) + /// .build() + /// .unwrap(); + /// + /// webview_window.on_menu_event(move |window, event| { + /// if event.id == save_menu_item.id() { + /// // save menu item + /// } + /// }); + /// + /// Ok(()) + /// }); + /// ``` pub fn on_menu_event, crate::menu::MenuEvent) + Send + Sync + 'static>( &self, f: F, @@ -1057,7 +1031,7 @@ tauri::Builder::default() /// ## Platform-specific: /// /// - **macOS:** Unsupported. The menu on macOS is app-wide and not specific to one - /// window, if you need to set it, use [`AppHandle::set_menu`] instead. + /// window, if you need to set it, use [`AppHandle::set_menu`] instead. #[cfg_attr(target_os = "macos", allow(unused_variables))] pub fn set_menu(&self, menu: Menu) -> crate::Result>> { self.webview.window().set_menu(menu) @@ -1068,7 +1042,7 @@ tauri::Builder::default() /// ## Platform-specific: /// /// - **macOS:** Unsupported. The menu on macOS is app-wide and not specific to one - /// window, if you need to remove it, use [`AppHandle::remove_menu`] instead. + /// window, if you need to remove it, use [`AppHandle::remove_menu`] instead. pub fn remove_menu(&self) -> crate::Result>> { self.webview.window().remove_menu() } @@ -1420,8 +1394,8 @@ impl WebviewWindow { /// /// - **Windows:** /// - `false` has no effect on decorated window, shadow are always ON. - /// - `true` will make ndecorated window have a 1px white border, - /// and on Windows 11, it will have a rounded corners. + /// - `true` will make undecorated window have a 1px white border, + /// and on Windows 11, it will have a rounded corners. /// - **Linux:** Unsupported. pub fn set_shadow(&self, enable: bool) -> crate::Result<()> { self.webview.window().set_shadow(enable) @@ -1503,6 +1477,11 @@ impl WebviewWindow { self.webview.window().set_max_size(size.map(|s| s.into())) } + /// Sets this window's minimum inner width. + pub fn set_size_constraints(&self, constriants: WindowSizeConstraints) -> crate::Result<()> { + self.webview.window().set_size_constraints(constriants) + } + /// Sets this window's position. pub fn set_position>(&self, position: Pos) -> crate::Result<()> { self.webview.window().set_position(position) @@ -1591,6 +1570,11 @@ impl WebviewWindow { ) -> crate::Result<()> { self.webview.window().set_progress_bar(progress_state) } + + /// Sets the title bar style. **macOS only**. + pub fn set_title_bar_style(&self, style: tauri_utils::TitleBarStyle) -> crate::Result<()> { + self.webview.window().set_title_bar_style(style) + } } /// Desktop webview setters and actions. @@ -1625,15 +1609,15 @@ impl WebviewWindow { /// main_webview.with_webview(|webview| { /// #[cfg(target_os = "linux")] /// { - /// // see https://docs.rs/webkit2gtk/2.0.0/webkit2gtk/struct.WebView.html - /// // and https://docs.rs/webkit2gtk/2.0.0/webkit2gtk/trait.WebViewExt.html + /// // see + /// // and /// use webkit2gtk::WebViewExt; /// webview.inner().set_zoom_level(4.); /// } /// /// #[cfg(windows)] /// unsafe { - /// // see https://docs.rs/webview2-com/0.19.1/webview2_com/Microsoft/Web/WebView2/Win32/struct.ICoreWebView2Controller.html + /// // see /// webview.controller().SetZoomFactor(4.).unwrap(); /// } /// @@ -1696,24 +1680,19 @@ impl WebviewWindow { /// ## Platform-specific /// /// - **macOS:** Only supported on macOS 10.15+. - /// This is a private API on macOS, so you cannot use this if your application will be published on the App Store. + /// This is a private API on macOS, so you cannot use this if your application will be published on the App Store. /// /// # Examples /// - #[cfg_attr( - feature = "unstable", - doc = r####" -```rust,no_run -use tauri::Manager; -tauri::Builder::default() - .setup(|app| { - #[cfg(debug_assertions)] - app.get_webview("main").unwrap().open_devtools(); - Ok(()) - }); -``` - "#### - )] + /// ```rust,no_run + /// use tauri::Manager; + /// tauri::Builder::default() + /// .setup(|app| { + /// #[cfg(debug_assertions)] + /// app.get_webview_window("main").unwrap().open_devtools(); + /// Ok(()) + /// }); + /// ``` #[cfg(any(debug_assertions, feature = "devtools"))] #[cfg_attr(docsrs, doc(cfg(any(debug_assertions, feature = "devtools"))))] pub fn open_devtools(&self) { @@ -1726,32 +1705,27 @@ tauri::Builder::default() /// ## Platform-specific /// /// - **macOS:** Only supported on macOS 10.15+. - /// This is a private API on macOS, so you cannot use this if your application will be published on the App Store. + /// This is a private API on macOS, so you cannot use this if your application will be published on the App Store. /// - **Windows:** Unsupported. /// /// # Examples /// - #[cfg_attr( - feature = "unstable", - doc = r####" -```rust,no_run -use tauri::Manager; -tauri::Builder::default() - .setup(|app| { - #[cfg(debug_assertions)] - { - let webview = app.get_webview("main").unwrap(); - webview.open_devtools(); - std::thread::spawn(move || { - std::thread::sleep(std::time::Duration::from_secs(10)); - webview.close_devtools(); - }); - } - Ok(()) - }); -``` - "#### - )] + /// ```rust,no_run + /// use tauri::Manager; + /// tauri::Builder::default() + /// .setup(|app| { + /// #[cfg(debug_assertions)] + /// { + /// let webview = app.get_webview_window("main").unwrap(); + /// webview.open_devtools(); + /// std::thread::spawn(move || { + /// std::thread::sleep(std::time::Duration::from_secs(10)); + /// webview.close_devtools(); + /// }); + /// } + /// Ok(()) + /// }); + /// ``` #[cfg(any(debug_assertions, feature = "devtools"))] #[cfg_attr(docsrs, doc(cfg(any(debug_assertions, feature = "devtools"))))] pub fn close_devtools(&self) { @@ -1764,30 +1738,25 @@ tauri::Builder::default() /// ## Platform-specific /// /// - **macOS:** Only supported on macOS 10.15+. - /// This is a private API on macOS, so you cannot use this if your application will be published on the App Store. + /// This is a private API on macOS, so you cannot use this if your application will be published on the App Store. /// - **Windows:** Unsupported. /// /// # Examples /// - #[cfg_attr( - feature = "unstable", - doc = r####" -```rust,no_run -use tauri::Manager; -tauri::Builder::default() - .setup(|app| { - #[cfg(debug_assertions)] - { - let webview = app.get_webview("main").unwrap(); - if !webview.is_devtools_open() { - webview.open_devtools(); - } - } - Ok(()) - }); -``` - "#### - )] + /// ```rust,no_run + /// use tauri::Manager; + /// tauri::Builder::default() + /// .setup(|app| { + /// #[cfg(debug_assertions)] + /// { + /// let webview = app.get_webview_window("main").unwrap(); + /// if !webview.is_devtools_open() { + /// webview.open_devtools(); + /// } + /// } + /// Ok(()) + /// }); + /// ``` #[cfg(any(debug_assertions, feature = "devtools"))] #[cfg_attr(docsrs, doc(cfg(any(debug_assertions, feature = "devtools"))))] pub fn is_devtools_open(&self) -> bool { @@ -1806,31 +1775,25 @@ tauri::Builder::default() } } -/// Event system APIs. -impl WebviewWindow { +impl Listener for WebviewWindow { /// Listen to an event on this webview window. /// /// # Examples /// - #[cfg_attr( - feature = "unstable", - doc = r####" -``` -use tauri::Manager; - -tauri::Builder::default() - .setup(|app| { - let webview = app.get_webview("main").unwrap(); - webview.listen("component-loaded", move |event| { - println!("window just loaded a component"); - }); - - Ok(()) - }); -``` - "#### - )] - pub fn listen(&self, event: impl Into, handler: F) -> EventId + /// ``` + /// use tauri::{Manager, Listener}; + /// + /// tauri::Builder::default() + /// .setup(|app| { + /// let webview_window = app.get_webview_window("main").unwrap(); + /// webview_window.listen("component-loaded", move |event| { + /// println!("window just loaded a component"); + /// }); + /// + /// Ok(()) + /// }); + /// ``` + fn listen(&self, event: impl Into, handler: F) -> EventId where F: Fn(Event) + Send + 'static, { @@ -1843,43 +1806,10 @@ tauri::Builder::default() ) } - /// Unlisten to an event on this webview window. - /// - /// # Examples - #[cfg_attr( - feature = "unstable", - doc = r####" -``` -use tauri::Manager; - -tauri::Builder::default() - .setup(|app| { - let webview = app.get_webview("main").unwrap(); - let webview_ = webview.clone(); - let handler = webview.listen("component-loaded", move |event| { - println!("webview just loaded a component"); - - // we no longer need to listen to the event - // we also could have used `webview.once` instead - webview_.unlisten(event.id()); - }); - - // stop listening to the event when you do not need it anymore - webview.unlisten(handler); - - Ok(()) - }); -``` - "#### - )] - pub fn unlisten(&self, id: EventId) { - self.manager().unlisten(id) - } - /// Listen to an event on this window webview only once. /// /// See [`Self::listen`] for more information. - pub fn once(&self, event: impl Into, handler: F) -> EventId + fn once(&self, event: impl Into, handler: F) -> EventId where F: FnOnce(Event) + Send + 'static, { @@ -1891,6 +1821,108 @@ tauri::Builder::default() handler, ) } + + /// Unlisten to an event on this webview window. + /// + /// # Examples + /// ``` + /// use tauri::{Manager, Listener}; + /// + /// tauri::Builder::default() + /// .setup(|app| { + /// let webview_window = app.get_webview_window("main").unwrap(); + /// let webview_window_ = webview_window.clone(); + /// let handler = webview_window.listen("component-loaded", move |event| { + /// println!("webview_window just loaded a component"); + /// + /// // we no longer need to listen to the event + /// // we also could have used `webview_window.once` instead + /// webview_window_.unlisten(event.id()); + /// }); + /// + /// // stop listening to the event when you do not need it anymore + /// webview_window.unlisten(handler); + /// + /// Ok(()) + /// }); + /// ``` + fn unlisten(&self, id: EventId) { + self.manager().unlisten(id) + } +} + +impl Emitter for WebviewWindow { + /// Emits an event to all [targets](EventTarget). + /// + /// # Examples + /// ``` + /// use tauri::Emitter; + /// + /// #[tauri::command] + /// fn synchronize(window: tauri::WebviewWindow) { + /// // emits the synchronized event to all webviews + /// window.emit("synchronized", ()); + /// } + /// ``` + fn emit(&self, event: &str, payload: S) -> crate::Result<()> { + self.manager().emit(event, payload) + } + + /// Emits an event to all [targets](EventTarget) matching the given target. + /// + /// # Examples + /// ``` + /// use tauri::{Emitter, EventTarget}; + /// + /// #[tauri::command] + /// fn download(window: tauri::WebviewWindow) { + /// for i in 1..100 { + /// std::thread::sleep(std::time::Duration::from_millis(150)); + /// // emit a download progress event to all listeners + /// window.emit_to(EventTarget::any(), "download-progress", i); + /// // emit an event to listeners that used App::listen or AppHandle::listen + /// window.emit_to(EventTarget::app(), "download-progress", i); + /// // emit an event to any webview/window/webviewWindow matching the given label + /// window.emit_to("updater", "download-progress", i); // similar to using EventTarget::labeled + /// window.emit_to(EventTarget::labeled("updater"), "download-progress", i); + /// // emit an event to listeners that used WebviewWindow::listen + /// window.emit_to(EventTarget::webview_window("updater"), "download-progress", i); + /// } + /// } + /// ``` + fn emit_to(&self, target: I, event: &str, payload: S) -> crate::Result<()> + where + I: Into, + S: Serialize + Clone, + { + self.manager().emit_to(target, event, payload) + } + + /// Emits an event to all [targets](EventTarget) based on the given filter. + /// + /// # Examples + /// ``` + /// use tauri::{Emitter, EventTarget}; + /// + /// #[tauri::command] + /// fn download(window: tauri::WebviewWindow) { + /// for i in 1..100 { + /// std::thread::sleep(std::time::Duration::from_millis(150)); + /// // emit a download progress event to the updater window + /// window.emit_filter("download-progress", i, |t| match t { + /// EventTarget::WebviewWindow { label } => label == "main", + /// _ => false, + /// }); + /// } + /// } + /// ``` + fn emit_filter(&self, event: &str, payload: S, filter: F) -> crate::Result<()> + where + S: Serialize + Clone, + F: Fn(&EventTarget) -> bool, + { + self.manager().emit_filter(event, payload, filter) + } } impl Manager for WebviewWindow { diff --git a/core/tauri/src/window/mod.rs b/core/tauri/src/window/mod.rs index 3ddc3ae28..47f8ad5fc 100644 --- a/core/tauri/src/window/mod.rs +++ b/core/tauri/src/window/mod.rs @@ -9,6 +9,7 @@ pub(crate) mod plugin; use tauri_runtime::{ dpi::{PhysicalPosition, PhysicalSize}, webview::PendingWebview, + window::WindowSizeConstraints, }; pub use tauri_utils::{config::Color, WindowEffect as Effect, WindowEffectState as EffectState}; @@ -28,7 +29,8 @@ use crate::{ sealed::{ManagerBase, RuntimeOrDispatch}, utils::config::{WindowConfig, WindowEffectsConfig}, webview::WebviewBuilder, - EventLoopMessage, Manager, ResourceTable, Runtime, Theme, Webview, WindowEvent, + Emitter, EventLoopMessage, Listener, Manager, ResourceTable, Runtime, Theme, Webview, + WindowEvent, }; #[cfg(desktop)] use crate::{ @@ -491,6 +493,13 @@ impl<'a, R: Runtime, M: Manager> WindowBuilder<'a, R, M> { self } + /// Window inner size constraints. + #[must_use] + pub fn inner_size_constraints(mut self, constraints: WindowSizeConstraints) -> Self { + self.window_builder = self.window_builder.inner_size_constraints(constraints); + self + } + /// Prevent the window from overflowing the working area (e.g. monitor size - taskbar size) on creation #[must_use] pub fn prevent_overflow(mut self, margin: Option) -> Self { @@ -678,7 +687,7 @@ impl<'a, R: Runtime, M: Manager> WindowBuilder<'a, R, M> { /// - **Windows:** /// - `false` has no effect on decorated window, shadows are always ON. /// - `true` will make undecorated window have a 1px white border, - /// and on Windows 11, it will have a rounded corners. + /// and on Windows 11, it will have a rounded corners. /// - **Linux:** Unsupported. #[must_use] pub fn shadow(mut self, enable: bool) -> Self { @@ -1155,7 +1164,7 @@ tauri::Builder::default() /// ## Platform-specific: /// /// - **macOS:** Unsupported. The menu on macOS is app-wide and not specific to one - /// window, if you need to set it, use [`AppHandle::set_menu`] instead. + /// window, if you need to set it, use [`AppHandle::set_menu`] instead. #[cfg_attr(target_os = "macos", allow(unused_variables))] pub fn set_menu(&self, menu: Menu) -> crate::Result>> { let prev_menu = self.remove_menu()?; @@ -1201,7 +1210,7 @@ tauri::Builder::default() /// ## Platform-specific: /// /// - **macOS:** Unsupported. The menu on macOS is app-wide and not specific to one - /// window, if you need to remove it, use [`AppHandle::remove_menu`] instead. + /// window, if you need to remove it, use [`AppHandle::remove_menu`] instead. pub fn remove_menu(&self) -> crate::Result>> { let prev_menu = self.menu_lock().take().map(|m| m.menu); @@ -1741,7 +1750,7 @@ impl Window { /// - **Windows:** /// - `false` has no effect on decorated window, shadow are always ON. /// - `true` will make undecorated window have a 1px white border, - /// and on Windows 11, it will have a rounded corners. + /// and on Windows 11, it will have a rounded corners. /// - **Linux:** Unsupported. pub fn set_shadow(&self, enable: bool) -> crate::Result<()> { self @@ -1861,6 +1870,15 @@ tauri::Builder::default() .map_err(Into::into) } + /// Sets this window's minimum inner width. + pub fn set_size_constraints(&self, constriants: WindowSizeConstraints) -> crate::Result<()> { + self + .window + .dispatcher + .set_size_constraints(constriants) + .map_err(Into::into) + } + /// Sets this window's position. pub fn set_position>(&self, position: Pos) -> crate::Result<()> { self @@ -2002,6 +2020,14 @@ tauri::Builder::default() }) .map_err(Into::into) } + /// Sets the title bar style. **macOS only**. + pub fn set_title_bar_style(&self, style: tauri_utils::TitleBarStyle) -> crate::Result<()> { + self + .window + .dispatcher + .set_title_bar_style(style) + .map_err(Into::into) + } } /// Progress bar state. @@ -2018,8 +2044,7 @@ pub struct ProgressBarState { pub progress: Option, } -/// Event system APIs. -impl Window { +impl Listener for Window { /// Listen to an event on this window. /// /// # Examples @@ -2027,7 +2052,7 @@ impl Window { feature = "unstable", doc = r####" ``` -use tauri::Manager; +use tauri::{Manager, Listener}; tauri::Builder::default() .setup(|app| { @@ -2041,7 +2066,7 @@ tauri::Builder::default() ``` "#### )] - pub fn listen(&self, event: impl Into, handler: F) -> EventId + fn listen(&self, event: impl Into, handler: F) -> EventId where F: Fn(Event) + Send + 'static, { @@ -2054,6 +2079,22 @@ tauri::Builder::default() ) } + /// Listen to an event on this window only once. + /// + /// See [`Self::listen`] for more information. + fn once(&self, event: impl Into, handler: F) -> EventId + where + F: FnOnce(Event) + Send + 'static, + { + self.manager.once( + event.into(), + EventTarget::Window { + label: self.label().to_string(), + }, + handler, + ) + } + /// Unlisten to an event on this window. /// /// # Examples @@ -2061,7 +2102,7 @@ tauri::Builder::default() feature = "unstable", doc = r####" ``` -use tauri::Manager; +use tauri::{Manager, Listener}; tauri::Builder::default() .setup(|app| { @@ -2083,24 +2124,97 @@ tauri::Builder::default() ``` "#### )] - pub fn unlisten(&self, id: EventId) { + fn unlisten(&self, id: EventId) { self.manager.unlisten(id) } +} - /// Listen to an event on this window only once. +impl Emitter for Window { + /// Emits an event to all [targets](EventTarget). /// - /// See [`Self::listen`] for more information. - pub fn once(&self, event: impl Into, handler: F) -> EventId + /// # Examples + #[cfg_attr( + feature = "unstable", + doc = r####" +``` +use tauri::Emitter; + +#[tauri::command] +fn synchronize(window: tauri::Window) { + // emits the synchronized event to all webviews + window.emit("synchronized", ()); +} + ``` + "#### + )] + fn emit(&self, event: &str, payload: S) -> crate::Result<()> { + self.manager.emit(event, payload) + } + + /// Emits an event to all [targets](EventTarget) matching the given target. + /// + /// # Examples + #[cfg_attr( + feature = "unstable", + doc = r####" +``` +use tauri::{Emitter, EventTarget}; + +#[tauri::command] +fn download(window: tauri::Window) { + for i in 1..100 { + std::thread::sleep(std::time::Duration::from_millis(150)); + // emit a download progress event to all listeners + window.emit_to(EventTarget::any(), "download-progress", i); + // emit an event to listeners that used App::listen or AppHandle::listen + window.emit_to(EventTarget::app(), "download-progress", i); + // emit an event to any webview/window/webviewWindow matching the given label + window.emit_to("updater", "download-progress", i); // similar to using EventTarget::labeled + window.emit_to(EventTarget::labeled("updater"), "download-progress", i); + // emit an event to listeners that used WebviewWindow::listen + window.emit_to(EventTarget::webview_window("updater"), "download-progress", i); + } +} +``` +"#### + )] + fn emit_to(&self, target: I, event: &str, payload: S) -> crate::Result<()> where - F: FnOnce(Event) + Send + 'static, + I: Into, + S: Serialize + Clone, { - self.manager.once( - event.into(), - EventTarget::Window { - label: self.label().to_string(), - }, - handler, - ) + self.manager.emit_to(target, event, payload) + } + + /// Emits an event to all [targets](EventTarget) based on the given filter. + /// + /// # Examples + #[cfg_attr( + feature = "unstable", + doc = r####" +``` +use tauri::{Emitter, EventTarget}; + +#[tauri::command] +fn download(window: tauri::Window) { + for i in 1..100 { + std::thread::sleep(std::time::Duration::from_millis(150)); + // emit a download progress event to the updater window + window.emit_filter("download-progress", i, |t| match t { + EventTarget::WebviewWindow { label } => label == "main", + _ => false, + }); + } +} + ``` + "#### + )] + fn emit_filter(&self, event: &str, payload: S, filter: F) -> crate::Result<()> + where + S: Serialize + Clone, + F: Fn(&EventTarget) -> bool, + { + self.manager.emit_filter(event, payload, filter) } } diff --git a/core/tauri/src/window/plugin.rs b/core/tauri/src/window/plugin.rs index afaf6026e..f45d4a6cd 100644 --- a/core/tauri/src/window/plugin.rs +++ b/core/tauri/src/window/plugin.rs @@ -11,7 +11,8 @@ use crate::{ #[cfg(desktop)] mod desktop_commands { - use tauri_runtime::ResizeDirection; + use tauri_runtime::{window::WindowSizeConstraints, ResizeDirection}; + use tauri_utils::TitleBarStyle; use super::*; use crate::{ @@ -130,6 +131,8 @@ mod desktop_commands { setter!(start_resize_dragging, ResizeDirection); setter!(set_progress_bar, ProgressBarState); setter!(set_visible_on_all_workspaces, bool); + setter!(set_title_bar_style, TitleBarStyle); + setter!(set_size_constraints, WindowSizeConstraints); #[command(root = "crate")] pub async fn set_icon( @@ -262,6 +265,7 @@ pub fn init() -> TauriPlugin { desktop_commands::set_size, desktop_commands::set_min_size, desktop_commands::set_max_size, + desktop_commands::set_size_constraints, desktop_commands::set_position, desktop_commands::set_fullscreen, desktop_commands::set_focus, @@ -276,6 +280,7 @@ pub fn init() -> TauriPlugin { desktop_commands::set_progress_bar, desktop_commands::set_icon, desktop_commands::set_visible_on_all_workspaces, + desktop_commands::set_title_bar_style, desktop_commands::toggle_maximize, desktop_commands::internal_toggle_maximize, ]); diff --git a/core/tauri/test/fixture/isolation/dist/index.html b/core/tauri/test/fixture/isolation/dist/index.html new file mode 100644 index 000000000..698a35779 --- /dev/null +++ b/core/tauri/test/fixture/isolation/dist/index.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/core/tauri/test/fixture/isolation/isolation-dist/index.html b/core/tauri/test/fixture/isolation/isolation-dist/index.html new file mode 100644 index 000000000..27c8d3f39 --- /dev/null +++ b/core/tauri/test/fixture/isolation/isolation-dist/index.html @@ -0,0 +1,10 @@ + + + + + Isolation Secure Script + + + + + diff --git a/core/tauri/test/fixture/isolation/isolation-dist/index.js b/core/tauri/test/fixture/isolation/isolation-dist/index.js new file mode 100644 index 000000000..6510a210e --- /dev/null +++ b/core/tauri/test/fixture/isolation/isolation-dist/index.js @@ -0,0 +1,8 @@ +// Copyright 2019-2024 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + +window.__TAURI_ISOLATION_HOOK__ = (payload, options) => { + console.log('hook', payload, options) + return payload +} diff --git a/core/tauri/test/fixture/isolation/src-tauri/icons/icon.ico b/core/tauri/test/fixture/isolation/src-tauri/icons/icon.ico new file mode 100644 index 000000000..b3636e4b2 Binary files /dev/null and b/core/tauri/test/fixture/isolation/src-tauri/icons/icon.ico differ diff --git a/core/tauri/test/fixture/isolation/src-tauri/icons/icon.ico~dev b/core/tauri/test/fixture/isolation/src-tauri/icons/icon.ico~dev new file mode 100644 index 000000000..db7fd9820 Binary files /dev/null and b/core/tauri/test/fixture/isolation/src-tauri/icons/icon.ico~dev differ diff --git a/core/tauri/test/fixture/isolation/src-tauri/icons/icon.png b/core/tauri/test/fixture/isolation/src-tauri/icons/icon.png new file mode 100644 index 000000000..a437dd517 Binary files /dev/null and b/core/tauri/test/fixture/isolation/src-tauri/icons/icon.png differ diff --git a/core/tauri/test/fixture/isolation/src-tauri/tauri.conf.json b/core/tauri/test/fixture/isolation/src-tauri/tauri.conf.json new file mode 100644 index 000000000..5aae4629a --- /dev/null +++ b/core/tauri/test/fixture/isolation/src-tauri/tauri.conf.json @@ -0,0 +1,27 @@ +{ + "$schema": "../../../../../../core/tauri-config-schema/schema.json", + "identifier": "isolation.tauri.example", + "build": { + "frontendDist": "../dist", + "devUrl": "http://localhost:4000" + }, + "app": { + "windows": [ + { + "title": "Isolation Tauri App" + } + ], + "security": { + "csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self'; connect-src ipc: http://ipc.localhost", + "pattern": { + "use": "isolation", + "options": { + "dir": "../isolation-dist" + } + } + } + }, + "bundle": { + "active": true + } +} diff --git a/core/tests/restart/Cargo.toml b/core/tests/restart/Cargo.toml index 1d7036e98..6a96e1af8 100644 --- a/core/tests/restart/Cargo.toml +++ b/core/tests/restart/Cargo.toml @@ -10,3 +10,6 @@ path = "../../tauri" [dev-dependencies] tempfile = "3" + +[features] +process-relaunch-dangerous-allow-symlink-macos = [] diff --git a/core/tests/restart/tests/restart.rs b/core/tests/restart/tests/restart.rs index 94ff2c8b3..89bfdd01b 100644 --- a/core/tests/restart/tests/restart.rs +++ b/core/tests/restart/tests/restart.rs @@ -9,7 +9,7 @@ use std::process::Command; /// Helper for generic catch-all errors. type Result = std::result::Result<(), Box>; -/// https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--1300-1699- +/// #[cfg(windows)] const ERROR_PRIVILEGE_NOT_HELD: i32 = 1314; diff --git a/examples/api/package.json b/examples/api/package.json index 8c9d326c7..b65d412c4 100644 --- a/examples/api/package.json +++ b/examples/api/package.json @@ -18,7 +18,6 @@ "@iconify-json/ph": "^1.1.13", "@sveltejs/vite-plugin-svelte": "^3.1.1", "@unocss/extractor-svelte": "^0.61.0", - "internal-ip": "^8.0.0", "svelte": "^4.2.18", "unocss": "^0.61.0", "vite": "^5.3.2" diff --git a/examples/api/src-tauri/Cargo.lock b/examples/api/src-tauri/Cargo.lock index 57e3e905d..62b0c1e53 100644 --- a/examples/api/src-tauri/Cargo.lock +++ b/examples/api/src-tauri/Cargo.lock @@ -3033,7 +3033,7 @@ checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "tauri" -version = "2.0.0-beta.22" +version = "2.0.0-rc.0" dependencies = [ "anyhow", "bytes", @@ -3083,7 +3083,7 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.0.0-beta.17" +version = "2.0.0-rc.0" dependencies = [ "anyhow", "cargo_toml", @@ -3105,7 +3105,7 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "2.0.0-beta.17" +version = "2.0.0-rc.0" dependencies = [ "base64 0.22.1", "brotli", @@ -3130,7 +3130,7 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.0.0-beta.17" +version = "2.0.0-rc.0" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -3142,7 +3142,7 @@ dependencies = [ [[package]] name = "tauri-plugin" -version = "2.0.0-beta.17" +version = "2.0.0-rc.0" dependencies = [ "anyhow", "glob", @@ -3168,7 +3168,7 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.0.0-beta.18" +version = "2.0.0-rc.0" dependencies = [ "dpi", "gtk", @@ -3185,7 +3185,7 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "2.0.0-beta.18" +version = "2.0.0-rc.0" dependencies = [ "cocoa", "gtk", @@ -3207,7 +3207,7 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.0.0-beta.17" +version = "2.0.0-rc.0" dependencies = [ "aes-gcm", "brotli", diff --git a/examples/api/src-tauri/Cargo.toml b/examples/api/src-tauri/Cargo.toml index fd489ff2d..63d1768d2 100644 --- a/examples/api/src-tauri/Cargo.toml +++ b/examples/api/src-tauri/Cargo.toml @@ -8,7 +8,7 @@ license = "Apache-2.0 OR MIT" [lib] name = "api_lib" -crate-type = ["staticlib", "cdylib", "rlib"] +crate-type = ["staticlib", "cdylib", "lib"] [build-dependencies] tauri-build = { path = "../../../core/tauri-build", features = [ diff --git a/examples/api/src-tauri/build.rs b/examples/api/src-tauri/build.rs index 40216f916..2b72c77a1 100644 --- a/examples/api/src-tauri/build.rs +++ b/examples/api/src-tauri/build.rs @@ -10,9 +10,11 @@ fn main() { "app-menu", tauri_build::InlinedPlugin::new().commands(&["toggle", "popup"]), ) - .app_manifest( - tauri_build::AppManifest::new().commands(&["log_operation", "perform_request"]), - ), + .app_manifest(tauri_build::AppManifest::new().commands(&[ + "log_operation", + "perform_request", + "echo", + ])), ) .expect("failed to run tauri-build"); } diff --git a/examples/api/src-tauri/capabilities/run-app.json b/examples/api/src-tauri/capabilities/run-app.json index 424fe5dd6..5c2bf7942 100644 --- a/examples/api/src-tauri/capabilities/run-app.json +++ b/examples/api/src-tauri/capabilities/run-app.json @@ -16,56 +16,50 @@ ] }, "allow-perform-request", + "allow-echo", "app-menu:default", "sample:allow-ping-scoped", "sample:global-scope", - "path:default", - "event:default", - "window:default", - "app:default", - "resources:default", - "image:default", - "menu:default", - "tray:default", - "app:allow-app-hide", - "app:allow-app-show", - "window:allow-center", - "window:allow-request-user-attention", - "window:allow-set-resizable", - "window:allow-set-maximizable", - "window:allow-set-minimizable", - "window:allow-set-closable", - "window:allow-set-title", - "window:allow-maximize", - "window:allow-unmaximize", - "window:allow-minimize", - "window:allow-unminimize", - "window:allow-show", - "window:allow-hide", - "window:allow-close", - "window:allow-set-decorations", - "window:allow-set-shadow", - "window:allow-set-effects", - "window:allow-set-always-on-top", - "window:allow-set-always-on-bottom", - "window:allow-set-content-protected", - "window:allow-set-size", - "window:allow-set-min-size", - "window:allow-set-max-size", - "window:allow-set-position", - "window:allow-set-fullscreen", - "window:allow-set-focus", - "window:allow-set-skip-taskbar", - "window:allow-set-cursor-grab", - "window:allow-set-cursor-visible", - "window:allow-set-cursor-icon", - "window:allow-set-cursor-position", - "window:allow-set-ignore-cursor-events", - "window:allow-start-dragging", - "window:allow-set-progress-bar", - "window:allow-set-icon", - "window:allow-toggle-maximize", - "webview:allow-create-webview-window", - "webview:allow-print" + "core:default", + "core:app:allow-app-hide", + "core:app:allow-app-show", + "core:window:allow-center", + "core:window:allow-request-user-attention", + "core:window:allow-set-resizable", + "core:window:allow-set-maximizable", + "core:window:allow-set-minimizable", + "core:window:allow-set-closable", + "core:window:allow-set-title", + "core:window:allow-maximize", + "core:window:allow-unmaximize", + "core:window:allow-minimize", + "core:window:allow-unminimize", + "core:window:allow-show", + "core:window:allow-hide", + "core:window:allow-close", + "core:window:allow-set-decorations", + "core:window:allow-set-shadow", + "core:window:allow-set-effects", + "core:window:allow-set-always-on-top", + "core:window:allow-set-always-on-bottom", + "core:window:allow-set-content-protected", + "core:window:allow-set-size", + "core:window:allow-set-min-size", + "core:window:allow-set-max-size", + "core:window:allow-set-position", + "core:window:allow-set-fullscreen", + "core:window:allow-set-focus", + "core:window:allow-set-skip-taskbar", + "core:window:allow-set-cursor-grab", + "core:window:allow-set-cursor-visible", + "core:window:allow-set-cursor-icon", + "core:window:allow-set-cursor-position", + "core:window:allow-set-ignore-cursor-events", + "core:window:allow-start-dragging", + "core:window:allow-set-progress-bar", + "core:window:allow-set-icon", + "core:window:allow-toggle-maximize", + "core:webview:allow-create-webview-window", + "core:webview:allow-print" ] -} +} \ No newline at end of file diff --git a/examples/api/src-tauri/permissions/autogenerated/echo.toml b/examples/api/src-tauri/permissions/autogenerated/echo.toml new file mode 100644 index 000000000..d8c458ee8 --- /dev/null +++ b/examples/api/src-tauri/permissions/autogenerated/echo.toml @@ -0,0 +1,11 @@ +# Automatically generated - DO NOT EDIT! + +[[permission]] +identifier = "allow-echo" +description = "Enables the echo command without any pre-configured scope." +commands.allow = ["echo"] + +[[permission]] +identifier = "deny-echo" +description = "Denies the echo command without any pre-configured scope." +commands.deny = ["echo"] diff --git a/examples/api/src-tauri/src/cmd.rs b/examples/api/src-tauri/src/cmd.rs index feeba329a..80ae03d10 100644 --- a/examples/api/src-tauri/src/cmd.rs +++ b/examples/api/src-tauri/src/cmd.rs @@ -45,3 +45,8 @@ pub fn perform_request(endpoint: String, body: RequestBody) -> ApiResponse { message: "message response".into(), } } + +#[command] +pub fn echo(request: tauri::ipc::Request<'_>) -> tauri::ipc::Response { + tauri::ipc::Response::new(request.body().clone()) +} diff --git a/examples/api/src-tauri/src/lib.rs b/examples/api/src-tauri/src/lib.rs index 0527174fe..ba1c41d9b 100644 --- a/examples/api/src-tauri/src/lib.rs +++ b/examples/api/src-tauri/src/lib.rs @@ -12,7 +12,7 @@ use serde::Serialize; use tauri::{ ipc::Channel, webview::{PageLoadEvent, WebviewWindowBuilder}, - App, AppHandle, Manager, RunEvent, Runtime, WebviewUrl, + App, AppHandle, Emitter, Listener, Manager, RunEvent, Runtime, WebviewUrl, }; use tauri_plugin_sample::{PingRequest, SampleExt}; @@ -141,6 +141,7 @@ pub fn run_app) + Send + 'static>( .invoke_handler(tauri::generate_handler![ cmd::log_operation, cmd::perform_request, + cmd::echo ]) .build(tauri::tauri_build_context!()) .expect("error while building tauri application"); diff --git a/examples/api/src-tauri/tauri-plugin-sample/android/settings.gradle b/examples/api/src-tauri/tauri-plugin-sample/android/settings.gradle index 14a752e43..d7782a40d 100644 --- a/examples/api/src-tauri/tauri-plugin-sample/android/settings.gradle +++ b/examples/api/src-tauri/tauri-plugin-sample/android/settings.gradle @@ -1,2 +1,31 @@ +pluginManagement { + repositories { + mavenCentral() + gradlePluginPortal() + google() + } + resolutionStrategy { + eachPlugin { + switch (requested.id.id) { + case "com.android.library": + useVersion("8.0.2") + break + case "org.jetbrains.kotlin.android": + useVersion("1.8.20") + break + } + } + } +} + +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + mavenCentral() + google() + + } +} + include ':tauri-android' project(':tauri-android').projectDir = new File('./.tauri/tauri-api') diff --git a/examples/api/src-tauri/tauri-plugin-sample/src/desktop.rs b/examples/api/src-tauri/tauri-plugin-sample/src/desktop.rs index 1526a1f5f..df5013d2c 100644 --- a/examples/api/src-tauri/tauri-plugin-sample/src/desktop.rs +++ b/examples/api/src-tauri/tauri-plugin-sample/src/desktop.rs @@ -17,14 +17,12 @@ pub fn init( /// A helper class to access the sample APIs. pub struct Sample(AppHandle); -#[derive(serde::Serialize)] -struct Event { - kind: &'static str, -} - impl Sample { pub fn ping(&self, payload: PingRequest) -> crate::Result { - let _ = payload.on_event.send(Event { kind: "ping" }); + let _ = payload.on_event.send(Event { + kind: "ping".to_string(), + value: payload.value.clone(), + }); Ok(PingResponse { value: payload.value, }) diff --git a/examples/api/src-tauri/tauri-plugin-sample/src/models.rs b/examples/api/src-tauri/tauri-plugin-sample/src/models.rs index 99ac80ba9..385d54fe3 100644 --- a/examples/api/src-tauri/tauri-plugin-sample/src/models.rs +++ b/examples/api/src-tauri/tauri-plugin-sample/src/models.rs @@ -6,10 +6,16 @@ use serde::{Deserialize, Serialize}; use tauri::ipc::Channel; #[derive(Serialize)] +pub struct Event { + pub kind: String, + pub value: Option +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] pub struct PingRequest { pub value: Option, - #[serde(rename = "onEvent")] - pub on_event: Channel, + pub on_event: Channel, } #[derive(Debug, Clone, Default, Deserialize, Serialize)] diff --git a/examples/api/src/App.svelte b/examples/api/src/App.svelte index 3b077748b..34ecda528 100644 --- a/examples/api/src/App.svelte +++ b/examples/api/src/App.svelte @@ -2,6 +2,7 @@ import { onMount, tick } from 'svelte' import { writable } from 'svelte/store' import { invoke } from '@tauri-apps/api/core' + import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow' import Welcome from './views/Welcome.svelte' import Communication from './views/Communication.svelte' @@ -17,6 +18,11 @@ } }) + const appWindow = getCurrentWebviewWindow() + appWindow.onDragDropEvent((event) => { + onMessage(event.payload) + }) + const userAgent = navigator.userAgent.toLowerCase() const isMobile = userAgent.includes('android') || userAgent.includes('iphone') @@ -83,12 +89,22 @@ let messages = writable([]) let consoleTextEl async function onMessage(value) { + const valueStr = + typeof value === 'string' + ? value + : JSON.stringify( + value instanceof ArrayBuffer + ? Array.from(new Uint8Array(value)) + : value, + null, + 1 + ) messages.update((r) => [ ...r, { html: `
[${new Date().toLocaleTimeString()}]: ` +
-          (typeof value === 'string' ? value : JSON.stringify(value, null, 1)) +
+          valueStr +
           '
' } ]) @@ -210,7 +226,7 @@