diff --git a/.changes/api-moduleresolution-node.md b/.changes/api-moduleresolution-node.md new file mode 100644 index 000000000000..26e96bf91dff --- /dev/null +++ b/.changes/api-moduleresolution-node.md @@ -0,0 +1,5 @@ +--- +"@tauri-apps/api": "patch:bug" +--- + +Fix a regression where typescript could not find types when using `"moduleResolution": "node"` diff --git a/.changes/api-primitives-core.md b/.changes/api-primitives-core.md new file mode 100644 index 000000000000..0615fd486a55 --- /dev/null +++ b/.changes/api-primitives-core.md @@ -0,0 +1,5 @@ +--- +'@tauri-apps/api': 'patch:breaking' +--- + +Changed former `tauri` module from `primitives` to `core`. diff --git a/.changes/api-top-level-main-module.md b/.changes/api-top-level-main-module.md new file mode 100644 index 000000000000..fba6cdb2c37b --- /dev/null +++ b/.changes/api-top-level-main-module.md @@ -0,0 +1,5 @@ +--- +'@tauri-apps/api': 'patch:bug' +--- + +Add top-level `main`, `module` and `types` fields in `package.json` to be compliant with typescripts's `"moduleResolution": "node"` diff --git a/.changes/api-tray-menu.md b/.changes/api-tray-menu.md new file mode 100644 index 000000000000..2071bcca177b --- /dev/null +++ b/.changes/api-tray-menu.md @@ -0,0 +1,5 @@ +--- +'@tauri-apps/api': 'minor:feat' +--- + +Add `tray` and `menu` modules to create and manage tray icons and menus from Javascript. diff --git a/.changes/cli-signer-env-vars.md b/.changes/cli-signer-env-vars.md new file mode 100644 index 000000000000..41c04062ea2f --- /dev/null +++ b/.changes/cli-signer-env-vars.md @@ -0,0 +1,9 @@ +--- +'tauri-cli': 'patch:enhance' +--- + +Read the following env vars when using the `tauri signer sign` command to make it easier to use in CI. + +- `TAURI_PRIVATE_KEY` +- `TAURI_PRIVATE_KEY_PASSWORD` +- `TAURI_PRIVATE_KEY_PATH` diff --git a/.changes/fix-file-drop-event-payload.md b/.changes/fix-file-drop-event-payload.md new file mode 100644 index 000000000000..44c1ff4bfe19 --- /dev/null +++ b/.changes/fix-file-drop-event-payload.md @@ -0,0 +1,5 @@ +--- +"@tauri-apps/api": 'patch:enhance' +--- + +Added `position` field to the `FileDropEvent` payload. diff --git a/.changes/fix-ide-build-run.md b/.changes/fix-ide-build-run.md new file mode 100644 index 000000000000..f89fab21bf12 --- /dev/null +++ b/.changes/fix-ide-build-run.md @@ -0,0 +1,6 @@ +--- +"tauri-cli": patch:bug +"@tauri-apps/cli": patch:bug +--- + +Fixes `android build --open` and `ios build --open` IDE failing to read CLI options. diff --git a/.changes/fix-ios-channel.md b/.changes/fix-ios-channel.md new file mode 100644 index 000000000000..a1bf8bf7ab41 --- /dev/null +++ b/.changes/fix-ios-channel.md @@ -0,0 +1,5 @@ +--- +"tauri": 'patch:enhance' +--- + +Fixed the deserialisation of a `Channel` in iOS. \ No newline at end of file diff --git a/.changes/get-ipc-response-test.md b/.changes/get-ipc-response-test.md new file mode 100644 index 000000000000..9cd3ce1d26c2 --- /dev/null +++ b/.changes/get-ipc-response-test.md @@ -0,0 +1,5 @@ +--- +"tauri": patch:enhance +--- + +Added `test::get_ipc_response`. diff --git a/.changes/merge-ios-plist.md b/.changes/merge-ios-plist.md new file mode 100644 index 000000000000..87cf86f3a789 --- /dev/null +++ b/.changes/merge-ios-plist.md @@ -0,0 +1,6 @@ +--- +"tauri-cli": patch:feat +"@tauri-apps/cli": patch:feat +--- + +Merge `src-tauri/Info.plist` and `src-tauri/Info.ios.plist` with the iOS project plist file. diff --git a/.changes/pre.json b/.changes/pre.json index af746e0d3138..29c82cdd2e1b 100644 --- a/.changes/pre.json +++ b/.changes/pre.json @@ -21,6 +21,7 @@ ".changes/api-min-node-18.md", ".changes/api-primitives.md", ".changes/api-tabbed.md", + ".changes/api-tray-menu.md", ".changes/api-window.md", ".changes/app-builder-send.md", ".changes/app-plugin-core.md", @@ -53,6 +54,7 @@ ".changes/cli-nodejs-detection.md", ".changes/cli-npx-mobile.md", ".changes/cli-plugin-init.md", + ".changes/cli-plugin-name-snake-case.md", ".changes/cli-pnpm.md", ".changes/cli-refactor-ipc-mobile.md", ".changes/cli-removed-new-version-check.md", @@ -94,7 +96,10 @@ ".changes/fix-clearmocks.md", ".changes/fix-dev-server-proxy-path.md", ".changes/fix-empty-identifier.md", + ".changes/fix-file-drop-event-payload.md", + ".changes/fix-global-event.md", ".changes/fix-icons-android.md", + ".changes/fix-ide-build-run.md", ".changes/fix-ios-cli-panic.md", ".changes/fix-ios-logs.md", ".changes/fix-ios-plugin-throws-command.md", @@ -108,6 +113,7 @@ ".changes/fix-plugin-ios-bool.md", ".changes/fix-plugin-removal.md", ".changes/fix-plugin-template-cargotoml.md", + ".changes/fix-plugin-template.md", ".changes/fix-proguard-injection.md", ".changes/fix-proguard-rules.md", ".changes/fix-shell-build.md", @@ -115,6 +121,7 @@ ".changes/fix-tray-icon-validation.md", ".changes/fix-windows-custom-protocol-url.md", ".changes/fix-windows-custom-protocol.md", + ".changes/fix-wix-output-filename-version.md", ".changes/fix-xcodescript-lib-path.md", ".changes/force-colored-logs.md", ".changes/generate-tauri-activity.md", @@ -122,6 +129,7 @@ ".changes/gtk018.md", ".changes/gtk16.md", ".changes/http-types-refactor.md", + ".changes/icon-svg.md", ".changes/improve-local-ip-detection.md", ".changes/improve-mobile-plugin-error-handling.md", ".changes/inject-config.md", @@ -148,6 +156,7 @@ ".changes/local-dev-path-mobile.md", ".changes/log-file-fix-for-linux-and-windows.md", ".changes/logcat-all-tags.md", + ".changes/merge-ios-plist.md", ".changes/migrate-cmd.md", ".changes/migrate-csp.md", ".changes/migrate-plugins.md", @@ -211,6 +220,7 @@ ".changes/refactor-setup.md", ".changes/refactor-tauri-android-dependency.md", ".changes/register_asynchronous_uri_scheme_protocol.md", + ".changes/relative-mobile-args.md", ".changes/remove-allowlist.md", ".changes/remove-attohttpc.md", ".changes/remove-clipboard.md", @@ -249,12 +259,14 @@ ".changes/skip-target-install-arg.md", ".changes/state-0.6.md", ".changes/submenu-and-menu-builders-item-and-id.md", + ".changes/syn-2.0.md", ".changes/system-tray-feat.md", ".changes/target-dir-detection.md", ".changes/tauri-api-removal.md", ".changes/tauri-app-handle-ref.md", ".changes/tauri-asset-protocol.md", ".changes/tauri-build-mobile.md", + ".changes/tauri-build-resource-compiler.md", ".changes/tauri-cleanup-before-exit.md", ".changes/tauri-defaultvbox.md", ".changes/tauri-env-args.md", @@ -277,6 +289,7 @@ ".changes/tauri-tray-on-tray-event.md", ".changes/tauri-utils-tabbed.md", ".changes/tauri-utils-tray-icon-id copy.md", + ".changes/tauri-utils-windows-version.md", ".changes/tauri-uuid-rand.md", ".changes/tempdir-api.md", ".changes/tempdir-core.md", @@ -298,6 +311,7 @@ ".changes/wry-0.32.md", ".changes/wry-0.34.md", ".changes/wry-navigate-method.md", - ".changes/wry26.md" + ".changes/wry26.md", + ".changes/xcode-archive.md" ] } diff --git a/.changes/syn-2.0.md b/.changes/syn-2.0.md new file mode 100644 index 000000000000..3ea03d003c14 --- /dev/null +++ b/.changes/syn-2.0.md @@ -0,0 +1,5 @@ +--- +"tauri-macros": patch:deps +--- + +Update to syn v2. diff --git a/.changes/tauri-menu-predefined-close-wiwndow.md b/.changes/tauri-menu-predefined-close-wiwndow.md new file mode 100644 index 000000000000..42c8b81fdd62 --- /dev/null +++ b/.changes/tauri-menu-predefined-close-wiwndow.md @@ -0,0 +1,5 @@ +--- +"tauri": "patch:bug" +--- + +Fix incorrect menu item for `PredefinedMenuItem::close_window` \ No newline at end of file diff --git a/.changes/tauri-resources-table.md b/.changes/tauri-resources-table.md new file mode 100644 index 000000000000..2f98fc883048 --- /dev/null +++ b/.changes/tauri-resources-table.md @@ -0,0 +1,5 @@ +--- +'tauri': 'patch:feat' +--- + +Exposed `Manager::resources_table` to access the resources table used by tauri, which could be used by plugins or app authors to store their resources and retrieve it later using an id. diff --git a/.changes/tauri-utils-windows-version.md b/.changes/tauri-utils-windows-version.md new file mode 100644 index 000000000000..d755a8f4a8e6 --- /dev/null +++ b/.changes/tauri-utils-windows-version.md @@ -0,0 +1,5 @@ +--- +'tauri-utils': 'minor:breaking' +--- + +Removed `platform::windows_version` and `platform::is_windows_7`, use `windows-version` crate instead. diff --git a/.changes/xcode-archive.md b/.changes/xcode-archive.md new file mode 100644 index 000000000000..f7d2407e93b3 --- /dev/null +++ b/.changes/xcode-archive.md @@ -0,0 +1,6 @@ +--- +"tauri-cli": patch:bug +"@tauri-apps/cli": patch:bug +--- + +Added support to Xcode's archive. This requires regenerating the Xcode project. diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 7e77aab2e672..1d856b7874fa 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -22,7 +22,7 @@ Hi! We, the maintainers, are really excited that you are interested in contribut - Issues with no clear repro steps will not be triaged. If an issue labeled "need repro" receives no further input from the issue author for more than 5 days, it will be closed. -- If your issue is resolved but still open, don’t hesitate to close it. In case you found a solution by yourself, it could be helpful to explain how you fixed it. +- If your issue is resolved but still open, don't hesitate to close it. In case you found a solution by yourself, it could be helpful to explain how you fixed it. - Most importantly, we beg your patience: the team must balance your request against many other responsibilities — fixing other bugs, answering other questions, new features, new documentation, etc. The issue list is not paid support and we cannot make guarantees about how fast your issue can be resolved. diff --git a/.github/sponsors/crabnebula.svg b/.github/sponsors/crabnebula.svg new file mode 100644 index 000000000000..40e24131b51e --- /dev/null +++ b/.github/sponsors/crabnebula.svg @@ -0,0 +1,31 @@ + \ No newline at end of file diff --git a/.github/workflows/covector-version-or-publish.yml b/.github/workflows/covector-version-or-publish.yml index 025e9772166d..f81ab3ab412b 100644 --- a/.github/workflows/covector-version-or-publish.yml +++ b/.github/workflows/covector-version-or-publish.yml @@ -112,14 +112,18 @@ jobs: repository: tauri-apps/tauri-docs event-type: update-docs - - name: Process covector output - id: covectorOutput + - name: Get `@tauri-apps/cli` release id + uses: actions/github-script@v6 + id: cliReleaseId if: | steps.covector.outputs.successfulPublish == 'true' && contains(steps.covector.outputs.packagesPublished, '@tauri-apps/cli') - run: | - id=$(node .scripts/covector/parse-output.js '${{ toJSON(steps.covector.outputs) }}' "-tauri-apps-cli-releaseId") - echo "cliReleaseId=$id" >> "$GITHUB_OUTPUT" + with: + result-encoding: string + script: | + const output = `${{ toJSON(steps.covector.outputs) }}`; + const [_, id] = /"-tauri-apps-cli-releaseId": "([0-9]+)"/g.exec(output); + return id; - name: Trigger `@tauri-apps/cli` publishing workflow if: | @@ -130,7 +134,7 @@ jobs: token: ${{ secrets.ORG_TAURI_BOT_PAT }} repository: tauri-apps/tauri event-type: publish-js-cli - client-payload: '{"releaseId": "${{ steps.covectorOutput.outputs.cliReleaseId }}" }' + client-payload: '{"releaseId": "${{ steps.cliReleaseId.outputs.result }}" }' - name: Trigger `tauri-cli` publishing workflow if: | diff --git a/.github/workflows/lint-js.yml b/.github/workflows/lint-js.yml index 587d8285d4af..5fe27a62c6c2 100644 --- a/.github/workflows/lint-js.yml +++ b/.github/workflows/lint-js.yml @@ -49,6 +49,9 @@ jobs: - name: install deps via yarn working-directory: ./tooling/api/ run: yarn + - name: run ts:check + working-directory: ./tooling/api/ + run: yarn ts:check - name: run lint working-directory: ./tooling/api/ run: yarn lint diff --git a/.github/workflows/publish-cli-js.yml b/.github/workflows/publish-cli-js.yml index 48f7803cf0e0..d7be5a5ad98f 100644 --- a/.github/workflows/publish-cli-js.yml +++ b/.github/workflows/publish-cli-js.yml @@ -294,14 +294,10 @@ jobs: - name: List packages run: ls -R . shell: bash - - name: Install system dependencies - run: | - apk add openssl-dev musl-dev glib-dev cairo-dev pkgconfig gdk-pixbuf-dev webkit2gtk-dev curl gtk+3.0-dev - name: Setup and run tests run: | yarn tauri --help ls -la - # TODO: fix this test: https://github.com/tauri-apps/tauri/runs/5145729140?check_suite_focus=true#step:9:704 #- name: Setup and run tests # run: | # rustup install stable diff --git a/.husky/pre-commit b/.husky/pre-commit index 3050d5d43f92..7178a5417264 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -11,7 +11,7 @@ if [ -z "$(git diff --name-only tooling/api)" ]; then else cd tooling/api yarn format - yarn lint-fix + yarn lint:fix cd ../.. fi diff --git a/.scripts/ci/check-license-header.js b/.scripts/ci/check-license-header.js index a3a8b32c0f36..40da761054bf 100644 --- a/.scripts/ci/check-license-header.js +++ b/.scripts/ci/check-license-header.js @@ -13,6 +13,8 @@ SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: MIT` const bundlerLicense = '// Copyright 2016-2019 Cargo-Bundle developers ' +const denoLicense = + '// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.' const extensions = ['.rs', '.js', '.ts', '.yml', '.swift', '.kt'] const ignore = [ @@ -43,7 +45,8 @@ async function checkFile(file) { line.length === 0 || line.startsWith('#!') || line.startsWith('// swift-tools-version:') || - line === bundlerLicense + line === bundlerLicense || + line === denoLicense ) { continue } diff --git a/README.md b/README.md index 18903b7b5f03..25a4c7218184 100644 --- a/README.md +++ b/README.md @@ -9,121 +9,49 @@ [![https://good-labs.github.io/greater-good-affirmation/assets/images/badge.svg](https://good-labs.github.io/greater-good-affirmation/assets/images/badge.svg)](https://good-labs.github.io/greater-good-affirmation) [![support](https://img.shields.io/badge/sponsor-Open%20Collective-blue.svg)](https://opencollective.com/tauri) -## Current Releases - -### Core - -| Component | Description | Version | Lin | Win | Mac | -| -------------------------------------------------------------------------------------------- | ----------------------------------------- | -------------------------------------------------------------------------------------------------------- | --- | --- | --- | -| [**tauri**](https://github.com/tauri-apps/tauri/tree/dev/core/tauri) | runtime core | [![](https://img.shields.io/crates/v/tauri.svg)](https://crates.io/crates/tauri) | ✅ | ✅ | ✅ | -| [**tauri-build**](https://github.com/tauri-apps/tauri/tree/dev/core/tauri-build) | applies macros at build-time | [![](https://img.shields.io/crates/v/tauri-build.svg)](https://crates.io/crates/tauri-build) | ✅ | ✅ | ✅ | -| [**tauri-codegen**](https://github.com/tauri-apps/tauri/tree/dev/core/tauri-codegen) | handles assets, parses tauri.conf.json | [![](https://img.shields.io/crates/v/tauri-codegen.svg)](https://crates.io/crates/tauri-codegen) | ✅ | ✅ | ✅ | -| [**tauri-macros**](https://github.com/tauri-apps/tauri/tree/dev/core/tauri-macros) | creates macros using tauri-codegen | [![](https://img.shields.io/crates/v/tauri-macros.svg)](https://crates.io/crates/tauri-macros) | ✅ | ✅ | ✅ | -| [**tauri-runtime**](https://github.com/tauri-apps/tauri/tree/dev/core/tauri-runtime) | layer between Tauri and webview libraries | [![](https://img.shields.io/crates/v/tauri-runtime.svg)](https://crates.io/crates/tauri-runtime) | ✅ | ✅ | ✅ | -| [**tauri-runtime-wry**](https://github.com/tauri-apps/tauri/tree/dev/core/tauri-runtime-wry) | enables system-level interaction via WRY | [![](https://img.shields.io/crates/v/tauri-runtime-wry.svg)](https://crates.io/crates/tauri-runtime-wry) | ✅ | ✅ | ✅ | -| [**tauri-utils**](https://github.com/tauri-apps/tauri/tree/dev/core/tauri-utils) | common code used across the tauri crates | [![](https://img.shields.io/crates/v/tauri-utils.svg)](https://crates.io/crates/tauri-utils) | ✅ | ✅ | ✅ | - -### Tooling - -| Component | Description | Version | Lin | Win | Mac | -| ------------------------------------------------------------------------------------ | ---------------------------------------- | ------------------------------------------------------------------------------------------------------ | --- | --- | --- | -| [**bundler**](https://github.com/tauri-apps/tauri/tree/dev/tooling/bundler) | manufacture the final binaries | [![](https://img.shields.io/crates/v/tauri-bundler.svg)](https://crates.io/crates/tauri-bundler) | ✅ | ✅ | ✅ | -| [**tauri-cli**](https://github.com/tauri-apps/tauri/tree/dev/tooling/cli) | create, develop and build apps | [![](https://img.shields.io/crates/v/tauri-cli.svg)](https://crates.io/crates/tauri-cli) | ✅ | ✅ | ✅ | -| [**@tauri-apps/cli**](https://github.com/tauri-apps/tauri/tree/dev/tooling/cli/node) | Node.js CLI wrapper for `tauri-cli` | [![](https://img.shields.io/npm/v/@tauri-apps/cli.svg)](https://www.npmjs.com/package/@tauri-apps/cli) | ✅ | ✅ | ✅ | -| [**@tauri-apps/api**](https://github.com/tauri-apps/tauri/tree/dev/tooling/api) | JS API for interaction with Rust backend | [![](https://img.shields.io/npm/v/@tauri-apps/api.svg)](https://www.npmjs.com/package/@tauri-apps/api) | ✅ | ✅ | ✅ | - -### Utilities and Plugins - -| Component | Description | Version | Lin | Win | Mac | -| ------------------------------------------------------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | --- | --- | --- | -| [**create-tauri-app**](https://github.com/tauri-apps/create-tauri-app) | Get started with your first Tauri app | [![](https://img.shields.io/npm/v/create-tauri-app.svg)](https://www.npmjs.com/package/create-tauri-app) | ✅ | ✅ | ✅ | -| [**vue-cli-plugin-tauri**](https://github.com/tauri-apps/vue-cli-plugin-tauri/) | Vue CLI plugin for Tauri | [![](https://img.shields.io/npm/v/vue-cli-plugin-tauri.svg)](https://www.npmjs.com/package/vue-cli-plugin-tauri) | ✅ | ✅ | ✅ | - ## Introduction Tauri is a framework for building tiny, blazingly fast binaries for all major desktop platforms. Developers can integrate any front-end framework that compiles to HTML, JS and CSS for building their user interface. The backend of the application is a rust-sourced binary with an API that the front-end can interact with. -The user interface in Tauri apps currently leverages [`tao`](https://docs.rs/tao) as a window handling library on macOS and Windows, and [`gtk`](https://gtk-rs.org/docs/gtk/) on Linux via the **Tauri-team** incubated and maintained [WRY](https://github.com/tauri-apps/wry), which creates a unified interface to the system webview (and other goodies like Menu and Taskbar), leveraging WebKit on macOS, WebView2 on Windows and WebKitGTK on Linux. +The user interface in Tauri apps currently leverages [`tao`](https://docs.rs/tao) as a window handling library on macOS, Windows, Linux, Android and iOS. To render your application, Tauri uses [WRY](https://github.com/tauri-apps/wry), a library which provides a unified interface to the system webview, leveraging WKWebView on macOS & iOS, WebView2 on Windows, WebKitGTK on Linux and Android System WebView on Android. 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. -## Get Started - -If you are interested in making a tauri app, please visit the [documentation website](https://tauri.app). This README is directed towards those who are interested in contributing to the core library. But if you just want a quick overview about where `tauri` is at in its development, here's a quick burndown: - -### Platforms - -Tauri currently supports development and distribution on the following platforms: - -| Platform | Versions | -| :----------------------- | :-------------- | -| Windows | 7 and above | -| macOS | 10.15 and above | -| Linux | See below | -| iOS/iPadOS (coming soon) | | -| Android (coming soon) | | - -**Linux Support** +## Getting Started -For **developing** Tauri apps refer to the [Getting Started guide on tauri.app](https://tauri.app/v1/guides/getting-started/prerequisites#setting-up-linux). +If you are interested in making a tauri app, please visit the [documentation website](https://tauri.app). -For **running** Tauri apps we support the below configurations (these are automatically added as dependencies for .deb and are bundled for AppImage so that your users don't need to manually install them): +The quickest way to get started is to install the [prerequisites](https://tauri.app/v1/guides/getting-started/prerequisites) for your system and create a new project with [`create-tauri-app`](https://github.com/tauri-apps/create-tauri-app/#usage). For example with `npm`: -- Debian (Ubuntu 18.04 and above or equivalent) with the following packages installed: - - `libwebkit2gtk-4.1-0`, `libgtk-3-0`, `libayatana-appindicator3-1`1 -- Arch with the following packages installed: - - `webkit2gtk`, `gtk3`, `libayatana-appindicator`1 -- Fedora (latest 2 versions) with the following packages installed: - - `webkit2gtk3`, `gtk3`, `libappindicator-gtk3`1 -- Void with the following packages installed: - - `webkit2gtk`, `gtk+3`, `libappindicator`1 +```sh +npm create tauri-app@latest +``` -1 `appindicator` is only required if system trays are used +## Features -### Features +The list of Tauri's features includes, but is not limited to: -- [x] Desktop Bundler (.app, .dmg, .deb, AppImage, .msi) -- [x] Self Updater -- [x] App Signing -- [x] Native Notifications (toast) -- [x] App Tray -- [x] Core Plugin System -- [x] Scoped Filesystem -- [x] Sidecar +- Built-in app bundler to create app bundles in formats like `.app`, `.dmg`, `.deb`, `.AppImage` and Windows installers like `.exe` (via NSIS) and `.msi` (via WiX). +- Built-in self updater (desktop only) +- System tray icons +- Native notifications +- Localhost free (:fire:) +- GitHub action for streamlined CI +- VS Code extension -### Security Features - -- [x] localhost-free (:fire:) -- [x] custom protocol for secure mode -- [x] Dynamic ahead of Time Compilation (dAoT) with functional tree-shaking -- [x] functional Address Space Layout Randomization -- [x] OTP salting of function names and messages at runtime -- [x] CSP Injection - -### Utilities - -- [x] Rust-based CLI -- [x] GH Action for creating binaries for all platforms -- [x] VS Code Extension - -## Development - -Tauri is a system composed of a number of moving pieces: - -### Infrastructure - -- Git for code management -- GitHub for project management -- GitHub actions for CI and CD -- Discord for discussions -- Netlify-hosted documentation website -- DigitalOcean Meilisearch instance +### Platforms -### Operating systems +Tauri currently supports development and distribution on the following platforms: -Tauri core can be developed on Mac, Linux and Windows, but you are encouraged to use the latest possible operating systems and build tools for your OS. +| Platform | Versions | +| :----------------- | :-------------------------------------------------------------------------------------------------------------- | +| Windows | 7 and above | +| macOS | 10.15 and above | +| Linux | webkit2gtk 4.0 for Tauri v1 (for example Ubuntu 18.04). webkit2gtk 4.1 for Tauri v2 (for example Ubuntu 22.04). | +| iOS/iPadOS (alpha) | 9 and above | +| Android (alpha) | 7 and above | -### Contributing +## Contributing Before you start working on something, it's best to check if there is an existing issue first. It's also a good idea to stop by the Discord server and confirm with the team if it makes sense or if someone else is already working on it. @@ -133,32 +61,31 @@ 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 of Rust code and at JSDoc in typescript / javascript code. We autocollect these and publish them using Docusaurus v2 and netlify. Here is the hosting repository for the documentation site: https://github.com/tauri-apps/tauri-docs - -### Testing & Linting +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 -Test all the things! We have a number of test suites, but are always looking to improve our coverage: +## Partners -- Rust (`cargo test`) => sourced via inline `#[cfg(test)]` declarations -- Typescript (`jest`) => via spec files -- Smoke Tests (run on merges to latest) -- eslint, clippy + + + + + + +
+ + CrabNebula + +
-### CI/CD - -We recommend you read this article to understand better how we run our pipelines: https://www.jacobbolda.com/setting-up-ci-and-cd-for-tauri/ +For the complete list of sponsors please visit our [website](https://tauri.app#sponsors) and [Open Collective](https://opencollective.com/tauri). ## Organization Tauri aims to be a sustainable collective based on principles that guide [sustainable free and open software communities](https://sfosc.org). To this end it has become a Programme within the [Commons Conservancy](https://commonsconservancy.org/), and you can contribute financially via [Open Collective](https://opencollective.com/tauri). -## Semver - -**tauri** is following [Semantic Versioning 2.0](https://semver.org/). - ## Licenses -Code: (c) 2015 - 2021 - The Tauri Programme within The Commons Conservancy. +Code: (c) 2015 - Present - The Tauri Programme within The Commons Conservancy. MIT or MIT/Apache 2.0 where applicable. diff --git a/core/tauri-build/CHANGELOG.md b/core/tauri-build/CHANGELOG.md index f4957e7623c7..b956bcc281d1 100644 --- a/core/tauri-build/CHANGELOG.md +++ b/core/tauri-build/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## \[2.0.0-alpha.12] + +### Bug Fixes + +- [`a5479712`](https://www.github.com/tauri-apps/tauri/commit/a5479712095c224e2cb147d5c271acbc2fc97e79)([#8168](https://www.github.com/tauri-apps/tauri/pull/8168)) Fixed an issue that caused the resource compiler to not run on Windows when `package.version` was not set in `tauri.conf.json` preventing the app from starting. + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-alpha.11` +- Upgraded to `tauri-codegen@2.0.0-alpha.11` + ## \[2.0.0-alpha.11] ### Enhancements diff --git a/core/tauri-build/Cargo.toml b/core/tauri-build/Cargo.toml index a3725585b68f..e595322711c2 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-alpha.11" +version = "2.0.0-alpha.12" 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-alpha.10", path = "../tauri-codegen", optional = true } -tauri-utils = { version = "2.0.0-alpha.10", path = "../tauri-utils", features = [ "build", "resources" ] } +tauri-codegen = { version = "2.0.0-alpha.11", path = "../tauri-codegen", optional = true } +tauri-utils = { version = "2.0.0-alpha.11", path = "../tauri-utils", features = [ "build", "resources" ] } cargo_toml = "0.17" serde = "1" serde_json = "1" diff --git a/core/tauri-codegen/CHANGELOG.md b/core/tauri-codegen/CHANGELOG.md index 7e1eb6e9a76e..ce98eb166894 100644 --- a/core/tauri-codegen/CHANGELOG.md +++ b/core/tauri-codegen/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## \[2.0.0-alpha.11] + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-alpha.11` + ## \[2.0.0-alpha.10] ### Enhancements diff --git a/core/tauri-codegen/Cargo.toml b/core/tauri-codegen/Cargo.toml index 5df1be4531ed..0c724cd74a15 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-alpha.10" +version = "2.0.0-alpha.11" description = "code generation meant to be consumed inside of `tauri` through `tauri-build` or `tauri-macros`" exclude = [ "CHANGELOG.md", "/target" ] readme = "README.md" @@ -19,7 +19,7 @@ proc-macro2 = "1" quote = "1" serde = { version = "1", features = [ "derive" ] } serde_json = "1" -tauri-utils = { version = "2.0.0-alpha.10", path = "../tauri-utils", features = [ "build" ] } +tauri-utils = { version = "2.0.0-alpha.11", path = "../tauri-utils", features = [ "build" ] } thiserror = "1" walkdir = "2" brotli = { version = "3", optional = true, default-features = false, features = [ "std" ] } diff --git a/core/tauri-config-schema/schema.json b/core/tauri-config-schema/schema.json index b4a96b2847de..573d37924808 100644 --- a/core/tauri-config-schema/schema.json +++ b/core/tauri-config-schema/schema.json @@ -37,6 +37,20 @@ "deb": { "files": {} }, + "dmg": { + "appPosition": { + "x": 180, + "y": 170 + }, + "applicationFolderPosition": { + "x": 480, + "y": 170 + }, + "windowSize": { + "height": 400, + "width": 660 + } + }, "iOS": {}, "icon": [], "identifier": "", @@ -171,6 +185,20 @@ "deb": { "files": {} }, + "dmg": { + "appPosition": { + "x": 180, + "y": 170 + }, + "applicationFolderPosition": { + "x": 480, + "y": 170 + }, + "windowSize": { + "height": 400, + "width": 660 + } + }, "iOS": {}, "icon": [], "identifier": "", @@ -1003,6 +1031,28 @@ } ] }, + "dmg": { + "description": "DMG-specific settings.", + "default": { + "appPosition": { + "x": 180, + "y": 170 + }, + "applicationFolderPosition": { + "x": 480, + "y": 170 + }, + "windowSize": { + "height": 400, + "width": 660 + } + }, + "allOf": [ + { + "$ref": "#/definitions/DmgConfig" + } + ] + }, "macOS": { "description": "Configuration for the macOS bundles.", "default": { @@ -1318,6 +1368,113 @@ }, "additionalProperties": false }, + "DmgConfig": { + "description": "Configuration for Apple Disk Image (.dmg) bundles.\n\nSee more: https://tauri.app/v1/api/config#dmgconfig", + "type": "object", + "properties": { + "background": { + "description": "Image to use as the background in dmg file. Accepted formats: `png`/`jpg`/`gif`.", + "type": [ + "string", + "null" + ] + }, + "windowPosition": { + "description": "Position of volume window on screen.", + "anyOf": [ + { + "$ref": "#/definitions/Position" + }, + { + "type": "null" + } + ] + }, + "windowSize": { + "description": "Size of volume window.", + "default": { + "height": 400, + "width": 660 + }, + "allOf": [ + { + "$ref": "#/definitions/Size" + } + ] + }, + "appPosition": { + "description": "Position of app file on window.", + "default": { + "x": 180, + "y": 170 + }, + "allOf": [ + { + "$ref": "#/definitions/Position" + } + ] + }, + "applicationFolderPosition": { + "description": "Position of application folder on window.", + "default": { + "x": 480, + "y": 170 + }, + "allOf": [ + { + "$ref": "#/definitions/Position" + } + ] + } + }, + "additionalProperties": false + }, + "Position": { + "description": "Position coordinates struct.", + "type": "object", + "required": [ + "x", + "y" + ], + "properties": { + "x": { + "description": "X coordinate.", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "y": { + "description": "Y coordinate.", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "Size": { + "description": "Size of the window.", + "type": "object", + "required": [ + "height", + "width" + ], + "properties": { + "width": { + "description": "Width of the window.", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "height": { + "description": "Height of the window.", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, "MacConfig": { "description": "Configuration for the macOS bundles.\n\nSee more: ", "type": "object", diff --git a/core/tauri-macros/CHANGELOG.md b/core/tauri-macros/CHANGELOG.md index e451005e293d..e9ce1f2f8d61 100644 --- a/core/tauri-macros/CHANGELOG.md +++ b/core/tauri-macros/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## \[2.0.0-alpha.11] + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-alpha.11` +- Upgraded to `tauri-codegen@2.0.0-alpha.11` +- [`b6ed4ecb`](https://www.github.com/tauri-apps/tauri/commit/b6ed4ecb3730c346c973f1b34aa0de1b7d43ac44)([#7634](https://www.github.com/tauri-apps/tauri/pull/7634)) Update to syn v2. + ## \[2.0.0-alpha.10] ### Enhancements diff --git a/core/tauri-macros/Cargo.toml b/core/tauri-macros/Cargo.toml index 2119570bbdfc..f115c4ba4088 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-alpha.10" +version = "2.0.0-alpha.11" description = "Macros for the tauri crate." exclude = [ "CHANGELOG.md", "/target" ] readme = "README.md" @@ -18,10 +18,10 @@ proc-macro = true [dependencies] proc-macro2 = "1" quote = "1" -syn = { version = "1", features = [ "full" ] } +syn = { version = "2", features = [ "full" ] } heck = "0.4" -tauri-codegen = { version = "2.0.0-alpha.10", default-features = false, path = "../tauri-codegen" } -tauri-utils = { version = "2.0.0-alpha.10", path = "../tauri-utils" } +tauri-codegen = { version = "2.0.0-alpha.11", default-features = false, path = "../tauri-codegen" } +tauri-utils = { version = "2.0.0-alpha.11", path = "../tauri-utils" } [features] custom-protocol = [ ] diff --git a/core/tauri-macros/src/command/handler.rs b/core/tauri-macros/src/command/handler.rs index 62a9ace45840..62bf999a6488 100644 --- a/core/tauri-macros/src/command/handler.rs +++ b/core/tauri-macros/src/command/handler.rs @@ -31,7 +31,7 @@ pub struct Handler { impl Parse for Handler { fn parse(input: &ParseBuffer<'_>) -> syn::Result { - let command_defs = input.parse_terminated::(CommandDef::parse)?; + let command_defs = input.parse_terminated(CommandDef::parse, Token![,])?; // parse the command names and wrappers from the passed paths let (commands, wrappers) = command_defs diff --git a/core/tauri-macros/src/command/wrapper.rs b/core/tauri-macros/src/command/wrapper.rs index fab592417eb4..ac56829f3b78 100644 --- a/core/tauri-macros/src/command/wrapper.rs +++ b/core/tauri-macros/src/command/wrapper.rs @@ -10,10 +10,28 @@ use syn::{ ext::IdentExt, parse::{Parse, ParseStream}, parse_macro_input, + punctuated::Punctuated, spanned::Spanned, - FnArg, ItemFn, Lit, Meta, Pat, Token, Visibility, + Expr, ExprLit, FnArg, ItemFn, Lit, Meta, Pat, Token, Visibility, }; +enum WrapperAttributeKind { + Meta(Meta), + Async, +} + +impl Parse for WrapperAttributeKind { + fn parse(input: ParseStream) -> syn::Result { + match input.parse::() { + Ok(m) => Ok(Self::Meta(m)), + Err(e) => match input.parse::() { + Ok(_) => Ok(Self::Async), + Err(_) => Err(e), + }, + } + } +} + struct WrapperAttributes { root: TokenStream2, execution_context: ExecutionContext, @@ -28,12 +46,19 @@ impl Parse for WrapperAttributes { argument_case: ArgumentCase::Camel, }; - loop { - match input.parse::() { - Ok(Meta::List(_)) => {} - Ok(Meta::NameValue(v)) => { + let attrs = Punctuated::::parse_terminated(input)?; + for attr in attrs { + match attr { + WrapperAttributeKind::Meta(Meta::List(_)) => { + return Err(syn::Error::new(input.span(), "unexpected list input")); + } + WrapperAttributeKind::Meta(Meta::NameValue(v)) => { if v.path.is_ident("rename_all") { - if let Lit::Str(s) = v.lit { + if let Expr::Lit(ExprLit { + lit: Lit::Str(s), + attrs: _, + }) = v.value + { wrapper_attributes.argument_case = match s.value().as_str() { "snake_case" => ArgumentCase::Snake, "camelCase" => ArgumentCase::Camel, @@ -46,7 +71,11 @@ impl Parse for WrapperAttributes { }; } } else if v.path.is_ident("root") { - if let Lit::Str(s) = v.lit { + if let Expr::Lit(ExprLit { + lit: Lit::Str(s), + attrs: _, + }) = v.value + { let lit = s.value(); wrapper_attributes.root = if lit == "crate" { @@ -58,22 +87,16 @@ impl Parse for WrapperAttributes { } } } - Ok(Meta::Path(p)) => { - if p.is_ident("async") { - wrapper_attributes.execution_context = ExecutionContext::Async; - } else { - return Err(syn::Error::new(p.span(), "expected `async`")); - } + WrapperAttributeKind::Meta(Meta::Path(_)) => { + return Err(syn::Error::new( + input.span(), + "unexpected input, expected one of `rename_all`, `root`, `async`", + )); } - Err(_e) => { - break; + WrapperAttributeKind::Async => { + wrapper_attributes.execution_context = ExecutionContext::Async; } } - - let lookahead = input.lookahead1(); - if lookahead.peek(Token![,]) { - input.parse::()?; - } } Ok(wrapper_attributes) @@ -101,10 +124,15 @@ struct Invoke { /// Create a new [`Wrapper`] from the function and the generated code parsed from the function. pub fn wrapper(attributes: TokenStream, item: TokenStream) -> TokenStream { + let mut attrs = parse_macro_input!(attributes as WrapperAttributes); let function = parse_macro_input!(item as ItemFn); let wrapper = super::format_command_wrapper(&function.sig.ident); let visibility = &function.vis; + if function.sig.asyncness.is_some() { + attrs.execution_context = ExecutionContext::Async; + } + // macros used with `pub use my_macro;` need to be exported with `#[macro_export]` let maybe_macro_export = match &function.vis { Visibility::Public(_) => quote!(#[macro_export]), @@ -173,28 +201,18 @@ pub fn wrapper(attributes: TokenStream, item: TokenStream) -> TokenStream { } } - // body to the command wrapper or a `compile_error!` of an error occurred while parsing it. - let (body, attributes) = syn::parse::(attributes) - .map(|mut attrs| { - if function.sig.asyncness.is_some() { - attrs.execution_context = ExecutionContext::Async; - } - attrs - }) - .and_then(|attrs| { - let body = match attrs.execution_context { - ExecutionContext::Async => body_async(&function, &invoke, &attrs), - ExecutionContext::Blocking => body_blocking(&function, &invoke, &attrs), - }; - body.map(|b| (b, Some(attrs))) - }) - .unwrap_or_else(|e| (syn::Error::into_compile_error(e), None)); + let body = match attrs.execution_context { + ExecutionContext::Async => { + body_async(&function, &invoke, &attrs).unwrap_or_else(syn::Error::into_compile_error) + } + ExecutionContext::Blocking => { + body_blocking(&function, &invoke, &attrs).unwrap_or_else(syn::Error::into_compile_error) + } + }; let Invoke { message, resolver } = invoke; - let root = attributes - .map(|a| a.root) - .unwrap_or_else(|| quote!(::tauri)); + let root = attrs.root; // Rely on rust 2018 edition to allow importing a macro from a path. quote!( diff --git a/core/tauri-macros/src/lib.rs b/core/tauri-macros/src/lib.rs index 3962b1012d19..990dc6aff0fa 100644 --- a/core/tauri-macros/src/lib.rs +++ b/core/tauri-macros/src/lib.rs @@ -16,6 +16,7 @@ use proc_macro::TokenStream; use syn::{parse_macro_input, DeriveInput}; mod command; +mod menu; mod mobile; mod runtime; @@ -89,3 +90,64 @@ pub fn default_runtime(attributes: TokenStream, input: TokenStream) -> TokenStre let input = parse_macro_input!(input as DeriveInput); runtime::default_runtime(attributes, input).into() } + +/// Accepts a closure-like syntax to call arbitrary code on a menu item +/// after matching against `kind` and retrieving it from `resources_table` using `rid`. +/// +/// You can optionally pass a third parameter to select which item kinds +/// to match against, by providing a `|` separated list of item kinds +/// ```ignore +/// do_menu_item!(|i| i.set_text(text), Check | Submenu); +/// ``` +/// You could also provide a negated list +/// ```ignore +/// do_menu_item!(|i| i.set_text(text), !Check); +/// do_menu_item!(|i| i.set_text(text), !Check | !Submenu); +/// ``` +/// but you can't have mixed negations and positive kinds. +/// ```ignore +/// do_menu_item!(|i| i.set_text(text), !Check | Submeun); +/// ``` +/// +/// #### Example +/// +/// ```ignore +/// let rid = 23; +/// let kind = ItemKind::Check; +/// let resources_table = app.resources_table(); +/// do_menu_item!(|i| i.set_text(text)) +/// ``` +/// which will expand into: +/// ```ignore +/// let rid = 23; +/// let kind = ItemKind::Check; +/// let resources_table = app.resources_table(); +/// match kind { +/// ItemKind::Submenu => { +/// let i = resources_table.get::>(rid)?; +/// i.set_text(text) +/// } +/// ItemKind::MenuItem => { +/// let i = resources_table.get::>(rid)?; +/// i.set_text(text) +/// } +/// ItemKind::Predefined => { +/// let i = resources_table.get::>(rid)?; +/// i.set_text(text) +/// } +/// ItemKind::Check => { +/// let i = resources_table.get::>(rid)?; +/// i.set_text(text) +/// } +/// ItemKind::Icon => { +/// let i = resources_table.get::>(rid)?; +/// i.set_text(text) +/// } +/// _ => unreachable!(), +/// } +/// ``` +#[proc_macro] +pub fn do_menu_item(input: TokenStream) -> TokenStream { + let tokens = parse_macro_input!(input as menu::DoMenuItemInput); + menu::do_menu_item(tokens).into() +} diff --git a/core/tauri-macros/src/menu.rs b/core/tauri-macros/src/menu.rs new file mode 100644 index 000000000000..2e6dc9bd8714 --- /dev/null +++ b/core/tauri-macros/src/menu.rs @@ -0,0 +1,118 @@ +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + +use proc_macro2::{Ident, Span, TokenStream}; +use quote::quote; +use syn::{ + parse::{Parse, ParseStream}, + punctuated::Punctuated, + Expr, Token, +}; + +pub struct DoMenuItemInput { + resources_table: Ident, + rid: Ident, + kind: Ident, + var: Ident, + expr: Expr, + kinds: Vec, +} + +#[derive(Clone)] +struct NegatedIdent(bool, Ident); + +impl Parse for NegatedIdent { + fn parse(input: ParseStream) -> syn::Result { + let t = input.parse::(); + let i: Ident = input.parse()?; + Ok(NegatedIdent(t.is_ok(), i)) + } +} + +impl Parse for DoMenuItemInput { + fn parse(input: ParseStream) -> syn::Result { + let resources_table: Ident = input.parse()?; + let _: Token![,] = input.parse()?; + let rid: Ident = input.parse()?; + let _: Token![,] = input.parse()?; + let kind: Ident = input.parse()?; + let _: Token![,] = input.parse()?; + let _: Token![|] = input.parse()?; + let var: Ident = input.parse()?; + let _: Token![|] = input.parse()?; + let expr: Expr = input.parse()?; + let _: syn::Result = input.parse(); + let kinds = Punctuated::::parse_terminated(input)?; + + Ok(Self { + resources_table, + rid, + kind, + var, + expr, + kinds: kinds.into_iter().collect(), + }) + } +} + +pub fn do_menu_item(input: DoMenuItemInput) -> TokenStream { + let DoMenuItemInput { + rid, + resources_table, + kind, + expr, + var, + mut kinds, + } = input; + + let defaults = vec![ + NegatedIdent(false, Ident::new("Submenu", Span::call_site())), + NegatedIdent(false, Ident::new("MenuItem", Span::call_site())), + NegatedIdent(false, Ident::new("Predefined", Span::call_site())), + NegatedIdent(false, Ident::new("Check", Span::call_site())), + NegatedIdent(false, Ident::new("Icon", Span::call_site())), + ]; + + if kinds.is_empty() { + kinds.extend(defaults.clone()); + } + + let has_negated = kinds.iter().any(|n| n.0); + + if has_negated { + kinds.extend(defaults); + kinds.sort_by(|a, b| a.1.cmp(&b.1)); + kinds.dedup_by(|a, b| a.1 == b.1); + } + + let (kinds, types): (Vec, Vec) = kinds + .into_iter() + .filter_map(|nident| { + if nident.0 { + None + } else { + match nident.1 { + i if i == "MenuItem" => Some((i, Ident::new("MenuItem", Span::call_site()))), + i if i == "Submenu" => Some((i, Ident::new("Submenu", Span::call_site()))), + i if i == "Predefined" => Some((i, Ident::new("PredefinedMenuItem", Span::call_site()))), + i if i == "Check" => Some((i, Ident::new("CheckMenuItem", Span::call_site()))), + i if i == "Icon" => Some((i, Ident::new("IconMenuItem", Span::call_site()))), + _ => None, + } + } + }) + .unzip(); + + quote! { + match #kind { + #( + ItemKind::#kinds => { + let #var = #resources_table.get::<#types>(#rid)?; + #expr + } + )* + _ => unreachable!(), + } + } +} diff --git a/core/tauri-runtime-wry/CHANGELOG.md b/core/tauri-runtime-wry/CHANGELOG.md index dc2c33761e22..9d7834a60091 100644 --- a/core/tauri-runtime-wry/CHANGELOG.md +++ b/core/tauri-runtime-wry/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## \[1.0.0-alpha.6] + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-alpha.11` +- Upgraded to `tauri-runtime@1.0.0-alpha.5` + ## \[1.0.0-alpha.5] ### New Features diff --git a/core/tauri-runtime-wry/Cargo.toml b/core/tauri-runtime-wry/Cargo.toml index 1ba8e78f53cd..35d6bc118cbf 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 = "1.0.0-alpha.5" +version = "1.0.0-alpha.6" description = "Wry bindings to the Tauri runtime" exclude = [ "CHANGELOG.md", "/target" ] readme = "README.md" @@ -13,17 +13,18 @@ edition = { workspace = true } rust-version = { workspace = true } [dependencies] -wry = { version = "0.34.2", default-features = false, features = [ "tao", "file-drop", "protocol" ] } -tauri-runtime = { version = "1.0.0-alpha.4", path = "../tauri-runtime" } -tauri-utils = { version = "2.0.0-alpha.10", path = "../tauri-utils" } +wry = { version = "0.35", default-features = false, features = [ "file-drop", "protocol", "os-webview" ] } +tao = { version = "0.24", default-features = false, features = ["rwh_05"] } +tauri-runtime = { version = "1.0.0-alpha.5", path = "../tauri-runtime" } +tauri-utils = { version = "2.0.0-alpha.11", path = "../tauri-utils" } raw-window-handle = "0.5" http = "0.2" [target."cfg(windows)".dependencies] -webview2-com = "0.27" +webview2-com = "0.28" [target."cfg(windows)".dependencies.windows] - version = "0.51" + version = "0.52" features = [ "Win32_Foundation" ] [target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies] @@ -32,7 +33,7 @@ webkit2gtk = { version = "=2.0", features = [ "v2_38" ] } percent-encoding = "2.1" [target."cfg(any(target_os = \"ios\", target_os = \"macos\"))".dependencies] -cocoa = "0.24" +cocoa = "0.25" [target."cfg(target_os = \"android\")".dependencies] jni = "0.21" diff --git a/core/tauri-runtime-wry/src/lib.rs b/core/tauri-runtime-wry/src/lib.rs index 38b7abdb2752..cbde23909c75 100644 --- a/core/tauri-runtime-wry/src/lib.rs +++ b/core/tauri-runtime-wry/src/lib.rs @@ -24,66 +24,65 @@ use tauri_runtime::{ WindowEventId, }; -#[cfg(windows)] -use webview2_com::FocusChangedEventHandler; -#[cfg(windows)] -use windows::Win32::{Foundation::HWND, System::WinRT::EventRegistrationToken}; #[cfg(target_os = "macos")] -use wry::application::platform::macos::EventLoopWindowTargetExtMacOS; +use tao::platform::macos::EventLoopWindowTargetExtMacOS; #[cfg(target_os = "macos")] -use wry::application::platform::macos::WindowBuilderExtMacOS; +use tao::platform::macos::WindowBuilderExtMacOS; #[cfg(target_os = "linux")] -use wry::application::platform::unix::{WindowBuilderExtUnix, WindowExtUnix}; +use tao::platform::unix::{WindowBuilderExtUnix, WindowExtUnix}; #[cfg(windows)] -use wry::application::platform::windows::{WindowBuilderExtWindows, WindowExtWindows}; +use tao::platform::windows::{WindowBuilderExtWindows, WindowExtWindows}; +#[cfg(windows)] +use webview2_com::FocusChangedEventHandler; +#[cfg(windows)] +use windows::Win32::{Foundation::HWND, System::WinRT::EventRegistrationToken}; #[cfg(windows)] -use wry::webview::WebViewBuilderExtWindows; +use wry::WebViewBuilderExtWindows; +use tao::{ + dpi::{ + LogicalPosition as TaoLogicalPosition, LogicalSize as TaoLogicalSize, + PhysicalPosition as TaoPhysicalPosition, PhysicalSize as TaoPhysicalSize, + Position as TaoPosition, Size as TaoSize, + }, + event::{Event, StartCause, WindowEvent as TaoWindowEvent}, + event_loop::{ + ControlFlow, DeviceEventFilter as TaoDeviceEventFilter, EventLoop, EventLoopBuilder, + EventLoopProxy as TaoEventLoopProxy, EventLoopWindowTarget, + }, + monitor::MonitorHandle, + window::{ + CursorIcon as TaoCursorIcon, Fullscreen, Icon as TaoWindowIcon, + ProgressBarState as TaoProgressBarState, ProgressState as TaoProgressState, Theme as TaoTheme, + UserAttentionType as TaoUserAttentionType, + }, +}; #[cfg(target_os = "macos")] use tauri_utils::TitleBarStyle; use tauri_utils::{ config::WindowConfig, debug_eprintln, ProgressBarState, ProgressBarStatus, Theme, }; -use wry::{ - application::{ - dpi::{ - LogicalPosition as WryLogicalPosition, LogicalSize as WryLogicalSize, - PhysicalPosition as WryPhysicalPosition, PhysicalSize as WryPhysicalSize, - Position as WryPosition, Size as WrySize, - }, - event::{Event, StartCause, WindowEvent as WryWindowEvent}, - event_loop::{ - ControlFlow, DeviceEventFilter as WryDeviceEventFilter, EventLoop, EventLoopBuilder, - EventLoopProxy as WryEventLoopProxy, EventLoopWindowTarget, - }, - monitor::MonitorHandle, - window::{ - CursorIcon as WryCursorIcon, Fullscreen, Icon as WryWindowIcon, - ProgressBarState as WryProgressBarState, ProgressState as WryProgressState, - Theme as WryTheme, UserAttentionType as WryUserAttentionType, - }, - }, - webview::{FileDropEvent as WryFileDropEvent, Url, WebContext, WebView, WebViewBuilder}, -}; +use wry::{FileDropEvent as WryFileDropEvent, Url, WebContext, WebView, WebViewBuilder}; +pub use tao; +pub use tao::window::{Window, WindowBuilder as TaoWindowBuilder, WindowId}; pub use wry; -pub use wry::application::window::{Window, WindowBuilder as WryWindowBuilder, WindowId}; -pub use wry::webview::webview_version; +pub use wry::webview_version; #[cfg(windows)] -use wry::webview::WebviewExtWindows; +use wry::WebViewExtWindows; #[cfg(target_os = "android")] -use wry::webview::{ +use wry::{ prelude::{dispatch, find_class}, - WebViewBuilderExtAndroid, WebviewExtAndroid, + WebViewBuilderExtAndroid, WebViewExtAndroid, }; #[cfg(target_os = "macos")] -use tauri_runtime::ActivationPolicy; -#[cfg(target_os = "macos")] -pub use wry::application::platform::macos::{ - ActivationPolicy as WryActivationPolicy, EventLoopExtMacOS, WindowExtMacOS, +pub use tao::platform::macos::{ + ActivationPolicy as TaoActivationPolicy, EventLoopExtMacOS, WindowExtMacOS, }; +#[cfg(target_os = "macos")] +use tauri_runtime::ActivationPolicy; use std::{ cell::RefCell, @@ -104,8 +103,8 @@ use std::{ }; pub type WebviewId = u32; -type IpcHandler = dyn Fn(&Window, String) + 'static; -type FileDropHandler = dyn Fn(&Window, WryFileDropEvent) -> bool + 'static; +type IpcHandler = dyn Fn(String) + 'static; +type FileDropHandler = dyn Fn(WryFileDropEvent) -> bool + 'static; mod webview; pub use webview::Webview; @@ -172,7 +171,7 @@ pub(crate) fn send_user_message( pub struct Context { pub webview_id_map: WebviewIdStore, main_thread_id: ThreadId, - pub proxy: WryEventLoopProxy>, + pub proxy: TaoEventLoopProxy>, main_thread: DispatcherMainThreadContext, plugins: Arc + Send>>>>, next_window_id: Arc, @@ -275,29 +274,29 @@ impl fmt::Debug for Context { } } -pub struct DeviceEventFilterWrapper(pub WryDeviceEventFilter); +pub struct DeviceEventFilterWrapper(pub TaoDeviceEventFilter); impl From for DeviceEventFilterWrapper { fn from(item: DeviceEventFilter) -> Self { match item { - DeviceEventFilter::Always => Self(WryDeviceEventFilter::Always), - DeviceEventFilter::Never => Self(WryDeviceEventFilter::Never), - DeviceEventFilter::Unfocused => Self(WryDeviceEventFilter::Unfocused), + DeviceEventFilter::Always => Self(TaoDeviceEventFilter::Always), + DeviceEventFilter::Never => Self(TaoDeviceEventFilter::Never), + DeviceEventFilter::Unfocused => Self(TaoDeviceEventFilter::Unfocused), } } } -/// Wrapper around a [`wry::application::window::Icon`] that can be created from an [`Icon`]. -pub struct WryIcon(pub WryWindowIcon); +/// Wrapper around a [`tao::window::Icon`] that can be created from an [`Icon`]. +pub struct TaoIcon(pub TaoWindowIcon); fn icon_err(e: E) -> Error { Error::InvalidIcon(Box::new(e)) } -impl TryFrom for WryIcon { +impl TryFrom for TaoIcon { type Error = Error; fn try_from(icon: Icon) -> std::result::Result { - WryWindowIcon::from_rgba(icon.rgba, icon.width, icon.height) + TaoWindowIcon::from_rgba(icon.rgba, icon.width, icon.height) .map(Self) .map_err(icon_err) } @@ -306,11 +305,11 @@ impl TryFrom for WryIcon { pub struct WindowEventWrapper(pub Option); impl WindowEventWrapper { - fn parse(webview: &Option, event: &WryWindowEvent<'_>) -> Self { + fn parse(webview: &Option, event: &TaoWindowEvent<'_>) -> Self { match event { // resized event from tao doesn't include a reliable size on macOS // because wry replaces the NSView - WryWindowEvent::Resized(_) => { + TaoWindowEvent::Resized(_) => { if let Some(webview) = webview { Self(Some(WindowEvent::Resized( PhysicalSizeWrapper(webview.inner_size()).into(), @@ -324,23 +323,23 @@ impl WindowEventWrapper { } } -pub fn map_theme(theme: &WryTheme) -> Theme { +pub fn map_theme(theme: &TaoTheme) -> Theme { match theme { - WryTheme::Light => Theme::Light, - WryTheme::Dark => Theme::Dark, + TaoTheme::Light => Theme::Light, + TaoTheme::Dark => Theme::Dark, _ => Theme::Light, } } -impl<'a> From<&WryWindowEvent<'a>> for WindowEventWrapper { - fn from(event: &WryWindowEvent<'a>) -> Self { +impl<'a> From<&TaoWindowEvent<'a>> for WindowEventWrapper { + fn from(event: &TaoWindowEvent<'a>) -> Self { let event = match event { - WryWindowEvent::Resized(size) => WindowEvent::Resized(PhysicalSizeWrapper(*size).into()), - WryWindowEvent::Moved(position) => { + TaoWindowEvent::Resized(size) => WindowEvent::Resized(PhysicalSizeWrapper(*size).into()), + TaoWindowEvent::Moved(position) => { WindowEvent::Moved(PhysicalPositionWrapper(*position).into()) } - WryWindowEvent::Destroyed => WindowEvent::Destroyed, - WryWindowEvent::ScaleFactorChanged { + TaoWindowEvent::Destroyed => WindowEvent::Destroyed, + TaoWindowEvent::ScaleFactorChanged { scale_factor, new_inner_size, } => WindowEvent::ScaleFactorChanged { @@ -348,8 +347,8 @@ impl<'a> From<&WryWindowEvent<'a>> for WindowEventWrapper { new_inner_size: PhysicalSizeWrapper(**new_inner_size).into(), }, #[cfg(any(target_os = "linux", target_os = "macos"))] - WryWindowEvent::Focused(focused) => WindowEvent::Focused(*focused), - WryWindowEvent::ThemeChanged(theme) => WindowEvent::ThemeChanged(map_theme(theme)), + TaoWindowEvent::Focused(focused) => WindowEvent::Focused(*focused), + TaoWindowEvent::ThemeChanged(theme) => WindowEvent::ThemeChanged(map_theme(theme)), _ => return Self(None), }; Self(Some(event)) @@ -378,7 +377,7 @@ impl From for Monitor { } } -pub struct PhysicalPositionWrapper(pub WryPhysicalPosition); +pub struct PhysicalPositionWrapper(pub TaoPhysicalPosition); impl From> for PhysicalPosition { fn from(position: PhysicalPositionWrapper) -> Self { @@ -391,25 +390,25 @@ impl From> for PhysicalPosition { impl From> for PhysicalPositionWrapper { fn from(position: PhysicalPosition) -> Self { - Self(WryPhysicalPosition { + Self(TaoPhysicalPosition { x: position.x, y: position.y, }) } } -struct LogicalPositionWrapper(WryLogicalPosition); +struct LogicalPositionWrapper(TaoLogicalPosition); impl From> for LogicalPositionWrapper { fn from(position: LogicalPosition) -> Self { - Self(WryLogicalPosition { + Self(TaoLogicalPosition { x: position.x, y: position.y, }) } } -pub struct PhysicalSizeWrapper(pub WryPhysicalSize); +pub struct PhysicalSizeWrapper(pub TaoPhysicalSize); impl From> for PhysicalSize { fn from(size: PhysicalSizeWrapper) -> Self { @@ -422,127 +421,127 @@ impl From> for PhysicalSize { impl From> for PhysicalSizeWrapper { fn from(size: PhysicalSize) -> Self { - Self(WryPhysicalSize { + Self(TaoPhysicalSize { width: size.width, height: size.height, }) } } -struct LogicalSizeWrapper(WryLogicalSize); +struct LogicalSizeWrapper(TaoLogicalSize); impl From> for LogicalSizeWrapper { fn from(size: LogicalSize) -> Self { - Self(WryLogicalSize { + Self(TaoLogicalSize { width: size.width, height: size.height, }) } } -pub struct SizeWrapper(pub WrySize); +pub struct SizeWrapper(pub TaoSize); impl From for SizeWrapper { fn from(size: Size) -> Self { match size { - Size::Logical(s) => Self(WrySize::Logical(LogicalSizeWrapper::from(s).0)), - Size::Physical(s) => Self(WrySize::Physical(PhysicalSizeWrapper::from(s).0)), + Size::Logical(s) => Self(TaoSize::Logical(LogicalSizeWrapper::from(s).0)), + Size::Physical(s) => Self(TaoSize::Physical(PhysicalSizeWrapper::from(s).0)), } } } -pub struct PositionWrapper(pub WryPosition); +pub struct PositionWrapper(pub TaoPosition); impl From for PositionWrapper { fn from(position: Position) -> Self { match position { - Position::Logical(s) => Self(WryPosition::Logical(LogicalPositionWrapper::from(s).0)), - Position::Physical(s) => Self(WryPosition::Physical(PhysicalPositionWrapper::from(s).0)), + Position::Logical(s) => Self(TaoPosition::Logical(LogicalPositionWrapper::from(s).0)), + Position::Physical(s) => Self(TaoPosition::Physical(PhysicalPositionWrapper::from(s).0)), } } } #[derive(Debug, Clone)] -pub struct UserAttentionTypeWrapper(pub WryUserAttentionType); +pub struct UserAttentionTypeWrapper(pub TaoUserAttentionType); impl From for UserAttentionTypeWrapper { fn from(request_type: UserAttentionType) -> Self { let o = match request_type { - UserAttentionType::Critical => WryUserAttentionType::Critical, - UserAttentionType::Informational => WryUserAttentionType::Informational, + UserAttentionType::Critical => TaoUserAttentionType::Critical, + UserAttentionType::Informational => TaoUserAttentionType::Informational, }; Self(o) } } #[derive(Debug)] -pub struct CursorIconWrapper(pub WryCursorIcon); +pub struct CursorIconWrapper(pub TaoCursorIcon); impl From for CursorIconWrapper { fn from(icon: CursorIcon) -> Self { use CursorIcon::*; let i = match icon { - Default => WryCursorIcon::Default, - Crosshair => WryCursorIcon::Crosshair, - Hand => WryCursorIcon::Hand, - Arrow => WryCursorIcon::Arrow, - Move => WryCursorIcon::Move, - Text => WryCursorIcon::Text, - Wait => WryCursorIcon::Wait, - Help => WryCursorIcon::Help, - Progress => WryCursorIcon::Progress, - NotAllowed => WryCursorIcon::NotAllowed, - ContextMenu => WryCursorIcon::ContextMenu, - Cell => WryCursorIcon::Cell, - VerticalText => WryCursorIcon::VerticalText, - Alias => WryCursorIcon::Alias, - Copy => WryCursorIcon::Copy, - NoDrop => WryCursorIcon::NoDrop, - Grab => WryCursorIcon::Grab, - Grabbing => WryCursorIcon::Grabbing, - AllScroll => WryCursorIcon::AllScroll, - ZoomIn => WryCursorIcon::ZoomIn, - ZoomOut => WryCursorIcon::ZoomOut, - EResize => WryCursorIcon::EResize, - NResize => WryCursorIcon::NResize, - NeResize => WryCursorIcon::NeResize, - NwResize => WryCursorIcon::NwResize, - SResize => WryCursorIcon::SResize, - SeResize => WryCursorIcon::SeResize, - SwResize => WryCursorIcon::SwResize, - WResize => WryCursorIcon::WResize, - EwResize => WryCursorIcon::EwResize, - NsResize => WryCursorIcon::NsResize, - NeswResize => WryCursorIcon::NeswResize, - NwseResize => WryCursorIcon::NwseResize, - ColResize => WryCursorIcon::ColResize, - RowResize => WryCursorIcon::RowResize, - _ => WryCursorIcon::Default, + Default => TaoCursorIcon::Default, + Crosshair => TaoCursorIcon::Crosshair, + Hand => TaoCursorIcon::Hand, + Arrow => TaoCursorIcon::Arrow, + Move => TaoCursorIcon::Move, + Text => TaoCursorIcon::Text, + Wait => TaoCursorIcon::Wait, + Help => TaoCursorIcon::Help, + Progress => TaoCursorIcon::Progress, + NotAllowed => TaoCursorIcon::NotAllowed, + ContextMenu => TaoCursorIcon::ContextMenu, + Cell => TaoCursorIcon::Cell, + VerticalText => TaoCursorIcon::VerticalText, + Alias => TaoCursorIcon::Alias, + Copy => TaoCursorIcon::Copy, + NoDrop => TaoCursorIcon::NoDrop, + Grab => TaoCursorIcon::Grab, + Grabbing => TaoCursorIcon::Grabbing, + AllScroll => TaoCursorIcon::AllScroll, + ZoomIn => TaoCursorIcon::ZoomIn, + ZoomOut => TaoCursorIcon::ZoomOut, + EResize => TaoCursorIcon::EResize, + NResize => TaoCursorIcon::NResize, + NeResize => TaoCursorIcon::NeResize, + NwResize => TaoCursorIcon::NwResize, + SResize => TaoCursorIcon::SResize, + SeResize => TaoCursorIcon::SeResize, + SwResize => TaoCursorIcon::SwResize, + WResize => TaoCursorIcon::WResize, + EwResize => TaoCursorIcon::EwResize, + NsResize => TaoCursorIcon::NsResize, + NeswResize => TaoCursorIcon::NeswResize, + NwseResize => TaoCursorIcon::NwseResize, + ColResize => TaoCursorIcon::ColResize, + RowResize => TaoCursorIcon::RowResize, + _ => TaoCursorIcon::Default, }; Self(i) } } -pub struct ProgressStateWrapper(pub WryProgressState); +pub struct ProgressStateWrapper(pub TaoProgressState); impl From for ProgressStateWrapper { fn from(status: ProgressBarStatus) -> Self { let state = match status { - ProgressBarStatus::None => WryProgressState::None, - ProgressBarStatus::Normal => WryProgressState::Normal, - ProgressBarStatus::Indeterminate => WryProgressState::Indeterminate, - ProgressBarStatus::Paused => WryProgressState::Paused, - ProgressBarStatus::Error => WryProgressState::Error, + ProgressBarStatus::None => TaoProgressState::None, + ProgressBarStatus::Normal => TaoProgressState::Normal, + ProgressBarStatus::Indeterminate => TaoProgressState::Indeterminate, + ProgressBarStatus::Paused => TaoProgressState::Paused, + ProgressBarStatus::Error => TaoProgressState::Error, }; Self(state) } } -pub struct ProgressBarStateWrapper(pub WryProgressBarState); +pub struct ProgressBarStateWrapper(pub TaoProgressBarState); impl From for ProgressBarStateWrapper { fn from(progress_state: ProgressBarState) -> Self { - Self(WryProgressBarState { + Self(TaoProgressBarState { progress: progress_state.progress, state: progress_state .status @@ -554,7 +553,7 @@ impl From for ProgressBarStateWrapper { #[derive(Clone, Default)] pub struct WindowBuilderWrapper { - inner: WryWindowBuilder, + inner: TaoWindowBuilder, center: bool, #[cfg(target_os = "macos")] tabbing_identifier: Option, @@ -659,28 +658,28 @@ impl WindowBuilder for WindowBuilderWrapper { } fn position(mut self, x: f64, y: f64) -> Self { - self.inner = self.inner.with_position(WryLogicalPosition::new(x, y)); + self.inner = self.inner.with_position(TaoLogicalPosition::new(x, y)); self } fn inner_size(mut self, width: f64, height: f64) -> Self { self.inner = self .inner - .with_inner_size(WryLogicalSize::new(width, height)); + .with_inner_size(TaoLogicalSize::new(width, height)); self } fn min_inner_size(mut self, min_width: f64, min_height: f64) -> Self { self.inner = self .inner - .with_min_inner_size(WryLogicalSize::new(min_width, min_height)); + .with_min_inner_size(TaoLogicalSize::new(min_width, min_height)); self } fn max_inner_size(mut self, max_width: f64, max_height: f64) -> Self { self.inner = self .inner - .with_max_inner_size(WryLogicalSize::new(max_width, max_height)); + .with_max_inner_size(TaoLogicalSize::new(max_width, max_height)); self } @@ -834,7 +833,7 @@ impl WindowBuilder for WindowBuilderWrapper { fn icon(mut self, icon: Icon) -> Result { self.inner = self .inner - .with_window_icon(Some(WryIcon::try_from(icon)?.0)); + .with_window_icon(Some(TaoIcon::try_from(icon)?.0)); Ok(self) } @@ -853,8 +852,8 @@ impl WindowBuilder for WindowBuilderWrapper { fn theme(mut self, theme: Option) -> Self { self.inner = self.inner.with_theme(if let Some(t) = theme { match t { - Theme::Dark => Some(WryTheme::Dark), - _ => Some(WryTheme::Light), + Theme::Dark => Some(TaoTheme::Dark), + _ => Some(TaoTheme::Light), } } else { None @@ -902,11 +901,11 @@ impl From for FileDropEvent { match event.0 { WryFileDropEvent::Hovered { paths, position } => FileDropEvent::Hovered { paths: paths.into_iter().map(decode_path).collect(), - position: PhysicalPositionWrapper(position).into(), + position: PhysicalPosition::new(position.0 as f64, position.1 as f64), }, WryFileDropEvent::Dropped { paths, position } => FileDropEvent::Dropped { paths: paths.into_iter().map(decode_path).collect(), - position: PhysicalPositionWrapper(position).into(), + position: PhysicalPosition::new(position.0 as f64, position.1 as f64), }, // default to cancelled // FIXME(maybe): Add `FileDropEvent::Unknown` event? @@ -1038,7 +1037,7 @@ pub enum WindowMessage { SetPosition(Position), SetFullscreen(bool), SetFocus, - SetIcon(WryWindowIcon), + SetIcon(TaoWindowIcon), SetSkipTaskbar(bool), SetCursorGrab(bool), SetCursorVisible(bool), @@ -1077,7 +1076,7 @@ pub enum Message { CreateWebview(WebviewId, CreateWebviewClosure), CreateWindow( WebviewId, - Box (String, WryWindowBuilder) + Send>, + Box (String, TaoWindowBuilder) + Send>, Sender>>, ), UserEvent(T), @@ -1093,7 +1092,7 @@ impl Clone for Message { } } -/// The Tauri [`Dispatch`] for [`Wry`]. +/// The Tauri [`Dispatch`] for [`Tao`]. #[derive(Debug, Clone)] pub struct WryDispatcher { window_id: WebviewId, @@ -1504,7 +1503,7 @@ impl Dispatch for WryDispatcher { &self.context, Message::Window( self.window_id, - WindowMessage::SetIcon(WryIcon::try_from(icon)?.0), + WindowMessage::SetIcon(TaoIcon::try_from(icon)?.0), ), ) } @@ -1585,6 +1584,7 @@ impl Dispatch for WryDispatcher { #[derive(Clone)] enum WindowHandle { Webview { + window: Arc, inner: Rc, context_store: WebContextStore, // the key of the WebContext if it's not shared @@ -1597,6 +1597,7 @@ impl Drop for WindowHandle { fn drop(&mut self) { if let Self::Webview { inner, + window: _, context_store, context_key, } = self @@ -1620,17 +1621,17 @@ impl Deref for WindowHandle { #[inline(always)] fn deref(&self) -> &Window { match self { - Self::Webview { inner, .. } => inner.window(), + Self::Webview { window, .. } => window, Self::Window(w) => w, } } } impl WindowHandle { - fn inner_size(&self) -> WryPhysicalSize { + fn inner_size(&self) -> TaoPhysicalSize { match self { WindowHandle::Window(w) => w.inner_size(), - WindowHandle::Webview { inner, .. } => inner.inner_size(), + WindowHandle::Webview { window, .. } => window.inner_size(), } } } @@ -1651,7 +1652,7 @@ impl fmt::Debug for WindowWrapper { } #[derive(Debug, Clone)] -pub struct EventProxy(WryEventLoopProxy>); +pub struct EventProxy(TaoEventLoopProxy>); #[cfg(target_os = "ios")] #[allow(clippy::non_send_fields_in_send_ty)] @@ -1676,7 +1677,7 @@ pub trait Plugin { &mut self, event: &Event>, event_loop: &EventLoopWindowTarget>, - proxy: &WryEventLoopProxy>, + proxy: &TaoEventLoopProxy>, control_flow: &mut ControlFlow, context: EventLoopIterationContext<'_, T>, web_context: &WebContextStore, @@ -1712,7 +1713,7 @@ unsafe impl Sync for WryHandle {} impl WryHandle { /// Creates a new tao window using a callback, and returns its window id. - pub fn create_tao_window (String, WryWindowBuilder) + Send + 'static>( + pub fn create_tao_window (String, TaoWindowBuilder) + Send + 'static>( &self, f: F, ) -> Result> { @@ -1845,7 +1846,7 @@ impl Wry { ) -> Result { #[cfg(windows)] if let Some(hook) = args.msg_hook { - use wry::application::platform::windows::EventLoopBuilderExtWindows; + use tao::platform::windows::EventLoopBuilderExtWindows; event_loop_builder.with_msg_hook(hook); } Self::init(event_loop_builder.build()) @@ -1897,7 +1898,7 @@ impl Runtime for Wry { target_os = "openbsd" ))] fn new_any_thread(args: RuntimeInitArgs) -> Result { - use wry::application::platform::unix::EventLoopBuilderExtUnix; + use tao::platform::unix::EventLoopBuilderExtUnix; let mut event_loop_builder = EventLoopBuilder::>::with_user_event(); event_loop_builder.with_any_thread(true); Self::init_with_builder(event_loop_builder, args) @@ -1905,7 +1906,7 @@ impl Runtime for Wry { #[cfg(windows)] fn new_any_thread(args: RuntimeInitArgs) -> Result { - use wry::application::platform::windows::EventLoopBuilderExtWindows; + use tao::platform::windows::EventLoopBuilderExtWindows; let mut event_loop_builder = EventLoopBuilder::>::with_user_event(); event_loop_builder.with_any_thread(true); Self::init_with_builder(event_loop_builder, args) @@ -1977,9 +1978,9 @@ impl Runtime for Wry { self .event_loop .set_activation_policy(match activation_policy { - ActivationPolicy::Regular => WryActivationPolicy::Regular, - ActivationPolicy::Accessory => WryActivationPolicy::Accessory, - ActivationPolicy::Prohibited => WryActivationPolicy::Prohibited, + ActivationPolicy::Regular => TaoActivationPolicy::Regular, + ActivationPolicy::Accessory => TaoActivationPolicy::Accessory, + ActivationPolicy::Prohibited => TaoActivationPolicy::Prohibited, _ => unimplemented!(), }); } @@ -2002,7 +2003,7 @@ impl Runtime for Wry { #[cfg(desktop)] fn run_iteration) + 'static>(&mut self, mut callback: F) -> RunIteration { - use wry::application::platform::run_return::EventLoopExtRunReturn; + use tao::platform::run_return::EventLoopExtRunReturn; let windows = self.context.main_thread.windows.clone(); let webview_id_map = self.context.webview_id_map.clone(); let web_context = &self.context.main_thread.web_context; @@ -2144,12 +2145,12 @@ fn handle_user_message( target_os = "openbsd" ))] { - use wry::webview::WebviewExtUnix; + use wry::WebViewExtUnix; f(w.webview()); } #[cfg(target_os = "macos")] { - use wry::webview::WebviewExtMacOS; + use wry::WebViewExtMacOS; f(Webview { webview: w.webview(), manager: w.manager(), @@ -2158,12 +2159,13 @@ fn handle_user_message( } #[cfg(target_os = "ios")] { - use wry::{application::platform::ios::WindowExtIOS, webview::WebviewExtIOS}; + use tao::platform::ios::WindowExtIOS; + use wry::WebViewExtIOS; f(Webview { webview: w.webview(), manager: w.manager(), - view_controller: w.window().ui_view_controller() as cocoa::base::id, + view_controller: window.ui_view_controller() as cocoa::base::id, }); } #[cfg(windows)] @@ -2508,22 +2510,22 @@ fn handle_event_loop( match event { #[cfg(windows)] - WryWindowEvent::ThemeChanged(theme) => { + TaoWindowEvent::ThemeChanged(theme) => { if let Some(window) = windows.borrow().get(&window_id) { if let Some(WindowHandle::Webview { inner, .. }) = &window.inner { let theme = match theme { - WryTheme::Dark => wry::webview::Theme::Dark, - WryTheme::Light => wry::webview::Theme::Light, - _ => wry::webview::Theme::Light, + TaoTheme::Dark => wry::Theme::Dark, + TaoTheme::Light => wry::Theme::Light, + _ => wry::Theme::Light, }; inner.set_theme(theme); } } } - WryWindowEvent::CloseRequested => { + TaoWindowEvent::CloseRequested => { on_close_requested(callback, window_id, windows.clone()); } - WryWindowEvent::Destroyed => { + TaoWindowEvent::Destroyed => { let removed = windows.borrow_mut().remove(&window_id).is_some(); if removed { let is_empty = windows.borrow().is_empty(); @@ -2611,13 +2613,13 @@ fn on_window_close(window_id: WebviewId, windows: Rc) -> Result<()> { +pub fn center_window(window: &Window, window_size: TaoPhysicalSize) -> Result<()> { if let Some(monitor) = window.current_monitor() { let screen_size = monitor.size(); let monitor_pos = monitor.position(); let x = (screen_size.width as i32 - window_size.width as i32) / 2; let y = (screen_size.height as i32 - window_size.height as i32) / 2; - window.set_outer_position(WryPhysicalPosition::new( + window.set_outer_position(TaoPhysicalPosition::new( monitor_pos.x + x, monitor_pos.y + y, )); @@ -2707,8 +2709,26 @@ fn create_webview( handler(raw); } - let mut webview_builder = WebViewBuilder::new(window) - .map_err(|e| Error::CreateWebview(Box::new(e)))? + #[cfg(any( + target_os = "windows", + target_os = "macos", + target_os = "ios", + target_os = "android" + ))] + let builder = WebViewBuilder::new(&window); + #[cfg(not(any( + target_os = "windows", + target_os = "macos", + target_os = "ios", + target_os = "android" + )))] + let builder = { + use wry::WebViewBuilderExtUnix; + let vbox = window.default_vbox().unwrap(); + WebViewBuilder::new_gtk(vbox) + }; + + let mut webview_builder = builder .with_focused(focused) .with_url(&url) .unwrap() // safe to unwrap because we validate the URL beforehand @@ -2732,8 +2752,8 @@ fn create_webview( page_load_handler( url, match event { - wry::webview::PageLoadEvent::Started => tauri_runtime::window::PageLoadEvent::Started, - wry::webview::PageLoadEvent::Finished => tauri_runtime::window::PageLoadEvent::Finished, + wry::PageLoadEvent::Started => tauri_runtime::window::PageLoadEvent::Started, + wry::PageLoadEvent::Finished => tauri_runtime::window::PageLoadEvent::Finished, }, ) }); @@ -2752,9 +2772,9 @@ fn create_webview( if let Some(theme) = window_theme { webview_builder = webview_builder.with_theme(match theme { - WryTheme::Dark => wry::webview::Theme::Dark, - WryTheme::Light => wry::webview::Theme::Light, - _ => wry::webview::Theme::Light, + TaoTheme::Dark => wry::Theme::Dark, + TaoTheme::Light => wry::Theme::Light, + _ => wry::Theme::Light, }); } } @@ -2765,8 +2785,12 @@ fn create_webview( } if let Some(handler) = ipc_handler { - webview_builder = - webview_builder.with_ipc_handler(create_ipc_handler(context.clone(), label.clone(), handler)); + webview_builder = webview_builder.with_ipc_handler(create_ipc_handler( + window_id, + context.clone(), + label.clone(), + handler, + )); } for (scheme, protocol) in uri_scheme_protocols { @@ -2810,11 +2834,11 @@ fn create_webview( }; if webview_attributes.clipboard { - webview_builder.webview.clipboard = true; + webview_builder.attrs.clipboard = true; } if webview_attributes.incognito { - webview_builder.webview.incognito = true; + webview_builder.attrs.incognito = true; } #[cfg(any(debug_assertions, feature = "devtools"))] @@ -2876,6 +2900,7 @@ fn create_webview( Ok(WindowWrapper { label, inner: Some(WindowHandle::Webview { + window: Arc::new(window), inner: Rc::new(webview), context_store: web_context_store.clone(), context_key: if automation_enabled { @@ -2890,12 +2915,12 @@ fn create_webview( /// Create a wry ipc handler from a tauri ipc handler. fn create_ipc_handler( + window_id: u32, context: Context, label: String, handler: WebviewIpcHandler>, ) -> Box { - Box::new(move |window, request| { - let window_id = context.webview_id_map.get(&window.id()).unwrap(); + Box::new(move |request| { handler( DetachedWindow { dispatcher: WryDispatcher { @@ -2911,7 +2936,7 @@ fn create_ipc_handler( /// Create a wry file drop handler. fn create_file_drop_handler(window_event_listeners: WindowEventListeners) -> Box { - Box::new(move |_window, event| { + Box::new(move |event| { let event: FileDropEvent = FileDropEventWrapper(event).into(); let window_event = WindowEvent::FileDrop(event); let listeners_map = window_event_listeners.lock().unwrap(); diff --git a/core/tauri-runtime-wry/src/webview.rs b/core/tauri-runtime-wry/src/webview.rs index 283c32fb5c3b..fc01cdf2a6a6 100644 --- a/core/tauri-runtime-wry/src/webview.rs +++ b/core/tauri-runtime-wry/src/webview.rs @@ -10,9 +10,7 @@ target_os = "openbsd" ))] mod imp { - use std::rc::Rc; - - pub type Webview = Rc; + pub type Webview = webkit2gtk::WebView; } #[cfg(target_os = "macos")] @@ -47,7 +45,7 @@ mod imp { #[cfg(target_os = "android")] mod imp { - use wry::webview::JniHandle; + use wry::JniHandle; pub type Webview = JniHandle; } diff --git a/core/tauri-runtime/CHANGELOG.md b/core/tauri-runtime/CHANGELOG.md index eac633c1f2f1..d7fea7345601 100644 --- a/core/tauri-runtime/CHANGELOG.md +++ b/core/tauri-runtime/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## \[1.0.0-alpha.5] + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-alpha.11` + ## \[1.0.0-alpha.4] ### New Features diff --git a/core/tauri-runtime/Cargo.toml b/core/tauri-runtime/Cargo.toml index 8c30ab13d5f2..1220495473fe 100644 --- a/core/tauri-runtime/Cargo.toml +++ b/core/tauri-runtime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tauri-runtime" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.5" description = "Runtime for Tauri applications" exclude = [ "CHANGELOG.md", "/target" ] readme = "README.md" @@ -29,13 +29,13 @@ targets = [ serde = { version = "1.0", features = [ "derive" ] } serde_json = "1.0" thiserror = "1.0" -tauri-utils = { version = "2.0.0-alpha.10", path = "../tauri-utils" } +tauri-utils = { version = "2.0.0-alpha.11", path = "../tauri-utils" } http = "0.2.4" raw-window-handle = "0.5" url = { version = "2" } [target."cfg(windows)".dependencies.windows] -version = "0.51" +version = "0.52" features = [ "Win32_Foundation" ] [target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies] diff --git a/core/tauri-utils/CHANGELOG.md b/core/tauri-utils/CHANGELOG.md index 51d521f67ee2..0513f1c4bb83 100644 --- a/core/tauri-utils/CHANGELOG.md +++ b/core/tauri-utils/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## \[2.0.0-alpha.11] + +### Breaking Changes + +- [`5e84e92e`](https://www.github.com/tauri-apps/tauri/commit/5e84e92e99376f24b730f8eba002239379b593e1)([#8243](https://www.github.com/tauri-apps/tauri/pull/8243)) Changed `platform::windows_version` to return a `(u32, u32, u32)` instead of `Option<(u32, u32, u32)>` + ## \[2.0.0-alpha.10] ### Enhancements diff --git a/core/tauri-utils/Cargo.toml b/core/tauri-utils/Cargo.toml index 010a183c740f..b9624529561f 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-alpha.10" +version = "2.0.0-alpha.11" description = "Utilities for Tauri" exclude = [ "CHANGELOG.md", "/target" ] readme = "README.md" @@ -43,16 +43,6 @@ log = "0.4.20" [target."cfg(target_os = \"linux\")".dependencies] heck = "0.4" -[target."cfg(windows)".dependencies.windows] -version = "0.51.1" -features = [ - "implement", - "Win32_Foundation", - "Win32_System_Com", - "Win32_System_LibraryLoader", - "Win32_System_SystemInformation" -] - [features] build = [ "proc-macro2", "quote" ] compression = [ "brotli" ] diff --git a/core/tauri-utils/src/config.rs b/core/tauri-utils/src/config.rs index 5d054c9a2f86..34744989ae27 100644 --- a/core/tauri-utils/src/config.rs +++ b/core/tauri-utils/src/config.rs @@ -282,6 +282,81 @@ pub struct DebConfig { pub desktop_template: Option, } +/// Position coordinates struct. +#[derive(Default, Debug, PartialEq, Eq, Clone, Deserialize, Serialize)] +#[cfg_attr(feature = "schema", derive(JsonSchema))] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +pub struct Position { + /// X coordinate. + pub x: u32, + /// Y coordinate. + pub y: u32, +} + +/// Size of the window. +#[derive(Default, Debug, PartialEq, Eq, Clone, Deserialize, Serialize)] +#[cfg_attr(feature = "schema", derive(JsonSchema))] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +pub struct Size { + /// Width of the window. + pub width: u32, + /// Height of the window. + pub height: u32, +} + +/// Configuration for Apple Disk Image (.dmg) bundles. +/// +/// See more: https://tauri.app/v1/api/config#dmgconfig +#[skip_serializing_none] +#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)] +#[cfg_attr(feature = "schema", derive(JsonSchema))] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +pub struct DmgConfig { + /// Image to use as the background in dmg file. Accepted formats: `png`/`jpg`/`gif`. + pub background: Option, + /// Position of volume window on screen. + pub window_position: Option, + /// Size of volume window. + #[serde(default = "dmg_window_size", alias = "window-size")] + pub window_size: Size, + /// Position of app file on window. + #[serde(default = "dmg_app_position", alias = "app-position")] + pub app_position: Position, + /// Position of application folder on window. + #[serde( + default = "dmg_application_folder_position", + alias = "application-folder-position" + )] + pub application_folder_position: Position, +} + +impl Default for DmgConfig { + fn default() -> Self { + Self { + background: None, + window_position: None, + window_size: dmg_window_size(), + app_position: dmg_app_position(), + application_folder_position: dmg_application_folder_position(), + } + } +} + +fn dmg_window_size() -> Size { + Size { + width: 660, + height: 400, + } +} + +fn dmg_app_position() -> Position { + Position { x: 180, y: 170 } +} + +fn dmg_application_folder_position() -> Position { + Position { x: 480, y: 170 } +} + fn de_minimum_system_version<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, @@ -850,6 +925,9 @@ pub struct BundleConfig { /// Configuration for the Debian bundle. #[serde(default)] pub deb: DebConfig, + /// DMG-specific settings. + #[serde(default)] + pub dmg: DmgConfig, /// Configuration for the macOS bundles. #[serde(rename = "macOS", default)] pub macos: MacConfig, @@ -2440,6 +2518,7 @@ mod build { let long_description = quote!(None); let appimage = quote!(Default::default()); let deb = quote!(Default::default()); + let dmg = quote!(Default::default()); let macos = quote!(Default::default()); let external_bin = opt_vec_str_lit(self.external_bin.as_ref()); let windows = &self.windows; @@ -2463,6 +2542,7 @@ mod build { long_description, appimage, deb, + dmg, macos, external_bin, windows, @@ -2771,6 +2851,7 @@ mod test { long_description: None, appimage: Default::default(), deb: Default::default(), + dmg: Default::default(), macos: Default::default(), external_bin: None, windows: Default::default(), diff --git a/core/tauri-utils/src/platform.rs b/core/tauri-utils/src/platform.rs index 248c5aa66cee..6659438b6097 100644 --- a/core/tauri-utils/src/platform.rs +++ b/core/tauri-utils/src/platform.rs @@ -255,87 +255,3 @@ pub fn resource_dir(package_info: &PackageInfo, env: &Env) -> crate::Result bool { - if let Some(v) = windows_version() { - // windows 7 is 6.1 - if v.0 == 6 && v.1 == 1 { - return true; - } - } - false - } - - fn encode_wide(string: impl AsRef) -> Vec { - string.as_ref().encode_wide().chain(once(0)).collect() - } - - /// Helper function to dynamically load function pointer. - /// `library` and `function` must be null-terminated. - pub fn get_function_impl(library: &str, function: &str) -> Option { - let library = encode_wide(library); - assert_eq!(function.chars().last(), Some('\0')); - let function = PCSTR::from_raw(function.as_ptr()); - - // Library names we will use are ASCII so we can use the A version to avoid string conversion. - let module = unsafe { LoadLibraryW(PCWSTR::from_raw(library.as_ptr())) }.unwrap_or_default(); - if module.is_invalid() { - None - } else { - Some(unsafe { GetProcAddress(module, function) }) - } - } - - macro_rules! get_function { - ($lib:expr, $func:ident) => { - get_function_impl(concat!($lib, '\0'), concat!(stringify!($func), '\0')) - .map(|f| unsafe { std::mem::transmute::(f) }) - }; - } - - /// Returns a tuple of (major, minor, buildnumber) for the Windows version. - pub fn windows_version() -> Option<(u32, u32, u32)> { - type RtlGetVersion = unsafe extern "system" fn(*mut OSVERSIONINFOW) -> i32; - let handle = get_function!("ntdll.dll", RtlGetVersion); - if let Some(rtl_get_version) = handle { - unsafe { - let mut vi = OSVERSIONINFOW { - dwOSVersionInfoSize: 0, - dwMajorVersion: 0, - dwMinorVersion: 0, - dwBuildNumber: 0, - dwPlatformId: 0, - szCSDVersion: [0; 128], - }; - - let status = (rtl_get_version)(&mut vi as _); - - if status >= 0 { - Some((vi.dwMajorVersion, vi.dwMinorVersion, vi.dwBuildNumber)) - } else { - None - } - } - } else { - None - } - } -} diff --git a/core/tauri/CHANGELOG.md b/core/tauri/CHANGELOG.md index c82ac1d3a3b0..4f05f8ff7303 100644 --- a/core/tauri/CHANGELOG.md +++ b/core/tauri/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## \[2.0.0-alpha.18] + +### Bug Fixes + +- [`b5f40ae5`](https://www.github.com/tauri-apps/tauri/commit/b5f40ae58dded34b9ddef8e301d0e6e777d135d6)([#8147](https://www.github.com/tauri-apps/tauri/pull/8147)) Fixes global events not reaching to window listeners. + +### Dependencies + +- Upgraded to `tauri-macros@2.0.0-alpha.11` +- Upgraded to `tauri-build@2.0.0-alpha.12` +- Upgraded to `tauri-utils@2.0.0-alpha.11` +- Upgraded to `tauri-runtime@1.0.0-alpha.5` +- Upgraded to `tauri-runtime-wry@1.0.0-alpha.6` + ## \[2.0.0-alpha.17] ### Enhancements diff --git a/core/tauri/Cargo.toml b/core/tauri/Cargo.toml index e6f5abff15a9..35409c41469b 100644 --- a/core/tauri/Cargo.toml +++ b/core/tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tauri" -version = "2.0.0-alpha.17" +version = "2.0.0-alpha.18" description = "Make tiny, secure apps for all desktop platforms with Tauri" exclude = [ "/test", "/.scripts", "CHANGELOG.md", "/target" ] readme = "README.md" @@ -49,11 +49,10 @@ uuid = { version = "1", features = [ "v4" ], optional = true } url = { version = "2.4" } anyhow = "1.0" thiserror = "1.0" -once_cell = "1" -tauri-runtime = { version = "1.0.0-alpha.4", path = "../tauri-runtime" } -tauri-macros = { version = "2.0.0-alpha.10", path = "../tauri-macros" } -tauri-utils = { version = "2.0.0-alpha.10", features = [ "resources" ], path = "../tauri-utils" } -tauri-runtime-wry = { version = "1.0.0-alpha.5", path = "../tauri-runtime-wry", optional = true } +tauri-runtime = { version = "1.0.0-alpha.5", path = "../tauri-runtime" } +tauri-macros = { version = "2.0.0-alpha.11", path = "../tauri-macros" } +tauri-utils = { version = "2.0.0-alpha.11", features = [ "resources" ], path = "../tauri-utils" } +tauri-runtime-wry = { version = "1.0.0-alpha.6", path = "../tauri-runtime-wry", optional = true } getrandom = "0.2" serde_repr = "0.1" state = "0.6" @@ -73,8 +72,8 @@ ico = { version = "0.3.0", optional = true } http-range = { version = "0.1.5", optional = true } [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.10", default-features = false } -tray-icon = { version = "0.10", default-features = false, optional = true } +muda = { version = "0.11", default-features = false, features = [ "serde" ] } +tray-icon = { version = "0.11", default-features = false, features = [ "serde" ], optional = true } [target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies] gtk = { version = "0.18", features = [ "v3_24" ] } @@ -87,11 +86,11 @@ objc = "0.2" window-vibrancy = "0.4" [target."cfg(windows)".dependencies] -webview2-com = "0.27" +webview2-com = "0.28" window-vibrancy = "0.4" [target."cfg(windows)".dependencies.windows] - version = "0.51" + version = "0.52" features = [ "Win32_Foundation" ] [target."cfg(any(target_os = \"android\", target_os = \"ios\"))".dependencies] @@ -109,11 +108,10 @@ swift-rs = "1.0.6" [build-dependencies] heck = "0.4" -once_cell = "1" -tauri-build = { path = "../tauri-build/", version = "2.0.0-alpha.11" } +tauri-build = { path = "../tauri-build/", version = "2.0.0-alpha.12" } [dev-dependencies] -proptest = "1.3.1" +proptest = "1.4.0" quickcheck = "1.0.3" quickcheck_macros = "1.0.0" serde = { version = "1.0", features = [ "derive" ] } diff --git a/core/tauri/build.rs b/core/tauri/build.rs index 669de4270fdf..01a589c86409 100644 --- a/core/tauri/build.rs +++ b/core/tauri/build.rs @@ -4,8 +4,6 @@ use heck::AsShoutySnakeCase; -use once_cell::sync::OnceCell; - use std::env::var_os; use std::fs::read_dir; use std::fs::read_to_string; @@ -13,10 +11,10 @@ use std::fs::write; use std::{ env::var, path::{Path, PathBuf}, - sync::Mutex, + sync::{Mutex, OnceLock}, }; -static CHECKED_FEATURES: OnceCell>> = OnceCell::new(); +static CHECKED_FEATURES: OnceLock>> = OnceLock::new(); // checks if the given Cargo feature is enabled. fn has_feature(feature: &str) -> bool { diff --git a/core/tauri/mobile/ios-api/Sources/Tauri/Channel.swift b/core/tauri/mobile/ios-api/Sources/Tauri/Channel.swift index 798104c7a349..bb448bf9b985 100644 --- a/core/tauri/mobile/ios-api/Sources/Tauri/Channel.swift +++ b/core/tauri/mobile/ios-api/Sources/Tauri/Channel.swift @@ -9,7 +9,7 @@ let channelDataKey = CodingUserInfoKey(rawValue: "sendChannelData")! public class Channel: Decodable { public let id: UInt64 - let handler: (String) -> Void + let handler: (UInt64, String) -> Void public required init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() @@ -30,7 +30,7 @@ public class Channel: Decodable { ) } - guard let handler = decoder.userInfo[channelDataKey] as? (String) -> Void else { + guard let handler = decoder.userInfo[channelDataKey] as? (UInt64, String) -> Void else { throw DecodingError.dataCorruptedError( in: container, debugDescription: "missing userInfo for Channel handler. This is a Tauri issue" @@ -54,12 +54,12 @@ public class Channel: Decodable { } public func send(_ data: JsonValue) { - handler(serialize(data)) + handler(id, serialize(data)) } public func send(_ data: T) throws { let json = try JSONEncoder().encode(data) - handler(String(decoding: json, as: UTF8.self)) + handler(id, String(decoding: json, as: UTF8.self)) } } diff --git a/core/tauri/scripts/bundle.global.js b/core/tauri/scripts/bundle.global.js index 29cf683faf99..3691845503da 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)}var n;function i(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}"function"==typeof SuppressedError&&SuppressedError;class r{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,n.set(this,(()=>{})),this.id=i((e=>{t(this,n,"f").call(this,e)}))}set onmessage(e){!function(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");"a"===i?r.call(e,n):r?r.value=n:t.set(e,n)}(this,n,e,"f")}get onmessage(){return t(this,n,"f")}toJSON(){return`__CHANNEL__:${this.id}`}}n=new WeakMap;class a{constructor(e,t,n){this.plugin=e,this.event=t,this.channelId=n}async unregister(){return l(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}}async function l(e,t={},n){return window.__TAURI_INTERNALS__.invoke(e,t,n)}var s=Object.freeze({__proto__:null,Channel:r,PluginListener:a,addPluginListener:async function(e,t,n){const i=new r;return i.onmessage=n,l(`plugin:${e}|register_listener`,{event:t,handler:i}).then((()=>new a(e,t,i.id)))},convertFileSrc:function(e,t="asset"){return window.__TAURI_INTERNALS__.convertFileSrc(e,t)},invoke:l,transformCallback:i});var o,u=Object.freeze({__proto__:null,getName:async function(){return l("plugin:app|name")},getTauriVersion:async function(){return l("plugin:app|tauri_version")},getVersion:async function(){return l("plugin:app|version")},hide:async function(){return l("plugin:app|app_hide")},show:async function(){return l("plugin:app|app_show")}});async function c(e,t){await l("plugin:event|unlisten",{event:e,eventId:t})}async function p(e,t,n){return l("plugin:event|listen",{event:e,windowLabel:n?.target,handler:i(t)}).then((t=>async()=>c(e,t)))}async function h(e,t,n){return p(e,(n=>{t(n),c(e,n.id).catch((()=>{}))}),n)}async function d(e,t,n){await l("plugin:event|emit",{event:e,windowLabel:n?.target,payload:t})}!function(e){e.WINDOW_RESIZED="tauri://resize",e.WINDOW_MOVED="tauri://move",e.WINDOW_CLOSE_REQUESTED="tauri://close-requested",e.WINDOW_CREATED="tauri://window-created",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_FILE_DROP="tauri://file-drop",e.WINDOW_FILE_DROP_HOVER="tauri://file-drop-hover",e.WINDOW_FILE_DROP_CANCELLED="tauri://file-drop-cancelled",e.MENU="tauri://menu"}(o||(o={}));var y=Object.freeze({__proto__:null,get TauriEvent(){return o},emit:d,listen:p,once:h});class w{constructor(e,t){this.type="Logical",this.width=e,this.height=t}}class _{constructor(e,t){this.type="Physical",this.width=e,this.height=t}toLogical(e){return new w(this.width/e,this.height/e)}}class g{constructor(e,t){this.type="Logical",this.x=e,this.y=t}}class b{constructor(e,t){this.type="Physical",this.x=e,this.y=t}toLogical(e){return new g(this.x/e,this.y/e)}}var f,m,v=Object.freeze({__proto__:null,LogicalPosition:g,LogicalSize:w,PhysicalPosition:b,PhysicalSize:_});!function(e){e[e.Critical=1]="Critical",e[e.Informational=2]="Informational"}(f||(f={}));class D{constructor(e){this._preventDefault=!1,this.event=e.event,this.windowLabel=e.windowLabel,this.id=e.id}preventDefault(){this._preventDefault=!0}isPreventDefault(){return this._preventDefault}}function E(){return new A(window.__TAURI_INTERNALS__.metadata.currentWindow.label,{skip:!0})}function L(){return window.__TAURI_INTERNALS__.metadata.windows.map((e=>new A(e.label,{skip:!0})))}!function(e){e.None="none",e.Normal="normal",e.Indeterminate="indeterminate",e.Paused="paused",e.Error="error"}(m||(m={}));const I=["tauri://created","tauri://error"];class A{constructor(e,t={}){this.label=e,this.listeners=Object.create(null),t?.skip||l("plugin:window|create",{options:{...t,label:e}}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static getByLabel(e){return L().some((t=>t.label===e))?new A(e,{skip:!0}):null}static getCurrent(){return E()}static getAll(){return L()}static async getFocusedWindow(){for(const e of L())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)})):p(e,t,{target:this.label})}async once(e,t){return this._handleTauriEvent(e,t)?Promise.resolve((()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)})):h(e,t,{target:this.label})}async emit(e,t){if(I.includes(e)){for(const n of this.listeners[e]||[])n({event:e,id:-1,windowLabel:this.label,payload:t});return Promise.resolve()}return d(e,t,{target:this.label})}_handleTauriEvent(e,t){return!!I.includes(e)&&(e in this.listeners?this.listeners[e].push(t):this.listeners[e]=[t],!0)}async scaleFactor(){return l("plugin:window|scale_factor",{label:this.label})}async innerPosition(){return l("plugin:window|inner_position",{label:this.label}).then((({x:e,y:t})=>new b(e,t)))}async outerPosition(){return l("plugin:window|outer_position",{label:this.label}).then((({x:e,y:t})=>new b(e,t)))}async innerSize(){return l("plugin:window|inner_size",{label:this.label}).then((({width:e,height:t})=>new _(e,t)))}async outerSize(){return l("plugin:window|outer_size",{label:this.label}).then((({width:e,height:t})=>new _(e,t)))}async isFullscreen(){return l("plugin:window|is_fullscreen",{label:this.label})}async isMinimized(){return l("plugin:window|is_minimized",{label:this.label})}async isMaximized(){return l("plugin:window|is_maximized",{label:this.label})}async isFocused(){return l("plugin:window|is_focused",{label:this.label})}async isDecorated(){return l("plugin:window|is_decorated",{label:this.label})}async isResizable(){return l("plugin:window|is_resizable",{label:this.label})}async isMaximizable(){return l("plugin:window|is_maximizable",{label:this.label})}async isMinimizable(){return l("plugin:window|is_minimizable",{label:this.label})}async isClosable(){return l("plugin:window|is_closable",{label:this.label})}async isVisible(){return l("plugin:window|is_visible",{label:this.label})}async title(){return l("plugin:window|title",{label:this.label})}async theme(){return l("plugin:window|theme",{label:this.label})}async center(){return l("plugin:window|center",{label:this.label})}async requestUserAttention(e){let t=null;return e&&(t=e===f.Critical?{type:"Critical"}:{type:"Informational"}),l("plugin:window|request_user_attention",{label:this.label,value:t})}async setResizable(e){return l("plugin:window|set_resizable",{label:this.label,value:e})}async setMaximizable(e){return l("plugin:window|set_maximizable",{label:this.label,value:e})}async setMinimizable(e){return l("plugin:window|set_minimizable",{label:this.label,value:e})}async setClosable(e){return l("plugin:window|set_closable",{label:this.label,value:e})}async setTitle(e){return l("plugin:window|set_title",{label:this.label,value:e})}async maximize(){return l("plugin:window|maximize",{label:this.label})}async unmaximize(){return l("plugin:window|unmaximize",{label:this.label})}async toggleMaximize(){return l("plugin:window|toggle_maximize",{label:this.label})}async minimize(){return l("plugin:window|minimize",{label:this.label})}async unminimize(){return l("plugin:window|unminimize",{label:this.label})}async show(){return l("plugin:window|show",{label:this.label})}async hide(){return l("plugin:window|hide",{label:this.label})}async close(){return l("plugin:window|close",{label:this.label})}async setDecorations(e){return l("plugin:window|set_decorations",{label:this.label,value:e})}async setShadow(e){return l("plugin:window|set_shadow",{label:this.label,value:e})}async setEffects(e){return l("plugin:window|set_effects",{label:this.label,value:e})}async clearEffects(){return l("plugin:window|set_effects",{label:this.label,value:null})}async setAlwaysOnTop(e){return l("plugin:window|set_always_on_top",{label:this.label,value:e})}async setAlwaysOnBottom(e){return l("plugin:window|set_always_on_bottom",{label:this.label,value:e})}async setContentProtected(e){return l("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");return l("plugin:window|set_size",{label:this.label,value:{type:e.type,data:{width:e.width,height:e.height}}})}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");return l("plugin:window|set_min_size",{label:this.label,value:e?{type:e.type,data:{width:e.width,height:e.height}}:null})}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");return l("plugin:window|set_max_size",{label:this.label,value:e?{type:e.type,data:{width:e.width,height:e.height}}:null})}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");return l("plugin:window|set_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setFullscreen(e){return l("plugin:window|set_fullscreen",{label:this.label,value:e})}async setFocus(){return l("plugin:window|set_focus",{label:this.label})}async setIcon(e){return l("plugin:window|set_icon",{label:this.label,value:"string"==typeof e?e:Array.from(e)})}async setSkipTaskbar(e){return l("plugin:window|set_skip_taskbar",{label:this.label,value:e})}async setCursorGrab(e){return l("plugin:window|set_cursor_grab",{label:this.label,value:e})}async setCursorVisible(e){return l("plugin:window|set_cursor_visible",{label:this.label,value:e})}async setCursorIcon(e){return l("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");return l("plugin:window|set_cursor_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setIgnoreCursorEvents(e){return l("plugin:window|set_ignore_cursor_events",{label:this.label,value:e})}async startDragging(){return l("plugin:window|start_dragging",{label:this.label})}async setProgressBar(e){return l("plugin:window|set_progress_bar",{label:this.label,value:e})}async onResized(e){return this.listen(o.WINDOW_RESIZED,(t=>{t.payload=N(t.payload),e(t)}))}async onMoved(e){return this.listen(o.WINDOW_MOVED,(t=>{t.payload=W(t.payload),e(t)}))}async onCloseRequested(e){return this.listen(o.WINDOW_CLOSE_REQUESTED,(t=>{const n=new D(t);Promise.resolve(e(n)).then((()=>{if(!n.isPreventDefault())return this.close()}))}))}async onFocusChanged(e){const t=await this.listen(o.WINDOW_FOCUS,(t=>{e({...t,payload:!0})})),n=await this.listen(o.WINDOW_BLUR,(t=>{e({...t,payload:!1})}));return()=>{t(),n()}}async onScaleChanged(e){return this.listen(o.WINDOW_SCALE_FACTOR_CHANGED,e)}async onMenuClicked(e){return this.listen(o.MENU,e)}async onFileDropEvent(e){const t=await this.listen(o.WINDOW_FILE_DROP,(t=>{e({...t,payload:{type:"drop",paths:t.payload}})})),n=await this.listen(o.WINDOW_FILE_DROP_HOVER,(t=>{e({...t,payload:{type:"hover",paths:t.payload}})})),i=await this.listen(o.WINDOW_FILE_DROP_CANCELLED,(t=>{e({...t,payload:{type:"cancel"}})}));return()=>{t(),n(),i()}}async onThemeChanged(e){return this.listen(o.WINDOW_THEME_CHANGED,e)}}var z,C;function P(e){return null===e?null:{name:e.name,scaleFactor:e.scaleFactor,position:W(e.position),size:N(e.size)}}function W(e){return new b(e.x,e.y)}function N(e){return new _(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"}(z||(z={})),function(e){e.FollowsWindowActiveState="followsWindowActiveState",e.Active="active",e.Inactive="inactive"}(C||(C={}));var T,O=Object.freeze({__proto__:null,CloseRequestedEvent:D,get Effect(){return z},get EffectState(){return C},LogicalPosition:g,LogicalSize:w,PhysicalPosition:b,PhysicalSize:_,get ProgressBarStatus(){return m},get UserAttentionType(){return f},Window:A,availableMonitors:async function(){return l("plugin:window|available_monitors").then((e=>e.map(P)))},currentMonitor:async function(){return l("plugin:window|current_monitor").then(P)},getAll:L,getCurrent:E,primaryMonitor:async function(){return l("plugin:window|primary_monitor").then(P)}});!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"}(T||(T={}));var R=Object.freeze({__proto__:null,get BaseDirectory(){return T},appCacheDir:async function(){return l("plugin:path|resolve_directory",{directory:T.AppCache})},appConfigDir:async function(){return l("plugin:path|resolve_directory",{directory:T.AppConfig})},appDataDir:async function(){return l("plugin:path|resolve_directory",{directory:T.AppData})},appLocalDataDir:async function(){return l("plugin:path|resolve_directory",{directory:T.AppLocalData})},appLogDir:async function(){return l("plugin:path|resolve_directory",{directory:T.AppLog})},audioDir:async function(){return l("plugin:path|resolve_directory",{directory:T.Audio})},basename:async function(e,t){return l("plugin:path|basename",{path:e,ext:t})},cacheDir:async function(){return l("plugin:path|resolve_directory",{directory:T.Cache})},configDir:async function(){return l("plugin:path|resolve_directory",{directory:T.Config})},dataDir:async function(){return l("plugin:path|resolve_directory",{directory:T.Data})},delimiter:function(){return window.__TAURI_INTERNALS__.plugins.path.delimiter},desktopDir:async function(){return l("plugin:path|resolve_directory",{directory:T.Desktop})},dirname:async function(e){return l("plugin:path|dirname",{path:e})},documentDir:async function(){return l("plugin:path|resolve_directory",{directory:T.Document})},downloadDir:async function(){return l("plugin:path|resolve_directory",{directory:T.Download})},executableDir:async function(){return l("plugin:path|resolve_directory",{directory:T.Executable})},extname:async function(e){return l("plugin:path|extname",{path:e})},fontDir:async function(){return l("plugin:path|resolve_directory",{directory:T.Font})},homeDir:async function(){return l("plugin:path|resolve_directory",{directory:T.Home})},isAbsolute:async function(e){return l("plugin:path|isAbsolute",{path:e})},join:async function(...e){return l("plugin:path|join",{paths:e})},localDataDir:async function(){return l("plugin:path|resolve_directory",{directory:T.LocalData})},normalize:async function(e){return l("plugin:path|normalize",{path:e})},pictureDir:async function(){return l("plugin:path|resolve_directory",{directory:T.Picture})},publicDir:async function(){return l("plugin:path|resolve_directory",{directory:T.Public})},resolve:async function(...e){return l("plugin:path|resolve",{paths:e})},resolveResource:async function(e){return l("plugin:path|resolve_directory",{directory:T.Resource,path:e})},resourceDir:async function(){return l("plugin:path|resolve_directory",{directory:T.Resource})},runtimeDir:async function(){return l("plugin:path|resolve_directory",{directory:T.Runtime})},sep:function(){return window.__TAURI_INTERNALS__.plugins.path.sep},tempDir:async function(e){return l("plugin:path|resolve_directory",{directory:T.Temp})},templateDir:async function(){return l("plugin:path|resolve_directory",{directory:T.Template})},videoDir:async function(){return l("plugin:path|resolve_directory",{directory:T.Video})}});return e.app=u,e.dpi=v,e.event=y,e.path=R,e.primitives=s,e.window=O,e}({});window.__TAURI__=__TAURI_IIFE__; +var __TAURI_IIFE__=function(e){"use strict";function n(e,n,t,i){if("a"===t&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof n?e!==n||!i:!n.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===t?i:"a"===t?i.call(e):i?i.value:n.get(e)}function t(e,n,t,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 n?e!==n||!r:!n.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===i?r.call(e,t):r?r.value=t:n.set(e,t),t}var i;function r(e,n=!1){return window.__TAURI_INTERNALS__.transformCallback(e,n)}"function"==typeof SuppressedError&&SuppressedError;class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),this.id=r((e=>{n(this,i,"f").call(this,e)}))}set onmessage(e){t(this,i,e,"f")}get onmessage(){return n(this,i,"f")}toJSON(){return`__CHANNEL__:${this.id}`}}i=new WeakMap;class s{constructor(e,n,t){this.plugin=e,this.event=n,this.channelId=t}async unregister(){return l(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}}async function l(e,n={},t){return window.__TAURI_INTERNALS__.invoke(e,n,t)}var o=Object.freeze({__proto__:null,Channel:a,PluginListener:s,addPluginListener:async function(e,n,t){const i=new a;return i.onmessage=t,l(`plugin:${e}|register_listener`,{event:n,handler:i}).then((()=>new s(e,n,i.id)))},convertFileSrc:function(e,n="asset"){return window.__TAURI_INTERNALS__.convertFileSrc(e,n)},invoke:l,transformCallback:r});var u,c=Object.freeze({__proto__:null,getName:async function(){return l("plugin:app|name")},getTauriVersion:async function(){return l("plugin:app|tauri_version")},getVersion:async function(){return l("plugin:app|version")},hide:async function(){return l("plugin:app|app_hide")},show:async function(){return l("plugin:app|app_show")}});async function d(e,n){await l("plugin:event|unlisten",{event:e,eventId:n})}async function p(e,n,t){return l("plugin:event|listen",{event:e,windowLabel:t?.target,handler:r(n)}).then((n=>async()=>d(e,n)))}async function h(e,n,t){return p(e,(t=>{n(t),d(e,t.id).catch((()=>{}))}),t)}async function y(e,n,t){await l("plugin:event|emit",{event:e,windowLabel:t?.target,payload:n})}!function(e){e.WINDOW_RESIZED="tauri://resize",e.WINDOW_MOVED="tauri://move",e.WINDOW_CLOSE_REQUESTED="tauri://close-requested",e.WINDOW_CREATED="tauri://window-created",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_FILE_DROP="tauri://file-drop",e.WINDOW_FILE_DROP_HOVER="tauri://file-drop-hover",e.WINDOW_FILE_DROP_CANCELLED="tauri://file-drop-cancelled"}(u||(u={}));var g=Object.freeze({__proto__:null,get TauriEvent(){return u},emit:y,listen:p,once:h});class w{constructor(e,n){this.type="Logical",this.width=e,this.height=n}}class _{constructor(e,n){this.type="Physical",this.width=e,this.height=n}toLogical(e){return new w(this.width/e,this.height/e)}}class m{constructor(e,n){this.type="Logical",this.x=e,this.y=n}}class b{constructor(e,n){this.type="Physical",this.x=e,this.y=n}toLogical(e){return new m(this.x/e,this.y/e)}}var f,v,k=Object.freeze({__proto__:null,LogicalPosition:m,LogicalSize:w,PhysicalPosition:b,PhysicalSize:_});!function(e){e[e.Critical=1]="Critical",e[e.Informational=2]="Informational"}(f||(f={}));class D{constructor(e){this._preventDefault=!1,this.event=e.event,this.windowLabel=e.windowLabel,this.id=e.id}preventDefault(){this._preventDefault=!0}isPreventDefault(){return this._preventDefault}}function A(){return new L(window.__TAURI_INTERNALS__.metadata.currentWindow.label,{skip:!0})}function E(){return window.__TAURI_INTERNALS__.metadata.windows.map((e=>new L(e.label,{skip:!0})))}!function(e){e.None="none",e.Normal="normal",e.Indeterminate="indeterminate",e.Paused="paused",e.Error="error"}(v||(v={}));const I=["tauri://created","tauri://error"];class L{constructor(e,n={}){this.label=e,this.listeners=Object.create(null),n?.skip||l("plugin:window|create",{options:{...n,label:e}}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static getByLabel(e){return E().some((n=>n.label===e))?new L(e,{skip:!0}):null}static getCurrent(){return A()}static getAll(){return E()}static async getFocusedWindow(){for(const e of E())if(await e.isFocused())return e;return null}async listen(e,n){return this._handleTauriEvent(e,n)?Promise.resolve((()=>{const t=this.listeners[e];t.splice(t.indexOf(n),1)})):p(e,n,{target:this.label})}async once(e,n){return this._handleTauriEvent(e,n)?Promise.resolve((()=>{const t=this.listeners[e];t.splice(t.indexOf(n),1)})):h(e,n,{target:this.label})}async emit(e,n){if(I.includes(e)){for(const t of this.listeners[e]||[])t({event:e,id:-1,windowLabel:this.label,payload:n});return Promise.resolve()}return y(e,n,{target:this.label})}_handleTauriEvent(e,n){return!!I.includes(e)&&(e in this.listeners?this.listeners[e].push(n):this.listeners[e]=[n],!0)}async scaleFactor(){return l("plugin:window|scale_factor",{label:this.label})}async innerPosition(){return l("plugin:window|inner_position",{label:this.label}).then((({x:e,y:n})=>new b(e,n)))}async outerPosition(){return l("plugin:window|outer_position",{label:this.label}).then((({x:e,y:n})=>new b(e,n)))}async innerSize(){return l("plugin:window|inner_size",{label:this.label}).then((({width:e,height:n})=>new _(e,n)))}async outerSize(){return l("plugin:window|outer_size",{label:this.label}).then((({width:e,height:n})=>new _(e,n)))}async isFullscreen(){return l("plugin:window|is_fullscreen",{label:this.label})}async isMinimized(){return l("plugin:window|is_minimized",{label:this.label})}async isMaximized(){return l("plugin:window|is_maximized",{label:this.label})}async isFocused(){return l("plugin:window|is_focused",{label:this.label})}async isDecorated(){return l("plugin:window|is_decorated",{label:this.label})}async isResizable(){return l("plugin:window|is_resizable",{label:this.label})}async isMaximizable(){return l("plugin:window|is_maximizable",{label:this.label})}async isMinimizable(){return l("plugin:window|is_minimizable",{label:this.label})}async isClosable(){return l("plugin:window|is_closable",{label:this.label})}async isVisible(){return l("plugin:window|is_visible",{label:this.label})}async title(){return l("plugin:window|title",{label:this.label})}async theme(){return l("plugin:window|theme",{label:this.label})}async center(){return l("plugin:window|center",{label:this.label})}async requestUserAttention(e){let n=null;return e&&(n=e===f.Critical?{type:"Critical"}:{type:"Informational"}),l("plugin:window|request_user_attention",{label:this.label,value:n})}async setResizable(e){return l("plugin:window|set_resizable",{label:this.label,value:e})}async setMaximizable(e){return l("plugin:window|set_maximizable",{label:this.label,value:e})}async setMinimizable(e){return l("plugin:window|set_minimizable",{label:this.label,value:e})}async setClosable(e){return l("plugin:window|set_closable",{label:this.label,value:e})}async setTitle(e){return l("plugin:window|set_title",{label:this.label,value:e})}async maximize(){return l("plugin:window|maximize",{label:this.label})}async unmaximize(){return l("plugin:window|unmaximize",{label:this.label})}async toggleMaximize(){return l("plugin:window|toggle_maximize",{label:this.label})}async minimize(){return l("plugin:window|minimize",{label:this.label})}async unminimize(){return l("plugin:window|unminimize",{label:this.label})}async show(){return l("plugin:window|show",{label:this.label})}async hide(){return l("plugin:window|hide",{label:this.label})}async close(){return l("plugin:window|close",{label:this.label})}async setDecorations(e){return l("plugin:window|set_decorations",{label:this.label,value:e})}async setShadow(e){return l("plugin:window|set_shadow",{label:this.label,value:e})}async setEffects(e){return l("plugin:window|set_effects",{label:this.label,value:e})}async clearEffects(){return l("plugin:window|set_effects",{label:this.label,value:null})}async setAlwaysOnTop(e){return l("plugin:window|set_always_on_top",{label:this.label,value:e})}async setAlwaysOnBottom(e){return l("plugin:window|set_always_on_bottom",{label:this.label,value:e})}async setContentProtected(e){return l("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");return l("plugin:window|set_size",{label:this.label,value:{type:e.type,data:{width:e.width,height:e.height}}})}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");return l("plugin:window|set_min_size",{label:this.label,value:e?{type:e.type,data:{width:e.width,height:e.height}}:null})}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");return l("plugin:window|set_max_size",{label:this.label,value:e?{type:e.type,data:{width:e.width,height:e.height}}:null})}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");return l("plugin:window|set_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setFullscreen(e){return l("plugin:window|set_fullscreen",{label:this.label,value:e})}async setFocus(){return l("plugin:window|set_focus",{label:this.label})}async setIcon(e){return l("plugin:window|set_icon",{label:this.label,value:"string"==typeof e?e:Array.from(e)})}async setSkipTaskbar(e){return l("plugin:window|set_skip_taskbar",{label:this.label,value:e})}async setCursorGrab(e){return l("plugin:window|set_cursor_grab",{label:this.label,value:e})}async setCursorVisible(e){return l("plugin:window|set_cursor_visible",{label:this.label,value:e})}async setCursorIcon(e){return l("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");return l("plugin:window|set_cursor_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setIgnoreCursorEvents(e){return l("plugin:window|set_ignore_cursor_events",{label:this.label,value:e})}async startDragging(){return l("plugin:window|start_dragging",{label:this.label})}async setProgressBar(e){return l("plugin:window|set_progress_bar",{label:this.label,value:e})}async onResized(e){return this.listen(u.WINDOW_RESIZED,(n=>{n.payload=x(n.payload),e(n)}))}async onMoved(e){return this.listen(u.WINDOW_MOVED,(n=>{n.payload=T(n.payload),e(n)}))}async onCloseRequested(e){return this.listen(u.WINDOW_CLOSE_REQUESTED,(n=>{const t=new D(n);Promise.resolve(e(t)).then((()=>{if(!t.isPreventDefault())return this.close()}))}))}async onFocusChanged(e){const n=await this.listen(u.WINDOW_FOCUS,(n=>{e({...n,payload:!0})})),t=await this.listen(u.WINDOW_BLUR,(n=>{e({...n,payload:!1})}));return()=>{n(),t()}}async onScaleChanged(e){return this.listen(u.WINDOW_SCALE_FACTOR_CHANGED,e)}async onFileDropEvent(e){const n=await this.listen(u.WINDOW_FILE_DROP,(n=>{e({...n,payload:{type:"drop",paths:n.payload.paths,position:T(n.payload.position)}})})),t=await this.listen(u.WINDOW_FILE_DROP_HOVER,(n=>{e({...n,payload:{type:"hover",paths:n.payload.paths,position:T(n.payload.position)}})})),i=await this.listen(u.WINDOW_FILE_DROP_CANCELLED,(n=>{e({...n,payload:{type:"cancel"}})}));return()=>{n(),t(),i()}}async onThemeChanged(e){return this.listen(u.WINDOW_THEME_CHANGED,e)}}var S,P;function C(e){return null===e?null:{name:e.name,scaleFactor:e.scaleFactor,position:T(e.position),size:x(e.size)}}function T(e){return new b(e.x,e.y)}function x(e){return new _(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"}(S||(S={})),function(e){e.FollowsWindowActiveState="followsWindowActiveState",e.Active="active",e.Inactive="inactive"}(P||(P={}));var F,z=Object.freeze({__proto__:null,CloseRequestedEvent:D,get Effect(){return S},get EffectState(){return P},LogicalPosition:m,LogicalSize:w,PhysicalPosition:b,PhysicalSize:_,get ProgressBarStatus(){return v},get UserAttentionType(){return f},Window:L,availableMonitors:async function(){return l("plugin:window|available_monitors").then((e=>e.map(C)))},currentMonitor:async function(){return l("plugin:window|current_monitor").then(C)},getAll:E,getCurrent:A,primaryMonitor:async function(){return l("plugin:window|primary_monitor").then(C)}});!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"}(F||(F={}));var R,W=Object.freeze({__proto__:null,get BaseDirectory(){return F},appCacheDir:async function(){return l("plugin:path|resolve_directory",{directory:F.AppCache})},appConfigDir:async function(){return l("plugin:path|resolve_directory",{directory:F.AppConfig})},appDataDir:async function(){return l("plugin:path|resolve_directory",{directory:F.AppData})},appLocalDataDir:async function(){return l("plugin:path|resolve_directory",{directory:F.AppLocalData})},appLogDir:async function(){return l("plugin:path|resolve_directory",{directory:F.AppLog})},audioDir:async function(){return l("plugin:path|resolve_directory",{directory:F.Audio})},basename:async function(e,n){return l("plugin:path|basename",{path:e,ext:n})},cacheDir:async function(){return l("plugin:path|resolve_directory",{directory:F.Cache})},configDir:async function(){return l("plugin:path|resolve_directory",{directory:F.Config})},dataDir:async function(){return l("plugin:path|resolve_directory",{directory:F.Data})},delimiter:function(){return window.__TAURI_INTERNALS__.plugins.path.delimiter},desktopDir:async function(){return l("plugin:path|resolve_directory",{directory:F.Desktop})},dirname:async function(e){return l("plugin:path|dirname",{path:e})},documentDir:async function(){return l("plugin:path|resolve_directory",{directory:F.Document})},downloadDir:async function(){return l("plugin:path|resolve_directory",{directory:F.Download})},executableDir:async function(){return l("plugin:path|resolve_directory",{directory:F.Executable})},extname:async function(e){return l("plugin:path|extname",{path:e})},fontDir:async function(){return l("plugin:path|resolve_directory",{directory:F.Font})},homeDir:async function(){return l("plugin:path|resolve_directory",{directory:F.Home})},isAbsolute:async function(e){return l("plugin:path|isAbsolute",{path:e})},join:async function(...e){return l("plugin:path|join",{paths:e})},localDataDir:async function(){return l("plugin:path|resolve_directory",{directory:F.LocalData})},normalize:async function(e){return l("plugin:path|normalize",{path:e})},pictureDir:async function(){return l("plugin:path|resolve_directory",{directory:F.Picture})},publicDir:async function(){return l("plugin:path|resolve_directory",{directory:F.Public})},resolve:async function(...e){return l("plugin:path|resolve",{paths:e})},resolveResource:async function(e){return l("plugin:path|resolve_directory",{directory:F.Resource,path:e})},resourceDir:async function(){return l("plugin:path|resolve_directory",{directory:F.Resource})},runtimeDir:async function(){return l("plugin:path|resolve_directory",{directory:F.Runtime})},sep:function(){return window.__TAURI_INTERNALS__.plugins.path.sep},tempDir:async function(){return l("plugin:path|resolve_directory",{directory:F.Temp})},templateDir:async function(){return l("plugin:path|resolve_directory",{directory:F.Template})},videoDir:async function(){return l("plugin:path|resolve_directory",{directory:F.Video})}});class N{get rid(){return n(this,R,"f")}constructor(e){R.set(this,void 0),t(this,R,e,"f")}async close(){return l("plugin:resources|close",{rid:this.rid})}}R=new WeakMap;class O extends N{constructor(e,n){super(e),this.id=n}static async new(e){e?.menu&&(e.menu=[e.menu.rid,e.menu.kind]),e?.icon&&(e.icon="string"==typeof e.icon?e.icon:Array.from(e.icon));const n=new a;return e?.action&&(n.onmessage=e.action,delete e.action),l("plugin:tray|new",{options:e??{},handler:n}).then((([e,n])=>new O(e,n)))}async setIcon(e){let n=null;return e&&(n="string"==typeof e?e:Array.from(e)),l("plugin:tray|set_icon",{rid:this.rid,icon:n})}async setMenu(e){return e&&(e=[e.rid,e.kind]),l("plugin:tray|set_menu",{rid:this.rid,menu:e})}async setTooltip(e){return l("plugin:tray|set_tooltip",{rid:this.rid,tooltip:e})}async setTitle(e){return l("plugin:tray|set_title",{rid:this.rid,title:e})}async setVisible(e){return l("plugin:tray|set_visible",{rid:this.rid,visible:e})}async setTempDirPath(e){return l("plugin:tray|set_temp_dir_path",{rid:this.rid,path:e})}async setIconAsTemplate(e){return l("plugin:tray|set_icon_as_template",{rid:this.rid,asTemplate:e})}async setMenuOnLeftClick(e){return l("plugin:tray|set_show_menu_on_left_click",{rid:this.rid,onLeft:e})}}var M,U,B,V=Object.freeze({__proto__:null,TrayIcon:O});function H(e){if("items"in e)e.items=e.items?.map((e=>"rid"in e?e:H(e)));else if("action"in e&&e.action){const n=new a;return n.onmessage=e.action,delete e.action,{...e,handler:n}}return e}async function G(e,n){const t=new a;let i=null;return n&&"object"==typeof n&&("action"in n&&n.action&&(t.onmessage=n.action,delete n.action),"items"in n&&n.items&&(i=n.items.map((e=>"rid"in e?[e.rid,e.kind]:H(e))))),l("plugin:menu|new",{kind:e,options:n?{...n,items:i}:void 0,handler:t})}class j extends N{get id(){return n(this,M,"f")}get kind(){return n(this,U,"f")}constructor(e,n,i){super(e),M.set(this,void 0),U.set(this,void 0),t(this,M,n,"f"),t(this,U,i,"f")}}M=new WeakMap,U=new WeakMap;class q extends j{constructor(e,n){super(e,n,"MenuItem")}static async new(e){return G("MenuItem",e).then((([e,n])=>new q(e,n)))}async text(){return l("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return l("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return l("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return l("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return l("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}}class Q extends j{constructor(e,n){super(e,n,"Check")}static async new(e){return G("Check",e).then((([e,n])=>new Q(e,n)))}async text(){return l("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return l("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return l("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return l("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return l("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async isChecked(){return l("plugin:menu|is_checked",{rid:this.rid})}async setChecked(e){return l("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"}(B||(B={}));class $ extends j{constructor(e,n){super(e,n,"Icon")}static async new(e){return G("Icon",e).then((([e,n])=>new $(e,n)))}async text(){return l("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return l("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return l("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return l("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return l("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async setIcon(e){return l("plugin:menu|set_icon",{rid:this.rid,icon:e})}}class Z extends j{constructor(e,n){super(e,n,"Predefined")}static async new(e){return G("Predefined",e).then((([e,n])=>new Z(e,n)))}async text(){return l("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return l("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}}function J([e,n,t]){switch(t){case"Submenu":return new K(e,n);case"Predefined":return new Z(e,n);case"Check":return new Q(e,n);case"Icon":return new $(e,n);default:return new q(e,n)}}class K extends j{constructor(e,n){super(e,n,"Submenu")}static async new(e){return G("Submenu",e).then((([e,n])=>new K(e,n)))}async text(){return l("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return l("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return l("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return l("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async append(e){return l("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 l("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,n){return l("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:n})}async remove(e){return l("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return l("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(J)}async items(){return l("plugin:menu|items",{rid:this.rid,kind:this.kind}).then((e=>e.map(J)))}async get(e){return l("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then((e=>e?J(e):null))}async popup(e,n){let t=null;return e&&(t={type:e instanceof b?"Physical":"Logical",data:e}),l("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:n?.label??null,at:t})}async setAsWindowsMenuForNSApp(){return l("plugin:menu|set_as_windows_menu_for_nsapp",{rid:this.rid})}async setAsHelpMenuForNSApp(){return l("plugin:menu|set_as_help_menu_for_nsapp",{rid:this.rid})}}function Y([e,n,t]){switch(t){case"Submenu":return new K(e,n);case"Predefined":return new Z(e,n);case"Check":return new Q(e,n);case"Icon":return new $(e,n);default:return new q(e,n)}}class X extends j{constructor(e,n){super(e,n,"Menu")}static async new(e){return G("Menu",e).then((([e,n])=>new X(e,n)))}static async default(){return l("plugin:menu|default").then((([e,n])=>new X(e,n)))}async append(e){return l("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 l("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,n){return l("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:n})}async remove(e){return l("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return l("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(Y)}async items(){return l("plugin:menu|items",{rid:this.rid,kind:this.kind}).then((e=>e.map(Y)))}async get(e){return l("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then((e=>e?Y(e):null))}async popup(e,n){let t=null;return e&&(t={type:e instanceof b?"Physical":"Logical",data:e}),l("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:n?.label??null,at:t})}async setAsAppMenu(){return l("plugin:menu|set_as_app_menu",{rid:this.rid}).then((e=>e?new X(e[0],e[1]):null))}async setAsWindowMenu(e){return l("plugin:menu|set_as_window_menu",{rid:this.rid,window:e?.label??null}).then((e=>e?new X(e[0],e[1]):null))}}var ee=Object.freeze({__proto__:null,CheckMenuItem:Q,IconMenuItem:$,Menu:X,MenuItem:q,get NativeIcon(){return B},PredefinedMenuItem:Z,Submenu:K});return e.app=c,e.core=o,e.dpi=k,e.event=g,e.menu=ee,e.path=W,e.tray=V,e.window=z,e}({});window.__TAURI__=__TAURI_IIFE__; diff --git a/core/tauri/src/app.rs b/core/tauri/src/app.rs index 389858bff9a8..337c8843ae48 100644 --- a/core/tauri/src/app.rs +++ b/core/tauri/src/app.rs @@ -267,7 +267,7 @@ pub struct AppHandle { impl AppHandle { /// Create a new tao window using a callback. The event loop must be running at this point. pub fn create_tao_window< - F: FnOnce() -> (String, tauri_runtime_wry::WryWindowBuilder) + Send + 'static, + F: FnOnce() -> (String, tauri_runtime_wry::TaoWindowBuilder) + Send + 'static, >( &self, f: F, @@ -772,7 +772,8 @@ macro_rules! shared_app_impl { /// **You should always exit the tauri app immediately after this function returns and not use any tauri-related APIs.** pub fn cleanup_before_exit(&self) { #[cfg(all(desktop, feature = "tray-icon"))] - self.manager.tray.icons.lock().unwrap().clear() + self.manager.tray.icons.lock().unwrap().clear(); + self.resources_table().clear(); } } }; @@ -787,6 +788,11 @@ impl App { self.handle.plugin(crate::event::plugin::init())?; self.handle.plugin(crate::window::plugin::init())?; self.handle.plugin(crate::app::plugin::init())?; + self.handle.plugin(crate::resources::plugin::init())?; + #[cfg(desktop)] + self.handle.plugin(crate::menu::plugin::init())?; + #[cfg(all(desktop, feature = "tray-icon"))] + self.handle.plugin(crate::tray::plugin::init())?; Ok(()) } diff --git a/core/tauri/src/async_runtime.rs b/core/tauri/src/async_runtime.rs index 01c7083be479..ebc65954befb 100644 --- a/core/tauri/src/async_runtime.rs +++ b/core/tauri/src/async_runtime.rs @@ -10,7 +10,6 @@ //! one you need isn't here, you could use types in [`tokio`] directly. //! For custom command handlers, it's recommended to use a plain `async fn` command. -use once_cell::sync::OnceCell; pub use tokio::{ runtime::{Handle as TokioHandle, Runtime as TokioRuntime}, sync::{ @@ -23,10 +22,11 @@ pub use tokio::{ use std::{ future::Future, pin::Pin, + sync::OnceLock, task::{Context, Poll}, }; -static RUNTIME: OnceCell = OnceCell::new(); +static RUNTIME: OnceLock = OnceLock::new(); struct GlobalRuntime { runtime: Option, diff --git a/core/tauri/src/error.rs b/core/tauri/src/error.rs index c8d8645dd48d..9af98ec35f82 100644 --- a/core/tauri/src/error.rs +++ b/core/tauri/src/error.rs @@ -130,6 +130,12 @@ pub enum Error { /// window not found. #[error("window not found")] WindowNotFound, + /// The resource id is invalid. + #[error("The resource id {0} is invalid.")] + BadResourceId(crate::resources::ResourceId), + /// The anyhow crate error. + #[error(transparent)] + Anyhow(#[from] anyhow::Error), } /// `Result` diff --git a/core/tauri/src/ipc/channel.rs b/core/tauri/src/ipc/channel.rs index 923770711062..d650371961d2 100644 --- a/core/tauri/src/ipc/channel.rs +++ b/core/tauri/src/ipc/channel.rs @@ -4,13 +4,14 @@ use std::{ collections::HashMap, + str::FromStr, sync::{ atomic::{AtomicU32, Ordering}, Arc, Mutex, }, }; -use serde::{Deserialize, Serialize, Serializer}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use crate::{ command, @@ -50,6 +51,62 @@ impl Serialize for Channel { } } +/// The ID of a channel that was defined on the JavaScript layer. +/// +/// Useful when expecting [`Channel`] as part of a JSON object instead of a top-level command argument. +/// +/// # Examples +/// +/// ```rust +/// use tauri::{ipc::JavaScriptChannelId, Runtime, Window}; +/// +/// #[derive(serde::Deserialize)] +/// #[serde(rename_all = "camelCase")] +/// struct Button { +/// label: String, +/// on_click: JavaScriptChannelId, +/// } +/// +/// #[tauri::command] +/// fn add_button(window: Window, button: Button) { +/// let channel = button.on_click.channel_on(window); +/// channel.send("clicked").unwrap(); +/// } +/// ``` +pub struct JavaScriptChannelId(CallbackFn); + +impl FromStr for JavaScriptChannelId { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + s.split_once(IPC_PAYLOAD_PREFIX) + .ok_or("invalid channel string") + .and_then(|(_prefix, id)| id.parse().map_err(|_| "invalid channel ID")) + .map(|id| Self(CallbackFn(id))) + } +} + +impl JavaScriptChannelId { + /// Gets a [`Channel`] for this channel ID on the given [`Window`]. + pub fn channel_on(&self, window: Window) -> Channel { + Channel::from_callback_fn(window, self.0) + } +} + +impl<'de> Deserialize<'de> for JavaScriptChannelId { + fn deserialize(deserializer: D) -> std::result::Result + where + D: Deserializer<'de>, + { + let value: String = Deserialize::deserialize(deserializer)?; + Self::from_str(&value).map_err(|_| { + serde::de::Error::custom(format!( + "invalid channel value `{value}`, expected a string in the `{IPC_PAYLOAD_PREFIX}ID` format" + )) + }) + } +} + impl Channel { /// Creates a new channel with the given message handler. pub fn new crate::Result<()> + Send + Sync + 'static>( @@ -58,7 +115,7 @@ impl Channel { Self::new_with_id(CHANNEL_COUNTER.fetch_add(1, Ordering::Relaxed), on_message) } - pub(crate) fn new_with_id crate::Result<()> + Send + Sync + 'static>( + fn new_with_id crate::Result<()> + Send + Sync + 'static>( id: u32, on_message: F, ) -> Self { @@ -74,7 +131,7 @@ impl Channel { channel } - pub(crate) fn from_ipc(window: Window, callback: CallbackFn) -> Self { + pub(crate) fn from_callback_fn(window: Window, callback: CallbackFn) -> Self { Channel::new_with_id(callback.0, move |body| { let data_id = CHANNEL_DATA_COUNTER.fetch_add(1, Ordering::Relaxed); window @@ -90,23 +147,12 @@ impl Channel { }) } - pub(crate) fn load_from_ipc( - window: Window, - value: impl AsRef, - ) -> Option { - value - .as_ref() - .split_once(IPC_PAYLOAD_PREFIX) - .and_then(|(_prefix, id)| id.parse().ok()) - .map(|callback_id| Self::from_ipc(window, CallbackFn(callback_id))) - } - /// The channel identifier. pub fn id(&self) -> u32 { self.id } - /// Sends the given data through the channel. + /// Sends the given data through the channel. pub fn send(&self, data: T) -> crate::Result<()> { let body = data.body()?; (self.on_message)(body) @@ -121,11 +167,13 @@ impl<'de, R: Runtime> CommandArg<'de, R> for Channel { let window = command.message.window(); let value: String = Deserialize::deserialize(command).map_err(|e| crate::Error::InvalidArgs(name, arg, e))?; - Channel::load_from_ipc(window, &value).ok_or_else(|| { - InvokeError::from_anyhow(anyhow::anyhow!( + JavaScriptChannelId::from_str(&value) + .map(|id| id.channel_on(window)) + .map_err(|_| { + InvokeError::from_anyhow(anyhow::anyhow!( "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 02bf1f6a83c6..eb37295f959e 100644 --- a/core/tauri/src/ipc/mod.rs +++ b/core/tauri/src/ipc/mod.rs @@ -25,7 +25,7 @@ pub(crate) mod channel; pub(crate) mod format_callback; pub(crate) mod protocol; -pub use channel::Channel; +pub use channel::{Channel, JavaScriptChannelId}; /// A closure that is run every time Tauri receives a message it doesn't explicitly handle. pub type InvokeHandler = dyn Fn(Invoke) -> bool + Send + Sync + 'static; diff --git a/core/tauri/src/ipc/protocol.rs b/core/tauri/src/ipc/protocol.rs index 61bf68ee9b4b..14e5780dec39 100644 --- a/core/tauri/src/ipc/protocol.rs +++ b/core/tauri/src/ipc/protocol.rs @@ -245,7 +245,7 @@ fn handle_ipc_message(message: String, manager: &AppManager, labe if !(cfg!(target_os = "macos") || cfg!(target_os = "ios")) && matches!(v, JsonValue::Object(_) | JsonValue::Array(_)) { - let _ = Channel::from_ipc(window, callback).send(v); + let _ = Channel::from_callback_fn(window, callback).send(v); } else { responder_eval( &window, @@ -262,7 +262,8 @@ fn handle_ipc_message(message: String, manager: &AppManager, labe error, ); } else { - let _ = Channel::from_ipc(window, callback).send(InvokeBody::Raw(v.clone())); + let _ = + Channel::from_callback_fn(window, callback).send(InvokeBody::Raw(v.clone())); } } InvokeResponse::Err(e) => responder_eval( diff --git a/core/tauri/src/lib.rs b/core/tauri/src/lib.rs index 61b3338aac1c..59a197ff93dd 100644 --- a/core/tauri/src/lib.rs +++ b/core/tauri/src/lib.rs @@ -65,6 +65,7 @@ pub use cocoa; #[doc(hidden)] pub use embed_plist; pub use error::{Error, Result}; +pub use resources::{Resource, ResourceId, ResourceTable}; #[cfg(target_os = "ios")] #[doc(hidden)] pub use swift_rs; @@ -82,6 +83,7 @@ mod manager; mod pattern; pub mod plugin; pub(crate) mod protocol; +mod resources; mod vibrancy; pub mod window; use tauri_runtime as runtime; @@ -114,15 +116,30 @@ pub type Wry = tauri_runtime_wry::Wry; #[macro_export] macro_rules! android_binding { ($domain:ident, $package:ident, $main: ident, $wry: path) => { - ::tauri::wry::android_binding!($domain, $package, $main, $wry); - ::tauri::wry::application::android_fn!( + use $wry::{ + android_setup, + prelude::{JClass, JNIEnv, JString}, + }; + + ::tauri::wry::android_binding!($domain, $package, $wry); + + ::tauri::tao::android_binding!( + $domain, + $package, + WryActivity, + android_setup, + $main, + ::tauri::tao + ); + + ::tauri::tao::platform::android::prelude::android_fn!( app_tauri, plugin, PluginManager, handlePluginResponse, [i32, JString, JString], ); - ::tauri::wry::application::android_fn!( + ::tauri::tao::platform::android::prelude::android_fn!( app_tauri, plugin, PluginManager, @@ -155,15 +172,16 @@ macro_rules! android_binding { pub use plugin::mobile::{handle_android_plugin_response, send_channel_data}; #[cfg(all(feature = "wry", target_os = "android"))] #[doc(hidden)] -pub use tauri_runtime_wry::wry; +pub use tauri_runtime_wry::{tao, wry}; /// A task to run on the main thread. pub type SyncTask = Box; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use std::{ collections::HashMap, fmt::{self, Debug}, + sync::MutexGuard, }; #[cfg(feature = "wry")] @@ -808,6 +826,11 @@ pub trait Manager: sealed::ManagerBase { self.manager().state.try_get() } + /// Get a reference to the resources table. + fn resources_table(&self) -> MutexGuard<'_, ResourceTable> { + self.manager().resources_table() + } + /// Gets the managed [`Env`]. fn env(&self) -> Env { self.state::().inner().clone() @@ -864,10 +887,9 @@ pub mod test; #[cfg(test)] mod tests { use cargo_toml::Manifest; - use once_cell::sync::OnceCell; - use std::{env::var, fs::read_to_string, path::PathBuf}; + use std::{env::var, fs::read_to_string, path::PathBuf, sync::OnceLock}; - static MANIFEST: OnceCell = OnceCell::new(); + static MANIFEST: OnceLock = OnceLock::new(); const CHECKED_FEATURES: &str = include_str!(concat!(env!("OUT_DIR"), "/checked_features")); fn get_manifest() -> &'static Manifest { @@ -903,6 +925,40 @@ mod tests { } } +#[derive(Deserialize)] +#[serde(untagged)] +pub(crate) enum IconDto { + #[cfg(any(feature = "icon-png", feature = "icon-ico"))] + File(std::path::PathBuf), + #[cfg(any(feature = "icon-png", feature = "icon-ico"))] + Raw(Vec), + Rgba { + rgba: Vec, + width: u32, + height: u32, + }, +} + +impl From for Icon { + fn from(icon: IconDto) -> Self { + match icon { + #[cfg(any(feature = "icon-png", feature = "icon-ico"))] + IconDto::File(path) => Self::File(path), + #[cfg(any(feature = "icon-png", feature = "icon-ico"))] + IconDto::Raw(raw) => Self::Raw(raw), + IconDto::Rgba { + rgba, + width, + height, + } => Self::Rgba { + rgba, + width, + height, + }, + } + } +} + #[allow(unused)] macro_rules! run_main_thread { ($self:ident, $ex:expr) => {{ diff --git a/core/tauri/src/manager/mod.rs b/core/tauri/src/manager/mod.rs index 92ed1b072494..a30fee400838 100644 --- a/core/tauri/src/manager/mod.rs +++ b/core/tauri/src/manager/mod.rs @@ -6,7 +6,7 @@ use std::{ borrow::Cow, collections::HashMap, fmt, - sync::{Arc, Mutex}, + sync::{Arc, Mutex, MutexGuard}, }; use serde::Serialize; @@ -20,7 +20,6 @@ use tauri_utils::{ html::{SCRIPT_NONCE_TOKEN, STYLE_NONCE_TOKEN}, }; -use crate::event::EmitArgs; use crate::{ app::{AppHandle, GlobalWindowEventListener, OnPageLoad}, event::{assert_event_name_is_valid, Event, EventId, Listeners}, @@ -33,6 +32,7 @@ use crate::{ }, Context, Pattern, Runtime, StateManager, Window, }; +use crate::{event::EmitArgs, resources::ResourceTable}; #[cfg(desktop)] mod menu; @@ -196,6 +196,9 @@ pub struct AppManager { /// Application pattern. pub pattern: Arc, + + /// Application Resources Table + pub(crate) resources_table: Arc>, } impl fmt::Debug for AppManager { @@ -274,6 +277,7 @@ impl AppManager { app_icon: context.app_icon, package_info: context.package_info, pattern: Arc::new(context.pattern), + resources_table: Arc::default(), } } @@ -535,6 +539,14 @@ impl AppManager { pub fn windows(&self) -> HashMap> { self.window.windows_lock().clone() } + + /// Resources table managed by the application. + pub(crate) fn resources_table(&self) -> MutexGuard<'_, ResourceTable> { + self + .resources_table + .lock() + .expect("poisoned window manager") + } } #[cfg(desktop)] diff --git a/core/tauri/src/menu/builders/mod.rs b/core/tauri/src/menu/builders/mod.rs index f86baee6b27b..172efc8c012f 100644 --- a/core/tauri/src/menu/builders/mod.rs +++ b/core/tauri/src/menu/builders/mod.rs @@ -6,8 +6,6 @@ //! A module containting menu builder types -pub use muda::AboutMetadataBuilder; - mod menu; pub use menu::MenuBuilder; mod normal; diff --git a/core/tauri/src/menu/check.rs b/core/tauri/src/menu/check.rs index 28d90990f2e4..97fa639601e3 100644 --- a/core/tauri/src/menu/check.rs +++ b/core/tauri/src/menu/check.rs @@ -2,9 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -use crate::{menu::MenuId, run_main_thread, AppHandle, Manager, Runtime}; +use crate::{menu::MenuId, resources::Resource, run_main_thread, AppHandle, Manager, Runtime}; -/// A menu item inside a [`Menu`] or [`Submenu`] and contains only text. +/// A menu item inside a [`Menu`] or [`Submenu`] +/// and usually contains a text and a check mark or a similar toggle +/// that corresponds to a checked and unchecked states. /// /// [`Menu`]: super::Menu /// [`Submenu`]: super::Submenu @@ -31,7 +33,7 @@ unsafe impl Sync for CheckMenuItem {} unsafe impl Send for CheckMenuItem {} impl super::sealed::IsMenuItemBase for CheckMenuItem { - fn inner(&self) -> &dyn muda::IsMenuItem { + fn inner_muda(&self) -> &dyn muda::IsMenuItem { &self.inner } } @@ -146,3 +148,5 @@ impl CheckMenuItem { run_main_thread!(self, |self_: Self| self_.inner.set_checked(checked)) } } + +impl Resource for CheckMenuItem {} diff --git a/core/tauri/src/menu/icon.rs b/core/tauri/src/menu/icon.rs index bdaab0203865..e2dd547e095c 100644 --- a/core/tauri/src/menu/icon.rs +++ b/core/tauri/src/menu/icon.rs @@ -3,9 +3,12 @@ // SPDX-License-Identifier: MIT use super::NativeIcon; -use crate::{menu::MenuId, run_main_thread, AppHandle, Icon, Manager, Runtime}; +use crate::{ + menu::MenuId, resources::Resource, run_main_thread, AppHandle, Icon, Manager, Runtime, +}; -/// A menu item inside a [`Menu`] or [`Submenu`] and contains only text. +/// A menu item inside a [`Menu`] or [`Submenu`] +/// and usually contains an icon and a text. /// /// [`Menu`]: super::Menu /// [`Submenu`]: super::Submenu @@ -32,7 +35,7 @@ unsafe impl Sync for IconMenuItem {} unsafe impl Send for IconMenuItem {} impl super::sealed::IsMenuItemBase for IconMenuItem { - fn inner(&self) -> &dyn muda::IsMenuItem { + fn inner_muda(&self) -> &dyn muda::IsMenuItem { &self.inner } } @@ -214,3 +217,5 @@ impl IconMenuItem { Ok(()) } } + +impl Resource for IconMenuItem {} diff --git a/core/tauri/src/menu/menu.rs b/core/tauri/src/menu/menu.rs index a29ecb3300d9..35638c7acd95 100644 --- a/core/tauri/src/menu/menu.rs +++ b/core/tauri/src/menu/menu.rs @@ -4,6 +4,7 @@ use super::sealed::ContextMenuBase; use super::{AboutMetadata, IsMenuItem, MenuItemKind, PredefinedMenuItem, Submenu}; +use crate::resources::Resource; use crate::Window; use crate::{run_main_thread, AppHandle, Manager, Position, Runtime}; use muda::ContextMenu; @@ -75,7 +76,9 @@ impl ContextMenuBase for Menu { target_os = "openbsd" ))] if let Ok(w) = window.gtk_window() { - self_.inner().show_context_menu_for_gtk_window(&w, position); + self_ + .inner() + .show_context_menu_for_gtk_window(w.as_ref(), position); } #[cfg(windows)] @@ -84,12 +87,12 @@ impl ContextMenuBase for Menu { } }) } - fn inner(&self) -> &dyn muda::ContextMenu { + fn inner_context(&self) -> &dyn muda::ContextMenu { &self.inner } - fn inner_owned(&self) -> Box { - Box::new(self.clone().inner) + fn inner_context_owned(&self) -> Box { + Box::new(self.inner.clone()) } } @@ -261,8 +264,10 @@ impl Menu { /// [`Submenu`]: super::Submenu pub fn append(&self, item: &dyn IsMenuItem) -> crate::Result<()> { let kind = item.kind(); - run_main_thread!(self, |self_: Self| self_.inner.append(kind.inner().inner()))? - .map_err(Into::into) + run_main_thread!(self, |self_: Self| self_ + .inner + .append(kind.inner().inner_muda()))? + .map_err(Into::into) } /// Add menu items to the end of this menu. It calls [`Menu::append`] in a loop internally. @@ -291,7 +296,7 @@ impl Menu { let kind = item.kind(); run_main_thread!(self, |self_: Self| self_ .inner - .prepend(kind.inner().inner()))? + .prepend(kind.inner().inner_muda()))? .map_err(Into::into) } @@ -317,7 +322,7 @@ impl Menu { let kind = item.kind(); run_main_thread!(self, |self_: Self| self_ .inner - .insert(kind.inner().inner(), position))? + .insert(kind.inner().inner_muda(), position))? .map_err(Into::into) } @@ -339,8 +344,18 @@ impl Menu { /// Remove a menu item from this menu. pub fn remove(&self, item: &dyn IsMenuItem) -> crate::Result<()> { let kind = item.kind(); - run_main_thread!(self, |self_: Self| self_.inner.remove(kind.inner().inner()))? - .map_err(Into::into) + run_main_thread!(self, |self_: Self| self_ + .inner + .remove(kind.inner().inner_muda()))? + .map_err(Into::into) + } + + /// Remove the menu item at the specified position from this menu and returns it. + pub fn remove_at(&self, position: usize) -> crate::Result>> { + run_main_thread!(self, |self_: Self| self_ + .inner + .remove_at(position) + .map(|i| MenuItemKind::from_muda(self_.app_handle.clone(), i))) } /// Retrieves the menu item matching the given identifier. @@ -358,40 +373,27 @@ impl Menu { /// Returns a list of menu items that has been added to this menu. pub fn items(&self) -> crate::Result>> { - let handle = self.app_handle.clone(); run_main_thread!(self, |self_: Self| self_ .inner .items() .into_iter() - .map(|i| match i { - muda::MenuItemKind::MenuItem(i) => super::MenuItemKind::MenuItem(super::MenuItem { - id: i.id().clone(), - inner: i, - app_handle: handle.clone(), - }), - muda::MenuItemKind::Submenu(i) => super::MenuItemKind::Submenu(super::Submenu { - id: i.id().clone(), - inner: i, - app_handle: handle.clone(), - }), - muda::MenuItemKind::Predefined(i) => { - super::MenuItemKind::Predefined(super::PredefinedMenuItem { - id: i.id().clone(), - inner: i, - app_handle: handle.clone(), - }) - } - muda::MenuItemKind::Check(i) => super::MenuItemKind::Check(super::CheckMenuItem { - id: i.id().clone(), - inner: i, - app_handle: handle.clone(), - }), - muda::MenuItemKind::Icon(i) => super::MenuItemKind::Icon(super::IconMenuItem { - id: i.id().clone(), - inner: i, - app_handle: handle.clone(), - }), - }) + .map(|i| MenuItemKind::from_muda(self_.app_handle.clone(), i)) .collect::>()) } + + /// Set this menu as the application menu. + /// + /// This is an alias for [`AppHandle::set_menu`]. + pub fn set_as_app_menu(&self) -> crate::Result>> { + self.app_handle.set_menu(self.clone()) + } + + /// Set this menu as the window menu. + /// + /// This is an alias for [`Window::set_menu`]. + pub fn set_as_window_menu(&self, window: &Window) -> crate::Result>> { + window.set_menu(self.clone()) + } } + +impl Resource for Menu {} diff --git a/core/tauri/src/menu/mod.rs b/core/tauri/src/menu/mod.rs index eaba4b52e730..53488caf1652 100644 --- a/core/tauri/src/menu/mod.rs +++ b/core/tauri/src/menu/mod.rs @@ -4,7 +4,7 @@ #![cfg(desktop)] -//! Menu types and utility functions +//! Menu types and utilities. // TODO(muda-migration): figure out js events @@ -14,6 +14,7 @@ mod icon; #[allow(clippy::module_inception)] mod menu; mod normal; +pub(crate) mod plugin; mod predefined; mod submenu; pub use builders::*; @@ -22,13 +23,14 @@ pub use icon::IconMenuItem; pub use menu::{Menu, HELP_SUBMENU_ID, WINDOW_SUBMENU_ID}; pub use normal::MenuItem; pub use predefined::PredefinedMenuItem; +use serde::{Deserialize, Serialize}; pub use submenu::Submenu; -use crate::{Icon, Runtime}; +use crate::{AppHandle, Icon, Runtime}; pub use muda::MenuId; /// Describes a menu event emitted when a menu item is activated -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize)] pub struct MenuEvent { /// Id of the menu item which triggered this event pub id: MenuId, @@ -233,7 +235,7 @@ impl From for muda::AboutMetadata { /// ## Platform-specific: /// /// - **Windows / Linux**: Unsupported. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)] pub enum NativeIcon { /// An add item template image. Add, @@ -449,6 +451,36 @@ impl MenuItemKind { } } + pub(crate) fn from_muda(app_handle: AppHandle, i: muda::MenuItemKind) -> Self { + match i { + muda::MenuItemKind::MenuItem(i) => Self::MenuItem(MenuItem { + id: i.id().clone(), + inner: i, + app_handle, + }), + muda::MenuItemKind::Submenu(i) => Self::Submenu(Submenu { + id: i.id().clone(), + inner: i, + app_handle, + }), + muda::MenuItemKind::Predefined(i) => Self::Predefined(PredefinedMenuItem { + id: i.id().clone(), + inner: i, + app_handle, + }), + muda::MenuItemKind::Check(i) => Self::Check(CheckMenuItem { + id: i.id().clone(), + inner: i, + app_handle, + }), + muda::MenuItemKind::Icon(i) => Self::Icon(IconMenuItem { + id: i.id().clone(), + inner: i, + app_handle, + }), + } + } + /// Casts this item to a [`MenuItem`], and returns `None` if it wasn't. pub fn as_menuitem(&self) -> Option<&MenuItem> { match self { @@ -543,8 +575,8 @@ impl Clone for MenuItemKind { } impl sealed::IsMenuItemBase for MenuItemKind { - fn inner(&self) -> &dyn muda::IsMenuItem { - self.inner().inner() + fn inner_muda(&self) -> &dyn muda::IsMenuItem { + self.inner().inner_muda() } } @@ -593,12 +625,12 @@ pub trait ContextMenu: sealed::ContextMenuBase + Send + Sync { pub(crate) mod sealed { pub trait IsMenuItemBase { - fn inner(&self) -> &dyn muda::IsMenuItem; + fn inner_muda(&self) -> &dyn muda::IsMenuItem; } pub trait ContextMenuBase { - fn inner(&self) -> &dyn muda::ContextMenu; - fn inner_owned(&self) -> Box; + fn inner_context(&self) -> &dyn muda::ContextMenu; + fn inner_context_owned(&self) -> Box; fn popup_inner>( &self, window: crate::Window, diff --git a/core/tauri/src/menu/normal.rs b/core/tauri/src/menu/normal.rs index a7eeb3e6b71e..cd1f64bca0a8 100644 --- a/core/tauri/src/menu/normal.rs +++ b/core/tauri/src/menu/normal.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -use crate::{menu::MenuId, run_main_thread, AppHandle, Manager, Runtime}; +use crate::{menu::MenuId, resources::Resource, run_main_thread, AppHandle, Manager, Runtime}; /// A menu item inside a [`Menu`] or [`Submenu`] and contains only text. /// @@ -31,7 +31,7 @@ unsafe impl Sync for MenuItem {} unsafe impl Send for MenuItem {} impl super::sealed::IsMenuItemBase for MenuItem { - fn inner(&self) -> &dyn muda::IsMenuItem { + fn inner_muda(&self) -> &dyn muda::IsMenuItem { &self.inner } } @@ -132,3 +132,5 @@ impl MenuItem { run_main_thread!(self, |self_: Self| self_.inner.set_accelerator(accel))?.map_err(Into::into) } } + +impl Resource for MenuItem {} diff --git a/core/tauri/src/menu/plugin.rs b/core/tauri/src/menu/plugin.rs new file mode 100644 index 000000000000..ad10c4d9e6e6 --- /dev/null +++ b/core/tauri/src/menu/plugin.rs @@ -0,0 +1,876 @@ +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + +use std::{ + collections::HashMap, + sync::{Mutex, MutexGuard}, +}; + +use serde::{Deserialize, Serialize}; +use tauri_runtime::window::dpi::Position; + +use super::{sealed::ContextMenuBase, *}; +use crate::{ + command, + ipc::{channel::JavaScriptChannelId, Channel}, + plugin::{Builder, TauriPlugin}, + resources::{ResourceId, ResourceTable}, + AppHandle, IconDto, Manager, RunEvent, Runtime, State, Window, +}; +use tauri_macros::do_menu_item; + +#[derive(Deserialize, Serialize)] +pub(crate) enum ItemKind { + Menu, + MenuItem, + Predefined, + Submenu, + Check, + Icon, +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub(crate) struct AboutMetadata { + pub name: Option, + pub version: Option, + pub short_version: Option, + pub authors: Option>, + pub comments: Option, + pub copyright: Option, + pub license: Option, + pub website: Option, + pub website_label: Option, + pub credits: Option, + pub icon: Option, +} + +impl From for super::AboutMetadata { + fn from(value: AboutMetadata) -> Self { + Self { + name: value.name, + version: value.version, + short_version: value.short_version, + authors: value.authors, + comments: value.comments, + copyright: value.copyright, + license: value.license, + website: value.website, + website_label: value.website_label, + credits: value.credits, + icon: value.icon.map(Into::into), + } + } +} + +#[allow(clippy::large_enum_variant)] +#[derive(Deserialize)] +enum Predefined { + Separator, + Copy, + Cut, + Paste, + SelectAll, + Undo, + Redo, + Minimize, + Maximize, + Fullscreen, + Hide, + HideOthers, + ShowAll, + CloseWindow, + Quit, + About(Option), + Services, +} + +#[derive(Deserialize)] +struct SubmenuPayload { + id: Option, + text: String, + enabled: Option, + items: Vec, +} + +impl SubmenuPayload { + pub fn create_item( + self, + window: &Window, + resources_table: &MutexGuard<'_, ResourceTable>, + ) -> crate::Result> { + let mut builder = if let Some(id) = self.id { + SubmenuBuilder::with_id(window, id, self.text) + } else { + SubmenuBuilder::new(window, self.text) + }; + if let Some(enabled) = self.enabled { + builder = builder.enabled(enabled); + } + for item in self.items { + builder = item.with_item(window, resources_table, |i| Ok(builder.item(i)))?; + } + + builder.build() + } +} + +#[derive(Deserialize)] +struct CheckMenuItemPayload { + handler: Option, + id: Option, + text: String, + checked: bool, + enabled: Option, + accelerator: Option, +} + +impl CheckMenuItemPayload { + pub fn create_item(self, window: &Window) -> CheckMenuItem { + let mut builder = if let Some(id) = self.id { + CheckMenuItemBuilder::with_id(id, self.text) + } else { + CheckMenuItemBuilder::new(self.text) + }; + if let Some(accelerator) = self.accelerator { + builder = builder.accelerator(accelerator); + } + if let Some(enabled) = self.enabled { + builder = builder.enabled(enabled); + } + + let item = builder.checked(self.checked).build(window); + + if let Some(handler) = self.handler { + let handler = handler.channel_on(window.clone()); + window + .state::() + .0 + .lock() + .unwrap() + .insert(item.id().clone(), handler); + } + + item + } +} + +#[derive(Deserialize)] +#[serde(untagged)] +enum Icon { + Native(NativeIcon), + Icon(IconDto), +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct IconMenuItemPayload { + handler: Option, + id: Option, + text: String, + icon: Icon, + enabled: Option, + accelerator: Option, +} + +impl IconMenuItemPayload { + pub fn create_item(self, window: &Window) -> IconMenuItem { + let mut builder = if let Some(id) = self.id { + IconMenuItemBuilder::with_id(id, self.text) + } else { + IconMenuItemBuilder::new(self.text) + }; + if let Some(accelerator) = self.accelerator { + builder = builder.accelerator(accelerator); + } + if let Some(enabled) = self.enabled { + builder = builder.enabled(enabled); + } + builder = match self.icon { + Icon::Native(native_icon) => builder.native_icon(native_icon), + Icon::Icon(icon) => builder.icon(icon.into()), + }; + + let item = builder.build(window); + + if let Some(handler) = self.handler { + let handler = handler.channel_on(window.clone()); + window + .state::() + .0 + .lock() + .unwrap() + .insert(item.id().clone(), handler); + } + + item + } +} + +#[derive(Deserialize)] +struct MenuItemPayload { + handler: Option, + id: Option, + text: String, + enabled: Option, + accelerator: Option, +} + +impl MenuItemPayload { + pub fn create_item(self, window: &Window) -> MenuItem { + let mut builder = if let Some(id) = self.id { + MenuItemBuilder::with_id(id, self.text) + } else { + MenuItemBuilder::new(self.text) + }; + if let Some(accelerator) = self.accelerator { + builder = builder.accelerator(accelerator); + } + if let Some(enabled) = self.enabled { + builder = builder.enabled(enabled); + } + + let item = builder.build(window); + + if let Some(handler) = self.handler { + let handler = handler.channel_on(window.clone()); + window + .state::() + .0 + .lock() + .unwrap() + .insert(item.id().clone(), handler); + } + + item + } +} + +#[derive(Deserialize)] +struct PredefinedMenuItemPayload { + item: Predefined, + text: Option, +} + +impl PredefinedMenuItemPayload { + pub fn create_item(self, window: &Window) -> PredefinedMenuItem { + match self.item { + Predefined::Separator => PredefinedMenuItem::separator(window), + Predefined::Copy => PredefinedMenuItem::copy(window, self.text.as_deref()), + Predefined::Cut => PredefinedMenuItem::cut(window, self.text.as_deref()), + Predefined::Paste => PredefinedMenuItem::paste(window, self.text.as_deref()), + Predefined::SelectAll => PredefinedMenuItem::select_all(window, self.text.as_deref()), + Predefined::Undo => PredefinedMenuItem::undo(window, self.text.as_deref()), + Predefined::Redo => PredefinedMenuItem::redo(window, self.text.as_deref()), + Predefined::Minimize => PredefinedMenuItem::minimize(window, self.text.as_deref()), + Predefined::Maximize => PredefinedMenuItem::maximize(window, self.text.as_deref()), + Predefined::Fullscreen => PredefinedMenuItem::fullscreen(window, self.text.as_deref()), + Predefined::Hide => PredefinedMenuItem::hide(window, self.text.as_deref()), + Predefined::HideOthers => PredefinedMenuItem::hide_others(window, self.text.as_deref()), + Predefined::ShowAll => PredefinedMenuItem::show_all(window, self.text.as_deref()), + Predefined::CloseWindow => PredefinedMenuItem::close_window(window, self.text.as_deref()), + Predefined::Quit => PredefinedMenuItem::quit(window, self.text.as_deref()), + Predefined::About(metadata) => { + PredefinedMenuItem::about(window, self.text.as_deref(), metadata.map(Into::into)) + } + Predefined::Services => PredefinedMenuItem::services(window, self.text.as_deref()), + } + } +} + +#[derive(Deserialize)] +#[serde(untagged)] +enum MenuItemPayloadKind { + ExistingItem((ResourceId, ItemKind)), + Predefined(PredefinedMenuItemPayload), + Check(CheckMenuItemPayload), + Submenu(SubmenuPayload), + Icon(IconMenuItemPayload), + MenuItem(MenuItemPayload), +} + +impl MenuItemPayloadKind { + pub fn with_item) -> crate::Result>( + self, + window: &Window, + resources_table: &MutexGuard<'_, ResourceTable>, + f: F, + ) -> crate::Result { + match self { + Self::ExistingItem((rid, kind)) => { + do_menu_item!(resources_table, rid, kind, |i| f(&*i)) + } + Self::Submenu(i) => f(&i.create_item(window, resources_table)?), + Self::Predefined(i) => f(&i.create_item(window)), + Self::Check(i) => f(&i.create_item(window)), + Self::Icon(i) => f(&i.create_item(window)), + Self::MenuItem(i) => f(&i.create_item(window)), + } + } +} + +#[derive(Deserialize, Default)] +#[serde(rename_all = "camelCase")] +struct NewOptions { + id: Option, + text: Option, + enabled: Option, + checked: Option, + accelerator: Option, + #[serde(rename = "item")] + predefined_item: Option, + icon: Option, + items: Option>, +} + +#[command(root = "crate")] +fn new( + app: AppHandle, + window: Window, + kind: ItemKind, + options: Option, + channels: State<'_, MenuChannels>, + handler: Channel, +) -> crate::Result<(ResourceId, MenuId)> { + let options = options.unwrap_or_default(); + let mut resources_table = app.resources_table(); + + let (rid, id) = match kind { + ItemKind::Menu => { + let mut builder = MenuBuilder::new(&app); + if let Some(id) = options.id { + builder = builder.id(id); + } + if let Some(items) = options.items { + for item in items { + builder = item.with_item(&window, &resources_table, |i| Ok(builder.item(i)))?; + } + } + let menu = builder.build()?; + let id = menu.id().clone(); + let rid = resources_table.add(menu); + + (rid, id) + } + + ItemKind::Submenu => { + let submenu = SubmenuPayload { + id: options.id, + text: options.text.unwrap_or_default(), + enabled: options.enabled, + items: options.items.unwrap_or_default(), + } + .create_item(&window, &resources_table)?; + let id = submenu.id().clone(); + let rid = resources_table.add(submenu); + + (rid, id) + } + + ItemKind::MenuItem => { + let item = MenuItemPayload { + // handler managed in this function instead + handler: None, + id: options.id, + text: options.text.unwrap_or_default(), + enabled: options.enabled, + accelerator: options.accelerator, + } + .create_item(&window); + let id = item.id().clone(); + let rid = resources_table.add(item); + (rid, id) + } + + ItemKind::Predefined => { + let item = PredefinedMenuItemPayload { + item: options.predefined_item.unwrap(), + text: options.text, + } + .create_item(&window); + let id = item.id().clone(); + let rid = resources_table.add(item); + (rid, id) + } + + ItemKind::Check => { + let item = CheckMenuItemPayload { + // handler managed in this function instead + handler: None, + id: options.id, + text: options.text.unwrap_or_default(), + checked: options.checked.unwrap_or_default(), + enabled: options.enabled, + accelerator: options.accelerator, + } + .create_item(&window); + let id = item.id().clone(); + let rid = resources_table.add(item); + (rid, id) + } + + ItemKind::Icon => { + let item = IconMenuItemPayload { + // handler managed in this function instead + handler: None, + id: options.id, + text: options.text.unwrap_or_default(), + icon: options.icon.unwrap_or(Icon::Native(NativeIcon::User)), + enabled: options.enabled, + accelerator: options.accelerator, + } + .create_item(&window); + let id = item.id().clone(); + let rid = resources_table.add(item); + (rid, id) + } + }; + + channels.0.lock().unwrap().insert(id.clone(), handler); + + Ok((rid, id)) +} + +#[command(root = "crate")] +fn append( + window: Window, + rid: ResourceId, + kind: ItemKind, + items: Vec, +) -> crate::Result<()> { + let resources_table = window.resources_table(); + match kind { + ItemKind::Menu => { + let menu = resources_table.get::>(rid)?; + for item in items { + item.with_item(&window, &resources_table, |i| menu.append(i))?; + } + } + ItemKind::Submenu => { + let submenu = resources_table.get::>(rid)?; + for item in items { + item.with_item(&window, &resources_table, |i| submenu.append(i))?; + } + } + _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), + }; + + Ok(()) +} + +#[command(root = "crate")] +fn prepend( + window: Window, + rid: ResourceId, + kind: ItemKind, + items: Vec, +) -> crate::Result<()> { + let resources_table = window.resources_table(); + match kind { + ItemKind::Menu => { + let menu = resources_table.get::>(rid)?; + for item in items { + item.with_item(&window, &resources_table, |i| menu.prepend(i))?; + } + } + ItemKind::Submenu => { + let submenu = resources_table.get::>(rid)?; + for item in items { + item.with_item(&window, &resources_table, |i| submenu.prepend(i))?; + } + } + _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), + }; + + Ok(()) +} + +#[command(root = "crate")] +fn insert( + window: Window, + rid: ResourceId, + kind: ItemKind, + items: Vec, + mut position: usize, +) -> crate::Result<()> { + let resources_table = window.resources_table(); + match kind { + ItemKind::Menu => { + let menu = resources_table.get::>(rid)?; + for item in items { + item.with_item(&window, &resources_table, |i| menu.insert(i, position))?; + position += 1 + } + } + ItemKind::Submenu => { + let submenu = resources_table.get::>(rid)?; + for item in items { + item.with_item(&window, &resources_table, |i| submenu.insert(i, position))?; + position += 1 + } + } + _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), + }; + + Ok(()) +} + +#[command(root = "crate")] +fn remove( + app: AppHandle, + menu_rid: ResourceId, + menu_kind: ItemKind, + item: (ResourceId, ItemKind), +) -> crate::Result<()> { + let resources_table = app.resources_table(); + let (rid, kind) = item; + match menu_kind { + ItemKind::Menu => { + let menu = resources_table.get::>(menu_rid)?; + do_menu_item!(resources_table, rid, kind, |i| menu.remove(&*i))?; + } + ItemKind::Submenu => { + let submenu = resources_table.get::>(menu_rid)?; + do_menu_item!(resources_table, rid, kind, |i| submenu.remove(&*i))?; + } + _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), + }; + + Ok(()) +} + +macro_rules! make_item_resource { + ($resources_table:ident, $item:ident) => {{ + let id = $item.id().clone(); + let (rid, kind) = match $item { + MenuItemKind::MenuItem(i) => ($resources_table.add(i), ItemKind::MenuItem), + MenuItemKind::Submenu(i) => ($resources_table.add(i), ItemKind::Submenu), + MenuItemKind::Predefined(i) => ($resources_table.add(i), ItemKind::Predefined), + MenuItemKind::Check(i) => ($resources_table.add(i), ItemKind::Check), + MenuItemKind::Icon(i) => ($resources_table.add(i), ItemKind::Icon), + }; + (rid, id, kind) + }}; +} + +#[command(root = "crate")] +fn remove_at( + app: AppHandle, + rid: ResourceId, + kind: ItemKind, + position: usize, +) -> crate::Result> { + let mut resources_table = app.resources_table(); + match kind { + ItemKind::Menu => { + let menu = resources_table.get::>(rid)?; + if let Some(item) = menu.remove_at(position)? { + return Ok(Some(make_item_resource!(resources_table, item))); + } + } + ItemKind::Submenu => { + let submenu = resources_table.get::>(rid)?; + if let Some(item) = submenu.remove_at(position)? { + return Ok(Some(make_item_resource!(resources_table, item))); + } + } + _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), + }; + + Ok(None) +} + +#[command(root = "crate")] +fn items( + app: AppHandle, + rid: ResourceId, + kind: ItemKind, +) -> crate::Result> { + let mut resources_table = app.resources_table(); + let items = match kind { + ItemKind::Menu => resources_table.get::>(rid)?.items()?, + ItemKind::Submenu => resources_table.get::>(rid)?.items()?, + _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), + }; + + Ok( + items + .into_iter() + .map(|i| make_item_resource!(resources_table, i)) + .collect::>(), + ) +} + +#[command(root = "crate")] +fn get( + app: AppHandle, + rid: ResourceId, + kind: ItemKind, + id: MenuId, +) -> crate::Result> { + let mut resources_table = app.resources_table(); + match kind { + ItemKind::Menu => { + let menu = resources_table.get::>(rid)?; + if let Some(item) = menu.get(&id) { + return Ok(Some(make_item_resource!(resources_table, item))); + } + } + ItemKind::Submenu => { + let submenu = resources_table.get::>(rid)?; + if let Some(item) = submenu.get(&id) { + return Ok(Some(make_item_resource!(resources_table, item))); + } + } + _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), + }; + + Ok(None) +} + +#[command(root = "crate")] +async fn popup( + app: AppHandle, + current_window: Window, + rid: ResourceId, + kind: ItemKind, + window: Option, + at: Option, +) -> crate::Result<()> { + let window = window + .map(|w| app.get_window(&w)) + .unwrap_or(Some(current_window)); + + if let Some(window) = window { + let resources_table = app.resources_table(); + match kind { + ItemKind::Menu => { + let menu = resources_table.get::>(rid)?; + menu.popup_inner(window, at)?; + } + ItemKind::Submenu => { + let submenu = resources_table.get::>(rid)?; + submenu.popup_inner(window, at)?; + } + _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), + }; + } + + Ok(()) +} + +#[command(root = "crate")] +fn default(app: AppHandle) -> crate::Result<(ResourceId, MenuId)> { + let mut resources_table = app.resources_table(); + let menu = Menu::default(&app)?; + let id = menu.id().clone(); + let rid = resources_table.add(menu); + Ok((rid, id)) +} + +#[command(root = "crate")] +async fn set_as_app_menu( + app: AppHandle, + rid: ResourceId, +) -> crate::Result> { + let mut resources_table = app.resources_table(); + let menu = resources_table.get::>(rid)?; + if let Some(menu) = menu.set_as_app_menu()? { + let id = menu.id().clone(); + let rid = resources_table.add(menu); + return Ok(Some((rid, id))); + } + Ok(None) +} + +#[command(root = "crate")] +async fn set_as_window_menu( + app: AppHandle, + current_window: Window, + rid: ResourceId, + window: Option, +) -> crate::Result> { + let window = window + .map(|w| app.get_window(&w)) + .unwrap_or(Some(current_window)); + + if let Some(window) = window { + let mut resources_table = app.resources_table(); + let menu = resources_table.get::>(rid)?; + if let Some(menu) = menu.set_as_window_menu(&window)? { + let id = menu.id().clone(); + let rid = resources_table.add(menu); + return Ok(Some((rid, id))); + } + } + Ok(None) +} + +#[command(root = "crate")] +fn text(app: AppHandle, rid: ResourceId, kind: ItemKind) -> crate::Result { + let resources_table = app.resources_table(); + do_menu_item!(resources_table, rid, kind, |i| i.text()) +} + +#[command(root = "crate")] +fn set_text( + app: AppHandle, + rid: ResourceId, + kind: ItemKind, + text: String, +) -> crate::Result<()> { + let resources_table = app.resources_table(); + do_menu_item!(resources_table, rid, kind, |i| i.set_text(text)) +} + +#[command(root = "crate")] +fn is_enabled( + app: AppHandle, + rid: ResourceId, + kind: ItemKind, +) -> crate::Result { + let resources_table = app.resources_table(); + do_menu_item!(resources_table, rid, kind, |i| i.is_enabled(), !Predefined) +} + +#[command(root = "crate")] +fn set_enabled( + app: AppHandle, + rid: ResourceId, + kind: ItemKind, + enabled: bool, +) -> crate::Result<()> { + let resources_table = app.resources_table(); + do_menu_item!( + resources_table, + rid, + kind, + |i| i.set_enabled(enabled), + !Predefined + ) +} + +#[command(root = "crate")] +fn set_accelerator( + app: AppHandle, + rid: ResourceId, + kind: ItemKind, + accelerator: Option, +) -> crate::Result<()> { + let resources_table = app.resources_table(); + do_menu_item!( + resources_table, + rid, + kind, + |i| i.set_accelerator(accelerator), + !Predefined | !Submenu + ) +} + +#[command(root = "crate")] +fn set_as_windows_menu_for_nsapp( + app: AppHandle, + rid: ResourceId, +) -> crate::Result<()> { + #[cfg(target_os = "macos")] + { + let resources_table = app.resources_table(); + let submenu = resources_table.get::>(rid)?; + submenu.set_as_help_menu_for_nsapp()?; + } + + let _ = rid; + let _ = app; + Ok(()) +} + +#[command(root = "crate")] +fn set_as_help_menu_for_nsapp(app: AppHandle, rid: ResourceId) -> crate::Result<()> { + #[cfg(target_os = "macos")] + { + let resources_table = app.resources_table(); + let submenu = resources_table.get::>(rid)?; + submenu.set_as_help_menu_for_nsapp()?; + } + + let _ = rid; + let _ = app; + + Ok(()) +} + +#[command(root = "crate")] +fn is_checked(app: AppHandle, rid: ResourceId) -> crate::Result { + let resources_table = app.resources_table(); + let check_item = resources_table.get::>(rid)?; + check_item.is_checked() +} + +#[command(root = "crate")] +fn set_checked(app: AppHandle, rid: ResourceId, checked: bool) -> crate::Result<()> { + let resources_table = app.resources_table(); + let check_item = resources_table.get::>(rid)?; + check_item.set_checked(checked) +} + +#[command(root = "crate")] +fn set_icon( + app: AppHandle, + rid: ResourceId, + icon: Option, +) -> crate::Result<()> { + let resources_table = app.resources_table(); + let icon_item = resources_table.get::>(rid)?; + match icon { + Some(Icon::Native(icon)) => icon_item.set_native_icon(Some(icon)), + Some(Icon::Icon(icon)) => icon_item.set_icon(Some(icon.into())), + None => { + icon_item.set_icon(None)?; + icon_item.set_native_icon(None)?; + Ok(()) + } + } +} + +struct MenuChannels(Mutex>); + +pub(crate) fn init() -> TauriPlugin { + Builder::new("menu") + .setup(|app, _api| { + app.manage(MenuChannels(Mutex::default())); + Ok(()) + }) + .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); + } + } + }) + .invoke_handler(crate::generate_handler![ + new, + append, + prepend, + insert, + remove, + remove_at, + items, + get, + popup, + default, + set_as_app_menu, + set_as_window_menu, + text, + set_text, + is_enabled, + set_enabled, + set_accelerator, + set_as_windows_menu_for_nsapp, + set_as_help_menu_for_nsapp, + is_checked, + set_checked, + set_icon, + ]) + .build() +} diff --git a/core/tauri/src/menu/predefined.rs b/core/tauri/src/menu/predefined.rs index 44c6aff01d63..933a8a044835 100644 --- a/core/tauri/src/menu/predefined.rs +++ b/core/tauri/src/menu/predefined.rs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MIT use super::AboutMetadata; -use crate::{menu::MenuId, run_main_thread, AppHandle, Manager, Runtime}; +use crate::{menu::MenuId, resources::Resource, run_main_thread, AppHandle, Manager, Runtime}; /// A predefined (native) menu item which has a predfined behavior by the OS or by this crate. pub struct PredefinedMenuItem { @@ -29,7 +29,7 @@ unsafe impl Sync for PredefinedMenuItem {} unsafe impl Send for PredefinedMenuItem {} impl super::sealed::IsMenuItemBase for PredefinedMenuItem { - fn inner(&self) -> &dyn muda::IsMenuItem { + fn inner_muda(&self) -> &dyn muda::IsMenuItem { &self.inner } } @@ -212,7 +212,7 @@ impl PredefinedMenuItem { /// /// - **Linux:** Unsupported. pub fn close_window>(manager: &M, text: Option<&str>) -> Self { - let inner = muda::PredefinedMenuItem::show_all(text); + let inner = muda::PredefinedMenuItem::close_window(text); Self { id: inner.id().clone(), inner, @@ -285,3 +285,5 @@ impl PredefinedMenuItem { &self.app_handle } } + +impl Resource for PredefinedMenuItem {} diff --git a/core/tauri/src/menu/submenu.rs b/core/tauri/src/menu/submenu.rs index 905f04830c98..3b2690116d27 100644 --- a/core/tauri/src/menu/submenu.rs +++ b/core/tauri/src/menu/submenu.rs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MIT use super::{sealed::ContextMenuBase, IsMenuItem, MenuItemKind}; -use crate::{run_main_thread, AppHandle, Manager, Position, Runtime, Window}; +use crate::{resources::Resource, run_main_thread, AppHandle, Manager, Position, Runtime, Window}; use muda::{ContextMenu, MenuId}; /// A type that is a submenu inside a [`Menu`] or [`Submenu`] @@ -33,7 +33,7 @@ impl Clone for Submenu { } impl super::sealed::IsMenuItemBase for Submenu { - fn inner(&self) -> &dyn muda::IsMenuItem { + fn inner_muda(&self) -> &dyn muda::IsMenuItem { &self.inner } } @@ -85,7 +85,9 @@ impl ContextMenuBase for Submenu { target_os = "openbsd" ))] if let Ok(w) = window.gtk_window() { - self_.inner().show_context_menu_for_gtk_window(&w, position); + self_ + .inner() + .show_context_menu_for_gtk_window(w.as_ref(), position); } #[cfg(windows)] @@ -95,11 +97,11 @@ impl ContextMenuBase for Submenu { }) } - fn inner(&self) -> &dyn muda::ContextMenu { + fn inner_context(&self) -> &dyn muda::ContextMenu { &self.inner } - fn inner_owned(&self) -> Box { + fn inner_context_owned(&self) -> Box { Box::new(self.clone().inner) } } @@ -173,8 +175,10 @@ impl Submenu { /// Add a menu item to the end of this submenu. pub fn append(&self, item: &dyn IsMenuItem) -> crate::Result<()> { let kind = item.kind(); - run_main_thread!(self, |self_: Self| self_.inner.append(kind.inner().inner()))? - .map_err(Into::into) + run_main_thread!(self, |self_: Self| self_ + .inner + .append(kind.inner().inner_muda()))? + .map_err(Into::into) } /// Add menu items to the end of this submenu. It calls [`Submenu::append`] in a loop internally. @@ -190,7 +194,7 @@ impl Submenu { pub fn prepend(&self, item: &dyn IsMenuItem) -> crate::Result<()> { let kind = item.kind(); run_main_thread!(self, |self_: Self| { - self_.inner.prepend(kind.inner().inner()) + self_.inner.prepend(kind.inner().inner_muda()) })? .map_err(Into::into) } @@ -204,7 +208,7 @@ impl Submenu { pub fn insert(&self, item: &dyn IsMenuItem, position: usize) -> crate::Result<()> { let kind = item.kind(); run_main_thread!(self, |self_: Self| { - self_.inner.insert(kind.inner().inner(), position) + self_.inner.insert(kind.inner().inner_muda(), position) })? .map_err(Into::into) } @@ -221,47 +225,41 @@ impl Submenu { /// Remove a menu item from this submenu. pub fn remove(&self, item: &dyn IsMenuItem) -> crate::Result<()> { let kind = item.kind(); - run_main_thread!(self, |self_: Self| self_.inner.remove(kind.inner().inner()))? - .map_err(Into::into) + run_main_thread!(self, |self_: Self| self_ + .inner + .remove(kind.inner().inner_muda()))? + .map_err(Into::into) + } + + /// Remove the menu item at the specified position from this submenu and returns it. + pub fn remove_at(&self, position: usize) -> crate::Result>> { + run_main_thread!(self, |self_: Self| self_ + .inner + .remove_at(position) + .map(|i| MenuItemKind::from_muda(self_.app_handle.clone(), i))) + } + + /// Retrieves the menu item matching the given identifier. + pub fn get<'a, I>(&self, id: &'a I) -> Option> + where + I: ?Sized, + MenuId: PartialEq<&'a I>, + { + self + .items() + .unwrap_or_default() + .into_iter() + .find(|i| i.id() == &id) } /// Returns a list of menu items that has been added to this submenu. pub fn items(&self) -> crate::Result>> { - let handle = self.app_handle.clone(); run_main_thread!(self, |self_: Self| { self_ .inner .items() .into_iter() - .map(|i| match i { - muda::MenuItemKind::MenuItem(i) => super::MenuItemKind::MenuItem(super::MenuItem { - id: i.id().clone(), - inner: i, - app_handle: handle.clone(), - }), - muda::MenuItemKind::Submenu(i) => super::MenuItemKind::Submenu(super::Submenu { - id: i.id().clone(), - inner: i, - app_handle: handle.clone(), - }), - muda::MenuItemKind::Predefined(i) => { - super::MenuItemKind::Predefined(super::PredefinedMenuItem { - id: i.id().clone(), - inner: i, - app_handle: handle.clone(), - }) - } - muda::MenuItemKind::Check(i) => super::MenuItemKind::Check(super::CheckMenuItem { - id: i.id().clone(), - inner: i, - app_handle: handle.clone(), - }), - muda::MenuItemKind::Icon(i) => super::MenuItemKind::Icon(super::IconMenuItem { - id: i.id().clone(), - inner: i, - app_handle: handle.clone(), - }), - }) + .map(|i| MenuItemKind::from_muda(self_.app_handle.clone(), i)) .collect::>() }) } @@ -307,22 +305,11 @@ impl Submenu { /// /// If no menu is set as the Help menu, macOS will automatically use any menu /// which has a title matching the localized word "Help". + #[cfg(target_os = "macos")] pub fn set_as_help_menu_for_nsapp(&self) -> crate::Result<()> { - #[cfg(target_os = "macos")] run_main_thread!(self, |self_: Self| self_.inner.set_as_help_menu_for_nsapp())?; Ok(()) } - - /// Retrieves the menu item matching the given identifier. - pub fn get<'a, I>(&self, id: &'a I) -> Option> - where - I: ?Sized, - MenuId: PartialEq<&'a I>, - { - self - .items() - .unwrap_or_default() - .into_iter() - .find(|i| i.id() == &id) - } } + +impl Resource for Submenu {} diff --git a/core/tauri/src/plugin/mobile.rs b/core/tauri/src/plugin/mobile.rs index 15f49aa79e02..d6271ca99911 100644 --- a/core/tauri/src/plugin/mobile.rs +++ b/core/tauri/src/plugin/mobile.rs @@ -14,13 +14,12 @@ use crate::{ #[cfg(mobile)] use std::sync::atomic::{AtomicI32, Ordering}; -use once_cell::sync::OnceCell; use serde::{de::DeserializeOwned, Serialize}; use std::{ collections::HashMap, fmt, - sync::{mpsc::channel, Mutex}, + sync::{mpsc::channel, Mutex, OnceLock}, }; type PluginResponse = Result; @@ -29,9 +28,9 @@ type PendingPluginCallHandler = Box #[cfg(mobile)] static PENDING_PLUGIN_CALLS_ID: AtomicI32 = AtomicI32::new(0); -static PENDING_PLUGIN_CALLS: OnceCell>> = - OnceCell::new(); -static CHANNELS: OnceCell>> = OnceCell::new(); +static PENDING_PLUGIN_CALLS: OnceLock>> = + OnceLock::new(); +static CHANNELS: OnceLock>> = OnceLock::new(); /// Possible errors when invoking a plugin. #[derive(Debug, thiserror::Error)] diff --git a/core/tauri/src/resources/mod.rs b/core/tauri/src/resources/mod.rs new file mode 100644 index 000000000000..0829374f5fe6 --- /dev/null +++ b/core/tauri/src/resources/mod.rs @@ -0,0 +1,215 @@ +// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + +// a modified version of https://github.com/denoland/deno/blob/0ae83847f498a2886ae32172e50fd5bdbab2f524/core/resources.rs#L220 + +pub(crate) mod plugin; + +use crate::error::Error; +use std::{ + any::{type_name, Any, TypeId}, + borrow::Cow, + collections::BTreeMap, + sync::Arc, +}; + +/// Resources are Rust objects that are stored in [ResourceTable] and managed by tauri. +/// They are identified in JS by a numeric ID (the resource ID, or rid). +/// Resources can be created in commands. Resources can also be retrieved in commands by +/// their rid. Resources are thread-safe. +/// +/// Resources are reference counted in Rust. This means that they can be +/// cloned and passed around. When the last reference is dropped, the resource +/// is automatically closed. As long as the resource exists in the resource +/// table, the reference count is at least 1. +pub trait Resource: Any + 'static + Send + Sync { + /// Returns a string representation of the resource. The default implementation + /// returns the Rust type name, but specific resource types may override this + /// trait method. + fn name(&self) -> Cow<'_, str> { + type_name::().into() + } + + /// Resources may implement the `close()` trait method if they need to do + /// resource specific clean-ups, such as cancelling pending futures, after a + /// resource has been removed from the resource table. + fn close(self: Arc) {} +} + +impl dyn Resource { + #[inline(always)] + fn is(&self) -> bool { + self.type_id() == TypeId::of::() + } + + #[inline(always)] + pub(crate) fn downcast_arc<'a, T: Resource>(self: &'a Arc) -> Option<&'a Arc> { + if self.is::() { + // A resource is stored as `Arc` in a BTreeMap + // and is safe to cast to `Arc` because of the runtime + // check done in `self.is::()` + let ptr = self as *const Arc<_> as *const Arc; + Some(unsafe { &*ptr }) + } else { + None + } + } +} + +/// A `ResourceId` is an integer value referencing a resource. It could be +/// considered to be the tauri equivalent of a `file descriptor` in POSIX like +/// operating systems. +pub type ResourceId = u32; + +/// Map-like data structure storing Tauri's resources (equivalent to file +/// descriptors). +/// +/// Provides basic methods for element access. A resource can be of any type. +/// Different types of resources can be stored in the same map, and provided +/// with a name for description. +/// +/// Each resource is identified through a _resource ID (rid)_, which acts as +/// the key in the map. +#[derive(Default)] +pub struct ResourceTable { + index: BTreeMap>, + next_rid: ResourceId, +} + +impl ResourceTable { + /// Inserts resource into the resource table, which takes ownership of it. + /// + /// The resource type is erased at runtime and must be statically known + /// when retrieving it through `get()`. + /// + /// Returns a unique resource ID, which acts as a key for this resource. + pub fn add(&mut self, resource: T) -> ResourceId { + self.add_arc(Arc::new(resource)) + } + + /// Inserts a `Arc`-wrapped resource into the resource table. + /// + /// The resource type is erased at runtime and must be statically known + /// when retrieving it through `get()`. + /// + /// Returns a unique resource ID, which acts as a key for this resource. + pub fn add_arc(&mut self, resource: Arc) -> ResourceId { + let resource = resource as Arc; + self.add_arc_dyn(resource) + } + + /// Inserts a `Arc`-wrapped resource into the resource table. + /// + /// The resource type is erased at runtime and must be statically known + /// when retrieving it through `get()`. + /// + /// Returns a unique resource ID, which acts as a key for this resource. + pub fn add_arc_dyn(&mut self, resource: Arc) -> ResourceId { + let rid = self.next_rid; + let removed_resource = self.index.insert(rid, resource); + assert!(removed_resource.is_none()); + self.next_rid += 1; + rid + } + + /// Returns true if any resource with the given `rid` exists. + pub fn has(&self, rid: ResourceId) -> bool { + self.index.contains_key(&rid) + } + + /// Returns a reference counted pointer to the resource of type `T` with the + /// given `rid`. If `rid` is not present or has a type different than `T`, + /// this function returns [`Error::BadResourceId`]. + pub fn get(&self, rid: ResourceId) -> Result, Error> { + self + .index + .get(&rid) + .and_then(|rc| rc.downcast_arc::()) + .map(Clone::clone) + .ok_or_else(|| Error::BadResourceId(rid)) + } + + /// Returns a reference counted pointer to the resource of the given `rid`. + /// If `rid` is not present, this function returns [`Error::BadResourceId`]. + pub fn get_any(&self, rid: ResourceId) -> Result, Error> { + self + .index + .get(&rid) + .map(Clone::clone) + .ok_or_else(|| Error::BadResourceId(rid)) + } + + /// Replaces a resource with a new resource. + /// + /// Panics if the resource does not exist. + pub fn replace(&mut self, rid: ResourceId, resource: T) { + let result = self + .index + .insert(rid, Arc::new(resource) as Arc); + assert!(result.is_some()); + } + + /// Removes a resource of type `T` from the resource table and returns it. + /// If a resource with the given `rid` exists but its type does not match `T`, + /// it is not removed from the resource table. Note that the resource's + /// `close()` method is *not* called. + /// + /// Also note that there might be a case where + /// the returned `Arc` is referenced by other variables. That is, we cannot + /// assume that `Arc::strong_count(&returned_arc)` is always equal to 1 on success. + /// In particular, be really careful when you want to extract the inner value of + /// type `T` from `Arc`. + pub fn take(&mut self, rid: ResourceId) -> Result, Error> { + let resource = self.get::(rid)?; + self.index.remove(&rid); + Ok(resource) + } + + /// Removes a resource from the resource table and returns it. Note that the + /// resource's `close()` method is *not* called. + /// + /// Also note that there might be a + /// case where the returned `Arc` is referenced by other variables. That is, + /// we cannot assume that `Arc::strong_count(&returned_arc)` is always equal to 1 + /// on success. In particular, be really careful when you want to extract the + /// inner value of type `T` from `Arc`. + pub fn take_any(&mut self, rid: ResourceId) -> Result, Error> { + self + .index + .remove(&rid) + .ok_or_else(|| Error::BadResourceId(rid)) + } + + /// Returns an iterator that yields a `(id, name)` pair for every resource + /// that's currently in the resource table. This can be used for debugging + /// purposes. Note that the order in + /// which items appear is not specified. + pub fn names(&self) -> impl Iterator)> { + self + .index + .iter() + .map(|(&id, resource)| (id, resource.name())) + } + + /// Removes the resource with the given `rid` from the resource table. If the + /// only reference to this resource existed in the resource table, this will + /// cause the resource to be dropped. However, since resources are reference + /// counted, therefore pending ops are not automatically cancelled. A resource + /// may implement the `close()` method to perform clean-ups such as canceling + /// ops. + pub fn close(&mut self, rid: ResourceId) -> Result<(), Error> { + self + .index + .remove(&rid) + .ok_or_else(|| Error::BadResourceId(rid)) + .map(|resource| resource.close()) + } + + /// Removes and frees all resources stored. Note that the + /// resource's `close()` method is *not* called. + pub(crate) fn clear(&mut self) { + self.index.clear() + } +} diff --git a/core/tauri/src/resources/plugin.rs b/core/tauri/src/resources/plugin.rs new file mode 100644 index 000000000000..863352fb6ebf --- /dev/null +++ b/core/tauri/src/resources/plugin.rs @@ -0,0 +1,22 @@ +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + +use crate::{ + command, + plugin::{Builder, TauriPlugin}, + AppHandle, Manager, Runtime, +}; + +use super::ResourceId; + +#[command(root = "crate")] +fn close(app: AppHandle, rid: ResourceId) -> crate::Result<()> { + app.resources_table().close(rid) +} + +pub(crate) fn init() -> TauriPlugin { + Builder::new("resources") + .invoke_handler(crate::generate_handler![close]) + .build() +} diff --git a/core/tauri/src/state.rs b/core/tauri/src/state.rs index 098014234375..c4bb85adef45 100644 --- a/core/tauri/src/state.rs +++ b/core/tauri/src/state.rs @@ -72,7 +72,6 @@ impl StateManager { /// Gets the state associated with the specified type. pub fn get(&self) -> State<'_, T> { - self.0.get::(); State( self .0 diff --git a/core/tauri/src/test/mod.rs b/core/tauri/src/test/mod.rs index e4dbc8e4e5e8..aef21163510d 100644 --- a/core/tauri/src/test/mod.rs +++ b/core/tauri/src/test/mod.rs @@ -11,47 +11,38 @@ //! # Examples //! //! ```rust +//! use tauri::test::{mock_builder, mock_context, noop_assets}; +//! //! #[tauri::command] -//! fn my_cmd() {} +//! fn ping() -> &'static str { +//! "pong" +//! } //! -//! fn create_app(mut builder: tauri::Builder) -> tauri::App { -//! builder -//! .setup(|app| { -//! // do something -//! Ok(()) -//! }) -//! .invoke_handler(tauri::generate_handler![my_cmd]) -//! // remove the string argument on your app -//! .build(tauri::generate_context!("test/fixture/src-tauri/tauri.conf.json")) -//! .expect("failed to build app") +//! fn create_app(builder: tauri::Builder) -> tauri::App { +//! builder +//! .invoke_handler(tauri::generate_handler![ping]) +//! // remove the string argument to use your app's config file +//! .build(tauri::generate_context!("test/fixture/src-tauri/tauri.conf.json")) +//! .expect("failed to build app") //! } //! //! fn main() { -//! // let app = create_app(tauri::Builder::default()); -//! // app.run(|_handle, _event| {}); -//! } +//! let app = create_app(mock_builder()); +//! let window = tauri::WindowBuilder::new(&app, "main", Default::default()) +//! .build() +//! .unwrap(); //! -//! //#[cfg(test)] -//! mod tests { -//! use tauri::Manager; -//! //#[cfg(test)] -//! fn something() { -//! let app = super::create_app(tauri::test::mock_builder()); -//! let window = app.get_window("main").unwrap(); -//! // do something with the app and window -//! // in this case we'll run the my_cmd command with no arguments -//! tauri::test::assert_ipc_response( -//! &window, -//! tauri::window::InvokeRequest { -//! cmd: "my_cmd".into(), -//! callback: tauri::ipc::CallbackFn(0), -//! error: tauri::ipc::CallbackFn(1), -//! body: serde_json::Value::Null.into(), -//! headers: Default::default(), -//! }, -//! Ok(()) -//! ); -//! } +//! // run the `ping` command and assert it returns `pong` +//! let res = tauri::test::get_ipc_response( +//! &window, +//! tauri::window::InvokeRequest { +//! cmd: "ping".into(), +//! callback: tauri::ipc::CallbackFn(0), +//! error: tauri::ipc::CallbackFn(1), +//! body: tauri::ipc::InvokeBody::default(), +//! headers: Default::default(), +//! }, +//! ).map(|b| b.deserialize::().unwrap()); //! } //! ``` @@ -61,14 +52,10 @@ mod mock_runtime; pub use mock_runtime::*; use serde::Serialize; -use std::{ - borrow::Cow, - fmt::Debug, - hash::{Hash, Hasher}, -}; +use std::{borrow::Cow, fmt::Debug}; use crate::{ - ipc::{CallbackFn, InvokeResponse}, + ipc::{InvokeBody, InvokeError, InvokeResponse}, window::InvokeRequest, App, Builder, Context, Pattern, Window, }; @@ -77,19 +64,6 @@ use tauri_utils::{ config::{Config, PatternKind, TauriConfig}, }; -#[derive(Eq, PartialEq)] -struct IpcKey { - callback: CallbackFn, - error: CallbackFn, -} - -impl Hash for IpcKey { - fn hash(&self, state: &mut H) { - self.callback.0.hash(state); - self.error.0.hash(state); - } -} - /// An empty [`Assets`] implementation. pub struct NoopAsset { csp_hashes: Vec>, @@ -175,48 +149,39 @@ pub fn mock_app() -> App { /// # Examples /// /// ```rust +/// use tauri::test::{mock_builder, mock_context, noop_assets}; +/// /// #[tauri::command] /// fn ping() -> &'static str { -/// "pong" +/// "pong" /// } /// -/// fn create_app(mut builder: tauri::Builder) -> tauri::App { -/// builder -/// .invoke_handler(tauri::generate_handler![ping]) -/// // remove the string argument on your app -/// .build(tauri::generate_context!("test/fixture/src-tauri/tauri.conf.json")) -/// .expect("failed to build app") +/// fn create_app(builder: tauri::Builder) -> tauri::App { +/// builder +/// .invoke_handler(tauri::generate_handler![ping]) +/// // remove the string argument to use your app's config file +/// .build(tauri::generate_context!("test/fixture/src-tauri/tauri.conf.json")) +/// .expect("failed to build app") /// } /// /// fn main() { -/// // let app = create_app(tauri::Builder::default()); -/// // app.run(|_handle, _event| {});} -/// } -/// -/// //#[cfg(test)] -/// mod tests { -/// use tauri::Manager; -/// -/// //#[cfg(test)] -/// fn something() { -/// let app = super::create_app(tauri::test::mock_builder()); -/// let window = app.get_window("main").unwrap(); +/// let app = create_app(mock_builder()); +/// let window = tauri::WindowBuilder::new(&app, "main", Default::default()) +/// .build() +/// .unwrap(); /// /// // run the `ping` command and assert it returns `pong` /// tauri::test::assert_ipc_response( -/// &window, -/// tauri::window::InvokeRequest { -/// cmd: "ping".into(), -/// callback: tauri::ipc::CallbackFn(0), -/// error: tauri::ipc::CallbackFn(1), -/// body: serde_json::Value::Null.into(), -/// headers: Default::default(), -/// }, -/// // the expected response is a success with the "pong" payload -/// // we could also use Err("error message") here to ensure the command failed +/// &window, +/// tauri::window::InvokeRequest { +/// cmd: "ping".into(), +/// callback: tauri::ipc::CallbackFn(0), +/// error: tauri::ipc::CallbackFn(1), +/// body: tauri::ipc::InvokeBody::default(), +/// headers: Default::default(), +/// }, /// Ok("pong") /// ); -/// } /// } /// ``` pub fn assert_ipc_response( @@ -224,25 +189,74 @@ pub fn assert_ipc_response( request: InvokeRequest, expected: Result, ) { + let response = + get_ipc_response(window, request).map(|b| b.deserialize::().unwrap()); + assert_eq!( + response, + expected + .map(|e| serde_json::to_value(e).unwrap()) + .map_err(|e| serde_json::to_value(e).unwrap()) + ); +} + +/// Executes the given IPC message and get the return value. +/// +/// # Examples +/// +/// ```rust +/// use tauri::test::{mock_builder, mock_context, noop_assets}; +/// +/// #[tauri::command] +/// fn ping() -> &'static str { +/// "pong" +/// } +/// +/// fn create_app(builder: tauri::Builder) -> tauri::App { +/// builder +/// .invoke_handler(tauri::generate_handler![ping]) +/// // remove the string argument to use your app's config file +/// .build(tauri::generate_context!("test/fixture/src-tauri/tauri.conf.json")) +/// .expect("failed to build app") +/// } +/// +/// fn main() { +/// let app = create_app(mock_builder()); +/// let window = tauri::WindowBuilder::new(&app, "main", Default::default()) +/// .build() +/// .unwrap(); +/// +/// // run the `ping` command and assert it returns `pong` +/// let res = tauri::test::get_ipc_response( +/// &window, +/// tauri::window::InvokeRequest { +/// cmd: "ping".into(), +/// callback: tauri::ipc::CallbackFn(0), +/// error: tauri::ipc::CallbackFn(1), +/// body: tauri::ipc::InvokeBody::default(), +/// headers: Default::default(), +/// }, +/// ); +/// assert!(res.is_ok()); +/// assert_eq!(res.unwrap().deserialize::().unwrap(), String::from("pong")); +/// } +///``` +pub fn get_ipc_response( + window: &Window, + request: InvokeRequest, +) -> Result { let (tx, rx) = std::sync::mpsc::sync_channel(1); window.clone().on_message( request, Box::new(move |_window, _cmd, response, _callback, _error| { - assert_eq!( - match response { - InvokeResponse::Ok(b) => Ok(b.into_json()), - InvokeResponse::Err(e) => Err(e.0), - }, - expected - .map(|e| serde_json::to_value(e).unwrap()) - .map_err(|e| serde_json::to_value(e).unwrap()) - ); - - tx.send(()).unwrap(); + tx.send(response).unwrap(); }), ); - rx.recv().unwrap(); + let res = rx.recv().expect("Failed to receive result from command"); + match res { + InvokeResponse::Ok(b) => Ok(b), + InvokeResponse::Err(InvokeError(v)) => Err(v), + } } #[cfg(test)] diff --git a/core/tauri/src/tray.rs b/core/tauri/src/tray/mod.rs similarity index 93% rename from core/tauri/src/tray.rs rename to core/tauri/src/tray/mod.rs index 450a4f95068d..11db0bb97db9 100644 --- a/core/tauri/src/tray.rs +++ b/core/tauri/src/tray/mod.rs @@ -4,19 +4,21 @@ #![cfg(all(desktop, feature = "tray-icon"))] -//! Tray icon types and utility functions +//! Tray icon types and utilities. + +pub(crate) mod plugin; use crate::app::{GlobalMenuEventListener, GlobalTrayIconEventListener}; use crate::menu::ContextMenu; use crate::menu::MenuEvent; +use crate::resources::Resource; use crate::{run_main_thread, AppHandle, Icon, Manager, Runtime}; +use serde::Serialize; use std::path::Path; pub use tray_icon::TrayIconId; -// TODO(muda-migration): figure out js events - /// Describes a rectangle including position (x - y axis) and size. -#[derive(Debug, PartialEq, Clone, Copy, Default)] +#[derive(Debug, PartialEq, Clone, Copy, Default, Serialize)] pub struct Rectangle { /// The x-coordinate of the upper-left corner of the rectangle. pub left: f64, @@ -29,7 +31,7 @@ pub struct Rectangle { } /// Describes the click type that triggered this tray icon event. -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize)] pub enum ClickType { /// Left mouse click. Left, @@ -51,7 +53,8 @@ impl Default for ClickType { /// /// - **Linux**: Unsupported. The event is not emmited even though the icon is shown, /// the icon will still show a context menu on right click. -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, Serialize)] +#[serde(rename_all = "camelCase")] pub struct TrayIconEvent { /// Id of the tray icon which triggered this event. pub id: TrayIconId, @@ -146,7 +149,7 @@ impl TrayIconBuilder { /// /// - **Linux**: once a menu is set, it cannot be removed or replaced but you can change its content. pub fn menu(mut self, menu: &M) -> Self { - self.inner = self.inner.with_menu(menu.inner_owned()); + self.inner = self.inner.with_menu(menu.inner_context_owned()); self } @@ -360,13 +363,13 @@ impl TrayIcon { &self.id } - /// Set new tray icon. If `None` is provided, it will remove the icon. + /// Sets a new tray icon. If `None` is provided, it will remove the icon. pub fn set_icon(&self, icon: Option) -> crate::Result<()> { let icon = icon.and_then(|i| i.try_into().ok()); run_main_thread!(self, |self_: Self| self_.inner.set_icon(icon))?.map_err(Into::into) } - /// Set new tray menu. + /// Sets a new tray menu. /// /// ## Platform-specific: /// @@ -374,7 +377,7 @@ impl TrayIcon { pub fn set_menu(&self, menu: Option) -> crate::Result<()> { run_main_thread!(self, |self_: Self| self_ .inner - .set_menu(menu.map(|m| m.inner_owned()))) + .set_menu(menu.map(|m| m.inner_context_owned()))) } /// Sets the tooltip for this tray icon. @@ -387,7 +390,7 @@ impl TrayIcon { run_main_thread!(self, |self_: Self| self_.inner.set_tooltip(s))?.map_err(Into::into) } - /// Sets the tooltip for this tray icon. + /// Sets the title for this tray icon. /// /// ## Platform-specific: /// @@ -402,7 +405,7 @@ impl TrayIcon { run_main_thread!(self, |self_: Self| self_.inner.set_title(s)) } - /// Show or hide this tray icon + /// Show or hide this tray icon. pub fn set_visible(&self, visible: bool) -> crate::Result<()> { run_main_thread!(self, |self_: Self| self_.inner.set_visible(visible))?.map_err(Into::into) } @@ -419,7 +422,7 @@ impl TrayIcon { Ok(()) } - /// Set the current icon as a [template](https://developer.apple.com/documentation/appkit/nsimage/1520017-template?language=objc). **macOS only**. + /// Sets the current icon as a [template](https://developer.apple.com/documentation/appkit/nsimage/1520017-template?language=objc). **macOS only**. pub fn set_icon_as_template(&self, #[allow(unused)] is_template: bool) -> crate::Result<()> { #[cfg(target_os = "macos")] run_main_thread!(self, |self_: Self| self_ @@ -446,3 +449,9 @@ impl TryFrom for tray_icon::Icon { tray_icon::Icon::from_rgba(value.rgba, value.width, value.height).map_err(Into::into) } } + +impl Resource for TrayIcon { + fn close(self: std::sync::Arc) { + self.app_handle.remove_tray_by_id(&self.id); + } +} diff --git a/core/tauri/src/tray/plugin.rs b/core/tauri/src/tray/plugin.rs new file mode 100644 index 000000000000..5ca61a10ca61 --- /dev/null +++ b/core/tauri/src/tray/plugin.rs @@ -0,0 +1,204 @@ +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + +use std::path::PathBuf; + +use serde::Deserialize; + +use crate::{ + command, + ipc::Channel, + menu::{plugin::ItemKind, Menu, Submenu}, + plugin::{Builder, TauriPlugin}, + resources::ResourceId, + tray::TrayIconBuilder, + AppHandle, IconDto, Manager, Runtime, +}; + +use super::TrayIcon; + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct TrayIconOptions { + id: Option, + menu: Option<(ResourceId, ItemKind)>, + icon: Option, + tooltip: Option, + title: Option, + temp_dir_path: Option, + icon_as_template: Option, + menu_on_left_click: Option, +} + +#[command(root = "crate")] +fn new( + app: AppHandle, + options: TrayIconOptions, + handler: Channel, +) -> crate::Result<(ResourceId, String)> { + let mut builder = if let Some(id) = options.id { + TrayIconBuilder::::with_id(id) + } else { + TrayIconBuilder::::new() + }; + + builder = builder.on_tray_icon_event(move |_tray, e| { + let _ = handler.send(e); + }); + + let mut resources_table = app.resources_table(); + + if let Some((rid, kind)) = options.menu { + match kind { + ItemKind::Menu => { + let menu = resources_table.get::>(rid)?; + builder = builder.menu(&*menu); + } + ItemKind::Submenu => { + let submenu = resources_table.get::>(rid)?; + builder = builder.menu(&*submenu); + } + _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), + }; + } + if let Some(icon) = options.icon { + builder = builder.icon(icon.into()); + } + if let Some(tooltip) = options.tooltip { + builder = builder.tooltip(tooltip); + } + if let Some(title) = options.title { + builder = builder.title(title); + } + if let Some(temp_dir_path) = options.temp_dir_path { + builder = builder.temp_dir_path(temp_dir_path); + } + if let Some(icon_as_template) = options.icon_as_template { + builder = builder.icon_as_template(icon_as_template); + } + if let Some(menu_on_left_click) = options.menu_on_left_click { + builder = builder.menu_on_left_click(menu_on_left_click); + } + + let tray = builder.build(&app)?; + let id = tray.id().as_ref().to_string(); + let rid = resources_table.add(tray); + + Ok((rid, id)) +} + +#[command(root = "crate")] +fn set_icon( + app: AppHandle, + rid: ResourceId, + icon: Option, +) -> crate::Result<()> { + let resources_table = app.resources_table(); + let tray = resources_table.get::>(rid)?; + tray.set_icon(icon.map(Into::into)) +} + +#[command(root = "crate")] +fn set_menu( + app: AppHandle, + rid: ResourceId, + menu: Option<(ResourceId, ItemKind)>, +) -> crate::Result<()> { + let resources_table = app.resources_table(); + let tray = resources_table.get::>(rid)?; + if let Some((rid, kind)) = menu { + match kind { + ItemKind::Menu => { + let menu = resources_table.get::>(rid)?; + tray.set_menu(Some((*menu).clone()))?; + } + ItemKind::Submenu => { + let submenu = resources_table.get::>(rid)?; + tray.set_menu(Some((*submenu).clone()))?; + } + _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), + }; + } else { + tray.set_menu(None::>)?; + } + Ok(()) +} + +#[command(root = "crate")] +fn set_tooltip( + app: AppHandle, + rid: ResourceId, + tooltip: Option, +) -> crate::Result<()> { + let resources_table = app.resources_table(); + let tray = resources_table.get::>(rid)?; + tray.set_tooltip(tooltip) +} + +#[command(root = "crate")] +fn set_title( + app: AppHandle, + rid: ResourceId, + title: Option, +) -> crate::Result<()> { + let resources_table = app.resources_table(); + let tray = resources_table.get::>(rid)?; + tray.set_title(title) +} + +#[command(root = "crate")] +fn set_visible(app: AppHandle, rid: ResourceId, visible: bool) -> crate::Result<()> { + let resources_table = app.resources_table(); + let tray = resources_table.get::>(rid)?; + tray.set_visible(visible) +} + +#[command(root = "crate")] +fn set_temp_dir_path( + app: AppHandle, + rid: ResourceId, + path: Option, +) -> crate::Result<()> { + let resources_table = app.resources_table(); + let tray = resources_table.get::>(rid)?; + tray.set_temp_dir_path(path) +} + +#[command(root = "crate")] +fn set_icon_as_template( + app: AppHandle, + rid: ResourceId, + as_template: bool, +) -> crate::Result<()> { + let resources_table = app.resources_table(); + let tray = resources_table.get::>(rid)?; + tray.set_icon_as_template(as_template) +} + +#[command(root = "crate")] +fn set_show_menu_on_left_click( + app: AppHandle, + rid: ResourceId, + on_left: bool, +) -> crate::Result<()> { + let resources_table = app.resources_table(); + let tray = resources_table.get::>(rid)?; + tray.set_show_menu_on_left_click(on_left) +} + +pub(crate) fn init() -> TauriPlugin { + Builder::new("tray") + .invoke_handler(crate::generate_handler![ + new, + set_icon, + set_menu, + set_tooltip, + set_title, + set_visible, + set_temp_dir_path, + set_icon_as_template, + set_show_menu_on_left_click, + ]) + .build() +} diff --git a/core/tauri/src/vibrancy/windows.rs b/core/tauri/src/vibrancy/windows.rs index e6133b5430d8..9c7cf744c725 100644 --- a/core/tauri/src/vibrancy/windows.rs +++ b/core/tauri/src/vibrancy/windows.rs @@ -12,7 +12,6 @@ use std::ffi::c_void; use crate::utils::config::WindowEffectsConfig; use crate::window::{Color, Effect}; use raw_window_handle::HasRawWindowHandle; -use tauri_utils::platform::{get_function_impl, is_windows_7, windows_version}; use windows::Win32::Foundation::HWND; pub fn apply_effects(window: impl HasRawWindowHandle, effects: WindowEffectsConfig) { diff --git a/core/tauri/src/window/mod.rs b/core/tauri/src/window/mod.rs index 217c83d44691..7cf5b386df2f 100644 --- a/core/tauri/src/window/mod.rs +++ b/core/tauri/src/window/mod.rs @@ -1108,7 +1108,7 @@ impl PlatformWebview { target_os = "openbsd" ))) )] - pub fn inner(&self) -> std::rc::Rc { + pub fn inner(&self) -> webkit2gtk::WebView { self.0.clone() } @@ -1159,7 +1159,7 @@ impl PlatformWebview { /// Returns handle for JNI execution. #[cfg(target_os = "android")] - pub fn jni_handle(&self) -> tauri_runtime_wry::wry::webview::JniHandle { + pub fn jni_handle(&self) -> tauri_runtime_wry::wry::JniHandle { self.0 } } @@ -1411,12 +1411,13 @@ impl Window { /// - **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. pub fn remove_menu(&self) -> crate::Result>> { - let current_menu = self.menu_lock().as_ref().map(|m| m.menu.clone()); + let prev_menu = self.menu_lock().take().map(|m| m.menu); // remove from the window #[cfg_attr(target_os = "macos", allow(unused_variables))] - if let Some(menu) = current_menu { + if let Some(menu) = &prev_menu { let window = self.clone(); + let menu = menu.clone(); self.run_on_main_thread(move || { #[cfg(windows)] if let Ok(hwnd) = window.hwnd() { @@ -1435,8 +1436,6 @@ impl Window { })?; } - let prev_menu = self.menu_lock().take().map(|m| m.menu); - self .manager .remove_menu_from_stash_by_id(prev_menu.as_ref().map(|m| m.id())); @@ -2287,12 +2286,13 @@ impl Window { handled = true; fn load_channels(payload: &serde_json::Value, window: &Window) { + use std::str::FromStr; + if let serde_json::Value::Object(map) = payload { for v in map.values() { if let serde_json::Value::String(s) = v { - if s.starts_with(crate::ipc::channel::IPC_PAYLOAD_PREFIX) { - crate::ipc::Channel::load_from_ipc(window.clone(), s); - } + let _ = crate::ipc::JavaScriptChannelId::from_str(s) + .map(|id| id.channel_on(window.clone())); } } } diff --git a/examples/api/README.md b/examples/api/README.md index d9fe94b1f479..c0cba6e1a211 100644 --- a/examples/api/README.md +++ b/examples/api/README.md @@ -1,4 +1,5 @@ # API example + This example demonstrates Tauri's API capabilities using the `@tauri-apps/api` package. It's used as the main validation app, serving as the testbed of our development process. In the future, this app will be used on Tauri's integration tests. @@ -7,19 +8,22 @@ In the future, this app will be used on Tauri's integration tests. ## Running the example - Compile Tauri -go to root of the Tauri repo and run: -Linux / Mac: + go to root of the Tauri repo and run: + Linux / Mac: + ``` # choose to install node cli (1) bash .scripts/setup.sh ``` Windows: + ``` ./.scripts/setup.ps1 ``` - Install dependencies (Run inside of this folder `examples/api/`) + ```bash # with yarn $ yarn @@ -28,6 +32,7 @@ $ npm install ``` - Run the app in development mode (Run inside of this folder `examples/api/`) + ```bash # with yarn $ yarn tauri dev @@ -36,6 +41,7 @@ $ npm run tauri dev ``` - Build an run the release app (Run inside of this folder `examples/api/`) + ```bash $ yarn tauri build $ ./src-tauri/target/release/app diff --git a/examples/api/dist/assets/index.css b/examples/api/dist/assets/index.css index 8723712d01fb..f256b138469f 100644 --- a/examples/api/dist/assets/index.css +++ b/examples/api/dist/assets/index.css @@ -1 +1 @@ -*,::before,::after{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x:var(--un-empty,/*!*/ /*!*/);--un-pan-y:var(--un-empty,/*!*/ /*!*/);--un-pinch-zoom:var(--un-empty,/*!*/ /*!*/);--un-scroll-snap-strictness:proximity;--un-ordinal:var(--un-empty,/*!*/ /*!*/);--un-slashed-zero:var(--un-empty,/*!*/ /*!*/);--un-numeric-figure:var(--un-empty,/*!*/ /*!*/);--un-numeric-spacing:var(--un-empty,/*!*/ /*!*/);--un-numeric-fraction:var(--un-empty,/*!*/ /*!*/);--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 #0000;--un-ring-shadow:0 0 #0000;--un-shadow-inset:var(--un-empty,/*!*/ /*!*/);--un-shadow:0 0 #0000;--un-ring-inset:var(--un-empty,/*!*/ /*!*/);--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgba(147,197,253,0.5);--un-blur:var(--un-empty,/*!*/ /*!*/);--un-brightness:var(--un-empty,/*!*/ /*!*/);--un-contrast:var(--un-empty,/*!*/ /*!*/);--un-drop-shadow:var(--un-empty,/*!*/ /*!*/);--un-grayscale:var(--un-empty,/*!*/ /*!*/);--un-hue-rotate:var(--un-empty,/*!*/ /*!*/);--un-invert:var(--un-empty,/*!*/ /*!*/);--un-saturate:var(--un-empty,/*!*/ /*!*/);--un-sepia:var(--un-empty,/*!*/ /*!*/);--un-backdrop-blur:var(--un-empty,/*!*/ /*!*/);--un-backdrop-brightness:var(--un-empty,/*!*/ /*!*/);--un-backdrop-contrast:var(--un-empty,/*!*/ /*!*/);--un-backdrop-grayscale:var(--un-empty,/*!*/ /*!*/);--un-backdrop-hue-rotate:var(--un-empty,/*!*/ /*!*/);--un-backdrop-invert:var(--un-empty,/*!*/ /*!*/);--un-backdrop-opacity:var(--un-empty,/*!*/ /*!*/);--un-backdrop-saturate:var(--un-empty,/*!*/ /*!*/);--un-backdrop-sepia:var(--un-empty,/*!*/ /*!*/);}@font-face { font-family: 'Fira Code'; font-style: normal; font-weight: 400; font-display: swap; src: url(https://fonts.gstatic.com/s/firacode/v22/uU9eCBsR6Z2vfE9aq3bL0fxyUs4tcw4W_D1sFVc.ttf) format('truetype');}@font-face { font-family: 'Fira Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url(https://fonts.gstatic.com/s/firamono/v14/N0bX2SlFPv1weGeLZDtQIQ.ttf) format('truetype');}@font-face { font-family: 'Fira Mono'; font-style: normal; font-weight: 700; font-display: swap; src: url(https://fonts.gstatic.com/s/firamono/v14/N0bS2SlFPv1weGeLZDtondv3mQ.ttf) format('truetype');}@font-face { font-family: 'Rubik'; font-style: normal; font-weight: 400; font-display: swap; src: url(https://fonts.gstatic.com/s/rubik/v28/iJWZBXyIfDnIV5PNhY1KTN7Z-Yh-B4i1UA.ttf) format('truetype');}.i-codicon-clear-all{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 16 16' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='m10 12.6l.7.7l1.6-1.6l1.6 1.6l.8-.7L13 11l1.7-1.6l-.8-.8l-1.6 1.7l-1.6-1.7l-.7.8l1.6 1.6l-1.6 1.6zM1 4h14V3H1v1zm0 3h14V6H1v1zm8 2.5V9H1v1h8v-.5zM9 13v-1H1v1h8z'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-codicon-close{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 16 16' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' fill-rule='evenodd' d='m8 8.707l3.646 3.647l.708-.707L8.707 8l3.647-3.646l-.707-.708L8 7.293L4.354 3.646l-.707.708L7.293 8l-3.646 3.646l.707.708L8 8.707z' clip-rule='evenodd'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-codicon-hubot{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 16 16' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' fill-rule='evenodd' d='M8.48 4h4l.5.5v2.03h.52l.5.5V8l-.5.5h-.52v3l-.5.5H9.36l-2.5 2.76L6 14.4V12H3.5l-.5-.64V8.5h-.5L2 8v-.97l.5-.5H3V4.36L3.53 4h4V2.86A1 1 0 0 1 7 2a1 1 0 0 1 2 0a1 1 0 0 1-.52.83V4zM12 8V5H4v5.86l2.5.14H7v2.19l1.8-2.04l.35-.15H12V8zm-2.12.51a2.71 2.71 0 0 1-1.37.74v-.01a2.71 2.71 0 0 1-2.42-.74l-.7.71c.34.34.745.608 1.19.79c.45.188.932.286 1.42.29a3.7 3.7 0 0 0 2.58-1.07l-.7-.71zM6.49 6.5h-1v1h1v-1zm3 0h1v1h-1v-1z' clip-rule='evenodd'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-codicon-link-external{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 16 16' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cg fill='currentColor'%3E%3Cpath d='M1.5 1H6v1H2v12h12v-4h1v4.5l-.5.5h-13l-.5-.5v-13l.5-.5z'/%3E%3Cpath d='M15 1.5V8h-1V2.707L7.243 9.465l-.707-.708L13.293 2H8V1h6.5l.5.5z'/%3E%3C/g%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-codicon-menu{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 16 16' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M16 5H0V4h16v1zm0 8H0v-1h16v1zm0-4.008H0V8h16v.992z'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-codicon-radio-tower{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 16 16' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' fill-rule='evenodd' d='M2.998 5.58a5.55 5.55 0 0 1 1.62-3.88l-.71-.7a6.45 6.45 0 0 0 0 9.16l.71-.7a5.55 5.55 0 0 1-1.62-3.88zm1.06 0a4.42 4.42 0 0 0 1.32 3.17l.71-.71a3.27 3.27 0 0 1-.76-1.12a3.45 3.45 0 0 1 0-2.67a3.22 3.22 0 0 1 .76-1.13l-.71-.71a4.46 4.46 0 0 0-1.32 3.17zm7.65 3.21l-.71-.71c.33-.32.59-.704.76-1.13a3.449 3.449 0 0 0 0-2.67a3.22 3.22 0 0 0-.76-1.13l.71-.7a4.468 4.468 0 0 1 0 6.34zM13.068 1l-.71.71a5.43 5.43 0 0 1 0 7.74l.71.71a6.45 6.45 0 0 0 0-9.16zM9.993 5.43a1.5 1.5 0 0 1-.245.98a2 2 0 0 1-.27.23l3.44 7.73l-.92.4l-.77-1.73h-5.54l-.77 1.73l-.92-.4l3.44-7.73a1.52 1.52 0 0 1-.33-1.63a1.55 1.55 0 0 1 .56-.68a1.5 1.5 0 0 1 2.325 1.1zm-1.595-.34a.52.52 0 0 0-.25.14a.52.52 0 0 0-.11.22a.48.48 0 0 0 0 .29c.04.09.102.17.18.23a.54.54 0 0 0 .28.08a.51.51 0 0 0 .5-.5a.54.54 0 0 0-.08-.28a.58.58 0 0 0-.23-.18a.48.48 0 0 0-.29 0zm.23 2.05h-.27l-.87 1.94h2l-.86-1.94zm2.2 4.94l-.89-2h-2.88l-.89 2h4.66z' clip-rule='evenodd'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-codicon-window{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 16 16' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M14.5 2h-13l-.5.5v11l.5.5h13l.5-.5v-11l-.5-.5zM14 13H2V6h12v7zm0-8H2V3h12v2z'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-ph-broadcast{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 256 256' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M128 88a40 40 0 1 0 40 40a40 40 0 0 0-40-40Zm0 64a24 24 0 1 1 24-24a24.1 24.1 0 0 1-24 24Zm-59-48.9a64.5 64.5 0 0 0 0 49.8a65.4 65.4 0 0 0 13.7 20.4a7.9 7.9 0 0 1 0 11.3a8 8 0 0 1-5.6 2.3a8.3 8.3 0 0 1-5.7-2.3a80 80 0 0 1-17.1-25.5a79.9 79.9 0 0 1 0-62.2a80 80 0 0 1 17.1-25.5a8 8 0 0 1 11.3 0a7.9 7.9 0 0 1 0 11.3A65.4 65.4 0 0 0 69 103.1Zm132.7 56a80 80 0 0 1-17.1 25.5a8.3 8.3 0 0 1-5.7 2.3a8 8 0 0 1-5.6-2.3a7.9 7.9 0 0 1 0-11.3a65.4 65.4 0 0 0 13.7-20.4a64.5 64.5 0 0 0 0-49.8a65.4 65.4 0 0 0-13.7-20.4a7.9 7.9 0 0 1 0-11.3a8 8 0 0 1 11.3 0a80 80 0 0 1 17.1 25.5a79.9 79.9 0 0 1 0 62.2ZM54.5 201.5a8.1 8.1 0 0 1 0 11.4a8.3 8.3 0 0 1-5.7 2.3a8.5 8.5 0 0 1-5.7-2.3a121.8 121.8 0 0 1-25.7-38.2a120.7 120.7 0 0 1 0-93.4a121.8 121.8 0 0 1 25.7-38.2a8.1 8.1 0 0 1 11.4 11.4A103.5 103.5 0 0 0 24 128a103.5 103.5 0 0 0 30.5 73.5ZM248 128a120.2 120.2 0 0 1-9.4 46.7a121.8 121.8 0 0 1-25.7 38.2a8.5 8.5 0 0 1-5.7 2.3a8.3 8.3 0 0 1-5.7-2.3a8.1 8.1 0 0 1 0-11.4A103.5 103.5 0 0 0 232 128a103.5 103.5 0 0 0-30.5-73.5a8.1 8.1 0 1 1 11.4-11.4a121.8 121.8 0 0 1 25.7 38.2A120.2 120.2 0 0 1 248 128Z'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-ph-hand-waving{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 256 256' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='m220.2 104l-20-34.7a28.1 28.1 0 0 0-47.3-1.9l-17.3-30a28.1 28.1 0 0 0-38.3-10.3a29.4 29.4 0 0 0-9.9 9.6a27.9 27.9 0 0 0-11.5-6.2a27.2 27.2 0 0 0-21.2 2.8a27.9 27.9 0 0 0-10.3 38.2l3.4 5.8A28.5 28.5 0 0 0 36 81a28.1 28.1 0 0 0-10.2 38.2l42 72.8a88 88 0 1 0 152.4-88Zm-6.7 62.6a71.2 71.2 0 0 1-33.5 43.7A72.1 72.1 0 0 1 81.6 184l-42-72.8a12 12 0 0 1 20.8-12l22 38.1l.6.9v.2l.5.5l.2.2l.7.6h.1l.7.5h.3l.6.3h.2l.9.3h.1l.8.2h2.2l.9-.2h.3l.6-.2h.3l.9-.4a8.1 8.1 0 0 0 2.9-11l-22-38.1l-16-27.7a12 12 0 0 1-1.2-9.1a11.8 11.8 0 0 1 5.6-7.3a12 12 0 0 1 9.1-1.2a12.5 12.5 0 0 1 7.3 5.6l8 14h.1l26 45a7 7 0 0 0 1.5 1.9a8 8 0 0 0 12.3-9.9l-26-45a12 12 0 1 1 20.8-12l30 51.9l6.3 11a48.1 48.1 0 0 0-10.9 61a8 8 0 0 0 13.8-8a32 32 0 0 1 11.7-43.7l.7-.4l.5-.4h.1l.6-.6l.5-.5l.4-.5l.3-.6h.1l.2-.5v-.2a1.9 1.9 0 0 0 .2-.7h.1c0-.2.1-.4.1-.6s0-.2.1-.2v-2.1a6.4 6.4 0 0 0-.2-.7a1.9 1.9 0 0 0-.2-.7v-.2c0-.2-.1-.3-.2-.5l-.3-.7l-10-17.4a12 12 0 0 1 13.5-17.5a11.8 11.8 0 0 1 7.2 5.5l20 34.7a70.9 70.9 0 0 1 7.2 53.8Zm-125.8 78a8.2 8.2 0 0 1-6.6 3.4a8.6 8.6 0 0 1-4.6-1.4A117.9 117.9 0 0 1 41.1 208a8 8 0 1 1 13.8-8a102.6 102.6 0 0 0 30.8 33.4a8.1 8.1 0 0 1 2 11.2ZM168 31a8 8 0 0 1 8-8a60.2 60.2 0 0 1 52 30a7.9 7.9 0 0 1-3 10.9a7.1 7.1 0 0 1-4 1.1a8 8 0 0 1-6.9-4A44 44 0 0 0 176 39a8 8 0 0 1-8-8Z'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-ph-moon{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 256 256' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M224.3 150.3a8.1 8.1 0 0 0-7.8-5.7l-2.2.4A84 84 0 0 1 111 41.6a5.7 5.7 0 0 0 .3-1.8a7.9 7.9 0 0 0-10.3-8.1a100 100 0 1 0 123.3 123.2a7.2 7.2 0 0 0 0-4.6ZM128 212A84 84 0 0 1 92.8 51.7a99.9 99.9 0 0 0 111.5 111.5A84.4 84.4 0 0 1 128 212Z'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-ph-sun{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 256 256' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M128 60a68 68 0 1 0 68 68a68.1 68.1 0 0 0-68-68Zm0 120a52 52 0 1 1 52-52a52 52 0 0 1-52 52Zm-8-144V16a8 8 0 0 1 16 0v20a8 8 0 0 1-16 0ZM43.1 54.5a8.1 8.1 0 1 1 11.4-11.4l14.1 14.2a8 8 0 0 1 0 11.3a8.1 8.1 0 0 1-11.3 0ZM36 136H16a8 8 0 0 1 0-16h20a8 8 0 0 1 0 16Zm32.6 51.4a8 8 0 0 1 0 11.3l-14.1 14.2a8.3 8.3 0 0 1-5.7 2.3a8.5 8.5 0 0 1-5.7-2.3a8.1 8.1 0 0 1 0-11.4l14.2-14.1a8 8 0 0 1 11.3 0ZM136 220v20a8 8 0 0 1-16 0v-20a8 8 0 0 1 16 0Zm76.9-18.5a8.1 8.1 0 0 1 0 11.4a8.5 8.5 0 0 1-5.7 2.3a8.3 8.3 0 0 1-5.7-2.3l-14.1-14.2a8 8 0 0 1 11.3-11.3ZM248 128a8 8 0 0 1-8 8h-20a8 8 0 0 1 0-16h20a8 8 0 0 1 8 8Zm-60.6-59.4a8 8 0 0 1 0-11.3l14.1-14.2a8.1 8.1 0 0 1 11.4 11.4l-14.2 14.1a8.1 8.1 0 0 1-11.3 0Z'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.note-red{position:relative;display:inline-flex;align-items:center;border-left-width:4px;border-left-style:solid;--un-border-opacity:1;border-color:rgba(53,120,229,var(--un-border-opacity));border-radius:0.25rem;background-color:rgba(53,120,229,0.1);background-color:rgba(185,28,28,0.1);padding:0.5rem;text-decoration:none;}.nv{position:relative;display:flex;align-items:center;border-radius:0.25rem;padding:0.5rem;--un-text-opacity:1;color:rgba(194,197,202,var(--un-text-opacity));text-decoration:none;transition-property:all;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:125ms;}.nv_selected{position:relative;display:flex;align-items:center;border-left-width:4px;border-left-style:solid;border-radius:0.25rem;--un-bg-opacity:.05;background-color:hsla(0,0%,100%,var(--un-bg-opacity));padding:0.5rem;--un-text-opacity:1;color:rgba(194,197,202,var(--un-text-opacity));color:rgba(53,120,229,var(--un-text-opacity));text-decoration:none;transition-property:all;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:125ms;}.input{height:2.5rem;display:flex;align-items:center;border-radius:0.25rem;border-style:none;--un-bg-opacity:1;background-color:rgba(233,236,239,var(--un-bg-opacity));padding:0.5rem;--un-text-opacity:1;color:rgba(28,30,33,var(--un-text-opacity));--un-shadow:var(--un-shadow-inset) 0 4px 6px -1px var(--un-shadow-color, rgba(0,0,0,0.1)),var(--un-shadow-inset) 0 2px 4px -2px var(--un-shadow-color, rgba(0,0,0,0.1));box-shadow:var(--un-ring-offset-shadow, 0 0 #0000), var(--un-ring-shadow, 0 0 #0000), var(--un-shadow);outline:2px solid transparent;outline-offset:2px;}.btn{user-select:none;border-radius:0.25rem;border-style:none;--un-bg-opacity:1;background-color:rgba(53,120,229,var(--un-bg-opacity));padding:0.5rem;font-weight:400;--un-text-opacity:1;color:rgba(28,30,33,var(--un-text-opacity));color:rgba(255,255,255,var(--un-text-opacity));--un-shadow:var(--un-shadow-inset) 0 4px 6px -1px var(--un-shadow-color, rgba(0,0,0,0.1)),var(--un-shadow-inset) 0 2px 4px -2px var(--un-shadow-color, rgba(0,0,0,0.1));box-shadow:var(--un-ring-offset-shadow, 0 0 #0000), var(--un-ring-shadow, 0 0 #0000), var(--un-shadow);outline:2px solid transparent;outline-offset:2px;}.nv_selected:hover,.nv:hover{border-left-width:4px;border-left-style:solid;--un-bg-opacity:.05;background-color:hsla(0,0%,100%,var(--un-bg-opacity));--un-text-opacity:1;color:rgba(53,120,229,var(--un-text-opacity));}.dark .note-red{--un-border-opacity:1;border-color:rgba(103,214,237,var(--un-border-opacity));background-color:rgba(103,214,237,0.1);background-color:rgba(185,28,28,0.1);}.btn:hover{--un-bg-opacity:1;background-color:rgba(45,102,195,var(--un-bg-opacity));}.dark .btn{--un-bg-opacity:1;background-color:rgba(103,214,237,var(--un-bg-opacity));font-weight:600;--un-text-opacity:1;color:rgba(28,30,33,var(--un-text-opacity));}.dark .btn:hover{--un-bg-opacity:1;background-color:rgba(57,202,232,var(--un-bg-opacity));}.dark .input{--un-bg-opacity:1;background-color:rgba(36,37,38,var(--un-bg-opacity));--un-text-opacity:1;color:rgba(227,227,227,var(--un-text-opacity));}.dark .note-red::after,.note-red::after{--un-bg-opacity:1;background-color:rgba(185,28,28,var(--un-bg-opacity));}.btn:active{--un-bg-opacity:1;background-color:rgba(37,84,160,var(--un-bg-opacity));}.dark .btn:active{--un-bg-opacity:1;background-color:rgba(25,181,213,var(--un-bg-opacity));}.dark .nv_selected,.dark .nv_selected:hover,.dark .nv:hover{--un-text-opacity:1;color:rgba(103,214,237,var(--un-text-opacity));} ::-webkit-scrollbar-thumb { background-color: #3578E5; } .dark ::-webkit-scrollbar-thumb { background-color: #67d6ed; } code { font-size: 0.75rem; font-family: "Fira Code","Fira Mono",ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace; border-radius: 0.25rem; background-color: #d6d8da; } .code-block { font-family: "Fira Code","Fira Mono",ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace; font-size: 0.875rem; } .dark code { background-color: #282a2e; } .visible{visibility:visible;}.absolute{position:absolute;}.left-2{left:0.5rem;}.top-2{top:0.5rem;}.z-2000{z-index:2000;}.grid{display:grid;}.grid-rows-\[2fr_auto\]{grid-template-rows:2fr auto;}.grid-rows-\[2px_2rem_1fr\]{grid-template-rows:2px 2rem 1fr;}.grid-rows-\[auto_1fr\]{grid-template-rows:auto 1fr;}.grid-rows-\[min-content_auto\]{grid-template-rows:min-content auto;}.mb-2{margin-bottom:0.5rem;}.mr-2{margin-right:0.5rem;}.display-none{display:none;}.children-h-10>*{height:2.5rem;}.h-15rem{height:15rem;}.h-2px{height:2px;}.h-8{height:2rem;}.h-85\%{height:85%;}.h-screen{height:100vh;}.w-8{width:2rem;}.w-screen{width:100vw;}.flex{display:flex;}.flex-1{flex:1 1 0%;}.children-flex-none>*{flex:none;}.children\:grow>*,.grow{flex-grow:1;}.flex-row{flex-direction:row;}.flex-col{flex-direction:column;}.flex-wrap{flex-wrap:wrap;}@keyframes fade-in{from{opacity:0}to{opacity:1}}.animate-fade-in{animation:fade-in 1s linear 1;}.animate-duration-300ms{animation-duration:300ms;}.cursor-ns-resize{cursor:ns-resize;}.cursor-pointer{cursor:pointer;}.select-none{user-select:none;}.items-center{align-items:center;}.self-center{align-self:center;}.justify-center{justify-content:center;}.justify-between{justify-content:space-between;}.gap-1{grid-gap:0.25rem;gap:0.25rem;}.gap-2{grid-gap:0.5rem;gap:0.5rem;}.overflow-hidden{overflow:hidden;}.overflow-y-auto{overflow-y:auto;}.b{border-width:1px;border-style:solid;}.rd-1{border-radius:0.25rem;}.rd-8{border-radius:2rem;}.bg-accent{--un-bg-opacity:1;background-color:rgba(53,120,229,var(--un-bg-opacity));}.bg-black\/20{background-color:rgba(0,0,0,0.2);}.bg-darkPrimaryLighter{--un-bg-opacity:1;background-color:rgba(36,37,38,var(--un-bg-opacity));}.bg-primary{--un-bg-opacity:1;background-color:rgba(255,255,255,var(--un-bg-opacity));}.bg-white\/5{background-color:rgba(255,255,255,0.05);}.dark .dark\:bg-darkAccent{--un-bg-opacity:1;background-color:rgba(103,214,237,var(--un-bg-opacity));}.dark .dark\:bg-darkPrimary{--un-bg-opacity:1;background-color:rgba(27,27,29,var(--un-bg-opacity));}.dark .dark\:hover\:bg-darkHoverOverlay:hover{--un-bg-opacity:.05;background-color:hsla(0,0%,100%,var(--un-bg-opacity));}.hover\:bg-hoverOverlay:hover{--un-bg-opacity:.05;background-color:rgba(0,0,0,var(--un-bg-opacity));}.active\:bg-accentDark:active{--un-bg-opacity:1;background-color:rgba(48,108,206,var(--un-bg-opacity));}.active\:bg-hoverOverlay\/25:active{background-color:rgba(0,0,0,0.25);}.dark .dark\:active\:bg-darkAccentDark:active{--un-bg-opacity:1;background-color:rgba(73,206,233,var(--un-bg-opacity));}.dark .dark\:active\:bg-darkHoverOverlay\/25:active{background-color:hsla(0,0%,100%,0.25);}.p-1{padding:0.25rem;}.p-7{padding:1.75rem;}.px{padding-left:1rem;padding-right:1rem;}.px-2{padding-left:0.5rem;padding-right:0.5rem;}.px-5{padding-left:1.25rem;padding-right:1.25rem;}.children-pb-2>*{padding-bottom:0.5rem;}.children-pt8>*{padding-top:2rem;}.all\:font-mono *{font-family:"Fira Code","Fira Mono",ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;}.all\:text-xs *{font-size:0.75rem;line-height:1rem;}.text-sm{font-size:0.875rem;line-height:1.25rem;}.font-700{font-weight:700;}.font-semibold{font-weight:600;}.dark .dark\:text-darkAccent{--un-text-opacity:1;color:rgba(103,214,237,var(--un-text-opacity));}.dark .dark\:text-darkPrimaryText{--un-text-opacity:1;color:rgba(227,227,227,var(--un-text-opacity));}.text-accent{--un-text-opacity:1;color:rgba(53,120,229,var(--un-text-opacity));}.text-primaryText{--un-text-opacity:1;color:rgba(28,30,33,var(--un-text-opacity));}.blur{--un-blur:blur(8px);filter:var(--un-blur) var(--un-brightness) var(--un-contrast) var(--un-drop-shadow) var(--un-grayscale) var(--un-hue-rotate) var(--un-invert) var(--un-saturate) var(--un-sepia);}.transition-colors-250{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:250ms;}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;}@media (max-width: 639.9px){.lt-sm\:absolute{position:absolute;}.lt-sm\:z-1999{z-index:1999;}.lt-sm\:h-screen{height:100vh;}.lt-sm\:flex{display:flex;}.lt-sm\:shadow{--un-shadow:var(--un-shadow-inset) 0 1px 3px 0 var(--un-shadow-color, rgba(0,0,0,0.1)),var(--un-shadow-inset) 0 1px 2px -1px var(--un-shadow-color, rgba(0,0,0,0.1));box-shadow:var(--un-ring-offset-shadow, 0 0 #0000), var(--un-ring-shadow, 0 0 #0000), var(--un-shadow);}.lt-sm\:shadow-lg{--un-shadow:var(--un-shadow-inset) 0 10px 15px -3px var(--un-shadow-color, rgba(0,0,0,0.1)),var(--un-shadow-inset) 0 4px 6px -4px var(--un-shadow-color, rgba(0,0,0,0.1));box-shadow:var(--un-ring-offset-shadow, 0 0 #0000), var(--un-ring-shadow, 0 0 #0000), var(--un-shadow);}.lt-sm\:transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;}}*:not(h1,h2,h3,h4,h5,h6){margin:0;padding:0}*{box-sizing:border-box;font-family:Rubik,sans-serif}::-webkit-scrollbar{width:.25rem;height:3px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{border-radius:.25rem}code{padding:.05rem .25rem}code.code-block{padding:.5rem}#sidebar{width:18.75rem}@media screen and (max-width: 640px){#sidebar{--translate-x: -18.75rem;transform:translate(var(--translate-x))}} +*,::before,::after{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x:var(--un-empty,/*!*/ /*!*/);--un-pan-y:var(--un-empty,/*!*/ /*!*/);--un-pinch-zoom:var(--un-empty,/*!*/ /*!*/);--un-scroll-snap-strictness:proximity;--un-ordinal:var(--un-empty,/*!*/ /*!*/);--un-slashed-zero:var(--un-empty,/*!*/ /*!*/);--un-numeric-figure:var(--un-empty,/*!*/ /*!*/);--un-numeric-spacing:var(--un-empty,/*!*/ /*!*/);--un-numeric-fraction:var(--un-empty,/*!*/ /*!*/);--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 #0000;--un-ring-shadow:0 0 #0000;--un-shadow-inset:var(--un-empty,/*!*/ /*!*/);--un-shadow:0 0 #0000;--un-ring-inset:var(--un-empty,/*!*/ /*!*/);--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgba(147,197,253,0.5);--un-blur:var(--un-empty,/*!*/ /*!*/);--un-brightness:var(--un-empty,/*!*/ /*!*/);--un-contrast:var(--un-empty,/*!*/ /*!*/);--un-drop-shadow:var(--un-empty,/*!*/ /*!*/);--un-grayscale:var(--un-empty,/*!*/ /*!*/);--un-hue-rotate:var(--un-empty,/*!*/ /*!*/);--un-invert:var(--un-empty,/*!*/ /*!*/);--un-saturate:var(--un-empty,/*!*/ /*!*/);--un-sepia:var(--un-empty,/*!*/ /*!*/);--un-backdrop-blur:var(--un-empty,/*!*/ /*!*/);--un-backdrop-brightness:var(--un-empty,/*!*/ /*!*/);--un-backdrop-contrast:var(--un-empty,/*!*/ /*!*/);--un-backdrop-grayscale:var(--un-empty,/*!*/ /*!*/);--un-backdrop-hue-rotate:var(--un-empty,/*!*/ /*!*/);--un-backdrop-invert:var(--un-empty,/*!*/ /*!*/);--un-backdrop-opacity:var(--un-empty,/*!*/ /*!*/);--un-backdrop-saturate:var(--un-empty,/*!*/ /*!*/);--un-backdrop-sepia:var(--un-empty,/*!*/ /*!*/);}@font-face { font-family: 'Fira Code'; font-style: normal; font-weight: 400; font-display: swap; src: url(https://fonts.gstatic.com/s/firacode/v22/uU9eCBsR6Z2vfE9aq3bL0fxyUs4tcw4W_D1sFVc.ttf) format('truetype');}@font-face { font-family: 'Fira Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url(https://fonts.gstatic.com/s/firamono/v14/N0bX2SlFPv1weGeLZDtQIQ.ttf) format('truetype');}@font-face { font-family: 'Fira Mono'; font-style: normal; font-weight: 700; font-display: swap; src: url(https://fonts.gstatic.com/s/firamono/v14/N0bS2SlFPv1weGeLZDtondv3mQ.ttf) format('truetype');}@font-face { font-family: 'Rubik'; font-style: normal; font-weight: 400; font-display: swap; src: url(https://fonts.gstatic.com/s/rubik/v28/iJWZBXyIfDnIV5PNhY1KTN7Z-Yh-B4i1UA.ttf) format('truetype');}.i-codicon-clear-all{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 16 16' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='m10 12.6l.7.7l1.6-1.6l1.6 1.6l.8-.7L13 11l1.7-1.6l-.8-.8l-1.6 1.7l-1.6-1.7l-.7.8l1.6 1.6l-1.6 1.6zM1 4h14V3H1v1zm0 3h14V6H1v1zm8 2.5V9H1v1h8v-.5zM9 13v-1H1v1h8z'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-codicon-close{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 16 16' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' fill-rule='evenodd' d='m8 8.707l3.646 3.647l.708-.707L8.707 8l3.647-3.646l-.707-.708L8 7.293L4.354 3.646l-.707.708L7.293 8l-3.646 3.646l.707.708L8 8.707z' clip-rule='evenodd'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-codicon-hubot{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 16 16' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' fill-rule='evenodd' d='M8.48 4h4l.5.5v2.03h.52l.5.5V8l-.5.5h-.52v3l-.5.5H9.36l-2.5 2.76L6 14.4V12H3.5l-.5-.64V8.5h-.5L2 8v-.97l.5-.5H3V4.36L3.53 4h4V2.86A1 1 0 0 1 7 2a1 1 0 0 1 2 0a1 1 0 0 1-.52.83V4zM12 8V5H4v5.86l2.5.14H7v2.19l1.8-2.04l.35-.15H12V8zm-2.12.51a2.71 2.71 0 0 1-1.37.74v-.01a2.71 2.71 0 0 1-2.42-.74l-.7.71c.34.34.745.608 1.19.79c.45.188.932.286 1.42.29a3.7 3.7 0 0 0 2.58-1.07l-.7-.71zM6.49 6.5h-1v1h1v-1zm3 0h1v1h-1v-1z' clip-rule='evenodd'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-codicon-link-external{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 16 16' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cg fill='currentColor'%3E%3Cpath d='M1.5 1H6v1H2v12h12v-4h1v4.5l-.5.5h-13l-.5-.5v-13l.5-.5z'/%3E%3Cpath d='M15 1.5V8h-1V2.707L7.243 9.465l-.707-.708L13.293 2H8V1h6.5l.5.5z'/%3E%3C/g%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-codicon-menu{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 16 16' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M16 5H0V4h16v1zm0 8H0v-1h16v1zm0-4.008H0V8h16v.992z'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-codicon-radio-tower{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 16 16' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' fill-rule='evenodd' d='M2.998 5.58a5.55 5.55 0 0 1 1.62-3.88l-.71-.7a6.45 6.45 0 0 0 0 9.16l.71-.7a5.55 5.55 0 0 1-1.62-3.88zm1.06 0a4.42 4.42 0 0 0 1.32 3.17l.71-.71a3.27 3.27 0 0 1-.76-1.12a3.45 3.45 0 0 1 0-2.67a3.22 3.22 0 0 1 .76-1.13l-.71-.71a4.46 4.46 0 0 0-1.32 3.17zm7.65 3.21l-.71-.71c.33-.32.59-.704.76-1.13a3.449 3.449 0 0 0 0-2.67a3.22 3.22 0 0 0-.76-1.13l.71-.7a4.468 4.468 0 0 1 0 6.34zM13.068 1l-.71.71a5.43 5.43 0 0 1 0 7.74l.71.71a6.45 6.45 0 0 0 0-9.16zM9.993 5.43a1.5 1.5 0 0 1-.245.98a2 2 0 0 1-.27.23l3.44 7.73l-.92.4l-.77-1.73h-5.54l-.77 1.73l-.92-.4l3.44-7.73a1.52 1.52 0 0 1-.33-1.63a1.55 1.55 0 0 1 .56-.68a1.5 1.5 0 0 1 2.325 1.1zm-1.595-.34a.52.52 0 0 0-.25.14a.52.52 0 0 0-.11.22a.48.48 0 0 0 0 .29c.04.09.102.17.18.23a.54.54 0 0 0 .28.08a.51.51 0 0 0 .5-.5a.54.54 0 0 0-.08-.28a.58.58 0 0 0-.23-.18a.48.48 0 0 0-.29 0zm.23 2.05h-.27l-.87 1.94h2l-.86-1.94zm2.2 4.94l-.89-2h-2.88l-.89 2h4.66z' clip-rule='evenodd'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-codicon-window{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 16 16' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M14.5 2h-13l-.5.5v11l.5.5h13l.5-.5v-11l-.5-.5zM14 13H2V6h12v7zm0-8H2V3h12v2z'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-ph-broadcast{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 256 256' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M128 88a40 40 0 1 0 40 40a40 40 0 0 0-40-40Zm0 64a24 24 0 1 1 24-24a24 24 0 0 1-24 24Zm73.71 7.14a80 80 0 0 1-14.08 22.2a8 8 0 0 1-11.92-10.67a63.95 63.95 0 0 0 0-85.33a8 8 0 1 1 11.92-10.67a80.08 80.08 0 0 1 14.08 84.47ZM69 103.09a64 64 0 0 0 11.26 67.58a8 8 0 0 1-11.92 10.67a79.93 79.93 0 0 1 0-106.67a8 8 0 1 1 11.95 10.67A63.77 63.77 0 0 0 69 103.09ZM248 128a119.58 119.58 0 0 1-34.29 84a8 8 0 1 1-11.42-11.2a103.9 103.9 0 0 0 0-145.56A8 8 0 1 1 213.71 44A119.58 119.58 0 0 1 248 128ZM53.71 200.78A8 8 0 1 1 42.29 212a119.87 119.87 0 0 1 0-168a8 8 0 1 1 11.42 11.2a103.9 103.9 0 0 0 0 145.56Z'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-ph-chat-teardrop-text{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 256 256' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M168 112a8 8 0 0 1-8 8H96a8 8 0 0 1 0-16h64a8 8 0 0 1 8 8Zm-8 24H96a8 8 0 0 0 0 16h64a8 8 0 0 0 0-16Zm72-12a100.11 100.11 0 0 1-100 100H47.67A15.69 15.69 0 0 1 32 208.33V124a100 100 0 0 1 200 0Zm-16 0a84 84 0 0 0-168 0v84h84a84.09 84.09 0 0 0 84-84Z'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-ph-check-duotone{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 256 256' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cg fill='currentColor'%3E%3Cpath d='M232 56v144a16 16 0 0 1-16 16H40a16 16 0 0 1-16-16V56a16 16 0 0 1 16-16h176a16 16 0 0 1 16 16Z' opacity='.2'/%3E%3Cpath d='m205.66 85.66l-96 96a8 8 0 0 1-11.32 0l-40-40a8 8 0 0 1 11.32-11.32L104 164.69l90.34-90.35a8 8 0 0 1 11.32 11.32Z'/%3E%3C/g%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-ph-globe-stand{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 256 256' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M128 176a80 80 0 1 0-80-80a80.09 80.09 0 0 0 80 80Zm0-144a64 64 0 1 1-64 64a64.07 64.07 0 0 1 64-64Zm77.77 133.5a8 8 0 0 1-.23 11.32a111.24 111.24 0 0 1-69.54 30.9V224h24a8 8 0 0 1 0 16H96a8 8 0 0 1 0-16h24v-16.29A112 112 0 0 1 47.18 18.46a8 8 0 1 1 11.54 11.08a96 96 0 0 0 135.74 135.74a8 8 0 0 1 11.31.22Z'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-ph-hand-waving{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 256 256' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='m220.2 100l-18-31.18a28 28 0 0 0-47.3-1.92l-15.34-26.59a28 28 0 0 0-48.12-.63a28 28 0 0 0-43 34.78l3.34 5.79a28 28 0 0 0-22 41.92l38 65.82a87.46 87.46 0 0 0 53.43 41a88.56 88.56 0 0 0 22.92 3A88 88 0 0 0 220.2 100Zm-6.67 62.63A72 72 0 0 1 81.63 180l-38-65.82a12 12 0 0 1 20.79-12l22 38.1a8 8 0 1 0 13.85-8l-38-65.81a12 12 0 0 1 13.5-17.59a11.9 11.9 0 0 1 7.29 5.59l34 58.89a8 8 0 0 0 13.85-8l-26-45a12 12 0 0 1 20.78-12L160 107.78a48.08 48.08 0 0 0-11 61a8 8 0 0 0 13.86-8a32 32 0 0 1 11.71-43.71a8 8 0 0 0 2.93-10.93l-10-17.32a12 12 0 0 1 20.78-12l18 31.18a71.49 71.49 0 0 1 7.25 54.62Zm-29.26-132.7a8 8 0 0 1 9.8-5.66c15.91 4.27 29 14.11 36.86 27.73a8 8 0 0 1-13.86 8c-5.72-9.92-15.36-17.12-27.14-20.27a8 8 0 0 1-5.66-9.8ZM80.91 237a8 8 0 0 1-11.24 1.33c-11-8.69-20.11-19.58-28.6-34.28a8 8 0 0 1 13.86-8c7.44 12.88 15.27 22.32 24.65 29.72A8 8 0 0 1 80.91 237Z'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-ph-images-square{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 256 256' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M208 32H80a16 16 0 0 0-16 16v16H48a16 16 0 0 0-16 16v128a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16v-16h16a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16ZM80 48h128v69.38l-16.7-16.7a16 16 0 0 0-22.62 0L93.37 176H80Zm96 160H48V80h16v96a16 16 0 0 0 16 16h96Zm32-32h-92l64-64l28 28v36Zm-88-64a24 24 0 1 0-24-24a24 24 0 0 0 24 24Zm0-32a8 8 0 1 1-8 8a8 8 0 0 1 8-8Z'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-ph-list{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 256 256' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M224 128a8 8 0 0 1-8 8H40a8 8 0 0 1 0-16h176a8 8 0 0 1 8 8ZM40 72h176a8 8 0 0 0 0-16H40a8 8 0 0 0 0 16Zm176 112H40a8 8 0 0 0 0 16h176a8 8 0 0 0 0-16Z'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-ph-moon{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 256 256' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M233.54 142.23a8 8 0 0 0-8-2a88.08 88.08 0 0 1-109.8-109.8a8 8 0 0 0-10-10a104.84 104.84 0 0 0-52.91 37A104 104 0 0 0 136 224a103.09 103.09 0 0 0 62.52-20.88a104.84 104.84 0 0 0 37-52.91a8 8 0 0 0-1.98-7.98Zm-44.64 48.11A88 88 0 0 1 65.66 67.11a89 89 0 0 1 31.4-26A106 106 0 0 0 96 56a104.11 104.11 0 0 0 104 104a106 106 0 0 0 14.92-1.06a89 89 0 0 1-26.02 31.4Z'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-ph-square-duotone{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 256 256' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cg fill='currentColor'%3E%3Cpath d='M216 48v160a8 8 0 0 1-8 8H48a8 8 0 0 1-8-8V48a8 8 0 0 1 8-8h160a8 8 0 0 1 8 8Z' opacity='.2'/%3E%3Cpath d='M208 32H48a16 16 0 0 0-16 16v160a16 16 0 0 0 16 16h160a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16Zm0 176H48V48h160v160Z'/%3E%3C/g%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-ph-sun{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 256 256' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M120 40V16a8 8 0 0 1 16 0v24a8 8 0 0 1-16 0Zm72 88a64 64 0 1 1-64-64a64.07 64.07 0 0 1 64 64Zm-16 0a48 48 0 1 0-48 48a48.05 48.05 0 0 0 48-48ZM58.34 69.66a8 8 0 0 0 11.32-11.32l-16-16a8 8 0 0 0-11.32 11.32Zm0 116.68l-16 16a8 8 0 0 0 11.32 11.32l16-16a8 8 0 0 0-11.32-11.32ZM192 72a8 8 0 0 0 5.66-2.34l16-16a8 8 0 0 0-11.32-11.32l-16 16A8 8 0 0 0 192 72Zm5.66 114.34a8 8 0 0 0-11.32 11.32l16 16a8 8 0 0 0 11.32-11.32ZM48 128a8 8 0 0 0-8-8H16a8 8 0 0 0 0 16h24a8 8 0 0 0 8-8Zm80 80a8 8 0 0 0-8 8v24a8 8 0 0 0 16 0v-24a8 8 0 0 0-8-8Zm112-88h-24a8 8 0 0 0 0 16h24a8 8 0 0 0 0-16Z'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.i-ph-tray{--un-icon:url("data:image/svg+xml;utf8,%3Csvg preserveAspectRatio='xMidYMid meet' viewBox='0 0 256 256' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M208 32H48a16 16 0 0 0-16 16v160a16 16 0 0 0 16 16h160a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16Zm0 16v104h-28.7a15.86 15.86 0 0 0-11.3 4.69L148.69 176h-41.38L88 156.69A15.86 15.86 0 0 0 76.69 152H48V48Zm0 160H48v-40h28.69L96 187.31a15.86 15.86 0 0 0 11.31 4.69h41.38a15.86 15.86 0 0 0 11.31-4.69L179.31 168H208v40Z'/%3E%3C/svg%3E");mask:var(--un-icon) no-repeat;mask-size:100% 100%;-webkit-mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;background-color:currentColor;width:1em;height:1em;}.note-red{position:relative;display:inline-flex;align-items:center;border-left-width:4px;border-left-style:solid;--un-border-opacity:1;border-color:rgba(53,120,229,var(--un-border-opacity));border-radius:0.25rem;background-color:rgba(53,120,229,0.1);background-color:rgba(185,28,28,0.1);padding:0.5rem;text-decoration:none;}.nv{position:relative;display:flex;align-items:center;border-radius:0.25rem;padding:0.5rem;--un-text-opacity:1;color:rgba(194,197,202,var(--un-text-opacity));text-decoration:none;transition-property:all;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:125ms;}.nv_selected{position:relative;display:flex;align-items:center;border-left-width:4px;border-left-style:solid;border-radius:0.25rem;--un-bg-opacity:.05;background-color:hsla(0,0%,100%,var(--un-bg-opacity));padding:0.5rem;--un-text-opacity:1;color:rgba(194,197,202,var(--un-text-opacity));color:rgba(53,120,229,var(--un-text-opacity));text-decoration:none;transition-property:all;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:125ms;}.input{height:2.5rem;display:flex;align-items:center;border-radius:0.25rem;border-style:none;--un-bg-opacity:1;background-color:rgba(233,236,239,var(--un-bg-opacity));padding:0.5rem;--un-text-opacity:1;color:rgba(28,30,33,var(--un-text-opacity));--un-shadow:var(--un-shadow-inset) 0 4px 6px -1px var(--un-shadow-color, rgba(0,0,0,0.1)),var(--un-shadow-inset) 0 2px 4px -2px var(--un-shadow-color, rgba(0,0,0,0.1));box-shadow:var(--un-ring-offset-shadow, 0 0 #0000), var(--un-ring-shadow, 0 0 #0000), var(--un-shadow);outline:2px solid transparent;outline-offset:2px;}.btn{user-select:none;border-radius:0.25rem;border-style:none;--un-bg-opacity:1;background-color:rgba(53,120,229,var(--un-bg-opacity));padding:0.5rem;font-weight:400;--un-text-opacity:1;color:rgba(28,30,33,var(--un-text-opacity));color:rgba(255,255,255,var(--un-text-opacity));--un-shadow:var(--un-shadow-inset) 0 4px 6px -1px var(--un-shadow-color, rgba(0,0,0,0.1)),var(--un-shadow-inset) 0 2px 4px -2px var(--un-shadow-color, rgba(0,0,0,0.1));box-shadow:var(--un-ring-offset-shadow, 0 0 #0000), var(--un-ring-shadow, 0 0 #0000), var(--un-shadow);outline:2px solid transparent;outline-offset:2px;}.nv_selected:hover,.nv:hover{border-left-width:4px;border-left-style:solid;--un-bg-opacity:.05;background-color:hsla(0,0%,100%,var(--un-bg-opacity));--un-text-opacity:1;color:rgba(53,120,229,var(--un-text-opacity));}.dark .note-red{--un-border-opacity:1;border-color:rgba(103,214,237,var(--un-border-opacity));background-color:rgba(103,214,237,0.1);background-color:rgba(185,28,28,0.1);}.btn:hover{--un-bg-opacity:1;background-color:rgba(45,102,195,var(--un-bg-opacity));}.dark .btn{--un-bg-opacity:1;background-color:rgba(103,214,237,var(--un-bg-opacity));font-weight:600;--un-text-opacity:1;color:rgba(28,30,33,var(--un-text-opacity));}.dark .btn:hover{--un-bg-opacity:1;background-color:rgba(57,202,232,var(--un-bg-opacity));}.dark .input{--un-bg-opacity:1;background-color:rgba(36,37,38,var(--un-bg-opacity));--un-text-opacity:1;color:rgba(227,227,227,var(--un-text-opacity));}.dark .note-red::after,.note-red::after{--un-bg-opacity:1;background-color:rgba(185,28,28,var(--un-bg-opacity));}.btn:active{--un-bg-opacity:1;background-color:rgba(37,84,160,var(--un-bg-opacity));}.dark .btn:active{--un-bg-opacity:1;background-color:rgba(25,181,213,var(--un-bg-opacity));}.dark .nv_selected,.dark .nv_selected:hover,.dark .nv:hover{--un-text-opacity:1;color:rgba(103,214,237,var(--un-text-opacity));} ::-webkit-scrollbar-thumb { background-color: #3578E5; } .dark ::-webkit-scrollbar-thumb { background-color: #67d6ed; } code { font-size: 0.75rem; font-family: "Fira Code","Fira Mono",ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace; border-radius: 0.25rem; background-color: #d6d8da; } .code-block { font-family: "Fira Code","Fira Mono",ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace; font-size: 0.875rem; } .dark code { background-color: #282a2e; } .visible{visibility:visible;}.absolute{position:absolute;}.left-2{left:0.5rem;}.top-2{top:0.5rem;}.z-2000{z-index:2000;}.grid{display:grid;}.grid-rows-\[2fr_auto\]{grid-template-rows:2fr auto;}.grid-rows-\[2px_2rem_1fr\]{grid-template-rows:2px 2rem 1fr;}.grid-rows-\[auto_1fr\]{grid-template-rows:auto 1fr;}.grid-rows-\[min-content_auto\]{grid-template-rows:min-content auto;}.mb-2{margin-bottom:0.5rem;}.mr-2{margin-right:0.5rem;}.display-none{display:none;}.children-h-10>*{height:2.5rem;}.h-15rem{height:15rem;}.h-2px{height:2px;}.h-8{height:2rem;}.h-85\%{height:85%;}.h-screen{height:100vh;}.w-1px{width:1px;}.w-8{width:2rem;}.w-screen{width:100vw;}.flex{display:flex;}.flex-1{flex:1 1 0%;}.children-flex-none>*{flex:none;}.flex-shrink-0{flex-shrink:0;}.children\:grow>*,.grow{flex-grow:1;}.flex-grow-0{flex-grow:0;}.flex-row{flex-direction:row;}.flex-col{flex-direction:column;}.flex-wrap{flex-wrap:wrap;}@keyframes fade-in{from{opacity:0}to{opacity:1}}.animate-fade-in{animation:fade-in 1s linear 1;}.animate-duration-300ms{animation-duration:300ms;}.cursor-ns-resize{cursor:ns-resize;}.cursor-pointer{cursor:pointer;}.select-none{user-select:none;}.items-center{align-items:center;}.self-center{align-self:center;}.justify-center{justify-content:center;}.justify-between{justify-content:space-between;}.gap-1{grid-gap:0.25rem;gap:0.25rem;}.gap-2{grid-gap:0.5rem;gap:0.5rem;}.overflow-hidden{overflow:hidden;}.overflow-y-auto{overflow-y:auto;}.b{border-width:1px;border-style:solid;}.rd-1{border-radius:0.25rem;}.rd-8{border-radius:2rem;}.bg-accent{--un-bg-opacity:1;background-color:rgba(53,120,229,var(--un-bg-opacity));}.bg-black\/20{background-color:rgba(0,0,0,0.2);}.bg-darkPrimaryLighter{--un-bg-opacity:1;background-color:rgba(36,37,38,var(--un-bg-opacity));}.bg-gray\/30{background-color:rgba(156,163,175,0.3);}.bg-primary{--un-bg-opacity:1;background-color:rgba(255,255,255,var(--un-bg-opacity));}.bg-white\/5,.dark .dark\:bg-white\/5{background-color:rgba(255,255,255,0.05);}.dark .dark\:bg-darkAccent{--un-bg-opacity:1;background-color:rgba(103,214,237,var(--un-bg-opacity));}.dark .dark\:bg-darkPrimary{--un-bg-opacity:1;background-color:rgba(27,27,29,var(--un-bg-opacity));}.dark .dark\:hover\:bg-darkHoverOverlay:hover{--un-bg-opacity:.05;background-color:hsla(0,0%,100%,var(--un-bg-opacity));}.hover\:bg-hoverOverlay:hover{--un-bg-opacity:.05;background-color:rgba(0,0,0,var(--un-bg-opacity));}.active\:bg-accentDark:active{--un-bg-opacity:1;background-color:rgba(48,108,206,var(--un-bg-opacity));}.active\:bg-hoverOverlay\/25:active{background-color:rgba(0,0,0,0.25);}.dark .dark\:active\:bg-darkAccentDark:active{--un-bg-opacity:1;background-color:rgba(73,206,233,var(--un-bg-opacity));}.dark .dark\:active\:bg-darkHoverOverlay\/25:active{background-color:hsla(0,0%,100%,0.25);}.p-1{padding:0.25rem;}.p-7{padding:1.75rem;}.px{padding-left:1rem;padding-right:1rem;}.px-2{padding-left:0.5rem;padding-right:0.5rem;}.px-5{padding-left:1.25rem;padding-right:1.25rem;}.children-pb-2>*{padding-bottom:0.5rem;}.children-pt8>*{padding-top:2rem;}.all\:font-mono *{font-family:"Fira Code","Fira Mono",ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;}.all\:text-xs *{font-size:0.75rem;line-height:1rem;}.text-sm{font-size:0.875rem;line-height:1.25rem;}.font-700{font-weight:700;}.font-semibold{font-weight:600;}.dark .dark\:text-darkAccent{--un-text-opacity:1;color:rgba(103,214,237,var(--un-text-opacity));}.dark .dark\:text-darkPrimaryText{--un-text-opacity:1;color:rgba(227,227,227,var(--un-text-opacity));}.text-accent{--un-text-opacity:1;color:rgba(53,120,229,var(--un-text-opacity));}.text-primaryText{--un-text-opacity:1;color:rgba(28,30,33,var(--un-text-opacity));}.blur{--un-blur:blur(8px);filter:var(--un-blur) var(--un-brightness) var(--un-contrast) var(--un-drop-shadow) var(--un-grayscale) var(--un-hue-rotate) var(--un-invert) var(--un-saturate) var(--un-sepia);}.transition-colors-250{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:250ms;}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;}@media (max-width: 639.9px){.lt-sm\:absolute{position:absolute;}.lt-sm\:z-1999{z-index:1999;}.lt-sm\:h-screen{height:100vh;}.lt-sm\:flex{display:flex;}.lt-sm\:shadow{--un-shadow:var(--un-shadow-inset) 0 1px 3px 0 var(--un-shadow-color, rgba(0,0,0,0.1)),var(--un-shadow-inset) 0 1px 2px -1px var(--un-shadow-color, rgba(0,0,0,0.1));box-shadow:var(--un-ring-offset-shadow, 0 0 #0000), var(--un-ring-shadow, 0 0 #0000), var(--un-shadow);}.lt-sm\:shadow-lg{--un-shadow:var(--un-shadow-inset) 0 10px 15px -3px var(--un-shadow-color, rgba(0,0,0,0.1)),var(--un-shadow-inset) 0 4px 6px -4px var(--un-shadow-color, rgba(0,0,0,0.1));box-shadow:var(--un-ring-offset-shadow, 0 0 #0000), var(--un-ring-shadow, 0 0 #0000), var(--un-shadow);}.lt-sm\:transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;}}*:not(h1,h2,h3,h4,h5,h6){margin:0;padding:0}*{box-sizing:border-box;font-family:Rubik,sans-serif}::-webkit-scrollbar{width:.25rem;height:3px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{border-radius:.25rem}code{padding:.05rem .25rem}code.code-block{padding:.5rem}#sidebar{width:18.75rem}@media screen and (max-width: 640px){#sidebar{--translate-x: -18.75rem;transform:translate(var(--translate-x))}} diff --git a/examples/api/dist/assets/index.js b/examples/api/dist/assets/index.js index 88acdd8fca5e..cf83e747ab0b 100644 --- a/examples/api/dist/assets/index.js +++ b/examples/api/dist/assets/index.js @@ -1,41 +1,43 @@ -var Rs=Object.defineProperty;var Hs=(e,t,n)=>t in e?Rs(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var ft=(e,t,n)=>(Hs(e,typeof t!="symbol"?t+"":t,n),n);(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))i(o);new MutationObserver(o=>{for(const r of o)if(r.type==="childList")for(const g of r.addedNodes)g.tagName==="LINK"&&g.rel==="modulepreload"&&i(g)}).observe(document,{childList:!0,subtree:!0});function n(o){const r={};return o.integrity&&(r.integrity=o.integrity),o.referrerPolicy&&(r.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?r.credentials="include":o.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function i(o){if(o.ep)return;o.ep=!0;const r=n(o);fetch(o.href,r)}})();function ee(){}function Es(e){return e()}function is(){return Object.create(null)}function je(e){e.forEach(Es)}function Is(e){return typeof e=="function"}function Ot(e,t){return e!=e?t==t:e!==t||e&&typeof e=="object"||typeof e=="function"}let Sl;function Fs(e,t){return e===t?!0:(Sl||(Sl=document.createElement("a")),Sl.href=t,e===Sl.href)}function Us(e){return Object.keys(e).length===0}function qs(e,...t){if(e==null){for(const i of t)i(void 0);return ee}const n=e.subscribe(...t);return n.unsubscribe?()=>n.unsubscribe():n}function Bs(e,t,n){e.$$.on_destroy.push(qs(t,n))}function l(e,t){e.appendChild(t)}function w(e,t,n){e.insertBefore(t,n||null)}function m(e){e.parentNode&&e.parentNode.removeChild(e)}function Pt(e,t){for(let n=0;ne.removeEventListener(t,n,i)}function ss(e){return function(t){return t.preventDefault(),e.call(this,t)}}function a(e,t,n){n==null?e.removeAttribute(t):e.getAttribute(t)!==n&&e.setAttribute(t,n)}function q(e){return e===""?null:+e}function Vs(e){return Array.from(e.childNodes)}function se(e,t){t=""+t,e.data!==t&&(e.data=t)}function E(e,t){e.value=t??""}function Qt(e,t,n,i){n==null?e.style.removeProperty(t):e.style.setProperty(t,n,i?"important":"")}function Ke(e,t,n){for(let i=0;ie.indexOf(i)===-1?t.push(i):n.push(i)),n.forEach(i=>i()),$t=t}const zl=new Set;let St;function Zs(){St={r:0,c:[],p:St}}function Js(){St.r||je(St.c),St=St.p}function ri(e,t){e&&e.i&&(zl.delete(e),e.i(t))}function rs(e,t,n,i){if(e&&e.o){if(zl.has(e))return;zl.add(e),St.c.push(()=>{zl.delete(e),i&&(n&&e.d(1),i())}),e.o(t)}else i&&i()}function ye(e){return(e==null?void 0:e.length)!==void 0?e:Array.from(e)}function us(e){e&&e.c()}function ui(e,t,n){const{fragment:i,after_update:o}=e.$$;i&&i.m(t,n),ht(()=>{const r=e.$$.on_mount.map(Es).filter(Is);e.$$.on_destroy?e.$$.on_destroy.push(...r):je(r),e.$$.on_mount=[]}),o.forEach(ht)}function ci(e,t){const n=e.$$;n.fragment!==null&&(Qs(n.after_update),je(n.on_destroy),n.fragment&&n.fragment.d(t),n.on_destroy=n.fragment=null,n.ctx=[])}function xs(e,t){e.$$.dirty[0]===-1&&(xt.push(e),Ys(),e.$$.dirty.fill(0)),e.$$.dirty[t/31|0]|=1<{const I=S.length?S[0]:Y;return d.ctx&&o(d.ctx[L],d.ctx[L]=I)&&(!d.skip_bound&&d.bound[L]&&d.bound[L](I),W&&xs(e,L)),Y}):[],d.update(),W=!0,je(d.before_update),d.fragment=i?i(d.ctx):!1,t.target){if(t.hydrate){const L=Vs(t.target);d.fragment&&d.fragment.l(L),L.forEach(m)}else d.fragment&&d.fragment.c();t.intro&&ri(e.$$.fragment),ui(e,t.target,t.anchor),As()}kn(b)}class nn{constructor(){ft(this,"$$");ft(this,"$$set")}$destroy(){ci(this,1),this.$destroy=ee}$on(t,n){if(!Is(n))return ee;const i=this.$$.callbacks[t]||(this.$$.callbacks[t]=[]);return i.push(n),()=>{const o=i.indexOf(n);o!==-1&&i.splice(o,1)}}$set(t){this.$$set&&!Us(t)&&(this.$$.skip_bound=!0,this.$$set(t),this.$$.skip_bound=!1)}}const $s="4";typeof window<"u"&&(window.__svelte||(window.__svelte={v:new Set})).v.add($s);const Jt=[];function eo(e,t=ee){let n;const i=new Set;function o(h){if(Ot(e,h)&&(e=h,n)){const b=!Jt.length;for(const d of i)d[1](),Jt.push(d,e);if(b){for(let d=0;d{i.delete(d),i.size===0&&n&&(n(),n=null)}}return{set:o,update:r,subscribe:g}}function to(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}async function _(e,t={},n){return window.__TAURI_INTERNALS__.invoke(e,t,n)}async function no(){return _("plugin:app|version")}async function lo(){return _("plugin:app|name")}async function io(){return _("plugin:app|tauri_version")}async function so(){return _("plugin:app|app_show")}async function oo(){return _("plugin:app|app_hide")}function ao(e){let t,n,i,o,r,g,h,b,d,W,L,Y,S,I,M,D,ae,H,N,V,G,O,B,re;return{c(){t=s("div"),n=s("p"),n.innerHTML=`This is a demo of Tauri's API capabilities using the @tauri-apps/api package. It's used as the main validation app, serving as the test bed of our +var br=Object.defineProperty;var wr=(t,e,n)=>e in t?br(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var _t=(t,e,n)=>(wr(t,typeof e!="symbol"?e+"":e,n),n);(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))l(s);new MutationObserver(s=>{for(const u of s)if(u.type==="childList")for(const d of u.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&l(d)}).observe(document,{childList:!0,subtree:!0});function n(s){const u={};return s.integrity&&(u.integrity=s.integrity),s.referrerPolicy&&(u.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?u.credentials="include":s.crossOrigin==="anonymous"?u.credentials="omit":u.credentials="same-origin",u}function l(s){if(s.ep)return;s.ep=!0;const u=n(s);fetch(s.href,u)}})();function ne(){}function lr(t){return t()}function Ms(){return Object.create(null)}function Ce(t){t.forEach(lr)}function sr(t){return typeof t=="function"}function je(t,e){return t!=t?e==e:t!==e||t&&typeof t=="object"||typeof t=="function"}let Vi;function kr(t,e){return t===e?!0:(Vi||(Vi=document.createElement("a")),Vi.href=e,t===Vi.href)}function yr(t){return Object.keys(t).length===0}function vr(t,...e){if(t==null){for(const l of e)l(void 0);return ne}const n=t.subscribe(...e);return n.unsubscribe?()=>n.unsubscribe():n}function Cr(t,e,n){t.$$.on_destroy.push(vr(e,n))}function i(t,e){t.appendChild(e)}function L(t,e,n){t.insertBefore(e,n||null)}function S(t){t.parentNode&&t.parentNode.removeChild(t)}function Je(t,e){for(let n=0;nt.removeEventListener(e,n,l)}function Ps(t){return function(e){return e.preventDefault(),t.call(this,e)}}function a(t,e,n){n==null?t.removeAttribute(e):t.getAttribute(e)!==n&&t.setAttribute(e,n)}function X(t){return t===""?null:+t}function Lr(t){return Array.from(t.childNodes)}function se(t,e){e=""+e,t.data!==e&&(t.data=e)}function O(t,e){t.value=e??""}function xt(t,e,n,l){n==null?t.style.removeProperty(e):t.style.setProperty(e,n,l?"important":"")}function Qe(t,e,n){for(let l=0;l{const s=t.$$.callbacks[e];if(s){const u=Ar(e,n,{cancelable:l});return s.slice().forEach(d=>{d.call(t,u)}),!u.defaultPrevented}return!0}}const tn=[],On=[];let nn=[];const El=[],Pr=Promise.resolve();let Tl=!1;function Er(){Tl||(Tl=!0,Pr.then(or))}function wt(t){nn.push(t)}function ur(t){El.push(t)}const Sl=new Set;let $t=0;function or(){if($t!==0)return;const t=zn;do{try{for(;$tt.indexOf(l)===-1?e.push(l):n.push(l)),n.forEach(l=>l()),nn=e}const qi=new Set;let zt;function Or(){zt={r:0,c:[],p:zt}}function Wr(){zt.r||Ce(zt.c),zt=zt.p}function sn(t,e){t&&t.i&&(qi.delete(t),t.i(e))}function Wn(t,e,n,l){if(t&&t.o){if(qi.has(t))return;qi.add(t),zt.c.push(()=>{qi.delete(t),l&&(n&&t.d(1),l())}),t.o(e)}else l&&l()}function he(t){return(t==null?void 0:t.length)!==void 0?t:Array.from(t)}function cr(t,e,n){const l=t.$$.props[e];l!==void 0&&(t.$$.bound[l]=n,n(t.$$.ctx[l]))}function In(t){t&&t.c()}function rn(t,e,n){const{fragment:l,after_update:s}=t.$$;l&&l.m(e,n),wt(()=>{const u=t.$$.on_mount.map(lr).filter(sr);t.$$.on_destroy?t.$$.on_destroy.push(...u):Ce(u),t.$$.on_mount=[]}),s.forEach(wt)}function an(t,e){const n=t.$$;n.fragment!==null&&(zr(n.after_update),Ce(n.on_destroy),n.fragment&&n.fragment.d(e),n.on_destroy=n.fragment=null,n.ctx=[])}function Ir(t,e){t.$$.dirty[0]===-1&&(tn.push(t),Er(),t.$$.dirty.fill(0)),t.$$.dirty[e/31|0]|=1<{const y=k.length?k[0]:W;return h.ctx&&s(h.ctx[_],h.ctx[_]=y)&&(!h.skip_bound&&h.bound[_]&&h.bound[_](y),w&&Ir(t,_)),W}):[],h.update(),w=!0,Ce(h.before_update),h.fragment=l?l(h.ctx):!1,e.target){if(e.hydrate){const _=Lr(e.target);h.fragment&&h.fragment.l(_),_.forEach(S)}else h.fragment&&h.fragment.c();e.intro&&sn(t.$$.fragment),rn(t,e.target,e.anchor),or()}Tn(c)}class xe{constructor(){_t(this,"$$");_t(this,"$$set")}$destroy(){an(this,1),this.$destroy=ne}$on(e,n){if(!sr(n))return ne;const l=this.$$.callbacks[e]||(this.$$.callbacks[e]=[]);return l.push(n),()=>{const s=l.indexOf(n);s!==-1&&l.splice(s,1)}}$set(e){this.$$set&&!yr(e)&&(this.$$.skip_bound=!0,this.$$set(e),this.$$.skip_bound=!1)}}const Rr="4";typeof window<"u"&&(window.__svelte||(window.__svelte={v:new Set})).v.add(Rr);const en=[];function Dr(t,e=ne){let n;const l=new Set;function s(o){if(je(t,o)&&(t=o,n)){const c=!en.length;for(const h of l)h[1](),en.push(h,t);if(c){for(let h=0;h{l.delete(h),l.size===0&&n&&(n(),n=null)}}return{set:s,update:u,subscribe:d}}function Rn(t,e,n,l){if(n==="a"&&!l)throw new TypeError("Private accessor was defined without a getter");if(typeof e=="function"?t!==e||!l:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return n==="m"?l:n==="a"?l.call(t):l?l.value:e.get(t)}function Xi(t,e,n,l,s){if(l==="m")throw new TypeError("Private method is not writable");if(l==="a"&&!s)throw new TypeError("Private accessor was defined without a setter");if(typeof e=="function"?t!==e||!s:!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return l==="a"?s.call(t,n):s?s.value=n:e.set(t,n),n}var En;function dr(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}class Il{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,En.set(this,()=>{}),this.id=dr(e=>{Rn(this,En,"f").call(this,e)})}set onmessage(e){Xi(this,En,e,"f")}get onmessage(){return Rn(this,En,"f")}toJSON(){return`__CHANNEL__:${this.id}`}}En=new WeakMap;async function m(t,e={},n){return window.__TAURI_INTERNALS__.invoke(t,e,n)}async function Fr(){return m("plugin:app|version")}async function Hr(){return m("plugin:app|name")}async function Ur(){return m("plugin:app|tauri_version")}async function Br(){return m("plugin:app|app_show")}async function Vr(){return m("plugin:app|app_hide")}function qr(t){let e,n,l,s,u,d,o,c,h,w,_,W,k,y,C,E,V,D,M,I,P,T,R,Y;return{c(){e=r("div"),n=r("p"),n.innerHTML=`This is a demo of Tauri's API capabilities using the @tauri-apps/api package. It's used as the main validation app, serving as the test bed of our development process. In the future, this app will be used on Tauri's integration - tests.`,i=c(),o=s("br"),r=c(),g=s("br"),h=c(),b=s("pre"),d=p(" App name: "),W=s("code"),L=p(e[2]),Y=p(` - App version: `),S=s("code"),I=p(e[0]),M=p(` - Tauri version: `),D=s("code"),ae=p(e[1]),H=p(` - `),N=c(),V=s("br"),G=c(),O=s("button"),O.textContent="Context menu",a(O,"class","btn")},m(T,x){w(T,t,x),l(t,n),l(t,i),l(t,o),l(t,r),l(t,g),l(t,h),l(t,b),l(b,d),l(b,W),l(W,L),l(b,Y),l(b,S),l(S,I),l(b,M),l(b,D),l(D,ae),l(b,H),l(t,N),l(t,V),l(t,G),l(t,O),B||(re=k(O,"click",e[3]),B=!0)},p(T,[x]){x&4&&se(L,T[2]),x&1&&se(I,T[0]),x&2&&se(ae,T[1])},i:ee,o:ee,d(T){T&&m(t),B=!1,re()}}}function ro(e,t,n){let i="1.0.0",o="1.0.0",r="Unknown";lo().then(h=>{n(2,r=h)}),no().then(h=>{n(0,i=h)}),io().then(h=>{n(1,o=h)});function g(){_("popup_context_menu")}return[i,o,r,g]}class uo extends nn{constructor(t){super(),tn(this,t,ro,ao,Ot,{})}}var Se;(function(e){e.WINDOW_RESIZED="tauri://resize",e.WINDOW_MOVED="tauri://move",e.WINDOW_CLOSE_REQUESTED="tauri://close-requested",e.WINDOW_CREATED="tauri://window-created",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_FILE_DROP="tauri://file-drop",e.WINDOW_FILE_DROP_HOVER="tauri://file-drop-hover",e.WINDOW_FILE_DROP_CANCELLED="tauri://file-drop-cancelled",e.MENU="tauri://menu"})(Se||(Se={}));async function Ds(e,t){await _("plugin:event|unlisten",{event:e,eventId:t})}async function hi(e,t,n){return _("plugin:event|listen",{event:e,windowLabel:n==null?void 0:n.target,handler:to(t)}).then(i=>async()=>Ds(e,i))}async function co(e,t,n){return hi(e,i=>{t(i),Ds(e,i.id).catch(()=>{})},n)}async function Ns(e,t,n){await _("plugin:event|emit",{event:e,windowLabel:n==null?void 0:n.target,payload:t})}function fo(e){let t,n,i,o,r,g,h,b;return{c(){t=s("div"),n=s("button"),n.textContent="Call Log API",i=c(),o=s("button"),o.textContent="Call Request (async) API",r=c(),g=s("button"),g.textContent="Send event to Rust",a(n,"class","btn"),a(n,"id","log"),a(o,"class","btn"),a(o,"id","request"),a(g,"class","btn"),a(g,"id","event")},m(d,W){w(d,t,W),l(t,n),l(t,i),l(t,o),l(t,r),l(t,g),h||(b=[k(n,"click",e[0]),k(o,"click",e[1]),k(g,"click",e[2])],h=!0)},p:ee,i:ee,o:ee,d(d){d&&m(t),h=!1,je(b)}}}function ho(e,t,n){let{onMessage:i}=t,o;Pl(async()=>{o=await hi("rust-event",i)}),Ws(()=>{o&&o()});function r(){_("log_operation",{event:"tauri-click",payload:"this payload is optional because we used Option in Rust"})}function g(){_("perform_request",{endpoint:"dummy endpoint arg",body:{id:5,name:"test"}}).then(i).catch(i)}function h(){Ns("js-event","this is the payload string")}return e.$$set=b=>{"onMessage"in b&&n(3,i=b.onMessage)},[r,g,h,i]}class po extends nn{constructor(t){super(),tn(this,t,ho,fo,Ot,{onMessage:3})}}class di{constructor(t,n){this.type="Logical",this.width=t,this.height=n}}class en{constructor(t,n){this.type="Physical",this.width=t,this.height=n}toLogical(t){return new di(this.width/t,this.height/t)}}class bo{constructor(t,n){this.type="Logical",this.x=t,this.y=n}}class zt{constructor(t,n){this.type="Physical",this.x=t,this.y=n}toLogical(t){return new bo(this.x/t,this.y/t)}}var Ol;(function(e){e[e.Critical=1]="Critical",e[e.Informational=2]="Informational"})(Ol||(Ol={}));class _o{constructor(t){this._preventDefault=!1,this.event=t.event,this.windowLabel=t.windowLabel,this.id=t.id}preventDefault(){this._preventDefault=!0}isPreventDefault(){return this._preventDefault}}var El;(function(e){e.None="none",e.Normal="normal",e.Indeterminate="indeterminate",e.Paused="paused",e.Error="error"})(El||(El={}));function Ts(){return new Cn(window.__TAURI_INTERNALS__.metadata.currentWindow.label,{skip:!0})}function si(){return window.__TAURI_INTERNALS__.metadata.windows.map(e=>new Cn(e.label,{skip:!0}))}const cs=["tauri://created","tauri://error"];class Cn{constructor(t,n={}){this.label=t,this.listeners=Object.create(null),n!=null&&n.skip||_("plugin:window|create",{options:{...n,label:t}}).then(async()=>this.emit("tauri://created")).catch(async i=>this.emit("tauri://error",i))}static getByLabel(t){return si().some(n=>n.label===t)?new Cn(t,{skip:!0}):null}static getCurrent(){return Ts()}static getAll(){return si()}static async getFocusedWindow(){for(const t of si())if(await t.isFocused())return t;return null}async listen(t,n){return this._handleTauriEvent(t,n)?Promise.resolve(()=>{const i=this.listeners[t];i.splice(i.indexOf(n),1)}):hi(t,n,{target:this.label})}async once(t,n){return this._handleTauriEvent(t,n)?Promise.resolve(()=>{const i=this.listeners[t];i.splice(i.indexOf(n),1)}):co(t,n,{target:this.label})}async emit(t,n){if(cs.includes(t)){for(const i of this.listeners[t]||[])i({event:t,id:-1,windowLabel:this.label,payload:n});return Promise.resolve()}return Ns(t,n,{target:this.label})}_handleTauriEvent(t,n){return cs.includes(t)?(t in this.listeners?this.listeners[t].push(n):this.listeners[t]=[n],!0):!1}async scaleFactor(){return _("plugin:window|scale_factor",{label:this.label})}async innerPosition(){return _("plugin:window|inner_position",{label:this.label}).then(({x:t,y:n})=>new zt(t,n))}async outerPosition(){return _("plugin:window|outer_position",{label:this.label}).then(({x:t,y:n})=>new zt(t,n))}async innerSize(){return _("plugin:window|inner_size",{label:this.label}).then(({width:t,height:n})=>new en(t,n))}async outerSize(){return _("plugin:window|outer_size",{label:this.label}).then(({width:t,height:n})=>new en(t,n))}async isFullscreen(){return _("plugin:window|is_fullscreen",{label:this.label})}async isMinimized(){return _("plugin:window|is_minimized",{label:this.label})}async isMaximized(){return _("plugin:window|is_maximized",{label:this.label})}async isFocused(){return _("plugin:window|is_focused",{label:this.label})}async isDecorated(){return _("plugin:window|is_decorated",{label:this.label})}async isResizable(){return _("plugin:window|is_resizable",{label:this.label})}async isMaximizable(){return _("plugin:window|is_maximizable",{label:this.label})}async isMinimizable(){return _("plugin:window|is_minimizable",{label:this.label})}async isClosable(){return _("plugin:window|is_closable",{label:this.label})}async isVisible(){return _("plugin:window|is_visible",{label:this.label})}async title(){return _("plugin:window|title",{label:this.label})}async theme(){return _("plugin:window|theme",{label:this.label})}async center(){return _("plugin:window|center",{label:this.label})}async requestUserAttention(t){let n=null;return t&&(t===Ol.Critical?n={type:"Critical"}:n={type:"Informational"}),_("plugin:window|request_user_attention",{label:this.label,value:n})}async setResizable(t){return _("plugin:window|set_resizable",{label:this.label,value:t})}async setMaximizable(t){return _("plugin:window|set_maximizable",{label:this.label,value:t})}async setMinimizable(t){return _("plugin:window|set_minimizable",{label:this.label,value:t})}async setClosable(t){return _("plugin:window|set_closable",{label:this.label,value:t})}async setTitle(t){return _("plugin:window|set_title",{label:this.label,value:t})}async maximize(){return _("plugin:window|maximize",{label:this.label})}async unmaximize(){return _("plugin:window|unmaximize",{label:this.label})}async toggleMaximize(){return _("plugin:window|toggle_maximize",{label:this.label})}async minimize(){return _("plugin:window|minimize",{label:this.label})}async unminimize(){return _("plugin:window|unminimize",{label:this.label})}async show(){return _("plugin:window|show",{label:this.label})}async hide(){return _("plugin:window|hide",{label:this.label})}async close(){return _("plugin:window|close",{label:this.label})}async setDecorations(t){return _("plugin:window|set_decorations",{label:this.label,value:t})}async setShadow(t){return _("plugin:window|set_shadow",{label:this.label,value:t})}async setEffects(t){return _("plugin:window|set_effects",{label:this.label,value:t})}async clearEffects(){return _("plugin:window|set_effects",{label:this.label,value:null})}async setAlwaysOnTop(t){return _("plugin:window|set_always_on_top",{label:this.label,value:t})}async setAlwaysOnBottom(t){return _("plugin:window|set_always_on_bottom",{label:this.label,value:t})}async setContentProtected(t){return _("plugin:window|set_content_protected",{label:this.label,value:t})}async setSize(t){if(!t||t.type!=="Logical"&&t.type!=="Physical")throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return _("plugin:window|set_size",{label:this.label,value:{type:t.type,data:{width:t.width,height:t.height}}})}async setMinSize(t){if(t&&t.type!=="Logical"&&t.type!=="Physical")throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return _("plugin:window|set_min_size",{label:this.label,value:t?{type:t.type,data:{width:t.width,height:t.height}}:null})}async setMaxSize(t){if(t&&t.type!=="Logical"&&t.type!=="Physical")throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return _("plugin:window|set_max_size",{label:this.label,value:t?{type:t.type,data:{width:t.width,height:t.height}}:null})}async setPosition(t){if(!t||t.type!=="Logical"&&t.type!=="Physical")throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");return _("plugin:window|set_position",{label:this.label,value:{type:t.type,data:{x:t.x,y:t.y}}})}async setFullscreen(t){return _("plugin:window|set_fullscreen",{label:this.label,value:t})}async setFocus(){return _("plugin:window|set_focus",{label:this.label})}async setIcon(t){return _("plugin:window|set_icon",{label:this.label,value:typeof t=="string"?t:Array.from(t)})}async setSkipTaskbar(t){return _("plugin:window|set_skip_taskbar",{label:this.label,value:t})}async setCursorGrab(t){return _("plugin:window|set_cursor_grab",{label:this.label,value:t})}async setCursorVisible(t){return _("plugin:window|set_cursor_visible",{label:this.label,value:t})}async setCursorIcon(t){return _("plugin:window|set_cursor_icon",{label:this.label,value:t})}async setCursorPosition(t){if(!t||t.type!=="Logical"&&t.type!=="Physical")throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");return _("plugin:window|set_cursor_position",{label:this.label,value:{type:t.type,data:{x:t.x,y:t.y}}})}async setIgnoreCursorEvents(t){return _("plugin:window|set_ignore_cursor_events",{label:this.label,value:t})}async startDragging(){return _("plugin:window|start_dragging",{label:this.label})}async setProgressBar(t){return _("plugin:window|set_progress_bar",{label:this.label,value:t})}async onResized(t){return this.listen(Se.WINDOW_RESIZED,n=>{n.payload=mo(n.payload),t(n)})}async onMoved(t){return this.listen(Se.WINDOW_MOVED,n=>{n.payload=go(n.payload),t(n)})}async onCloseRequested(t){return this.listen(Se.WINDOW_CLOSE_REQUESTED,n=>{const i=new _o(n);Promise.resolve(t(i)).then(()=>{if(!i.isPreventDefault())return this.close()})})}async onFocusChanged(t){const n=await this.listen(Se.WINDOW_FOCUS,o=>{t({...o,payload:!0})}),i=await this.listen(Se.WINDOW_BLUR,o=>{t({...o,payload:!1})});return()=>{n(),i()}}async onScaleChanged(t){return this.listen(Se.WINDOW_SCALE_FACTOR_CHANGED,t)}async onMenuClicked(t){return this.listen(Se.MENU,t)}async onFileDropEvent(t){const n=await this.listen(Se.WINDOW_FILE_DROP,r=>{t({...r,payload:{type:"drop",paths:r.payload}})}),i=await this.listen(Se.WINDOW_FILE_DROP_HOVER,r=>{t({...r,payload:{type:"hover",paths:r.payload}})}),o=await this.listen(Se.WINDOW_FILE_DROP_CANCELLED,r=>{t({...r,payload:{type:"cancel"}})});return()=>{n(),i(),o()}}async onThemeChanged(t){return this.listen(Se.WINDOW_THEME_CHANGED,t)}}var Il;(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"})(Il||(Il={}));var Ml;(function(e){e.FollowsWindowActiveState="followsWindowActiveState",e.Active="active",e.Inactive="inactive"})(Ml||(Ml={}));function go(e){return new zt(e.x,e.y)}function mo(e){return new en(e.width,e.height)}function ds(e,t,n){const i=e.slice();return i[105]=t[n],i}function fs(e,t,n){const i=e.slice();return i[108]=t[n],i}function hs(e,t,n){const i=e.slice();return i[111]=t[n],i}function ps(e,t,n){const i=e.slice();return i[114]=t[n],i}function bs(e,t,n){const i=e.slice();return i[117]=t[n],i}function _s(e){let t,n,i,o,r,g,h=ye(Object.keys(e[1])),b=[];for(let d=0;de[59].call(i))},m(d,W){w(d,t,W),w(d,n,W),w(d,i,W),l(i,o);for(let L=0;Le[83].call(Je)),a(ut,"class","input"),a(ut,"type","number"),a(ct,"class","input"),a(ct,"type","number"),a(Ze,"class","flex gap-2"),a(dt,"class","input grow"),a(dt,"id","title"),a(mn,"class","btn"),a(mn,"type","submit"),a(Lt,"class","flex gap-1"),a(gn,"class","flex flex-col gap-1"),a(xe,"class","input"),e[26]===void 0&&ht(()=>e[87].call(xe)),a(Ye,"class","input"),a(Ye,"type","number"),a(Ye,"min","0"),a(Ye,"max","100"),a(Xt,"class","flex gap-2"),a(wn,"class","flex flex-col gap-1")},m(u,f){w(u,t,f),w(u,n,f),w(u,i,f),l(i,o),l(i,r),l(i,g),l(g,h),E(h,e[43]),l(g,b),l(g,d),w(u,W,f),w(u,L,f),w(u,Y,f),w(u,S,f),l(S,I),l(S,M),l(S,D),l(S,ae),l(S,H),l(S,N),l(S,V),w(u,G,f),w(u,O,f),l(O,B),l(B,re),l(B,T),T.checked=e[6],l(O,x),l(O,te),l(te,y),l(te,F),F.checked=e[2],l(O,j),l(O,$),l($,ue),l($,K),K.checked=e[3],l(O,ge),l(O,ke),l(ke,de),l(ke,oe),oe.checked=e[4],l(O,Q),l(O,he),l(he,U),l(he,ne),ne.checked=e[5],l(O,J),l(O,v),l(v,X),l(v,z),z.checked=e[7],l(O,fe),l(O,ze),l(ze,me),l(ze,pe),pe.checked=e[8],l(O,We),l(O,Pe),l(Pe,Ae),l(Pe,be),be.checked=e[9],l(O,_e),l(O,Le),l(Le,Oe),l(Le,ce),ce.checked=e[10],l(O,Ce),l(O,le),l(le,De),l(le,Ne),Ne.checked=e[11],w(u,Ee,f),w(u,ie,f),w(u,C,f),w(u,Z,f),l(Z,P),l(P,Ie),l(Ie,Sn),l(Ie,Te),E(Te,e[18]),l(P,zn),l(P,Et),l(Et,Pn),l(Et,Re),E(Re,e[19]),l(Z,On),l(Z,$e),l($e,It),l(It,En),l(It,He),E(He,e[12]),l($e,In),l($e,Mt),l(Mt,Mn),l(Mt,Fe),E(Fe,e[13]),l(Z,Wn),l(Z,et),l(et,Wt),l(Wt,An),l(Wt,Ve),E(Ve,e[14]),l(et,Dn),l(et,At),l(At,Nn),l(At,Ge),E(Ge,e[15]),l(Z,Tn),l(Z,tt),l(tt,Dt),l(Dt,Rn),l(Dt,Ue),E(Ue,e[16]),l(tt,Hn),l(tt,Nt),l(Nt,Fn),l(Nt,qe),E(qe,e[17]),w(u,ln,f),w(u,sn,f),w(u,on,f),w(u,Me,f),l(Me,nt),l(nt,Xe),l(Xe,A),l(Xe,an),l(Xe,pt),l(pt,rn),l(pt,Tt),l(Xe,un),l(Xe,_t),l(_t,cn),l(_t,Rt),l(nt,dn),l(nt,Be),l(Be,mt),l(Be,fn),l(Be,wt),l(wt,hn),l(wt,Ht),l(Be,pn),l(Be,yt),l(yt,bn),l(yt,Ft),l(Me,Un),l(Me,Ut),l(Ut,lt),l(lt,qn),l(lt,pi),l(lt,Bn),l(Bn,bi),l(Bn,Wl),l(lt,_i),l(lt,Vn),l(Vn,gi),l(Vn,Al),l(Ut,mi),l(Ut,it),l(it,Xn),l(it,wi),l(it,Yn),l(Yn,vi),l(Yn,Dl),l(it,yi),l(it,Qn),l(Qn,ki),l(Qn,Nl),l(Me,Li),l(Me,qt),l(qt,st),l(st,Jn),l(st,Ci),l(st,xn),l(xn,Si),l(xn,Tl),l(st,zi),l(st,el),l(el,Pi),l(el,Rl),l(qt,Oi),l(qt,ot),l(ot,nl),l(ot,Ei),l(ot,ll),l(ll,Ii),l(ll,Hl),l(ot,Mi),l(ot,sl),l(sl,Wi),l(sl,Fl),l(Me,Ai),l(Me,Bt),l(Bt,at),l(at,al),l(at,Di),l(at,rl),l(rl,Ni),l(rl,Ul),l(at,Ti),l(at,cl),l(cl,Ri),l(cl,ql),l(Bt,Hi),l(Bt,rt),l(rt,fl),l(rt,Fi),l(rt,hl),l(hl,Ui),l(hl,Bl),l(rt,qi),l(rt,bl),l(bl,Bi),l(bl,jl),w(u,Vl,f),w(u,Gl,f),w(u,Xl,f),w(u,_n,f),w(u,Yl,f),w(u,Qe,f),l(Qe,gl),l(gl,jt),jt.checked=e[20],l(gl,ji),l(Qe,Vi),l(Qe,ml),l(ml,Vt),Vt.checked=e[21],l(ml,Gi),l(Qe,Xi),l(Qe,wl),l(wl,Gt),Gt.checked=e[25],l(wl,Yi),w(u,Kl,f),w(u,Ze,f),l(Ze,vl),l(vl,Ki),l(vl,Je);for(let R=0;Re[89].call(r)),a(d,"class","input"),e[37]===void 0&&ht(()=>e[90].call(d)),a(S,"class","input"),a(S,"type","number"),a(n,"class","flex"),Qt(N,"max-width","120px"),a(N,"class","input"),a(N,"type","number"),a(N,"placeholder","R"),Qt(G,"max-width","120px"),a(G,"class","input"),a(G,"type","number"),a(G,"placeholder","G"),Qt(B,"max-width","120px"),a(B,"class","input"),a(B,"type","number"),a(B,"placeholder","B"),Qt(T,"max-width","120px"),a(T,"class","input"),a(T,"type","number"),a(T,"placeholder","A"),a(H,"class","flex"),a(M,"class","flex"),a(y,"class","btn"),Qt(y,"width","80px"),a(te,"class","flex"),a(de,"class","btn"),Qt(de,"width","80px"),a(j,"class","flex"),a(t,"class","flex flex-col gap-1")},m(v,X){w(v,t,X),l(t,n),l(n,i),l(i,o),l(i,r);for(let z=0;z=1,W,L,Y,S=d&&_s(e),I=e[1][e[0]]&&ms(e);return{c(){t=s("div"),n=s("div"),i=s("input"),o=c(),r=s("button"),r.textContent="New window",g=c(),h=s("br"),b=c(),S&&S.c(),W=c(),I&&I.c(),a(i,"class","input grow"),a(i,"type","text"),a(i,"placeholder","New Window label.."),a(r,"class","btn"),a(n,"class","flex gap-1"),a(t,"class","flex flex-col children:grow gap-2")},m(M,D){w(M,t,D),l(t,n),l(n,i),E(i,e[28]),l(n,o),l(n,r),l(t,g),l(t,h),l(t,b),S&&S.m(t,null),l(t,W),I&&I.m(t,null),L||(Y=[k(i,"input",e[58]),k(r,"click",e[53])],L=!0)},p(M,D){D[0]&268435456&&i.value!==M[28]&&E(i,M[28]),D[0]&2&&(d=Object.keys(M[1]).length>=1),d?S?S.p(M,D):(S=_s(M),S.c(),S.m(t,W)):S&&(S.d(1),S=null),M[1][M[0]]?I?I.p(M,D):(I=ms(M),I.c(),I.m(t,null)):I&&(I.d(1),I=null)},i:ee,o:ee,d(M){M&&m(t),S&&S.d(),I&&I.d(),L=!1,je(Y)}}}function yo(e,t,n){const i=Ts();let o=i.label;const r={[i.label]:i},g=["default","crosshair","hand","arrow","move","text","wait","help","progress","notAllowed","contextMenu","cell","verticalText","alias","copy","noDrop","grab","grabbing","allScroll","zoomIn","zoomOut","eResize","nResize","neResize","nwResize","sResize","seResize","swResize","wResize","ewResize","nsResize","neswResize","nwseResize","colResize","rowResize"],h=["mica","blur","acrylic","tabbed","tabbedDark","tabbedLight"],b=navigator.appVersion.includes("Windows"),d=navigator.appVersion.includes("Macintosh");let W=b?h:Object.keys(Il).map(A=>Il[A]).filter(A=>!h.includes(A));const L=Object.keys(Ml).map(A=>Ml[A]),Y=Object.keys(El).map(A=>El[A]);let{onMessage:S}=t;const I=document.querySelector("main");let M,D=!0,ae=!0,H=!0,N=!0,V=!1,G=!0,O=!1,B=!1,re=!0,T=!1,x=null,te=null,y=null,F=null,j=null,$=null,ue=null,K=null,ge=1,ke=new zt(ue,K),de=new zt(ue,K),oe=new en(x,te),Q=new en(x,te),he,U,ne=!1,J=!0,v=null,X=null,z="default",fe=!1,ze="Awesome Tauri Example!",me=[],pe,We,Pe,Ae,be,_e,Le,Oe="none",ce=0,Ce;function le(){r[o].setTitle(ze)}function De(){r[o].hide(),setTimeout(r[o].show,2e3)}function Ne(){r[o].minimize(),setTimeout(r[o].unminimize,2e3)}function Ee(){if(!M)return;const A=new Cn(M);n(1,r[M]=A,r),A.once("tauri://error",function(){S("Error creating new webview")})}function ie(){r[o].innerSize().then(A=>{n(32,oe=A),n(12,x=oe.width),n(13,te=oe.height)}),r[o].outerSize().then(A=>{n(33,Q=A)})}function C(){r[o].innerPosition().then(A=>{n(30,ke=A)}),r[o].outerPosition().then(A=>{n(31,de=A),n(18,ue=de.x),n(19,K=de.y)})}async function Z(A){A&&(he&&he(),U&&U(),U=await A.listen("tauri://move",C),he=await A.listen("tauri://resize",ie))}async function P(){await r[o].minimize(),await r[o].requestUserAttention(Ol.Critical),await new Promise(A=>setTimeout(A,3e3)),await r[o].requestUserAttention(null)}async function Ie(){me.includes(pe)||n(35,me=[...me,pe]);const A={effects:me,state:We,radius:Pe};Number.isInteger(Ae)&&Number.isInteger(be)&&Number.isInteger(_e)&&Number.isInteger(Le)&&(A.color=[Ae,be,_e,Le]),I.classList.remove("bg-primary"),I.classList.remove("dark:bg-darkPrimary"),await r[o].clearEffects(),await r[o].setEffects(A)}async function Sn(){n(35,me=[]),await r[o].clearEffects(),I.classList.add("bg-primary"),I.classList.add("dark:bg-darkPrimary")}function Te(){M=this.value,n(28,M)}function zn(){o=yn(this),n(0,o),n(1,r)}function Et(){Ce=this.value,n(43,Ce)}const Pn=()=>r[o].center();function Re(){V=this.checked,n(6,V)}function On(){D=this.checked,n(2,D)}function $e(){ae=this.checked,n(3,ae)}function It(){H=this.checked,n(4,H)}function En(){N=this.checked,n(5,N)}function He(){G=this.checked,n(7,G)}function In(){O=this.checked,n(8,O)}function Mt(){B=this.checked,n(9,B)}function Mn(){re=this.checked,n(10,re)}function Fe(){T=this.checked,n(11,T)}function Wn(){ue=q(this.value),n(18,ue)}function et(){K=q(this.value),n(19,K)}function Wt(){x=q(this.value),n(12,x)}function An(){te=q(this.value),n(13,te)}function Ve(){y=q(this.value),n(14,y)}function Dn(){F=q(this.value),n(15,F)}function At(){j=q(this.value),n(16,j)}function Nn(){$=q(this.value),n(17,$)}function Ge(){ne=this.checked,n(20,ne)}function Tn(){J=this.checked,n(21,J)}function tt(){fe=this.checked,n(25,fe)}function Dt(){z=yn(this),n(24,z),n(44,g)}function Rn(){v=q(this.value),n(22,v)}function Ue(){X=q(this.value),n(23,X)}function Hn(){ze=this.value,n(34,ze)}function Nt(){Oe=yn(this),n(26,Oe),n(49,Y)}function Fn(){ce=q(this.value),n(27,ce)}function qe(){pe=yn(this),n(36,pe),n(47,W)}function ln(){We=yn(this),n(37,We),n(48,L)}function sn(){Pe=q(this.value),n(38,Pe)}function on(){Ae=q(this.value),n(39,Ae)}function Me(){be=q(this.value),n(40,be)}function nt(){_e=q(this.value),n(41,_e)}function Xe(){Le=q(this.value),n(42,Le)}return e.$$set=A=>{"onMessage"in A&&n(57,S=A.onMessage)},e.$$.update=()=>{var A,an,pt,rn,bt,Tt,un,_t,cn,gt,Rt,dn,Be,mt,fn,wt,hn,vt,Ht,pn,yt,bn,kt,Ft;e.$$.dirty[0]&3&&(r[o],C(),ie()),e.$$.dirty[0]&7&&((A=r[o])==null||A.setResizable(D)),e.$$.dirty[0]&11&&((an=r[o])==null||an.setMaximizable(ae)),e.$$.dirty[0]&19&&((pt=r[o])==null||pt.setMinimizable(H)),e.$$.dirty[0]&35&&((rn=r[o])==null||rn.setClosable(N)),e.$$.dirty[0]&67&&(V?(bt=r[o])==null||bt.maximize():(Tt=r[o])==null||Tt.unmaximize()),e.$$.dirty[0]&131&&((un=r[o])==null||un.setDecorations(G)),e.$$.dirty[0]&259&&((_t=r[o])==null||_t.setAlwaysOnTop(O)),e.$$.dirty[0]&515&&((cn=r[o])==null||cn.setAlwaysOnBottom(B)),e.$$.dirty[0]&1027&&((gt=r[o])==null||gt.setContentProtected(re)),e.$$.dirty[0]&2051&&((Rt=r[o])==null||Rt.setFullscreen(T)),e.$$.dirty[0]&12291&&x&&te&&((dn=r[o])==null||dn.setSize(new en(x,te))),e.$$.dirty[0]&49155&&(y&&F?(Be=r[o])==null||Be.setMinSize(new di(y,F)):(mt=r[o])==null||mt.setMinSize(null)),e.$$.dirty[0]&196611&&(j>800&&$>400?(fn=r[o])==null||fn.setMaxSize(new di(j,$)):(wt=r[o])==null||wt.setMaxSize(null)),e.$$.dirty[0]&786435&&ue!==null&&K!==null&&((hn=r[o])==null||hn.setPosition(new zt(ue,K))),e.$$.dirty[0]&3&&((vt=r[o])==null||vt.scaleFactor().then(Un=>n(29,ge=Un))),e.$$.dirty[0]&3&&Z(r[o]),e.$$.dirty[0]&1048579&&((Ht=r[o])==null||Ht.setCursorGrab(ne)),e.$$.dirty[0]&2097155&&((pn=r[o])==null||pn.setCursorVisible(J)),e.$$.dirty[0]&16777219&&((yt=r[o])==null||yt.setCursorIcon(z)),e.$$.dirty[0]&12582915&&v!==null&&X!==null&&((bn=r[o])==null||bn.setCursorPosition(new zt(v,X))),e.$$.dirty[0]&33554435&&((kt=r[o])==null||kt.setIgnoreCursorEvents(fe)),e.$$.dirty[0]&201326595&&((Ft=r[o])==null||Ft.setProgressBar({status:Oe,progress:ce}))},[o,r,D,ae,H,N,V,G,O,B,re,T,x,te,y,F,j,$,ue,K,ne,J,v,X,z,fe,Oe,ce,M,ge,ke,de,oe,Q,ze,me,pe,We,Pe,Ae,be,_e,Le,Ce,g,b,d,W,L,Y,le,De,Ne,Ee,P,Ie,Sn,S,Te,zn,Et,Pn,Re,On,$e,It,En,He,In,Mt,Mn,Fe,Wn,et,Wt,An,Ve,Dn,At,Nn,Ge,Tn,tt,Dt,Rn,Ue,Hn,Nt,Fn,qe,ln,sn,on,Me,nt,Xe]}class ko extends nn{constructor(t){super(),tn(this,t,yo,vo,Ot,{onMessage:57},null,[-1,-1,-1,-1])}}function Lo(e){let t;return{c(){t=s("div"),t.innerHTML='
Not available for Linux
',a(t,"class","flex flex-col gap-2")},m(n,i){w(n,t,i)},p:ee,i:ee,o:ee,d(n){n&&m(t)}}}function Co(e,t,n){let{onMessage:i}=t;const o=window.constraints={audio:!0,video:!0};function r(h){const b=document.querySelector("video"),d=h.getVideoTracks();i("Got stream with constraints:",o),i(`Using video device: ${d[0].label}`),window.stream=h,b.srcObject=h}function g(h){if(h.name==="ConstraintNotSatisfiedError"){const b=o.video;i(`The resolution ${b.width.exact}x${b.height.exact} px is not supported by your device.`)}else h.name==="PermissionDeniedError"&&i("Permissions have not been granted to use your camera and microphone, you need to allow the page access to your devices in order for the demo to work.");i(`getUserMedia error: ${h.name}`,h)}return Pl(async()=>{try{const h=await navigator.mediaDevices.getUserMedia(o);r(h)}catch(h){g(h)}}),Ws(()=>{window.stream.getTracks().forEach(function(h){h.stop()})}),e.$$set=h=>{"onMessage"in h&&n(0,i=h.onMessage)},[i]}class So extends nn{constructor(t){super(),tn(this,t,Co,Lo,Ot,{onMessage:0})}}function zo(e){let t,n,i,o,r,g;return{c(){t=s("div"),n=s("button"),n.textContent="Show",i=c(),o=s("button"),o.textContent="Hide",a(n,"class","btn"),a(n,"id","show"),a(n,"title","Hides and shows the app after 2 seconds"),a(o,"class","btn"),a(o,"id","hide")},m(h,b){w(h,t,b),l(t,n),l(t,i),l(t,o),r||(g=[k(n,"click",e[0]),k(o,"click",e[1])],r=!0)},p:ee,i:ee,o:ee,d(h){h&&m(t),r=!1,je(g)}}}function Po(e,t,n){let{onMessage:i}=t;function o(){r().then(()=>{setTimeout(()=>{so().then(()=>i("Shown app")).catch(i)},2e3)}).catch(i)}function r(){return oo().then(()=>i("Hide app")).catch(i)}return e.$$set=g=>{"onMessage"in g&&n(2,i=g.onMessage)},[o,r,i]}class Oo extends nn{constructor(t){super(),tn(this,t,Po,zo,Ot,{onMessage:2})}}function Ls(e,t,n){const i=e.slice();return i[25]=t[n],i}function Cs(e,t,n){const i=e.slice();return i[28]=t[n],i}function Eo(e){let t;return{c(){t=s("span"),a(t,"class","i-codicon-menu animate-duration-300ms animate-fade-in")},m(n,i){w(n,t,i)},d(n){n&&m(t)}}}function Io(e){let t;return{c(){t=s("span"),a(t,"class","i-codicon-close animate-duration-300ms animate-fade-in")},m(n,i){w(n,t,i)},d(n){n&&m(t)}}}function Mo(e){let t,n;return{c(){t=p(`Switch to Dark mode - `),n=s("div"),a(n,"class","i-ph-moon")},m(i,o){w(i,t,o),w(i,n,o)},d(i){i&&(m(t),m(n))}}}function Wo(e){let t,n;return{c(){t=p(`Switch to Light mode - `),n=s("div"),a(n,"class","i-ph-sun")},m(i,o){w(i,t,o),w(i,n,o)},d(i){i&&(m(t),m(n))}}}function Ao(e){let t,n,i,o,r,g,h;function b(){return e[14](e[28])}return{c(){t=s("a"),n=s("div"),i=c(),o=s("p"),o.textContent=`${e[28].label}`,a(n,"class",e[28].icon+" mr-2"),a(t,"href","##"),a(t,"class",r="nv "+(e[1]===e[28]?"nv_selected":""))},m(d,W){w(d,t,W),l(t,n),l(t,i),l(t,o),g||(h=k(t,"click",b),g=!0)},p(d,W){e=d,W&2&&r!==(r="nv "+(e[1]===e[28]?"nv_selected":""))&&a(t,"class",r)},d(d){d&&m(t),g=!1,h()}}}function Ss(e){let t,n=e[28]&&Ao(e);return{c(){n&&n.c(),t=fi()},m(i,o){n&&n.m(i,o),w(i,t,o)},p(i,o){i[28]&&n.p(i,o)},d(i){i&&m(t),n&&n.d(i)}}}function zs(e){let t,n=e[25].html+"",i;return{c(){t=new Gs(!1),i=fi(),t.a=i},m(o,r){t.m(n,o,r),w(o,i,r)},p(o,r){r&16&&n!==(n=o[25].html+"")&&t.p(n)},d(o){o&&(m(i),t.d())}}}function Do(e){let t,n,i,o,r,g,h,b,d,W,L,Y,S,I,M,D,ae,H,N,V,G,O,B,re,T,x,te,y,F,j,$,ue,K=e[1].label+"",ge,ke,de,oe,Q,he,U,ne,J,v,X,z,fe,ze,me,pe,We,Pe;function Ae(C,Z){return C[0]?Io:Eo}let be=Ae(e),_e=be(e);function Le(C,Z){return C[2]?Wo:Mo}let Oe=Le(e),ce=Oe(e),Ce=ye(e[5]),le=[];for(let C=0;C`,ae=c(),H=s("a"),H.innerHTML=`GitHub - `,N=c(),V=s("a"),V.innerHTML=`Source - `,G=c(),O=s("br"),B=c(),re=s("div"),T=c(),x=s("br"),te=c(),y=s("div");for(let C=0;C',ze=c(),me=s("div");for(let C=0;C{ci(P,1)}),Js()}De?(Q=os(De,Ne(C)),us(Q.$$.fragment),ri(Q.$$.fragment,1),ui(Q,oe,null)):Q=null}if(Z&16){Ee=ye(C[4]);let P;for(P=0;P{y.ctrlKey&&y.key==="b"&&_("toggle_menu")});const o=navigator.userAgent.toLowerCase(),r=o.includes("android")||o.includes("iphone"),g=[{label:"Welcome",component:uo,icon:"i-ph-hand-waving"},{label:"Communication",component:po,icon:"i-codicon-radio-tower"},!r&&{label:"App",component:Oo,icon:"i-codicon-hubot"},{label:"Window",component:ko,icon:"i-codicon-window"},{label:"WebRTC",component:So,icon:"i-ph-broadcast"}];let h=g[0];function b(y){n(1,h=y)}let d;Pl(()=>{n(2,d=localStorage&&localStorage.getItem("theme")=="dark"),Os(d)});function W(){n(2,d=!d),Os(d)}let L=eo([]);Bs(e,L,y=>n(4,i=y));function Y(y){L.update(F=>[{html:`
[${new Date().toLocaleTimeString()}]: `+(typeof y=="string"?y:JSON.stringify(y,null,1))+"
"},...F])}function S(y){L.update(F=>[{html:`
[${new Date().toLocaleTimeString()}]: `+y+"
"},...F])}function I(){L.update(()=>[])}let M,D,ae;function H(y){ae=y.clientY;const F=window.getComputedStyle(M);D=parseInt(F.height,10);const j=ue=>{const K=ue.clientY-ae,ge=D-K;n(3,M.style.height=`${ge{document.removeEventListener("mouseup",$),document.removeEventListener("mousemove",j)};document.addEventListener("mouseup",$),document.addEventListener("mousemove",j)}let N=!1,V,G,O=!1,B=0,re=0;const T=(y,F,j)=>Math.min(Math.max(F,y),j);Pl(()=>{n(13,V=document.querySelector("#sidebar")),G=document.querySelector("#sidebarToggle"),document.addEventListener("click",y=>{G.contains(y.target)?n(0,N=!N):N&&!V.contains(y.target)&&n(0,N=!1)}),document.addEventListener("touchstart",y=>{if(G.contains(y.target))return;const F=y.touches[0].clientX;(0{if(O){const F=y.touches[0].clientX;re=F;const j=(F-B)/10;V.style.setProperty("--translate-x",`-${T(0,N?0-j:18.75-j,18.75)}rem`)}}),document.addEventListener("touchend",()=>{if(O){const y=(re-B)/10;n(0,N=N?y>-(18.75/2):y>18.75/2)}O=!1})});const x=y=>{b(y),n(0,N=!1)};function te(y){oi[y?"unshift":"push"](()=>{M=y,n(3,M)})}return e.$$.update=()=>{if(e.$$.dirty&1){const y=document.querySelector("#sidebar");y&&No(y,N)}},[N,h,d,M,i,g,b,W,L,Y,S,I,H,V,x,te]}class Ro extends nn{constructor(t){super(),tn(this,t,To,Do,Ot,{})}}new Ro({target:document.querySelector("#app")}); + tests.`,l=p(),s=r("br"),u=p(),d=r("br"),o=p(),c=r("pre"),h=b(" App name: "),w=r("code"),_=b(t[2]),W=b(` + App version: `),k=r("code"),y=b(t[0]),C=b(` + Tauri version: `),E=r("code"),V=b(t[1]),D=b(` + `),M=p(),I=r("br"),P=p(),T=r("button"),T.textContent="Context menu",a(T,"class","btn")},m(q,Q){L(q,e,Q),i(e,n),i(e,l),i(e,s),i(e,u),i(e,d),i(e,o),i(e,c),i(c,h),i(c,w),i(w,_),i(c,W),i(c,k),i(k,y),i(c,C),i(c,E),i(E,V),i(c,D),i(e,M),i(e,I),i(e,P),i(e,T),R||(Y=A(T,"click",t[3]),R=!0)},p(q,[Q]){Q&4&&se(_,q[2]),Q&1&&se(y,q[0]),Q&2&&se(V,q[1])},i:ne,o:ne,d(q){q&&S(e),R=!1,Y()}}}function Nr(t,e,n){let l="1.0.0",s="1.0.0",u="Unknown";Hr().then(o=>{n(2,u=o)}),Fr().then(o=>{n(0,l=o)}),Ur().then(o=>{n(1,s=o)});function d(){m("popup_context_menu")}return[l,s,u,d]}class jr extends xe{constructor(e){super(),Ze(this,e,Nr,qr,je,{})}}var Oe;(function(t){t.WINDOW_RESIZED="tauri://resize",t.WINDOW_MOVED="tauri://move",t.WINDOW_CLOSE_REQUESTED="tauri://close-requested",t.WINDOW_CREATED="tauri://window-created",t.WINDOW_DESTROYED="tauri://destroyed",t.WINDOW_FOCUS="tauri://focus",t.WINDOW_BLUR="tauri://blur",t.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",t.WINDOW_THEME_CHANGED="tauri://theme-changed",t.WINDOW_FILE_DROP="tauri://file-drop",t.WINDOW_FILE_DROP_HOVER="tauri://file-drop-hover",t.WINDOW_FILE_DROP_CANCELLED="tauri://file-drop-cancelled"})(Oe||(Oe={}));async function hr(t,e){await m("plugin:event|unlisten",{event:t,eventId:e})}async function Rl(t,e,n){return m("plugin:event|listen",{event:t,windowLabel:n==null?void 0:n.target,handler:dr(e)}).then(l=>async()=>hr(t,l))}async function Gr(t,e,n){return Rl(t,l=>{e(l),hr(t,l.id).catch(()=>{})},n)}async function fr(t,e,n){await m("plugin:event|emit",{event:t,windowLabel:n==null?void 0:n.target,payload:e})}function Kr(t){let e,n,l,s,u,d,o,c;return{c(){e=r("div"),n=r("button"),n.textContent="Call Log API",l=p(),s=r("button"),s.textContent="Call Request (async) API",u=p(),d=r("button"),d.textContent="Send event to Rust",a(n,"class","btn"),a(n,"id","log"),a(s,"class","btn"),a(s,"id","request"),a(d,"class","btn"),a(d,"id","event")},m(h,w){L(h,e,w),i(e,n),i(e,l),i(e,s),i(e,u),i(e,d),o||(c=[A(n,"click",t[0]),A(s,"click",t[1]),A(d,"click",t[2])],o=!0)},p:ne,i:ne,o:ne,d(h){h&&S(e),o=!1,Ce(c)}}}function Xr(t,e,n){let{onMessage:l}=e,s;Ki(async()=>{s=await Rl("rust-event",l)}),rr(()=>{s&&s()});function u(){m("log_operation",{event:"tauri-click",payload:"this payload is optional because we used Option in Rust"})}function d(){m("perform_request",{endpoint:"dummy endpoint arg",body:{id:5,name:"test"}}).then(l).catch(l)}function o(){fr("js-event","this is the payload string")}return t.$$set=c=>{"onMessage"in c&&n(3,l=c.onMessage)},[u,d,o,l]}class Yr extends xe{constructor(e){super(),Ze(this,e,Xr,Kr,je,{onMessage:3})}}class zl{constructor(e,n){this.type="Logical",this.width=e,this.height=n}}class ln{constructor(e,n){this.type="Physical",this.width=e,this.height=n}toLogical(e){return new zl(this.width/e,this.height/e)}}class Qr{constructor(e,n){this.type="Logical",this.x=e,this.y=n}}class it{constructor(e,n){this.type="Physical",this.x=e,this.y=n}toLogical(e){return new Qr(this.x/e,this.y/e)}}var Yi;(function(t){t[t.Critical=1]="Critical",t[t.Informational=2]="Informational"})(Yi||(Yi={}));class Jr{constructor(e){this._preventDefault=!1,this.event=e.event,this.windowLabel=e.windowLabel,this.id=e.id}preventDefault(){this._preventDefault=!0}isPreventDefault(){return this._preventDefault}}var Qi;(function(t){t.None="none",t.Normal="normal",t.Indeterminate="indeterminate",t.Paused="paused",t.Error="error"})(Qi||(Qi={}));function pr(){return new Dn(window.__TAURI_INTERNALS__.metadata.currentWindow.label,{skip:!0})}function Ll(){return window.__TAURI_INTERNALS__.metadata.windows.map(t=>new Dn(t.label,{skip:!0}))}const Ts=["tauri://created","tauri://error"];class Dn{constructor(e,n={}){this.label=e,this.listeners=Object.create(null),n!=null&&n.skip||m("plugin:window|create",{options:{...n,label:e}}).then(async()=>this.emit("tauri://created")).catch(async l=>this.emit("tauri://error",l))}static getByLabel(e){return Ll().some(n=>n.label===e)?new Dn(e,{skip:!0}):null}static getCurrent(){return pr()}static getAll(){return Ll()}static async getFocusedWindow(){for(const e of Ll())if(await e.isFocused())return e;return null}async listen(e,n){return this._handleTauriEvent(e,n)?Promise.resolve(()=>{const l=this.listeners[e];l.splice(l.indexOf(n),1)}):Rl(e,n,{target:this.label})}async once(e,n){return this._handleTauriEvent(e,n)?Promise.resolve(()=>{const l=this.listeners[e];l.splice(l.indexOf(n),1)}):Gr(e,n,{target:this.label})}async emit(e,n){if(Ts.includes(e)){for(const l of this.listeners[e]||[])l({event:e,id:-1,windowLabel:this.label,payload:n});return Promise.resolve()}return fr(e,n,{target:this.label})}_handleTauriEvent(e,n){return Ts.includes(e)?(e in this.listeners?this.listeners[e].push(n):this.listeners[e]=[n],!0):!1}async scaleFactor(){return m("plugin:window|scale_factor",{label:this.label})}async innerPosition(){return m("plugin:window|inner_position",{label:this.label}).then(({x:e,y:n})=>new it(e,n))}async outerPosition(){return m("plugin:window|outer_position",{label:this.label}).then(({x:e,y:n})=>new it(e,n))}async innerSize(){return m("plugin:window|inner_size",{label:this.label}).then(({width:e,height:n})=>new ln(e,n))}async outerSize(){return m("plugin:window|outer_size",{label:this.label}).then(({width:e,height:n})=>new ln(e,n))}async isFullscreen(){return m("plugin:window|is_fullscreen",{label:this.label})}async isMinimized(){return m("plugin:window|is_minimized",{label:this.label})}async isMaximized(){return m("plugin:window|is_maximized",{label:this.label})}async isFocused(){return m("plugin:window|is_focused",{label:this.label})}async isDecorated(){return m("plugin:window|is_decorated",{label:this.label})}async isResizable(){return m("plugin:window|is_resizable",{label:this.label})}async isMaximizable(){return m("plugin:window|is_maximizable",{label:this.label})}async isMinimizable(){return m("plugin:window|is_minimizable",{label:this.label})}async isClosable(){return m("plugin:window|is_closable",{label:this.label})}async isVisible(){return m("plugin:window|is_visible",{label:this.label})}async title(){return m("plugin:window|title",{label:this.label})}async theme(){return m("plugin:window|theme",{label:this.label})}async center(){return m("plugin:window|center",{label:this.label})}async requestUserAttention(e){let n=null;return e&&(e===Yi.Critical?n={type:"Critical"}:n={type:"Informational"}),m("plugin:window|request_user_attention",{label:this.label,value:n})}async setResizable(e){return m("plugin:window|set_resizable",{label:this.label,value:e})}async setMaximizable(e){return m("plugin:window|set_maximizable",{label:this.label,value:e})}async setMinimizable(e){return m("plugin:window|set_minimizable",{label:this.label,value:e})}async setClosable(e){return m("plugin:window|set_closable",{label:this.label,value:e})}async setTitle(e){return m("plugin:window|set_title",{label:this.label,value:e})}async maximize(){return m("plugin:window|maximize",{label:this.label})}async unmaximize(){return m("plugin:window|unmaximize",{label:this.label})}async toggleMaximize(){return m("plugin:window|toggle_maximize",{label:this.label})}async minimize(){return m("plugin:window|minimize",{label:this.label})}async unminimize(){return m("plugin:window|unminimize",{label:this.label})}async show(){return m("plugin:window|show",{label:this.label})}async hide(){return m("plugin:window|hide",{label:this.label})}async close(){return m("plugin:window|close",{label:this.label})}async setDecorations(e){return m("plugin:window|set_decorations",{label:this.label,value:e})}async setShadow(e){return m("plugin:window|set_shadow",{label:this.label,value:e})}async setEffects(e){return m("plugin:window|set_effects",{label:this.label,value:e})}async clearEffects(){return m("plugin:window|set_effects",{label:this.label,value:null})}async setAlwaysOnTop(e){return m("plugin:window|set_always_on_top",{label:this.label,value:e})}async setAlwaysOnBottom(e){return m("plugin:window|set_always_on_bottom",{label:this.label,value:e})}async setContentProtected(e){return m("plugin:window|set_content_protected",{label:this.label,value:e})}async setSize(e){if(!e||e.type!=="Logical"&&e.type!=="Physical")throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return m("plugin:window|set_size",{label:this.label,value:{type:e.type,data:{width:e.width,height:e.height}}})}async setMinSize(e){if(e&&e.type!=="Logical"&&e.type!=="Physical")throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return m("plugin:window|set_min_size",{label:this.label,value:e?{type:e.type,data:{width:e.width,height:e.height}}:null})}async setMaxSize(e){if(e&&e.type!=="Logical"&&e.type!=="Physical")throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return m("plugin:window|set_max_size",{label:this.label,value:e?{type:e.type,data:{width:e.width,height:e.height}}:null})}async setPosition(e){if(!e||e.type!=="Logical"&&e.type!=="Physical")throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");return m("plugin:window|set_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setFullscreen(e){return m("plugin:window|set_fullscreen",{label:this.label,value:e})}async setFocus(){return m("plugin:window|set_focus",{label:this.label})}async setIcon(e){return m("plugin:window|set_icon",{label:this.label,value:typeof e=="string"?e:Array.from(e)})}async setSkipTaskbar(e){return m("plugin:window|set_skip_taskbar",{label:this.label,value:e})}async setCursorGrab(e){return m("plugin:window|set_cursor_grab",{label:this.label,value:e})}async setCursorVisible(e){return m("plugin:window|set_cursor_visible",{label:this.label,value:e})}async setCursorIcon(e){return m("plugin:window|set_cursor_icon",{label:this.label,value:e})}async setCursorPosition(e){if(!e||e.type!=="Logical"&&e.type!=="Physical")throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");return m("plugin:window|set_cursor_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setIgnoreCursorEvents(e){return m("plugin:window|set_ignore_cursor_events",{label:this.label,value:e})}async startDragging(){return m("plugin:window|start_dragging",{label:this.label})}async setProgressBar(e){return m("plugin:window|set_progress_bar",{label:this.label,value:e})}async onResized(e){return this.listen(Oe.WINDOW_RESIZED,n=>{n.payload=Zr(n.payload),e(n)})}async onMoved(e){return this.listen(Oe.WINDOW_MOVED,n=>{n.payload=Al(n.payload),e(n)})}async onCloseRequested(e){return this.listen(Oe.WINDOW_CLOSE_REQUESTED,n=>{const l=new Jr(n);Promise.resolve(e(l)).then(()=>{if(!l.isPreventDefault())return this.close()})})}async onFocusChanged(e){const n=await this.listen(Oe.WINDOW_FOCUS,s=>{e({...s,payload:!0})}),l=await this.listen(Oe.WINDOW_BLUR,s=>{e({...s,payload:!1})});return()=>{n(),l()}}async onScaleChanged(e){return this.listen(Oe.WINDOW_SCALE_FACTOR_CHANGED,e)}async onFileDropEvent(e){const n=await this.listen(Oe.WINDOW_FILE_DROP,u=>{e({...u,payload:{type:"drop",paths:u.payload.paths,position:Al(u.payload.position)}})}),l=await this.listen(Oe.WINDOW_FILE_DROP_HOVER,u=>{e({...u,payload:{type:"hover",paths:u.payload.paths,position:Al(u.payload.position)}})}),s=await this.listen(Oe.WINDOW_FILE_DROP_CANCELLED,u=>{e({...u,payload:{type:"cancel"}})});return()=>{n(),l(),s()}}async onThemeChanged(e){return this.listen(Oe.WINDOW_THEME_CHANGED,e)}}var Ji;(function(t){t.AppearanceBased="appearanceBased",t.Light="light",t.Dark="dark",t.MediumLight="mediumLight",t.UltraDark="ultraDark",t.Titlebar="titlebar",t.Selection="selection",t.Menu="menu",t.Popover="popover",t.Sidebar="sidebar",t.HeaderView="headerView",t.Sheet="sheet",t.WindowBackground="windowBackground",t.HudWindow="hudWindow",t.FullScreenUI="fullScreenUI",t.Tooltip="tooltip",t.ContentBackground="contentBackground",t.UnderWindowBackground="underWindowBackground",t.UnderPageBackground="underPageBackground",t.Mica="mica",t.Blur="blur",t.Acrylic="acrylic",t.Tabbed="tabbed",t.TabbedDark="tabbedDark",t.TabbedLight="tabbedLight"})(Ji||(Ji={}));var Zi;(function(t){t.FollowsWindowActiveState="followsWindowActiveState",t.Active="active",t.Inactive="inactive"})(Zi||(Zi={}));function Al(t){return new it(t.x,t.y)}function Zr(t){return new ln(t.width,t.height)}function zs(t,e,n){const l=t.slice();return l[105]=e[n],l}function Os(t,e,n){const l=t.slice();return l[108]=e[n],l}function Ws(t,e,n){const l=t.slice();return l[111]=e[n],l}function Is(t,e,n){const l=t.slice();return l[114]=e[n],l}function Rs(t,e,n){const l=t.slice();return l[117]=e[n],l}function Ds(t){let e,n,l,s,u,d,o=he(Object.keys(t[1])),c=[];for(let h=0;ht[59].call(l))},m(h,w){L(h,e,w),L(h,n,w),L(h,l,w),i(l,s);for(let _=0;_t[83].call(tt)),a(pt,"class","input"),a(pt,"type","number"),a(mt,"class","input"),a(mt,"type","number"),a(et,"class","flex gap-2"),a(gt,"class","input grow"),a(gt,"id","title"),a(Ln,"class","btn"),a(Ln,"type","submit"),a(Et,"class","flex gap-1"),a(Sn,"class","flex flex-col gap-1"),a(nt,"class","input"),t[26]===void 0&&wt(()=>t[87].call(nt)),a(Ye,"class","input"),a(Ye,"type","number"),a(Ye,"min","0"),a(Ye,"max","100"),a(Qt,"class","flex gap-2"),a(An,"class","flex flex-col gap-1")},m(f,g){L(f,e,g),L(f,n,g),L(f,l,g),i(l,s),i(l,u),i(l,d),i(d,o),O(o,t[43]),i(d,c),i(d,h),L(f,w,g),L(f,_,g),L(f,W,g),L(f,k,g),i(k,y),i(k,C),i(k,E),i(k,V),i(k,D),i(k,M),i(k,I),L(f,P,g),L(f,T,g),i(T,R),i(R,Y),i(R,q),q.checked=t[6],i(T,Q),i(T,ie),i(ie,ee),i(ie,v),v.checked=t[2],i(T,B),i(T,G),i(G,oe),i(G,Z),Z.checked=t[3],i(T,we),i(T,be),i(be,fe),i(be,ce),ce.checked=t[4],i(T,x),i(T,pe),i(pe,K),i(pe,le),le.checked=t[5],i(T,te),i(T,z),i(z,J),i(z,H),H.checked=t[7],i(T,re),i(T,Ae),i(Ae,ke),i(Ae,me),me.checked=t[8],i(T,We),i(T,Me),i(Me,Ie),i(Me,ge),ge.checked=t[9],i(T,_e),i(T,Se),i(Se,Pe),i(Se,de),de.checked=t[10],i(T,Le),i(T,ae),i(ae,Re),i(ae,De),De.checked=t[11],L(f,Ee,g),L(f,ue,g),L(f,F,g),L(f,$,g),i($,U),i(U,Te),i(Te,Vn),i(Te,Fe),O(Fe,t[18]),i(U,qn),i(U,Ot),i(Ot,Nn),i(Ot,He),O(He,t[19]),i($,jn),i($,lt),i(lt,Wt),i(Wt,Gn),i(Wt,Ue),O(Ue,t[12]),i(lt,Kn),i(lt,It),i(It,Xn),i(It,Be),O(Be,t[13]),i($,Yn),i($,st),i(st,Rt),i(Rt,Qn),i(Rt,Ge),O(Ge,t[14]),i(st,Jn),i(st,Dt),i(Dt,Zn),i(Dt,Ke),O(Ke,t[15]),i($,xn),i($,rt),i(rt,Ft),i(Ft,$n),i(Ft,Ve),O(Ve,t[16]),i(rt,ei),i(rt,Ht),i(Ht,ti),i(Ht,qe),O(qe,t[17]),L(f,dn,g),L(f,hn,g),L(f,fn,g),L(f,ze,g),i(ze,at),i(at,Xe),i(Xe,N),i(Xe,pn),i(Xe,kt),i(kt,mn),i(kt,Ut),i(Xe,gn),i(Xe,vt),i(vt,_n),i(vt,Bt),i(at,bn),i(at,Ne),i(Ne,St),i(Ne,wn),i(Ne,Lt),i(Lt,kn),i(Lt,Vt),i(Ne,yn),i(Ne,Mt),i(Mt,vn),i(Mt,qt),i(ze,ni),i(ze,Nt),i(Nt,ut),i(ut,ii),i(ut,Fl),i(ut,li),i(li,Hl),i(li,xi),i(ut,Ul),i(ut,ri),i(ri,Bl),i(ri,$i),i(Nt,Vl),i(Nt,ot),i(ot,ui),i(ot,ql),i(ot,oi),i(oi,Nl),i(oi,el),i(ot,jl),i(ot,di),i(di,Gl),i(di,tl),i(ze,Kl),i(ze,jt),i(jt,ct),i(ct,fi),i(ct,Xl),i(ct,pi),i(pi,Yl),i(pi,nl),i(ct,Ql),i(ct,gi),i(gi,Jl),i(gi,il),i(jt,Zl),i(jt,dt),i(dt,bi),i(dt,xl),i(dt,wi),i(wi,$l),i(wi,ll),i(dt,es),i(dt,yi),i(yi,ts),i(yi,sl),i(ze,ns),i(ze,Gt),i(Gt,ht),i(ht,Ci),i(ht,is),i(ht,Si),i(Si,ls),i(Si,rl),i(ht,ss),i(ht,Ai),i(Ai,rs),i(Ai,al),i(Gt,as),i(Gt,ft),i(ft,Pi),i(ft,us),i(ft,Ei),i(Ei,os),i(Ei,ul),i(ft,cs),i(ft,zi),i(zi,ds),i(zi,ol),L(f,cl,g),L(f,dl,g),L(f,hl,g),L(f,Cn,g),L(f,fl,g),L(f,$e,g),i($e,Wi),i(Wi,Kt),Kt.checked=t[20],i(Wi,hs),i($e,fs),i($e,Ii),i(Ii,Xt),Xt.checked=t[21],i(Ii,ps),i($e,ms),i($e,Ri),i(Ri,Yt),Yt.checked=t[25],i(Ri,gs),L(f,pl,g),L(f,et,g),i(et,Di),i(Di,_s),i(Di,tt);for(let j=0;jt[89].call(u)),a(h,"class","input"),t[37]===void 0&&wt(()=>t[90].call(h)),a(k,"class","input"),a(k,"type","number"),a(n,"class","flex"),xt(M,"max-width","120px"),a(M,"class","input"),a(M,"type","number"),a(M,"placeholder","R"),xt(P,"max-width","120px"),a(P,"class","input"),a(P,"type","number"),a(P,"placeholder","G"),xt(R,"max-width","120px"),a(R,"class","input"),a(R,"type","number"),a(R,"placeholder","B"),xt(q,"max-width","120px"),a(q,"class","input"),a(q,"type","number"),a(q,"placeholder","A"),a(D,"class","flex"),a(C,"class","flex"),a(ee,"class","btn"),xt(ee,"width","80px"),a(ie,"class","flex"),a(fe,"class","btn"),xt(fe,"width","80px"),a(B,"class","flex"),a(e,"class","flex flex-col gap-1")},m(z,J){L(z,e,J),i(e,n),i(n,l),i(l,s),i(l,u);for(let H=0;H=1,w,_,W,k=h&&Ds(t),y=t[1][t[0]]&&Hs(t);return{c(){e=r("div"),n=r("div"),l=r("input"),s=p(),u=r("button"),u.textContent="New window",d=p(),o=r("br"),c=p(),k&&k.c(),w=p(),y&&y.c(),a(l,"class","input grow"),a(l,"type","text"),a(l,"placeholder","New Window label.."),a(u,"class","btn"),a(n,"class","flex gap-1"),a(e,"class","flex flex-col children:grow gap-2")},m(C,E){L(C,e,E),i(e,n),i(n,l),O(l,t[28]),i(n,s),i(n,u),i(e,d),i(e,o),i(e,c),k&&k.m(e,null),i(e,w),y&&y.m(e,null),_||(W=[A(l,"input",t[58]),A(u,"click",t[53])],_=!0)},p(C,E){E[0]&268435456&&l.value!==C[28]&&O(l,C[28]),E[0]&2&&(h=Object.keys(C[1]).length>=1),h?k?k.p(C,E):(k=Ds(C),k.c(),k.m(e,w)):k&&(k.d(1),k=null),C[1][C[0]]?y?y.p(C,E):(y=Hs(C),y.c(),y.m(e,null)):y&&(y.d(1),y=null)},i:ne,o:ne,d(C){C&&S(e),k&&k.d(),y&&y.d(),_=!1,Ce(W)}}}function ea(t,e,n){const l=pr();let s=l.label;const u={[l.label]:l},d=["default","crosshair","hand","arrow","move","text","wait","help","progress","notAllowed","contextMenu","cell","verticalText","alias","copy","noDrop","grab","grabbing","allScroll","zoomIn","zoomOut","eResize","nResize","neResize","nwResize","sResize","seResize","swResize","wResize","ewResize","nsResize","neswResize","nwseResize","colResize","rowResize"],o=["mica","blur","acrylic","tabbed","tabbedDark","tabbedLight"],c=navigator.appVersion.includes("Windows"),h=navigator.appVersion.includes("Macintosh");let w=c?o:Object.keys(Ji).map(N=>Ji[N]).filter(N=>!o.includes(N));const _=Object.keys(Zi).map(N=>Zi[N]),W=Object.keys(Qi).map(N=>Qi[N]);let{onMessage:k}=e;const y=document.querySelector("main");let C,E=!0,V=!0,D=!0,M=!0,I=!1,P=!0,T=!1,R=!1,Y=!0,q=!1,Q=null,ie=null,ee=null,v=null,B=null,G=null,oe=null,Z=null,we=1,be=new it(oe,Z),fe=new it(oe,Z),ce=new ln(Q,ie),x=new ln(Q,ie),pe,K,le=!1,te=!0,z=null,J=null,H="default",re=!1,Ae="Awesome Tauri Example!",ke=[],me,We,Me,Ie,ge,_e,Se,Pe="none",de=0,Le;function ae(){u[s].setTitle(Ae)}function Re(){u[s].hide(),setTimeout(u[s].show,2e3)}function De(){u[s].minimize(),setTimeout(u[s].unminimize,2e3)}function Ee(){if(!C)return;const N=new Dn(C);n(1,u[C]=N,u),N.once("tauri://error",function(){k("Error creating new webview")})}function ue(){u[s].innerSize().then(N=>{n(32,ce=N),n(12,Q=ce.width),n(13,ie=ce.height)}),u[s].outerSize().then(N=>{n(33,x=N)})}function F(){u[s].innerPosition().then(N=>{n(30,be=N)}),u[s].outerPosition().then(N=>{n(31,fe=N),n(18,oe=fe.x),n(19,Z=fe.y)})}async function $(N){N&&(pe&&pe(),K&&K(),K=await N.listen("tauri://move",F),pe=await N.listen("tauri://resize",ue))}async function U(){await u[s].minimize(),await u[s].requestUserAttention(Yi.Critical),await new Promise(N=>setTimeout(N,3e3)),await u[s].requestUserAttention(null)}async function Te(){ke.includes(me)||n(35,ke=[...ke,me]);const N={effects:ke,state:We,radius:Me};Number.isInteger(Ie)&&Number.isInteger(ge)&&Number.isInteger(_e)&&Number.isInteger(Se)&&(N.color=[Ie,ge,_e,Se]),y.classList.remove("bg-primary"),y.classList.remove("dark:bg-darkPrimary"),await u[s].clearEffects(),await u[s].setEffects(N)}async function Vn(){n(35,ke=[]),await u[s].clearEffects(),y.classList.add("bg-primary"),y.classList.add("dark:bg-darkPrimary")}function Fe(){C=this.value,n(28,C)}function qn(){s=Pn(this),n(0,s),n(1,u)}function Ot(){Le=this.value,n(43,Le)}const Nn=()=>u[s].center();function He(){I=this.checked,n(6,I)}function jn(){E=this.checked,n(2,E)}function lt(){V=this.checked,n(3,V)}function Wt(){D=this.checked,n(4,D)}function Gn(){M=this.checked,n(5,M)}function Ue(){P=this.checked,n(7,P)}function Kn(){T=this.checked,n(8,T)}function It(){R=this.checked,n(9,R)}function Xn(){Y=this.checked,n(10,Y)}function Be(){q=this.checked,n(11,q)}function Yn(){oe=X(this.value),n(18,oe)}function st(){Z=X(this.value),n(19,Z)}function Rt(){Q=X(this.value),n(12,Q)}function Qn(){ie=X(this.value),n(13,ie)}function Ge(){ee=X(this.value),n(14,ee)}function Jn(){v=X(this.value),n(15,v)}function Dt(){B=X(this.value),n(16,B)}function Zn(){G=X(this.value),n(17,G)}function Ke(){le=this.checked,n(20,le)}function xn(){te=this.checked,n(21,te)}function rt(){re=this.checked,n(25,re)}function Ft(){H=Pn(this),n(24,H),n(44,d)}function $n(){z=X(this.value),n(22,z)}function Ve(){J=X(this.value),n(23,J)}function ei(){Ae=this.value,n(34,Ae)}function Ht(){Pe=Pn(this),n(26,Pe),n(49,W)}function ti(){de=X(this.value),n(27,de)}function qe(){me=Pn(this),n(36,me),n(47,w)}function dn(){We=Pn(this),n(37,We),n(48,_)}function hn(){Me=X(this.value),n(38,Me)}function fn(){Ie=X(this.value),n(39,Ie)}function ze(){ge=X(this.value),n(40,ge)}function at(){_e=X(this.value),n(41,_e)}function Xe(){Se=X(this.value),n(42,Se)}return t.$$set=N=>{"onMessage"in N&&n(57,k=N.onMessage)},t.$$.update=()=>{var N,pn,kt,mn,yt,Ut,gn,vt,_n,Ct,Bt,bn,Ne,St,wn,Lt,kn,At,Vt,yn,Mt,vn,Pt,qt;t.$$.dirty[0]&3&&(u[s],F(),ue()),t.$$.dirty[0]&7&&((N=u[s])==null||N.setResizable(E)),t.$$.dirty[0]&11&&((pn=u[s])==null||pn.setMaximizable(V)),t.$$.dirty[0]&19&&((kt=u[s])==null||kt.setMinimizable(D)),t.$$.dirty[0]&35&&((mn=u[s])==null||mn.setClosable(M)),t.$$.dirty[0]&67&&(I?(yt=u[s])==null||yt.maximize():(Ut=u[s])==null||Ut.unmaximize()),t.$$.dirty[0]&131&&((gn=u[s])==null||gn.setDecorations(P)),t.$$.dirty[0]&259&&((vt=u[s])==null||vt.setAlwaysOnTop(T)),t.$$.dirty[0]&515&&((_n=u[s])==null||_n.setAlwaysOnBottom(R)),t.$$.dirty[0]&1027&&((Ct=u[s])==null||Ct.setContentProtected(Y)),t.$$.dirty[0]&2051&&((Bt=u[s])==null||Bt.setFullscreen(q)),t.$$.dirty[0]&12291&&Q&&ie&&((bn=u[s])==null||bn.setSize(new ln(Q,ie))),t.$$.dirty[0]&49155&&(ee&&v?(Ne=u[s])==null||Ne.setMinSize(new zl(ee,v)):(St=u[s])==null||St.setMinSize(null)),t.$$.dirty[0]&196611&&(B>800&&G>400?(wn=u[s])==null||wn.setMaxSize(new zl(B,G)):(Lt=u[s])==null||Lt.setMaxSize(null)),t.$$.dirty[0]&786435&&oe!==null&&Z!==null&&((kn=u[s])==null||kn.setPosition(new it(oe,Z))),t.$$.dirty[0]&3&&((At=u[s])==null||At.scaleFactor().then(ni=>n(29,we=ni))),t.$$.dirty[0]&3&&$(u[s]),t.$$.dirty[0]&1048579&&((Vt=u[s])==null||Vt.setCursorGrab(le)),t.$$.dirty[0]&2097155&&((yn=u[s])==null||yn.setCursorVisible(te)),t.$$.dirty[0]&16777219&&((Mt=u[s])==null||Mt.setCursorIcon(H)),t.$$.dirty[0]&12582915&&z!==null&&J!==null&&((vn=u[s])==null||vn.setCursorPosition(new it(z,J))),t.$$.dirty[0]&33554435&&((Pt=u[s])==null||Pt.setIgnoreCursorEvents(re)),t.$$.dirty[0]&201326595&&((qt=u[s])==null||qt.setProgressBar({status:Pe,progress:de}))},[s,u,E,V,D,M,I,P,T,R,Y,q,Q,ie,ee,v,B,G,oe,Z,le,te,z,J,H,re,Pe,de,C,we,be,fe,ce,x,Ae,ke,me,We,Me,Ie,ge,_e,Se,Le,d,c,h,w,_,W,ae,Re,De,Ee,U,Te,Vn,k,Fe,qn,Ot,Nn,He,jn,lt,Wt,Gn,Ue,Kn,It,Xn,Be,Yn,st,Rt,Qn,Ge,Jn,Dt,Zn,Ke,xn,rt,Ft,$n,Ve,ei,Ht,ti,qe,dn,hn,fn,ze,at,Xe]}class ta extends xe{constructor(e){super(),Ze(this,e,ea,$r,je,{onMessage:57},null,[-1,-1,-1,-1])}}function na(t){let e;return{c(){e=r("div"),e.innerHTML='
Not available for Linux
',a(e,"class","flex flex-col gap-2")},m(n,l){L(n,e,l)},p:ne,i:ne,o:ne,d(n){n&&S(e)}}}function ia(t,e,n){let{onMessage:l}=e;const s=window.constraints={audio:!0,video:!0};function u(o){const c=document.querySelector("video"),h=o.getVideoTracks();l("Got stream with constraints:",s),l(`Using video device: ${h[0].label}`),window.stream=o,c.srcObject=o}function d(o){if(o.name==="ConstraintNotSatisfiedError"){const c=s.video;l(`The resolution ${c.width.exact}x${c.height.exact} px is not supported by your device.`)}else o.name==="PermissionDeniedError"&&l("Permissions have not been granted to use your camera and microphone, you need to allow the page access to your devices in order for the demo to work.");l(`getUserMedia error: ${o.name}`,o)}return Ki(async()=>{try{const o=await navigator.mediaDevices.getUserMedia(s);u(o)}catch(o){d(o)}}),rr(()=>{var o;(o=window.stream)==null||o.getTracks().forEach(function(c){c.stop()})}),t.$$set=o=>{"onMessage"in o&&n(0,l=o.onMessage)},[l]}class la extends xe{constructor(e){super(),Ze(this,e,ia,na,je,{onMessage:0})}}function sa(t){let e,n,l,s,u,d;return{c(){e=r("div"),n=r("button"),n.textContent="Show",l=p(),s=r("button"),s.textContent="Hide",a(n,"class","btn"),a(n,"id","show"),a(n,"title","Hides and shows the app after 2 seconds"),a(s,"class","btn"),a(s,"id","hide")},m(o,c){L(o,e,c),i(e,n),i(e,l),i(e,s),u||(d=[A(n,"click",t[0]),A(s,"click",t[1])],u=!0)},p:ne,i:ne,o:ne,d(o){o&&S(e),u=!1,Ce(d)}}}function ra(t,e,n){let{onMessage:l}=e;function s(){u().then(()=>{setTimeout(()=>{Br().then(()=>l("Shown app")).catch(l)},2e3)}).catch(l)}function u(){return Vr().then(()=>l("Hide app")).catch(l)}return t.$$set=d=>{"onMessage"in d&&n(2,l=d.onMessage)},[s,u,l]}class aa extends xe{constructor(e){super(),Ze(this,e,ra,sa,je,{onMessage:2})}}var Ni;class mr{get rid(){return Rn(this,Ni,"f")}constructor(e){Ni.set(this,void 0),Xi(this,Ni,e,"f")}async close(){return m("plugin:resources|close",{rid:this.rid})}}Ni=new WeakMap;var ji,Gi;function gr(t){var e;if("items"in t)t.items=(e=t.items)==null?void 0:e.map(n=>"rid"in n?n:gr(n));else if("action"in t&&t.action){const n=new Il;return n.onmessage=t.action,delete t.action,{...t,handler:n}}return t}async function un(t,e){const n=new Il;let l=null;return e&&typeof e=="object"&&("action"in e&&e.action&&(n.onmessage=e.action,delete e.action),"items"in e&&e.items&&(l=e.items.map(s=>"rid"in s?[s.rid,s.kind]:gr(s)))),m("plugin:menu|new",{kind:t,options:e?{...e,items:l}:void 0,handler:n})}class on extends mr{get id(){return Rn(this,ji,"f")}get kind(){return Rn(this,Gi,"f")}constructor(e,n,l){super(e),ji.set(this,void 0),Gi.set(this,void 0),Xi(this,ji,n,"f"),Xi(this,Gi,l,"f")}}ji=new WeakMap,Gi=new WeakMap;class Fn extends on{constructor(e,n){super(e,n,"MenuItem")}static async new(e){return un("MenuItem",e).then(([n,l])=>new Fn(n,l))}async text(){return m("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return m("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return m("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return m("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return m("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}}class cn extends on{constructor(e,n){super(e,n,"Check")}static async new(e){return un("Check",e).then(([n,l])=>new cn(n,l))}async text(){return m("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return m("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return m("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return m("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return m("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async isChecked(){return m("plugin:menu|is_checked",{rid:this.rid})}async setChecked(e){return m("plugin:menu|set_checked",{rid:this.rid,checked:e})}}var Ns;(function(t){t.Add="Add",t.Advanced="Advanced",t.Bluetooth="Bluetooth",t.Bookmarks="Bookmarks",t.Caution="Caution",t.ColorPanel="ColorPanel",t.ColumnView="ColumnView",t.Computer="Computer",t.EnterFullScreen="EnterFullScreen",t.Everyone="Everyone",t.ExitFullScreen="ExitFullScreen",t.FlowView="FlowView",t.Folder="Folder",t.FolderBurnable="FolderBurnable",t.FolderSmart="FolderSmart",t.FollowLinkFreestanding="FollowLinkFreestanding",t.FontPanel="FontPanel",t.GoLeft="GoLeft",t.GoRight="GoRight",t.Home="Home",t.IChatTheater="IChatTheater",t.IconView="IconView",t.Info="Info",t.InvalidDataFreestanding="InvalidDataFreestanding",t.LeftFacingTriangle="LeftFacingTriangle",t.ListView="ListView",t.LockLocked="LockLocked",t.LockUnlocked="LockUnlocked",t.MenuMixedState="MenuMixedState",t.MenuOnState="MenuOnState",t.MobileMe="MobileMe",t.MultipleDocuments="MultipleDocuments",t.Network="Network",t.Path="Path",t.PreferencesGeneral="PreferencesGeneral",t.QuickLook="QuickLook",t.RefreshFreestanding="RefreshFreestanding",t.Refresh="Refresh",t.Remove="Remove",t.RevealFreestanding="RevealFreestanding",t.RightFacingTriangle="RightFacingTriangle",t.Share="Share",t.Slideshow="Slideshow",t.SmartBadge="SmartBadge",t.StatusAvailable="StatusAvailable",t.StatusNone="StatusNone",t.StatusPartiallyAvailable="StatusPartiallyAvailable",t.StatusUnavailable="StatusUnavailable",t.StopProgressFreestanding="StopProgressFreestanding",t.StopProgress="StopProgress",t.TrashEmpty="TrashEmpty",t.TrashFull="TrashFull",t.User="User",t.UserAccounts="UserAccounts",t.UserGroup="UserGroup",t.UserGuest="UserGuest"})(Ns||(Ns={}));class Hn extends on{constructor(e,n){super(e,n,"Icon")}static async new(e){return un("Icon",e).then(([n,l])=>new Hn(n,l))}async text(){return m("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return m("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return m("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return m("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return m("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async setIcon(e){return m("plugin:menu|set_icon",{rid:this.rid,icon:e})}}class Un extends on{constructor(e,n){super(e,n,"Predefined")}static async new(e){return un("Predefined",e).then(([n,l])=>new Un(n,l))}async text(){return m("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return m("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}}function Ml([t,e,n]){switch(n){case"Submenu":return new Bn(t,e);case"Predefined":return new Un(t,e);case"Check":return new cn(t,e);case"Icon":return new Hn(t,e);case"MenuItem":default:return new Fn(t,e)}}class Bn extends on{constructor(e,n){super(e,n,"Submenu")}static async new(e){return un("Submenu",e).then(([n,l])=>new Bn(n,l))}async text(){return m("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return m("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return m("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return m("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async append(e){return m("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map(n=>"rid"in n?[n.rid,n.kind]:n)})}async prepend(e){return m("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map(n=>"rid"in n?[n.rid,n.kind]:n)})}async insert(e,n){return m("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map(l=>"rid"in l?[l.rid,l.kind]:l),position:n})}async remove(e){return m("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return m("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(Ml)}async items(){return m("plugin:menu|items",{rid:this.rid,kind:this.kind}).then(e=>e.map(Ml))}async get(e){return m("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then(n=>n?Ml(n):null)}async popup(e,n){let l=null;return e&&(l={type:e instanceof it?"Physical":"Logical",data:e}),m("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:(n==null?void 0:n.label)??null,at:l})}async setAsWindowsMenuForNSApp(){return m("plugin:menu|set_as_windows_menu_for_nsapp",{rid:this.rid})}async setAsHelpMenuForNSApp(){return m("plugin:menu|set_as_help_menu_for_nsapp",{rid:this.rid})}}function Pl([t,e,n]){switch(n){case"Submenu":return new Bn(t,e);case"Predefined":return new Un(t,e);case"Check":return new cn(t,e);case"Icon":return new Hn(t,e);case"MenuItem":default:return new Fn(t,e)}}class bt extends on{constructor(e,n){super(e,n,"Menu")}static async new(e){return un("Menu",e).then(([n,l])=>new bt(n,l))}static async default(){return m("plugin:menu|default").then(([e,n])=>new bt(e,n))}async append(e){return m("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map(n=>"rid"in n?[n.rid,n.kind]:n)})}async prepend(e){return m("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map(n=>"rid"in n?[n.rid,n.kind]:n)})}async insert(e,n){return m("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map(l=>"rid"in l?[l.rid,l.kind]:l),position:n})}async remove(e){return m("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return m("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(Pl)}async items(){return m("plugin:menu|items",{rid:this.rid,kind:this.kind}).then(e=>e.map(Pl))}async get(e){return m("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then(n=>n?Pl(n):null)}async popup(e,n){let l=null;return e&&(l={type:e instanceof it?"Physical":"Logical",data:e}),m("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:(n==null?void 0:n.label)??null,at:l})}async setAsAppMenu(){return m("plugin:menu|set_as_app_menu",{rid:this.rid}).then(e=>e?new bt(e[0],e[1]):null)}async setAsWindowMenu(e){return m("plugin:menu|set_as_window_menu",{rid:this.rid,window:(e==null?void 0:e.label)??null}).then(n=>n?new bt(n[0],n[1]):null)}}function js(t,e,n){const l=t.slice();return l[16]=e[n],l[17]=e,l[18]=n,l}function Gs(t,e,n){const l=t.slice();return l[19]=e[n],l[20]=e,l[21]=n,l}function Ks(t){let e,n,l,s,u,d,o=t[19]+"",c,h,w,_,W;function k(){t[9].call(n,t[20],t[21])}return{c(){e=r("div"),n=r("input"),u=p(),d=r("label"),c=b(o),w=p(),a(n,"id",l=t[19]+"Input"),n.checked=s=t[0]===t[19],a(n,"type","radio"),a(n,"name","kind"),a(d,"for",h=t[19]+"Input"),a(e,"class","flex gap-1")},m(y,C){L(y,e,C),i(e,n),O(n,t[19]),i(e,u),i(e,d),i(d,c),i(e,w),_||(W=[A(n,"change",t[6]),A(n,"change",k)],_=!0)},p(y,C){t=y,C&16&&l!==(l=t[19]+"Input")&&a(n,"id",l),C&17&&s!==(s=t[0]===t[19])&&(n.checked=s),C&16&&O(n,t[19]),C&16&&o!==(o=t[19]+"")&&se(c,o),C&16&&h!==(h=t[19]+"Input")&&a(d,"for",h)},d(y){y&&S(e),_=!1,Ce(W)}}}function Xs(t){let e,n,l;return{c(){e=r("input"),a(e,"class","input"),a(e,"type","text"),a(e,"placeholder","Text")},m(s,u){L(s,e,u),O(e,t[1]),n||(l=A(e,"input",t[10]),n=!0)},p(s,u){u&2&&e.value!==s[1]&&O(e,s[1])},d(s){s&&S(e),n=!1,l()}}}function ua(t){let e,n=he(t[5]),l=[];for(let s=0;sl("itemClick",{id:T,text:P})},I=await Fn.new(M);break;case"Icon":M={text:u,icon:d,action:T=>l("itemClick",{id:T,text:P})},I=await Hn.new(M);break;case"Check":M={text:u,checked:c,action:T=>l("itemClick",{id:T,text:P})},I=await cn.new(M);break;case"Predefined":M={item:o},I=await Un.new(M);break}l("new",{item:I,options:M}),n(1,u=""),o=""}function y(M,I){M[I]=this.value,n(4,h)}function C(){u=this.value,n(1,u)}function E(){d=this.value,n(2,d)}function V(){c=this.checked,n(3,c)}function D(M,I){M[I]=this.value,n(5,w)}return[s,u,d,c,h,w,_,W,k,y,C,E,V,D]}class fa extends xe{constructor(e){super(),Ze(this,e,ha,da,je,{})}}function Qs(t,e,n){const l=t.slice();return l[5]=e[n],l}function Js(t){let e,n,l,s,u,d=Zs(t[5])+"",o,c;return{c(){e=r("div"),n=r("div"),s=p(),u=r("p"),o=b(d),c=p(),a(n,"class",l=t[3](t[5])),a(e,"class","flex flex-row gap-1")},m(h,w){L(h,e,w),i(e,n),i(e,s),i(e,u),i(u,o),i(e,c)},p(h,w){w&1&&l!==(l=h[3](h[5]))&&a(n,"class",l),w&1&&d!==(d=Zs(h[5])+"")&&se(o,d)},d(h){h&&S(e)}}}function pa(t){let e,n,l,s,u;n=new fa({}),n.$on("new",t[1]),n.$on("itemClick",t[2]);let d=he(t[0]),o=[];for(let c=0;c{"items"in c&&n(0,l=c.items)},[l,u,d,o]}class _r extends xe{constructor(e){super(),Ze(this,e,ma,pa,je,{items:0})}}function ga(t){let e,n,l,s,u,d,o,c,h,w;function _(k){t[5](k)}let W={};return t[0]!==void 0&&(W.items=t[0]),n=new _r({props:W}),On.push(()=>cr(n,"items",_)),n.$on("itemClick",t[3]),{c(){e=r("div"),In(n.$$.fragment),s=p(),u=r("button"),u.textContent="Create menu",d=p(),o=r("button"),o.textContent="Popup",a(u,"class","btn"),a(o,"class","btn")},m(k,y){L(k,e,y),rn(n,e,null),i(e,s),i(e,u),i(e,d),i(e,o),c=!0,h||(w=[A(u,"click",t[1]),A(o,"click",t[2])],h=!0)},p(k,[y]){const C={};!l&&y&1&&(l=!0,C.items=k[0],ur(()=>l=!1)),n.$set(C)},i(k){c||(sn(n.$$.fragment,k),c=!0)},o(k){Wn(n.$$.fragment,k),c=!1},d(k){k&&S(e),an(n),h=!1,Ce(w)}}}function _a(t,e,n){let{onMessage:l}=e,s=[],u=null,d=null,o=0;const c=navigator.userAgent.includes("Macintosh");async function h(){d=await Bn.new({text:"app",items:s.map(y=>y.item)})}async function w(){await h(),o=s.length,u=await bt.new({items:[d]}),await(c?u.setAsAppMenu():u.setAsWindowMenu())}async function _(){(!d||o!==s.length)&&await h(),(await bt.new({items:[d]})).popup()}function W(y){l(`Item ${y.detail.text} clicked`)}function k(y){s=y,n(0,s)}return t.$$set=y=>{"onMessage"in y&&n(4,l=y.onMessage)},[s,w,_,W,l,k]}class ba extends xe{constructor(e){super(),Ze(this,e,_a,ga,je,{onMessage:4})}}class Dl extends mr{constructor(e,n){super(e),this.id=n}static async new(e){e!=null&&e.menu&&(e.menu=[e.menu.rid,e.menu.kind]),e!=null&&e.icon&&(e.icon=typeof e.icon=="string"?e.icon:Array.from(e.icon));const n=new Il;return e!=null&&e.action&&(n.onmessage=e.action,delete e.action),m("plugin:tray|new",{options:e??{},handler:n}).then(([l,s])=>new Dl(l,s))}async setIcon(e){let n=null;return e&&(n=typeof e=="string"?e:Array.from(e)),m("plugin:tray|set_icon",{rid:this.rid,icon:n})}async setMenu(e){return e&&(e=[e.rid,e.kind]),m("plugin:tray|set_menu",{rid:this.rid,menu:e})}async setTooltip(e){return m("plugin:tray|set_tooltip",{rid:this.rid,tooltip:e})}async setTitle(e){return m("plugin:tray|set_title",{rid:this.rid,title:e})}async setVisible(e){return m("plugin:tray|set_visible",{rid:this.rid,visible:e})}async setTempDirPath(e){return m("plugin:tray|set_temp_dir_path",{rid:this.rid,path:e})}async setIconAsTemplate(e){return m("plugin:tray|set_icon_as_template",{rid:this.rid,asTemplate:e})}async setMenuOnLeftClick(e){return m("plugin:tray|set_show_menu_on_left_click",{rid:this.rid,onLeft:e})}}function wa(t){let e,n,l,s,u,d,o,c,h,w,_,W,k,y,C,E,V,D,M,I,P,T,R,Y,q,Q;function ie(v){t[14](v)}let ee={};return t[5]!==void 0&&(ee.items=t[5]),M=new _r({props:ee}),On.push(()=>cr(M,"items",ie)),M.$on("itemClick",t[6]),{c(){e=r("div"),n=r("div"),l=r("input"),s=p(),u=r("input"),d=p(),o=r("label"),c=b(`Menu on left click + `),h=r("input"),w=p(),_=r("div"),W=r("input"),k=p(),y=r("label"),C=b(`Icon as template + `),E=r("input"),V=p(),D=r("div"),In(M.$$.fragment),P=p(),T=r("div"),R=r("button"),R.textContent="Create tray",a(l,"class","input grow"),a(l,"type","text"),a(l,"placeholder","Title"),a(u,"class","input grow"),a(u,"type","text"),a(u,"placeholder","Tooltip"),a(h,"type","checkbox"),a(n,"class","flex gap-1"),a(W,"class","input grow"),a(W,"type","text"),a(W,"placeholder","Icon path"),a(E,"type","checkbox"),a(_,"class","flex gap-1"),a(D,"class","flex children:grow"),a(R,"class","btn"),a(R,"title","Creates the tray icon"),a(T,"class","flex"),a(e,"class","flex flex-col children:grow gap-2")},m(v,B){L(v,e,B),i(e,n),i(n,l),O(l,t[2]),i(n,s),i(n,u),O(u,t[1]),i(n,d),i(n,o),i(o,c),i(o,h),h.checked=t[4],i(e,w),i(e,_),i(_,W),O(W,t[0]),i(_,k),i(_,y),i(y,C),i(y,E),E.checked=t[3],i(e,V),i(e,D),rn(M,D,null),i(e,P),i(e,T),i(T,R),Y=!0,q||(Q=[A(l,"input",t[9]),A(u,"input",t[10]),A(h,"change",t[11]),A(W,"input",t[12]),A(E,"change",t[13]),A(R,"click",t[7])],q=!0)},p(v,[B]){B&4&&l.value!==v[2]&&O(l,v[2]),B&2&&u.value!==v[1]&&O(u,v[1]),B&16&&(h.checked=v[4]),B&1&&W.value!==v[0]&&O(W,v[0]),B&8&&(E.checked=v[3]);const G={};!I&&B&32&&(I=!0,G.items=v[5],ur(()=>I=!1)),M.$set(G)},i(v){Y||(sn(M.$$.fragment,v),Y=!0)},o(v){Wn(M.$$.fragment,v),Y=!1},d(v){v&&S(e),an(M),q=!1,Ce(Q)}}}function ka(t,e,n){let{onMessage:l}=e,s=null,u=null,d=null,o=!1,c=!0,h=[];function w(D){l(`Item ${D.detail.text} clicked`)}async function _(){Dl.new({icon:s,tooltip:u,title:d,iconAsTemplate:o,menuOnLeftClick:c,menu:await bt.new({items:h.map(D=>D.item)}),action:D=>l(D)}).catch(l)}function W(){d=this.value,n(2,d)}function k(){u=this.value,n(1,u)}function y(){c=this.checked,n(4,c)}function C(){s=this.value,n(0,s)}function E(){o=this.checked,n(3,o)}function V(D){h=D,n(5,h)}return t.$$set=D=>{"onMessage"in D&&n(8,l=D.onMessage)},[s,u,d,o,c,h,w,_,l,W,k,y,C,E,V]}class ya extends xe{constructor(e){super(),Ze(this,e,ka,wa,je,{onMessage:8})}}function xs(t,e,n){const l=t.slice();return l[26]=e[n],l}function $s(t,e,n){const l=t.slice();return l[29]=e[n],l}function va(t){let e;return{c(){e=r("span"),a(e,"class","i-codicon-menu animate-duration-300ms animate-fade-in")},m(n,l){L(n,e,l)},d(n){n&&S(e)}}}function Ca(t){let e;return{c(){e=r("span"),a(e,"class","i-codicon-close animate-duration-300ms animate-fade-in")},m(n,l){L(n,e,l)},d(n){n&&S(e)}}}function Sa(t){let e,n;return{c(){e=b(`Switch to Dark mode + `),n=r("div"),a(n,"class","i-ph-moon")},m(l,s){L(l,e,s),L(l,n,s)},d(l){l&&(S(e),S(n))}}}function La(t){let e,n;return{c(){e=b(`Switch to Light mode + `),n=r("div"),a(n,"class","i-ph-sun")},m(l,s){L(l,e,s),L(l,n,s)},d(l){l&&(S(e),S(n))}}}function Aa(t){let e,n,l,s,u,d,o;function c(){return t[14](t[29])}return{c(){e=r("a"),n=r("div"),l=p(),s=r("p"),s.textContent=`${t[29].label}`,a(n,"class",t[29].icon+" mr-2"),a(e,"href","##"),a(e,"class",u="nv "+(t[1]===t[29]?"nv_selected":""))},m(h,w){L(h,e,w),i(e,n),i(e,l),i(e,s),d||(o=A(e,"click",c),d=!0)},p(h,w){t=h,w[0]&2&&u!==(u="nv "+(t[1]===t[29]?"nv_selected":""))&&a(e,"class",u)},d(h){h&&S(e),d=!1,o()}}}function er(t){let e,n=t[29]&&Aa(t);return{c(){n&&n.c(),e=Ol()},m(l,s){n&&n.m(l,s),L(l,e,s)},p(l,s){l[29]&&n.p(l,s)},d(l){l&&S(e),n&&n.d(l)}}}function tr(t){let e,n=t[26].html+"",l;return{c(){e=new Mr(!1),l=Ol(),e.a=l},m(s,u){e.m(n,s,u),L(s,l,u)},p(s,u){u[0]&16&&n!==(n=s[26].html+"")&&e.p(n)},d(s){s&&(S(l),e.d())}}}function Ma(t){let e,n,l,s,u,d,o,c,h,w,_,W,k,y,C,E,V,D,M,I,P,T,R,Y,q,Q,ie,ee,v,B,G,oe,Z=t[1].label+"",we,be,fe,ce,x,pe,K,le,te,z,J,H,re,Ae,ke,me,We,Me;function Ie(F,$){return F[0]?Ca:va}let ge=Ie(t),_e=ge(t);function Se(F,$){return F[2]?La:Sa}let Pe=Se(t),de=Pe(t),Le=he(t[5]),ae=[];for(let F=0;F`,V=p(),D=r("a"),D.innerHTML=`GitHub + `,M=p(),I=r("a"),I.innerHTML=`Source + `,P=p(),T=r("br"),R=p(),Y=r("div"),q=p(),Q=r("br"),ie=p(),ee=r("div");for(let F=0;F',Ae=p(),ke=r("div");for(let F=0;F{an(U,1)}),Wr()}Re?(x=Es(Re,De(F)),In(x.$$.fragment),sn(x.$$.fragment,1),rn(x,ce,null)):x=null}if($[0]&16){Ee=he(F[4]);let U;for(U=0;U{v.ctrlKey&&v.key==="b"&&m("toggle_menu")});const s=navigator.userAgent.toLowerCase(),u=s.includes("android")||s.includes("iphone"),d=[{label:"Welcome",component:jr,icon:"i-ph-hand-waving"},{label:"Communication",component:Yr,icon:"i-codicon-radio-tower"},!u&&{label:"App",component:aa,icon:"i-codicon-hubot"},{label:"Window",component:ta,icon:"i-codicon-window"},{label:"Menu",component:ba,icon:"i-ph-list"},{label:"Tray",component:ya,icon:"i-ph-tray"},{label:"WebRTC",component:la,icon:"i-ph-broadcast"}];let o=d[0];function c(v){n(1,o=v)}let h;Ki(()=>{n(2,h=localStorage&&localStorage.getItem("theme")=="dark"),ir(h)});function w(){n(2,h=!h),ir(h)}let _=Dr([]);Cr(t,_,v=>n(4,l=v));function W(v){_.update(B=>[{html:`
[${new Date().toLocaleTimeString()}]: `+(typeof v=="string"?v:JSON.stringify(v,null,1))+"
"},...B])}function k(v){_.update(B=>[{html:`
[${new Date().toLocaleTimeString()}]: `+v+"
"},...B])}function y(){_.update(()=>[])}let C,E,V;function D(v){V=v.clientY;const B=window.getComputedStyle(C);E=parseInt(B.height,10);const G=Z=>{const we=Z.clientY-V,be=E-we;n(3,C.style.height=`${be{document.removeEventListener("mouseup",oe),document.removeEventListener("mousemove",G)};document.addEventListener("mouseup",oe),document.addEventListener("mousemove",G)}let M=!1,I,P,T=!1,R=0,Y=0;const q=(v,B,G)=>Math.min(Math.max(B,v),G);Ki(()=>{n(13,I=document.querySelector("#sidebar")),P=document.querySelector("#sidebarToggle"),document.addEventListener("click",v=>{P.contains(v.target)?n(0,M=!M):M&&!I.contains(v.target)&&n(0,M=!1)}),document.addEventListener("touchstart",v=>{if(P.contains(v.target))return;const B=v.touches[0].clientX;(0{if(T){const B=v.touches[0].clientX;Y=B;const G=(B-R)/10;I.style.setProperty("--translate-x",`-${q(0,M?0-G:18.75-G,18.75)}rem`)}}),document.addEventListener("touchend",()=>{if(T){const v=(Y-R)/10;n(0,M=M?v>-(18.75/2):v>18.75/2)}T=!1})});const Q=v=>{c(v),n(0,M=!1)},ie=v=>v.key==="Enter"?y():{};function ee(v){On[v?"unshift":"push"](()=>{C=v,n(3,C)})}return t.$$.update=()=>{if(t.$$.dirty[0]&1){const v=document.querySelector("#sidebar");v&&Pa(v,M)}},[M,o,h,C,l,d,c,w,_,W,k,y,D,I,Q,ie,ee]}class Ta extends xe{constructor(e){super(),Ze(this,e,Ea,Ma,je,{},null,[-1,-1])}}new Ta({target:document.querySelector("#app")}); diff --git a/examples/api/dist/index.html b/examples/api/dist/index.html index a3d79e1136b6..843e37e3bcae 100644 --- a/examples/api/dist/index.html +++ b/examples/api/dist/index.html @@ -3,7 +3,7 @@ - Svelte + Vite App + API Example App diff --git a/examples/api/index.html b/examples/api/index.html index 3b39b0f66a9f..df11ed2eaedf 100644 --- a/examples/api/index.html +++ b/examples/api/index.html @@ -3,7 +3,7 @@ - Svelte + Vite App + API Example App diff --git a/examples/api/package.json b/examples/api/package.json index 654c53662dd7..b1ab68734517 100644 --- a/examples/api/package.json +++ b/examples/api/package.json @@ -1,11 +1,12 @@ { - "name": "svelte-app", + "name": "api", + "private": true, "version": "1.0.0", "type": "module", "scripts": { - "dev": "vite --clearScreen false", + "dev": "vite", "build": "vite build", - "serve": "vite preview", + "preview": "vite preview", "tauri": "node ../../tooling/cli/node/tauri.js" }, "dependencies": { diff --git a/examples/api/src-tauri/Cargo.lock b/examples/api/src-tauri/Cargo.lock index df4121460bf3..332f6bf0c23f 100644 --- a/examples/api/src-tauri/Cargo.lock +++ b/examples/api/src-tauri/Cargo.lock @@ -193,11 +193,11 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b0c4a4f319e45986f347ee47fef8bf5e81c9abc3f6f58dc2391439f30df65f0" dependencies = [ - "async-lock", + "async-lock 2.8.0", "async-task", "concurrent-queue", "fastrand 2.0.1", - "futures-lite", + "futures-lite 1.13.0", "slab", ] @@ -207,10 +207,10 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" dependencies = [ - "async-lock", + "async-lock 2.8.0", "autocfg", "blocking", - "futures-lite", + "futures-lite 1.13.0", ] [[package]] @@ -219,20 +219,40 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" dependencies = [ - "async-lock", + "async-lock 2.8.0", "autocfg", "cfg-if", "concurrent-queue", - "futures-lite", + "futures-lite 1.13.0", "log", "parking", - "polling", - "rustix 0.37.26", + "polling 2.8.0", + "rustix 0.37.27", "slab", "socket2 0.4.9", "waker-fn", ] +[[package]] +name = "async-io" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41ed9d5715c2d329bf1b4da8d60455b99b187f27ba726df2883799af9af60997" +dependencies = [ + "async-lock 3.0.0", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite 2.0.1", + "parking", + "polling 3.3.0", + "rustix 0.38.21", + "slab", + "tracing", + "waker-fn", + "windows-sys 0.48.0", +] + [[package]] name = "async-lock" version = "2.8.0" @@ -242,20 +262,31 @@ dependencies = [ "event-listener 2.5.3", ] +[[package]] +name = "async-lock" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e900cdcd39bb94a14487d3f7ef92ca222162e6c7c3fe7cb3550ea75fb486ed" +dependencies = [ + "event-listener 3.0.1", + "event-listener-strategy", + "pin-project-lite", +] + [[package]] name = "async-process" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" dependencies = [ - "async-io", - "async-lock", + "async-io 1.13.0", + "async-lock 2.8.0", "async-signal", "blocking", "cfg-if", - "event-listener 3.0.0", - "futures-lite", - "rustix 0.38.20", + "event-listener 3.0.1", + "futures-lite 1.13.0", + "rustix 0.38.21", "windows-sys 0.48.0", ] @@ -272,17 +303,17 @@ dependencies = [ [[package]] name = "async-signal" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2a5415b7abcdc9cd7d63d6badba5288b2ca017e3fbd4173b8f405449f1a2399" +checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" dependencies = [ - "async-io", - "async-lock", + "async-io 2.2.0", + "async-lock 2.8.0", "atomic-waker", "cfg-if", "futures-core", "futures-io", - "rustix 0.38.20", + "rustix 0.38.21", "signal-hook-registry", "slab", "windows-sys 0.48.0", @@ -398,11 +429,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c36a4d0d48574b3dd360b4b7d95cc651d2b6557b6402848a27d4b228a473e2a" dependencies = [ "async-channel", - "async-lock", + "async-lock 2.8.0", "async-task", "fastrand 2.0.1", "futures-io", - "futures-lite", + "futures-lite 1.13.0", "piper", "tracing", ] @@ -532,6 +563,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + [[package]] name = "chrono" version = "0.4.31" @@ -1002,9 +1039,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "7c18ee0ed65a5f1f81cac6b1d213b69c35fa47d4252ad41f1486dbd8226fe36e" dependencies = [ "libc", "windows-sys 0.48.0", @@ -1018,15 +1055,25 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29e56284f00d94c1bc7fd3c77027b4623c88c1f53d8d2394c6199f2921dea325" +checksum = "01cec0252c2afff729ee6f00e903d479fba81784c8e2bd77447673471fdfaea1" dependencies = [ "concurrent-queue", "parking", "pin-project-lite", ] +[[package]] +name = "event-listener-strategy" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96b852f1345da36d551b9473fa1e2b1eb5c5195585c6c018118bc92a8d91160" +dependencies = [ + "event-listener 3.0.1", + "pin-project-lite", +] + [[package]] name = "fastrand" version = "1.9.0" @@ -1185,6 +1232,16 @@ dependencies = [ "waker-fn", ] +[[package]] +name = "futures-lite" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3831c2651acb5177cbd83943f3d9c8912c5ad03c76afcc0e9511ba568ec5ebb" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "futures-macro" version = "0.3.28" @@ -1306,6 +1363,20 @@ dependencies = [ "system-deps", ] +[[package]] +name = "gdkx11" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2ea8a4909d530f79921290389cbd7c34cb9d623bfe970eaae65ca5f9cd9cce" +dependencies = [ + "gdk", + "gdkx11-sys", + "gio", + "glib", + "libc", + "x11", +] + [[package]] name = "gdkx11-sys" version = "0.18.0" @@ -1666,7 +1737,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.51.1", ] [[package]] @@ -1948,9 +2019,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" [[package]] name = "lock_api" @@ -2080,9 +2151,9 @@ dependencies = [ [[package]] name = "muda" -version = "0.10.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9767ce3b12d2928f17ff4f91b29e7e872a8594033d82bf00e56017cc23bb8410" +checksum = "b564d551449738387fb4541aef5fbfceaa81b2b732f2534c1c7c89dc7d673eaa" dependencies = [ "cocoa 0.25.0", "crossbeam-channel", @@ -2091,8 +2162,9 @@ dependencies = [ "objc", "once_cell", "png", + "serde", "thiserror", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2550,6 +2622,20 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "polling" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e53b6af1f60f36f8c2ac2aad5459d75a5a9b4be1e8cdd40264f315d78193e531" +dependencies = [ + "cfg-if", + "concurrent-queue", + "pin-project-lite", + "rustix 0.38.21", + "tracing", + "windows-sys 0.48.0", +] + [[package]] name = "polyval" version = "0.6.1" @@ -2743,15 +2829,6 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -2870,9 +2947,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.26" +version = "0.37.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f3f8f960ed3b5a59055428714943298bf3fa2d4a1d53135084e0544829d995" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" dependencies = [ "bitflags 1.3.2", "errno", @@ -2884,14 +2961,14 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.20" +version = "0.38.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0" +checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" dependencies = [ "bitflags 2.4.1", "errno", "libc", - "linux-raw-sys 0.4.10", + "linux-raw-sys 0.4.11", "windows-sys 0.48.0", ] @@ -3325,26 +3402,19 @@ dependencies = [ [[package]] name = "tao" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f130523fee9820ad78141d443e6cef75043acade79107bc483872bc183928c0f" +checksum = "3c0dff18fed076d29cb5779e918ef4b8a5dbb756204e4a027794f0bce233d949" dependencies = [ "bitflags 1.3.2", - "cairo-rs", "cc", - "cocoa 0.24.1", + "cocoa 0.25.0", "core-foundation", - "core-graphics 0.22.3", + "core-graphics 0.23.1", "crossbeam-channel", "dispatch", - "gdk", - "gdk-pixbuf", - "gdk-sys", "gdkwayland-sys", "gdkx11-sys", - "gio", - "glib", - "glib-sys", "gtk", "image", "instant", @@ -3361,13 +3431,12 @@ dependencies = [ "png", "raw-window-handle", "scopeguard", - "serde", "tao-macros", "unicode-segmentation", "url", - "uuid", - "windows 0.51.1", + "windows 0.52.0", "windows-implement", + "windows-version", "x11-dl", "zbus", ] @@ -3391,7 +3460,7 @@ checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" [[package]] name = "tauri" -version = "2.0.0-alpha.17" +version = "2.0.0-alpha.18" dependencies = [ "anyhow", "bytes", @@ -3437,12 +3506,12 @@ dependencies = [ "webkit2gtk", "webview2-com", "window-vibrancy", - "windows 0.51.1", + "windows 0.52.0", ] [[package]] name = "tauri-build" -version = "2.0.0-alpha.11" +version = "2.0.0-alpha.12" dependencies = [ "anyhow", "cargo_toml", @@ -3463,7 +3532,7 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "2.0.0-alpha.10" +version = "2.0.0-alpha.11" dependencies = [ "base64", "brotli", @@ -3487,12 +3556,12 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.0.0-alpha.10" +version = "2.0.0-alpha.11" dependencies = [ "heck", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.38", "tauri-codegen", "tauri-utils", ] @@ -3523,7 +3592,7 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.5" dependencies = [ "gtk", "http", @@ -3534,12 +3603,12 @@ dependencies = [ "tauri-utils", "thiserror", "url", - "windows 0.51.1", + "windows 0.52.0", ] [[package]] name = "tauri-runtime-wry" -version = "1.0.0-alpha.5" +version = "1.0.0-alpha.6" dependencies = [ "cocoa 0.24.1", "gtk", @@ -3547,17 +3616,18 @@ dependencies = [ "jni", "percent-encoding", "raw-window-handle", + "tao", "tauri-runtime", "tauri-utils", "webkit2gtk", "webview2-com", - "windows 0.51.1", + "windows 0.52.0", "wry", ] [[package]] name = "tauri-utils" -version = "2.0.0-alpha.10" +version = "2.0.0-alpha.11" dependencies = [ "aes-gcm", "brotli", @@ -3583,7 +3653,6 @@ dependencies = [ "thiserror", "url", "walkdir", - "windows 0.51.1", ] [[package]] @@ -3598,14 +3667,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", "fastrand 2.0.1", - "redox_syscall 0.3.5", - "rustix 0.38.20", + "redox_syscall 0.4.1", + "rustix 0.38.21", "windows-sys 0.48.0", ] @@ -3871,9 +3940,9 @@ dependencies = [ [[package]] name = "tray-icon" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a7dce8a4b6d7a566ca78fa43f37efc7a3ec427480828d35fe3474c4f0c75396" +checksum = "5375d350db4ccd3c783a4c683be535e70df5c62b07a824e7bcd6d43ef6d74181" dependencies = [ "cocoa 0.25.0", "core-graphics 0.23.1", @@ -3884,8 +3953,9 @@ dependencies = [ "objc", "once_cell", "png", + "serde", "thiserror", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -4199,14 +4269,14 @@ dependencies = [ [[package]] name = "webview2-com" -version = "0.27.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15556ff1d1d6bc850dbb362762bae86069773dd30177c90d3bfa917080dc73" +checksum = "e0ae9c7e420783826cf769d2c06ac9ba462f450eca5893bb8c6c6529a4e5dd33" dependencies = [ "webview2-com-macros", "webview2-com-sys", - "windows 0.51.1", - "windows-core", + "windows 0.52.0", + "windows-core 0.52.0", "windows-implement", "windows-interface", ] @@ -4224,13 +4294,13 @@ dependencies = [ [[package]] name = "webview2-com-sys" -version = "0.27.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3775bb005c3170497ec411b36005708b57ad486bfa3d23864c92f5973858ce8d" +checksum = "d6ad85fceee6c42fa3d61239eba5a11401bf38407a849ed5ea1b407df08cca72" dependencies = [ "thiserror", - "windows 0.51.1", - "windows-core", + "windows 0.52.0", + "windows-core 0.52.0", ] [[package]] @@ -4299,14 +4369,14 @@ dependencies = [ [[package]] name = "windows" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ - "windows-core", + "windows-core 0.52.0", "windows-implement", "windows-interface", - "windows-targets 0.48.5", + "windows-targets 0.52.0", ] [[package]] @@ -4318,11 +4388,20 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-implement" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb2b158efec5af20d8846836622f50a87e6556b9153a42772fa047f773c0e555" +checksum = "12168c33176773b86799be25e2a2ba07c7aab9968b37541f1094dbd7a60c8946" dependencies = [ "proc-macro2", "quote", @@ -4331,9 +4410,9 @@ dependencies = [ [[package]] name = "windows-interface" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0546e63e1ce64c04403d2311fa0e3ab5ae3a367bd524b4a38d8d8d18c70cfa76" +checksum = "9d8dc32e0095a7eeccebd0e3f09e9509365ecb3fc6ac4d6f5f14a3f6392942d1" dependencies = [ "proc-macro2", "quote", @@ -4358,6 +4437,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -4388,6 +4476,30 @@ dependencies = [ "windows_x86_64_msvc 0.48.5", ] +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + +[[package]] +name = "windows-version" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75aa004c988e080ad34aff5739c39d0312f4684699d6d71fc8a198d057b8b9b4" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -4400,6 +4512,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -4412,6 +4530,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -4424,6 +4548,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -4436,6 +4566,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -4448,6 +4584,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -4460,6 +4602,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -4472,6 +4620,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "winnow" version = "0.5.17" @@ -4503,38 +4657,47 @@ dependencies = [ [[package]] name = "wry" -version = "0.34.2" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f1e29660f22d8eec141f41f59b7fef231e4113c370c89b90ae3a0db8dec1927" +checksum = "764ce8212721205a90c79f5fa04f5135af597bea9072f22a5e7f39dcd0669f2e" dependencies = [ "base64", "block", + "cfg_aliases", "cocoa 0.25.0", "core-graphics 0.23.1", "crossbeam-channel", "dunce", + "gdkx11", "gtk", "html5ever", "http", "javascriptcore-rs", + "jni", "kuchikiki", "libc", "log", + "ndk", + "ndk-context", + "ndk-sys", "objc", "objc_id", "once_cell", + "raw-window-handle", "serde", "serde_json", "sha2", "soup3", - "tao", + "tao-macros", "thiserror", "url", "webkit2gtk", "webkit2gtk-sys", "webview2-com", - "windows 0.51.1", + "windows 0.52.0", "windows-implement", + "windows-version", + "x11-dl", ] [[package]] @@ -4577,8 +4740,8 @@ dependencies = [ "async-broadcast", "async-executor", "async-fs", - "async-io", - "async-lock", + "async-io 1.13.0", + "async-lock 2.8.0", "async-process", "async-recursion", "async-task", diff --git a/examples/api/src-tauri/Cargo.toml b/examples/api/src-tauri/Cargo.toml index c83ce5c1ce12..050df85030c5 100644 --- a/examples/api/src-tauri/Cargo.toml +++ b/examples/api/src-tauri/Cargo.toml @@ -43,7 +43,7 @@ path = "../../../core/tauri" features = ["test"] [target."cfg(target_os = \"windows\")".dependencies] -window-shadows= "0.2" +window-shadows = "0.2" [features] custom-protocol = [ "tauri/custom-protocol" ] diff --git a/examples/api/src-tauri/src/lib.rs b/examples/api/src-tauri/src/lib.rs index 58e12a291924..1fff529f64f6 100644 --- a/examples/api/src-tauri/src/lib.rs +++ b/examples/api/src-tauri/src/lib.rs @@ -2,11 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -#![cfg_attr( - all(not(debug_assertions), target_os = "windows"), - windows_subsystem = "windows" -)] - mod cmd; #[cfg(desktop)] mod tray; @@ -49,7 +44,7 @@ pub fn run_app) + Send + 'static>( #[cfg(desktop)] { let handle = app.handle(); - tray::create_tray(&handle)?; + tray::create_tray(handle)?; handle.plugin(tauri_plugin_cli::init())?; } @@ -73,7 +68,7 @@ pub fn run_app) + Send + 'static>( .inner_size(1000., 800.) .min_inner_size(600., 400.) .content_protected(true) - .menu(tauri::menu::Menu::default(&app.handle())?); + .menu(tauri::menu::Menu::default(app.handle())?); } let window = window_builder.build().unwrap(); diff --git a/examples/api/src-tauri/tauri.conf.json b/examples/api/src-tauri/tauri.conf.json index 20bf653403b7..95efe9a3f98f 100644 --- a/examples/api/src-tauri/tauri.conf.json +++ b/examples/api/src-tauri/tauri.conf.json @@ -2,7 +2,7 @@ "$schema": "../../../core/tauri-config-schema/schema.json", "build": { "distDir": "../dist", - "devPath": "http://localhost:5173", + "devPath": "http://localhost:1420", "beforeDevCommand": "yarn dev", "beforeBuildCommand": "yarn build", "withGlobalTauri": true @@ -26,11 +26,7 @@ "name": "theme", "takesValue": true, "description": "App theme", - "possibleValues": [ - "light", - "dark", - "system" - ] + "possibleValues": ["light", "dark", "system"] }, { "short": "v", @@ -93,9 +89,7 @@ "csp": { "default-src": "'self' customprotocol: asset:", "connect-src": "ipc: http://ipc.localhost", - "font-src": [ - "https://fonts.gstatic.com" - ], + "font-src": ["https://fonts.gstatic.com"], "img-src": "'self' asset: http://asset.localhost blob: data:", "style-src": "'unsafe-inline' 'self' https://fonts.googleapis.com" }, @@ -103,15 +97,10 @@ "assetProtocol": { "enable": true, "scope": { - "allow": [ - "$APPDATA/db/**", - "$RESOURCE/**" - ], - "deny": [ - "$APPDATA/db/*.stronghold" - ] + "allow": ["$APPDATA/db/**", "$RESOURCE/**"], + "deny": ["$APPDATA/db/*.stronghold"] } } } } -} \ No newline at end of file +} diff --git a/examples/api/src/App.svelte b/examples/api/src/App.svelte index e5e14bc64119..5576fbc39f6f 100644 --- a/examples/api/src/App.svelte +++ b/examples/api/src/App.svelte @@ -1,14 +1,15 @@ + +
+ + +
+ {#each items as item} +
+
+

{itemToString(item)}

+
+ {/each} +
+
diff --git a/examples/api/src/components/MenuItemBuilder.svelte b/examples/api/src/components/MenuItemBuilder.svelte new file mode 100644 index 000000000000..a2feea435843 --- /dev/null +++ b/examples/api/src/components/MenuItemBuilder.svelte @@ -0,0 +1,158 @@ + + +
+
+ {#each itemKinds as itemKind} +
+ + +
+ {/each} +
+ +
+ +
+ {#if kind == 'Normal' || kind == 'Icon' || kind == 'Check'} + + {/if} + {#if kind == 'Icon'} + + {:else if kind == 'Check'} +
+ + +
+ {:else if kind == 'Predefined'} +
+ {#each predefinedOptions as predefinedOption} +
+ + +
+ {/each} +
+ {/if} +
+ +
+ +
+ +
+
diff --git a/examples/api/src/views/Communication.svelte b/examples/api/src/views/Communication.svelte index 69f5593fea36..e24a8600931a 100644 --- a/examples/api/src/views/Communication.svelte +++ b/examples/api/src/views/Communication.svelte @@ -1,6 +1,6 @@ + +
+ + + +
diff --git a/examples/api/src/views/Tray.svelte b/examples/api/src/views/Tray.svelte new file mode 100644 index 000000000000..586b0ef7e0d0 --- /dev/null +++ b/examples/api/src/views/Tray.svelte @@ -0,0 +1,79 @@ + + +
+
+ + + + + +
+ +
+ + + +
+ +
+ +
+ +
+ +
+
diff --git a/examples/api/src/views/WebRTC.svelte b/examples/api/src/views/WebRTC.svelte index e0f9862a5ec6..f646b2dc69e5 100644 --- a/examples/api/src/views/WebRTC.svelte +++ b/examples/api/src/views/WebRTC.svelte @@ -42,7 +42,7 @@ }) onDestroy(() => { - window.stream.getTracks().forEach(function (track) { + window.stream?.getTracks().forEach(function (track) { track.stop() }) }) diff --git a/examples/api/src/views/Welcome.svelte b/examples/api/src/views/Welcome.svelte index 8e8c205226c8..084c66521950 100644 --- a/examples/api/src/views/Welcome.svelte +++ b/examples/api/src/views/Welcome.svelte @@ -1,5 +1,5 @@ diff --git a/examples/streaming/index.html b/examples/streaming/index.html index a0eabf610ab7..ce2e413d74a2 100644 --- a/examples/streaming/index.html +++ b/examples/streaming/index.html @@ -20,7 +20,7 @@ diff --git a/tooling/bundler/CHANGELOG.md b/tooling/bundler/CHANGELOG.md index 008bd90472de..3249edd5f4c2 100644 --- a/tooling/bundler/CHANGELOG.md +++ b/tooling/bundler/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## \[2.0.0-alpha.12] + +### Bug Fixes + +- [`34196e25`](https://www.github.com/tauri-apps/tauri/commit/34196e25c4ca2362bdfe1cf4598082aca71fe0a0)([#8182](https://www.github.com/tauri-apps/tauri/pull/8182)) Use original version string on WiX output file name. + +### Dependencies + +- Upgraded to `tauri-utils@2.0.0-alpha.11` + ## \[2.0.0-alpha.11] ### Enhancements diff --git a/tooling/bundler/Cargo.toml b/tooling/bundler/Cargo.toml index cda994c7736a..5631d5041434 100644 --- a/tooling/bundler/Cargo.toml +++ b/tooling/bundler/Cargo.toml @@ -2,7 +2,7 @@ workspace = { } [package] name = "tauri-bundler" -version = "2.0.0-alpha.11" +version = "2.0.0-alpha.12" authors = [ "George Burton ", "Tauri Programme within The Commons Conservancy" @@ -17,7 +17,7 @@ rust-version = "1.70" exclude = [ "CHANGELOG.md", "/target", "rustfmt.toml" ] [dependencies] -tauri-utils = { version = "2.0.0-alpha.10", path = "../../core/tauri-utils", features = [ "resources" ] } +tauri-utils = { version = "2.0.0-alpha.11", path = "../../core/tauri-utils", features = [ "resources" ] } image = "0.24.7" libflate = "2.0" anyhow = "1.0" diff --git a/tooling/bundler/src/bundle.rs b/tooling/bundler/src/bundle.rs index 763ca75b7696..ae26b0d7d8fa 100644 --- a/tooling/bundler/src/bundle.rs +++ b/tooling/bundler/src/bundle.rs @@ -20,8 +20,8 @@ use tauri_utils::display_path; pub use self::{ category::AppCategory, settings::{ - BundleBinary, BundleSettings, DebianSettings, MacOsSettings, PackageSettings, PackageType, - Settings, SettingsBuilder, UpdaterSettings, + BundleBinary, BundleSettings, DebianSettings, DmgSettings, MacOsSettings, PackageSettings, + PackageType, Position, Settings, SettingsBuilder, Size, UpdaterSettings, }, }; #[cfg(target_os = "macos")] diff --git a/tooling/bundler/src/bundle/macos/dmg.rs b/tooling/bundler/src/bundle/macos/dmg.rs index 3748a5cfe6de..94214e5a7d18 100644 --- a/tooling/bundler/src/bundle/macos/dmg.rs +++ b/tooling/bundler/src/bundle/macos/dmg.rs @@ -96,55 +96,90 @@ pub fn bundle_project(settings: &Settings, bundles: &[Bundle]) -> crate::Result< .output() .expect("Failed to chmod script"); - let mut args = vec![ + let dmg_settings = settings.dmg(); + + let app_position = &dmg_settings.app_position; + let application_folder_position = &dmg_settings.application_folder_position; + let window_size = &dmg_settings.window_size; + + let app_position_x = app_position.x.to_string(); + let app_position_y = app_position.y.to_string(); + let application_folder_position_x = application_folder_position.x.to_string(); + let application_folder_position_y = application_folder_position.y.to_string(); + let window_size_width = window_size.width.to_string(); + let window_size_height = window_size.height.to_string(); + + let mut bundle_dmg_cmd = Command::new(&bundle_script_path); + + bundle_dmg_cmd.args([ "--volname", product_name, "--icon", &bundle_file_name, - "180", - "170", + &app_position_x, + &app_position_y, "--app-drop-link", - "480", - "170", + &application_folder_position_x, + &application_folder_position_y, "--window-size", - "660", - "400", + &window_size_width, + &window_size_height, "--hide-extension", &bundle_file_name, - ]; + ]); - let icns_icon_path = - create_icns_file(&output_path, settings)?.map(|path| path.to_string_lossy().to_string()); + let window_position = dmg_settings + .window_position + .as_ref() + .map(|position| (position.x.to_string(), position.y.to_string())); + + if let Some(window_position) = &window_position { + bundle_dmg_cmd.arg("--window-pos"); + bundle_dmg_cmd.arg(&window_position.0); + bundle_dmg_cmd.arg(&window_position.1); + } + + let background_path = if let Some(background_path) = &dmg_settings.background { + Some(env::current_dir()?.join(background_path)) + } else { + None + }; + + if let Some(background_path) = &background_path { + bundle_dmg_cmd.arg("--background"); + bundle_dmg_cmd.arg(background_path); + } + + let icns_icon_path = create_icns_file(&output_path, settings)?; if let Some(icon) = &icns_icon_path { - args.push("--volicon"); - args.push(icon); + bundle_dmg_cmd.arg("--volicon"); + bundle_dmg_cmd.arg(icon); } - #[allow(unused_assignments)] - let mut license_path_ref = "".to_string(); - if let Some(license_path) = &settings.macos().license { - args.push("--eula"); - license_path_ref = env::current_dir()? - .join(license_path) - .to_string_lossy() - .to_string(); - args.push(&license_path_ref); + let license_path = if let Some(license_path) = &settings.macos().license { + Some(env::current_dir()?.join(license_path)) + } else { + None + }; + + if let Some(license_path) = &license_path { + bundle_dmg_cmd.arg("--eula"); + bundle_dmg_cmd.arg(license_path); } // Issue #592 - Building MacOS dmg files on CI // https://github.com/tauri-apps/tauri/issues/592 if let Some(value) = env::var_os("CI") { if value == "true" { - args.push("--skip-jenkins"); + bundle_dmg_cmd.arg("--skip-jenkins"); } } info!(action = "Running"; "bundle_dmg.sh"); // execute the bundle script - Command::new(&bundle_script_path) + bundle_dmg_cmd .current_dir(bundle_dir.clone()) - .args(args) .args(vec![dmg_name.as_str(), bundle_file_name.as_str()]) .output_ok() .context("error running bundle_dmg.sh")?; diff --git a/tooling/bundler/src/bundle/macos/sign.rs b/tooling/bundler/src/bundle/macos/sign.rs index bbdcd55daae2..48f7bfcddcbd 100644 --- a/tooling/bundler/src/bundle/macos/sign.rs +++ b/tooling/bundler/src/bundle/macos/sign.rs @@ -305,23 +305,21 @@ pub fn notarize( log::info!(action = "Notarizing"; "{}", log_message); staple_app(app_bundle_path)?; Ok(()) - } else { - if let Ok(output) = Command::new("xcrun") - .args(["notarytool", "log"]) - .arg(&submit_output.id) - .notarytool_args(&auth) - .output_ok() - { - Err( - anyhow::anyhow!( - "{log_message}\nLog:\n{}", - String::from_utf8_lossy(&output.stdout) - ) - .into(), + } else if let Ok(output) = Command::new("xcrun") + .args(["notarytool", "log"]) + .arg(&submit_output.id) + .notarytool_args(&auth) + .output_ok() + { + Err( + anyhow::anyhow!( + "{log_message}\nLog:\n{}", + String::from_utf8_lossy(&output.stdout) ) - } else { - Err(anyhow::anyhow!("{log_message}").into()) - } + .into(), + ) + } else { + Err(anyhow::anyhow!("{log_message}").into()) } } else { Err(anyhow::anyhow!("failed to parse notarytool output as JSON: `{output_str}`").into()) diff --git a/tooling/bundler/src/bundle/settings.rs b/tooling/bundler/src/bundle/settings.rs index 7a5e35d964dd..68934ded1f5e 100644 --- a/tooling/bundler/src/bundle/settings.rs +++ b/tooling/bundler/src/bundle/settings.rs @@ -183,6 +183,39 @@ pub struct DebianSettings { pub desktop_template: Option, } +/// Position coordinates struct. +#[derive(Clone, Debug, Default)] +pub struct Position { + /// X coordinate. + pub x: u32, + /// Y coordinate. + pub y: u32, +} + +/// Size of the window. +#[derive(Clone, Debug, Default)] +pub struct Size { + /// Width of the window. + pub width: u32, + /// Height of the window. + pub height: u32, +} + +/// The DMG bundle settings. +#[derive(Clone, Debug, Default)] +pub struct DmgSettings { + /// Image to use as the background in dmg file. Accepted formats: `png`/`jpg`/`gif`. + pub background: Option, + /// Position of volume window on screen. + pub window_position: Option, + /// Size of volume window. + pub window_size: Size, + /// Position of app file on window. + pub app_position: Position, + /// Position of application folder on window. + pub application_folder_position: Position, +} + /// The macOS bundle settings. #[derive(Clone, Debug, Default)] pub struct MacOsSettings { @@ -416,6 +449,8 @@ pub struct BundleSettings { pub external_bin: Option>, /// Debian-specific settings. pub deb: DebianSettings, + /// DMG-specific settings. + pub dmg: DmgSettings, /// MacOS-specific settings. pub macos: MacOsSettings, /// Updater configuration. @@ -850,6 +885,11 @@ impl Settings { &self.bundle_settings.deb } + /// Returns the DMG settings. + pub fn dmg(&self) -> &DmgSettings { + &self.bundle_settings.dmg + } + /// Returns the MacOS settings. pub fn macos(&self) -> &MacOsSettings { &self.bundle_settings.macos diff --git a/tooling/bundler/src/bundle/windows/nsis.rs b/tooling/bundler/src/bundle/windows/nsis.rs index ed15a642739d..0b59a15a66b4 100644 --- a/tooling/bundler/src/bundle/windows/nsis.rs +++ b/tooling/bundler/src/bundle/windows/nsis.rs @@ -429,7 +429,7 @@ fn build_nsis_app_installer( } write_ut16_le_with_bom( - &output_path.join("FileAssociation.nsh"), + output_path.join("FileAssociation.nsh"), include_str!("./templates/FileAssociation.nsh"), )?; diff --git a/tooling/bundler/src/error.rs b/tooling/bundler/src/error.rs index ad73de876813..cc412d85bce1 100644 --- a/tooling/bundler/src/error.rs +++ b/tooling/bundler/src/error.rs @@ -67,6 +67,9 @@ pub enum Error { /// Couldn't find icons. #[error("Could not find Icon paths. Please make sure they exist in the tauri config JSON file")] IconPathError, + /// Couldn't find background file. + #[error("Could not find background file. Make sure it exists in the tauri config JSON file and extension is png/jpg/gif")] + BackgroundPathError, /// Error on path util operation. #[error("Path Error:`{0}`")] PathUtilError(String), diff --git a/tooling/cli/CHANGELOG.md b/tooling/cli/CHANGELOG.md index 003e28fa2b07..172c0a523afa 100644 --- a/tooling/cli/CHANGELOG.md +++ b/tooling/cli/CHANGELOG.md @@ -1,5 +1,28 @@ # Changelog +## \[2.0.0-alpha.18] + +### New Features + +- [`50f7ccbb`](https://www.github.com/tauri-apps/tauri/commit/50f7ccbbf3467f33cc7dd1cca53125fec6eda1c6)([#6444](https://www.github.com/tauri-apps/tauri/pull/6444)) Add suport to SVG input image for the `tauri icon` command. +- [`25e5f91d`](https://www.github.com/tauri-apps/tauri/commit/25e5f91dae7fe2bbc1ba4317d5d829402bfd1d50)([#8200](https://www.github.com/tauri-apps/tauri/pull/8200)) Merge `src-tauri/Info.plist` and `src-tauri/Info.ios.plist` with the iOS project plist file. + +### Enhancements + +- [`01a7a983`](https://www.github.com/tauri-apps/tauri/commit/01a7a983aba2946b455a608b8a6a4b08cb25fc11)([#8128](https://www.github.com/tauri-apps/tauri/pull/8128)) Transform paths to relative to the mobile project for the IDE script runner script. + +### Bug Fixes + +- [`88dac86f`](https://www.github.com/tauri-apps/tauri/commit/88dac86f3b301d1919df6473a9e20f46b560f29b)([#8149](https://www.github.com/tauri-apps/tauri/pull/8149)) Ensure `tauri add` prints `rust_code` with plugin name in snake case. +- [`977d0e52`](https://www.github.com/tauri-apps/tauri/commit/977d0e52f14b1ad01c86371765ef25b36572459e)([#8202](https://www.github.com/tauri-apps/tauri/pull/8202)) Fixes `android build --open` and `ios build --open` IDE failing to read CLI options. +- [`bfbbefdb`](https://www.github.com/tauri-apps/tauri/commit/bfbbefdb9e13ed1f42f6db7fa9ceaa84db1267e9)([#8161](https://www.github.com/tauri-apps/tauri/pull/8161)) Fix invalid plugin template. +- [`92b50a3a`](https://www.github.com/tauri-apps/tauri/commit/92b50a3a398c9d55b6992a8f5c2571e4d72bdaaf)([#8209](https://www.github.com/tauri-apps/tauri/pull/8209)) Added support to Xcode's archive. This requires regenerating the Xcode project. + +### Dependencies + +- Upgraded to `tauri-bundler@2.0.0-alpha.12` +- Upgraded to `tauri-utils@2.0.0-alpha.11` + ## \[2.0.0-alpha.17] ### Enhancements diff --git a/tooling/cli/Cargo.lock b/tooling/cli/Cargo.lock index fbfc953a994e..480d6f57d9ba 100644 --- a/tooling/cli/Cargo.lock +++ b/tooling/cli/Cargo.lock @@ -60,15 +60,16 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" dependencies = [ "cfg-if", - "getrandom 0.2.10", + "getrandom 0.2.11", "once_cell", "serde", "version_check", + "zerocopy", ] [[package]] @@ -184,7 +185,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -346,9 +347,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c79ad7fb2dd38f3dabd76b09c6a5a20c038fc0213ef1e9afd30eb777f120f019" +checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c" dependencies = [ "memchr", "serde", @@ -362,9 +363,9 @@ checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytecount" -version = "0.6.4" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad152d03a2c813c80bb94fedbf3a3f02b28f793e39e7c214c8a0bcc196343de7" +checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" [[package]] name = "bytemuck" @@ -413,7 +414,7 @@ dependencies = [ "serde_json", "textwrap", "thiserror", - "toml 0.8.2", + "toml 0.8.8", "ureq", "which", "windows 0.51.1", @@ -470,9 +471,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.6" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" +checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" dependencies = [ "clap_builder", "clap_derive", @@ -480,9 +481,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.6" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" +checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" dependencies = [ "anstream", "anstyle", @@ -492,30 +493,30 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.4.3" +version = "4.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ae8ba90b9d8b007efe66e55e48fb936272f5ca00349b5b0e89877520d35ea7" +checksum = "bffe91f06a11b4b9420f62103854e90867812cd5d01557f853c5ee8e791b12ae" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.4.2" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "color_quant" @@ -601,9 +602,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" dependencies = [ "libc", ] @@ -707,7 +708,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -727,7 +728,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37e366bff8cd32dd8754b0991fb66b279dc48f598c3a18914852a6673deef583" dependencies = [ "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -770,7 +771,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -781,7 +782,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -920,9 +921,9 @@ checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "dyn-clone" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd" +checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" [[package]] name = "either" @@ -938,7 +939,7 @@ checksum = "f54cc3e827ee1c3812239a9a41dede7b4d7d5d5464faa32d71bd7cba28ce2cb2" dependencies = [ "cc", "rustc_version", - "toml 0.8.2", + "toml 0.8.8", "vswhom", "winreg 0.51.0", ] @@ -966,9 +967,9 @@ checksum = "4e4f5d6e192964d498b45abee72ca445e91909094bc8e8791259e82c2a0d1aa6" [[package]] name = "env_logger" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" dependencies = [ "humantime", "is-terminal", @@ -994,9 +995,9 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" dependencies = [ "libc", "windows-sys 0.48.0", @@ -1042,9 +1043,9 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "fdeflate" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" +checksum = "64d6dafc854908ff5da46ff3f8f473c6984119a2876a383a860246dd7841a868" dependencies = [ "simd-adler32", ] @@ -1083,7 +1084,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ - "spin 0.9.8", + "spin", ] [[package]] @@ -1180,9 +1181,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" dependencies = [ "futures-channel", "futures-core", @@ -1194,9 +1195,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" dependencies = [ "futures-core", "futures-sink", @@ -1204,38 +1205,38 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" [[package]] name = "futures-timer" @@ -1245,9 +1246,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" dependencies = [ "futures-channel", "futures-core", @@ -1293,9 +1294,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", "js-sys", @@ -1351,9 +1352,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.21" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" dependencies = [ "bytes", "fnv", @@ -1361,7 +1362,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 1.9.3", + "indexmap 2.1.0", "slab", "tokio", "tokio-util", @@ -1379,9 +1380,9 @@ dependencies = [ [[package]] name = "handlebars" -version = "4.4.0" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39b3bc2a8f715298032cf5087e58573809374b08160aa7d750582bdb82d2683" +checksum = "faa67bab9ff362228eb3d00bd024a4965d8231bbb7921167f0cfa66c6626b225" dependencies = [ "log", "pest", @@ -1467,9 +1468,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", @@ -1522,7 +1523,7 @@ dependencies = [ "httpdate", "itoa 1.0.9", "pin-project-lite", - "socket2 0.4.9", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -1642,9 +1643,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", "hashbrown 0.14.2", @@ -1711,9 +1712,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is-terminal" @@ -1722,7 +1723,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi", - "rustix 0.38.21", + "rustix 0.38.25", "windows-sys 0.48.0", ] @@ -1778,9 +1779,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" dependencies = [ "wasm-bindgen", ] @@ -1810,9 +1811,9 @@ dependencies = [ [[package]] name = "jsonrpsee" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de902baa44bf34a58b1a4906f8b840d7d60dcec5f41fe08b4dbc14cf9efa821c" +checksum = "affdc52f7596ccb2d7645231fc6163bb314630c989b64998f3699a28b4d5d4dc" dependencies = [ "jsonrpsee-core", "jsonrpsee-server", @@ -1822,9 +1823,9 @@ dependencies = [ [[package]] name = "jsonrpsee-client-transport" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58d9851f8f5653e0433a898e9032bde4910b35d625bd9dcf33ef6e36e7c3d456" +checksum = "b5b005c793122d03217da09af68ba9383363caa950b90d3436106df8cabce935" dependencies = [ "futures-util", "http", @@ -1840,9 +1841,9 @@ dependencies = [ [[package]] name = "jsonrpsee-core" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f45d37af23707750136379f6799e76ebfcf2d425ec4e36d0deb7921da5e65c" +checksum = "da2327ba8df2fdbd5e897e2b5ed25ce7f299d345b9736b6828814c3dbd1fd47b" dependencies = [ "anyhow", "async-lock", @@ -1865,9 +1866,9 @@ dependencies = [ [[package]] name = "jsonrpsee-server" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ed2bec9c76cee118c27138cc1c877938bcaa01207a5d902b80dbfc60466bc9c" +checksum = "82c39a00449c9ef3f50b84fc00fc4acba20ef8f559f07902244abf4c15c5ab9c" dependencies = [ "futures-util", "http", @@ -1888,9 +1889,9 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05eaff23af19f10ba6fbb76519bed6da4d3b9bbaef13d39b7c2b6c14e532d27e" +checksum = "5be0be325642e850ed0bdff426674d2e66b2b7117c9be23a7caef68a2902b7d9" dependencies = [ "anyhow", "beef", @@ -1902,9 +1903,9 @@ dependencies = [ [[package]] name = "jsonrpsee-ws-client" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd34d3ab8c09f02fd4c432f256bc8b143b616b222b03050f941ee53f0e8d7b24" +checksum = "bca9cb3933ccae417eb6b08c3448eb1cb46e39834e5b503e395e5e5bd08546c0" dependencies = [ "http", "jsonrpsee-client-transport", @@ -1926,7 +1927,7 @@ dependencies = [ "clap", "fancy-regex", "fraction", - "getrandom 0.2.10", + "getrandom 0.2.11", "iso8601", "itoa 1.0.9", "memchr", @@ -1999,9 +2000,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.149" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libflate" @@ -2029,12 +2030,23 @@ dependencies = [ [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", - "winapi", + "windows-sys 0.48.0", +] + +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall 0.4.1", ] [[package]] @@ -2054,9 +2066,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" [[package]] name = "local-ip-address" @@ -2169,7 +2181,7 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2b6f58413c6cee060115673578e47271838f3c87cb9322c61a3bcd6d740b7d2" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.11", "rpassword", "scrypt", ] @@ -2186,9 +2198,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" dependencies = [ "libc", "log", @@ -2198,9 +2210,9 @@ dependencies = [ [[package]] name = "napi" -version = "2.13.3" +version = "2.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd063c93b900149304e3ba96ce5bf210cd4f81ef5eb80ded0d100df3e85a3ac0" +checksum = "1133249c46e92da921bafc8aba4912bf84d6c475f7625183772ed2d0844dc3a7" dependencies = [ "bitflags 2.4.1", "ctor 0.2.5", @@ -2211,15 +2223,15 @@ dependencies = [ [[package]] name = "napi-build" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882a73d9ef23e8dc2ebbffb6a6ae2ef467c0f18ac10711e4cc59c5485d41df0e" +checksum = "d4b4532cf86bfef556348ac65e561e3123879f0e7566cca6d43a6ff5326f13df" [[package]] name = "napi-derive" -version = "2.13.0" +version = "2.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da1c6a8fa84d549aa8708fcd062372bf8ec6e849de39016ab921067d21bde367" +checksum = "a0cca5738c6e81eb5ffd2c8ff2b4f05ece9c4c60c7e2b36cec6524492cf7f330" dependencies = [ "cfg-if", "convert_case 0.6.0", @@ -2231,9 +2243,9 @@ dependencies = [ [[package]] name = "napi-derive-backend" -version = "1.0.52" +version = "1.0.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20bbc7c69168d06a848f925ec5f0e0997f98e8c8d4f2cc30157f0da51c009e17" +checksum = "35960e5f33228192a9b661447d0dfe8f5a3790ff5b4058c4d67680ded4f65b91" dependencies = [ "convert_case 0.6.0", "once_cell", @@ -2246,9 +2258,9 @@ dependencies = [ [[package]] name = "napi-sys" -version = "2.2.3" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "166b5ef52a3ab5575047a9fe8d4a030cdd0f63c96f071cd6907674453b07bae3" +checksum = "2503fa6af34dc83fb74888df8b22afe933b58d37daf7d80424b1c60c68196b8b" dependencies = [ "libloading", ] @@ -2484,9 +2496,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.57" +version = "0.10.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" +checksum = "7a257ad03cd8fb16ad4172fedf8094451e1af1c4b70097636ef2eac9a5f0cc33" dependencies = [ "bitflags 2.4.1", "cfg-if", @@ -2505,7 +2517,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -2516,18 +2528,18 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.1.5+3.1.3" +version = "300.1.6+3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "559068e4c12950d7dcaa1857a61725c0d38d4fc03ff8e070ab31a75d6e316491" +checksum = "439fac53e092cd7442a3660c85dde4643ab3b5bd39040912388dcdabf6b88085" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.93" +version = "0.9.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" +checksum = "40a4130519a360279579c2053038317e40eff64d13fd3f004f9e1b72b8a6aaf9" dependencies = [ "cc", "libc", @@ -2619,9 +2631,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pest" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c022f1e7b65d6a24c0dbbd5fb344c66881bc01f3e5ae74a1c8100f2f985d98a4" +checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" dependencies = [ "memchr", "thiserror", @@ -2630,9 +2642,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35513f630d46400a977c4cb58f78e1bfbe01434316e60c37d27b9ad6139c66d8" +checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2" dependencies = [ "pest", "pest_generator", @@ -2640,22 +2652,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc9fc1b9e7057baba189b5c626e2d6f40681ae5b6eb064dc7c7834101ec8123a" +checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] name = "pest_meta" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df74e9e7ec4053ceb980e7c0c8bd3594e977fde1af91daba9c928e8e8c6708d" +checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6" dependencies = [ "once_cell", "pest", @@ -2782,7 +2794,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -2835,7 +2847,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -2858,12 +2870,12 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "plist" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdc0001cfea3db57a2e24bc0d818e9e20e554b5f97fabb9bc231dc240269ae06" +checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef" dependencies = [ "base64 0.21.5", - "indexmap 1.9.3", + "indexmap 2.1.0", "line-wrap", "quick-xml", "serde", @@ -2939,9 +2951,9 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.29.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b9228215d82c7b61490fec1de287136b5de6f5700f6e58ea9ad61a7964ca51" +checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" dependencies = [ "memchr", ] @@ -3015,7 +3027,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.11", ] [[package]] @@ -3062,15 +3074,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b42e27ef78c35d3998403c1d26f3efd9e135d3e5121b0a4845cc5cc27547f4f" -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.3.5" @@ -3091,12 +3094,12 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ - "getrandom 0.2.10", - "redox_syscall 0.2.16", + "getrandom 0.2.11", + "libredox", "thiserror", ] @@ -3192,17 +3195,16 @@ dependencies = [ [[package]] name = "ring" -version = "0.16.20" +version = "0.17.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" dependencies = [ "cc", + "getrandom 0.2.11", "libc", - "once_cell", - "spin 0.5.2", + "spin", "untrusted", - "web-sys", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -3228,23 +3230,23 @@ dependencies = [ [[package]] name = "rpassword" -version = "7.2.0" +version = "7.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6678cf63ab3491898c0d021b493c94c9b221d91295294a2a5746eacbe5928322" +checksum = "80472be3c897911d0137b2d2b9055faf6eeac5b14e324073d83bc17b191d7e3f" dependencies = [ "libc", "rtoolbox", - "winapi", + "windows-sys 0.48.0", ] [[package]] name = "rtoolbox" -version = "0.0.1" +version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "034e22c514f5c0cb8a10ff341b9b048b5ceb21591f31c8f44c43b960f9b3524a" +checksum = "c247d24e63230cdb56463ae328478bd5eac8b8faa8c69461a77e8e323afac90e" dependencies = [ "libc", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -3284,22 +3286,22 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.21" +version = "0.38.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" dependencies = [ "bitflags 2.4.1", "errno", "libc", - "linux-raw-sys 0.4.10", + "linux-raw-sys 0.4.11", "windows-sys 0.48.0", ] [[package]] name = "rustls" -version = "0.21.7" +version = "0.21.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" +checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9" dependencies = [ "log", "ring", @@ -3309,9 +3311,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.101.6" +version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ "ring", "untrusted", @@ -3380,9 +3382,9 @@ dependencies = [ [[package]] name = "schemars" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f7b0ce13155372a76ee2e1c5ffba1fe61ede73fbea5630d61eee6fac4929c0c" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" dependencies = [ "dyn-clone", "schemars_derive", @@ -3393,9 +3395,9 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e85e2a16b12bdb763244c69ab79363d71db2b4b918a2def53f80b02e0574b13c" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" dependencies = [ "proc-macro2", "quote", @@ -3422,9 +3424,9 @@ dependencies = [ [[package]] name = "sct" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ "ring", "untrusted", @@ -3481,9 +3483,9 @@ checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" [[package]] name = "serde" -version = "1.0.189" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" +checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" dependencies = [ "serde_derive", ] @@ -3500,13 +3502,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.189" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" +checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -3531,9 +3533,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa 1.0.9", "ryu", @@ -3552,9 +3554,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" dependencies = [ "serde", ] @@ -3581,7 +3583,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.0.2", + "indexmap 2.1.0", "serde", "serde_json", "serde_with_macros", @@ -3597,7 +3599,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -3730,9 +3732,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "smawk" @@ -3742,9 +3744,9 @@ checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" [[package]] name = "socket2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", @@ -3752,9 +3754,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", "windows-sys 0.48.0", @@ -3776,12 +3778,6 @@ dependencies = [ "sha-1", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.8" @@ -3957,9 +3953,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.38" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", @@ -4019,7 +4015,7 @@ dependencies = [ [[package]] name = "tauri-bundler" -version = "2.0.0-alpha.11" +version = "2.0.0-alpha.12" dependencies = [ "anyhow", "ar", @@ -4046,7 +4042,7 @@ dependencies = [ "strsim", "tar", "tauri-icns", - "tauri-utils 2.0.0-alpha.10", + "tauri-utils 2.0.0-alpha.11", "tempfile", "thiserror", "time", @@ -4060,7 +4056,7 @@ dependencies = [ [[package]] name = "tauri-cli" -version = "2.0.0-alpha.17" +version = "2.0.0-alpha.18" dependencies = [ "anyhow", "axum", @@ -4096,9 +4092,9 @@ dependencies = [ "minisign", "notify", "notify-debouncer-mini", - "once_cell", "os_info", "os_pipe", + "plist", "regex", "resvg", "semver", @@ -4110,11 +4106,11 @@ dependencies = [ "tauri-bundler", "tauri-icns", "tauri-utils 1.5.0", - "tauri-utils 2.0.0-alpha.10", + "tauri-utils 2.0.0-alpha.11", "thiserror", "tokio", - "toml 0.8.2", - "toml_edit", + "toml 0.8.8", + "toml_edit 0.20.7", "unicode-width", "ureq", "url", @@ -4152,7 +4148,7 @@ dependencies = [ "aes-gcm", "ctor 0.1.26", "dunce", - "getrandom 0.2.10", + "getrandom 0.2.11", "heck", "html5ever", "infer 0.12.0", @@ -4176,12 +4172,12 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.0.0-alpha.10" +version = "2.0.0-alpha.11" dependencies = [ "aes-gcm", "ctor 0.2.5", "dunce", - "getrandom 0.2.10", + "getrandom 0.2.11", "glob", "heck", "html5ever", @@ -4199,10 +4195,9 @@ dependencies = [ "serde_with", "serialize-to-javascript", "thiserror", - "toml 0.8.2", + "toml 0.8.8", "url", "walkdir", - "windows 0.51.1", ] [[package]] @@ -4214,7 +4209,7 @@ dependencies = [ "cfg-if", "fastrand", "redox_syscall 0.4.1", - "rustix 0.38.21", + "rustix 0.38.25", "windows-sys 0.48.0", ] @@ -4231,9 +4226,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" dependencies = [ "winapi-util", ] @@ -4283,7 +4278,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -4379,9 +4374,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.33.0" +version = "1.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" dependencies = [ "backtrace", "bytes", @@ -4389,20 +4384,20 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite", - "socket2 0.5.4", + "socket2 0.5.5", "tokio-macros", "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -4430,9 +4425,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", @@ -4454,33 +4449,44 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.2" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.1.0", "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.21.0", ] [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.20.2" +version = "0.20.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" +dependencies = [ + "indexmap 2.1.0", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.1.0", "serde", "serde_spanned", "toml_datetime", @@ -4535,7 +4541,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -4689,15 +4695,15 @@ dependencies = [ [[package]] name = "untrusted" -version = "0.7.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5ccd538d4a604753ebc2f17cd9946e89b77bf87f6a8e2309667c6f2e87855e3" +checksum = "7830e33f6e25723d41a63f77e434159dad02919f18f55a512b5f16f3b1d77138" dependencies = [ "base64 0.21.5", "flate2", @@ -4797,11 +4803,11 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.5.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" +checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.11", "sha1_smol", ] @@ -4906,9 +4912,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -4916,24 +4922,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02" dependencies = [ "cfg-if", "js-sys", @@ -4943,9 +4949,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4953,28 +4959,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" dependencies = [ "js-sys", "wasm-bindgen", @@ -5001,7 +5007,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.21", + "rustix 0.38.25", "windows-sys 0.48.0", ] @@ -5042,7 +5048,7 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1c4bd0a50ac6020f65184721f758dba47bb9fbc2133df715ec74a237b26794a" dependencies = [ - "windows-implement 0.39.0", + "windows-implement", "windows_aarch64_msvc 0.39.0", "windows_i686_gnu 0.39.0", "windows_i686_msvc 0.39.0", @@ -5057,8 +5063,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" dependencies = [ "windows-core", - "windows-implement 0.51.1", - "windows-interface", "windows-targets 0.48.5", ] @@ -5081,28 +5085,6 @@ dependencies = [ "windows-tokens", ] -[[package]] -name = "windows-implement" -version = "0.51.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb2b158efec5af20d8846836622f50a87e6556b9153a42772fa047f773c0e555" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "windows-interface" -version = "0.51.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0546e63e1ce64c04403d2311fa0e3ab5ae3a367bd524b4a38d8d8d18c70cfa76" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - [[package]] name = "windows-sys" version = "0.45.0" @@ -5273,9 +5255,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.5.17" +version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c" +checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" dependencies = [ "memchr", ] @@ -5321,11 +5303,31 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" +[[package]] +name = "zerocopy" +version = "0.7.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + [[package]] name = "zeroize" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" [[package]] name = "zip" diff --git a/tooling/cli/Cargo.toml b/tooling/cli/Cargo.toml index ceb4a0d14328..c12eef8e355f 100644 --- a/tooling/cli/Cargo.toml +++ b/tooling/cli/Cargo.toml @@ -3,7 +3,7 @@ members = [ "node" ] [package] name = "tauri-cli" -version = "2.0.0-alpha.17" +version = "2.0.0-alpha.18" authors = [ "Tauri Programme within The Commons Conservancy" ] edition = "2021" rust-version = "1.70" @@ -49,9 +49,8 @@ sublime_fuzzy = "0.7" clap_complete = "4" clap = { version = "4.4", features = [ "derive", "env" ] } anyhow = "1.0" -tauri-bundler = { version = "2.0.0-alpha.11", default-features = false, path = "../bundler" } +tauri-bundler = { version = "2.0.0-alpha.12", default-features = false, path = "../bundler" } colored = "2.0" -once_cell = "1" serde = { version = "1.0", features = [ "derive" ] } serde_json = "1.0" notify = "6.1" @@ -60,7 +59,7 @@ shared_child = "1.0" duct = "0.13" toml_edit = "0.20" json-patch = "1.2" -tauri-utils = { version = "2.0.0-alpha.10", path = "../../core/tauri-utils", features = [ "isolation", "schema", "config-json5", "config-toml" ] } +tauri-utils = { version = "2.0.0-alpha.11", path = "../../core/tauri-utils", features = [ "isolation", "schema", "config-json5", "config-toml" ] } tauri-utils-v1 = { version = "1", package = "tauri-utils", features = [ "isolation", "schema", "config-json5", "config-toml" ] } toml = "0.8" jsonschema = "0.17" @@ -102,6 +101,9 @@ cc = "1" [target."cfg(unix)".dependencies] libc = "0.2" +[target."cfg(target_os = \"macos\")".dependencies] +plist = "1" + [features] default = [ "rustls" ] native-tls = [ diff --git a/tooling/cli/metadata-v2.json b/tooling/cli/metadata-v2.json index 5f76eb3bf855..6facfd74815b 100644 --- a/tooling/cli/metadata-v2.json +++ b/tooling/cli/metadata-v2.json @@ -1,8 +1,8 @@ { "cli.js": { - "version": "2.0.0-alpha.17", + "version": "2.0.0-alpha.18", "node": ">= 10.0.0" }, - "tauri": "2.0.0-alpha.17", - "tauri-build": "2.0.0-alpha.11" + "tauri": "2.0.0-alpha.18", + "tauri-build": "2.0.0-alpha.12" } diff --git a/tooling/cli/node/CHANGELOG.md b/tooling/cli/node/CHANGELOG.md index c5db62f320bb..8b294a38e4de 100644 --- a/tooling/cli/node/CHANGELOG.md +++ b/tooling/cli/node/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## \[2.0.0-alpha.18] + +### New Features + +- [`50f7ccbb`](https://www.github.com/tauri-apps/tauri/commit/50f7ccbbf3467f33cc7dd1cca53125fec6eda1c6)([#6444](https://www.github.com/tauri-apps/tauri/pull/6444)) Add suport to SVG input image for the `tauri icon` command. +- [`25e5f91d`](https://www.github.com/tauri-apps/tauri/commit/25e5f91dae7fe2bbc1ba4317d5d829402bfd1d50)([#8200](https://www.github.com/tauri-apps/tauri/pull/8200)) Merge `src-tauri/Info.plist` and `src-tauri/Info.ios.plist` with the iOS project plist file. + +### Enhancements + +- [`01a7a983`](https://www.github.com/tauri-apps/tauri/commit/01a7a983aba2946b455a608b8a6a4b08cb25fc11)([#8128](https://www.github.com/tauri-apps/tauri/pull/8128)) Transform paths to relative to the mobile project for the IDE script runner script. + +### Bug Fixes + +- [`88dac86f`](https://www.github.com/tauri-apps/tauri/commit/88dac86f3b301d1919df6473a9e20f46b560f29b)([#8149](https://www.github.com/tauri-apps/tauri/pull/8149)) Ensure `tauri add` prints `rust_code` with plugin name in snake case. +- [`977d0e52`](https://www.github.com/tauri-apps/tauri/commit/977d0e52f14b1ad01c86371765ef25b36572459e)([#8202](https://www.github.com/tauri-apps/tauri/pull/8202)) Fixes `android build --open` and `ios build --open` IDE failing to read CLI options. +- [`bfbbefdb`](https://www.github.com/tauri-apps/tauri/commit/bfbbefdb9e13ed1f42f6db7fa9ceaa84db1267e9)([#8161](https://www.github.com/tauri-apps/tauri/pull/8161)) Fix invalid plugin template. +- [`92b50a3a`](https://www.github.com/tauri-apps/tauri/commit/92b50a3a398c9d55b6992a8f5c2571e4d72bdaaf)([#8209](https://www.github.com/tauri-apps/tauri/pull/8209)) Added support to Xcode's archive. This requires regenerating the Xcode project. + +### Dependencies + +- Upgraded to `tauri-cli@2.0.0-alpha.18` + ## \[2.0.0-alpha.17] ### Enhancements diff --git a/tooling/cli/node/package.json b/tooling/cli/node/package.json index 603a44375223..ee8322865fb2 100644 --- a/tooling/cli/node/package.json +++ b/tooling/cli/node/package.json @@ -1,6 +1,6 @@ { "name": "@tauri-apps/cli", - "version": "2.0.0-alpha.17", + "version": "2.0.0-alpha.18", "description": "Command line interface for building Tauri apps", "funding": { "type": "opencollective", diff --git a/tooling/cli/schema.json b/tooling/cli/schema.json index b4a96b2847de..573d37924808 100644 --- a/tooling/cli/schema.json +++ b/tooling/cli/schema.json @@ -37,6 +37,20 @@ "deb": { "files": {} }, + "dmg": { + "appPosition": { + "x": 180, + "y": 170 + }, + "applicationFolderPosition": { + "x": 480, + "y": 170 + }, + "windowSize": { + "height": 400, + "width": 660 + } + }, "iOS": {}, "icon": [], "identifier": "", @@ -171,6 +185,20 @@ "deb": { "files": {} }, + "dmg": { + "appPosition": { + "x": 180, + "y": 170 + }, + "applicationFolderPosition": { + "x": 480, + "y": 170 + }, + "windowSize": { + "height": 400, + "width": 660 + } + }, "iOS": {}, "icon": [], "identifier": "", @@ -1003,6 +1031,28 @@ } ] }, + "dmg": { + "description": "DMG-specific settings.", + "default": { + "appPosition": { + "x": 180, + "y": 170 + }, + "applicationFolderPosition": { + "x": 480, + "y": 170 + }, + "windowSize": { + "height": 400, + "width": 660 + } + }, + "allOf": [ + { + "$ref": "#/definitions/DmgConfig" + } + ] + }, "macOS": { "description": "Configuration for the macOS bundles.", "default": { @@ -1318,6 +1368,113 @@ }, "additionalProperties": false }, + "DmgConfig": { + "description": "Configuration for Apple Disk Image (.dmg) bundles.\n\nSee more: https://tauri.app/v1/api/config#dmgconfig", + "type": "object", + "properties": { + "background": { + "description": "Image to use as the background in dmg file. Accepted formats: `png`/`jpg`/`gif`.", + "type": [ + "string", + "null" + ] + }, + "windowPosition": { + "description": "Position of volume window on screen.", + "anyOf": [ + { + "$ref": "#/definitions/Position" + }, + { + "type": "null" + } + ] + }, + "windowSize": { + "description": "Size of volume window.", + "default": { + "height": 400, + "width": 660 + }, + "allOf": [ + { + "$ref": "#/definitions/Size" + } + ] + }, + "appPosition": { + "description": "Position of app file on window.", + "default": { + "x": 180, + "y": 170 + }, + "allOf": [ + { + "$ref": "#/definitions/Position" + } + ] + }, + "applicationFolderPosition": { + "description": "Position of application folder on window.", + "default": { + "x": 480, + "y": 170 + }, + "allOf": [ + { + "$ref": "#/definitions/Position" + } + ] + } + }, + "additionalProperties": false + }, + "Position": { + "description": "Position coordinates struct.", + "type": "object", + "required": [ + "x", + "y" + ], + "properties": { + "x": { + "description": "X coordinate.", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "y": { + "description": "Y coordinate.", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "Size": { + "description": "Size of the window.", + "type": "object", + "required": [ + "height", + "width" + ], + "properties": { + "width": { + "description": "Width of the window.", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "height": { + "description": "Height of the window.", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, "MacConfig": { "description": "Configuration for the macOS bundles.\n\nSee more: ", "type": "object", diff --git a/tooling/cli/src/dev.rs b/tooling/cli/src/dev.rs index 4a25a1cc5282..ecf95713f893 100644 --- a/tooling/cli/src/dev.rs +++ b/tooling/cli/src/dev.rs @@ -16,7 +16,6 @@ use crate::{ use anyhow::{bail, Context}; use clap::{ArgAction, Parser}; use log::{error, info, warn}; -use once_cell::sync::OnceCell; use shared_child::SharedChild; use tauri_utils::platform::Target; @@ -26,12 +25,12 @@ use std::{ process::{exit, Command, Stdio}, sync::{ atomic::{AtomicBool, Ordering}, - Arc, Mutex, + Arc, Mutex, OnceLock, }, }; -static BEFORE_DEV: OnceCell>> = OnceCell::new(); -static KILL_BEFORE_DEV_FLAG: OnceCell = OnceCell::new(); +static BEFORE_DEV: OnceLock>> = OnceLock::new(); +static KILL_BEFORE_DEV_FLAG: OnceLock = OnceLock::new(); #[cfg(unix)] const KILL_CHILDREN_SCRIPT: &[u8] = include_bytes!("../scripts/kill-children.sh"); @@ -107,7 +106,7 @@ fn command_internal(mut options: Options) -> Result<()> { } pub fn local_ip_address(force: bool) -> &'static IpAddr { - static LOCAL_IP: OnceCell = OnceCell::new(); + static LOCAL_IP: OnceLock = OnceLock::new(); LOCAL_IP.get_or_init(|| { let prompt_for_ip = || { let addresses: Vec = local_ip_address::list_afinet_netifas() diff --git a/tooling/cli/src/helpers/app_paths.rs b/tooling/cli/src/helpers/app_paths.rs index c183eee28c7f..1e1465f3ee96 100644 --- a/tooling/cli/src/helpers/app_paths.rs +++ b/tooling/cli/src/helpers/app_paths.rs @@ -7,10 +7,10 @@ use std::{ env::current_dir, ffi::OsStr, path::{Path, PathBuf}, + sync::OnceLock, }; use ignore::WalkBuilder; -use once_cell::sync::Lazy; use tauri_utils::{ config::parse::{folder_has_configuration_file, is_configuration_file, ConfigFormat}, @@ -114,9 +114,10 @@ fn get_app_dir() -> Option { } pub fn app_dir() -> &'static PathBuf { - static APP_DIR: Lazy = - Lazy::new(|| get_app_dir().unwrap_or_else(|| get_tauri_dir().parent().unwrap().to_path_buf())); - &APP_DIR + static APP_DIR: OnceLock = OnceLock::new(); + APP_DIR.get_or_init(|| { + get_app_dir().unwrap_or_else(|| get_tauri_dir().parent().unwrap().to_path_buf()) + }) } pub fn tauri_dir() -> PathBuf { diff --git a/tooling/cli/src/helpers/config.rs b/tooling/cli/src/helpers/config.rs index 9fe845aca6c7..9dfd70e2998e 100644 --- a/tooling/cli/src/helpers/config.rs +++ b/tooling/cli/src/helpers/config.rs @@ -5,7 +5,6 @@ use anyhow::Context; use json_patch::merge; use log::error; -use once_cell::sync::Lazy; use serde_json::Value as JsonValue; pub use tauri_utils::{config::*, platform::Target}; @@ -15,7 +14,7 @@ use std::{ env::{current_dir, set_current_dir, set_var, var_os}, ffi::OsStr, process::exit, - sync::{Arc, Mutex}, + sync::{Arc, Mutex, OnceLock}, }; pub const MERGE_CONFIG_EXTENSION_NAME: &str = "--config"; @@ -115,8 +114,8 @@ pub fn nsis_settings(config: NsisConfig) -> tauri_bundler::NsisSettings { } fn config_handle() -> &'static ConfigHandle { - static CONFING_HANDLE: Lazy = Lazy::new(Default::default); - &CONFING_HANDLE + static CONFIG_HANDLE: OnceLock = OnceLock::new(); + CONFIG_HANDLE.get_or_init(Default::default) } /// Gets the static parsed config from `tauri.conf.json`. diff --git a/tooling/cli/src/interface/rust.rs b/tooling/cli/src/interface/rust.rs index ef386aef1ad0..1d2829c3de3e 100644 --- a/tooling/cli/src/interface/rust.rs +++ b/tooling/cli/src/interface/rust.rs @@ -22,8 +22,8 @@ use notify::RecursiveMode; use notify_debouncer_mini::new_debouncer; use serde::Deserialize; use tauri_bundler::{ - AppCategory, BundleBinary, BundleSettings, DebianSettings, MacOsSettings, PackageSettings, - UpdaterSettings, WindowsSettings, + AppCategory, BundleBinary, BundleSettings, DebianSettings, DmgSettings, MacOsSettings, + PackageSettings, Position, Size, UpdaterSettings, WindowsSettings, }; use tauri_utils::config::parse::is_configuration_file; @@ -228,8 +228,16 @@ impl Interface for Rust { self.app_settings.target_triple.clone(), ); - let mut s = self.app_settings.target_triple.split('-'); - let (arch, _, host) = (s.next().unwrap(), s.next().unwrap(), s.next().unwrap()); + let target_triple = &self.app_settings.target_triple; + let target_components: Vec<&str> = target_triple.split('-').collect(); + let (arch, host) = match target_components.as_slice() { + [arch, _, host] => (*arch, *host), + _ => { + log::warn!("Invalid target triple: {}", target_triple); + return env; + } + }; + env.insert( "TAURI_ENV_ARCH", match arch { @@ -1177,6 +1185,25 @@ fn tauri_config_to_bundle_settings( files: config.deb.files, desktop_template: config.deb.desktop_template, }, + dmg: DmgSettings { + background: config.dmg.background, + window_position: config.dmg.window_position.map(|window_position| Position { + x: window_position.x, + y: window_position.y, + }), + window_size: Size { + width: config.dmg.window_size.width, + height: config.dmg.window_size.height, + }, + app_position: Position { + x: config.dmg.app_position.x, + y: config.dmg.app_position.y, + }, + application_folder_position: Position { + x: config.dmg.application_folder_position.x, + y: config.dmg.application_folder_position.y, + }, + }, macos: MacOsSettings { frameworks: config.macos.frameworks, minimum_system_version: config.macos.minimum_system_version, diff --git a/tooling/cli/src/migrate/frontend.rs b/tooling/cli/src/migrate/frontend.rs index 9c842dc666fa..4d21ecbc6716 100644 --- a/tooling/cli/src/migrate/frontend.rs +++ b/tooling/cli/src/migrate/frontend.rs @@ -13,7 +13,7 @@ use std::{ process::Command, }; -const CORE_API_MODULES: &[&str] = &["dpi", "event", "path", "primitives", "window", "mocks"]; +const CORE_API_MODULES: &[&str] = &["dpi", "event", "path", "core", "window", "mocks"]; const JS_EXTENSIONS: &[&str] = &["js", "jsx", "ts", "tsx", "mjs"]; pub fn migrate(app_dir: &Path, tauri_dir: &Path) -> Result<()> { @@ -40,7 +40,7 @@ pub fn migrate(app_dir: &Path, tauri_dir: &Path) -> Result<()> { let original = cap.get(0).unwrap().as_str(); if module == "tauri" { - let new = "@tauri-apps/api/primitives".to_string(); + let new = "@tauri-apps/api/core".to_string(); log::info!("Replacing `{original}` with `{new}` on {}", path.display()); new } else if CORE_API_MODULES.contains(&module) { diff --git a/tooling/cli/src/mobile/android/build.rs b/tooling/cli/src/mobile/android/build.rs index 2cfa76c2a20a..d64196d153e2 100644 --- a/tooling/cli/src/mobile/android/build.rs +++ b/tooling/cli/src/mobile/android/build.rs @@ -4,7 +4,7 @@ use super::{ configure_cargo, delete_codegen_vars, ensure_init, env, get_app, get_config, inject_assets, - log_finished, open_and_wait, MobileTarget, + log_finished, open_and_wait, MobileTarget, OptionsHandle, }; use crate::{ build::Options as BuildOptions, @@ -131,7 +131,7 @@ pub fn command(mut options: Options, noise_level: NoiseLevel) -> Result<()> { )?; let open = options.open; - run_build( + let _handle = run_build( options, tauri_config, profile, @@ -154,7 +154,7 @@ fn run_build( config: &AndroidConfig, env: &mut Env, noise_level: NoiseLevel, -) -> Result<()> { +) -> Result { if !(options.apk || options.aab) { // if the user didn't specify the format to build, we'll do both options.apk = true; @@ -192,7 +192,7 @@ fn run_build( noise_level, vars: Default::default(), }; - let _handle = write_options( + let handle = write_options( &tauri_config .lock() .unwrap() @@ -240,7 +240,7 @@ fn run_build( log_finished(apk_outputs, "APK"); log_finished(aab_outputs, "AAB"); - Ok(()) + Ok(handle) } fn get_targets_or_all<'a>(targets: Vec) -> Result>> { diff --git a/tooling/cli/src/mobile/android/mod.rs b/tooling/cli/src/mobile/android/mod.rs index 1a622c7b40c6..d9ffeec5ba61 100644 --- a/tooling/cli/src/mobile/android/mod.rs +++ b/tooling/cli/src/mobile/android/mod.rs @@ -29,7 +29,7 @@ use sublime_fuzzy::best_match; use super::{ ensure_init, get_app, init::{command as init_command, configure_cargo}, - log_finished, read_options, setup_dev_config, CliOptions, Target as MobileTarget, + log_finished, read_options, setup_dev_config, CliOptions, OptionsHandle, Target as MobileTarget, MIN_DEVICE_MATCH_SCORE, }; use crate::{helpers::config::Config as TauriConfig, Result}; diff --git a/tooling/cli/src/mobile/ios/build.rs b/tooling/cli/src/mobile/ios/build.rs index 76c3d03be181..094489066752 100644 --- a/tooling/cli/src/mobile/ios/build.rs +++ b/tooling/cli/src/mobile/ios/build.rs @@ -4,7 +4,7 @@ use super::{ configure_cargo, detect_target_ok, ensure_init, env, get_app, get_config, inject_assets, - log_finished, open_and_wait, MobileTarget, + log_finished, merge_plist, open_and_wait, MobileTarget, OptionsHandle, }; use crate::{ build::Options as BuildOptions, @@ -94,16 +94,28 @@ pub fn command(mut options: Options, noise_level: NoiseLevel) -> Result<()> { }; let tauri_path = tauri_dir(); - set_current_dir(tauri_path).with_context(|| "failed to change current working directory")?; + set_current_dir(&tauri_path).with_context(|| "failed to change current working directory")?; ensure_init(config.project_dir(), MobileTarget::Ios)?; inject_assets(&config)?; + let info_plist_path = config + .project_dir() + .join(config.scheme()) + .join("Info.plist"); + merge_plist( + &[ + tauri_path.join("Info.plist"), + tauri_path.join("Info.ios.plist"), + ], + &info_plist_path, + )?; + let mut env = env()?; configure_cargo(&app, None)?; let open = options.open; - run_build(options, tauri_config, &config, &mut env, noise_level)?; + let _handle = run_build(options, tauri_config, &config, &mut env, noise_level)?; if open { open_and_wait(&config, &env); @@ -118,7 +130,7 @@ fn run_build( config: &AppleConfig, env: &mut Env, noise_level: NoiseLevel, -) -> Result<()> { +) -> Result { let profile = if options.debug { Profile::Debug } else { @@ -151,7 +163,7 @@ fn run_build( noise_level, vars: Default::default(), }; - let _handle = write_options( + let handle = write_options( &tauri_config .lock() .unwrap() @@ -199,5 +211,5 @@ fn run_build( log_finished(out_files, "IPA"); - Ok(()) + Ok(handle) } diff --git a/tooling/cli/src/mobile/ios/dev.rs b/tooling/cli/src/mobile/ios/dev.rs index 230bb339a5bc..7664a0e203ff 100644 --- a/tooling/cli/src/mobile/ios/dev.rs +++ b/tooling/cli/src/mobile/ios/dev.rs @@ -4,7 +4,7 @@ use super::{ configure_cargo, device_prompt, ensure_init, env, get_app, get_config, inject_assets, - open_and_wait, setup_dev_config, MobileTarget, APPLE_DEVELOPMENT_TEAM_ENV_VAR_NAME, + merge_plist, open_and_wait, setup_dev_config, MobileTarget, APPLE_DEVELOPMENT_TEAM_ENV_VAR_NAME, }; use crate::{ dev::Options as DevOptions, @@ -145,10 +145,23 @@ fn run_command(mut options: Options, noise_level: NoiseLevel) -> Result<()> { }; let tauri_path = tauri_dir(); - set_current_dir(tauri_path).with_context(|| "failed to change current working directory")?; + set_current_dir(&tauri_path).with_context(|| "failed to change current working directory")?; ensure_init(config.project_dir(), MobileTarget::Ios)?; inject_assets(&config)?; + + let info_plist_path = config + .project_dir() + .join(config.scheme()) + .join("Info.plist"); + merge_plist( + &[ + tauri_path.join("Info.plist"), + tauri_path.join("Info.ios.plist"), + ], + &info_plist_path, + )?; + run_dev(options, tauri_config, &app, &config, noise_level) } diff --git a/tooling/cli/src/mobile/ios/mod.rs b/tooling/cli/src/mobile/ios/mod.rs index 05039a53d2f8..8b235e433920 100644 --- a/tooling/cli/src/mobile/ios/mod.rs +++ b/tooling/cli/src/mobile/ios/mod.rs @@ -24,12 +24,19 @@ use sublime_fuzzy::best_match; use super::{ ensure_init, env, get_app, init::{command as init_command, configure_cargo}, - log_finished, read_options, setup_dev_config, CliOptions, Target as MobileTarget, + log_finished, read_options, setup_dev_config, CliOptions, OptionsHandle, Target as MobileTarget, MIN_DEVICE_MATCH_SCORE, }; use crate::{helpers::config::Config as TauriConfig, Result}; -use std::{env::set_var, fs::create_dir_all, process::exit, thread::sleep, time::Duration}; +use std::{ + env::set_var, + fs::create_dir_all, + path::{Path, PathBuf}, + process::exit, + thread::sleep, + time::Duration, +}; mod build; mod dev; @@ -261,3 +268,30 @@ fn inject_assets(config: &AppleConfig) -> Result<()> { create_dir_all(asset_dir)?; Ok(()) } + +fn merge_plist(src: &[PathBuf], dest: &Path) -> Result<()> { + let mut dest_plist = None; + + for src_path in src { + if let Ok(src_plist) = plist::Value::from_file(src_path) { + if dest_plist.is_none() { + dest_plist.replace(plist::Value::from_file(dest)?); + } + + let plist = dest_plist.as_mut().expect("Info.plist not loaded"); + if let Some(plist) = plist.as_dictionary_mut() { + if let Some(dict) = src_plist.into_dictionary() { + for (key, value) in dict { + plist.insert(key, value); + } + } + } + } + } + + if let Some(dest_plist) = dest_plist { + dest_plist.to_file_xml(dest)?; + } + + Ok(()) +} diff --git a/tooling/cli/src/mobile/ios/xcode_script.rs b/tooling/cli/src/mobile/ios/xcode_script.rs index d24e98f3d10a..0b586aaee242 100644 --- a/tooling/cli/src/mobile/ios/xcode_script.rs +++ b/tooling/cli/src/mobile/ios/xcode_script.rs @@ -134,22 +134,17 @@ pub fn command(options: Options) -> Result<()> { let isysroot = format!("-isysroot {}", options.sdk_root.display()); - // when using Xcode, the arches will be ['Simulator', 'arm64'] instead of ['arm64-sim'] - let arches = if options.arches.contains(&"Simulator".into()) { - vec![if cfg!(target_arch = "aarch64") { - "arm64-sim".to_string() - } else { - "x86_64".to_string() - }] - } else { - options.arches - }; - for arch in arches { + for arch in options.arches { // Set target-specific flags let (env_triple, rust_triple) = match arch.as_str() { "arm64" => ("aarch64_apple_ios", "aarch64-apple-ios"), "arm64-sim" => ("aarch64_apple_ios_sim", "aarch64-apple-ios-sim"), "x86_64" => ("x86_64_apple_ios", "x86_64-apple-ios"), + "Simulator" => { + // when using Xcode, the arches for a simulator build will be ['Simulator', 'arm64-sim'] instead of ['arm64-sim'] + // so we ignore that on our end + continue; + } _ => { return Err(anyhow::anyhow!( "Arch specified by Xcode was invalid. {} isn't a known arch", @@ -206,14 +201,11 @@ pub fn command(options: Options) -> Result<()> { } let project_dir = config.project_dir(); - std::fs::create_dir_all(project_dir.join(format!("Externals/{}", profile.as_str())))?; + let externals_lib_dir = project_dir.join(format!("Externals/{arch}/{}", profile.as_str())); + std::fs::create_dir_all(&externals_lib_dir)?; std::fs::copy( lib_path, - project_dir.join(format!( - "Externals/{}/lib{}.a", - profile.as_str(), - config.app().lib_name() - )), + externals_lib_dir.join(format!("lib{}.a", config.app().lib_name())), )?; } Ok(()) diff --git a/tooling/cli/src/mobile/mod.rs b/tooling/cli/src/mobile/mod.rs index 2534e6ecded3..eeac3f0f1919 100644 --- a/tooling/cli/src/mobile/mod.rs +++ b/tooling/cli/src/mobile/mod.rs @@ -217,11 +217,10 @@ fn env() -> Result { Ok(env) } +pub struct OptionsHandle(Runtime, ServerHandle); + /// Writes CLI options to be used later on the Xcode and Android Studio build commands -pub fn write_options( - identifier: &str, - mut options: CliOptions, -) -> crate::Result<(Runtime, ServerHandle)> { +pub fn write_options(identifier: &str, mut options: CliOptions) -> crate::Result { options.vars.extend(env_vars()); let runtime = Runtime::new().unwrap(); @@ -243,7 +242,7 @@ pub fn write_options( addr.to_string(), )?; - Ok((runtime, handle)) + Ok(OptionsHandle(runtime, handle)) } fn read_options(identifier: &str) -> CliOptions { diff --git a/tooling/cli/src/signer/sign.rs b/tooling/cli/src/signer/sign.rs index 66422b8aa89d..28484c76fd07 100644 --- a/tooling/cli/src/signer/sign.rs +++ b/tooling/cli/src/signer/sign.rs @@ -17,13 +17,23 @@ use tauri_utils::display_path; #[clap(about = "Sign a file")] pub struct Options { /// Load the private key from a string - #[clap(short = 'k', long, conflicts_with("private_key_path"))] + #[clap( + short = 'k', + long, + conflicts_with("private_key_path"), + env = "TAURI_PRIVATE_KEY" + )] private_key: Option, /// Load the private key from a file - #[clap(short = 'f', long, conflicts_with("private_key"))] + #[clap( + short = 'f', + long, + conflicts_with("private_key"), + env = "TAURI_PRIVATE_KEY_PATH" + )] private_key_path: Option, /// Set private key password when signing - #[clap(short, long)] + #[clap(short, long, env = "TAURI_PRIVATE_KEY_PASSWORD")] password: Option, /// Sign the specified file file: PathBuf, diff --git a/tooling/cli/templates/mobile/ios/project.yml b/tooling/cli/templates/mobile/ios/project.yml index 6320d44d95b9..302658f50b98 100644 --- a/tooling/cli/templates/mobile/ios/project.yml +++ b/tooling/cli/templates/mobile/ios/project.yml @@ -75,10 +75,12 @@ targets: ENABLE_BITCODE: false ARCHS: [{{join ios-valid-archs}}] VALID_ARCHS: {{~#each ios-valid-archs}} {{this}} {{/each}} - LIBRARY_SEARCH_PATHS[arch=x86_64]: $(inherited) $(PROJECT_DIR)/Externals/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME) - LIBRARY_SEARCH_PATHS[arch=arm64]: $(inherited) $(PROJECT_DIR)/Externals/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME) - LIBRARY_SEARCH_PATHS[arch=arm64-sim]: $(inherited) $(PROJECT_DIR)/Externals/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME) + LIBRARY_SEARCH_PATHS[arch=x86_64]: $(inherited) $(PROJECT_DIR)/Externals/x86_64/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME) + LIBRARY_SEARCH_PATHS[arch=arm64]: $(inherited) $(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME) + LIBRARY_SEARCH_PATHS[arch=arm64-sim]: $(inherited) $(PROJECT_DIR)/Externals/arm64-sim/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME) ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES: true + EXCLUDED_ARCHS[sdk=iphonesimulator*]: arm64 + EXCLUDED_ARCHS[sdk=iphoneos*]: arm64-sim x86_64 groups: [app] dependencies: - framework: lib{{app.lib-name}}.a diff --git a/tooling/cli/templates/plugin/__example-api/tauri-app/src/lib/Greet.svelte b/tooling/cli/templates/plugin/__example-api/tauri-app/src/lib/Greet.svelte index 54f8185d9216..4f9be745f1f6 100644 --- a/tooling/cli/templates/plugin/__example-api/tauri-app/src/lib/Greet.svelte +++ b/tooling/cli/templates/plugin/__example-api/tauri-app/src/lib/Greet.svelte @@ -1,5 +1,5 @@