Repository: tauri-apps/tauri Branch: dev Commit: 1ef6a119b157 Files: 956 Total size: 6.1 MB Directory structure: gitextract_bd3gcnsk/ ├── .cargo/ │ ├── audit.toml │ └── config.toml ├── .changes/ │ ├── README.md │ ├── base64.md │ ├── config.json │ ├── data-tauri-drag-region-deep.md │ ├── fix-build-bundles-arg.md │ ├── linux-deploy-link.md │ ├── prompt-signing-key-password-context.md │ └── toml-ver.md ├── .devcontainer/ │ ├── Dockerfile │ ├── README.md │ └── devcontainer.json ├── .docker/ │ └── cross/ │ ├── aarch64.Dockerfile │ ├── cmake.sh │ ├── common.sh │ ├── deny-debian-packages.sh │ ├── dropbear.sh │ ├── lib.sh │ ├── linux-image.sh │ ├── linux-runner │ ├── qemu.sh │ └── xargo.sh ├── .editorconfig ├── .github/ │ ├── CODEOWNERS │ ├── CODE_OF_CONDUCT.md │ ├── CONTRIBUTING.md │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.yml │ │ ├── config.yml │ │ ├── docs_report.md │ │ └── feature_request.yml │ ├── PULL_REQUEST_TEMPLATE.md │ ├── RELEASING.md │ └── workflows/ │ ├── audit.yml │ ├── bench.yml │ ├── check-change-tags.yml │ ├── check-generated-files.yml │ ├── check-license-header.yml │ ├── covector-comment-on-fork.yml │ ├── covector-status.yml │ ├── covector-version-or-publish.yml │ ├── deploy-schema-worker.yml │ ├── docker.yml │ ├── fmt.yml │ ├── lint-js.yml │ ├── lint-rust.yml │ ├── publish-cli-js.yml │ ├── publish-cli-rs.yml │ ├── supply-chain.yml │ ├── test-android.yml │ ├── test-cli-js.yml │ ├── test-cli-rs.yml │ ├── test-core.yml │ └── udeps.yml ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .scripts/ │ └── ci/ │ ├── check-change-tags.js │ ├── check-license-header.js │ ├── has-diff.sh │ ├── pack-cli.sh │ └── sync-cli-metadata.js ├── .vscode/ │ └── extensions.json ├── ARCHITECTURE.md ├── Cargo.toml ├── LICENSE.spdx ├── LICENSE_APACHE-2.0 ├── LICENSE_MIT ├── README.md ├── SECURITY.md ├── bench/ │ ├── Cargo.toml │ ├── README.md │ ├── src/ │ │ ├── build_benchmark_jsons.rs │ │ ├── run_benchmark.rs │ │ └── utils.rs │ └── tests/ │ ├── cpu_intensive/ │ │ ├── public/ │ │ │ ├── index.css │ │ │ ├── index.html │ │ │ ├── site.js │ │ │ └── worker.js │ │ └── src-tauri/ │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── build.rs │ │ ├── src/ │ │ │ └── main.rs │ │ └── tauri.conf.json │ ├── files_transfer/ │ │ ├── public/ │ │ │ └── index.html │ │ └── src-tauri/ │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── build.rs │ │ ├── src/ │ │ │ └── main.rs │ │ └── tauri.conf.json │ └── helloworld/ │ ├── public/ │ │ └── index.html │ └── src-tauri/ │ ├── .gitignore │ ├── Cargo.toml │ ├── build.rs │ ├── src/ │ │ └── main.rs │ └── tauri.conf.json ├── crates/ │ ├── tauri/ │ │ ├── .scripts/ │ │ │ └── loop_qc.sh │ │ ├── CHANGELOG.md │ │ ├── Cargo.toml │ │ ├── LICENSE_APACHE-2.0 │ │ ├── LICENSE_MIT │ │ ├── README.md │ │ ├── build.rs │ │ ├── mobile/ │ │ │ ├── android/ │ │ │ │ ├── .gitignore │ │ │ │ ├── build.gradle.kts │ │ │ │ ├── proguard-rules.pro │ │ │ │ └── src/ │ │ │ │ ├── androidTest/ │ │ │ │ │ └── java/ │ │ │ │ │ └── app/ │ │ │ │ │ └── tauri/ │ │ │ │ │ └── ExampleInstrumentedTest.kt │ │ │ │ ├── main/ │ │ │ │ │ ├── AndroidManifest.xml │ │ │ │ │ └── java/ │ │ │ │ │ └── app/ │ │ │ │ │ └── tauri/ │ │ │ │ │ ├── AppPlugin.kt │ │ │ │ │ ├── FsUtils.kt │ │ │ │ │ ├── JniMethod.kt │ │ │ │ │ ├── Logger.kt │ │ │ │ │ ├── PathPlugin.kt │ │ │ │ │ ├── PermissionHelper.kt │ │ │ │ │ ├── PermissionState.kt │ │ │ │ │ ├── annotation/ │ │ │ │ │ │ ├── ActivityCallback.kt │ │ │ │ │ │ ├── InvokeArg.kt │ │ │ │ │ │ ├── Permission.kt │ │ │ │ │ │ ├── PermissionCallback.kt │ │ │ │ │ │ ├── PluginMethod.kt │ │ │ │ │ │ └── TauriPlugin.kt │ │ │ │ │ └── plugin/ │ │ │ │ │ ├── Channel.kt │ │ │ │ │ ├── InvalidPluginMethodException.kt │ │ │ │ │ ├── Invoke.kt │ │ │ │ │ ├── JSArray.kt │ │ │ │ │ ├── JSObject.kt │ │ │ │ │ ├── Plugin.kt │ │ │ │ │ ├── PluginHandle.kt │ │ │ │ │ ├── PluginManager.kt │ │ │ │ │ ├── PluginMethodData.kt │ │ │ │ │ └── PluginResult.kt │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── app/ │ │ │ │ └── tauri/ │ │ │ │ └── ExampleUnitTest.kt │ │ │ ├── android-codegen/ │ │ │ │ └── TauriActivity.kt │ │ │ ├── ios-api/ │ │ │ │ ├── .gitignore │ │ │ │ ├── Package.swift │ │ │ │ ├── README.md │ │ │ │ ├── Sources/ │ │ │ │ │ └── Tauri/ │ │ │ │ │ ├── Channel.swift │ │ │ │ │ ├── Invoke.swift │ │ │ │ │ ├── JSTypes.swift │ │ │ │ │ ├── JsonValue.swift │ │ │ │ │ ├── Logger.swift │ │ │ │ │ ├── Plugin/ │ │ │ │ │ │ └── Plugin.swift │ │ │ │ │ ├── Tauri.swift │ │ │ │ │ └── UiUtils.swift │ │ │ │ └── Tests/ │ │ │ │ └── TauriTests/ │ │ │ │ └── TauriTests.swift │ │ │ └── proguard-tauri.pro │ │ ├── permissions/ │ │ │ ├── app/ │ │ │ │ └── autogenerated/ │ │ │ │ └── reference.md │ │ │ ├── event/ │ │ │ │ └── autogenerated/ │ │ │ │ └── reference.md │ │ │ ├── image/ │ │ │ │ └── autogenerated/ │ │ │ │ └── reference.md │ │ │ ├── menu/ │ │ │ │ └── autogenerated/ │ │ │ │ └── reference.md │ │ │ ├── path/ │ │ │ │ └── autogenerated/ │ │ │ │ └── reference.md │ │ │ ├── resources/ │ │ │ │ └── autogenerated/ │ │ │ │ └── reference.md │ │ │ ├── tray/ │ │ │ │ └── autogenerated/ │ │ │ │ └── reference.md │ │ │ ├── webview/ │ │ │ │ └── autogenerated/ │ │ │ │ └── reference.md │ │ │ └── window/ │ │ │ └── autogenerated/ │ │ │ └── reference.md │ │ ├── scripts/ │ │ │ ├── bundle.global.js │ │ │ ├── core.js │ │ │ ├── freeze_prototype.js │ │ │ ├── init.js │ │ │ ├── ipc-protocol.js │ │ │ ├── ipc.js │ │ │ ├── isolation.js │ │ │ ├── pattern.js │ │ │ └── process-ipc-message-fn.js │ │ ├── src/ │ │ │ ├── app/ │ │ │ │ └── plugin.rs │ │ │ ├── app.rs │ │ │ ├── async_runtime.rs │ │ │ ├── error.rs │ │ │ ├── event/ │ │ │ │ ├── event-system-spec.md │ │ │ │ ├── event_name.rs │ │ │ │ ├── init.js │ │ │ │ ├── listener.rs │ │ │ │ ├── mod.rs │ │ │ │ └── plugin.rs │ │ │ ├── image/ │ │ │ │ ├── mod.rs │ │ │ │ └── plugin.rs │ │ │ ├── ios.rs │ │ │ ├── ipc/ │ │ │ │ ├── authority.rs │ │ │ │ ├── capability_builder.rs │ │ │ │ ├── channel.rs │ │ │ │ ├── command.rs │ │ │ │ ├── format_callback.rs │ │ │ │ ├── mod.rs │ │ │ │ └── protocol.rs │ │ │ ├── lib.rs │ │ │ ├── manager/ │ │ │ │ ├── menu.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── tray.rs │ │ │ │ ├── webview.rs │ │ │ │ └── window.rs │ │ │ ├── menu/ │ │ │ │ ├── builders/ │ │ │ │ │ ├── check.rs │ │ │ │ │ ├── icon.rs │ │ │ │ │ ├── menu.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ └── normal.rs │ │ │ │ ├── check.rs │ │ │ │ ├── icon.rs │ │ │ │ ├── menu.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── normal.rs │ │ │ │ ├── plugin.rs │ │ │ │ ├── predefined.rs │ │ │ │ └── submenu.rs │ │ │ ├── path/ │ │ │ │ ├── android.rs │ │ │ │ ├── desktop.rs │ │ │ │ ├── init.js │ │ │ │ ├── mod.rs │ │ │ │ └── plugin.rs │ │ │ ├── pattern.rs │ │ │ ├── plugin/ │ │ │ │ └── mobile.rs │ │ │ ├── plugin.rs │ │ │ ├── process.rs │ │ │ ├── protocol/ │ │ │ │ ├── asset.rs │ │ │ │ ├── isolation.rs │ │ │ │ ├── mod.rs │ │ │ │ └── tauri.rs │ │ │ ├── resources/ │ │ │ │ ├── mod.rs │ │ │ │ └── plugin.rs │ │ │ ├── scope/ │ │ │ │ ├── fs.rs │ │ │ │ └── mod.rs │ │ │ ├── state.rs │ │ │ ├── test/ │ │ │ │ ├── mock_runtime.rs │ │ │ │ └── mod.rs │ │ │ ├── tray/ │ │ │ │ ├── mod.rs │ │ │ │ └── plugin.rs │ │ │ ├── vibrancy/ │ │ │ │ ├── macos.rs │ │ │ │ ├── mod.rs │ │ │ │ └── windows.rs │ │ │ ├── webview/ │ │ │ │ ├── mod.rs │ │ │ │ ├── plugin.rs │ │ │ │ ├── scripts/ │ │ │ │ │ ├── print.js │ │ │ │ │ ├── toggle-devtools.js │ │ │ │ │ └── zoom-hotkey.js │ │ │ │ └── webview_window.rs │ │ │ └── window/ │ │ │ ├── mod.rs │ │ │ ├── plugin.rs │ │ │ └── scripts/ │ │ │ └── drag.js │ │ └── test/ │ │ ├── api/ │ │ │ ├── test.txt │ │ │ └── test_binary │ │ ├── fixture/ │ │ │ ├── config.json │ │ │ ├── dist/ │ │ │ │ └── index.html │ │ │ ├── isolation/ │ │ │ │ ├── dist/ │ │ │ │ │ └── index.html │ │ │ │ ├── isolation-dist/ │ │ │ │ │ ├── index.html │ │ │ │ │ └── index.js │ │ │ │ └── src-tauri/ │ │ │ │ ├── icons/ │ │ │ │ │ └── icon.ico~dev │ │ │ │ └── tauri.conf.json │ │ │ ├── src-tauri/ │ │ │ │ ├── icons/ │ │ │ │ │ └── icon.ico~dev │ │ │ │ └── tauri.conf.json │ │ │ └── test.txt │ │ └── updater/ │ │ └── fixture/ │ │ ├── archives/ │ │ │ ├── archive.linux.tar.gz.sig │ │ │ ├── archive.macos.tar.gz.sig │ │ │ └── archive.windows.zip.sig │ │ ├── bad_signature/ │ │ │ ├── update.key │ │ │ └── update.key.pub │ │ └── good_signature/ │ │ ├── update.key │ │ └── update.key.pub │ ├── tauri-build/ │ │ ├── CHANGELOG.md │ │ ├── Cargo.toml │ │ ├── LICENSE_APACHE-2.0 │ │ ├── LICENSE_MIT │ │ ├── README.md │ │ └── src/ │ │ ├── acl.rs │ │ ├── codegen/ │ │ │ ├── context.rs │ │ │ └── mod.rs │ │ ├── lib.rs │ │ ├── manifest.rs │ │ ├── mobile.rs │ │ ├── static_vcruntime.rs │ │ └── windows-app-manifest.xml │ ├── tauri-bundler/ │ │ ├── CHANGELOG.md │ │ ├── Cargo.toml │ │ ├── License_Apache.md │ │ ├── License_MIT.md │ │ ├── README.md │ │ └── src/ │ │ ├── bundle/ │ │ │ ├── category.rs │ │ │ ├── kmp/ │ │ │ │ └── mod.rs │ │ │ ├── linux/ │ │ │ │ ├── appimage/ │ │ │ │ │ ├── linuxdeploy-plugin-gstreamer.sh │ │ │ │ │ ├── linuxdeploy-plugin-gtk.sh │ │ │ │ │ ├── linuxdeploy.rs │ │ │ │ │ └── mod.rs │ │ │ │ ├── debian.rs │ │ │ │ ├── freedesktop/ │ │ │ │ │ ├── main.desktop │ │ │ │ │ └── mod.rs │ │ │ │ ├── mod.rs │ │ │ │ └── rpm.rs │ │ │ ├── macos/ │ │ │ │ ├── app.rs │ │ │ │ ├── dmg/ │ │ │ │ │ ├── bundle_dmg │ │ │ │ │ ├── eula-resources-template.xml │ │ │ │ │ ├── mod.rs │ │ │ │ │ └── template.applescript │ │ │ │ ├── icon.rs │ │ │ │ ├── ios.rs │ │ │ │ ├── mod.rs │ │ │ │ └── sign.rs │ │ │ ├── platform.rs │ │ │ ├── settings.rs │ │ │ ├── updater_bundle.rs │ │ │ └── windows/ │ │ │ ├── mod.rs │ │ │ ├── msi/ │ │ │ │ ├── default-locale-strings.xml │ │ │ │ ├── install-task.ps1 │ │ │ │ ├── languages.json │ │ │ │ ├── main.wxs │ │ │ │ ├── mod.rs │ │ │ │ ├── uninstall-task.ps1 │ │ │ │ └── update-task.xml │ │ │ ├── nsis/ │ │ │ │ ├── FileAssociation.nsh │ │ │ │ ├── installer.nsi │ │ │ │ ├── languages/ │ │ │ │ │ ├── Arabic.nsh │ │ │ │ │ ├── Bulgarian.nsh │ │ │ │ │ ├── Dutch.nsh │ │ │ │ │ ├── English.nsh │ │ │ │ │ ├── French.nsh │ │ │ │ │ ├── German.nsh │ │ │ │ │ ├── Hebrew.nsh │ │ │ │ │ ├── Italian.nsh │ │ │ │ │ ├── Japanese.nsh │ │ │ │ │ ├── Korean.nsh │ │ │ │ │ ├── Norwegian.nsh │ │ │ │ │ ├── Persian.nsh │ │ │ │ │ ├── Portuguese.nsh │ │ │ │ │ ├── PortugueseBR.nsh │ │ │ │ │ ├── Russian.nsh │ │ │ │ │ ├── SimpChinese.nsh │ │ │ │ │ ├── Spanish.nsh │ │ │ │ │ ├── SpanishInternational.nsh │ │ │ │ │ ├── Swedish.nsh │ │ │ │ │ ├── TradChinese.nsh │ │ │ │ │ ├── Turkish.nsh │ │ │ │ │ └── Ukrainian.nsh │ │ │ │ ├── mod.rs │ │ │ │ └── utils.nsh │ │ │ ├── sign.rs │ │ │ └── util.rs │ │ ├── bundle.rs │ │ ├── error.rs │ │ ├── lib.rs │ │ └── utils/ │ │ ├── fs_utils.rs │ │ ├── http_utils.rs │ │ └── mod.rs │ ├── tauri-cli/ │ │ ├── CHANGELOG.md │ │ ├── Cargo.toml │ │ ├── ENVIRONMENT_VARIABLES.md │ │ ├── LICENSE_APACHE-2.0 │ │ ├── LICENSE_MIT │ │ ├── README.md │ │ ├── build.rs │ │ ├── config.schema.json │ │ ├── metadata-v2.json │ │ ├── metadata.json │ │ ├── schema.json │ │ ├── scripts/ │ │ │ └── kill-children.sh │ │ ├── src/ │ │ │ ├── acl/ │ │ │ │ ├── capability/ │ │ │ │ │ ├── mod.rs │ │ │ │ │ └── new.rs │ │ │ │ ├── mod.rs │ │ │ │ └── permission/ │ │ │ │ ├── add.rs │ │ │ │ ├── ls.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── new.rs │ │ │ │ └── rm.rs │ │ │ ├── add.rs │ │ │ ├── build.rs │ │ │ ├── bundle.rs │ │ │ ├── completions.rs │ │ │ ├── dev/ │ │ │ │ ├── auto-reload.js │ │ │ │ └── builtin_dev_server.rs │ │ │ ├── dev.rs │ │ │ ├── error.rs │ │ │ ├── helpers/ │ │ │ │ ├── app_paths.rs │ │ │ │ ├── cargo.rs │ │ │ │ ├── cargo_manifest.rs │ │ │ │ ├── config.rs │ │ │ │ ├── flock.rs │ │ │ │ ├── framework.rs │ │ │ │ ├── fs.rs │ │ │ │ ├── http.rs │ │ │ │ ├── icns.json │ │ │ │ ├── mod.rs │ │ │ │ ├── npm.rs │ │ │ │ ├── pbxproj.rs │ │ │ │ ├── plist.rs │ │ │ │ ├── plugins.rs │ │ │ │ ├── prompts.rs │ │ │ │ ├── template.rs │ │ │ │ └── updater_signature.rs │ │ │ ├── icon.rs │ │ │ ├── info/ │ │ │ │ ├── app.rs │ │ │ │ ├── env_nodejs.rs │ │ │ │ ├── env_rust.rs │ │ │ │ ├── env_system.rs │ │ │ │ ├── ios.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── packages_nodejs.rs │ │ │ │ ├── packages_rust.rs │ │ │ │ └── plugins.rs │ │ │ ├── init.rs │ │ │ ├── inspect.rs │ │ │ ├── interface/ │ │ │ │ ├── mod.rs │ │ │ │ ├── rust/ │ │ │ │ │ ├── cargo_config.rs │ │ │ │ │ ├── desktop.rs │ │ │ │ │ ├── installation.rs │ │ │ │ │ └── manifest.rs │ │ │ │ └── rust.rs │ │ │ ├── lib.rs │ │ │ ├── main.rs │ │ │ ├── migrate/ │ │ │ │ ├── migrations/ │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── v1/ │ │ │ │ │ │ ├── config.rs │ │ │ │ │ │ ├── fixtures/ │ │ │ │ │ │ │ ├── api-example.tauri.conf.json │ │ │ │ │ │ │ └── cli-template.tauri.conf.json │ │ │ │ │ │ ├── frontend/ │ │ │ │ │ │ │ └── partial_loader/ │ │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ │ ├── svelte.rs │ │ │ │ │ │ │ └── vue.rs │ │ │ │ │ │ ├── frontend.rs │ │ │ │ │ │ ├── manifest.rs │ │ │ │ │ │ └── mod.rs │ │ │ │ │ └── v2_beta.rs │ │ │ │ └── mod.rs │ │ │ ├── mobile/ │ │ │ │ ├── android/ │ │ │ │ │ ├── android_studio_script.rs │ │ │ │ │ ├── build.rs │ │ │ │ │ ├── dev.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── project.rs │ │ │ │ │ └── run.rs │ │ │ │ ├── init.rs │ │ │ │ ├── ios/ │ │ │ │ │ ├── build.rs │ │ │ │ │ ├── dev.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── project.rs │ │ │ │ │ ├── run.rs │ │ │ │ │ └── xcode_script.rs │ │ │ │ └── mod.rs │ │ │ ├── plugin/ │ │ │ │ ├── android.rs │ │ │ │ ├── init.rs │ │ │ │ ├── ios.rs │ │ │ │ ├── mod.rs │ │ │ │ └── new.rs │ │ │ ├── remove.rs │ │ │ └── signer/ │ │ │ ├── generate.rs │ │ │ ├── mod.rs │ │ │ └── sign.rs │ │ ├── tauri-dev-watcher.gitignore │ │ ├── tauri.config.schema.json │ │ ├── tauri.gitignore │ │ ├── templates/ │ │ │ ├── app/ │ │ │ │ └── src-tauri/ │ │ │ │ ├── .gitignore │ │ │ │ ├── Cargo.crate-manifest │ │ │ │ ├── build.rs │ │ │ │ ├── capabilities/ │ │ │ │ │ └── default.json │ │ │ │ ├── icons/ │ │ │ │ │ └── icon.icns │ │ │ │ ├── src/ │ │ │ │ │ ├── lib.rs │ │ │ │ │ └── main.rs │ │ │ │ └── tauri.conf.json │ │ │ ├── mobile/ │ │ │ │ ├── android/ │ │ │ │ │ ├── .editorconfig │ │ │ │ │ ├── .gitignore │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── .gitignore │ │ │ │ │ │ ├── build.gradle.kts │ │ │ │ │ │ ├── proguard-rules.pro │ │ │ │ │ │ └── src/ │ │ │ │ │ │ └── main/ │ │ │ │ │ │ ├── AndroidManifest.xml │ │ │ │ │ │ ├── MainActivity.kt │ │ │ │ │ │ └── res/ │ │ │ │ │ │ ├── drawable/ │ │ │ │ │ │ │ └── ic_launcher_background.xml │ │ │ │ │ │ ├── drawable-v24/ │ │ │ │ │ │ │ └── ic_launcher_foreground.xml │ │ │ │ │ │ ├── layout/ │ │ │ │ │ │ │ └── activity_main.xml │ │ │ │ │ │ ├── values/ │ │ │ │ │ │ │ ├── colors.xml │ │ │ │ │ │ │ ├── strings.xml │ │ │ │ │ │ │ └── themes.xml │ │ │ │ │ │ ├── values-night/ │ │ │ │ │ │ │ └── themes.xml │ │ │ │ │ │ └── xml/ │ │ │ │ │ │ └── file_paths.xml │ │ │ │ │ ├── build.gradle.kts │ │ │ │ │ ├── buildSrc/ │ │ │ │ │ │ ├── build.gradle.kts │ │ │ │ │ │ └── src/ │ │ │ │ │ │ └── main/ │ │ │ │ │ │ └── kotlin/ │ │ │ │ │ │ ├── BuildTask.kt │ │ │ │ │ │ └── RustPlugin.kt │ │ │ │ │ ├── gradle/ │ │ │ │ │ │ └── wrapper/ │ │ │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ │ │ └── gradle-wrapper.properties │ │ │ │ │ ├── gradle.properties │ │ │ │ │ ├── gradlew │ │ │ │ │ ├── gradlew.bat │ │ │ │ │ └── settings.gradle │ │ │ │ └── ios/ │ │ │ │ ├── .gitignore │ │ │ │ ├── Assets.xcassets/ │ │ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ │ │ └── Contents.json │ │ │ │ │ └── Contents.json │ │ │ │ ├── ExportOptions.plist │ │ │ │ ├── LaunchScreen.storyboard │ │ │ │ ├── Podfile │ │ │ │ ├── Sources/ │ │ │ │ │ └── {{app.name}}/ │ │ │ │ │ ├── bindings/ │ │ │ │ │ │ └── bindings.h │ │ │ │ │ └── main.mm │ │ │ │ ├── project.yml │ │ │ │ └── {{app.name}}.xcodeproj/ │ │ │ │ └── project.xcworkspace/ │ │ │ │ └── xcshareddata/ │ │ │ │ └── WorkspaceSettings.xcsettings │ │ │ ├── plugin/ │ │ │ │ ├── .github/ │ │ │ │ │ └── workflows/ │ │ │ │ │ ├── audit.yml │ │ │ │ │ ├── clippy.yml │ │ │ │ │ └── test.yml │ │ │ │ ├── .gitignore │ │ │ │ ├── Cargo.crate-manifest │ │ │ │ ├── README.md │ │ │ │ ├── __example-api/ │ │ │ │ │ └── tauri-app/ │ │ │ │ │ ├── .gitignore │ │ │ │ │ ├── .vscode/ │ │ │ │ │ │ └── extensions.json │ │ │ │ │ ├── README.md │ │ │ │ │ ├── index.html │ │ │ │ │ ├── jsconfig.json │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── App.svelte │ │ │ │ │ │ ├── lib/ │ │ │ │ │ │ │ └── Greet.svelte │ │ │ │ │ │ ├── main.js │ │ │ │ │ │ ├── style.css │ │ │ │ │ │ └── vite-env.d.ts │ │ │ │ │ ├── src-tauri/ │ │ │ │ │ │ ├── .gitignore │ │ │ │ │ │ ├── Cargo.crate-manifest │ │ │ │ │ │ ├── build.rs │ │ │ │ │ │ ├── capabilities/ │ │ │ │ │ │ │ └── default.json │ │ │ │ │ │ ├── icons/ │ │ │ │ │ │ │ └── icon.icns │ │ │ │ │ │ ├── src/ │ │ │ │ │ │ │ ├── lib.rs │ │ │ │ │ │ │ └── main.rs │ │ │ │ │ │ └── tauri.conf.json │ │ │ │ │ └── vite.config.js │ │ │ │ ├── __example-basic/ │ │ │ │ │ └── vanilla/ │ │ │ │ │ ├── .gitignore │ │ │ │ │ ├── package.json │ │ │ │ │ ├── public/ │ │ │ │ │ │ └── index.html │ │ │ │ │ └── src-tauri/ │ │ │ │ │ ├── .gitignore │ │ │ │ │ ├── Cargo.crate-manifest │ │ │ │ │ ├── build.rs │ │ │ │ │ ├── capabilities/ │ │ │ │ │ │ └── default.json │ │ │ │ │ ├── icons/ │ │ │ │ │ │ └── icon.icns │ │ │ │ │ ├── rustfmt.toml │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── lib.rs │ │ │ │ │ │ └── main.rs │ │ │ │ │ └── tauri.conf.json │ │ │ │ ├── android/ │ │ │ │ │ ├── .gitignore │ │ │ │ │ ├── build.gradle.kts │ │ │ │ │ ├── proguard-rules.pro │ │ │ │ │ ├── settings.gradle │ │ │ │ │ └── src/ │ │ │ │ │ ├── androidTest/ │ │ │ │ │ │ └── java/ │ │ │ │ │ │ └── ExampleInstrumentedTest.kt │ │ │ │ │ ├── main/ │ │ │ │ │ │ ├── AndroidManifest.xml │ │ │ │ │ │ └── java/ │ │ │ │ │ │ ├── Example.kt │ │ │ │ │ │ └── ExamplePlugin.kt │ │ │ │ │ └── test/ │ │ │ │ │ └── java/ │ │ │ │ │ └── ExampleUnitTest.kt │ │ │ │ ├── build.rs │ │ │ │ ├── guest-js/ │ │ │ │ │ └── index.ts │ │ │ │ ├── ios-spm/ │ │ │ │ │ ├── .gitignore │ │ │ │ │ ├── Package.swift │ │ │ │ │ ├── README.md │ │ │ │ │ ├── Sources/ │ │ │ │ │ │ └── ExamplePlugin.swift │ │ │ │ │ └── Tests/ │ │ │ │ │ └── PluginTests/ │ │ │ │ │ └── PluginTests.swift │ │ │ │ ├── ios-xcode/ │ │ │ │ │ ├── tauri-plugin-{{ plugin_name }}/ │ │ │ │ │ │ └── ExamplePlugin.swift │ │ │ │ │ └── tauri-plugin-{{ plugin_name }}.xcodeproj/ │ │ │ │ │ ├── project.pbxproj │ │ │ │ │ └── project.xcworkspace/ │ │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ │ └── xcshareddata/ │ │ │ │ │ └── IDEWorkspaceChecks.plist │ │ │ │ ├── package.json │ │ │ │ ├── rollup.config.js │ │ │ │ ├── src/ │ │ │ │ │ ├── commands.rs │ │ │ │ │ ├── desktop.rs │ │ │ │ │ ├── error.rs │ │ │ │ │ ├── lib.rs │ │ │ │ │ ├── mobile.rs │ │ │ │ │ └── models.rs │ │ │ │ └── tsconfig.json │ │ │ └── tauri.conf.json │ │ └── tests/ │ │ └── fixtures/ │ │ └── pbxproj/ │ │ ├── project.pbxproj │ │ └── snapshots/ │ │ ├── tauri_cli__helpers__pbxproj__tests__project-modified.pbxproj.snap │ │ └── tauri_cli__helpers__pbxproj__tests__project.pbxproj.snap │ ├── tauri-codegen/ │ │ ├── CHANGELOG.md │ │ ├── Cargo.toml │ │ ├── LICENSE_APACHE-2.0 │ │ ├── LICENSE_MIT │ │ ├── README.md │ │ └── src/ │ │ ├── context.rs │ │ ├── embedded_assets.rs │ │ ├── image.rs │ │ ├── lib.rs │ │ └── vendor/ │ │ ├── blake3_reference.rs │ │ └── mod.rs │ ├── tauri-driver/ │ │ ├── CHANGELOG.md │ │ ├── Cargo.toml │ │ ├── LICENSE.spdx │ │ ├── LICENSE_APACHE-2.0 │ │ ├── LICENSE_MIT │ │ ├── README.md │ │ └── src/ │ │ ├── cli.rs │ │ ├── main.rs │ │ ├── server.rs │ │ └── webdriver.rs │ ├── tauri-macos-sign/ │ │ ├── CHANGELOG.md │ │ ├── Cargo.toml │ │ ├── README.md │ │ └── src/ │ │ ├── certificate.rs │ │ ├── keychain/ │ │ │ └── identity.rs │ │ ├── keychain.rs │ │ ├── lib.rs │ │ └── provisioning_profile.rs │ ├── tauri-macros/ │ │ ├── CHANGELOG.md │ │ ├── Cargo.toml │ │ ├── LICENSE_APACHE-2.0 │ │ ├── LICENSE_MIT │ │ ├── README.md │ │ └── src/ │ │ ├── command/ │ │ │ ├── handler.rs │ │ │ ├── mod.rs │ │ │ └── wrapper.rs │ │ ├── context.rs │ │ ├── lib.rs │ │ ├── menu.rs │ │ ├── mobile.rs │ │ └── runtime.rs │ ├── tauri-plugin/ │ │ ├── CHANGELOG.md │ │ ├── Cargo.toml │ │ └── src/ │ │ ├── build/ │ │ │ ├── mobile.rs │ │ │ └── mod.rs │ │ ├── lib.rs │ │ └── runtime.rs │ ├── tauri-runtime/ │ │ ├── CHANGELOG.md │ │ ├── Cargo.toml │ │ ├── LICENSE_APACHE-2.0 │ │ ├── LICENSE_MIT │ │ ├── README.md │ │ ├── build.rs │ │ └── src/ │ │ ├── dpi.rs │ │ ├── lib.rs │ │ ├── monitor.rs │ │ ├── webview.rs │ │ └── window.rs │ ├── tauri-runtime-wry/ │ │ ├── CHANGELOG.md │ │ ├── Cargo.toml │ │ ├── LICENSE_APACHE-2.0 │ │ ├── LICENSE_MIT │ │ ├── README.md │ │ ├── build.rs │ │ └── src/ │ │ ├── dialog/ │ │ │ ├── mod.rs │ │ │ └── windows.rs │ │ ├── lib.rs │ │ ├── monitor/ │ │ │ ├── linux.rs │ │ │ ├── macos.rs │ │ │ ├── mod.rs │ │ │ └── windows.rs │ │ ├── undecorated_resizing.rs │ │ ├── util.rs │ │ ├── webview.rs │ │ └── window/ │ │ ├── linux.rs │ │ ├── macos.rs │ │ ├── mod.rs │ │ └── windows.rs │ ├── tauri-schema-generator/ │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── build.rs │ │ ├── schemas/ │ │ │ ├── capability.schema.json │ │ │ ├── config.schema.json │ │ │ ├── permission.schema.json │ │ │ └── scope.schema.json │ │ └── src/ │ │ └── main.rs │ ├── tauri-schema-worker/ │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── config.rs │ │ │ └── lib.rs │ │ └── wrangler.toml │ ├── tauri-utils/ │ │ ├── CHANGELOG.md │ │ ├── Cargo.toml │ │ ├── LICENSE_APACHE-2.0 │ │ ├── LICENSE_MIT │ │ ├── README.md │ │ └── src/ │ │ ├── acl/ │ │ │ ├── build.rs │ │ │ ├── capability.rs │ │ │ ├── identifier.rs │ │ │ ├── manifest.rs │ │ │ ├── mod.rs │ │ │ ├── resolved.rs │ │ │ ├── schema.rs │ │ │ └── value.rs │ │ ├── assets.rs │ │ ├── build.rs │ │ ├── config/ │ │ │ └── parse.rs │ │ ├── config.rs │ │ ├── config_v1/ │ │ │ ├── mod.rs │ │ │ └── parse.rs │ │ ├── html.rs │ │ ├── io.rs │ │ ├── lib.rs │ │ ├── mime_type.rs │ │ ├── pattern/ │ │ │ ├── isolation.js │ │ │ ├── isolation.rs │ │ │ └── mod.rs │ │ ├── platform/ │ │ │ └── starting_binary.rs │ │ ├── platform.rs │ │ ├── plugin.rs │ │ ├── resources.rs │ │ └── tokens.rs │ └── tests/ │ ├── acl/ │ │ ├── Cargo.toml │ │ ├── fixtures/ │ │ │ ├── capabilities/ │ │ │ │ ├── basic-ping/ │ │ │ │ │ ├── cap.toml │ │ │ │ │ └── required-plugins.json │ │ │ │ ├── file-explorer/ │ │ │ │ │ ├── cap.toml │ │ │ │ │ └── required-plugins.json │ │ │ │ ├── file-explorer-remote/ │ │ │ │ │ ├── cap.toml │ │ │ │ │ └── required-plugins.json │ │ │ │ ├── multiwebview/ │ │ │ │ │ ├── cap.toml │ │ │ │ │ └── required-plugins.json │ │ │ │ ├── multiwindow/ │ │ │ │ │ ├── cap-external.toml │ │ │ │ │ ├── cap-main.json │ │ │ │ │ └── required-plugins.json │ │ │ │ ├── platform-specific-permissions/ │ │ │ │ │ ├── cap.toml │ │ │ │ │ └── required-plugins.json │ │ │ │ ├── scope/ │ │ │ │ │ ├── cap.toml │ │ │ │ │ └── required-plugins.json │ │ │ │ └── scope-extended/ │ │ │ │ ├── cap.json │ │ │ │ └── required-plugins.json │ │ │ ├── plugins/ │ │ │ │ ├── fs/ │ │ │ │ │ ├── deny-home.toml │ │ │ │ │ ├── move-tmp.toml │ │ │ │ │ ├── read-dir.toml │ │ │ │ │ ├── read-download-dir.toml │ │ │ │ │ ├── read-file.toml │ │ │ │ │ ├── read-resources.toml │ │ │ │ │ ├── read.toml │ │ │ │ │ └── scope.toml │ │ │ │ ├── os/ │ │ │ │ │ ├── linux.toml │ │ │ │ │ ├── macos.toml │ │ │ │ │ ├── open-browser.toml │ │ │ │ │ └── windows.toml │ │ │ │ └── ping/ │ │ │ │ └── ping.toml │ │ │ └── snapshots/ │ │ │ ├── acl_tests__tests__basic-ping.snap │ │ │ ├── acl_tests__tests__file-explorer-remote.snap │ │ │ ├── acl_tests__tests__file-explorer.snap │ │ │ ├── acl_tests__tests__multiwebview.snap │ │ │ ├── acl_tests__tests__multiwindow.snap │ │ │ ├── acl_tests__tests__scope-extended.snap │ │ │ ├── acl_tests__tests__scope.snap │ │ │ ├── linux/ │ │ │ │ └── acl_tests__tests__platform-specific-permissions.snap │ │ │ ├── macOS/ │ │ │ │ └── acl_tests__tests__platform-specific-permissions.snap │ │ │ └── windows/ │ │ │ └── acl_tests__tests__platform-specific-permissions.snap │ │ └── src/ │ │ └── lib.rs │ ├── app-updater/ │ │ └── frameworks/ │ │ └── test.framework/ │ │ ├── Headers │ │ ├── Modules │ │ ├── Resources │ │ └── Versions/ │ │ ├── A/ │ │ │ ├── Headers/ │ │ │ │ └── test.h │ │ │ ├── Modules/ │ │ │ │ └── module.modulemap │ │ │ ├── Resources/ │ │ │ │ └── Info.plist │ │ │ ├── _CodeSignature/ │ │ │ │ └── CodeResources │ │ │ └── test │ │ └── Current │ └── restart/ │ ├── Cargo.toml │ ├── LICENSE.spdx │ ├── LICENSE_APACHE-2.0 │ ├── LICENSE_MIT │ ├── build.rs │ ├── src/ │ │ └── main.rs │ └── tests/ │ └── restart.rs ├── dependabot.yml ├── examples/ │ ├── .icons/ │ │ └── icon.icns │ ├── README.md │ ├── api/ │ │ ├── .gitignore │ │ ├── .setup-cross.sh │ │ ├── .taurignore │ │ ├── README.md │ │ ├── dist/ │ │ │ └── .gitkeep │ │ ├── index.html │ │ ├── isolation-dist/ │ │ │ ├── index.html │ │ │ └── index.js │ │ ├── jsconfig.json │ │ ├── package.json │ │ ├── src/ │ │ │ ├── App.svelte │ │ │ ├── app.css │ │ │ ├── components/ │ │ │ │ ├── MenuBuilder.svelte │ │ │ │ └── MenuItemBuilder.svelte │ │ │ ├── main.js │ │ │ ├── views/ │ │ │ │ ├── App.svelte │ │ │ │ ├── Communication.svelte │ │ │ │ ├── Menu.svelte │ │ │ │ ├── Tray.svelte │ │ │ │ ├── WebRTC.svelte │ │ │ │ ├── Welcome.svelte │ │ │ │ └── Window.svelte │ │ │ └── vite-env.d.ts │ │ ├── src-tauri/ │ │ │ ├── .gitignore │ │ │ ├── .taurignore │ │ │ ├── Cargo.toml │ │ │ ├── Cross.toml │ │ │ ├── Info.plist │ │ │ ├── build.rs │ │ │ ├── capabilities/ │ │ │ │ ├── .gitignore │ │ │ │ ├── main.json │ │ │ │ └── run-app.json │ │ │ ├── locales/ │ │ │ │ └── pt-BR.wxl │ │ │ ├── permissions/ │ │ │ │ ├── app-menu/ │ │ │ │ │ └── default.toml │ │ │ │ └── autogenerated/ │ │ │ │ ├── echo.toml │ │ │ │ ├── log_operation.toml │ │ │ │ ├── perform_request.toml │ │ │ │ └── spam.toml │ │ │ ├── src/ │ │ │ │ ├── cmd.rs │ │ │ │ ├── lib.rs │ │ │ │ ├── main.rs │ │ │ │ ├── menu_plugin.rs │ │ │ │ └── tray.rs │ │ │ ├── tauri-plugin-sample/ │ │ │ │ ├── .gitignore │ │ │ │ ├── Cargo.toml │ │ │ │ ├── android/ │ │ │ │ │ ├── .gitignore │ │ │ │ │ ├── build.gradle.kts │ │ │ │ │ ├── proguard-rules.pro │ │ │ │ │ ├── settings.gradle │ │ │ │ │ └── src/ │ │ │ │ │ ├── androidTest/ │ │ │ │ │ │ └── java/ │ │ │ │ │ │ └── com/ │ │ │ │ │ │ └── plugin/ │ │ │ │ │ │ └── sample/ │ │ │ │ │ │ └── ExampleInstrumentedTest.kt │ │ │ │ │ ├── main/ │ │ │ │ │ │ ├── AndroidManifest.xml │ │ │ │ │ │ └── java/ │ │ │ │ │ │ └── com/ │ │ │ │ │ │ └── plugin/ │ │ │ │ │ │ └── sample/ │ │ │ │ │ │ ├── Example.kt │ │ │ │ │ │ └── ExamplePlugin.kt │ │ │ │ │ └── test/ │ │ │ │ │ └── java/ │ │ │ │ │ └── com/ │ │ │ │ │ └── plugin/ │ │ │ │ │ └── sample/ │ │ │ │ │ └── ExampleUnitTest.kt │ │ │ │ ├── api-iife.js │ │ │ │ ├── build.rs │ │ │ │ ├── ios/ │ │ │ │ │ ├── .gitignore │ │ │ │ │ ├── Package.swift │ │ │ │ │ ├── README.md │ │ │ │ │ ├── Sources/ │ │ │ │ │ │ └── ExamplePlugin.swift │ │ │ │ │ └── Tests/ │ │ │ │ │ └── PluginTests/ │ │ │ │ │ └── PluginTests.swift │ │ │ │ ├── permissions/ │ │ │ │ │ ├── .gitignore │ │ │ │ │ ├── autogenerated/ │ │ │ │ │ │ ├── commands/ │ │ │ │ │ │ │ └── ping.toml │ │ │ │ │ │ └── reference.md │ │ │ │ │ ├── global-scope.toml │ │ │ │ │ └── ping-scoped.toml │ │ │ │ └── src/ │ │ │ │ ├── desktop.rs │ │ │ │ ├── error.rs │ │ │ │ ├── lib.rs │ │ │ │ ├── mobile.rs │ │ │ │ └── models.rs │ │ │ └── tauri.conf.json │ │ ├── svelte.config.js │ │ ├── unocss.config.js │ │ └── vite.config.js │ ├── commands/ │ │ ├── README.md │ │ ├── commands.rs │ │ ├── index.html │ │ ├── main.rs │ │ └── tauri.conf.json │ ├── file-associations/ │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ └── src-tauri/ │ │ ├── .license_template │ │ ├── Cargo.toml │ │ ├── Info.plist │ │ ├── build.rs │ │ ├── src/ │ │ │ └── main.rs │ │ └── tauri.conf.json │ ├── helloworld/ │ │ ├── README.md │ │ ├── index.html │ │ ├── main.rs │ │ └── tauri.conf.json │ ├── isolation/ │ │ ├── README.md │ │ ├── dist/ │ │ │ ├── index.html │ │ │ └── linked.js │ │ ├── isolation-dist/ │ │ │ ├── index.html │ │ │ └── index.js │ │ ├── main.rs │ │ └── tauri.conf.json │ ├── multiwebview/ │ │ ├── README.md │ │ ├── index.html │ │ ├── main.rs │ │ └── tauri.conf.json │ ├── multiwindow/ │ │ ├── README.md │ │ ├── index.html │ │ ├── main.rs │ │ └── tauri.conf.json │ ├── resources/ │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ └── src-tauri/ │ │ ├── Cargo.toml │ │ ├── assets/ │ │ │ └── index.js │ │ ├── build.rs │ │ ├── capabilities/ │ │ │ └── app.json │ │ ├── src/ │ │ │ └── main.rs │ │ └── tauri.conf.json │ ├── run-return/ │ │ ├── README.md │ │ ├── index.html │ │ ├── main.rs │ │ └── tauri.conf.json │ ├── splashscreen/ │ │ ├── README.md │ │ ├── dist/ │ │ │ ├── index.html │ │ │ └── splashscreen.html │ │ ├── main.rs │ │ └── tauri.conf.json │ ├── state/ │ │ ├── README.md │ │ ├── index.html │ │ ├── main.rs │ │ └── tauri.conf.json │ └── streaming/ │ ├── README.md │ ├── index.html │ ├── main.rs │ └── tauri.conf.json ├── package.json ├── packages/ │ ├── api/ │ │ ├── .gitignore │ │ ├── CHANGELOG.md │ │ ├── LICENSE_APACHE-2.0 │ │ ├── LICENSE_MIT │ │ ├── README.md │ │ ├── eslint.config.js │ │ ├── package.json │ │ ├── rollup.config.ts │ │ ├── src/ │ │ │ ├── app.ts │ │ │ ├── core.ts │ │ │ ├── dpi.ts │ │ │ ├── event.ts │ │ │ ├── global.d.ts │ │ │ ├── image.ts │ │ │ ├── index.ts │ │ │ ├── menu/ │ │ │ │ ├── base.ts │ │ │ │ ├── checkMenuItem.ts │ │ │ │ ├── iconMenuItem.ts │ │ │ │ ├── menu.ts │ │ │ │ ├── menuItem.ts │ │ │ │ ├── predefinedMenuItem.ts │ │ │ │ └── submenu.ts │ │ │ ├── menu.ts │ │ │ ├── mocks.ts │ │ │ ├── path.ts │ │ │ ├── tray.ts │ │ │ ├── webview.ts │ │ │ ├── webviewWindow.ts │ │ │ └── window.ts │ │ └── tsconfig.json │ └── cli/ │ ├── .cargo/ │ │ └── config.toml │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── Cargo.toml │ ├── LICENSE_APACHE-2.0 │ ├── LICENSE_MIT │ ├── README.md │ ├── __tests__/ │ │ ├── fixtures/ │ │ │ └── empty/ │ │ │ ├── .gitignore │ │ │ ├── dist/ │ │ │ │ └── index.html │ │ │ └── package.json │ │ └── template.spec.ts │ ├── append-headers.js │ ├── build.rs │ ├── index.d.ts │ ├── index.js │ ├── main.d.ts │ ├── main.js │ ├── npm/ │ │ ├── darwin-arm64/ │ │ │ ├── README.md │ │ │ └── package.json │ │ ├── darwin-x64/ │ │ │ ├── README.md │ │ │ └── package.json │ │ ├── linux-arm-gnueabihf/ │ │ │ ├── README.md │ │ │ └── package.json │ │ ├── linux-arm64-gnu/ │ │ │ ├── README.md │ │ │ └── package.json │ │ ├── linux-arm64-musl/ │ │ │ ├── README.md │ │ │ └── package.json │ │ ├── linux-riscv64-gnu/ │ │ │ ├── README.md │ │ │ └── package.json │ │ ├── linux-x64-gnu/ │ │ │ ├── README.md │ │ │ └── package.json │ │ ├── linux-x64-musl/ │ │ │ ├── README.md │ │ │ └── package.json │ │ ├── win32-arm64-msvc/ │ │ │ ├── README.md │ │ │ └── package.json │ │ ├── win32-ia32-msvc/ │ │ │ ├── README.md │ │ │ └── package.json │ │ └── win32-x64-msvc/ │ │ ├── README.md │ │ └── package.json │ ├── package.json │ ├── src/ │ │ └── lib.rs │ └── tauri.js ├── pnpm-workspace.yaml ├── renovate.json ├── rustfmt.toml └── supply-chain/ ├── audits.toml └── config.toml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .cargo/audit.toml ================================================ [advisories] ignore = [ # rsa Marvin Attack "RUSTSEC-2023-0071", # difference is unmaintained "RUSTSEC-2020-0095", # proc-macro-error is unmaintained "RUSTSEC-2024-0370", # time crate can't be updated in the repo because of MSRV, users are unaffected "RUSTSEC-2026-0009", ] ================================================ FILE: .cargo/config.toml ================================================ [env] # workaround needed to prevent `STATUS_ENTRYPOINT_NOT_FOUND` error in tests # see https://github.com/tauri-apps/tauri/pull/4383#issuecomment-1212221864 __TAURI_WORKSPACE__ = "true" ================================================ FILE: .changes/README.md ================================================ # Changes ##### via https://github.com/jbolda/covector As you create PRs and make changes that require a version bump, please add a new markdown file in this folder. You do not note the version _number_, but rather the type of bump that you expect: major, minor, or patch. The filename is not important, as long as it is a `.md`, but we recommend that it represents the overall change for organizational purposes. When you select the version bump required, you do _not_ need to consider dependencies. Only note the package with the actual change, and any packages that depend on that package will be bumped automatically in the process. Use the following format: ```md --- 'package-a': 'patch:enhance' 'package-b': 'patch:enhance' --- Change summary goes here ``` Summaries do not have a specific character limit, but are text only. These summaries are used within the (future implementation of) changelogs. They will give context to the change and also point back to the original PR if more details and context are needed. Changes will be designated as a `major`, `minor` or `patch` as further described in [semver](https://semver.org/). Given a version number MAJOR.MINOR.PATCH, increment the: - MAJOR version when you make incompatible API changes, - MINOR version when you add functionality in a backwards compatible manner, and - PATCH version when you make backwards compatible bug fixes. Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format, but will be discussed prior to usage (as extra steps will be necessary in consideration of merging and publishing). Additionally you could specify a tag for the change file to group it with other changes by prefixing the bump with `:`, for example: ```md --- 'package-a': 'patch:enhance' --- Change summary goes here ``` which will group this change file with other changes that specify the `bug` tag. For list of available tags, see the `changeTags` key in [./config.json](./config.json) ================================================ FILE: .changes/base64.md ================================================ --- "tauri-macos-sign": patch:enhance --- Do not rely on system base64 CLI to decode certificates. ================================================ FILE: .changes/config.json ================================================ { "gitSiteUrl": "https://www.github.com/tauri-apps/tauri/", "changeTags": { "feat": "New Features", "enhance": "Enhancements", "bug": "Bug Fixes", "perf": "Performance Improvements", "changes": "What's Changed", "sec": "Security fixes", "deps": "Dependencies", "breaking": "Breaking Changes" }, "defaultChangeTag": "changes", "pkgManagers": { "rust": { "version": true, "getPublishedVersion": { "use": "fetch:check", "options": { "url": "https://crates.io/api/v1/crates/${ pkg.pkgFile.pkg.package.name }/${ pkg.pkgFile.version }" } }, "prepublish": [ "cargo install cargo-audit --features=fix", { "command": "echo '
\n

Cargo Audit

\n\n```'", "dryRunCommand": true, "pipe": true }, { "command": "cargo audit ${ process.env.CARGO_AUDIT_OPTIONS || '' }", "dryRunCommand": true, "runFromRoot": true, "pipe": true }, { "command": "echo '```\n\n
\n'", "dryRunCommand": true, "pipe": true } ], "publish": [ { "command": "echo '
\n

Cargo Publish

\n\n```'", "dryRunCommand": true, "pipe": true }, { "command": "cargo publish", "dryRunCommand": "cargo publish --dry-run", "pipe": true }, { "command": "echo '```\n\n
\n'", "dryRunCommand": true, "pipe": true } ], "postpublish": { "use": "fetch:check", "options": { "url": "https://crates.io/api/v1/crates/${ pkg.pkgFile.pkg.package.name }/${ pkg.pkgFile.version }" }, "retries": [5000, 5000, 5000] } }, "javascript": { "version": true, "getPublishedVersion": { "use": "fetch:check", "options": { "url": "https://registry.npmjs.com/${ pkg.pkgFile.pkg.name }/${ pkg.pkgFile.version }" } }, "prepublish": [ { "command": "echo '
\n

PNPM Audit

\n\n```'", "dryRunCommand": true, "pipe": true }, { "command": "pnpm i --frozen-lockfile", "dryRunCommand": true }, { "command": "pnpm audit", "dryRunCommand": true, "runFromRoot": true, "pipe": true }, { "command": "echo '```\n\n
\n'", "dryRunCommand": true, "pipe": true } ], "publish": [ { "command": "echo '
\n

PNPM Publish

\n\n```'", "dryRunCommand": true, "pipe": true }, { "command": "pnpm publish --access public --loglevel silly --no-git-checks", "dryRunCommand": "npm publish --dry-run --access public --no-git-checks", "pipe": true }, { "command": "echo '```\n\n
\n'", "dryRunCommand": true, "pipe": true } ], "postpublish": { "use": "fetch:check", "options": { "url": "https://registry.npmjs.com/${ pkg.pkgFile.pkg.name }/${ pkg.pkgFile.version }" }, "retries": [5000, 5000, 5000] } } }, "packages": { "@tauri-apps/api": { "path": "./packages/api", "manager": "javascript", "publish": [ { "command": "echo '
\n

PNPM Publish

\n\n```'", "dryRunCommand": true, "pipe": true }, { "command": "pnpm npm-publish", "dryRunCommand": true, "pipe": true }, { "command": "echo '```\n\n
\n'", "dryRunCommand": true, "pipe": true } ] }, "tauri-utils": { "path": "./crates/tauri-utils", "manager": "rust" }, "tauri-macos-sign": { "path": "./crates/tauri-macos-sign", "manager": "rust" }, "tauri-bundler": { "path": "./crates/tauri-bundler", "manager": "rust", "dependencies": ["tauri-utils", "tauri-macos-sign"] }, "tauri-runtime": { "path": "./crates/tauri-runtime", "manager": "rust", "dependencies": ["tauri-utils"] }, "tauri-runtime-wry": { "path": "./crates/tauri-runtime-wry", "manager": "rust", "dependencies": ["tauri-utils", "tauri-runtime"] }, "tauri-codegen": { "path": "./crates/tauri-codegen", "manager": "rust", "dependencies": ["tauri-utils"] }, "tauri-macros": { "path": "./crates/tauri-macros", "manager": "rust", "dependencies": ["tauri-codegen", "tauri-utils"] }, "tauri-plugin": { "path": "./crates/tauri-plugin", "manager": "rust", "dependencies": ["tauri-utils"], "postversion": "node ../../.scripts/ci/sync-cli-metadata.js ${ pkg.pkg } ${ release.type }" }, "tauri-build": { "path": "./crates/tauri-build", "manager": "rust", "dependencies": ["tauri-codegen", "tauri-utils"], "postversion": "node ../../.scripts/ci/sync-cli-metadata.js ${ pkg.pkg } ${ release.type }" }, "tauri": { "path": "./crates/tauri", "manager": "rust", "dependencies": [ "tauri-macros", "tauri-utils", "tauri-runtime", "tauri-runtime-wry", "tauri-build" ], "postversion": [ "node ../../.scripts/ci/sync-cli-metadata.js ${ pkg.pkg } ${ release.type }", "cargo build --manifest-path ../tauri-schema-generator/Cargo.toml" ] }, "@tauri-apps/cli": { "path": "./packages/cli", "manager": "javascript", "dependencies": ["tauri-cli"], "postversion": "node ../../.scripts/ci/sync-cli-metadata.js ${ pkg.pkg } ${ release.type }", "prepublish": [], "publish": [], "postpublish": [] }, "tauri-cli": { "path": "./crates/tauri-cli", "manager": "rust", "dependencies": ["tauri-bundler", "tauri-utils", "tauri-macos-sign"] }, "tauri-driver": { "path": "./crates/tauri-driver", "manager": "rust" } } } ================================================ FILE: .changes/data-tauri-drag-region-deep.md ================================================ --- "tauri": minor:feat --- Add `data-tauri-drag-region="deep"` so clicks on non-clickable children will drag as well. Can still opt out of drag on some regions using `data-tauri-drag-region="false"` ================================================ FILE: .changes/fix-build-bundles-arg.md ================================================ --- "tauri-bundler": patch:bug "tauri-cli": patch:bug "@tauri-apps/cli": patch:bug --- Fix `build --bundles` to allow `nsis` arg in linux+macOS ================================================ FILE: .changes/linux-deploy-link.md ================================================ --- "tauri-bundler": patch:bug --- Correct GitHub Release URL path for Linux i686 tooling. ================================================ FILE: .changes/prompt-signing-key-password-context.md ================================================ --- "tauri-cli": patch:enhance "@tauri-apps/cli": patch:enhance --- Show the context before prompting for updater signing key password ================================================ FILE: .changes/toml-ver.md ================================================ --- tauri-utils: patch:deps --- Changed `toml` crate version from `0.9` to `">=0.9, <=1"` ================================================ FILE: .devcontainer/Dockerfile ================================================ # See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/master/containers/ubuntu/.devcontainer/base.Dockerfile # [Choice] Ubuntu version (use jammy or bionic on local arm64/Apple Silicon): jammy, focal, bionic ARG VARIANT="jammy" FROM mcr.microsoft.com/vscode/devcontainers/base:0-${VARIANT} # Derived from Tauri contribution and setup guides: # See: https://github.com/tauri-apps/tauri/blob/dev/.github/CONTRIBUTING.md#development-guide # See: https://v2.tauri.app/start/prerequisites/ ARG TAURI_BUILD_DEPS="build-essential curl libappindicator3-dev libgtk-3-dev librsvg2-dev libssl-dev libwebkit2gtk-4.1-dev wget" RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ && apt-get install -y --no-install-recommends $TAURI_BUILD_DEPS ================================================ FILE: .devcontainer/README.md ================================================ # VS Code Devcontainer for Tauri ## Overview Please note that most of these instructions are derived from Microsoft's VS Code documentation: [Developing inside a Container](https://code.visualstudio.com/docs/remote/containers). Check the official documentation if you encounter problems and submit a PR with any corrections you find for the instructions below. The development container included in this repository is derived from [Microsoft's default Ubuntu development container](https://github.com/microsoft/vscode-dev-containers/tree/master/containers/ubuntu). Contents of the Ubuntu Docker image can be in the [VS Code devcontainer Ubuntu base Dockerfile](https://github.com/microsoft/vscode-dev-containers/blob/main/containers/ubuntu/.devcontainer/base.Dockerfile). The contents of the container used for development can be found in the [Dockerfile](./Dockerfile) located in the same directory as this README. ## Usage 1. Ensure you have all [Devcontainer Prerequisites](#devcontainer-prerequisites) 2. Open the directory containing your [`tauri-apps/tauri`](https://github.com/tauri-apps/tauri) code. 3. Install the [Remote Development](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack) extension pack for VS Code. This will be included if you install recommended workspace extensions upon opening this repository. 4. Ensure Docker is running 5. [Open your workspace in the provided devcontainer](https://code.visualstudio.com/docs/remote/containers#_open-an-existing-workspace-in-a-container): Open this repository in VS Code and run **Remote-Containers: Reopen in Container...** from the Command Palette (F1). ### Devcontainer Prerequisites Prerequisites are mainly derived from VS Code's instructions for usage of development containers, documented here: [Developing inside a Container: Getting Started](https://code.visualstudio.com/docs/remote/containers#_getting-started). 1. Docker (Docker Desktop recommended) 2. VS Code 3. X window host - required if you want to be able to interact with a GUI from your Docker host ### A note on filesystem performance Due to limitations in how Docker shares files between the Docker host and a container, it's also recommended that developers [clone Tauri source code into a container volume](https://code.visualstudio.com/remote/advancedcontainers/improve-performance#_use-clone-repository-in-container-volume). This is optional, but highly advised as many filesystem/IO heavy operations (`cargo build`, `pnpm install`, etc) will be very slow if they operate on directories shared with a Docker container from the Docker host. To do this, open your project with VS Code and run **Remote-Containers: Clone Repository in Container Volume...** from the Command Palette (F1). ### Accessing a Tauri application running you the devcontainer Docker Desktop provides facilities for [allowing the development container to connect to a service on the Docker host](https://docs.docker.com/desktop/windows/networking/#i-want-to-connect-from-a-container-to-a-service-on-the-host). So long as you have an X window server running on your Docker host, the devcontainer can connect to it and expose your Tauri GUI via an X window. **Export the `DISPLAY` variable within the devcontainer terminal you launch your Tauri application from to expose your GUI outside of the devcontainer**. ```bash export DISPLAY="host.docker.internal:0" ``` ================================================ FILE: .devcontainer/devcontainer.json ================================================ // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: // https://github.com/microsoft/vscode-dev-containers/tree/v0.234.0/containers/ubuntu { "name": "Ubuntu", "build": { "dockerfile": "Dockerfile", // Update 'VARIANT' to pick an Ubuntu version: jammy / ubuntu-22.04, focal / ubuntu-20.04, bionic /ubuntu-18.04 // Use ubuntu-22.04 or ubuntu-18.04 on local arm64/Apple Silicon. "args": { "VARIANT": "ubuntu-22.04" } }, // Set *default* container specific settings.json values on container create. "settings": {}, // Add the IDs of extensions you want installed when the container is created. "extensions": [], // Use 'forwardPorts' to make a list of ports inside the container available locally. // "forwardPorts": [], // Use 'postCreateCommand' to run commands after the container is created. // "postCreateCommand": "uname -a", // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. "remoteUser": "vscode", "features": { "node": "lts", "rust": "latest" } } ================================================ FILE: .docker/cross/aarch64.Dockerfile ================================================ FROM ubuntu:22.04 ARG DEBIAN_FRONTEND=noninteractive COPY common.sh lib.sh / RUN /common.sh COPY cmake.sh / RUN /cmake.sh COPY xargo.sh / RUN /xargo.sh RUN apt-get update && apt-get install --assume-yes --no-install-recommends \ g++-aarch64-linux-gnu \ libc6-dev-arm64-cross COPY deny-debian-packages.sh / RUN TARGET_ARCH=arm64 /deny-debian-packages.sh \ binutils \ binutils-aarch64-linux-gnu COPY qemu.sh / RUN /qemu.sh aarch64 softmmu COPY dropbear.sh / RUN /dropbear.sh COPY linux-image.sh / RUN /linux-image.sh aarch64 COPY linux-runner / ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc \ CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER="/linux-runner aarch64" \ CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc \ CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++ \ BINDGEN_EXTRA_CLANG_ARGS_aarch64_unknown_linux_gnu="--sysroot=/usr/aarch64-linux-gnu" \ QEMU_LD_PREFIX=/usr/aarch64-linux-gnu \ RUST_TEST_THREADS=1 \ PKG_CONFIG_PATH="/usr/lib/aarch64-linux-gnu/pkgconfig/:${PKG_CONFIG_PATH}" RUN dpkg --add-architecture arm64 RUN apt-get update RUN apt-get install --assume-yes --no-install-recommends libssl-dev:arm64 libdbus-1-dev:arm64 libsoup2.4-dev:arm64 libssl-dev:arm64 libgtk-3-dev:arm64 webkit2gtk-4.1-dev:arm64 libappindicator3-1:arm64 librsvg2-dev:arm64 patchelf:arm64 ================================================ FILE: .docker/cross/cmake.sh ================================================ #!/usr/bin/env bash set -x set -euo pipefail # shellcheck disable=SC1091 . lib.sh main() { local version=3.23.1 install_packages curl local td td="$(mktemp -d)" pushd "${td}" curl --retry 3 -sSfL "https://github.com/Kitware/CMake/releases/download/v${version}/cmake-${version}-linux-x86_64.sh" -o cmake.sh sh cmake.sh --skip-license --prefix=/usr/local popd purge_packages rm -rf "${td}" rm -rf /var/lib/apt/lists/* rm "${0}" } main "${@}" ================================================ FILE: .docker/cross/common.sh ================================================ #!/usr/bin/env bash set -x set -euo pipefail # shellcheck disable=SC1091 . lib.sh # For architectures except amd64 and i386, look for packages on ports.ubuntu.com instead. # This is important if you enable additional architectures so you can install libraries to cross-compile against. # Look for 'dpkg --add-architecture' in the README for more details. if grep -i ubuntu /etc/os-release >/dev/null; then sed 's/http:\/\/\(.*\).ubuntu.com\/ubuntu\//[arch-=amd64,i386] http:\/\/ports.ubuntu.com\/ubuntu-ports\//g' /etc/apt/sources.list > /etc/apt/sources.list.d/ports.list sed -i 's/http:\/\/\(.*\).ubuntu.com\/ubuntu\//[arch=amd64,i386] http:\/\/\1.archive.ubuntu.com\/ubuntu\//g' /etc/apt/sources.list fi install_packages \ autoconf \ automake \ binutils \ ca-certificates \ curl \ file \ gcc \ git \ libtool \ m4 \ make if_centos install_packages \ clang-devel \ gcc-c++ \ glibc-devel \ pkgconfig if_ubuntu install_packages \ g++ \ libc6-dev \ libclang-dev \ pkg-config ================================================ FILE: .docker/cross/deny-debian-packages.sh ================================================ #!/usr/bin/env bash set -x set -euo pipefail main() { local package for package in "${@}"; do echo "Package: ${package}:${TARGET_ARCH} Pin: release * Pin-Priority: -1" > "/etc/apt/preferences.d/${package}" echo "${package}" done rm "${0}" } main "${@}" ================================================ FILE: .docker/cross/dropbear.sh ================================================ #!/usr/bin/env bash set -x set -euo pipefail # shellcheck disable=SC1091 . lib.sh main() { local version=2022.82 install_packages \ autoconf \ automake \ bzip2 \ curl \ make if_centos install_packages zlib-devel if_ubuntu install_packages zlib1g-dev local td td="$(mktemp -d)" pushd "${td}" curl --retry 3 -sSfL "https://matt.ucc.asn.au/dropbear/releases/dropbear-${version}.tar.bz2" -O tar --strip-components=1 -xjf "dropbear-${version}.tar.bz2" # Remove some unwanted message sed -i '/skipping hostkey/d' cli-kex.c sed -i '/failed to identify current user/d' cli-runopts.c ./configure \ --disable-syslog \ --disable-shadow \ --disable-lastlog \ --disable-utmp \ --disable-utmpx \ --disable-wtmp \ --disable-wtmpx \ --disable-pututline \ --disable-pututxline make "-j$(nproc)" PROGRAMS=dbclient cp dbclient /usr/local/bin/ purge_packages popd rm -rf "${td}" rm "${0}" } main "${@}" ================================================ FILE: .docker/cross/lib.sh ================================================ purge_list=() install_packages() { if grep -i ubuntu /etc/os-release; then apt-get update for pkg in "${@}"; do if ! dpkg -L "${pkg}" >/dev/null 2>/dev/null; then apt-get install --assume-yes --no-install-recommends "${pkg}" purge_list+=( "${pkg}" ) fi done else for pkg in "${@}"; do if ! yum list installed "${pkg}" >/dev/null 2>/dev/null; then yum install -y "${pkg}" purge_list+=( "${pkg}" ) fi done fi } purge_packages() { if (( ${#purge_list[@]} )); then if grep -i ubuntu /etc/os-release; then apt-get purge --assume-yes --auto-remove "${purge_list[@]}" else yum remove -y "${purge_list[@]}" fi fi } if_centos() { if grep -q -i centos /etc/os-release; then eval "${@}" fi } if_ubuntu() { if grep -q -i ubuntu /etc/os-release; then eval "${@}" fi } ================================================ FILE: .docker/cross/linux-image.sh ================================================ #!/usr/bin/env bash set -x set -euo pipefail # shellcheck disable=SC1091 . lib.sh main() { # arch in the rust target local arch="${1}" \ kversion=4.19.0-20 local debsource="deb http://http.debian.net/debian/ buster main" debsource="${debsource}\ndeb http://security.debian.org/ buster/updates main" local dropbear="dropbear-bin" local -a deps local kernel= local libgcc="libgcc1" # select debian arch and kernel version case "${arch}" in aarch64) arch=arm64 kernel="${kversion}-arm64" ;; armv7) arch=armhf kernel="${kversion}-armmp" ;; i686) arch=i386 kernel="${kversion}-686" ;; mips|mipsel) kernel="${kversion}-4kc-malta" ;; mips64el) kernel="${kversion}-5kc-malta" ;; powerpc) # there is no buster powerpc port, so we use jessie # use a more recent kernel from backports kversion='4.9.0-0.bpo.6' kernel="${kversion}-powerpc" debsource="deb http://archive.debian.org/debian jessie main" debsource="${debsource}\ndeb http://archive.debian.org/debian jessie-backports main" debsource="${debsource}\ndeb http://ftp.ports.debian.org/debian-ports unstable main" debsource="${debsource}\ndeb http://ftp.ports.debian.org/debian-ports unreleased main" # archive.debian.org Release files are expired. echo "Acquire::Check-Valid-Until false;" | tee -a /etc/apt/apt.conf.d/10-nocheckvalid echo "APT::Get::AllowUnauthenticated true;" | tee -a /etc/apt/apt.conf.d/10-nocheckvalid dropbear="dropbear" deps=(libcrypt1:"${arch}") ;; powerpc64) # there is no stable port arch=ppc64 # https://packages.debian.org/en/sid/linux-image-powerpc64 kversion='5.*' kernel="${kversion}-powerpc64" libgcc="libgcc-s1" debsource="deb http://ftp.ports.debian.org/debian-ports unstable main" debsource="${debsource}\ndeb http://ftp.ports.debian.org/debian-ports unreleased main" # sid version of dropbear requires these dependencies deps=(libcrypt1:"${arch}") ;; powerpc64le) arch=ppc64el kernel="${kversion}-powerpc64le" ;; s390x) arch=s390x kernel="${kversion}-s390x" ;; sparc64) # there is no stable port # https://packages.debian.org/en/sid/linux-image-sparc64 kernel='*-sparc64' libgcc="libgcc-s1" debsource="deb http://ftp.ports.debian.org/debian-ports unstable main" debsource="${debsource}\ndeb http://ftp.ports.debian.org/debian-ports unreleased main" # sid version of dropbear requires these dependencies deps=(libcrypt1:"${arch}") ;; x86_64) arch=amd64 kernel="${kversion}-amd64" ;; *) echo "Invalid arch: ${arch}" exit 1 ;; esac install_packages ca-certificates \ curl \ cpio \ sharutils \ gnupg # Download packages mv /etc/apt/sources.list /etc/apt/sources.list.bak echo -e "${debsource}" > /etc/apt/sources.list # Old ubuntu does not support --add-architecture, so we directly change multiarch file if [ -f /etc/dpkg/dpkg.cfg.d/multiarch ]; then cp /etc/dpkg/dpkg.cfg.d/multiarch /etc/dpkg/dpkg.cfg.d/multiarch.bak fi dpkg --add-architecture "${arch}" || echo "foreign-architecture ${arch}" > /etc/dpkg/dpkg.cfg.d/multiarch # Add Debian keys. curl --retry 3 -sSfL 'https://ftp-master.debian.org/keys/archive-key-{7.0,8,9,10}.asc' -O curl --retry 3 -sSfL 'https://ftp-master.debian.org/keys/archive-key-{8,9,10}-security.asc' -O curl --retry 3 -sSfL 'https://ftp-master.debian.org/keys/release-{7,8,9,10}.asc' -O curl --retry 3 -sSfL 'https://www.ports.debian.org/archive_{2020,2021,2022}.key' -O for key in *.asc *.key; do apt-key add "${key}" rm "${key}" done # allow apt-get to retry downloads echo 'APT::Acquire::Retries "3";' > /etc/apt/apt.conf.d/80-retries apt-get update mkdir -p "/qemu/${arch}" chmod 777 /qemu "/qemu/${arch}" cd "/qemu/${arch}" apt-get -d --no-install-recommends download \ ${deps[@]+"${deps[@]}"} \ "busybox:${arch}" \ "${dropbear}:${arch}" \ "libtommath1:${arch}" \ "libtomcrypt1:${arch}" \ "libgmp10:${arch}" \ "libc6:${arch}" \ "${libgcc}:${arch}" \ "libstdc++6:${arch}" \ "linux-image-${kernel}:${arch}" \ ncurses-base \ "zlib1g:${arch}" cd /qemu # Install packages root="root-${arch}" mkdir -p "${root}"/{bin,etc/dropbear,root,sys,dev,proc,sbin,tmp,usr/{bin,sbin},var/log} for deb in "${arch}"/*deb; do dpkg -x "${deb}" "${root}"/ done cp "${root}/boot/vmlinu"* kernel # initrd mkdir -p "${root}/modules" cp -v \ "${root}/lib/modules"/*/kernel/drivers/net/net_failover.ko \ "${root}/lib/modules"/*/kernel/drivers/net/virtio_net.ko \ "${root}/lib/modules"/*/kernel/drivers/virtio/* \ "${root}/lib/modules"/*/kernel/fs/netfs/netfs.ko \ "${root}/lib/modules"/*/kernel/fs/9p/9p.ko \ "${root}/lib/modules"/*/kernel/fs/fscache/fscache.ko \ "${root}/lib/modules"/*/kernel/net/9p/9pnet.ko \ "${root}/lib/modules"/*/kernel/net/9p/9pnet_virtio.ko \ "${root}/lib/modules"/*/kernel/net/core/failover.ko \ "${root}/modules" || true # some file may not exist rm -rf "${root:?}/boot" rm -rf "${root:?}/lib/modules" cat << 'EOF' > "${root}/etc/hosts" 127.0.0.1 localhost qemu EOF cat << 'EOF' > $root/etc/hostname qemu EOF cat << 'EOF' > $root/etc/passwd root::0:0:root:/root:/bin/sh EOF cat << 'EOF' | uudecode -o $root/etc/dropbear/dropbear_rsa_host_key begin 600 dropbear_rsa_host_key M````!W-S:"UR+3[X=QMH,B*4$RYULV,V3X6]K:7@Q?80"#WXGGQZNFN6CZ7LTDX(F6J[\]F5<0`HEOF:Z MX;^53`L'4I/A```!``$L:$Z*#6<^3@+O%.[-#/5H+.C'3\#QQZN[1;J>L`8I MZ_&T'!"J'/Y+?R?55G:M^=]R*-&I3TOJYZA8@&H51ZOAF59'1_>>Z@?E4#)$ MQU)X/RWH51ZB5KSDWJS:D'7GD(!?NAY`C'7\)I:_4)J")QBV/P"RJQGHG'%B M1BT2LE6676>`1K,0\NIMZTKQNB(IC+88<7#8%_-=P<&6<"9LH>60TSS?3?-C MN`T36YB/3^<(Q;`N1NT>I9EZS`BAC^-?.:,R\7EL"<4>7E=]^1]B\K9])AQU MBM\]M;4V(S(6KH-I.4[6>9E+@\UEM.J6:[2LUEEJDG:G:+:/EVF^Y75@(S$` M``"!`.O+KW=&*CBCHL"11&SVO4/K]$R-]7MV7,3RR)Q[X'0;6.?4JHW!3VR6 M*FGBY--37ZD-+UV.8_+"$6PH9)(/E.\G19#G0K`LRM?JWS!58&;D0C1```` M@0"\[@NYWSTW(?Q@:_A*1Y3/AKYO5?S=0"<2>#V-AH6W-NCSDTSRP=2D79FS M"D?[;.)V>8'#9&I3"MU@+:2\Z%$0-MG0+J'(0>T1_C6?*C=4U0I$DI<=@D]1 H_&DE8Y(OT%%EPG]!$H&5HX*),_D1A2\P=R.7G'`0L%YM-79Y"T">$0`` ` end EOF # dropbear complains when this file is missing touch "${root}/var/log/lastlog" cat << 'EOF' > $root/init #!/bin/busybox sh set -e /bin/busybox --install mount -t devtmpfs devtmpfs /dev mount -t proc none /proc mount -t sysfs none /sys mkdir /dev/pts mount -t devpts none /dev/pts/ # some archs does not have virtio modules insmod /modules/failover.ko || true insmod /modules/net_failover.ko || true insmod /modules/virtio.ko || true insmod /modules/virtio_ring.ko || true insmod /modules/virtio_mmio.ko || true insmod /modules/virtio_pci_legacy_dev.ko || true insmod /modules/virtio_pci_modern_dev.ko || true insmod /modules/virtio_pci.ko || true insmod /modules/virtio_net.ko || true insmod /modules/netfs.ko || true insmod /modules/fscache.ko insmod /modules/9pnet.ko insmod /modules/9pnet_virtio.ko || true insmod /modules/9p.ko ifconfig lo 127.0.0.1 ifconfig eth0 10.0.2.15 route add default gw 10.0.2.2 eth0 mkdir /target mount -t 9p -o trans=virtio target /target -oversion=9p2000.u || true exec dropbear -F -E -B EOF chmod +x "${root}/init" cd "${root}" find . | cpio --create --format='newc' --quiet | gzip > ../initrd.gz cd - # Clean up rm -rf "/qemu/${root}" "/qemu/${arch}" mv -f /etc/apt/sources.list.bak /etc/apt/sources.list if [ -f /etc/dpkg/dpkg.cfg.d/multiarch.bak ]; then mv /etc/dpkg/dpkg.cfg.d/multiarch.bak /etc/dpkg/dpkg.cfg.d/multiarch fi # can fail if arch is used (amd64 and/or i386) dpkg --remove-architecture "${arch}" || true apt-get update purge_packages ls -lh /qemu } main "${@}" ================================================ FILE: .docker/cross/linux-runner ================================================ #!/usr/bin/env bash set -e LOG=/tmp/qemu.log LOCK=/tmp/qemu.lock if [ -n "${CROSS_DEBUG}" ]; then set -x fi # arch in the rust target arch="${1}" shift if [ "${CROSS_RUNNER}" = "" ]; then if [[ "${arch}" == i?86 ]] || [[ "${arch}" == x86_64 ]]; then CROSS_RUNNER=native else CROSS_RUNNER=qemu-user fi fi # select qemu arch qarch="${arch}" case "${arch}" in armv7) qarch="arm" ;; i686) qarch="i386" ;; powerpc) qarch="ppc" ;; powerpc64) qarch="ppc64" ;; powerpc64le) if [ "${CROSS_RUNNER}" = "qemu-user" ]; then qarch="ppc64le" else qarch="ppc64" fi ;; esac case "${CROSS_RUNNER}" in native) exec "${@}" ;; qemu-user) exec "qemu-${qarch}" "${@}" ;; qemu-system) true ;; *) echo "Invalid runner: \"${CROSS_RUNNER}\""; echo "Valid runners are: native, qemu-user and qemu-system" exit 1 ;; esac n="$(nproc)" memory=1G driver9p="virtio-9p-pci" drivernet="virtio-net-pci" # select qemu parameters case "${arch}" in aarch64) # 8 is the max number of cpu supported by qemu-aarch64 n=$(( n > 8 ? 8 : n )) opt="-machine virt -cpu cortex-a57" ;; armv7) opt="-machine virt" driver9p="virtio-9p-device" drivernet="virtio-net-device" ;; i686) opt="-append console=ttyS0" ;; mips|mipsel) # avoid kernel error # https://blahcat.github.io/2017/07/14/building-a-debian-stretch-qemu-image-for-mipsel/ opt="-append nokaslr" n=1 ;; mips64el) # avoid kernel error # https://blahcat.github.io/2017/07/14/building-a-debian-stretch-qemu-image-for-mipsel/ opt="-append nokaslr -cpu MIPS64R2-generic" n=1 ;; powerpc) opt="-append console=ttyPZ0" n=1 ;; powerpc64|powerpc64le) opt="-append console=hvc0 --nodefaults -serial stdio" ;; s390x) n=1 driver9p="virtio-9p-ccw" drivernet="virtio-net-ccw" ;; sparc64) n=1 driver9p+=",bus=pciB" drivernet+=",bus=pciB" ;; x86_64) opt="-append console=ttyS0" ;; esac ( flock -n 200 || exit 0 echo Booting QEMU virtual machine with $n cpus... QEMU_CMD="qemu-system-${qarch} \ -m ${memory} \ -smp ${n} \ -nographic \ -monitor none \ -netdev user,id=net0,hostfwd=tcp::10022-:22 \ -device ${drivernet},netdev=net0 \ -kernel /qemu/kernel \ -initrd /qemu/initrd.gz \ ${opt} \ -fsdev local,id=fs0,path=/target,security_model=mapped \ -device ${driver9p},fsdev=fs0,mount_tag=target" touch "${LOG}" if [[ -n "${CROSS_DEBUG}" ]]; then (${QEMU_CMD} 2>&1 | tee -a "${LOG}") & else ${QEMU_CMD} >> "${LOG}" 2>&1 & fi # wait for dropbear for _ in $(seq 240); do if grep -q "Not backgrounding" "${LOG}"; then READY=1 break fi sleep 0.5s done if [ -z "${READY}" ]; then if [ -n "${CROSS_DEBUG}" ]; then echo "Not ready but continuing because CROSS_DEBUG is set" else echo "Qemu is not ready after ${SECONDS} seconds..." echo "Set the environment variable CROSS_DEBUG=1 to debug" echo "Last 100 lines of qemu output:" tail -n 100 "${LOG}" exit 1 fi fi echo "Booted in ${SECONDS} seconds" ) 200>"${LOCK}" if [[ -t 1 ]] && [[ -t 2 ]]; then tty_flag='-t' fi exec dbclient ${tty_flag} -p 10022 -y -y root@localhost "${@}" ================================================ FILE: .docker/cross/qemu.sh ================================================ #!/usr/bin/env bash set -x set -euo pipefail # shellcheck disable=SC1091 . lib.sh build_static_libffi () { local version=3.0.13 local td td="$(mktemp -d)" pushd "${td}" curl --retry 3 -sSfL "https://github.com/libffi/libffi/archive/refs/tags/v${version}.tar.gz" -O -L tar --strip-components=1 -xzf "v${version}.tar.gz" ./configure --prefix="$td"/lib --disable-builddir --disable-shared --enable-static make "-j$(nproc)" install -m 644 ./.libs/libffi.a /usr/lib64/ popd rm -rf "${td}" } build_static_libmount () { local version_spec=2.23.2 local version=2.23 local td td="$(mktemp -d)" pushd "${td}" curl --retry 3 -sSfL "https://kernel.org/pub/linux/utils/util-linux/v${version}/util-linux-${version_spec}.tar.xz" -O -L tar --strip-components=1 -xJf "util-linux-${version_spec}.tar.xz" ./configure --disable-shared --enable-static --without-ncurses make "-j$(nproc)" mount blkid install -m 644 ./.libs/*.a /usr/lib64/ popd rm -rf "${td}" } build_static_libattr() { local version=2.4.46 local td td="$(mktemp -d)" pushd "${td}" yum install -y gettext curl --retry 3 -sSfL "https://download.savannah.nongnu.org/releases/attr/attr-${version}.src.tar.gz" -O tar --strip-components=1 -xzf "attr-${version}.src.tar.gz" cp /usr/share/automake*/config.* . ./configure make "-j$(nproc)" install -m 644 ./libattr/.libs/libattr.a /usr/lib64/ yum remove -y gettext popd rm -rf "${td}" } build_static_libcap() { local version=2.22 local td td="$(mktemp -d)" pushd "${td}" curl --retry 3 -sSfL "https://www.kernel.org/pub/linux/libs/security/linux-privs/libcap2/libcap-${version}.tar.xz" -O tar --strip-components=1 -xJf "libcap-${version}.tar.xz" make "-j$(nproc)" install -m 644 libcap/libcap.a /usr/lib64/ popd rm -rf "${td}" } build_static_pixman() { local version=0.34.0 local td td="$(mktemp -d)" pushd "${td}" curl --retry 3 -sSfL "https://www.cairographics.org/releases/pixman-${version}.tar.gz" -O tar --strip-components=1 -xzf "pixman-${version}.tar.gz" ./configure make "-j$(nproc)" install -m 644 ./pixman/.libs/libpixman-1.a /usr/lib64/ popd rm -rf "${td}" } main() { local version=5.1.0 if_centos version=4.2.1 local arch="${1}" \ softmmu="${2:-}" install_packages \ autoconf \ automake \ bison \ bzip2 \ curl \ flex \ libtool \ make \ patch \ python3 \ if_centos install_packages \ gcc-c++ \ pkgconfig \ xz \ glib2-devel \ glib2-static \ glibc-static \ libattr-devel \ libcap-devel \ libfdt-devel \ pcre-static \ pixman-devel \ libselinux-devel \ libselinux-static \ libffi \ libuuid-devel \ libblkid-devel \ libmount-devel \ zlib-devel \ zlib-static if_centos 'curl --retry 3 -sSfL "https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD" -o /usr/share/automake*/config.guess' if_centos 'curl --retry 3 -sSfL "https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD" -o /usr/share/automake*/config.sub' # these are not packaged as static libraries in centos; build them manually if_centos build_static_libffi if_centos build_static_libmount if_centos build_static_libattr if_centos build_static_libcap if_centos build_static_pixman if_ubuntu install_packages \ g++ \ pkg-config \ xz-utils \ libattr1-dev \ libcap-ng-dev \ libffi-dev \ libglib2.0-dev \ libpixman-1-dev \ libselinux1-dev \ zlib1g-dev # if we have python3.6+, we can install qemu 6.1.0, which needs ninja-build # ubuntu 16.04 only provides python3.5, so remove when we have a newer qemu. is_ge_python36=$(python3 -c "import sys; print(int(sys.version_info >= (3, 6)))") if [[ "${is_ge_python36}" == "1" ]]; then if_ubuntu version=6.1.0 if_ubuntu install_packages ninja-build fi local td td="$(mktemp -d)" pushd "${td}" curl --retry 3 -sSfL "https://download.qemu.org/qemu-${version}.tar.xz" -O tar --strip-components=1 -xJf "qemu-${version}.tar.xz" local targets="${arch}-linux-user" local virtfs="" case "${softmmu}" in softmmu) if [ "${arch}" = "ppc64le" ]; then targets="${targets},ppc64-softmmu" else targets="${targets},${arch}-softmmu" fi virtfs="--enable-virtfs" ;; "") true ;; *) echo "Invalid softmmu option: ${softmmu}" exit 1 ;; esac ./configure \ --disable-kvm \ --disable-vnc \ --disable-guest-agent \ --enable-linux-user \ --static \ ${virtfs} \ --target-list="${targets}" make "-j$(nproc)" make install # HACK the binfmt_misc interpreter we'll use expects the QEMU binary to be # in /usr/bin. Create an appropriate symlink ln -s "/usr/local/bin/qemu-${arch}" "/usr/bin/qemu-${arch}-static" purge_packages popd rm -rf "${td}" rm "${0}" } main "${@}" ================================================ FILE: .docker/cross/xargo.sh ================================================ #!/usr/bin/env bash set -x set -euo pipefail # shellcheck disable=SC1091 . lib.sh main() { install_packages ca-certificates curl export RUSTUP_HOME=/tmp/rustup export CARGO_HOME=/tmp/cargo curl --retry 3 -sSfL https://sh.rustup.rs -o rustup-init.sh sh rustup-init.sh -y --no-modify-path --profile minimal rm rustup-init.sh PATH="${CARGO_HOME}/bin:${PATH}" cargo install xargo --root /usr/local rm -r "${RUSTUP_HOME}" "${CARGO_HOME}" purge_packages rm "${0}" } main "${@}" ================================================ FILE: .editorconfig ================================================ root = true [*] charset = utf-8 indent_style = space indent_size = 2 end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true ================================================ FILE: .github/CODEOWNERS ================================================ # Current WG Code Sub Teams: # @tauri-apps/wg-tauri # @tauri-apps/wg-devops # Order is important; the last matching pattern takes the most precedence. * @tauri-apps/wg-tauri .github @tauri-apps/wg-devops ================================================ FILE: .github/CODE_OF_CONDUCT.md ================================================ # Contributor Covenant Code of Conduct ## Our Pledge We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards Examples of behavior that contributes to a positive environment for our community include: - Demonstrating empathy and kindness toward other people - Being respectful of differing opinions, viewpoints, and experiences - Giving and gracefully accepting constructive feedback - Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience - Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: - The use of sexualized language or imagery, and sexual attention or advances of any kind - Trolling, insulting or derogatory comments, and personal or political attacks - Public or private harassment - Publishing others' private information, such as a physical or email address, without their explicit permission - Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [contact@tauri.app](mailto:contact@tauri.app). All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. ## Enforcement Guidelines Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: ### 1. Correction **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. ### 2. Warning **Community Impact**: A violation through a single incident or series of actions. **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. ### 3. Temporary Ban **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within the community. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at [https://www.contributor-covenant.org/translations][translations]. [homepage]: https://www.contributor-covenant.org [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html [Mozilla CoC]: https://github.com/mozilla/diversity [FAQ]: https://www.contributor-covenant.org/faq [translations]: https://www.contributor-covenant.org/translations ================================================ FILE: .github/CONTRIBUTING.md ================================================ # Tauri Contributing Guide Hi! We, the maintainers, are really excited that you are interested in contributing to Tauri. Before submitting your contribution though, please make sure to take a moment and read through the [Code of Conduct](CODE_OF_CONDUCT.md), as well as the appropriate section for the contribution you intend to make: - [Issue Reporting Guidelines](#issue-reporting-guidelines) - [Pull Request Guidelines](#pull-request-guidelines) - [Development Guide](#development-guide) - [AI Tool Policy](#ai-tool-policy) ## Issue Reporting Guidelines - The issue list of this repo is **exclusively** for bug reports and feature requests. Non-conforming issues will be closed immediately. - If you have a question, you can get quick answers from the [Tauri Discord chat](https://discord.gg/SpmNs4S). - Try to search for your issue, it may have already been answered or even fixed in the development branch (`dev`). - Check if the issue is reproducible with the latest stable version of Tauri. If you are using a pre-release, please indicate the specific version you are using. - It is **required** that you clearly describe the steps necessary to reproduce the issue you are running into. Although we would love to help our users as much as possible, diagnosing issues without clear reproduction steps is extremely time-consuming and simply not sustainable. - Use only the minimum amount of code necessary to reproduce the unexpected behavior. A good bug report should isolate specific methods that exhibit unexpected behavior and precisely define how expectations were violated. What did you expect the method or methods to do, and how did the observed behavior differ? The more precisely you isolate the issue, the faster we can investigate. - 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. - 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. ## Pull Request Guidelines - You have to [sign your commits](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits). - It's OK to have multiple small commits as you work on the PR - we will let GitHub automatically squash it before merging. - If adding new feature: - Provide convincing reason to add this feature. Ideally you should open a suggestion issue first and have it greenlighted before working on it. - If fixing a bug: - If you are resolving a special issue, add `(fix: #xxxx[,#xxx])` (#xxxx is the issue id) in your PR title for a better release log, e.g. `fix: update entities encoding/decoding (fix #3899)`. - Provide detailed description of the bug in the PR, or link to an issue that does. - If the PR is meant to be released, follow the instructions in `.changes/readme.md` to log your changes. ie. [readme.md](https://github.com/tauri-apps/tauri/blob/dev/.changes/README.md) ## Development Guide **NOTE: If you have any question don't hesitate to ask in our Discord server. We try to keep this guide to up guide, but if something doesn't work let us know.** ### General Setup First, [join our Discord server](https://discord.gg/SpmNs4S) and let us know that you want to contribute. This way we can point you in the right direction and help ensure your contribution will be as helpful as possible. To set up your machine for development, follow the [Tauri setup guide](https://v2.tauri.app/start/prerequisites/) to get all the tools you need to develop Tauri apps. The only additional tool you may need is [PNPM](https://pnpm.io/), it is only required if you are developing the Node CLI or API packages (`packages/cli` and `packages/api`). Next, [fork](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo) and clone [this repository](https://github.com/tauri-apps). The development process varies depending on what part of Tauri you are contributing to, see the guides below for per-package instructions. Some Tauri packages will be automatically built when running one of the examples. Others, however, will need to be built beforehand. To initialize, execute these commands in the repository root: ```bash pnpm install pnpm build ``` ### Overview See [Architecture](../ARCHITECTURE.md#major-components) for an overview of the packages in this repository. ### Developing Tauri Core and Related Components (Rust API, Macros, Codegen, and Utils) The code for the Rust crates, including the Core, Macros, Utils, WRY runtime, and a few more are located in the [main Tauri repository](https://github.com/tauri-apps/tauri/tree/dev/crates). The easiest way to test your changes is to use the [helloworld](https://github.com/tauri-apps/tauri/tree/dev/examples/helloworld) example app. It automatically rebuilds and uses your local copy of the Tauri core packages. Just run `cargo run --example helloworld` after making changes to test them out. To test local changes against your own application simply point the Tauri create to your local repository. In `src-tauri/Cargo.toml` file change: `tauri = { version = "2.1.1" }` to: `tauri = { path = "path/to/local/tauri/crates/tauri" }` If any other crates depend on Tauri you will have to point them to the local repo as well. ### Developing Tauri Bundler and Rust CLI The code for the bundler is located in [crates/tauri-bundler](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri-bundler), and the code for the Rust CLI is located in [tauri-cli](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri-cli). Running `cargo install --path .` in the Rust CLI directory will allow you to run `cargo tauri build` and `cargo tauri dev` anywhere, using the updated copy of the bundler and cli. You will have to run this command each time you make a change in either package. You can use `cargo install --path . --debug` to speed up test builds. ### Developing The Node.js CLI (`@tauri-apps/cli`) [`@tauri-apps/cli`](https://github.com/tauri-apps/tauri/tree/dev/packages/cli) is a small wrapper around `tauri-cli` so most changes should be happen in the Rust CLI (see above). #### Building the documentation locally You can build the Rust documentation locally running the following script: ```bash $ cargo +nightly doc --all-features --open ``` ### Developing the JS API The JS API provides bindings between the developer's JS in the Webview and the built-in Tauri APIs, written in Rust. Its code is located in [/packages/api](https://github.com/tauri-apps/tauri/tree/dev/packages/api). After making changes to the code, run `pnpm build` to build it. To test your changes, we recommend using the API example app, located in [/examples/api](https://github.com/tauri-apps/tauri/tree/dev/examples/api). It will automatically use your local copy of the JS API and provides a helpful UI to test the various commands. ## AI Tool Policy It takes a lot of time to review a Pull Request while it's very easy to make a nonsensical but plausible looking one using AI tools. It is unfair for other contributors and the reviewers to spend much of the time dealing with this, hence these rules: 1. Review and test all LLM-generated content before submitting, you're the one responsible for it, not the AI. 2. Don't use AI to respond to review comments (except for translations). We will close the Pull Request with a `ai-slop` tag if you failed to do so. ## Financial Contribution Tauri is an MIT-licensed open source project. Its ongoing development can be supported via [GitHub Sponsors](https://github.com/sponsors/tauri-apps) or [Open Collective](https://opencollective.com/tauri). We prefer GitHub Sponsors as donations made are doubled through the matching fund program. ================================================ FILE: .github/FUNDING.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT # These are supported funding model platforms github: tauri-apps patreon: # open_collective: tauri ko_fi: # Replace with a single Ko-fi username tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel custom: # Replace with a single custom sponsorship URL ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: 🐞 Bug Report title: '[bug] ' description: Report a bug labels: ['type: bug', 'status: needs triage'] body: - type: markdown attributes: value: | ## First of all 1. Please search for [existing issues](https://github.com/tauri-apps/tauri/issues?q=is%3Aissue) about this problem first. 2. Make sure `rustc` and all relevant Tauri packages are up to date. 3. Make sure it's an issue with Tauri and not something else you are using. 4. Remember to follow our community guidelines and be friendly. - type: textarea id: description attributes: label: Describe the bug description: A clear description of what the bug is. Include screenshots if applicable. placeholder: Bug description validations: required: true - type: textarea id: reproduction attributes: label: Reproduction description: A link to a reproduction repo or steps to reproduce the behaviour. placeholder: | Please provide a minimal reproduction or steps to reproduce, see this guide https://stackoverflow.com/help/minimal-reproducible-example Why reproduction is required? see this article https://antfu.me/posts/why-reproductions-are-required - type: textarea id: expected-behavior attributes: label: Expected behavior description: A clear description of what you expected to happen. - type: textarea id: info attributes: label: Full `tauri info` output description: 'Output of `npm run tauri info` or `cargo tauri info`' render: text validations: required: true - type: textarea id: logs attributes: label: Stack trace render: text - type: textarea id: context attributes: label: Additional context description: Add any other context about the problem here. ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT contact_links: - name: 💬 Discord Chat url: https://discord.com/invite/tauri about: Ask questions and talk to other Tauri users and the maintainers ================================================ FILE: .github/ISSUE_TEMPLATE/docs_report.md ================================================ --- name: 📚 Docs Report about: Create a report to help us improve the docs title: '[docs] ' labels: 'type: documentation' assignees: '' --- ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: 💡 Feature Request title: '[feat] ' description: Suggest an idea labels: ['type: feature request'] body: - type: textarea id: problem attributes: label: Describe the problem description: A clear description of the problem this feature would solve placeholder: "I'm always frustrated when..." validations: required: true - type: textarea id: solution attributes: label: "Describe the solution you'd like" description: A clear description of what change you would like placeholder: 'I would like to...' validations: required: true - type: textarea id: alternatives attributes: label: Alternatives considered description: "Any alternative solutions you've considered" - type: textarea id: context attributes: label: Additional context description: Add any other context about the problem here. ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ ================================================ FILE: .github/RELEASING.md ================================================ # Tauri Releasing Handbook This handbook contains information about our release pipeline and how to deal with common issues. This document is mainly intended for team members responsible for maintaining the project. - [Covector](#covector) - [Version Pull Request](#version-pull-request) - [Releasing and Publishing](#releasing-and-publishing) - [Publishing failed, what to do?](#publishing-failed-what-to-do) ## Covector We use [`covector`](https://github.com/jbolda/covector) to manage our version bumps and release pipeline. It can be configured in [`.changes/config.json`](../.changes/config.json) which includes how each package should be published step by step. Some packages can't be published directly using `covector` as it requires to be built on a matrix of platforms such as `tauri-cli` prebuilt binaries which is published using [publish-cli-rs.yml](./workflows/publish-cli-rs.yml) and `@tauri-apps/cli` native Node.js modules which is published using using [publish-cli-js.yml](./workflows/publish-cli-js.yml) both of which are triggered after `covector` has created a github release for both of them, see `Trigger @tauri-apps/cli publishing workflow` and `Trigger tauri-cli publishing workflow` steps in [covector-version-or-publish.yml](./workflows/covector-version-or-publish.yml) ## Version Pull Request On each pull request merged, [covector-version-or-publish.yml](./workflows/covector-version-or-publish.yml) workflow will run, and: When there're change files inside `.changes` folder and they're not all included in `pre.json` (usually this is only when we are in `-alpha` to `-rc` phase), it will open/update an `Apply Version Updates From Current Changes` PR (https://github.com/tauri-apps/tauri/pull/11029 for example) that bumps all packages based on current existing change files and generate `CHANGELOG.md` entries. see `Create Pull Request With Versions Bumped` step in [covector-version-or-publish.yml](./workflows/covector-version-or-publish.yml). Otherwise, covector will start to publish packages configured in [`.changes/config.json`](../.changes/config.json). ## Releasing and Publishing Releasing can be as easy as merging the version pull request but here is a checklist to follow: - [ ] Double check that every package is bumped correctly and there are no accidental major or minor being released unless that is indeed the intention. - [ ] Make sure that there are no pending or unfinished [covector-version-or-publish.yml](./workflows/covector-version-or-publish.yml) workflow runs. - [ ] Approve and merge the version pull request ## Publishing failed, what to do? It is possible and due to many factors that one or many packages release can fail to release, there is no reason to panic, we can fix this. Did all of the packages fail to release? - yes? - [ ] `git checkout -b revert-branch` - [ ] `git revert HEAD~1` - no? - [ ] `git checkout -b revert-branch` - [ ] `git revert HEAD~1 --no-commit` - [ ] Edit the commit and revert only changes related to packages that failed to publish - [ ] `git revert --continue` Then: - [ ] Make a pull request with reverted changes, get it approved and merged - [ ] Fix the issue that caused releases to fail in another PR, get it approved and merged - [ ] Repeat the release process again. ================================================ FILE: .github/workflows/audit.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: Audit on: workflow_dispatch: schedule: - cron: '0 0 * * *' pull_request: paths: - '.github/workflows/audit.yml' - '**/Cargo.lock' - '**/Cargo.toml' - '**/package.json' - '**/pnpm-lock.yaml' push: branches: - dev paths: - '.github/workflows/audit.yml' - '**/Cargo.lock' - '**/Cargo.toml' - '**/package.json' - '**/pnpm-lock.yaml' concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: audit-rust: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: rust audit uses: rustsec/audit-check@v2 with: token: ${{ secrets.GITHUB_TOKEN }} audit-js: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm i -g --force corepack - uses: actions/setup-node@v4 with: node-version: 'lts/*' - run: pnpm audit ================================================ FILE: .github/workflows/bench.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: bench on: push: branches: - dev workflow_dispatch: pull_request: paths: - '.github/workflows/bench.yml' - 'bench/**' env: RUST_BACKTRACE: 1 CARGO_PROFILE_DEV_DEBUG: 0 # This would add unnecessary bloat to the target folder, decreasing cache efficiency. LC_ALL: en_US.UTF-8 # This prevents strace from changing its number format to use commas. concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: bench: strategy: fail-fast: false matrix: rust: [nightly] platform: - { target: x86_64-unknown-linux-gnu, os: ubuntu-latest } runs-on: ${{ matrix.platform.os }} steps: - uses: actions/checkout@v4 - name: install Rust ${{ matrix.rust }} uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} components: rust-src targets: ${{ matrix.platform.target }} - name: setup python uses: actions/setup-python@v5 with: python-version: '3.10' architecture: x64 - name: install dependencies run: | python -m pip install --upgrade pip sudo apt-get update sudo apt-get install -y --no-install-recommends \ webkit2gtk-4.1 libayatana-appindicator3-dev \ xvfb \ at-spi2-core wget https://github.com/sharkdp/hyperfine/releases/download/v1.18.0/hyperfine_1.18.0_amd64.deb sudo dpkg -i hyperfine_1.18.0_amd64.deb pip install memory_profiler - uses: Swatinem/rust-cache@v2 - name: run benchmarks run: | cargo build --manifest-path bench/tests/cpu_intensive/src-tauri/Cargo.toml --release -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort --target ${{ matrix.platform.target }} cargo build --manifest-path bench/tests/files_transfer/src-tauri/Cargo.toml --release -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort --target ${{ matrix.platform.target }} cargo build --manifest-path bench/tests/helloworld/src-tauri/Cargo.toml --release -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort --target ${{ matrix.platform.target }} xvfb-run --auto-servernum cargo run --manifest-path bench/Cargo.toml --bin run_benchmark - name: clone benchmarks_results if: github.repository == 'tauri-apps/tauri' && github.ref == 'refs/heads/dev' uses: actions/checkout@v4 with: token: ${{ secrets.BENCH_PAT }} path: gh-pages repository: tauri-apps/benchmark_results - name: push new benchmarks if: github.repository == 'tauri-apps/tauri' && github.ref == 'refs/heads/dev' run: | cargo run --manifest-path bench/Cargo.toml --bin build_benchmark_jsons cd gh-pages git pull git config user.name "tauri-bench" git config user.email "gh.tauribot@gmail.com" git add . git commit --message "Update Tauri benchmarks" git push origin gh-pages - name: Print worker info run: | cat /proc/cpuinfo cat /proc/meminfo ================================================ FILE: .github/workflows/check-change-tags.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: check change tags on: pull_request: paths: - '.changes/*.md' concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: check change files end with .md run: | for file in .changes/* do if [[ ! "$file" =~ \.(md|json)$ ]]; then echo ".changes directory should only contain files that end with .md" echo "found an invalid file in .changes directory:" echo "$file" exit 1 fi done - uses: dorny/paths-filter@v3 id: filter with: list-files: shell filters: | changes: - added|modified: '.changes/*.md' - name: check run: node ./.scripts/ci/check-change-tags.js ${{ steps.filter.outputs.changes_files }} if: ${{ steps.filter.outputs.changes == 'true' }} ================================================ FILE: .github/workflows/check-generated-files.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: check generated files on: pull_request: paths: - '.github/workflows/check-generated-files.yml' - 'pnpm-lock.yaml' - 'packages/api/src/**' - 'crates/tauri/scripts/bundle.global.js' - 'crates/tauri-utils/src/config.rs' - 'crates/tauri-cli/config.schema.json' - 'crates/tauri-schema-generator/schemas/*.json' concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: changes: runs-on: ubuntu-latest outputs: api: ${{ steps.filter.outputs.api }} schema: ${{ steps.filter.outputs.schema }} steps: - uses: actions/checkout@v4 - uses: dorny/paths-filter@v3 id: filter with: filters: | api: - 'pnpm-lock.yaml' - 'packages/api/src/**' - 'crates/tauri/scripts/bundle.global.js' schema: - 'crates/tauri-utils/src/config.rs' - 'crates/tauri-cli/config.schema.json' - 'crates/tauri-schema-generator/schemas/*.json' api: runs-on: ubuntu-latest needs: changes if: needs.changes.outputs.api == 'true' steps: - uses: actions/checkout@v4 - run: npm i -g --force corepack - uses: actions/setup-node@v4 with: node-version: 'lts/*' cache: 'pnpm' - name: install deps run: pnpm i --frozen-lockfile - name: build api run: pnpm build working-directory: packages/api - name: check api run: ./.scripts/ci/has-diff.sh schema: runs-on: ubuntu-latest needs: changes if: needs.changes.outputs.schema == 'true' steps: - uses: actions/checkout@v4 - name: install stable uses: dtolnay/rust-toolchain@stable - name: install Linux dependencies run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev - uses: Swatinem/rust-cache@v2 - name: generate schemas run: cargo build --manifest-path ./crates/tauri-schema-generator/Cargo.toml - name: check schemas run: ./.scripts/ci/has-diff.sh ================================================ FILE: .github/workflows/check-license-header.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: check license headers on: pull_request: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: dorny/paths-filter@v3 id: filter with: list-files: shell filters: | added: - added: '**' - name: check header license on new files if: ${{ steps.filter.outputs.added == 'true' }} run: node ./.scripts/ci/check-license-header.js ${{ steps.filter.outputs.added_files }} ================================================ FILE: .github/workflows/covector-comment-on-fork.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: covector comment on: workflow_run: workflows: [covector status] # the `name` of the workflow run on `pull_request` running `status` with `comment: true` types: - completed # note all other permissions are set to none if not specified # and these set the permissions for `secrets.GITHUB_TOKEN` permissions: # to read the action artifacts on `covector status` workflows actions: read # to write the comment pull-requests: write jobs: comment: runs-on: ubuntu-latest if: github.event.workflow_run.conclusion == 'success' && (github.event.workflow_run.head_repository.full_name != github.repository || github.actor == 'dependabot[bot]') steps: - name: covector status uses: jbolda/covector/packages/action@covector-v0 with: token: ${{ secrets.GITHUB_TOKEN }} command: 'status' ================================================ FILE: .github/workflows/covector-status.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: covector status on: [pull_request] jobs: covector: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: covector status uses: jbolda/covector/packages/action@covector-v0 id: covector with: command: 'status' token: ${{ secrets.GITHUB_TOKEN }} comment: true ================================================ FILE: .github/workflows/covector-version-or-publish.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: covector version or publish on: push: branches: - dev jobs: run-integration-tests: runs-on: ${{ matrix.platform }} strategy: fail-fast: false matrix: platform: [ubuntu-latest, macos-latest, windows-latest] steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - run: npm i -g --force corepack - uses: actions/setup-node@v4 with: node-version: 20 cache: 'pnpm' - name: install stable uses: dtolnay/rust-toolchain@stable - name: install Linux dependencies if: matrix.platform == 'ubuntu-latest' run: | sudo apt-get update sudo apt-get install -y webkit2gtk-4.1 libayatana-appindicator3-dev libfuse2 librsvg2-dev - uses: Swatinem/rust-cache@v2 - name: build CLI run: cargo build --manifest-path ./crates/tauri-cli/Cargo.toml - name: run integration tests run: cargo test --test '*' -- --ignored - name: run CLI tests timeout-minutes: 30 run: | cd ./packages/cli pnpm i --frozen-lockfile pnpm build pnpm test version-or-publish: runs-on: ubuntu-latest timeout-minutes: 65 permissions: actions: write # required for workflow_dispatch contents: write # required to create new releases pull-requests: write # required to open version update pr id-token: write # pnpm provenance / oidc token outputs: change: ${{ steps.covector.outputs.change }} commandRan: ${{ steps.covector.outputs.commandRan }} successfulPublish: ${{ steps.covector.outputs.successfulPublish }} needs: - run-integration-tests steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - run: npm i -g --force corepack - uses: actions/setup-node@v6 with: node-version: 24 - name: cargo login run: cargo login ${{ secrets.ORG_CRATES_IO_TOKEN }} - name: git config run: | git config --global user.name "${{ github.event.pusher.name }}" git config --global user.email "${{ github.event.pusher.email }}" - name: install Linux dependencies run: | sudo apt-get update sudo apt-get install -y webkit2gtk-4.1 libayatana-appindicator3-dev librsvg2-dev - name: covector version or publish (publish when no change files present) uses: jbolda/covector/packages/action@covector-v0 id: covector env: CARGO_AUDIT_OPTIONS: ${{ secrets.CARGO_AUDIT_OPTIONS }} NPM_CONFIG_PROVENANCE: true with: command: 'version-or-publish' token: ${{ secrets.GITHUB_TOKEN }} createRelease: true recognizeContributors: true - name: Sync Cargo.lock if: steps.covector.outputs.commandRan == 'version' run: cargo tree --depth 0 - name: Create Pull Request With Versions Bumped if: steps.covector.outputs.commandRan == 'version' uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # 7.0.6 with: token: ${{ secrets.GITHUB_TOKEN }} branch: release/version-updates title: Apply Version Updates From Current Changes commit-message: 'apply version updates' labels: 'version updates' body: ${{ steps.covector.outputs.change }} sign-commits: true - name: Trigger doc update if: | steps.covector.outputs.successfulPublish == 'true' && steps.covector.outputs.packagesPublished != '' uses: peter-evans/repository-dispatch@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0 # 3.0.0 with: token: ${{ secrets.ORG_TAURI_BOT_PAT }} repository: tauri-apps/tauri-docs event-type: update-docs - name: Trigger `@tauri-apps/cli` publishing workflow if: | steps.covector.outputs.successfulPublish == 'true' && contains(steps.covector.outputs.packagesPublished, '@tauri-apps/cli') run: gh workflow run 31554138 -r dev -f releaseId=${{ steps.covector.outputs['-tauri-apps-cli-releaseId'] }} env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Trigger `tauri-cli` publishing workflow if: | steps.covector.outputs.successfulPublish == 'true' && contains(steps.covector.outputs.packagesPublished, 'tauri-cli') run: gh workflow run 31554139 -r dev env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} ================================================ FILE: .github/workflows/deploy-schema-worker.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: deploy schema worker on: push: branches: - dev paths: - '.github/workflows/deploy-schema-worker.yml' - 'crates/tauri-schema-worker/**' jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: cloudflare/wrangler-action@v3 with: command: deploy workingDirectory: 'crates/tauri-schema-worker' apiToken: ${{ secrets.SCHEMA_WORKER_CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.SCHEMA_WORKER_CLOUDFLARE_ACCOUNT_ID }} ================================================ FILE: .github/workflows/docker.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: docker on: workflow_dispatch: #pull_request: # paths: # - '.docker/**' # - '.github/workflows/docker.yml' jobs: setup: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: install stable uses: dtolnay/rust-toolchain@stable - name: install Linux dependencies run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev - name: install cross run: cargo install cross --git https://github.com/cross-rs/cross - name: Upload cross uses: actions/upload-artifact@v4 with: name: cross path: '~/.cargo/bin/cross' if-no-files-found: error - name: build CLI run: cargo build --manifest-path ./crates/tauri-cli/Cargo.toml - name: Upload CLI uses: actions/upload-artifact@v4 with: name: cargo-tauri path: crates/tauri-cli/target/debug/cargo-tauri if-no-files-found: error docker: needs: setup runs-on: ubuntu-latest strategy: fail-fast: false matrix: target: - { name: 'aarch64-unknown-linux-gnu', filename: 'aarch64' } steps: - name: Checkout uses: actions/checkout@v4 - name: install stable uses: dtolnay/rust-toolchain@stable with: targets: ${{ matrix.target.name }} - run: npm i -g --force corepack - name: Setup node uses: actions/setup-node@v4 with: node-version: 'lts/*' - name: Download cross uses: actions/download-artifact@v4.1.7 with: name: cross path: '~/.cargo/bin' - name: Download CLI uses: actions/download-artifact@v4.1.7 with: name: cargo-tauri path: 'examples/api' - name: Set up QEMU uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Login to GitHub Container Registry uses: docker/login-action@v2 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and export to Docker uses: docker/build-push-action@v3 with: context: .docker/cross file: .docker/cross/${{ matrix.target.filename }}.Dockerfile load: true tags: ${{ matrix.target.name }}:latest - name: install dependencies run: | sudo apt-get update sudo apt-get install -y webkit2gtk-4.1 libayatana-appindicator3-dev - name: Test run: | cd packages/api pnpm i --frozen-lockfile && pnpm build cd ../../examples/api pnpm i --frozen-lockfile . .setup-cross.sh chmod +x cargo-tauri chmod +x $HOME/.cargo/bin/cross ./cargo-tauri build --runner cross --bundles deb --target ${{ matrix.target.name }} --verbose - name: Build and push uses: docker/build-push-action@v3 with: context: .docker/cross file: .docker/cross/${{ matrix.target.filename }}.Dockerfile push: true tags: ghcr.io/${{ github.repository }}/${{ matrix.target.name }}:latest ================================================ FILE: .github/workflows/fmt.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: check formatting on: pull_request: jobs: rustfmt: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: install Rust stable and rustfmt uses: dtolnay/rust-toolchain@stable with: components: rustfmt - name: run cargo fmt run: cargo fmt --all -- --check prettier: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm i -g --force corepack - uses: actions/setup-node@v4 with: node-version: 'lts/*' cache: 'pnpm' - run: pnpm i --frozen-lockfile - run: pnpm format:check taplo: name: taplo (.toml files) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: install Rust stable uses: dtolnay/rust-toolchain@stable - name: install taplo-cli uses: taiki-e/install-action@v2 with: tool: taplo-cli - run: taplo fmt --check --diff ================================================ FILE: .github/workflows/lint-js.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: lint js on: pull_request: paths: - '.github/workflows/lint-js.yml' - 'packages/**' concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: eslint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm i -g --force corepack - uses: actions/setup-node@v4 with: node-version: 'lts/*' cache: 'pnpm' - run: pnpm i --frozen-lockfile - run: pnpm eslint:check typescript: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm i -g --force corepack - uses: actions/setup-node@v4 with: node-version: 'lts/*' cache: 'pnpm' - run: pnpm i --frozen-lockfile - run: pnpm ts:check ================================================ FILE: .github/workflows/lint-rust.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: lint rust on: push: branches: - dev pull_request: paths: - '.github/workflows/lint-rust.yml' - 'crates/**' env: RUST_BACKTRACE: 1 CARGO_PROFILE_DEV_DEBUG: 0 # This would add unnecessary bloat to the target folder, decreasing cache efficiency. concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: clippy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: install rust stable and clippy uses: dtolnay/rust-toolchain@stable with: components: clippy - name: install dependencies run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev webkit2gtk-4.1 libayatana-appindicator3-dev - uses: Swatinem/rust-cache@v2 - run: cargo clippy --all-targets --all-features -- -D warnings ================================================ FILE: .github/workflows/publish-cli-js.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: publish `@tauri-apps/cli` env: DEBUG: napi:* APP_NAME: cli MACOSX_DEPLOYMENT_TARGET: '10.13' on: workflow_dispatch: inputs: releaseId: description: 'ID of the `@tauri-apps/cli` release' required: true repository_dispatch: types: [publish-js-cli] defaults: run: working-directory: packages/cli/ permissions: contents: write # update release id-token: write # oidc token jobs: build: strategy: fail-fast: false matrix: settings: - host: macos-latest target: x86_64-apple-darwin architecture: x64 build: | pnpm build --target=x86_64-apple-darwin strip -x *.node - host: windows-latest build: pnpm build target: x86_64-pc-windows-msvc architecture: x64 - host: windows-latest build: pnpm build --target i686-pc-windows-msvc target: i686-pc-windows-msvc architecture: x64 - host: windows-latest architecture: x64 target: aarch64-pc-windows-msvc build: pnpm build --target aarch64-pc-windows-msvc - host: ubuntu-22.04 target: x86_64-unknown-linux-gnu docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian build: | npm i -g --force corepack cd packages/cli pnpm build --target x86_64-unknown-linux-gnu strip *.node - host: ubuntu-22.04 target: x86_64-unknown-linux-musl docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine build: | cd packages/cli pnpm build strip *.node - host: macos-latest target: aarch64-apple-darwin build: | pnpm build --features native-tls-vendored --target=aarch64-apple-darwin strip -x *.node - host: ubuntu-22.04 target: aarch64-unknown-linux-gnu docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian-aarch64 build: | npm i -g --force corepack cd packages/cli pnpm build --target aarch64-unknown-linux-gnu aarch64-unknown-linux-gnu-strip *.node - host: ubuntu-22.04 architecture: x64 target: armv7-unknown-linux-gnueabihf setup: | sudo apt-get update sudo apt-get install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf -y build: | pnpm build --target=armv7-unknown-linux-gnueabihf arm-linux-gnueabihf-strip *.node - host: ubuntu-22.04 architecture: x64 target: aarch64-unknown-linux-musl docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine build: | cd packages/cli rustup target add aarch64-unknown-linux-musl pnpm build --target aarch64-unknown-linux-musl /aarch64-linux-musl-cross/bin/aarch64-linux-musl-strip *.node - host: ubuntu-22.04 architecture: x64 target: riscv64gc-unknown-linux-gnu setup: | sudo apt-get update sudo apt-get install gcc-riscv64-linux-gnu g++-riscv64-linux-gnu -y build: | pnpm build --target=riscv64gc-unknown-linux-gnu riscv64-linux-gnu-strip *.node name: stable - ${{ matrix.settings.target }} - node@20 runs-on: ${{ matrix.settings.host }} steps: - uses: actions/checkout@v4 - run: npm i -g --force corepack - name: Setup node uses: actions/setup-node@v4 if: ${{ !matrix.settings.docker }} with: node-version: 20 cache: 'pnpm' architecture: ${{ matrix.settings.architecture }} - name: Install Rust uses: dtolnay/rust-toolchain@stable if: ${{ !matrix.settings.docker }} with: targets: ${{ matrix.settings.target }} - uses: Swatinem/rust-cache@v2 with: key: ${{ matrix.settings.target }} if: ${{ matrix.settings.docker }} - name: Setup toolchain run: ${{ matrix.settings.setup }} if: ${{ matrix.settings.setup }} shell: bash - name: Install dependencies run: pnpm i --frozen-lockfile --ignore-scripts - name: Build in docker uses: addnab/docker-run-action@v3 if: ${{ matrix.settings.docker }} with: image: ${{ matrix.settings.docker }} options: --user 0:0 -v ${{ github.workspace }}/.cargo-cache/git/db:/root/.cargo/git/db -v ${{ github.workspace }}/.cargo/registry/cache:/root/.cargo/registry/cache -v ${{ github.workspace }}/.cargo/registry/index:/root/.cargo/registry/index -v ${{ github.workspace }}:/build -w /build run: ${{ matrix.settings.build }} - name: Build run: ${{ matrix.settings.build }} if: ${{ !matrix.settings.docker }} shell: bash - name: Upload artifact uses: actions/upload-artifact@v4 with: name: bindings-${{ matrix.settings.target }} path: packages/cli/${{ env.APP_NAME }}.*.node if-no-files-found: error # build-freebsd: # runs-on: macos-10.15 # name: Build FreeBSD # steps: # - uses: actions/checkout@v4 # - name: Build # id: build # uses: vmactions/freebsd-vm@v0.1.6 # env: # DEBUG: napi:* # RUSTUP_HOME: /usr/local/rustup # CARGO_HOME: /usr/local/cargo # RUSTUP_IO_THREADS: 1 # with: # envs: DEBUG RUSTUP_HOME CARGO_HOME RUSTUP_IO_THREADS # usesh: true # mem: 3000 # prepare: | # pkg install -y curl node14 python2 # curl -qL https://www.npmjs.com/install.sh | sh # npm install -g pnpm # curl https://sh.rustup.rs -sSf --output rustup.sh # sh rustup.sh -y --profile minimal --default-toolchain stable # export PATH="/usr/local/cargo/bin:$PATH" # echo "~~~~ rustc --version ~~~~" # rustc --version # echo "~~~~ node -v ~~~~" # node -v # echo "~~~~ pnpm --version ~~~~" # pnpm --version # run: | # export PATH="/usr/local/cargo/bin:$PATH" # pwd # ls -lah # whoami # env # freebsd-version # cd ./packages/cli/ # pnpm i --frozen-lockfile --ignore-scripts # pnpm build # strip -x *.node # rm -rf node_modules # rm -rf ../../target # - name: Upload artifact # uses: actions/upload-artifact@v4 # with: # name: bindings-freebsd # path: packages/cli/${{ env.APP_NAME }}.*.node # if-no-files-found: error test-macOS-windows-binding: name: Test bindings on ${{ matrix.settings.target }} - node@${{ matrix.node }} needs: - build strategy: fail-fast: false matrix: settings: - host: macos-latest target: aarch64-apple-darwin - host: windows-latest target: x86_64-pc-windows-msvc node: - '18' - '20' runs-on: ${{ matrix.settings.host }} steps: - uses: actions/checkout@v4 - run: npm i -g --force corepack - name: Setup node uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} cache: 'pnpm' - name: Install dependencies run: pnpm i --frozen-lockfile --ignore-scripts - name: Download artifacts uses: actions/download-artifact@v4.1.7 with: name: bindings-${{ matrix.settings.target }} path: 'packages/cli/' - name: List packages run: ls -R . shell: bash - name: Test bindings run: pnpm test test-linux-x64-gnu-binding: name: Test bindings on Linux-x64-gnu - node@${{ matrix.node }} needs: - build strategy: fail-fast: false matrix: node: - '18' - '20' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm i -g --force corepack - name: Setup node uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} cache: 'pnpm' - name: Install dependencies run: pnpm i --frozen-lockfile --ignore-scripts - name: Download artifacts uses: actions/download-artifact@v4.1.7 with: name: bindings-x86_64-unknown-linux-gnu path: 'packages/cli' - name: List packages run: ls -R . shell: bash - name: install system dependencies run: | sudo apt-get update sudo apt-get install -y webkit2gtk-4.1 libayatana-appindicator3-dev librsvg2-dev - name: Test bindings run: pnpm test test-linux-x64-musl-binding: name: Test bindings on x86_64-unknown-linux-musl - node@${{ matrix.node }} needs: - build strategy: fail-fast: false matrix: node: - '18' - '20' runs-on: ubuntu-latest container: image: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine steps: - uses: actions/checkout@v4 - run: npm i -g --force corepack - name: Setup node uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} cache: 'pnpm' - name: Install dependencies run: pnpm i --frozen-lockfile --ignore-scripts - name: Download artifacts uses: actions/download-artifact@v4.1.7 with: name: bindings-x86_64-unknown-linux-musl path: 'packages/cli/' - name: List packages run: ls -R . shell: bash - name: Setup and run tests run: | pnpm tauri --help ls -la #- name: Setup and run tests # run: | # rustup install stable # rustup default stable # pnpm test # ls -la test-linux-arm-bindings: name: Test bindings on ${{ matrix.image }} - node@${{ matrix.node }} needs: - build strategy: fail-fast: false matrix: node: - '18' - '20' image: - ghcr.io/napi-rs/napi-rs/nodejs:aarch64-16 runs-on: ubuntu-latest steps: - run: docker run --rm --privileged multiarch/qemu-user-static:register --reset working-directory: ${{ github.workspace }} - uses: actions/checkout@v4 - name: List packages run: ls -R . shell: bash - name: Download aarch64-gnu artifacts uses: actions/download-artifact@v4.1.7 with: name: bindings-aarch64-unknown-linux-gnu path: 'packages/cli' - name: Download armv7-gnueabihf artifacts uses: actions/download-artifact@v4.1.7 with: name: bindings-armv7-unknown-linux-gnueabihf path: 'packages/cli/' # TODO: actually run test, blocked by https://github.com/rust-lang/cargo/issues/8719 - uses: addnab/docker-run-action@v3 with: image: ${{ matrix.image }} options: '-v ${{ github.workspace }}:/build -w /build -e RUSTUP_HOME=/usr/local/rustup -e CARGO_HOME=/usr/local/cargo' shell: bash run: | set -e export PATH=/usr/local/cargo/bin/:/usr/local/fnm:$PATH apt-get update DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install --no-install-recommends -y unzip libayatana-appindicator3-dev bash curl https://sh.rustup.rs -sSf | bash -s -- -y curl -fsSL https://fnm.vercel.app/install | bash -s -- --install-dir "/usr/local/fnm" --skip-shell eval "$(fnm env --use-on-cd)" fnm install ${{ matrix.node }} fnm use ${{ matrix.node }} cd packages/cli node tauri.js --help ls -la publish: name: Publish runs-on: ubuntu-latest needs: #- build-freebsd - test-macOS-windows-binding - test-linux-x64-gnu-binding - test-linux-x64-musl-binding #- test-linux-arm-bindings steps: - uses: actions/checkout@v4 - run: npm i -g --force corepack - name: Setup node uses: actions/setup-node@v6 with: node-version: 24 cache: 'pnpm' - name: Install dependencies run: pnpm i --frozen-lockfile --ignore-scripts - name: Download all artifacts uses: actions/download-artifact@v4.1.7 with: path: packages/cli/artifacts - name: Move artifacts run: pnpm artifacts - name: List packages run: ls -R ./npm shell: bash - name: Publish run: | npm publish env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NODE_AUTH_TOKEN: '' RELEASE_ID: ${{ github.event.client_payload.releaseId || inputs.releaseId }} ================================================ FILE: .github/workflows/publish-cli-rs.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: publish `tauri-cli` env: MACOSX_DEPLOYMENT_TARGET: '10.13' on: workflow_dispatch: repository_dispatch: types: [publish-clirs] jobs: build: runs-on: ${{ matrix.config.os }} strategy: fail-fast: false matrix: config: - os: ubuntu-22.04 rust_target: x86_64-unknown-linux-gnu ext: '' args: '' - os: macos-latest rust_target: x86_64-apple-darwin ext: '' args: '' - os: macos-latest rust_target: aarch64-apple-darwin ext: '' args: '' - os: windows-latest rust_target: x86_64-pc-windows-msvc ext: '.exe' args: '' - os: windows-latest rust_target: aarch64-pc-windows-msvc ext: '.exe' args: '' - os: ubuntu-22.04 rust_target: riscv64gc-unknown-linux-gnu ext: '' args: '' cross: true steps: - uses: actions/checkout@v4 - name: 'Setup Rust' if: ${{ !matrix.config.cross }} uses: dtolnay/rust-toolchain@stable with: targets: ${{ matrix.config.rust_target }} - uses: Swatinem/rust-cache@v2 if: ${{ !matrix.config.cross }} with: key: ${{ matrix.config.rust_target }} - name: install Linux dependencies if: ${{ !matrix.config.cross && startsWith(matrix.config.os, 'ubuntu') }} run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev - name: Install cross if: ${{ matrix.config.cross }} uses: taiki-e/install-action@v2 with: tool: cross@0.2.5 - name: Build CLI if: ${{ !matrix.config.cross }} run: cargo build --manifest-path ./crates/tauri-cli/Cargo.toml --profile release-size-optimized ${{ matrix.config.args }} - name: Build CLI (cross) if: ${{ matrix.config.cross }} run: cross build --manifest-path ./crates/tauri-cli/Cargo.toml --target ${{ matrix.config.rust_target }} --profile release-size-optimized ${{ matrix.config.args }} - name: Upload CLI if: ${{ !matrix.config.cross }} uses: actions/upload-artifact@v4 with: name: cargo-tauri-${{ matrix.config.rust_target }}${{ matrix.config.ext }} path: target/release-size-optimized/cargo-tauri${{ matrix.config.ext }} if-no-files-found: error - name: Upload CLI (cross) if: ${{ matrix.config.cross }} uses: actions/upload-artifact@v4 with: name: cargo-tauri-${{ matrix.config.rust_target }}${{ matrix.config.ext }} path: target/${{ matrix.config.rust_target }}/release-size-optimized/cargo-tauri${{ matrix.config.ext }} if-no-files-found: error upload: needs: build runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Download built CLIs uses: actions/download-artifact@v4.1.7 with: path: outputs - name: Pack archives run: ./.scripts/ci/pack-cli.sh - name: Get CLI version run: echo "CLI_VERSION=$(cat crates/tauri-cli/metadata-v2.json | jq '."cli.js".version' -r)" >> $GITHUB_ENV - name: Publish release uses: softprops/action-gh-release@50195ba7f6f93d1ac97ba8332a178e008ad176aa with: tag_name: tauri-cli-v${{ env.CLI_VERSION }} files: | outputs/cargo-tauri-*.zip outputs/cargo-tauri-*.tgz ================================================ FILE: .github/workflows/supply-chain.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: supply chain health status on: workflow_dispatch: schedule: - cron: '0 0 * * *' push: branches: - dev paths: - '.github/workflows/supply-chain.yml' - '**/Cargo.lock' - '**/Cargo.toml' jobs: cargo-vet: name: check rust dependencies with cargo vet runs-on: ubuntu-latest env: CARGO_VET_VERSION: 0.9.1 steps: - uses: actions/checkout@master - name: Install Rust run: rustup update stable && rustup default stable - uses: actions/cache@v4 with: path: ${{ runner.tool_cache }}/cargo-vet key: cargo-vet-bin-${{ env.CARGO_VET_VERSION }} - name: Add the tool cache directory to the search path run: echo "${{ runner.tool_cache }}/cargo-vet/bin" >> $GITHUB_PATH - name: Ensure that the tool cache is populated with the cargo-vet binary run: cargo install --root ${{ runner.tool_cache }}/cargo-vet --version ${{ env.CARGO_VET_VERSION }} cargo-vet # Enable this again to break the workflow once we have a reasonable amount of suggestions to get to a clean base line # - name: Invoke cargo-vet # run: cargo vet --locked - name: Provide audit suggestions run: cargo vet suggest ================================================ FILE: .github/workflows/test-android.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: test android on: pull_request: paths: - '.github/workflows/test-android.yml' - 'crates/tauri-cli/templates/mobile/android/**' - 'crates/tauri-cli/src/mobile/**' - '!crates/tauri-cli/src/mobile/ios.rs' - '!crates/tauri-cli/src/mobile/ios/**' - 'crates/tauri-build/src/mobile.rs' - 'crates/tauri/mobile/android/**' - 'crates/tauri/mobile/android-codegen/**' workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: test: runs-on: ${{ matrix.platform }} strategy: fail-fast: false matrix: platform: [ubuntu-latest, macos-latest, windows-latest] steps: - uses: actions/checkout@v4 - name: install Rust 1.77.2 uses: dtolnay/rust-toolchain@1.77.2 - name: install Linux dependencies if: matrix.platform == 'ubuntu-latest' run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev webkit2gtk-4.1 - run: npm i -g --force corepack - name: setup node uses: actions/setup-node@v4 with: node-version: lts/* cache: 'pnpm' - uses: actions/setup-java@v3 with: distribution: temurin java-version: 17 cache: 'gradle' - name: Setup NDK uses: nttld/setup-ndk@v1 id: setup-ndk with: ndk-version: r25b local-cache: true # TODO check after https://github.com/nttld/setup-ndk/issues/518 is fixed - name: Restore Android Symlinks if: matrix.platform == 'ubuntu-latest' || matrix.platform == 'macos-latest' run: | directory="${{ steps.setup-ndk.outputs.ndk-path }}/toolchains/llvm/prebuilt/linux-x86_64/bin" find "$directory" -type l | while read link; do current_target=$(readlink "$link") new_target="$directory/$(basename "$current_target")" ln -sf "$new_target" "$link" echo "Changed $(basename "$link") from $current_target to $new_target" done - uses: Swatinem/rust-cache@v2 - name: build CLI run: cargo build --manifest-path ./crates/tauri-cli/Cargo.toml - name: move CLI to cargo bin dir if: matrix.platform != 'windows-latest' run: mv ./target/debug/cargo-tauri $HOME/.cargo/bin - name: move CLI to cargo bin dir if: matrix.platform == 'windows-latest' run: mv ./target/debug/cargo-tauri.exe $HOME/.cargo/bin - run: pnpm i --frozen-lockfile - name: build Tauri API working-directory: ./packages/api run: pnpm build - name: init Android Studio project working-directory: ./examples/api run: cargo tauri android init env: NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} - name: build APK working-directory: ./examples/api run: cargo tauri android build env: NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} ================================================ FILE: .github/workflows/test-cli-js.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: test `@tauri-apps/cli` on: push: branches: - dev pull_request: paths: - '.github/workflows/test-cli-js.yml' - 'packages/cli/**' # currently` @tauri-apps/cli` only tests the template - 'crates/tauri-cli/templates/app/**' env: RUST_BACKTRACE: 1 CARGO_PROFILE_DEV_DEBUG: 0 # This would add unnecessary bloat to the target folder, decreasing cache efficiency. concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: test: runs-on: ${{ matrix.platform }} strategy: fail-fast: false matrix: platform: [ubuntu-latest, macos-latest, windows-latest] steps: - uses: actions/checkout@v4 - name: install Rust stable uses: dtolnay/rust-toolchain@stable - run: npm i -g --force corepack - name: setup node uses: actions/setup-node@v4 with: node-version: 'lts/*' cache: 'pnpm' - name: install Linux dependencies if: matrix.platform == 'ubuntu-latest' run: | sudo apt-get update sudo apt-get install -y webkit2gtk-4.1 libayatana-appindicator3-dev librsvg2-dev - uses: Swatinem/rust-cache@v2 - name: test timeout-minutes: 30 run: | cd ./packages/cli pnpm i --frozen-lockfile pnpm build pnpm test ================================================ FILE: .github/workflows/test-cli-rs.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: test `tauri-cli` on: push: branches: - dev pull_request: paths: - '.github/workflows/test-cli-rs.yml' - 'crates/tauri-utils/**' - 'crates/tauri-bundler/**' - 'crates/tauri-cli/**' env: RUST_BACKTRACE: 1 CARGO_PROFILE_DEV_DEBUG: 0 # This would add unnecessary bloat to the target folder, decreasing cache efficiency. concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: test: runs-on: ${{ matrix.platform.os }} strategy: fail-fast: false matrix: platform: - { target: x86_64-pc-windows-msvc, os: windows-latest } - { target: aarch64-pc-windows-msvc, os: windows-latest, args: --no-default-features --features native-tls-vendored } - { target: x86_64-unknown-linux-gnu, os: ubuntu-latest } - { target: x86_64-apple-darwin, os: macos-latest } steps: - uses: actions/checkout@v4 - name: 'Setup Rust' uses: dtolnay/rust-toolchain@1.77.2 with: targets: ${{ matrix.platform.target }} - name: install Linux dependencies if: matrix.platform.os == 'ubuntu-latest' run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev webkit2gtk-4.1 libayatana-appindicator3-dev librsvg2-dev - uses: Swatinem/rust-cache@v2 - name: test CLI run: cargo test --manifest-path ./crates/tauri-cli/Cargo.toml ${{ matrix.platform.args }} ================================================ FILE: .github/workflows/test-core.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: test core on: push: branches: - dev pull_request: paths: - '.github/workflows/test-core.yml' - 'crates/**' - '!crates/tauri/scripts/**' - '!crates/tauri-cli/**' - '!crates/tauri-bundler/**' - '!crates/tauri-macos-sign/**' - '!crates/tauri-schema-generator/**' env: RUST_BACKTRACE: 1 CARGO_PROFILE_DEV_DEBUG: 0 # This would add unnecessary bloat to the target folder, decreasing cache efficiency. concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: test: runs-on: ${{ matrix.platform.os }} strategy: fail-fast: false matrix: platform: - { target: x86_64-pc-windows-msvc, os: windows-latest, toolchain: '1.77.2', cross: false, command: 'test' } - { target: x86_64-unknown-linux-gnu, os: ubuntu-latest, toolchain: '1.77.2', cross: false, command: 'test' } - { target: aarch64-apple-darwin, os: macos-14, toolchain: '1.77.2', cross: false, command: 'test' } - { target: aarch64-apple-ios, os: macos-latest, toolchain: '1.77.2', cross: false, command: 'build' } - { target: aarch64-linux-android, os: ubuntu-latest, toolchain: '1.77.2', cross: true, command: 'build' } features: - { args: --no-default-features, key: no-default } - { args: --all-features, key: all } steps: - uses: actions/checkout@v4 - name: install Rust uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.platform.toolchain }} targets: ${{ matrix.platform.target }} - name: install Linux dependencies if: contains(matrix.platform.target, 'unknown-linux') run: | sudo apt-get update sudo apt-get install -y webkit2gtk-4.1 libxdo-dev libayatana-appindicator3-dev - uses: Swatinem/rust-cache@v2 with: key: ${{ matrix.platform.target }} save-if: ${{ matrix.features.key == 'all' }} - name: test tauri-utils if: ${{ !matrix.platform.cross }} # Using --lib --bins --tests to skip doc tests run: cargo ${{ matrix.platform.command }} --target ${{ matrix.platform.target }} ${{ matrix.features.args }} --lib --bins --tests --manifest-path crates/tauri-utils/Cargo.toml - name: test tauri-utils (using cross) if: ${{ matrix.platform.cross }} # Using --lib --bins --tests to skip doc tests run: | cargo install cross --git https://github.com/cross-rs/cross --rev 51f46f296253d8122c927c5bb933e3c4f27cc317 --locked cross ${{ matrix.platform.command }} --target ${{ matrix.platform.target }} ${{ matrix.features.args }} --lib --bins --tests --manifest-path crates/tauri-utils/Cargo.toml - name: test tauri if: ${{ !matrix.platform.cross }} run: cargo ${{ matrix.features.key == 'no-default' && 'check' || matrix.platform.command }} --target ${{ matrix.platform.target }} ${{ matrix.features.args }} --manifest-path crates/tauri/Cargo.toml - name: test tauri (using cross) if: ${{ matrix.platform.cross }} run: | cargo install cross --git https://github.com/cross-rs/cross --rev 51f46f296253d8122c927c5bb933e3c4f27cc317 --locked cross ${{ matrix.features.key == 'no-default' && 'check' || matrix.platform.command }} --target ${{ matrix.platform.target }} ${{ matrix.features.args }} --manifest-path crates/tauri/Cargo.toml ================================================ FILE: .github/workflows/udeps.yml ================================================ # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name: Udeps on: push: branches: - dev env: RUST_BACKTRACE: 1 CARGO_PROFILE_DEV_DEBUG: 0 # This would add unnecessary bloat to the target folder, decreasing cache efficiency. concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: changes: runs-on: ubuntu-latest outputs: tauri: ${{ steps.filter.outputs.tauri }} build: ${{ steps.filter.outputs.build }} codegen: ${{ steps.filter.outputs.codegen }} macros: ${{ steps.filter.outputs.macros }} runtime: ${{ steps.filter.outputs.runtime }} wry: ${{ steps.filter.outputs.wry }} utils: ${{ steps.filter.outputs.utils }} bundler: ${{ steps.filter.outputs.bundler }} cli: ${{ steps.filter.outputs.cli }} steps: - uses: actions/checkout@v4 - uses: dorny/paths-filter@v3 id: filter with: filters: | tauri: - 'crates/tauri/**' - '!crates/tauri/scripts/**' build: - 'crates/tauri-build/**' codegen: - 'crates/tauri-codegen/**' macros: - 'crates/tauri-macros/**' runtime: - 'crates/tauri-runtime/**' wry: - 'crates/tauri-runtime-wry/**' utils: - 'crates/tauri-utils/**' bundler: - 'crates/tauri-bundler/**' cli: - 'crates/tauri-cli/**' macossign: - 'crates/tauri-macos-sign/**' setup: runs-on: ubuntu-latest needs: changes if: | needs.changes.outputs.tauri == 'true' || needs.changes.outputs.build == 'true' || needs.changes.outputs.codegen == 'true' || needs.changes.outputs.macros == 'true' || needs.changes.outputs.runtime == 'true' || needs.changes.outputs.wry == 'true' || needs.changes.outputs.utils == 'true' || needs.changes.outputs.bundler == 'true' || needs.changes.outputs.cli == 'true' || needs.changes.outputs.macossign == 'true' steps: - uses: actions/checkout@v4 - name: Install Rust nightly uses: dtolnay/rust-toolchain@nightly - name: Install udeps run: cargo install cargo-udeps --locked --force - name: Upload udeps uses: actions/upload-artifact@v4 with: name: udeps path: '~/.cargo/bin/cargo-udeps' if-no-files-found: error - name: Create udeps matrix id: create-matrix env: TAURI: ${{ needs.changes.outputs.tauri == 'true' }} BUILD: ${{ needs.changes.outputs.build == 'true' }} CODEGEN: ${{ needs.changes.outputs.codegen == 'true' }} MACROS: ${{ needs.changes.outputs.macros == 'true' }} RUNTIME: ${{ needs.changes.outputs.runtime == 'true' }} WRY: ${{ needs.changes.outputs.wry == 'true' }} UTILS: ${{ needs.changes.outputs.utils == 'true' }} BUNDLER: ${{ needs.changes.outputs.bundler == 'true' }} CLI: ${{ needs.changes.outputs.cli == 'true' }} MACOSSIGN: ${{ needs.changes.outputs.macossign == 'true' }} run: | crates=() if [ "${TAURI}" == "true" ]; then crates[${#crates[@]}]="\"./crates/tauri\""; fi if [ "${BUILD}" == "true" ]; then crates[${#crates[@]}]="\"./crates/tauri-build\""; fi if [ "${CODEGEN}" == "true" ]; then crates[${#crates[@]}]="\"./crates/tauri-codegen\""; fi if [ "${MACROS}" == "true" ]; then crates[${#crates[@]}]="\"./crates/tauri-macros\""; fi if [ "${RUNTIME}" == "true" ]; then crates[${#crates[@]}]="\"./crates/tauri-runtime\""; fi if [ "${WRY}" == "true" ]; then crates[${#crates[@]}]="\"./crates/tauri-runtime-wry\""; fi if [ "${UTILS}" == "true" ]; then crates[${#crates[@]}]="\"./crates/tauri-utils\""; fi if [ "${BUNDLER}" == "true" ]; then crates[${#crates[@]}]="\"./crates/tauri-bundler\""; fi if [ "${CLI}" == "true" ]; then crates[${#crates[@]}]="\"./crates/tauri-cli\""; fi if [ "${MACOSSIGN}" == "true" ]; then crates[${#crates[@]}]="\"./crates/tauri-macos-sign\""; fi echo "matrix=[$crates]" >> "$GITHUB_OUTPUT" outputs: matrix: ${{ steps.create-matrix.outputs.matrix }} udeps: runs-on: ubuntu-latest needs: setup strategy: matrix: path: ${{ fromJson(needs.setup.outputs.matrix) }} steps: - uses: actions/checkout@v4 - name: Install Rust nightly uses: dtolnay/rust-toolchain@nightly - name: install dependencies run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev - uses: Swatinem/rust-cache@v2 - name: Download udeps uses: actions/download-artifact@v4.1.7 with: name: udeps path: '~/.cargo/bin' - run: chmod +x $HOME/.cargo/bin/cargo-udeps - name: Install required packages run: | sudo apt-get update sudo apt-get install -y webkit2gtk-4.1 libayatana-appindicator3-dev - name: Run udeps run: cargo udeps --manifest-path ${{ matrix.path }}/Cargo.toml --all-targets --all-features ================================================ FILE: .gitignore ================================================ # dependency directories node_modules/ # Optional npm and yarn cache directory .npm/ .yarn/ # Output of 'npm pack' *.tgz # dotenv environment variables file .env # .vscode workspace settings file .vscode/settings.json .vscode/launch.json .vscode/tasks.json # npm, yarn and bun lock files package-lock.json yarn.lock bun.lockb # rust compiled folders target/ # test video for streaming example streaming_example_test_video.mp4 # examples /gen directory /examples/**/src-tauri/gen/ /bench/**/src-tauri/gen/ # logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* # runtime data pids *.pid *.seed *.pid.lock # miscellaneous /.vs .DS_Store .Thumbs.db *.sublime* .idea debug.log TODO.md .aider* ================================================ FILE: .prettierignore ================================================ /audits /.vscode # change files are hand-written and shouldn't be formatted /.changes/* !/.changes/config.json # dependcies and artifacts directories node_modules/ target/ dist/ # lock files pnpm-lock.yaml # autogenerated and minimized js file crates/tauri/scripts/bundle.global.js # this file is an IIFE, shouldn't be formatted crates/tauri/scripts/process-ipc-message-fn.js # cli templates should be formatted manually # it also includes invalid json files that # prettier can't handle crates/tauri-cli/templates # autogenerated files **/autogenerated/**/*.md packages/cli/index.js packages/cli/index.d.ts crates/tauri-schema-worker/.wrangler CHANGELOG.md *schema.json # WiX templates *.wxs # examples /gen directory examples/**/src-tauri/gen bench/**/src-tauri/gen ================================================ FILE: .prettierrc ================================================ { "singleQuote": true, "semi": false, "trailingComma": "none", "experimentalOperatorPosition": "start" } ================================================ FILE: .scripts/ci/check-change-tags.js ================================================ #!/usr/bin/env node // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT const fs = require('fs') const path = require('path') const ignorePackages = [ 'tauri-macros', 'tauri-codegen', 'tauri-runtime', 'tauri-runtime-wry', 'tauri-driver' ] const covectorConfig = JSON.parse( fs.readFileSync('.changes/config.json', 'utf8') ) const tags = Object.keys(covectorConfig.changeTags) const missingTagsFiles = {} const unknownTagsFiles = {} function checkChangeFiles(changeFiles) { for (const file of changeFiles) { const content = fs.readFileSync(file, 'utf8') const [frontMatter] = /^---[\s\S.]*---\n/i.exec(content) const packages = frontMatter .split('\n') .filter((l) => !(l === '---' || !l)) .map((l) => l.replace(/('|")/g, '').split(':')) for (const [package, _, tag] of packages) { if (!tag) { if (ignorePackages.includes(package)) continue if (!missingTagsFiles[file]) missingTagsFiles[file] = [] missingTagsFiles[file].push(package) } else if (!tags.includes(tag)) { if (!unknownTagsFiles[file]) unknownTagsFiles[file] = [] unknownTagsFiles[file].push({ package, tag }) } } } const missingTagsEntries = Object.entries(missingTagsFiles) const unknownTagsEntries = Object.entries(unknownTagsFiles) if (missingTagsEntries.length > 0 || unknownTagsEntries.length > 0) { for (const [file, packages] of missingTagsEntries) { for (const package of packages) { console.error( `Package \`${package}\` is missing a change tag in ${file} ` ) } } for (const [file, packages] of unknownTagsEntries) { for (const { package, tag } of packages) { console.error( `Package \`${package}\` has an unknown change tag ${tag} in ${file} ` ) } } process.exit(1) } } const [_bin, _script, ...files] = process.argv if (files.length > 0) { checkChangeFiles( files.filter((f) => f.toLowerCase() !== '.changes/readme.md') ) } else { const changeFiles = fs .readdirSync('.changes') .filter((f) => f.endsWith('.md') && f.toLowerCase() !== 'readme.md') .map((p) => path.join('.changes', p)) checkChangeFiles(changeFiles) } ================================================ FILE: .scripts/ci/check-license-header.js ================================================ #!/usr/bin/env node // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT const fs = require('fs') const path = require('path') const readline = require('readline') const header = `Copyright 2019-2024 Tauri Programme within The Commons Conservancy 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 = [ 'target', 'templates', 'node_modules', 'gen', 'dist', 'bundle.global.js' ] async function checkFile(file) { if ( extensions.some((e) => file.endsWith(e)) && !ignore.some((i) => file.includes(`/${i}/`) || path.basename(file) === i) ) { const fileStream = fs.createReadStream(file) const rl = readline.createInterface({ input: fileStream, crlfDelay: Infinity }) let contents = `` let i = 0 for await (let line of rl) { // ignore empty lines, allow shebang and bundler license if ( line.length === 0 || line.startsWith('#!') || line.startsWith('// swift-tools-version:') || line === bundlerLicense || line === denoLicense ) { continue } // strip comment marker if (line.startsWith('// ')) { line = line.substring(3) } else if (line.startsWith('# ')) { line = line.substring(2) } contents += line if (++i === 3) { break } contents += '\n' } if (contents !== header) { return true } } return false } async function check(src) { const missingHeader = [] for (const entry of fs.readdirSync(src, { withFileTypes: true })) { const p = path.join(src, entry.name) if (entry.isSymbolicLink() || ignore.includes(entry.name)) { continue } if (entry.isDirectory()) { const missing = await check(p) missingHeader.push(...missing) } else { const isMissing = await checkFile(p) if (isMissing) { missingHeader.push(p) } } } return missingHeader } const [_bin, _script, ...files] = process.argv if (files.length > 0) { async function run() { const missing = [] for (const f of files) { const isMissing = await checkFile(f) if (isMissing) { missing.push(f) } } if (missing.length > 0) { console.log(missing.join('\n')) process.exit(1) } } run() } else { check('.').then((missing) => { if (missing.length > 0) { console.log(missing.join('\n')) process.exit(1) } }) } ================================================ FILE: .scripts/ci/has-diff.sh ================================================ #!/bin/bash # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT git_output=$(git diff --ignore-submodules --name-only HEAD) if [ -z "$git_output" ]; then echo "✔ working directory is clean" else echo "✘ found diff:" echo "$git_output" exit 1 fi ================================================ FILE: .scripts/ci/pack-cli.sh ================================================ #!/bin/bash # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT set -euxo pipefail for o in outputs/*; do pushd "$o" chmod +x cargo-tauri* cp ../../crates/tauri-cli/LICENSE* ../../crates/tauri-cli/README.md . target=$(basename "$o" | cut -d. -f1) if grep -qE '(apple|windows)' <<< "$target"; then zip "../${target}.zip" * else tar cv * | gzip -9 > "../${target}.tgz" fi popd done ================================================ FILE: .scripts/ci/sync-cli-metadata.js ================================================ #!/usr/bin/env node // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT /* This script is solely intended to be run as part of the `covector version` step to keep the `../../crates/tauri-cli/metadata-v2.json` up to date with other version bumps. Long term we should look to find a more "rusty way" to import / "pin" a version value in our tauri-cli rust binaries. */ const { readFileSync, writeFileSync } = require('fs') const { resolve } = require('path') const packageNickname = process.argv[2] const filePath = resolve(__dirname, '../../crates/tauri-cli/metadata-v2.json') const bump = process.argv[3] let index = null switch (bump) { case 'major': case 'premajor': index = 0 break case 'minor': index = 1 break case 'patch': index = 2 break case 'prerelease': case 'prepatch': index = 3 break default: throw new Error('unexpected bump ' + bump) } const inc = (version) => { const v = version.split('.') for (let i = 0; i < v.length; i++) { if (i === index) { v[i] = String(Number(v[i]) + 1) } else if (i > index) { v[i] = 0 } } if (bump === 'premajor') { const pre = JSON.parse( readFileSync(resolve(__dirname, '../../.changes/pre.json'), 'utf-8') ) return `${v.join('.')}-${pre.tag}.0` } return v.join('.') } // read file into js object const metadata = JSON.parse(readFileSync(filePath, 'utf-8')) // set field version let version if (packageNickname === '@tauri-apps/cli') { version = inc(metadata['cli.js'].version) metadata['cli.js'].version = version } else { version = inc(metadata[packageNickname]) metadata[packageNickname] = version } writeFileSync(filePath, JSON.stringify(metadata, null, 2) + '\n') console.log(`wrote ${version} for ${packageNickname} into metadata-v2.json`) console.dir(metadata) ================================================ FILE: .vscode/extensions.json ================================================ { "recommendations": [ "rust-lang.rust-analyzer", "EditorConfig.EditorConfig", "esbenp.prettier-vscode", "tamasfe.even-better-toml" ] } ================================================ FILE: ARCHITECTURE.md ================================================ # The Tauri Architecture ## Introduction Tauri is a polyglot and generic toolkit that is very composable and allows engineers to make a wide variety of applications. It is used for building applications for Desktop Computers using a combination of Rust tools and HTML rendered in a Webview. Apps built with Tauri can ship with any number of pieces of an optional JS API / Rust API so that webviews can control the system via message passing. In fact, developers can extend the default API with their own functionality and bridge the Webview and Rust-based backend easily. Tauri apps can have custom menus and have tray-type interfaces. They can be updated, and are managed by the user's operating system as expected. They are very small, because they use the OS's webview. They do not ship a runtime, since the final binary is compiled from Rust. This makes the reversing of Tauri apps not a trivial task. ## What Tauri is NOT - Tauri is not a lightweight kernel wrapper...instead it directly uses [WRY](#wry) and [TAO](#tao) to do the heavy-lifting in making system calls to the OS. - Tauri is not a VM or virtualized environment...instead it is an application toolkit that allows making Webview OS applications. ## Major Components The following section briefly describes the roles of the various parts of Tauri. ### Tauri Core [STABLE RUST] #### [tauri](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri) This is the major crate that holds everything together. It brings the runtimes, macros, utilities and API into one final product. It reads the `tauri.conf.json` file at compile time in order to bring in features and undertake actual configuration of the app (and even the `Cargo.toml` file in the project's folder). It handles script injection (for polyfills / prototype revision) at runtime, hosts the API for systems interaction, and even manages updating. #### [tauri-build](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri-build) Apply the macros at build-time in order to rig some special features needed by `cargo`. #### [tauri-codegen](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri-codegen) - Embed, hash, and compress assets, including icons for the app as well as the system-tray. - Parse `tauri.conf.json` at compile time and generate the Config struct. #### [tauri-macros](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri-macros) Create macros for the context, handler, and commands by leveraging the `tauri-codegen` crate. #### [tauri-runtime](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri-runtime) This is the glue layer between tauri itself and lower level webview libraries. #### [tauri-runtime-wry](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri-runtime-wry) This crate opens up direct systems-level interactions specifically for WRY, such as printing, monitor detection, and other windowing related tasks. `tauri-runtime` implementation for WRY. #### [tauri-utils](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri-utils) This is common code that is reused in many places and offers useful utilities like parsing configuration files, detecting platform triples, injecting the CSP, and managing assets. ### Tauri Tooling #### [@tauri-apps/api](https://github.com/tauri-apps/tauri/tree/dev/packages/api) [TS -> JS] A TypeScript library that creates `cjs` and `esm` JavaScript endpoints for you to import into your Frontend framework so that the Webview can call and listen to backend activity. We also ship the pure TypeScript, because for some frameworks this is more optimal. It uses the message passing of webviews to their hosts. #### [bundler](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri-bundler) [RUST / SHELL] The bundler is a library that builds a Tauri App for the platform triple it detects / is told. At the moment it currently supports macOS, Windows and Linux - but in the near future will support mobile platforms as well. May be used outside of Tauri projects. #### [@tauri-apps/cli](https://github.com/tauri-apps/tauri/tree/dev/packages/cli) [JS] It is a wrapper around [tauri-cli](https://github.com/tauri-apps/tauri/blob/dev/crates/tauri-cli) using [napi-rs](https://github.com/napi-rs/napi-rs) to produce NPM packages for each platform. #### [tauri-cli](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri-cli) [RUST] This rust executable provides the full interface to all of the required activities for which the CLI is required. It will run on macOS, Windows, and Linux. #### [create-tauri-app](https://github.com/tauri-apps/create-tauri-app) [JS] This is a toolkit that will enable engineering teams to rapidly scaffold out a new tauri-apps project using the frontend framework of their choice (as long as it has been configured). # External Crates The Tauri-Apps organisation maintains two "upstream" crates from Tauri, namely TAO for creating and managing application windows, and WRY for interfacing with the Webview that lives within the window. ## [TAO](https://github.com/tauri-apps/tao) Cross-platform application window creation library in Rust that supports all major platforms like Windows, macOS, Linux, iOS and Android. Written in Rust, it is a fork of [winit](https://github.com/rust-windowing/winit) that we have extended for our own needs like menu bar and system tray. ## [WRY](https://github.com/tauri-apps/wry) WRY is a cross-platform WebView rendering library in Rust that supports all major desktop platforms like Windows, macOS, and Linux. Tauri uses WRY as the abstract layer responsible to determine which webview is used (and how interactions are made). # Additional tooling ## [tauri-action](https://github.com/tauri-apps/tauri-action) This is a github workflow that builds tauri binaries for all platforms. It is not the fastest out there, but it gets the job done and is highly configurable. Even allowing you to create a (very basic) tauri app even if tauri is not setup. ## [create-pull-request](https://github.com/tauri-apps/create-pull-request) Because this is a very risky (potentially destructive) github action, we forked it in order to have strong guarantees that the code we think is running is actually the code that is running. ## [vue-cli-plugin-tauri](https://github.com/tauri-apps/vue-cli-plugin-tauri) This plugin allows you to very quickly install tauri in a vue-cli project. ## [tauri-vscode](https://github.com/tauri-apps/tauri-vscode) This project enhances the VS Code interface with several nice-to-have features. # Tauri Plugins [documentation](https://v2.tauri.app/develop/plugins/) Generally speaking, plugins are authored by third parties (even though there may be official, supported plugins). A plugin generally does 3 things: 1. It provides rust code to do "something". 2. It provides interface glue to make it easy to integrate into an app. 3. It provides a JS API for interfacing with the rust code. Here are several examples of Tauri Plugins: - - - # Workflows ## What does the Development flow look like? A developer must first install the prerequisite toolchains for creating a Tauri app. At the very least this will entail installing rust & cargo, and most likely also a modern version of node.js and potentially another package manager. Some platforms may also require other tooling and libraries, but this has been documented carefully in the respective platform docs. Because of the many ways to build front-ends, we will stick with a common node.js based approach for development. (Note: Tauri does not by default ship a node.js runtime.) The easiest way to do this is to run the following: ``` npm create tauri-app ``` Which will ask you a bunch of questions about the framework you want to install and then create everything you need in a single folder - some via the placement of template files and some through normal installation procedures of your framework. > If you don't use this process, you will have to manually install the tauri cli, initialise tauri and manually configure the `tauri.conf.json` file. Once everything is installed, you can run: ``` pnpm tauri dev -or- yarn tauri dev -or- npm run tauri dev ``` This will do several things: 1. start the JS Framework devserver 2. begin the long process of downloading and compiling the rust libraries 3. open an application window with devtools enabled 4. keep a long-lived console alive If you change your HTML/CSS/TS/JS, your framework devserver should give you its best shot at instant hot module reloading and you will see the changes instantly. If you modify your rust code or anything in the Cargo.toml, the window will close while rust recompiles. When finished it will reload. If you need to get deeper insight into your current project, or triage requires investigation of installed components, just run: ``` pnpm tauri info ``` ## What does the Release flow look like? The release flow begins with proper configuration in the `tauri.conf.json` file. In this file, the developer can configure not only the basic behaviour of the application (like window size and decoration), they can also provide settings for signing and updating. Depending upon the operating system that the developer (or CI) is building the application on, there will be an app built for them for that system. (Cross compilation is not currently available, however there is an official [GitHub Action](https://github.com/tauri-apps/tauri-action) that can be used to build for all platforms.) To kick off this process, just: ``` pnpm tauri build ``` After some time, the process will end and you can see the results in the `./src-tauri/target/release` folder. ## What does the End-User flow look like? End users will be provided with binaries in ways that are appropriate for their systems. Whether macOS, Linux, or Windows, direct download or store installations - they will be able to follow procedures for installing and removing that they are used to. ## What does the Updating flow look like? When a new version is ready, the developer publishes the new signed artifacts to a server (that they have configured within `tauri.conf.json`). The application can poll this server to see if there is a new release. When there is a new release, the user is prompted to update. The application update is downloaded, verified (checksum & signature), updated, closed, and restarted. ## License Tauri itself is licensed under MIT or Apache-2.0. If you repackage it and modify any source code, it is your responsibility to verify that you are complying with all upstream licenses. Tauri is provided AS-IS with no explicit claim for suitability for any purpose. Here you may peruse our [Software Bill of Materials](https://app.fossa.com/projects/git%2Bgithub.com%2Ftauri-apps%2Ftauri). ================================================ FILE: Cargo.toml ================================================ [workspace] members = [ "crates/tauri", "crates/tauri-runtime", "crates/tauri-runtime-wry", "crates/tauri-macros", "crates/tauri-utils", "crates/tauri-build", "crates/tauri-codegen", "crates/tauri-plugin", "crates/tauri-schema-generator", "crates/tauri-schema-worker", "crates/tauri-cli", "crates/tauri-bundler", "crates/tauri-macos-sign", "crates/tauri-driver", # @tauri-apps/cli rust project "packages/cli", # integration tests "crates/tests/restart", "crates/tests/acl", # bench "bench", "bench/tests/cpu_intensive/src-tauri", "bench/tests/files_transfer/src-tauri", "bench/tests/helloworld/src-tauri", # examples "examples/file-associations/src-tauri", "examples/resources/src-tauri", "examples/api/src-tauri", "examples/api/src-tauri/tauri-plugin-sample", ] resolver = "2" [workspace.package] authors = ["Tauri Programme within The Commons Conservancy"] homepage = "https://tauri.app/" repository = "https://github.com/tauri-apps/tauri" categories = ["gui", "web-programming"] license = "Apache-2.0 OR MIT" edition = "2021" rust-version = "1.77.2" # default to small, optimized workspace release binaries [profile.release] panic = "abort" codegen-units = 1 lto = true incremental = false opt-level = "s" strip = true # profiles for tauri-cli [profile.dev.package.miniz_oxide] opt-level = 3 [profile.release-size-optimized] inherits = "release" codegen-units = 1 lto = true incremental = false opt-level = "s" # Temporary patch to schemars to preserve newlines in docstrings for our reference docs schemas # See https://github.com/GREsau/schemars/issues/120 for reference [patch.crates-io] schemars_derive = { git = 'https://github.com/tauri-apps/schemars.git', branch = 'feat/preserve-description-newlines' } tauri = { path = "./crates/tauri" } tauri-plugin = { path = "./crates/tauri-plugin" } tauri-utils = { path = "./crates/tauri-utils" } ================================================ FILE: LICENSE.spdx ================================================ SPDXVersion: SPDX-2.1 DataLicense: CC0-1.0 PackageName: tauri DataFormat: SPDXRef-1 PackageSupplier: Organization: The Tauri Programme in the Commons Conservancy PackageHomePage: https://tauri.app PackageLicenseDeclared: Apache-2.0 PackageLicenseDeclared: MIT PackageCopyrightText: 2019-2025, The Tauri Programme in the Commons Conservancy PackageSummary: Tauri is a rust project that enables developers to make secure and small desktop applications using a web frontend. PackageComment: The package includes the following libraries; see Relationship information. Created: 2019-05-20T09:00:00Z PackageDownloadLocation: git://github.com/tauri-apps/tauri PackageDownloadLocation: git+https://github.com/tauri-apps/tauri.git PackageDownloadLocation: git+ssh://github.com/tauri-apps/tauri.git Creator: Person: Daniel Thompson-Yvetot ================================================ FILE: LICENSE_APACHE-2.0 ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS ================================================ FILE: LICENSE_MIT ================================================ MIT License Copyright (c) 2017 - Present Tauri Apps Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ Tauri [![status](https://img.shields.io/badge/status-stable-blue.svg)](https://github.com/tauri-apps/tauri/tree/dev) [![License](https://img.shields.io/badge/License-MIT%20or%20Apache%202-green.svg)](https://opencollective.com/tauri) [![test core](https://img.shields.io/github/actions/workflow/status/tauri-apps/tauri/test-core.yml?label=test%20core&logo=github)](https://github.com/tauri-apps/tauri/actions/workflows/test-core.yml) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Ftauri-apps%2Ftauri.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Ftauri-apps%2Ftauri?ref=badge_shield) [![Chat Server](https://img.shields.io/badge/chat-discord-7289da.svg)](https://discord.com/invite/tauri) [![website](https://img.shields.io/badge/website-tauri.app-purple.svg)](https://tauri.app) [![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) ## 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, 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. ## Getting Started If you are interested in making a tauri app, please visit the [documentation website](https://tauri.app). The quickest way to get started is to install the [prerequisites](https://v2.tauri.app/start/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`: ```sh npm create tauri-app@latest ``` ## Features The list of Tauri's features includes, but is not limited to: - Built-in app bundler to create app bundles in formats like `.app`, `.dmg`, `.deb`, `.rpm`, `.AppImage` and Windows installers like `.exe` (via NSIS) and `.msi` (via WiX). - Built-in self updater (desktop only) - System tray icons - Native notifications - Native WebView Protocol (tauri doesn't create a localhost http(s) server to serve the WebView contents) - GitHub action for streamlined CI - VS Code extension ### Platforms Tauri currently supports development and distribution on the following platforms: | 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 | 9 and above | | Android | 7 and above (currently 8 and above) | ## 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. Please make sure to read the [Contributing Guide](./.github/CONTRIBUTING.md) before making a pull request. Thank you to everyone contributing to Tauri! ### Documentation Documentation in a polyglot system is a tricky proposition. To this end, we prefer to use inline documentation in the Rust & JS source code as much as possible. Check out the hosting repository for the documentation site for further information: ## Partners
CrabNebula
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. 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). ## Licenses Code: (c) 2015 - Present - The Tauri Programme within The Commons Conservancy. MIT or MIT/Apache 2.0 where applicable. Logo: CC-BY-NC-ND - Original Tauri Logo Designs by [Alve Larsson](https://alve.io/), [Daniel Thompson-Yvetot](https://github.com/nothingismagick) and [Guillaume Chau](https://github.com/akryum) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Ftauri-apps%2Ftauri.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Ftauri-apps%2Ftauri?ref=badge_large) ================================================ FILE: SECURITY.md ================================================ # Security Policy ## Supported Versions | Version | Supported | | ------- | ------------------ | | > 1.0 | :white_check_mark: | | < 1.0 | :x: | ## Reporting a Vulnerability If you have found a potential security threat, vulnerability or exploit in Tauri or one of its upstream dependencies, please DON'T create a pull-request, DON'T file an issue on GitHub, DON'T mention it on Discord and DON'T create a forum thread. Please submit your report via the GitHub Private Vulnerability Disclosure functionality. Find out more about the reporting process [here](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability). Our team will triage your report and keep you informed about the progress. We may ask questions or request further guidance on reproduction of the vulnerability in the comments of the advisory, which will be publicized. Additionally, we may ask you to independently verify our patch, which will be available in the private advisory branch. Please do not publish your vulnerability during the process or before coordinated public disclosure from our side. We try to adhere to common standards of publication within 90-Days of disclosure. Depending on your decision to accept or deny credit for the vulnerability, you will be publicly attributed to the vulnerability and may be mentioned in our announcements. At the current time we do not have the financial ability to reward bounties, but in extreme cases will at our discretion consider a reward. ================================================ FILE: bench/Cargo.toml ================================================ [package] name = "tauri_bench" version = "0.1.0" authors = ["Tauri Programme within The Commons Conservancy"] edition = "2021" rust-version = "1.77.2" license = "Apache-2.0 OR MIT" description = "Cross-platform WebView rendering library" repository = "https://github.com/tauri-apps/wry" [dependencies] anyhow = "1" time = { version = "0.3", features = ["formatting"] } tempfile = "3" serde_json = "1" serde = { version = "1", features = ["derive"] } [[bin]] name = "run_benchmark" path = "src/run_benchmark.rs" [[bin]] name = "build_benchmark_jsons" path = "src/build_benchmark_jsons.rs" ================================================ FILE: bench/README.md ================================================ # Tauri Bench [![status](https://img.shields.io/badge/Status-beta-green.svg)](https://github.com/tauri-apps/tauri) [![License](https://img.shields.io/badge/License-MIT%20or%20Apache%202-green.svg)](https://opencollective.com/tauri) [![test core](https://img.shields.io/github/actions/workflow/status/tauri-apps/tauri/test-core.yml?label=test%20core&logo=github)](https://github.com/tauri-apps/tauri/actions/workflows/test-core.yml) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Ftauri-apps%2Ftauri.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Ftauri-apps%2Ftauri?ref=badge_shield) [![Chat Server](https://img.shields.io/badge/chat-discord-7289da.svg)](https://discord.gg/SpmNs4S) [![website](https://img.shields.io/badge/website-tauri.app-purple.svg)](https://tauri.app) [![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) ## About Tauri Tauri is a polyglot and generic system that is very composable and allows engineers to make a wide variety of applications. It is used for building applications for Desktop Computers using a combination of Rust tools and HTML rendered in a Webview. Apps built with Tauri can ship with any number of pieces of an optional JS API / Rust API so that webviews can control the system via message passing. In fact, developers can extend the default API with their own functionality and bridge the Webview and Rust-based backend easily. Tauri apps can have custom menus and have tray-type interfaces. They can be updated, and are managed by the user's operating system as expected. They are very small, because they use the system's webview. They do not ship a runtime, since the final binary is compiled from rust. This makes the reversing of Tauri apps not a trivial task. ## This module This rust module run on CI, provides internal metrics results of Tauri. To learn more see [benchmark_results](https://github.com/tauri-apps/benchmark_results) repository. **\*_Internal use only_** ## Semver **tauri** is following [Semantic Versioning 2.0](https://semver.org/). ## Licenses Code: (c) 2015 - 2021 - The Tauri Programme within The Commons Conservancy. MIT or MIT/Apache 2.0 where applicable. Logo: CC-BY-NC-ND - Original Tauri Logo Designs by [Daniel Thompson-Yvetot](https://github.com/nothingismagick) and [Guillaume Chau](https://github.com/akryum) ================================================ FILE: bench/src/build_benchmark_jsons.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT //! This Rust binary runs on CI and provides internal metrics results of Tauri. To learn more see [benchmark_results](https://github.com/tauri-apps/benchmark_results) repository. //! //! ***_Internal use only_** #![doc( html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png", html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png" )] // file is used by multiple binaries #![allow(dead_code)] use std::{fs::File, io::BufReader}; mod utils; fn main() { let tauri_data = &utils::tauri_root_path() .join("gh-pages") .join("tauri-data.json"); let tauri_recent = &utils::tauri_root_path() .join("gh-pages") .join("tauri-recent.json"); // current data let current_data_buffer = BufReader::new( File::open(utils::target_dir().join("bench.json")).expect("Unable to read current data file"), ); let current_data: utils::BenchResult = serde_json::from_reader(current_data_buffer).expect("Unable to read current data buffer"); // all data's let all_data_buffer = BufReader::new(File::open(tauri_data).expect("Unable to read all data file")); let mut all_data: Vec = serde_json::from_reader(all_data_buffer).expect("Unable to read all data buffer"); // add current data to all data all_data.push(current_data); // use only latest 20 elements from all data let recent: Vec = if all_data.len() > 20 { all_data[all_data.len() - 20..].to_vec() } else { all_data.clone() }; // write json's utils::write_json( tauri_data .to_str() .expect("Something wrong with tauri_data"), &serde_json::to_value(all_data).expect("Unable to build final json (all)"), ) .unwrap_or_else(|_| panic!("Unable to write {tauri_data:?}")); utils::write_json( tauri_recent .to_str() .expect("Something wrong with tauri_recent"), &serde_json::to_value(recent).expect("Unable to build final json (recent)"), ) .unwrap_or_else(|_| panic!("Unable to write {tauri_recent:?}")); } ================================================ FILE: bench/src/run_benchmark.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT //! This Rust binary runs on CI and provides internal metrics results of Tauri. //! To learn more see [benchmark_results](https://github.com/tauri-apps/benchmark_results) repository. //! //! ***_Internal use only_*** #![doc( html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png", html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png" )] use anyhow::{Context, Result}; use std::{ collections::{HashMap, HashSet}, env, path::Path, process::{Command, Stdio}, }; mod utils; /// The list of examples for benchmarks fn get_all_benchmarks(target: &str) -> Vec<(String, String)> { vec![ ( "tauri_hello_world".into(), format!("../target/{target}/release/bench_helloworld"), ), ( "tauri_cpu_intensive".into(), format!("../target/{target}/release/bench_cpu_intensive"), ), ( "tauri_3mb_transfer".into(), format!("../target/{target}/release/bench_files_transfer"), ), ] } fn run_strace_benchmarks(new_data: &mut utils::BenchResult, target: &str) -> Result<()> { use std::io::Read; let mut thread_count = HashMap::::new(); let mut syscall_count = HashMap::::new(); for (name, example_exe) in get_all_benchmarks(target) { let mut file = tempfile::NamedTempFile::new() .context("failed to create temporary file for strace output")?; let exe_path = utils::bench_root_path().join(&example_exe); let exe_path_str = exe_path .to_str() .context("executable path contains invalid UTF-8")?; let temp_path_str = file .path() .to_str() .context("temporary file path contains invalid UTF-8")?; Command::new("strace") .args(["-c", "-f", "-o", temp_path_str, exe_path_str]) .stdout(Stdio::inherit()) .spawn() .context("failed to spawn strace process")? .wait() .context("failed to wait for strace process")?; let mut output = String::new(); file .as_file_mut() .read_to_string(&mut output) .context("failed to read strace output")?; let strace_result = utils::parse_strace_output(&output); // Count clone/clone3 syscalls as thread creation indicators let clone_calls = strace_result.get("clone").map(|d| d.calls).unwrap_or(0) + strace_result.get("clone3").map(|d| d.calls).unwrap_or(0); if let Some(total) = strace_result.get("total") { thread_count.insert(name.clone(), clone_calls); syscall_count.insert(name, total.calls); } } new_data.thread_count = thread_count; new_data.syscall_count = syscall_count; Ok(()) } fn run_max_mem_benchmark(target: &str) -> Result> { let mut results = HashMap::::new(); for (name, example_exe) in get_all_benchmarks(target) { let benchmark_file = utils::target_dir().join(format!("mprof{name}_.dat")); let benchmark_file_str = benchmark_file .to_str() .context("benchmark file path contains invalid UTF-8")?; let exe_path = utils::bench_root_path().join(&example_exe); let exe_path_str = exe_path .to_str() .context("executable path contains invalid UTF-8")?; let proc = Command::new("mprof") .args(["run", "-C", "-o", benchmark_file_str, exe_path_str]) .stdout(Stdio::null()) .stderr(Stdio::piped()) .spawn() .with_context(|| format!("failed to spawn mprof for benchmark {name}"))?; let proc_result = proc .wait_with_output() .with_context(|| format!("failed to wait for mprof {name}"))?; if !proc_result.status.success() { eprintln!( "mprof failed for {name}: {}", String::from_utf8_lossy(&proc_result.stderr) ); } if let Some(mem) = utils::parse_max_mem(benchmark_file_str) .with_context(|| format!("failed to parse mprof data for {name}"))? { results.insert(name, mem); } // Clean up the temporary file if let Err(e) = std::fs::remove_file(&benchmark_file) { eprintln!("Warning: failed to remove temporary file {benchmark_file_str}: {e}"); } } Ok(results) } fn rlib_size(target_dir: &Path, prefix: &str) -> Result { let mut size = 0; let mut seen = HashSet::new(); let deps_dir = target_dir.join("deps"); for entry in std::fs::read_dir(&deps_dir).with_context(|| { format!( "failed to read target deps directory: {}", deps_dir.display() ) })? { let entry = entry.context("failed to read directory entry")?; let name = entry.file_name().to_string_lossy().to_string(); if name.starts_with(prefix) && name.ends_with(".rlib") { if let Some(start) = name.split('-').next() { if seen.insert(start.to_string()) { size += entry .metadata() .context("failed to read file metadata")? .len(); } } } } if size == 0 { anyhow::bail!( "no rlib files found for prefix {prefix} in {}", deps_dir.display() ); } Ok(size) } fn get_binary_sizes(target_dir: &Path, target: &str) -> Result> { let mut sizes = HashMap::::new(); let wry_size = rlib_size(target_dir, "libwry")?; sizes.insert("wry_rlib".to_string(), wry_size); for (name, example_exe) in get_all_benchmarks(target) { let exe_path = utils::bench_root_path().join(&example_exe); let meta = std::fs::metadata(&exe_path) .with_context(|| format!("failed to read metadata for {}", exe_path.display()))?; sizes.insert(name, meta.len()); } Ok(sizes) } /// (target OS, target triple) const TARGETS: &[(&str, &[&str])] = &[ ( "Windows", &[ "x86_64-pc-windows-gnu", "i686-pc-windows-gnu", "i686-pc-windows-msvc", "x86_64-pc-windows-msvc", ], ), ( "Linux", &[ "x86_64-unknown-linux-gnu", "i686-unknown-linux-gnu", "aarch64-unknown-linux-gnu", ], ), ("macOS", &["x86_64-apple-darwin", "aarch64-apple-darwin"]), ]; fn cargo_deps() -> HashMap { let mut results = HashMap::new(); for (os, targets) in TARGETS { for target in *targets { let mut cmd = Command::new("cargo"); cmd.arg("tree"); cmd.arg("--no-dedupe"); cmd.args(["--edges", "normal"]); cmd.args(["--prefix", "none"]); cmd.args(["--target", target]); cmd.current_dir(utils::tauri_root_path()); match cmd.output() { Ok(output) if output.status.success() => { let full_deps = String::from_utf8_lossy(&output.stdout); let count = full_deps .lines() .collect::>() .len() .saturating_sub(1); // output includes wry itself // set the count to the highest count seen for this OS let existing = results.entry(os.to_string()).or_default(); *existing = count.max(*existing); if count <= 10 { eprintln!("Warning: dependency count for {target} seems low: {count}"); } } Ok(output) => { eprintln!( "cargo tree failed for {target}: {}", String::from_utf8_lossy(&output.stderr) ); } Err(e) => { eprintln!("Failed to run cargo tree for {target}: {e}"); } } } } results } const RESULT_KEYS: &[&str] = &["mean", "stddev", "user", "system", "min", "max"]; fn run_exec_time(target: &str) -> Result>> { let target_dir = utils::target_dir(); let benchmark_file = target_dir.join("hyperfine_results.json"); let benchmark_file_str = benchmark_file .to_str() .context("benchmark file path contains invalid UTF-8")?; let mut command = vec![ "hyperfine", "--export-json", benchmark_file_str, "--show-output", "--warmup", "3", ]; let benchmarks = get_all_benchmarks(target); let mut benchmark_paths = Vec::new(); for (_, example_exe) in &benchmarks { let exe_path = utils::bench_root_path().join(example_exe); let exe_path_str = exe_path .to_str() .context("executable path contains invalid UTF-8")?; benchmark_paths.push(exe_path_str.to_string()); } for path in &benchmark_paths { command.push(path.as_str()); } utils::run(&command)?; let mut results = HashMap::>::new(); let hyperfine_results = utils::read_json(benchmark_file_str)?; if let Some(results_array) = hyperfine_results .as_object() .and_then(|obj| obj.get("results")) .and_then(|val| val.as_array()) { for ((name, _), data) in benchmarks.iter().zip(results_array.iter()) { if let Some(data_obj) = data.as_object() { let filtered_data: HashMap = data_obj .iter() .filter(|(key, _)| RESULT_KEYS.contains(&key.as_str())) .filter_map(|(key, val)| val.as_f64().map(|v| (key.clone(), v))) .collect(); results.insert(name.clone(), filtered_data); } } } Ok(results) } fn main() -> Result<()> { let json_3mb = utils::home_path().join(".tauri_3mb.json"); if !json_3mb.exists() { println!("Downloading test data..."); utils::download_file( "https://github.com/lemarier/tauri-test/releases/download/v2.0.0/json_3mb.json", json_3mb, ) .context("failed to download test data")?; } println!("Starting tauri benchmark"); let target_dir = utils::target_dir(); let target = utils::get_target(); env::set_current_dir(utils::bench_root_path()) .context("failed to set working directory to bench root")?; let now = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .context("failed to get current time")?; let timestamp = format!("{}", now.as_secs()); println!("Running execution time benchmarks..."); let exec_time = run_exec_time(target)?; println!("Getting binary sizes..."); let binary_size = get_binary_sizes(&target_dir, target)?; println!("Analyzing cargo dependencies..."); let cargo_deps = cargo_deps(); let mut new_data = utils::BenchResult { created_at: timestamp, sha1: { let output = utils::run_collect(&["git", "rev-parse", "HEAD"])?; output.0.trim().to_string() }, exec_time, binary_size, cargo_deps, ..Default::default() }; if cfg!(target_os = "linux") { println!("Running Linux-specific benchmarks..."); run_strace_benchmarks(&mut new_data, target)?; new_data.max_memory = run_max_mem_benchmark(target)?; } println!("===== "); serde_json::to_writer_pretty(std::io::stdout(), &new_data) .context("failed to serialize benchmark results")?; println!("\n===== "); let bench_file = target_dir.join("bench.json"); if let Some(filename) = bench_file.to_str() { utils::write_json(filename, &serde_json::to_value(&new_data)?) .context("failed to write benchmark results to file")?; println!("Results written to: {filename}"); } else { eprintln!("Cannot write bench.json, path contains invalid UTF-8"); } Ok(()) } ================================================ FILE: bench/src/utils.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT //! Utility functions for benchmarking tasks in the Tauri project. //! //! This module provides helpers for: //! - Paths to project directories and targets //! - Running and collecting process outputs //! - Parsing memory profiler (`mprof`) and syscall profiler (`strace`) outputs //! - JSON read/write utilities //! - File download utilities (via `curl` or file copy) use anyhow::{bail, Context, Result}; use serde::{Deserialize, Serialize}; use serde_json::Value; use std::{ collections::HashMap, fs, io::{BufRead, BufReader}, path::PathBuf, process::{Command, Output, Stdio}, }; /// Holds the results of a benchmark run. #[derive(Default, Clone, Serialize, Deserialize, Debug)] pub struct BenchResult { pub created_at: String, pub sha1: String, pub exec_time: HashMap>, pub binary_size: HashMap, pub max_memory: HashMap, pub thread_count: HashMap, pub syscall_count: HashMap, pub cargo_deps: HashMap, } /// Represents a single line of parsed `strace` output. #[derive(Debug, Clone, Serialize)] pub struct StraceOutput { pub percent_time: f64, pub seconds: f64, pub usecs_per_call: Option, pub calls: u64, pub errors: u64, } /// Get the compilation target triple for the current platform. pub fn get_target() -> &'static str { #[cfg(target_os = "macos")] return if cfg!(target_arch = "aarch64") { "aarch64-apple-darwin" } else { "x86_64-apple-darwin" }; #[cfg(target_os = "ios")] return if cfg!(target_arch = "aarch64") { "aarch64-apple-ios" } else { "x86_64-apple-ios" }; #[cfg(target_os = "linux")] return "x86_64-unknown-linux-gnu"; #[cfg(target_os = "windows")] unimplemented!("Windows target not implemented yet"); } /// Get the `target/release` directory path for benchmarks. pub fn target_dir() -> PathBuf { bench_root_path() .join("..") .join("target") .join(get_target()) .join("release") } /// Get the root path of the current benchmark crate. pub fn bench_root_path() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")) } /// Get the home directory of the current user. pub fn home_path() -> PathBuf { #[cfg(any(target_os = "macos", target_os = "ios", target_os = "linux"))] { PathBuf::from(std::env::var("HOME").unwrap_or_default()) } #[cfg(target_os = "windows")] { PathBuf::from(std::env::var("USERPROFILE").unwrap_or_default()) } } /// Get the root path of the Tauri repository. pub fn tauri_root_path() -> PathBuf { bench_root_path().parent().map(|p| p.to_path_buf()).unwrap() } /// Run a command and collect its stdout and stderr as strings. /// Returns an error if the command fails or exits with a non-zero status. pub fn run_collect(cmd: &[&str]) -> Result<(String, String)> { let output: Output = Command::new(cmd[0]) .args(&cmd[1..]) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .output() .with_context(|| format!("failed to execute command: {cmd:?}"))?; if !output.status.success() { bail!( "Command {:?} exited with {:?}\nstdout:\n{}\nstderr:\n{}", cmd, output.status.code(), String::from_utf8_lossy(&output.stdout), String::from_utf8_lossy(&output.stderr) ); } Ok(( String::from_utf8_lossy(&output.stdout).to_string(), String::from_utf8_lossy(&output.stderr).to_string(), )) } /// Parse a memory profiler (`mprof`) output file and return the maximum /// memory usage in bytes. Returns `None` if no values are found. pub fn parse_max_mem(file_path: &str) -> Result> { let file = fs::File::open(file_path) .with_context(|| format!("failed to open mprof output file {file_path}"))?; let output = BufReader::new(file); let mut highest: u64 = 0; for line in output.lines().map_while(Result::ok) { let split: Vec<&str> = line.split(' ').collect(); if split.len() == 3 { if let Ok(mb) = split[1].parse::() { let current_bytes = (mb * 1024.0 * 1024.0) as u64; highest = highest.max(current_bytes); } } } // Best-effort cleanup let _ = fs::remove_file(file_path); Ok(if highest > 0 { Some(highest) } else { None }) } /// Parse the output of `strace -c` and return a summary of syscalls. pub fn parse_strace_output(output: &str) -> HashMap { let mut summary = HashMap::new(); let mut lines = output .lines() .filter(|line| !line.is_empty() && !line.contains("detached ...")); let count = lines.clone().count(); if count < 4 { return summary; } let total_line = lines.next_back().unwrap(); lines.next_back(); // Drop separator let data_lines = lines.skip(2); for line in data_lines { let syscall_fields: Vec<&str> = line.split_whitespace().collect(); let len = syscall_fields.len(); if let Some(&syscall_name) = syscall_fields.last() { if (5..=6).contains(&len) { let output = StraceOutput { percent_time: syscall_fields[0].parse().unwrap_or(0.0), seconds: syscall_fields[1].parse().unwrap_or(0.0), usecs_per_call: syscall_fields[2].parse().ok(), calls: syscall_fields[3].parse().unwrap_or(0), errors: if len < 6 { 0 } else { syscall_fields[4].parse().unwrap_or(0) }, }; summary.insert(syscall_name.to_string(), output); } } } let total_fields: Vec<&str> = total_line.split_whitespace().collect(); let total = match total_fields.len() { 5 => StraceOutput { percent_time: total_fields[0].parse().unwrap_or(0.0), seconds: total_fields[1].parse().unwrap_or(0.0), usecs_per_call: None, calls: total_fields[2].parse().unwrap_or(0), errors: total_fields[3].parse().unwrap_or(0), }, 6 => StraceOutput { percent_time: total_fields[0].parse().unwrap_or(0.0), seconds: total_fields[1].parse().unwrap_or(0.0), usecs_per_call: total_fields[2].parse().ok(), calls: total_fields[3].parse().unwrap_or(0), errors: total_fields[4].parse().unwrap_or(0), }, _ => { panic!("Unexpected total field count: {}", total_fields.len()); } }; summary.insert("total".to_string(), total); summary } /// Run a command and wait for completion. /// Returns an error if the command fails. pub fn run(cmd: &[&str]) -> Result<()> { let status = Command::new(cmd[0]) .args(&cmd[1..]) .stdin(Stdio::piped()) .status() .with_context(|| format!("failed to execute command: {cmd:?}"))?; if !status.success() { bail!("Command {:?} exited with {:?}", cmd, status.code()); } Ok(()) } /// Read a JSON file into a [`serde_json::Value`]. pub fn read_json(filename: &str) -> Result { let f = fs::File::open(filename).with_context(|| format!("failed to open JSON file {filename}"))?; Ok(serde_json::from_reader(f)?) } /// Write a [`serde_json::Value`] into a JSON file. pub fn write_json(filename: &str, value: &Value) -> Result<()> { let f = fs::File::create(filename).with_context(|| format!("failed to create JSON file {filename}"))?; serde_json::to_writer(f, value)?; Ok(()) } /// Download a file from either a local path or an HTTP/HTTPS URL. /// Falls back to copying the file if the URL does not start with http/https. pub fn download_file(url: &str, filename: PathBuf) -> Result<()> { if !url.starts_with("http:") && !url.starts_with("https:") { fs::copy(url, &filename).with_context(|| format!("failed to copy from {url}"))?; return Ok(()); } println!("Downloading {url}"); let status = Command::new("curl") .arg("-L") .arg("-s") .arg("-o") .arg(&filename) .arg(url) .status() .with_context(|| format!("failed to execute curl for {url}"))?; if !status.success() { bail!("curl failed with exit code {:?}", status.code()); } if !filename.exists() { bail!("expected file {:?} to exist after download", filename); } Ok(()) } ================================================ FILE: bench/tests/cpu_intensive/public/index.css ================================================ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; margin: auto; max-width: 38rem; padding: 2rem; } ================================================ FILE: bench/tests/cpu_intensive/public/index.html ================================================ Hello World!

Calculate prime numbers

================================================ FILE: bench/tests/cpu_intensive/public/site.js ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT // Create web worker const THRESHOLD = 10000000 const worker = new Worker('worker.js') /** @type {HTMLButtonElement} */ const start = document.getElementById('start') /** @type {HTMLParagraphElement} */ const status = document.getElementById('status') const results = document.getElementById('results') const ITERATIONS = 1 let resolver const onMessage = (message) => { // Update the UI let prefix = '[Calculating]' if (message.data.status === 'done') { // tell tauri that we are done window.__TAURI__.core.invoke('app_completed_successfully') } status.innerHTML = `${prefix} Found ${message.data.count} prime numbers in ${message.data.time}ms` if (message.data.status === 'done') { resolver(message.data.time) } } worker.addEventListener('message', onMessage) const benchmark = () => { return new Promise((resolve) => { const startTime = Date.now() resolver = resolve worker.postMessage({ value: THRESHOLD, startTime }) }) } const calculate = async () => { let total = 0 for (let i = 0; i < ITERATIONS; i++) { const result = await benchmark() total += result } const average = total / ITERATIONS results.innerText = `Average time: ${average}ms` } window.addEventListener('DOMContentLoaded', calculate) ================================================ FILE: bench/tests/cpu_intensive/public/worker.js ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT const isPrime = (number) => { if (number % 2 === 0 && number > 2) { return false } let start = 2 const limit = Math.sqrt(number) while (start <= limit) { if (number % start++ < 1) { return false } } return number > 1 } addEventListener('message', (e) => { const { startTime } = e.data let n = 0 let total = 0 const THRESHOLD = e.data.value const primes = [] let previous = startTime while (++n <= THRESHOLD) { if (isPrime(n)) { primes.push(n) total++ const now = Date.now() if (now - previous > 250) { previous = now postMessage({ status: 'calculating', count: total, time: Date.now() - startTime }) } } } postMessage({ status: 'done', count: total, time: Date.now() - startTime }) }) ================================================ FILE: bench/tests/cpu_intensive/src-tauri/.gitignore ================================================ # Generated by Cargo # will have compiled files and executables /target/ ================================================ FILE: bench/tests/cpu_intensive/src-tauri/Cargo.toml ================================================ [package] name = "bench_cpu_intensive" version = "0.1.0" description = "A very simple Tauri Application" edition = "2021" rust-version = "1.77.2" [build-dependencies] tauri-build = { path = "../../../../crates/tauri-build", features = [ "codegen", ] } [dependencies] serde_json = "1" serde = { version = "1", features = ["derive"] } tauri = { path = "../../../../crates/tauri", features = [] } ================================================ FILE: bench/tests/cpu_intensive/src-tauri/build.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT fn main() { tauri_build::build() } ================================================ FILE: bench/tests/cpu_intensive/src-tauri/src/main.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] #[tauri::command] fn app_completed_successfully() { std::process::exit(0); } fn main() { tauri::Builder::default() .invoke_handler(tauri::generate_handler![app_completed_successfully]) .run(tauri::generate_context!()) .expect("error while running tauri application"); } ================================================ FILE: bench/tests/cpu_intensive/src-tauri/tauri.conf.json ================================================ { "$schema": "../../../../crates/tauri-schema-generator/schemas/config.schema.json", "identifier": "com.tauri.dev", "build": { "frontendDist": "../public" }, "app": { "withGlobalTauri": true, "windows": [ { "title": "Welcome to Tauri!", "width": 800, "height": 600, "resizable": true, "fullscreen": false } ], "security": { "csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self'; connect-src ipc: http://ipc.localhost" } }, "bundle": { "active": true, "targets": "all", "icon": [ "../../../../examples/.icons/32x32.png", "../../../../examples/.icons/128x128.png", "../../../../examples/.icons/128x128@2x.png", "../../../../examples/.icons/icon.icns", "../../../../examples/.icons/icon.ico" ] } } ================================================ FILE: bench/tests/files_transfer/public/index.html ================================================ Welcome to Tauri!

Welcome to Tauri!

================================================ FILE: bench/tests/files_transfer/src-tauri/.gitignore ================================================ # Generated by Cargo # will have compiled files and executables /target/ ================================================ FILE: bench/tests/files_transfer/src-tauri/Cargo.toml ================================================ [package] name = "bench_files_transfer" version = "0.1.0" description = "A very simple Tauri Application" edition = "2021" rust-version = "1.77.2" [build-dependencies] tauri-build = { path = "../../../../crates/tauri-build", features = [ "codegen", ] } [dependencies] serde_json = "1" serde = { version = "1", features = ["derive"] } tauri = { path = "../../../../crates/tauri", features = [] } ================================================ FILE: bench/tests/files_transfer/src-tauri/build.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT fn main() { tauri_build::build() } ================================================ FILE: bench/tests/files_transfer/src-tauri/src/main.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] use std::fs::read; use tauri::{command, ipc::Response, path::BaseDirectory, AppHandle, Manager, Runtime}; #[command] fn app_should_close(exit_code: i32) { std::process::exit(exit_code); } #[command] async fn read_file(app: AppHandle) -> Result { let path = app .path() .resolve(".tauri_3mb.json", BaseDirectory::Home) .map_err(|e| e.to_string())?; let contents = read(path).map_err(|e| e.to_string())?; Ok(Response::new(contents)) } fn main() { tauri::Builder::default() .invoke_handler(tauri::generate_handler![app_should_close, read_file]) .run(tauri::generate_context!()) .expect("error while running tauri application"); } ================================================ FILE: bench/tests/files_transfer/src-tauri/tauri.conf.json ================================================ { "$schema": "../../../../crates/tauri-schema-generator/schemas/config.schema.json", "identifier": "com.tauri.dev", "build": { "frontendDist": "../public" }, "app": { "withGlobalTauri": true, "windows": [ { "title": "Welcome to Tauri!", "width": 800, "height": 600, "resizable": true, "fullscreen": false } ], "security": { "csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self'; connect-src ipc: http://ipc.localhost" } }, "bundle": { "active": true, "targets": "all", "icon": [ "../../../../examples/.icons/32x32.png", "../../../../examples/.icons/128x128.png", "../../../../examples/.icons/128x128@2x.png", "../../../../examples/.icons/icon.icns", "../../../../examples/.icons/icon.ico" ] } } ================================================ FILE: bench/tests/helloworld/public/index.html ================================================ Welcome to Tauri!

Welcome to Tauri!

================================================ FILE: bench/tests/helloworld/src-tauri/.gitignore ================================================ # Generated by Cargo # will have compiled files and executables /target/ ================================================ FILE: bench/tests/helloworld/src-tauri/Cargo.toml ================================================ [package] name = "bench_helloworld" version = "0.1.0" description = "A very simple Tauri Application" edition = "2021" rust-version = "1.77.2" [build-dependencies] tauri-build = { path = "../../../../crates/tauri-build", features = [ "codegen", ] } [dependencies] serde_json = "1" serde = { version = "1", features = ["derive"] } tauri = { path = "../../../../crates/tauri", features = [] } ================================================ FILE: bench/tests/helloworld/src-tauri/build.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT fn main() { tauri_build::build() } ================================================ FILE: bench/tests/helloworld/src-tauri/src/main.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] #[tauri::command] fn app_loaded_successfully() { std::process::exit(0); } fn main() { tauri::Builder::default() .invoke_handler(tauri::generate_handler![app_loaded_successfully]) .run(tauri::generate_context!()) .expect("error while running tauri application"); } ================================================ FILE: bench/tests/helloworld/src-tauri/tauri.conf.json ================================================ { "$schema": "../../../../crates/tauri-schema-generator/schemas/config.schema.json", "identifier": "com.tauri.dev", "build": { "frontendDist": "../public", "beforeDevCommand": "", "beforeBuildCommand": "" }, "app": { "withGlobalTauri": true, "windows": [ { "title": "Welcome to Tauri!", "width": 800, "height": 600, "resizable": true, "fullscreen": false } ], "security": { "csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self'; connect-src ipc: http://ipc.localhost" } }, "bundle": { "active": true, "targets": "all", "icon": [ "../../../../examples/.icons/32x32.png", "../../../../examples/.icons/128x128.png", "../../../../examples/.icons/128x128@2x.png", "../../../../examples/.icons/icon.icns", "../../../../examples/.icons/icon.ico" ] } } ================================================ FILE: crates/tauri/.scripts/loop_qc.sh ================================================ #!/bin/bash # Copyright 2019-2024 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT # Loop all quickcheck tests for tauri. while true do cargo test qc_ if [[ x$? != x0 ]] ; then exit $? fi done ================================================ FILE: crates/tauri/CHANGELOG.md ================================================ # Changelog ## \[2.10.3] ### Dependencies - Upgraded to `tauri-utils@2.8.3` - Upgraded to `tauri-runtime@2.10.1` - Upgraded to `tauri-runtime-wry@2.10.1` - Upgraded to `tauri-macros@2.5.5` - Upgraded to `tauri-build@2.5.6` ## \[2.10.2] ### Dependencies - Upgraded to `tauri-macros@2.5.4` - Upgraded to `tauri-build@2.5.5` ## \[2.10.1] ### Dependencies - [`ce8fddb46`](https://www.github.com/tauri-apps/tauri/commit/ce8fddb4648d6421579d43c7dd44959bc57a74e0) ([#14873](https://www.github.com/tauri-apps/tauri/pull/14873)) Unlocked version range for webkit2gtk-rs dependency. ## \[2.10.0] ### New Features - [`e919a760e`](https://www.github.com/tauri-apps/tauri/commit/e919a760edfc115f9e4b5d841e29cc38d5535ed1) ([#14619](https://www.github.com/tauri-apps/tauri/pull/14619) by [@NaamuKim](https://www.github.com/tauri-apps/tauri/../../NaamuKim)) Add `set_simple_fullscreen` method to `WebviewWindow`. This method was already available on the `Window` type and is now also available on `WebviewWindow` for consistency. On macOS, it toggles fullscreen mode without creating a new macOS Space. On other platforms, it falls back to regular fullscreen. ### Bug Fixes - [`853ed4642`](https://www.github.com/tauri-apps/tauri/commit/853ed4642ff77154ccd380dd9289d90815d42691) ([#14442](https://www.github.com/tauri-apps/tauri/pull/14442) by [@ish1416](https://www.github.com/tauri-apps/tauri/../../ish1416)) Fixed 500 error when accessing local video files in Android external storage directory via `convertFileSrc`. Added better error handling and logging for Android external storage access to help diagnose permission and accessibility issues. - [`4d5d78daf`](https://www.github.com/tauri-apps/tauri/commit/4d5d78daf636feaac20c5bc48a6071491c4291ee) ([#14812](https://www.github.com/tauri-apps/tauri/pull/14812) by [@oscartbeaumont](https://www.github.com/tauri-apps/tauri/../../oscartbeaumont)) fix(specta): don't use `#[specta(rename = ...)]` with `tauri::ipc::Channel` - [`ff5d76ca2`](https://www.github.com/tauri-apps/tauri/commit/ff5d76ca214b94a7b6e88aa4f0f797bbf747824d) ([#14653](https://www.github.com/tauri-apps/tauri/pull/14653) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) `WindowConfig::focus` is set to `false` in `WindowConfig::default()` ### What's Changed - [`0575dd287`](https://www.github.com/tauri-apps/tauri/commit/0575dd287e021b61d2aedf64d62ae84a2c925fb4) ([#14521](https://www.github.com/tauri-apps/tauri/pull/14521) by [@kandrelczyk](https://www.github.com/tauri-apps/tauri/../../kandrelczyk)) Change the way bundle type information is added to binary files. Instead of looking up the value of a variable we simply look for the default value. ### Dependencies - Upgraded to `tauri-utils@2.8.2` - Upgraded to `tauri-build@2.5.4` - Upgraded to `tauri-runtime-wry@2.10.0` - Upgraded to `tauri-runtime@2.10.0` - Upgraded to `tauri-macros@2.5.3` - [`75057c7c0`](https://www.github.com/tauri-apps/tauri/commit/75057c7c08f0d4d3dd8d10cea4e2217e5d61fe1a) ([#14778](https://www.github.com/tauri-apps/tauri/pull/14778) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) **Breaking Change** for `with_webview` users: Updated webkit2gtk-rs crates to `v2.0.2`. - [`75057c7c0`](https://www.github.com/tauri-apps/tauri/commit/75057c7c08f0d4d3dd8d10cea4e2217e5d61fe1a) ([#14778](https://www.github.com/tauri-apps/tauri/pull/14778) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Update wry to `v0.54`. ## \[2.9.5] ### Bug Fixes - [`251203b89`](https://www.github.com/tauri-apps/tauri/commit/251203b8963419cb3b40741767393e8f3c909ef9) ([#14637](https://www.github.com/tauri-apps/tauri/pull/14637) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix `Monitor::work_area` returns logical position and size inside the `PhysicalRect` on Linux ### Dependencies - Upgraded to `tauri-runtime-wry@2.9.3` ## \[2.9.4] ### Performance Improvements - [`ce98d87ce`](https://www.github.com/tauri-apps/tauri/commit/ce98d87ce0aaa907285852eb80691197424e03c3) ([#14474](https://www.github.com/tauri-apps/tauri/pull/14474) by [@Tunglies](https://www.github.com/tauri-apps/tauri/../../Tunglies)) refactor: remove needless collect. No user facing changes. - [`ee3cc4a91`](https://www.github.com/tauri-apps/tauri/commit/ee3cc4a91bf1315ecaefe90f423ffd55ef6c40db) ([#14475](https://www.github.com/tauri-apps/tauri/pull/14475) by [@Tunglies](https://www.github.com/tauri-apps/tauri/../../Tunglies)) perf: remove needless clones in various files for improved performance. No user facing changes. ### Dependencies - Upgraded to `tauri-utils@2.8.1` - Upgraded to `tauri-runtime@2.9.2` - Upgraded to `tauri-runtime-wry@2.9.2` - Upgraded to `tauri-macros@2.5.2` - Upgraded to `tauri-build@2.5.3` ## \[2.9.3] ### Bug Fixes - [`4b00130b8`](https://www.github.com/tauri-apps/tauri/commit/4b00130b86a27b6f121bf57897b5e92d83bcc0fc) ([#14385](https://www.github.com/tauri-apps/tauri/pull/14385) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix iOS deadlock when running on the simulator from Xcode by properly piping stdout/stderr messages through the Xcode console and OSLog. ### Dependencies - Upgraded to `tauri-macros@2.5.1` - Upgraded to `tauri-build@2.5.2` ## \[2.9.2] ### Bug Fixes - [`28b9e7c7b`](https://www.github.com/tauri-apps/tauri/commit/28b9e7c7b83845c35fe46c37e8ed8e9022b4634e) ([#14377](https://www.github.com/tauri-apps/tauri/pull/14377) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix `undefined is not an object (evaluating '[callbackId, data]')` error on custom protocol IPC fails ## \[2.9.1] ### Bug Fixes - [`4b6b8690a`](https://www.github.com/tauri-apps/tauri/commit/4b6b8690ab886ebdf1307951cffbe03e31280baa) ([#14347](https://www.github.com/tauri-apps/tauri/pull/14347) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused docs.rs builds to fail. No user facing changes. ### Dependencies - Upgraded to `tauri-build@2.5.1` - Upgraded to `tauri-runtime@2.9.1` - Upgraded to `tauri-runtime-wry@2.9.1` ## \[2.9.0] ### New Features - [`f5851ee00`](https://www.github.com/tauri-apps/tauri/commit/f5851ee00d6d1f4d560a220ca5a728fedd525092) ([#14089](https://www.github.com/tauri-apps/tauri/pull/14089)) Adds the `scroll_bar_style` option to the Webview and WebviewWindow builders. The possible values for this option are gated behind conditional compilation flags, and will need to be applied using conditional compilation if customised. - [`3397fd9bf`](https://www.github.com/tauri-apps/tauri/commit/3397fd9bfe5f6b1337110149f6c34731b8a44bb3) ([#14133](https://www.github.com/tauri-apps/tauri/pull/14133)) Added mobile app plugin to support exit and back button press event. - [`68cb31897`](https://www.github.com/tauri-apps/tauri/commit/68cb318979317c09f401825150e007d60377e75e) ([#14328](https://www.github.com/tauri-apps/tauri/pull/14328)) Added `onStop`, `onDestroy`, `onRestart`, `onConfigurationChanged` Android plugin hooks. - [`2e089f6ac`](https://www.github.com/tauri-apps/tauri/commit/2e089f6acb854e4d7f8eafb9b2f8242b1c9fa491) ([#14148](https://www.github.com/tauri-apps/tauri/pull/14148)) Support async Swift plugin methods (`completionHandler:`) in PluginManager ### Bug Fixes - [`006d59283`](https://www.github.com/tauri-apps/tauri/commit/006d592837259cac87f15cf3ffc99e7fce97685e) ([#14260](https://www.github.com/tauri-apps/tauri/pull/14260)) Properly deserialize Android plugin args with key starting with `is` (previously treated as a getter instead of a field name). - [`69476d8e2`](https://www.github.com/tauri-apps/tauri/commit/69476d8e2314b85bf46046140bc5495fe29b7d29) ([#14170](https://www.github.com/tauri-apps/tauri/pull/14170)) Fix the stack overflow when having too many commands in a single invoke handler in release build ### Dependencies - Upgraded to `tauri-utils@2.8.0` - Upgraded to `tauri-runtime-wry@2.9.0` - Upgraded to `tauri-runtime@2.9.0` - Upgraded to `tauri-build@2.5.0` - Upgraded to `tauri-macros@2.5.0` ## \[2.8.5] ### Enhancements - [`07e134f70`](https://www.github.com/tauri-apps/tauri/commit/07e134f70e3a65424641f1b384a26bf059fd9c56) ([#14107](https://www.github.com/tauri-apps/tauri/pull/14107) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Improve error message for request errors on iOS when local network permission has been denied and the app tries to reach the development server. ### Dependencies - Upgraded to `tauri-build@2.4.1` ## \[2.8.4] ### Bug Fixes - [`03e7c1193`](https://www.github.com/tauri-apps/tauri/commit/03e7c1193208716170f120a1d4a39cea0bc21064) ([#14080](https://www.github.com/tauri-apps/tauri/pull/14080) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Ignore initial navigation to `about:blank` so `on_new_window` does not give a warning on first navigation on macOS. ### Dependencies - Upgraded to `tauri-runtime-wry@2.8.1` ## \[2.8.3] ### Bug Fixes - [`534998406`](https://www.github.com/tauri-apps/tauri/commit/534998406433a1be52caa9792d120763ab8339ac) ([#14054](https://www.github.com/tauri-apps/tauri/pull/14054) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused the runtime WebView2 detection to fail for FixedRuntime installations. ## \[2.8.2] ### Bug Fixes - [`5075b67d3`](https://www.github.com/tauri-apps/tauri/commit/5075b67d368e63e07df5bac5e43c24396460692d) ([#14039](https://www.github.com/tauri-apps/tauri/pull/14039) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix compilation when the `wry` Cargo feature is disabled. ## \[2.8.1] ### Bug Fixes - [`902727`](https://www.github.com/tauri-apps/tauri/commit/902727a6acea0bd9569b62ca243ae9563b4ed795) Move `WebviewWindowBuilder::with_related_view` behind the `wry` feature flag. ## \[2.8.0] ### New Features - [`68874c68c`](https://www.github.com/tauri-apps/tauri/commit/68874c68c566638b4c21a3aa67844d1bdaeb6dab) ([#13564](https://www.github.com/tauri-apps/tauri/pull/13564) by [@robertrpf](https://www.github.com/tauri-apps/tauri/../../robertrpf)) Add window focusable attribute and set_focusable API. - [`22d6bcacb`](https://www.github.com/tauri-apps/tauri/commit/22d6bcacbb2001eb292ebd8c5d021447700f9512) ([#14008](https://www.github.com/tauri-apps/tauri/pull/14008) by [@WSH032](https://www.github.com/tauri-apps/tauri/../../WSH032)) Implement `App::set_device_event_filter` for `AppHandle` also. - [`d6d5f3707`](https://www.github.com/tauri-apps/tauri/commit/d6d5f3707768a094ff7e961ae75ba0398d772655) ([#13358](https://www.github.com/tauri-apps/tauri/pull/13358) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Load root certificate from CLI-set environment variable and use it on the mobile dev server proxy. - [`33d0b3f0c`](https://www.github.com/tauri-apps/tauri/commit/33d0b3f0c133edebb1c716e2f5942d70509ae347) ([#13876](https://www.github.com/tauri-apps/tauri/pull/13876) by [@thlstsul](https://www.github.com/tauri-apps/tauri/../../thlstsul)) Added `WebviewBuilder::on_document_title_changed` and `WebviewWindowBuilder::on_document_title_changed`. - [`33d0b3f0c`](https://www.github.com/tauri-apps/tauri/commit/33d0b3f0c133edebb1c716e2f5942d70509ae347) ([#13876](https://www.github.com/tauri-apps/tauri/pull/13876) by [@thlstsul](https://www.github.com/tauri-apps/tauri/../../thlstsul)) Added `WebviewBuilder::on_new_window` and `WebviewWindowBuilder::on_new_window`. - [`7c2eb31c8`](https://www.github.com/tauri-apps/tauri/commit/7c2eb31c83a202b3481a6d560ae2048bcbe4157b) ([#13895](https://www.github.com/tauri-apps/tauri/pull/13895) by [@ahqsoftwares](https://www.github.com/tauri-apps/tauri/../../ahqsoftwares)) Introduces `PluginHandle::run_mobile_plugin_async` as an async alternative to `run_mobile_plugin` - [`dfadcb764`](https://www.github.com/tauri-apps/tauri/commit/dfadcb764bdf84089a5487005a7b4f3b7cf09494) ([#13661](https://www.github.com/tauri-apps/tauri/pull/13661) by [@WSH032](https://www.github.com/tauri-apps/tauri/../../WSH032)) Added `Webview::set_cookie()`, `Webview::delete_cookie()`, `WebviewWindow::set_cookie()` and `WebviewWindow::delete_cookie()`. - [`5110a762e`](https://www.github.com/tauri-apps/tauri/commit/5110a762e9db978a28a15400bf76e3c864da2a86) ([#13830](https://www.github.com/tauri-apps/tauri/pull/13830) by [@Sky-walkerX](https://www.github.com/tauri-apps/tauri/../../Sky-walkerX)) Added `Window::set_simple_fullscreen`. ### Enhancements - [`7261a1436`](https://www.github.com/tauri-apps/tauri/commit/7261a14368eeef040aee3350bb39183558d18bf0) ([#14012](https://www.github.com/tauri-apps/tauri/pull/14012) by [@WSH032](https://www.github.com/tauri-apps/tauri/../../WSH032)) Implemented `Webview::on_webview_event` for `WebviewWindow` as well - [`0e6b5cbe5`](https://www.github.com/tauri-apps/tauri/commit/0e6b5cbe5f44b53aca7aff22bc3ea1a9444b3209) ([#14009](https://www.github.com/tauri-apps/tauri/pull/14009) by [@WSH032](https://www.github.com/tauri-apps/tauri/../../WSH032)) re-export `PixelUnit`, `PhysicalUnit`, `LogicalUnit` - [`a3dc42477`](https://www.github.com/tauri-apps/tauri/commit/a3dc42477a9aae0471ecf3caa5812e9537532bbf) ([#14013](https://www.github.com/tauri-apps/tauri/pull/14013) by [@WSH032](https://www.github.com/tauri-apps/tauri/../../WSH032)) export `TitleBarStyle` for all platforms. - [`f1232671a`](https://www.github.com/tauri-apps/tauri/commit/f1232671abc15f03118a35da1883ce9aca88ff2a) ([#13959](https://www.github.com/tauri-apps/tauri/pull/13959) by [@petersamokhin](https://www.github.com/tauri-apps/tauri/../../petersamokhin)) Introduce `with_inner_tray_icon` for Tauri `TrayIcon` to access the inner platform-specific tray icon. Note that `tray-icon` crate may be updated in minor releases of Tauri. Therefore, it's recommended to pin Tauri to at least a minor version when you're using `with_inner_tray_icon`. - [`72b4226ee`](https://www.github.com/tauri-apps/tauri/commit/72b4226ee9932b4dafa4837a49420b2c02d14bb7) ([#13809](https://www.github.com/tauri-apps/tauri/pull/13809) by [@Beanow](https://www.github.com/tauri-apps/tauri/../../Beanow)) Reduced `Debug` format size for binary buffers. - [`21ebc6e82`](https://www.github.com/tauri-apps/tauri/commit/21ebc6e82062b55a12f3a360d9a979daf5ae7e66) ([#14007](https://www.github.com/tauri-apps/tauri/pull/14007) by [@WSH032](https://www.github.com/tauri-apps/tauri/../../WSH032)) Changed the parameter type of `AppHandle::remove_plugin` from `&'static str` to `&str`. - [`5ba1c3faa`](https://www.github.com/tauri-apps/tauri/commit/5ba1c3faa468073512bdb5035a01f7f99720fcf0) ([#13722](https://www.github.com/tauri-apps/tauri/pull/13722) by [@s00d](https://www.github.com/tauri-apps/tauri/../../s00d)) Added icon (icon and nativeIcon) support for Submenu: - In the Rust API (`tauri`), you can now set an icon for submenus via the builder and dedicated methods. - In the JS/TS API (`@tauri-apps/api`), `SubmenuOptions` now has an `icon` field, and the `Submenu` class provides `setIcon` and `setNativeIcon` methods. - Usage examples are added to the documentation and demo app. This is a backwards-compatible feature. Submenus can now display icons just like regular menu items. ### Dependencies - Upgraded to `tauri-utils@2.7.0` - Upgraded to `tauri-runtime-wry@2.8.0` - Upgraded to `tauri-runtime@2.8.0` - Upgraded to `tauri-macros@2.3.3` - Upgraded to `tauri-build@2.3.2` ## \[2.7.0] ### New Features - [`7bc77a038`](https://www.github.com/tauri-apps/tauri/commit/7bc77a038af062a02aabeaf9b228577447bad5e5) ([#13609](https://www.github.com/tauri-apps/tauri/pull/13609) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Added `tauri::plugin::Builder::js_init_script_on_all_frames` that allows plugins to add initialization scripts that runs on all frames ### Enhancements - [`7f3c98911`](https://www.github.com/tauri-apps/tauri/commit/7f3c989111e007d7eeb5da118421214848e4bfcd) ([#13837](https://www.github.com/tauri-apps/tauri/pull/13837) by [@WSH032](https://www.github.com/tauri-apps/tauri/../../WSH032)) Add `AppHandle::plugin_boxed` and `Builder::plugin_boxed` methods to allow adding plugins in the form of boxed trait objects. - [`7bc77a038`](https://www.github.com/tauri-apps/tauri/commit/7bc77a038af062a02aabeaf9b228577447bad5e5) ([#13609](https://www.github.com/tauri-apps/tauri/pull/13609) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) `tauri::plugin::Builder::js_init_script` now takes `impl Into` instead of `String` ### Bug Fixes - [`6a4451bcd`](https://www.github.com/tauri-apps/tauri/commit/6a4451bcd9cf5a2428857d2e47ea25e3d74712ae) ([#13849](https://www.github.com/tauri-apps/tauri/pull/13849) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix isolation pattern creates iframes within iframes on Windows - [`4ba871c5d`](https://www.github.com/tauri-apps/tauri/commit/4ba871c5d2eb3fbb8db56c8d8f9916e65d3e34ac) ([#13782](https://www.github.com/tauri-apps/tauri/pull/13782) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes loading external URLs in mobile development mode. - [`1c5df96fe`](https://www.github.com/tauri-apps/tauri/commit/1c5df96fe8542e815cd887e66c29efb268add710) ([#13773](https://www.github.com/tauri-apps/tauri/pull/13773) by [@tasgon](https://www.github.com/tauri-apps/tauri/../../tasgon)) Forward request body on the mobile frontend proxy. ### Dependencies - Upgraded to `tauri-runtime-wry@2.7.2` - Upgraded to `tauri-utils@2.6.0` - Upgraded to `tauri-runtime@2.7.1` - Upgraded to `tauri-macros@2.3.2` - Upgraded to `tauri-build@2.3.1` ## \[2.6.2] ### Dependencies - Upgraded to `tauri-runtime-wry@2.7.1` ## \[2.6.1] ### Bug Fixes - [`5bbcaaec8`](https://www.github.com/tauri-apps/tauri/commit/5bbcaaec891c3011b147caed8908a5d043a34f48) ([#13707](https://www.github.com/tauri-apps/tauri/pull/13707) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix a regression that the JavaScript API can no longer set menus and icons for tray icons ### Dependencies - Upgraded to `tauri-macros@2.3.1` ## \[2.6.0] ### New Features - [`50ebddaa2`](https://www.github.com/tauri-apps/tauri/commit/50ebddaa2d83033a393a176ba07ef28352b98210) ([#13319](https://www.github.com/tauri-apps/tauri/pull/13319) by [@kingsword09](https://www.github.com/tauri-apps/tauri/../../kingsword09)) Expose the `setAutoResize` API for webviews in `@tauri-apps/api`. - [`267368fd4`](https://www.github.com/tauri-apps/tauri/commit/267368fd4f83e0a71dfb1b72a66d56592a2066bc) ([#13276](https://www.github.com/tauri-apps/tauri/pull/13276) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `Monitor::work_area` getter - [`267368fd4`](https://www.github.com/tauri-apps/tauri/commit/267368fd4f83e0a71dfb1b72a66d56592a2066bc) ([#13276](https://www.github.com/tauri-apps/tauri/pull/13276) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Added `tauri::PhysicalRect` and `tauri::LogicalRect` types. - [`09c19932d`](https://www.github.com/tauri-apps/tauri/commit/09c19932d2ddf05f28bcdc73796a966532e7ca1c) ([#13304](https://www.github.com/tauri-apps/tauri/pull/13304) by [@39zde](https://www.github.com/tauri-apps/tauri/../../39zde)) Adds the option to configure the HTTP `Service-Worker-Allowed` response header in `app > security > headers` - [`9c16eefa3`](https://www.github.com/tauri-apps/tauri/commit/9c16eefa319b4697bac1d1019bbb5f93eca63173) ([#13629](https://www.github.com/tauri-apps/tauri/pull/13629) by [@sftse](https://www.github.com/tauri-apps/tauri/../../sftse)) Added `x11` Cargo feature (enabled by default). Disabling it is useful for apps that only support Wayland, reducing its size. **NOTE**: When manually disabling tauri default features, you must enable the `x11` feature to support it. ### Enhancements - [`96ecfca42`](https://www.github.com/tauri-apps/tauri/commit/96ecfca428e4e5d9ff5d5eeed3f94a06a466ed02) ([#13406](https://www.github.com/tauri-apps/tauri/pull/13406) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Check if the webview runtime is accessible when creating a webview, returning an error if it doesn't. ### Bug Fixes - [`94b77b36e`](https://www.github.com/tauri-apps/tauri/commit/94b77b36e35cd8396a5589fbcce26cf44f43d938) ([#13288](https://www.github.com/tauri-apps/tauri/pull/13288) by [@oscartbeaumont](https://www.github.com/tauri-apps/tauri/../../oscartbeaumont)) Prevent the JavaScript runtime crashing when channel events fire in a webview that no longer has callbacks for the channel. - [`bc2f0e48a`](https://www.github.com/tauri-apps/tauri/commit/bc2f0e48acba5c1c99b9fceb1000863c47df89ef) ([#13401](https://www.github.com/tauri-apps/tauri/pull/13401) by [@oscartbeaumont](https://www.github.com/tauri-apps/tauri/../../oscartbeaumont)) fix(macOS): caculation for work area - [`dfacb656d`](https://www.github.com/tauri-apps/tauri/commit/dfacb656d266de5d99656b1513eacc0f498f0b0a) ([#13360](https://www.github.com/tauri-apps/tauri/pull/13360) by [@velocitysystems](https://www.github.com/tauri-apps/tauri/../../velocitysystems)) Fixes multiple event listeners registration for iOS plugins. - [`23b9da75b`](https://www.github.com/tauri-apps/tauri/commit/23b9da75b91379cca9520bc53b10fdf39ebae241) ([#13324](https://www.github.com/tauri-apps/tauri/pull/13324) by [@kingsword09](https://www.github.com/tauri-apps/tauri/../../kingsword09)) Fixed path joining behavior where `path.join('', 'a')` incorrectly returns "/a" instead of "a". - [`638804e9c`](https://www.github.com/tauri-apps/tauri/commit/638804e9c488afdcd51bff8f329a321903337263) ([#13423](https://www.github.com/tauri-apps/tauri/pull/13423) by [@kingsword09](https://www.github.com/tauri-apps/tauri/../../kingsword09)) Fixed set_window_effects not runs on main thread in WindowBuilder. - [`039f44b7b`](https://www.github.com/tauri-apps/tauri/commit/039f44b7b1ecd411e3b3406aa28ccb8e8a0ec63a) ([#13307](https://www.github.com/tauri-apps/tauri/pull/13307) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix `TrayIcon.getById` returning a new resource ID instead of reusing a previously created id from `TrayIcon.new`. - [`76cbeef20`](https://www.github.com/tauri-apps/tauri/commit/76cbeef20848d9adf95c0e95ca17058dbf76fe1e) ([#13278](https://www.github.com/tauri-apps/tauri/pull/13278) by [@situ2001](https://www.github.com/tauri-apps/tauri/../../situ2001)) Fix JavaScript API `Webview.proxyUrl` had no effect when used in the `Webview` constructor - [`b985eaf0a`](https://www.github.com/tauri-apps/tauri/commit/b985eaf0a231ea570e36d686c665cddbc76ab4f6) ([#13306](https://www.github.com/tauri-apps/tauri/pull/13306) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Immediately unregister event listener when the unlisten function is called. ### Performance Improvements - [`6a39f4999`](https://www.github.com/tauri-apps/tauri/commit/6a39f49991e613e8f3befe0e8dff288482ccdd89) ([#13464](https://www.github.com/tauri-apps/tauri/pull/13464) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Use dynamic dispatch for async commands in dev, this should speed up the compilation time by quite a bit, and significantly reduces the incremental compilation time ### What's Changed - [`168629646`](https://www.github.com/tauri-apps/tauri/commit/168629646335f24cc7f1c4a61df22688b2198f98) ([#13418](https://www.github.com/tauri-apps/tauri/pull/13418) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Put dynamic ACL into a feature `dynamic-acl`, this is currently enabled by default to align with the previous behaviors, you can disable it through `default-features = false` to reduce the final binary size by not including the ACL references - [`b5c549d18`](https://www.github.com/tauri-apps/tauri/commit/b5c549d1898ecdb712822c02dc665cc6771fbd07) ([#13325](https://www.github.com/tauri-apps/tauri/pull/13325) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) `transformCallback` now registers the callbacks inside `window.__TAURI_INTERNALS__.callbacks` instead of directly on `window['_{id}']` ### Dependencies - Upgraded to `tauri-utils@2.5.0` - Upgraded to `tauri-runtime-wry@2.7.0` - Upgraded to `tauri-macros@2.3.0` - Upgraded to `tauri-build@2.3.0` - Upgraded to `tauri-runtime@2.7.0` - [`9c16eefa3`](https://www.github.com/tauri-apps/tauri/commit/9c16eefa319b4697bac1d1019bbb5f93eca63173) ([#13629](https://www.github.com/tauri-apps/tauri/pull/13629) by [@sftse](https://www.github.com/tauri-apps/tauri/../../sftse)) Updated tao to 0.34, wry to 0.52 and webview2-com to 0.38. ### Breaking Changes - [`b7cdb3b39`](https://www.github.com/tauri-apps/tauri/commit/b7cdb3b39ef7e84773ce9312535825801350fa20) ([#13410](https://www.github.com/tauri-apps/tauri/pull/13410) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Feature gated the HTML manipulation code in `tauri-utils` behined a flag to reduce compile time ## \[2.5.1] ### Enhancements - [`31becbd1d`](https://www.github.com/tauri-apps/tauri/commit/31becbd1d19ae75d82854d7d28e7b204be0d9a4c) ([#13269](https://www.github.com/tauri-apps/tauri/pull/13269) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Respect `data-tauri-drag-region="false"`, it will no longer start dragging. This is useful when binding the attribute to a state using React, or another framework. ### Bug Fixes - [`da2a6ae5e`](https://www.github.com/tauri-apps/tauri/commit/da2a6ae5e396aace7d90d15f150294241a6ba0e2) ([#13268](https://www.github.com/tauri-apps/tauri/pull/13268) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix a regression that made the raw type messages received from `Channel.onmessage` became `number[]` instead of `ArrayBuffer` when that message is small - [`85b191252`](https://www.github.com/tauri-apps/tauri/commit/85b19125294917e10e89fc9e09722eaaa4f69962) ([#13241](https://www.github.com/tauri-apps/tauri/pull/13241) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Make `tauri-runtime-wry` optional even with features like `macos-private-api` ## \[2.5.0] ### New Features - [`dd4f13ce4`](https://www.github.com/tauri-apps/tauri/commit/dd4f13ce4b3cd89cde2fa3f18a063c272f215621) ([#13185](https://www.github.com/tauri-apps/tauri/pull/13185)) MacOS: Add `set_dock_visibility` method to support setting the visibility of the application in the dock. - [`8cf662e34`](https://www.github.com/tauri-apps/tauri/commit/8cf662e34bf738a0d16bb7b9aeb35667e2e4984b) ([#13076](https://www.github.com/tauri-apps/tauri/pull/13076)) - add API to run initialization scripts on all frames \- `WebviewBuilder::initialization_script_on_all_frames` \- `WebviewWindowBuilder::initialization_script_on_all_frames` \- `WebviewAttributes::initialization_script_on_all_frames` - [`ea36294cb`](https://www.github.com/tauri-apps/tauri/commit/ea36294cbca98f7725c91d1464fd92e77c89698a) ([#13208](https://www.github.com/tauri-apps/tauri/pull/13208)) Added `WebviewWindowBuilder::with_input_accessory_view_builder` and `WebviewBuilder::with_input_accessory_view_builder` on iOS. - [`c1cd0a2dd`](https://www.github.com/tauri-apps/tauri/commit/c1cd0a2ddb5bc3e99451cbe399b5fc9f0035f571) ([#13090](https://www.github.com/tauri-apps/tauri/pull/13090)) macOS/iOS: add option to disable or enable link previews when building a webview (the webkit api has it enabled by default) - `WebViewBuilder.allow_link_preview(allow_link_preview: bool)` - `WebviewWindowBuilder.allow_link_preview(allow_link_preview: bool)` - [`b072e2b29`](https://www.github.com/tauri-apps/tauri/commit/b072e2b2967640ae4fa1af466ae878c156551edd) ([#9687](https://www.github.com/tauri-apps/tauri/pull/9687)) Add `preventOverflow` config option to prevent the window from overflowing the monitor size on creation - [`b072e2b29`](https://www.github.com/tauri-apps/tauri/commit/b072e2b2967640ae4fa1af466ae878c156551edd) ([#9687](https://www.github.com/tauri-apps/tauri/pull/9687)) Add `WindowBuilder::prevent_overflow`, `WebviewWindowBuilder::prevent_overflow`, `WindowBuilder::prevent_overflow_with_margin` and `WebviewWindowBuilder::prevent_overflow_with_margin` APIs to prevent the window from overflowing the monitor size on creation. ### Enhancements - [`9356fa15d`](https://www.github.com/tauri-apps/tauri/commit/9356fa15d87e14b4512fe1b86383a597e6e641d4) ([#13239](https://www.github.com/tauri-apps/tauri/pull/13239)) Enhance panic message when fetching unmanaged state. - [`ebd3dcb92`](https://www.github.com/tauri-apps/tauri/commit/ebd3dcb92f8c0381daf6f5fdb2eaeef05f11bb6c) ([#13135](https://www.github.com/tauri-apps/tauri/pull/13135)) `Webview::eval` and `WebviewWindow::eval` now takes `impl Into` instead of `&str` to allow passing the scripts more flexible and efficiently - [`fbd57a1af`](https://www.github.com/tauri-apps/tauri/commit/fbd57a1afd94cc4aadff0b252724fe44060c67e5) ([#13175](https://www.github.com/tauri-apps/tauri/pull/13175)) `Builder::invoke_system` takes `AsRef` now ### Bug Fixes - [`66e6325f4`](https://www.github.com/tauri-apps/tauri/commit/66e6325f43efa49ec2165c45afec911a1a14ecfb) ([#13136](https://www.github.com/tauri-apps/tauri/pull/13136)) Fix `Channel`'s callback attached to `window` never cleaned up - [`0d39ff6b0`](https://www.github.com/tauri-apps/tauri/commit/0d39ff6b09e0a58a2e031d60f7bdc92b48d3cdf0) ([#13150](https://www.github.com/tauri-apps/tauri/pull/13150)) Fix missing `core:` in referenced commands in ACL error message - [`690146e31`](https://www.github.com/tauri-apps/tauri/commit/690146e3115f615818ec6927eb56fab157221504) ([#13217](https://www.github.com/tauri-apps/tauri/pull/13217)) Fix large number of commands with large structs as parameters causing stack overflow on debug build on Windows - [`f888502fd`](https://www.github.com/tauri-apps/tauri/commit/f888502fd228ad96b105e1e66f01c20c9f109983) ([#13227](https://www.github.com/tauri-apps/tauri/pull/13227)) `invoke` will now properly throw when `options.headers` contains non-ascii characters instead of silently replacing them - [`f888502fd`](https://www.github.com/tauri-apps/tauri/commit/f888502fd228ad96b105e1e66f01c20c9f109983) ([#13227](https://www.github.com/tauri-apps/tauri/pull/13227)) Fix `invoke` ignores the headers option if it's an `Headers` - [`b8c0d7e40`](https://www.github.com/tauri-apps/tauri/commit/b8c0d7e402b2ea8114bfa0f9322c986bd3eb7845) ([#13040](https://www.github.com/tauri-apps/tauri/pull/13040)) Fix `run_return` not responding to `restart` and `request_restart` ### Performance Improvements - [`66e6325f4`](https://www.github.com/tauri-apps/tauri/commit/66e6325f43efa49ec2165c45afec911a1a14ecfb) ([#13136](https://www.github.com/tauri-apps/tauri/pull/13136)) Improve `Channel`'s performance when sending small amount of data (e.g. sending a number) ### Dependencies - Upgraded to `tauri-utils@2.4.0` - Upgraded to `tauri-runtime@2.6.0` - Upgraded to `tauri-runtime-wry@2.6.0` - Upgraded to `tauri-macros@2.2.0` - Upgraded to `tauri-build@2.2.0` - [`bb5faa21f`](https://www.github.com/tauri-apps/tauri/commit/bb5faa21f418dd765ce81b495b56e9c519251b6d) ([#13163](https://www.github.com/tauri-apps/tauri/pull/13163)) Update webview2-com to 0.37. - [`bb5faa21f`](https://www.github.com/tauri-apps/tauri/commit/bb5faa21f418dd765ce81b495b56e9c519251b6d) ([#13163](https://www.github.com/tauri-apps/tauri/pull/13163)) Update windows to 0.61. ### Breaking Changes - [`fca5154e7`](https://www.github.com/tauri-apps/tauri/commit/fca5154e7ab57bb1bc8c6f4c3c6e4b5650d170d9) ([#13130](https://www.github.com/tauri-apps/tauri/pull/13130)) Removed re-exported `WebviewAttributes` from `tauri-runtime` which is exposed by accident in `tauri` and not used by any public facing APIs ## \[2.4.1] ### Enhancements - [`a851b6597`](https://www.github.com/tauri-apps/tauri/commit/a851b6597f7e37d12f9e4632945e8466800eb5ff) ([#13057](https://www.github.com/tauri-apps/tauri/pull/13057) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Enhanced the description of generated docs and schema for permission sets to include list of permissions within. ### Dependencies - Upgraded to `tauri-utils@2.3.1` - Upgraded to `tauri-runtime@2.5.1` - Upgraded to `tauri-runtime-wry@2.5.1` - Upgraded to `tauri-macros@2.1.1` - Upgraded to `tauri-build@2.1.1` ## \[2.4.0] ### New Features - [`be2e6b85f`](https://www.github.com/tauri-apps/tauri/commit/be2e6b85fed226732b4a98f68cc5d72b4f8f5a13) ([#12944](https://www.github.com/tauri-apps/tauri/pull/12944) by [@Simon-Laux](https://www.github.com/tauri-apps/tauri/../../Simon-Laux)) add `Window.is_always_on_top()` and `WebviewWindow.is_always_on_top()` - [`c10802425`](https://www.github.com/tauri-apps/tauri/commit/c10802425781d6ce7aac0a8beeddf2b51120f69c) ([#12710](https://www.github.com/tauri-apps/tauri/pull/12710) by [@WSH032](https://www.github.com/tauri-apps/tauri/../../WSH032)) derive `Clone` for `tauri::ExitRequestApi`. - [`cedb24d49`](https://www.github.com/tauri-apps/tauri/commit/cedb24d494b84111daa3206c05196c8b89f1e994) ([#12665](https://www.github.com/tauri-apps/tauri/pull/12665) by [@charrondev](https://www.github.com/tauri-apps/tauri/../../charrondev)) Added `Webview::cookies()`, `Webview::cookies_for_url()`, `WebviewWindow::cookies()` and `Webview::cookies_for_url()`. - [`20c190691`](https://www.github.com/tauri-apps/tauri/commit/20c19069125c89b2d45a2127278c9ffc2df35fc2) ([#12821](https://www.github.com/tauri-apps/tauri/pull/12821) by [@Simon-Laux](https://www.github.com/tauri-apps/tauri/../../Simon-Laux)) Add `WebviewBuilder.disable_javascript` and `WebviewWindowBuilder.disable_javascript` api to disable JavaScript. - [`060de5bbd`](https://www.github.com/tauri-apps/tauri/commit/060de5bbdddca384e3965a8938d89840f27c581d) ([#12837](https://www.github.com/tauri-apps/tauri/pull/12837) by [@niladrix719](https://www.github.com/tauri-apps/tauri/../../niladrix719)) Added `getIdentifier()` function to get the application identifier configured in tauri.conf.json - [`658e5f5d1`](https://www.github.com/tauri-apps/tauri/commit/658e5f5d1dc1bd970ae572a42447448d064a7fee) ([#12668](https://www.github.com/tauri-apps/tauri/pull/12668) by [@thomaseizinger](https://www.github.com/tauri-apps/tauri/../../thomaseizinger)) Add `App::run_return` function. Contrary to `App::run`, this will **not** exit the process but instead return the requested exit-code. This allows the host app to perform further cleanup after Tauri has exited. `App::run_return` is not available on iOS and fallbacks to the regular `App::run` functionality. The `App::run_iteration` function is deprecated as part of this because calling it in a loop - as suggested by the name - will cause a busy-loop. - [`5591a4f0b`](https://www.github.com/tauri-apps/tauri/commit/5591a4f0b41afb175acf188a30e86b7c09e51328) ([#12912](https://www.github.com/tauri-apps/tauri/pull/12912) by [@Daedaluz](https://www.github.com/tauri-apps/tauri/../../Daedaluz)) Change webview zoom on mousewheel when the `zoom_hotkeys_enabled` configuration is set to `true`. - [`bcdd51025`](https://www.github.com/tauri-apps/tauri/commit/bcdd510254ebe37827e22a5ffeb944321361e97c) ([#13012](https://www.github.com/tauri-apps/tauri/pull/13012) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) The `path` basename and extname APIs now accept Android content URIs, such as the paths returned by the dialog plugin. - [`bcdd51025`](https://www.github.com/tauri-apps/tauri/commit/bcdd510254ebe37827e22a5ffeb944321361e97c) ([#13012](https://www.github.com/tauri-apps/tauri/pull/13012) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Added `PathResolver::file_name` to resolve file names from content URIs on Android (leverating `std::path::Path::file_name` on other platforms). - [`c698a6d6f`](https://www.github.com/tauri-apps/tauri/commit/c698a6d6f3e02548444a4aa0e5220bbc6fc05c74) ([#12818](https://www.github.com/tauri-apps/tauri/pull/12818) by [@Simon-Laux](https://www.github.com/tauri-apps/tauri/../../Simon-Laux)) feat: add `Webview.reload` and `WebviewWindow.reload` - [`013f8f652`](https://www.github.com/tauri-apps/tauri/commit/013f8f652302f2d49c5ec0a075582033d8b074fb) ([#12890](https://www.github.com/tauri-apps/tauri/pull/12890) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Added `build > removeUnusedCommands` to trigger the build scripts and macros to remove unused commands based on the capabilities you defined. Note this won't be accounting for dynamically added ACLs so make sure to check it when using this. - [`35018eed0`](https://www.github.com/tauri-apps/tauri/commit/35018eed026d101273d758fca049ba91bfc891fa) ([#12996](https://www.github.com/tauri-apps/tauri/pull/12996) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Introduce `AppHandle::request_restart()` as an alternative to `AppHandle::restart()` to trigger exit event reliably - [`30f5a1553`](https://www.github.com/tauri-apps/tauri/commit/30f5a1553d3c0ce460c9006764200a9210915a44) ([#12366](https://www.github.com/tauri-apps/tauri/pull/12366) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Added `WebviewWindowBuilder::traffic_light_position` to set the traffic light buttons position on macOS. - [`30f5a1553`](https://www.github.com/tauri-apps/tauri/commit/30f5a1553d3c0ce460c9006764200a9210915a44) ([#12366](https://www.github.com/tauri-apps/tauri/pull/12366) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Added `trafficLightPosition` window configuration to set the traffic light buttons position on macOS. ### Enhancements - [`55ffa23c9`](https://www.github.com/tauri-apps/tauri/commit/55ffa23c9e4075ec3b3e64f808398b323db79e6a) ([#12855](https://www.github.com/tauri-apps/tauri/pull/12855) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix docs.rs build for mobile targets. - [`f2c94aaca`](https://www.github.com/tauri-apps/tauri/commit/f2c94aaca074bf15164d08e959b67f67f4c934ed) ([#12682](https://www.github.com/tauri-apps/tauri/pull/12682) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Add `Plugin#startIntentSenderForResult` Android API for mobile plugins. ### Bug Fixes - [`755533c51`](https://www.github.com/tauri-apps/tauri/commit/755533c518391824c7393a16577d10db3aa91d19) ([#12876](https://www.github.com/tauri-apps/tauri/pull/12876) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Removed `TSend: Clone` requirement for `Channel` by implementing `Clone` manually instead of driving it. - [`f98598817`](https://www.github.com/tauri-apps/tauri/commit/f98598817ca5b481d9de7a661ad00d14fd6b3b72) ([#12870](https://www.github.com/tauri-apps/tauri/pull/12870) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Update path plugin to use older dataDir API on SDK < 24. - [`f67a4a6bf`](https://www.github.com/tauri-apps/tauri/commit/f67a4a6bfec8ba21ae75f58c6fc74f12a07d4abf) ([#12971](https://www.github.com/tauri-apps/tauri/pull/12971) by [@WofWca](https://www.github.com/tauri-apps/tauri/../../WofWca)) Fix `tauri::AssetResolver::get` and `tauri::AssetResolver::get_for_scheme` skipping the first character of the `path` even if it's not a slash (/). - [`dc90cd391`](https://www.github.com/tauri-apps/tauri/commit/dc90cd3919e6760ab28c8b781e5c864bf836240e) ([#12911](https://www.github.com/tauri-apps/tauri/pull/12911) by [@Daedaluz](https://www.github.com/tauri-apps/tauri/../../Daedaluz)) Listen for `Ctrl +` or `Cmd +` to support zoom functionality in swedish keyboard layouts. - [`b05f82d35`](https://www.github.com/tauri-apps/tauri/commit/b05f82d35ba068bfeb44193b204fbfe365415a25) ([#12313](https://www.github.com/tauri-apps/tauri/pull/12313) by [@anatawa12](https://www.github.com/tauri-apps/tauri/../../anatawa12)) `AppHandle::restart()` now waits for `RunEvent::Exit` to be delivered before restarting the application. ### Performance Improvements - [`1cd8f55ee`](https://www.github.com/tauri-apps/tauri/commit/1cd8f55eed326d61860fee62ba2d2f4464bdcfcc) ([#13033](https://www.github.com/tauri-apps/tauri/pull/13033) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Don't ship global `bundle.global.js` if `app > withGlobalTauri` is set to false ### Dependencies - Upgraded to `tauri-runtime@2.5.0` - Upgraded to `tauri-runtime-wry@2.5.0` - Upgraded to `tauri-utils@2.3.0` - Upgraded to `tauri-build@2.1.0` - Upgraded to `tauri-macros@2.1.0` ## \[2.3.1] ### Bug Fixes - [`4f26dcf30`](https://www.github.com/tauri-apps/tauri/commit/4f26dcf3090f230d2996626423c8b9d58cc2e8aa) ([#12833](https://www.github.com/tauri-apps/tauri/pull/12833) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix OS webviews (`webview2` and `webkit2gtk`) are always compiled with tauri even without `wry` feature - [`e103e87f1`](https://www.github.com/tauri-apps/tauri/commit/e103e87f155cf7fa51baa0a48a476463216c0d62) ([#12848](https://www.github.com/tauri-apps/tauri/pull/12848) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix crash on Windows because of missing functions on older Windows systems, regression in 2.3.0 ### Dependencies - Upgraded to `tauri-runtime-wry@2.4.1` ## \[2.3.0] ### New Features - [`abdd55807`](https://www.github.com/tauri-apps/tauri/commit/abdd55807587f1bb41b95d0b129ba24b3c6e1d28) ([#12460](https://www.github.com/tauri-apps/tauri/pull/12460) by [@WSH032](https://www.github.com/tauri-apps/tauri/../../WSH032)) Add `emit_str*` methods to `Emitter` trait to allow emitting JSON serialized data directly. - [`7d8252679`](https://www.github.com/tauri-apps/tauri/commit/7d8252679d7c28b948d94ccd8130a5c9feaa3d27) ([#12701](https://www.github.com/tauri-apps/tauri/pull/12701) by [@WSH032](https://www.github.com/tauri-apps/tauri/../../WSH032)) Export `struct tauri::ExitRequestApi`. ### Enhancements - [`a2d36b8c3`](https://www.github.com/tauri-apps/tauri/commit/a2d36b8c34a8dcfc6736797ca5cd4665faf75e7e) ([#12181](https://www.github.com/tauri-apps/tauri/pull/12181) by [@bastiankistner](https://www.github.com/tauri-apps/tauri/../../bastiankistner)) Add an option to change the default background throttling policy (currently for WebKit only). - [`e9c9c4d6f`](https://www.github.com/tauri-apps/tauri/commit/e9c9c4d6f6f9c39f848183bc432790b1f9cb74fc) ([#12529](https://www.github.com/tauri-apps/tauri/pull/12529) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Derive `Clone` for `PathResolver` struct. - [`385a41dea`](https://www.github.com/tauri-apps/tauri/commit/385a41dea27330b42ae21419815c458afab47f94) ([#12817](https://www.github.com/tauri-apps/tauri/pull/12817) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) On Windows, undecorated window with shadows, now have native resize handles outside of the window client area. - [`d6520a21c`](https://www.github.com/tauri-apps/tauri/commit/d6520a21ce02c3e2be2955999946c2cb7bdb07aa) ([#12541](https://www.github.com/tauri-apps/tauri/pull/12541) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Updated `wry` to 0.50, `windows` to 0.60, `webview2-com` to 0.36, and `objc2` to 0.6. This can be a **breaking change** if you use the `with_webview` API! ### Bug Fixes - [`d7b998fe7`](https://www.github.com/tauri-apps/tauri/commit/d7b998fe71eca4d5471d73900f7694c043a17256) ([#12723](https://www.github.com/tauri-apps/tauri/pull/12723) by [@WSH032](https://www.github.com/tauri-apps/tauri/../../WSH032)) Deprecate `Manager::unmanage` to fix `use-after-free` unsoundness, see tauri-apps/tauri#12721 for details. - [`3dbcbe768`](https://www.github.com/tauri-apps/tauri/commit/3dbcbe7685319724c41e66d912b5daaec7f99868) ([#12461](https://www.github.com/tauri-apps/tauri/pull/12461) by [@WSH032](https://www.github.com/tauri-apps/tauri/../../WSH032)) `Webview::navigate` and `WebviewWindow::navigate` borrows `&self` instead of unnecessarily borrowing `&mut self`. ### Dependencies - Upgraded to `tauri-runtime@2.4.0` - Upgraded to `tauri-runtime-wry@2.4.0` - Upgraded to `tauri-utils@2.2.0` - Upgraded to `tauri-macros@2.0.5` - Upgraded to `tauri-build@2.0.6` ## \[2.2.5] ### Bug Fixes - [`477e9c049`](https://www.github.com/tauri-apps/tauri/commit/477e9c0496ff75ef8ef7aedc5430c77e213cd740) ([#12514](https://www.github.com/tauri-apps/tauri/pull/12514) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused iOS apps to panic when using an async function for `tauri::mobile_entry_point`. ## \[2.2.4] ### Bug Fixes - [`27096cdc0`](https://www.github.com/tauri-apps/tauri/commit/27096cdc05d89b61b2372b4e4a3018c87f240ab8) ([#12445](https://www.github.com/tauri-apps/tauri/pull/12445) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused Tauri's CLI to enable tauri's `native-tls` feature even though it wasn't needed. Moved `reqwest` to a mobile-only dependency in `tauri` and enabled its `rustls-tls` feature flag. ## \[2.2.3] ### Bug Fixes - [`d2c8f0eb5`](https://www.github.com/tauri-apps/tauri/commit/d2c8f0eb5ce2a5ebacd857614b7c89bbd5c9dca4) ([#12424](https://www.github.com/tauri-apps/tauri/pull/12424) by [@mattyg](https://www.github.com/tauri-apps/tauri/../../mattyg)) Ensure that tauri's builtin initialization scripts and plugin initialization scripts are executed before any user-added initialization scripts in a webview. ## \[2.2.2] ### Bug Fixes - [`61e69db9e`](https://www.github.com/tauri-apps/tauri/commit/61e69db9e48f6a652ed3ecb05567c648c6e788d0) ([#12376](https://www.github.com/tauri-apps/tauri/pull/12376) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Widen `specta` version range to `^2.0.0-rc.16` again. ## \[2.2.1] ### Bug Fixes - [`cd1d026f9`](https://www.github.com/tauri-apps/tauri/commit/cd1d026f9799c26b04acb64f49e7ee0a8b193049) ([#11961](https://www.github.com/tauri-apps/tauri/pull/11961) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix tauri fails to build if the project path contains glob characters ### Dependencies - Upgraded to `tauri-build@2.0.5` ## \[2.2.0] ### New Features - [`f884bae75`](https://www.github.com/tauri-apps/tauri/commit/f884bae75b3ad8f8debfd29bb05ac9cbc9748c89) ([#11742](https://www.github.com/tauri-apps/tauri/pull/11742) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `tauri::Builder::on_tray_icon_event` handler. - [`5188c0fae`](https://www.github.com/tauri-apps/tauri/commit/5188c0fae2bb47e40d09f70bf308c300045a2e2b) ([#11767](https://www.github.com/tauri-apps/tauri/pull/11767) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Added `Scope::is_forbidden` to check if a path was explicitly forbidden. - [`18bd639f6`](https://www.github.com/tauri-apps/tauri/commit/18bd639f6e22c0188aa219739f367b5bf5ab0398) ([#11798](https://www.github.com/tauri-apps/tauri/pull/11798) by [@lars-berger](https://www.github.com/tauri-apps/tauri/../../lars-berger)) Add `WebviewWindowBuilder/WebviewBuilder::data_store_identifier` on macOS. - [`dc4d79477`](https://www.github.com/tauri-apps/tauri/commit/dc4d79477665bc3bfefb4048772414cf5d78e3df) ([#11628](https://www.github.com/tauri-apps/tauri/pull/11628) by [@SpikeHD](https://www.github.com/tauri-apps/tauri/../../SpikeHD)) Add `WebviewWindowBuilder/WebviewBuilder::extensions_path` on Linux and Windows. - [`020ea0556`](https://www.github.com/tauri-apps/tauri/commit/020ea05561348dcd6d2a7df358f8a5190f661ba2) ([#11661](https://www.github.com/tauri-apps/tauri/pull/11661) by [@ahqsoftwares](https://www.github.com/tauri-apps/tauri/../../ahqsoftwares)) Add badging APIs: - `Window/WebviewWindow::set_badge_count` for Linux, macOS and IOS. - `Window/WebviewWindow::set_overlay_icon` for Windows Only. - `Window/WebviewWindow::set_badge_label`for macOS Only. - [`fc30b20be`](https://www.github.com/tauri-apps/tauri/commit/fc30b20bea125f647db00ca824663f8e1da4d61f) ([#11726](https://www.github.com/tauri-apps/tauri/pull/11726) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `TrayIconBuilder::show_menu_on_left_click` method and deprecate `TrayIconBuilder::menu_on_left_click` for consistent naming and clarity. ### Enhancements - [`d86aaccb0`](https://www.github.com/tauri-apps/tauri/commit/d86aaccb0b42760bb59bc04d74a6ea234bb64229) ([#11729](https://www.github.com/tauri-apps/tauri/pull/11729) by [@sandercox](https://www.github.com/tauri-apps/tauri/../../sandercox)) Add support for `TrayIconBuilder::menu_on_left_click` and `TrayIcon::set_show_menu_on_left_click` on Windows. - [`b0ddee899`](https://www.github.com/tauri-apps/tauri/commit/b0ddee8992ac3c7d47e2cfc9714f5725fadca7cf) ([#12101](https://www.github.com/tauri-apps/tauri/pull/12101) by [@renovate](https://www.github.com/tauri-apps/tauri/../../renovate)) **Breaking change:** Updated `webview2-com` to `0.34`. This may be a breaking change if you use the `with_webview` method. ### Bug Fixes - [`b50a1ac0e`](https://www.github.com/tauri-apps/tauri/commit/b50a1ac0ef4c7686c3537512f1ba607b9ba6589c) ([#11850](https://www.github.com/tauri-apps/tauri/pull/11850) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Add webview and window color setters to autogenerated permissions. - [`ba6f37014`](https://www.github.com/tauri-apps/tauri/commit/ba6f3701472daa9295a39709761ea85c128881f1) ([#11785](https://www.github.com/tauri-apps/tauri/pull/11785) by [@lars-berger](https://www.github.com/tauri-apps/tauri/../../lars-berger)) Fix panic when a plugin command is run with a capability added at runtime (via `Manager::add_capability`). - [`e349dfe57`](https://www.github.com/tauri-apps/tauri/commit/e349dfe5722c0b47620582bd03f8c184ffeb6979) ([#12000](https://www.github.com/tauri-apps/tauri/pull/12000) by [@stringhandler](https://www.github.com/tauri-apps/tauri/../../stringhandler)) Fixed a panic caused by an assert when the resource random id has been used already. - [`46935212b`](https://www.github.com/tauri-apps/tauri/commit/46935212b61da44dc82dfeb803fceebf5659f7b7) ([#11658](https://www.github.com/tauri-apps/tauri/pull/11658) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix `.json5` capability files not recognized even with `config-json5` feature enabled - [`b37741da6`](https://www.github.com/tauri-apps/tauri/commit/b37741da6a2d3dad71490c910a64eeedda2ba9ca) ([#11871](https://www.github.com/tauri-apps/tauri/pull/11871) by [@johncarmack1984](https://www.github.com/tauri-apps/tauri/../../johncarmack1984)) Fix `specta-util` dependency not found error when using `specta` feature - [`ca7f025fd`](https://www.github.com/tauri-apps/tauri/commit/ca7f025fd8666f8fce6894bb5e16cf2d4fc81e0c) ([#11958](https://www.github.com/tauri-apps/tauri/pull/11958) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix panic when invoking a command with an unmanaged state, an error will be returned instead. ### Dependencies - Upgraded to `tauri-runtime@2.3.0` - Upgraded to `tauri-runtime-wry@2.3.0` - Upgraded to `tauri-utils@2.1.1` - Upgraded to `tauri-macros@2.0.4` - Upgraded to `tauri-build@2.0.4` ## \[2.1.1] ### Bug Fixes - [`e8a50f6d7`](https://www.github.com/tauri-apps/tauri/commit/e8a50f6d760fad4529e7abb400302a1b487f11dd) ([#11645](https://www.github.com/tauri-apps/tauri/pull/11645)) Fix integer values of `BasDirectory.Home` and `BaseDirectory.Font` regression which broke path APIs in JS. ## \[2.1.0] ### New Features - [`fabc2f283`](https://www.github.com/tauri-apps/tauri/commit/fabc2f283e38b62c721326e44645d47138418cbc) ([#11485](https://www.github.com/tauri-apps/tauri/pull/11485) by [@39zde](https://www.github.com/tauri-apps/tauri/../../39zde)) Adds a new configuration option `app > security > headers` to define headers that will be added to every http response from tauri to the web view. This doesn't include IPC messages and error responses. - [`8036c78e0`](https://www.github.com/tauri-apps/tauri/commit/8036c78e08715b1bc6b9fcb0c59a570eec98014f) ([#11455](https://www.github.com/tauri-apps/tauri/pull/11455) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `PathResolver::home_dir()` method on Android. - [`5c4b83084`](https://www.github.com/tauri-apps/tauri/commit/5c4b830843ab085f8ff9db9e08d832223b027e4e) ([#11191](https://www.github.com/tauri-apps/tauri/pull/11191) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Improved support for `dpi` module types to allow these types to be used without manual conversions with `invoke`: - Added `SERIALIZE_TO_IPC_FN` const in `core` module which can be used to implement custom IPC serialization for types passed to `invoke`. - Added `Size` and `Position` classes in `dpi` module. - Implementd `SERIALIZE_TO_IPC_FN` method on `PhysicalSize`, `PhysicalPosition`, `LogicalSize` and `LogicalPosition` to convert it into a valid IPC-compatible value that can be deserialized correctly on the Rust side into its equivalent struct. - [`4d545ab3c`](https://www.github.com/tauri-apps/tauri/commit/4d545ab3ca228c8a21b966b709f84a0da2864479) ([#11486](https://www.github.com/tauri-apps/tauri/pull/11486) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Added `Window::set_background_color` and `WindowBuilder::background_color`. - [`cbc095ec5`](https://www.github.com/tauri-apps/tauri/commit/cbc095ec5fe7de29b5c9265576d4e071ec159c1c) ([#11451](https://www.github.com/tauri-apps/tauri/pull/11451) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `app > windows > devtools` config option and when creating the webview from JS, to enable or disable devtools for a specific webview. - [`f0da0bde8`](https://www.github.com/tauri-apps/tauri/commit/f0da0bde87a80fdca20c588cefcad86e03b9627c) ([#11439](https://www.github.com/tauri-apps/tauri/pull/11439) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Added `WebviewWindow::resolve_command_scope` to check a command scope at runtime. - [\`\`](https://www.github.com/tauri-apps/tauri/commit/undefined) Detect if `SERIALIZE_TO_IPC_FN`, const from the JS `core` module, is implemented on objects when serializing over IPC and use it. - [`f37e97d41`](https://www.github.com/tauri-apps/tauri/commit/f37e97d410c4a219e99f97692da05ca9d8e0ba3a) ([#11477](https://www.github.com/tauri-apps/tauri/pull/11477) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `app > windows > useHttpsScheme` config option to choose whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android - [`f37e97d41`](https://www.github.com/tauri-apps/tauri/commit/f37e97d410c4a219e99f97692da05ca9d8e0ba3a) ([#11477](https://www.github.com/tauri-apps/tauri/pull/11477) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `WebviewWindowBuilder/WebviewBuilder::use_https_scheme` to choose whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android - [`cbc095ec5`](https://www.github.com/tauri-apps/tauri/commit/cbc095ec5fe7de29b5c9265576d4e071ec159c1c) ([#11451](https://www.github.com/tauri-apps/tauri/pull/11451) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `WebviewWindowBuilder::devtools` and `WebviewBuilder::devtools` to enable or disable devtools for a specific webview. - [`129414faa`](https://www.github.com/tauri-apps/tauri/commit/129414faa4e027c9035d56614682cacc0335a6a0) ([#11569](https://www.github.com/tauri-apps/tauri/pull/11569) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `WebviewBuilder::focused` method to choose whether to focus webview or not on creation. - [`2a75c64b5`](https://www.github.com/tauri-apps/tauri/commit/2a75c64b5431284e7340e8743d4ea56a62c75466) ([#11469](https://www.github.com/tauri-apps/tauri/pull/11469) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Added `app > windows > windowClassname` config option to specify the name of the window class on Windows. - [`2a75c64b5`](https://www.github.com/tauri-apps/tauri/commit/2a75c64b5431284e7340e8743d4ea56a62c75466) ([#11469](https://www.github.com/tauri-apps/tauri/pull/11469) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Added `WindowBuilder/WebviewWindowBuilder::window_classname` method to specify the name of the window class on Windows. ### Enhancements - [`17c6952ae`](https://www.github.com/tauri-apps/tauri/commit/17c6952aec965fa41e6695ad68461a218afc20f1) ([#11522](https://www.github.com/tauri-apps/tauri/pull/11522) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Enhance the error message when using `async` commands with a reference. - [`c33bbf457`](https://www.github.com/tauri-apps/tauri/commit/c33bbf45740274b6918ea6c647f366fb6008e459) ([#11575](https://www.github.com/tauri-apps/tauri/pull/11575) by [@kornelski](https://www.github.com/tauri-apps/tauri/../../kornelski)) Include the path in ACL I/O errors. ### Bug Fixes - [`229d7f8e2`](https://www.github.com/tauri-apps/tauri/commit/229d7f8e220cc8d5ca06eff1ed85cb7d047c1d6c) ([#11616](https://www.github.com/tauri-apps/tauri/pull/11616) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix regression in creating child webviews on macOS and Windows, covering the whole window. - [`8c6d1e8e6`](https://www.github.com/tauri-apps/tauri/commit/8c6d1e8e6c852667bb223b5f4823948868c26d98) ([#11401](https://www.github.com/tauri-apps/tauri/pull/11401) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix `App/AppHandle/Window/Webview/WebviewWindow::cursor_position` getter method failing on Linux with `GDK may only be used from the main thread`. - [`f8994b214`](https://www.github.com/tauri-apps/tauri/commit/f8994b214e89acc99ab5ce8dcca8485f43a62dbb) ([#11581](https://www.github.com/tauri-apps/tauri/pull/11581) by [@Mikkel-T](https://www.github.com/tauri-apps/tauri/../../Mikkel-T)) Fix listeners created with `EventTarget::AnyLabel` never receiving events. - [`4191a7a53`](https://www.github.com/tauri-apps/tauri/commit/4191a7a53d941b179780a550638f1b4a09d17fd1) ([#11583](https://www.github.com/tauri-apps/tauri/pull/11583) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix tray events not fired for tray icons created inside an async command. - [`129414faa`](https://www.github.com/tauri-apps/tauri/commit/129414faa4e027c9035d56614682cacc0335a6a0) ([#11569](https://www.github.com/tauri-apps/tauri/pull/11569) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix webview not focused by default. ### Dependencies - Upgraded to `tauri-utils@2.1.0` - Upgraded to `tauri-runtime@2.2.0` - Upgraded to `tauri-runtime-wry@2.2.0` - Upgraded to `tauri-macros@2.0.3` - Upgraded to `tauri-build@2.0.3` ## \[2.0.6] ### Dependencies - Upgraded to `tauri-utils@2.0.2` ## \[2.0.5] ### New Features - [`6cd917c22`](https://www.github.com/tauri-apps/tauri/commit/6cd917c227596e4e557496347ccae8ef579f6ea0) ([#11390](https://www.github.com/tauri-apps/tauri/pull/11390) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add new methods on `tauri::menu::MenuBuilder` and `tauri::menu::SubmenuBuilder` to create predefined menu item with specific text. ### Enhancements - [`eb61d44f9`](https://www.github.com/tauri-apps/tauri/commit/eb61d44f9fc1be591c3d10a6ac1451aa39e6a77b) ([#11398](https://www.github.com/tauri-apps/tauri/pull/11398) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fallback to the Window and AppHandle resource table when closing a resource by ID. ### Bug Fixes - [`e1bf6ef8c`](https://www.github.com/tauri-apps/tauri/commit/e1bf6ef8cbe3421eeaec47a222446121bcc28354) ([#11374](https://www.github.com/tauri-apps/tauri/pull/11374) by [@chrox](https://www.github.com/tauri-apps/tauri/../../chrox)) Expose `content-range` header in `range` response of `asset` protocol ### What's Changed - [`2e88633ba`](https://www.github.com/tauri-apps/tauri/commit/2e88633ba4da8fc289c6d8a29c36f3327f9b576e) ([#11369](https://www.github.com/tauri-apps/tauri/pull/11369) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Remove references to no longer used `__TAURI_INTERNALS__.metadata.windows` and `__TAURI_INTERNALS__.metadata.webviews`. ## \[2.0.4] ### New Features - [`bcf279278`](https://www.github.com/tauri-apps/tauri/commit/bcf279278dd36e05836be9568c432a679143258c) ([#11354](https://www.github.com/tauri-apps/tauri/pull/11354)) On Windows, Add `ContextMenu::hpopupmenu` method to get the [`HMENU`](https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types#HMENU) used for popups and tray icon menu. ### Enhancements - [`e3b09be7f`](https://www.github.com/tauri-apps/tauri/commit/e3b09be7f0b7d47407cf51d6c2aafed741a96efe) ([#11362](https://www.github.com/tauri-apps/tauri/pull/11362)) Added `Builder::channel_interceptor` to intercept messages to be sent to the frontend, complemeting the `Builder::invoke_system` interface. - [`3cb73d08c`](https://www.github.com/tauri-apps/tauri/commit/3cb73d08c6d9b1e9f8a60c6ef6c492415cb41029) ([#11355](https://www.github.com/tauri-apps/tauri/pull/11355)) Mark the event commands as async so they do not block the main thread. ### Bug Fixes - [`f3f521f03`](https://www.github.com/tauri-apps/tauri/commit/f3f521f038fa94ad583392092efe5bf1098fc94a) ([#11348](https://www.github.com/tauri-apps/tauri/pull/11348)) Fix `TAURI_ANDROID_PACKAGE_UNESCAPED not set` panic during compilation for Android when using an older tauri cli. ### Dependencies - Upgraded to `tauri-runtime-wry@2.1.1` ## \[2.0.3] ### New Features - [`1d3f51e10`](https://www.github.com/tauri-apps/tauri/commit/1d3f51e100b0efc0e4ce164796460e9acdc458da) ([#11228](https://www.github.com/tauri-apps/tauri/pull/11228) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `tauri::Builder::on_menu_event`. ### Bug Fixes - [`d609bef9f`](https://www.github.com/tauri-apps/tauri/commit/d609bef9fd7cd6eeb2bd701558100bd9cfb6e6f6) ([#11314](https://www.github.com/tauri-apps/tauri/pull/11314) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix android invalid proguard file when using an `identifier` that contains a component that is a reserved kotlin keyword, like `in`, `class`, etc - [`04fd3a7db`](https://www.github.com/tauri-apps/tauri/commit/04fd3a7db556a5d83989c9de2a03095061996c9d) ([#11264](https://www.github.com/tauri-apps/tauri/pull/11264) by [@chrox](https://www.github.com/tauri-apps/tauri/../../chrox)) Respond with empty body for `HEAD` requests to `asset` protocol - [`4731f0cf3`](https://www.github.com/tauri-apps/tauri/commit/4731f0cf31fc99876f17a9b0e8170c1ef759443b) ([#11290](https://www.github.com/tauri-apps/tauri/pull/11290) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Export the `ipc::Invoke` struct. - [`2d087ee4b`](https://www.github.com/tauri-apps/tauri/commit/2d087ee4b7d3e8849933f81284e4f5ed1aaa6455) ([#11268](https://www.github.com/tauri-apps/tauri/pull/11268) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) On Linux, fix commands, that use `Webview` or `WebviewWindow` as an argument, receiving an incorrect webview when using multi webviews. - [`2d087ee4b`](https://www.github.com/tauri-apps/tauri/commit/2d087ee4b7d3e8849933f81284e4f5ed1aaa6455) ([#11268](https://www.github.com/tauri-apps/tauri/pull/11268) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) On Linux, fix events only emitted to first webview only when using multi webviews. - [`2d087ee4b`](https://www.github.com/tauri-apps/tauri/commit/2d087ee4b7d3e8849933f81284e4f5ed1aaa6455) ([#11268](https://www.github.com/tauri-apps/tauri/pull/11268) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) On Linux, fix custom protocols receiving an incorrect webview label when using multi webviews ### Dependencies - Upgraded to `tauri-runtime@2.1.0` - Upgraded to `tauri-runtime-wry@2.1.0` ## \[2.0.2] ### Enhancements - [`03e759042`](https://www.github.com/tauri-apps/tauri/commit/03e759042913e2ae9d45f299d6b6ad4b64ac3d2c) ([#11235](https://www.github.com/tauri-apps/tauri/pull/11235) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Added `App::invoke_key` and `AppHandle::invoke_key` for custom invoke systems that rely on manual `Webview::on_message` calls. ## \[2.0.1] ### What's Changed - [`0ab2b3306`](https://www.github.com/tauri-apps/tauri/commit/0ab2b330644b6419f6cee1d5377bfb5cdda2ccf9) ([#11205](https://www.github.com/tauri-apps/tauri/pull/11205) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Downgrade MSRV to 1.77.2 to support Windows 7. ### Dependencies - Upgraded to `tauri-utils@2.0.1` - Upgraded to `tauri-runtime@2.0.1` - Upgraded to `tauri-runtime-wry@2.0.1` - Upgraded to `tauri-macros@2.0.1` - Upgraded to `tauri-build@2.0.1` ## \[2.0.0] ### What's Changed - [`382ed482b`](https://www.github.com/tauri-apps/tauri/commit/382ed482bd08157c39e62f9a0aaad8802f1092cb) Bump MSRV to 1.78. - [`637285790`](https://www.github.com/tauri-apps/tauri/commit/6372857905ae9c0aedb7f482ddf6cf9f9836c9f2) Promote to v2 stable! ### Dependencies - Upgraded to `tauri-utils@2.0.0` - Upgraded to `tauri-runtime@2.0.0` - Upgraded to `tauri-runtime-wry@2.0.0` - Upgraded to `tauri-macros@2.0.0` - Upgraded to `tauri-build@2.0.0` ## \[2.0.0-rc.17] ### Breaking Changes - [`354be36d4`](https://www.github.com/tauri-apps/tauri/commit/354be36d4efed6c0c53639af44607f7b050adfd2) ([#11163](https://www.github.com/tauri-apps/tauri/pull/11163) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Changed uri scheme protocol handler to take `UriSchemeContext` as first argument instead of `AppHandle`. `UriSchemeContext` can be used to access an app handle or the webview label that made the request. The following methods are affected: - `tauri::Builder::register_uri_scheme_protocol` - `tauri::Builder::register_asynchronous_uri_scheme_protocol` - `tauri::plugin::Builder::register_uri_scheme_protocol` - `tauri::plugin::Builder::register_asynchronous_uri_scheme_protocol` ## \[2.0.0-rc.16] ### New Features - [`a247170e1`](https://www.github.com/tauri-apps/tauri/commit/a247170e1f620a9b012274b11cfe51e90327d6e9) ([#11056](https://www.github.com/tauri-apps/tauri/pull/11056) by [@SpikeHD](https://www.github.com/tauri-apps/tauri/../../SpikeHD)) Expose the ability to enabled browser extensions in WebView2 on Windows. - [`9014a3f17`](https://www.github.com/tauri-apps/tauri/commit/9014a3f1765ca406ea5c3e5224267a79c52cd53d) ([#11066](https://www.github.com/tauri-apps/tauri/pull/11066) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `WebviewWindow::clear_all_browsing_data` and `Webview::clear_all_browsing_data` to clear the webview browsing data. - [`0ddfc59d6`](https://www.github.com/tauri-apps/tauri/commit/0ddfc59d6785e3b6a85a674a2f80d4c0affd2898) ([#11071](https://www.github.com/tauri-apps/tauri/pull/11071) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `Manager::unmanage` to remove previously managed state. - [`1d8b67b29`](https://www.github.com/tauri-apps/tauri/commit/1d8b67b2970a09ec478093e127612fac823de805) ([#11162](https://www.github.com/tauri-apps/tauri/pull/11162) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Support async functions for `mobile_entry_point` macro - [`5621174b0`](https://www.github.com/tauri-apps/tauri/commit/5621174b05f615e1589292ccd3954dc7e6b5569f) ([#11132](https://www.github.com/tauri-apps/tauri/pull/11132) by [@chippers](https://www.github.com/tauri-apps/tauri/../../chippers)) Add `ScopeObjectMatch` for easy scope validation those that can be represented by a boolean return value. - [`95df53a2e`](https://www.github.com/tauri-apps/tauri/commit/95df53a2ed96873cd35a4b14a5e312d07e4e3004) ([#11143](https://www.github.com/tauri-apps/tauri/pull/11143) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Add the ability to set theme dynamically using `Window::set_theme`, `App::set_theme` - [`d9d2502b4`](https://www.github.com/tauri-apps/tauri/commit/d9d2502b41e39efde679e30c8955006e2ba9ea64) ([#11140](https://www.github.com/tauri-apps/tauri/pull/11140) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `Webview::hide` and `Webview::show` methods. - [`de7414aab`](https://www.github.com/tauri-apps/tauri/commit/de7414aab935e45540594ea930eb60bae4dbc979) ([#11154](https://www.github.com/tauri-apps/tauri/pull/11154) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `Window::set_enabled` and `Window::is_enabled` methods ### Bug Fixes - [`948772a65`](https://www.github.com/tauri-apps/tauri/commit/948772a657eb3caf20843628abac9109e3b67d41) ([#11114](https://www.github.com/tauri-apps/tauri/pull/11114) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Change the `button_state` tray event field to camelCase `buttonState`. - [`a49fc999f`](https://www.github.com/tauri-apps/tauri/commit/a49fc999fc3eba3bfd47480b0a8c68c0b45e3127) ([#11161](https://www.github.com/tauri-apps/tauri/pull/11161) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix internal crash when trying to close the same window multiple times. - [`62b3a5cd1`](https://www.github.com/tauri-apps/tauri/commit/62b3a5cd1c804440c2130ab36cc3eadb3baf61cb) ([#11043](https://www.github.com/tauri-apps/tauri/pull/11043) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix `localStorage` not shared between webviews that use the same data directory. ### Dependencies - Upgraded to `tauri-runtime-wry@2.0.0-rc.14` - Upgraded to `tauri-runtime@2.0.0-rc.13` - Upgraded to `tauri-utils@2.0.0-rc.13` - Upgraded to `tauri-macros@2.0.0-rc.12` - Upgraded to `tauri-build@2.0.0-rc.13` ### Breaking Changes - [`0b4495996`](https://www.github.com/tauri-apps/tauri/commit/0b4495996d3131a5ee80fbb2c71a28203e491ee7) ([#11121](https://www.github.com/tauri-apps/tauri/pull/11121) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Simplified emitted tray event JS value and updated `TrayIconEvent` type definition to match it. ## \[2.0.0-rc.15] ### New Features - [`ad294d274`](https://www.github.com/tauri-apps/tauri/commit/ad294d274dd81d2ef91ed73af9163b6e9b8eb964) ([#11032](https://www.github.com/tauri-apps/tauri/pull/11032) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `app > windows > create` option to choose whether to create this window at app startup or not. ### Enhancements - [`e7fd676c2`](https://www.github.com/tauri-apps/tauri/commit/e7fd676c2741929727e3e25bd81cd6ea45e4da7b) ([#11025](https://www.github.com/tauri-apps/tauri/pull/11025) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Inject `__INVOKE_KEY__` into custom invoke systems so their implementations can properly construct `tauri::webview::InvokeRequest`. ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.12` - Upgraded to `tauri-runtime@2.0.0-rc.12` - Upgraded to `tauri-runtime-wry@2.0.0-rc.13` - Upgraded to `tauri-macros@2.0.0-rc.11` - Upgraded to `tauri-build@2.0.0-rc.12` ### Breaking Changes - [`551e0624a`](https://www.github.com/tauri-apps/tauri/commit/551e0624a903ed6cf8390add7868c655c7778ce4) ([#11027](https://www.github.com/tauri-apps/tauri/pull/11027) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Remove the `responder` part of a custom invoke system now that the responder can be set directly in the `tauri::WebviewWindow::on_message` function. ## \[2.0.0-rc.14] ### Bug Fixes - [`e5f037277`](https://www.github.com/tauri-apps/tauri/commit/e5f037277505c477b8d563bd77b7bd6e23b46296) ([#11018](https://www.github.com/tauri-apps/tauri/pull/11018) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix compilation error on macOS due to a missing feature for `NSImage`. ## \[2.0.0-rc.13] ### Enhancements - [`bc4804d48`](https://www.github.com/tauri-apps/tauri/commit/bc4804d4841efefd57fd1f3e147550a3340e2b31) ([#10924](https://www.github.com/tauri-apps/tauri/pull/10924) by [@madsmtm](https://www.github.com/tauri-apps/tauri/../../madsmtm)) Use `objc2` internally and in examples, leading to better memory safety. ### Dependencies - Upgraded to `tauri-runtime-wry@2.0.0-rc.12` ### Breaking Changes - [`bc4804d48`](https://www.github.com/tauri-apps/tauri/commit/bc4804d4841efefd57fd1f3e147550a3340e2b31) ([#10924](https://www.github.com/tauri-apps/tauri/pull/10924) by [@madsmtm](https://www.github.com/tauri-apps/tauri/../../madsmtm)) Change the pointer type of `PlatformWebview`'s `inner`, `controller`, `ns_window` and `view_controller` to `c_void`, to avoid publically depending on `objc`. ## \[2.0.0-rc.12] ### New Features - [`35bd9dd3d`](https://www.github.com/tauri-apps/tauri/commit/35bd9dd3dc3d8972bbc4aa5f4a6c6fa14354e9bf) ([#10977](https://www.github.com/tauri-apps/tauri/pull/10977) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `mainBinaryName` config option to set the file name for the main binary. ### Enhancements - [`5eb036f33`](https://www.github.com/tauri-apps/tauri/commit/5eb036f33951a9946f25ce5fa7fc47ae4469aa60) ([#11002](https://www.github.com/tauri-apps/tauri/pull/11002) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Handle macOS binary name change on the `process::restart` function. ### Bug Fixes - [`63649d82d`](https://www.github.com/tauri-apps/tauri/commit/63649d82d20b8f69d973b41bd0c157997770d6a0) ([#10971](https://www.github.com/tauri-apps/tauri/pull/10971) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix schema generation for `core:default` set. - [`be18ed50d`](https://www.github.com/tauri-apps/tauri/commit/be18ed50d8e04261da1553662a768e7ce0f1dd8f) ([#10982](https://www.github.com/tauri-apps/tauri/pull/10982) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Add a Proguard rule to prevent custom JSON deserializer and serializer classes from being optimized away. - [`00182ebf8`](https://www.github.com/tauri-apps/tauri/commit/00182ebf894b83302179ccb7f415f97d04600c77) ([#10988](https://www.github.com/tauri-apps/tauri/pull/10988) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix `requestPermissions` not resolving on Android. ### Dependencies - Upgraded to `tauri-build@2.0.0-rc.11` - Upgraded to `tauri-utils@2.0.0-rc.11` - Upgraded to `tauri-runtime@2.0.0-rc.11` - Upgraded to `tauri-runtime-wry@2.0.0-rc.11` - Upgraded to `tauri-macros@2.0.0-rc.10` ### Breaking Changes - [`fe5ff1228`](https://www.github.com/tauri-apps/tauri/commit/fe5ff1228c34cf12929d861454ab9716da9480da) ([#10978](https://www.github.com/tauri-apps/tauri/pull/10978) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Rename `PermissionState::Unknown` to `PermissionState::Prompt`. ## \[2.0.0-rc.11] ### Bug Fixes - [`fafceec30`](https://www.github.com/tauri-apps/tauri/commit/fafceec3092f405fbc6642d331e5440b90d9fd62) ([#10943](https://www.github.com/tauri-apps/tauri/pull/10943) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes mobile dev server proxy request URL with trailing slashes. ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.10` - Upgraded to `tauri-runtime@2.0.0-rc.10` - Upgraded to `tauri-runtime-wry@2.0.0-rc.10` - Upgraded to `tauri-macros@2.0.0-rc.9` - Upgraded to `tauri-build@2.0.0-rc.10` ## \[2.0.0-rc.10] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.9` - Upgraded to `tauri-runtime@2.0.0-rc.9` - Upgraded to `tauri-runtime-wry@2.0.0-rc.9` - Upgraded to `tauri-macros@2.0.0-rc.8` - Upgraded to `tauri-build@2.0.0-rc.9` - [`d9c8d3cc8`](https://www.github.com/tauri-apps/tauri/commit/d9c8d3cc8d5ca67cd767ffc7a521f801b41ce201) ([#10902](https://www.github.com/tauri-apps/tauri/pull/10902) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Update infer to 0.16, tray icon to 0.17, urlpattern to 0.3, image to 0.25 ### Breaking Changes - [`faa259bac`](https://www.github.com/tauri-apps/tauri/commit/faa259bacf1ace670af763982c6903190faf163a) ([#10907](https://www.github.com/tauri-apps/tauri/pull/10907) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) The `Assets::iter` function now must return a iterator with `Item = (Cow<'_, str>, Cow<'_, [u8]>)` to be more flexible on contexts where the assets are not `'static`. ## \[2.0.0-rc.9] ### New Features - [`0899e5083`](https://www.github.com/tauri-apps/tauri/commit/0899e5083104dfcf924a0530ba73ead2963ee421) ([#10884](https://www.github.com/tauri-apps/tauri/pull/10884) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Derive serde `Serialize` for `SafePathBuf` - [`431ca2c77`](https://www.github.com/tauri-apps/tauri/commit/431ca2c7763f7e31ad533c49576ab658569ddd29) ([#10870](https://www.github.com/tauri-apps/tauri/pull/10870) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Add `FromStr` impl for `SafePathBuf` ### Bug Fixes - [`79de4332b`](https://www.github.com/tauri-apps/tauri/commit/79de4332b6fe01e848c286cedf9ceea773cf6190) ([#10841](https://www.github.com/tauri-apps/tauri/pull/10841) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes IPC postMessage raw body processing when using the isolation pattern. - [`6696e4880`](https://www.github.com/tauri-apps/tauri/commit/6696e48800576e124066388156f1d083376eec30) ([#10842](https://www.github.com/tauri-apps/tauri/pull/10842) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes a warning when using a null value on the `invoke.resolve()` iOS plugin API. ### What's Changed - [`27d018343`](https://www.github.com/tauri-apps/tauri/commit/27d01834312ee7953b6ccd5b0a368e7a69b225e9) ([#10844](https://www.github.com/tauri-apps/tauri/pull/10844) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Changes how the Info.plist is embedded on macOS development to avoid a clippy warning. ### Dependencies - Upgraded to `tauri-runtime-wry@2.0.0-rc.8` - Upgraded to `tauri-utils@2.0.0-rc.8` - Upgraded to `tauri-runtime@2.0.0-rc.8` - Upgraded to `tauri-macros@2.0.0-rc.7` - Upgraded to `tauri-build@2.0.0-rc.8` ### Breaking Changes - [`5048a7293`](https://www.github.com/tauri-apps/tauri/commit/5048a7293b87b5b93aaefd42dedc0e551e08086c) ([#10840](https://www.github.com/tauri-apps/tauri/pull/10840) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) The `linux-ipc-protocol` feature is now always enabled, so the Cargo feature flag was removed. This increases the minimum webkit2gtk version to a release that does not affect the minimum target Linux distros for Tauri apps. ## \[2.0.0-rc.8] ### Enhancements - [`d7e5c00e9`](https://www.github.com/tauri-apps/tauri/commit/d7e5c00e94938f6be94e693d3f21f1f8f431c4f9) ([#10817](https://www.github.com/tauri-apps/tauri/pull/10817) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Added `plugin:::PermissionState` enum. ## \[2.0.0-rc.7] ### New Features - [`1e441811e`](https://www.github.com/tauri-apps/tauri/commit/1e441811ee16c687343760f555c86d52ebfe8f87) ([#10786](https://www.github.com/tauri-apps/tauri/pull/10786) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) On Windows, Add and emit `DoubleClick` variant for `TrayIconEvent`. ### Enhancements - [`f86a8146a`](https://www.github.com/tauri-apps/tauri/commit/f86a8146addd8a25bc44c492300fe0563104b83d) ([#10761](https://www.github.com/tauri-apps/tauri/pull/10761) by [@rdlabo](https://www.github.com/tauri-apps/tauri/../../rdlabo)) Added `getArgs` and `getRawArgs` methods to the plugin `Invoke` class (Kotlin and Swift), which lets you parse the arguments manually instead of through the `parseArgs` method. ### Bug Fixes - [`03f2a5098`](https://www.github.com/tauri-apps/tauri/commit/03f2a50981b8c01b1c196811fce9d93f1bf0820d) ([#10718](https://www.github.com/tauri-apps/tauri/pull/10718) by [@rdlabo](https://www.github.com/tauri-apps/tauri/../../rdlabo)) Update swift-rs fixing a plugin build when native dependencies are used. - [`22d2afa89`](https://www.github.com/tauri-apps/tauri/commit/22d2afa89bfe626bf952c2bb4b1f37935c1a2f71) ([#10800](https://www.github.com/tauri-apps/tauri/pull/10800) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Change the Android Proguard rules to keep custom JSON deserializers. - [`fbe76a955`](https://www.github.com/tauri-apps/tauri/commit/fbe76a955a63af9fb33f66d5f747caf858cf179b) ([#10797](https://www.github.com/tauri-apps/tauri/pull/10797) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Uint8Arrays and ArrayBuffers are now properly serialized as an array of numbers. ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.7` - Upgraded to `tauri-build@2.0.0-rc.7` - Upgraded to `tauri-runtime@2.0.0-rc.7` - Upgraded to `tauri-runtime-wry@2.0.0-rc.7` - Upgraded to `tauri-macros@2.0.0-rc.6` ## \[2.0.0-rc.6] ### What's Changed - [`f4d5241b3`](https://www.github.com/tauri-apps/tauri/commit/f4d5241b377d0f7a1b58100ee19f7843384634ac) ([#10731](https://www.github.com/tauri-apps/tauri/pull/10731) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Update documentation icon path. ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.6` - Upgraded to `tauri-build@2.0.0-rc.6` - Upgraded to `tauri-runtime-wry@2.0.0-rc.6` - Upgraded to `tauri-runtime@2.0.0-rc.6` - Upgraded to `tauri-macros@2.0.0-rc.5` ## \[2.0.0-rc.5] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.5` - Upgraded to `tauri-runtime@2.0.0-rc.5` - Upgraded to `tauri-runtime-wry@2.0.0-rc.5` - Upgraded to `tauri-macros@2.0.0-rc.5` - Upgraded to `tauri-build@2.0.0-rc.5` ## \[2.0.0-rc.4] ### Enhancements - [`30c7685eb`](https://www.github.com/tauri-apps/tauri/commit/30c7685eb82c7a1a9af53abdca7d75b1a886cc6e) ([#10295](https://www.github.com/tauri-apps/tauri/pull/10295) by [@liesauer](https://www.github.com/tauri-apps/tauri/../../liesauer)) Added `Builder::append_invoke_initialization_script`. - [`ed04cc3d3`](https://www.github.com/tauri-apps/tauri/commit/ed04cc3d36205b277517d052dfd997b6c3cb673d) ([#10664](https://www.github.com/tauri-apps/tauri/pull/10664) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Include more information in the IPC permission error message. ### Bug Fixes - [`5c335ae9a`](https://www.github.com/tauri-apps/tauri/commit/5c335ae9ad88e46c2135a557390f6e808c9a6088) ([#10648](https://www.github.com/tauri-apps/tauri/pull/10648) by [@Flakebi](https://www.github.com/tauri-apps/tauri/../../Flakebi)) Prevent build script from rerunning unnecessarily by only writing files when the content changes. ### Dependencies - Upgraded to `tauri-build@2.0.0-rc.4` - Upgraded to `tauri-utils@2.0.0-rc.4` - Upgraded to `tauri-runtime@2.0.0-rc.4` - Upgraded to `tauri-runtime-wry@2.0.0-rc.4` - Upgraded to `tauri-macros@2.0.0-rc.4` ## \[2.0.0-rc.3] ### Bug Fixes - [`b1d9ffa1a`](https://www.github.com/tauri-apps/tauri/commit/b1d9ffa1abc9eff65acf16792b4fb33d9c45ba8a) ([#10582](https://www.github.com/tauri-apps/tauri/pull/10582) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix IPC fallback (postMessage implementation when custom protocol fails) hanging when sending responses. ### What's Changed - [`bfc49cc7a`](https://www.github.com/tauri-apps/tauri/commit/bfc49cc7a1d43e3378e93865b9b37ce4bddfa6e6) ([#10558](https://www.github.com/tauri-apps/tauri/pull/10558) by [@ahqsoftwares](https://www.github.com/tauri-apps/tauri/../../ahqsoftwares)) Remove targetSdk from gradle files - [`fedf93eb7`](https://www.github.com/tauri-apps/tauri/commit/fedf93eb7e09c161997f6ba96a17fc29e727af69) ([#10585](https://www.github.com/tauri-apps/tauri/pull/10585) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Change how IPC handles errors to simplify what's logged in the console. ### Dependencies - Upgraded to `tauri-build@2.0.0-rc.3` - Upgraded to `tauri-utils@2.0.0-rc.3` - Upgraded to `tauri-runtime@2.0.0-rc.3` - Upgraded to `tauri-runtime-wry@2.0.0-rc.3` - Upgraded to `tauri-macros@2.0.0-rc.3` - [`d39c392b7`](https://www.github.com/tauri-apps/tauri/commit/d39c392b7cec746da423211f9c74632abe4b6af5) ([#10655](https://www.github.com/tauri-apps/tauri/pull/10655) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Update `tao` to 0.29 and `wry` to 0.42. ### Breaking Changes - [`d0510f52e`](https://www.github.com/tauri-apps/tauri/commit/d0510f52eb7efeabe00df5030cf10be16f99e178) ([#10641](https://www.github.com/tauri-apps/tauri/pull/10641) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Added a dedicated type for IPC response body `InvokeResponseBody` for performance reasons. This is only a breaking change if you are directly using types from `tauri::ipc`. ## \[2.0.0-rc.2] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.2` - Upgraded to `tauri-runtime@2.0.0-rc.2` - Upgraded to `tauri-runtime-wry@2.0.0-rc.2` - Upgraded to `tauri-macros@2.0.0-rc.2` - Upgraded to `tauri-build@2.0.0-rc.2` ## \[2.0.0-rc.1] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.1` - Upgraded to `tauri-runtime@2.0.0-rc.1` - Upgraded to `tauri-runtime-wry@2.0.0-rc.1` - Upgraded to `tauri-macros@2.0.0-rc.1` - Upgraded to `tauri-build@2.0.0-rc.1` ## \[2.0.0-rc.0] ### Bug Fixes - [`6755af230`](https://www.github.com/tauri-apps/tauri/commit/6755af23021a254cff98c07aa7711545771097a6)([#10435](https://www.github.com/tauri-apps/tauri/pull/10435)) Fix Specta remote implementation target for `Channel`. - [`24445d71d`](https://www.github.com/tauri-apps/tauri/commit/24445d71de92d526d0ccaecb54f13003ddc6f6b4)([#10432](https://www.github.com/tauri-apps/tauri/pull/10432)) Fixes asset resolving when not using the `compression` feature. ### Enhancements - [`1e0793b68`](https://www.github.com/tauri-apps/tauri/commit/1e0793b6821799829e380c88066b3415cc9006df) ([#10357](https://www.github.com/tauri-apps/tauri/pull/10357)) Enhance `AssetResolver::get` in development mode by reading distDir directly as a fallback to the embedded assets. - [`7aeac39e7`](https://www.github.com/tauri-apps/tauri/commit/7aeac39e7fb97dc57ca278f1c097058275c20aa2) ([#10397](https://www.github.com/tauri-apps/tauri/pull/10397)) Make the set of gtk application id optional, to allow more then one instance of the app running at the same time. - [`cf994a6bb`](https://www.github.com/tauri-apps/tauri/commit/cf994a6bb064a50d3e5aef67e9a25903ee17a1e2) ([#10405](https://www.github.com/tauri-apps/tauri/pull/10405)) Add `tauri::plugin::Builder::try_build` to allow plugins to check if their `TauriPlugin` initialization is valid. ### Security fixes - [`426d14bb4`](https://www.github.com/tauri-apps/tauri/commit/426d14bb4164290d93b5a0f61e925cb2dfc4aafa) ([#10423](https://www.github.com/tauri-apps/tauri/pull/10423)) Explicitly check that the main frame's origin is the sender of Isolation Payloads - [`289ae5555`](https://www.github.com/tauri-apps/tauri/commit/289ae5555da3802741018015bfe4927729a2eb33) ([#10386](https://www.github.com/tauri-apps/tauri/pull/10386)) Re-enable TLS checks that were previously disabled to support an insecure HTTPS custom protocol on Android which is no longer used. ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.0` - Upgraded to `tauri-macros@2.0.0-rc.0` - Upgraded to `tauri-build@2.0.0-rc.0` - Upgraded to `tauri-runtime@2.0.0-rc.0` - Upgraded to `tauri-runtime-wry@2.0.0-rc.0` ### Breaking Changes - [`758d28c8a`](https://www.github.com/tauri-apps/tauri/commit/758d28c8a2d5c9567158e339326b765f72da983e) ([#10390](https://www.github.com/tauri-apps/tauri/pull/10390)) Core plugin permissions are now prefixed with `core:`, the `core:default` permission set can now be used and the `core` plugin name is reserved. The `tauri migrate` tool will automate the migration process, which involves prefixing all `app`, `event`, `image`, `menu`, `path`, `resources`, `tray`, `webview` and `window` permissions with `core:`. ## \[2.0.0-beta.25] ### New Features - [`da25f7353`](https://www.github.com/tauri-apps/tauri/commit/da25f7353070477ba969851e974379d7666d6806) ([#10242](https://www.github.com/tauri-apps/tauri/pull/10242) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add APIs to enable setting window size constraints separately: - Added `WindowBuilder::inner_size_constraints` and `WebviewWindowBuilder::inner_size_constraints` which can be used for setting granular constraints. - Added `WindowSizeConstraints` struct - Added `Window::set_size_constraints` and `WebviewWindow::set_size_constraints` ### Bug Fixes - [`e1776946a`](https://www.github.com/tauri-apps/tauri/commit/e1776946ad034d7a6e005834a754773671d9f7ef) ([#10362](https://www.github.com/tauri-apps/tauri/pull/10362) by [@Brendonovich](https://www.github.com/tauri-apps/tauri/../../Brendonovich)) Use ` specta rc.15's `derive\` feature which fixes build issues in docs.rs. - [`da25f7353`](https://www.github.com/tauri-apps/tauri/commit/da25f7353070477ba969851e974379d7666d6806) ([#10242](https://www.github.com/tauri-apps/tauri/pull/10242) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Apply `minWidth`, `minHieght`, `maxWidth` and `maxHeight` constraints separately, which fixes a long standing bug where these constraints were never applied unless width and height were constrained together. ### What's Changed - [`9546548ec`](https://www.github.com/tauri-apps/tauri/commit/9546548ec0c83ba620b1bc9d1d424a7009d0b423) ([#10297](https://www.github.com/tauri-apps/tauri/pull/10297) by [@pewsheen](https://www.github.com/tauri-apps/tauri/../../pewsheen)) On macOS, set default titlebar style to `Visible` to prevent webview move out of the view. ### Dependencies - Upgraded to `tauri-runtime-wry@2.0.0-beta.21` - Upgraded to `tauri-runtime@2.0.0-beta.21` ## \[2.0.0-beta.24] ### New Features - [`7bc6a2a1d`](https://www.github.com/tauri-apps/tauri/commit/7bc6a2a1d6d2c5406d91cac94d33bce76443c28f) ([#9788](https://www.github.com/tauri-apps/tauri/pull/9788) by [@pewsheen](https://www.github.com/tauri-apps/tauri/../../pewsheen)) Add a new method to set title bar style dynamically on macOS. ### Enhancements - [`a7354f9a8`](https://www.github.com/tauri-apps/tauri/commit/a7354f9a81d4db83ff3d34b29617717117ad64d2) ([#10171](https://www.github.com/tauri-apps/tauri/pull/10171) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Mark `AppHandle::restart` and `process::restart` as [diverging functions](https://doc.rust-lang.org/rust-by-example/fn/diverging.html). ### Bug Fixes - [`4c239729c`](https://www.github.com/tauri-apps/tauri/commit/4c239729c3e1b899ecbc6793c3682848e8de1729) ([#10167](https://www.github.com/tauri-apps/tauri/pull/10167) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix deserialization of raw invoke requests when using `isolation` pattern. - [`55733aba9`](https://www.github.com/tauri-apps/tauri/commit/55733aba9c5a5c8d664afea0c83d9337bc99387d) ([#10176](https://www.github.com/tauri-apps/tauri/pull/10176) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Move `PluginApi::register_ios_plugin` behind the `wry` Cargo feature as `Webview::with_webview` is only available when that feature is enabled. ### Dependencies - Upgraded to `tauri-macros@2.0.0-beta.19` - Upgraded to `tauri-build@2.0.0-beta.19` - Upgraded to `tauri-runtime-wry@2.0.0-beta.20` - Upgraded to `tauri-utils@2.0.0-beta.19` - Upgraded to `tauri-runtime@2.0.0-beta.20` ### Breaking Changes - [`ba9590aa9`](https://www.github.com/tauri-apps/tauri/commit/ba9590aa92a67a11fa1e559e506d87b7e643cc24) ([#9640](https://www.github.com/tauri-apps/tauri/pull/9640) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Added `Emitter` and `Listener` traits that defines what an emitter or a listener can do, this however comes with a few breaking changes: - Removed `Manager::listen_any`, use `Listener::listen_any` instead. - Removed `Manager::once_any`, use `Listener::once_any` instead. - Removed `Manager::unlisten`, use `Listener::unlisten` instead. - Removed `Manager::emit`, use `Emitter::emit` instead. - Removed `Manager::emit_to`, use `Emitter::emit_to` instead. - Removed `Manager::emit_filter`, use `Emitter::emit_filter` instead. - Removed `App/AppHandle::listen`, `WebviewWindow::listen`, `Window::listen` and `Webview::listen`, use `Listener::listen` instead. - Removed `App/AppHandle::once`, `WebviewWindow::once`, `Window::once` and `Webview::once`, use `Listener::once` instead. - Removed `App/AppHandle::unlisten`, `WebviewWindow::unlisten`, `Window::unlisten` and `Webview::unlisten`, use `Listener::unlisten` instead. - [`261c9f942`](https://www.github.com/tauri-apps/tauri/commit/261c9f942de9a598b5c6cc504de6bddd1306113b) ([#10170](https://www.github.com/tauri-apps/tauri/pull/10170) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Renamed `DragDropEvent` enum variants to better convey when they are triggered: - `DragDropEvent::Dragged` -> `DragDropEvent::Enter` - `DragDropEvent::DragOver` -> `DragDropEvent::Over` - `DragDropEvent::Dropped` -> `DragDropEvent::Drop` - `DragDropEvent::Cancelled` -> `DragDropEvent::Leave` This also comes with a change in the events being emitted to JS and Rust event listeners: - `tauri://drag` -> `tauri://drag-enter` - `tauri://drop-over` -> `tauri://drag-over` - `tauri://drop` -> `tauri://drag-drop` - `tauri://drag-cancelled` -> `tauri://drag-leave` - [`2b1ceb40d`](https://www.github.com/tauri-apps/tauri/commit/2b1ceb40d345aef42dd79438fa69ca7989ee0194) ([#10229](https://www.github.com/tauri-apps/tauri/pull/10229) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Renamed the JS `getCurrent` and `getAll` functions to a clearer name to avoid ambiguity: - `getCurrent` in `window` module has been renamed to `getCurrentWindow` - `getCurrent` in `webview` module has been renamed to `getCurrentWebview` - `getCurrent` in `webviewWindow` module has been renamed to `getCurrentWebviewWindow` - `getAll` in `window` module has been renamed to `getAllWindows` - `getAll` in `webview` module has been renamed to `getAllWebviews` - `getAll` in `webviewWindow` module has been renamed to `getAllWebviewWindows` - [`57612ab24`](https://www.github.com/tauri-apps/tauri/commit/57612ab24963b02d769ce408b0283ef552fb7b0d) ([#10139](https://www.github.com/tauri-apps/tauri/pull/10139) by [@Brendonovich](https://www.github.com/tauri-apps/tauri/../../Brendonovich)) Add `TSend` generic to `ipc::Channel` for typesafe `send` calls and type inspection in `tauri-specta` ## \[2.0.0-beta.23] ### New Features - [`148f04887`](https://www.github.com/tauri-apps/tauri/commit/148f048871caee21498b236c058b8890f2b66cc7) ([#9979](https://www.github.com/tauri-apps/tauri/pull/9979)) Add `defaultWindowIcon` to the JS `app` module to retrieve the default window icon in JS. - [`5b769948a`](https://www.github.com/tauri-apps/tauri/commit/5b769948a81cac333f64c870a470ba6525bd5cd3) ([#9959](https://www.github.com/tauri-apps/tauri/pull/9959)) Add `include_image` macro to help embedding instances of `Image` struct at compile-time in rust to be used with window, menu or tray icons. - [`ddaabda36`](https://www.github.com/tauri-apps/tauri/commit/ddaabda365ed5dc0780925049473989cbd1d7ea3) ([#9922](https://www.github.com/tauri-apps/tauri/pull/9922)) Add `WebviewWindowBuilder::on_download`. ### Enhancements - [`cee0bfcd6`](https://www.github.com/tauri-apps/tauri/commit/cee0bfcd6c03c2a6794abca8f4fde700f3f818ba) ([#10092](https://www.github.com/tauri-apps/tauri/pull/10092)) Make `tray:default` and `menu:default` include all tray and menu permissions ### Bug Fixes - [`e93ca1df3`](https://www.github.com/tauri-apps/tauri/commit/e93ca1df3b3948647f501f9f958e894ade6a27fb) ([#10138](https://www.github.com/tauri-apps/tauri/pull/10138)) Fix `InvokeBody::deserialize` method deserialization for `InvokeBody::Raw` variant - [`e6e17ad1c`](https://www.github.com/tauri-apps/tauri/commit/e6e17ad1c8a6b53463946c407a354c250bd7e701) ([#9954](https://www.github.com/tauri-apps/tauri/pull/9954)) Add `std` feature to `raw-window-handle` crate so that using `default-features = false` on `tauri` crate can work - [`f29b78811`](https://www.github.com/tauri-apps/tauri/commit/f29b78811080bc8313459f34545152d939c62bf6) ([#9862](https://www.github.com/tauri-apps/tauri/pull/9862)) On Windows, handle resizing undecorated windows natively which improves performance and fixes a couple of annoyances with previous JS implementation: - No more cursor flickering when moving the cursor across an edge. - Can resize from top even when `data-tauri-drag-region` element exists there. - Upon starting rezing, clicks don't go through elements behind it so no longer accidental clicks. ### What's Changed - [`669b9c6b5`](https://www.github.com/tauri-apps/tauri/commit/669b9c6b5af791129b77ee440dacaa98288c906b) ([#9621](https://www.github.com/tauri-apps/tauri/pull/9621)) Set the gtk application to the identifier defined in `tauri.conf.json` to ensure the app uniqueness. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.18` - Upgraded to `tauri-build@2.0.0-beta.18` - Upgraded to `tauri-macros@2.0.0-beta.18` - Upgraded to `tauri-runtime-wry@2.0.0-beta.19` - Upgraded to `tauri-runtime@2.0.0-beta.19` - [`f955f7b49`](https://www.github.com/tauri-apps/tauri/commit/f955f7b4903bcea376c0a8b430736f66c8cebf56) ([#9929](https://www.github.com/tauri-apps/tauri/pull/9929)) Switch from `dirs_next` to `dirs` as `dirs_next` is now unmaintained while `dirs` is - [`d4c908cfb`](https://www.github.com/tauri-apps/tauri/commit/d4c908cfb8c567abdaf99b85f65f482ea81967e5) ([#10048](https://www.github.com/tauri-apps/tauri/pull/10048)) Update `windows` crate to version `0.57` and `webview2-com` crate to version `0.31` ### Breaking Changes - [`3afe82894`](https://www.github.com/tauri-apps/tauri/commit/3afe8289407b53791e761764964a42207a7f7881) ([#10134](https://www.github.com/tauri-apps/tauri/pull/10134)) Changed `WebviewWindow::navigate` and `Webview::navigate` method signature to return a `Result` ## \[2.0.0-beta.22] ### Bug Fixes - [`dfd05441c`](https://www.github.com/tauri-apps/tauri/commit/dfd05441c761b1737e29794ab1f02e41e5d7cc12)([#9860](https://www.github.com/tauri-apps/tauri/pull/9860)) Revert adding `app-region: drag` to HTML elements with `data-tauri-drag-region` on Windows as it has a few issues: - Doesn't allow right click, as it will always show the system context menu on right click. - `data-tauri-drag-region` works only if the click was on an element that has it, this allows buttons in the custom titlebar to work, however `app-region: drag` will treat the whole area as a titlebar won't even allow clicks on buttons. ## \[2.0.0-beta.21] ### New Features - [`8a1ae2dea`](https://www.github.com/tauri-apps/tauri/commit/8a1ae2deaf3086e531ada25b1627f900e2e421fb)([#9843](https://www.github.com/tauri-apps/tauri/pull/9843)) Added an option to use a Xcode project for the iOS plugin instead of a plain SwiftPM project. ### Bug Fixes - [`276c4b143`](https://www.github.com/tauri-apps/tauri/commit/276c4b14385e17cff15a2e5b57fd2a7cddef9f08)([#9832](https://www.github.com/tauri-apps/tauri/pull/9832)) On Windows, fix wrong menubar theme when window is using an explicit theme. - [`ccc3ea729`](https://www.github.com/tauri-apps/tauri/commit/ccc3ea729de205ef467f737f1feeb5bf02d9cd72)([#9646](https://www.github.com/tauri-apps/tauri/pull/9646)) Parse the correct platform `tauri..conf.json` config file when building or developing for mobile. - [`aa55e0335`](https://www.github.com/tauri-apps/tauri/commit/aa55e033540cc77c3fb159b9230337d9dd33034e)([#9899](https://www.github.com/tauri-apps/tauri/pull/9899)) Set default window origin to `null`. Prevent window crash when loading `about:blank`. ### What's Changed - [`9ac930380`](https://www.github.com/tauri-apps/tauri/commit/9ac930380a5df3fe700e68e75df8684d261ca292)([#9850](https://www.github.com/tauri-apps/tauri/pull/9850)) Emit `cargo:rustc-check-cfg` instruction so Cargo validates custom cfg attributes on Rust 1.80 (or nightly-2024-05-05). - [`80aa50498`](https://www.github.com/tauri-apps/tauri/commit/80aa504987dd9cfa59aa5848c4d7960e1d58d0e6)([#9870](https://www.github.com/tauri-apps/tauri/pull/9870)) Updated Android target SDK to 34. ### Dependencies - Upgraded to `tauri-build@2.0.0-beta.17` - Upgraded to `tauri-macros@2.0.0-beta.17` - Upgraded to `tauri-utils@2.0.0-beta.17` - Upgraded to `tauri-runtime@2.0.0-beta.18` - Upgraded to `tauri-runtime-wry@2.0.0-beta.18` ### Breaking Changes - [`e8f6eb59a`](https://www.github.com/tauri-apps/tauri/commit/e8f6eb59a5eaad26ae0314ac9e4c0061e6bd25fe)([#9552](https://www.github.com/tauri-apps/tauri/pull/9552)) Include binary path in `Env.args_os`, previously it was skipped. - [`1df5cdeb0`](https://www.github.com/tauri-apps/tauri/commit/1df5cdeb06f5464e0eec4055e21b7b7bc8739eed)([#9858](https://www.github.com/tauri-apps/tauri/pull/9858)) Use `tauri.conf.json > identifier` to set the `PackageName` in Android and `BundleId` in iOS. - [`aaecb6a72`](https://www.github.com/tauri-apps/tauri/commit/aaecb6a72e5d1462967cc910c2628999997742d0)([#9890](https://www.github.com/tauri-apps/tauri/pull/9890)) Renamed `dev` function to `is_dev` and marked it as `const fn` - [`c4410daa8`](https://www.github.com/tauri-apps/tauri/commit/c4410daa85616340e911c8243fdaa69e6906fd49)([#9777](https://www.github.com/tauri-apps/tauri/pull/9777)) This release contains breaking changes to the tray event structure because of newly added events: - Changed `TrayIconEvent` to be an enum instead of a struct. - Added `MouseButtonState` and `MouseButton` enums. - Removed `ClickType` enum and replaced it with `MouseButton` enum. - Added `MouseButtonState` enum. ## \[2.0.0-beta.20] ### New Features - [`ae6b13dfc`](https://www.github.com/tauri-apps/tauri/commit/ae6b13dfc0590dcaedbdb619c148072f072df050)([#9789](https://www.github.com/tauri-apps/tauri/pull/9789)) Add `app-region: drag` to HTML elements with `data-tauri-drag-region` on Windows, only WebView2 123+, which should fix dragging using touch. - [`ec0e092ec`](https://www.github.com/tauri-apps/tauri/commit/ec0e092ecd23b547c756c7476f23a0d95be6db80)([#9770](https://www.github.com/tauri-apps/tauri/pull/9770)) Add `App/AppHandle/Window/Webview/WebviewWindow::monitor_from_point(x, y)` getter to get the monitor from a given point. ### Enhancements - [`5d20530c9`](https://www.github.com/tauri-apps/tauri/commit/5d20530c91495e548ecc9cb4369da09977a9a962)([#9842](https://www.github.com/tauri-apps/tauri/pull/9842)) Added `AppHandle::set_activation_policy` for macOS. ### Bug Fixes - [`0b690f242`](https://www.github.com/tauri-apps/tauri/commit/0b690f242f3a9fdffc268ee66464151b3466d00b)([#9845](https://www.github.com/tauri-apps/tauri/pull/9845)) Export `tauri::UriSchemeResponder`. ### Security fixes - [`d950ac123`](https://www.github.com/tauri-apps/tauri/commit/d950ac1239817d17324c035e5c4769ee71fc197d) Only process IPC commands from the main frame. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.16` - Upgraded to `tauri-runtime-wry@2.0.0-beta.17` - Upgraded to `tauri-runtime@2.0.0-beta.17` - Upgraded to `tauri-macros@2.0.0-beta.16` - Upgraded to `tauri-build@2.0.0-beta.16` ## \[2.0.0-beta.19] ### New Features - [`78839b6d2`](https://www.github.com/tauri-apps/tauri/commit/78839b6d2f1005a5e6e1a54b0305136bae0c3a7c)([#4865](https://www.github.com/tauri-apps/tauri/pull/4865)) Add `RunEvent::Reopen` for handle click on dock icon on macOS. ### Bug Fixes - [`fedca7386`](https://www.github.com/tauri-apps/tauri/commit/fedca7386079fe639c629d6084cc13031150baf6)([#9720](https://www.github.com/tauri-apps/tauri/pull/9720)) Fix IPC tracing format incompatible between the custom protocol and the postMessage implementations. ### Dependencies - Upgraded to `tauri-runtime@2.0.0-beta.16` - Upgraded to `tauri-runtime-wry@2.0.0-beta.16` - Upgraded to `tauri-utils@2.0.0-beta.15` - Upgraded to `tauri-macros@2.0.0-beta.15` - Upgraded to `tauri-build@2.0.0-beta.15` ### Breaking Changes - [`783ef0f2d`](https://www.github.com/tauri-apps/tauri/commit/783ef0f2d331f520fa827c3112f36c0b519b9292)([#9647](https://www.github.com/tauri-apps/tauri/pull/9647)) Changed `WebviewWindow::url` and `Webview::url` getter to return a result. ## \[2.0.0-beta.18] ### New Features - [`07ff78c2d`](https://www.github.com/tauri-apps/tauri/commit/07ff78c2de74d3bd85328ce6536f8a858be89128)([#9615](https://www.github.com/tauri-apps/tauri/pull/9615)) Add `TrayIcon::rect` method to retrieve the tray icon rectangle ### Enhancements - [`7f6d2698c`](https://www.github.com/tauri-apps/tauri/commit/7f6d2698c923019e4ce53f794e68aa7e56fd7b86)([#9631](https://www.github.com/tauri-apps/tauri/pull/9631)) Improve the error message that is shown when deserializing the Tauri plugin config. - [`8a71858eb`](https://www.github.com/tauri-apps/tauri/commit/8a71858eb2a9dc12a43d8fb56f803cdcae072b68)([#9630](https://www.github.com/tauri-apps/tauri/pull/9630)) Provide a default for the runtime generic on `Menu`, `MenuItem`, `Submenu`, `PredefinedMenuItem`, `CheckMenuItem` and `IconMenuItem`. - [`8a71858eb`](https://www.github.com/tauri-apps/tauri/commit/8a71858eb2a9dc12a43d8fb56f803cdcae072b68)([#9630](https://www.github.com/tauri-apps/tauri/pull/9630)) Provide a default for the runtime generic on `TrayIcon`. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.14` - Upgraded to `tauri-runtime@2.0.0-beta.15` - Upgraded to `tauri-runtime-wry@2.0.0-beta.15` - Upgraded to `tauri-macros@2.0.0-beta.14` - Upgraded to `tauri-build@2.0.0-beta.14` ## \[2.0.0-beta.17] ### New Features - [`12b4159bd`](https://www.github.com/tauri-apps/tauri/commit/12b4159bdaf6e1f8d7b58ed8ff96345fa69c2ef0)([#9392](https://www.github.com/tauri-apps/tauri/pull/9392)) Add `specta` feature flag which adds `specta` support for `AppHandle`, `State`, `Window`, `Webview` and `WebviewWindow` types. - [`477bb8cd4`](https://www.github.com/tauri-apps/tauri/commit/477bb8cd4ea88ade3f6c1f268ad1701a68150161)([#9297](https://www.github.com/tauri-apps/tauri/pull/9297)) Add `App/AppHandle/Window/Webview/WebviewWindow::cursor_position` getter to get the current cursor position. ### Enhancements - [`eff778b8f`](https://www.github.com/tauri-apps/tauri/commit/eff778b8f0c675fda3f6f6d1041bc94afd765d1c)([#9571](https://www.github.com/tauri-apps/tauri/pull/9571)) Run each plugin initialization script on its own context so they do not interfere with each other or the Tauri init script. ### Bug Fixes - [`6c047aee1`](https://www.github.com/tauri-apps/tauri/commit/6c047aee14fcae86b341e4fcefdbbf8f8378ac20)([#9612](https://www.github.com/tauri-apps/tauri/pull/9612)) Fix window white flashing on exit on Windows - [`98101cb17`](https://www.github.com/tauri-apps/tauri/commit/98101cb17fe49f305a75fcb4267f82d89f7ac0c3)([#9561](https://www.github.com/tauri-apps/tauri/pull/9561)) Allow any headers on the IPC custom protocol. ### Dependencies - Upgraded to `tauri-runtime@2.0.0-beta.14` - Upgraded to `tauri-runtime-wry@2.0.0-beta.14` ## \[2.0.0-beta.16] ### New Features - [`70c51371e`](https://www.github.com/tauri-apps/tauri/commit/70c51371e01184223312de3dba8030394a5a9406)([#9539](https://www.github.com/tauri-apps/tauri/pull/9539)) Add `window.isTauri` to check whether running inside tauri or not. ### Bug Fixes - [`daf018e4f`](https://www.github.com/tauri-apps/tauri/commit/daf018e4f5d5f6dcde51c5de42d73ab15287ec7e)([#9505](https://www.github.com/tauri-apps/tauri/pull/9505)) Fix resource tables not cleaned up on exit which causes tray icon inside resource tables not cleaned up on exit - [`a07b51320`](https://www.github.com/tauri-apps/tauri/commit/a07b5132019faa7695c573a6610d2def0ff9c40a)([#9490](https://www.github.com/tauri-apps/tauri/pull/9490)) Add missing permission for `window.start_resize_dragging` - [`35b25f7e5`](https://www.github.com/tauri-apps/tauri/commit/35b25f7e5c0fe03af4ed3582e22a626863f035f0)([#9530](https://www.github.com/tauri-apps/tauri/pull/9530)) Do not use JS optional chaining to prevent script errors on older webviews such as macOS 10.14. ### What's Changed - [`005fe8ce1`](https://www.github.com/tauri-apps/tauri/commit/005fe8ce1ef71ea46a7d86f98bdf397ca81eb920)([#9410](https://www.github.com/tauri-apps/tauri/pull/9410)) Fix `closable`, `maximizable` and `minimizable` options not taking effect when used in tauri.conf.json or from JS APIs. ### Dependencies - Upgraded to `tauri-runtime-wry@2.0.0-beta.13` - Upgraded to `tauri-build@2.0.0-beta.13` - Upgraded to `tauri-utils@2.0.0-beta.13` - Upgraded to `tauri-runtime@2.0.0-beta.13` - Upgraded to `tauri-macros@2.0.0-beta.13` ## \[2.0.0-beta.15] ### New Features - [`58a7a552d`](https://www.github.com/tauri-apps/tauri/commit/58a7a552d739b77b71d61af11c53f7f2dc7a6e7e)([#9378](https://www.github.com/tauri-apps/tauri/pull/9378)) Added the `set_zoom` function to the webview API. - [`58a7a552d`](https://www.github.com/tauri-apps/tauri/commit/58a7a552d739b77b71d61af11c53f7f2dc7a6e7e)([#9378](https://www.github.com/tauri-apps/tauri/pull/9378)) Add `zoom_hotkeys_enabled` to enable browser native zoom controls on creating webviews. - [`4973d73a2`](https://www.github.com/tauri-apps/tauri/commit/4973d73a237dc5c60618c1011e202278e7a29b5c)([#9386](https://www.github.com/tauri-apps/tauri/pull/9386)) Provide a basic zoom hotkey polyfill for non-Windows platforms ### Enhancements - [`f1674fce6`](https://www.github.com/tauri-apps/tauri/commit/f1674fce6dfb1cf0378a85165bb62c270715211b)([#9420](https://www.github.com/tauri-apps/tauri/pull/9420)) Tauri's built-in commands for the JS api will now return simplified paths on Windows, removing the `\\?\` prefix. ### Bug Fixes - [`c8a82ad22`](https://www.github.com/tauri-apps/tauri/commit/c8a82ad2236ee1def621b5930bdb136f01dd07e4)([#9379](https://www.github.com/tauri-apps/tauri/pull/9379)) Fix deadlock when using the menu/tray/image JS APIs. - [`6251645ac`](https://www.github.com/tauri-apps/tauri/commit/6251645acfe2df2da726f38a09373d7370bfcc86)([#9360](https://www.github.com/tauri-apps/tauri/pull/9360)) Fixes an issue causing `getAll()` to list webviews that were already destroyed. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.12` - Upgraded to `tauri-runtime-wry@2.0.0-beta.12` - Upgraded to `tauri-runtime@2.0.0-beta.12` - Upgraded to `tauri-macros@2.0.0-beta.12` - Upgraded to `tauri-build@2.0.0-beta.12` ### Breaking Changes - [`c8a82ad22`](https://www.github.com/tauri-apps/tauri/commit/c8a82ad2236ee1def621b5930bdb136f01dd07e4)([#9379](https://www.github.com/tauri-apps/tauri/pull/9379)) Changed `JsImage::into_img` to take a reference to a `ResourceTable` instead of a `Manager`. ## \[2.0.0-beta.14] ### New Features - [`06833f4fa`](https://www.github.com/tauri-apps/tauri/commit/06833f4fa8e63ecc55fe3fc874a9e397e77a5709)([#9100](https://www.github.com/tauri-apps/tauri/pull/9100)) Added `Rect` struct. - [`06833f4fa`](https://www.github.com/tauri-apps/tauri/commit/06833f4fa8e63ecc55fe3fc874a9e397e77a5709)([#9100](https://www.github.com/tauri-apps/tauri/pull/9100)) Add `Webview::bounds` and `Webview::set_bounds` APIs. ### Enhancements - [`06833f4fa`](https://www.github.com/tauri-apps/tauri/commit/06833f4fa8e63ecc55fe3fc874a9e397e77a5709)([#9100](https://www.github.com/tauri-apps/tauri/pull/9100)) Enhance the IPC URL check by using the Origin header on the custom protocol IPC and the new request URI field on the postMessage IPC instead of using `Webview::url()` which only returns the URL of the main frame and is not suitable for iframes (iframe URL fetch is still not supported on Android and on Linux when using the postMessage IPC). ### Bug Fixes - [`c33f6e6cf`](https://www.github.com/tauri-apps/tauri/commit/c33f6e6cf35a0d34b5598875a2e5b642a01c8b38)([#9211](https://www.github.com/tauri-apps/tauri/pull/9211)) Fixed an issue preventing webview/window creation events to not be emitted. This also fixed the `getByLabel` and `getAll` JavaScript functions. ### What's Changed - [`06833f4fa`](https://www.github.com/tauri-apps/tauri/commit/06833f4fa8e63ecc55fe3fc874a9e397e77a5709)([#9100](https://www.github.com/tauri-apps/tauri/pull/9100)) Updated `http` crate to `1.1` ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.11` - Upgraded to `tauri-runtime-wry@2.0.0-beta.11` - Upgraded to `tauri-runtime@2.0.0-beta.11` - Upgraded to `tauri-macros@2.0.0-beta.11` - Upgraded to `tauri-build@2.0.0-beta.11` ### Breaking Changes - [`06833f4fa`](https://www.github.com/tauri-apps/tauri/commit/06833f4fa8e63ecc55fe3fc874a9e397e77a5709)([#9100](https://www.github.com/tauri-apps/tauri/pull/9100)) Rename `FileDrop` to `DragDrop` on structs, enums and enum variants. Also renamed `file_drop` to `drag_drop` on fields and function names. - [`284eca9ef`](https://www.github.com/tauri-apps/tauri/commit/284eca9ef2396b76ce3df6f32fb3b2d2c40044ad)([#9272](https://www.github.com/tauri-apps/tauri/pull/9272)) `Manager::resources_table` is now scoped so each `App/AppHandle/Window/Webview/WebviewWindow` has its own resource collection. - [`06833f4fa`](https://www.github.com/tauri-apps/tauri/commit/06833f4fa8e63ecc55fe3fc874a9e397e77a5709)([#9100](https://www.github.com/tauri-apps/tauri/pull/9100)) Refactored the tray icon event struct: - Changed `TrayIconEvent.icon_rect` type to use the new `tauri::Rect` type. - Removed `TrayIconEvent.x` and `TrayIconEvent.y` fields and combined them into `TrayIconEvent.position` field. - Removed `tauri::tray::Rectangle` struct. ## \[2.0.0-beta.13] ### Enhancements - [`75f5cb401`](https://www.github.com/tauri-apps/tauri/commit/75f5cb4015f72745161110ad0076cf4945411a6d)([#9214](https://www.github.com/tauri-apps/tauri/pull/9214)) `tauri::Window` and `tauri::WebviewWindow` now implement `raw_window_handle::HasDisplayHandle`. ### Bug Fixes - [`81b853bc8`](https://www.github.com/tauri-apps/tauri/commit/81b853bc875ce2da4e300614ca234f10d54966a6)([#9213](https://www.github.com/tauri-apps/tauri/pull/9213)) Fixed an issue where errors where returned as strings instead of objects from commands. - [`43230cb6b`](https://www.github.com/tauri-apps/tauri/commit/43230cb6b7a4b14a23ea8f05636ae06f03c718e9)([#9219](https://www.github.com/tauri-apps/tauri/pull/9219)) Fixes the menu plugin `remove` command signature. ## \[2.0.0-beta.12] ### New Features - [`e227fe02f`](https://www.github.com/tauri-apps/tauri/commit/e227fe02f986e145c0731a64693e1c830a9eb5b0)([#9156](https://www.github.com/tauri-apps/tauri/pull/9156)) Allow plugins to define (at compile time) JavaScript that are initialized when `withGlobalTauri` is true. ### Enhancements - [`79b8a3514`](https://www.github.com/tauri-apps/tauri/commit/79b8a3514baedcd9c35e777d2b6d89a7a086ddec)([#9151](https://www.github.com/tauri-apps/tauri/pull/9151)) Improve and optimize event emit calls. ### Bug Fixes - [`379cc2b35`](https://www.github.com/tauri-apps/tauri/commit/379cc2b3547395474d4b66b4222679cf4538428d)([#9165](https://www.github.com/tauri-apps/tauri/pull/9165)) Fix `basename(path, 'ext')` JS API when removing all occurances of `ext` where it should only remove the last one. ### Dependencies - Upgraded to `tauri-build@2.0.0-beta.10` - Upgraded to `tauri-utils@2.0.0-beta.10` - Upgraded to `tauri-runtime@2.0.0-beta.10` - Upgraded to `tauri-runtime-wry@2.0.0-beta.10` - Upgraded to `tauri-macros@2.0.0-beta.10` ### Breaking Changes - [`acdd76833`](https://www.github.com/tauri-apps/tauri/commit/acdd76833db6d81f4012418133d0042220de100b)([#9155](https://www.github.com/tauri-apps/tauri/pull/9155)) Removed `App/AppHandle::tray` and `App/AppHandle::remove_tray`, use `App/AppHandle::tray_by_id` and `App/AppHandle::remove_tray_by_id` instead. If these APIs were used to access tray icon configured in `tauri.conf.json`, you can use `App/AppHandle::tray_by_id` with ID `main` or the configured value. - [`ea0242db4`](https://www.github.com/tauri-apps/tauri/commit/ea0242db4aa6c127d2bb4a2e275000ba47c9e68c)([#9179](https://www.github.com/tauri-apps/tauri/pull/9179)) Removed `width` and `height` methods on the JS `Image` class, use `size` instead. ## \[2.0.0-beta.11] ### New Features - [`490a6b424`](https://www.github.com/tauri-apps/tauri/commit/490a6b424e81714524150aef96fbf6cf7004b940)([#9147](https://www.github.com/tauri-apps/tauri/pull/9147)) The `Assets` trait now include a `setup` method that lets you run initialization code for your custom asset provider. ### Bug Fixes - [`85de230f3`](https://www.github.com/tauri-apps/tauri/commit/85de230f313da81cbbd061e66e8de64e5b33104c)([#9144](https://www.github.com/tauri-apps/tauri/pull/9144)) Fix old JS listeners being dropped on page load after it was possible to create new listeners. - [`e673854c8`](https://www.github.com/tauri-apps/tauri/commit/e673854c8333cb8a8d298471737293f17ec5a3ee)([#9133](https://www.github.com/tauri-apps/tauri/pull/9133)) Fixes capability remote domain not allowing subpaths, query parameters and hash when those values are empty. ### Dependencies - Upgraded to `tauri-macros@2.0.0-beta.9` - Upgraded to `tauri-utils@2.0.0-beta.9` - Upgraded to `tauri-build@2.0.0-beta.9` - Upgraded to `tauri-runtime@2.0.0-beta.9` - Upgraded to `tauri-runtime-wry@2.0.0-beta.9` ### Breaking Changes - [`490a6b424`](https://www.github.com/tauri-apps/tauri/commit/490a6b424e81714524150aef96fbf6cf7004b940)([#9147](https://www.github.com/tauri-apps/tauri/pull/9147)) The `Context` struct and the `Assets` trait now takes a `R: Runtime` generic. - [`ba0206d8a`](https://www.github.com/tauri-apps/tauri/commit/ba0206d8a30a9b43ec5090dcaabd1a23baa1420c)([#9141](https://www.github.com/tauri-apps/tauri/pull/9141)) `Context::assets` now returns `&dyn Assets` instead of `&A` generic. - [`ba0206d8a`](https://www.github.com/tauri-apps/tauri/commit/ba0206d8a30a9b43ec5090dcaabd1a23baa1420c)([#9141](https://www.github.com/tauri-apps/tauri/pull/9141)) The `Context` type no longer uses the `` generic so the assets implementation can be swapped with `Context::assets_mut`. - [`490a6b424`](https://www.github.com/tauri-apps/tauri/commit/490a6b424e81714524150aef96fbf6cf7004b940)([#9147](https://www.github.com/tauri-apps/tauri/pull/9147)) Removed `Context::assets_mut` and added `Context::set_assets`. - [`db0a24a97`](https://www.github.com/tauri-apps/tauri/commit/db0a24a973191752aeecfbd556faa254b0f17e79)([#9132](https://www.github.com/tauri-apps/tauri/pull/9132)) Use the image crate for `tauri::image::Image` and remove the `from_png_bytes` and `from_ico_bytes` APIs. ## \[2.0.0-beta.10] ### New Features - [`3e472d0af`](https://www.github.com/tauri-apps/tauri/commit/3e472d0afcd67545dd6d9f18d304580a3b2759a8)([#9115](https://www.github.com/tauri-apps/tauri/pull/9115)) Added `CapabilityBuilder::platform` to link the runtime capability with a specific platform. ### Enhancements - [`3e472d0af`](https://www.github.com/tauri-apps/tauri/commit/3e472d0afcd67545dd6d9f18d304580a3b2759a8)([#9115](https://www.github.com/tauri-apps/tauri/pull/9115)) Changed the permission and capability platforms to be optional. - [`9dc9ca6e3`](https://www.github.com/tauri-apps/tauri/commit/9dc9ca6e38be62ef2746c7a4c2b77b2d67c0d998)([#9113](https://www.github.com/tauri-apps/tauri/pull/9113)) Added `tauri::dev()` to determine whether we are running in development mode or not. ### Bug Fixes - [`5541aafef`](https://www.github.com/tauri-apps/tauri/commit/5541aafef33113bc292558ba125e685135aabab4)([#9107](https://www.github.com/tauri-apps/tauri/pull/9107)) Fix `emit` and `emit_to` (when used with `EventTarget::Any`) always skipping the webview listeners. - [`80c12ead4`](https://www.github.com/tauri-apps/tauri/commit/80c12ead4655af91f08046f19c2d478a4cbf94cd)([#9121](https://www.github.com/tauri-apps/tauri/pull/9121)) Fix regression on IPC response when using a channel to return objects. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.8` - Upgraded to `tauri-runtime@2.0.0-beta.8` - Upgraded to `tauri-runtime-wry@2.0.0-beta.8` - Upgraded to `tauri-macros@2.0.0-beta.8` - Upgraded to `tauri-build@2.0.0-beta.8` ### Breaking Changes - [`4ef17d083`](https://www.github.com/tauri-apps/tauri/commit/4ef17d08336a2e0df4a7ef9adea746d7419710b6)([#9116](https://www.github.com/tauri-apps/tauri/pull/9116)) The ACL configuration for remote URLs now uses the URLPattern standard instead of glob patterns. - [`ed48e2b3c`](https://www.github.com/tauri-apps/tauri/commit/ed48e2b3c7fa914e4c9af432c02b8154f872c68a)([#9122](https://www.github.com/tauri-apps/tauri/pull/9122)) Expose `tauri::image` module to export the `JsImage` type and removed the `Image` root re-export. ## \[2.0.0-beta.9] ### New Features - [`46de49aaa`](https://www.github.com/tauri-apps/tauri/commit/46de49aaad4a148fafc31d591be0e2ed12256507)([#9059](https://www.github.com/tauri-apps/tauri/pull/9059)) Added `set_auto_resize` method for the webview. - [`d1e77acd8`](https://www.github.com/tauri-apps/tauri/commit/d1e77acd8dfdf554b90b542513a58a2de1ef2360)([#9011](https://www.github.com/tauri-apps/tauri/pull/9011)) Add a new `Image` type in Rust and JS. ### Enhancements - [`a77be9747`](https://www.github.com/tauri-apps/tauri/commit/a77be9747443ffc29c34160b55893483bb5f0d74)([#9038](https://www.github.com/tauri-apps/tauri/pull/9038)) Fallback to the postMessage IPC interface if we cannot reach the IPC custom protocol. - [`e62ca4ee9`](https://www.github.com/tauri-apps/tauri/commit/e62ca4ee95f4308a6ad128d0f100c85634e28223)([#9070](https://www.github.com/tauri-apps/tauri/pull/9070)) Added a mechanism to preserve channel message order. - [`03098b531`](https://www.github.com/tauri-apps/tauri/commit/03098b531562e4d58ab12ad9da2acb1eb3480497)([#9036](https://www.github.com/tauri-apps/tauri/pull/9036)) `Manager::add_capability` now allows adding a dynamically defined capability instead of only relying on static strings. - [`b5c743276`](https://www.github.com/tauri-apps/tauri/commit/b5c7432769b84ffe22db721dcfc6af218026f5d4)([#9086](https://www.github.com/tauri-apps/tauri/pull/9086)) Use a strict content security policy on the isolation pattern iframe. - [`46de49aaa`](https://www.github.com/tauri-apps/tauri/commit/46de49aaad4a148fafc31d591be0e2ed12256507)([#9059](https://www.github.com/tauri-apps/tauri/pull/9059)) When using the `unstable` feature flag, `WebviewWindow` will internally use the child webview interface for flexibility. ### Bug Fixes - [`86fa339de`](https://www.github.com/tauri-apps/tauri/commit/86fa339de7b176efafa9b3e89f94dcad5fcd03da)([#9071](https://www.github.com/tauri-apps/tauri/pull/9071)) Fix compile time error in context generation when using `app.windows.windowEffects.color` - [`947a50b8e`](https://www.github.com/tauri-apps/tauri/commit/947a50b8e28379c452c32eddc3e0101870e50055)([#9049](https://www.github.com/tauri-apps/tauri/pull/9049)) Fix `tauri migrate` for http plugin ACL. - [`fe18012d3`](https://www.github.com/tauri-apps/tauri/commit/fe18012d30d1d8b3ffa10c8e321710eba644ef94)([#9072](https://www.github.com/tauri-apps/tauri/pull/9072)) Resolve symlinks on the filesystem scope check. - [`6c0683224`](https://www.github.com/tauri-apps/tauri/commit/6c068322460300e9d56a4fac5b018d4c437daa9e)([#9068](https://www.github.com/tauri-apps/tauri/pull/9068)) Fixes scope resolution grouping scopes for all windows. ### Dependencies - Upgraded to `tauri-build@2.0.0-beta.7` - Upgraded to `tauri-utils@2.0.0-beta.7` - Upgraded to `tauri-runtime@2.0.0-beta.7` - Upgraded to `tauri-runtime-wry@2.0.0-beta.7` - Upgraded to `tauri-macros@2.0.0-beta.7` ### Breaking Changes - [`d1e77acd8`](https://www.github.com/tauri-apps/tauri/commit/d1e77acd8dfdf554b90b542513a58a2de1ef2360)([#9011](https://www.github.com/tauri-apps/tauri/pull/9011)) Renamed `icon-ico` and `icon-png` feature flags to `image-ico` and `image-png` respectively - [`720357fd5`](https://www.github.com/tauri-apps/tauri/commit/720357fd5cd1fefef8485077dfb116ee39ef4ab4)([#9104](https://www.github.com/tauri-apps/tauri/pull/9104)) Removed `tauri::path::Result` and `tauri::path::Error` which were merely an unintentional re-export of `tauri::Result` and `tauri::Error` so use those instead. - [`6c0683224`](https://www.github.com/tauri-apps/tauri/commit/6c068322460300e9d56a4fac5b018d4c437daa9e)([#9068](https://www.github.com/tauri-apps/tauri/pull/9068)) The `allows` and `denies` methods from `ipc::ScopeValue`, `ipc::CommandScope` and `ipc::GlobalScope` now returns `&Vec>` instead of `&Vec`. - [`d1e77acd8`](https://www.github.com/tauri-apps/tauri/commit/d1e77acd8dfdf554b90b542513a58a2de1ef2360)([#9011](https://www.github.com/tauri-apps/tauri/pull/9011)) Removed `Context::default_window_icon_mut` and `Context::tray_icon_mut`, use `Context::set_default_window_icon` and `Context::set_tray_icon` instead. Also changed `Context::set_tray_icon` to accept `Option`. - [`d1e77acd8`](https://www.github.com/tauri-apps/tauri/commit/d1e77acd8dfdf554b90b542513a58a2de1ef2360)([#9011](https://www.github.com/tauri-apps/tauri/pull/9011)) Removed `Icon` enum, use the new `Image` type instead. All APIs that previously accepted `Icon` have changed to accept `Image` instead. ## \[2.0.0-beta.8] ### New Features - [`d7f56fef`](https://www.github.com/tauri-apps/tauri/commit/d7f56fef85cac3af4e2dbac1eac40e5567b1f160)([#9014](https://www.github.com/tauri-apps/tauri/pull/9014)) Allow defining a permission that only applies to a set of target platforms via the `platforms` configuration option. ### Bug Fixes - [`e1d5b790`](https://www.github.com/tauri-apps/tauri/commit/e1d5b7906369a40df19e8ee86c56f90a27d6357c)([#8995](https://www.github.com/tauri-apps/tauri/pull/8995)) Fixes capability webview label check. - [`222a96b7`](https://www.github.com/tauri-apps/tauri/commit/222a96b74b145fb48d3f0c109897962d56fae57a)([#8999](https://www.github.com/tauri-apps/tauri/pull/8999)) Fixes `Window::add_child` deadlock. - [`e4463f08`](https://www.github.com/tauri-apps/tauri/commit/e4463f08145c044bd37dc1c6f5f39e6a572ace3e)([#8930](https://www.github.com/tauri-apps/tauri/pull/8930)) Clear JS event listeneres on page load, which fixes zombie listeners when the page reloads. - [`222a96b7`](https://www.github.com/tauri-apps/tauri/commit/222a96b74b145fb48d3f0c109897962d56fae57a)([#8999](https://www.github.com/tauri-apps/tauri/pull/8999)) Fixes `Webview::reparent` not updating the webview parent window reference. ### Dependencies - Upgraded to `tauri-build@2.0.0-beta.6` - Upgraded to `tauri-utils@2.0.0-beta.6` - Upgraded to `tauri-runtime-wry@2.0.0-beta.6` - Upgraded to `tauri-runtime@2.0.0-beta.6` - Upgraded to `tauri-macros@2.0.0-beta.6` ### Breaking Changes - [`3657ad82`](https://www.github.com/tauri-apps/tauri/commit/3657ad82f88ce528551d032d521c52eed3f396b4)([#9008](https://www.github.com/tauri-apps/tauri/pull/9008)) Allow defining permissions for the application commands via `tauri_build::Attributes::app_manifest`. ### Breaking Changes - [`b9e6a018`](https://www.github.com/tauri-apps/tauri/commit/b9e6a01879d9233040f3d3fab11c59e70563da7e)([#8937](https://www.github.com/tauri-apps/tauri/pull/8937)) The `custom-protocol` Cargo feature is no longer required on your application and is now ignored. To check if running on production, use `#[cfg(not(dev))]` instead of `#[cfg(feature = "custom-protocol")]`. ## \[2.0.0-beta.7] ### Enhancements - [`bc5b5e67`](https://www.github.com/tauri-apps/tauri/commit/bc5b5e671a546512f823f1c157421b4c3311dfc0)([#8984](https://www.github.com/tauri-apps/tauri/pull/8984)) Do not include a CSP tag in the application HTML and rely on the custom protocol response header instead. ### Bug Fixes - [`6cb601d4`](https://www.github.com/tauri-apps/tauri/commit/6cb601d42e2af75aa818371b8b8f7d5b2e77dc90)([#8983](https://www.github.com/tauri-apps/tauri/pull/8983)) Convert the command name to camelCase when executing a mobile plugin command. - [`60bf11ab`](https://www.github.com/tauri-apps/tauri/commit/60bf11abcbec8d0362aa256e2293985bfd62620f)([#8986](https://www.github.com/tauri-apps/tauri/pull/8986)) Export `ProgressBarStatus`, regression introduced in `2.0.0-beta.4` ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.5` - Upgraded to `tauri-runtime@2.0.0-beta.5` - Upgraded to `tauri-runtime-wry@2.0.0-beta.5` - Upgraded to `tauri-macros@2.0.0-beta.5` - Upgraded to `tauri-build@2.0.0-beta.5` ## \[2.0.0-beta.6] ### Bug Fixes - [`6edc563c`](https://www.github.com/tauri-apps/tauri/commit/6edc563cf9ca26b4622c3135d92e493a5d5bd6e8)([#8953](https://www.github.com/tauri-apps/tauri/pull/8953)) Fixes a deadlock when the window is destroyed. ## \[2.0.0-beta.5] ### New Features - [`fdcaf935`](https://www.github.com/tauri-apps/tauri/commit/fdcaf935fa75ecfa2806939c4faad4fe9e880386)([#8939](https://www.github.com/tauri-apps/tauri/pull/8939)) Added the `reparent` function to the webview API. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.4` - Upgraded to `tauri-runtime-wry@2.0.0-beta.4` - Upgraded to `tauri-build@2.0.0-beta.4` - Upgraded to `tauri-runtime@2.0.0-beta.4` - Upgraded to `tauri-macros@2.0.0-beta.4` ## \[2.0.0-beta.4] ### Enhancements - [`3fb414b6`](https://www.github.com/tauri-apps/tauri/commit/3fb414b61ad7cfce67751230826fddfb39effec5)([#8914](https://www.github.com/tauri-apps/tauri/pull/8914)) Return an id when using from `Manager::once_any`, `App::once`, `Window::once`, `Webview::once`, `WebviewWindow::once` and `fs::Scope::once`. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.3` - Upgraded to `tauri-runtime@2.0.0-beta.3` - Upgraded to `tauri-runtime-wry@2.0.0-beta.3` - Upgraded to `tauri-macros@2.0.0-beta.3` - Upgraded to `tauri-build@2.0.0-beta.3` ### Breaking Changes - [`361ec37f`](https://www.github.com/tauri-apps/tauri/commit/361ec37fd4a5caa5b6630b9563ef079f53c6c336)([#8932](https://www.github.com/tauri-apps/tauri/pull/8932)) Moved `ProgressBarState` from `tauri-utils` to the `tauri::window` module and removed the `unity_uri` field. ## \[2.0.0-beta.3] ### New Features - [`16e550ec`](https://www.github.com/tauri-apps/tauri/commit/16e550ec1503765158cdc3bb2a20e70ec710e981)([#8844](https://www.github.com/tauri-apps/tauri/pull/8844)) Add webview-specific events for multi-webview windows: - Add `WebviewEvent` enum - Add `RunEvent::WebviewEvent` variant. - Add `Builder::on_webview_event` and `Webview::on_webview_event` methods. ### Enhancements - [`11a5816b`](https://www.github.com/tauri-apps/tauri/commit/11a5816bdffcbaa20df936dee43751de2cf67530)([#8864](https://www.github.com/tauri-apps/tauri/pull/8864)) A file-drop now allows sub-directories recursively when the path is a directory. - [`0cb0a15c`](https://www.github.com/tauri-apps/tauri/commit/0cb0a15ce22af3d649cf219ac04188c14c5f4905)([#8789](https://www.github.com/tauri-apps/tauri/pull/8789)) Add `webviews` array on the capability for usage on multiwebview contexts. - [`258494bd`](https://www.github.com/tauri-apps/tauri/commit/258494bd247b6d36485bf16bf7184b93fd299da9)([#8806](https://www.github.com/tauri-apps/tauri/pull/8806)) Added `Manager::add_capability` to add a capability file at runtime. - [`5618f6d2`](https://www.github.com/tauri-apps/tauri/commit/5618f6d2ffc9ebf40710145538b06bebfa55f878)([#8856](https://www.github.com/tauri-apps/tauri/pull/8856)) Relax requirements on plugin's identifiers to be alphanumeric and `-` instead of only lower alpha and `-`. ### Bug Fixes - [`16e550ec`](https://www.github.com/tauri-apps/tauri/commit/16e550ec1503765158cdc3bb2a20e70ec710e981)([#8844](https://www.github.com/tauri-apps/tauri/pull/8844)) Fix JS event listeners registered using JS `listen` api with `EventTarget::Any` never fired. - [`8751c329`](https://www.github.com/tauri-apps/tauri/commit/8751c3299f2b7229c6108aa37dedf1dc5edb3e5c)([#8793](https://www.github.com/tauri-apps/tauri/pull/8793)) Fix invoking toggle devtools by hotkey. - [`bd73ab0a`](https://www.github.com/tauri-apps/tauri/commit/bd73ab0a1adcf648e38d579b92515dababf34993)([#8766](https://www.github.com/tauri-apps/tauri/pull/8766)) When using the multiwebview mode, properly remove the webview from memory on `Webview::close`. - [`46b6598a`](https://www.github.com/tauri-apps/tauri/commit/46b6598a94cd0c6fa4a1654ac67432d94ea20ebf)([#8826](https://www.github.com/tauri-apps/tauri/pull/8826)) Fix JS `onCloseRequested` catching close event from other windows. - [`2e6db908`](https://www.github.com/tauri-apps/tauri/commit/2e6db908d7b3a2c928c46b0ad9ccf9ec55a29480)([#8777](https://www.github.com/tauri-apps/tauri/pull/8777)) Fix regression in `tauri::Error` not being `Sync`. ### What's Changed - [`76ce9f61`](https://www.github.com/tauri-apps/tauri/commit/76ce9f61dd3c5bdd589c7557543894e1f770dd16)([#3002](https://www.github.com/tauri-apps/tauri/pull/3002)) Enhance centering a newly created window, it will no longer jump to center after being visible. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.2` - Upgraded to `tauri-build@2.0.0-beta.2` - Upgraded to `tauri-macros@2.0.0-beta.2` - Upgraded to `tauri-runtime-wry@2.0.0-beta.2` - Upgraded to `tauri-runtime@2.0.0-beta.2` ### Breaking Changes - [`258494bd`](https://www.github.com/tauri-apps/tauri/commit/258494bd247b6d36485bf16bf7184b93fd299da9)([#8806](https://www.github.com/tauri-apps/tauri/pull/8806)) Removed the lifetime parameter from `ipc::GlobalScope` and `ipc::CommandScope`. - [`f284f9c5`](https://www.github.com/tauri-apps/tauri/commit/f284f9c545deeb77d15b6e8b1d0d05f49c40634c)([#8898](https://www.github.com/tauri-apps/tauri/pull/8898)) Changed the capability `remote` configuration to take a list of `urls` instead of `domains` for more flexibility. - [`2f55bfec`](https://www.github.com/tauri-apps/tauri/commit/2f55bfecbf0244f3b5aa1ad7622182fca3fcdcbb)([#8795](https://www.github.com/tauri-apps/tauri/pull/8795)) Update raw-window-handle to 0.6. - [`2e6db908`](https://www.github.com/tauri-apps/tauri/commit/2e6db908d7b3a2c928c46b0ad9ccf9ec55a29480)([#8777](https://www.github.com/tauri-apps/tauri/pull/8777)) Require `ScopeObject::Error` to be `Sync` as well. ## \[2.0.0-beta.2] ### Bug Fixes - [`fe67ab7f`](https://www.github.com/tauri-apps/tauri/commit/fe67ab7f2532c668b35f15415d876e576b3fb74e)([#8761](https://www.github.com/tauri-apps/tauri/pull/8761)) Workaround for zbus not enabling the proper Cargo features for its nix dependency. ### Dependencies - Upgraded to `tauri-build@2.0.0-beta.1` - Upgraded to `tauri-utils@2.0.0-beta.1` - Upgraded to `tauri-runtime@2.0.0-beta.1` - Upgraded to `tauri-runtime-wry@2.0.0-beta.1` - Upgraded to `tauri-macros@2.0.0-beta.1` ## \[2.0.0-beta.1] ### Bug Fixes - [`863bc9e5`](https://www.github.com/tauri-apps/tauri/commit/863bc9e55f9099207403e34cb5c218231265b2c1)([#8749](https://www.github.com/tauri-apps/tauri/pull/8749)) Fix regression on the JavaScript code that processes the IPC message. ## \[2.0.0-beta.0] ### New Features - [`74a2a603`](https://www.github.com/tauri-apps/tauri/commit/74a2a6036a5e57462f161d728cbd8a6f121028ca)([#8661](https://www.github.com/tauri-apps/tauri/pull/8661)) Implement access control list for IPC usage. - [`a2fc3a63`](https://www.github.com/tauri-apps/tauri/commit/a2fc3a63579ca739646d696870cbecbb3a169d33)([#8657](https://www.github.com/tauri-apps/tauri/pull/8657)) Add `visibleOnAllWorkspaces` option when creating the window in JS and `Window.setVisibleOnAllWorkspaces` method. - [`af610232`](https://www.github.com/tauri-apps/tauri/commit/af6102327376884364b2075b468bdf08ee0d02aa)([#8710](https://www.github.com/tauri-apps/tauri/pull/8710)) Added `Window::destroy` to force close a window. - [`c77b4032`](https://www.github.com/tauri-apps/tauri/commit/c77b40324ea9bf580871fc11aed69ba0c9b6b8cf)([#8280](https://www.github.com/tauri-apps/tauri/pull/8280)) Add multiwebview support behind the `unstable` feature flag. See `WindowBuilder` and `WebviewBuilder` for more information. - [`9eaeb5a8`](https://www.github.com/tauri-apps/tauri/commit/9eaeb5a8cd95ae24b5e66205bdc2763cb7f965ce)([#8622](https://www.github.com/tauri-apps/tauri/pull/8622)) Add `WindowBuilder::parent` which is a convenient wrapper around parent functionality for Windows, Linux and macOS. Also added `WindowBuilder::owner` on Windows only. Also added `WindowBuilder::transient_for` and `WindowBuilder::transient_for_raw` on Linux only. ### Enhancements - [`e8d3793c`](https://www.github.com/tauri-apps/tauri/commit/e8d3793c3c34715569312a91633fde4d58d7621c)([#8732](https://www.github.com/tauri-apps/tauri/pull/8732)) Add `common-controls-v6` cargo feature flag (enabled by default). - [`58fe2e81`](https://www.github.com/tauri-apps/tauri/commit/58fe2e812a85b9f4eba105286a63f271ea637836)([#8670](https://www.github.com/tauri-apps/tauri/pull/8670)) Allow IPC calls when window origin is a defined custom protocol. ### Bug Fixes - [`95da1a27`](https://www.github.com/tauri-apps/tauri/commit/95da1a27476e01e06f6ce0335df8535b662dd9c4)([#8713](https://www.github.com/tauri-apps/tauri/pull/8713)) Fix calling `set_activation_policy` when the event loop is running. - [`e1eb911f`](https://www.github.com/tauri-apps/tauri/commit/e1eb911f5ebe84285aae710e0ebdd945ad389431)([#8582](https://www.github.com/tauri-apps/tauri/pull/8582)) Ensure initalize logic and dropping of menu item is done on the main thread, this fixes the crash when a menu item is dropped on another thread. - [`a093682d`](https://www.github.com/tauri-apps/tauri/commit/a093682d2df7169b024bb4f736c7f1fd2ea8b327)([#8621](https://www.github.com/tauri-apps/tauri/pull/8621)) Fix can not prevent closing a window from another webview. - [`7f033f6d`](https://www.github.com/tauri-apps/tauri/commit/7f033f6dcd54c69a4193765a5c1584755ba92c61)([#8537](https://www.github.com/tauri-apps/tauri/pull/8537)) Fix undecorated window resizing on Windows and Linux. ### What's Changed - [`9f8037c2`](https://www.github.com/tauri-apps/tauri/commit/9f8037c2882abac19582025001675370f0d7b669)([#8633](https://www.github.com/tauri-apps/tauri/pull/8633)) On Windows, fix decorated window not transparent initially until resized. - [`7f033f6d`](https://www.github.com/tauri-apps/tauri/commit/7f033f6dcd54c69a4193765a5c1584755ba92c61)([#8537](https://www.github.com/tauri-apps/tauri/pull/8537)) Add `Window::start_resize_dragging` and `ResizeDirection` enum. - [`6639a579`](https://www.github.com/tauri-apps/tauri/commit/6639a579c76d45210f33a72d37e21d4c5a9d334b)([#8441](https://www.github.com/tauri-apps/tauri/pull/8441)) Added the `WindowConfig::proxy_url` `WebviewBuilder::proxy_url() / WebviewWindowBuilder::proxy_url()` options when creating a webview. ### Dependencies - Upgraded to `tauri-build@22.0.0-beta.0` - Upgraded to `tauri-utils@2.0.0-beta.0` - Upgraded to `tauri-macros@2.0.0-beta.0` - Upgraded to `tauri-runtime@2.0.0-beta.0` - Upgraded to `tauri-runtime-wry@2.0.0-beta.0` ### Breaking Changes - [`8de308d1`](https://www.github.com/tauri-apps/tauri/commit/8de308d1bf6a855d7a26af58bd0e744938ba47d8)([#8723](https://www.github.com/tauri-apps/tauri/pull/8723)) Restructured Tauri config per [RFC#5](https://github.com/tauri-apps/rfcs/blob/f3e82a6b0c5390401e855850d47dc7b7d9afd684/texts/0005-tauri-config-restructure.md): - Moved `package.productName`, `package.version` and `tauri.bundle.identifier` fields to the top-level. - Removed `package` object. - Renamed `tauri` object to `app`. - Moved `tauri.bundle` object to the top-level. - Renamed `build.distDir` field to `frontendDist`. - Renamed `build.devPath` field to `devUrl` and will no longer accepts paths, it will only accept URLs. - Moved `tauri.pattern` to `app.security.pattern`. - Removed `tauri.bundle.updater` object, and its fields have been moved to the updater plugin under `plugins.updater` object. - Moved `build.withGlobalTauri` to `app.withGlobalTauri`. - Moved `tauri.bundle.dmg` object to `bundle.macOS.dmg`. - Moved `tauri.bundle.deb` object to `bundle.linux.deb`. - Moved `tauri.bundle.appimage` object to `bundle.linux.appimage`. - Removed all license fields from each bundle configuration object and instead added `bundle.license` and `bundle.licenseFile`. - Renamed `AppUrl` to `FrontendDist` and refactored its variants to be more explicit. - [`c77b4032`](https://www.github.com/tauri-apps/tauri/commit/c77b40324ea9bf580871fc11aed69ba0c9b6b8cf)([#8280](https://www.github.com/tauri-apps/tauri/pull/8280)) The `invoke_system`, `on_page_load` hooks now gives you a `Webview` argument instead of a `Window`. - [`e1eb911f`](https://www.github.com/tauri-apps/tauri/commit/e1eb911f5ebe84285aae710e0ebdd945ad389431)([#8582](https://www.github.com/tauri-apps/tauri/pull/8582)) All menu item constructors `accelerator` argument have been changed to `Option>` so when providing `None` you need to specify the generic argument like `None::<&str>`. - [`e1eb911f`](https://www.github.com/tauri-apps/tauri/commit/e1eb911f5ebe84285aae710e0ebdd945ad389431)([#8582](https://www.github.com/tauri-apps/tauri/pull/8582)) All menu item constructors have been changed to return a `Result` - [`aa758a85`](https://www.github.com/tauri-apps/tauri/commit/aa758a850f7a3c8e57520ee4ea63a17689469cb0)([#8716](https://www.github.com/tauri-apps/tauri/pull/8716)) Moved the `command` module items to the `ipc` module so its import name does not clash with the `command` macro. - [`00e15675`](https://www.github.com/tauri-apps/tauri/commit/00e1567584721644797b587205187f9cbe4e5cd1)([#8708](https://www.github.com/tauri-apps/tauri/pull/8708)) `AppHandle::exit` and `AppHandle::restart` now go triggers `RunEvent::ExitRequested` and `RunEvent::Exit` and cannot be executed on the event loop handler. - [`ec9818ac`](https://www.github.com/tauri-apps/tauri/commit/ec9818accba567816cb5647c0fac2019f11c027a)([#8696](https://www.github.com/tauri-apps/tauri/pull/8696)) Added a callback to the `App::run_iteration` and removed its return value. - [`a093682d`](https://www.github.com/tauri-apps/tauri/commit/a093682d2df7169b024bb4f736c7f1fd2ea8b327)([#8621](https://www.github.com/tauri-apps/tauri/pull/8621)) Refactored the event system to better accommodate the new window types: - Added `EventTarget` enum. - Added `App/AppHandle::listen`, `App/AppHandle::once` and `App/AppHandle::unlisten` to listen to events targeting `App/AppHandle` - `App/AppHandle/Window/Webview/WebviewWindow::emit` will now emit to all event listeners. - `App/AppHandle/Window/Webview/WebviewWindow::emit_to` will emit to event targets that match the given label, see `EventTarget` enum. - `App/AppHandle/Window/Webview/WebviewWindow::emit_filter` will emit to event targets based on a filter callback which now takes `&EventTarget` instead of `&Window`. - Renamed `Manager::listen_global` and `Manager::once_global` to `listen_any` and `once_any` respectively to be consistent with `EventTarget::Any`, it will now also listen to any event to any target (aka event sniffer). - [`9eaeb5a8`](https://www.github.com/tauri-apps/tauri/commit/9eaeb5a8cd95ae24b5e66205bdc2763cb7f965ce)([#8622](https://www.github.com/tauri-apps/tauri/pull/8622)) Renamed `WindowBuilder::owner_window` to `WindowBuilder::owner_raw` and `WindowBuilder::parent_window` to `WindowBuilder::parent_raw`. - [`9eaeb5a8`](https://www.github.com/tauri-apps/tauri/commit/9eaeb5a8cd95ae24b5e66205bdc2763cb7f965ce)([#8622](https://www.github.com/tauri-apps/tauri/pull/8622)) Changed `WindowBuilder::from_config` to return a `Result`. - [`c77b4032`](https://www.github.com/tauri-apps/tauri/commit/c77b40324ea9bf580871fc11aed69ba0c9b6b8cf)([#8280](https://www.github.com/tauri-apps/tauri/pull/8280)) Renamed `Window` to `WebviewWindow`, `WindowBuilder` to `WebviewWindowBuilder`, `Manager::windows` to `Manager::webview_windows` and `Manager::get_window` to `Manager::get_webview_window`. - [`af610232`](https://www.github.com/tauri-apps/tauri/commit/af6102327376884364b2075b468bdf08ee0d02aa)([#8710](https://www.github.com/tauri-apps/tauri/pull/8710)) `Window::close` now triggers a close requested event instead of forcing the window to be closed. - [`c77b4032`](https://www.github.com/tauri-apps/tauri/commit/c77b40324ea9bf580871fc11aed69ba0c9b6b8cf)([#8280](https://www.github.com/tauri-apps/tauri/pull/8280)) Renamed the `window-data-url` feature flag to `webview-data-url`. ## \[2.0.0-alpha.21] ### New Features - [`29ced5ce`](https://www.github.com/tauri-apps/tauri/commit/29ced5ceec40b2934094ade2db9a8855f294e1d1)([#8159](https://www.github.com/tauri-apps/tauri/pull/8159)) Added `WindowBuilder::on_download` to handle download request events. ### Enhancements - [`d621d343`](https://www.github.com/tauri-apps/tauri/commit/d621d3437ce3947175eecf345b2c6d1c4c7ce020)([#8607](https://www.github.com/tauri-apps/tauri/pull/8607)) Added tracing for window startup, plugins, `Window::eval`, events, IPC, updater and custom protocol request handlers behind the `tracing` feature flag. ### What's Changed - [`cb640c8e`](https://www.github.com/tauri-apps/tauri/commit/cb640c8e949a3d78d78162e2e61b51bf8afae983)([#8393](https://www.github.com/tauri-apps/tauri/pull/8393)) Fix `RunEvent::WindowEvent(event: WindowEvent::FileDrop(FileDropEvent))` never triggered and always prevent default OS behavior when `disable_file_drop_handler` is not used. ### Dependencies - Upgraded to `tauri-runtime-wry@1.0.0-alpha.9` - Upgraded to `tauri-utils@2.0.0-alpha.13` - Upgraded to `tauri-runtime@1.0.0-alpha.8` - Upgraded to `tauri-macros@2.0.0-alpha.13` - Upgraded to `tauri-build@2.0.0-alpha.14` ### Breaking Changes - [`2032228c`](https://www.github.com/tauri-apps/tauri/commit/2032228cad0de6500616ca765af5c9ff1f231f0f)([#8430](https://www.github.com/tauri-apps/tauri/pull/8430)) Removed `GlobalWindowEvent` struct, and unpacked its field to be passed directly to `tauri::Builder::on_window_event`. ## \[2.0.0-alpha.20] ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.12` - Upgraded to `tauri-runtime@1.0.0-alpha.7` - Upgraded to `tauri-runtime-wry@1.0.0-alpha.8` - Upgraded to `tauri-macros@2.0.0-alpha.12` - Upgraded to `tauri-build@2.0.0-alpha.13` ## \[2.0.0-alpha.19] ### New Features - [`b59f2f54`](https://www.github.com/tauri-apps/tauri/commit/b59f2f54e7c1e01e33baf710d50c046401edb9d8)([#8432](https://www.github.com/tauri-apps/tauri/pull/8432)) Expose `scope::fs::Scope::new`. - [`bf095df5`](https://www.github.com/tauri-apps/tauri/commit/bf095df55aa27fb22c9240ddf8d673cfe0a4a2db)([#8276](https://www.github.com/tauri-apps/tauri/pull/8276)) 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 and can be used to create Rust-backed resources in JS. ### Enhancements - [`5848b4e8`](https://www.github.com/tauri-apps/tauri/commit/5848b4e8e9fde1e0d895238cafdb57ed20be4c07)([#8386](https://www.github.com/tauri-apps/tauri/pull/8386)) Fixed the deserialisation of a `Channel` in iOS. - [`11a1529d`](https://www.github.com/tauri-apps/tauri/commit/11a1529d6ace47e731f5d69bf421e7f59f0d7567)([#8419](https://www.github.com/tauri-apps/tauri/pull/8419)) Include CORS header on custom protocol response errors to ensure frontend can read the error message. - [`db127777`](https://www.github.com/tauri-apps/tauri/commit/db127777423e467758781d58c1121cbe94844161)([#8380](https://www.github.com/tauri-apps/tauri/pull/8380)) Added `test::get_ipc_response`. ### Bug Fixes - [`effe5871`](https://www.github.com/tauri-apps/tauri/commit/effe5871aff1267a73ecbba1693304941a691932)([#8420](https://www.github.com/tauri-apps/tauri/pull/8420)) Fixes file scope checks on Android. - [`f98ce5aa`](https://www.github.com/tauri-apps/tauri/commit/f98ce5aa475d1b3f8606e773579e77f41309feb0)([#8328](https://www.github.com/tauri-apps/tauri/pull/8328)) Fix incorrect menu item for `PredefinedMenuItem::close_window` ## \[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 - [`b89de9fa`](https://www.github.com/tauri-apps/tauri/commit/b89de9fa43b793c74a42230c7a82c11c3734278e)([#8092](https://www.github.com/tauri-apps/tauri/pull/8092)) Add support for onResume and onPause events in android plugins. - [`c6c59cf2`](https://www.github.com/tauri-apps/tauri/commit/c6c59cf2373258b626b00a26f4de4331765dd487) Pull changes from Tauri 1.5 release. - [`198abe3c`](https://www.github.com/tauri-apps/tauri/commit/198abe3c2cae06dacab860b3a93f715dcf529a95)([#8076](https://www.github.com/tauri-apps/tauri/pull/8076)) Mobile plugins can now resolve using an arbitrary object instead of using the `JSObject` class via `Invoke.resolve` on iOS and `Invoke.resolveObject` on Android. ### Bug Fixes - [`22f26882`](https://www.github.com/tauri-apps/tauri/commit/22f26882cfe0adbfe4c51586a1c9fdcf8e9cfb68)([#8049](https://www.github.com/tauri-apps/tauri/pull/8049)) Prevent crash on iOS when the Swift plugin data is not a valid JSON string. ### Dependencies - Upgraded to `tauri-build@2.0.0-alpha.11` - Upgraded to `tauri-macros@2.0.0-alpha.10` - Upgraded to `tauri-utils@2.0.0-alpha.10` - Upgraded to `tauri-runtime@1.0.0-alpha.4` - Upgraded to `tauri-runtime-wry@1.0.0-alpha.5` - [`9580df1d`](https://www.github.com/tauri-apps/tauri/commit/9580df1d7b027befb9e5f025ea2cbaf2dcc82c8e)([#8084](https://www.github.com/tauri-apps/tauri/pull/8084)) Upgrade `gtk` to 0.18. - [`c7c2507d`](https://www.github.com/tauri-apps/tauri/commit/c7c2507da16a9beb71bf06745fe7ac1325ab7c2a)([#8035](https://www.github.com/tauri-apps/tauri/pull/8035)) Update `windows` to version `0.51` and `webview2-com` to version `0.27` - [`9580df1d`](https://www.github.com/tauri-apps/tauri/commit/9580df1d7b027befb9e5f025ea2cbaf2dcc82c8e)([#8084](https://www.github.com/tauri-apps/tauri/pull/8084)) Updated to wry@0.34, removing the `dox` feature flag. ### Breaking Changes - [`198abe3c`](https://www.github.com/tauri-apps/tauri/commit/198abe3c2cae06dacab860b3a93f715dcf529a95)([#8076](https://www.github.com/tauri-apps/tauri/pull/8076)) The Android `PluginManager.loadConfig` now takes a third parameter to define the class type of the config object. - [`198abe3c`](https://www.github.com/tauri-apps/tauri/commit/198abe3c2cae06dacab860b3a93f715dcf529a95)([#8076](https://www.github.com/tauri-apps/tauri/pull/8076)) Mobile plugins now have access to a parser for the invoke arguments instead of relying on the `Invoke#get${TYPE}` methods. - [`74d2464d`](https://www.github.com/tauri-apps/tauri/commit/74d2464d0e490fae341ad73bdf2964cf215fe6c5)([#8116](https://www.github.com/tauri-apps/tauri/pull/8116)) Added `WindowBuilder::on_page_load` and refactored the `Builder::on_page_load` handler to take references. The page load hook is now triggered for load started and finished events, to determine what triggered it see `PageLoadPayload::event`. - [`93c8a77b`](https://www.github.com/tauri-apps/tauri/commit/93c8a77b347b9934ec0732784d4b78b3260abc08)([#7996](https://www.github.com/tauri-apps/tauri/pull/7996)) The event system APIS on Rust is recieving a few changes for consistency and quality of life improvements: - Renamed `Manager::emit_all` to just `Manager::emit` and will now both trigger the events on JS side as well as Rust. - Removed `Manager::trigger_global`, use `Manager::emit` - Added `Manager::emit_filter`. - Removed `Window::emit`, and moved the implementation to `Manager::emit`. - Removed `Window::emit_and_trigger` and `Window::trigger`, use `Window::emit` instead. - Changed `Window::emit_to` to only trigger the target window listeners so it won't be catched by `Manager::listen_global` ## \[2.0.0-alpha.16] ### New Features - [`c085adda`](https://www.github.com/tauri-apps/tauri/commit/c085addab58ba851398373c6fd13f9cb026d71e8)([#8009](https://www.github.com/tauri-apps/tauri/pull/8009)) Added `set_progress_bar` to `Window`. - [`c1ec0f15`](https://www.github.com/tauri-apps/tauri/commit/c1ec0f155118527361dd5645d920becbc8afd569)([#7933](https://www.github.com/tauri-apps/tauri/pull/7933)) Added `Window::set_always_on_bottom` and the `always_on_bottom` option when creating a window. - [`880266a7`](https://www.github.com/tauri-apps/tauri/commit/880266a7f697e1fe58d685de3bb6836ce5251e92)([#8031](https://www.github.com/tauri-apps/tauri/pull/8031)) Bump the MSRV to 1.70. - [`ed32257d`](https://www.github.com/tauri-apps/tauri/commit/ed32257d044f90b5eb15053efd1667125def2d2b)([#7794](https://www.github.com/tauri-apps/tauri/pull/7794)) On Windows, add `Effect::Tabbed`,`Effect::TabbedDark` and `Effect::TabbedLight` effects. ### Enhancements - [`46dcb941`](https://www.github.com/tauri-apps/tauri/commit/46dcb94110ac16d0d4328fa149bb86975b658f59)([#8006](https://www.github.com/tauri-apps/tauri/pull/8006)) Include mobile on docs.rs targets. ### What's Changed - [`fb10b879`](https://www.github.com/tauri-apps/tauri/commit/fb10b87970a43320ef4d14564f45e7579b774eaf)([#8039](https://www.github.com/tauri-apps/tauri/pull/8039)) Added the `app` plugin back into core. - [`c9a9246c`](https://www.github.com/tauri-apps/tauri/commit/c9a9246c37bdf190661355c8ee406dac6c427344)([#8007](https://www.github.com/tauri-apps/tauri/pull/8007)) Added the `window` plugin back into core. ### Dependencies - Upgraded to `tauri-runtime@1.0.0-alpha.3` - Upgraded to `tauri-runtime-wry@1.0.0-alpha.4` - Upgraded to `tauri-utils@2.0.0-alpha.9` - Upgraded to `tauri-build@2.0.0-alpha.10` - Upgraded to `tauri-macros@2.0.0-alpha.9` ### Breaking Changes - [`a63e71f9`](https://www.github.com/tauri-apps/tauri/commit/a63e71f9799e9bbc82521d2f17b5238fbf690e89)([#7942](https://www.github.com/tauri-apps/tauri/pull/7942)) The initialization script for `Builder::invoke_system` now must initialize the `window.__TAURI_INTERNALS__.postMessage` function instead of `window.__TAURI_POST_MESSAGE__`. - [`12b8d18b`](https://www.github.com/tauri-apps/tauri/commit/12b8d18bf7ff833047cb87f356fd007d47d082c9)([#7875](https://www.github.com/tauri-apps/tauri/pull/7875)) - Removed `tauri::path::Error` and added its variants to `tauri::Error` - Removed `tauri::path::Result` and `tauri::plugin::Result` aliases, you should use `tauri::Result` or your own `Result` type. - [`8b166e9b`](https://www.github.com/tauri-apps/tauri/commit/8b166e9bf82e69ddb3200a3a825614980bd8d433)([#7949](https://www.github.com/tauri-apps/tauri/pull/7949)) Changed `TAURI_AUTOMATION` to `TAURI_WEBVIEW_AUTOMATION` - [`2558fab8`](https://www.github.com/tauri-apps/tauri/commit/2558fab861006936296e8511e43ccd69a38f61b0)([#7939](https://www.github.com/tauri-apps/tauri/pull/7939)) This release contains a number of breaking changes to improve the consistency of tauri internals and the public facing APIs and simplifying the types where applicable: - Removed `EventHandler` type. - Added `EventId` type - Changed `Manager::listen_global` and `Window::listen` to return the new `EventId` type instead of `EventHandler`. - Removed the return type of `Manager::once_global` and `Window::once` - Changed `Manager::unlisten` and `Window::unlisten` to take he new `EventId` type. - Added `tauri::scope::ScopeEventId` - Changed `FsScope::listen` to return the new `ScopeEventId` instead of `Uuid`. - Added `FsScope::unlisten` ## \[2.0.0-alpha.15] ### Enhancements - [`b597aa5f`](https://www.github.com/tauri-apps/tauri/commit/b597aa5f3974f5ca5ca5159d441abc9ed3e80721)([#7871](https://www.github.com/tauri-apps/tauri/pull/7871)) Set `main` as the default `id` for the tray icon registered from the configuration file, so if the `id` is not specified, it can be retrieved using `app.tray_by_id("main")`. ### Bug Fixes - [`a2021c30`](https://www.github.com/tauri-apps/tauri/commit/a2021c30ba1139fcfe4db2522b96125f3fa4d9d6)([#7866](https://www.github.com/tauri-apps/tauri/pull/7866)) Changed `IconMenuItem::set_native_icon` signature to take `&self` instead of `&mut self` to fix compilation error on macos. - [`a68ccaf5`](https://www.github.com/tauri-apps/tauri/commit/a68ccaf59a6731dc030bdb4642a35e3bc64d5769)([#7822](https://www.github.com/tauri-apps/tauri/pull/7822)) Fix `asset` protocol failing to fetch files. - [`6fbd6dba`](https://www.github.com/tauri-apps/tauri/commit/6fbd6dba5290dc017ab0ba5a44cf4358b022836f)([#17](https://www.github.com/tauri-apps/tauri/pull/17)) Fix the validation of `std::env::current_exe` warn the user if AppImage is not mounted instead of panicking ### Dependencies - Upgraded to `tauri-macros@2.0.0-alpha.8` - Upgraded to `tauri-utils@2.0.0-alpha.8` - Upgraded to `tauri-build@2.0.0-alpha.9` - Upgraded to `tauri-runtime@1.0.0-alpha.2` - Upgraded to `tauri-runtime-wry@1.0.0-alpha.3` ### Breaking Changes - [`092a561c`](https://www.github.com/tauri-apps/tauri/commit/092a561ca69a631d2a03777e29debeba37b197a7)([#7874](https://www.github.com/tauri-apps/tauri/pull/7874)) Removed `tauri::api` module as most apis have been moved to either a plugin or we recommend using other crates. - [`deea9436`](https://www.github.com/tauri-apps/tauri/commit/deea9436261f651188e0bc86104779bf30029c32)([#7876](https://www.github.com/tauri-apps/tauri/pull/7876)) Changed `Env.args` to `Env.args_os` and now uses `OsString` instead of `String` - [`b7fd88e1`](https://www.github.com/tauri-apps/tauri/commit/b7fd88e18d24e4450129a5a5007f2e740c69afe5)([#7944](https://www.github.com/tauri-apps/tauri/pull/7944)) `tauri::scope` module is recieving a couple of consistency changes: - Added `tauri::scope::fs` module. - Removed `scope::IpcScope` re-export, use `scope::ipc::Scope`. - Removed `FsScope`, `GlobPattern` and `FsScopeEvent`, use `scope::fs::Scope`, `scope::fs::Pattern` and `scope::fs::Event` respectively. - [`c0d03af4`](https://www.github.com/tauri-apps/tauri/commit/c0d03af4704c828698e06e9662dab1087c99c42e)([#7943](https://www.github.com/tauri-apps/tauri/pull/7943)) Changed `TrayIconBuilder/TrayIcon::on_tray_event` to `TrayIconBuilder/TrayIcon::on_tray_icon_event` for consistency of naming. ## \[2.0.0-alpha.14] ### Bug Fixes - [`d5074af5`](https://www.github.com/tauri-apps/tauri/commit/d5074af562b2b5cb6c5711442097c4058af32db6)([#7801](https://www.github.com/tauri-apps/tauri/pull/7801)) Fixes custom protocol not working on Windows. ### Dependencies - Upgraded to `tauri-runtime-wry@1.0.0-alpha.2` ### Breaking Changes - [`d5074af5`](https://www.github.com/tauri-apps/tauri/commit/d5074af562b2b5cb6c5711442097c4058af32db6)([#7801](https://www.github.com/tauri-apps/tauri/pull/7801)) The custom protocol on Android now uses the `http` scheme instead of `https`. ## \[2.0.0-alpha.13] ### Breaking Changes - [`4cb51a2d`](https://www.github.com/tauri-apps/tauri/commit/4cb51a2d56cfcae0749062c79ede5236bd8c02c2)([#7779](https://www.github.com/tauri-apps/tauri/pull/7779)) The custom protocol on Windows now uses the `http` scheme instead of `https`. ## \[2.0.0-alpha.12] ### Enhancements - [`8a676617`](https://www.github.com/tauri-apps/tauri/commit/8a6766173b3da4446a87642e7282c73a5b631afe)([#7618](https://www.github.com/tauri-apps/tauri/pull/7618)) Ensure Builder is Send by requiring the menu closure to be Send. - [`0d63732b`](https://www.github.com/tauri-apps/tauri/commit/0d63732b962e71b98430f8d7b34ea5b59a2e8bb4)([#7754](https://www.github.com/tauri-apps/tauri/pull/7754)) Added `Builder::register_asynchronous_uri_scheme_protocol` to allow resolving a custom URI scheme protocol request asynchronously to prevent blocking the main thread. ### Bug Fixes - [`0d63732b`](https://www.github.com/tauri-apps/tauri/commit/0d63732b962e71b98430f8d7b34ea5b59a2e8bb4)([#7754](https://www.github.com/tauri-apps/tauri/pull/7754)) Fixes invalid header value type when requesting IPC body through a channel. - [`e98393e4`](https://www.github.com/tauri-apps/tauri/commit/e98393e499c03504851e97dd9f740b817c4534df)([#7673](https://www.github.com/tauri-apps/tauri/pull/7673)) No longer unpacking and flattening the `payload` over the IPC so that commands with arguments called `cmd`, `callback`, `error`, `options` or `payload` aren't breaking the IPC. - [`29818de6`](https://www.github.com/tauri-apps/tauri/commit/29818de682146a75cd9a886f7b215154cad1d42d)([#7662](https://www.github.com/tauri-apps/tauri/pull/7662)) Fixes IPC failing to communicate for remote URLs on macOS and iOS. ### What's Changed - [`6177150b`](https://www.github.com/tauri-apps/tauri/commit/6177150b6f83b52ca359d6e20f7e540f7554e4eb)([#7601](https://www.github.com/tauri-apps/tauri/pull/7601)) Changed `FileDropEvent` to include drop and hover position. ### Dependencies - Upgraded to `tauri-runtime@1.0.0-alpha.1` - Upgraded to `tauri-runtime-wry@1.0.0-alpha.1` ### Breaking Changes - [`0d63732b`](https://www.github.com/tauri-apps/tauri/commit/0d63732b962e71b98430f8d7b34ea5b59a2e8bb4)([#7754](https://www.github.com/tauri-apps/tauri/pull/7754)) Changed `Builder::register_uri_scheme_protocol` to return a `http::Response` instead of `Result`. To return an error response, manually create a response with status code >= 400. - [`0d63732b`](https://www.github.com/tauri-apps/tauri/commit/0d63732b962e71b98430f8d7b34ea5b59a2e8bb4)([#7754](https://www.github.com/tauri-apps/tauri/pull/7754)) `tauri-runtime` no longer implements its own HTTP types and relies on the `http` crate instead. - [`0d63732b`](https://www.github.com/tauri-apps/tauri/commit/0d63732b962e71b98430f8d7b34ea5b59a2e8bb4)([#7754](https://www.github.com/tauri-apps/tauri/pull/7754)) Changed `Builder::invoke_system` to take references instead of owned values. - [`5c95152c`](https://www.github.com/tauri-apps/tauri/commit/5c95152c76391607746f6da942ec57d23c89e89e)([#7621](https://www.github.com/tauri-apps/tauri/pull/7621)) Changed `MenuBuilder\SubmenuBuilder::text`, `MenuBuilder\SubmenuBuilder::check`, `MenuBuilder\SubmenuBuilder::icon` and `MenuBuilder\SubmenuBuilder::native_icon` to take an `id` as the first argument. - [`0d63732b`](https://www.github.com/tauri-apps/tauri/commit/0d63732b962e71b98430f8d7b34ea5b59a2e8bb4)([#7754](https://www.github.com/tauri-apps/tauri/pull/7754)) Changed `Window::on_message` signature to take a responder closure instead of returning the response object in order to asynchronously process the request. ## \[2.0.0-alpha.11] ### New Features - [`4db363a0`](https://www.github.com/tauri-apps/tauri/commit/4db363a03c182349f8491f46ced258d84723b11f)([#6589](https://www.github.com/tauri-apps/tauri/pull/6589)) Added `visible_on_all_workspaces` configuration option to `WindowBuilder`, `Window`, and `WindowConfig`. - [`84c41597`](https://www.github.com/tauri-apps/tauri/commit/84c4159754b2e59244211ed9e1fc702d851a0562)([#6394](https://www.github.com/tauri-apps/tauri/pull/6394)) Add `App::primary_monitor`, `App::available_monitors`, `AppHandle::primary_monitor`, and `AppHandle::available_monitors` - [`2a000e15`](https://www.github.com/tauri-apps/tauri/commit/2a000e150d02dff28c8b20ad097b29e209160045)([#7235](https://www.github.com/tauri-apps/tauri/pull/7235)) Added `Window::navigate`. - [`3b98141a`](https://www.github.com/tauri-apps/tauri/commit/3b98141aa26f74c641a4090874247b97079bd58a)([#3736](https://www.github.com/tauri-apps/tauri/pull/3736)) Added support to file associations. - [`3a2c3e74`](https://www.github.com/tauri-apps/tauri/commit/3a2c3e74710bef9a14932dce74c351cca6215429)([#7306](https://www.github.com/tauri-apps/tauri/pull/7306)) Added `PluginBuilder::on_navigation`. Added `Plugin::on_navigation`. - [`753900dd`](https://www.github.com/tauri-apps/tauri/commit/753900dd6e549aaf56f419144382669e3b246404)([#7440](https://www.github.com/tauri-apps/tauri/pull/7440)) Expose `RunEvent::Opened` on macOS and iOS for deep link support. - [`7fb419c3`](https://www.github.com/tauri-apps/tauri/commit/7fb419c326aaf72ecd556d8404377444ebb200e7)([#7535](https://www.github.com/tauri-apps/tauri/pull/7535)) Add `App::cleanup_before_exit` and `AppHandle::cleanup_before_exit` to manually call the cleanup logic. **You should always exit the tauri app immediately after this function returns and not use any tauri-related APIs.** - [`7fb419c3`](https://www.github.com/tauri-apps/tauri/commit/7fb419c326aaf72ecd556d8404377444ebb200e7)([#7535](https://www.github.com/tauri-apps/tauri/pull/7535)) On Linux, add `Window::default_vbox` to get a reference to the `gtk::Box` that contains the menu bar and the webview. - [`7fb419c3`](https://www.github.com/tauri-apps/tauri/commit/7fb419c326aaf72ecd556d8404377444ebb200e7)([#7535](https://www.github.com/tauri-apps/tauri/pull/7535)) Add `linux-libxdo` feature flag (disabled by default) to enable linking to `libxdo` which is used to make `Cut`, `Copy`, `Paste` and `SelectAll` native menu items work on Linux. - [`7fb419c3`](https://www.github.com/tauri-apps/tauri/commit/7fb419c326aaf72ecd556d8404377444ebb200e7)([#7535](https://www.github.com/tauri-apps/tauri/pull/7535)) On macOS, add `Window::ns_view` to get a pointer to the NSWindow content view. - [`7fb419c3`](https://www.github.com/tauri-apps/tauri/commit/7fb419c326aaf72ecd556d8404377444ebb200e7)([#7535](https://www.github.com/tauri-apps/tauri/pull/7535)) Expose `run_on_main_thread` method on `App` that is similar to `AppHandle::run_on_main_thread`. ### Enhancements - [`a5752db9`](https://www.github.com/tauri-apps/tauri/commit/a5752db9852bb852e61f19dfb48a9435c1fdc79c)([#7436](https://www.github.com/tauri-apps/tauri/pull/7436)) Listen to `onNewIntent` and forward it to registered plugins. - [`fbeb5b91`](https://www.github.com/tauri-apps/tauri/commit/fbeb5b9185baeda19e865228179e3e44c165f1d9)([#7170](https://www.github.com/tauri-apps/tauri/pull/7170)) Added `Channel::new` allowing communication from a mobile plugin with Rust. - [`fbeb5b91`](https://www.github.com/tauri-apps/tauri/commit/fbeb5b9185baeda19e865228179e3e44c165f1d9)([#7170](https://www.github.com/tauri-apps/tauri/pull/7170)) Use custom protocols on the IPC implementation to enhance performance. ### Dependencies - Upgraded to `tauri-runtime@1.0.0-alpha.0` - Upgraded to `tauri-utils@2.0.0-alpha.7` - Upgraded to `tauri-macros@2.0.0-alpha.7` - Upgraded to `tauri-runtime-wry@1.0.0-alpha.0` - Upgraded to `tauri-build@2.0.0-alpha.7` - [`d1a6e2f3`](https://www.github.com/tauri-apps/tauri/commit/d1a6e2f33326161a78a9a72bd9320dcb1b1f9710)([#7252](https://www.github.com/tauri-apps/tauri/pull/7252)) Update `state` to v0.6. ### Breaking Changes - [`fd5dc788`](https://www.github.com/tauri-apps/tauri/commit/fd5dc788d10b2a048e0804b5415b84ae8f9152ea)([#7352](https://www.github.com/tauri-apps/tauri/pull/7352)) - Removed `tauri::api::file` and `tauri::api::dir` modules, use `std::fs` instead. - Removed `tauri::api::version` module, use `semver` crate instead. - [`fbeb5b91`](https://www.github.com/tauri-apps/tauri/commit/fbeb5b9185baeda19e865228179e3e44c165f1d9)([#7170](https://www.github.com/tauri-apps/tauri/pull/7170)) Moved `tauri::api::ipc` to `tauri::ipc` and refactored all types. - [`fbeb5b91`](https://www.github.com/tauri-apps/tauri/commit/fbeb5b9185baeda19e865228179e3e44c165f1d9)([#7170](https://www.github.com/tauri-apps/tauri/pull/7170)) Removed the `linux-protocol-headers` feature (now always enabled) and added `linux-ipc-protocol`. - [`7fb419c3`](https://www.github.com/tauri-apps/tauri/commit/7fb419c326aaf72ecd556d8404377444ebb200e7)([#7535](https://www.github.com/tauri-apps/tauri/pull/7535)) Changed `App::handle` and `Manager::app_handle` to return a reference to an `AppHandle` instead of an owned value. - [`7fb419c3`](https://www.github.com/tauri-apps/tauri/commit/7fb419c326aaf72ecd556d8404377444ebb200e7)([#7535](https://www.github.com/tauri-apps/tauri/pull/7535)) The tray icon and menu have received a huge refactor with a lot of breaking changes in order to add new functionalities and improve the DX around using them and here is an overview of the changes: - All menu and tray types are now exported from `tauri::menu` and `tauri::tray` modules with new names so make sure to check the new types. - Removed `tauri::Builder::system_tray`, instead you should use `tauri::tray::TrayIconBuilder` inside `tauri::Builder::setup` hook to create your tray icons. - Changed `tauri::Builder::menu` to be a function to accommodate for new menu changes, you can passe `tauri::menu::Menu::default` to it to create a default menu. - Renamed `tauri::Context` methods `system_tray_icon`, `tauri::Context::system_tray_icon_mut` and `tauri::Context::set_system_tray_icon` to `tauri::Context::tray_icon`, `tauri::Context::tray_icon_mut` and `tauri::Context::set_tray_icon` to be consistent with new type names. - Added `RunEvent::MenuEvent` and `RunEvent::TrayIconEvent`. - Added `App/AppHandle::set_menu`, `App/AppHandle::remove_menu`, `App/AppHandle::show_menu`, `App/AppHandle::hide_menu` and `App/AppHandle::menu` to access, remove, hide or show the app-wide menu that is used as the global menu on macOS and on all windows that don't have a specific menu set for it on Windows and Linux. - Added `Window::set_menu`, `Window::remove_menu`, `Window::show_menu`, `Window::hide_menu`, `Window::is_menu_visible` and `Window::menu` to access, remove, hide or show the menu on this window. - Added `Window::popup_menu` and `Window::popup_menu_at` to show a context menu on the window at the cursor position or at a specific position. You can also popup a context menu using `popup` and `popup_at` methods from `ContextMenu` trait which is implemented for `Menu` and `Submenu` types. - Added `App/AppHandle::tray`, `App/AppHandle::tray_by_id`, `App/AppHandle::remove_tray` and `App/AppHandle::remove_tray_by_id` to access or remove a registered tray. - Added `WindowBuilder/App/AppHandle::on_menu_event` to register a new menu event handler. - Added `App/AppHandle::on_tray_icon_event` to register a new tray event handler. - [`7fb419c3`](https://www.github.com/tauri-apps/tauri/commit/7fb419c326aaf72ecd556d8404377444ebb200e7)([#7535](https://www.github.com/tauri-apps/tauri/pull/7535)) Renamed `system-tray` feature flag to `tray-icon`. - [`3a2c3e74`](https://www.github.com/tauri-apps/tauri/commit/3a2c3e74710bef9a14932dce74c351cca6215429)([#7306](https://www.github.com/tauri-apps/tauri/pull/7306)) The `Window#on_navigation` closure now receives a `&Url` argument instead of `Url`. ## \[2.0.0-alpha.10] ### New Features - [`f2d68cf7`](https://www.github.com/tauri-apps/tauri/commit/f2d68cf7d4e53443b2d53d2ae841e56c16a92514)([#6767](https://www.github.com/tauri-apps/tauri/pull/6767)) Add `incognito` option to the window configuration object. - [`f2d68cf7`](https://www.github.com/tauri-apps/tauri/commit/f2d68cf7d4e53443b2d53d2ae841e56c16a92514)([#6767](https://www.github.com/tauri-apps/tauri/pull/6767)) Add `WindowBuilder::incognito` - [`e0f0dce2`](https://www.github.com/tauri-apps/tauri/commit/e0f0dce220730e2822fc202463aedf0166145de7)([#6442](https://www.github.com/tauri-apps/tauri/pull/6442)) Added the `window_effects` option when creating a window and `Window::set_effects` to change it at runtime. ### Enhancements - [`2d2fd6ab`](https://www.github.com/tauri-apps/tauri/commit/2d2fd6abe291ddf645fa2fdecc08111d2c0e258e)([#7191](https://www.github.com/tauri-apps/tauri/pull/7191)) Use correct HTTP method when making requests to the proxied server on mobile. - [`b66e7d60`](https://www.github.com/tauri-apps/tauri/commit/b66e7d60f27d9a7973eae48d54cb72e30a710cca)([#7174](https://www.github.com/tauri-apps/tauri/pull/7174)) Implement `Clone` for `Channel` - [`8124145d`](https://www.github.com/tauri-apps/tauri/commit/8124145d6c6a629809c138d2c34082e1feb4fdbf)([#7171](https://www.github.com/tauri-apps/tauri/pull/7171)) Fixes path commands not being added. - [`4652c446`](https://www.github.com/tauri-apps/tauri/commit/4652c446b361a801252bcf45e9da39813bf85482)([#7144](https://www.github.com/tauri-apps/tauri/pull/7144)) Add `temp_dir` method to `PathResolver` ### Bug Fixes - [`8e855765`](https://www.github.com/tauri-apps/tauri/commit/8e85576506f5dea066d7e9317dbcab3681baff73)([#6809](https://www.github.com/tauri-apps/tauri/pull/6809)) Fix default log path for linux and windows ## \[2.0.0-alpha.9] - [`256c30c7`](https://www.github.com/tauri-apps/tauri/commit/256c30c72b737e49ced0d6a6483910dc779fc185)([#6863](https://www.github.com/tauri-apps/tauri/pull/6863)) Enhance parsing of annotated Android plugin methods to support private functions. - [`73c803a5`](https://www.github.com/tauri-apps/tauri/commit/73c803a561181137f20366f5d52511392a619f2b)([#6837](https://www.github.com/tauri-apps/tauri/pull/6837)) Added static function `loadConfig` on the Android `PluginManager` class. - [`edb16d13`](https://www.github.com/tauri-apps/tauri/commit/edb16d13a503da4b264ce459319fec25374c5c4f)([#6831](https://www.github.com/tauri-apps/tauri/pull/6831)) Adjust Android plugin exception error. - [`0ab5f40d`](https://www.github.com/tauri-apps/tauri/commit/0ab5f40d3a4207f20e4440587b41c4e78f91d233)([#6813](https://www.github.com/tauri-apps/tauri/pull/6813)) Add channel API for sending data across the IPC. - [`31444ac1`](https://www.github.com/tauri-apps/tauri/commit/31444ac196add770f2ad18012d7c18bce7538f22)([#6725](https://www.github.com/tauri-apps/tauri/pull/6725)) On Android, update proguard rules. - [`8ce32e74`](https://www.github.com/tauri-apps/tauri/commit/8ce32e74b5573931c3bc81e8e893a6d3b9686b0e)([#6986](https://www.github.com/tauri-apps/tauri/pull/6986)) Add `default_window_icon` getter on `App` and `AppHandle`. - [`2a5175a8`](https://www.github.com/tauri-apps/tauri/commit/2a5175a8f8f318aac9a6434271f2cc065e5989ae)([#6779](https://www.github.com/tauri-apps/tauri/pull/6779)) Enhance Android's `JSObject` return types. - [`bb2a8ccf`](https://www.github.com/tauri-apps/tauri/commit/bb2a8ccf1356e59b98947d827d61e4e99533f2bc)([#6830](https://www.github.com/tauri-apps/tauri/pull/6830)) Use actual iOS plugin instance to run command with `throws`. - [`94224906`](https://www.github.com/tauri-apps/tauri/commit/942249060ed12a5d21a2b21c30e0638c1d2b9df0)([#6783](https://www.github.com/tauri-apps/tauri/pull/6783)) Generate `TauriActivity` Kotlin class on the build script. - [`7a4b1fb9`](https://www.github.com/tauri-apps/tauri/commit/7a4b1fb96da475053c61960f362bbecf18cd00d4)([#6839](https://www.github.com/tauri-apps/tauri/pull/6839)) Added support to attibutes for each command path in the `generate_handler` macro. - [`9a79dc08`](https://www.github.com/tauri-apps/tauri/commit/9a79dc085870e0c1a5df13481ff271b8c6cc3b78)([#6947](https://www.github.com/tauri-apps/tauri/pull/6947)) Remove `enable_tauri_api` from the IPC scope. - [`dfa407ff`](https://www.github.com/tauri-apps/tauri/commit/dfa407ffcbc8a853d61139b68b55747ae49fb231)([#6763](https://www.github.com/tauri-apps/tauri/pull/6763)) Expose plugin configuration on the Android and iOS plugin classes. - [`3245d14b`](https://www.github.com/tauri-apps/tauri/commit/3245d14b9eb256a5c5675c7030bac7082855df47)([#6895](https://www.github.com/tauri-apps/tauri/pull/6895)) Moved the `app` feature to its own plugin in the plugins-workspace repository. - [`09376af5`](https://www.github.com/tauri-apps/tauri/commit/09376af59424cc27803fa2820d2ac0d4cdc90a6d)([#6704](https://www.github.com/tauri-apps/tauri/pull/6704)) Moved the `cli` feature to its own plugin in the plugins-workspace repository. - [`2d5378bf`](https://www.github.com/tauri-apps/tauri/commit/2d5378bfc1ba817ee2f331b41738a90e5997e5e8)([#6717](https://www.github.com/tauri-apps/tauri/pull/6717)) Moved the dialog APIs to its own plugin in the plugins-workspace repository. - [`39f1b04f`](https://www.github.com/tauri-apps/tauri/commit/39f1b04f7be4966488484829cd54c8ce72a04200)([#6943](https://www.github.com/tauri-apps/tauri/pull/6943)) Moved the `event` JS APIs to a plugin. - [`fc4d687e`](https://www.github.com/tauri-apps/tauri/commit/fc4d687ef0ef2ea069ed73c40916da733b5dcb8f)([#6716](https://www.github.com/tauri-apps/tauri/pull/6716)) Moved the file system APIs to its own plugin in the plugins-workspace repository. - [`f78a3783`](https://www.github.com/tauri-apps/tauri/commit/f78a378344bbec48533641661d865920a8f46f8f)([#6742](https://www.github.com/tauri-apps/tauri/pull/6742)) Moved the `http` feature to its own plugin in the plugins-workspace repository. - [`29ce9ce2`](https://www.github.com/tauri-apps/tauri/commit/29ce9ce2ce7dfb260d556d5cffd075e8fe06660c)([#6902](https://www.github.com/tauri-apps/tauri/pull/6902)) Moved the `os` feature to its own plugin in the plugins-workspace repository. - [`60cf9ed2`](https://www.github.com/tauri-apps/tauri/commit/60cf9ed2fcd7be4df41e86cf18735efe9b6cb254)([#6905](https://www.github.com/tauri-apps/tauri/pull/6905)) Moved the `process` feature to its own plugin in the plugins-workspace repository. - [`e1e85dc2`](https://www.github.com/tauri-apps/tauri/commit/e1e85dc2a5f656fc37867e278cae8042037740ac)([#6925](https://www.github.com/tauri-apps/tauri/pull/6925)) Moved the `protocol` scope configuration to the `asset_protocol` field in `SecurityConfig`. - [`96639ca2`](https://www.github.com/tauri-apps/tauri/commit/96639ca239c9e4f75142fc07868ac46822111cff)([#6749](https://www.github.com/tauri-apps/tauri/pull/6749)) Moved the `shell` functionality to its own plugin in the plugins-workspace repository. - [`e1e85dc2`](https://www.github.com/tauri-apps/tauri/commit/e1e85dc2a5f656fc37867e278cae8042037740ac)([#6925](https://www.github.com/tauri-apps/tauri/pull/6925)) Moved the updater configuration to the `BundleConfig`. - [`b072daa3`](https://www.github.com/tauri-apps/tauri/commit/b072daa3bd3e38b808466666619ddb885052c5b2)([#6919](https://www.github.com/tauri-apps/tauri/pull/6919)) Moved the `updater` feature to its own plugin in the plugins-workspace repository. - [`3188f376`](https://www.github.com/tauri-apps/tauri/commit/3188f3764978c6d1452ee31d5a91469691e95094)([#6883](https://www.github.com/tauri-apps/tauri/pull/6883)) Bump the MSRV to 1.65. - [`d693e526`](https://www.github.com/tauri-apps/tauri/commit/d693e526e8607129d7f7b62a10db715f3b87d2b9)([#6780](https://www.github.com/tauri-apps/tauri/pull/6780)) Added the `onNewIntent` Plugin hook on Android. - [`34b8f339`](https://www.github.com/tauri-apps/tauri/commit/34b8f339a4276ebff20b9d52caa103e8e3a7af66)([#6705](https://www.github.com/tauri-apps/tauri/pull/6705)) Add `app` method for the `PluginApi` struct. - [`96639ca2`](https://www.github.com/tauri-apps/tauri/commit/96639ca239c9e4f75142fc07868ac46822111cff)([#6749](https://www.github.com/tauri-apps/tauri/pull/6749)) Moved the `tauri::api::process` module to `tauri::process`. - [`cdad6e08`](https://www.github.com/tauri-apps/tauri/commit/cdad6e083728ea61bd6fc734ef93f6306056ea2e)([#6774](https://www.github.com/tauri-apps/tauri/pull/6774)) Changed how the `tauri-android` dependency is injected. This requires the `gen/android` project to be recreated. - [`e1e85dc2`](https://www.github.com/tauri-apps/tauri/commit/e1e85dc2a5f656fc37867e278cae8042037740ac)([#6925](https://www.github.com/tauri-apps/tauri/pull/6925)) Removed the allowlist configuration. - [`cebd7526`](https://www.github.com/tauri-apps/tauri/commit/cebd75261ac71b98976314a450cb292eeeec1515)([#6728](https://www.github.com/tauri-apps/tauri/pull/6728)) Moved the `clipboard` feature to its own plugin in the plugins-workspace repository. - [`e1e85dc2`](https://www.github.com/tauri-apps/tauri/commit/e1e85dc2a5f656fc37867e278cae8042037740ac)([#6925](https://www.github.com/tauri-apps/tauri/pull/6925)) Removed extract and move APIs from `tauri::api::file`. - [`3f17ee82`](https://www.github.com/tauri-apps/tauri/commit/3f17ee82f6ff21108806edb7b00500b8512b8dc7)([#6737](https://www.github.com/tauri-apps/tauri/pull/6737)) Moved the `global-shortcut` feature to its own plugin in the plugins-workspace repository. - [`ae102980`](https://www.github.com/tauri-apps/tauri/commit/ae102980fcdde3f55effdc0623ea425b48d07dd1)([#6719](https://www.github.com/tauri-apps/tauri/pull/6719)) Refactor the `Context` conditional fields and only parse the tray icon on desktop. - [`2d5378bf`](https://www.github.com/tauri-apps/tauri/commit/2d5378bfc1ba817ee2f331b41738a90e5997e5e8)([#6717](https://www.github.com/tauri-apps/tauri/pull/6717)) Remove the updater's dialog option. - [`e1e85dc2`](https://www.github.com/tauri-apps/tauri/commit/e1e85dc2a5f656fc37867e278cae8042037740ac)([#6925](https://www.github.com/tauri-apps/tauri/pull/6925)) Removed `UpdaterEvent`. See `tauri-plugin-updater` for new usage. - [`9a79dc08`](https://www.github.com/tauri-apps/tauri/commit/9a79dc085870e0c1a5df13481ff271b8c6cc3b78)([#6947](https://www.github.com/tauri-apps/tauri/pull/6947)) Moved the `window` JS APIs to its own plugin in the plugins-workspace repository. - [`22a76338`](https://www.github.com/tauri-apps/tauri/commit/22a763381622407d58ae72aa24c0afff00b40e04)([#6713](https://www.github.com/tauri-apps/tauri/pull/6713)) Expose `SafePathBuf` type in `tauri::path`. - [`c4171152`](https://www.github.com/tauri-apps/tauri/commit/c4171152c1846f425a937e82f8af1759bcc8c9ac)([#6909](https://www.github.com/tauri-apps/tauri/pull/6909)) Enable shadows by default. - [`dfa407ff`](https://www.github.com/tauri-apps/tauri/commit/dfa407ffcbc8a853d61139b68b55747ae49fb231)([#6763](https://www.github.com/tauri-apps/tauri/pull/6763)) Change iOS plugin init function signature to `func init_plugin() -> Plugin`. ## \[2.0.0-alpha.8] - Fixes boolean plugin parameters freezing the application. - [9de89791](https://www.github.com/tauri-apps/tauri/commit/9de897919aa7236913ba6ca7c34a68099f4ff600) fix(core): iOS plugin freezing when receiving a bool parameter ([#6700](https://www.github.com/tauri-apps/tauri/pull/6700)) on 2023-04-13 ## \[2.0.0-alpha.7] - Change minimum Android SDK version to 21 for the plugin library. - [db4c9dc6](https://www.github.com/tauri-apps/tauri/commit/db4c9dc655e07ee2184fe04571f500f7910890cd) feat(core): add option to configure Android's minimum SDK version ([#6651](https://www.github.com/tauri-apps/tauri/pull/6651)) on 2023-04-07 - Improve the `run_mobile_plugin` function error handling. - [f0570d9f](https://www.github.com/tauri-apps/tauri/commit/f0570d9feee05792cc720d26ef32da5eaed7f797) feat(core): improve `run_mobile_plugin` error handling ([#6655](https://www.github.com/tauri-apps/tauri/pull/6655)) on 2023-04-07 - Implement `Clone` for `plugin::PluginHandle`. - [052c5822](https://www.github.com/tauri-apps/tauri/commit/052c5822b53d55e118674d13914f58113a0d1121) feat(core): implement Clone for PluginHandle ([#6644](https://www.github.com/tauri-apps/tauri/pull/6644)) on 2023-04-05 ## \[2.0.0-alpha.6] - Fix compilation issues without the shell API features. - [a8137927](https://www.github.com/tauri-apps/tauri/commit/a813792786b55c51173e557834f515d4b2f7ce00) fix(core): compilation issues without execute or sidecar features ([#6621](https://www.github.com/tauri-apps/tauri/pull/6621)) on 2023-04-03 ## \[2.0.0-alpha.5] - Fixes ProGuard rules. - [adf4627b](https://www.github.com/tauri-apps/tauri/commit/adf4627b73bd7098772b7f3020b4aca7228bf239) fix(core): adjust ProGuard rules ([#6588](https://www.github.com/tauri-apps/tauri/pull/6588)) on 2023-03-31 - Added `raw` encoding option to read stdout and stderr raw bytes. - [f992e7f5](https://www.github.com/tauri-apps/tauri/commit/f992e7f58bf975c654a3daf36780b31a32bac064) chore(changes): readd change file on 2023-04-03 - Renamed the `default-tls` feature to `native-tls` and added `rustls-tls` feature. - [cfdee00f](https://www.github.com/tauri-apps/tauri/commit/cfdee00f2b1455a9719bc44823fdaeabbe4c1cb2) refactor(core): fix tls features, use rustls on mobile ([#6591](https://www.github.com/tauri-apps/tauri/pull/6591)) on 2023-03-30 ## \[2.0.0-alpha.4] - Allow a wry plugin to be registered at runtime. - [ae296f3d](https://www.github.com/tauri-apps/tauri/commit/ae296f3de16fb6a8badbad5555075a5861681fe5) refactor(tauri-runtime-wry): register runtime plugin after run() ([#6478](https://www.github.com/tauri-apps/tauri/pull/6478)) on 2023-03-17 - Inject `proguard-tauri.pro` file in the Android project. - [bef4ef51](https://www.github.com/tauri-apps/tauri/commit/bef4ef51bc2c633b88db121c2087a38dddb7d6bf) feat(android): enable minify on release, add proguard rules ([#6257](https://www.github.com/tauri-apps/tauri/pull/6257)) on 2023-02-13 - Return `bool` in the invoke handler. - [05dad087](https://www.github.com/tauri-apps/tauri/commit/05dad0876842e2a7334431247d49365cee835d3e) feat: initial work for iOS plugins ([#6205](https://www.github.com/tauri-apps/tauri/pull/6205)) on 2023-02-11 - Use correct lib name in xcode project. - [d1752fb1](https://www.github.com/tauri-apps/tauri/commit/d1752fb1f6223fa47d224cb6c62df9b74944a507) fix(cli): use correct lib name in xcode project ([#6387](https://www.github.com/tauri-apps/tauri/pull/6387)) on 2023-03-08 - Run Android and iOS native plugins on the invoke handler if a Rust plugin command is not found. - [05dad087](https://www.github.com/tauri-apps/tauri/commit/05dad0876842e2a7334431247d49365cee835d3e) feat: initial work for iOS plugins ([#6205](https://www.github.com/tauri-apps/tauri/pull/6205)) on 2023-02-11 - Added `initialize_android_plugin` and `initialize_ios_plugin` APIs on `AppHandle`. - [05dad087](https://www.github.com/tauri-apps/tauri/commit/05dad0876842e2a7334431247d49365cee835d3e) feat: initial work for iOS plugins ([#6205](https://www.github.com/tauri-apps/tauri/pull/6205)) on 2023-02-11 - Changed the plugin setup hook to take a second argument of type `PluginApi`. - [6aaba834](https://www.github.com/tauri-apps/tauri/commit/6aaba83476339fa413fe34d28877a932cb485117) refactor(plugin): add PluginApi and PluginHandle, expose on setup hook ([#6291](https://www.github.com/tauri-apps/tauri/pull/6291)) on 2023-02-16 - Refactored the implementation of the `mobile_entry_point` macro. - [9feab904](https://www.github.com/tauri-apps/tauri/commit/9feab904bf08b5c168d4779c21d0419409a68d30) feat(core): add API to call Android plugin ([#6239](https://www.github.com/tauri-apps/tauri/pull/6239)) on 2023-02-10 - Removed the attohttpc client. The `reqwest-*` Cargo features were also removed. - [dddaa943](https://www.github.com/tauri-apps/tauri/commit/dddaa943e7e0bf13935d567ef2f3f73e1c913300) refactor(core): remove attohttpc client, closes [#6415](https://www.github.com/tauri-apps/tauri/pull/6415) ([#6468](https://www.github.com/tauri-apps/tauri/pull/6468)) on 2023-03-17 - Added `App::run_mobile_plugin` and `AppHandle::run_mobile_plugin`. - [bfb2ab24](https://www.github.com/tauri-apps/tauri/commit/bfb2ab24e0b1d0860ea6e37688b5209541f0eda1) feat: add API to call iOS plugin ([#6242](https://www.github.com/tauri-apps/tauri/pull/6242)) on 2023-02-11 - Added the `shadow` option when creating a window and `Window::set_shadow`. - [a81750d7](https://www.github.com/tauri-apps/tauri/commit/a81750d779bc72f0fdb7de90b7fbddfd8049b328) feat(core): add shadow APIs ([#6206](https://www.github.com/tauri-apps/tauri/pull/6206)) on 2023-02-08 - Implemented `with_webview` on Android and iOS. - [05dad087](https://www.github.com/tauri-apps/tauri/commit/05dad0876842e2a7334431247d49365cee835d3e) feat: initial work for iOS plugins ([#6205](https://www.github.com/tauri-apps/tauri/pull/6205)) on 2023-02-11 ## \[2.0.0-alpha.3] - Update gtk to 0.16. - [7eb9aa75](https://www.github.com/tauri-apps/tauri/commit/7eb9aa75cfd6a3176d3f566fdda02d88aa529b0f) Update gtk to 0.16 ([#6155](https://www.github.com/tauri-apps/tauri/pull/6155)) on 2023-01-30 - Show all application logs on iOS. - [dee9460f](https://www.github.com/tauri-apps/tauri/commit/dee9460f9c9bc92e9c638e7691e616849ac2085b) feat: keep CLI alive when iOS app exits, show logs, closes [#5855](https://www.github.com/tauri-apps/tauri/pull/5855) ([#5902](https://www.github.com/tauri-apps/tauri/pull/5902)) on 2022-12-27 - Bump the MSRV to 1.64. - [7eb9aa75](https://www.github.com/tauri-apps/tauri/commit/7eb9aa75cfd6a3176d3f566fdda02d88aa529b0f) Update gtk to 0.16 ([#6155](https://www.github.com/tauri-apps/tauri/pull/6155)) on 2023-01-30 - Only proxy the dev server on mobile to simplify desktop usage. - [78eaadae](https://www.github.com/tauri-apps/tauri/commit/78eaadae2e75ab165d1970e592bb1455bb8636e3) refactor(core): only proxy on mobile ([#6126](https://www.github.com/tauri-apps/tauri/pull/6126)) on 2023-01-23 - Removed mobile logging initialization, which will be handled by `tauri-plugin-log`. - [](https://www.github.com/tauri-apps/tauri/commit/undefined) on undefined - Update rfd to 0.11. - [f0a1d9cd](https://www.github.com/tauri-apps/tauri/commit/f0a1d9cdbcfb645ce1c5f1cdd597f764991772cd) chore: update rfd and wry versions ([#6174](https://www.github.com/tauri-apps/tauri/pull/6174)) on 2023-02-03 ## \[2.0.0-alpha.2] - Fix the filesystem scope allowing sub-directories of the directory picked by the dialog when `recursive` option was `false`. - [9ad0a9a0](https://www.github.com/tauri-apps/tauri/commit/9ad0a9a0aa88a67c3d81ef84df4aad23556affde) Merge pull request from GHSA-6mv3-wm7j-h4w5 on 2022-12-22 ## \[2.0.0-alpha.1] - Implement response cache on the dev server proxy, used when the server responds with status 304. - [3ad5e72f](https://www.github.com/tauri-apps/tauri/commit/3ad5e72ff147b76267c010c778a3b94bba209bb0) feat(core): cache dev server proxy responses for 304 status code ([#5818](https://www.github.com/tauri-apps/tauri/pull/5818)) on 2022-12-12 - Properly proxy dev server requests with query strings and fragments. - [a9b4cf20](https://www.github.com/tauri-apps/tauri/commit/a9b4cf20a3e9a5cc984727a56111591504e084c0) fix(core): use entire request URL on dev server proxy ([#5819](https://www.github.com/tauri-apps/tauri/pull/5819)) on 2022-12-12 ## \[2.0.0-alpha.0] - Added the `default-tls` and `reqwest-default-tls` Cargo features for enabling TLS suppport to connect over HTTPS. - [f6f9192a](https://www.github.com/tauri-apps/tauri/commit/f6f9192aa51bd842df8aa1d1aa538b12aa6c2d29) fix(core): Android compilation on Windows ([#5658](https://www.github.com/tauri-apps/tauri/pull/5658)) on 2022-11-20 - **Breaking change:** Use the custom protocol as a proxy to the development server on all platforms except Linux. - [6f061504](https://www.github.com/tauri-apps/tauri/commit/6f0615044d09ec58393a7ebca5e45bb175e20db3) feat(cli): add `android dev` and `ios dev` commands ([#4982](https://www.github.com/tauri-apps/tauri/pull/4982)) on 2022-08-20 - Support `with_webview` for Android platform alowing execution of JNI code in context. - [8ea87e9c](https://www.github.com/tauri-apps/tauri/commit/8ea87e9c9ca8ba4c7017c8281f78aacd08f45785) feat(android): with_webview access for jni execution ([#5148](https://www.github.com/tauri-apps/tauri/pull/5148)) on 2022-09-08 - First mobile alpha release! - [fa3a1098](https://www.github.com/tauri-apps/tauri/commit/fa3a10988a03aed1b66fb17d893b1a9adb90f7cd) feat(ci): prepare 2.0.0-alpha.0 ([#5786](https://www.github.com/tauri-apps/tauri/pull/5786)) on 2022-12-08 - **Breaking change:** The window creation and setup hook are now called when the event loop is ready. - [b4622ea4](https://www.github.com/tauri-apps/tauri/commit/b4622ea4d32720bc3bb2a8c740bb70cfe32fed93) refactor(app): run setup and window creation when event loop is ready ([#4914](https://www.github.com/tauri-apps/tauri/pull/4914)) on 2022-08-11 - Export types required by the `mobile_entry_point` macro. - [98904863](https://www.github.com/tauri-apps/tauri/commit/9890486321c9c79ccfb7c547fafee85b5c3ffa71) feat(core): add `mobile_entry_point` macro ([#4983](https://www.github.com/tauri-apps/tauri/pull/4983)) on 2022-08-21 ## \[1.6.0] ### New Features - [`6e488378`](https://www.github.com/tauri-apps/tauri/commit/6e48837860203582d2ef8e59d4524f98511a14c0)([#8474](https://www.github.com/tauri-apps/tauri/pull/8474)) Re-export `Url` type. ### Enhancements - [`8ce51cec`](https://www.github.com/tauri-apps/tauri/commit/8ce51cec3baf4ed88d80c59bf3bbe96fd369c7a0)([#7718](https://www.github.com/tauri-apps/tauri/pull/7718)) On Windows, retain command line args when relaunching the app after an update. Supports NSIS and WiX (without elevated update task). ### Bug Fixes - [`cc3d8e77`](https://www.github.com/tauri-apps/tauri/commit/cc3d8e77313672f25520e278bbe8fae1b275a735)([#8539](https://www.github.com/tauri-apps/tauri/pull/8539)) Fixes a deadlock when reading a stdout or stderr line returns an error. - [`b546b42d`](https://www.github.com/tauri-apps/tauri/commit/b546b42db7e75a59232367dd6212fe3b75bb4c6d)([#8577](https://www.github.com/tauri-apps/tauri/pull/8577)) Preserve the order of JS object/map keys in IPC calls. This also fixes issues with the JS `http` module when calling to servers that required a specific order of `FormBody` contents. - [`8f8729d9`](https://www.github.com/tauri-apps/tauri/commit/8f8729d91843acd2bd2a24731db865d690dd9ab1)([#8312](https://www.github.com/tauri-apps/tauri/pull/8312)) On macOS, allow cancelling maximization when doubleclick happens on `data-tauri-drag-region` by simply keeping the left moust button pressed and then moving the mouse away of the starting position of the click, which is consistent with the native behavior of macOS. ### Dependencies - Upgraded to `tauri-runtime-wry@0.14.4` ## \[1.5.4] ### Enhancements - [`3c371aa8`](https://www.github.com/tauri-apps/tauri/commit/3c371aa8ee4032998f859b570702e81e26e77c6c)([#8228](https://www.github.com/tauri-apps/tauri/pull/8228)) Added `test::get_ipc_response`. ### Bug Fixes - [`50a3d170`](https://www.github.com/tauri-apps/tauri/commit/50a3d170f242178d41fe7e8a3adf964541f6fe9c)([#8408](https://www.github.com/tauri-apps/tauri/pull/8408)) On Windows, fix `open` dialog `defaultPath`, when invoked from JS, not working if the path uses forward slash (`/`) - [`645e1dcc`](https://www.github.com/tauri-apps/tauri/commit/645e1dcc6e113564e2ddaacf9cb8338aed1a0bd0)([#8404](https://www.github.com/tauri-apps/tauri/pull/8404)) Fix NSIS updater failing to launch when using `basicUi` mode. ### Dependencies - Upgraded to `tauri-runtime-wry@0.14.3` - Upgraded to `tauri-utils@1.5.2` - Upgraded to `tauri-runtime@0.14.2` - Upgraded to `tauri-macros@1.4.3` ## \[1.5.3] ### Enhancements - [`b3e53e72`](https://www.github.com/tauri-apps/tauri/commit/b3e53e7243311a2659b7569dddc20c56ac9f9d8e)([#8288](https://www.github.com/tauri-apps/tauri/pull/8288)) Added `AssetResolver::iter` to iterate on all embedded assets. - [`5e05236b`](https://www.github.com/tauri-apps/tauri/commit/5e05236b4987346697c7caae0567d3c50714c198)([#8289](https://www.github.com/tauri-apps/tauri/pull/8289)) Added tracing for window startup, plugins, `Window::eval`, events, IPC, updater and custom protocol request handlers behind the `tracing` feature flag. ### Bug Fixes - [`2ba88563`](https://www.github.com/tauri-apps/tauri/commit/2ba8856343e284ed022f28cff6d16db15ad4645f)([#8095](https://www.github.com/tauri-apps/tauri/pull/8095)) Fix docs.rs build for `x86_64-apple-darwin`. - [`4b6a602a`](https://www.github.com/tauri-apps/tauri/commit/4b6a602a89b36f24d34d6ccd8e3c9b7ce202c9eb)([#8234](https://www.github.com/tauri-apps/tauri/pull/8234)) Escape path of the updater msi to avoid crashing on installers with spaces. ### Dependencies - Upgraded to `tauri-runtime-wry@0.14.2` - Upgraded to `tauri-macros@1.4.2` ## \[1.5.2] ### Bug Fixes - [`21cdbb41`](https://www.github.com/tauri-apps/tauri/commit/21cdbb41a38f465148bbeb82feb3e7886c320182)([#7982](https://www.github.com/tauri-apps/tauri/pull/7982)) Set the correct `truncate` option on `OpenOptions` so that `write_file` can completely overwrite existing files. ## \[1.5.1] ### Bug Fixes - [`3671edbc`](https://www.github.com/tauri-apps/tauri/commit/3671edbcff37447c95382ab4c9fd1c36a460a037)([#7937](https://www.github.com/tauri-apps/tauri/pull/7937)) Fix devtools not toggling on `ctrl+shift+i` or `cmd+alt+i` shortcuts. ## \[1.5.0] ### New Features - [`eeb6be54`](https://www.github.com/tauri-apps/tauri/commit/eeb6be54228f3e5463a28c68956abb06a694c010)([#7512](https://www.github.com/tauri-apps/tauri/pull/7512)) Add `tauri::Manager::emit_filter` and only serialize once when emitting to multiple windows. - [`6c408b73`](https://www.github.com/tauri-apps/tauri/commit/6c408b736c7aa2a0a91f0a40d45a2b7a7dedfe78)([#7269](https://www.github.com/tauri-apps/tauri/pull/7269)) Add option to specify notification sound. - [`fdaee9a5`](https://www.github.com/tauri-apps/tauri/commit/fdaee9a5ce988c448dd035c2050c339d275e8d15)([#7350](https://www.github.com/tauri-apps/tauri/pull/7350)) Add `tauri::plugin::Builder::register_uri_scheme_protocol` - [`10e362d0`](https://www.github.com/tauri-apps/tauri/commit/10e362d098c9bed48f832bad471fb2fab83ab0bb)([#7432](https://www.github.com/tauri-apps/tauri/pull/7432)) Added `UpdateBuilder::endpoints` to add request endpoints at runtime. - [`10e362d0`](https://www.github.com/tauri-apps/tauri/commit/10e362d098c9bed48f832bad471fb2fab83ab0bb)([#7432](https://www.github.com/tauri-apps/tauri/pull/7432)) Added `UpdateResponse::header` and `UpdateResponse::remove_header` to modify the update download request headers. ### Enhancements - [`757e959e`](https://www.github.com/tauri-apps/tauri/commit/757e959eb276ed535cfddb0dea8897c56441c644)([#7344](https://www.github.com/tauri-apps/tauri/pull/7344)) Open links externally when `` exists - [`c9827338`](https://www.github.com/tauri-apps/tauri/commit/c98273387c0ffbb8d0de78ce17006411a1f503ee)([#7416](https://www.github.com/tauri-apps/tauri/pull/7416)) Enhance `readDir` API error with path information. - [`58d6b899`](https://www.github.com/tauri-apps/tauri/commit/58d6b899e21d37bb42810890d289deb57f2273bd)([#7636](https://www.github.com/tauri-apps/tauri/pull/7636)) Add `append` option to `FsOptions` in the `fs` JS module, used in `writeTextFile` and `writeBinaryFile`, to be able to append to existing files instead of overwriting it. - [`9aa34ada`](https://www.github.com/tauri-apps/tauri/commit/9aa34ada5769dbefa7dfe5f7a6288b3d20b294e4)([#7645](https://www.github.com/tauri-apps/tauri/pull/7645)) Add setting to switch to `http://.localhost/` for custom protocols on Windows. ### Bug Fixes - [`4bf1e85e`](https://www.github.com/tauri-apps/tauri/commit/4bf1e85e6bf85a7ec92d50c8465bc0588a6399d8)([#7722](https://www.github.com/tauri-apps/tauri/pull/7722)) Properly respect the `focused` option when creating the webview. - [`0797a002`](https://www.github.com/tauri-apps/tauri/commit/0797a002caad29cd8bedccf01f64bf3b45a5e528)([#7746](https://www.github.com/tauri-apps/tauri/pull/7746)) On macOS, fixed tapping on custom title bar doesn't maximize the window. - [`1a3dcdb8`](https://www.github.com/tauri-apps/tauri/commit/1a3dcdb8302fad511f2c1cd418fbc4cff0bd62ac)([#7185](https://www.github.com/tauri-apps/tauri/pull/7185)) On Windows, fix NSIS installers requiring administrator rights failing to be launched by updater. - [`fa7f9b77`](https://www.github.com/tauri-apps/tauri/commit/fa7f9b77ab8f0c890e9d7b120901610e0d3e4c46)([#7341](https://www.github.com/tauri-apps/tauri/pull/7341)) Fix updater not following endpoint redirects. - [`6fbd6dba`](https://www.github.com/tauri-apps/tauri/commit/6fbd6dba5290dc017ab0ba5a44cf4358b022836f)([#17](https://www.github.com/tauri-apps/tauri/pull/17)) Fix the validation of `std::env::current_exe` warn the user if AppImage is not mounted instead of panicking ### Dependencies - Upgraded to `tauri-utils@1.5.0` - Upgraded to `tauri-runtime-wry@0.14.1` - Upgraded to `tauri-runtime@0.14.1` - Upgraded to `tauri-macros@1.4.1` ## \[1.4.1] ### Bug Fixes - [`6afd3472`](https://www.github.com/tauri-apps/tauri/commit/6afd34727f153b32dbc568d169dbb17fb8dc3539)([#6680](https://www.github.com/tauri-apps/tauri/pull/6680)) Revert [#6680](https://github.com/tauri-apps/tauri/pull/6680) which added a default sound for notifications on Windows. This introduced inconsistency with other platforms that has silent notifications by default. In the upcoming releases, we will add support for modifying the notification sound across all platforms. ### Security fixes - [`066c09a6`](https://www.github.com/tauri-apps/tauri/commit/066c09a6ea06f42f550d090715e06beb65cd5564)([#7227](https://www.github.com/tauri-apps/tauri/pull/7227)) Fix regression in `1.4` where the default behavior of the file system scope was changed to allow reading hidden files and directories by default. ## \[1.4.0] ### New Features - [`7c237209`](https://www.github.com/tauri-apps/tauri/commit/7c237209207cd2938df660b6fd87d3b7d728bd03)([#6546](https://www.github.com/tauri-apps/tauri/pull/6546)) Added `tauri::VERSION` const to get Tauri's version from Rust. - [`4c39e46a`](https://www.github.com/tauri-apps/tauri/commit/4c39e46a3b438d007f139166ab2a0ba34291a10a)([#7026](https://www.github.com/tauri-apps/tauri/pull/7026)) Added `tauri::webview_version` , to get webview version. - [`359058ce`](https://www.github.com/tauri-apps/tauri/commit/359058cecca44a9c30b65140c44a8bb3a6dd3be8)([#5939](https://www.github.com/tauri-apps/tauri/pull/5939)) Add `tauri::api::os::locale` function to get the system locale. - [`c4d6fb4b`](https://www.github.com/tauri-apps/tauri/commit/c4d6fb4b1ea8acf02707a9fe5dcab47c1c5bae7b)([#2353](https://www.github.com/tauri-apps/tauri/pull/2353)) Added the `maximizable`, `minimizable` and `closable` options to the window builder. - [`c4d6fb4b`](https://www.github.com/tauri-apps/tauri/commit/c4d6fb4b1ea8acf02707a9fe5dcab47c1c5bae7b)([#2353](https://www.github.com/tauri-apps/tauri/pull/2353)) Added the `set_maximizable`, `set_minimizable`, `set_closable`, `is_maximizable`, `is_minimizable` and `is_closable` methods on `Window`. - [`1d99f8a3`](https://www.github.com/tauri-apps/tauri/commit/1d99f8a3c2f989d1a5ba4d805e3a40b07a3ca8a5)([#4752](https://www.github.com/tauri-apps/tauri/pull/4752)) Expose the `test` module behind the `test` Cargo feature. - [`000104bc`](https://www.github.com/tauri-apps/tauri/commit/000104bc3bc0c9ff3d20558ab9cf2080f126e9e0)([#6472](https://www.github.com/tauri-apps/tauri/pull/6472)) Add `Window::is_focused` and `Manager::get_focused_window` getters. - [`441f9646`](https://www.github.com/tauri-apps/tauri/commit/441f96465488a4f8a5731cc51b8ac97b685898c7)([#5491](https://www.github.com/tauri-apps/tauri/pull/5491)) Add `MenuHandle::try_get_item` and `SystemTrayHandle::try_get_item` which returns a `Option` instead of panicking. ### Enhancements - [`45330e38`](https://www.github.com/tauri-apps/tauri/commit/45330e38193d0b2a01aa926aec433acc6b8f6597)([#6375](https://www.github.com/tauri-apps/tauri/pull/6375)) Enhance the `asset` protocol to support streaming of large files. - [`df89ccc1`](https://www.github.com/tauri-apps/tauri/commit/df89ccc1912db6b81d43d56c9e6d66980ece2e8d)([#6955](https://www.github.com/tauri-apps/tauri/pull/6955)) Support `passive` mode for NSIS updater. - [`cd3846c8`](https://www.github.com/tauri-apps/tauri/commit/cd3846c8ce61ab2879b3911e831525e6242aaab2)([#6955](https://www.github.com/tauri-apps/tauri/pull/6955)) Restart the app after the NSIS updater is finished. - [`db7c5fbf`](https://www.github.com/tauri-apps/tauri/commit/db7c5fbf2e86f3694720f65834eb2c258b7c1291)([#7143](https://www.github.com/tauri-apps/tauri/pull/7143)) Remove `attohttpc` in favor of `reqwest`. - [`d2710e9d`](https://www.github.com/tauri-apps/tauri/commit/d2710e9d2e8fd93975ef6494512370faa8cb3b7e)([#6944](https://www.github.com/tauri-apps/tauri/pull/6944)) Unpin `time`, `ignore`, and `winnow` crate versions. Developers now have to pin crates if needed themselves. A list of crates that need pinning to adhere to Tauri's MSRV will be visible in Tauri's GitHub workflow: https://github.com/tauri-apps/tauri/blob/dev/.github/workflows/test-core.yml#L85. - [`5d85d099`](https://www.github.com/tauri-apps/tauri/commit/5d85d0990cd13a1446953a58633edc24eda55afe)([#7128](https://www.github.com/tauri-apps/tauri/pull/7128)) Send updater status events even if default dialog is enabled. ### Bug Fixes - [`82169e69`](https://www.github.com/tauri-apps/tauri/commit/82169e69fc904d2c7980534c4479bb6f38259fb4)([#5208](https://www.github.com/tauri-apps/tauri/pull/5208)) Fix parsing `allowlist > http > scope` urls that added a trailing slash which broke matching the incoming requests url. - [`b41b57eb`](https://www.github.com/tauri-apps/tauri/commit/b41b57ebb27befd366db5befaafb6043c18fdfef)([#7105](https://www.github.com/tauri-apps/tauri/pull/7105)) Fix panics when registering an invalid global shortcuts or checking it is registered and return proper errors instead. - [`aecf1469`](https://www.github.com/tauri-apps/tauri/commit/aecf14690947d109745b4ad823a3e8f4338de47a)([#6889](https://www.github.com/tauri-apps/tauri/pull/6889)) Fix IPC failing after a failed navigation to an external URL. - [`076e1a81`](https://www.github.com/tauri-apps/tauri/commit/076e1a81a50468e3dfb34ae9ca7e77c5e1758daa)([#7119](https://www.github.com/tauri-apps/tauri/pull/7119)) Fix unlistening to window events failing sometimes. - [`3f35b452`](https://www.github.com/tauri-apps/tauri/commit/3f35b452637ef1c794a423f1eda62a15d2ddaf42)([#4080](https://www.github.com/tauri-apps/tauri/pull/4080)) Fix `WindowBuilder::on_navigation` handler not registered properly. - [`0503eb69`](https://www.github.com/tauri-apps/tauri/commit/0503eb69ce7df6b4ed8f5249fdb519b86cd57d8d)([#7078](https://www.github.com/tauri-apps/tauri/pull/7078)) On macOS and Linux, fix app crashing when creating a window with `data:` uri. - [`3700793a`](https://www.github.com/tauri-apps/tauri/commit/3700793a2f1ea3686b1889c345d73007bb622a29)([#6934](https://www.github.com/tauri-apps/tauri/pull/6934)) Emit `UPTODATE` update status to javascript when the updater server returns status code `204` - [`ff5e4dbb`](https://www.github.com/tauri-apps/tauri/commit/ff5e4dbbb01bf3fc9c5143df732c75eef6fd98cb)([#6794](https://www.github.com/tauri-apps/tauri/pull/6794)) Fix some configurations not applied when creating the window through Javascript. - [`65fd674f`](https://www.github.com/tauri-apps/tauri/commit/65fd674f50ba0395d5cea23daf9d2f49f95647fe)([#6652](https://www.github.com/tauri-apps/tauri/pull/6652)) Play a sound when showing a notification on Windows. - [`696d77c3`](https://www.github.com/tauri-apps/tauri/commit/696d77c3ce480f4a3b4c1c57dae64ff2bb7842ce)([#4493](https://www.github.com/tauri-apps/tauri/pull/4493)) Fixes global events not being received on window-specific event listeners. ## \[1.3.0] - Added the `additional_browser_args` option when creating a window. - [3dc38b15](https://www.github.com/tauri-apps/tauri/commit/3dc38b150ea8c59c8ba67fd586f921016928f47c) feat(core): expose additional_browser_args to window config (fix: [#5757](https://www.github.com/tauri-apps/tauri/pull/5757)) ([#5799](https://www.github.com/tauri-apps/tauri/pull/5799)) on 2022-12-14 - Fix passing `--profile` to cargo in `tauri build` causing conflict with `--release` passed by the CLI. - [bfa69691](https://www.github.com/tauri-apps/tauri/commit/bfa69691a5171af97cc6a6d880cb3090338ed9e9) fix(cli): detect `--profile`. closes [#6255](https://www.github.com/tauri-apps/tauri/pull/6255) ([#6268](https://www.github.com/tauri-apps/tauri/pull/6268)) on 2023-02-18 - Added the `content_protected` option when creating a window and `Window::set_content_protected` to change it at runtime. - [4ab5545b](https://www.github.com/tauri-apps/tauri/commit/4ab5545b7a831c549f3c65e74de487ede3ab7ce5) feat: add content protection api, closes [#5132](https://www.github.com/tauri-apps/tauri/pull/5132) ([#5513](https://www.github.com/tauri-apps/tauri/pull/5513)) on 2022-12-13 - Fix serialization of js `Map` when used in `invoke`. - [d4d6a98d](https://www.github.com/tauri-apps/tauri/commit/d4d6a98d98fd09ba4e9ee4857ef3604d9e454337) fix(core): convert js `Map` to object before serialization, closes [#6078](https://www.github.com/tauri-apps/tauri/pull/6078) ([#6099](https://www.github.com/tauri-apps/tauri/pull/6099)) on 2023-01-19 - Added `Window::on_navigation`. - [3f35b452](https://www.github.com/tauri-apps/tauri/commit/3f35b452637ef1c794a423f1eda62a15d2ddaf42) Expose wry navigation_handler via WindowBuilder closes [#4080](https://www.github.com/tauri-apps/tauri/pull/4080) ([#5686](https://www.github.com/tauri-apps/tauri/pull/5686)) on 2022-12-27 - Sync `__TAURI_METADATA__.__windows` across all windows. - [146a794c](https://www.github.com/tauri-apps/tauri/commit/146a794cb696816854648d33e2124e82154c7b2f) fix(core): sync windows metadata across all windows, closes [#5571](https://www.github.com/tauri-apps/tauri/pull/5571) ([#5615](https://www.github.com/tauri-apps/tauri/pull/5615)) on 2022-12-27 - Fix `UpdaterBuilder::check` returning a parsing error when `204` is sent from server where it should instead return a `UpToDate` error. - [eb1ec041](https://www.github.com/tauri-apps/tauri/commit/eb1ec0416c52c75830dee77e4d714d882d1145b3) fix(core/updater): read and parse response after checking status code, closes [#6192](https://www.github.com/tauri-apps/tauri/pull/6192) ([#6575](https://www.github.com/tauri-apps/tauri/pull/6575)) on 2023-03-31 - Added `OkWithLabel` and `OkCancelWithLabels` variants to the `api::dialog::MessageDialogButtons` enum to set the text of the dialog buttons. - [00e1efaa](https://www.github.com/tauri-apps/tauri/commit/00e1efaa9b33876d41dd360624b69971e70d3856) feat: customize button texts of message dialog ([#4383](https://www.github.com/tauri-apps/tauri/pull/4383)) on 2022-12-28 - Added `Builder::device_event_filter` and `App::set_device_event_filter` methods. - [73fd60ee](https://www.github.com/tauri-apps/tauri/commit/73fd60eef2b60f5dc84525ef9c315f4d80c4414f) expose set_device_event_filter in tauri ([#5562](https://www.github.com/tauri-apps/tauri/pull/5562)) on 2022-12-13 - Fix resize glitch when double clicking a custom titlebar in the top resize area. - [4892637f](https://www.github.com/tauri-apps/tauri/commit/4892637f83b0f64822a5d304e8786a4c92a8957d) fix: Resizing glitch on custom titlebar click (closes [#2549](https://www.github.com/tauri-apps/tauri/pull/2549)) ([#5966](https://www.github.com/tauri-apps/tauri/pull/5966)) on 2023-01-04 - Fixes tray events not being delivered. - [138cb8d7](https://www.github.com/tauri-apps/tauri/commit/138cb8d739b15bccdb388e555c20f17ffe16318c) fix(tauri-runtime-wry): tray event listener not registered ([#6270](https://www.github.com/tauri-apps/tauri/pull/6270)) on 2023-02-14 - Fix the filesystem scope allowing sub-directories of the directory picked by the dialog when `recursive` option was `false`. - [72389b00](https://www.github.com/tauri-apps/tauri/commit/72389b00d7b495ffd7750eb1e75a3b8537d07cf3) Merge pull request from GHSA-6mv3-wm7j-h4w5 on 2022-12-22 - Add `is_minimized()` window method. - [62144ef3](https://www.github.com/tauri-apps/tauri/commit/62144ef3be63b237869e511826edfb938e2c7174) feat: add is_minimized (fix [#3878](https://www.github.com/tauri-apps/tauri/pull/3878)) ([#5618](https://www.github.com/tauri-apps/tauri/pull/5618)) on 2022-12-13 - Bump minimum supported Rust version to 1.60. - [5fdc616d](https://www.github.com/tauri-apps/tauri/commit/5fdc616df9bea633810dcb814ac615911d77222c) feat: Use the zbus-backed of notify-rust ([#6332](https://www.github.com/tauri-apps/tauri/pull/6332)) on 2023-03-31 - Update the `open` crate to v3.2 to fix an URL encoding bug on Windows. - [708efbd9](https://www.github.com/tauri-apps/tauri/commit/708efbd9b72508a5a5aa55092a48d3218e008ce3) fix(core/tauri): upgrade `open` to 3.2 to fix a bug on Windows ([#6441](https://www.github.com/tauri-apps/tauri/pull/6441)) on 2023-04-06 - Added support to `mailto:` and `tel:` links on the shell API. - [d0d873e3](https://www.github.com/tauri-apps/tauri/commit/d0d873e39a3cd5e51e9cf0145a024ffdb0c2a941) feat(core): add support to mailto: and tel: links, closes [#5521](https://www.github.com/tauri-apps/tauri/pull/5521) ([#5544](https://www.github.com/tauri-apps/tauri/pull/5544)) on 2022-12-12 - Pin `os_info` to `=3.5`. - [a8d640b3](https://www.github.com/tauri-apps/tauri/commit/a8d640b3c659c7cfea23fe60cc5d9ef377841c5e) fix(core): pin unarray and os_info ([#6212](https://www.github.com/tauri-apps/tauri/pull/6212)) on 2023-02-07 - Pin raw-window-handle to 0.5.0 to keep MSRV. - [c46c09f3](https://www.github.com/tauri-apps/tauri/commit/c46c09f31d9f5169ca8a7e62406a9ea170e3a5c5) fix(deps): pin raw-window-handle to 0.5.0 ([#6480](https://www.github.com/tauri-apps/tauri/pull/6480)) on 2023-03-17 - Pin `time` to `0.3.15`. - [3d16461b](https://www.github.com/tauri-apps/tauri/commit/3d16461b68583ba7db037fbc217786e79b46ddf2) fix(core): pin time to 0.3.15 ([#6312](https://www.github.com/tauri-apps/tauri/pull/6312)) on 2023-02-19 - Added configuration to specify remote URLs allowed to access the IPC. - [ee71c31f](https://www.github.com/tauri-apps/tauri/commit/ee71c31fd09cc5427da6d29d37c003a914547696) feat(core): allow configuring remote domains with IPC access, closes [#5088](https://www.github.com/tauri-apps/tauri/pull/5088) ([#5918](https://www.github.com/tauri-apps/tauri/pull/5918)) on 2023-04-11 - Add `title` getter on window. - [233e43b0](https://www.github.com/tauri-apps/tauri/commit/233e43b0c34fada1ca025378533a0b76931a6540) feat: add `title` getter on window, closes [#5023](https://www.github.com/tauri-apps/tauri/pull/5023) ([#5515](https://www.github.com/tauri-apps/tauri/pull/5515)) on 2022-12-13 - Implement `SystemTray::with_tooltip` and `SystemTrayHandle::set_tooltip` for Windows and macOS. - [2265e097](https://www.github.com/tauri-apps/tauri/commit/2265e09718f6ebfeb1d200f11e1e1e069075af6e) feat(windows): implement `with_tooltip` ([#5938](https://www.github.com/tauri-apps/tauri/pull/5938)) on 2023-01-01 - Added window's `url()` getter. - [d17027e1](https://www.github.com/tauri-apps/tauri/commit/d17027e1a0db3e8c5ae81fc4f472c5918fbce611) feat: expose url method ([#5914](https://www.github.com/tauri-apps/tauri/pull/5914)) on 2022-12-26 - On Windows, change webview theme based on Window theme for more accurate `prefers-color-scheme` support. - [7a8d570d](https://www.github.com/tauri-apps/tauri/commit/7a8d570db72667367eb24b75ddc5dd07a968f7c0) fix: sync webview theme with window theme on Windows, closes [#5802](https://www.github.com/tauri-apps/tauri/pull/5802) ([#5874](https://www.github.com/tauri-apps/tauri/pull/5874)) on 2022-12-27 - Add a method to the `WindowBuilder` struct to recreate windows from tauri.conf.json configurations. - [49dff27e](https://www.github.com/tauri-apps/tauri/commit/49dff27ef1b36c48dbfd49f44b9b3ac07b372bdf) feat(core): create WindowBuilder from WindowConfig ([#6073](https://www.github.com/tauri-apps/tauri/pull/6073)) on 2023-01-17 - On Windows, Fix missing `WindowEvent::Focused` in `App::run` callback. - [ff4ea1ea](https://www.github.com/tauri-apps/tauri/commit/ff4ea1eabbf2874b113c6b4698002929bbac737a) fix: dispatch focus event to app.run on Windows, closes [#6460](https://www.github.com/tauri-apps/tauri/pull/6460) ([#6504](https://www.github.com/tauri-apps/tauri/pull/6504)) on 2023-03-31 - Pin `winnow` crate to 0.4.1 to keep the 1.60 MSRV. ## \[1.2.5] - Block remote URLs from accessing the IPC. - [9c0593c33](https://www.github.com/tauri-apps/tauri/commit/9c0593c33af52cd9e00ec784d15f63efebdf039c) feat(core): block remote URLs from accessing the IPC on 2023-04-12 ## \[1.2.4] - Pin `ignore` to `=0.4.18`. - [adcb082b](https://www.github.com/tauri-apps/tauri/commit/adcb082b1651ecb2a6208b093e12f4185aa3fc98) chore(deps): pin `ignore` to =0.4.18 on 2023-01-17 ## \[1.2.3] - Fix the filesystem scope allowing sub-directories of the directory picked by the dialog when `recursive` option was `false`. - [f1b0ad6e](https://www.github.com/tauri-apps/tauri/commit/f1b0ad6e8b721cf1420a9a4b9be5b05c39941d16) Merge pull request from GHSA-6mv3-wm7j-h4w5 on 2022-12-22 ## \[1.2.2] - Invoke event listener in windows safely to avoid causing uncaught errors in windows that have loaded external urls - [c14b1df3](https://www.github.com/tauri-apps/tauri/commit/c14b1df37284020b3edb32400eb4b9e32c945472) fix(core): Invoke event listener in windows safely to avoid causing uncaught errors in windows that have loaded external urls ([#5563](https://www.github.com/tauri-apps/tauri/pull/5563)) on 2022-12-08 - Cleanup sidecar and tray icons when calling `app.exit()` from JS. - [0f269608](https://www.github.com/tauri-apps/tauri/commit/0f26960891228c5909e06d9f850c44ffaebf536c) fix(core/api): cleanup before exit ([#5765](https://www.github.com/tauri-apps/tauri/pull/5765)) on 2022-12-07 - Fix compatibility with older Linux distributions. - [b490308c](https://www.github.com/tauri-apps/tauri/commit/b490308c8897b893292951754607c2253abbc6e1) fix(core): compilation error on older Linux versions, fixes [#5684](https://www.github.com/tauri-apps/tauri/pull/5684) ([#5697](https://www.github.com/tauri-apps/tauri/pull/5697)) on 2022-11-28 - Add `tauri::Builder::enable_macos_default_menu` to enable or disable the default menu creation on macOS. - [8866ecac](https://www.github.com/tauri-apps/tauri/commit/8866ecac3cd1af8bf02e29569d605be5a1afe22c) feat(core): add `tauri::Builder::enable_macos_default_menu` ([#5756](https://www.github.com/tauri-apps/tauri/pull/5756)) on 2022-12-07 - [b293da35](https://www.github.com/tauri-apps/tauri/commit/b293da35dd5ae8c1569a3f3c994b4c1a4c227f4a) fix(changes): change `enable_macos_default_menu` bump to patch on 2022-12-08 ## \[1.2.1] - Fixes a double serialization on the IPC. - [677838cc](https://www.github.com/tauri-apps/tauri/commit/677838ccfadfdf37039be53bfad666bbe1dab8c3) fix double serialize on invoke ([#5639](https://www.github.com/tauri-apps/tauri/pull/5639)) on 2022-11-20 - Moved the custom protocol headers support on Linux behind the `linux-protocol-headers` Cargo feature to enhance compatibility with older Linux distributions. - [d7109460](https://www.github.com/tauri-apps/tauri/commit/d710946064c47fa488eca01a62403e70b2b5ff87) refactor: move Linux custom protocol headers support behind feature flag ([#5683](https://www.github.com/tauri-apps/tauri/pull/5683)) on 2022-11-24 - Fixes definition of `impl HasRawDisplayHandle` for `AppHandle` and `App`. - [ed43ff32](https://www.github.com/tauri-apps/tauri/commit/ed43ff324330d1bd9c042a53a6636dfc7d97b410) fix(tauri): add missing generics on AppHandle and App ([#5642](https://www.github.com/tauri-apps/tauri/pull/5642)) on 2022-11-17 ## \[1.2.0] - Add `accept_first_mouse` option for macOS windows. - [95f467ad](https://www.github.com/tauri-apps/tauri/commit/95f467add51448319983c54e2f382c7c09fb72d6) feat(core): add window `accept_first_mouse` option, closes [#5347](https://www.github.com/tauri-apps/tauri/pull/5347) ([#5374](https://www.github.com/tauri-apps/tauri/pull/5374)) on 2022-10-17 - Add new app-specific `BaseDirectory` enum variants `AppConfig`, `AppData`, `AppLocalData`, `AppCache` and `AppLog` along with equivalent functions in `path` module and deprecated ambiguous variants `Log` and `App` along with their equivalent functions in `path` module. - [5d89905e](https://www.github.com/tauri-apps/tauri/commit/5d89905e39ce0e6eaaec50a693679335449edb32) feat(api): add app-specific directory APIs, closes [#5263](https://www.github.com/tauri-apps/tauri/pull/5263) ([#5272](https://www.github.com/tauri-apps/tauri/pull/5272)) on 2022-09-28 - Set the correct mimetype when streaming files through `asset:` protocol - [39443b43](https://www.github.com/tauri-apps/tauri/commit/39443b4350bd208c4d6eec5e1095f215199f8aa3) fix(core): set correct mimetype for asset protocol streams, closes [#5203](https://www.github.com/tauri-apps/tauri/pull/5203) ([#5210](https://www.github.com/tauri-apps/tauri/pull/5210)) on 2022-09-30 - [2d9c2b47](https://www.github.com/tauri-apps/tauri/commit/2d9c2b472416339829f9113f976f193bf8e0665f) Revert "fix(core): set correct mimetype for asset protocol streams, closes [#5203](https://www.github.com/tauri-apps/tauri/pull/5203) ([#5210](https://www.github.com/tauri-apps/tauri/pull/5210))" on 2022-09-30 - [9b1a6a1c](https://www.github.com/tauri-apps/tauri/commit/9b1a6a1c02b8d62dd47d9ce42aa05723d7c1b892) fix(core): set correct mimetype for asset protocol streams, [#5203](https://www.github.com/tauri-apps/tauri/pull/5203) ([#5536](https://www.github.com/tauri-apps/tauri/pull/5536)) on 2022-11-04 - Disable automatic window tabbing on macOS when the `tabbing_identifier` option is not defined, the window is transparent or does not have decorations. - [4137ab44](https://www.github.com/tauri-apps/tauri/commit/4137ab44a81d739556cbc7583485887e78952bf1) feat(macos): add `tabbing_identifier` option, closes [#2804](https://www.github.com/tauri-apps/tauri/pull/2804), [#3912](https://www.github.com/tauri-apps/tauri/pull/3912) ([#5399](https://www.github.com/tauri-apps/tauri/pull/5399)) on 2022-10-19 - The custom protocol now validates the request URI. This has implications when using the `asset` protocol without the `convertFileSrc` helper, the URL must now use the `asset://localhost/$filePath` format. - [357480f4](https://www.github.com/tauri-apps/tauri/commit/357480f4ae43aa8da99f7ba61ae2ee51b4552c60) feat(core): custom protocol headers on Linux, closes [#4496](https://www.github.com/tauri-apps/tauri/pull/4496) ([#5421](https://www.github.com/tauri-apps/tauri/pull/5421)) on 2022-10-17 - Escape glob special characters in files/directories when dropping files or using the open/save dialogs. - [4cbdf0fb](https://www.github.com/tauri-apps/tauri/commit/4cbdf0fb1c0de5004eab51c36d5843a9816f18af) fix(core): escape glob characters in drop/dialogs , closes [#5234](https://www.github.com/tauri-apps/tauri/pull/5234) ([#5237](https://www.github.com/tauri-apps/tauri/pull/5237)) on 2022-10-05 - Properly emit events with object payload. - [79dd6e16](https://www.github.com/tauri-apps/tauri/commit/79dd6e16a7306351e2acf21166506b2876b58a7e) fix(core): properly emit events with object payload, closes [#5482](https://www.github.com/tauri-apps/tauri/pull/5482) ([#5492](https://www.github.com/tauri-apps/tauri/pull/5492)) on 2022-10-27 - Fixes access to the `WebviewWindow.getByLabel` function in a `tauri://window-created` event listener. - [e00b1e5f](https://www.github.com/tauri-apps/tauri/commit/e00b1e5f94b3f841bf107cc17ee74be9203ea080) fix(core): update metadata before window-created listeners, closes [#5191](https://www.github.com/tauri-apps/tauri/pull/5191) ([#5458](https://www.github.com/tauri-apps/tauri/pull/5458)) on 2022-10-22 - Fixes resource reading being always rejected by the scope. - [a06dc699](https://www.github.com/tauri-apps/tauri/commit/a06dc6993148f10ff7623c9dcc81f313dd960ad0) fix(core): canonicalize resource dir to fix scope check, closes [#5196](https://www.github.com/tauri-apps/tauri/pull/5196) ([#5218](https://www.github.com/tauri-apps/tauri/pull/5218)) on 2022-09-29 - Fixes `__TAURI_PATTERN__` object freeze. - [49f06ca4](https://www.github.com/tauri-apps/tauri/commit/49f06ca4b9f1d02933e46bbc50330b84ac81be87) fix: deepfreeze check by prop ([#5407](https://www.github.com/tauri-apps/tauri/pull/5407)) on 2022-10-17 - Readd the option to create an unfocused window via the `focused` method. The `focus` function has been deprecated. - [4036e15f](https://www.github.com/tauri-apps/tauri/commit/4036e15f5af933bdc0d0913508b5103958afc143) feat(core): reimplement window initial focus flag, closes [#5120](https://www.github.com/tauri-apps/tauri/pull/5120) ([#5338](https://www.github.com/tauri-apps/tauri/pull/5338)) on 2022-10-08 - Add `hidden_title` option for macOS windows. - [321f3fed](https://www.github.com/tauri-apps/tauri/commit/321f3fed19df40c1223099bce953332b7f00f7a9) feat(macos): `title_bar_style` and `hidden_title` window options, closes [#2663](https://www.github.com/tauri-apps/tauri/pull/2663) ([#3965](https://www.github.com/tauri-apps/tauri/pull/3965)) on 2022-09-30 - Custom protocol headers are now implemented on Linux when running on webkit2gtk 2.36 or above. - [357480f4](https://www.github.com/tauri-apps/tauri/commit/357480f4ae43aa8da99f7ba61ae2ee51b4552c60) feat(core): custom protocol headers on Linux, closes [#4496](https://www.github.com/tauri-apps/tauri/pull/4496) ([#5421](https://www.github.com/tauri-apps/tauri/pull/5421)) on 2022-10-17 - Add `App::show()`, `AppHandle::show()`, `App::hide()` and `AppHandle::hide()` for hiding/showing the entire application on macOS. - [39bf895b](https://www.github.com/tauri-apps/tauri/commit/39bf895b73ec6b53f5758815396ba85dda6b9c67) feat(macOS): Add application `show` and `hide` methods ([#3689](https://www.github.com/tauri-apps/tauri/pull/3689)) on 2022-10-03 - Fix a deadlock when modifying the menu in the `on_menu_event` closure. - [ae65951b](https://www.github.com/tauri-apps/tauri/commit/ae65951bc477126b71816d77424f8167814bbe8d) fix(core): fix deadlock in `on_menu_event`, closes [#5254](https://www.github.com/tauri-apps/tauri/pull/5254) ([#5257](https://www.github.com/tauri-apps/tauri/pull/5257)) on 2022-09-28 - - [7d9aa398](https://www.github.com/tauri-apps/tauri/commit/7d9aa3987efce2d697179ffc33646d086c68030c) feat: bump MSRV to 1.59 ([#5296](https://www.github.com/tauri-apps/tauri/pull/5296)) on 2022-09-28 - Resolve base system directory in shell scope. - [99fe1c56](https://www.github.com/tauri-apps/tauri/commit/99fe1c562ffcea4089f785c73f4e6706d4ebc16b) fix(core): resolve base dir in shell scope, closes [#5480](https://www.github.com/tauri-apps/tauri/pull/5480) ([#5508](https://www.github.com/tauri-apps/tauri/pull/5508)) on 2022-11-04 - Added `tabbing_identifier` to the window builder on macOS. - [4137ab44](https://www.github.com/tauri-apps/tauri/commit/4137ab44a81d739556cbc7583485887e78952bf1) feat(macos): add `tabbing_identifier` option, closes [#2804](https://www.github.com/tauri-apps/tauri/pull/2804), [#3912](https://www.github.com/tauri-apps/tauri/pull/3912) ([#5399](https://www.github.com/tauri-apps/tauri/pull/5399)) on 2022-10-19 - Add `title_bar_style` option for macOS windows. - [321f3fed](https://www.github.com/tauri-apps/tauri/commit/321f3fed19df40c1223099bce953332b7f00f7a9) feat(macos): `title_bar_style` and `hidden_title` window options, closes [#2663](https://www.github.com/tauri-apps/tauri/pull/2663) ([#3965](https://www.github.com/tauri-apps/tauri/pull/3965)) on 2022-09-30 - Added methods to set the system tray title on macOS. - [8f1ace77](https://www.github.com/tauri-apps/tauri/commit/8f1ace77956ac3477826ceb059a191e55b3fff93) feat: expose `set_title` for MacOS tray ([#5182](https://www.github.com/tauri-apps/tauri/pull/5182)) on 2022-09-30 - Added the `user_agent` option when creating a window. - [a6c94119](https://www.github.com/tauri-apps/tauri/commit/a6c94119d8545d509723b147c273ca5edfe3729f) feat(core): expose user_agent to window config ([#5317](https://www.github.com/tauri-apps/tauri/pull/5317)) on 2022-10-02 ## \[1.1.4] - Block remote URLs from accessing the IPC. - [58ea0b452](https://www.github.com/tauri-apps/tauri/commit/58ea0b45268dbd46cbac0ebb0887353d057ca767) feat(core): block remote URLs from accessing the IPC on 2023-04-12 ## \[1.1.3] - Fix the filesystem scope allowing sub-directories of the directory picked by the dialog when `recursive` option was `false`. - [2654c0f4](https://www.github.com/tauri-apps/tauri/commit/2654c0f49da23434d36447d0908fa24e61ff5e4e) Merge pull request from GHSA-6mv3-wm7j-h4w5 on 2022-12-22 ## \[1.1.2] - Escape glob special characters in files/directories when dropping files or using the open/save dialogs. - [e4dc5bed](https://www.github.com/tauri-apps/tauri/commit/e4dc5bedbb54fbe6e06ab833d7fb7e0cacebad10) fix(core): escape glob characters in drop/dialogs , closes [#5234](https://www.github.com/tauri-apps/tauri/pull/5234) ([#5237](https://www.github.com/tauri-apps/tauri/pull/5237)) on 2022-10-05 ## \[1.1.1] - Add missing allowlist config for `set_cursor_grab`, `set_cursor_visible`, `set_cursor_icon` and `set_cursor_position` APIs. - Bumped due to a bump in tauri-utils. - [c764408d](https://www.github.com/tauri-apps/tauri/commit/c764408da7fae123edd41115bda42fa75a4731d2) fix: Add missing allowlist config for cursor apis, closes [#5207](https://www.github.com/tauri-apps/tauri/pull/5207) ([#5211](https://www.github.com/tauri-apps/tauri/pull/5211)) on 2022-09-16 ## \[1.1.0] - Implement `api::http::ClientBuilder::max_redirections` for the default attohttpc client. - [ba5560b2](https://www.github.com/tauri-apps/tauri/commit/ba5560b2a1a61666d8e0bda31424333815714b2f) feat(core): implement max_redirections for attohttpc, ref [#4795](https://www.github.com/tauri-apps/tauri/pull/4795) ([#4811](https://www.github.com/tauri-apps/tauri/pull/4811)) on 2022-07-31 - Implement `From for std::process::Command`. - [9f1d34c2](https://www.github.com/tauri-apps/tauri/commit/9f1d34c288cbe64f0453cf210bc9488bb42ed19a) feat: implement From for std::process::Command, closes [#4673](https://www.github.com/tauri-apps/tauri/pull/4673) ([#4836](https://www.github.com/tauri-apps/tauri/pull/4836)) on 2022-08-02 - Added support to configuration files in TOML format (Tauri.toml file). - [ae83d008](https://www.github.com/tauri-apps/tauri/commit/ae83d008f9e1b89bfc8dddaca42aa5c1fbc36f6d) feat: add support to TOML config file `Tauri.toml`, closes [#4806](https://www.github.com/tauri-apps/tauri/pull/4806) ([#4813](https://www.github.com/tauri-apps/tauri/pull/4813)) on 2022-08-02 - Enhance `SystemTray::with_icon` to accept `tauri::Icon`. - [964926ff](https://www.github.com/tauri-apps/tauri/commit/964926ff850b82e104d29fec4c8a1d9a16798c06) feat(core): enhance `SystemTray::with_icon` ([#4849](https://www.github.com/tauri-apps/tauri/pull/4849)) on 2022-08-03 - Fixes CLI parser ignoring inner subcommands. - [dcd50667](https://www.github.com/tauri-apps/tauri/commit/dcd506676c0a15ac4af7705b62574cc2eea3bb43) fix(core): parse inner CLI subcommands, closes [#4688](https://www.github.com/tauri-apps/tauri/pull/4688) ([#4841](https://www.github.com/tauri-apps/tauri/pull/4841)) on 2022-08-02 - Fix `fs.readDir` recursive option reading symlinked directories that are not allowed by the scope. - [f4121c12](https://www.github.com/tauri-apps/tauri/commit/f4121c128e69b06c3eb5eea14dd2af4720afed49) fix(endpoints/fs/readDir): don't read symlinks that are not allowed b… ([#5123](https://www.github.com/tauri-apps/tauri/pull/5123)) on 2022-09-08 - Fix typo in invalid state access panic message. - [c7fec3e1](https://www.github.com/tauri-apps/tauri/commit/c7fec3e1ff73f7d857548cab78777a3aaf084c68) fix typo in state.rs ([#4699](https://www.github.com/tauri-apps/tauri/pull/4699)) on 2022-07-25 - Fixes updater breaking the app icon in Finder. - [58fc1f21](https://www.github.com/tauri-apps/tauri/commit/58fc1f2150b6ddd1b322deb03ca9083222fc3522) fix(updater): blank icon after update on macOS, closes [#4613](https://www.github.com/tauri-apps/tauri/pull/4613) ([#4861](https://www.github.com/tauri-apps/tauri/pull/4861)) on 2022-08-04 - Implement theme APIs for Linux. - [f21cbecd](https://www.github.com/tauri-apps/tauri/commit/f21cbecdeb3571ac4ad971b9a865ff62a131a176) feat(core): implement theme APIs for Linux ([#4808](https://www.github.com/tauri-apps/tauri/pull/4808)) on 2022-08-02 - Implement `raw_window_handle::HasRawDisplayHandle` for `App` and `AppHandle` - [0ad9531d](https://www.github.com/tauri-apps/tauri/commit/0ad9531d799d81e1f807000a9d74dfd7998206fe) chore(deps): update tao to 0.13, wry to 0.20, rfd to 0.10, raw-window-handle to 0.5 ([#4804](https://www.github.com/tauri-apps/tauri/pull/4804)) on 2022-07-31 - Retain command line arguments in `api::process::restart`. - [6218c31e](https://www.github.com/tauri-apps/tauri/commit/6218c31e175d43b59b87bd5b36ee773467566f67) fix(core): retain command line arguments on restart, closes [#4760](https://www.github.com/tauri-apps/tauri/pull/4760) ([#4763](https://www.github.com/tauri-apps/tauri/pull/4763)) on 2022-07-25 - Added APIs to create a system tray at runtime. - [4d063ae9](https://www.github.com/tauri-apps/tauri/commit/4d063ae9ee9538cd6fa5e01b80070c6edf8eaeb9) feat(core): create system tray at runtime, closes [#2278](https://www.github.com/tauri-apps/tauri/pull/2278) ([#4862](https://www.github.com/tauri-apps/tauri/pull/4862)) on 2022-08-09 - Add `api::Command::encoding` method to set the stdout/stderr encoding. - [d8cf9f9f](https://www.github.com/tauri-apps/tauri/commit/d8cf9f9fcd617ac24fa418952fd4a32c08804f5c) Command support for specified character encoding, closes [#4644](https://www.github.com/tauri-apps/tauri/pull/4644) ([#4772](https://www.github.com/tauri-apps/tauri/pull/4772)) on 2022-07-28 - Do not follow redirects when `api::http::ClientBuilder::max_redirections` is `0`. - [d576e8ae](https://www.github.com/tauri-apps/tauri/commit/d576e8ae72b025ca41f96ddf7a885b84f950a4b1) feat(core): do not follow redirects if `max_redirects` is 0 closes [#4795](https://www.github.com/tauri-apps/tauri/pull/4795) ([#4812](https://www.github.com/tauri-apps/tauri/pull/4812)) on 2022-07-31 - Added the `SystemTrayHandle::destroy` method. - [4d063ae9](https://www.github.com/tauri-apps/tauri/commit/4d063ae9ee9538cd6fa5e01b80070c6edf8eaeb9) feat(core): create system tray at runtime, closes [#2278](https://www.github.com/tauri-apps/tauri/pull/2278) ([#4862](https://www.github.com/tauri-apps/tauri/pull/4862)) on 2022-08-09 - Added `native-tls-vendored` and `reqwest-native-tls-vendored` Cargo features to compile and statically link to a vendored copy of OpenSSL on Linux. - [331f3460](https://www.github.com/tauri-apps/tauri/commit/331f3460027614738ddbbbbcd04bfc59a349f3de) feat(core): add option to use vendored openssl, closes [#4470](https://www.github.com/tauri-apps/tauri/pull/4470) ([#4809](https://www.github.com/tauri-apps/tauri/pull/4809)) on 2022-08-02 - Update windows to 0.39.0 and webview2-com to 0.19.1. - [e6d9b670](https://www.github.com/tauri-apps/tauri/commit/e6d9b670b0b314ed667b0e164f2c8d27048e678f) refactor: remove unneeded focus code ([#5065](https://www.github.com/tauri-apps/tauri/pull/5065)) on 2022-09-03 - Add `exists` function to the fs module. - [3c62dbc9](https://www.github.com/tauri-apps/tauri/commit/3c62dbc902c904d35a7472ce72a969084c95fbbe) feat(api): Add `exists` function to the fs module. ([#5060](https://www.github.com/tauri-apps/tauri/pull/5060)) on 2022-09-15 ## \[1.0.9] - Block remote URLs from accessing the IPC. - [fa90214b0](https://www.github.com/tauri-apps/tauri/commit/fa90214b052b1a5d38d54fbf1ca422b4c37cfd1f) feat(core): block remote URLs from accessing the IPC on 2023-04-12 ## \[1.0.8] - Fix the filesystem scope allowing sub-directories of the directory picked by the dialog when `recursive` option was `false`. - [f0602e7c](https://www.github.com/tauri-apps/tauri/commit/f0602e7c294245ab6ef6fbf2a976ef398340ef58) Merge pull request from GHSA-6mv3-wm7j-h4w5 on 2022-12-22 ## \[1.0.7] - Escape glob special characters in files/directories when dropping files or using the open/save dialogs. - [bcd9dc7f](https://www.github.com/tauri-apps/tauri/commit/bcd9dc7f859fa7e65fea5de835fa938ca1368eaf) fix(core): escape glob characters in drop/dialogs , closes [#5234](https://www.github.com/tauri-apps/tauri/pull/5234) ([#5237](https://www.github.com/tauri-apps/tauri/pull/5237)) on 2022-11-08 ## \[1.0.6] - Fix `fs.readDir` recursive option reading symlinked directories that are not allowed by the scope. - [bb178829](https://www.github.com/tauri-apps/tauri/commit/bb178829086e80916f9be190f02d83bc25802799) fix(endpoints/fs/readDir): don't read symlinks that are not allowed b… ([#5123](https://www.github.com/tauri-apps/tauri/pull/5123)) on 2022-09-08 ## \[1.0.5] - Escape the MSI file path when running msiexec via powershell. - [9af43134](https://www.github.com/tauri-apps/tauri/commit/9af43134e1e58369907281024d31bdb4d16ee6f6) fix(updater): escape MSI path ([#4737](https://www.github.com/tauri-apps/tauri/pull/4737)) on 2022-07-22 ## \[1.0.4] - Reduce the amount of allocations when converting cases. - [bc370e32](https://www.github.com/tauri-apps/tauri/commit/bc370e326810446e15b1f50fb962b980114ba16b) feat: reduce the amount of `heck`-related allocations ([#4634](https://www.github.com/tauri-apps/tauri/pull/4634)) on 2022-07-11 ## \[1.0.3] - `tauri::Builder` will now include a default menu for macOS without explicitly using `Menu::os_default`, you can still override it through `tauri::Builder::menu` or remove it using `tauri::Builder::enable_macos_default_menu(false)`. - [91055883](https://www.github.com/tauri-apps/tauri/commit/9105588373cc8401bd9ad79bdef26f509b2d76b7) feat: add implicit default menu for macOS only, closes [#4551](https://www.github.com/tauri-apps/tauri/pull/4551) ([#4570](https://www.github.com/tauri-apps/tauri/pull/4570)) on 2022-07-04 - Use `toString()` on message/confirm/ask dialogs title and message values. - [b8cd2a79](https://www.github.com/tauri-apps/tauri/commit/b8cd2a7993cd2aa5b71b30c545b3307245d254bf) feat(api): call `toString()` on dialog title and message, closes [#4583](https://www.github.com/tauri-apps/tauri/pull/4583) ([#4588](https://www.github.com/tauri-apps/tauri/pull/4588)) on 2022-07-04 - Fix stack overflow on Windows on commands by changing the implementation of the `async_runtime::spawn` method. - [7e3ac847](https://www.github.com/tauri-apps/tauri/commit/7e3ac8475cfa146f80e13cd4e3cdf82502018d9a) fix(core): command stack overflow on Windows, closes [#4548](https://www.github.com/tauri-apps/tauri/pull/4548) ([#4562](https://www.github.com/tauri-apps/tauri/pull/4562)) on 2022-07-03 - Emits RunEvent::Exit prior to killing child processes managed by Tauri, allowing graceful shutdown of sidecar binaries. - [34879f73](https://www.github.com/tauri-apps/tauri/commit/34879f73446e218fd08d0d079c086fa556a08b4e) fix: allow graceful shutdown of sidecar commands on exit ([#4561](https://www.github.com/tauri-apps/tauri/pull/4561)) on 2022-07-03 - Added option to disable tray menu on left click on macOS. - [f8a3becb](https://www.github.com/tauri-apps/tauri/commit/f8a3becb287942db7f7b551b5db6aeb5a2e939ee) feat(core): add option to disable tray menu on left click, closes [#4584](https://www.github.com/tauri-apps/tauri/pull/4584) ([#4587](https://www.github.com/tauri-apps/tauri/pull/4587)) on 2022-07-05 - Only run the updater default dialog mode in supported platforms or development mode. - [e29fff25](https://www.github.com/tauri-apps/tauri/commit/e29fff2566bf130e9f9cae432edba2f842607516) fix(updater): do not run in dialog mode on .deb, closes [#4573](https://www.github.com/tauri-apps/tauri/pull/4573) ([#4577](https://www.github.com/tauri-apps/tauri/pull/4577)) on 2022-07-05 - Configure the updater to relaunch after installing the update on Windows. - [0fa74534](https://www.github.com/tauri-apps/tauri/commit/0fa745344e0667434ebf3011a8b9fd776dfc5f59) feat(updater): relaunch on Windows, closes [#4220](https://www.github.com/tauri-apps/tauri/pull/4220) ([#4568](https://www.github.com/tauri-apps/tauri/pull/4568)) on 2022-07-03 ## \[1.0.2] - Fixes check for local URL when an external URL is provided to the window and it is based on the configured devPath. - [2e74d20e](https://www.github.com/tauri-apps/tauri/commit/2e74d20e834c0cb8c19fed25f8e7968f758ca8b1) fix(core): check whether external url is local, ref [#4449](https://www.github.com/tauri-apps/tauri/pull/4449) ([#4536](https://www.github.com/tauri-apps/tauri/pull/4536)) on 2022-06-30 ## \[1.0.1] - Added `fn new` constructors for `PhysicalSize`, `LogicalSize`, `PhysicalPosition` and `LogicalPosition` and missing conversion methods. - [c7d13a1c](https://www.github.com/tauri-apps/tauri/commit/c7d13a1c60cdbe0c42834ea059321d7a3a7f01a0) feat(core): add missing methods to the dpi module ([#4393](https://www.github.com/tauri-apps/tauri/pull/4393)) on 2022-06-19 - Set the bundle name and app metadata in the Info.plist file in development mode. - [38f5db6e](https://www.github.com/tauri-apps/tauri/commit/38f5db6e6a8b496b50d486db6fd8204266de3a69) feat(codegen): fill app metadata in development Info.plist on 2022-06-21 - Set the application icon in development mode on macOS. - [307c2ebf](https://www.github.com/tauri-apps/tauri/commit/307c2ebfb68238dacab6088f9c6ba310c727c68c) feat(core): set macOS app icon in development ([#4385](https://www.github.com/tauri-apps/tauri/pull/4385)) on 2022-06-19 - Fixes the error message when using the `window.unminimize` API without enabling it in the allowlist. - [cbceb7d6](https://www.github.com/tauri-apps/tauri/commit/cbceb7d6cf7c9ee8c093e81d8569285ef3ca5fe3) fix: some typos ([#4403](https://www.github.com/tauri-apps/tauri/pull/4403)) on 2022-06-19 - Initialize Tauri script when `devPath` is an external URL with path. - [079b1cc0](https://www.github.com/tauri-apps/tauri/commit/079b1cc06e1e5437686bac9049d5ac569c3f42df) fix(core): properly get external URL origin, closes [#4414](https://www.github.com/tauri-apps/tauri/pull/4414) ([#4417](https://www.github.com/tauri-apps/tauri/pull/4417)) on 2022-06-21 - Fixes deadlock when a plugin window ready event needs to block the thread waiting on the event loop. - [9d33d093](https://www.github.com/tauri-apps/tauri/commit/9d33d09341fd995740149f92387b88120e33dcad) fix(core): deadlock on plugin webview ready hook ([#4462](https://www.github.com/tauri-apps/tauri/pull/4462)) on 2022-06-24 - Adjust the updater to fallback to `$HOME/.cache` or the current working directory as temp directory if the system default is in a different mount point. - [fd125f76](https://www.github.com/tauri-apps/tauri/commit/fd125f76d768099dc3d4b2d4114349ffc31ffac9) fix(updater): fallback if tmp is on different mount point, closes [#4500](https://www.github.com/tauri-apps/tauri/pull/4500) ([#4504](https://www.github.com/tauri-apps/tauri/pull/4504)) on 2022-06-28 - Properly fill the origin window when using `emit_to` and `emit_all` from `Window`. - [643ae846](https://www.github.com/tauri-apps/tauri/commit/643ae846d86108b00cec748cd02a307b5badba18) fix: fire window-specific event on Window emit_to/emit_all, closes [#4493](https://www.github.com/tauri-apps/tauri/pull/4493) ([#4498](https://www.github.com/tauri-apps/tauri/pull/4498)) on 2022-06-28 - Implement `raw_window_handle::HasRawWindowHandle` on Linux. - [3efbc67f](https://www.github.com/tauri-apps/tauri/commit/3efbc67f7469ce65a2d9ea4ff2b60b51d2a36aa5) feat: implement `raw_window_handle` on Linux ([#4469](https://www.github.com/tauri-apps/tauri/pull/4469)) on 2022-06-26 - Added `on_drop` hook to the `plugin::Builder`. - [be4bb391](https://www.github.com/tauri-apps/tauri/commit/be4bb391a9bcd76dd949c001b1ace11684a8c6dc) feat: add `AppHandle::remove_plugin` and plugin `on_drop`, closes [#4361](https://www.github.com/tauri-apps/tauri/pull/4361) ([#4443](https://www.github.com/tauri-apps/tauri/pull/4443)) on 2022-06-23 - Refactored the `tauri-runtime-wry` plugin interface. - [e39e2999](https://www.github.com/tauri-apps/tauri/commit/e39e2999e0ab1843a8195ba83aea3d6de705c3d8) refactor(tauri-runtime-wry): enhance plugin interface ([#4476](https://www.github.com/tauri-apps/tauri/pull/4476)) on 2022-06-27 - Added `AppHandle::remove_plugin`. - [be4bb391](https://www.github.com/tauri-apps/tauri/commit/be4bb391a9bcd76dd949c001b1ace11684a8c6dc) feat: add `AppHandle::remove_plugin` and plugin `on_drop`, closes [#4361](https://www.github.com/tauri-apps/tauri/pull/4361) ([#4443](https://www.github.com/tauri-apps/tauri/pull/4443)) on 2022-06-23 - The theme API is now implemented on macOS 10.14+. - [6d94ce42](https://www.github.com/tauri-apps/tauri/commit/6d94ce42353204a02fe9c82ed397d349439f75ef) feat(core): theme is now implemented on macOS ([#4380](https://www.github.com/tauri-apps/tauri/pull/4380)) on 2022-06-17 - Suppress unused variable warning in release builds. - [45981851](https://www.github.com/tauri-apps/tauri/commit/45981851e35119266c1a079e1ff27a39f1fdfaed) chore(lint): unused variable warnings for release builds ([#4411](https://www.github.com/tauri-apps/tauri/pull/4411)) on 2022-06-22 - Update tao to 0.12 and wry to 0.19. - [f6edc6df](https://www.github.com/tauri-apps/tauri/commit/f6edc6df29b1c45b483fa87c481a3b95730b131b) chore(deps): update tao to 0.12, wry to 0.19, closes [#3220](https://www.github.com/tauri-apps/tauri/pull/3220) ([#4502](https://www.github.com/tauri-apps/tauri/pull/4502)) on 2022-06-28 - Added `Notification::notify` API behind the `windows7-compat` Cargo feature, which includes Windows 7 support. - [57039fb2](https://www.github.com/tauri-apps/tauri/commit/57039fb2166571de85271b014a8711a29f06be1a) fix(core): add windows 7 notification support ([#4491](https://www.github.com/tauri-apps/tauri/pull/4491)) on 2022-06-28 ## \[1.0.0] - Allow choosing multiple folders in `dialog.open`. - [4e51dce6](https://www.github.com/tauri-apps/tauri/commit/4e51dce6ca21c7664de779bc78a04be1051371f7) fix: dialog open supports multiple dirs, fixes [#4091](https://www.github.com/tauri-apps/tauri/pull/4091) ([#4354](https://www.github.com/tauri-apps/tauri/pull/4354)) on 2022-06-15 - Upgrade to `stable`! - [f4bb30cc](https://www.github.com/tauri-apps/tauri/commit/f4bb30cc73d6ba9b9ef19ef004dc5e8e6bb901d3) feat(covector): prepare for v1 ([#4351](https://www.github.com/tauri-apps/tauri/pull/4351)) on 2022-06-15 ## \[1.0.0-rc.17] - Add `Menu::os_default` which will create a menu filled with default menu items and submenus. - [4c4acc30](https://www.github.com/tauri-apps/tauri/commit/4c4acc3094218dd9cee0f1ad61810c979e0b41fa) feat: implement `Default` for `Menu`, closes [#2398](https://www.github.com/tauri-apps/tauri/pull/2398) ([#4291](https://www.github.com/tauri-apps/tauri/pull/4291)) on 2022-06-15 ## \[1.0.0-rc.16] - **Breaking change:** The `TrayIcon` enum has been removed and now `Icon` is used instead. This allows you to use more image formats and use embedded icons on Linux. - [4ce8e228](https://www.github.com/tauri-apps/tauri/commit/4ce8e228134cd3f22973b74ef26ca0d165fbbbd9) refactor(core): use `Icon` for tray icons ([#4342](https://www.github.com/tauri-apps/tauri/pull/4342)) on 2022-06-14 ## \[1.0.0-rc.15] - Fixes filesystem scope check when using the HTTP API to upload files. - [8ce5b762](https://www.github.com/tauri-apps/tauri/commit/8ce5b7626478db5c4767e894d005fafb79aa5a7f) fix: scope check when using the HTTP API to upload files closes [#4312](https://www.github.com/tauri-apps/tauri/pull/4312) on 2022-06-10 - Fixes a memory leak in the command system. - [f72cace3](https://www.github.com/tauri-apps/tauri/commit/f72cace36821dc675a6d25268ae85a21bdbd6296) fix: never remove ipc callback & mem never be released ([#4274](https://www.github.com/tauri-apps/tauri/pull/4274)) on 2022-06-05 - Fixes the `Content-Type` header value when sending multipart requests using the `reqwest-client` feature. - [f6205afc](https://www.github.com/tauri-apps/tauri/commit/f6205afc0d0e419ecb56b9b6b04bd0a0cc9f62ca) fix(core): wrong Content-Type when using reqwest's multipart, ref [#4312](https://www.github.com/tauri-apps/tauri/pull/4312) on 2022-06-10 - Kill sidecar processes on app exit even when only the `shell-sidecar` feature is enabled. - [6ba91272](https://www.github.com/tauri-apps/tauri/commit/6ba9127298632531b64d2831bccec6d22ef6c874) Fix: sidecar cleanup when only `shell-sidecar` is enabled ([#4254](https://www.github.com/tauri-apps/tauri/pull/4254)) on 2022-06-04 - Fixes a crash when a request is made to `https://tauri.$URL` on Windows where `$URL` is not `localhost/**` e.g. `https://tauri.app`. - [74457222](https://www.github.com/tauri-apps/tauri/commit/74457222b47221f08388f528a7d52133b6734af6) fix(core): handle requests to `https://tauri.*` on Windows ([#4270](https://www.github.com/tauri-apps/tauri/pull/4270)) on 2022-06-05 - Set notification icon to app icon on Linux. - [235e448d](https://www.github.com/tauri-apps/tauri/commit/235e448defd8271739804d9b005ffee9c149dd8e) fix: add a default icon to notifications on linux ([#4283](https://www.github.com/tauri-apps/tauri/pull/4283)) on 2022-06-09 - **Breaking change:** Revert the window creation to be blocking in the main thread. This ensures the window is created before using other methods, but has an issue on Windows where the program deadlocks when creating a window in a Tauri command if it is not `async`. The documentation now states that commands must be `async` in other to prevent it until the issue is fixed in Webview2. - [69ae6f14](https://www.github.com/tauri-apps/tauri/commit/69ae6f14943f94285f4279c3a92f9003f74aacff) refactor(window): block main thread when creating a new window ([#4298](https://www.github.com/tauri-apps/tauri/pull/4298)) on 2022-06-08 - No longer ask for permission to send notifications and always allow it. - [f482b094](https://www.github.com/tauri-apps/tauri/commit/f482b0942276e9402ab3725957535039bacb4fef) fix: remove notification permission prompt ([#4302](https://www.github.com/tauri-apps/tauri/pull/4302)) on 2022-06-09 - **Breaking change:** Removed the `settings` module. - [f482b094](https://www.github.com/tauri-apps/tauri/commit/f482b0942276e9402ab3725957535039bacb4fef) fix: remove notification permission prompt ([#4302](https://www.github.com/tauri-apps/tauri/pull/4302)) on 2022-06-09 - **Breaking change**: Removed the `gtk-tray` and `ayatana-tray` Cargo features. - [6216eb49](https://www.github.com/tauri-apps/tauri/commit/6216eb49e72863bfb6d4c9edb8827b21406ac393) refactor(core): drop `ayatana-tray` and `gtk-tray` Cargo features ([#4247](https://www.github.com/tauri-apps/tauri/pull/4247)) on 2022-06-02 - Call `preventDefault()` in the mousedown event handler for `[data-tauri-drag-region]` elements. - [a0e20621](https://www.github.com/tauri-apps/tauri/commit/a0e20621f5369682700daa234ec1f4df0c3c4d28) fix: preventDefault mousedown on data-tauri-drag-region, closes [#4059](https://www.github.com/tauri-apps/tauri/pull/4059) on 2022-06-13 - Set permission to `0o700` for the tmp folder used to move the current AppImage on the updater process. - [b77877fd](https://www.github.com/tauri-apps/tauri/commit/b77877fd2c643c810659fd059cb1bca5b2c68238) fix(updater): set tmp folder permissions ([#4311](https://www.github.com/tauri-apps/tauri/pull/4311)) on 2022-06-12 ## \[1.0.0-rc.14] - **Breaking change:** `PackageInfo::version` is now a `semver::Version` instead of a `String`. - [2badbd2d](https://www.github.com/tauri-apps/tauri/commit/2badbd2d7ed51bf33c1b547b4c837b600574bd4a) refactor: force semver versions, change updater `should_install` sig ([#4215](https://www.github.com/tauri-apps/tauri/pull/4215)) on 2022-05-25 - [a7388e23](https://www.github.com/tauri-apps/tauri/commit/a7388e23c3b9019d48b078cae00a75c74d74d11b) fix(ci): adjust change file to include tauri-utils and tauri-codegen on 2022-05-27 - **Breaking change**: `UpdateBuilder::should_update` now takes the current version as a `semver::Version` and a `RemoteRelease` struct, allowing you to check other release fields. - [2badbd2d](https://www.github.com/tauri-apps/tauri/commit/2badbd2d7ed51bf33c1b547b4c837b600574bd4a) refactor: force semver versions, change updater `should_install` sig ([#4215](https://www.github.com/tauri-apps/tauri/pull/4215)) on 2022-05-25 - **Breaking change:** The `tauri::UpdaterEvent::UpdateEvent` date field is now an `Option`. - [ac7656ab](https://www.github.com/tauri-apps/tauri/commit/ac7656ab19ebeda1955698ff7a16199d7055d640) refactor(updater): strong type for the `pub_date` field, ref [#4162](https://www.github.com/tauri-apps/tauri/pull/4162) ([#4218](https://www.github.com/tauri-apps/tauri/pull/4218)) on 2022-05-25 - **Breaking change:** The updater response `pub_date` now must be a valid RFC 3339 string. - [ac7656ab](https://www.github.com/tauri-apps/tauri/commit/ac7656ab19ebeda1955698ff7a16199d7055d640) refactor(updater): strong type for the `pub_date` field, ref [#4162](https://www.github.com/tauri-apps/tauri/pull/4162) ([#4218](https://www.github.com/tauri-apps/tauri/pull/4218)) on 2022-05-25 ## \[1.0.0-rc.13] - Fix `` cannot find macro `message_dialog` `` error. - [80458a03](https://www.github.com/tauri-apps/tauri/commit/80458a031b15c83019f11a6c222a2993e16d5dc3) Fix `message_dialog` flag ([#4204](https://www.github.com/tauri-apps/tauri/pull/4204)) on 2022-05-25 ## \[1.0.0-rc.12] - Expose option to set the dialog type. - [f46175d5](https://www.github.com/tauri-apps/tauri/commit/f46175d5d46fa3eae66ad2415a0eb1efb7d31da2) feat(core): expose option to set dialog type, closes [#4183](https://www.github.com/tauri-apps/tauri/pull/4183) ([#4187](https://www.github.com/tauri-apps/tauri/pull/4187)) on 2022-05-21 - Expose `title` option in the message dialog API. - [ae99f991](https://www.github.com/tauri-apps/tauri/commit/ae99f991674d77c322a2240d10ed4b78ed2f4d4b) feat(core): expose message dialog's title option, ref [#4183](https://www.github.com/tauri-apps/tauri/pull/4183) ([#4186](https://www.github.com/tauri-apps/tauri/pull/4186)) on 2022-05-21 - Immediately create windows when using `tauri::App` as manager. - [52d17754](https://www.github.com/tauri-apps/tauri/commit/52d177543ab5d0b316628ef30c2a32f303bc451d) fix(core): immediately create window when using tauri::App, closes [#4170](https://www.github.com/tauri-apps/tauri/pull/4170) ([#4172](https://www.github.com/tauri-apps/tauri/pull/4172)) on 2022-05-21 - Account the monitor position when centering a window. - [a7a9fde1](https://www.github.com/tauri-apps/tauri/commit/a7a9fde16fb7c35d48d4f97e83ff95b8baf9e090) fix(core): account for monitor position when centering window ([#4166](https://www.github.com/tauri-apps/tauri/pull/4166)) on 2022-05-21 - Allow the canonical, absolute form of a path for the filesystem scope on Windows if `std::fs::canonicalize` returns a path, fallback to `\\?\$PATH`. - [78f2565e](https://www.github.com/tauri-apps/tauri/commit/78f2565e14a5a8292045200967a36d6a40899721) fix: allow return value of fs::canonicalize on fs scope, closes [#4130](https://www.github.com/tauri-apps/tauri/pull/4130) ([#4188](https://www.github.com/tauri-apps/tauri/pull/4188)) on 2022-05-21 - Fixes updater documentation not showing on docs.rs. - [55892c35](https://www.github.com/tauri-apps/tauri/commit/55892c35f5c60836a8b7244e1660a83a01a4bc37) fix(core): updater documentation not showing on docs.rs ([#4190](https://www.github.com/tauri-apps/tauri/pull/4190)) on 2022-05-22 - Fixes HTTP timeout not working on Windows when using the `attohttpc` client. - [d99c5d58](https://www.github.com/tauri-apps/tauri/commit/d99c5d583bdb1429966283cc5cd4a977cf0770b2) fix(core): HTTP timeout not working on Windows, closes [#4050](https://www.github.com/tauri-apps/tauri/pull/4050) ([#4185](https://www.github.com/tauri-apps/tauri/pull/4185)) on 2022-05-21 - Update `windows-rs` to `0.37.0`, which requires Rust 1.61.0+. - [2326be39](https://www.github.com/tauri-apps/tauri/commit/2326be39821890cdd4de76e7029a531424dcb26f) feat(core): update windows-rs to 0.37.0 ([#4199](https://www.github.com/tauri-apps/tauri/pull/4199)) on 2022-05-24 - **Breaking change:** The `WindowBuilder` struct now has a lifetime annotation `WindowBuilder`. - [52d17754](https://www.github.com/tauri-apps/tauri/commit/52d177543ab5d0b316628ef30c2a32f303bc451d) fix(core): immediately create window when using tauri::App, closes [#4170](https://www.github.com/tauri-apps/tauri/pull/4170) ([#4172](https://www.github.com/tauri-apps/tauri/pull/4172)) on 2022-05-21 ## \[1.0.0-rc.11] - Added the `App::get_cli_matches` helper function. - [617f1144](https://www.github.com/tauri-apps/tauri/commit/617f1144f3f5c4a88e229ff410a511aa72795eef) feat(core): add `App::get_cli_matches` helper ref [#4145](https://www.github.com/tauri-apps/tauri/pull/4145) on 2022-05-17 - Fixes `fileDropEnabled` option not working. - [706fcbd3](https://www.github.com/tauri-apps/tauri/commit/706fcbd39c9c08f58da12f874199bd0c06016fb2) fix(core): fileDropEnabled option is not working when creating a new WebviewWindow ([#4146](https://www.github.com/tauri-apps/tauri/pull/4146)) on 2022-05-18 - Prepare window icon and menu even when loading remote URLs. Previously it was behind a `is local URL?` condition. - [25aa4347](https://www.github.com/tauri-apps/tauri/commit/25aa4347b3a85c66d445e09f864b7fe6c140a0f9) fix(core): prepare window icon and menu on remote URLs, closes [#4131](https://www.github.com/tauri-apps/tauri/pull/4131) ([#4140](https://www.github.com/tauri-apps/tauri/pull/4140)) on 2022-05-16 - Fix `.mjs` not being recognised as a file extension for JavaScript files (`text/javascript`). - [45c45253](https://www.github.com/tauri-apps/tauri/commit/45c45253866ce0de317a6a547af3ea0434d4bcac) fix: add mjs mime type (fix: [#4098](https://www.github.com/tauri-apps/tauri/pull/4098)) ([#4108](https://www.github.com/tauri-apps/tauri/pull/4108)) on 2022-05-13 - Added `PathResolver::resolve_resource` API. - [e35aaebc](https://www.github.com/tauri-apps/tauri/commit/e35aaebc309f5796cf6f380d1ac7d5a8094b9033) feat(core): add `PathResolver::resolve_resource` API ([#4116](https://www.github.com/tauri-apps/tauri/pull/4116)) on 2022-05-13 - Allow configuring the display options for the MSI execution allowing quieter updates. - [9f2c3413](https://www.github.com/tauri-apps/tauri/commit/9f2c34131952ea83c3f8e383bc3cec7e1450429f) feat(core): configure msiexec display options, closes [#3951](https://www.github.com/tauri-apps/tauri/pull/3951) ([#4061](https://www.github.com/tauri-apps/tauri/pull/4061)) on 2022-05-15 ## \[1.0.0-rc.10] - Update wry to 0.16.2 and webkit2gtk to 0.18.0. - [71a553b7](https://www.github.com/tauri-apps/tauri/commit/71a553b715312e2bcceb963c83e42cffca7a63bc) chore(deps): update wry to 0.16.2, webkit2gtk to 0.18.0 ([#4099](https://www.github.com/tauri-apps/tauri/pull/4099)) on 2022-05-10 - Adds the `App#wry_plugin` API to inject a plugin for the wry integration. - [c8e0e5b9](https://www.github.com/tauri-apps/tauri/commit/c8e0e5b97d542e549b37be08b545515c862af0e5) feat(tauri-runtime-wry): add plugin API ([#4094](https://www.github.com/tauri-apps/tauri/pull/4094)) on 2022-05-10 ## \[1.0.0-rc.9] - The `dangerous_allow_asset_csp_modification` configuration value has been changed to allow a list of CSP directives to disable. - [164078c0](https://www.github.com/tauri-apps/tauri/commit/164078c0b719ccbc12e956fecf8a7d4a3c5044e1) feat: allow limiting dangerousDisableAssetCspModification, closes [#3831](https://www.github.com/tauri-apps/tauri/pull/3831) ([#4021](https://www.github.com/tauri-apps/tauri/pull/4021)) on 2022-05-02 - The file drop event payloads are now percent-decoded. - [a0ecd81a](https://www.github.com/tauri-apps/tauri/commit/a0ecd81a934e1aa8935151a74cad686786054204) fix(core): percent decode file drop payloads, closes [#4034](https://www.github.com/tauri-apps/tauri/pull/4034) ([#4035](https://www.github.com/tauri-apps/tauri/pull/4035)) on 2022-05-03 - Fix dialog crash on macOS when the `default_path` value is just the file name. - [d31167c5](https://www.github.com/tauri-apps/tauri/commit/d31167c520e4e5ea5c75518c180574f5fffc1a40) fix(core): dialog crashing on macOS when the parent is empty ([#4028](https://www.github.com/tauri-apps/tauri/pull/4028)) on 2022-05-02 - Fixes the `title` option being ignored in the dialog API endpoints. - [220e7460](https://www.github.com/tauri-apps/tauri/commit/220e7460148df476171579878c3cfffcdb1423d8) fix(core): set dialog title via API, closes [#4029](https://www.github.com/tauri-apps/tauri/pull/4029) ([#4030](https://www.github.com/tauri-apps/tauri/pull/4030)) on 2022-05-02 - Fixes nested isolation iframe injection. - [022eed46](https://www.github.com/tauri-apps/tauri/commit/022eed46675976e8dfe5f352a875754b4bd78131) fix(core): nested isolation iframes, closes [#4015](https://www.github.com/tauri-apps/tauri/pull/4015) ([#4020](https://www.github.com/tauri-apps/tauri/pull/4020)) on 2022-05-01 - Deserialize numeric values (seconds) in the http API `ClientBuilder.connect_timeout` and `HttpRequestBuilder.timeout` fields. - [f3c5ca89](https://www.github.com/tauri-apps/tauri/commit/f3c5ca89e79d429183c4e15a9e7cebada2b493a0) fix(core): http api `connect_timeout` deserialization, closes [#4004](https://www.github.com/tauri-apps/tauri/pull/4004) ([#4006](https://www.github.com/tauri-apps/tauri/pull/4006)) on 2022-04-29 - Fix updater dialog removing single and double quotes from the release notes - [0180dcc8](https://www.github.com/tauri-apps/tauri/commit/0180dcc812bacb78822bc0f97a3202633821dbce) fix(updater): remove single\&double quotes escaping in updater dialog … ([#4047](https://www.github.com/tauri-apps/tauri/pull/4047)) on 2022-05-04 - Expose methods to access the underlying native handles of the webview. - [c82b4761](https://www.github.com/tauri-apps/tauri/commit/c82b4761e1660592472dc55308ad69d9efc5855b) feat(core): expose `with_webview` API to access the platform webview ([#4058](https://www.github.com/tauri-apps/tauri/pull/4058)) on 2022-05-04 ## \[1.0.0-rc.8] - **Breaking change:** Removed the `ayatana-tray` from the default features. You must select one of `ayatana-tray` and `gtk-tray` to use system tray on Linux. - [62cdb2b3](https://www.github.com/tauri-apps/tauri/commit/62cdb2b307534cf1cb69fdb8688f7c0f3176f41b) refactor(tauri): remove ayatana-tray from the default features ([#3976](https://www.github.com/tauri-apps/tauri/pull/3976)) on 2022-04-26 - Re-export the `GlobalShortcutManager` when the `global-shortcut` feature is enabled. - [62cdb2b3](https://www.github.com/tauri-apps/tauri/commit/62cdb2b307534cf1cb69fdb8688f7c0f3176f41b) refactor(tauri): remove ayatana-tray from the default features ([#3976](https://www.github.com/tauri-apps/tauri/pull/3976)) on 2022-04-26 - Fixes `docs.rs` documentation build. - [dd94917b](https://www.github.com/tauri-apps/tauri/commit/dd94917b619f22849a7487805315c5306e4847b8) fix(tauri): docs.rs build error ([#3974](https://www.github.com/tauri-apps/tauri/pull/3974)) on 2022-04-26 ## \[1.0.0-rc.7] - **Breaking change:** Removed `tauri::api::file::ArchiveFormat::Plain`. - [f7d3d93b](https://www.github.com/tauri-apps/tauri/commit/f7d3d93b625ffc8bccf8068793f44af2f9a4f997) refactor(core): improve performance of the `extract` API ([#3963](https://www.github.com/tauri-apps/tauri/pull/3963)) on 2022-04-25 - Fallback to `{path}.html` when `{path}` is not found in the Tauri custom protocol handler. - [7864d41d](https://www.github.com/tauri-apps/tauri/commit/7864d41de8650f20fa73cefbddd78381b9d8aa11) feat(core): fallback to `{path}.html` in Tauri protocol loader ref [#3887](https://www.github.com/tauri-apps/tauri/pull/3887) ([#3939](https://www.github.com/tauri-apps/tauri/pull/3939)) on 2022-04-21 - **Breaking change:** Use ayatana-appindicator for Linux system tray by default. Use the `gtk-tray` Cargo feature to use `libappindicator` instead. - [f2a30d8b](https://www.github.com/tauri-apps/tauri/commit/f2a30d8bc54fc3ba49e16f69a413eca5f61a9b1f) refactor(core): use ayatana appindicator by default, keep option to use gtk ([#3916](https://www.github.com/tauri-apps/tauri/pull/3916)) on 2022-04-19 - Reduce the amount of generated code for the API endpoints. - [c23f139b](https://www.github.com/tauri-apps/tauri/commit/c23f139ba86628fe0217a966bc8676afe7202a05) perf(core): improve binary size with api enum serde refactor ([#3952](https://www.github.com/tauri-apps/tauri/pull/3952)) on 2022-04-24 - \**Breaking change::* Added the `clipboard` Cargo feature. - [24e4ff20](https://www.github.com/tauri-apps/tauri/commit/24e4ff208ee0fe1a4cc5b10667ea0922ac63dfb5) refactor(core): add clipboard Cargo feature, enhancing binary size ([#3957](https://www.github.com/tauri-apps/tauri/pull/3957)) on 2022-04-24 - **Breaking change:** The process Command API stdio lines now includes the trailing `\r`. - [b5622882](https://www.github.com/tauri-apps/tauri/commit/b5622882cf3748e1e5a90915f415c0cd922aaaf8) fix(cli): exit on non-compilation Cargo errors, closes [#3930](https://www.github.com/tauri-apps/tauri/pull/3930) ([#3942](https://www.github.com/tauri-apps/tauri/pull/3942)) on 2022-04-22 - Expose Window cursor APIs `set_cursor_grab`, `set_cursor_visible`, `set_cursor_icon` and `set_cursor_position`. - [c54ddfe9](https://www.github.com/tauri-apps/tauri/commit/c54ddfe9338e7eb90b4d5b02dfde687d432d5bc1) feat: expose window cursor APIs, closes [#3888](https://www.github.com/tauri-apps/tauri/pull/3888) [#3890](https://www.github.com/tauri-apps/tauri/pull/3890) ([#3935](https://www.github.com/tauri-apps/tauri/pull/3935)) on 2022-04-21 - **Breaking change:** The `tauri::api::file::Extract#extract_file` function has been moved to `tauri::api::file::Entry#extract`. - [f7d3d93b](https://www.github.com/tauri-apps/tauri/commit/f7d3d93b625ffc8bccf8068793f44af2f9a4f997) refactor(core): improve performance of the `extract` API ([#3963](https://www.github.com/tauri-apps/tauri/pull/3963)) on 2022-04-25 - **Breaking change:** The `tauri::api::file::Extract#files` function has been renamed to `with_files` for performance reasons. - [f7d3d93b](https://www.github.com/tauri-apps/tauri/commit/f7d3d93b625ffc8bccf8068793f44af2f9a4f997) refactor(core): improve performance of the `extract` API ([#3963](https://www.github.com/tauri-apps/tauri/pull/3963)) on 2022-04-25 - Improved the performance of the `tauri::api::fs::Extract` API. - [f7d3d93b](https://www.github.com/tauri-apps/tauri/commit/f7d3d93b625ffc8bccf8068793f44af2f9a4f997) refactor(core): improve performance of the `extract` API ([#3963](https://www.github.com/tauri-apps/tauri/pull/3963)) on 2022-04-25 - Fixes a panic when using the `create_tao_window` API. - [320329a9](https://www.github.com/tauri-apps/tauri/commit/320329a9a7d8a249c0fc9dee6db5669057ca8b39) fix(core): insert to webview_id_map on tao window creation, closes [#3883](https://www.github.com/tauri-apps/tauri/pull/3883) ([#3932](https://www.github.com/tauri-apps/tauri/pull/3932)) on 2022-04-21 - Fixes the HTTP API form text fields. - [cc356084](https://www.github.com/tauri-apps/tauri/commit/cc35608430b47101255b93ae2f58dfd15e1297d3) fix(core): do not serialize strings in http api form, closes [#3910](https://www.github.com/tauri-apps/tauri/pull/3910) ([#3928](https://www.github.com/tauri-apps/tauri/pull/3928)) on 2022-04-20 - Set the application bundle identifier for the notifications on macOS. - [f67ae6bd](https://www.github.com/tauri-apps/tauri/commit/f67ae6bd6052d5bc30305ecaa3b83d071da3cfca) fix(core): set bundle id for notifications on macOS ([#3839](https://www.github.com/tauri-apps/tauri/pull/3839)) on 2022-04-01 - Fixes a panic when a menu event is triggered when all windows are minimized on macOS. - [70ff55c1](https://www.github.com/tauri-apps/tauri/commit/70ff55c1aa69ed59cd2a78d865e1cb398ef2a4ba) fix(core): panic on menu event with minimized windows, closes [#3902](https://www.github.com/tauri-apps/tauri/pull/3902) ([#3918](https://www.github.com/tauri-apps/tauri/pull/3918)) on 2022-04-20 - Fixes a rendering issue when resizing the window with the devtools open. - [80b714af](https://www.github.com/tauri-apps/tauri/commit/80b714af6b31365b9026bc92f8631b1721950447) fix: rendering issue when resizing with devtools open closes [#3914](https://www.github.com/tauri-apps/tauri/pull/3914) [#3814](https://www.github.com/tauri-apps/tauri/pull/3814) ([#3915](https://www.github.com/tauri-apps/tauri/pull/3915)) on 2022-04-19 - Fixes the `WindowBuilder` export. - [985d2508](https://www.github.com/tauri-apps/tauri/commit/985d250898f07ebc975b579ea25555337947ab76) fix(tauri): export `WindowBuilder` struct instead of trait, closes [#3827](https://www.github.com/tauri-apps/tauri/pull/3827) ([#3833](https://www.github.com/tauri-apps/tauri/pull/3833)) on 2022-03-31 - The HTTP API now supports `multipart/form-data` requests. You need to set the `Content-Type` header and enable the `http-multipart` Cargo feature. - [1397d912](https://www.github.com/tauri-apps/tauri/commit/1397d9121aae8188bceceacae5565fbbeb67ddd9) feat(core): add support to multipart/form-data requests, closes [#2118](https://www.github.com/tauri-apps/tauri/pull/2118) ([#3929](https://www.github.com/tauri-apps/tauri/pull/3929)) on 2022-04-22 - \**Breaking change::* Added the `global-shortcut` Cargo feature. - [e11878bc](https://www.github.com/tauri-apps/tauri/commit/e11878bcf7174b261a1fa146fc7d564d12e6312a) refactor(core): add global-shortcut Cargo feature, enhancing binary size ([#3956](https://www.github.com/tauri-apps/tauri/pull/3956)) on 2022-04-24 - Added `tauri::api::http::HttpRequestBuilder#header` method. - [81705bb3](https://www.github.com/tauri-apps/tauri/commit/81705bb332623a53433c28d941ff00da1a6d50fa) feat(updater): add method to set request headers closes [#3896](https://www.github.com/tauri-apps/tauri/pull/3896) ([#3931](https://www.github.com/tauri-apps/tauri/pull/3931)) on 2022-04-22 - **Breaking change:** The `tauri::api::http::HttpRequestBuilder#headers` method now takes `header::HeaderMap` instead of a `HashMap`. - [81705bb3](https://www.github.com/tauri-apps/tauri/commit/81705bb332623a53433c28d941ff00da1a6d50fa) feat(updater): add method to set request headers closes [#3896](https://www.github.com/tauri-apps/tauri/pull/3896) ([#3931](https://www.github.com/tauri-apps/tauri/pull/3931)) on 2022-04-22 - **Breaking change:** The `tauri::api::http::Response#headers` method now returns `&header::HeaderMap` instead of `&HashMap`. - [81705bb3](https://www.github.com/tauri-apps/tauri/commit/81705bb332623a53433c28d941ff00da1a6d50fa) feat(updater): add method to set request headers closes [#3896](https://www.github.com/tauri-apps/tauri/pull/3896) ([#3931](https://www.github.com/tauri-apps/tauri/pull/3931)) on 2022-04-22 - **Breaking change:** The `api::http` timeouts are now represented as `std::time::Duration` instead of a `u64`. - [0ecfad59](https://www.github.com/tauri-apps/tauri/commit/0ecfad5924d7e19719812fd2e460e5242d8f352f) refactor(updater): unset request timeout, add builder setter ([#3847](https://www.github.com/tauri-apps/tauri/pull/3847)) on 2022-04-02 - **Breaking change:** The `tauri::api::http::FormPart::Bytes` enum variant has been renamed to `File` with a value object `{ file, mime, file_name }`. - [1397d912](https://www.github.com/tauri-apps/tauri/commit/1397d9121aae8188bceceacae5565fbbeb67ddd9) feat(core): add support to multipart/form-data requests, closes [#2118](https://www.github.com/tauri-apps/tauri/pull/2118) ([#3929](https://www.github.com/tauri-apps/tauri/pull/3929)) on 2022-04-22 - **Breaking change:** Removed `App::create_window`, `AppHandle::create_window`, `Builder::create_window` and `Window::create_window`. - [7c7d854a](https://www.github.com/tauri-apps/tauri/commit/7c7d854ab9183d3f78bafd9027f0304d84abe159) refactor(core): remove deprecated APIs ([#3834](https://www.github.com/tauri-apps/tauri/pull/3834)) on 2022-04-01 - **Breaking change:** Removed `tauri::api::http::FormPart::File`. - [cc356084](https://www.github.com/tauri-apps/tauri/commit/cc35608430b47101255b93ae2f58dfd15e1297d3) fix(core): do not serialize strings in http api form, closes [#3910](https://www.github.com/tauri-apps/tauri/pull/3910) ([#3928](https://www.github.com/tauri-apps/tauri/pull/3928)) on 2022-04-20 - Added `WindowEvent::ThemeChanged(theme)`. - [4cebcf6d](https://www.github.com/tauri-apps/tauri/commit/4cebcf6da7cad1953e0f01b426afac3b5ef1f81e) feat: expose theme APIs, closes [#3903](https://www.github.com/tauri-apps/tauri/pull/3903) ([#3937](https://www.github.com/tauri-apps/tauri/pull/3937)) on 2022-04-21 - Added `theme` getter on `Window`. - [4cebcf6d](https://www.github.com/tauri-apps/tauri/commit/4cebcf6da7cad1953e0f01b426afac3b5ef1f81e) feat: expose theme APIs, closes [#3903](https://www.github.com/tauri-apps/tauri/pull/3903) ([#3937](https://www.github.com/tauri-apps/tauri/pull/3937)) on 2022-04-21 - Added `UpdateResponse::body` and `UpdateResponse::date`. - [c7696f34](https://www.github.com/tauri-apps/tauri/commit/c7696f34ecb7baa0da583736e727f74a01f5996a) feat(updater): add `body` and `date` getters ([#3802](https://www.github.com/tauri-apps/tauri/pull/3802)) on 2022-03-29 - **Breaking change**: Removed the `tauri::updater::Error::UnsupportedPlatform` variant and added `UnsupportedLinuxPackage`, `UnsupportedOs` and `UnsupportedArch` for better error information. - [ed716793](https://www.github.com/tauri-apps/tauri/commit/ed71679368845f603680465fdffcc90fe842bb8c) refactor(updater): improve unsupported error variants, closes [#3817](https://www.github.com/tauri-apps/tauri/pull/3817) ([#3849](https://www.github.com/tauri-apps/tauri/pull/3849)) on 2022-04-05 - Add updater `Downloaded` status event. - [9712ed1a](https://www.github.com/tauri-apps/tauri/commit/9712ed1a6893438270e99cfecbc7968b68716cba) feat(updater): add `Downloaded` status event ([#3804](https://www.github.com/tauri-apps/tauri/pull/3804)) on 2022-04-01 - Allow setting app updater request headers via `AppHandle::updater().header()`. - [81705bb3](https://www.github.com/tauri-apps/tauri/commit/81705bb332623a53433c28d941ff00da1a6d50fa) feat(updater): add method to set request headers closes [#3896](https://www.github.com/tauri-apps/tauri/pull/3896) ([#3931](https://www.github.com/tauri-apps/tauri/pull/3931)) on 2022-04-22 - The updater default timeout is now unset, and the `UpdateBuilder` has a `timeout` setter. - [0ecfad59](https://www.github.com/tauri-apps/tauri/commit/0ecfad5924d7e19719812fd2e460e5242d8f352f) refactor(updater): unset request timeout, add builder setter ([#3847](https://www.github.com/tauri-apps/tauri/pull/3847)) on 2022-04-02 - Added `theme` setter to the WindowBuilder. - [4cebcf6d](https://www.github.com/tauri-apps/tauri/commit/4cebcf6da7cad1953e0f01b426afac3b5ef1f81e) feat: expose theme APIs, closes [#3903](https://www.github.com/tauri-apps/tauri/pull/3903) ([#3937](https://www.github.com/tauri-apps/tauri/pull/3937)) on 2022-04-21 ## \[1.0.0-rc.6] - Fixes the `WindowEvent` type used on `Window::on_window_event`. - [06aa87b6](https://www.github.com/tauri-apps/tauri/commit/06aa87b65f4608ded0dc312d526e83065618a1c8) fix(core): `WindowEvent` type used on `Window::on_window_event` ([#3796](https://www.github.com/tauri-apps/tauri/pull/3796)) on 2022-03-28 - Fixes `WindowEvent::Destroyed` not firing. - [169b5035](https://www.github.com/tauri-apps/tauri/commit/169b5035a93e3f33a420d4b2b0f8943e6404e07f) fix(core): actually fire `WindowEvent::Destroyed` ([#3797](https://www.github.com/tauri-apps/tauri/pull/3797)) on 2022-03-28 ## \[1.0.0-rc.5] - Added `updater_target` method to the `Builder` struct. - [579312f8](https://www.github.com/tauri-apps/tauri/commit/579312f834f08dca15e51e4f43c1d0bb65b54a51) feat(updater): separate intel and apple silicon targets, closes [#3359](https://www.github.com/tauri-apps/tauri/pull/3359) ([#3739](https://www.github.com/tauri-apps/tauri/pull/3739)) on 2022-03-23 - Added an option to disable the CSP injection of distributable assets nonces and hashes. - [f6e32ee1](https://www.github.com/tauri-apps/tauri/commit/f6e32ee1880eb364ed76beb937c9d12e14d54910) feat(core): add dangerous option to disable compile time CSP injection ([#3775](https://www.github.com/tauri-apps/tauri/pull/3775)) on 2022-03-28 - Toggle devtools when `Ctrl + Shift + I` or `Command + Option + I` is pressed. - [e05d718a](https://www.github.com/tauri-apps/tauri/commit/e05d718a7b46476d1fe4817c169008080e84f959) feat(core): add hotkey to toggle devtools, closes [#3776](https://www.github.com/tauri-apps/tauri/pull/3776) ([#3791](https://www.github.com/tauri-apps/tauri/pull/3791)) on 2022-03-28 - Use asynchronous file dialog on macOS and Windows to properly set the parent window. - [bf89a05f](https://www.github.com/tauri-apps/tauri/commit/bf89a05fcfef976886a833b24346e010fd1bd06c) fix(core): dialog parent window on macOS, closes [#3312](https://www.github.com/tauri-apps/tauri/pull/3312) ([#3753](https://www.github.com/tauri-apps/tauri/pull/3753)) on 2022-03-23 - The `Error` enum is now `Send + Sync`. - [da1e8793](https://www.github.com/tauri-apps/tauri/commit/da1e879358895f7b190b1c1b20d23da23666a74b) feat(core): improve and cleanup the `Error` enum ([#3748](https://www.github.com/tauri-apps/tauri/pull/3748)) on 2022-03-22 - Do not allow path traversal on the asset protocol. - [34a402f9](https://www.github.com/tauri-apps/tauri/commit/34a402f9b559af377b276d73b800e5e8b7dacbb1) fix(core): do not allow path traversal on the asset protocol ([#3774](https://www.github.com/tauri-apps/tauri/pull/3774)) on 2022-03-27 - Properly apply the CSP when loading a route that fallbacks to index.html. - [bcd43168](https://www.github.com/tauri-apps/tauri/commit/bcd43168a528dc4c54e28788430a93654c8fb452) fix(core): properly add CSP header to fallback routes ([#3641](https://www.github.com/tauri-apps/tauri/pull/3641)) on 2022-03-08 - Fix CSP usage on Linux when changing it via the `on_web_resource_request` handler. - [f5efc248](https://www.github.com/tauri-apps/tauri/commit/f5efc248da511e0924c9673b947d5de7ef69ac45) fix(core): runtime CSP changes on Linux on 2022-03-07 - Improved the updater response validation and error messages. - [dbc2873e](https://www.github.com/tauri-apps/tauri/commit/dbc2873e82dd56e13025f73281769fff323d32aa) feat(updater): improve validation and error messages, closes [#3761](https://www.github.com/tauri-apps/tauri/pull/3761) ([#3780](https://www.github.com/tauri-apps/tauri/pull/3780)) on 2022-03-27 - **Breaking change:** The `MenuItem::About` variant is now associated with a tuple value `(String, AboutMetadata)`. - [5fb74332](https://www.github.com/tauri-apps/tauri/commit/5fb74332ab9210ac062d96b0e9afd1c942ee2911) chore(deps): update wry to 0.14, tao to 0.7 ([#3790](https://www.github.com/tauri-apps/tauri/pull/3790)) on 2022-03-28 - Replace multiple dependencies who's C code compiled concurrently and caused the other ones to bloat compile time significantly. - `zstd` -> `brotli` - `blake3` -> a vendored version of the blake3 reference - `ring` -> `getrandom` See https://github.com/tauri-apps/tauri/pull/3773 for more information about these specific choices. - [8661e3e2](https://www.github.com/tauri-apps/tauri/commit/8661e3e24d96c399bfbcdee5d8e9d6beba2265a7) replace dependencies with long build times when used together (closes [#3571](https://www.github.com/tauri-apps/tauri/pull/3571)) ([#3773](https://www.github.com/tauri-apps/tauri/pull/3773)) on 2022-03-27 - **Breaking change:** The `Window::hwnd` method now returns *HWND* from `windows-rs` crate instead of *c_void* on Windows. - [4e807a53](https://www.github.com/tauri-apps/tauri/commit/4e807a53e2d6d3f3cd5293d90013d5cdded5454e) Support window parenting on macOS, closes [#3751](https://www.github.com/tauri-apps/tauri/pull/3751) ([#3754](https://www.github.com/tauri-apps/tauri/pull/3754)) on 2022-03-23 - Support window parenting on macOS - [4e807a53](https://www.github.com/tauri-apps/tauri/commit/4e807a53e2d6d3f3cd5293d90013d5cdded5454e) Support window parenting on macOS, closes [#3751](https://www.github.com/tauri-apps/tauri/pull/3751) ([#3754](https://www.github.com/tauri-apps/tauri/pull/3754)) on 2022-03-23 - **Breaking change:** The updater default targets have been renamed to include better support for different architectures. - [579312f8](https://www.github.com/tauri-apps/tauri/commit/579312f834f08dca15e51e4f43c1d0bb65b54a51) feat(updater): separate intel and apple silicon targets, closes [#3359](https://www.github.com/tauri-apps/tauri/pull/3359) ([#3739](https://www.github.com/tauri-apps/tauri/pull/3739)) on 2022-03-23 - **Breaking change:** Removed `RunEvent::CloseRequested` and `RunEvent::WindowClosed` and added `RunEvent::WindowEvent`. - [edad9f4f](https://www.github.com/tauri-apps/tauri/commit/edad9f4f55dcc69a06cd9d6d5a5068c94ecb77dd) refactor(core): add `RunEvent::WindowEvent` ([#3793](https://www.github.com/tauri-apps/tauri/pull/3793)) on 2022-03-28 - **Breaking change:** Removed `window_label` from `RunEvent::ExitRequested`. - [9ddf8d84](https://www.github.com/tauri-apps/tauri/commit/9ddf8d84a22cd6ccdce04bcc98b2b0f5fc54381a) fix(core): properly fire `WindowEvent::Destroyed`, closes [#3688](https://www.github.com/tauri-apps/tauri/pull/3688) ([#3778](https://www.github.com/tauri-apps/tauri/pull/3778)) on 2022-03-28 - **Breaking change:** The `tauri://` events are no longer emitted to listeners using `Window::listen`. Use the `App::run` closure, `Window::on_window_event` and `Window::on_menu_event` instead. - [5d538ec2](https://www.github.com/tauri-apps/tauri/commit/5d538ec27c246274df4ff5b8057ff78b6364a43f) refactor(core): use the event loop proxy to send updater events ([#3687](https://www.github.com/tauri-apps/tauri/pull/3687)) on 2022-03-15 - The `App::setup` closure can now return a boxed error directly. - [da1e8793](https://www.github.com/tauri-apps/tauri/commit/da1e879358895f7b190b1c1b20d23da23666a74b) feat(core): improve and cleanup the `Error` enum ([#3748](https://www.github.com/tauri-apps/tauri/pull/3748)) on 2022-03-22 - Implement `Debug` for `tauri::State`. - [0b49dd56](https://www.github.com/tauri-apps/tauri/commit/0b49dd566dae21c4dcb1cf110115aab982a7dab6) impl Debug for State closes [#3676](https://www.github.com/tauri-apps/tauri/pull/3676) ([#3677](https://www.github.com/tauri-apps/tauri/pull/3677)) on 2022-03-12 - **Breaking change:** The `Manager::manage` function now returns a bool indicating whether the type is already managed or not. - [263b45e1](https://www.github.com/tauri-apps/tauri/commit/263b45e1b4e72d6c99fc27e41d0c5e1d134f363b) refactor(core): return boolean on `Manager::manage` ([#3682](https://www.github.com/tauri-apps/tauri/pull/3682)) on 2022-03-13 - Set the `Access-Control-Allow-Origin` header on the `tauri` protocol response with the initial webview URL as value. - [1730b1a5](https://www.github.com/tauri-apps/tauri/commit/1730b1a51d1220e6c6a2eec405a3830cc3878224) feat(core): enable CORS on the tauri protocol ([#3750](https://www.github.com/tauri-apps/tauri/pull/3750)) on 2022-03-22 - **Breaking change:** The `tauri_runtime` crate is no longer exported since its API is not stable. - [1099a969](https://www.github.com/tauri-apps/tauri/commit/1099a9696e6639b46d736f8f3b446d2dfc4ef2f0) refactor(core): do not export `tauri_runtime` on `tauri` ([#3749](https://www.github.com/tauri-apps/tauri/pull/3749)) on 2022-03-22 - Added `Temp` to the `BaseDirectory` enum. - [266156a0](https://www.github.com/tauri-apps/tauri/commit/266156a0b08150b21140dd552c8bc252fe413cdd) feat(core): add `BaseDirectory::Temp` and `$TEMP` variable ([#3763](https://www.github.com/tauri-apps/tauri/pull/3763)) on 2022-03-24 - Added `$TEMP` to the allowed variables to the filesystem and asset protocol scopes. - [266156a0](https://www.github.com/tauri-apps/tauri/commit/266156a0b08150b21140dd552c8bc252fe413cdd) feat(core): add `BaseDirectory::Temp` and `$TEMP` variable ([#3763](https://www.github.com/tauri-apps/tauri/pull/3763)) on 2022-03-24 - Update `wry` to `0.14` and `tao` to `0.7`. - [f2d24ef2](https://www.github.com/tauri-apps/tauri/commit/f2d24ef2fbd95ec7d3433ba651964f4aa3b7f48c) chore(deps): update wry ([#1482](https://www.github.com/tauri-apps/tauri/pull/1482)) on 2021-04-14 - [e267ebf1](https://www.github.com/tauri-apps/tauri/commit/e267ebf1f1009b99829e0a7d71519925f5792f9f) Apply Version Updates From Current Changes ([#1486](https://www.github.com/tauri-apps/tauri/pull/1486)) on 2021-04-14 - [5fb74332](https://www.github.com/tauri-apps/tauri/commit/5fb74332ab9210ac062d96b0e9afd1c942ee2911) chore(deps): update wry to 0.14, tao to 0.7 ([#3790](https://www.github.com/tauri-apps/tauri/pull/3790)) on 2022-03-28 - Added `updater` method to `App` and `AppHandle`, a builder to check for app updates. - [4094494a](https://www.github.com/tauri-apps/tauri/commit/4094494a1b3125bf01676dabaa69e56cc8741d59) feat(core): add API to manually trigger updater check ([#3712](https://www.github.com/tauri-apps/tauri/pull/3712)) on 2022-03-17 - [c64268f9](https://www.github.com/tauri-apps/tauri/commit/c64268f9274bdb7352da1a53184e487b03437dc2) feat(updater): expose builder, allow setting a custom version checker ([#3792](https://www.github.com/tauri-apps/tauri/pull/3792)) on 2022-03-28 - Allow using a custom updater version checker via `App::updater().should_install()`. - [c64268f9](https://www.github.com/tauri-apps/tauri/commit/c64268f9274bdb7352da1a53184e487b03437dc2) feat(updater): expose builder, allow setting a custom version checker ([#3792](https://www.github.com/tauri-apps/tauri/pull/3792)) on 2022-03-28 - Added download progress events to the updater. - [f0db3f9b](https://www.github.com/tauri-apps/tauri/commit/f0db3f9b8357dc304a8254426034c4d1733fbd45) feat(updater): add download progress events ([#3734](https://www.github.com/tauri-apps/tauri/pull/3734)) on 2022-03-18 - Send updater events to the `App::run` closure. - [5d538ec2](https://www.github.com/tauri-apps/tauri/commit/5d538ec27c246274df4ff5b8057ff78b6364a43f) refactor(core): use the event loop proxy to send updater events ([#3687](https://www.github.com/tauri-apps/tauri/pull/3687)) on 2022-03-15 - Run the updater on startup even if no window was created. - [c4ca80f9](https://www.github.com/tauri-apps/tauri/commit/c4ca80f919551cbcae53d931f860115c2d591d14) feat(core): use AppHandle instead of Window on the updater logic ([#3702](https://www.github.com/tauri-apps/tauri/pull/3702)) on 2022-03-15 - Properly fire the window destroyed event. - [9ddf8d84](https://www.github.com/tauri-apps/tauri/commit/9ddf8d84a22cd6ccdce04bcc98b2b0f5fc54381a) fix(core): properly fire `WindowEvent::Destroyed`, closes [#3688](https://www.github.com/tauri-apps/tauri/pull/3688) ([#3778](https://www.github.com/tauri-apps/tauri/pull/3778)) on 2022-03-28 - Added `close_devtools` and `is_devtools_open` APIs to the `Window` struct. - [e05d718a](https://www.github.com/tauri-apps/tauri/commit/e05d718a7b46476d1fe4817c169008080e84f959) feat(core): add hotkey to toggle devtools, closes [#3776](https://www.github.com/tauri-apps/tauri/pull/3776) ([#3791](https://www.github.com/tauri-apps/tauri/pull/3791)) on 2022-03-28 - Added the `WindowEvent::FileDrop` variant. - [07d1584c](https://www.github.com/tauri-apps/tauri/commit/07d1584cf06ea326aa45d8044bee1b77ecba5006) feat(core): add `WindowEvent::FileDrop`, closes [#3664](https://www.github.com/tauri-apps/tauri/pull/3664) ([#3686](https://www.github.com/tauri-apps/tauri/pull/3686)) on 2022-03-13 - Added a configuration flag for disallowing install downgrades on Windows. **Breaking change:** The default behavior on Windows is now to allow downgrades. - [8b807e09](https://www.github.com/tauri-apps/tauri/commit/8b807e09d6868f6bff8357f16d27b15bd1fccadd) refactor(bundler): allow downgrades, add option to disallow on Windows ([#3777](https://www.github.com/tauri-apps/tauri/pull/3777)) on 2022-03-27 ## \[1.0.0-rc.4] - Run `AppHandle` cleanup code before restarting the application on the `process > relaunch` API. - [9c65abce](https://www.github.com/tauri-apps/tauri/commit/9c65abce1bd3895b7f8d9d4d8a449ac4802fce24) feat(core): run cleanup code on the relaunch API ([#3629](https://www.github.com/tauri-apps/tauri/pull/3629)) on 2022-03-07 - **Breaking change:** The `Builder#create_window` API now returns a Result validating the window label. - [64e00542](https://www.github.com/tauri-apps/tauri/commit/64e0054299c95f10ef5a1a9d3f914bbaeff3d73f) refactor(core): do not panic on invalid window labels,[#3544](https://www.github.com/tauri-apps/tauri/pull/3544) ([#3596](https://www.github.com/tauri-apps/tauri/pull/3596)) on 2022-03-03 - Added `tsp` config option under `tauri > bundle > windows`, which enables Time-Stamp Protocol (RFC 3161) for the timestamping server under code signing on Windows if set to `true`. - [bdd5f7c2](https://www.github.com/tauri-apps/tauri/commit/bdd5f7c2f03af4af8b60a9527e55bb18525d989b) fix: add support for Time-Stamping Protocol for Windows codesigning (fix [#3563](https://www.github.com/tauri-apps/tauri/pull/3563)) ([#3570](https://www.github.com/tauri-apps/tauri/pull/3570)) on 2022-03-07 - Revert the `clap` usage back to the version 3.0 API. - [2b554c38](https://www.github.com/tauri-apps/tauri/commit/2b554c38a5181b948d7674b6ef33e4049ca7d327) fix(core): revert to clap 3.0 API, allow deprecations, closes [#3549](https://www.github.com/tauri-apps/tauri/pull/3549) ([#3552](https://www.github.com/tauri-apps/tauri/pull/3552)) on 2022-02-24 - The `tauri::api::process::Command` API now properly reads stdout and stderr messages that ends with a carriage return (`\r`) instead of just a newline (`\n`). - [0a0de8ab](https://www.github.com/tauri-apps/tauri/commit/0a0de8ab6ed80b7722012e83636dff41a813b770) fix: read Command output ending with a carriage return, closes [#3508](https://www.github.com/tauri-apps/tauri/pull/3508) ([#3523](https://www.github.com/tauri-apps/tauri/pull/3523)) on 2022-02-24 - Fixes filesystem and asset scope stripping the first component of the allowed path. - [4d0e2ecc](https://www.github.com/tauri-apps/tauri/commit/4d0e2eccd9e0e1db16e6cc20613ffdc3dbe0474e) fix(core): scope should not strip the first path component, closes [#3592](https://www.github.com/tauri-apps/tauri/pull/3592) ([#3602](https://www.github.com/tauri-apps/tauri/pull/3602)) on 2022-03-03 - Ignore trailing slashes on path scope validation. - [929a83dd](https://www.github.com/tauri-apps/tauri/commit/929a83dd4d2614a119ab05122663669648e8c701) fix(core): ignore trailing slashes on scope validation, closes [#3580](https://www.github.com/tauri-apps/tauri/pull/3580) ([#3601](https://www.github.com/tauri-apps/tauri/pull/3601)) on 2022-03-03 - Fixes `Command::output` and `Command::status` deadlock when running on async commands. - [0163489e](https://www.github.com/tauri-apps/tauri/commit/0163489ed60ec0fe9486b5556ec0234499852a16) fix(core): `safe_block_on` usage on async contexts, closes [#3505](https://www.github.com/tauri-apps/tauri/pull/3505) ([#3513](https://www.github.com/tauri-apps/tauri/pull/3513)) on 2022-02-24 - Update tray menu id map when `SystemTrayHandle::set_menu` is called. - [da882431](https://www.github.com/tauri-apps/tauri/commit/da8824318affb50475f28b9c78c56da3fb048708) fix(core): update tray menu ids on `set_menu`, closes [#3608](https://www.github.com/tauri-apps/tauri/pull/3608) ([#3611](https://www.github.com/tauri-apps/tauri/pull/3611)) on 2022-03-04 - Allow absolute paths on the filesystem APIs as long as it does not include parent directory components. - [b744cd27](https://www.github.com/tauri-apps/tauri/commit/b744cd2758bbc5da39d6105fd82002dc6536dd16) feat: extend scopes with user selected paths, closes [#3591](https://www.github.com/tauri-apps/tauri/pull/3591) ([#3595](https://www.github.com/tauri-apps/tauri/pull/3595)) on 2022-03-03 - **Breaking change:** The `tauri::api::file::Extract` API is now available when the `fs-extract-api` feature is enabled. - [0f155898](https://www.github.com/tauri-apps/tauri/commit/0f1558980a0fb1d6c042988e173047f0590b6574) fix(core): docs.rs on Windows and macOS ([#3566](https://www.github.com/tauri-apps/tauri/pull/3566)) on 2022-03-02 - Allow listening to events on the filesystem and asset scopes. - [58070c1e](https://www.github.com/tauri-apps/tauri/commit/58070c1eb443c29b01638b7fc3f69aacdcc464a6) feat(core): filesystem and asset protocol scope events ([#3609](https://www.github.com/tauri-apps/tauri/pull/3609)) on 2022-03-04 - Allow configuring forbidden paths on the asset and filesystem scopes. - [983ccb81](https://www.github.com/tauri-apps/tauri/commit/983ccb815b1cb094ac681c2b36c69ec16f123b4e) feat(core): allow denying paths on the fs and asset scopes ([#3607](https://www.github.com/tauri-apps/tauri/pull/3607)) on 2022-03-03 - Extend the allowed patterns for the filesystem and asset protocol when the user selects a path (dialog open and save commands and file drop on the window). - [b744cd27](https://www.github.com/tauri-apps/tauri/commit/b744cd2758bbc5da39d6105fd82002dc6536dd16) feat: extend scopes with user selected paths, closes [#3591](https://www.github.com/tauri-apps/tauri/pull/3591) ([#3595](https://www.github.com/tauri-apps/tauri/pull/3595)) on 2022-03-03 - The HTTP scope now matches the entire URL using a glob pattern instead of only its path. - [944b124c](https://www.github.com/tauri-apps/tauri/commit/944b124ce04a15a415fcbb0afdfa78b0e900c97a) feat(core): enhance HTTP scope glob validation, closes [#3507](https://www.github.com/tauri-apps/tauri/pull/3507) ([#3515](https://www.github.com/tauri-apps/tauri/pull/3515)) on 2022-02-24 - Parse window icons at compile time. - [8c935872](https://www.github.com/tauri-apps/tauri/commit/8c9358725a17dcc2acaf4d10c3f654afdff586b0) refactor(core): move `png` and `ico` behind Cargo features ([#3588](https://www.github.com/tauri-apps/tauri/pull/3588)) on 2022-03-05 - **Breaking change:** Move `ico` and `png` parsing behind `icon-ico` and `icon-png` Cargo features. - [8c935872](https://www.github.com/tauri-apps/tauri/commit/8c9358725a17dcc2acaf4d10c3f654afdff586b0) refactor(core): move `png` and `ico` behind Cargo features ([#3588](https://www.github.com/tauri-apps/tauri/pull/3588)) on 2022-03-05 - Return an error when creating a window with an invalid label instead of panicking. - [64e00542](https://www.github.com/tauri-apps/tauri/commit/64e0054299c95f10ef5a1a9d3f914bbaeff3d73f) refactor(core): do not panic on invalid window labels,[#3544](https://www.github.com/tauri-apps/tauri/pull/3544) ([#3596](https://www.github.com/tauri-apps/tauri/pull/3596)) on 2022-03-03 - Allows the configuration CSP to be an object mapping a directive name to its source list. - [3fe0260f](https://www.github.com/tauri-apps/tauri/commit/3fe0260f4c7f47dba28b0d049c741d885bc6d356) feat(core): allow CSP configuration to be an object, ref [#3533](https://www.github.com/tauri-apps/tauri/pull/3533) ([#3603](https://www.github.com/tauri-apps/tauri/pull/3603)) on 2022-03-04 - Allow range in the form of `bytes=0-*` on the asset protocol. - [d06efc77](https://www.github.com/tauri-apps/tauri/commit/d06efc7704092a549c886be701122ad420db5543) fix(core): parse range `bytes=0-*`, closes [#3143](https://www.github.com/tauri-apps/tauri/pull/3143) ([#3516](https://www.github.com/tauri-apps/tauri/pull/3516)) on 2022-02-24 - Reimplement endpoint to read file as string for performance. - [834ccc51](https://www.github.com/tauri-apps/tauri/commit/834ccc51539401d36a7dfa1c0982623c9c446a4c) feat(core): reimplement `readTextFile` for performance ([#3631](https://www.github.com/tauri-apps/tauri/pull/3631)) on 2022-03-07 - **Breaking change:** Renamed the `command` Cargo feature to `process-command-api`. - [4e1af005](https://www.github.com/tauri-apps/tauri/commit/4e1af005a1fc80e911299b5fd6d6b0f3eb44f8e7) refactor(core): rename `command` feature to `process-command-api` ([#3594](https://www.github.com/tauri-apps/tauri/pull/3594)) on 2022-03-03 - Disabled the default features for the `zip` crate. - [5293445f](https://www.github.com/tauri-apps/tauri/commit/5293445f08f1484639ad9f56c45aad53039ba579) refactor(core): disable default features for the zip crate ([#3624](https://www.github.com/tauri-apps/tauri/pull/3624)) on 2022-03-06 - The `cmd` field is no longer required on the shell scope for sidecars. - [9b3b163b](https://www.github.com/tauri-apps/tauri/commit/9b3b163baa9b8eb2ef0bbc53f6303cc7a59a01af) feat(core): simplify scope definition for sidecars ([#3574](https://www.github.com/tauri-apps/tauri/pull/3574)) on 2022-03-02 - Fixes a regression on the `unlisten` command. - [76c791bd](https://www.github.com/tauri-apps/tauri/commit/76c791bd2b836d2055410e37e71716172a3f81ef) fix(core): regression on the unlisten function ([#3623](https://www.github.com/tauri-apps/tauri/pull/3623)) on 2022-03-06 - Run `AppHandle` cleanup code before restarting the application when a new update is installed. - [fce7d3bb](https://www.github.com/tauri-apps/tauri/commit/fce7d3bbae8d9e7e928a31b04a0a87dcaf4cd65f) feat(core): run app cleanup code before updater restart, closes [#3605](https://www.github.com/tauri-apps/tauri/pull/3605) ([#3616](https://www.github.com/tauri-apps/tauri/pull/3616)) on 2022-03-04 - Added a `WindowBuilder` type. - [141133a4](https://www.github.com/tauri-apps/tauri/commit/141133a414154631d42a0873c6abe2d76391b87d) feat(core): add WindowBuilder type ([#3598](https://www.github.com/tauri-apps/tauri/pull/3598)) on 2022-03-04 - Added `WindowBuilder::on_web_resource_request`, which allows customizing the tauri custom protocol response. - [3b13fda5](https://www.github.com/tauri-apps/tauri/commit/3b13fda56f515c708014c0396ed5ca295faaef84) feat(core): add `WindowBuilder::on_request`, closes [#3533](https://www.github.com/tauri-apps/tauri/pull/3533) ([#3618](https://www.github.com/tauri-apps/tauri/pull/3618)) on 2022-03-06 ## \[1.0.0-rc.3] - `tauri::plugin::Builder` closures are no longer required to implement `Sync`. - [fb7ee2c9](https://www.github.com/tauri-apps/tauri/commit/fb7ee2c987d9fca23f08bd470789069d9477c66e) drop Sync req from `setup` and `setup_with_config` ([#3471](https://www.github.com/tauri-apps/tauri/pull/3471)) on 2022-02-16 - [b8e4d651](https://www.github.com/tauri-apps/tauri/commit/b8e4d651f9866b34bd3afcf2392812a18e1cee53) fix(core): drop all plugin builder Sync requirements ([#3490](https://www.github.com/tauri-apps/tauri/pull/3490)) on 2022-02-17 - Added context to the file system endpoint errors. - [06053833](https://www.github.com/tauri-apps/tauri/commit/060538331c138473159cf8fee0fcb7904ca33d3b) feat(core): add context to the filesystem APIs errors, closes [#3457](https://www.github.com/tauri-apps/tauri/pull/3457) ([#3480](https://www.github.com/tauri-apps/tauri/pull/3480)) on 2022-02-16 - Changed the default value for `tauri > bundle > macOS > minimumSystemVersion` to `10.13`. - [fce344b9](https://www.github.com/tauri-apps/tauri/commit/fce344b90b7227f8f5514853c2f885fb24d3648e) feat(core): set default value for `minimum_system_version` to 10.13 ([#3497](https://www.github.com/tauri-apps/tauri/pull/3497)) on 2022-02-17 ## \[1.0.0-rc.2] - Ease the requirements for plugin hooks. `setup` and `setup_with_config` can now be `FnOnce` and `on_webview_ready`, `on_event` and `on_page_load` can be `FnMut`. - [fd557e98](https://www.github.com/tauri-apps/tauri/commit/fd557e984db17335a7c2ff10e6fe9c07065a95ed) Ease plugin hook restrictions ([#3404](https://www.github.com/tauri-apps/tauri/pull/3404)) on 2022-02-13 - Fixes an issue with the updater when replacing the `{{target}}` and `{{current_version}}` variables due to percent-encoding on the `Url` that is parsed from the configuration. - [20f0477f](https://www.github.com/tauri-apps/tauri/commit/20f0477f95b836cdf03ca66dadd9c0d3c95b198a) fix(core): updater not replacing variables, closes [#3428](https://www.github.com/tauri-apps/tauri/pull/3428) ([#3432](https://www.github.com/tauri-apps/tauri/pull/3432)) on 2022-02-13 ## \[1.0.0-rc.1] - Change default value for the `freezePrototype` configuration to `false`. - [3a4c0160](https://www.github.com/tauri-apps/tauri/commit/3a4c01606184be762adee055ddac803de0d28527) fix(core): change default `freezePrototype` to false, closes [#3416](https://www.github.com/tauri-apps/tauri/pull/3416) [#3406](https://www.github.com/tauri-apps/tauri/pull/3406) ([#3423](https://www.github.com/tauri-apps/tauri/pull/3423)) on 2022-02-12 ## \[1.0.0-rc.0] - The dialog allowlist now includes flags for the `message`, `ask` and `confirm` APIs. - [d660cab3](https://www.github.com/tauri-apps/tauri/commit/d660cab38d7d703e8b2bb85a3e9462d9e28b086b) feat: enhance allowlist configuration \[TRI-027] ([#11](https://www.github.com/tauri-apps/tauri/pull/11)) on 2022-01-09 - - **Breaking change:** Renamed `tauri::Event` to `tauri::RunEvent` - Exported `tauri::Event` and `tauri::EventHandler` so you can define a function and pass it to `Window::listen` - [15358b18](https://www.github.com/tauri-apps/tauri/commit/15358b1895487cb9c258a8ca4d2336b4215e2a8f) Expose event interface. fixes [#2733](https://www.github.com/tauri-apps/tauri/pull/2733) ([#3321](https://www.github.com/tauri-apps/tauri/pull/3321)) on 2022-02-04 - The `tauri::api` modules `http`, `notification`, `dialog`, and `process::Command` APIs are now hidden behind a feature flag, `http-api`, `notification`, `dialog` and `command`, respectively. - [6feb5a0c](https://www.github.com/tauri-apps/tauri/commit/6feb5a0c50852a4792a9cc80967eab0fcf18609e) refactor(core): api feature flags, documentation ([#26](https://www.github.com/tauri-apps/tauri/pull/26)) on 2022-01-09 - Add `title` option to file open/save dialogs. - [e1d6a6e6](https://www.github.com/tauri-apps/tauri/commit/e1d6a6e6445637723e2331ca799a662e720e15a8) Create api-file-dialog-title.md ([#3235](https://www.github.com/tauri-apps/tauri/pull/3235)) on 2022-01-16 - [62c7a8ad](https://www.github.com/tauri-apps/tauri/commit/62c7a8ad30fd3031b8679960590e5ef3eef8e4da) chore(covector): prepare for `rc` release ([#3376](https://www.github.com/tauri-apps/tauri/pull/3376)) on 2022-02-10 - Added `any_thread()` to the `tauri::Builder` to run applications on any thread (only exposed on Linux and Windows). - [af44bf81](https://www.github.com/tauri-apps/tauri/commit/af44bf8168310cf77fbe102a53e7c433f11641a3) feat(core): allow app run on any thread on Linux & Windows, closes [#3172](https://www.github.com/tauri-apps/tauri/pull/3172) ([#3353](https://www.github.com/tauri-apps/tauri/pull/3353)) on 2022-02-07 - Enable CORS on the `asset` protocol. - [d28ac8aa](https://www.github.com/tauri-apps/tauri/commit/d28ac8aac0d19a70bb658f12e56330ec8ac4dda5) fix(core): enable CORS on the `asset` protocol, closes [#2965](https://www.github.com/tauri-apps/tauri/pull/2965) ([#2974](https://www.github.com/tauri-apps/tauri/pull/2974)) on 2021-12-09 - The `asset://` custom protocol is only defined when either the `api-all`, `protocol-all` or `protocol-asset` feature flags are enabled. These feature flags are accessible with the `tauri.conf.json` allowlist. - [7920ff14](https://www.github.com/tauri-apps/tauri/commit/7920ff14e6424079c48ea5645d9aa13e7a272b87) feat: scope the `fs` API and the `asset` protocol \[TRI-026] \[TRI-010] \[TRI-011] ([#10](https://www.github.com/tauri-apps/tauri/pull/10)) on 2022-01-09 - Expose the `asset_resolver` API on the `App` and `AppHandle` structs. - [7c6c7adc](https://www.github.com/tauri-apps/tauri/commit/7c6c7adcc4c1ddd7406dd2d3b31541d5b962b385) feat(core): add `asset_resolver` API ([#2879](https://www.github.com/tauri-apps/tauri/pull/2879)) on 2021-11-12 - **Breaking change:** Refactored the types returned from the `async_runtime` module. - [a3537078](https://www.github.com/tauri-apps/tauri/commit/a3537078ddeaac7d26250f111f071072cf328b0b) feat(core): allow running along another tokio runtime, closes [#2838](https://www.github.com/tauri-apps/tauri/pull/2838) ([#2973](https://www.github.com/tauri-apps/tauri/pull/2973)) on 2021-12-08 - Added `tauri::async_runtime::set` method, allowing to share your tokio runtime with Tauri. - [a3537078](https://www.github.com/tauri-apps/tauri/commit/a3537078ddeaac7d26250f111f071072cf328b0b) feat(core): allow running along another tokio runtime, closes [#2838](https://www.github.com/tauri-apps/tauri/pull/2838) ([#2973](https://www.github.com/tauri-apps/tauri/pull/2973)) on 2021-12-08 - Added `tauri::async_runtime::spawn_blocking` API. - [a3537078](https://www.github.com/tauri-apps/tauri/commit/a3537078ddeaac7d26250f111f071072cf328b0b) feat(core): allow running along another tokio runtime, closes [#2838](https://www.github.com/tauri-apps/tauri/pull/2838) ([#2973](https://www.github.com/tauri-apps/tauri/pull/2973)) on 2021-12-08 - The `callback` and `error` invoke fields, along with other `transformCallback` usages, are now validated to be numeric. - [a48b8b18](https://www.github.com/tauri-apps/tauri/commit/a48b8b18d428bcc404d489daa690bbefe1f57311) feat(core): validate callbacks and event names \[TRI-038] \[TRI-020] ([#21](https://www.github.com/tauri-apps/tauri/pull/21)) on 2022-01-09 - Change `Error::ParseCliArguments(clap::Error)` to `Error::ParseCliArguments(String)` because `clap::Error` is not `Send`. - [1f988535](https://www.github.com/tauri-apps/tauri/commit/1f98853573a837dd0cfc2161b206a5033ec2da5e) chore(deps) Update Tauri Core ([#2480](https://www.github.com/tauri-apps/tauri/pull/2480)) on 2021-08-24 - The `api::process::Command` APIs are now hidden behind the `command` feature flag. - [eed01728](https://www.github.com/tauri-apps/tauri/commit/eed017287fed2ade689af4268e8b63b9c9f2e585) feat(core): add `shell > sidecar` allowlist and `process` feature flag \[TRI-037] ([#18](https://www.github.com/tauri-apps/tauri/pull/18)) on 2021-10-24 - Add `tauri::api::path::log_dir` function to access the suggested log directory path. - [acbb3ae7](https://www.github.com/tauri-apps/tauri/commit/acbb3ae7bb0165846b9456aea103269f027fc548) feat: add Log directory ([#2736](https://www.github.com/tauri-apps/tauri/pull/2736)) on 2021-10-16 - [62c7a8ad](https://www.github.com/tauri-apps/tauri/commit/62c7a8ad30fd3031b8679960590e5ef3eef8e4da) chore(covector): prepare for `rc` release ([#3376](https://www.github.com/tauri-apps/tauri/pull/3376)) on 2022-02-10 - The `process`, `path` and `updater` APIs now takes a `tauri::Env` argument, used to force environment variables load on startup to prevent env var update attacks. - [7209fdf7](https://www.github.com/tauri-apps/tauri/commit/7209fdf732ffe1893aaa9cd970ab6491a883d997) refactor(core): load APPIMAGE and APPDIR env vars on startup \[TRI-007] \[TRI-041] on 2022-01-09 - Now `resolve()`, `join()` and `normalize()` from the `path` module, won't throw errors if the path doesn't exist, which matches NodeJS behavior. - [fe381a0b](https://www.github.com/tauri-apps/tauri/commit/fe381a0bde86ebf4014007f6e21af4c1a9e58cef) fix: `join` no longer cares if path doesn't exist, closes [#2499](https://www.github.com/tauri-apps/tauri/pull/2499) ([#2548](https://www.github.com/tauri-apps/tauri/pull/2548)) on 2021-09-21 - **Breaking change:** Return `Window` on `App` and `AppHandle`'s `create_window` function. - [e15a8af8](https://www.github.com/tauri-apps/tauri/commit/e15a8af8434805da9716f3f840daa4e87b18b0a2) refactor(core): return `Window` on `create_window` API ([#3211](https://www.github.com/tauri-apps/tauri/pull/3211)) on 2022-01-13 - [62c7a8ad](https://www.github.com/tauri-apps/tauri/commit/62c7a8ad30fd3031b8679960590e5ef3eef8e4da) chore(covector): prepare for `rc` release ([#3376](https://www.github.com/tauri-apps/tauri/pull/3376)) on 2022-02-10 - Apply `nonce` to `script` and `style` tags and set them on the `CSP` (`script-src` and `style-src` fetch directives). - [cf54dcf9](https://www.github.com/tauri-apps/tauri/commit/cf54dcf9c81730e42c9171daa9c8aa474c95b522) feat: improve `CSP` security with nonces and hashes, add `devCsp` \[TRI-004] ([#8](https://www.github.com/tauri-apps/tauri/pull/8)) on 2022-01-09 - The path returned from `tauri::api::process::current_binary` is now cached when loading the binary. - [7c3db7a3](https://www.github.com/tauri-apps/tauri/commit/7c3db7a3811fd4de3e71c78cfd00894fa51ab786) cache current binary path much sooner ([#45](https://www.github.com/tauri-apps/tauri/pull/45)) on 2022-02-01 - Added an API to use a custom invoke system to receive and respond to commands (`Builder#invoke_system`). - [15164d93](https://www.github.com/tauri-apps/tauri/commit/15164d930a64807054057d83a2b6dae8540bcd9a) feat(core): allow defining a custom invoke system ([#2899](https://www.github.com/tauri-apps/tauri/pull/2899)) on 2021-11-16 - Inject configured `CSP` on `data:` URLs. - [8259cd64](https://www.github.com/tauri-apps/tauri/commit/8259cd64c2087b23b694a78aa98c43866762faec) feat(core): inject `CSP` on data URLs \[TRI-049] ([#16](https://www.github.com/tauri-apps/tauri/pull/16)) on 2022-01-09 - Emit `tauri://*` events to Rust listeners. - [4c4ab1eb](https://www.github.com/tauri-apps/tauri/commit/4c4ab1eb8b0b8b98ded402d0afb9dbca7ffe08e8) fix(core): trigger `tauri://*` events to Rust listeners, closes [#2901](https://www.github.com/tauri-apps/tauri/pull/2901) ([#2902](https://www.github.com/tauri-apps/tauri/pull/2902)) on 2021-11-16 - Emit `tauri://window-created` event for windows created on the backend. - [1dbd887a](https://www.github.com/tauri-apps/tauri/commit/1dbd887a6e0fc77b56e1b4d1b96dae8ddea1d5ea) fix(core): emit tauri://window-created event for windows created on Rust ([#3299](https://www.github.com/tauri-apps/tauri/pull/3299)) on 2022-02-04 - Enable non-session cookie persistence on Linux. - [d7c02a30](https://www.github.com/tauri-apps/tauri/commit/d7c02a30a56de79100804969138b379e703f0e07) feat(core): persist non-session cookies on Linux ([#3052](https://www.github.com/tauri-apps/tauri/pull/3052)) on 2021-12-09 - Expose `tauri::api::ipc::{serialize_js_with, serialize_js}` functions. - [5a94200f](https://www.github.com/tauri-apps/tauri/commit/5a94200f65feb4fddc79f0c68f8bc0a4067ad51a) feat(core): expose functions to serialize `serde::Serialize` values to JS ([#3354](https://www.github.com/tauri-apps/tauri/pull/3354)) on 2022-02-07 - Resolve `asset` protocol HTTP request instead of panicking if the file does not exist or cannot be read. - [03fc92c8](https://www.github.com/tauri-apps/tauri/commit/03fc92c8304efe897a09de6e82da2fea7f69ecab) fix(core): resolve request instead of panicking on asset protocol ([#3347](https://www.github.com/tauri-apps/tauri/pull/3347)) on 2022-02-06 - Avoid `async_runtime::block_on` panics when used along another tokio runtime. - [a3537078](https://www.github.com/tauri-apps/tauri/commit/a3537078ddeaac7d26250f111f071072cf328b0b) feat(core): allow running along another tokio runtime, closes [#2838](https://www.github.com/tauri-apps/tauri/pull/2838) ([#2973](https://www.github.com/tauri-apps/tauri/pull/2973)) on 2021-12-08 - Prevent window closing if `tauri://close-requested` is listened on the JS layer. Users must call `appWindow.close()` manually when listening to that event. - [74dff536](https://www.github.com/tauri-apps/tauri/commit/74dff536d4757820e68ab05301be83c0870c22ed) fix(core): emit `tauri://close-requested` to JS, closes [#2996](https://www.github.com/tauri-apps/tauri/pull/2996) ([#3041](https://www.github.com/tauri-apps/tauri/pull/3041)) on 2021-12-09 - Fixes a deadlock when creating a window from a menu event handler. - [9c82006b](https://www.github.com/tauri-apps/tauri/commit/9c82006b2fe166d20510183e36cee099bf96e8d9) fix(core): deadlock when creating window from menu handler, closes [#3110](https://www.github.com/tauri-apps/tauri/pull/3110) ([#3126](https://www.github.com/tauri-apps/tauri/pull/3126)) on 2021-12-28 - Fixes the dialog `defaultPath` usage on Linux. - [2212bd5d](https://www.github.com/tauri-apps/tauri/commit/2212bd5d75146f5a2df27cc2157a057642f626da) fix: dialog default path on Linux, closes [#3091](https://www.github.com/tauri-apps/tauri/pull/3091) ([#3123](https://www.github.com/tauri-apps/tauri/pull/3123)) on 2021-12-27 - Fixes `WindowEvent::Focus` and `WindowEvent::Blur` events not firing. - [3b33d67a](https://www.github.com/tauri-apps/tauri/commit/3b33d67aa4f48dcf4e32b3b8a5f45e83808efc2d) fix: re-adding focus/blur events for linux and macos (fix [#2485](https://www.github.com/tauri-apps/tauri/pull/2485)) ([#2489](https://www.github.com/tauri-apps/tauri/pull/2489)) on 2021-08-24 - Fixes `tauri://focus` and `tauri://blur` events not firing. - [3b33d67a](https://www.github.com/tauri-apps/tauri/commit/3b33d67aa4f48dcf4e32b3b8a5f45e83808efc2d) fix: re-adding focus/blur events for linux and macos (fix [#2485](https://www.github.com/tauri-apps/tauri/pull/2485)) ([#2489](https://www.github.com/tauri-apps/tauri/pull/2489)) on 2021-08-24 - Use webview's inner_size instead of window's value to get the correct size on macOS. - [4c0c780e](https://www.github.com/tauri-apps/tauri/commit/4c0c780e00d8851be38cb1c22f636d9e4ed34a23) fix(core): window's inner_size usage, closes [#2187](https://www.github.com/tauri-apps/tauri/pull/2187) ([#2690](https://www.github.com/tauri-apps/tauri/pull/2690)) on 2021-09-29 - Fixes resource directory resolution on Linux. - [1a28904b](https://www.github.com/tauri-apps/tauri/commit/1a28904b8ebea92e143d5dc21ebd209e9edec531) fix(core): resource path resolution on Linux, closes [#2493](https://www.github.com/tauri-apps/tauri/pull/2493) on 2021-08-22 - Fixes the menu id mapping not reflecting the current window. - [ac37b56e](https://www.github.com/tauri-apps/tauri/commit/ac37b56ef43c9e97039967a5fd99f0d2dccb5b5a) fix(core): menu id map not reflecting the current window menu ([#2726](https://www.github.com/tauri-apps/tauri/pull/2726)) on 2021-10-08 - `Manager::once_global` and `Window::once` allow `FnOnce` callbacks. - [d5400a3d](https://www.github.com/tauri-apps/tauri/commit/d5400a3d62ff2a37ccad20987dfea309725975a6) `once_global` and `once` accept FnOnce callbacks ([#3383](https://www.github.com/tauri-apps/tauri/pull/3383)) on 2022-02-10 - Properly check if document is loaded before invoking commands. - [000d126e](https://www.github.com/tauri-apps/tauri/commit/000d126e0e7231fb666b9ef53d6a1479dca774f7) fix(core): properly check if document is loaded, closes [#2716](https://www.github.com/tauri-apps/tauri/pull/2716) ([#2900](https://www.github.com/tauri-apps/tauri/pull/2900)) on 2021-11-16 - Initialize system tray before windows so `tray_handle` can be accessed on command handlers. - [dbe0d21b](https://www.github.com/tauri-apps/tauri/commit/dbe0d21b6fdc0f7d4c7b5e099cef805b60ef203e) fix(core): initialize system tray before app windows on 2021-08-31 - Reimplement `remove_system_tray` on Windows to drop the `SystemTray` to run its cleanup code. - [a03b8554](https://www.github.com/tauri-apps/tauri/commit/a03b85545a4b0b61a598a43eabe96e03565dcaf0) fix(core): tray not closing on Windows ([#3351](https://www.github.com/tauri-apps/tauri/pull/3351)) on 2022-02-07 - Immediately listen to `tauri://window-created` event to catch it before the application triggers it. - [878b8b9a](https://www.github.com/tauri-apps/tauri/commit/878b8b9a1fc825b1ea34f955e053311409a1468d) fix(core): immediately listen to window-created, closes [#3297](https://www.github.com/tauri-apps/tauri/pull/3297) ([#3298](https://www.github.com/tauri-apps/tauri/pull/3298)) on 2022-02-04 - The `tauri::Window#emit` function now correctly sends the event to all windows that has a registered listener. **Breaking change:** `Window#emit_and_trigger` and `Window#emit` now requires the payload to be cloneable. - [9b340552](https://www.github.com/tauri-apps/tauri/commit/9b340552643a1d8b9311219101329ce23c9271ea) fix(core): window-specific event delivery, closes [#3302](https://www.github.com/tauri-apps/tauri/pull/3302) ([#3344](https://www.github.com/tauri-apps/tauri/pull/3344)) on 2022-02-06 - Allow using a fixed version for the Webview2 runtime via the `tauri > bundle > windows > webviewFixedRuntimePath` config option. - [85df94f2](https://www.github.com/tauri-apps/tauri/commit/85df94f2b0d40255812b42c5e32a70c4b45392df) feat(core): config for fixed webview2 runtime version path ([#27](https://www.github.com/tauri-apps/tauri/pull/27)) on 2021-11-02 - The updater `pubkey` is now a required field for security reasons. Sign your updates with the `tauri signer` command. - [d95cc831](https://www.github.com/tauri-apps/tauri/commit/d95cc83105dda52df7514e30e54f3676cdb374ee) feat: enforce updater public key \[TRI-015] ([#42](https://www.github.com/tauri-apps/tauri/pull/42)) on 2022-01-09 - `tauri::api::HttpRequestBuilder::new` now returns a `Result` to validate the url. - [0ad1c651](https://www.github.com/tauri-apps/tauri/commit/0ad1c6515f696fadefddbf133a9561836b3d5934) feat(core): add `http` allowlist scope \[TRI-008] ([#24](https://www.github.com/tauri-apps/tauri/pull/24)) on 2021-10-29 - Added the `isolation` pattern. - [d5d6d2ab](https://www.github.com/tauri-apps/tauri/commit/d5d6d2abc17cd89c3a079d2ce01581193469dbc0) Isolation Pattern ([#43](https://www.github.com/tauri-apps/tauri/pull/43)) Co-authored-by: Ngo Iok Ui (Wu Yu Wei) Co-authored-by: Lucas Fernandes Nogueira on 2022-01-17 - Added `abort` method to `tauri::async_runtime::JoinHandle`. - [ad169759](https://www.github.com/tauri-apps/tauri/commit/ad16975938afc9e87747de5fdcb0f07fc2d24811) feat: Add JoinHandle::abort() ([#2877](https://www.github.com/tauri-apps/tauri/pull/2877)) on 2021-11-13 - Adds support for using JSON5 format for the `tauri.conf.json` file, along with also supporting the `.json5` extension. Here is the logic flow that determines if JSON or JSON5 will be used to parse the config: 1. Check if `tauri.conf.json` exists a. Parse it with `serde_json` b. Parse it with `json5` if `serde_json` fails c. Return original `serde_json` error if all above steps failed 2. Check if `tauri.conf.json5` exists a. Parse it with `json5` b. Return error if all above steps failed 3. Return error if all above steps failed - [995de57a](https://www.github.com/tauri-apps/tauri/commit/995de57a76cf51215277673e526d7ec32b86b564) Add seamless support for using JSON5 in the config file ([#47](https://www.github.com/tauri-apps/tauri/pull/47)) on 2022-02-03 - Allow preventing opening the default browser on a click on an `` element via `stopImmediatePropagation()`. - [10e3190f](https://www.github.com/tauri-apps/tauri/commit/10e3190fdd38893a720a51b7bfd06744e0306626) fix(core): do not use capture on \_blank link event handler, closes [#2791](https://www.github.com/tauri-apps/tauri/pull/2791) ([#3349](https://www.github.com/tauri-apps/tauri/pull/3349)) on 2022-02-07 - The `run_return` API is now available on Linux. - [8483fde9](https://www.github.com/tauri-apps/tauri/commit/8483fde975aac8833d2ce426e42fb40aeaeecba9) feat(core): expose `run_return` on Linux ([#3352](https://www.github.com/tauri-apps/tauri/pull/3352)) on 2022-02-07 - Allow window, global shortcut and clipboard APIs to be called on the main thread. - [2812c446](https://www.github.com/tauri-apps/tauri/commit/2812c4464b93a365ab955935d05b5cea8cb03aab) feat(core): window, shortcut and clipboard API calls on main thread ([#2659](https://www.github.com/tauri-apps/tauri/pull/2659)) on 2021-09-26 - [d24fd8d1](https://www.github.com/tauri-apps/tauri/commit/d24fd8d10242da3da143a971d976b42ec4de6079) feat(tauri-runtime-wry): allow window creation and closing on the main thread ([#2668](https://www.github.com/tauri-apps/tauri/pull/2668)) on 2021-09-27 - Add `Menu::with_items` constructor, taking an iterator of `MenuEntry`. - [7cc95e10](https://www.github.com/tauri-apps/tauri/commit/7cc95e10ec66d8b155e9bb7f89cf73df56d1f107) feat(core): add `Menu::with_items`, closes [#2807](https://www.github.com/tauri-apps/tauri/pull/2807) ([#2966](https://www.github.com/tauri-apps/tauri/pull/2966)) on 2021-12-27 - The updater now expects signatures created with the latest CLI release. - [c2a6e8d7](https://www.github.com/tauri-apps/tauri/commit/c2a6e8d7e64284080129f09b3a0ae6cf93a87df0) chore(deps) Update Tauri Core ([#2746](https://www.github.com/tauri-apps/tauri/pull/2746)) on 2021-10-13 - Change event loop callbacks definition to allow callers to move in mutable values. - [bdbf905e](https://www.github.com/tauri-apps/tauri/commit/bdbf905e5d802b58693d2bd27582ce4269faf79c) Transformed event-loop callback to FnMut to allow mutable values ([#2667](https://www.github.com/tauri-apps/tauri/pull/2667)) on 2021-09-27 - Fixes `Notification.requestPermission()` deadlock. - [48f3768c](https://www.github.com/tauri-apps/tauri/commit/48f3768c41a2c68e2e097fcc1ef50e549c1dfb78) fix(core): `Notification.requestPermission()` deadlock regression on 2021-08-24 - Added `Window#open_devtools` API. - [55aa22de](https://www.github.com/tauri-apps/tauri/commit/55aa22de80c3de873e29bcffcb5b2fe236a637a6) feat(core): add `Window#open_devtools` API, closes [#1213](https://www.github.com/tauri-apps/tauri/pull/1213) ([#3350](https://www.github.com/tauri-apps/tauri/pull/3350)) on 2022-02-07 - Add a `plugin::Builder` struct to make plugin creation more convenient. - [9aed2996](https://www.github.com/tauri-apps/tauri/commit/9aed299621763a6e0a35d102cdf012da522dac35) feat: `plugin::Builder` closes [#2959](https://www.github.com/tauri-apps/tauri/pull/2959) ([#3005](https://www.github.com/tauri-apps/tauri/pull/3005)) on 2022-02-07 - [62c7a8ad](https://www.github.com/tauri-apps/tauri/commit/62c7a8ad30fd3031b8679960590e5ef3eef8e4da) chore(covector): prepare for `rc` release ([#3376](https://www.github.com/tauri-apps/tauri/pull/3376)) on 2022-02-10 - Added `on_event` on the `Plugin` trait, which allows a plugin to react to the event loop. - [cc2f39a2](https://www.github.com/tauri-apps/tauri/commit/cc2f39a29fc8852724aa3954ff0d42a36484929b) feat(core): add `on_event` hook on the `Plugin` trait ([#2656](https://www.github.com/tauri-apps/tauri/pull/2656)) on 2021-09-26 - Prevent path traversal on the file system APIs. - [4d89f60d](https://www.github.com/tauri-apps/tauri/commit/4d89f60d77a2abe7f3358cec00e15ecacf5e1148) refactor(core): prevent path traversal \[TRI-012] ([#35](https://www.github.com/tauri-apps/tauri/pull/35)) on 2021-12-06 - **Breaking change:** Add `macos-private-api` feature flag, enabled via `tauri.conf.json > tauri > macOSPrivateApi`. - [6ac21b3c](https://www.github.com/tauri-apps/tauri/commit/6ac21b3cef7f14358df38cc69ea3d277011accaf) feat: add private api feature flag ([#7](https://www.github.com/tauri-apps/tauri/pull/7)) on 2022-01-09 - Add `raw_headers` to `tauri::api::http::ResponseData`. - [b7a2345b](https://www.github.com/tauri-apps/tauri/commit/b7a2345b06ca0306988b4ba3d3deadd449e65af9) feat(core): add raw headers to HTTP API, closes [#2695](https://www.github.com/tauri-apps/tauri/pull/2695) ([#3053](https://www.github.com/tauri-apps/tauri/pull/3053)) on 2022-01-07 - Implement `raw_window_handle::RawWindowHandle` for `tauri::Window` on `Windows` and `macOS`. The `tauri::api::dialog::window_parent` function was removed since now you can use the window directly. - [e98c1af4](https://www.github.com/tauri-apps/tauri/commit/e98c1af44279a5ff6c8a6f0a506ecc219c9f77af) feat(core): expose message dialog APIs, fix window.confirm, implement HasRawWindowHandle for Window, closes [#2535](https://www.github.com/tauri-apps/tauri/pull/2535) ([#2700](https://www.github.com/tauri-apps/tauri/pull/2700)) on 2021-10-02 - Refactor `create_tao_window` API to return `Weak` instead of `Arc`. - [c1494b35](https://www.github.com/tauri-apps/tauri/commit/c1494b353233c6a9552d7ace962fdf8d5b1f199a) refactor: return Weak on create_tao_window on 2021-08-31 - Added the `tauri::api::dialog::blocking` module. - [4818531a](https://www.github.com/tauri-apps/tauri/commit/4818531aba47e126af91253d5d0eae3972b27d4c) refactor(core): add blocking dialog APIs, improve docs, closes [#3255](https://www.github.com/tauri-apps/tauri/pull/3255) ([#3270](https://www.github.com/tauri-apps/tauri/pull/3270)) on 2022-02-05 - The notification endpoint now checks for the permission flag and requests if the value is not set. - [239bba56](https://www.github.com/tauri-apps/tauri/commit/239bba56666c96acce24f30851f2d0719c95fc2c) refactor(core): check notification permission on the Rust endpoint \[TRI-017] ([#23](https://www.github.com/tauri-apps/tauri/pull/23)) on 2022-01-09 - **Breaking change:** The `WindowEvent::CloseRequested` variant now includes `label` and `signal_tx` fields to allow preventing closing the window. - [74dff536](https://www.github.com/tauri-apps/tauri/commit/74dff536d4757820e68ab05301be83c0870c22ed) fix(core): emit `tauri://close-requested` to JS, closes [#2996](https://www.github.com/tauri-apps/tauri/pull/2996) ([#3041](https://www.github.com/tauri-apps/tauri/pull/3041)) on 2021-12-09 - **Breaking change:** Move `__currentWindow` and `__windows` values from `window.__TAURI__` to `window.__TAURI_METADATA__`. - [f5109e0c](https://www.github.com/tauri-apps/tauri/commit/f5109e0c962e3d25404995194968bade1be33b16) fix(api): window label null instead of actual value, closes [#3295](https://www.github.com/tauri-apps/tauri/pull/3295) ([#3332](https://www.github.com/tauri-apps/tauri/pull/3332)) on 2022-02-04 - Remove the `BaseDirectory::Current` enum variant for security reasons. - [696dca58](https://www.github.com/tauri-apps/tauri/commit/696dca58a9f8ee127a1cf857eb848e09f5845d18) refactor(core): remove `BaseDirectory::Current` variant on 2022-01-26 - **Breaking change:** Remove default webview window when `tauri.conf.json > tauri > windows` is not set. - [c119060e](https://www.github.com/tauri-apps/tauri/commit/c119060e3d9a5a824639fb6b3c45a87e7a62e4e2) refactor(core): empty default value for config > tauri > windows ([#3380](https://www.github.com/tauri-apps/tauri/pull/3380)) on 2022-02-10 - **Breaking change:** Renamed the `rpc` module to `ipc`. - [3420aa50](https://www.github.com/tauri-apps/tauri/commit/3420aa5031b3274a95c6c5fa0f8683ca13213396) refactor: IPC handler \[TRI-019] ([#9](https://www.github.com/tauri-apps/tauri/pull/9)) on 2022-01-09 - Expose `run_on_main_thread` APIs on `Window` and `AppHandle`. - [53fdfe52](https://www.github.com/tauri-apps/tauri/commit/53fdfe52bb30d52653c72ca9f42506c3863dcf4a) feat(core): expose `run_on_main_thread` API ([#2711](https://www.github.com/tauri-apps/tauri/pull/2711)) on 2021-10-04 - The minimum Rust version is now `1.56`. - [a9dfc015](https://www.github.com/tauri-apps/tauri/commit/a9dfc015505afe91281c2027954ffcc588b1a59c) feat: update to edition 2021 and set minimum rust to 1.56 ([#2789](https://www.github.com/tauri-apps/tauri/pull/2789)) on 2021-10-22 - The minimum Rust version is now 1.57. - [d5d6d2ab](https://www.github.com/tauri-apps/tauri/commit/d5d6d2abc17cd89c3a079d2ce01581193469dbc0) Isolation Pattern ([#43](https://www.github.com/tauri-apps/tauri/pull/43)) Co-authored-by: Ngo Iok Ui (Wu Yu Wei) Co-authored-by: Lucas Fernandes Nogueira on 2022-01-17 - Scopes the `filesystem` APIs from the webview access using `tauri.conf.json > tauri > allowlist > fs > scope`. Scopes the `asset` protocol access using `tauri.conf.json > tauri > allowlist > protocol > assetScope`. Scopes the `http` APIs from the webview access using `tauri.conf.json > tauri > allowlist > http > scope`. Scopes the `shell` execute API from the webview access using `tauri.conf.json > tauri > allowlist > shell > scope`. Additionally, check the `tauri.conf.json > tauri > bundle > externalBin` to prevent access to unknown sidecars. - [7920ff14](https://www.github.com/tauri-apps/tauri/commit/7920ff14e6424079c48ea5645d9aa13e7a272b87) feat: scope the `fs` API and the `asset` protocol \[TRI-026] \[TRI-010] \[TRI-011] ([#10](https://www.github.com/tauri-apps/tauri/pull/10)) on 2022-01-09 - [0ad1c651](https://www.github.com/tauri-apps/tauri/commit/0ad1c6515f696fadefddbf133a9561836b3d5934) feat(core): add `http` allowlist scope \[TRI-008] ([#24](https://www.github.com/tauri-apps/tauri/pull/24)) on 2021-10-29 - [d4db95e7](https://www.github.com/tauri-apps/tauri/commit/d4db95e7161e064d9463bc84d871a5391c3ce2d7) feat(core): shell execute API scope \[TRI-002] ([#36](https://www.github.com/tauri-apps/tauri/pull/36)) on 2021-12-01 - `Builder#setup` closure type changed from `Fn` to `FnOnce`. - [3f3599b9](https://www.github.com/tauri-apps/tauri/commit/3f3599b9cc238da06b36aff4c120a013a97fc3f0) refactor(core): change `setup` closure type to `FnOnce`, closes [#3061](https://www.github.com/tauri-apps/tauri/pull/3061) ([#3065](https://www.github.com/tauri-apps/tauri/pull/3065)) on 2021-12-27 - The `tauri::api::shell::open`'s `with` argument is now an enum value instead of any string. - [63921fad](https://www.github.com/tauri-apps/tauri/commit/63921fada436f010c33bb5e647bd67c6e549571c) refactor: change `tauri::api::open` `with` argument to an enum \[TRI-022] ([#19](https://www.github.com/tauri-apps/tauri/pull/19)) on 2022-01-09 - The `shell` allowlist now includes a `sidecar` flag, which enables the use of the `shell` API to execute sidecars. - [eed01728](https://www.github.com/tauri-apps/tauri/commit/eed017287fed2ade689af4268e8b63b9c9f2e585) feat(core): add `shell > sidecar` allowlist and `process` feature flag \[TRI-037] ([#18](https://www.github.com/tauri-apps/tauri/pull/18)) on 2021-10-24 - **Breaking change:** The sidecar's target triple suffix is now removed at build time. - [3035e458](https://www.github.com/tauri-apps/tauri/commit/3035e4581c161ec7f0bd6d9b42e9015cf1dd1d77) Remove target triple from sidecar bin paths, closes [#3355](https://www.github.com/tauri-apps/tauri/pull/3355) ([#3356](https://www.github.com/tauri-apps/tauri/pull/3356)) on 2022-02-07 - Fix streaming of small files using the `asset` protocol. - [151e629e](https://www.github.com/tauri-apps/tauri/commit/151e629ebf15ec5c068eb623e3dbc0ecdef1f816) fix(core): streaming of small files using `asset://`, closes [#2854](https://www.github.com/tauri-apps/tauri/pull/2854) ([#3039](https://www.github.com/tauri-apps/tauri/pull/3039)) on 2021-12-09 - Add `set_menu` API on `tauri::SystemTrayHandle`. - [0e4d12b5](https://www.github.com/tauri-apps/tauri/commit/0e4d12b541652d98c5a73de65034db8214e0363c) fix: [#2502](https://www.github.com/tauri-apps/tauri/pull/2502) Expose `set_menu` from tao through the TrayHandle struct ([#2532](https://www.github.com/tauri-apps/tauri/pull/2532)) on 2021-10-02 - Adds `unlisten` function to the `Window` struct. - [3a59f5f7](https://www.github.com/tauri-apps/tauri/commit/3a59f5f79e1b3ea08a224e6f2e0a56668d96cda3) Unlisten to an event on this window ([#2664](https://www.github.com/tauri-apps/tauri/pull/2664)) on 2021-09-28 - Force updater endpoint URL to use `https` on release builds. - [c077f449](https://www.github.com/tauri-apps/tauri/commit/c077f449270cffbf7956b1af81e1fb237ebf564a) feat: force endpoint URL to use https on release \[TRI-015] ([#41](https://www.github.com/tauri-apps/tauri/pull/41)) on 2022-01-09 - Validate the `std::env::current_exe` return value if `APPDIR` or `APPIMAGE` environment variables are set. - [6fbd6dba](https://www.github.com/tauri-apps/tauri/commit/6fbd6dba5290dc017ab0ba5a44cf4358b022836f) feat(core): validate `AppImage` execution when env vars are set \[TRI-041] ([#17](https://www.github.com/tauri-apps/tauri/pull/17)) on 2021-10-24 - The event name is now validated. On a IPC message, it returns an error if it fails validation; on the Rust side, it panics. It must include only alphanumeric characters, `-`, `/`, `:` and `_`. - [a48b8b18](https://www.github.com/tauri-apps/tauri/commit/a48b8b18d428bcc404d489daa690bbefe1f57311) feat(core): validate callbacks and event names \[TRI-038] \[TRI-020] ([#21](https://www.github.com/tauri-apps/tauri/pull/21)) on 2022-01-09 - The window label is now validated and must be alphanumeric, resulting in a panic if it isn't. - [680554de](https://www.github.com/tauri-apps/tauri/commit/680554de3ef6b7fccf87c441ad355cfef7aab6fe) feat: validate window label \[TRI-021] ([#13](https://www.github.com/tauri-apps/tauri/pull/13)) on 2021-10-23 - Allow `tauri.conf.json > package > version` to specify a path to a `package.json` file and pull the version from it. - [46f2eae8](https://www.github.com/tauri-apps/tauri/commit/46f2eae8aad7c6a228eaf48480d5603dae6454b4) feat: allow config's version to be a path to package.json, closes [#2967](https://www.github.com/tauri-apps/tauri/pull/2967) ([#2971](https://www.github.com/tauri-apps/tauri/pull/2971)) on 2022-01-07 - Added `clipboard` field on the `WebviewAttributes` struct, which must be set to `true` to enable clipboard access on the webview. - [d42ccfb3](https://www.github.com/tauri-apps/tauri/commit/d42ccfb34f71851dfeb22fe74c83a8bdbddb5550) feat: add `clipboard` flag to `WebviewAttributes` \[TRI-032] ([#12](https://www.github.com/tauri-apps/tauri/pull/12)) on 2021-10-23 - Replace all of the `winapi` crate references with the `windows` crate, and replace `webview2` and `webview2-sys` with `webview2-com` and `webview2-com-sys` built with the `windows` crate. This goes along with updates to the TAO and WRY `next` branches. - [bb00d5bd](https://www.github.com/tauri-apps/tauri/commit/bb00d5bd6c9dfcb6bdd0d308dadb70e6c6aafe5c) Replace winapi with windows crate and use webview2-com instead of webview2 ([#2615](https://www.github.com/tauri-apps/tauri/pull/2615)) on 2021-09-24 - Show `Ok/Cancel` buttons instead of `Yes/No` when executing `window.confirm`. - [e98c1af4](https://www.github.com/tauri-apps/tauri/commit/e98c1af44279a5ff6c8a6f0a506ecc219c9f77af) feat(core): expose message dialog APIs, fix window.confirm, implement HasRawWindowHandle for Window, closes [#2535](https://www.github.com/tauri-apps/tauri/pull/2535) ([#2700](https://www.github.com/tauri-apps/tauri/pull/2700)) on 2021-10-02 - Update the `windows` crate to 0.25.0, which comes with pre-built libraries. WRY and Tao can both reference the same types directly from the `windows` crate instead of sharing bindings in `webview2-com-sys`. - [34be6cf3](https://www.github.com/tauri-apps/tauri/commit/34be6cf37a98ee7cbd66623ebddae08e5a6520fd) Update webview2-com and windows crates ([#2875](https://www.github.com/tauri-apps/tauri/pull/2875)) on 2021-11-11 ## \[1.0.0-beta.8] - Fix missing asset protocol path.Now the protocol is `https://asset.localhost/path/to/file` on Windows. Lunix and macOS is still `asset://path/to/file`. - [994b5325](https://www.github.com/tauri-apps/tauri/commit/994b5325dd385f564b37fe1530c5d798dc925fff) fix: missing asset protocol path ([#2484](https://www.github.com/tauri-apps/tauri/pull/2484)) on 2021-08-23 - **Breaking change:** Removed `register_uri_scheme_protocol` from the `WebviewAttributes` struct and renamed `register_global_uri_scheme_protocol` to `register_uri_scheme_protocol` on the `Builder` struct, which now takes a `Fn(&AppHandle, &http::Request) -> http::Response` closure. - [539e4489](https://www.github.com/tauri-apps/tauri/commit/539e4489e0bac7029d86917e9982ea49e02fe489) refactor: custom protocol ([#2503](https://www.github.com/tauri-apps/tauri/pull/2503)) on 2021-08-23 - Migrate to latest custom protocol allowing `Partial content` streaming and Header parsing. - [539e4489](https://www.github.com/tauri-apps/tauri/commit/539e4489e0bac7029d86917e9982ea49e02fe489) refactor: custom protocol ([#2503](https://www.github.com/tauri-apps/tauri/pull/2503)) on 2021-08-23 ## \[1.0.0-beta.7] - Cleanup application on `AppHandle#exit`. - [a54bba6c](https://www.github.com/tauri-apps/tauri/commit/a54bba6c868508844d68a9f4ea9f5519a2b94d09) fix(core): cleanup app before exit, closes [#2464](https://www.github.com/tauri-apps/tauri/pull/2464) ([#2466](https://www.github.com/tauri-apps/tauri/pull/2466)) on 2021-08-17 - Fix `raw-window-handle` dependency declaration. - [aecdfaf7](https://www.github.com/tauri-apps/tauri/commit/aecdfaf76fcf0d2820d6ce6eb7590ebe399bfa04) fix(core): `raw-window-handle` dependency, closes [#2460](https://www.github.com/tauri-apps/tauri/pull/2460) ([#2465](https://www.github.com/tauri-apps/tauri/pull/2465)) on 2021-08-17 ## \[1.0.0-beta.6] - **Breaking change:** The `tauri::async_runtime::spawn` function now returns `tauri::async_runtime::JoinHandle`. - [9aeb04fa](https://www.github.com/tauri-apps/tauri/commit/9aeb04faf40989e8fd9d3dcac1d430a9e8bd23a9) feat(core): `async_runtime` `handle` API, `spawn` returns `JoinHandle` ([#2399](https://www.github.com/tauri-apps/tauri/pull/2399)) on 2021-08-11 - **Breaking change:** Added `window_parent: Option<&Window>` as first argument to the `ask` and `message` APIs on the `tauri::api::dialog` module. - [c76f4b7d](https://www.github.com/tauri-apps/tauri/commit/c76f4b7d39a620c7710c2046bb13b140a4793881) feat(core): set parent window on ask and message dialog APIs ([#2454](https://www.github.com/tauri-apps/tauri/pull/2454)) on 2021-08-16 - Allow the `tauri::api::dialog` APIs to be executed on any secondary thread. **Breaking change:** All dialog APIs now takes a closure instead of returning the response on the function call. - [2088cd0f](https://www.github.com/tauri-apps/tauri/commit/2088cd0f24cd56ba427241136138c74bebee28f2) refactor(core): handle dialog threading internally, closes [#2223](https://www.github.com/tauri-apps/tauri/pull/2223) ([#2429](https://www.github.com/tauri-apps/tauri/pull/2429)) on 2021-08-14 - [60b1e260](https://www.github.com/tauri-apps/tauri/commit/60b1e260f511f50bbebceb6367f412c11f8dcf11) chore: adjust change file on 2021-08-16 - **Breaking change:** The `Plugin` trait `initialize` method now takes an `AppHandle` reference instead of `App`. - [c17532f7](https://www.github.com/tauri-apps/tauri/commit/c17532f7412bdcc57ae850c1251052ad1421fd67) refactor(core): change Plugin `initialize` signature, move register t… ([#2347](https://www.github.com/tauri-apps/tauri/pull/2347)) on 2021-08-03 - **Breaking change:** Remove menu feature flag since there's no package dependency need to be installed on any platform anymore. - [f81ebddf](https://www.github.com/tauri-apps/tauri/commit/f81ebddfcc1aea0d4989706aef43538e8ea98bea) feat: remove menu feature flag ([#2415](https://www.github.com/tauri-apps/tauri/pull/2415)) on 2021-08-13 - Adds `set_activation_policy` API to the `tauri::App` struct (macOS only). - [4a031add](https://www.github.com/tauri-apps/tauri/commit/4a031add69014a1f3823f4ea19b172a2557f6794) feat(core): expose `set_activation_policy`, closes [#2258](https://www.github.com/tauri-apps/tauri/pull/2258) ([#2420](https://www.github.com/tauri-apps/tauri/pull/2420)) on 2021-08-13 - Add `handle` API to `tauri::async_runtime`. - [9aeb04fa](https://www.github.com/tauri-apps/tauri/commit/9aeb04faf40989e8fd9d3dcac1d430a9e8bd23a9) feat(core): `async_runtime` `handle` API, `spawn` returns `JoinHandle` ([#2399](https://www.github.com/tauri-apps/tauri/pull/2399)) on 2021-08-11 - Assets will now fallback to `/index.html` before `/index.html`, allowing anchor links to work as expected. - [d22da650](https://www.github.com/tauri-apps/tauri/commit/d22da650ef5b51ab7dd0e45dd9527a9c5a01f84d) fix(core): fallback to `{asset}/index.html` before `index.html`, closes [#2328](https://www.github.com/tauri-apps/tauri/pull/2328) ([#2329](https://www.github.com/tauri-apps/tauri/pull/2329)) on 2021-08-02 - Fix `data-tauri-drag-region` double-click, will now respect `resizable: false` and won't maximize. - [1a510066](https://www.github.com/tauri-apps/tauri/commit/1a510066732d5f61c88c0ceed1c5f5cc559faf7d) fix(core): `data-tauri-drag-region` didn't respect resizable, closes [#2314](https://www.github.com/tauri-apps/tauri/pull/2314) ([#2316](https://www.github.com/tauri-apps/tauri/pull/2316)) on 2021-08-02 - Fix `Notification.requestPermission()` throwing `Unhandled Promise Rejection: TypeError: undefined is not a function (near '...window.__TAURI__.invoke...')` - [cf9f6aa1](https://www.github.com/tauri-apps/tauri/commit/cf9f6aa148db31c6fd4e3571b301db18654a1249) fix(core): fix typo in notifications, closes [#2330](https://www.github.com/tauri-apps/tauri/pull/2330) ([#2331](https://www.github.com/tauri-apps/tauri/pull/2331)) on 2021-08-02 - Fix blur/focus events being incorrect on Windows. - [d832d575](https://www.github.com/tauri-apps/tauri/commit/d832d575d9b03a0ff78accabe4631cc638c08c3b) fix(windows): use webview events on windows ([#2277](https://www.github.com/tauri-apps/tauri/pull/2277)) on 2021-07-23 - Move items which `tauri::api` re-exports from `tauri-utils` to individual module `utils`. Because these items has their own Error/Result types which are not related to api module at all. - [12642a1a](https://www.github.com/tauri-apps/tauri/commit/12642a1ad42b23d8d4e31ae67cb8de287ba526c0) doc: update doc in tauri-utils and tauri ([#2435](https://www.github.com/tauri-apps/tauri/pull/2435)) on 2021-08-15 - [cd55d671](https://www.github.com/tauri-apps/tauri/commit/cd55d671498d48cf83ae603c4241031b9827119b) doc: update tauri documentations ([#2446](https://www.github.com/tauri-apps/tauri/pull/2446)) on 2021-08-16 - Allow registering a plugin through an `AppHandle` instance using the `plugin` method. - [5b7be813](https://www.github.com/tauri-apps/tauri/commit/5b7be8133a6a861128ad53d1202d633f7ea8c2d2) feat(core): add plugin register API on the `Manager` trait ([#2340](https://www.github.com/tauri-apps/tauri/pull/2340)) on 2021-08-02 - [c17532f7](https://www.github.com/tauri-apps/tauri/commit/c17532f7412bdcc57ae850c1251052ad1421fd67) refactor(core): change Plugin `initialize` signature, move register t… ([#2347](https://www.github.com/tauri-apps/tauri/pull/2347)) on 2021-08-03 - Embed Info.plist file contents on binary on dev. - [537ab1b6](https://www.github.com/tauri-apps/tauri/commit/537ab1b6d5a792c550a535619965c9e4126292e6) feat(core): inject src-tauri/Info.plist file on dev and merge on bundle, closes [#1570](https://www.github.com/tauri-apps/tauri/pull/1570) [#2338](https://www.github.com/tauri-apps/tauri/pull/2338) ([#2444](https://www.github.com/tauri-apps/tauri/pull/2444)) on 2021-08-15 - Add `ExitRequested` event that allows preventing the app from exiting when all windows are closed, and an `AppHandle.exit()` function to exit the app manually. - [892c63a0](https://www.github.com/tauri-apps/tauri/commit/892c63a0538f8d62680dce5848657128ad6b7af3) feat([#2287](https://www.github.com/tauri-apps/tauri/pull/2287)): Add `ExitRequested` event to let users prevent app from exiting ([#2293](https://www.github.com/tauri-apps/tauri/pull/2293)) on 2021-08-09 - Change `App.create_window()` and `AppHandle.create_window()` to accept an `Into` type instead of `String`. - [8216cba1](https://www.github.com/tauri-apps/tauri/commit/8216cba13da10b272aae8e5058b1ec2cc937e196) `App.create_window()` to accept any `Into` type (fix [#2290](https://www.github.com/tauri-apps/tauri/pull/2290)) ([#2291](https://www.github.com/tauri-apps/tauri/pull/2291)) on 2021-07-26 - Fixes `defaultPath` option on dialog API not setting the file name if it doesn't exist on Linux. - [8b2cc261](https://www.github.com/tauri-apps/tauri/commit/8b2cc2615d784100980807a520d16681819d83c7) fix(core): dialog's `defaultPath` behavior on Linux, closes [#2232](https://www.github.com/tauri-apps/tauri/pull/2232) ([#2382](https://www.github.com/tauri-apps/tauri/pull/2382)) on 2021-08-10 - Fix ES Module detection for default imports with relative paths or scoped packages and exporting of async functions. - [b2b36cfe](https://www.github.com/tauri-apps/tauri/commit/b2b36cfe8dfcccb341638a4cb6dc23a514c54148) fix(core): fixes ES Module detection for default imports with relative paths or scoped packages ([#2380](https://www.github.com/tauri-apps/tauri/pull/2380)) on 2021-08-10 - [fbf8caf5](https://www.github.com/tauri-apps/tauri/commit/fbf8caf5c419cb4fc3d123be910e094a8e8c4bef) fix(core): ESM detection when using `export async function` ([#2425](https://www.github.com/tauri-apps/tauri/pull/2425)) on 2021-08-14 - Fix `listen` calls receiving past events. - [1ecb8651](https://www.github.com/tauri-apps/tauri/commit/1ecb8651a795aa53eded31e3fb357c857dcf2ab1) fix(core): `listen` receiving past events, closes [#2323](https://www.github.com/tauri-apps/tauri/pull/2323) ([#2371](https://www.github.com/tauri-apps/tauri/pull/2371)) on 2021-08-09 - Fixes file drop events being swapped (`file-drop-hover` on drop and `file-drop` on hover). - [c2b0fe1c](https://www.github.com/tauri-apps/tauri/commit/c2b0fe1ce58e54dbcfdb63162ad17d7e6d8774d9) fix(core): fix wrong file drop events ([#2300](https://www.github.com/tauri-apps/tauri/pull/2300)) on 2021-07-31 - Fixes `app.listen_global` not receiving events emitted in javascript. - [a8c1de55](https://www.github.com/tauri-apps/tauri/commit/a8c1de5547cd3968aa238a06c410cb936391db5d) fix listen_global not listening to events with a window label ([#2272](https://www.github.com/tauri-apps/tauri/pull/2272)) on 2021-07-23 - Fixes minimum window height being used as maximum height. - [e3f99165](https://www.github.com/tauri-apps/tauri/commit/e3f9916526b226866137cb663e5cafab2b6a0e01) fix(core) minHeight being used as maxHeight ([#2247](https://www.github.com/tauri-apps/tauri/pull/2247)) on 2021-07-19 - Fixes `unlisten` calls from JavaScript removing every registered event listener. - [aa498e72](https://www.github.com/tauri-apps/tauri/commit/aa498e72614f59afcdd1f637b4e3bdf6fe00b137) fix: unlisten removes all listeners, closes [#2264](https://www.github.com/tauri-apps/tauri/pull/2264) ([#2302](https://www.github.com/tauri-apps/tauri/pull/2302)) on 2021-07-29 - Use [`Url.join()`](https://docs.rs/url/2.2.2/url/struct.Url.html#method.join) when building webview URLs in `WindowManager`, to handle edge cases and leading/trailing slashes in paths and urls. - [31685c9f](https://www.github.com/tauri-apps/tauri/commit/31685c9f9d9c2f12d3debc3189ed67e8d669f3d8) fix([#2281](https://www.github.com/tauri-apps/tauri/pull/2281)): Prevent double slashes when joining URLs ([#2282](https://www.github.com/tauri-apps/tauri/pull/2282)) on 2021-07-23 - Fixes `fs-all` feature not requiring the `base64` crate. - [9b32b939](https://www.github.com/tauri-apps/tauri/commit/9b32b93996201190d83fcad4767709774e5a0780) fix(core): `fs-all` feature not including `base64` crate, closes [#2336](https://www.github.com/tauri-apps/tauri/pull/2336) ([#2368](https://www.github.com/tauri-apps/tauri/pull/2368)) on 2021-08-08 - Update gtk and its related libraries to v0.14. This also remove requirements of `clang` as build dependency. - [63ad3039](https://www.github.com/tauri-apps/tauri/commit/63ad303903bbee7c9a7382413b342e2a05d3ea75) chore(linux): bump gtk to v0.14 ([#2361](https://www.github.com/tauri-apps/tauri/pull/2361)) on 2021-08-07 - Use `HeaderValue::from_bytes` instead of `HeaderValue::from_str` and `HeaderValue#to_bytes` instead of `HeaderValue#to_str` to improve compatibility. - [1635798a](https://www.github.com/tauri-apps/tauri/commit/1635798a669ced825577941dc66f1334c5904b43) feat(core): improve HeaderValue compatibility, closes [#2162](https://www.github.com/tauri-apps/tauri/pull/2162) ([#2438](https://www.github.com/tauri-apps/tauri/pull/2438)) on 2021-08-15 - Implement `Debug` on public API structs and enums. - [fa9341ba](https://www.github.com/tauri-apps/tauri/commit/fa9341ba18ba227735341530900714dba0f27291) feat(core): implement `Debug` on public API structs/enums, closes [#2292](https://www.github.com/tauri-apps/tauri/pull/2292) ([#2387](https://www.github.com/tauri-apps/tauri/pull/2387)) on 2021-08-11 - Adds `Resumed` and `MainEventsCleared` variants to the `Event` enum. - [6be3f433](https://www.github.com/tauri-apps/tauri/commit/6be3f4339168651fe4e003b09f7d181fd12cd5a8) feat(core): add `Resumed` and `MainEventsCleared` events, closes [#2127](https://www.github.com/tauri-apps/tauri/pull/2127) ([#2439](https://www.github.com/tauri-apps/tauri/pull/2439)) on 2021-08-15 - Panic when a dispatcher getter method (`Window`, `GlobalShortcutHandle`, `ClipboardManager` and `MenuHandle` APIs) is called on the main thread. - [50ffdc06](https://www.github.com/tauri-apps/tauri/commit/50ffdc06fbde56aba32b4291fd130104935d1408) feat(core): panic when a dispatcher getter is used on the main thread ([#2455](https://www.github.com/tauri-apps/tauri/pull/2455)) on 2021-08-16 - Use `percent_encoding::percent_decode` on the `asset` custom protocol URL before reading the file. - [9acd8301](https://www.github.com/tauri-apps/tauri/commit/9acd83017f25b5b04e97e6e98af80f3076f8dbe3) fix(core): percent decode asset protocol URL ([#2427](https://www.github.com/tauri-apps/tauri/pull/2427)) on 2021-08-14 - Keep original value on `config > package > productName` on Linux (previously converted to kebab-case). - [3f039cb8](https://www.github.com/tauri-apps/tauri/commit/3f039cb8a308b0f18deaa37d7cfb1cc50d308d0e) fix: keep original `productName` for .desktop `Name` field, closes [#2295](https://www.github.com/tauri-apps/tauri/pull/2295) ([#2384](https://www.github.com/tauri-apps/tauri/pull/2384)) on 2021-08-10 - Inject the invoke key on regular `` tags. - [d0142e87](https://www.github.com/tauri-apps/tauri/commit/d0142e87ddf5231fd46e2cbe4769bb16f3fe01e9) fix(core): invoke key injection on regular JS scripts, closes [#2342](https://www.github.com/tauri-apps/tauri/pull/2342) ([#2344](https://www.github.com/tauri-apps/tauri/pull/2344)) on 2021-08-03 - Remove salt-related APIs (no longer needed after the `__TAURI_INVOKE_KEY__` implementation). - [e2a0704c](https://www.github.com/tauri-apps/tauri/commit/e2a0704c6c7a447b628a95f8920f9bbe9feef229) refactor(core): remove salt APIs ([#2426](https://www.github.com/tauri-apps/tauri/pull/2426)) on 2021-08-14 - Update minimum Rust version to 1.54.0. - [a5394716](https://www.github.com/tauri-apps/tauri/commit/a53947160985a4f5b0ad1fbb4aa6865d6f852c66) chore: update rust to 1.54.0 ([#2434](https://www.github.com/tauri-apps/tauri/pull/2434)) on 2021-08-15 - Run the setup callback after preparing the system tray. - [1792c455](https://www.github.com/tauri-apps/tauri/commit/1792c45592cd4999af063fa89017f52a985553c1) fix(core): run setup after preparing system tray ([#2312](https://www.github.com/tauri-apps/tauri/pull/2312)) on 2021-07-28 - Fixes a consistency issue on the order of `tauri::process::Command` emitted events. - [737da872](https://www.github.com/tauri-apps/tauri/commit/737da87244cbdeb1158c93944bcb5e10bb383b31) fix(core): random shell command output order, closes [#2184](https://www.github.com/tauri-apps/tauri/pull/2184) ([#2376](https://www.github.com/tauri-apps/tauri/pull/2376)) on 2021-08-09 - Force data directory even on non-local window. - [70a19414](https://www.github.com/tauri-apps/tauri/commit/70a1941468f55f0dc09ac2e13802945891d766f4) fix(core): Force data_directory on Windows ([#2288](https://www.github.com/tauri-apps/tauri/pull/2288)) on 2021-07-23 - Allow creation of empty Window with `create_tao_window()` and management with `send_tao_window_event()` on the AppHandler. - [88080855](https://www.github.com/tauri-apps/tauri/commit/8808085541a629b8e22b612a06cef01cf9b3722e) feat(window): Allow creation of Window without `wry` ([#2321](https://www.github.com/tauri-apps/tauri/pull/2321)) on 2021-07-29 - [15566cfd](https://www.github.com/tauri-apps/tauri/commit/15566cfd64f5072fa4980a6ce5b33259958e9021) feat(core): add API to send wry window message to the event loop ([#2339](https://www.github.com/tauri-apps/tauri/pull/2339)) on 2021-08-02 - Make `ClipboardManager` and `GlobalShortcutManager` public as they are exposed in the `AppHandle`. - [6e0dbf63](https://www.github.com/tauri-apps/tauri/commit/6e0dbf639ac2c79e00fee9270a2ca8e613dc1f98) fix(core): Expose `ClipboardManager` and `GlobalShortcutManager` ([#2263](https://www.github.com/tauri-apps/tauri/pull/2263)) on 2021-08-03 - - Support [macOS tray icon template](https://developer.apple.com/documentation/appkit/nsimage/1520017-template?language=objc) to adjust automatically based on taskbar color. - Images you mark as template images should consist of only black and clear colors. You can use the alpha channel in the image to adjust the opacity of black content, however. - [426a6b49](https://www.github.com/tauri-apps/tauri/commit/426a6b49962de8faf061db2e820ac10fcbb300d6) feat(macOS): Implement tray icon template ([#2322](https://www.github.com/tauri-apps/tauri/pull/2322)) on 2021-07-29 - Add `Event::Ready` on the `run()` callback. Triggered once when the event loop is ready. - [28c6b7ad](https://www.github.com/tauri-apps/tauri/commit/28c6b7adfe98e701b158e936eafb7541ddc700e0) feat: add `Event::Ready` ([#2433](https://www.github.com/tauri-apps/tauri/pull/2433)) on 2021-08-15 - - Do not run the updater with UAC task if server don't tell us. (Allow toggling server-side) - The updater expect a field named `with_elevated_task` with a `boolean` and will not run if the task is not installed first. (windows only) - [c5761190](https://www.github.com/tauri-apps/tauri/commit/c576119013297f3731d76924a887c5c2a62c13ba) fix(updater): Run elevated task only if server tell us ([#2357](https://www.github.com/tauri-apps/tauri/pull/2357)) on 2021-08-08 - Add `try_state` API to the `Manager` trait. - [84a0e04c](https://www.github.com/tauri-apps/tauri/commit/84a0e04cbe242b2b7abb388da2d878fce10bc27d) feat(core): `try_state` API on the `Manager` trait ([#2341](https://www.github.com/tauri-apps/tauri/pull/2341)) on 2021-08-02 ## \[1.0.0-beta.5] - Allow preventing window close when the user requests it. - [8157a68a](https://www.github.com/tauri-apps/tauri/commit/8157a68af1d94de1b90a14aa44139bb123b3436b) feat(core): allow listening to event loop events & prevent window close ([#2131](https://www.github.com/tauri-apps/tauri/pull/2131)) on 2021-07-06 - Add `App#run` method with callback argument (event loop event handler). - [8157a68a](https://www.github.com/tauri-apps/tauri/commit/8157a68af1d94de1b90a14aa44139bb123b3436b) feat(core): allow listening to event loop events & prevent window close ([#2131](https://www.github.com/tauri-apps/tauri/pull/2131)) on 2021-07-06 - Fixes `data-tauri-drag-region` not firing its events. - [578610a2](https://www.github.com/tauri-apps/tauri/commit/578610a29d5cefb8df070606b7587318b14c397a) fix(core): fix drag-region not sending its events correctly ([#2196](https://www.github.com/tauri-apps/tauri/pull/2196)) on 2021-07-12 - Fix macOS `EXC_BAD_ACCESS` panic when app is code-signed. - [456a94f6](https://www.github.com/tauri-apps/tauri/commit/456a94f6637746800b9b85fc3922e82871603402) fix(macOS): updater `EXC_BAD_ACCESS` ([#2181](https://www.github.com/tauri-apps/tauri/pull/2181)) on 2021-07-12 - Fixes SVG loading on custom protocol. - [e663bdd5](https://www.github.com/tauri-apps/tauri/commit/e663bdd5938830ab4eba961e69c3985191b499dd) fix(core): svg mime type ([#2129](https://www.github.com/tauri-apps/tauri/pull/2129)) on 2021-06-30 - Expose `gtk_window` getter. - [e0a8e09c](https://www.github.com/tauri-apps/tauri/commit/e0a8e09cab6799eeb9ec524b5f7780d1e5a84299) feat(core): expose `gtk_window`, closes [#2083](https://www.github.com/tauri-apps/tauri/pull/2083) ([#2141](https://www.github.com/tauri-apps/tauri/pull/2141)) on 2021-07-02 - Inject invoke key on `script` tags with `type="module"`. - [f03eea9c](https://www.github.com/tauri-apps/tauri/commit/f03eea9c9b964709532afbc4d1dd343b3fd96081) feat(core): inject invoke key on ` ================================================ FILE: crates/tauri/test/fixture/isolation/isolation-dist/index.js ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT window.__TAURI_ISOLATION_HOOK__ = (payload, options) => { console.log('hook', payload, options) return payload } ================================================ FILE: crates/tauri/test/fixture/isolation/src-tauri/tauri.conf.json ================================================ { "$schema": "../../../../../../crates/tauri-schema-generator/schemas/config.schema.json", "identifier": "isolation.tauri.example", "build": { "frontendDist": "../dist", "devUrl": "http://localhost:4000" }, "app": { "windows": [ { "title": "Isolation Tauri App" } ], "security": { "csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self'; connect-src ipc: http://ipc.localhost", "pattern": { "use": "isolation", "options": { "dir": "../isolation-dist" } } } }, "bundle": { "active": true } } ================================================ FILE: crates/tauri/test/fixture/src-tauri/tauri.conf.json ================================================ { "$schema": "../../../../../crates/tauri-schema-generator/schemas/config.schema.json", "identifier": "studio.tauri.example", "build": { "frontendDist": "../dist", "devUrl": "http://localhost:4000" }, "app": { "windows": [ { "title": "Tauri App" } ], "security": { "csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self'; connect-src ipc: http://ipc.localhost", "headers": null } }, "bundle": { "active": true } } ================================================ FILE: crates/tauri/test/fixture/test.txt ================================================ ================================================ FILE: crates/tauri/test/updater/fixture/archives/archive.linux.tar.gz.sig ================================================ dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUldSWTRKaFRZQmJER2NJZ21zb1RObVMwZmdkQUZ2OFFxM2dYdVhLRXpSNFp1VW03Zml2THlDRldpSmJPRkYyQlQ4QzltdkYxTG5MbzdWODZwdFN4aUNoWXY1V0lMem55T3djPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjI5OTE2MjIwCWZpbGU6YXJjaGl2ZS5saW51eC50YXIuZ3oKZXExb3FCVGlxVkc3YThBVklQeVdhS0psOWROT3p4aVcwaE1ZaE9SRWVFU2lBdnRTVFd1SnJ4QjlTWW90d045UXFZZ1VROE1mUFJhUWxaUjVSaXAwREE9PQo= ================================================ FILE: crates/tauri/test/updater/fixture/archives/archive.macos.tar.gz.sig ================================================ dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUldSWTRKaFRZQmJER1VrQzlhaWFLOExCM3VoV1gxTW1IU0ZQQTZKTXN6U0MwMDEzcThyc3R3a0pmVkJrdWFhN1JCOTNpaEg5c1JhSGY0QWxROENlbTBxbFhpVTNWUWViWVFBPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjE1Mzk5ODg3CWZpbGU6Li4vLi4vdGF1cmktdXBkYXRlci90ZXN0L2ZpeHR1cmUvYXJjaGl2ZXMvYXJjaGl2ZS50YXIuZ3oKczI0cUxjM2YvMGdpMDI1ejE3ZnREQTNtdlBwR2xydW5rVFBvcUxVcUt2dVpxZkpPd1ZLT1Z1K0hZS0hjRVk3Ylg4UVQxWEtWMHJ4ZUwwSXcvZjlaQmc9PQo= ================================================ FILE: crates/tauri/test/updater/fixture/archives/archive.windows.zip.sig ================================================ dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUldUTE5QWWxkQnlZOVVZN3dSRm5KTmZPMlovQjAxdGtCN3YxYWJybFM2RzlxRm1rMnNkc20rbWRrS2d4ZlNJT0F4RUdrTFVGYWlUQVMxUE1VRk1uNW5IS2tucHNYNnRLZGdFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNTkxODg2NjIzCWZpbGU6L1VzZXJzL2RhdmlkL2Rldi90YXVyaV91cGRhdGVyL3RhdXJpLXVwZGF0ZXIvdGVzdC9maXh0dXJlL2FyY2hpdmVzL2FyY2hpdmUuemlwCkNiNkJBKzNkR2M3WFhGTDgwSnB6NnpSYUl0VUFKVFNyRTJGVEdFbVkrNXZPTHBOQU1UeWIxbTB5QVpLRTBoM1NHeGs0RGxvTFRKY0FoWmVIS2psNkJBPT0K ================================================ FILE: crates/tauri/test/updater/fixture/bad_signature/update.key ================================================ dW50cnVzdGVkIGNvbW1lbnQ6IHJzaWduIGVuY3J5cHRlZCBzZWNyZXQga2V5ClJXUlRZMEl5dGlHbTEvRFhRRis2STdlTzF3eWhOVk9LNjdGRENJMnFSREE3R2V3b3Rwb0FBQkFBQUFBQUFBQUFBQUlBQUFBQWFNZEJTNXFuVjk0bmdJMENRRXVYNG5QVzBDd1NMOWN4Q2RKRXZxRDZNakw3Y241Vkt3aTg2WGtoajJGS1owV0ZuSmo4ZXJ0ZCtyaWF0RWJObFpnd1EveDB4NzBTU2RweG9ZaUpuc3hnQ3BYVG9HNnBXUW5SZ2Q3b3dvZ3Y2UnhQZ1BQZDU3bXl6d3M9Cg== ================================================ FILE: crates/tauri/test/updater/fixture/bad_signature/update.key.pub ================================================ dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEY1OTgwQzc0UjVGNjM0Q0IKUldUTE5QWWxkQnlZOWFBK21kekU4OGgzdStleEtkeStHaFR5NjEyRHovRnlUdzAwWGJxWEU2aGYK ================================================ FILE: crates/tauri/test/updater/fixture/good_signature/update.key ================================================ dW50cnVzdGVkIGNvbW1lbnQ6IHJzaWduIGVuY3J5cHRlZCBzZWNyZXQga2V5ClJXUlRZMEl5YTBGV3JiTy9lRDZVd3NkL0RoQ1htZmExNDd3RmJaNmRMT1ZGVjczWTBKZ0FBQkFBQUFBQUFBQUFBQUlBQUFBQWdMekUzVkE4K0tWQ1hjeGt1Vkx2QnRUR3pzQjVuV0ZpM2czWXNkRm9hVUxrVnB6TUN3K1NheHJMREhQbUVWVFZRK3NIL1VsMDBHNW5ET1EzQno0UStSb21nRW4vZlpTaXIwZFh5ZmRlL1lSN0dKcHdyOUVPclVvdzFhVkxDVnZrbHM2T1o4Tk1NWEU9Cg== ================================================ FILE: crates/tauri/test/updater/fixture/good_signature/update.key.pub ================================================ dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDE5QzMxNjYwNTM5OEUwNTgKUldSWTRKaFRZQmJER1h4d1ZMYVA3dnluSjdpN2RmMldJR09hUFFlZDY0SlFqckkvRUJhZDJVZXAK ================================================ FILE: crates/tauri-build/CHANGELOG.md ================================================ # Changelog ## \[2.5.6] ### Dependencies - Upgraded to `tauri-utils@2.8.3` - Upgraded to `tauri-codegen@2.5.5` ## \[2.5.5] ### Dependencies - Upgraded to `tauri-codegen@2.5.4` ## \[2.5.4] ### Enhancements - [`2d28e3143`](https://www.github.com/tauri-apps/tauri/commit/2d28e3143ee3d97d7570ea03877aa00a0d6e47d0) ([#14632](https://www.github.com/tauri-apps/tauri/pull/14632) by [@sftse](https://www.github.com/tauri-apps/tauri/../../sftse)) Small code refactors for improved code readability. No user facing changes. ### Dependencies - Upgraded to `tauri-utils@2.8.2` - Upgraded to `tauri-codegen@2.5.3` ## \[2.5.3] ### Dependencies - Upgraded to `tauri-utils@2.8.1` - Upgraded to `tauri-codegen@2.5.2` ## \[2.5.2] ### Dependencies - Upgraded to `tauri-codegen@2.5.1` ## \[2.5.1] ### Bug Fixes - [`4b6b8690a`](https://www.github.com/tauri-apps/tauri/commit/4b6b8690ab886ebdf1307951cffbe03e31280baa) ([#14347](https://www.github.com/tauri-apps/tauri/pull/14347) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused docs.rs builds to fail. No user facing changes. ## \[2.5.0] ### New Features - [`3b4fac201`](https://www.github.com/tauri-apps/tauri/commit/3b4fac2017832d426dd07c5e24e26684eda57f7b) ([#14194](https://www.github.com/tauri-apps/tauri/pull/14194)) Add `tauri.conf.json > bundle > android > autoIncrementVersionCode` config option to automatically increment the Android version code. ### Dependencies - Upgraded to `tauri-utils@2.8.0` - Upgraded to `tauri-codegen@2.5.0` ## \[2.4.1] ### Enhancements - [`c23bec62d`](https://www.github.com/tauri-apps/tauri/commit/c23bec62d6d5724798869681aa1534423aae28e2) ([#14083](https://www.github.com/tauri-apps/tauri/pull/14083) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Tauri now ignores `macOS.minimumSystemVersion` in `tauri dev` to prevent forced rebuilds of macOS specific dependencies when using something like `rust-analyzer` at the same time as `tauri dev`. ## \[2.4.0] ### Dependencies - Upgraded to `tauri-utils@2.7.0` - Upgraded to `tauri-codegen@2.4.0` ## \[2.3.1] ### Dependencies - Upgraded to `tauri-utils@2.6.0` - Upgraded to `tauri-codegen@2.3.1` ## \[2.2.1] ### Dependencies - Upgraded to `tauri-codegen@2.3.0` - Upgraded to `tauri-utils@2.5.0` ## \[2.2.0] ### Dependencies - Upgraded to `tauri-utils@2.4.0` - Upgraded to `tauri-codegen@2.2.0` - [`48b12b440`](https://www.github.com/tauri-apps/tauri/commit/48b12b440478937c46fdfef9f9d95194be117020) Update to `tauri-utils@2.4.0` ## \[2.1.1] ### Dependencies - Upgraded to `tauri-utils@2.3.1` - Upgraded to `tauri-codegen@2.1.1` ## \[2.1.0] ### New Features - [`013f8f652`](https://www.github.com/tauri-apps/tauri/commit/013f8f652302f2d49c5ec0a075582033d8b074fb) ([#12890](https://www.github.com/tauri-apps/tauri/pull/12890) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Added `build > removeUnusedCommands` to trigger the build scripts and macros to remove unused commands based on the capabilities you defined. Note this won't be accounting for dynamically added ACLs so make sure to check it when using this. ### Performance Improvements - [`1cd8f55ee`](https://www.github.com/tauri-apps/tauri/commit/1cd8f55eed326d61860fee62ba2d2f4464bdcfcc) ([#13033](https://www.github.com/tauri-apps/tauri/pull/13033) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Don't ship global `bundle.global.js` if `app > withGlobalTauri` is set to false ### Dependencies - Upgraded to `tauri-utils@2.3.0` - Upgraded to `tauri-codegen@2.1.0` ## \[2.0.6] ### Dependencies - Upgraded to `tauri-utils@2.2.0` - Upgraded to `tauri-codegen@2.0.5` ## \[2.0.5] ### Bug Fixes - [`848d0e060`](https://www.github.com/tauri-apps/tauri/commit/848d0e060e6eb3c8e9e8175adc7896587b5a947d) ([#12270](https://www.github.com/tauri-apps/tauri/pull/12270) by [@aurelj](https://www.github.com/tauri-apps/tauri/../../aurelj)) Update `cargo_toml` to `0.21.0`. This adds compatibility with Rust's 2024 Edition. - [`cd1d026f9`](https://www.github.com/tauri-apps/tauri/commit/cd1d026f9799c26b04acb64f49e7ee0a8b193049) ([#11961](https://www.github.com/tauri-apps/tauri/pull/11961) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix tauri fails to build if the project path contains glob characters ## \[2.0.4] ### Dependencies - Upgraded to `tauri-utils@2.1.1` - Upgraded to `tauri-codegen@2.0.4` ## \[2.0.3] ### Dependencies - Upgraded to `tauri-utils@2.1.0` - Upgraded to `tauri-codegen@2.0.3` ## \[2.0.2] ### Dependencies - Upgraded to `tauri-utils@2.0.2` ## \[2.0.1] ### What's Changed - [`0ab2b3306`](https://www.github.com/tauri-apps/tauri/commit/0ab2b330644b6419f6cee1d5377bfb5cdda2ccf9) ([#11205](https://www.github.com/tauri-apps/tauri/pull/11205) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Downgrade MSRV to 1.77.2 to support Windows 7. ### Dependencies - Upgraded to `tauri-utils@2.0.1` - Upgraded to `tauri-codegen@2.0.1` ## \[2.0.0] ### What's Changed - [`382ed482b`](https://www.github.com/tauri-apps/tauri/commit/382ed482bd08157c39e62f9a0aaad8802f1092cb) Bump MSRV to 1.78. - [`637285790`](https://www.github.com/tauri-apps/tauri/commit/6372857905ae9c0aedb7f482ddf6cf9f9836c9f2) Promote to v2 stable! ### Dependencies - Upgraded to `tauri-utils@2.0.0` - Upgraded to `tauri-codegen@2.0.0` ## \[2.0.0-rc.13] ### Bug Fixes - [`1efa5e718`](https://www.github.com/tauri-apps/tauri/commit/1efa5e7184009537b688a395596c696173ae0231) ([#11099](https://www.github.com/tauri-apps/tauri/pull/11099) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Rerun build script if the platform-specific configuration file changes. ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.13` - Upgraded to `tauri-codegen@2.0.0-rc.13` ## \[2.0.0-rc.12] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.12` - Upgraded to `tauri-codegen@2.0.0-rc.12` ## \[2.0.0-rc.11] ### Bug Fixes - [`9d468774a`](https://www.github.com/tauri-apps/tauri/commit/9d468774a94b5f5210a3012db2e58dbfab4755f4) ([#10975](https://www.github.com/tauri-apps/tauri/pull/10975) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) The executable and NSIS installer on Windows will now use the `productName` config for the `FileDescription` property instead of `shortDescription`. ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.11` - Upgraded to `tauri-codegen@2.0.0-rc.11` ## \[2.0.0-rc.10] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.10` - Upgraded to `tauri-codegen@2.0.0-rc.10` ## \[2.0.0-rc.9] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.9` - Upgraded to `tauri-codegen@2.0.0-rc.9` ## \[2.0.0-rc.8] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.8` - Upgraded to `tauri-codegen@2.0.0-rc.8` ## \[2.0.0-rc.7] ### New Features - [`ad83d41cb`](https://www.github.com/tauri-apps/tauri/commit/ad83d41cb5bc3bc3611a3dbaf0e355df3021dac0) ([#10743](https://www.github.com/tauri-apps/tauri/pull/10743) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `WindowsAttributes::new_without_app_manifest` to create `WindowsAttributes` without the default manifest. ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.7` - Upgraded to `tauri-codegen@2.0.0-rc.7` ## \[2.0.0-rc.6] ### Bug Fixes - [`793ee0531`](https://www.github.com/tauri-apps/tauri/commit/793ee0531730597e6008c9c0dedabbab7a2bef53) ([#10700](https://www.github.com/tauri-apps/tauri/pull/10700) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Allow hyphens and underscores on app identifiers. ### What's Changed - [`f4d5241b3`](https://www.github.com/tauri-apps/tauri/commit/f4d5241b377d0f7a1b58100ee19f7843384634ac) ([#10731](https://www.github.com/tauri-apps/tauri/pull/10731) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Update documentation icon path. ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.6` - Upgraded to `tauri-codegen@2.0.0-rc.6` ## \[2.0.0-rc.5] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.5` - Upgraded to `tauri-codegen@2.0.0-rc.5` ## \[2.0.0-rc.4] ### Bug Fixes - [`5c335ae9a`](https://www.github.com/tauri-apps/tauri/commit/5c335ae9ad88e46c2135a557390f6e808c9a6088) ([#10648](https://www.github.com/tauri-apps/tauri/pull/10648) by [@Flakebi](https://www.github.com/tauri-apps/tauri/../../Flakebi)) Prevent build script from rerunning unnecessarily by only writing files when the content changes. - [`77844529f`](https://www.github.com/tauri-apps/tauri/commit/77844529f323434919ad6581d54cb2d97500cf4d) ([#10678](https://www.github.com/tauri-apps/tauri/pull/10678) by [@Norbiros](https://www.github.com/tauri-apps/tauri/../../Norbiros)) Correctly export `DefaultPermissionsRule` ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.4` - Upgraded to `tauri-codegen@2.0.0-rc.4` ## \[2.0.0-rc.3] ### New Features - [`0bb7b0f35`](https://www.github.com/tauri-apps/tauri/commit/0bb7b0f352960fb5111a40157c0953d19e76f1fd) ([#10559](https://www.github.com/tauri-apps/tauri/pull/10559) by [@Norbiros](https://www.github.com/tauri-apps/tauri/../../Norbiros)) Added `InlinedPlugin::default_permission` to autogenerate the default permission of an inlined plugin. ### Dependencies - Upgraded to `tauri-codegen@2.0.0-rc.3` - Upgraded to `tauri-utils@2.0.0-rc.3` ## \[2.0.0-rc.2] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.2` - Upgraded to `tauri-codegen@2.0.0-rc.2` ## \[2.0.0-rc.1] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.1` - Upgraded to `tauri-codegen@2.0.0-rc.1` ## \[2.0.0-rc.0] ### Dependencies - Upgraded to `tauri-codegen@2.0.0-rc.0` - Upgraded to `tauri-utils@2.0.0-rc.0` ## \[2.0.0-beta.19] ### Bug Fixes - [`69dcfdfe0`](https://www.github.com/tauri-apps/tauri/commit/69dcfdfe0f3b0570fcf5997267a7200087d5341b) ([#10267](https://www.github.com/tauri-apps/tauri/pull/10267) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix build script rerun-if-changed instruction if Info.plist do not exist next to tauri.conf.json. ### Dependencies - Upgraded to `tauri-codegen@2.0.0-beta.19` - Upgraded to `tauri-utils@2.0.0-beta.19` ## \[2.0.0-beta.18] ### Enhancements - [`35110dba2`](https://www.github.com/tauri-apps/tauri/commit/35110dba21d7db0f155c45da58b41c9ca4d5853c) ([#10106](https://www.github.com/tauri-apps/tauri/pull/10106)) Fix delete app data button gone on higher scaling (>= 1.5) ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.18` - Upgraded to `tauri-codegen@2.0.0-beta.18` - [`f955f7b49`](https://www.github.com/tauri-apps/tauri/commit/f955f7b4903bcea376c0a8b430736f66c8cebf56) ([#9929](https://www.github.com/tauri-apps/tauri/pull/9929)) Switch from `dirs_next` to `dirs` as `dirs_next` is now unmaintained while `dirs` is ## \[2.0.0-beta.17] ### Enhancements - [`adac2185a`](https://www.github.com/tauri-apps/tauri/commit/adac2185a3e2e65a89a3c392363c50ddde4acff2)([#9898](https://www.github.com/tauri-apps/tauri/pull/9898)) Check for Android version code before building the package in release mode. ### Bug Fixes - [`19b696b61`](https://www.github.com/tauri-apps/tauri/commit/19b696b61c95ced0f07dd7471565ad329a0badcf)([#9710](https://www.github.com/tauri-apps/tauri/pull/9710)) Avoid copying resources if the target path is the same as source. ### What's Changed - [`9ac930380`](https://www.github.com/tauri-apps/tauri/commit/9ac930380a5df3fe700e68e75df8684d261ca292)([#9850](https://www.github.com/tauri-apps/tauri/pull/9850)) Emit `cargo:rustc-check-cfg` instruction so Cargo validates custom cfg attributes on Rust 1.80 (or nightly-2024-05-05). ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.17` - Upgraded to `tauri-codegen@2.0.0-beta.17` ### Breaking Changes - [`1df5cdeb0`](https://www.github.com/tauri-apps/tauri/commit/1df5cdeb06f5464e0eec4055e21b7b7bc8739eed)([#9858](https://www.github.com/tauri-apps/tauri/pull/9858)) Use `tauri.conf.json > identifier` to set the `PackageName` in Android and `BundleId` in iOS. - [`aaecb6a72`](https://www.github.com/tauri-apps/tauri/commit/aaecb6a72e5d1462967cc910c2628999997742d0)([#9890](https://www.github.com/tauri-apps/tauri/pull/9890)) Renamed `dev` function to `is_dev` ## \[2.0.0-beta.16] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.16` - Upgraded to `tauri-codegen@2.0.0-beta.16` ## \[2.0.0-beta.15] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.15` - Upgraded to `tauri-codegen@2.0.0-beta.15` ## \[2.0.0-beta.14] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.14` - Upgraded to `tauri-codegen@2.0.0-beta.14` ## \[2.0.0-beta.13] ### Bug Fixes - [`88c0ad9cf`](https://www.github.com/tauri-apps/tauri/commit/88c0ad9cf5d2f9ed65285540c26b54fb18b10137)([#9471](https://www.github.com/tauri-apps/tauri/pull/9471)) Fix tauri always rebuilding even if source code didn't change. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.13` - Upgraded to `tauri-codegen@2.0.0-beta.13` ## \[2.0.0-beta.12] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.12` - Upgraded to `tauri-codegen@2.0.0-beta.12` ## \[2.0.0-beta.11] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.11` - Upgraded to `tauri-codegen@2.0.0-beta.11` ## \[2.0.0-beta.10] ### New Features - [`e227fe02f`](https://www.github.com/tauri-apps/tauri/commit/e227fe02f986e145c0731a64693e1c830a9eb5b0)([#9156](https://www.github.com/tauri-apps/tauri/pull/9156)) Allow plugins to define (at compile time) JavaScript that are initialized when `withGlobalTauri` is true. ### Enhancements - [`7213b9e47`](https://www.github.com/tauri-apps/tauri/commit/7213b9e47242bef814aa7257e0bf84631bf5fe7e)([#9124](https://www.github.com/tauri-apps/tauri/pull/9124)) Fallback to an empty permission set if the plugin did not define its `default` permissions. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.10` - Upgraded to `tauri-codegen@2.0.0-beta.10` ## \[2.0.0-beta.9] ### Dependencies - Upgraded to `tauri-codegen@2.0.0-beta.9` - Upgraded to `tauri-utils@2.0.0-beta.9` ## \[2.0.0-beta.8] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.8` - Upgraded to `tauri-codegen@2.0.0-beta.8` ## \[2.0.0-beta.7] ### Bug Fixes - [`bb23511ea`](https://www.github.com/tauri-apps/tauri/commit/bb23511ea80bcaffbdebf057301e463fff268c90)([#9079](https://www.github.com/tauri-apps/tauri/pull/9079)) Fixed generation of capability schema for permissions field which previously disallowed mixed (strings and objects) permission definition. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.7` - Upgraded to `tauri-codegen@2.0.0-beta.7` ## \[2.0.0-beta.6] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.6` - Upgraded to `tauri-codegen@2.0.0-beta.6` ### Breaking Changes - [`3657ad82`](https://www.github.com/tauri-apps/tauri/commit/3657ad82f88ce528551d032d521c52eed3f396b4)([#9008](https://www.github.com/tauri-apps/tauri/pull/9008)) Allow defining permissions for the application commands via `tauri_build::Attributes::app_manifest`. ## \[2.0.0-beta.5] ### Breaking Changes - [`b9e6a018`](https://www.github.com/tauri-apps/tauri/commit/b9e6a01879d9233040f3d3fab11c59e70563da7e)([#8937](https://www.github.com/tauri-apps/tauri/pull/8937)) The `custom-protocol` Cargo feature is no longer required on your application and is now ignored. To check if running on production, use `#[cfg(not(dev))]` instead of `#[cfg(feature = "custom-protocol")]`. - [`b9e6a018`](https://www.github.com/tauri-apps/tauri/commit/b9e6a01879d9233040f3d3fab11c59e70563da7e)([#8937](https://www.github.com/tauri-apps/tauri/pull/8937)) Removed `tauri_build::CodegenContext::dev()` and added `tauri_build::dev()`. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.5` - Upgraded to `tauri-codegen@2.0.0-beta.5` ## \[2.0.0-beta.4] ### Enhancements - [`b5eb6472`](https://www.github.com/tauri-apps/tauri/commit/b5eb64728aeb410d3f3068608a94762655c4690f)([#8940](https://www.github.com/tauri-apps/tauri/pull/8940)) Enable Hight DPI awareness for NSIS installer so it is not blurry on some systems. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.4` - Upgraded to `tauri-codegen@2.0.0-beta.4` ## \[2.0.0-beta.3] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.3` - Upgraded to `tauri-codegen@2.0.0-beta.3` ## \[2.0.0-beta.2] ### Enhancements - [`83a68deb`](https://www.github.com/tauri-apps/tauri/commit/83a68deb5676d39cd4728d2e140f6b46d5f787ed)([#8797](https://www.github.com/tauri-apps/tauri/pull/8797)) Added a new configuration option `tauri.conf.json > app > security > capabilities` to reference existing capabilities and inline new ones. If it is empty, all capabilities are still included preserving the current behavior. - [`edb11c13`](https://www.github.com/tauri-apps/tauri/commit/edb11c138def2e317099db432479e3ca5dbf803f)([#8781](https://www.github.com/tauri-apps/tauri/pull/8781)) Added `Attributes::plugin()` to register a plugin that is inlined in the application crate. - [`8d16a80d`](https://www.github.com/tauri-apps/tauri/commit/8d16a80d2fb2468667e7987d0cc99dbc7e3b9d0a)([#8802](https://www.github.com/tauri-apps/tauri/pull/8802)) Added `CodegenContext::capability` to include a capability file dynamically. ### Bug Fixes - [`0e8e9cd0`](https://www.github.com/tauri-apps/tauri/commit/0e8e9cd064627e734adf8f62e571dc5f4e8f4d9f)([#8906](https://www.github.com/tauri-apps/tauri/pull/8906)) Fixes the capability schema not resolving inner definitions. - [`19fb5f0b`](https://www.github.com/tauri-apps/tauri/commit/19fb5f0b20479885bf8bc4fdd8c431052420191d)([#8782](https://www.github.com/tauri-apps/tauri/pull/8782)) Fix generating invalid schema files. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.2` - Upgraded to `tauri-codegen@2.0.0-beta.2` ## \[2.0.0-beta.1] ### Enhancements - [`4e101f80`](https://www.github.com/tauri-apps/tauri/commit/4e101f801657e7d01ce8c22f9c6468067d0caab2)([#8756](https://www.github.com/tauri-apps/tauri/pull/8756)) Moved the capability JSON schema to the `src-tauri/gen` folder so it's easier to track changes on the `capabilities` folder. ### Bug Fixes - [`4e101f80`](https://www.github.com/tauri-apps/tauri/commit/4e101f801657e7d01ce8c22f9c6468067d0caab2)([#8756](https://www.github.com/tauri-apps/tauri/pull/8756)) Do not trigger build script to rerun if the frontendDist directory does not exist. - [`0f2789cd`](https://www.github.com/tauri-apps/tauri/commit/0f2789cd6767e2eadbc4f7dfe32e2173e972b9a0)([#8757](https://www.github.com/tauri-apps/tauri/pull/8757)) Do not rewrite capability JSON schema if it did not change. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.1` - Upgraded to `tauri-codegen@2.0.0-beta.1` ## \[2.0.0-beta.0] ### New Features - [`74a2a603`](https://www.github.com/tauri-apps/tauri/commit/74a2a6036a5e57462f161d728cbd8a6f121028ca)([#8661](https://www.github.com/tauri-apps/tauri/pull/8661)) Implement access control list for IPC usage. ### Enhancements - [`e8d3793c`](https://www.github.com/tauri-apps/tauri/commit/e8d3793c3c34715569312a91633fde4d58d7621c)([#8732](https://www.github.com/tauri-apps/tauri/pull/8732)) Add `config-json` cargo feature flag (enabled by default) to. Disabling this feature flag will stop cargo from rebuilding when `tauri.conf.json` changes, see [#8721](https://github.com/tauri-apps/tauri/issues/8721) for more info. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.0` - Upgraded to `tauri-codegen@2.0.0-beta.0` ### Breaking Changes - [`8de308d1`](https://www.github.com/tauri-apps/tauri/commit/8de308d1bf6a855d7a26af58bd0e744938ba47d8)([#8723](https://www.github.com/tauri-apps/tauri/pull/8723)) Restructured Tauri config per [RFC#5](https://github.com/tauri-apps/rfcs/blob/f3e82a6b0c5390401e855850d47dc7b7d9afd684/texts/0005-tauri-config-restructure.md): - Moved `package.productName`, `package.version` and `tauri.bundle.identifier` fields to the top-level. - Removed `package` object. - Renamed `tauri` object to `app`. - Moved `tauri.bundle` object to the top-level. - Renamed `build.distDir` field to `frontendDist`. - Renamed `build.devPath` field to `devUrl` and will no longer accepts paths, it will only accept URLs. - Moved `tauri.pattern` to `app.security.pattern`. - Removed `tauri.bundle.updater` object, and its fields have been moved to the updater plugin under `plugins.updater` object. - Moved `build.withGlobalTauri` to `app.withGlobalTauri`. - Moved `tauri.bundle.dmg` object to `bundle.macOS.dmg`. - Moved `tauri.bundle.deb` object to `bundle.linux.deb`. - Moved `tauri.bundle.appimage` object to `bundle.linux.appimage`. - Removed all license fields from each bundle configuration object and instead added `bundle.license` and `bundle.licenseFile`. - Renamed `AppUrl` to `FrontendDist` and refactored its variants to be more explicit. - [`0cdfda28`](https://www.github.com/tauri-apps/tauri/commit/0cdfda28767701369cd774e2b20d943c6ddc9f05)([#8737](https://www.github.com/tauri-apps/tauri/pull/8737)) Moved `mobile::PluginBuilder`, `mobile::update_entitlements`, `config::plugin_config` and `mobile::update_android_manifest` to the new `tauri-plugin` crate. - [`74a2a603`](https://www.github.com/tauri-apps/tauri/commit/74a2a6036a5e57462f161d728cbd8a6f121028ca)([#8661](https://www.github.com/tauri-apps/tauri/pull/8661)) `CodegenContext::build` and `CodegenContext::try_build` have been removed, use `tauri_build::try_build(tauri_build::Attributes::new().codegen(codegen))` instead. ## \[2.0.0-alpha.14] ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.13` - Upgraded to `tauri-codegen@2.0.0-alpha.13` ## \[2.0.0-alpha.13] ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.12` - Upgraded to `tauri-codegen@2.0.0-alpha.12` ## \[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 - [`c6c59cf2`](https://www.github.com/tauri-apps/tauri/commit/c6c59cf2373258b626b00a26f4de4331765dd487) Pull changes from Tauri 1.5 release. ### Dependencies - Upgraded to `tauri-codegen@2.0.0-alpha.10` - Upgraded to `tauri-utils@2.0.0-alpha.10` ## \[2.0.0-alpha.10] ### New Features - [`880266a7`](https://www.github.com/tauri-apps/tauri/commit/880266a7f697e1fe58d685de3bb6836ce5251e92)([#8031](https://www.github.com/tauri-apps/tauri/pull/8031)) Bump the MSRV to 1.70. ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.9` - Upgraded to `tauri-codegen@2.0.0-alpha.9` ### Breaking Changes - [`ebcc21e4`](https://www.github.com/tauri-apps/tauri/commit/ebcc21e4b95f4e8c27639fb1bca545b432f52d5e)([#8057](https://www.github.com/tauri-apps/tauri/pull/8057)) Renamed the beforeDevCommand, beforeBuildCommand and beforeBundleCommand hooks environment variables from `TAURI_PLATFORM, TAURI_ARCH, TAURI_FAMILY, TAURI_PLATFORM_VERSION, TAURI_PLATFORM_TYPE and TAURI_DEBUG` to `TAURI_ENV_PLATFORM, TAURI_ENV_ARCH, TAURI_ENV_FAMILY, TAURI_ENV_PLATFORM_VERSION, TAURI_ENV_PLATFORM_TYPE and TAURI_ENV_DEBUG` to differentiate the prefix with other CLI environment variables. ## \[2.0.0-alpha.9] ### Dependencies - Upgraded to `tauri-codegen@2.0.0-alpha.8` - Upgraded to `tauri-utils@2.0.0-alpha.8` ## \[2.0.0-alpha.8] ### Bug Fixes - [`560b34dd`](https://www.github.com/tauri-apps/tauri/commit/560b34dd2a194ad62db09b3e9e41a2cfff4e5710)([#7610](https://www.github.com/tauri-apps/tauri/pull/7610)) Skip validation of the `tray-icon` feature flag. ## \[2.0.0-alpha.7] ### New Features - [`522de0e7`](https://www.github.com/tauri-apps/tauri/commit/522de0e78891d0bdf6387a5118985fc41a11baeb)([#7447](https://www.github.com/tauri-apps/tauri/pull/7447)) Added the `config::plugin_config` function to read the plugin configuration set from the CLI. - [`1e1d839e`](https://www.github.com/tauri-apps/tauri/commit/1e1d839e7e3d9496f71b6bc1336ced01f2965541)([#7450](https://www.github.com/tauri-apps/tauri/pull/7450)) Added the `mobile::update_android_manifest` function. - [`aba04fa8`](https://www.github.com/tauri-apps/tauri/commit/aba04fa823d70ff8df9bd22f8e6a25184689c3cb)([#7448](https://www.github.com/tauri-apps/tauri/pull/7448)) Added the `mobile::update_entitlements` function for iOS. ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.7` - Upgraded to `tauri-codegen@2.0.0-alpha.7` ## \[2.0.0-alpha.6] ### Bug Fixes - [`3256a372`](https://www.github.com/tauri-apps/tauri/commit/3256a37263f60eafdf5a8321458b868bff26c1b8)([#7016](https://www.github.com/tauri-apps/tauri/pull/7016)) Fixes injection of the proguard rules on the Android project. ## \[2.0.0-alpha.5] - [`3188f376`](https://www.github.com/tauri-apps/tauri/commit/3188f3764978c6d1452ee31d5a91469691e95094)([#6883](https://www.github.com/tauri-apps/tauri/pull/6883)) Bump the MSRV to 1.65. - [`2969d1cb`](https://www.github.com/tauri-apps/tauri/commit/2969d1cbba39301f9cc611d9f7d7051d80eef846)([#6773](https://www.github.com/tauri-apps/tauri/pull/6773)) Use absolute path to each Android plugin project instead of copying the files to enhance developer experience. - [`cdad6e08`](https://www.github.com/tauri-apps/tauri/commit/cdad6e083728ea61bd6fc734ef93f6306056ea2e)([#6774](https://www.github.com/tauri-apps/tauri/pull/6774)) Changed how the `tauri-android` dependency is injected. This requires the `gen/android` project to be recreated. - [`5a768d5c`](https://www.github.com/tauri-apps/tauri/commit/5a768d5ce69d6c9011c41f38a43481087c8d4921)([#6886](https://www.github.com/tauri-apps/tauri/pull/6886)) Remove `WindowsAttributes::sdk_dir`. ## \[2.0.0-alpha.4] - Added `android` configuration object under `tauri > bundle`. - Bumped due to a bump in tauri-utils. - [db4c9dc6](https://www.github.com/tauri-apps/tauri/commit/db4c9dc655e07ee2184fe04571f500f7910890cd) feat(core): add option to configure Android's minimum SDK version ([#6651](https://www.github.com/tauri-apps/tauri/pull/6651)) on 2023-04-07 ## \[2.0.0-alpha.3] - Read the `IPHONEOS_DEPLOYMENT_TARGET` environment variable to set the Swift iOS target version, defaults to 13. - [4c3b9ecf](https://www.github.com/tauri-apps/tauri/commit/4c3b9ecfdcd1a4489b1e466727f11045ef34d67a) fix(build): iOS deployment target env var is IPHONEOS_DEPLOYMENT_TARGET ([#6602](https://www.github.com/tauri-apps/tauri/pull/6602)) on 2023-03-31 ## \[2.0.0-alpha.2] - Add `mobile::PluginBuilder` for running build tasks related to Tauri plugins. - [05dad087](https://www.github.com/tauri-apps/tauri/commit/05dad0876842e2a7334431247d49365cee835d3e) feat: initial work for iOS plugins ([#6205](https://www.github.com/tauri-apps/tauri/pull/6205)) on 2023-02-11 ## \[2.0.0-alpha.1] - Refactor mobile environment variables. - [dee9460f](https://www.github.com/tauri-apps/tauri/commit/dee9460f9c9bc92e9c638e7691e616849ac2085b) feat: keep CLI alive when iOS app exits, show logs, closes [#5855](https://www.github.com/tauri-apps/tauri/pull/5855) ([#5902](https://www.github.com/tauri-apps/tauri/pull/5902)) on 2022-12-27 - Bump the MSRV to 1.64. - [7eb9aa75](https://www.github.com/tauri-apps/tauri/commit/7eb9aa75cfd6a3176d3f566fdda02d88aa529b0f) Update gtk to 0.16 ([#6155](https://www.github.com/tauri-apps/tauri/pull/6155)) on 2023-01-30 - Removed mobile logging initialization, which will be handled by `tauri-plugin-log`. - [](https://www.github.com/tauri-apps/tauri/commit/undefined) on undefined ## \[2.0.0-alpha.0] - Set environment variables used by `tauri::mobile_entry_point`. - [98904863](https://www.github.com/tauri-apps/tauri/commit/9890486321c9c79ccfb7c547fafee85b5c3ffa71) feat(core): add `mobile_entry_point` macro ([#4983](https://www.github.com/tauri-apps/tauri/pull/4983)) on 2022-08-21 - First mobile alpha release! - [fa3a1098](https://www.github.com/tauri-apps/tauri/commit/fa3a10988a03aed1b66fb17d893b1a9adb90f7cd) feat(ci): prepare 2.0.0-alpha.0 ([#5786](https://www.github.com/tauri-apps/tauri/pull/5786)) on 2022-12-08 ## \[1.5.1] ### Dependencies - Upgraded to `tauri-utils@1.5.2` - Upgraded to `tauri-codegen@1.4.2` ## \[1.5.0] ### What's Changed - [`d1e09da0`](https://www.github.com/tauri-apps/tauri/commit/d1e09da084b849b9e384fc27ed250dd17e72c7a3)([#7918](https://www.github.com/tauri-apps/tauri/pull/7918)) Bump to 1.5 due to tauri-utils dependency bump. ## \[1.4.1] ### Bug Fixes - [`5ecb46b3`](https://www.github.com/tauri-apps/tauri/commit/5ecb46b3410afd1b5c82494c1e0a91d5a358c41a)([#7773](https://www.github.com/tauri-apps/tauri/pull/7773)) Automatically set rpath on macOS if frameworks are bundled and copy frameworks to `src-tauri/target/Frameworks` for usage in development. - [`290e366a`](https://www.github.com/tauri-apps/tauri/commit/290e366ae98e9a52b1b43bfd3e285150427ebffa)([#7419](https://www.github.com/tauri-apps/tauri/pull/7419)) Correctly copy the WebView2 runtime in development when `webviewInstallMode` is used instead of `webviewFixedRuntimePath`. ### Dependencies - Upgraded to `tauri-utils@1.5.0` - Upgraded to `tauri-codegen@1.4.1` ## \[1.4.0] ### Enhancements - [`52474e47`](https://www.github.com/tauri-apps/tauri/commit/52474e479d695865299d8c8d868fb98b99731020)([#7141](https://www.github.com/tauri-apps/tauri/pull/7141)) Enhance Cargo features check. - [`af937290`](https://www.github.com/tauri-apps/tauri/commit/af93729031565a69d1fde6cf16bea3b9b6e43a65)([#6676](https://www.github.com/tauri-apps/tauri/pull/6676)) On Windows, set `LegalCopyright` and `FileDescription` file properties on the executable from `tauri.bundle.copyright` and `tauri.bundle.shortDescription`, - [`d2710e9d`](https://www.github.com/tauri-apps/tauri/commit/d2710e9d2e8fd93975ef6494512370faa8cb3b7e)([#6944](https://www.github.com/tauri-apps/tauri/pull/6944)) Unpin `time`, `ignore`, and `winnow` crate versions. Developers now have to pin crates if needed themselves. A list of crates that need pinning to adhere to Tauri's MSRV will be visible in Tauri's GitHub workflow: . ## \[1.3.0] - Bump minimum supported Rust version to 1.60. - [5fdc616d](https://www.github.com/tauri-apps/tauri/commit/5fdc616df9bea633810dcb814ac615911d77222c) feat: Use the zbus-backed of notify-rust ([#6332](https://www.github.com/tauri-apps/tauri/pull/6332)) on 2023-03-31 - Add initial support for building `nsis` bundles on non-Windows platforms. - [60e6f6c3](https://www.github.com/tauri-apps/tauri/commit/60e6f6c3f1605f3064b5bb177992530ff788ccf0) feat(bundler): Add support for creating NSIS bundles on unix hosts ([#5788](https://www.github.com/tauri-apps/tauri/pull/5788)) on 2023-01-19 - Add `WindowsAttributes::app_manifest` to specify the application manifest on Windows. - [bca09f7f](https://www.github.com/tauri-apps/tauri/commit/bca09f7f5ff1c9c5a4b51da043bdd5da668a179b) feat(tauri-build): add option to specify Windows manifest, closes [#5584](https://www.github.com/tauri-apps/tauri/pull/5584) ([#5730](https://www.github.com/tauri-apps/tauri/pull/5730)) on 2022-12-14 - Added support for Cargo's workspace inheritance for package information. The cli now also detects inherited `tauri` and `tauri-build` dependencies and disables manifest rewrites accordingly. - [cd8c074a](https://www.github.com/tauri-apps/tauri/commit/cd8c074ae6592303d3f6844a4fb6d262eae913b2) feat(cli): add support for Cargo's workspace inheritance for the package version, closes [#5070](https://www.github.com/tauri-apps/tauri/pull/5070) ([#5775](https://www.github.com/tauri-apps/tauri/pull/5775)) on 2022-12-14 - [d20a7288](https://www.github.com/tauri-apps/tauri/commit/d20a728892eee1858ab525ab6216cd721f473ab5) feat: Further improve workspace inheritance, closes [#6122](https://www.github.com/tauri-apps/tauri/pull/6122), [#5070](https://www.github.com/tauri-apps/tauri/pull/5070) ([#6144](https://www.github.com/tauri-apps/tauri/pull/6144)) on 2023-01-26 - Pin `winnow` crate to 0.4.1 to keep the 1.60 MSRV. ## \[1.2.1] - Fix `allowlist > app > show/hide` always disabled when `allowlist > app > all: false`. - Bumped due to a bump in tauri-utils. - [bb251087](https://www.github.com/tauri-apps/tauri/commit/bb2510876d0bdff736d36bf3a465cdbe4ad2b90c) fix(core): extend allowlist with `app`'s allowlist, closes [#5650](https://www.github.com/tauri-apps/tauri/pull/5650) ([#5652](https://www.github.com/tauri-apps/tauri/pull/5652)) on 2022-11-18 ## \[1.2.0] - - [7d9aa398](https://www.github.com/tauri-apps/tauri/commit/7d9aa3987efce2d697179ffc33646d086c68030c) feat: bump MSRV to 1.59 ([#5296](https://www.github.com/tauri-apps/tauri/pull/5296)) on 2022-09-28 ## \[1.1.1] - Add missing allowlist config for `set_cursor_grab`, `set_cursor_visible`, `set_cursor_icon` and `set_cursor_position` APIs. - Bumped due to a bump in tauri-utils. - [c764408d](https://www.github.com/tauri-apps/tauri/commit/c764408da7fae123edd41115bda42fa75a4731d2) fix: Add missing allowlist config for cursor apis, closes [#5207](https://www.github.com/tauri-apps/tauri/pull/5207) ([#5211](https://www.github.com/tauri-apps/tauri/pull/5211)) on 2022-09-16 ## \[1.1.0] - Rerun codegen if assets or icons change. - [ff8fd761](https://www.github.com/tauri-apps/tauri/commit/ff8fd7619ae894b70f149b192d8635d842827141) fix(tauri-build): rerun if assets or icons change ([#4910](https://www.github.com/tauri-apps/tauri/pull/4910)) on 2022-08-10 - Create the `desktop` and `mobile` cfg aliases. - [c04d0340](https://www.github.com/tauri-apps/tauri/commit/c04d0340e2f163483f3556c7aabe35322ee71e6a) feat(core): prepare build for mobile targets ([#4830](https://www.github.com/tauri-apps/tauri/pull/4830)) on 2022-08-02 - Added support to configuration files in TOML format (Tauri.toml file). - [ae83d008](https://www.github.com/tauri-apps/tauri/commit/ae83d008f9e1b89bfc8dddaca42aa5c1fbc36f6d) feat: add support to TOML config file `Tauri.toml`, closes [#4806](https://www.github.com/tauri-apps/tauri/pull/4806) ([#4813](https://www.github.com/tauri-apps/tauri/pull/4813)) on 2022-08-02 - Enhance the dialog style on Windows via the manifest dependency `Microsoft.Windows.Common-Controls v6.0.0.0`. - [5c5c42ed](https://www.github.com/tauri-apps/tauri/commit/5c5c42edb64adf4250af6891d7d226fda7d4d783) feat(build): use modern dialog styles on Windows, closes [#4709](https://www.github.com/tauri-apps/tauri/pull/4709) ([#4840](https://www.github.com/tauri-apps/tauri/pull/4840)) on 2022-08-02 - Fix root of codegen output when using the `CodegenContext` API. - [ed581950](https://www.github.com/tauri-apps/tauri/commit/ed581950ea6fd0afee47aa73fb63083d2483429f) fix(tauri-build): use `::tauri` as root for the CodegenContext ([#4894](https://www.github.com/tauri-apps/tauri/pull/4894)) on 2022-08-08 - Return an error if a sidecar is configured with the same file name as the application. - [5cc1fd0f](https://www.github.com/tauri-apps/tauri/commit/5cc1fd0f7b01b257a461d4e867ddc8cd5072ff15) feat(tauri-build): validate sidecar name, closes [#4780](https://www.github.com/tauri-apps/tauri/pull/4780) closes [#4823](https://www.github.com/tauri-apps/tauri/pull/4823) ([#4814](https://www.github.com/tauri-apps/tauri/pull/4814)) on 2022-08-02 - Only rewrite temporary icon files when the content change, avoid needless rebuilds. - [f957cbb5](https://www.github.com/tauri-apps/tauri/commit/f957cbb56ccbd8d1c047a978b4579946252a6fd2) fix(codegen): write output file when contents change ([#4889](https://www.github.com/tauri-apps/tauri/pull/4889)) on 2022-08-09 ## \[1.0.4] - Reduce the amount of allocations when converting cases. - [bc370e32](https://www.github.com/tauri-apps/tauri/commit/bc370e326810446e15b1f50fb962b980114ba16b) feat: reduce the amount of `heck`-related allocations ([#4634](https://www.github.com/tauri-apps/tauri/pull/4634)) on 2022-07-11 ## \[1.0.3] - Improve configuration deserialization error messages. - [9170c920](https://www.github.com/tauri-apps/tauri/commit/9170c9207044fa561535f624916dfdbaa41ff79d) feat(core): improve config deserialization error messages ([#4607](https://www.github.com/tauri-apps/tauri/pull/4607)) on 2022-07-06 - The `TAURI_CONFIG` environment variable now represents the configuration to be merged instead of the entire JSON. - [fa028ebf](https://www.github.com/tauri-apps/tauri/commit/fa028ebf3c8ca7b43a70d283a01dbea86217594f) refactor: do not pass entire config from CLI to core, send patch instead ([#4598](https://www.github.com/tauri-apps/tauri/pull/4598)) on 2022-07-06 ## \[1.0.2] - Expose `platform::windows_version` function. - Bumped due to a bump in tauri-utils. - [bf764e83](https://www.github.com/tauri-apps/tauri/commit/bf764e83e01e7443e6cc54572001e1c98c357465) feat(utils): expose `windows_version` function ([#4534](https://www.github.com/tauri-apps/tauri/pull/4534)) on 2022-06-30 ## \[1.0.1] - Changed the `BundleConfig::targets` to a `BundleTarget` enum to enhance generated documentation. - Bumped due to a bump in tauri-utils. - [31c15cd2](https://www.github.com/tauri-apps/tauri/commit/31c15cd2bd94dbe39fb94982a15cbe02ac5d8925) docs(config): enhance documentation for bundle targets, closes [#3251](https://www.github.com/tauri-apps/tauri/pull/3251) ([#4418](https://www.github.com/tauri-apps/tauri/pull/4418)) on 2022-06-21 - Added `platform::is_windows_7`. - Bumped due to a bump in tauri-utils. - [57039fb2](https://www.github.com/tauri-apps/tauri/commit/57039fb2166571de85271b014a8711a29f06be1a) fix(core): add windows 7 notification support ([#4491](https://www.github.com/tauri-apps/tauri/pull/4491)) on 2022-06-28 - Suppress unused variable warning in release builds. - Bumped due to a bump in tauri-utils. - [45981851](https://www.github.com/tauri-apps/tauri/commit/45981851e35119266c1a079e1ff27a39f1fdfaed) chore(lint): unused variable warnings for release builds ([#4411](https://www.github.com/tauri-apps/tauri/pull/4411)) on 2022-06-22 - Added webview install mode options. - Bumped due to a bump in tauri-utils. - [2ca762d2](https://www.github.com/tauri-apps/tauri/commit/2ca762d207030a892a6d128b519e150e2d733468) feat(bundler): extend webview2 installation options, closes [#2882](https://www.github.com/tauri-apps/tauri/pull/2882) [#2452](https://www.github.com/tauri-apps/tauri/pull/2452) ([#4466](https://www.github.com/tauri-apps/tauri/pull/4466)) on 2022-06-26 ## \[1.0.0] - Upgrade to `stable`! - [f4bb30cc](https://www.github.com/tauri-apps/tauri/commit/f4bb30cc73d6ba9b9ef19ef004dc5e8e6bb901d3) feat(covector): prepare for v1 ([#4351](https://www.github.com/tauri-apps/tauri/pull/4351)) on 2022-06-15 ## \[1.0.0-rc.15] - Read the tray icon path relatively to the config directory. - Bumped due to a bump in tauri-codegen. - [562e8ca2](https://www.github.com/tauri-apps/tauri/commit/562e8ca23facf1a8e5fa6c8cdf872357d3523a78) fix(codegen): tray icon path is relative to the config directory on 2022-06-15 ## \[1.0.0-rc.14] - Do not copy the tray icon to the output directory on Linux since it is embedded in the binary. - [4ce8e228](https://www.github.com/tauri-apps/tauri/commit/4ce8e228134cd3f22973b74ef26ca0d165fbbbd9) refactor(core): use `Icon` for tray icons ([#4342](https://www.github.com/tauri-apps/tauri/pull/4342)) on 2022-06-14 ## \[1.0.0-rc.13] - Copy `tauri.conf.json > tauri.bundle.windows.webview_fixed_runtime_path` as a resource to the target directory to fix development usage of a fixed Webview2 runtime path. - [8a634895](https://www.github.com/tauri-apps/tauri/commit/8a63489567b9fa86e404ad42b5b30c64361efe85) fix(build): fixed Webview2 runtime path in development, closes [#4308](https://www.github.com/tauri-apps/tauri/pull/4308) on 2022-06-10 - Improve usage of the GNU toolchain on Windows by copying the Webview2Loader.dll file to the target directory. - [58a6879b](https://www.github.com/tauri-apps/tauri/commit/58a6879b82e3a82027604cdd0913caacaaab5c76) feat(tauri-build): improve Windows GNU toolchain usage, closes [#4319](https://www.github.com/tauri-apps/tauri/pull/4319) ([#4323](https://www.github.com/tauri-apps/tauri/pull/4323)) on 2022-06-12 - Only statically link the VC runtime when the `STATIC_VCRUNTIME` environment variable is set to `true` (automatically done by the Tauri CLI). - [d703d27a](https://www.github.com/tauri-apps/tauri/commit/d703d27a707edc028f13b35603205da1133fcc2b) fix(build): statically link VC runtime only on `tauri build` ([#4292](https://www.github.com/tauri-apps/tauri/pull/4292)) on 2022-06-07 ## \[1.0.0-rc.12] - Statically link the Visual C++ runtime instead of using a merge module on the installer. - [bb061509](https://www.github.com/tauri-apps/tauri/commit/bb061509fb674bef86ecbc1de3aa8f3e367a9907) refactor(core): statically link vcruntime, closes [#4122](https://www.github.com/tauri-apps/tauri/pull/4122) ([#4227](https://www.github.com/tauri-apps/tauri/pull/4227)) on 2022-05-27 ## \[1.0.0-rc.11] - Create `dev` cfg alias. - [9cdcf9b3](https://www.github.com/tauri-apps/tauri/commit/9cdcf9b3a8fa27612b3156c1702a4e776627e869) feat(build): create `dev` alias ([#4212](https://www.github.com/tauri-apps/tauri/pull/4212)) on 2022-05-25 ## \[1.0.0-rc.10] - Delete existing sidecar before copying new one. - [a737f25c](https://www.github.com/tauri-apps/tauri/commit/a737f25c1078083e0b0f7f338f5c958b86914323) fix(tauri-build): delete existing sidecar file, closes [#4134](https://www.github.com/tauri-apps/tauri/pull/4134) ([#4167](https://www.github.com/tauri-apps/tauri/pull/4167)) on 2022-05-18 ## \[1.0.0-rc.9] - Search `tauri.conf.json > tauri > bundle > icons` for a `.ico` file for the window icon instead of simple default `icons/icon.ico` when `WindowsAttributes::window_icon_path` is not set. - [bad85a1f](https://www.github.com/tauri-apps/tauri/commit/bad85a1f11da03421401080531275ba201480cd1) feat(build): find .ico in config instead of default `icons/icon.ico` ([#4115](https://www.github.com/tauri-apps/tauri/pull/4115)) on 2022-05-13 ## \[1.0.0-rc.8] - Properly set file version information for the Windows executable. - [1ca2dd67](https://www.github.com/tauri-apps/tauri/commit/1ca2dd677d50b4c724c55b37060c3ba64b81c54a) fix(tauri-build): properly set executable version info on Windows ([#4045](https://www.github.com/tauri-apps/tauri/pull/4045)) on 2022-05-03 ## \[1.0.0-rc.7] - Rerun build script if `TAURI_CONFIG` environment variable change. - [7ae9e252](https://www.github.com/tauri-apps/tauri/commit/7ae9e25262376529637cd3b47b1cf84809efaec9) fix(tauri-build): rerun if `TAURI_CONFIG` env var changes on 2022-04-26 ## \[1.0.0-rc.6] - Copy system tray icon resource to the target directory on Linux. - [f2a30d8b](https://www.github.com/tauri-apps/tauri/commit/f2a30d8bc54fc3ba49e16f69a413eca5f61a9b1f) refactor(core): use ayatana appindicator by default, keep option to use gtk ([#3916](https://www.github.com/tauri-apps/tauri/pull/3916)) on 2022-04-19 ## \[1.0.0-rc.5] - Print error context on the `build` panic. - [49546c52](https://www.github.com/tauri-apps/tauri/commit/49546c5269080f38d57365788eb2592bff8f6d10) feat(build): print error context ([#3644](https://www.github.com/tauri-apps/tauri/pull/3644)) on 2022-03-09 ## \[1.0.0-rc.4] - Parse window icons at compile time. - Bumped due to a bump in tauri-codegen. - [8c935872](https://www.github.com/tauri-apps/tauri/commit/8c9358725a17dcc2acaf4d10c3f654afdff586b0) refactor(core): move `png` and `ico` behind Cargo features ([#3588](https://www.github.com/tauri-apps/tauri/pull/3588)) on 2022-03-05 ## \[1.0.0-rc.3] - Automatically emit `cargo:rustc-env=MACOSX_DEPLOYMENT_TARGET` with the value set on `tauri.conf.json > tauri > bundle > macos > minimumSystemVersion`. - [4bacea5b](https://www.github.com/tauri-apps/tauri/commit/4bacea5bf48ea5ca6c9bdd10e28e85e67a0c6ef9) feat(core): set `MACOSX_DEPLOYMENT_TARGET` environment variable, closes [#2732](https://www.github.com/tauri-apps/tauri/pull/2732) ([#3496](https://www.github.com/tauri-apps/tauri/pull/3496)) on 2022-02-17 ## \[1.0.0-rc.2] - Rerun if sidecar or resource change. - [afcc3ec5](https://www.github.com/tauri-apps/tauri/commit/afcc3ec50148074293350aaa26a05812207716be) fix(build): rerun if resource or sidecar change ([#3460](https://www.github.com/tauri-apps/tauri/pull/3460)) on 2022-02-14 ## \[1.0.0-rc.1] - Remove `cargo:rerun-if-changed` check for non-existent file that caused projects to *always* rebuild. - [65287cd6](https://www.github.com/tauri-apps/tauri/commit/65287cd6148feeba91df86217b261770fed34608) remove non-existent cargo rerun check ([#3412](https://www.github.com/tauri-apps/tauri/pull/3412)) on 2022-02-11 ## \[1.0.0-rc.0] - Allow user to specify windows sdk path in build.rs. - [59b6ee87](https://www.github.com/tauri-apps/tauri/commit/59b6ee87932d341433032befe3babd897ed8f7d0) fix(tauri-build): allow user to specify win sdk path (fix: [#2871](https://www.github.com/tauri-apps/tauri/pull/2871)) ([#2893](https://www.github.com/tauri-apps/tauri/pull/2893)) on 2021-11-16 - Adds support for using JSON5 format for the `tauri.conf.json` file, along with also supporting the `.json5` extension. Here is the logic flow that determines if JSON or JSON5 will be used to parse the config: 1. Check if `tauri.conf.json` exists a. Parse it with `serde_json` b. Parse it with `json5` if `serde_json` fails c. Return original `serde_json` error if all above steps failed 2. Check if `tauri.conf.json5` exists a. Parse it with `json5` b. Return error if all above steps failed 3. Return error if all above steps failed - [995de57a](https://www.github.com/tauri-apps/tauri/commit/995de57a76cf51215277673e526d7ec32b86b564) Add seamless support for using JSON5 in the config file ([#47](https://www.github.com/tauri-apps/tauri/pull/47)) on 2022-02-03 - Move the copying of resources and sidecars from `cli.rs` to `tauri-build` so using the Cargo CLI directly processes the files for the application execution in development. - [5eb72c24](https://www.github.com/tauri-apps/tauri/commit/5eb72c24deddf5a01093bea96b90c0d8806afc3f) refactor: copy resources and sidecars on the Cargo build script ([#3357](https://www.github.com/tauri-apps/tauri/pull/3357)) on 2022-02-08 - The minimum Rust version is now `1.56`. - [a9dfc015](https://www.github.com/tauri-apps/tauri/commit/a9dfc015505afe91281c2027954ffcc588b1a59c) feat: update to edition 2021 and set minimum rust to 1.56 ([#2789](https://www.github.com/tauri-apps/tauri/pull/2789)) on 2021-10-22 - Validate `tauri` dependency `features` under `Cargo.toml` matching `tauri.conf.json`'s `allowlist`. - [4de285c3](https://www.github.com/tauri-apps/tauri/commit/4de285c3967d32250d73acdd5d171a6fd332d2b3) feat(core): validate Cargo features matching allowlist \[TRI-023] on 2022-01-09 ## \[1.0.0-beta.4] - Implement `Debug` on public API structs and enums. - [fa9341ba](https://www.github.com/tauri-apps/tauri/commit/fa9341ba18ba227735341530900714dba0f27291) feat(core): implement `Debug` on public API structs/enums, closes [#2292](https://www.github.com/tauri-apps/tauri/pull/2292) ([#2387](https://www.github.com/tauri-apps/tauri/pull/2387)) on 2021-08-11 ## \[1.0.0-beta.3] - Improve ESM detection with regexes. - Bumped due to a bump in tauri-codegen. - [4b0ec018](https://www.github.com/tauri-apps/tauri/commit/4b0ec0188078a8fefd4119fe5e19ebc30191f802) fix(core): improve JS ESM detection ([#2139](https://www.github.com/tauri-apps/tauri/pull/2139)) on 2021-07-02 - Inject invoke key on `script` tags with `type="module"`. - Bumped due to a bump in tauri-codegen. - [f03eea9c](https://www.github.com/tauri-apps/tauri/commit/f03eea9c9b964709532afbc4d1dd343b3fd96081) feat(core): inject invoke key on `"; #[derive(Debug, Clone, Copy)] pub struct JavaScriptSource<'a> { pub source_text: &'a str, pub source_type: SourceType, /// The javascript source could be embedded in some file, /// use `start` to record start offset of js block in the original file. pub start: usize, } impl<'a> JavaScriptSource<'a> { pub fn new(source_text: &'a str, source_type: SourceType, start: usize) -> Self { Self { source_text, source_type, start, } } } pub struct PartialLoader; impl PartialLoader { /// Extract js section of specifial files. /// Returns `None` if the specifial file does not have a js section. pub fn parse<'a>(ext: &str, source_text: &'a str) -> Option>> { match ext { "vue" => Some(VuePartialLoader::new(source_text).parse()), "svelte" => Some(SveltePartialLoader::new(source_text).parse()), _ => None, } } } /// Find closing angle for situations where there is another `>` in between. /// e.g. `" let offset = script_end_finder.find(&self.source_text.as_bytes()[pointer..])?; let js_end = pointer + offset; let source_text = &self.source_text[js_start..js_end]; let source_type = SourceType::default() .with_module(true) .with_typescript(is_ts); Some(JavaScriptSource::new(source_text, source_type, js_start)) } } #[cfg(test)] mod test { use super::{JavaScriptSource, SveltePartialLoader}; fn parse_svelte(source_text: &str) -> JavaScriptSource<'_> { let sources = SveltePartialLoader::new(source_text).parse(); *sources.first().unwrap() } #[test] fn test_parse_svelte() { let source_text = r#"

Hello World

"#; let result = parse_svelte(source_text); assert_eq!(result.source_text.trim(), r#"console.log("hi");"#); } #[test] fn test_parse_svelte_ts_with_generic() { let source_text = r#"

Hello World

"#; let result = parse_svelte(source_text); assert_eq!(result.source_text.trim(), r#"console.log("hi");"#); } } ================================================ FILE: crates/tauri-cli/src/migrate/migrations/v1/frontend/partial_loader/vue.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT // taken from https://github.com/oxc-project/oxc/blob/main/crates/oxc_linter/src/partial_loader/vue.rs use memchr::memmem::Finder; use oxc_span::SourceType; use super::{find_script_closing_angle, JavaScriptSource, SCRIPT_END, SCRIPT_START}; pub struct VuePartialLoader<'a> { source_text: &'a str, } impl<'a> VuePartialLoader<'a> { pub fn new(source_text: &'a str) -> Self { Self { source_text } } pub fn parse(self) -> Vec> { self.parse_scripts() } /// Each *.vue file can contain at most /// * one `" let offset = script_end_finder.find(&self.source_text.as_bytes()[*pointer..])?; let js_end = *pointer + offset; *pointer += offset + SCRIPT_END.len(); let source_text = &self.source_text[js_start..js_end]; let source_type = SourceType::default() .with_module(true) .with_typescript(is_ts) .with_jsx(is_jsx); Some(JavaScriptSource::new(source_text, source_type, js_start)) } } #[cfg(test)] mod test { use super::{JavaScriptSource, VuePartialLoader}; fn parse_vue(source_text: &str) -> JavaScriptSource<'_> { let sources = VuePartialLoader::new(source_text).parse(); *sources.first().unwrap() } #[test] fn test_parse_vue_one_line() { let source_text = r#" "#; let result = parse_vue(source_text); assert_eq!(result.source_text, r#" console.log("hi") "#); } #[test] fn test_build_vue_with_ts_flag_1() { let source_text = r#" "#; let result = parse_vue(source_text); assert!(result.source_type.is_typescript()); assert_eq!(result.source_text.trim(), "1/1"); } #[test] fn test_build_vue_with_ts_flag_2() { let source_text = r" "; let result = parse_vue(source_text); assert!(result.source_type.is_typescript()); assert_eq!(result.source_text.trim(), "1/1"); } #[test] fn test_build_vue_with_ts_flag_3() { let source_text = r" "; let result = parse_vue(source_text); assert!(result.source_type.is_typescript()); assert_eq!(result.source_text.trim(), "1/1"); } #[test] fn test_build_vue_with_tsx_flag() { let source_text = r" "; let result = parse_vue(source_text); assert!(result.source_type.is_jsx()); assert!(result.source_type.is_typescript()); assert_eq!(result.source_text.trim(), "1/1"); } #[test] fn test_build_vue_with_escape_string() { let source_text = r" "; let result = parse_vue(source_text); assert!(!result.source_type.is_typescript()); assert_eq!(result.source_text.trim(), r"a.replace(/'/g, '\''))"); } #[test] fn test_multi_level_template_literal() { let source_text = r" "; let result = parse_vue(source_text); assert_eq!(result.source_text.trim(), r"`a${b( `c \`${d}\``)}`"); } #[test] fn test_brace_with_regex_in_template_literal() { let source_text = r" "; let result = parse_vue(source_text); assert_eq!(result.source_text.trim(), r"`${/{/}`"); } #[test] fn test_no_script() { let source_text = r" "; let sources = VuePartialLoader::new(source_text).parse(); assert!(sources.is_empty()); } #[test] fn test_syntax_error() { let source_text = r" "; let sources = VuePartialLoader::new(source_text).parse(); assert_eq!(sources.len(), 2); assert_eq!(sources[0].source_text, "a"); assert_eq!(sources[1].source_text, "b"); } #[test] fn test_unicode() { let source_text = r" "; let result = parse_vue(source_text); assert_eq!( result.source_text.trim(), "let 日历 = '2000年'; const t = useTranslate({ 'zh-CN': { calendar: '日历', tiledDisplay: '平铺展示', }, });" .trim() ); } } ================================================ FILE: crates/tauri-cli/src/migrate/migrations/v1/frontend.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use crate::{ error::Context, helpers::{app_paths::walk_builder, npm::PackageManager}, Error, ErrorExt, Result, }; use itertools::Itertools; use magic_string::MagicString; use oxc_allocator::Allocator; use oxc_ast::ast::*; use oxc_parser::Parser; use oxc_span::SourceType; use std::{fs, path::Path}; mod partial_loader; const RENAMED_MODULES: phf::Map<&str, &str> = phf::phf_map! { "tauri" => "core", "window" => "webviewWindow" }; const PLUGINIFIED_MODULES: [&str; 11] = [ "cli", "clipboard", "dialog", "fs", "globalShortcut", "http", "notification", "os", "process", "shell", "updater", ]; // (from, to) const MODULES_MAP: phf::Map<&str, &str> = phf::phf_map! { // renamed "@tauri-apps/api/tauri" => "@tauri-apps/api/core", "@tauri-apps/api/window" => "@tauri-apps/api/webviewWindow", // pluginified "@tauri-apps/api/cli" => "@tauri-apps/plugin-cli", "@tauri-apps/api/clipboard" => "@tauri-apps/plugin-clipboard-manager", "@tauri-apps/api/dialog" => "@tauri-apps/plugin-dialog", "@tauri-apps/api/fs" => "@tauri-apps/plugin-fs", "@tauri-apps/api/globalShortcut" => "@tauri-apps/plugin-global-shortcut", "@tauri-apps/api/http" => "@tauri-apps/plugin-http", "@tauri-apps/api/notification" => "@tauri-apps/plugin-notification", "@tauri-apps/api/os" => "@tauri-apps/plugin-os", "@tauri-apps/api/process" => "@tauri-apps/plugin-process", "@tauri-apps/api/shell" => "@tauri-apps/plugin-shell", "@tauri-apps/api/updater" => "@tauri-apps/plugin-updater", // v1 plugins to v2 "tauri-plugin-sql-api" => "@tauri-apps/plugin-sql", "tauri-plugin-store-api" => "@tauri-apps/plugin-store", "tauri-plugin-upload-api" => "@tauri-apps/plugin-upload", "tauri-plugin-fs-extra-api" => "@tauri-apps/plugin-fs", "tauri-plugin-fs-watch-api" => "@tauri-apps/plugin-fs", "tauri-plugin-autostart-api" => "@tauri-apps/plugin-autostart", "tauri-plugin-websocket-api" => "@tauri-apps/plugin-websocket", "tauri-plugin-positioner-api" => "@tauri-apps/plugin-positioner", "tauri-plugin-stronghold-api" => "@tauri-apps/plugin-stronghold", "tauri-plugin-window-state-api" => "@tauri-apps/plugin-window-state", "tauri-plugin-authenticator-api" => "@tauri-apps/plugin-authenticator", }; const JS_EXTENSIONS: &[&str] = &["js", "mjs", "jsx", "ts", "mts", "tsx", "svelte", "vue"]; /// Returns a list of migrated plugins pub fn migrate(frontend_dir: &Path) -> Result> { let mut new_npm_packages = Vec::new(); let mut new_plugins = Vec::new(); let mut npm_packages_to_remove = Vec::new(); let pre = env!("CARGO_PKG_VERSION_PRE"); let npm_version = if pre.is_empty() { format!("{}.0.0", env!("CARGO_PKG_VERSION_MAJOR")) } else { format!( "{}.0.0-{}.0", env!("CARGO_PKG_VERSION_MAJOR"), pre.split('.').next().unwrap() ) }; let pm = PackageManager::from_project(frontend_dir); for pkg in ["@tauri-apps/cli", "@tauri-apps/api"] { let version = pm .current_package_version(pkg, frontend_dir) .unwrap_or_default() .unwrap_or_default(); if version.starts_with('1') { new_npm_packages.push(format!("{pkg}@^{npm_version}")); } } for entry in walk_builder(frontend_dir).build().flatten() { if entry.file_type().map(|t| t.is_file()).unwrap_or_default() { let path = entry.path(); let ext = path.extension().unwrap_or_default(); if JS_EXTENSIONS.iter().any(|e| e == &ext) { let js_contents = std::fs::read_to_string(path).fs_context("failed to read JS file", path.to_path_buf())?; let new_contents = migrate_imports( path, &js_contents, &mut new_plugins, &mut npm_packages_to_remove, )?; if new_contents != js_contents { fs::write(path, new_contents) .fs_context("failed to write JS file", path.to_path_buf())?; } } } } if !npm_packages_to_remove.is_empty() { npm_packages_to_remove.sort(); npm_packages_to_remove.dedup(); pm.remove(&npm_packages_to_remove, frontend_dir) .context("Error removing npm packages")?; } if !new_npm_packages.is_empty() { new_npm_packages.sort(); new_npm_packages.dedup(); pm.install(&new_npm_packages, frontend_dir) .context("Error installing new npm packages")?; } Ok(new_plugins) } fn migrate_imports<'a>( path: &'a Path, js_source: &'a str, new_plugins: &mut Vec, npm_packages_to_remove: &mut Vec, ) -> crate::Result { let mut magic_js_source = MagicString::new(js_source); let has_partial_js = path .extension() .is_some_and(|ext| ext == "vue" || ext == "svelte"); let sources = if !has_partial_js { vec![(SourceType::from_path(path).unwrap(), js_source, 0i64)] } else { partial_loader::PartialLoader::parse( path .extension() .unwrap_or_default() .to_str() .unwrap_or_default(), js_source, ) .unwrap() .into_iter() .map(|s| (s.source_type, s.source_text, s.start as i64)) .collect() }; for (source_type, js_source, script_start) in sources { let allocator = Allocator::default(); let ret = Parser::new(&allocator, js_source, source_type).parse(); if !ret.errors.is_empty() { crate::error::bail!( "failed to parse {} as valid Javascript/Typescript file", path.display() ) } let mut program = ret.program; let mut stmts_to_add = Vec::new(); let mut imports_to_add = Vec::new(); for import in program.body.iter_mut() { if let Statement::ImportDeclaration(stmt) = import { let module = stmt.source.value.as_str(); // convert module to its pluginfied module or renamed one // import { ... } from "@tauri-apps/api/window" -> import { ... } from "@tauri-apps/api/webviewWindow" // import { ... } from "@tauri-apps/api/cli" -> import { ... } from "@tauri-apps/plugin-cli" if let Some(&new_module) = MODULES_MAP.get(module) { // +1 and -1, to skip modifying the import quotes magic_js_source .overwrite( script_start + stmt.source.span.start as i64 + 1, script_start + stmt.source.span.end as i64 - 1, new_module, Default::default(), ) .map_err(|e| { Error::Context( "failed to replace import source".to_string(), e.to_string().into(), ) })?; // if module was pluginified, add to packages if let Some(plugin_name) = new_module.strip_prefix("@tauri-apps/plugin-") { new_plugins.push(plugin_name.to_string()); } // if the module is a v1 plugin, we should remove it if module.starts_with("tauri-plugin-") { npm_packages_to_remove.push(module.to_string()); } } // skip parsing non @tauri-apps/api imports if !module.starts_with("@tauri-apps/api") { continue; } let Some(specifiers) = &mut stmt.specifiers else { continue; }; for specifier in specifiers.iter() { if let ImportDeclarationSpecifier::ImportSpecifier(specifier) = specifier { let new_identifier = match specifier.imported.name().as_str() { // migrate appWindow from: // ``` // import { appWindow } from "@tauri-apps/api/window" // ``` // to: // ``` // import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow" // const appWindow = getCurrentWebviewWindow() // ``` "appWindow" if module == "@tauri-apps/api/window" => { stmts_to_add.push("\nconst appWindow = getCurrentWebviewWindow()"); Some("getCurrentWebviewWindow") } // migrate pluginified modules from: // ``` // import { dialog, cli as superCli } from "@tauri-apps/api" // ``` // to: // ``` // import * as dialog from "@tauri-apps/plugin-dialog" // import * as cli as superCli from "@tauri-apps/plugin-cli" // ``` import if PLUGINIFIED_MODULES.contains(&import) && module == "@tauri-apps/api" => { let js_plugin: &str = MODULES_MAP[&format!("@tauri-apps/api/{import}")]; let (_, plugin_name) = js_plugin.split_once("plugin-").unwrap(); new_plugins.push(plugin_name.to_string()); if specifier.local.name.as_str() != import { let local = &specifier.local.name; imports_to_add.push(format!( "\nimport * as {import} as {local} from \"{js_plugin}\"" )); } else { imports_to_add.push(format!("\nimport * as {import} from \"{js_plugin}\"")); }; None } import if module == "@tauri-apps/api" => match RENAMED_MODULES.get(import) { Some(m) => Some(*m), None => continue, }, // nothing to do, go to next specifier _ => continue, }; // if identifier was renamed, it will be Some() // and so we convert the import // import { appWindow } from "@tauri-apps/api/window" -> import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow" if let Some(new_identifier) = new_identifier { magic_js_source .overwrite( script_start + specifier.span.start as i64, script_start + specifier.span.end as i64, new_identifier, Default::default(), ) .map_err(|e| { Error::Context( "failed to rename identifier".to_string(), e.to_string().into(), ) })?; } else { // if None, we need to remove this specifier, // it will also be replaced with an import from its new plugin below // find the next comma or the bracket ending the import let start = specifier.span.start as usize; let sliced = &js_source[start..]; let comma_or_bracket = sliced.chars().find_position(|&c| c == ',' || c == '}'); let end = match comma_or_bracket { Some((n, ',')) => n + start + 1, Some((_, '}')) => specifier.span.end as _, _ => continue, }; magic_js_source .remove(script_start + start as i64, script_start + end as i64) .map_err(|e| { Error::Context( "failed to remove identifier".to_string(), e.to_string().into(), ) })?; } } } } } // find the end of import list // fallback to the program start let start = program .body .iter() .rev() .find(|s| matches!(s, Statement::ImportDeclaration(_))) .map(|s| match s { Statement::ImportDeclaration(s) => s.span.end, _ => unreachable!(), }) .unwrap_or(program.span.start); if !imports_to_add.is_empty() { for import in imports_to_add { magic_js_source .append_right(script_start as u32 + start, &import) .map_err(|e| Error::Context("failed to add import".to_string(), e.to_string().into()))?; } } if !stmts_to_add.is_empty() { for stmt in stmts_to_add { magic_js_source .append_right(script_start as u32 + start, stmt) .map_err(|e| { Error::Context("failed to add statement".to_string(), e.to_string().into()) })?; } } } Ok(magic_js_source.to_string()) } #[cfg(test)] mod tests { use super::*; use pretty_assertions::assert_eq; #[test] fn migrates_vue() { let input = r#" "#; let expected = r#" "#; let mut new_plugins = Vec::new(); let mut npm_packages_to_remove = Vec::new(); let migrated = migrate_imports( Path::new("file.vue"), input, &mut new_plugins, &mut npm_packages_to_remove, ) .unwrap(); assert_eq!(migrated, expected); assert_eq!( new_plugins, vec![ "dialog", "cli", "dialog", "global-shortcut", "clipboard-manager", "fs" ] ); assert_eq!(npm_packages_to_remove, Vec::::new()); } #[test] fn migrates_svelte() { let input = r#"
"#; let expected = r#"
"#; let mut new_plugins = Vec::new(); let mut npm_packages_to_remove = Vec::new(); let migrated = migrate_imports( Path::new("file.svelte"), input, &mut new_plugins, &mut npm_packages_to_remove, ) .unwrap(); assert_eq!(migrated, expected); assert_eq!( new_plugins, vec![ "dialog", "cli", "dialog", "global-shortcut", "clipboard-manager", "fs" ] ); assert_eq!(npm_packages_to_remove, Vec::::new()); } #[test] fn migrates_js() { let input = r#" import { useState } from "react"; import reactLogo from "./assets/react.svg"; import { invoke, dialog, cli as superCli } from "@tauri-apps/api"; import { appWindow } from "@tauri-apps/api/window"; import { convertFileSrc } from "@tauri-apps/api/tauri"; import { open } from "@tauri-apps/api/dialog"; import { register } from "@tauri-apps/api/globalShortcut"; import clipboard from "@tauri-apps/api/clipboard"; import * as fs from "@tauri-apps/api/fs"; import { Store } from "tauri-plugin-store-api"; import Database from "tauri-plugin-sql-api"; import "./App.css"; function App() { const [greetMsg, setGreetMsg] = useState(""); const [name, setName] = useState(""); async function greet() { // Learn more about Tauri commands at https://v2.tauri.app/develop/calling-rust/#commands setGreetMsg(await invoke("greet", { name })); await open(); await dialog.save(); await convertFileSrc(""); const a = appWindow.label; superCli.getMatches(); clipboard.readText(); fs.exists(""); } return (

Welcome to Tauri!

Click on the Tauri, Vite, and React logos to learn more.

{ e.preventDefault(); greet(); }} > setName(e.currentTarget.value)} placeholder="Enter a name..." />

{greetMsg}

); } export default App; "#; let expected = r#" import { useState } from "react"; import reactLogo from "./assets/react.svg"; import { invoke, } from "@tauri-apps/api"; import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow"; import { convertFileSrc } from "@tauri-apps/api/core"; import { open } from "@tauri-apps/plugin-dialog"; import { register } from "@tauri-apps/plugin-global-shortcut"; import clipboard from "@tauri-apps/plugin-clipboard-manager"; import * as fs from "@tauri-apps/plugin-fs"; import { Store } from "@tauri-apps/plugin-store"; import Database from "@tauri-apps/plugin-sql"; import "./App.css"; import * as dialog from "@tauri-apps/plugin-dialog" import * as cli as superCli from "@tauri-apps/plugin-cli" const appWindow = getCurrentWebviewWindow() function App() { const [greetMsg, setGreetMsg] = useState(""); const [name, setName] = useState(""); async function greet() { // Learn more about Tauri commands at https://v2.tauri.app/develop/calling-rust/#commands setGreetMsg(await invoke("greet", { name })); await open(); await dialog.save(); await convertFileSrc(""); const a = appWindow.label; superCli.getMatches(); clipboard.readText(); fs.exists(""); } return (

Welcome to Tauri!

Click on the Tauri, Vite, and React logos to learn more.

{ e.preventDefault(); greet(); }} > setName(e.currentTarget.value)} placeholder="Enter a name..." />

{greetMsg}

); } export default App; "#; let mut new_plugins = Vec::new(); let mut npm_packages_to_remove = Vec::new(); let migrated = migrate_imports( Path::new("file.js"), input, &mut new_plugins, &mut npm_packages_to_remove, ) .unwrap(); assert_eq!(migrated, expected); assert_eq!( new_plugins, vec![ "dialog", "cli", "dialog", "global-shortcut", "clipboard-manager", "fs", "store", "sql" ] ); assert_eq!( npm_packages_to_remove, vec!["tauri-plugin-store-api", "tauri-plugin-sql-api"] ); } } ================================================ FILE: crates/tauri-cli/src/migrate/migrations/v1/manifest.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use crate::{ error::ErrorExt, interface::rust::manifest::{read_manifest, serialize_manifest}, Result, }; use tauri_utils::config_v1::Allowlist; use toml_edit::{DocumentMut, Entry, Item, TableLike, Value}; use std::path::Path; const CRATE_TYPES: [&str; 3] = ["lib", "staticlib", "cdylib"]; pub fn migrate(tauri_dir: &Path) -> Result<()> { let manifest_path = tauri_dir.join("Cargo.toml"); let (mut manifest, _) = read_manifest(&manifest_path)?; migrate_manifest(&mut manifest)?; std::fs::write(&manifest_path, serialize_manifest(&manifest)) .fs_context("failed to rewrite Cargo manifest", &manifest_path)?; Ok(()) } fn migrate_manifest(manifest: &mut DocumentMut) -> Result<()> { let version = dependency_version(); let remove_features = features_to_remove(); let rename_features = features_to_rename(); let rename_message = rename_features .iter() .map(|(from, to)| format!("{from} to {to}")) .collect::>() .join(", "); for (dependency, table) in [ // normal deps ("tauri", "dependencies"), ("tauri-utils", "dependencies"), ("tauri-runtime", "dependencies"), ("tauri-codegen", "dependencies"), ("tauri-macros", "dependencies"), ("tauri-runtime-wry", "dependencies"), // normal deps - plugins ("tauri-plugin-authenticator", "dependencies"), ("tauri-plugin-autostart", "dependencies"), ("tauri-plugin-fs-extra", "dependencies"), ("tauri-plugin-fs-watch", "dependencies"), ("tauri-plugin-localhost", "dependencies"), ("tauri-plugin-log", "dependencies"), ("tauri-plugin-persisted-scope", "dependencies"), ("tauri-plugin-positioner", "dependencies"), ("tauri-plugin-single-instance", "dependencies"), ("tauri-plugin-sql", "dependencies"), ("tauri-plugin-store", "dependencies"), ("tauri-plugin-stronghold", "dependencies"), ("tauri-plugin-upload", "dependencies"), ("tauri-plugin-websocket", "dependencies"), ("tauri-plugin-window-state", "dependencies"), // dev ("tauri", "dev-dependencies"), ("tauri-utils", "dev-dependencies"), ("tauri-runtime", "dev-dependencies"), ("tauri-codegen", "dev-dependencies"), ("tauri-macros", "dev-dependencies"), ("tauri-runtime-wry", "dev-dependencies"), // build ("tauri-build", "build-dependencies"), ] { let items = find_dependency(manifest, dependency, table); for item in items { // do not rewrite if dependency uses workspace inheritance if item .get("workspace") .and_then(|v| v.as_bool()) .unwrap_or_default() { log::warn!("`{dependency}` dependency has workspace inheritance enabled. This migration must be manually migrated to v2 by changing its version to {version}, removing any of the {remove_features:?} and renaming [{}] Cargo features.", rename_message); } else { migrate_dependency(item, &version, &remove_features, &rename_features); } } } if let Some(lib) = manifest .as_table_mut() .get_mut("lib") .and_then(|l| l.as_table_mut()) { match lib.entry("crate-type") { Entry::Occupied(mut e) => { if let Item::Value(Value::Array(types)) = e.get_mut() { let mut crate_types_to_add = CRATE_TYPES.to_vec(); for t in types.iter() { // type is already in the manifest, skip adding it if let Some(i) = crate_types_to_add .iter() .position(|ty| Some(ty) == t.as_str().as_ref()) { crate_types_to_add.remove(i); } } for t in crate_types_to_add { types.push(t); } } } Entry::Vacant(e) => { let mut arr = toml_edit::Array::new(); arr.extend(CRATE_TYPES.to_vec()); e.insert(Item::Value(arr.into())); } } } Ok(()) } fn find_dependency<'a>( manifest: &'a mut DocumentMut, name: &'a str, table: &'a str, ) -> Vec<&'a mut Item> { let m = manifest.as_table_mut(); for (k, v) in m.iter_mut() { if let Some(t) = v.as_table_mut() { if k == table { if let Some(item) = t.get_mut(name) { return vec![item]; } } else if k == "target" { let mut matching_deps = Vec::new(); for (_, target_value) in t.iter_mut() { if let Some(target_table) = target_value.as_table_mut() { if let Some(deps) = target_table.get_mut(table) { if let Some(item) = deps.as_table_mut().and_then(|t| t.get_mut(name)) { matching_deps.push(item); } } } } return matching_deps; } } } Vec::new() } fn features_to_rename() -> Vec<(&'static str, &'static str)> { vec![ ("window-data-url", "webview-data-url"), ("reqwest-native-tls-vendored", "native-tls-vendored"), ("system-tray", "tray-icon"), ("icon-ico", "image-ico"), ("icon-png", "image-png"), ] } fn features_to_remove() -> Vec<&'static str> { let mut features_to_remove = tauri_utils::config_v1::AllowlistConfig::all_features(); features_to_remove.extend(&[ "reqwest-client", "http-multipart", "process-command-api", "shell-open-api", "os-api", "global-shortcut", "clipboard", "dialog", "notification", "fs-extract-api", "windows7-compat", "updater", "cli", "linux-protocol-headers", "dox", ]); // this allowlist feature was not removed let index = features_to_remove .iter() .position(|x| x == &"protocol-asset") .unwrap(); features_to_remove.remove(index); features_to_remove } fn dependency_version() -> String { let pre = env!("CARGO_PKG_VERSION_PRE"); if pre.is_empty() { env!("CARGO_PKG_VERSION_MAJOR").to_string() } else { format!( "{}.0.0-{}", env!("CARGO_PKG_VERSION_MAJOR"), pre.split('.').next().unwrap() ) } } fn migrate_dependency(item: &mut Item, version: &str, remove: &[&str], rename: &[(&str, &str)]) { if let Some(dep) = item.as_table_mut() { migrate_dependency_table(dep, version, remove, rename); } else if let Some(Value::InlineTable(table)) = item.as_value_mut() { migrate_dependency_table(table, version, remove, rename); } else if item.as_str().is_some() { *item = Item::Value(version.into()); } } fn migrate_dependency_table( dep: &mut D, version: &str, remove: &[&str], rename: &[(&str, &str)], ) { dep.remove("rev"); dep.remove("git"); dep.remove("branch"); dep.remove("tag"); *dep.entry("version").or_insert(Item::None) = Item::Value(version.into()); let manifest_features = dep.entry("features").or_insert(Item::None); if let Some(features_array) = manifest_features.as_array_mut() { // remove features that shouldn't be in the manifest anymore let mut i = features_array.len(); let mut add_features = Vec::new(); while i != 0 { let index = i - 1; if let Some(f) = features_array.get(index).and_then(|f| f.as_str()) { if remove.contains(&f) { features_array.remove(index); } else if let Some((_from, rename_to)) = rename.iter().find(|(from, _to)| *from == f) { features_array.remove(index); add_features.push(rename_to); } } i -= 1; } for f in add_features { features_array.push(f.to_string()); } } } #[cfg(test)] mod tests { use itertools::Itertools; fn migrate_deps String>(get_toml: F) { let keep_features = vec!["isolation", "protocol-asset"]; let mut features = super::features_to_remove(); features.extend(keep_features.clone()); let toml = get_toml(&features); let mut manifest = toml .parse::() .expect("invalid toml"); super::migrate_manifest(&mut manifest).expect("failed to migrate manifest"); let dependencies = manifest .as_table() .get("dependencies") .expect("missing manifest dependencies") .as_table() .expect("manifest dependencies isn't a table"); let tauri = dependencies .get("tauri") .expect("missing tauri dependency in manifest"); let tauri_table = if let Some(table) = tauri.as_table() { table.clone() } else if let Some(toml_edit::Value::InlineTable(table)) = tauri.as_value() { table.clone().into_table() } else if let Some(version) = tauri.as_str() { // convert the value to a table for the assert logic below let mut table = toml_edit::Table::new(); table.insert( "version", toml_edit::Item::Value(version.to_string().into()), ); table.insert( "features", toml_edit::Item::Value(toml_edit::Value::Array(Default::default())), ); table } else { panic!("unexpected tauri dependency format"); }; // assert version matches let version = tauri_table .get("version") .expect("missing version") .as_str() .expect("version must be a string"); assert_eq!(version, super::dependency_version()); // assert features matches let features = tauri_table .get("features") .expect("missing features") .as_array() .expect("features must be an array") .clone(); if toml.contains("reqwest-native-tls-vendored") { assert!( features .iter() .any(|f| f.as_str().expect("feature must be a string") == "native-tls-vendored"), "reqwest-native-tls-vendored was not replaced with native-tls-vendored" ); } if toml.contains("system-tray") { assert!( features .iter() .any(|f| f.as_str().expect("feature must be a string") == "tray-icon"), "system-tray was not replaced with tray-icon" ); } for feature in features.iter() { let feature = feature.as_str().expect("feature must be a string"); assert!( keep_features.contains(&feature) || feature == "native-tls-vendored" || feature == "tray-icon", "feature {feature} should have been removed" ); } } #[test] fn migrate_table() { migrate_deps(|features| { format!( r#" [dependencies] tauri = {{ version = "1.0.0", features = [{}] }} "#, features.iter().map(|f| format!("{f:?}")).join(", ") ) }); } #[test] fn migrate_inline_table() { migrate_deps(|features| { format!( r#" [dependencies.tauri] version = "1.0.0" features = [{}] "#, features.iter().map(|f| format!("{f:?}")).join(", ") ) }); } #[test] fn migrate_str() { migrate_deps(|_features| { r#" [dependencies] tauri = "1.0.0" "# .into() }) } #[test] fn migrate_add_crate_types() { let toml = r#" [lib] crate-type = ["something"]"#; let mut manifest = toml .parse::() .expect("invalid toml"); super::migrate_manifest(&mut manifest).expect("failed to migrate manifest"); if let Some(crate_types) = manifest .as_table() .get("lib") .and_then(|l| l.get("crate-type")) .and_then(|c| c.as_array()) { let mut not_added_crate_types = super::CRATE_TYPES.to_vec(); for t in crate_types { let t = t.as_str().expect("crate-type must be a string"); if let Some(i) = not_added_crate_types.iter().position(|ty| ty == &t) { not_added_crate_types.remove(i); } } assert!( not_added_crate_types.is_empty(), "missing crate-type: {not_added_crate_types:?}" ); } } } ================================================ FILE: crates/tauri-cli/src/migrate/migrations/v1/mod.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use crate::{error::Context, helpers::app_paths::Dirs, Result}; mod config; mod frontend; mod manifest; pub fn run(dirs: &Dirs) -> Result<()> { let mut migrated = config::migrate(dirs.tauri).context("Could not migrate config")?; manifest::migrate(dirs.tauri).context("Could not migrate manifest")?; let plugins = frontend::migrate(dirs.frontend)?; migrated.plugins.extend(plugins); // Add plugins for plugin in migrated.plugins { crate::add::run( crate::add::Options { plugin: plugin.clone(), branch: None, tag: None, rev: None, no_fmt: false, }, dirs, ) .with_context(|| format!("Could not migrate plugin '{plugin}'"))?; } Ok(()) } ================================================ FILE: crates/tauri-cli/src/migrate/migrations/v2_beta.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use crate::{ error::{Context, ErrorExt}, helpers::{app_paths::Dirs, npm::PackageManager}, interface::rust::manifest::{read_manifest, serialize_manifest}, Result, }; use std::{fs::read_to_string, path::Path}; use toml_edit::{DocumentMut, Item, Table, TableLike, Value}; pub fn run(dirs: &Dirs) -> Result<()> { let manifest_path = dirs.tauri.join("Cargo.toml"); let (mut manifest, _) = read_manifest(&manifest_path)?; migrate_manifest(&mut manifest)?; migrate_permissions(dirs.tauri)?; migrate_npm_dependencies(dirs.frontend)?; std::fs::write(&manifest_path, serialize_manifest(&manifest)) .fs_context("failed to rewrite Cargo manifest", &manifest_path)?; Ok(()) } fn migrate_npm_dependencies(frontend_dir: &Path) -> Result<()> { let pm = PackageManager::from_project(frontend_dir); let mut install_deps = Vec::new(); for pkg in [ "@tauri-apps/cli", "@tauri-apps/api", "@tauri-apps/plugin-authenticator", "@tauri-apps/plugin-autostart", "@tauri-apps/plugin-barcode-scanner", "@tauri-apps/plugin-biometric", "@tauri-apps/plugin-cli", "@tauri-apps/plugin-clipboard-manager", "@tauri-apps/plugin-deep-link", "@tauri-apps/plugin-dialog", "@tauri-apps/plugin-fs", "@tauri-apps/plugin-global-shortcut", "@tauri-apps/plugin-http", "@tauri-apps/plugin-log", "@tauri-apps/plugin-nfc", "@tauri-apps/plugin-notification", "@tauri-apps/plugin-os", "@tauri-apps/plugin-positioner", "@tauri-apps/plugin-process", "@tauri-apps/plugin-shell", "@tauri-apps/plugin-sql", "@tauri-apps/plugin-store", "@tauri-apps/plugin-stronghold", "@tauri-apps/plugin-updater", "@tauri-apps/plugin-upload", "@tauri-apps/plugin-websocket", "@tauri-apps/plugin-window-state", ] { let version = pm .current_package_version(pkg, frontend_dir) .unwrap_or_default() .unwrap_or_default(); if version.starts_with('1') { install_deps.push(format!("{pkg}@^2.0.0")); } } if !install_deps.is_empty() { pm.install(&install_deps, frontend_dir)?; } Ok(()) } fn migrate_permissions(tauri_dir: &Path) -> Result<()> { let core_plugins = [ "app", "event", "image", "menu", "path", "resources", "tray", "webview", "window", ]; for entry in walkdir::WalkDir::new(tauri_dir.join("capabilities")) { let entry = entry.map_err(std::io::Error::other).fs_context( "failed to walk capabilities directory", tauri_dir.join("capabilities"), )?; let path = entry.path(); if path.extension().is_some_and(|ext| ext == "json") { let mut capability = read_to_string(path).fs_context("failed to read capability", path.to_path_buf())?; for plugin in core_plugins { capability = capability.replace(&format!("\"{plugin}:"), &format!("\"core:{plugin}:")); } std::fs::write(path, capability) .fs_context("failed to rewrite capability", path.to_path_buf())?; } } Ok(()) } fn migrate_manifest(manifest: &mut DocumentMut) -> Result<()> { let version = "2.0.0"; let dependencies = manifest .as_table_mut() .entry("dependencies") .or_insert(Item::Table(Table::new())) .as_table_mut() .context("manifest dependencies isn't a table")?; for dep in [ "tauri", "tauri-plugin-authenticator", "tauri-plugin-autostart", "tauri-plugin-barcode-scanner", "tauri-plugin-biometric", "tauri-plugin-cli", "tauri-plugin-clipboard-manager", "tauri-plugin-deep-link", "tauri-plugin-dialog", "tauri-plugin-fs", "tauri-plugin-global-shortcut", "tauri-plugin-http", "tauri-plugin-localhost", "tauri-plugin-log", "tauri-plugin-nfc", "tauri-plugin-notification", "tauri-plugin-os", "tauri-plugin-persisted-scope", "tauri-plugin-positioner", "tauri-plugin-process", "tauri-plugin-shell", "tauri-plugin-single-instance", "tauri-plugin-sql", "tauri-plugin-store", "tauri-plugin-stronghold", "tauri-plugin-updater", "tauri-plugin-upload", "tauri-plugin-websocket", "tauri-plugin-window-state", ] { migrate_dependency(dependencies, dep, version); } let build_dependencies = manifest .as_table_mut() .entry("build-dependencies") .or_insert(Item::Table(Table::new())) .as_table_mut() .context("manifest build-dependencies isn't a table")?; migrate_dependency(build_dependencies, "tauri-build", version); Ok(()) } fn migrate_dependency(dependencies: &mut Table, name: &str, version: &str) { let item = dependencies.entry(name).or_insert(Item::None); // do not rewrite if dependency uses workspace inheritance if item .get("workspace") .and_then(|v| v.as_bool()) .unwrap_or_default() { log::info!("`{name}` dependency has workspace inheritance enabled. The features array won't be automatically rewritten."); return; } if let Some(dep) = item.as_table_mut() { migrate_dependency_table(dep, version); } else if let Some(Value::InlineTable(table)) = item.as_value_mut() { migrate_dependency_table(table, version); } else if item.as_str().is_some() { *item = Item::Value(version.into()); } } fn migrate_dependency_table(dep: &mut D, version: &str) { *dep.entry("version").or_insert(Item::None) = Item::Value(version.into()); } ================================================ FILE: crates/tauri-cli/src/migrate/mod.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use crate::{ error::{bail, Context, ErrorExt}, helpers::cargo_manifest::{crate_version, CargoLock, CargoManifest}, interface::rust::get_workspace_dir, Result, }; use std::{fs::read_to_string, str::FromStr}; mod migrations; pub fn command() -> Result<()> { let dirs = crate::helpers::app_paths::resolve_dirs(); let manifest_contents = read_to_string(dirs.tauri.join("Cargo.toml")).fs_context( "failed to read Cargo manifest", dirs.tauri.join("Cargo.toml"), )?; let manifest = toml::from_str::(&manifest_contents).with_context(|| { format!( "failed to parse Cargo manifest {}", dirs.tauri.join("Cargo.toml").display() ) })?; let workspace_dir = get_workspace_dir(dirs.tauri)?; let lock_path = workspace_dir.join("Cargo.lock"); let lock = if lock_path.exists() { let lockfile_contents = read_to_string(&lock_path).fs_context("failed to read Cargo lockfile", &lock_path)?; let lock = toml::from_str::(&lockfile_contents) .with_context(|| format!("failed to parse Cargo lockfile {}", lock_path.display()))?; Some(lock) } else { None }; let tauri_version = crate_version(dirs.tauri, Some(&manifest), lock.as_ref(), "tauri") .version .context("failed to get tauri version")?; let tauri_version = semver::Version::from_str(&tauri_version) .with_context(|| format!("failed to parse tauri version {tauri_version}"))?; if tauri_version.major == 1 { migrations::v1::run(&dirs).context("failed to migrate from v1")?; } else if tauri_version.major == 2 { if let Some((pre, _number)) = tauri_version.pre.as_str().split_once('.') { match pre { "beta" => { migrations::v2_beta::run(&dirs).context("failed to migrate from v2 beta")?; } "alpha" => { bail!( "Migrating from v2 alpha ({tauri_version}) to v2 stable is not supported yet, \ if your project started early, try downgrading to v1 and then try again" ) } _ => { bail!("Migrating from {tauri_version} to v2 stable is not supported yet") } } } else { log::info!("Nothing to do, the tauri version is already at v2 stable"); } } Ok(()) } ================================================ FILE: crates/tauri-cli/src/mobile/android/android_studio_script.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use super::{detect_target_ok, ensure_init, env, get_app, get_config, read_options, MobileTarget}; use crate::{ error::{Context, ErrorExt}, helpers::config::{get_config as get_tauri_config, reload_config as reload_tauri_config}, interface::AppInterface, mobile::CliOptions, Error, Result, }; use clap::{ArgAction, Parser}; use cargo_mobile2::{ android::{adb, target::Target}, opts::Profile, target::{call_for_targets_with_fallback, TargetTrait}, }; use std::path::Path; #[derive(Debug, Parser)] pub struct Options { /// Targets to build. #[clap( short, long = "target", action = ArgAction::Append, num_args(0..), default_value = Target::DEFAULT_KEY, value_parser(clap::builder::PossibleValuesParser::new(Target::name_list())) )] targets: Option>, /// Builds with the release flag #[clap(short, long)] release: bool, } pub fn command(options: Options) -> Result<()> { let dirs = crate::helpers::app_paths::resolve_dirs(); let profile = if options.release { Profile::Release } else { Profile::Debug }; let mut tauri_config = get_tauri_config(tauri_utils::platform::Target::Android, &[], dirs.tauri)?; let cli_options = read_options(&tauri_config); if !cli_options.config.is_empty() { // reload config with merges from the android dev|build script reload_tauri_config( &mut tauri_config, &cli_options .config .iter() .map(|conf| &conf.0) .collect::>(), dirs.tauri, )? }; let (config, metadata) = get_config( &get_app( MobileTarget::Android, &tauri_config, &AppInterface::new(&tauri_config, None, dirs.tauri)?, dirs.tauri, ), &tauri_config, &[], &cli_options, ); ensure_init( &tauri_config, config.app(), config.project_dir(), MobileTarget::Android, std::env::var("CI").is_ok(), )?; if !cli_options.config.is_empty() { crate::helpers::config::merge_config_with( &mut tauri_config, &cli_options .config .iter() .map(|conf| &conf.0) .collect::>(), )?; } let env = env(std::env::var("CI").is_ok())?; if cli_options.dev { if let Some(url) = &tauri_config.build.dev_url { let localhost = match url.host() { Some(url::Host::Domain(d)) => d == "localhost", Some(url::Host::Ipv4(i)) => i == std::net::Ipv4Addr::LOCALHOST, _ => false, }; if localhost { if let Some(port) = url.port_or_known_default() { adb_forward_port(port, &env, &cli_options)?; } } } } let mut validated_lib = false; let installed_targets = crate::interface::rust::installation::installed_targets().unwrap_or_default(); call_for_targets_with_fallback( options.targets.unwrap_or_default().iter(), &detect_target_ok, &env, |target: &Target| { if !installed_targets.contains(&target.triple().into()) { log::info!("Installing target {}", target.triple()); target .install() .map_err(|error| Error::CommandFailed { command: "rustup target add".to_string(), error, }) .context("failed to install target")?; } target .build( &config, &metadata, &env, cli_options.noise_level, true, profile, ) .context("failed to build Android app")?; if !validated_lib { validated_lib = true; let lib_path = config .app() .target_dir(target.triple, profile) .join(config.so_name()); validate_lib(&lib_path).context("failed to validate library")?; } Ok(()) }, ) .map_err(|e| Error::GenericError(e.to_string()))? } fn validate_lib(path: &Path) -> Result<()> { let so_bytes = std::fs::read(path).fs_context("failed to read library", path.to_path_buf())?; let elf = elf::ElfBytes::::minimal_parse(&so_bytes) .context("failed to parse ELF")?; let (symbol_table, string_table) = elf .dynamic_symbol_table() .context("failed to read dynsym section")? .context("missing dynsym tables")?; let mut symbols = Vec::new(); for s in symbol_table.iter() { if let Ok(symbol) = string_table.get(s.st_name as usize) { symbols.push(symbol); } } if !symbols.contains(&"Java_app_tauri_plugin_PluginManager_handlePluginResponse") { crate::error::bail!( "Library from {} does not include required runtime symbols. This means you are likely missing the tauri::mobile_entry_point macro usage, see the documentation for more information: https://v2.tauri.app/start/migrate/from-tauri-1", path.display() ); } Ok(()) } fn adb_forward_port( port: u16, env: &cargo_mobile2::android::env::Env, cli_options: &CliOptions, ) -> Result<()> { let forward = format!("tcp:{port}"); log::info!("Forwarding port {port} with adb"); let mut devices = adb::device_list(env).unwrap_or_default(); // if we could not detect any running device, let's wait a few seconds, it might be booting up if devices.is_empty() { log::warn!( "ADB device list is empty, waiting a few seconds to see if there's any booting device..." ); let max = 5; let mut count = 0; loop { std::thread::sleep(std::time::Duration::from_secs(1)); devices = adb::device_list(env).unwrap_or_default(); if !devices.is_empty() { break; } count += 1; if count == max { break; } } } let target_device = if let Some(target_device) = &cli_options.target_device { Some((target_device.id.clone(), target_device.name.clone())) } else if devices.len() == 1 { let device = devices.first().unwrap(); Some((device.serial_no().to_string(), device.name().to_string())) } else if devices.len() > 1 { crate::error::bail!("Multiple Android devices are connected ({}), please disconnect devices you do not intend to use so Tauri can determine which to use", devices.iter().map(|d| d.name()).collect::>().join(", ")); } else { // when building the app without running to a device, we might have an empty devices list None }; if let Some((target_device_serial_no, target_device_name)) = target_device { let mut already_forwarded = false; // clear port forwarding for all devices for device in &devices { let reverse_list_output = adb_reverse_list(env, device.serial_no()).map_err(|error| Error::CommandFailed { command: "adb reverse --list".to_string(), error, })?; // check if the device has the port forwarded if String::from_utf8_lossy(&reverse_list_output.stdout).contains(&forward) { // device matches our target, we can skip forwarding if device.serial_no() == target_device_serial_no { log::debug!( "device {} already has the forward for {}", device.name(), forward ); already_forwarded = true; } break; } } // if there's a known target, we should forward the port to it if already_forwarded { log::info!("{forward} already forwarded to {target_device_name}"); } else { loop { run_adb_reverse(env, &target_device_serial_no, &forward, &forward).map_err(|error| { Error::CommandFailed { command: format!("adb reverse {forward} {forward}"), error, } })?; let reverse_list_output = adb_reverse_list(env, &target_device_serial_no).map_err(|error| { Error::CommandFailed { command: "adb reverse --list".to_string(), error, } })?; // wait and retry until the port has actually been forwarded if String::from_utf8_lossy(&reverse_list_output.stdout).contains(&forward) { break; } else { log::warn!( "waiting for the port to be forwarded to {}...", target_device_name ); std::thread::sleep(std::time::Duration::from_secs(1)); } } } } else { log::warn!("no running devices detected with ADB; skipping port forwarding"); } Ok(()) } fn run_adb_reverse( env: &cargo_mobile2::android::env::Env, device_serial_no: &str, remote: &str, local: &str, ) -> std::io::Result { adb::adb(env, ["-s", device_serial_no, "reverse", remote, local]) .stdin_file(os_pipe::dup_stdin().unwrap()) .stdout_file(os_pipe::dup_stdout().unwrap()) .stderr_file(os_pipe::dup_stdout().unwrap()) .run() } fn adb_reverse_list( env: &cargo_mobile2::android::env::Env, device_serial_no: &str, ) -> std::io::Result { adb::adb(env, ["-s", device_serial_no, "reverse", "--list"]) .stdin_file(os_pipe::dup_stdin().unwrap()) .stdout_capture() .stderr_capture() .run() } ================================================ FILE: crates/tauri-cli/src/mobile/android/build.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use super::{ configure_cargo, delete_codegen_vars, ensure_init, env, get_app, get_config, inject_resources, log_finished, open_and_wait, MobileTarget, OptionsHandle, }; use crate::{ build::Options as BuildOptions, error::Context, helpers::{ app_paths::Dirs, config::{get_config as get_tauri_config, ConfigMetadata}, flock, }, interface::{AppInterface, Options as InterfaceOptions}, mobile::{android::generate_tauri_properties, write_options, CliOptions, TargetDevice}, ConfigValue, Error, Result, }; use clap::{ArgAction, Parser}; use cargo_mobile2::{ android::{aab, apk, config::Config as AndroidConfig, env::Env, target::Target}, opts::{NoiseLevel, Profile}, target::TargetTrait, }; use std::env::set_current_dir; use std::path::Path; #[derive(Debug, Clone, Parser)] #[clap( about = "Build your app in release mode for Android and generate APKs and AABs", long_about = "Build your app in release mode for Android and generate APKs and AABs. It makes use of the `build.frontendDist` property from your `tauri.conf.json` file. It also runs your `build.beforeBuildCommand` which usually builds your frontend into `build.frontendDist`." )] pub struct Options { /// Builds with the debug flag #[clap(short, long)] pub debug: bool, /// Which targets to build (all by default). #[clap( short, long = "target", action = ArgAction::Append, num_args(0..), value_parser(clap::builder::PossibleValuesParser::new(Target::name_list())) )] pub targets: Option>, /// List of cargo features to activate #[clap(short, long, action = ArgAction::Append, num_args(0..), value_delimiter = ',')] pub features: Vec, /// JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file /// /// Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts. /// /// Note that a platform-specific file is looked up and merged with the default file by default /// (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json) /// but you can use this for more specific use cases such as different build flavors. #[clap(short, long)] pub config: Vec, /// Whether to split the APKs and AABs per ABIs. #[clap(long)] pub split_per_abi: bool, /// Build APKs. #[clap(long)] pub apk: bool, /// Build AABs. #[clap(long)] pub aab: bool, #[clap(skip)] pub skip_bundle: bool, /// Open Android Studio #[clap(short, long)] pub open: bool, /// Skip prompting for values #[clap(long, env = "CI")] pub ci: bool, /// Command line arguments passed to the runner. /// Use `--` to explicitly mark the start of the arguments. /// e.g. `tauri android build -- [runnerArgs]`. #[clap(last(true))] pub args: Vec, /// Do not error out if a version mismatch is detected on a Tauri package. /// /// Only use this when you are sure the mismatch is incorrectly detected as version mismatched Tauri packages can lead to unknown behavior. #[clap(long)] pub ignore_version_mismatches: bool, /// Target device of this build #[clap(skip)] pub target_device: Option, } impl From for BuildOptions { fn from(options: Options) -> Self { Self { runner: None, debug: options.debug, target: None, features: options.features, bundles: None, no_bundle: false, config: options.config, args: options.args, ci: options.ci, skip_stapling: false, ignore_version_mismatches: options.ignore_version_mismatches, no_sign: false, } } } pub struct BuiltApplication { pub config: AndroidConfig, pub interface: AppInterface, // prevent drop #[allow(dead_code)] options_handle: OptionsHandle, } pub fn command(options: Options, noise_level: NoiseLevel) -> Result { let dirs = crate::helpers::app_paths::resolve_dirs(); let tauri_config = get_tauri_config( tauri_utils::platform::Target::Android, &options .config .iter() .map(|conf| &conf.0) .collect::>(), dirs.tauri, )?; run(options, noise_level, &dirs, &tauri_config) } pub fn run( options: Options, noise_level: NoiseLevel, dirs: &Dirs, tauri_config: &ConfigMetadata, ) -> Result { delete_codegen_vars(); let mut build_options: BuildOptions = options.clone().into(); let first_target = Target::all() .get( options .targets .as_ref() .and_then(|l| l.first().map(|t| t.as_str())) .unwrap_or(Target::DEFAULT_KEY), ) .unwrap(); build_options.target = Some(first_target.triple.into()); let interface = AppInterface::new(tauri_config, build_options.target.clone(), dirs.tauri)?; interface.build_options(&mut build_options.args, &mut build_options.features, true); let app = get_app(MobileTarget::Android, tauri_config, &interface, dirs.tauri); let (config, metadata) = get_config( &app, tauri_config, &build_options.features, &CliOptions { dev: false, features: build_options.features.clone(), args: build_options.args.clone(), noise_level, vars: Default::default(), config: build_options.config.clone(), target_device: None, }, ); let profile = if options.debug { Profile::Debug } else { Profile::Release }; set_current_dir(dirs.tauri).context("failed to set current directory to Tauri directory")?; ensure_init( tauri_config, config.app(), config.project_dir(), MobileTarget::Android, options.ci, )?; let mut env = env(options.ci)?; configure_cargo(&mut env, &config)?; generate_tauri_properties(&config, tauri_config, false)?; crate::build::setup(&interface, &mut build_options, tauri_config, dirs, true)?; let installed_targets = crate::interface::rust::installation::installed_targets().unwrap_or_default(); if !installed_targets.contains(&first_target.triple().into()) { log::info!("Installing target {}", first_target.triple()); first_target .install() .map_err(|error| Error::CommandFailed { command: "rustup target add".to_string(), error, }) .context("failed to install target")?; } // run an initial build to initialize plugins first_target .build(&config, &metadata, &env, noise_level, true, profile) .context("failed to build Android app")?; let open = options.open; let options_handle = run_build( &interface, options, build_options, tauri_config, profile, &config, &mut env, noise_level, dirs.tauri, )?; if open { open_and_wait(&config, &env); } Ok(BuiltApplication { config, interface, options_handle, }) } #[allow(clippy::too_many_arguments)] fn run_build( interface: &AppInterface, mut options: Options, build_options: BuildOptions, tauri_config: &ConfigMetadata, profile: Profile, config: &AndroidConfig, env: &mut Env, noise_level: NoiseLevel, tauri_dir: &Path, ) -> Result { if !(options.skip_bundle || options.apk || options.aab) { // if the user didn't specify the format to build, we'll do both options.apk = true; options.aab = true; } let interface_options = InterfaceOptions { debug: build_options.debug, target: build_options.target.clone(), args: build_options.args.clone(), ..Default::default() }; let app_settings = interface.app_settings(); let out_dir = app_settings.out_dir(&interface_options, tauri_dir)?; let _lock = flock::open_rw(out_dir.join("lock").with_extension("android"), "Android")?; let cli_options = CliOptions { dev: false, features: build_options.features.clone(), args: build_options.args.clone(), noise_level, vars: Default::default(), config: build_options.config, target_device: options.target_device.clone(), }; let handle = write_options(tauri_config, cli_options)?; inject_resources(config, tauri_config)?; let apk_outputs = if options.apk { apk::build( config, env, noise_level, profile, get_targets_or_all(options.targets.clone().unwrap_or_default())?, options.split_per_abi, ) .context("failed to build APK")? } else { Vec::new() }; let aab_outputs = if options.aab { aab::build( config, env, noise_level, profile, get_targets_or_all(options.targets.unwrap_or_default())?, options.split_per_abi, ) .context("failed to build AAB")? } else { Vec::new() }; if !apk_outputs.is_empty() { log_finished(apk_outputs, "APK"); } if !aab_outputs.is_empty() { log_finished(aab_outputs, "AAB"); } Ok(handle) } fn get_targets_or_all<'a>(targets: Vec) -> Result>> { if targets.is_empty() { Ok(Target::all().iter().map(|t| t.1).collect()) } else { let mut outs = Vec::new(); let possible_targets = Target::all() .keys() .map(|key| key.to_string()) .collect::>() .join(","); for t in targets { let target = Target::for_name(&t).with_context(|| { format!("Target {t} is invalid; the possible targets are {possible_targets}",) })?; outs.push(target); } Ok(outs) } } ================================================ FILE: crates/tauri-cli/src/mobile/android/dev.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use super::{ configure_cargo, delete_codegen_vars, device_prompt, ensure_init, env, get_app, get_config, inject_resources, open_and_wait, MobileTarget, }; use crate::{ dev::Options as DevOptions, error::{Context, ErrorExt}, helpers::{ app_paths::Dirs, config::{get_config as get_tauri_config, ConfigMetadata}, flock, }, interface::{AppInterface, MobileOptions, Options as InterfaceOptions}, mobile::{ android::generate_tauri_properties, use_network_address_for_dev_url, write_options, CliOptions, DevChild, DevHost, DevProcess, TargetDevice, }, ConfigValue, Error, Result, }; use clap::{ArgAction, Parser}; use cargo_mobile2::{ android::{ config::{Config as AndroidConfig, Metadata as AndroidMetadata}, device::Device, env::Env, target::Target, }, opts::{FilterLevel, NoiseLevel, Profile}, target::TargetTrait, }; use url::Host; use std::{env::set_current_dir, net::Ipv4Addr, path::PathBuf}; #[derive(Debug, Clone, Parser)] #[clap( about = "Run your app in development mode on Android", long_about = "Run your app in development mode on Android with hot-reloading for the Rust code. It makes use of the `build.devUrl` property from your `tauri.conf.json` file. It also runs your `build.beforeDevCommand` which usually starts your frontend devServer." )] pub struct Options { /// List of cargo features to activate #[clap(short, long, action = ArgAction::Append, num_args(0..), value_delimiter = ',')] pub features: Vec, /// Exit on panic #[clap(short, long)] exit_on_panic: bool, /// JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file /// /// Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts. /// /// Note that a platform-specific file is looked up and merged with the default file by default /// (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json) /// but you can use this for more specific use cases such as different build flavors. #[clap(short, long)] pub config: Vec, /// Run the code in release mode #[clap(long = "release")] pub release_mode: bool, /// Skip waiting for the frontend dev server to start before building the tauri application. #[clap(long, env = "TAURI_CLI_NO_DEV_SERVER_WAIT")] pub no_dev_server_wait: bool, /// Disable the file watcher #[clap(long)] pub no_watch: bool, /// Additional paths to watch for changes. #[clap(long)] pub additional_watch_folders: Vec, /// Open Android Studio instead of trying to run on a connected device #[clap(short, long)] pub open: bool, /// Runs on the given device name pub device: Option, /// Force prompting for an IP to use to connect to the dev server on mobile. #[clap(long)] pub force_ip_prompt: bool, /// Use the public network address for the development server. /// If an actual address it provided, it is used instead of prompting to pick one. /// /// On Windows we use the public network address by default. /// /// This option is particularly useful along the `--open` flag when you intend on running on a physical device. /// /// This replaces the devUrl configuration value to match the public network address host, /// it is your responsibility to set up your development server to listen on this address /// by using 0.0.0.0 as host for instance. /// /// When this is set or when running on an iOS device the CLI sets the `TAURI_DEV_HOST` /// environment variable so you can check this on your framework's configuration to expose the development server /// on the public network address. #[clap(long, default_value_t, default_missing_value(""), num_args(0..=1))] pub host: DevHost, /// Disable the built-in dev server for static files. #[clap(long)] pub no_dev_server: bool, /// Specify port for the built-in dev server for static files. Defaults to 1430. #[clap(long, env = "TAURI_CLI_PORT")] pub port: Option, /// Command line arguments passed to the runner. /// Use `--` to explicitly mark the start of the arguments. /// e.g. `tauri android dev -- [runnerArgs]`. #[clap(last(true))] pub args: Vec, /// Path to the certificate file used by your dev server. Required for mobile dev when using HTTPS. #[clap(long, env = "TAURI_DEV_ROOT_CERTIFICATE_PATH")] pub root_certificate_path: Option, } impl From for DevOptions { fn from(options: Options) -> Self { Self { runner: None, target: None, features: options.features, exit_on_panic: options.exit_on_panic, config: options.config, args: options.args, no_watch: options.no_watch, additional_watch_folders: options.additional_watch_folders, no_dev_server_wait: options.no_dev_server_wait, no_dev_server: options.no_dev_server, port: options.port, release_mode: options.release_mode, host: options.host.0.unwrap_or_default(), } } } pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> { let dirs = crate::helpers::app_paths::resolve_dirs(); let result = run_command(options, noise_level, dirs); if result.is_err() { crate::dev::kill_before_dev_process(); } result } fn run_command(options: Options, noise_level: NoiseLevel, dirs: Dirs) -> Result<()> { delete_codegen_vars(); // setup env additions before calling env() if let Some(root_certificate_path) = &options.root_certificate_path { std::env::set_var( "TAURI_DEV_ROOT_CERTIFICATE", std::fs::read_to_string(root_certificate_path).fs_context( "failed to read certificate file", root_certificate_path.clone(), )?, ); } let tauri_config = get_tauri_config( tauri_utils::platform::Target::Android, &options .config .iter() .map(|conf| &conf.0) .collect::>(), dirs.tauri, )?; let env = env(false)?; let device = if options.open { None } else { match device_prompt(&env, options.device.as_deref()) { Ok(d) => Some(d), Err(e) => { log::error!("{e}"); None } } }; let mut dev_options: DevOptions = options.clone().into(); let target_triple = device .as_ref() .map(|d| d.target().triple.to_string()) .unwrap_or_else(|| Target::all().values().next().unwrap().triple.into()); dev_options.target = Some(target_triple); dev_options.args.push("--lib".into()); let interface = AppInterface::new(&tauri_config, dev_options.target.clone(), dirs.tauri)?; let app = get_app(MobileTarget::Android, &tauri_config, &interface, dirs.tauri); let (config, metadata) = get_config( &app, &tauri_config, dev_options.features.as_ref(), &CliOptions { dev: true, features: dev_options.features.clone(), args: dev_options.args.clone(), noise_level, vars: Default::default(), config: dev_options.config.clone(), target_device: None, }, ); set_current_dir(dirs.tauri).context("failed to set current directory to Tauri directory")?; ensure_init( &tauri_config, config.app(), config.project_dir(), MobileTarget::Android, false, )?; run_dev( interface, options, dev_options, tauri_config, device, env, &config, &metadata, noise_level, &dirs, ) } #[allow(clippy::too_many_arguments)] fn run_dev( mut interface: AppInterface, options: Options, mut dev_options: DevOptions, mut tauri_config: ConfigMetadata, device: Option, mut env: Env, config: &AndroidConfig, metadata: &AndroidMetadata, noise_level: NoiseLevel, dirs: &Dirs, ) -> Result<()> { // when --host is provided or running on a physical device or resolving 0.0.0.0 we must use the network IP if options.host.0.is_some() || device .as_ref() .map(|device| !device.serial_no().starts_with("emulator")) .unwrap_or(false) || tauri_config.build.dev_url.as_ref().is_some_and(|url| { matches!( url.host(), Some(Host::Ipv4(i)) if i == Ipv4Addr::UNSPECIFIED ) }) { use_network_address_for_dev_url( &mut tauri_config, &mut dev_options, options.force_ip_prompt, dirs.tauri, )?; } crate::dev::setup(&interface, &mut dev_options, &mut tauri_config, dirs)?; let interface_options = InterfaceOptions { debug: !dev_options.release_mode, target: dev_options.target.clone(), ..Default::default() }; let app_settings = interface.app_settings(); let out_dir = app_settings.out_dir(&interface_options, dirs.tauri)?; let _lock = flock::open_rw(out_dir.join("lock").with_extension("android"), "Android")?; configure_cargo(&mut env, config)?; generate_tauri_properties(config, &tauri_config, true)?; let installed_targets = crate::interface::rust::installation::installed_targets().unwrap_or_default(); // run an initial build to initialize plugins let target_triple = dev_options.target.as_ref().unwrap(); let target = Target::all() .values() .find(|t| t.triple == target_triple) .unwrap_or_else(|| Target::all().values().next().unwrap()); if !installed_targets.contains(&target.triple().into()) { log::info!("Installing target {}", target.triple()); target.install().map_err(|error| Error::CommandFailed { command: "rustup target add".to_string(), error, })?; } target .build( config, metadata, &env, noise_level, true, if options.release_mode { Profile::Release } else { Profile::Debug }, ) .context("failed to build Android app")?; let open = options.open; interface.mobile_dev( &mut tauri_config, MobileOptions { debug: !options.release_mode, features: options.features, args: options.args, config: dev_options.config.clone(), no_watch: options.no_watch, additional_watch_folders: options.additional_watch_folders, }, |options, tauri_config| { let cli_options = CliOptions { dev: true, features: options.features.clone(), args: options.args.clone(), noise_level, vars: Default::default(), config: dev_options.config.clone(), target_device: device.as_ref().map(|d| TargetDevice { id: d.serial_no().to_string(), name: d.name().to_string(), }), }; let _handle = write_options(tauri_config, cli_options)?; inject_resources(config, tauri_config)?; if open { open_and_wait(config, &env) } else if let Some(device) = &device { match run(device, options, config, &env, metadata, noise_level) { Ok(c) => Ok(Box::new(c) as Box), Err(e) => { crate::dev::kill_before_dev_process(); Err(e) } } } else { open_and_wait(config, &env) } }, dirs, ) } fn run( device: &Device<'_>, options: MobileOptions, config: &AndroidConfig, env: &Env, metadata: &AndroidMetadata, noise_level: NoiseLevel, ) -> crate::Result { let profile = if options.debug { Profile::Debug } else { Profile::Release }; let build_app_bundle = metadata.asset_packs().is_some(); device .run( config, env, noise_level, profile, Some(match noise_level { NoiseLevel::Polite => FilterLevel::Info, NoiseLevel::LoudAndProud => FilterLevel::Debug, NoiseLevel::FranklyQuitePedantic => FilterLevel::Verbose, }), build_app_bundle, false, ".MainActivity".into(), ) .map(DevChild::new) .context("failed to run Android app") } ================================================ FILE: crates/tauri-cli/src/mobile/android/mod.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use cargo_mobile2::{ android::{ adb, config::{Config as AndroidConfig, Metadata as AndroidMetadata, Raw as RawAndroidConfig}, device::Device, emulator, env::Env, target::Target, }, config::app::{App, DEFAULT_ASSET_DIR}, opts::{FilterLevel, NoiseLevel}, os, target::TargetTrait, util::prompt, }; use clap::{Parser, Subcommand}; use semver::Version; use std::{ env::set_var, fs::{create_dir, create_dir_all, read_dir, write}, io::Cursor, path::{Path, PathBuf}, process::{exit, Command}, thread::sleep, time::Duration, }; use sublime_fuzzy::best_match; use tauri_utils::resources::ResourcePaths; use super::{ ensure_init, get_app, init::command as init_command, log_finished, read_options, CliOptions, OptionsHandle, Target as MobileTarget, MIN_DEVICE_MATCH_SCORE, }; use crate::{ error::Context, helpers::config::{BundleResources, Config as TauriConfig}, ConfigValue, Error, ErrorExt, Result, }; mod android_studio_script; mod build; mod dev; pub(crate) mod project; mod run; const NDK_VERSION: &str = "29.0.13846066"; const SDK_VERSION: u8 = 36; #[cfg(target_os = "macos")] const CMDLINE_TOOLS_URL: &str = "https://dl.google.com/android/repository/commandlinetools-mac-13114758_latest.zip"; #[cfg(target_os = "linux")] const CMDLINE_TOOLS_URL: &str = "https://dl.google.com/android/repository/commandlinetools-linux-13114758_latest.zip"; #[cfg(windows)] const CMDLINE_TOOLS_URL: &str = "https://dl.google.com/android/repository/commandlinetools-win-13114758_latest.zip"; #[derive(Parser)] #[clap( author, version, about = "Android commands", subcommand_required(true), arg_required_else_help(true) )] pub struct Cli { #[clap(subcommand)] command: Commands, } #[derive(Debug, Parser)] #[clap(about = "Initialize Android target in the project")] pub struct InitOptions { /// Skip prompting for values #[clap(long, env = "CI")] ci: bool, /// Skips installing rust toolchains via rustup #[clap(long)] skip_targets_install: bool, /// JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file /// /// Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts. /// /// Note that a platform-specific file is looked up and merged with the default file by default /// (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json) /// but you can use this for more specific use cases such as different build flavors. #[clap(short, long)] pub config: Vec, } #[derive(Subcommand)] enum Commands { Init(InitOptions), Dev(dev::Options), Build(build::Options), Run(run::Options), #[clap(hide(true))] AndroidStudioScript(android_studio_script::Options), } pub fn command(cli: Cli, verbosity: u8) -> Result<()> { let noise_level = NoiseLevel::from_occurrences(verbosity as u64); match cli.command { Commands::Init(options) => init_command( MobileTarget::Android, options.ci, false, options.skip_targets_install, options.config, )?, Commands::Dev(options) => dev::command(options, noise_level)?, Commands::Build(options) => build::command(options, noise_level).map(|_| ())?, Commands::Run(options) => run::command(options, noise_level)?, Commands::AndroidStudioScript(options) => android_studio_script::command(options)?, } Ok(()) } pub fn get_config( app: &App, config: &TauriConfig, features: &[String], cli_options: &CliOptions, ) -> (AndroidConfig, AndroidMetadata) { let mut android_options = cli_options.clone(); android_options.features.extend_from_slice(features); let raw = RawAndroidConfig { features: Some(android_options.features.clone()), logcat_filter_specs: vec![ "RustStdoutStderr".into(), format!( "*:{}", match cli_options.noise_level { NoiseLevel::Polite => FilterLevel::Info, NoiseLevel::LoudAndProud => FilterLevel::Debug, NoiseLevel::FranklyQuitePedantic => FilterLevel::Verbose, } .logcat() ), ], min_sdk_version: Some(config.bundle.android.min_sdk_version), ..Default::default() }; let config = AndroidConfig::from_raw(app.clone(), Some(raw)).unwrap(); let metadata = AndroidMetadata { supported: true, cargo_args: Some(android_options.args), features: Some(android_options.features), ..Default::default() }; set_var( "WRY_ANDROID_PACKAGE", app.android_identifier_escape_kotlin_keyword(), ); set_var("TAURI_ANDROID_PACKAGE_UNESCAPED", app.identifier()); set_var("WRY_ANDROID_LIBRARY", app.lib_name()); set_var("TAURI_ANDROID_PROJECT_PATH", config.project_dir()); let src_main_dir = config .project_dir() .join("app/src/main") .join(format!("java/{}", app.identifier().replace('.', "/"),)); if config.project_dir().exists() { if src_main_dir.exists() { let _ = create_dir(src_main_dir.join("generated")); } else { log::error!( "Project directory {} does not exist. Did you update the package name in `Cargo.toml` or the bundle identifier in `tauri.conf.json > identifier`? Save your changes, delete the `gen/android` folder and run `tauri android init` to recreate the Android project.", src_main_dir.display() ); exit(1); } } set_var( "WRY_ANDROID_KOTLIN_FILES_OUT_DIR", src_main_dir.join("generated"), ); (config, metadata) } pub fn env(non_interactive: bool) -> Result { let env = super::env().context("failed to setup Android environment")?; ensure_env(non_interactive).context("failed to ensure Android environment")?; cargo_mobile2::android::env::Env::from_env(env).context("failed to load Android environment") } fn download_cmdline_tools(extract_path: &Path) -> Result<()> { log::info!("Downloading Android command line tools..."); let mut response = crate::helpers::http::get(CMDLINE_TOOLS_URL) .context("failed to download Android command line tools")?; let body = response .body_mut() .with_config() .limit(200 * 1024 * 1024 /* 200MB */) .read_to_vec() .context("failed to read Android command line tools download response")?; let mut zip = zip::ZipArchive::new(Cursor::new(body)) .context("failed to create zip archive from Android command line tools download response")?; log::info!( "Extracting Android command line tools to {}", extract_path.display() ); zip .extract(extract_path) .context("failed to extract Android command line tools")?; Ok(()) } fn ensure_env(non_interactive: bool) -> Result<()> { ensure_java()?; ensure_sdk(non_interactive)?; ensure_ndk(non_interactive)?; Ok(()) } fn ensure_java() -> Result<()> { if std::env::var_os("JAVA_HOME").is_none() { #[cfg(windows)] let default_java_home = "C:\\Program Files\\Android\\Android Studio\\jbr"; #[cfg(target_os = "macos")] let default_java_home = "/Applications/Android Studio.app/Contents/jbr/Contents/Home"; #[cfg(target_os = "linux")] let default_java_home = "/opt/android-studio/jbr"; if Path::new(default_java_home).exists() { log::info!("Using Android Studio's default Java installation: {default_java_home}"); std::env::set_var("JAVA_HOME", default_java_home); } else if which::which("java").is_err() { crate::error::bail!("Java not found in PATH, default Android Studio Java installation not found at {default_java_home} and JAVA_HOME environment variable not set. Please install Java before proceeding"); } } Ok(()) } fn ensure_sdk(non_interactive: bool) -> Result<()> { let android_home = std::env::var_os("ANDROID_HOME") .or_else(|| std::env::var_os("ANDROID_SDK_ROOT")) .map(PathBuf::from); if !android_home.as_ref().is_some_and(|v| v.exists()) { log::info!( "ANDROID_HOME {}, trying to locate Android SDK...", if let Some(v) = &android_home { format!("not found at {}", v.display()) } else { "not set".into() } ); #[cfg(target_os = "macos")] let default_android_home = dirs::home_dir().unwrap().join("Library/Android/sdk"); #[cfg(target_os = "linux")] let default_android_home = dirs::home_dir().unwrap().join("Android/Sdk"); #[cfg(windows)] let default_android_home = dirs::data_local_dir().unwrap().join("Android/Sdk"); if default_android_home.exists() { log::info!( "Using installed Android SDK: {}", default_android_home.display() ); } else if non_interactive { crate::error::bail!("Android SDK not found. Make sure the SDK and NDK are installed and the ANDROID_HOME and NDK_HOME environment variables are set."); } else { log::error!( "Android SDK not found at {}", default_android_home.display() ); let extract_path = if create_dir_all(&default_android_home).is_ok() { default_android_home.clone() } else { std::env::current_dir().context("failed to get current directory")? }; let sdk_manager_path = extract_path .join("cmdline-tools/bin/sdkmanager") .with_extension(if cfg!(windows) { "bat" } else { "" }); let mut granted_permission_to_install = false; if !sdk_manager_path.exists() { granted_permission_to_install = crate::helpers::prompts::confirm( "Do you want to install the Android Studio command line tools to setup the Android SDK?", Some(false), ) .unwrap_or_default(); if !granted_permission_to_install { crate::error::bail!("Skipping Android Studio command line tools installation. Please go through the manual setup process described in the documentation: https://tauri.app/start/prerequisites/#android"); } download_cmdline_tools(&extract_path)?; } if !granted_permission_to_install { granted_permission_to_install = crate::helpers::prompts::confirm( "Do you want to install the Android SDK using the command line tools?", Some(false), ) .unwrap_or_default(); if !granted_permission_to_install { crate::error::bail!("Skipping Android Studio SDK installation. Please go through the manual setup process described in the documentation: https://tauri.app/start/prerequisites/#android"); } } log::info!("Running sdkmanager to install platform-tools, android-{SDK_VERSION} and ndk-{NDK_VERSION} on {}...", default_android_home.display()); let status = Command::new(&sdk_manager_path) .arg(format!("--sdk_root={}", default_android_home.display())) .arg("--install") .arg("platform-tools") .arg(format!("platforms;android-{SDK_VERSION}")) .arg(format!("ndk;{NDK_VERSION}")) .status() .map_err(|error| Error::CommandFailed { command: format!("{} --sdk_root={} --install platform-tools platforms;android-{SDK_VERSION} ndk;{NDK_VERSION}", sdk_manager_path.display(), default_android_home.display()), error, })?; if !status.success() { crate::error::bail!("Failed to install Android SDK"); } } std::env::set_var("ANDROID_HOME", default_android_home); } Ok(()) } fn ensure_ndk(non_interactive: bool) -> Result<()> { // re-evaluate ANDROID_HOME let android_home = std::env::var_os("ANDROID_HOME") .or_else(|| std::env::var_os("ANDROID_SDK_ROOT")) .map(PathBuf::from) .context("Failed to locate Android SDK")?; let mut installed_ndks = read_dir(android_home.join("ndk")) .map(|dir| { dir .into_iter() .flat_map(|e| e.ok().map(|e| e.path())) .collect::>() }) .unwrap_or_default(); installed_ndks.sort(); if let Some(ndk) = installed_ndks.last() { log::info!("Using installed NDK: {}", ndk.display()); std::env::set_var("NDK_HOME", ndk); } else if non_interactive { crate::error::bail!("Android NDK not found. Make sure the NDK is installed and the NDK_HOME environment variable is set."); } else { let sdk_manager_path = android_home .join("cmdline-tools/bin/sdkmanager") .with_extension(if cfg!(windows) { "bat" } else { "" }); let mut granted_permission_to_install = false; if !sdk_manager_path.exists() { granted_permission_to_install = crate::helpers::prompts::confirm( "Do you want to install the Android Studio command line tools to setup the Android NDK?", Some(false), ) .unwrap_or_default(); if !granted_permission_to_install { crate::error::bail!("Skipping Android Studio command line tools installation. Please go through the manual setup process described in the documentation: https://tauri.app/start/prerequisites/#android"); } download_cmdline_tools(&android_home)?; } if !granted_permission_to_install { granted_permission_to_install = crate::helpers::prompts::confirm( "Do you want to install the Android NDK using the command line tools?", Some(false), ) .unwrap_or_default(); if !granted_permission_to_install { crate::error::bail!("Skipping Android Studio NDK installation. Please go through the manual setup process described in the documentation: https://tauri.app/start/prerequisites/#android"); } } log::info!( "Running sdkmanager to install ndk-{NDK_VERSION} on {}...", android_home.display() ); let status = Command::new(&sdk_manager_path) .arg(format!("--sdk_root={}", android_home.display())) .arg("--install") .arg(format!("ndk;{NDK_VERSION}")) .status() .map_err(|error| Error::CommandFailed { command: format!( "{} --sdk_root={} --install ndk;{NDK_VERSION}", sdk_manager_path.display(), android_home.display() ), error, })?; if !status.success() { crate::error::bail!("Failed to install Android NDK"); } let ndk_path = android_home.join("ndk").join(NDK_VERSION); log::info!("Installed NDK: {}", ndk_path.display()); std::env::set_var("NDK_HOME", ndk_path); } Ok(()) } fn delete_codegen_vars() { for (k, _) in std::env::vars() { if k.starts_with("WRY_") && (k.ends_with("CLASS_EXTENSION") || k.ends_with("CLASS_INIT")) { std::env::remove_var(k); } } } fn adb_device_prompt<'a>(env: &'_ Env, target: Option<&str>) -> Result> { let device_list = adb::device_list(env).context("failed to detect connected Android devices")?; if !device_list.is_empty() { let device = if let Some(t) = target { let (device, score) = device_list .into_iter() .rev() .map(|d| { let score = best_match(t, d.name()).map_or(0, |m| m.score()); (d, score) }) .max_by_key(|(_, score)| *score) // we already checked the list is not empty .unwrap(); if score > MIN_DEVICE_MATCH_SCORE { device } else { crate::error::bail!("Could not find an Android device matching {t}") } } else if device_list.len() > 1 { let index = prompt::list( concat!("Detected ", "Android", " devices"), device_list.iter(), "device", None, "Device", ) .context("failed to prompt for device")?; device_list.into_iter().nth(index).unwrap() } else { device_list.into_iter().next().unwrap() }; log::info!( "Detected connected device: {} with target {:?}", device, device.target().triple, ); Ok(device) } else { Err(Error::GenericError( "No connected Android devices detected".to_string(), )) } } fn emulator_prompt(env: &'_ Env, target: Option<&str>) -> Result { let emulator_list = emulator::avd_list(env).unwrap_or_default(); if !emulator_list.is_empty() { let emulator = if let Some(t) = target { let (device, score) = emulator_list .into_iter() .rev() .map(|d| { let score = best_match(t, d.name()).map_or(0, |m| m.score()); (d, score) }) .max_by_key(|(_, score)| *score) // we already checked the list is not empty .unwrap(); if score > MIN_DEVICE_MATCH_SCORE { device } else { crate::error::bail!("Could not find an Android Emulator matching {t}") } } else if emulator_list.len() > 1 { let index = prompt::list( concat!("Detected ", "Android", " emulators"), emulator_list.iter(), "emulator", None, "Emulator", ) .context("failed to prompt for emulator")?; emulator_list.into_iter().nth(index).unwrap() } else { emulator_list.into_iter().next().unwrap() }; Ok(emulator) } else { Err(Error::GenericError( "No available Android Emulator detected".to_string(), )) } } fn device_prompt<'a>(env: &'_ Env, target: Option<&str>) -> Result> { if let Ok(device) = adb_device_prompt(env, target) { Ok(device) } else { let emulator = emulator_prompt(env, target)?; log::info!("Starting emulator {}", emulator.name()); emulator .start_detached(env) .context("failed to start emulator")?; let mut tries = 0; loop { sleep(Duration::from_secs(2)); if let Ok(device) = adb_device_prompt(env, Some(emulator.name())) { return Ok(device); } if tries >= 3 { log::info!("Waiting for emulator to start... (maybe the emulator is unauthorized or offline, run `adb devices` to check)"); } else { log::info!("Waiting for emulator to start..."); } tries += 1; } } } fn detect_target_ok<'a>(env: &Env) -> Option<&'a Target<'a>> { device_prompt(env, None).map(|device| device.target()).ok() } fn open_and_wait(config: &AndroidConfig, env: &Env) -> ! { log::info!("Opening Android Studio"); if let Err(e) = os::open_file_with("Android Studio", config.project_dir(), &env.base) { log::error!("{e}"); } loop { sleep(Duration::from_secs(24 * 60 * 60)); } } fn inject_resources(config: &AndroidConfig, tauri_config: &TauriConfig) -> Result<()> { let asset_dir = config .project_dir() .join("app/src/main") .join(DEFAULT_ASSET_DIR); create_dir_all(&asset_dir).fs_context("failed to create asset directory", asset_dir.clone())?; write( asset_dir.join("tauri.conf.json"), serde_json::to_string(&tauri_config).with_context(|| "failed to serialize tauri config")?, ) .fs_context( "failed to write tauri config", asset_dir.join("tauri.conf.json"), )?; let resources = match &tauri_config.bundle.resources { Some(BundleResources::List(paths)) => Some(ResourcePaths::new(paths.as_slice(), true)), Some(BundleResources::Map(map)) => Some(ResourcePaths::from_map(map, true)), None => None, }; if let Some(resources) = resources { for resource in resources.iter() { let resource = resource.context("failed to get resource")?; let dest = asset_dir.join(resource.target()); crate::helpers::fs::copy_file(resource.path(), dest).context("failed to copy resource")?; } } Ok(()) } fn configure_cargo(env: &mut Env, config: &AndroidConfig) -> Result<()> { for target in Target::all().values() { let config = target .generate_cargo_config(config, env) .context("failed to find Android tool")?; let target_var_name = target.triple.replace('-', "_").to_uppercase(); if let Some(linker) = config.linker { env.base.insert_env_var( format!("CARGO_TARGET_{target_var_name}_LINKER"), linker.into(), ); } env.base.insert_env_var( format!("CARGO_TARGET_{target_var_name}_RUSTFLAGS"), config.rustflags.join(" ").into(), ); } Ok(()) } fn generate_tauri_properties( config: &AndroidConfig, tauri_config: &TauriConfig, dev: bool, ) -> Result<()> { let app_tauri_properties_path = config.project_dir().join("app").join("tauri.properties"); let mut app_tauri_properties = Vec::new(); if let Some(version) = tauri_config.version.as_ref() { app_tauri_properties.push(format!("tauri.android.versionName={version}")); if tauri_config.bundle.android.auto_increment_version_code && !dev { let last_version_code = std::fs::read_to_string(&app_tauri_properties_path) .ok() .and_then(|content| { content .lines() .find(|line| line.starts_with("tauri.android.versionCode=")) .and_then(|line| line.split('=').nth(1)) .and_then(|s| s.trim().parse::().ok()) }); let new_version_code = last_version_code.map(|v| v.saturating_add(1)).unwrap_or(1); app_tauri_properties.push(format!("tauri.android.versionCode={new_version_code}")); } else if let Some(version_code) = tauri_config.bundle.android.version_code.as_ref() { app_tauri_properties.push(format!("tauri.android.versionCode={version_code}")); } else if let Ok(version) = Version::parse(version) { let mut version_code = version.major * 1000000 + version.minor * 1000 + version.patch; if dev { version_code = version_code.clamp(1, 2100000000); } if version_code == 0 { crate::error::bail!( "You must change the `version` in `tauri.conf.json`. The default value `0.0.0` is not allowed for Android package and must be at least `0.0.1`." ); } else if version_code > 2100000000 { crate::error::bail!( "Invalid version code {}. Version code must be between 1 and 2100000000. You must change the `version` in `tauri.conf.json`.", version_code ); } app_tauri_properties.push(format!("tauri.android.versionCode={version_code}")); } } if !app_tauri_properties.is_empty() { let app_tauri_properties_content = format!( "// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n{}", app_tauri_properties.join("\n") ); if std::fs::read_to_string(&app_tauri_properties_path) .map(|o| o != app_tauri_properties_content) .unwrap_or(true) { write(&app_tauri_properties_path, app_tauri_properties_content) .context("failed to write tauri.properties")?; } } Ok(()) } ================================================ FILE: crates/tauri-cli/src/mobile/android/project.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use crate::{ error::{Context, ErrorExt}, helpers::template, Error, Result, }; use cargo_mobile2::{ android::{ config::{Config, Metadata}, target::Target, }, config::app::DEFAULT_ASSET_DIR, os, target::TargetTrait as _, util::{ self, cli::{Report, TextWrapper}, prefix_path, }, }; use handlebars::Handlebars; use include_dir::{include_dir, Dir}; use std::{ ffi::OsStr, fs, path::{Path, PathBuf}, }; const TEMPLATE_DIR: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR/templates/mobile/android"); pub fn gen( config: &Config, metadata: &Metadata, (handlebars, mut map): (Handlebars, template::JsonMap), wrapper: &TextWrapper, skip_targets_install: bool, ) -> Result<()> { if !skip_targets_install { let installed_targets = crate::interface::rust::installation::installed_targets().unwrap_or_default(); let missing_targets = Target::all() .values() .filter(|t| !installed_targets.contains(&t.triple().into())) .collect::>(); if !missing_targets.is_empty() { log::info!("Installing Android Rust targets..."); for target in missing_targets { log::info!("Installing target {}", target.triple()); target.install().map_err(|error| Error::CommandFailed { command: "rustup target add".to_string(), error, })?; } } } println!("Generating Android Studio project..."); let dest = config.project_dir(); let asset_packs = metadata.asset_packs().unwrap_or_default(); map.insert( "root-dir-rel", Path::new(&os::replace_path_separator( util::relativize_path( config.app().root_dir(), config.project_dir().join(config.app().name_snake()), ) .into_os_string(), )), ); map.insert("root-dir", config.app().root_dir()); map.insert( "abi-list", Target::all() .values() .map(|target| target.abi) .collect::>(), ); map.insert("target-list", Target::all().keys().collect::>()); map.insert( "arch-list", Target::all() .values() .map(|target| target.arch) .collect::>(), ); map.insert("android-app-plugins", metadata.app_plugins()); map.insert( "android-project-dependencies", metadata.project_dependencies(), ); map.insert("android-app-dependencies", metadata.app_dependencies()); map.insert( "android-app-dependencies-platform", metadata.app_dependencies_platform(), ); map.insert( "has-code", metadata.project_dependencies().is_some() || metadata.app_dependencies().is_some() || metadata.app_dependencies_platform().is_some(), ); map.insert("has-asset-packs", !asset_packs.is_empty()); map.insert( "asset-packs", asset_packs .iter() .map(|p| p.name.as_str()) .collect::>(), ); map.insert("windows", cfg!(windows)); let identifier = config.app().identifier().replace('.', "/"); let package_path = format!("java/{identifier}"); map.insert("package-path", &package_path); let mut created_dirs = Vec::new(); template::render_with_generator( &handlebars, map.inner(), &TEMPLATE_DIR, &dest, &mut |path| generate_out_file(&path, &dest, &package_path, &mut created_dirs), ) .with_context(|| "failed to process template")?; if !asset_packs.is_empty() { Report::action_request( "When running from Android Studio, you must first set your deployment option to \"APK from app bundle\".", "Android Studio will not be able to find your asset packs otherwise. The option can be found under \"Run > Edit Configurations > Deploy\"." ).print(wrapper); } let source_dest = dest.join("app"); for source in metadata.app_sources() { let source_src = config.app().root_dir().join(source); let source_file = source_src .file_name() .with_context(|| format!("asset source {} is invalid", source_src.display()))?; fs::copy(&source_src, source_dest.join(source_file)) .fs_context("failed to copy asset", source_src)?; } let dest = prefix_path(dest, "app/src/main/"); fs::create_dir_all(&dest).fs_context("failed to create directory", dest.clone())?; let asset_dir = dest.join(DEFAULT_ASSET_DIR); if !asset_dir.is_dir() { fs::create_dir_all(&asset_dir).fs_context("failed to create asset dir", asset_dir)?; } Ok(()) } fn generate_out_file( path: &Path, dest: &Path, package_path: &str, created_dirs: &mut Vec, ) -> std::io::Result> { let mut iter = path.iter(); let root = iter.next().unwrap().to_str().unwrap(); let path_without_root: std::path::PathBuf = iter.collect(); let path = match ( root, path.extension().and_then(|o| o.to_str()), path_without_root.strip_prefix("src/main"), ) { ("app" | "buildSrc", Some("kt"), Ok(path)) => { let parent = path.parent().unwrap(); let file_name = path.file_name().unwrap(); let out_dir = dest .join(root) .join("src/main") .join(package_path) .join(parent); out_dir.join(file_name) } _ => dest.join(path), }; let parent = path.parent().unwrap().to_path_buf(); if !created_dirs.contains(&parent) { fs::create_dir_all(&parent)?; created_dirs.push(parent); } let mut options = fs::OpenOptions::new(); options.write(true); #[cfg(unix)] if path.file_name().unwrap() == OsStr::new("gradlew") { use std::os::unix::fs::OpenOptionsExt; options.mode(0o755); } if path.file_name().unwrap() == OsStr::new("BuildTask.kt") { options.truncate(true).create(true).open(path).map(Some) } else if !path.exists() { options.create(true).open(path).map(Some) } else { Ok(None) } } ================================================ FILE: crates/tauri-cli/src/mobile/android/run.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use cargo_mobile2::{ android::target::Target, opts::{FilterLevel, NoiseLevel, Profile}, target::TargetTrait, }; use clap::{ArgAction, Parser}; use std::path::PathBuf; use super::{configure_cargo, device_prompt, env}; use crate::{ error::Context, helpers::config::ConfigMetadata, interface::{DevProcess, WatcherOptions}, mobile::{DevChild, TargetDevice}, ConfigValue, Result, }; #[derive(Debug, Clone, Parser)] #[clap( about = "Run your app in production mode on Android", long_about = "Run your app in production mode on Android. It makes use of the `build.frontendDist` property from your `tauri.conf.json` file. It also runs your `build.beforeBuildCommand` which usually builds your frontend into `build.frontendDist`." )] pub struct Options { /// Run the app in release mode #[clap(short, long)] pub release: bool, /// List of cargo features to activate #[clap(short, long, action = ArgAction::Append, num_args(0..), value_delimiter = ',')] pub features: Vec, /// JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file /// /// Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts. /// /// Note that a platform-specific file is looked up and merged with the default file by default /// (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json) /// but you can use this for more specific use cases such as different build flavors. #[clap(short, long)] pub config: Vec, /// Disable the file watcher #[clap(long)] pub no_watch: bool, /// Additional paths to watch for changes. #[clap(long)] pub additional_watch_folders: Vec, /// Open Android Studio #[clap(short, long)] pub open: bool, /// Runs on the given device name pub device: Option, /// Command line arguments passed to the runner. /// Use `--` to explicitly mark the start of the arguments. /// e.g. `tauri android build -- [runnerArgs]`. #[clap(last(true))] pub args: Vec, /// Do not error out if a version mismatch is detected on a Tauri package. /// /// Only use this when you are sure the mismatch is incorrectly detected as version mismatched Tauri packages can lead to unknown behavior. #[clap(long)] pub ignore_version_mismatches: bool, } pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> { let mut env = env(false)?; let device = if options.open { None } else { match device_prompt(&env, options.device.as_deref()) { Ok(d) => Some(d), Err(e) => { log::error!("{e}"); None } } }; let dirs = crate::helpers::app_paths::resolve_dirs(); let mut tauri_config = crate::helpers::config::get_config( tauri_utils::platform::Target::Android, &options .config .iter() .map(|conf| &conf.0) .collect::>(), dirs.tauri, )?; let mut built_application = super::build::run( super::build::Options { debug: !options.release, targets: device.as_ref().map(|d| { vec![Target::all() .iter() .find(|(_key, t)| t.arch == d.target().arch) .map(|(key, _t)| key.to_string()) .expect("Target not found")] }), features: options.features, config: options.config.clone(), split_per_abi: true, apk: false, aab: false, skip_bundle: false, open: options.open, ci: false, args: options.args, ignore_version_mismatches: options.ignore_version_mismatches, target_device: device.as_ref().map(|d| TargetDevice { id: d.serial_no().to_string(), name: d.name().to_string(), }), }, noise_level, &dirs, &tauri_config, )?; configure_cargo(&mut env, &built_application.config)?; // options.open is handled by the build command // so all we need to do here is run the app on the selected device if let Some(device) = device { let config = built_application.config.clone(); let release = options.release; let runner = move |_tauri_config: &ConfigMetadata| { device .run( &config, &env, noise_level, if !release { Profile::Debug } else { Profile::Release }, Some(match noise_level { NoiseLevel::Polite => FilterLevel::Info, NoiseLevel::LoudAndProud => FilterLevel::Debug, NoiseLevel::FranklyQuitePedantic => FilterLevel::Verbose, }), false, false, ".MainActivity".into(), ) .map(|c| Box::new(DevChild::new(c)) as Box) .context("failed to run Android app") }; if options.no_watch { runner(&tauri_config)?; } else { built_application.interface.watch( &mut tauri_config, WatcherOptions { config: options.config, additional_watch_folders: options.additional_watch_folders, }, runner, &dirs, )?; } } Ok(()) } ================================================ FILE: crates/tauri-cli/src/mobile/init.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use super::{get_app, Target}; use crate::{ helpers::app_paths::Dirs, helpers::{config::get_config as get_tauri_config, template::JsonMap}, interface::AppInterface, ConfigValue, Result, }; use cargo_mobile2::{ config::app::App, reserved_names::KOTLIN_ONLY_KEYWORDS, util::{ self, cli::{Report, TextWrapper}, }, }; use handlebars::{ Context, Handlebars, Helper, HelperResult, Output, RenderContext, RenderError, RenderErrorReason, }; use std::{env::var_os, path::PathBuf}; pub fn command( target: Target, ci: bool, reinstall_deps: bool, skip_targets_install: bool, config: Vec, ) -> Result<()> { let dirs = crate::helpers::app_paths::resolve_dirs(); let wrapper = TextWrapper::default(); exec( target, &wrapper, ci, reinstall_deps, skip_targets_install, config, dirs, )?; Ok(()) } fn exec( target: Target, wrapper: &TextWrapper, #[allow(unused_variables)] non_interactive: bool, #[allow(unused_variables)] reinstall_deps: bool, skip_targets_install: bool, config: Vec, dirs: Dirs, ) -> Result { let tauri_config = get_tauri_config( target.platform_target(), &config.iter().map(|conf| &conf.0).collect::>(), dirs.tauri, )?; let app = get_app( target, &tauri_config, &AppInterface::new(&tauri_config, None, dirs.tauri)?, dirs.tauri, ); let (handlebars, mut map) = handlebars(&app); let mut args = std::env::args_os(); let (binary, mut build_args) = args .next() .map(|bin| { let bin_path = PathBuf::from(&bin); let mut build_args = vec!["tauri"]; if let Some(bin_stem) = bin_path.file_stem() { let r = regex::Regex::new("(nodejs|node)\\-?([1-9]*)*$").unwrap(); if r.is_match(&bin_stem.to_string_lossy()) { if var_os("PNPM_PACKAGE_NAME").is_some() { return ("pnpm".into(), build_args); } else if is_pnpm_dlx() { return ("pnpm".into(), vec!["dlx", "@tauri-apps/cli"]); } else if let Some(npm_execpath) = var_os("npm_execpath") { let manager_stem = PathBuf::from(&npm_execpath) .file_stem() .unwrap() .to_os_string(); let is_npm = manager_stem == "npm-cli"; let binary = if is_npm { "npm".into() } else if manager_stem == "npx-cli" { "npx".into() } else { manager_stem }; if is_npm { build_args.insert(0, "run"); build_args.insert(1, "--"); } return (binary, build_args); } } else if bin_stem == "deno" { build_args.insert(0, "task"); return (std::ffi::OsString::from("deno"), build_args); } else if !cfg!(debug_assertions) && bin_stem == "cargo-tauri" { return (std::ffi::OsString::from("cargo"), build_args); } } (bin, build_args) }) .unwrap_or_else(|| (std::ffi::OsString::from("cargo"), vec!["tauri"])); build_args.push(target.command_name()); build_args.push(target.ide_build_script_name()); let mut binary = binary.to_string_lossy().to_string(); if binary.ends_with(".exe") || binary.ends_with(".cmd") || binary.ends_with(".bat") { // remove Windows-only extension binary.pop(); binary.pop(); binary.pop(); binary.pop(); } map.insert("tauri-binary", binary); map.insert("tauri-binary-args", &build_args); map.insert("tauri-binary-args-str", build_args.join(" ")); let app = match target { // Generate Android Studio project Target::Android => { let _env = super::android::env(non_interactive)?; let (config, metadata) = super::android::get_config(&app, &tauri_config, &[], &Default::default()); map.insert("android", &config); super::android::project::gen( &config, &metadata, (handlebars, map), wrapper, skip_targets_install, )?; app } #[cfg(target_os = "macos")] // Generate Xcode project Target::Ios => { let (config, metadata) = super::ios::get_config(&app, &tauri_config, &[], &Default::default(), dirs.tauri)?; map.insert("apple", &config); super::ios::project::gen( &tauri_config, &config, &metadata, (handlebars, map), wrapper, non_interactive, reinstall_deps, skip_targets_install, )?; app } }; Report::victory( "Project generated successfully!", "Make cool apps! 🌻 🐕 🎉", ) .print(wrapper); Ok(app) } fn handlebars(app: &App) -> (Handlebars<'static>, JsonMap) { let mut h = Handlebars::new(); h.register_escape_fn(handlebars::no_escape); h.register_helper("html-escape", Box::new(html_escape)); h.register_helper("join", Box::new(join)); h.register_helper("quote-and-join", Box::new(quote_and_join)); h.register_helper( "quote-and-join-colon-prefix", Box::new(quote_and_join_colon_prefix), ); h.register_helper("snake-case", Box::new(snake_case)); h.register_helper("escape-kotlin-keyword", Box::new(escape_kotlin_keyword)); // don't mix these up or very bad things will happen to all of us h.register_helper("prefix-path", Box::new(prefix_path)); h.register_helper("unprefix-path", Box::new(unprefix_path)); let mut map = JsonMap::default(); map.insert("app", app); (h, map) } fn get_str<'a>(helper: &'a Helper) -> &'a str { helper .param(0) .and_then(|v| v.value().as_str()) .unwrap_or("") } fn get_str_array(helper: &Helper, formatter: impl Fn(&str) -> String) -> Option> { helper.param(0).and_then(|v| { v.value() .as_array() .and_then(|arr| arr.iter().map(|val| val.as_str().map(&formatter)).collect()) }) } fn html_escape( helper: &Helper, _: &Handlebars, _ctx: &Context, _: &mut RenderContext, out: &mut dyn Output, ) -> HelperResult { out .write(&handlebars::html_escape(get_str(helper))) .map_err(Into::into) } fn join( helper: &Helper, _: &Handlebars, _: &Context, _: &mut RenderContext, out: &mut dyn Output, ) -> HelperResult { out .write( &get_str_array(helper, |s| s.to_string()) .ok_or_else(|| { RenderErrorReason::ParamTypeMismatchForName("join", "0".to_owned(), "array".to_owned()) })? .join(", "), ) .map_err(Into::into) } fn quote_and_join( helper: &Helper, _: &Handlebars, _: &Context, _: &mut RenderContext, out: &mut dyn Output, ) -> HelperResult { out .write( &get_str_array(helper, |s| format!("{s:?}")) .ok_or_else(|| { RenderErrorReason::ParamTypeMismatchForName( "quote-and-join", "0".to_owned(), "array".to_owned(), ) })? .join(", "), ) .map_err(Into::into) } fn quote_and_join_colon_prefix( helper: &Helper, _: &Handlebars, _: &Context, _: &mut RenderContext, out: &mut dyn Output, ) -> HelperResult { out .write( &get_str_array(helper, |s| format!("{:?}", format!(":{s}"))) .ok_or_else(|| { RenderErrorReason::ParamTypeMismatchForName( "quote-and-join-colon-prefix", "0".to_owned(), "array".to_owned(), ) })? .join(", "), ) .map_err(Into::into) } fn snake_case( helper: &Helper, _: &Handlebars, _: &Context, _: &mut RenderContext, out: &mut dyn Output, ) -> HelperResult { use heck::ToSnekCase as _; out .write(&get_str(helper).to_snek_case()) .map_err(Into::into) } fn escape_kotlin_keyword( helper: &Helper, _: &Handlebars, _: &Context, _: &mut RenderContext, out: &mut dyn Output, ) -> HelperResult { let escaped_result = get_str(helper) .split('.') .map(|s| { if KOTLIN_ONLY_KEYWORDS.contains(&s) { format!("`{s}`") } else { s.to_string() } }) .collect::>() .join("."); out.write(&escaped_result).map_err(Into::into) } fn app_root(ctx: &Context) -> std::result::Result<&str, RenderError> { let app_root = ctx .data() .get("app") .ok_or_else(|| RenderErrorReason::Other("`app` missing from template data.".to_owned()))? .get("root-dir") .ok_or_else(|| { RenderErrorReason::Other("`app.root-dir` missing from template data.".to_owned()) })?; app_root.as_str().ok_or_else(|| { RenderErrorReason::Other("`app.root-dir` contained invalid UTF-8.".to_owned()).into() }) } fn prefix_path( helper: &Helper, _: &Handlebars, ctx: &Context, _: &mut RenderContext, out: &mut dyn Output, ) -> HelperResult { out .write( util::prefix_path(app_root(ctx)?, get_str(helper)) .to_str() .ok_or_else(|| { RenderErrorReason::Other( "Either the `app.root-dir` or the specified path contained invalid UTF-8.".to_owned(), ) })?, ) .map_err(Into::into) } fn unprefix_path( helper: &Helper, _: &Handlebars, ctx: &Context, _: &mut RenderContext, out: &mut dyn Output, ) -> HelperResult { out .write( util::unprefix_path(app_root(ctx)?, get_str(helper)) .map_err(|_| { RenderErrorReason::Other( "Attempted to unprefix a path that wasn't in the app root dir.".to_owned(), ) })? .to_str() .ok_or_else(|| { RenderErrorReason::Other( "Either the `app.root-dir` or the specified path contained invalid UTF-8.".to_owned(), ) })?, ) .map_err(Into::into) } fn is_pnpm_dlx() -> bool { var_os("NODE_PATH") .map(PathBuf::from) .is_some_and(|node_path| { let mut iter = node_path.components().peekable(); while let Some(c) = iter.next() { if c.as_os_str() == "pnpm" && iter.peek().is_some_and(|c| c.as_os_str() == "dlx") { return true; } } false }) } ================================================ FILE: crates/tauri-cli/src/mobile/ios/build.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use super::{ detect_target_ok, ensure_init, env, get_app, get_config, inject_resources, load_pbxproj, log_finished, open_and_wait, project_config, synchronize_project_config, MobileTarget, OptionsHandle, }; use crate::{ build::Options as BuildOptions, error::{Context, ErrorExt}, helpers::{ app_paths::Dirs, config::{get_config as get_tauri_config, ConfigMetadata}, flock, plist::merge_plist, }, interface::{AppInterface, Options as InterfaceOptions}, mobile::{ios::ensure_ios_runtime_installed, write_options, CliOptions, TargetDevice}, ConfigValue, Error, Result, }; use clap::{ArgAction, Parser, ValueEnum}; use cargo_mobile2::{ apple::{ config::Config as AppleConfig, target::{ArchiveConfig, BuildConfig, ExportConfig, Target}, }, env::Env, opts::{NoiseLevel, Profile}, target::{call_for_targets_with_fallback, TargetInvalid, TargetTrait}, }; use rand::distr::{Alphanumeric, SampleString}; use std::{ env::{set_current_dir, var, var_os}, fs, path::PathBuf, }; #[derive(Debug, Clone, Parser)] #[clap( about = "Build your app in release mode for iOS and generate IPAs", long_about = "Build your app in release mode for iOS and generate IPAs. It makes use of the `build.frontendDist` property from your `tauri.conf.json` file. It also runs your `build.beforeBuildCommand` which usually builds your frontend into `build.frontendDist`." )] pub struct Options { /// Builds with the debug flag #[clap(short, long)] pub debug: bool, /// Which targets to build. #[clap( short, long = "target", action = ArgAction::Append, num_args(0..), default_value = Target::DEFAULT_KEY, value_parser(clap::builder::PossibleValuesParser::new(Target::name_list())) )] pub targets: Option>, /// List of cargo features to activate #[clap(short, long, action = ArgAction::Append, num_args(0..), value_delimiter = ',')] pub features: Vec, /// JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file /// /// Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts. /// /// Note that a platform-specific file is looked up and merged with the default file by default /// (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json) /// but you can use this for more specific use cases such as different build flavors. #[clap(short, long)] pub config: Vec, /// Build number to append to the app version. #[clap(long)] pub build_number: Option, /// Open Xcode #[clap(short, long)] pub open: bool, /// Skip prompting for values #[clap(long, env = "CI")] pub ci: bool, /// Describes how Xcode should export the archive. /// /// Use this to create a package ready for the App Store (app-store-connect option) or TestFlight (release-testing option). #[clap(long, value_enum)] pub export_method: Option, /// Command line arguments passed to the runner. /// Use `--` to explicitly mark the start of the arguments. /// e.g. `tauri ios build -- [runnerArgs]`. #[clap(last(true))] pub args: Vec, /// Do not error out if a version mismatch is detected on a Tauri package. /// /// Only use this when you are sure the mismatch is incorrectly detected as version mismatched Tauri packages can lead to unknown behavior. #[clap(long)] pub ignore_version_mismatches: bool, /// Target device of this build #[clap(skip)] pub target_device: Option, } #[derive(Debug, Clone, Copy, ValueEnum)] pub enum ExportMethod { AppStoreConnect, ReleaseTesting, Debugging, } impl ExportMethod { /// Xcode 15.4 deprecated these names (in this case we should use the Display impl). pub fn pre_xcode_15_4_name(&self) -> String { match self { Self::AppStoreConnect => "app-store".to_string(), Self::ReleaseTesting => "ad-hoc".to_string(), Self::Debugging => "development".to_string(), } } } impl std::fmt::Display for ExportMethod { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::AppStoreConnect => write!(f, "app-store-connect"), Self::ReleaseTesting => write!(f, "release-testing"), Self::Debugging => write!(f, "debugging"), } } } impl std::str::FromStr for ExportMethod { type Err = &'static str; fn from_str(s: &str) -> std::result::Result { match s { "app-store-connect" => Ok(Self::AppStoreConnect), "release-testing" => Ok(Self::ReleaseTesting), "debugging" => Ok(Self::Debugging), _ => Err("unknown ios target"), } } } impl From for BuildOptions { fn from(options: Options) -> Self { Self { runner: None, debug: options.debug, target: None, features: options.features, bundles: None, no_bundle: false, config: options.config, args: options.args, ci: options.ci, skip_stapling: false, ignore_version_mismatches: options.ignore_version_mismatches, no_sign: false, } } } pub struct BuiltApplication { pub config: AppleConfig, pub interface: AppInterface, // prevent drop #[allow(dead_code)] options_handle: OptionsHandle, } pub fn command(options: Options, noise_level: NoiseLevel) -> Result { let dirs = crate::helpers::app_paths::resolve_dirs(); run(options, noise_level, &dirs) } pub fn run(options: Options, noise_level: NoiseLevel, dirs: &Dirs) -> Result { let mut build_options: BuildOptions = options.clone().into(); build_options.target = Some( Target::all() .get( options .targets .as_ref() .and_then(|t| t.first()) .map(|t| t.as_str()) .unwrap_or(Target::DEFAULT_KEY), ) .unwrap() .triple .into(), ); let tauri_config = get_tauri_config( tauri_utils::platform::Target::Ios, &options.config.iter().map(|c| &c.0).collect::>(), dirs.tauri, )?; let interface = AppInterface::new(&tauri_config, build_options.target.clone(), dirs.tauri)?; interface.build_options(&mut build_options.args, &mut build_options.features, true); let app = get_app(MobileTarget::Ios, &tauri_config, &interface, dirs.tauri); let (mut config, _) = get_config( &app, &tauri_config, &build_options.features, &CliOptions { dev: false, features: build_options.features.clone(), args: build_options.args.clone(), noise_level, vars: Default::default(), config: build_options.config.clone(), target_device: None, }, dirs.tauri, )?; set_current_dir(dirs.tauri).context("failed to set current directory")?; ensure_init( &tauri_config, config.app(), config.project_dir(), MobileTarget::Ios, options.ci, )?; inject_resources(&config, &tauri_config)?; let mut plist = plist::Dictionary::new(); plist.insert( "CFBundleShortVersionString".into(), config.bundle_version_short().into(), ); let info_plist_path = config .project_dir() .join(config.scheme()) .join("Info.plist"); let mut src_plists = vec![info_plist_path.clone().into()]; src_plists.push(plist::Value::Dictionary(plist).into()); if dirs.tauri.join("Info.plist").exists() { src_plists.push(dirs.tauri.join("Info.plist").into()); } if dirs.tauri.join("Info.ios.plist").exists() { src_plists.push(dirs.tauri.join("Info.ios.plist").into()); } if let Some(info_plist) = &tauri_config.bundle.ios.info_plist { src_plists.push(info_plist.clone().into()); } let merged_info_plist = merge_plist(src_plists)?; merged_info_plist .to_file_xml(&info_plist_path) .map_err(std::io::Error::other) .fs_context("failed to save merged Info.plist file", info_plist_path)?; let mut env = env().context("failed to load iOS environment")?; if !options.open { ensure_ios_runtime_installed()?; } let mut export_options_plist = plist::Dictionary::new(); if let Some(method) = options.export_method { let xcode_version = crate::info::env_system::xcode_version().context("failed to determine Xcode version")?; let mut iter = xcode_version.split('.'); let major = iter.next().context(format!( "failed to parse Xcode version `{xcode_version}` as semver" ))?; let minor = iter.next().context(format!( "failed to parse Xcode version `{xcode_version}` as semver" ))?; let major = major.parse::().ok().context(format!( "failed to parse Xcode version `{xcode_version}` as semver: major is not a number" ))?; let minor = minor.parse::().ok().context(format!( "failed to parse Xcode version `{xcode_version}` as semver: minor is not a number" ))?; if major < 15 || (major == 15 && minor < 4) { export_options_plist.insert("method".to_string(), method.pre_xcode_15_4_name().into()); } else { export_options_plist.insert("method".to_string(), method.to_string().into()); } } let (keychain, provisioning_profile) = super::signing_from_env()?; let project_config = project_config(keychain.as_ref(), provisioning_profile.as_ref())?; let mut pbxproj = load_pbxproj(&config)?; // synchronize pbxproj and exportoptions synchronize_project_config( &config, &tauri_config, &mut pbxproj, &mut export_options_plist, &project_config, options.debug, )?; if pbxproj.has_changes() { pbxproj .save() .fs_context("failed to save pbxproj file", pbxproj.path)?; } // merge export options and write to temp file let _export_options_tmp = if !export_options_plist.is_empty() { let export_options_plist_path = config.project_dir().join("ExportOptions.plist"); let export_options = tempfile::NamedTempFile::new().context("failed to create temporary file")?; let merged_plist = merge_plist(vec![ export_options_plist_path.into(), plist::Value::from(export_options_plist).into(), ])?; merged_plist .to_file_xml(export_options.path()) .map_err(std::io::Error::other) .fs_context( "failed to save export options plist file", export_options.path().to_path_buf(), )?; config.set_export_options_plist_path(export_options.path()); Some(export_options) } else { None }; let open = options.open; let options_handle = run_build( &interface, options, build_options, tauri_config, &mut config, &mut env, noise_level, dirs, )?; if open { open_and_wait(&config, &env); } Ok(BuiltApplication { config, interface, options_handle, }) } #[allow(clippy::too_many_arguments)] fn run_build( interface: &AppInterface, options: Options, mut build_options: BuildOptions, tauri_config: ConfigMetadata, config: &mut AppleConfig, env: &mut Env, noise_level: NoiseLevel, dirs: &Dirs, ) -> Result { let profile = if options.debug { Profile::Debug } else { Profile::Release }; crate::build::setup(interface, &mut build_options, &tauri_config, dirs, true)?; let app_settings = interface.app_settings(); let out_dir = app_settings.out_dir( &InterfaceOptions { debug: build_options.debug, target: build_options.target.clone(), args: build_options.args.clone(), ..Default::default() }, dirs.tauri, )?; let _lock = flock::open_rw(out_dir.join("lock").with_extension("ios"), "iOS")?; let cli_options = CliOptions { dev: false, features: build_options.features.clone(), args: build_options.args.clone(), noise_level, vars: Default::default(), config: build_options.config.clone(), target_device: options.target_device.clone(), }; let handle = write_options(&tauri_config, cli_options)?; if options.open { return Ok(handle); } let mut out_files = Vec::new(); let force_skip_target_fallback = options.targets.as_ref().is_some_and(|t| t.is_empty()); call_for_targets_with_fallback( options.targets.unwrap_or_default().iter(), if force_skip_target_fallback { &|_| None } else { &detect_target_ok }, env, |target: &Target| -> Result<()> { let mut app_version = config.bundle_version().to_string(); if let Some(build_number) = options.build_number { app_version.push('.'); app_version.push_str(&build_number.to_string()); } let credentials = auth_credentials_from_env()?; let skip_signing = credentials.is_some(); let mut build_config = BuildConfig::new().allow_provisioning_updates(); if let Some(credentials) = &credentials { build_config = build_config .authentication_credentials(credentials.clone()) .skip_codesign(); } target .build(None, config, env, noise_level, profile, build_config) .context("failed to build iOS app")?; let mut archive_config = ArchiveConfig::new(); if skip_signing { archive_config = archive_config.skip_codesign(); } target .archive( config, env, noise_level, profile, Some(app_version), archive_config, ) .context("failed to archive iOS app")?; let out_dir = config.export_dir().join(target.arch); if target.sdk == "iphonesimulator" { fs::create_dir_all(&out_dir) .fs_context("failed to create Xcode output directory", out_dir.clone())?; let app_path = config .archive_dir() .join(format!("{}.xcarchive", config.scheme())) .join("Products") .join("Applications") .join(config.app().stylized_name()) .with_extension("app"); let path = out_dir.join(app_path.file_name().unwrap()); fs::rename(&app_path, &path).fs_context("failed to rename app", app_path)?; out_files.push(path); } else { // if we skipped code signing, we do not have the entitlements applied to our exported IPA // we must force sign the app binary with a dummy certificate just to preserve the entitlements // target.export() will sign it with an actual certificate for us if skip_signing { let password = Alphanumeric.sample_string(&mut rand::rng(), 16); let certificate = tauri_macos_sign::certificate::generate_self_signed( tauri_macos_sign::certificate::SelfSignedCertificateRequest { algorithm: "rsa".to_string(), profile: tauri_macos_sign::certificate::CertificateProfile::AppleDistribution, team_id: "unset".to_string(), person_name: "Tauri".to_string(), country_name: "NL".to_string(), validity_days: 365, password: password.clone(), }, ) .map_err(Box::new)?; let tmp_dir = tempfile::tempdir().context("failed to create temporary directory")?; let cert_path = tmp_dir.path().join("cert.p12"); std::fs::write(&cert_path, certificate) .fs_context("failed to write certificate", cert_path.clone())?; let self_signed_cert_keychain = tauri_macos_sign::Keychain::with_certificate_file(&cert_path, &password.into()) .map_err(Box::new)?; let app_dir = config .export_dir() .join(format!("{}.xcarchive", config.scheme())) .join("Products/Applications") .join(format!("{}.app", config.app().stylized_name())); self_signed_cert_keychain .sign( &app_dir.join(config.app().stylized_name()), Some( &config .project_dir() .join(config.scheme()) .join(format!("{}.entitlements", config.scheme())), ), false, ) .map_err(Box::new)?; } let mut export_config = ExportConfig::new().allow_provisioning_updates(); if let Some(credentials) = &credentials { export_config = export_config.authentication_credentials(credentials.clone()); } target .export(config, env, noise_level, export_config) .context("failed to export iOS app")?; if let Ok(ipa_path) = config.ipa_path() { fs::create_dir_all(&out_dir) .fs_context("failed to create Xcode output directory", out_dir.clone())?; let path = out_dir.join(ipa_path.file_name().unwrap()); fs::rename(&ipa_path, &path).fs_context("failed to rename IPA", ipa_path)?; out_files.push(path); } } Ok(()) }, ) .map_err(|e: TargetInvalid| Error::GenericError(e.to_string()))??; if !out_files.is_empty() { log_finished(out_files, "iOS Bundle"); } Ok(handle) } fn auth_credentials_from_env() -> Result> { match ( var("APPLE_API_KEY"), var("APPLE_API_ISSUER"), var_os("APPLE_API_KEY_PATH").map(PathBuf::from), ) { (Ok(key_id), Ok(key_issuer_id), Some(key_path)) => { Ok(Some(cargo_mobile2::apple::AuthCredentials { key_path, key_id, key_issuer_id, })) } (Err(_), Err(_), None) => Ok(None), _ => crate::error::bail!( "APPLE_API_KEY, APPLE_API_ISSUER and APPLE_API_KEY_PATH must be provided for code signing" ), } } ================================================ FILE: crates/tauri-cli/src/mobile/ios/dev.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use super::{ device_prompt, ensure_init, env, get_app, get_config, inject_resources, load_pbxproj, open_and_wait, synchronize_project_config, MobileTarget, ProjectConfig, }; use crate::{ dev::Options as DevOptions, error::{Context, ErrorExt}, helpers::{ app_paths::Dirs, config::{get_config as get_tauri_config, ConfigMetadata}, flock, plist::merge_plist, }, interface::{AppInterface, MobileOptions, Options as InterfaceOptions}, mobile::{ ios::ensure_ios_runtime_installed, use_network_address_for_dev_url, write_options, CliOptions, DevChild, DevHost, DevProcess, }, ConfigValue, Result, }; use clap::{ArgAction, Parser}; use cargo_mobile2::{ apple::{ config::Config as AppleConfig, device::{Device, DeviceKind, RunError}, target::BuildError, }, env::Env, opts::{NoiseLevel, Profile}, }; use url::Host; use std::{env::set_current_dir, net::Ipv4Addr, path::PathBuf}; const PHYSICAL_IPHONE_DEV_WARNING: &str = "To develop on physical phones you need the `--host` option (not required for Simulators). See the documentation for more information: https://v2.tauri.app/develop/#development-server"; #[derive(Debug, Clone, Parser)] #[clap( about = "Run your app in development mode on iOS", long_about = "Run your app in development mode on iOS with hot-reloading for the Rust code. It makes use of the `build.devUrl` property from your `tauri.conf.json` file. It also runs your `build.beforeDevCommand` which usually starts your frontend devServer. When connected to a physical iOS device, the public network address must be used instead of `localhost` for the devUrl property. Tauri makes that change automatically, but your dev server might need a different configuration to listen on the public address. You can check the `TAURI_DEV_HOST` environment variable to determine whether the public network should be used or not." )] pub struct Options { /// List of cargo features to activate #[clap(short, long, action = ArgAction::Append, num_args(0..), value_delimiter = ',')] pub features: Vec, /// Exit on panic #[clap(short, long)] exit_on_panic: bool, /// JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file /// /// Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts. /// /// Note that a platform-specific file is looked up and merged with the default file by default /// (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json) /// but you can use this for more specific use cases such as different build flavors. #[clap(short, long)] pub config: Vec, /// Run the code in release mode #[clap(long = "release")] pub release_mode: bool, /// Skip waiting for the frontend dev server to start before building the tauri application. #[clap(long, env = "TAURI_CLI_NO_DEV_SERVER_WAIT")] pub no_dev_server_wait: bool, /// Disable the file watcher #[clap(long)] pub no_watch: bool, /// Additional paths to watch for changes. #[clap(long)] pub additional_watch_folders: Vec, /// Open Xcode instead of trying to run on a connected device #[clap(short, long)] pub open: bool, /// Runs on the given device name pub device: Option, /// Force prompting for an IP to use to connect to the dev server on mobile. #[clap(long)] pub force_ip_prompt: bool, /// Use the public network address for the development server. /// If an actual address it provided, it is used instead of prompting to pick one. /// /// This option is particularly useful along the `--open` flag when you intend on running on a physical device. /// /// This replaces the devUrl configuration value to match the public network address host, /// it is your responsibility to set up your development server to listen on this address /// by using 0.0.0.0 as host for instance. /// /// When this is set or when running on an iOS device the CLI sets the `TAURI_DEV_HOST` /// environment variable so you can check this on your framework's configuration to expose the development server /// on the public network address. #[clap(long, default_value_t, default_missing_value(""), num_args(0..=1))] pub host: DevHost, /// Disable the built-in dev server for static files. #[clap(long)] pub no_dev_server: bool, /// Specify port for the built-in dev server for static files. Defaults to 1430. #[clap(long, env = "TAURI_CLI_PORT")] pub port: Option, /// Command line arguments passed to the runner. /// Use `--` to explicitly mark the start of the arguments. /// e.g. `tauri ios dev -- [runnerArgs]`. #[clap(last(true))] pub args: Vec, /// Path to the certificate file used by your dev server. Required for mobile dev when using HTTPS. #[clap(long, env = "TAURI_DEV_ROOT_CERTIFICATE_PATH")] pub root_certificate_path: Option, } impl From for DevOptions { fn from(options: Options) -> Self { Self { runner: None, target: None, features: options.features, exit_on_panic: options.exit_on_panic, config: options.config, release_mode: options.release_mode, args: options.args, no_watch: options.no_watch, additional_watch_folders: options.additional_watch_folders, no_dev_server: options.no_dev_server, no_dev_server_wait: options.no_dev_server_wait, port: options.port, host: options.host.0.unwrap_or_default(), } } } pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> { let dirs = crate::helpers::app_paths::resolve_dirs(); let result = run_command(options, noise_level, dirs); if result.is_err() { crate::dev::kill_before_dev_process(); } result } fn run_command(options: Options, noise_level: NoiseLevel, dirs: Dirs) -> Result<()> { // setup env additions before calling env() if let Some(root_certificate_path) = &options.root_certificate_path { std::env::set_var( "TAURI_DEV_ROOT_CERTIFICATE", std::fs::read_to_string(root_certificate_path).fs_context( "failed to read root certificate file", root_certificate_path.clone(), )?, ); } let env = env().context("failed to load iOS environment")?; let device = if options.open { None } else { match device_prompt(&env, options.device.as_deref()) { Ok(d) => Some(d), Err(e) => { log::error!("{e}"); None } } }; if device.is_some() { ensure_ios_runtime_installed()?; } let mut dev_options: DevOptions = options.clone().into(); let target_triple = device .as_ref() .map(|d| d.target().triple.to_string()) .unwrap_or_else(|| "aarch64-apple-ios".into()); dev_options.target = Some(target_triple.clone()); dev_options.args.push("--lib".into()); let tauri_config = get_tauri_config( tauri_utils::platform::Target::Ios, &options.config.iter().map(|c| &c.0).collect::>(), dirs.tauri, )?; let interface = AppInterface::new(&tauri_config, Some(target_triple), dirs.tauri)?; let app = get_app(MobileTarget::Ios, &tauri_config, &interface, dirs.tauri); let (config, _) = get_config( &app, &tauri_config, &dev_options.features, &CliOptions { dev: true, features: dev_options.features.clone(), args: dev_options.args.clone(), noise_level, vars: Default::default(), config: dev_options.config.clone(), target_device: None, }, dirs.tauri, )?; set_current_dir(dirs.tauri).context("failed to set current directory to Tauri directory")?; ensure_init( &tauri_config, config.app(), config.project_dir(), MobileTarget::Ios, false, )?; inject_resources(&config, &tauri_config)?; let info_plist_path = config .project_dir() .join(config.scheme()) .join("Info.plist"); let mut src_plists = vec![info_plist_path.clone().into()]; if dirs.tauri.join("Info.plist").exists() { src_plists.push(dirs.tauri.join("Info.plist").into()); } if dirs.tauri.join("Info.ios.plist").exists() { src_plists.push(dirs.tauri.join("Info.ios.plist").into()); } if let Some(info_plist) = &tauri_config.bundle.ios.info_plist { src_plists.push(info_plist.clone().into()); } let merged_info_plist = merge_plist(src_plists)?; merged_info_plist .to_file_xml(&info_plist_path) .map_err(std::io::Error::other) .fs_context("failed to save merged Info.plist file", info_plist_path)?; let mut pbxproj = load_pbxproj(&config)?; // synchronize pbxproj synchronize_project_config( &config, &tauri_config, &mut pbxproj, &mut plist::Dictionary::new(), &ProjectConfig { code_sign_identity: None, team_id: None, provisioning_profile_uuid: None, }, !options.release_mode, )?; if pbxproj.has_changes() { pbxproj .save() .fs_context("failed to save pbxproj file", pbxproj.path)?; } run_dev( interface, options, dev_options, tauri_config, device, env, &config, noise_level, &dirs, ) } #[allow(clippy::too_many_arguments)] fn run_dev( mut interface: AppInterface, options: Options, mut dev_options: DevOptions, mut tauri_config: ConfigMetadata, device: Option, env: Env, config: &AppleConfig, noise_level: NoiseLevel, dirs: &Dirs, ) -> Result<()> { // when --host is provided or running on a physical device or resolving 0.0.0.0 we must use the network IP if options.host.0.is_some() || device .as_ref() .map(|device| !matches!(device.kind(), DeviceKind::Simulator)) .unwrap_or(false) || tauri_config.build.dev_url.as_ref().is_some_and(|url| { matches!( url.host(), Some(Host::Ipv4(i)) if i == Ipv4Addr::UNSPECIFIED ) }) { use_network_address_for_dev_url( &mut tauri_config, &mut dev_options, options.force_ip_prompt, dirs.tauri, )?; } crate::dev::setup(&interface, &mut dev_options, &mut tauri_config, dirs)?; let app_settings = interface.app_settings(); let out_dir = app_settings.out_dir( &InterfaceOptions { debug: !dev_options.release_mode, target: dev_options.target.clone(), ..Default::default() }, dirs.tauri, )?; let _lock = flock::open_rw(out_dir.join("lock").with_extension("ios"), "iOS")?; let set_host = options.host.0.is_some(); let open = options.open; interface.mobile_dev( &mut tauri_config, MobileOptions { debug: true, features: options.features, args: options.args, config: dev_options.config.clone(), no_watch: options.no_watch, additional_watch_folders: options.additional_watch_folders, }, |options, tauri_config| { let cli_options = CliOptions { dev: true, features: options.features.clone(), args: options.args.clone(), noise_level, vars: Default::default(), config: dev_options.config.clone(), target_device: None, }; let _handle = write_options(tauri_config, cli_options)?; let open_xcode = || { if !set_host { log::warn!("{PHYSICAL_IPHONE_DEV_WARNING}"); } open_and_wait(config, &env) }; if open { open_xcode() } else if let Some(device) = &device { match run(device, options, config, noise_level, &env) { Ok(c) => Ok(Box::new(c) as Box), Err(RunError::BuildFailed(BuildError::Sdk(sdk_err))) => { log::warn!("{sdk_err}"); open_xcode() } Err(e) => { crate::dev::kill_before_dev_process(); crate::error::bail!("failed to run iOS app: {}", e) } } } else { open_xcode() } }, dirs, ) } fn run( device: &Device<'_>, options: MobileOptions, config: &AppleConfig, noise_level: NoiseLevel, env: &Env, ) -> std::result::Result { let profile = if options.debug { Profile::Debug } else { Profile::Release }; device .run( config, env, noise_level, false, // do not quit on app exit profile, ) .map(DevChild::new) } ================================================ FILE: crates/tauri-cli/src/mobile/ios/mod.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use cargo_mobile2::{ apple::{ config::{ Config as AppleConfig, Metadata as AppleMetadata, Platform as ApplePlatform, Raw as RawAppleConfig, }, device::{self, Device}, target::Target, teams::find_development_teams, }, config::app::{App, DEFAULT_ASSET_DIR}, env::Env, opts::NoiseLevel, os, util::{prompt, relativize_path}, }; use clap::{Parser, Subcommand}; use serde::Deserialize; use sublime_fuzzy::best_match; use tauri_utils::resources::ResourcePaths; use super::{ ensure_init, env, get_app, init::command as init_command, log_finished, read_options, CliOptions, OptionsHandle, Target as MobileTarget, MIN_DEVICE_MATCH_SCORE, }; use crate::{ error::{Context, ErrorExt}, helpers::{ config::{BundleResources, Config as TauriConfig, ConfigMetadata}, pbxproj, strip_semver_prerelease_tag, }, ConfigValue, Error, Result, }; use std::{ env::{set_var, var_os}, fs::create_dir_all, path::Path, str::FromStr, thread::sleep, time::Duration, }; mod build; mod dev; pub(crate) mod project; mod run; mod xcode_script; pub const APPLE_DEVELOPMENT_TEAM_ENV_VAR_NAME: &str = "APPLE_DEVELOPMENT_TEAM"; pub const LIB_OUTPUT_FILE_NAME: &str = "libapp.a"; #[derive(Parser)] #[clap( author, version, about = "iOS commands", subcommand_required(true), arg_required_else_help(true) )] pub struct Cli { #[clap(subcommand)] command: Commands, } #[derive(Debug, Parser)] #[clap(about = "Initialize iOS target in the project")] pub struct InitOptions { /// Skip prompting for values #[clap(long, env = "CI")] ci: bool, /// Reinstall dependencies #[clap(short, long)] reinstall_deps: bool, /// Skips installing rust toolchains via rustup #[clap(long)] skip_targets_install: bool, /// JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file /// /// Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts. /// /// Note that a platform-specific file is looked up and merged with the default file by default /// (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json) /// but you can use this for more specific use cases such as different build flavors. #[clap(short, long)] pub config: Vec, } #[derive(Subcommand)] enum Commands { Init(InitOptions), Dev(dev::Options), Build(build::Options), Run(run::Options), #[clap(hide(true))] XcodeScript(xcode_script::Options), } pub fn command(cli: Cli, verbosity: u8) -> Result<()> { let noise_level = NoiseLevel::from_occurrences(verbosity as u64); match cli.command { Commands::Init(options) => init_command( MobileTarget::Ios, options.ci, options.reinstall_deps, options.skip_targets_install, options.config, )?, Commands::Dev(options) => dev::command(options, noise_level)?, Commands::Build(options) => build::command(options, noise_level).map(|_| ())?, Commands::Run(options) => run::command(options, noise_level)?, Commands::XcodeScript(options) => xcode_script::command(options)?, } Ok(()) } pub fn get_config( app: &App, tauri_config: &TauriConfig, features: &[String], cli_options: &CliOptions, tauri_dir: &Path, ) -> Result<(AppleConfig, AppleMetadata)> { let mut ios_options = cli_options.clone(); ios_options.features.extend_from_slice(features); let bundle_version = if let Some(bundle_version) = tauri_config .bundle .ios .bundle_version .clone() .or_else(|| tauri_config.version.clone()) { // if it's a semver string, we must strip the prerelease tag if let Ok(mut version) = semver::Version::from_str(&bundle_version) { if !version.pre.is_empty() { log::warn!("CFBundleVersion cannot have prerelease tag; stripping from {bundle_version}"); strip_semver_prerelease_tag(&mut version)?; } // correctly serialize version - cannot contain `+` as build metadata separator Some(format!( "{}.{}.{}{}", version.major, version.minor, version.patch, if version.build.is_empty() { "".to_string() } else { format!(".{}", version.build.as_str()) } )) } else { // let it go as is - cargo-mobile2 will validate it Some(bundle_version) } } else { None }; let full_bundle_version_short = if let Some(app_version) = &tauri_config.version { if let Ok(mut version) = semver::Version::from_str(app_version) { if !version.pre.is_empty() { log::warn!( "CFBundleShortVersionString cannot have prerelease tag; stripping from {app_version}" ); strip_semver_prerelease_tag(&mut version)?; } // correctly serialize version - cannot contain `+` as build metadata separator Some(format!( "{}.{}.{}{}", version.major, version.minor, version.patch, if version.build.is_empty() { "".to_string() } else { format!(".{}", version.build.as_str()) } )) } else { // let it go as is - cargo-mobile2 will validate it Some(app_version.clone()) } } else { bundle_version.clone() }; let bundle_version_short = if let Some(full_version) = full_bundle_version_short.as_deref() { let mut s = full_version.split('.'); let short_version = format!( "{}.{}.{}", s.next().unwrap_or("0"), s.next().unwrap_or("0"), s.next().unwrap_or("0") ); if short_version != full_version { log::warn!("{full_version:?} is not a valid CFBundleShortVersionString since it must contain exactly three dot separated integers; setting it to {short_version} instead"); } Some(short_version) } else { None }; let raw = RawAppleConfig { development_team: std::env::var(APPLE_DEVELOPMENT_TEAM_ENV_VAR_NAME) .ok() .or_else(|| tauri_config.bundle.ios.development_team.clone()) .or_else(|| { let teams = find_development_teams().unwrap_or_default(); match teams.len() { 0 => { log::warn!("No code signing certificates found. You must add one and set the certificate development team ID on the `bundle > iOS > developmentTeam` config value or the `{APPLE_DEVELOPMENT_TEAM_ENV_VAR_NAME}` environment variable. To list the available certificates, run `tauri info`."); None } 1 => None, _ => { log::warn!("You must set the code signing certificate development team ID on the `bundle > iOS > developmentTeam` config value or the `{APPLE_DEVELOPMENT_TEAM_ENV_VAR_NAME}` environment variable. Available certificates: {}", teams.iter().map(|t| format!("{} (ID: {})", t.name, t.id)).collect::>().join(", ")); None } } }), ios_features: Some(ios_options.features.clone()), bundle_version, bundle_version_short, ios_version: Some(tauri_config.bundle.ios.minimum_system_version.clone()), ..Default::default() }; let config = AppleConfig::from_raw(app.clone(), Some(raw)) .context("failed to create Apple configuration")?; let mut vendor_frameworks = Vec::new(); let mut frameworks = Vec::new(); for framework in tauri_config .bundle .ios .frameworks .clone() .unwrap_or_default() { let framework_path = Path::new(&framework); let ext = framework_path.extension().unwrap_or_default(); if ext.is_empty() { frameworks.push(framework); } else if ext == "framework" { frameworks.push( framework_path .file_stem() .unwrap() .to_string_lossy() .to_string(), ); } else { vendor_frameworks.push( relativize_path(tauri_dir.join(framework_path), config.project_dir()) .to_string_lossy() .to_string(), ); } } let metadata = AppleMetadata { supported: true, ios: ApplePlatform { cargo_args: Some(ios_options.args), features: Some(ios_options.features), frameworks: Some(frameworks), vendor_frameworks: Some(vendor_frameworks), ..Default::default() }, macos: Default::default(), }; set_var("TAURI_IOS_PROJECT_PATH", config.project_dir()); set_var("TAURI_IOS_APP_NAME", config.app().name()); Ok((config, metadata)) } fn connected_device_prompt<'a>(env: &'_ Env, target: Option<&str>) -> Result> { let device_list = device::list_devices(env).map_err(|cause| { Error::GenericError(format!("Failed to detect connected iOS devices: {cause}")) })?; if !device_list.is_empty() { let device = if let Some(t) = target { let (device, score) = device_list .into_iter() .rev() .map(|d| { let score = best_match(t, d.name()).map_or(0, |m| m.score()); (d, score) }) .max_by_key(|(_, score)| *score) // we already checked the list is not empty .unwrap(); if score > MIN_DEVICE_MATCH_SCORE { device } else { crate::error::bail!("Could not find an iOS device matching {t}") } } else { let index = if device_list.len() > 1 { prompt::list( concat!("Detected ", "iOS", " devices"), device_list.iter(), "device", None, "Device", ) .context("failed to prompt for device")? } else { 0 }; device_list.into_iter().nth(index).unwrap() }; println!( "Detected connected device: {} with target {:?}", device, device.target().triple, ); Ok(device) } else { crate::error::bail!("No connected iOS devices detected") } } #[derive(Default, Deserialize)] struct InstalledRuntimesList { runtimes: Vec, } #[derive(Deserialize)] struct InstalledRuntime { name: String, } fn simulator_prompt(env: &'_ Env, target: Option<&str>) -> Result { let simulator_list = device::list_simulators(env).map_err(|cause| { Error::GenericError(format!( "Failed to detect connected iOS Simulator devices: {cause}" )) })?; if !simulator_list.is_empty() { let device = if let Some(t) = target { let (device, score) = simulator_list .into_iter() .rev() .map(|d| { let score = best_match(t, d.name()).map_or(0, |m| m.score()); (d, score) }) .max_by_key(|(_, score)| *score) // we already checked the list is not empty .unwrap(); if score > MIN_DEVICE_MATCH_SCORE { device } else { crate::error::bail!("Could not find an iOS Simulator matching {t}") } } else if simulator_list.len() > 1 { let index = prompt::list( concat!("Detected ", "iOS", " simulators"), simulator_list.iter(), "simulator", None, "Simulator", ) .context("failed to prompt for simulator")?; simulator_list.into_iter().nth(index).unwrap() } else { simulator_list.into_iter().next().unwrap() }; Ok(device) } else { log::warn!("No available iOS Simulator detected"); let install_ios = crate::helpers::prompts::confirm( "Would you like to install the latest iOS runtime?", Some(false), ) .unwrap_or_default(); if install_ios { duct::cmd("xcodebuild", ["-downloadPlatform", "iOS"]) .stdout_file(os_pipe::dup_stdout().unwrap()) .stderr_file(os_pipe::dup_stderr().unwrap()) .run() .map_err(|e| Error::CommandFailed { command: "xcodebuild -downloadPlatform iOS".to_string(), error: e, })?; return simulator_prompt(env, target); } crate::error::bail!("No available iOS Simulator detected") } } fn device_prompt<'a>(env: &'_ Env, target: Option<&str>) -> Result> { if let Ok(device) = connected_device_prompt(env, target) { Ok(device) } else { let simulator = simulator_prompt(env, target)?; log::info!("Starting simulator {}", simulator.name()); simulator .start_detached(env) .context("failed to start simulator")?; Ok(simulator.into()) } } fn ensure_ios_runtime_installed() -> Result<()> { let installed_platforms_json = duct::cmd("xcrun", ["simctl", "list", "runtimes", "--json"]) .read() .map_err(|e| Error::CommandFailed { command: "xcrun simctl list runtimes --json".to_string(), error: e, })?; let installed_platforms: InstalledRuntimesList = serde_json::from_str(&installed_platforms_json).unwrap_or_default(); if !installed_platforms .runtimes .iter() .any(|r| r.name.starts_with("iOS")) { log::warn!("iOS platform not installed"); let install_ios = crate::helpers::prompts::confirm( "Would you like to install the latest iOS runtime?", Some(false), ) .unwrap_or_default(); if install_ios { duct::cmd("xcodebuild", ["-downloadPlatform", "iOS"]) .stdout_file(os_pipe::dup_stdout().unwrap()) .stderr_file(os_pipe::dup_stderr().unwrap()) .run() .map_err(|e| Error::CommandFailed { command: "xcodebuild -downloadPlatform iOS".to_string(), error: e, })?; } else { crate::error::bail!("iOS platform not installed"); } } Ok(()) } fn detect_target_ok<'a>(env: &Env) -> Option<&'a Target<'a>> { device_prompt(env, None).map(|device| device.target()).ok() } fn open_and_wait(config: &AppleConfig, env: &Env) -> ! { log::info!("Opening Xcode"); if let Err(e) = os::open_file_with("Xcode", config.project_dir(), env) { log::error!("{e}"); } loop { sleep(Duration::from_secs(24 * 60 * 60)); } } fn inject_resources(config: &AppleConfig, tauri_config: &TauriConfig) -> Result<()> { let asset_dir = config.project_dir().join(DEFAULT_ASSET_DIR); create_dir_all(&asset_dir).fs_context("failed to create asset directory", asset_dir.clone())?; let resources = match &tauri_config.bundle.resources { Some(BundleResources::List(paths)) => Some(ResourcePaths::new(paths.as_slice(), true)), Some(BundleResources::Map(map)) => Some(ResourcePaths::from_map(map, true)), None => None, }; if let Some(resources) = resources { for resource in resources.iter() { let resource = resource.context("failed to get resource")?; let dest = asset_dir.join(resource.target()); crate::helpers::fs::copy_file(resource.path(), dest)?; } } Ok(()) } pub fn signing_from_env() -> Result<( Option, Option, )> { let keychain = match ( var_os("IOS_CERTIFICATE"), var_os("IOS_CERTIFICATE_PASSWORD"), ) { (Some(certificate), Some(certificate_password)) => { log::info!("Reading iOS certificates from "); tauri_macos_sign::Keychain::with_certificate(&certificate, &certificate_password) .map(Some) .map_err(Box::new)? } (Some(_), None) => { log::warn!("The IOS_CERTIFICATE environment variable is set but not IOS_CERTIFICATE_PASSWORD. Ignoring the certificate..."); None } _ => None, }; let provisioning_profile = if let Some(provisioning_profile) = var_os("IOS_MOBILE_PROVISION") { tauri_macos_sign::ProvisioningProfile::from_base64(&provisioning_profile) .map(Some) .map_err(Box::new)? } else { if keychain.is_some() { log::warn!("You have provided an iOS certificate via environment variables but the IOS_MOBILE_PROVISION environment variable is not set. This will fail when signing unless the profile is set in your Xcode project."); } None }; Ok((keychain, provisioning_profile)) } pub struct ProjectConfig { pub code_sign_identity: Option, pub team_id: Option, pub provisioning_profile_uuid: Option, } pub fn project_config( keychain: Option<&tauri_macos_sign::Keychain>, provisioning_profile: Option<&tauri_macos_sign::ProvisioningProfile>, ) -> Result { Ok(ProjectConfig { code_sign_identity: keychain.map(|k| k.signing_identity()), team_id: keychain.and_then(|k| k.team_id().map(ToString::to_string)), provisioning_profile_uuid: provisioning_profile.and_then(|p| p.uuid().ok()), }) } pub fn load_pbxproj(config: &AppleConfig) -> Result { pbxproj::parse( config .project_dir() .join(format!("{}.xcodeproj", config.app().name())) .join("project.pbxproj"), ) } pub fn synchronize_project_config( config: &AppleConfig, tauri_config: &ConfigMetadata, pbxproj: &mut pbxproj::Pbxproj, export_options_plist: &mut plist::Dictionary, project_config: &ProjectConfig, debug: bool, ) -> Result<()> { let identifier = tauri_config.identifier.clone(); let product_name = tauri_config.product_name.clone(); let manual_signing = project_config.code_sign_identity.is_some() || project_config.provisioning_profile_uuid.is_some(); if let Some(xc_configuration_list) = pbxproj .xc_configuration_list .clone() .into_values() .find(|l| l.comment.contains("_iOS")) { for build_configuration_ref in xc_configuration_list.build_configurations { if manual_signing { pbxproj.set_build_settings(&build_configuration_ref.id, "CODE_SIGN_STYLE", "Manual"); } if let Some(team) = config.development_team() { let team = format!("\"{team}\""); pbxproj.set_build_settings(&build_configuration_ref.id, "DEVELOPMENT_TEAM", &team); } pbxproj.set_build_settings( &build_configuration_ref.id, "PRODUCT_BUNDLE_IDENTIFIER", &identifier, ); if let Some(product_name) = &product_name { pbxproj.set_build_settings( &build_configuration_ref.id, "PRODUCT_NAME", &format!("\"{product_name}\""), ); } if let Some(identity) = &project_config.code_sign_identity { let identity = format!("\"{identity}\""); pbxproj.set_build_settings(&build_configuration_ref.id, "CODE_SIGN_IDENTITY", &identity); pbxproj.set_build_settings( &build_configuration_ref.id, "\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\"", &identity, ); } if let Some(id) = &project_config.team_id { let id = format!("\"{id}\""); pbxproj.set_build_settings(&build_configuration_ref.id, "DEVELOPMENT_TEAM", &id); pbxproj.set_build_settings( &build_configuration_ref.id, "\"DEVELOPMENT_TEAM[sdk=iphoneos*]\"", &id, ); } if let Some(profile_uuid) = &project_config.provisioning_profile_uuid { let profile_uuid = format!("\"{profile_uuid}\""); pbxproj.set_build_settings( &build_configuration_ref.id, "PROVISIONING_PROFILE_SPECIFIER", &profile_uuid, ); pbxproj.set_build_settings( &build_configuration_ref.id, "\"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]\"", &profile_uuid, ); } } } let build_configuration = { if let Some(xc_configuration_list) = pbxproj .xc_configuration_list .clone() .into_values() .find(|l| l.comment.contains("_iOS")) { let mut configuration = None; let target = if debug { "debug" } else { "release" }; for build_configuration_ref in xc_configuration_list.build_configurations { if build_configuration_ref.comments.contains(target) { configuration = pbxproj .xc_build_configuration .get(&build_configuration_ref.id); break; } } configuration } else { None } }; if let Some(build_configuration) = build_configuration { if let Some(style) = build_configuration.get_build_setting("CODE_SIGN_STYLE") { export_options_plist.insert( "signingStyle".to_string(), style.value.to_lowercase().into(), ); } else { export_options_plist.insert("signingStyle".to_string(), "automatic".into()); } if manual_signing { if let Some(identity) = build_configuration .get_build_setting("\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\"") .or_else(|| build_configuration.get_build_setting("CODE_SIGN_IDENTITY")) { export_options_plist.insert( "signingCertificate".to_string(), identity.value.trim_matches('"').into(), ); } let profile_uuid = project_config .provisioning_profile_uuid .clone() .or_else(|| { build_configuration .get_build_setting("\"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]\"") .or_else(|| build_configuration.get_build_setting("PROVISIONING_PROFILE_SPECIFIER")) .map(|setting| setting.value.trim_matches('"').to_string()) }); if let Some(profile_uuid) = profile_uuid { let mut provisioning_profiles = plist::Dictionary::new(); provisioning_profiles.insert(config.app().identifier().to_string(), profile_uuid.into()); export_options_plist.insert( "provisioningProfiles".to_string(), provisioning_profiles.into(), ); } } if let Some(id) = build_configuration .get_build_setting("\"DEVELOPMENT_TEAM[sdk=iphoneos*]\"") .or_else(|| build_configuration.get_build_setting("DEVELOPMENT_TEAM")) { export_options_plist.insert("teamID".to_string(), id.value.trim_matches('"').into()); } } Ok(()) } ================================================ FILE: crates/tauri-cli/src/mobile/ios/project.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use crate::{ error::Context, helpers::{config::Config as TauriConfig, template}, mobile::ios::LIB_OUTPUT_FILE_NAME, Error, ErrorExt, Result, }; use cargo_mobile2::{ apple::{ config::{Config, Metadata}, deps, target::Target, }, config::app::DEFAULT_ASSET_DIR, target::TargetTrait as _, util::{self, cli::TextWrapper}, }; use handlebars::Handlebars; use include_dir::{include_dir, Dir}; use std::{ ffi::OsString, fs::{create_dir_all, OpenOptions}, path::{Component, PathBuf}, }; const TEMPLATE_DIR: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR/templates/mobile/ios"); // unprefixed app_root seems pretty dangerous!! // TODO: figure out what cargo-mobile meant by that #[allow(clippy::too_many_arguments)] pub fn gen( tauri_config: &TauriConfig, config: &Config, metadata: &Metadata, (handlebars, mut map): (Handlebars, template::JsonMap), wrapper: &TextWrapper, non_interactive: bool, reinstall_deps: bool, skip_targets_install: bool, ) -> Result<()> { if !skip_targets_install { let installed_targets = crate::interface::rust::installation::installed_targets().unwrap_or_default(); let missing_targets = Target::all() .values() .filter(|t| !installed_targets.contains(&t.triple().into())) .collect::>(); if !missing_targets.is_empty() { log::info!("Installing iOS Rust targets..."); for target in missing_targets { log::info!("Installing target {}", target.triple()); target.install().map_err(|error| Error::CommandFailed { command: "rustup target add".to_string(), error, })?; } } } deps::install_all(wrapper, non_interactive, true, reinstall_deps).map_err(|error| { Error::CommandFailed { command: "pod install".to_string(), error: std::io::Error::other(error), } })?; let dest = config.project_dir(); let rel_prefix = util::relativize_path(config.app().root_dir(), &dest); let source_dirs = vec![rel_prefix.join("src")]; let asset_catalogs = metadata.ios().asset_catalogs().unwrap_or_default(); let ios_pods = metadata.ios().pods().unwrap_or_default(); let macos_pods = metadata.macos().pods().unwrap_or_default(); #[cfg(target_arch = "aarch64")] let default_archs = ["arm64"]; #[cfg(not(target_arch = "aarch64"))] let default_archs = ["arm64", "x86_64"]; map.insert("lib-output-file-name", LIB_OUTPUT_FILE_NAME); map.insert("file-groups", &source_dirs); map.insert("ios-frameworks", metadata.ios().frameworks()); map.insert("ios-valid-archs", default_archs); map.insert("ios-vendor-frameworks", metadata.ios().vendor_frameworks()); map.insert("ios-vendor-sdks", metadata.ios().vendor_sdks()); map.insert("macos-frameworks", metadata.macos().frameworks()); map.insert( "macos-vendor-frameworks", metadata.macos().vendor_frameworks(), ); map.insert("macos-vendor-sdks", metadata.macos().vendor_frameworks()); map.insert("asset-catalogs", asset_catalogs); map.insert("ios-pods", ios_pods); map.insert("macos-pods", macos_pods); map.insert( "ios-additional-targets", metadata.ios().additional_targets(), ); map.insert( "macos-additional-targets", metadata.macos().additional_targets(), ); map.insert("ios-pre-build-scripts", metadata.ios().pre_build_scripts()); map.insert( "ios-post-compile-scripts", metadata.ios().post_compile_scripts(), ); map.insert( "ios-post-build-scripts", metadata.ios().post_build_scripts(), ); map.insert( "macos-pre-build-scripts", metadata.macos().pre_build_scripts(), ); map.insert( "macos-post-compile-scripts", metadata.macos().post_compile_scripts(), ); map.insert( "macos-post-build-scripts", metadata.macos().post_build_scripts(), ); map.insert( "ios-command-line-arguments", metadata.ios().command_line_arguments(), ); map.insert( "macos-command-line-arguments", metadata.macos().command_line_arguments(), ); let mut created_dirs = Vec::new(); template::render_with_generator( &handlebars, map.inner(), &TEMPLATE_DIR, &dest, &mut |path| { let mut components: Vec<_> = path.components().collect(); let mut new_component = None; for component in &mut components { if let Component::Normal(c) = component { let c = c.to_string_lossy(); if c.contains("{{app.name}}") { new_component.replace(OsString::from( &c.replace("{{app.name}}", config.app().name()), )); *component = Component::Normal(new_component.as_ref().unwrap()); break; } } } let path = dest.join(components.iter().collect::()); let parent = path.parent().unwrap().to_path_buf(); if !created_dirs.contains(&parent) { create_dir_all(&parent)?; created_dirs.push(parent); } let mut options = OpenOptions::new(); options.write(true); if !path.exists() { options.create(true).open(path).map(Some) } else { Ok(None) } }, ) .with_context(|| "failed to process template")?; if let Some(template_path) = tauri_config.bundle.ios.template.as_ref() { let template = std::fs::read_to_string(template_path).fs_context( "failed to read custom Xcode project template", template_path.to_path_buf(), )?; let mut output_file = std::fs::File::create(dest.join("project.yml")).fs_context( "failed to create project.yml file", dest.join("project.yml"), )?; handlebars .render_template_to_write(&template, map.inner(), &mut output_file) .expect("Failed to render template"); } let mut dirs_to_create = asset_catalogs.to_vec(); dirs_to_create.push(dest.join(DEFAULT_ASSET_DIR)); dirs_to_create.push(dest.join("Externals")); dirs_to_create.push(dest.join(format!("{}_iOS", config.app().name()))); // Create all required project directories if they don't already exist for dir in &dirs_to_create { std::fs::create_dir_all(dir).fs_context("failed to create directory", dir.to_path_buf())?; } // Note that Xcode doesn't always reload the project nicely; reopening is // often necessary. println!("Generating Xcode project..."); duct::cmd( "xcodegen", [ "generate", "--spec", &dest.join("project.yml").to_string_lossy(), ], ) .stdout_file(os_pipe::dup_stdout().unwrap()) .stderr_file(os_pipe::dup_stderr().unwrap()) .run() .map_err(|error| Error::CommandFailed { command: "xcodegen".to_string(), error, })?; if !ios_pods.is_empty() || !macos_pods.is_empty() { duct::cmd( "pod", [ "install", &format!("--project-directory={}", dest.display()), ], ) .stdout_file(os_pipe::dup_stdout().unwrap()) .stderr_file(os_pipe::dup_stderr().unwrap()) .run() .map_err(|error| Error::CommandFailed { command: "pod install".to_string(), error, })?; } Ok(()) } ================================================ FILE: crates/tauri-cli/src/mobile/ios/run.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use std::path::PathBuf; use cargo_mobile2::opts::{NoiseLevel, Profile}; use clap::{ArgAction, Parser}; use super::{device_prompt, env}; use crate::{ error::Context, helpers::config::{get_config as get_tauri_config, ConfigMetadata}, interface::{DevProcess, WatcherOptions}, mobile::{DevChild, TargetDevice}, ConfigValue, Result, }; #[derive(Debug, Clone, Parser)] #[clap( about = "Run your app in production mode on iOS", long_about = "Run your app in production mode on iOS. It makes use of the `build.frontendDist` property from your `tauri.conf.json` file. It also runs your `build.beforeBuildCommand` which usually builds your frontend into `build.frontendDist`." )] pub struct Options { /// Run the app in release mode #[clap(short, long)] pub release: bool, /// List of cargo features to activate #[clap(short, long, action = ArgAction::Append, num_args(0..), value_delimiter = ',')] pub features: Vec, /// JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file /// /// Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts. /// /// Note that a platform-specific file is looked up and merged with the default file by default /// (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json) /// but you can use this for more specific use cases such as different build flavors. #[clap(short, long)] pub config: Vec, /// Disable the file watcher #[clap(long)] pub no_watch: bool, /// Additional paths to watch for changes. #[clap(long)] pub additional_watch_folders: Vec, /// Open Xcode #[clap(short, long)] pub open: bool, /// Runs on the given device name pub device: Option, /// Command line arguments passed to the runner. /// Use `--` to explicitly mark the start of the arguments. /// e.g. `tauri android build -- [runnerArgs]`. #[clap(last(true))] pub args: Vec, /// Do not error out if a version mismatch is detected on a Tauri package. /// /// Only use this when you are sure the mismatch is incorrectly detected as version mismatched Tauri packages can lead to unknown behavior. #[clap(long)] pub ignore_version_mismatches: bool, } pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> { let env = env().context("failed to load iOS environment")?; let device = if options.open { None } else { match device_prompt(&env, options.device.as_deref()) { Ok(d) => Some(d), Err(e) => { log::error!("{e}"); None } } }; let dirs = crate::helpers::app_paths::resolve_dirs(); let mut built_application = super::build::run( super::build::Options { debug: !options.release, targets: Some(vec![]), /* skips IPA build since there's no target */ features: Vec::new(), config: options.config.clone(), build_number: None, open: options.open, ci: false, export_method: None, args: options.args, ignore_version_mismatches: options.ignore_version_mismatches, target_device: device.as_ref().map(|d| TargetDevice { id: d.id().to_string(), name: d.name().to_string(), }), }, noise_level, &dirs, )?; let mut tauri_config = get_tauri_config( tauri_utils::platform::Target::Ios, &options.config.iter().map(|c| &c.0).collect::>(), dirs.tauri, )?; // options.open is handled by the build command // so all we need to do here is run the app on the selected device if let Some(device) = device { let runner = move |_tauri_config: &ConfigMetadata| { device .run( &built_application.config, &env, noise_level, false, // do not quit on app exit if !options.release { Profile::Debug } else { Profile::Release }, ) .map(|c| Box::new(DevChild::new(c)) as Box) .context("failed to run iOS app") }; if options.no_watch { runner(&tauri_config)?; } else { built_application.interface.watch( &mut tauri_config, WatcherOptions { config: options.config, additional_watch_folders: options.additional_watch_folders, }, runner, &dirs, )?; } } Ok(()) } ================================================ FILE: crates/tauri-cli/src/mobile/ios/xcode_script.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use super::{ensure_init, env, get_app, get_config, read_options, MobileTarget}; use crate::{ error::{Context, ErrorExt}, helpers::config::{get_config as get_tauri_config, reload_config as reload_tauri_config}, interface::{AppInterface, Options as InterfaceOptions}, mobile::ios::LIB_OUTPUT_FILE_NAME, Error, Result, }; use cargo_mobile2::{apple::target::Target, opts::Profile, target::TargetTrait}; use clap::{ArgAction, Parser}; use object::{Object, ObjectSymbol}; use std::{ collections::HashMap, env::{current_dir, set_current_dir, var, var_os}, ffi::OsStr, fs::read_to_string, io::Read, path::{Path, PathBuf}, }; #[derive(Debug, Parser)] pub struct Options { /// Value of `PLATFORM_DISPLAY_NAME` env var #[clap(long)] platform: String, /// Value of `SDKROOT` env var #[clap(long)] sdk_root: PathBuf, /// Value of `FRAMEWORK_SEARCH_PATHS` env var #[clap(long, action = ArgAction::Append, num_args(0..))] framework_search_paths: Vec, /// Value of `GCC_PREPROCESSOR_DEFINITIONS` env var #[clap(long, action = ArgAction::Append, num_args(0..))] gcc_preprocessor_definitions: Vec, /// Value of `HEADER_SEARCH_PATHS` env var #[clap(long, action = ArgAction::Append, num_args(0..))] header_search_paths: Vec, /// Value of `CONFIGURATION` env var #[clap(long)] configuration: String, /// Value of `FORCE_COLOR` env var #[clap(long)] force_color: bool, /// Value of `ARCHS` env var #[clap(index = 1, required = true)] arches: Vec, } pub fn command(options: Options) -> Result<()> { fn macos_from_platform(platform: &str) -> bool { platform == "macOS" } fn profile_from_configuration(configuration: &str) -> Profile { if configuration == "release" { Profile::Release } else { Profile::Debug } } let process_path = std::env::current_exe().unwrap_or_default(); // `xcode-script` is ran from the `gen/apple` folder when not using NPM/yarn/pnpm/deno. // so we must change working directory to the src-tauri folder to resolve the tauri dir // additionally, bun@<1.2 does not modify the current working directory, so it is also runs this script from `gen/apple` // bun@>1.2 now actually moves the CWD to the package root so we shouldn't modify CWD in that case // see https://bun.sh/blog/bun-v1.2#bun-run-uses-the-correct-directory if (var_os("npm_lifecycle_event").is_none() && var_os("PNPM_PACKAGE_NAME").is_none() && process_path.file_stem().unwrap_or_default() != "deno") || var("npm_config_user_agent") .is_ok_and(|agent| agent.starts_with("bun/1.0") || agent.starts_with("bun/1.1")) { set_current_dir( current_dir() .context("failed to resolve current directory")? .parent() .unwrap() .parent() .unwrap(), ) .unwrap(); } let dirs = crate::helpers::app_paths::resolve_dirs(); let profile = profile_from_configuration(&options.configuration); let macos = macos_from_platform(&options.platform); let mut tauri_config = get_tauri_config(tauri_utils::platform::Target::Ios, &[], dirs.tauri)?; let cli_options = read_options(&tauri_config); if !cli_options.config.is_empty() { // reload config with merges from the ios dev|build script reload_tauri_config( &mut tauri_config, &cli_options .config .iter() .map(|conf| &conf.0) .collect::>(), dirs.tauri, )? }; let (config, metadata) = get_config( &get_app( MobileTarget::Ios, &tauri_config, &AppInterface::new(&tauri_config, None, dirs.tauri)?, dirs.tauri, ), &tauri_config, &[], &cli_options, dirs.tauri, )?; ensure_init( &tauri_config, config.app(), config.project_dir(), MobileTarget::Ios, std::env::var("CI").is_ok(), )?; if !cli_options.config.is_empty() { crate::helpers::config::merge_config_with( &mut tauri_config, &cli_options .config .iter() .map(|conf| &conf.0) .collect::>(), )?; } let env = env() .context("failed to load iOS environment")? .explicit_env_vars(cli_options.vars); if !options.sdk_root.is_dir() { crate::error::bail!( "SDK root provided by Xcode was invalid. {} doesn't exist or isn't a directory", options.sdk_root.display(), ); } let include_dir = options.sdk_root.join("usr/include"); if !include_dir.is_dir() { crate::error::bail!( "Include dir was invalid. {} doesn't exist or isn't a directory", include_dir.display() ); } // Host flags that are used by build scripts let macos_isysroot = { let macos_sdk_root = options .sdk_root .join("../../../../MacOSX.platform/Developer/SDKs/MacOSX.sdk"); if !macos_sdk_root.is_dir() { crate::error::bail!("Invalid SDK root {}", macos_sdk_root.display()); } format!("-isysroot {}", macos_sdk_root.display()) }; let mut host_env = HashMap::<&str, &OsStr>::new(); host_env.insert("RUST_BACKTRACE", "1".as_ref()); host_env.insert("CFLAGS_x86_64_apple_darwin", macos_isysroot.as_ref()); host_env.insert("CXXFLAGS_x86_64_apple_darwin", macos_isysroot.as_ref()); host_env.insert( "OBJC_INCLUDE_PATH_x86_64_apple_darwin", include_dir.as_os_str(), ); let framework_search_paths = options.framework_search_paths.join(" "); host_env.insert("FRAMEWORK_SEARCH_PATHS", framework_search_paths.as_ref()); let gcc_preprocessor_definitions = options.gcc_preprocessor_definitions.join(" "); host_env.insert( "GCC_PREPROCESSOR_DEFINITIONS", gcc_preprocessor_definitions.as_ref(), ); let header_search_paths = options.header_search_paths.join(" "); host_env.insert("HEADER_SEARCH_PATHS", header_search_paths.as_ref()); let macos_target = Target::macos(); let isysroot = format!("-isysroot {}", options.sdk_root.display()); let simulator = options.platform == "iOS Simulator" || options.arches.contains(&"Simulator".to_string()); let arches = if simulator { // when compiling for the simulator, we don't need to build other targets vec![if cfg!(target_arch = "aarch64") { "arm64" } else { "x86_64" } .to_string()] } else { options.arches }; let installed_targets = crate::interface::rust::installation::installed_targets().unwrap_or_default(); for arch in arches { // Set target-specific flags let (env_triple, rust_triple) = match arch.as_str() { "arm64" if !simulator => ("aarch64_apple_ios", "aarch64-apple-ios"), "arm64" if simulator => ("aarch64_apple_ios_sim", "aarch64-apple-ios-sim"), "x86_64" => ("x86_64_apple_ios", "x86_64-apple-ios"), _ => { crate::error::bail!("Arch specified by Xcode was invalid. {arch} isn't a known arch") } }; let interface = AppInterface::new(&tauri_config, Some(rust_triple.into()), dirs.tauri)?; let cflags = format!("CFLAGS_{env_triple}"); let cxxflags = format!("CFLAGS_{env_triple}"); let objc_include_path = format!("OBJC_INCLUDE_PATH_{env_triple}"); let mut target_env = host_env.clone(); target_env.insert(cflags.as_ref(), isysroot.as_ref()); target_env.insert(cxxflags.as_ref(), isysroot.as_ref()); target_env.insert(objc_include_path.as_ref(), include_dir.as_ref()); let target = if macos { &macos_target } else { Target::for_arch(if arch == "arm64" && simulator { "arm64-sim" } else { &arch }) .with_context(|| format!("Arch specified by Xcode was invalid. {arch} isn't a known arch"))? }; if !installed_targets.contains(&rust_triple.into()) { log::info!("Installing target {}", target.triple()); target.install().map_err(|error| Error::CommandFailed { command: "rustup target add".to_string(), error, })?; } target .compile_lib( &config, &metadata, cli_options.noise_level, true, profile, &env, target_env, ) .context("failed to compile iOS app")?; let out_dir = interface.app_settings().out_dir( &InterfaceOptions { debug: matches!(profile, Profile::Debug), target: Some(rust_triple.into()), ..Default::default() }, dirs.tauri, )?; let lib_path = out_dir.join(format!("lib{}.a", config.app().lib_name())); if !lib_path.exists() { crate::error::bail!("Library not found at {}. Make sure your Cargo.toml file has a [lib] block with `crate-type = [\"staticlib\", \"cdylib\", \"lib\"]`", lib_path.display()); } validate_lib(&lib_path)?; let project_dir = config.project_dir(); let externals_lib_dir = project_dir.join(format!("Externals/{arch}/{}", profile.as_str())); std::fs::create_dir_all(&externals_lib_dir).fs_context( "failed to create externals lib directory", externals_lib_dir.clone(), )?; // backwards compatible lib output file name let uses_new_lib_output_file_name = { let pbxproj_path = project_dir .join(format!("{}.xcodeproj", config.app().name())) .join("project.pbxproj"); let pbxproj_contents = read_to_string(&pbxproj_path) .fs_context("failed to read project.pbxproj file", pbxproj_path)?; pbxproj_contents.contains(LIB_OUTPUT_FILE_NAME) }; let lib_output_file_name = if uses_new_lib_output_file_name { LIB_OUTPUT_FILE_NAME.to_string() } else { format!("lib{}.a", config.app().lib_name()) }; std::fs::copy(&lib_path, externals_lib_dir.join(lib_output_file_name)).fs_context( "failed to copy mobile lib file to Externals directory", lib_path.to_path_buf(), )?; } Ok(()) } fn validate_lib(path: &Path) -> Result<()> { let mut archive = ar::Archive::new( std::fs::File::open(path).fs_context("failed to open mobile lib file", path.to_path_buf())?, ); // Iterate over all entries in the archive: while let Some(entry) = archive.next_entry() { let Ok(mut entry) = entry else { continue; }; let mut obj_bytes = Vec::new(); entry .read_to_end(&mut obj_bytes) .fs_context("failed to read mobile lib entry", path.to_path_buf())?; let file = object::File::parse(&*obj_bytes) .map_err(std::io::Error::other) .fs_context("failed to parse mobile lib entry", path.to_path_buf())?; for symbol in file.symbols() { let Ok(name) = symbol.name() else { continue; }; if name.contains("start_app") { return Ok(()); } } } crate::error::bail!( "Library from {} does not include required runtime symbols. This means you are likely missing the tauri::mobile_entry_point macro usage, see the documentation for more information: https://v2.tauri.app/start/migrate/from-tauri-1", path.display() ) } ================================================ FILE: crates/tauri-cli/src/mobile/mod.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use crate::{ error::{Context, ErrorExt}, helpers::config::{reload_config, Config as TauriConfig, ConfigMetadata}, interface::{AppInterface, AppSettings, DevProcess, Options as InterfaceOptions}, ConfigValue, Error, Result, }; use heck::ToSnekCase; use jsonrpsee::core::client::{Client, ClientBuilder, ClientT}; use jsonrpsee::server::{RpcModule, ServerBuilder, ServerHandle}; use jsonrpsee_client_transport::ws::WsTransportClientBuilder; use jsonrpsee_core::rpc_params; use serde::{Deserialize, Serialize}; use cargo_mobile2::{ config::app::{App, Raw as RawAppConfig}, env::Error as EnvError, opts::{NoiseLevel, Profile}, ChildHandle, }; use std::{ collections::HashMap, env::{set_var, temp_dir}, ffi::OsString, fmt::{Display, Write}, fs::{read_to_string, write}, net::{AddrParseError, IpAddr, Ipv4Addr, SocketAddr}, path::{Path, PathBuf}, process::{exit, ExitStatus}, str::FromStr, sync::{ atomic::{AtomicBool, Ordering}, Arc, OnceLock, }, }; use tokio::runtime::Runtime; #[cfg(not(windows))] use cargo_mobile2::env::Env; #[cfg(windows)] use cargo_mobile2::os::Env; pub mod android; mod init; #[cfg(target_os = "macos")] pub mod ios; const MIN_DEVICE_MATCH_SCORE: isize = 0; #[derive(Clone)] pub struct DevChild { child: Arc, manually_killed_process: Arc, } impl DevChild { fn new(handle: ChildHandle) -> Self { Self { child: Arc::new(handle), manually_killed_process: Default::default(), } } } impl DevProcess for DevChild { fn kill(&self) -> std::io::Result<()> { self.child.kill()?; self.manually_killed_process.store(true, Ordering::SeqCst); Ok(()) } fn wait(&self) -> std::io::Result { self.child.wait().map(|o| o.status) } fn manually_killed_process(&self) -> bool { self.manually_killed_process.load(Ordering::SeqCst) } } #[derive(PartialEq, Eq, Copy, Clone)] pub enum Target { Android, #[cfg(target_os = "macos")] Ios, } impl Target { fn ide_name(&self) -> &'static str { match self { Self::Android => "Android Studio", #[cfg(target_os = "macos")] Self::Ios => "Xcode", } } fn command_name(&self) -> &'static str { match self { Self::Android => "android", #[cfg(target_os = "macos")] Self::Ios => "ios", } } fn ide_build_script_name(&self) -> &'static str { match self { Self::Android => "android-studio-script", #[cfg(target_os = "macos")] Self::Ios => "xcode-script", } } fn platform_target(&self) -> tauri_utils::platform::Target { match self { Self::Android => tauri_utils::platform::Target::Android, #[cfg(target_os = "macos")] Self::Ios => tauri_utils::platform::Target::Ios, } } } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TargetDevice { id: String, name: String, } #[derive(Debug, Clone)] pub struct DevHost(Option>); impl FromStr for DevHost { type Err = AddrParseError; fn from_str(s: &str) -> std::result::Result { if s.is_empty() || s == "" { Ok(Self(Some(None))) } else if s == "" { Ok(Self(None)) } else { IpAddr::from_str(s).map(|addr| Self(Some(Some(addr)))) } } } impl Display for DevHost { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self.0 { Some(None) => write!(f, ""), Some(Some(addr)) => write!(f, "{addr}"), None => write!(f, ""), } } } impl Default for DevHost { fn default() -> Self { // on Windows we want to force using the public network address for the development server // because the adb port forwarding does not work well if cfg!(windows) { Self(Some(None)) } else { Self(None) } } } #[derive(Debug, Default, Clone, Serialize, Deserialize)] pub struct CliOptions { pub dev: bool, pub features: Vec, pub args: Vec, pub noise_level: NoiseLevel, pub vars: HashMap, pub config: Vec, pub target_device: Option, } fn local_ip_address(force: bool) -> &'static IpAddr { static LOCAL_IP: OnceLock = OnceLock::new(); LOCAL_IP.get_or_init(|| { let prompt_for_ip = || { let addresses: Vec = local_ip_address::list_afinet_netifas() .expect("failed to list networks") .into_iter() .map(|(_, ipaddr)| ipaddr) .filter(|ipaddr| match ipaddr { IpAddr::V4(i) => i != &Ipv4Addr::LOCALHOST, IpAddr::V6(i) => i.to_string().ends_with("::2"), }) .collect(); match addresses.as_slice() { [] => panic!("No external IP detected."), [ipaddr] => *ipaddr, _ => { let selected = dialoguer::Select::with_theme(&dialoguer::theme::ColorfulTheme::default()) .with_prompt( "Failed to detect external IP, What IP should we use to access your development server?", ) .items(&addresses) .default(0) .interact() .expect("failed to select external IP"); *addresses.get(selected).unwrap() } } }; let ip = if force { prompt_for_ip() } else { local_ip_address::local_ip().unwrap_or_else(|_| prompt_for_ip()) }; log::info!("Using {ip} to access the development server."); ip }) } struct DevUrlConfig { no_dev_server_wait: bool, } fn use_network_address_for_dev_url( config: &mut ConfigMetadata, dev_options: &mut crate::dev::Options, force_ip_prompt: bool, tauri_dir: &Path, ) -> crate::Result { let mut dev_url = config.build.dev_url.clone(); let ip = if let Some(url) = &mut dev_url { let localhost = match url.host() { Some(url::Host::Domain(d)) => d == "localhost", Some(url::Host::Ipv4(i)) => i == Ipv4Addr::LOCALHOST || i == Ipv4Addr::UNSPECIFIED, _ => false, }; if localhost { let ip = dev_options .host .unwrap_or_else(|| *local_ip_address(force_ip_prompt)); log::info!( "Replacing devUrl host with {ip}. {}.", "If your frontend is not listening on that address, try configuring your development server to use the `TAURI_DEV_HOST` environment variable or 0.0.0.0 as host" ); let url_str = format!( "{}://{}{}", url.scheme(), SocketAddr::new(ip, url.port_or_known_default().unwrap()), url.path() ); *url = url::Url::parse(&url_str).with_context(|| format!("failed to parse URL: {url_str}"))?; dev_options .config .push(crate::ConfigValue(serde_json::json!({ "build": { "devUrl": url } }))); reload_config( config, &dev_options .config .iter() .map(|conf| &conf.0) .collect::>(), tauri_dir, )?; Some(ip) } else { None } } else if !dev_options.no_dev_server { let ip = dev_options .host .unwrap_or_else(|| *local_ip_address(force_ip_prompt)); dev_options.host.replace(ip); Some(ip) } else { None }; let mut dev_url_config = DevUrlConfig { no_dev_server_wait: false, }; if let Some(ip) = ip { std::env::set_var("TAURI_DEV_HOST", ip.to_string()); std::env::set_var("TRUNK_SERVE_ADDRESS", ip.to_string()); if ip.is_ipv6() { // in this case we can't ping the server for some reason dev_url_config.no_dev_server_wait = true; } } Ok(dev_url_config) } fn env_vars() -> HashMap { let mut vars = HashMap::new(); vars.insert("RUST_LOG_STYLE".into(), "always".into()); for (k, v) in std::env::vars_os() { let k = k.to_string_lossy(); if (k.starts_with("TAURI") && k != "TAURI_SIGNING_PRIVATE_KEY" && k != "TAURI_SIGNING_PRIVATE_KEY_PASSWORD") || k.starts_with("WRY") || k.starts_with("CARGO_") || k.starts_with("RUST_") || k == "TMPDIR" || k == "PATH" { vars.insert(k.into_owned(), v); } } vars } fn env() -> std::result::Result { let env = Env::new()?.explicit_env_vars(env_vars()); Ok(env) } pub struct OptionsHandle(#[allow(unused)] Runtime, #[allow(unused)] ServerHandle); /// Writes CLI options to be used later on the Xcode and Android Studio build commands pub fn write_options( config: &ConfigMetadata, mut options: CliOptions, ) -> crate::Result { options.vars.extend(env_vars()); let runtime = Runtime::new().unwrap(); let r: crate::Result<(ServerHandle, SocketAddr)> = runtime.block_on(async move { let server = ServerBuilder::default() .build("127.0.0.1:0") .await .context("failed to build WebSocket server")?; let addr = server.local_addr().context("failed to get local address")?; let mut module = RpcModule::new(()); module .register_method("options", move |_, _, _| Some(options.clone())) .context("failed to register options method")?; let handle = server.start(module); Ok((handle, addr)) }); let (handle, addr) = r?; let server_addr_path = temp_dir().join(format!( "{}-server-addr", config .original_identifier() .context("app configuration is missing an identifier")? )); write(&server_addr_path, addr.to_string()) .fs_context("failed to write server address file", server_addr_path)?; Ok(OptionsHandle(runtime, handle)) } fn read_options(config: &ConfigMetadata) -> CliOptions { let runtime = tokio::runtime::Runtime::new().unwrap(); let options = runtime .block_on(async move { let addr_path = temp_dir().join(format!( "{}-server-addr", config .original_identifier() .context("app configuration is missing an identifier")? )); let (tx, rx) = WsTransportClientBuilder::default() .build( format!( "ws://{}", read_to_string(&addr_path).unwrap_or_else(|e| panic!( "failed to read missing addr file {}: {e}", addr_path.display() )) ) .parse() .unwrap(), ) .await .context("failed to build WebSocket client")?; let client: Client = ClientBuilder::default().build_with_tokio(tx, rx); let options: CliOptions = client .request("options", rpc_params![]) .await .context("failed to request options")?; Ok::(options) }) .expect("failed to read CLI options"); for (k, v) in &options.vars { set_var(k, v); } options } pub fn get_app( target: Target, config: &TauriConfig, interface: &AppInterface, tauri_dir: &Path, ) -> App { let identifier = match target { Target::Android => config.identifier.replace('-', "_"), #[cfg(target_os = "macos")] Target::Ios => config.identifier.replace('_', "-"), }; if identifier.is_empty() { log::error!("Bundle identifier set in `tauri.conf.json > identifier` cannot be empty"); exit(1); } let app_name = interface .app_settings() .app_name() .unwrap_or_else(|| "app".into()); let lib_name = interface .app_settings() .lib_name() .unwrap_or_else(|| app_name.to_snek_case()); if config.product_name.is_none() { log::warn!( "`productName` is not set in the Tauri configuration. Using `{app_name}` as the app name." ); } let raw = RawAppConfig { name: app_name, lib_name: Some(lib_name), stylized_name: config.product_name.clone(), identifier, asset_dir: None, template_pack: None, }; let app_settings = interface.app_settings(); let tauri_dir = tauri_dir.to_path_buf(); App::from_raw(tauri_dir.to_path_buf(), raw) .unwrap() .with_target_dir_resolver(move |target, profile| { app_settings .out_dir( &InterfaceOptions { debug: matches!(profile, Profile::Debug), target: Some(target.into()), ..Default::default() }, &tauri_dir, ) .expect("failed to resolve target directory") }) } #[allow(unused_variables)] fn ensure_init( tauri_config: &ConfigMetadata, app: &App, project_dir: PathBuf, target: Target, noninteractive: bool, ) -> Result<()> { if !project_dir.exists() { crate::error::bail!( "{} project directory {} doesn't exist. Please run `tauri {} init` and try again.", target.ide_name(), project_dir.display(), target.command_name(), ) } let mut project_outdated_reasons = Vec::new(); match target { Target::Android => { let java_folder = project_dir .join("app/src/main/java") .join(tauri_config.identifier.replace('.', "/").replace('-', "_")); if java_folder.exists() { #[cfg(unix)] ensure_gradlew(&project_dir)?; } else { project_outdated_reasons .push("you have modified your \"identifier\" in the Tauri configuration"); } } #[cfg(target_os = "macos")] Target::Ios => { let xcodeproj_path = crate::helpers::fs::find_in_directory(&project_dir, "*.xcodeproj") .with_context(|| format!("failed to locate xcodeproj in {}", project_dir.display()))?; let xcodeproj_name = xcodeproj_path.file_stem().unwrap().to_str().unwrap(); if xcodeproj_name != app.name() { let rename_targets = vec![ // first rename the entitlements ( format!("{xcodeproj_name}_iOS/{xcodeproj_name}_iOS.entitlements"), format!("{xcodeproj_name}_iOS/{}_iOS.entitlements", app.name()), ), // then the scheme folder ( format!("{xcodeproj_name}_iOS"), format!("{}_iOS", app.name()), ), ( format!("{xcodeproj_name}.xcodeproj"), format!("{}.xcodeproj", app.name()), ), ]; let rename_info = rename_targets .iter() .map(|(from, to)| format!("- {from} to {to}")) .collect::>() .join("\n"); log::error!( "you have modified your package name from {current_project_name} to {new_project_name}\nWe need to apply the name change to the Xcode project, renaming:\n{rename_info}", new_project_name = app.name(), current_project_name = xcodeproj_name, ); if noninteractive { project_outdated_reasons .push("you have modified your [lib.name] or [package.name] in the Cargo.toml file"); } else { let confirm = crate::helpers::prompts::confirm( "Do you want to apply the name change to the Xcode project?", Some(true), ) .unwrap_or_default(); if confirm { for (from, to) in rename_targets { std::fs::rename(project_dir.join(&from), project_dir.join(&to)) .with_context(|| format!("failed to rename {from} to {to}"))?; } // update scheme name in pbxproj // identifier / product name are synchronized by the dev/build commands let pbxproj_path = project_dir.join(format!("{}.xcodeproj/project.pbxproj", app.name())); let pbxproj_contents = std::fs::read_to_string(&pbxproj_path) .with_context(|| format!("failed to read {}", pbxproj_path.display()))?; std::fs::write( &pbxproj_path, pbxproj_contents.replace( &format!("{xcodeproj_name}_iOS"), &format!("{}_iOS", app.name()), ), ) .with_context(|| format!("failed to write {}", pbxproj_path.display()))?; } else { project_outdated_reasons .push("you have modified your [lib.name] or [package.name] in the Cargo.toml file"); } } } // note: pbxproj is synchronied by the dev/build commands } } if !project_outdated_reasons.is_empty() { let reason = project_outdated_reasons.join(" and "); crate::error::bail!( "{} project directory is outdated because {reason}. Please delete {}, run `tauri {} init` and try again.", target.ide_name(), project_dir.display(), target.command_name(), ) } Ok(()) } #[cfg(unix)] fn ensure_gradlew(project_dir: &std::path::Path) -> Result<()> { use std::os::unix::fs::PermissionsExt; let gradlew_path = project_dir.join("gradlew"); if let Ok(metadata) = gradlew_path.metadata() { let mut permissions = metadata.permissions(); let is_executable = permissions.mode() & 0o111 != 0; if !is_executable { permissions.set_mode(permissions.mode() | 0o111); std::fs::set_permissions(&gradlew_path, permissions) .fs_context("failed to mark gradlew as executable", gradlew_path.clone())?; } std::fs::write( &gradlew_path, std::fs::read_to_string(&gradlew_path) .fs_context("failed to read gradlew", gradlew_path.clone())? .replace("\r\n", "\n"), ) .fs_context("failed to replace gradlew CRLF with LF", gradlew_path)?; } Ok(()) } fn log_finished(outputs: Vec, kind: &str) { if !outputs.is_empty() { let mut printable_paths = String::new(); for path in &outputs { writeln!(printable_paths, " {}", path.display()).unwrap(); } log::info!(action = "Finished"; "{} {}{} at:\n{}", outputs.len(), kind, if outputs.len() == 1 { "" } else { "s" }, printable_paths); } } ================================================ FILE: crates/tauri-cli/src/plugin/android.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use crate::{ error::Context, helpers::{prompts, template}, Result, }; use clap::{Parser, Subcommand}; use handlebars::Handlebars; use std::{ collections::BTreeMap, env::current_dir, ffi::OsStr, path::{Component, PathBuf}, }; #[derive(Parser)] #[clap( author, version, about = "Manage the Android project for a Tauri plugin", subcommand_required(true), arg_required_else_help(true) )] pub struct Cli { #[clap(subcommand)] command: Commands, } #[derive(Subcommand)] enum Commands { Init(InitOptions), } #[derive(Debug, Parser)] #[clap(about = "Initializes the Android project for an existing Tauri plugin")] pub struct InitOptions { /// Name of your Tauri plugin. Must match the current plugin's name. /// If not specified, it will be inferred from the current directory. plugin_name: Option, /// The output directory. #[clap(short, long)] #[clap(default_value_t = current_dir().expect("failed to read cwd").to_string_lossy().into_owned())] out_dir: String, } pub fn command(cli: Cli) -> Result<()> { match cli.command { Commands::Init(options) => { let plugin_name = match options.plugin_name { None => super::infer_plugin_name( std::env::current_dir().context("failed to get current directory")?, )?, Some(name) => name, }; let out_dir = PathBuf::from(options.out_dir); if out_dir.join("android").exists() { crate::error::bail!("Android folder already exists"); } let plugin_id = prompts::input( "What should be the Android Package ID for your plugin?", Some(format!("com.plugin.{plugin_name}")), false, false, )? .unwrap(); let handlebars = Handlebars::new(); let mut data = BTreeMap::new(); super::init::plugin_name_data(&mut data, &plugin_name); data.insert("android_package_id", handlebars::to_json(&plugin_id)); let mut created_dirs = Vec::new(); template::render_with_generator( &handlebars, &data, &super::init::TEMPLATE_DIR, &out_dir, &mut |path| { let mut components = path.components(); let root = components.next().unwrap(); if let Component::Normal(component) = root { if component == OsStr::new("android") { return super::init::generate_android_out_file( &path, &out_dir, &plugin_id.replace('.', "/"), &mut created_dirs, ); } } Ok(None) }, )?; let metadata = super::init::crates_metadata()?; let cargo_toml_addition = format!( r#" [build-dependencies] tauri-build = "{}" "#, metadata.tauri_build ); let build_file = super::init::TEMPLATE_DIR .get_file("build.rs") .unwrap() .contents_utf8() .unwrap(); let init_fn = format!( r#" pub fn init() -> TauriPlugin {{ Builder::new("{plugin_name}") .setup(|app, api| {{ #[cfg(target_os = "android")] let handle = api.register_android_plugin("{plugin_id}", "ExamplePlugin")?; Ok(()) }}) .build() }} "# ); log::info!("Android project added"); println!("You must add the following to the Cargo.toml file:\n{cargo_toml_addition}",); println!("You must add the following code to the build.rs file:\n\n{build_file}",); println!("Your plugin's init function under src/lib.rs must initialize the Android plugin:\n{init_fn}"); } } Ok(()) } ================================================ FILE: crates/tauri-cli/src/plugin/init.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use super::PluginIosFramework; use crate::Result; use crate::{ error::{Context, ErrorExt}, helpers::{prompts, resolve_tauri_path, template}, VersionMetadata, }; use clap::Parser; use handlebars::{to_json, Handlebars}; use heck::{ToKebabCase, ToPascalCase, ToSnakeCase}; use include_dir::{include_dir, Dir}; use std::ffi::{OsStr, OsString}; use std::{ collections::BTreeMap, env::current_dir, fs::{create_dir_all, remove_dir_all, File, OpenOptions}, path::{Component, Path, PathBuf}, }; pub const TEMPLATE_DIR: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR/templates/plugin"); #[derive(Debug, Parser)] #[clap(about = "Initialize a Tauri plugin project on an existing directory")] pub struct Options { /// Name of your Tauri plugin. /// If not specified, it will be inferred from the current directory. pub(crate) plugin_name: Option, /// Initializes a Tauri plugin without the TypeScript API #[clap(long)] pub(crate) no_api: bool, /// Initialize without an example project. #[clap(long)] pub(crate) no_example: bool, /// Set target directory for init #[clap(short, long)] #[clap(default_value_t = current_dir().expect("failed to read cwd").display().to_string())] pub(crate) directory: String, /// Author name #[clap(short, long)] pub(crate) author: Option, /// Whether to initialize an Android project for the plugin. #[clap(long)] pub(crate) android: bool, /// Whether to initialize an iOS project for the plugin. #[clap(long)] pub(crate) ios: bool, /// Whether to initialize Android and iOS projects for the plugin. #[clap(long)] pub(crate) mobile: bool, /// Type of framework to use for the iOS project. #[clap(long)] #[clap(default_value_t = PluginIosFramework::default())] pub(crate) ios_framework: PluginIosFramework, /// Generate github workflows #[clap(long)] pub(crate) github_workflows: bool, /// Initializes a Tauri core plugin (internal usage) #[clap(long, hide(true))] pub(crate) tauri: bool, /// Path of the Tauri project to use (relative to the cwd) #[clap(short, long)] pub(crate) tauri_path: Option, } impl Options { fn load(&mut self) { if self.author.is_none() { self.author.replace(if self.tauri { "Tauri Programme within The Commons Conservancy".into() } else { "You".into() }); } } } pub fn command(mut options: Options) -> Result<()> { options.load(); let plugin_name = match options.plugin_name { None => super::infer_plugin_name(&options.directory)?, Some(name) => name, }; let template_target_path = PathBuf::from(options.directory); let metadata = crates_metadata()?; if std::fs::read_dir(&template_target_path) .fs_context( "failed to read target directory", template_target_path.clone(), )? .count() > 0 { log::warn!("Plugin dir ({:?}) not empty.", template_target_path); } else { let (tauri_dep, tauri_example_dep, tauri_build_dep, tauri_plugin_dep) = if let Some(tauri_path) = options.tauri_path { ( format!( r#"{{ path = {:?} }}"#, resolve_tauri_path(&tauri_path, "crates/tauri") ), format!( r#"{{ path = {:?} }}"#, resolve_tauri_path(&tauri_path, "crates/tauri") ), format!( "{{ path = {:?}, default-features = false }}", resolve_tauri_path(&tauri_path, "crates/tauri-build") ), format!( r#"{{ path = {:?}, features = ["build"] }}"#, resolve_tauri_path(&tauri_path, "crates/tauri-plugin") ), ) } else { ( format!(r#"{{ version = "{}" }}"#, metadata.tauri), format!(r#"{{ version = "{}" }}"#, metadata.tauri), format!( r#"{{ version = "{}", default-features = false }}"#, metadata.tauri_build ), format!( r#"{{ version = "{}", features = ["build"] }}"#, metadata.tauri_plugin ), ) }; let _ = remove_dir_all(&template_target_path); let mut handlebars = Handlebars::new(); handlebars.register_escape_fn(handlebars::no_escape); let mut data = BTreeMap::new(); plugin_name_data(&mut data, &plugin_name); data.insert("tauri_dep", to_json(tauri_dep)); data.insert("tauri_example_dep", to_json(tauri_example_dep)); data.insert("tauri_build_dep", to_json(tauri_build_dep)); data.insert("tauri_plugin_dep", to_json(tauri_plugin_dep)); data.insert("author", to_json(options.author)); if options.tauri { data.insert( "license_header", to_json( "// Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT\n\n" .replace(" ", "") .replace(" //", "//"), ), ); } let plugin_id = if options.android || options.mobile { let plugin_id = prompts::input( "What should be the Android Package ID for your plugin?", Some(format!("com.plugin.{plugin_name}")), false, false, )? .unwrap(); data.insert("android_package_id", to_json(&plugin_id)); Some(plugin_id) } else { None }; let ios_framework = options.ios_framework; let mut created_dirs = Vec::new(); template::render_with_generator( &handlebars, &data, &TEMPLATE_DIR, &template_target_path, &mut |mut path| { let mut components = path.components(); let root = components.next().unwrap(); if let Component::Normal(component) = root { match component.to_str().unwrap() { "__example-api" => { if options.no_api || options.no_example { return Ok(None); } else { path = Path::new("examples").join(components.collect::()); } } "__example-basic" => { if options.no_api && !options.no_example { path = Path::new("examples").join(components.collect::()); } else { return Ok(None); } } ".github" if !options.github_workflows => return Ok(None), "android" => { if options.android || options.mobile { return generate_android_out_file( &path, &template_target_path, &plugin_id.as_ref().unwrap().replace('.', "/"), &mut created_dirs, ); } else { return Ok(None); } } "ios-spm" | "ios-xcode" if !(options.ios || options.mobile) => return Ok(None), "ios-spm" if !matches!(ios_framework, PluginIosFramework::Spm) => return Ok(None), "ios-xcode" if !matches!(ios_framework, PluginIosFramework::Xcode) => return Ok(None), "ios-spm" | "ios-xcode" => { let folder_name = components.next().unwrap().as_os_str().to_string_lossy(); let new_folder_name = folder_name.replace("{{ plugin_name }}", &plugin_name); let new_folder_name = OsString::from(&new_folder_name); path = [ Component::Normal(OsStr::new("ios")), Component::Normal(&new_folder_name), ] .into_iter() .chain(components) .collect::(); } "guest-js" | "rollup.config.js" | "tsconfig.json" | "package.json" if options.no_api => { return Ok(None); } _ => (), } } let path = template_target_path.join(path); let parent = path.parent().unwrap().to_path_buf(); if !created_dirs.contains(&parent) { create_dir_all(&parent)?; created_dirs.push(parent); } File::create(path).map(Some) }, ) .with_context(|| "failed to render plugin template")?; } let permissions_dir = template_target_path.join("permissions"); std::fs::create_dir(&permissions_dir).fs_context( "failed to create `permissions` directory", permissions_dir.clone(), )?; let default_permissions = r#"[default] description = "Default permissions for the plugin" permissions = ["allow-ping"] "#; std::fs::write(permissions_dir.join("default.toml"), default_permissions).fs_context( "failed to write default permissions file", permissions_dir.join("default.toml"), )?; Ok(()) } pub fn plugin_name_data(data: &mut BTreeMap<&'static str, serde_json::Value>, plugin_name: &str) { data.insert("plugin_name_original", to_json(plugin_name)); data.insert("plugin_name", to_json(plugin_name.to_kebab_case())); data.insert( "plugin_name_snake_case", to_json(plugin_name.to_snake_case()), ); data.insert( "plugin_name_pascal_case", to_json(plugin_name.to_pascal_case()), ); } pub fn crates_metadata() -> Result { serde_json::from_str::(include_str!("../../metadata-v2.json")) .context("failed to parse Tauri version metadata") } pub fn generate_android_out_file( path: &Path, dest: &Path, package_path: &str, created_dirs: &mut Vec, ) -> std::io::Result> { let mut iter = path.iter(); let root = iter.next().unwrap().to_str().unwrap(); let path = match (root, path.extension().and_then(|o| o.to_str())) { ("src", Some("kt")) => { let parent = path.parent().unwrap(); let file_name = path.file_name().unwrap(); let out_dir = dest.join(parent).join(package_path); out_dir.join(file_name) } _ => dest.join(path), }; let parent = path.parent().unwrap().to_path_buf(); if !created_dirs.contains(&parent) { create_dir_all(&parent)?; created_dirs.push(parent); } let mut options = OpenOptions::new(); options.write(true); #[cfg(unix)] if path.file_name().unwrap() == std::ffi::OsStr::new("gradlew") { use std::os::unix::fs::OpenOptionsExt; options.mode(0o755); } if !path.exists() { options.create(true).open(path).map(Some) } else { Ok(None) } } ================================================ FILE: crates/tauri-cli/src/plugin/ios.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use super::PluginIosFramework; use crate::{error::Context, helpers::template, Result}; use clap::{Parser, Subcommand}; use handlebars::Handlebars; use std::{ collections::BTreeMap, env::current_dir, ffi::{OsStr, OsString}, fs::{create_dir_all, File}, path::{Component, PathBuf}, }; #[derive(Parser)] #[clap( author, version, about = "Manage the iOS project for a Tauri plugin", subcommand_required(true), arg_required_else_help(true) )] pub struct Cli { #[clap(subcommand)] command: Commands, } #[derive(Subcommand)] enum Commands { Init(InitOptions), } #[derive(Debug, Parser)] #[clap(about = "Initializes the iOS project for an existing Tauri plugin")] pub struct InitOptions { /// Name of your Tauri plugin. Must match the current plugin's name. /// If not specified, it will be inferred from the current directory. plugin_name: Option, /// The output directory. #[clap(short, long)] #[clap(default_value_t = current_dir().expect("failed to read cwd").to_string_lossy().into_owned())] out_dir: String, /// Type of framework to use for the iOS project. #[clap(long)] #[clap(default_value_t = PluginIosFramework::default())] ios_framework: PluginIosFramework, } pub fn command(cli: Cli) -> Result<()> { match cli.command { Commands::Init(options) => { let plugin_name = match options.plugin_name { None => super::infer_plugin_name( std::env::current_dir().context("failed to get current directory")?, )?, Some(name) => name, }; let out_dir = PathBuf::from(options.out_dir); if out_dir.join("ios").exists() { crate::error::bail!("iOS folder already exists"); } let handlebars = Handlebars::new(); let mut data = BTreeMap::new(); super::init::plugin_name_data(&mut data, &plugin_name); let ios_folder_name = match options.ios_framework { PluginIosFramework::Spm => OsStr::new("ios-spm"), PluginIosFramework::Xcode => OsStr::new("ios-xcode"), }; let mut created_dirs = Vec::new(); template::render_with_generator( &handlebars, &data, &super::init::TEMPLATE_DIR, &out_dir, &mut |path| { let mut components = path.components(); let root = components.next().unwrap(); if let Component::Normal(component) = root { if component == ios_folder_name { let folder_name = components.next().unwrap().as_os_str().to_string_lossy(); let new_folder_name = folder_name.replace("{{ plugin_name }}", &plugin_name); let new_folder_name = OsString::from(&new_folder_name); let path = [ Component::Normal(OsStr::new("ios")), Component::Normal(&new_folder_name), ] .into_iter() .chain(components) .collect::(); let path = out_dir.join(path); let parent = path.parent().unwrap().to_path_buf(); if !created_dirs.contains(&parent) { create_dir_all(&parent)?; created_dirs.push(parent); } return File::create(path).map(Some); } } Ok(None) }, )?; let metadata = super::init::crates_metadata()?; let cargo_toml_addition = format!( r#" [build-dependencies] tauri-build = "{}" "#, metadata.tauri_build ); let build_file = super::init::TEMPLATE_DIR .get_file("build.rs") .unwrap() .contents_utf8() .unwrap(); let init_fn = format!( r#" #[cfg(target_os = "ios")] tauri::ios_plugin_binding!(init_plugin_{plugin_name}); pub fn init() -> TauriPlugin {{ Builder::new("{plugin_name}") .setup(|app| {{ #[cfg(target_os = "ios")] app.register_ios_plugin(init_plugin_{plugin_name})?; Ok(()) }}) .build() }} "#, ); log::info!("iOS project added"); println!("You must add the following to the Cargo.toml file:\n{cargo_toml_addition}",); println!("You must add the following code to the build.rs file:\n\n{build_file}",); println!( "Your plugin's init function under src/lib.rs must initialize the iOS plugin:\n{init_fn}" ); } } Ok(()) } ================================================ FILE: crates/tauri-cli/src/plugin/mod.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use std::{fmt::Display, path::Path}; use clap::{Parser, Subcommand, ValueEnum}; use crate::{ error::{Context, ErrorExt}, Result, }; mod android; mod init; mod ios; mod new; #[derive(Debug, Clone, ValueEnum, Default)] pub enum PluginIosFramework { /// Swift Package Manager project #[default] Spm, /// Xcode project Xcode, } impl Display for PluginIosFramework { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Spm => write!(f, "spm"), Self::Xcode => write!(f, "xcode"), } } } #[derive(Parser)] #[clap( author, version, about = "Manage or create Tauri plugins", subcommand_required(true), arg_required_else_help(true) )] pub struct Cli { #[clap(subcommand)] command: Commands, } #[derive(Subcommand)] enum Commands { New(new::Options), Init(init::Options), Android(android::Cli), Ios(ios::Cli), } pub fn command(cli: Cli) -> Result<()> { match cli.command { Commands::New(options) => new::command(options)?, Commands::Init(options) => init::command(options)?, Commands::Android(cli) => android::command(cli)?, Commands::Ios(cli) => ios::command(cli)?, } Ok(()) } fn infer_plugin_name>(directory: P) -> Result { let dir = directory.as_ref(); let cargo_toml_path = dir.join("Cargo.toml"); let name = if cargo_toml_path.exists() { let contents = std::fs::read_to_string(&cargo_toml_path) .fs_context("failed to read Cargo manifest", cargo_toml_path)?; let cargo_toml: toml::Value = toml::from_str(&contents).context("failed to parse Cargo.toml")?; cargo_toml .get("package") .and_then(|v| v.get("name")) .map(|v| v.as_str().unwrap_or_default()) .unwrap_or_default() .to_string() } else { dir .file_name() .unwrap_or_default() .to_string_lossy() .to_string() }; Ok( name .strip_prefix("tauri-plugin-") .unwrap_or(&name) .to_string(), ) } ================================================ FILE: crates/tauri-cli/src/plugin/new.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use super::PluginIosFramework; use crate::{ error::{Context, ErrorExt}, Result, }; use clap::Parser; use std::path::PathBuf; #[derive(Debug, Parser)] #[clap(about = "Initializes a new Tauri plugin project")] pub struct Options { /// Name of your Tauri plugin plugin_name: String, /// Initializes a Tauri plugin without the TypeScript API #[clap(long)] no_api: bool, /// Initialize without an example project. #[clap(long)] no_example: bool, /// Set target directory for init #[clap(short, long)] directory: Option, /// Author name #[clap(short, long)] author: Option, /// Whether to initialize an Android project for the plugin. #[clap(long)] android: bool, /// Whether to initialize an iOS project for the plugin. #[clap(long)] ios: bool, /// Whether to initialize Android and iOS projects for the plugin. #[clap(long)] mobile: bool, /// Type of framework to use for the iOS project. #[clap(long)] #[clap(default_value_t = PluginIosFramework::default())] pub(crate) ios_framework: PluginIosFramework, /// Generate github workflows #[clap(long)] github_workflows: bool, /// Initializes a Tauri core plugin (internal usage) #[clap(long, hide(true))] tauri: bool, /// Path of the Tauri project to use (relative to the cwd) #[clap(short, long)] tauri_path: Option, } impl From for super::init::Options { fn from(o: Options) -> Self { Self { plugin_name: Some(o.plugin_name), no_api: o.no_api, no_example: o.no_example, directory: o.directory.unwrap(), author: o.author, android: o.android, ios: o.ios, mobile: o.mobile, ios_framework: o.ios_framework, github_workflows: o.github_workflows, tauri: o.tauri, tauri_path: o.tauri_path, } } } pub fn command(mut options: Options) -> Result<()> { let cwd = std::env::current_dir().context("failed to get current directory")?; if let Some(dir) = &options.directory { std::fs::create_dir_all(cwd.join(dir)) .fs_context("failed to create crate directory", cwd.join(dir))?; } else { let target = cwd.join(format!("tauri-plugin-{}", options.plugin_name)); std::fs::create_dir_all(&target) .fs_context("failed to create crate directory", target.clone())?; options.directory.replace(target.display().to_string()); } super::init::command(options.into()) } ================================================ FILE: crates/tauri-cli/src/remove.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use clap::Parser; use crate::{ acl, helpers::{app_paths::resolve_frontend_dir, cargo, npm::PackageManager}, Result, }; #[derive(Debug, Parser)] #[clap(about = "Remove a tauri plugin from the project")] pub struct Options { /// The plugin to remove. pub plugin: String, } pub fn command(options: Options) -> Result<()> { let dirs = crate::helpers::app_paths::resolve_dirs(); let plugin = options.plugin; let crate_name = format!("tauri-plugin-{plugin}"); let mut plugins = crate::helpers::plugins::known_plugins(); let metadata = plugins.remove(plugin.as_str()).unwrap_or_default(); let frontend_dir = resolve_frontend_dir(); let target_str = metadata .desktop_only .then_some(r#"cfg(not(any(target_os = "android", target_os = "ios")))"#) .or_else(|| { metadata .mobile_only .then_some(r#"cfg(any(target_os = "android", target_os = "ios"))"#) }); cargo::uninstall_one(cargo::CargoUninstallOptions { name: &crate_name, cwd: Some(dirs.tauri), target: target_str, })?; if !metadata.rust_only { if let Some(manager) = frontend_dir.map(PackageManager::from_project) { let npm_name = format!("@tauri-apps/plugin-{plugin}"); manager.remove(&[npm_name], dirs.tauri)?; } acl::permission::rm::command(acl::permission::rm::Options { identifier: format!("{plugin}:*"), })?; } log::info!("Now, you must manually remove the plugin from your Rust code.",); Ok(()) } ================================================ FILE: crates/tauri-cli/src/signer/generate.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use crate::{ helpers::updater_signature::{generate_key, save_keypair}, Result, }; use clap::Parser; use std::path::PathBuf; use tauri_utils::display_path; #[derive(Debug, Parser)] #[clap(about = "Generate a new signing key to sign files")] pub struct Options { /// Set private key password when signing #[clap(short, long)] password: Option, /// Write private key to a file #[clap(short, long)] write_keys: Option, /// Overwrite private key even if it exists on the specified path #[clap(short, long)] force: bool, /// Skip prompting for values #[clap(long, env = "CI")] ci: bool, } pub fn command(mut options: Options) -> Result<()> { if options.ci && options.password.is_none() { log::warn!("Generating new private key without password. For security reasons, we recommend setting a password instead."); options.password.replace("".into()); } let keypair = generate_key(options.password).expect("Failed to generate key"); if let Some(output_path) = options.write_keys { let (secret_path, public_path) = save_keypair(options.force, output_path, &keypair.sk, &keypair.pk) .expect("Unable to write keypair"); println!(); println!("Your keypair was generated successfully:"); println!("Private: {} (Keep it secret!)", display_path(secret_path)); println!("Public: {}", display_path(public_path)); println!("---------------------------") } else { println!(); println!("Your keys were generated successfully!",); println!(); println!("Private: (Keep it secret!)"); println!("{}", keypair.sk); println!(); println!("Public:"); println!("{}", keypair.pk); } println!(); println!("Environment variables used to sign:"); println!("- `TAURI_SIGNING_PRIVATE_KEY`: String of your private key"); println!("- `TAURI_SIGNING_PRIVATE_KEY_PATH`: Path to your private key file"); println!("- `TAURI_SIGNING_PRIVATE_KEY_PASSWORD`: Your private key password (optional if key has no password)"); println!(); println!("ATTENTION: If you lose your private key OR password, you'll not be able to sign your update package and updates will not work"); Ok(()) } ================================================ FILE: crates/tauri-cli/src/signer/mod.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use crate::Result; use clap::{Parser, Subcommand}; mod generate; mod sign; #[derive(Parser)] #[clap( author, version, about = "Generate signing keys for Tauri updater or sign files", subcommand_required(true), arg_required_else_help(true) )] pub struct Cli { #[clap(subcommand)] command: Commands, } #[derive(Subcommand)] enum Commands { Sign(sign::Options), Generate(generate::Options), } pub fn command(cli: Cli) -> Result<()> { match cli.command { Commands::Sign(options) => sign::command(options)?, Commands::Generate(options) => generate::command(options)?, } Ok(()) } ================================================ FILE: crates/tauri-cli/src/signer/sign.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use std::path::{Path, PathBuf}; use crate::{ error::Context, helpers::updater_signature::{secret_key, sign_file}, Result, }; use base64::Engine; use clap::Parser; use tauri_utils::display_path; #[derive(Debug, Parser)] #[clap(about = "Sign a file")] pub struct Options { /// Load the private key from a string #[clap( short = 'k', long, conflicts_with("private_key_path"), env = "TAURI_SIGNING_PRIVATE_KEY" )] private_key: Option, /// Load the private key from a file #[clap( short = 'f', long, conflicts_with("private_key"), env = "TAURI_SIGNING_PRIVATE_KEY_PATH" )] private_key_path: Option, /// Set private key password when signing #[clap(short, long, env = "TAURI_SIGNING_PRIVATE_KEY_PASSWORD")] password: Option, /// Sign the specified file file: PathBuf, } // Backwards compatibility with old env vars // TODO: remove in v3.0 fn backward_env_vars(mut options: Options) -> Options { let get_env = |old, new| { if let Ok(old_value) = std::env::var(old) { println!( "\x1b[33mWarning: The environment variable '{old}' is deprecated. Please use '{new}' instead.\x1b[0m", ); Some(old_value) } else { None } }; options.private_key = options .private_key .or_else(|| get_env("TAURI_PRIVATE_KEY", "TAURI_SIGNING_PRIVATE_KEY")); options.private_key_path = options.private_key_path.or_else(|| { get_env("TAURI_PRIVATE_KEY_PATH", "TAURI_SIGNING_PRIVATE_KEY_PATH").map(PathBuf::from) }); options.password = options.password.or_else(|| { get_env( "TAURI_PRIVATE_KEY_PASSWORD", "TAURI_SIGNING_PRIVATE_KEY_PASSWORD", ) }); options } pub fn command(mut options: Options) -> Result<()> { options = backward_env_vars(options); options.private_key = if let Some(private_key) = options.private_key_path { Some(std::fs::read_to_string(Path::new(&private_key)).expect("Unable to extract private key")) } else { options.private_key }; let private_key = if let Some(pk) = options.private_key { pk } else { crate::error::bail!("Key generation aborted: Unable to find the private key"); }; if options.password.is_none() { println!("Signing without password."); } let (manifest_dir, signature) = sign_file(&secret_key(private_key, options.password)?, options.file) .with_context(|| "failed to sign file")?; println!( "\nYour file was signed successfully, You can find the signature here:\n{}\n\nPublic signature:\n{}\n\nMake sure to include this into the signature field of your update server.", display_path(manifest_dir), base64::engine::general_purpose::STANDARD.encode(signature.to_string()) ); Ok(()) } ================================================ FILE: crates/tauri-cli/tauri-dev-watcher.gitignore ================================================ node_modules/ target/ gen/ Cargo.lock .DS_Store ================================================ FILE: crates/tauri-cli/tauri.config.schema.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Config", "description": "The Tauri configuration object.\n It is read from a file where you can define your frontend assets,\n configure the bundler and define a tray icon.\n\n The configuration file is generated by the\n [`tauri init`](https://tauri.app/v1/api/cli#init) command that lives in\n your Tauri application source directory (src-tauri).\n\n Once generated, you may modify it at will to customize your Tauri application.\n\n ## File Formats\n\n By default, the configuration is defined as a JSON file named `tauri.conf.json`.\n\n Tauri also supports JSON5 and TOML files via the `config-json5` and `config-toml` Cargo features, respectively.\n The JSON5 file name must be either `tauri.conf.json` or `tauri.conf.json5`.\n The TOML file name is `Tauri.toml`.\n\n ## Platform-Specific Configuration\n\n In addition to the default configuration file, Tauri can\n read a platform-specific configuration from `tauri.linux.conf.json`,\n `tauri.windows.conf.json`, `tauri.macos.conf.json`, `tauri.android.conf.json` and `tauri.ios.conf.json`\n (or `Tauri.linux.toml`, `Tauri.windows.toml`, `Tauri.macos.toml`, `Tauri.android.toml` and `Tauri.ios.toml` if the `Tauri.toml` format is used),\n which gets merged with the main configuration object.\n\n ## Configuration Structure\n\n The configuration is composed of the following objects:\n\n - [`app`](#appconfig): The Tauri configuration\n - [`build`](#buildconfig): The build configuration\n - [`bundle`](#bundleconfig): The bundle configurations\n - [`plugins`](#pluginconfig): The plugins configuration\n\n Example tauri.config.json file:\n\n ```json\n {\n \"productName\": \"tauri-app\",\n \"version\": \"0.1.0\",\n \"build\": {\n \"beforeBuildCommand\": \"\",\n \"beforeDevCommand\": \"\",\n \"devUrl\": \"../dist\",\n \"frontendDist\": \"../dist\"\n },\n \"app\": {\n \"security\": {\n \"csp\": null\n },\n \"windows\": [\n {\n \"fullscreen\": false,\n \"height\": 600,\n \"resizable\": true,\n \"title\": \"Tauri App\",\n \"width\": 800\n }\n ]\n },\n \"bundle\": {},\n \"plugins\": {}\n }\n ```", "type": "object", "properties": { "$schema": { "description": "The JSON schema for the Tauri config.", "type": [ "string", "null" ] }, "productName": { "description": "App name.", "type": [ "string", "null" ], "pattern": "^[^/\\:*?\"<>|]+$" }, "version": { "description": "App version. It is a semver version number or a path to a `package.json` file containing the `version` field. If removed the version number from `Cargo.toml` is used.\n\n By default version 1.0 is used on Android.", "type": [ "string", "null" ] }, "identifier": { "description": "The application identifier in reverse domain name notation (e.g. `com.tauri.example`).\n This string must be unique across applications since it is used in system configurations like\n the bundle ID and path to the webview data directory.\n This string must contain only alphanumeric characters (A–Z, a–z, and 0–9), hyphens (-),\n and periods (.).", "default": "", "type": "string" }, "app": { "description": "The App configuration.", "default": { "enableGTKAppId": false, "macOSPrivateApi": false, "security": { "assetProtocol": { "enable": false, "scope": [] }, "capabilities": [], "dangerousDisableAssetCspModification": false, "freezePrototype": false, "pattern": { "use": "brownfield" } }, "windows": [], "withGlobalTauri": false }, "allOf": [ { "$ref": "#/definitions/AppConfig" } ] }, "build": { "description": "The build configuration.", "default": {}, "allOf": [ { "$ref": "#/definitions/BuildConfig" } ] }, "bundle": { "description": "The bundler configuration.", "default": { "active": false, "android": { "minSdkVersion": 24 }, "createUpdaterArtifacts": false, "iOS": { "minimumSystemVersion": "13.0" }, "icon": [], "linux": { "appimage": { "bundleMediaFramework": false, "files": {} }, "deb": { "files": {} }, "rpm": { "epoch": 0, "files": {}, "release": "1" } }, "macOS": { "dmg": { "appPosition": { "x": 180, "y": 170 }, "applicationFolderPosition": { "x": 480, "y": 170 }, "windowSize": { "height": 400, "width": 660 } }, "files": {}, "hardenedRuntime": true, "minimumSystemVersion": "10.13" }, "targets": "all", "windows": { "allowDowngrades": true, "certificateThumbprint": null, "digestAlgorithm": null, "nsis": null, "signCommand": null, "timestampUrl": null, "tsp": false, "webviewInstallMode": { "silent": true, "type": "downloadBootstrapper" }, "wix": null } }, "allOf": [ { "$ref": "#/definitions/BundleConfig" } ] }, "plugins": { "description": "The plugins config.", "default": {}, "allOf": [ { "$ref": "#/definitions/PluginConfig" } ] } }, "additionalProperties": false, "definitions": { "AppConfig": { "description": "The App configuration object.\n\n See more: ", "type": "object", "properties": { "windows": { "description": "The windows configuration.", "default": [], "type": "array", "items": { "$ref": "#/definitions/WindowConfig" } }, "security": { "description": "Security configuration.", "default": { "assetProtocol": { "enable": false, "scope": [] }, "capabilities": [], "dangerousDisableAssetCspModification": false, "freezePrototype": false, "pattern": { "use": "brownfield" } }, "allOf": [ { "$ref": "#/definitions/SecurityConfig" } ] }, "trayIcon": { "description": "Configuration for app tray icon.", "anyOf": [ { "$ref": "#/definitions/TrayIconConfig" }, { "type": "null" } ] }, "macOSPrivateApi": { "description": "MacOS private API configuration. Enables the transparent background API and sets the `fullScreenEnabled` preference to `true`.", "default": false, "type": "boolean" }, "withGlobalTauri": { "description": "Whether we should inject the Tauri API on `window.__TAURI__` or not.", "default": false, "type": "boolean" }, "enableGTKAppId": { "description": "If set to true \"identifier\" will be set as GTK app ID (on systems that use GTK).", "default": false, "type": "boolean" } }, "additionalProperties": false }, "WindowConfig": { "description": "The window configuration object.\n\n See more: ", "type": "object", "properties": { "label": { "description": "The window identifier. It must be alphanumeric.", "default": "main", "type": "string" }, "url": { "description": "The window webview URL.", "default": "index.html", "allOf": [ { "$ref": "#/definitions/WebviewUrl" } ] }, "userAgent": { "description": "The user agent for the webview", "type": [ "string", "null" ] }, "dragDropEnabled": { "description": "Whether the drag and drop is enabled or not on the webview. By default it is enabled.\n\n Disabling it is required to use HTML5 drag and drop on the frontend on Windows.", "default": true, "type": "boolean" }, "center": { "description": "Whether or not the window starts centered or not.", "default": false, "type": "boolean" }, "x": { "description": "The horizontal position of the window's top left corner", "type": [ "number", "null" ], "format": "double" }, "y": { "description": "The vertical position of the window's top left corner", "type": [ "number", "null" ], "format": "double" }, "width": { "description": "The window width.", "default": 800.0, "type": "number", "format": "double" }, "height": { "description": "The window height.", "default": 600.0, "type": "number", "format": "double" }, "minWidth": { "description": "The min window width.", "type": [ "number", "null" ], "format": "double" }, "minHeight": { "description": "The min window height.", "type": [ "number", "null" ], "format": "double" }, "maxWidth": { "description": "The max window width.", "type": [ "number", "null" ], "format": "double" }, "maxHeight": { "description": "The max window height.", "type": [ "number", "null" ], "format": "double" }, "preventOverflow": { "description": "Whether or not to prevent window overflow", "anyOf": [ { "$ref": "#/definitions/PreventOverflowMarginConfig" }, { "type": "null" } ] }, "resizable": { "description": "Whether the window is resizable or not. When resizable is set to false, native window's maximize button is automatically disabled.", "default": true, "type": "boolean" }, "maximizable": { "description": "Whether the window's native maximize button is enabled or not.\n If resizable is set to false, this setting is ignored.\n\n ## Platform-specific\n\n - **macOS:** Disables the \"zoom\" button in the window titlebar, which is also used to enter fullscreen mode.\n - **Linux / iOS / Android:** Unsupported.", "default": true, "type": "boolean" }, "minimizable": { "description": "Whether the window's native minimize button is enabled or not.\n\n ## Platform-specific\n\n - **Linux / iOS / Android:** Unsupported.", "default": true, "type": "boolean" }, "closable": { "description": "Whether the window's native close button is enabled or not.\n\n ## Platform-specific\n\n - **Linux:** \"GTK+ will do its best to convince the window manager not to show a close button.\n Depending on the system, this function may not have any effect when called on a window that is already visible\"\n - **iOS / Android:** Unsupported.", "default": true, "type": "boolean" }, "title": { "description": "The window title.", "default": "Tauri App", "type": "string" }, "fullscreen": { "description": "Whether the window starts as fullscreen or not.", "default": false, "type": "boolean" }, "focus": { "description": "Whether the window will be initially focused or not.", "default": true, "type": "boolean" }, "focusable": { "description": "Whether the window will be focusable or not.", "default": true, "type": "boolean" }, "transparent": { "description": "Whether the window is transparent or not.\n\n Note that on `macOS` this requires the `macos-private-api` feature flag, enabled under `tauri > macOSPrivateApi`.\n WARNING: Using private APIs on `macOS` prevents your application from being accepted to the `App Store`.", "default": false, "type": "boolean" }, "maximized": { "description": "Whether the window is maximized or not.", "default": false, "type": "boolean" }, "visible": { "description": "Whether the window is visible or not.", "default": true, "type": "boolean" }, "decorations": { "description": "Whether the window should have borders and bars.", "default": true, "type": "boolean" }, "alwaysOnBottom": { "description": "Whether the window should always be below other windows.", "default": false, "type": "boolean" }, "alwaysOnTop": { "description": "Whether the window should always be on top of other windows.", "default": false, "type": "boolean" }, "visibleOnAllWorkspaces": { "description": "Whether the window should be visible on all workspaces or virtual desktops.\n\n ## Platform-specific\n\n - **Windows / iOS / Android:** Unsupported.", "default": false, "type": "boolean" }, "contentProtected": { "description": "Prevents the window contents from being captured by other apps.", "default": false, "type": "boolean" }, "skipTaskbar": { "description": "If `true`, hides the window icon from the taskbar on Windows and Linux.", "default": false, "type": "boolean" }, "theme": { "description": "The initial window theme. Defaults to the system theme. Only implemented on Windows and macOS 10.14+.", "anyOf": [ { "$ref": "#/definitions/Theme" }, { "type": "null" } ] }, "titleBarStyle": { "description": "The style of the macOS title bar.", "default": "Visible", "allOf": [ { "$ref": "#/definitions/TitleBarStyle" } ] }, "hiddenTitle": { "description": "If `true`, sets the window title to be hidden on macOS.", "default": false, "type": "boolean" }, "acceptFirstMouse": { "description": "Whether clicking an inactive window also clicks through to the webview on macOS.", "default": false, "type": "boolean" }, "tabbingIdentifier": { "description": "Defines the window [tabbing identifier] for macOS.\n\n Windows with matching tabbing identifiers will be grouped together.\n If the tabbing identifier is not set, automatic tabbing will be disabled.\n\n [tabbing identifier]: ", "type": [ "string", "null" ] }, "additionalBrowserArgs": { "description": "Defines additional browser arguments on Windows. By default wry passes `--disable-features=msWebOOUI,msPdfOOUI,msSmartScreenProtection`\n so if you use this method, you also need to disable these components by yourself if you want.", "type": [ "string", "null" ] }, "shadow": { "description": "Whether or not the window has shadow.\n\n ## Platform-specific\n\n - **Windows:**\n - `false` has no effect on decorated window, shadow are always ON.\n - `true` will make undecorated window have a 1px white border,\n and on Windows 11, it will have a rounded corners.\n - **Linux:** Unsupported.", "default": true, "type": "boolean" }, "windowEffects": { "description": "Window effects.\n\n Requires the window to be transparent.\n\n ## Platform-specific:\n\n - **Windows**: If using decorations or shadows, you may want to try this workaround \n - **Linux**: Unsupported", "anyOf": [ { "$ref": "#/definitions/WindowEffectsConfig" }, { "type": "null" } ] }, "incognito": { "description": "Whether or not the webview should be launched in incognito mode.\n\n ## Platform-specific:\n\n - **Android**: Unsupported.", "default": false, "type": "boolean" }, "parent": { "description": "Sets the window associated with this label to be the parent of the window to be created.\n\n ## Platform-specific\n\n - **Windows**: This sets the passed parent as an owner window to the window to be created.\n From [MSDN owned windows docs](https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#owned-windows):\n - An owned window is always above its owner in the z-order.\n - The system automatically destroys an owned window when its owner is destroyed.\n - An owned window is hidden when its owner is minimized.\n - **Linux**: This makes the new window transient for parent, see \n - **macOS**: This adds the window as a child of parent, see ", "type": [ "string", "null" ] }, "proxyUrl": { "description": "The proxy URL for the WebView for all network requests.\n\n Must be either a `http://` or a `socks5://` URL.\n\n ## Platform-specific\n\n - **macOS**: Requires the `macos-proxy` feature flag and only compiles for macOS 14+.", "type": [ "string", "null" ], "format": "uri" }, "zoomHotkeysEnabled": { "description": "Whether page zooming by hotkeys is enabled\n\n ## Platform-specific:\n\n - **Windows**: Controls WebView2's [`IsZoomControlEnabled`](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/microsoft_web_webview2_core/corewebview2settings?view=webview2-winrt-1.0.2420.47#iszoomcontrolenabled) setting.\n - **MacOS / Linux**: Injects a polyfill that zooms in and out with `ctrl/command` + `-/=`,\n 20% in each step, ranging from 20% to 1000%. Requires `webview:allow-set-webview-zoom` permission\n\n - **Android / iOS**: Unsupported.", "default": false, "type": "boolean" }, "backgroundThrottling": { "description": "Change the default background throttling behaviour.\n\n By default, browsers use a suspend policy that will throttle timers and even unload\n the whole tab (view) to free resources after roughly 5 minutes when a view became\n minimized or hidden. This will pause all tasks until the documents visibility state\n changes back from hidden to visible by bringing the view back to the foreground.\n\n ## Platform-specific\n\n - **Linux / Windows / Android**: Unsupported. Workarounds like a pending WebLock transaction might suffice.\n - **iOS**: Supported since version 17.0+.\n - **macOS**: Supported since version 14.0+.\n\n see https://github.com/tauri-apps/tauri/issues/5250#issuecomment-2569380578", "type": "string", "enum": [ "disabled", "throttle", "suspend" ] } }, "additionalProperties": false }, "WebviewUrl": { "description": "An URL to open on a Tauri webview window.", "anyOf": [ { "description": "An external URL. Must use either the `http` or `https` schemes.", "type": "string", "format": "uri" }, { "description": "The path portion of an app URL.\n For instance, to load `tauri://localhost/users/john`,\n you can simply provide `users/john` in this configuration.", "type": "string" }, { "description": "A custom protocol url, for example, `doom://index.html`", "type": "string", "format": "uri" } ] }, "PreventOverflowMarginConfig": { "description": "Prevent overflow with a margin", "anyOf": [ { "description": "Enable prevent overflow or not", "type": "boolean" }, { "description": "Enable prevent overflow with a margin", "allOf": [ { "$ref": "#/definitions/PreventOverflowMargin" } ] } ] }, "PreventOverflowMargin": { "description": "Enable prevent overflow with a margin", "type": "object", "required": [ "height", "width" ], "properties": { "width": { "description": "Horizontal margin in physical unit", "type": "integer", "format": "uint32", "minimum": 0.0 }, "height": { "description": "Vertical margin in physical unit", "type": "integer", "format": "uint32", "minimum": 0.0 } }, "additionalProperties": false }, "Theme": { "description": "System theme.", "oneOf": [ { "description": "Light theme.", "type": "string", "enum": [ "Light" ] }, { "description": "Dark theme.", "type": "string", "enum": [ "Dark" ] } ] }, "TitleBarStyle": { "description": "How the window title bar should be displayed on macOS.", "oneOf": [ { "description": "A normal title bar.", "type": "string", "enum": [ "Visible" ] }, { "description": "Makes the title bar transparent, so the window background color is shown instead.\n\n Useful if you don't need to have actual HTML under the title bar. This lets you avoid the caveats of using `TitleBarStyle::Overlay`. Will be more useful when Tauri lets you set a custom window background color.", "type": "string", "enum": [ "Transparent" ] }, { "description": "Shows the title bar as a transparent overlay over the window's content.\n\n Keep in mind:\n - The height of the title bar is different on different OS versions, which can lead to window the controls and title not being where you don't expect.\n - You need to define a custom drag region to make your window draggable, however due to a limitation you can't drag the window when it's not in focus .\n - The color of the window title depends on the system theme.", "type": "string", "enum": [ "Overlay" ] } ] }, "WindowEffectsConfig": { "description": "The window effects configuration object", "type": "object", "required": [ "effects" ], "properties": { "effects": { "description": "List of Window effects to apply to the Window.\n Conflicting effects will apply the first one and ignore the rest.", "type": "array", "items": { "$ref": "#/definitions/WindowEffect" } }, "state": { "description": "Window effect state **macOS Only**", "anyOf": [ { "$ref": "#/definitions/WindowEffectState" }, { "type": "null" } ] }, "radius": { "description": "Window effect corner radius **macOS Only**", "type": [ "number", "null" ], "format": "double" }, "color": { "description": "Window effect color. Affects [`WindowEffect::Blur`] and [`WindowEffect::Acrylic`] only\n on Windows 10 v1903+. Doesn't have any effect on Windows 7 or Windows 11.", "anyOf": [ { "$ref": "#/definitions/Color" }, { "type": "null" } ] } }, "additionalProperties": false }, "WindowEffect": { "description": "Platform-specific window effects", "oneOf": [ { "description": "A default material appropriate for the view's effectiveAppearance. **macOS 10.14-**", "deprecated": true, "type": "string", "enum": [ "appearanceBased" ] }, { "description": "**macOS 10.14-**", "deprecated": true, "type": "string", "enum": [ "light" ] }, { "description": "**macOS 10.14-**", "deprecated": true, "type": "string", "enum": [ "dark" ] }, { "description": "**macOS 10.14-**", "deprecated": true, "type": "string", "enum": [ "mediumLight" ] }, { "description": "**macOS 10.14-**", "deprecated": true, "type": "string", "enum": [ "ultraDark" ] }, { "description": "**macOS 10.10+**", "type": "string", "enum": [ "titlebar" ] }, { "description": "**macOS 10.10+**", "type": "string", "enum": [ "selection" ] }, { "description": "**macOS 10.11+**", "type": "string", "enum": [ "menu" ] }, { "description": "**macOS 10.11+**", "type": "string", "enum": [ "popover" ] }, { "description": "**macOS 10.11+**", "type": "string", "enum": [ "sidebar" ] }, { "description": "**macOS 10.14+**", "type": "string", "enum": [ "headerView" ] }, { "description": "**macOS 10.14+**", "type": "string", "enum": [ "sheet" ] }, { "description": "**macOS 10.14+**", "type": "string", "enum": [ "windowBackground" ] }, { "description": "**macOS 10.14+**", "type": "string", "enum": [ "hudWindow" ] }, { "description": "**macOS 10.14+**", "type": "string", "enum": [ "fullScreenUI" ] }, { "description": "**macOS 10.14+**", "type": "string", "enum": [ "tooltip" ] }, { "description": "**macOS 10.14+**", "type": "string", "enum": [ "contentBackground" ] }, { "description": "**macOS 10.14+**", "type": "string", "enum": [ "underWindowBackground" ] }, { "description": "**macOS 10.14+**", "type": "string", "enum": [ "underPageBackground" ] }, { "description": "Mica effect that matches the system dark perefence **Windows 11 Only**", "type": "string", "enum": [ "mica" ] }, { "description": "Mica effect with dark mode but only if dark mode is enabled on the system **Windows 11 Only**", "type": "string", "enum": [ "micaDark" ] }, { "description": "Mica effect with light mode **Windows 11 Only**", "type": "string", "enum": [ "micaLight" ] }, { "description": "Tabbed effect that matches the system dark perefence **Windows 11 Only**", "type": "string", "enum": [ "tabbed" ] }, { "description": "Tabbed effect with dark mode but only if dark mode is enabled on the system **Windows 11 Only**", "type": "string", "enum": [ "tabbedDark" ] }, { "description": "Tabbed effect with light mode **Windows 11 Only**", "type": "string", "enum": [ "tabbedLight" ] }, { "description": "**Windows 7/10/11(22H1) Only**\n\n ## Notes\n\n This effect has bad performance when resizing/dragging the window on Windows 11 build 22621.", "type": "string", "enum": [ "blur" ] }, { "description": "**Windows 10/11 Only**\n\n ## Notes\n\n This effect has bad performance when resizing/dragging the window on Windows 10 v1903+ and Windows 11 build 22000.", "type": "string", "enum": [ "acrylic" ] } ] }, "WindowEffectState": { "description": "Window effect state **macOS only**\n\n ", "oneOf": [ { "description": "Make window effect state follow the window's active state", "type": "string", "enum": [ "followsWindowActiveState" ] }, { "description": "Make window effect state always active", "type": "string", "enum": [ "active" ] }, { "description": "Make window effect state always inactive", "type": "string", "enum": [ "inactive" ] } ] }, "Color": { "description": "a tuple struct of RGBA colors. Each value has minimum of 0 and maximum of 255.", "type": "array", "items": [ { "type": "integer", "format": "uint8", "minimum": 0.0 }, { "type": "integer", "format": "uint8", "minimum": 0.0 }, { "type": "integer", "format": "uint8", "minimum": 0.0 }, { "type": "integer", "format": "uint8", "minimum": 0.0 } ], "maxItems": 4, "minItems": 4 }, "SecurityConfig": { "description": "Security configuration.\n\n See more: ", "type": "object", "properties": { "csp": { "description": "The Content Security Policy that will be injected on all HTML files on the built application.\n If [`dev_csp`](#SecurityConfig.devCsp) is not specified, this value is also injected on dev.\n\n This is a really important part of the configuration since it helps you ensure your WebView is secured.\n See .", "anyOf": [ { "$ref": "#/definitions/Csp" }, { "type": "null" } ] }, "devCsp": { "description": "The Content Security Policy that will be injected on all HTML files on development.\n\n This is a really important part of the configuration since it helps you ensure your WebView is secured.\n See .", "anyOf": [ { "$ref": "#/definitions/Csp" }, { "type": "null" } ] }, "freezePrototype": { "description": "Freeze the `Object.prototype` when using the custom protocol.", "default": false, "type": "boolean" }, "dangerousDisableAssetCspModification": { "description": "Disables the Tauri-injected CSP sources.\n\n At compile time, Tauri parses all the frontend assets and changes the Content-Security-Policy\n to only allow loading of your own scripts and styles by injecting nonce and hash sources.\n This stricts your CSP, which may introduce issues when using along with other flexing sources.\n\n This configuration option allows both a boolean and a list of strings as value.\n A boolean instructs Tauri to disable the injection for all CSP injections,\n and a list of strings indicates the CSP directives that Tauri cannot inject.\n\n **WARNING:** Only disable this if you know what you are doing and have properly configured the CSP.\n Your application might be vulnerable to XSS attacks without this Tauri protection.", "default": false, "allOf": [ { "$ref": "#/definitions/DisabledCspModificationKind" } ] }, "assetProtocol": { "description": "Custom protocol config.", "default": { "enable": false, "scope": [] }, "allOf": [ { "$ref": "#/definitions/AssetProtocolConfig" } ] }, "pattern": { "description": "The pattern to use.", "default": { "use": "brownfield" }, "allOf": [ { "$ref": "#/definitions/PatternKind" } ] }, "capabilities": { "description": "List of capabilities that are enabled on the application.\n\n If the list is empty, all capabilities are included.", "default": [], "type": "array", "items": { "$ref": "#/definitions/CapabilityEntry" } } }, "additionalProperties": false }, "Csp": { "description": "A Content-Security-Policy definition.\n See .", "anyOf": [ { "description": "The entire CSP policy in a single text string.", "type": "string" }, { "description": "An object mapping a directive with its sources values as a list of strings.", "type": "object", "additionalProperties": { "$ref": "#/definitions/CspDirectiveSources" } } ] }, "CspDirectiveSources": { "description": "A Content-Security-Policy directive source list.\n See .", "anyOf": [ { "description": "An inline list of CSP sources. Same as [`Self::List`], but concatenated with a space separator.", "type": "string" }, { "description": "A list of CSP sources. The collection will be concatenated with a space separator for the CSP string.", "type": "array", "items": { "type": "string" } } ] }, "DisabledCspModificationKind": { "description": "The possible values for the `dangerous_disable_asset_csp_modification` config option.", "anyOf": [ { "description": "If `true`, disables all CSP modification.\n `false` is the default value and it configures Tauri to control the CSP.", "type": "boolean" }, { "description": "Disables the given list of CSP directives modifications.", "type": "array", "items": { "type": "string" } } ] }, "AssetProtocolConfig": { "description": "Config for the asset custom protocol.\n\n See more: ", "type": "object", "properties": { "scope": { "description": "The access scope for the asset protocol.", "default": [], "allOf": [ { "$ref": "#/definitions/FsScope" } ] }, "enable": { "description": "Enables the asset protocol.", "default": false, "type": "boolean" } }, "additionalProperties": false }, "FsScope": { "description": "Protocol scope definition.\n It is a list of glob patterns that restrict the API access from the webview.\n\n Each pattern can start with a variable that resolves to a system base directory.\n The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`,\n `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`,\n `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`,\n `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.", "anyOf": [ { "description": "A list of paths that are allowed by this scope.", "type": "array", "items": { "type": "string" } }, { "description": "A complete scope configuration.", "type": "object", "properties": { "allow": { "description": "A list of paths that are allowed by this scope.", "default": [], "type": "array", "items": { "type": "string" } }, "deny": { "description": "A list of paths that are not allowed by this scope.\n This gets precedence over the [`Self::Scope::allow`] list.", "default": [], "type": "array", "items": { "type": "string" } }, "requireLiteralLeadingDot": { "description": "Whether or not paths that contain components that start with a `.`\n will require that `.` appears literally in the pattern; `*`, `?`, `**`,\n or `[...]` will not match. This is useful because such files are\n conventionally considered hidden on Unix systems and it might be\n desirable to skip them when listing files.\n\n Defaults to `true` on Unix systems and `false` on Windows", "type": [ "boolean", "null" ] } } } ] }, "PatternKind": { "description": "The application pattern.", "oneOf": [ { "description": "Brownfield pattern.", "type": "object", "required": [ "use" ], "properties": { "use": { "type": "string", "enum": [ "brownfield" ] } } }, { "description": "Isolation pattern. Recommended for security purposes.", "type": "object", "required": [ "options", "use" ], "properties": { "use": { "type": "string", "enum": [ "isolation" ] }, "options": { "type": "object", "required": [ "dir" ], "properties": { "dir": { "description": "The dir containing the index.html file that contains the secure isolation application.", "type": "string" } } } } } ] }, "CapabilityEntry": { "description": "A capability entry which can be either an inlined capability or a reference to a capability defined on its own file.", "anyOf": [ { "description": "An inlined capability.", "allOf": [ { "$ref": "#/definitions/Capability" } ] }, { "description": "Reference to a capability identifier.", "type": "string" } ] }, "Capability": { "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```", "type": "object", "required": [ "identifier", "permissions" ], "properties": { "identifier": { "description": "Identifier of the capability.\n\n ## Example\n\n `main-user-files-write`", "type": "string" }, "description": { "description": "Description of what the capability is intended to allow on associated windows.\n\n It should contain a description of what the grouped permissions should allow.\n\n ## Example\n\n This capability allows the `main` window access to `filesystem` write related\n commands and `dialog` commands to enable programatic access to files selected by the user.", "default": "", "type": "string" }, "remote": { "description": "Configure remote URLs that can use the capability permissions.\n\n This setting is optional and defaults to not being set, as our\n default use case is that the content is served from our local application.\n\n :::caution\n Make sure you understand the security implications of providing remote\n sources with local system access.\n :::\n\n ## Example\n\n ```json\n {\n \"urls\": [\"https://*.mydomain.dev\"]\n }\n ```", "anyOf": [ { "$ref": "#/definitions/CapabilityRemote" }, { "type": "null" } ] }, "local": { "description": "Whether this capability is enabled for local app URLs or not. Defaults to `true`.", "default": true, "type": "boolean" }, "windows": { "description": "List of windows that are affected by this capability. Can be a glob pattern.\n\n On multiwebview windows, prefer [`Self::webviews`] for a fine grained access control.\n\n ## Example\n\n `[\"main\"]`", "type": "array", "items": { "type": "string" } }, "webviews": { "description": "List of webviews that are affected by this capability. Can be a glob pattern.\n\n This is only required when using on multiwebview contexts, by default\n all child webviews of a window that matches [`Self::windows`] are linked.\n\n ## Example\n\n `[\"sub-webview-one\", \"sub-webview-two\"]`", "type": "array", "items": { "type": "string" } }, "permissions": { "description": "List of permissions attached to this capability.\n\n Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.\n For commands directly implemented in the application itself only `${permission-name}`\n is required.\n\n ## Example\n\n ```json\n [\n \"core:default\",\n \"shell:allow-open\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n }\n ```", "type": "array", "items": { "$ref": "#/definitions/PermissionEntry" }, "uniqueItems": true }, "platforms": { "description": "Limit which target platforms this capability applies to.\n\n By default all platforms are targeted.\n\n ## Example\n\n `[\"macOS\",\"windows\"]`", "type": [ "array", "null" ], "items": { "$ref": "#/definitions/Target" } } } }, "CapabilityRemote": { "description": "Configuration for remote URLs that are associated with the capability.", "type": "object", "required": [ "urls" ], "properties": { "urls": { "description": "Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).\n\n ## Examples\n\n - \"https://*.mydomain.dev\": allows subdomains of mydomain.dev\n - \"https://mydomain.dev/api/*\": allows any subpath of mydomain.dev/api", "type": "array", "items": { "type": "string" } } } }, "PermissionEntry": { "description": "An entry for a permission value in a [`Capability`] can be either a raw permission [`Identifier`]\n or an object that references a permission and extends its scope.", "anyOf": [ { "description": "Reference a permission or permission set by identifier.", "allOf": [ { "$ref": "#/definitions/Identifier" } ] }, { "description": "Reference a permission or permission set by identifier and extends its scope.", "type": "object", "required": [ "identifier" ], "properties": { "identifier": { "description": "Identifier of the permission or permission set.", "allOf": [ { "$ref": "#/definitions/Identifier" } ] }, "allow": { "description": "Data that defines what is allowed by the scope.", "type": [ "array", "null" ], "items": { "$ref": "#/definitions/Value" } }, "deny": { "description": "Data that defines what is denied by the scope. This should be prioritized by validation logic.", "type": [ "array", "null" ], "items": { "$ref": "#/definitions/Value" } } } } ] }, "Identifier": { "type": "string" }, "Value": { "description": "All supported ACL values.", "anyOf": [ { "description": "Represents a null JSON value.", "type": "null" }, { "description": "Represents a [`bool`].", "type": "boolean" }, { "description": "Represents a valid ACL [`Number`].", "allOf": [ { "$ref": "#/definitions/Number" } ] }, { "description": "Represents a [`String`].", "type": "string" }, { "description": "Represents a list of other [`Value`]s.", "type": "array", "items": { "$ref": "#/definitions/Value" } }, { "description": "Represents a map of [`String`] keys to [`Value`]s.", "type": "object", "additionalProperties": { "$ref": "#/definitions/Value" } } ] }, "Number": { "description": "A valid ACL number.", "anyOf": [ { "description": "Represents an [`i64`].", "type": "integer", "format": "int64" }, { "description": "Represents a [`f64`].", "type": "number", "format": "double" } ] }, "Target": { "description": "Platform target.", "oneOf": [ { "description": "MacOS.", "type": "string", "enum": [ "macOS" ] }, { "description": "Windows.", "type": "string", "enum": [ "windows" ] }, { "description": "Linux.", "type": "string", "enum": [ "linux" ] }, { "description": "Android.", "type": "string", "enum": [ "android" ] }, { "description": "iOS.", "type": "string", "enum": [ "iOS" ] } ] }, "TrayIconConfig": { "description": "Configuration for application tray icon.\n\n See more: ", "type": "object", "required": [ "iconPath" ], "properties": { "id": { "description": "Set an id for this tray icon so you can reference it later, defaults to `main`.", "type": [ "string", "null" ] }, "iconPath": { "description": "Path to the default icon to use for the tray icon.\n\n Note: this stores the image in raw pixels to the final binary,\n so keep the icon size (width and height) small\n or else it's going to bloat your final executable", "type": "string" }, "iconAsTemplate": { "description": "A Boolean value that determines whether the image represents a [template](https://developer.apple.com/documentation/appkit/nsimage/1520017-template?language=objc) image on macOS.", "default": false, "type": "boolean" }, "menuOnLeftClick": { "description": "A Boolean value that determines whether the menu should appear when the tray icon receives a left click on macOS.", "default": true, "type": "boolean" }, "title": { "description": "Title for MacOS tray", "type": [ "string", "null" ] }, "tooltip": { "description": "Tray icon tooltip on Windows and macOS", "type": [ "string", "null" ] } }, "additionalProperties": false }, "BuildConfig": { "description": "The Build configuration object.\n\n See more: ", "type": "object", "properties": { "runner": { "description": "The binary used to build and run the application.", "type": [ "string", "null" ] }, "devUrl": { "description": "The URL to load in development.\n\n This is usually an URL to a dev server, which serves your application assets with hot-reload and HMR.\n Most modern JavaScript bundlers like [Vite](https://vite.dev/guide/) provides a way to start a dev server by default.\n\n If you don't have a dev server or don't want to use one, ignore this option and use [`frontendDist`](BuildConfig::frontend_dist)\n and point to a web assets directory, and Tauri CLI will run its built-in dev server and provide a simple hot-reload experience.", "type": [ "string", "null" ], "format": "uri" }, "frontendDist": { "description": "The path to the application assets (usually the `dist` folder of your javascript bundler)\n or a URL that could be either a custom protocol registered in the tauri app (for example: `myprotocol://`)\n or a remote URL (for example: `https://site.com/app`).\n\n When a path relative to the configuration file is provided,\n it is read recursively and all files are embedded in the application binary.\n Tauri then looks for an `index.html` and serves it as the default entry point for your application.\n\n You can also provide a list of paths to be embedded, which allows granular control over what files are added to the binary.\n In this case, all files are added to the root and you must reference it that way in your HTML files.\n\n When a URL is provided, the application won't have bundled assets\n and the application will load that URL by default.", "anyOf": [ { "$ref": "#/definitions/FrontendDist" }, { "type": "null" } ] }, "beforeDevCommand": { "description": "A shell command to run before `tauri dev` kicks in.\n\n The TAURI_ENV_PLATFORM, TAURI_ENV_ARCH, TAURI_ENV_FAMILY, TAURI_ENV_PLATFORM_VERSION, TAURI_ENV_PLATFORM_TYPE and TAURI_ENV_DEBUG environment variables are set if you perform conditional compilation.", "anyOf": [ { "$ref": "#/definitions/BeforeDevCommand" }, { "type": "null" } ] }, "beforeBuildCommand": { "description": "A shell command to run before `tauri build` kicks in.\n\n The TAURI_ENV_PLATFORM, TAURI_ENV_ARCH, TAURI_ENV_FAMILY, TAURI_ENV_PLATFORM_VERSION, TAURI_ENV_PLATFORM_TYPE and TAURI_ENV_DEBUG environment variables are set if you perform conditional compilation.", "anyOf": [ { "$ref": "#/definitions/HookCommand" }, { "type": "null" } ] }, "beforeBundleCommand": { "description": "A shell command to run before the bundling phase in `tauri build` kicks in.\n\n The TAURI_ENV_PLATFORM, TAURI_ENV_ARCH, TAURI_ENV_FAMILY, TAURI_ENV_PLATFORM_VERSION, TAURI_ENV_PLATFORM_TYPE and TAURI_ENV_DEBUG environment variables are set if you perform conditional compilation.", "anyOf": [ { "$ref": "#/definitions/HookCommand" }, { "type": "null" } ] }, "features": { "description": "Features passed to `cargo` commands.", "type": [ "array", "null" ], "items": { "type": "string" } } }, "additionalProperties": false }, "FrontendDist": { "description": "Defines the URL or assets to embed in the application.", "anyOf": [ { "description": "An external URL that should be used as the default application URL.", "type": "string", "format": "uri" }, { "description": "Path to a directory containing the frontend dist assets.", "type": "string" }, { "description": "An array of files to embed on the app.", "type": "array", "items": { "type": "string" } } ] }, "BeforeDevCommand": { "description": "Describes the shell command to run before `tauri dev`.", "anyOf": [ { "description": "Run the given script with the default options.", "type": "string" }, { "description": "Run the given script with custom options.", "type": "object", "required": [ "script" ], "properties": { "script": { "description": "The script to execute.", "type": "string" }, "cwd": { "description": "The current working directory.", "type": [ "string", "null" ] }, "wait": { "description": "Whether `tauri dev` should wait for the command to finish or not. Defaults to `false`.", "default": false, "type": "boolean" } } } ] }, "HookCommand": { "description": "Describes a shell command to be executed when a CLI hook is triggered.", "anyOf": [ { "description": "Run the given script with the default options.", "type": "string" }, { "description": "Run the given script with custom options.", "type": "object", "required": [ "script" ], "properties": { "script": { "description": "The script to execute.", "type": "string" }, "cwd": { "description": "The current working directory.", "type": [ "string", "null" ] } } } ] }, "BundleConfig": { "description": "Configuration for tauri-bundler.\n\n See more: ", "type": "object", "properties": { "active": { "description": "Whether Tauri should bundle your application or just output the executable.", "default": false, "type": "boolean" }, "targets": { "description": "The bundle targets, currently supports [\"deb\", \"rpm\", \"appimage\", \"nsis\", \"msi\", \"app\", \"dmg\"] or \"all\".", "default": "all", "allOf": [ { "$ref": "#/definitions/BundleTarget" } ] }, "createUpdaterArtifacts": { "description": "Produce updaters and their signatures or not", "default": false, "allOf": [ { "$ref": "#/definitions/Updater" } ] }, "publisher": { "description": "The application's publisher. Defaults to the second element in the identifier string.\n Currently maps to the Manufacturer property of the Windows Installer.", "type": [ "string", "null" ] }, "homepage": { "description": "A url to the home page of your application. If unset, will\n fallback to `homepage` defined in `Cargo.toml`.\n\n Supported bundle targets: `deb`, `rpm`, `nsis` and `msi`.", "type": [ "string", "null" ] }, "icon": { "description": "The app's icons", "default": [], "type": "array", "items": { "type": "string" } }, "resources": { "description": "App resources to bundle.\n Each resource is a path to a file or directory.\n Glob patterns are supported.", "anyOf": [ { "$ref": "#/definitions/BundleResources" }, { "type": "null" } ] }, "copyright": { "description": "A copyright string associated with your application.", "type": [ "string", "null" ] }, "license": { "description": "The package's license identifier to be included in the appropriate bundles.\n If not set, defaults to the license from the Cargo.toml file.", "type": [ "string", "null" ] }, "licenseFile": { "description": "The path to the license file to be included in the appropriate bundles.", "type": [ "string", "null" ] }, "category": { "description": "The application kind.\n\n Should be one of the following:\n Business, DeveloperTool, Education, Entertainment, Finance, Game, ActionGame, AdventureGame, ArcadeGame, BoardGame, CardGame, CasinoGame, DiceGame, EducationalGame, FamilyGame, KidsGame, MusicGame, PuzzleGame, RacingGame, RolePlayingGame, SimulationGame, SportsGame, StrategyGame, TriviaGame, WordGame, GraphicsAndDesign, HealthcareAndFitness, Lifestyle, Medical, Music, News, Photography, Productivity, Reference, SocialNetworking, Sports, Travel, Utility, Video, Weather.", "type": [ "string", "null" ] }, "fileAssociations": { "description": "File associations to application.", "type": [ "array", "null" ], "items": { "$ref": "#/definitions/FileAssociation" } }, "shortDescription": { "description": "A short description of your application.", "type": [ "string", "null" ] }, "longDescription": { "description": "A longer, multi-line description of the application.", "type": [ "string", "null" ] }, "externalBin": { "description": "A list of—either absolute or relative—paths to binaries to embed with your application.\n\n Note that Tauri will look for system-specific binaries following the pattern \"binary-name{-target-triple}{.system-extension}\".\n\n E.g. for the external binary \"my-binary\", Tauri looks for:\n\n - \"my-binary-x86_64-pc-windows-msvc.exe\" for Windows\n - \"my-binary-x86_64-apple-darwin\" for macOS\n - \"my-binary-x86_64-unknown-linux-gnu\" for Linux\n\n so don't forget to provide binaries for all targeted platforms.", "type": [ "array", "null" ], "items": { "type": "string" } }, "windows": { "description": "Configuration for the Windows bundles.", "default": { "allowDowngrades": true, "certificateThumbprint": null, "digestAlgorithm": null, "nsis": null, "signCommand": null, "timestampUrl": null, "tsp": false, "webviewInstallMode": { "silent": true, "type": "downloadBootstrapper" }, "wix": null }, "allOf": [ { "$ref": "#/definitions/WindowsConfig" } ] }, "linux": { "description": "Configuration for the Linux bundles.", "default": { "appimage": { "bundleMediaFramework": false, "files": {} }, "deb": { "files": {} }, "rpm": { "epoch": 0, "files": {}, "release": "1" } }, "allOf": [ { "$ref": "#/definitions/LinuxConfig" } ] }, "macOS": { "description": "Configuration for the macOS bundles.", "default": { "dmg": { "appPosition": { "x": 180, "y": 170 }, "applicationFolderPosition": { "x": 480, "y": 170 }, "windowSize": { "height": 400, "width": 660 } }, "files": {}, "hardenedRuntime": true, "minimumSystemVersion": "10.13" }, "allOf": [ { "$ref": "#/definitions/MacConfig" } ] }, "iOS": { "description": "iOS configuration.", "default": { "minimumSystemVersion": "13.0" }, "allOf": [ { "$ref": "#/definitions/IosConfig" } ] }, "android": { "description": "Android configuration.", "default": { "minSdkVersion": 24 }, "allOf": [ { "$ref": "#/definitions/AndroidConfig" } ] } }, "additionalProperties": false }, "BundleTarget": { "description": "Targets to bundle. Each value is case insensitive.", "anyOf": [ { "description": "Bundle all targets.", "enum": [ "all" ] }, { "description": "A list of bundle targets.", "type": "array", "items": { "$ref": "#/definitions/BundleType" } }, { "description": "A single bundle target.", "allOf": [ { "$ref": "#/definitions/BundleType" } ] } ] }, "BundleType": { "description": "A bundle referenced by tauri-bundler.", "oneOf": [ { "description": "The debian bundle (.deb).", "type": "string", "enum": [ "deb" ] }, { "description": "The RPM bundle (.rpm).", "type": "string", "enum": [ "rpm" ] }, { "description": "The AppImage bundle (.appimage).", "type": "string", "enum": [ "appimage" ] }, { "description": "The Microsoft Installer bundle (.msi).", "type": "string", "enum": [ "msi" ] }, { "description": "The NSIS bundle (.exe).", "type": "string", "enum": [ "nsis" ] }, { "description": "The macOS application bundle (.app).", "type": "string", "enum": [ "app" ] }, { "description": "The Apple Disk Image bundle (.dmg).", "type": "string", "enum": [ "dmg" ] } ] }, "Updater": { "description": "Updater type", "anyOf": [ { "description": "Generates lagacy zipped v1 compatible updaters", "allOf": [ { "$ref": "#/definitions/V1Compatible" } ] }, { "description": "Produce updaters and their signatures or not", "type": "boolean" } ] }, "V1Compatible": { "description": "Generates lagacy zipped v1 compatible updaters", "oneOf": [ { "description": "Generates lagacy zipped v1 compatible updaters", "type": "string", "enum": [ "v1Compatible" ] } ] }, "BundleResources": { "description": "Definition for bundle resources.\n Can be either a list of paths to include or a map of source to target paths.", "anyOf": [ { "description": "A list of paths to include.", "type": "array", "items": { "type": "string" } }, { "description": "A map of source to target paths.", "type": "object", "additionalProperties": { "type": "string" } } ] }, "FileAssociation": { "description": "File association", "type": "object", "required": [ "ext" ], "properties": { "ext": { "description": "File extensions to associate with this app. e.g. 'png'", "type": "array", "items": { "$ref": "#/definitions/AssociationExt" } }, "name": { "description": "The name. Maps to `CFBundleTypeName` on macOS. Default to `ext[0]`", "type": [ "string", "null" ] }, "description": { "description": "The association description. Windows-only. It is displayed on the `Type` column on Windows Explorer.", "type": [ "string", "null" ] }, "role": { "description": "The app's role with respect to the type. Maps to `CFBundleTypeRole` on macOS.", "default": "Editor", "allOf": [ { "$ref": "#/definitions/BundleTypeRole" } ] }, "mimeType": { "description": "The mime-type e.g. 'image/png' or 'text/plain'. Linux-only.", "type": [ "string", "null" ] }, "rank": { "description": "The ranking of this app among apps that declare themselves as editors or viewers of the given file type. Maps to `LSHandlerRank` on macOS.", "default": "Default", "allOf": [ { "$ref": "#/definitions/HandlerRank" } ] } }, "additionalProperties": false }, "AssociationExt": { "description": "An extension for a [`FileAssociation`].\n\n A leading `.` is automatically stripped.", "type": "string" }, "BundleTypeRole": { "description": "macOS-only. Corresponds to CFBundleTypeRole", "oneOf": [ { "description": "CFBundleTypeRole.Editor. Files can be read and edited.", "type": "string", "enum": [ "Editor" ] }, { "description": "CFBundleTypeRole.Viewer. Files can be read.", "type": "string", "enum": [ "Viewer" ] }, { "description": "CFBundleTypeRole.Shell", "type": "string", "enum": [ "Shell" ] }, { "description": "CFBundleTypeRole.QLGenerator", "type": "string", "enum": [ "QLGenerator" ] }, { "description": "CFBundleTypeRole.None", "type": "string", "enum": [ "None" ] } ] }, "HandlerRank": { "description": "Corresponds to LSHandlerRank", "oneOf": [ { "description": "LSHandlerRank.Default. This app is an opener of files of this type; this value is also used if no rank is specified.", "type": "string", "enum": [ "Default" ] }, { "description": "LSHandlerRank.Owner. This app is the primary creator of files of this type.", "type": "string", "enum": [ "Owner" ] }, { "description": "LSHandlerRank.Alternate. This app is a secondary viewer of files of this type.", "type": "string", "enum": [ "Alternate" ] }, { "description": "LSHandlerRank.None. This app is never selected to open files of this type, but it accepts drops of files of this type.", "type": "string", "enum": [ "None" ] } ] }, "WindowsConfig": { "description": "Windows bundler configuration.\n\n See more: ", "type": "object", "properties": { "digestAlgorithm": { "description": "Specifies the file digest algorithm to use for creating file signatures.\n Required for code signing. SHA-256 is recommended.", "type": [ "string", "null" ] }, "certificateThumbprint": { "description": "Specifies the SHA1 hash of the signing certificate.", "type": [ "string", "null" ] }, "timestampUrl": { "description": "Server to use during timestamping.", "type": [ "string", "null" ] }, "tsp": { "description": "Whether to use Time-Stamp Protocol (TSP, a.k.a. RFC 3161) for the timestamp server. Your code signing provider may\n use a TSP timestamp server, like e.g. SSL.com does. If so, enable TSP by setting to true.", "default": false, "type": "boolean" }, "webviewInstallMode": { "description": "The installation mode for the Webview2 runtime.", "default": { "silent": true, "type": "downloadBootstrapper" }, "allOf": [ { "$ref": "#/definitions/WebviewInstallMode" } ] }, "allowDowngrades": { "description": "Validates a second app installation, blocking the user from installing an older version if set to `false`.\n\n For instance, if `1.2.1` is installed, the user won't be able to install app version `1.2.0` or `1.1.5`.\n\n The default value of this flag is `true`.", "default": true, "type": "boolean" }, "wix": { "description": "Configuration for the MSI generated with WiX.", "anyOf": [ { "$ref": "#/definitions/WixConfig" }, { "type": "null" } ] }, "nsis": { "description": "Configuration for the installer generated with NSIS.", "anyOf": [ { "$ref": "#/definitions/NsisConfig" }, { "type": "null" } ] }, "signCommand": { "description": "Specify a custom command to sign the binaries.\n This command needs to have a `%1` in args which is just a placeholder for the binary path,\n which we will detect and replace before calling the command.\n\n By Default we use `signtool.exe` which can be found only on Windows so\n if you are on another platform and want to cross-compile and sign you will\n need to use another tool like `osslsigncode`.", "anyOf": [ { "$ref": "#/definitions/CustomSignCommandConfig" }, { "type": "null" } ] } }, "additionalProperties": false }, "WebviewInstallMode": { "description": "Install modes for the Webview2 runtime.\n Note that for the updater bundle [`Self::DownloadBootstrapper`] is used.\n\n For more information see .", "oneOf": [ { "description": "Do not install the Webview2 as part of the Windows Installer.", "type": "object", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "skip" ] } }, "additionalProperties": false }, { "description": "Download the bootstrapper and run it.\n Requires an internet connection.\n Results in a smaller installer size, but is not recommended on Windows 7.", "type": "object", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "downloadBootstrapper" ] }, "silent": { "description": "Instructs the installer to run the bootstrapper in silent mode. Defaults to `true`.", "default": true, "type": "boolean" } }, "additionalProperties": false }, { "description": "Embed the bootstrapper and run it.\n Requires an internet connection.\n Increases the installer size by around 1.8MB, but offers better support on Windows 7.", "type": "object", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "embedBootstrapper" ] }, "silent": { "description": "Instructs the installer to run the bootstrapper in silent mode. Defaults to `true`.", "default": true, "type": "boolean" } }, "additionalProperties": false }, { "description": "Embed the offline installer and run it.\n Does not require an internet connection.\n Increases the installer size by around 127MB.", "type": "object", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "offlineInstaller" ] }, "silent": { "description": "Instructs the installer to run the installer in silent mode. Defaults to `true`.", "default": true, "type": "boolean" } }, "additionalProperties": false }, { "description": "Embed a fixed webview2 version and use it at runtime.\n Increases the installer size by around 180MB.", "type": "object", "required": [ "path", "type" ], "properties": { "type": { "type": "string", "enum": [ "fixedRuntime" ] }, "path": { "description": "The path to the fixed runtime to use.\n\n The fixed version can be downloaded [on the official website](https://developer.microsoft.com/en-us/microsoft-edge/webview2/#download-section).\n The `.cab` file must be extracted to a folder and this folder path must be defined on this field.", "type": "string" } }, "additionalProperties": false } ] }, "WixConfig": { "description": "Configuration for the MSI bundle using WiX.\n\n See more: ", "type": "object", "properties": { "language": { "description": "The installer languages to build. See .", "default": "en-US", "allOf": [ { "$ref": "#/definitions/WixLanguage" } ] }, "template": { "description": "A custom .wxs template to use.", "type": [ "string", "null" ] }, "fragmentPaths": { "description": "A list of paths to .wxs files with WiX fragments to use.", "default": [], "type": "array", "items": { "type": "string" } }, "componentGroupRefs": { "description": "The ComponentGroup element ids you want to reference from the fragments.", "default": [], "type": "array", "items": { "type": "string" } }, "componentRefs": { "description": "The Component element ids you want to reference from the fragments.", "default": [], "type": "array", "items": { "type": "string" } }, "featureGroupRefs": { "description": "The FeatureGroup element ids you want to reference from the fragments.", "default": [], "type": "array", "items": { "type": "string" } }, "featureRefs": { "description": "The Feature element ids you want to reference from the fragments.", "default": [], "type": "array", "items": { "type": "string" } }, "mergeRefs": { "description": "The Merge element ids you want to reference from the fragments.", "default": [], "type": "array", "items": { "type": "string" } }, "enableElevatedUpdateTask": { "description": "Create an elevated update task within Windows Task Scheduler.", "default": false, "type": "boolean" }, "bannerPath": { "description": "Path to a bitmap file to use as the installation user interface banner.\n This bitmap will appear at the top of all but the first page of the installer.\n\n The required dimensions are 493px × 58px.", "type": [ "string", "null" ] }, "dialogImagePath": { "description": "Path to a bitmap file to use on the installation user interface dialogs.\n It is used on the welcome and completion dialogs.\n The required dimensions are 493px × 312px.", "type": [ "string", "null" ] }, "fipsCompliant": { "description": "Enables FIPS compliant algorithms.", "default": null, "type": [ "boolean", "null" ] } }, "additionalProperties": false }, "WixLanguage": { "description": "The languages to build using WiX.", "anyOf": [ { "description": "A single language to build, without configuration.", "type": "string" }, { "description": "A list of languages to build, without configuration.", "type": "array", "items": { "type": "string" } }, { "description": "A map of languages and its configuration.", "type": "object", "additionalProperties": { "$ref": "#/definitions/WixLanguageConfig" } } ] }, "WixLanguageConfig": { "description": "Configuration for a target language for the WiX build.\n\n See more: ", "type": "object", "properties": { "localePath": { "description": "The path to a locale (`.wxl`) file. See .", "type": [ "string", "null" ] } }, "additionalProperties": false }, "NsisConfig": { "description": "Configuration for the Installer bundle using NSIS.", "type": "object", "properties": { "template": { "description": "A custom .nsi template to use.", "type": [ "string", "null" ] }, "headerImage": { "description": "The path to a bitmap file to display on the header of installers pages.\n\n The recommended dimensions are 150px x 57px.", "type": [ "string", "null" ] }, "sidebarImage": { "description": "The path to a bitmap file for the Welcome page and the Finish page.\n\n The recommended dimensions are 164px x 314px.", "type": [ "string", "null" ] }, "installerIcon": { "description": "The path to an icon file used as the installer icon.", "type": [ "string", "null" ] }, "installMode": { "description": "Whether the installation will be for all users or just the current user.", "default": "currentUser", "allOf": [ { "$ref": "#/definitions/NSISInstallerMode" } ] }, "languages": { "description": "A list of installer languages.\n By default the OS language is used. If the OS language is not in the list of languages, the first language will be used.\n To allow the user to select the language, set `display_language_selector` to `true`.\n\n See for the complete list of languages.", "type": [ "array", "null" ], "items": { "type": "string" } }, "customLanguageFiles": { "description": "A key-value pair where the key is the language and the\n value is the path to a custom `.nsh` file that holds the translated text for tauri's custom messages.\n\n See for an example `.nsh` file.\n\n **Note**: the key must be a valid NSIS language and it must be added to [`NsisConfig`] languages array,", "type": [ "object", "null" ], "additionalProperties": { "type": "string" } }, "displayLanguageSelector": { "description": "Whether to display a language selector dialog before the installer and uninstaller windows are rendered or not.\n By default the OS language is selected, with a fallback to the first language in the `languages` array.", "default": false, "type": "boolean" }, "compression": { "description": "Set the compression algorithm used to compress files in the installer.\n\n See ", "default": "lzma", "allOf": [ { "$ref": "#/definitions/NsisCompression" } ] }, "startMenuFolder": { "description": "Set the folder name for the start menu shortcut.\n\n Use this option if you have multiple apps and wish to group their shortcuts under one folder\n or if you generally prefer to set your shortcut inside a folder.\n\n Examples:\n - `AwesomePublisher`, shortcut will be placed in `%AppData%\\Microsoft\\Windows\\Start Menu\\Programs\\AwesomePublisher\\.lnk`\n - If unset, shortcut will be placed in `%AppData%\\Microsoft\\Windows\\Start Menu\\Programs\\.lnk`", "type": [ "string", "null" ] }, "installerHooks": { "description": "A path to a `.nsh` file that contains special NSIS macros to be hooked into the\n main installer.nsi script.\n\n Supported hooks are:\n - `NSIS_HOOK_PREINSTALL`: This hook runs before copying files, setting registry key values and creating shortcuts.\n - `NSIS_HOOK_POSTINSTALL`: This hook runs after the installer has finished copying all files, setting the registry keys and created shortcuts.\n - `NSIS_HOOK_PREUNINSTALL`: This hook runs before removing any files, registry keys and shortcuts.\n - `NSIS_HOOK_POSTUNINSTALL`: This hook runs after files, registry keys and shortcuts have been removed.\n\n\n ### Example\n\n ```nsh\n !macro NSIS_HOOK_PREINSTALL\n MessageBox MB_OK \"PreInstall\"\n !macroend\n\n !macro NSIS_HOOK_POSTINSTALL\n MessageBox MB_OK \"PostInstall\"\n !macroend\n\n !macro NSIS_HOOK_PREUNINSTALL\n MessageBox MB_OK \"PreUnInstall\"\n !macroend\n\n !macro NSIS_HOOK_POSTUNINSTALL\n MessageBox MB_OK \"PostUninstall\"\n !macroend\n\n ```", "type": [ "string", "null" ] }, "minimumWebview2Version": { "description": "Try to ensure that the WebView2 version is equal to or newer than this version,\n if the user's WebView2 is older than this version,\n the installer will try to trigger a WebView2 update.", "type": [ "string", "null" ] } }, "additionalProperties": false }, "NSISInstallerMode": { "description": "Install Modes for the NSIS installer.", "oneOf": [ { "description": "Default mode for the installer.\n\n Install the app by default in a directory that doesn't require Administrator access.\n\n Installer metadata will be saved under the `HKCU` registry path.", "type": "string", "enum": [ "currentUser" ] }, { "description": "Install the app by default in the `Program Files` folder directory requires Administrator\n access for the installation.\n\n Installer metadata will be saved under the `HKLM` registry path.", "type": "string", "enum": [ "perMachine" ] }, { "description": "Combines both modes and allows the user to choose at install time\n whether to install for the current user or per machine. Note that this mode\n will require Administrator access even if the user wants to install it for the current user only.\n\n Installer metadata will be saved under the `HKLM` or `HKCU` registry path based on the user's choice.", "type": "string", "enum": [ "both" ] } ] }, "NsisCompression": { "description": "Compression algorithms used in the NSIS installer.\n\n See ", "oneOf": [ { "description": "ZLIB uses the deflate algorithm, it is a quick and simple method. With the default compression level it uses about 300 KB of memory.", "type": "string", "enum": [ "zlib" ] }, { "description": "BZIP2 usually gives better compression ratios than ZLIB, but it is a bit slower and uses more memory. With the default compression level it uses about 4 MB of memory.", "type": "string", "enum": [ "bzip2" ] }, { "description": "LZMA (default) is a new compression method that gives very good compression ratios. The decompression speed is high (10-20 MB/s on a 2 GHz CPU), the compression speed is lower. The memory size that will be used for decompression is the dictionary size plus a few KBs, the default is 8 MB.", "type": "string", "enum": [ "lzma" ] }, { "description": "Disable compression", "type": "string", "enum": [ "none" ] } ] }, "CustomSignCommandConfig": { "description": "Custom Signing Command configuration.", "anyOf": [ { "description": "A string notation of the script to execute.\n\n \"%1\" will be replaced with the path to the binary to be signed.\n\n This is a simpler notation for the command.\n Tauri will split the string with `' '` and use the first element as the command name and the rest as arguments.\n\n If you need to use whitespace in the command or arguments, use the object notation [`Self::ScriptWithOptions`].", "type": "string" }, { "description": "An object notation of the command.\n\n This is more complex notation for the command but\n this allows you to use whitespace in the command and arguments.", "type": "object", "required": [ "args", "cmd" ], "properties": { "cmd": { "description": "The command to run to sign the binary.", "type": "string" }, "args": { "description": "The arguments to pass to the command.\n\n \"%1\" will be replaced with the path to the binary to be signed.", "type": "array", "items": { "type": "string" } } }, "additionalProperties": false } ] }, "LinuxConfig": { "description": "Configuration for Linux bundles.\n\n See more: ", "type": "object", "properties": { "appimage": { "description": "Configuration for the AppImage bundle.", "default": { "bundleMediaFramework": false, "files": {} }, "allOf": [ { "$ref": "#/definitions/AppImageConfig" } ] }, "deb": { "description": "Configuration for the Debian bundle.", "default": { "files": {} }, "allOf": [ { "$ref": "#/definitions/DebConfig" } ] }, "rpm": { "description": "Configuration for the RPM bundle.", "default": { "epoch": 0, "files": {}, "release": "1" }, "allOf": [ { "$ref": "#/definitions/RpmConfig" } ] } }, "additionalProperties": false }, "AppImageConfig": { "description": "Configuration for AppImage bundles.\n\n See more: ", "type": "object", "properties": { "bundleMediaFramework": { "description": "Include additional gstreamer dependencies needed for audio and video playback.\n This increases the bundle size by ~15-35MB depending on your build system.", "default": false, "type": "boolean" }, "files": { "description": "The files to include in the Appimage Binary.", "default": {}, "type": "object", "additionalProperties": { "type": "string" } } }, "additionalProperties": false }, "DebConfig": { "description": "Configuration for Debian (.deb) bundles.\n\n See more: ", "type": "object", "properties": { "depends": { "description": "The list of deb dependencies your application relies on.", "type": [ "array", "null" ], "items": { "type": "string" } }, "provides": { "description": "The list of dependencies the package provides.", "type": [ "array", "null" ], "items": { "type": "string" } }, "conflicts": { "description": "The list of package conflicts.", "type": [ "array", "null" ], "items": { "type": "string" } }, "replaces": { "description": "The list of package replaces.", "type": [ "array", "null" ], "items": { "type": "string" } }, "files": { "description": "The files to include on the package.", "default": {}, "type": "object", "additionalProperties": { "type": "string" } }, "section": { "description": "Define the section in Debian Control file. See : https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections", "type": [ "string", "null" ] }, "priority": { "description": "Change the priority of the Debian Package. By default, it is set to `optional`.\n Recognized Priorities as of now are : `required`, `important`, `standard`, `optional`, `extra`", "type": [ "string", "null" ] }, "changelog": { "description": "Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See\n ", "type": [ "string", "null" ] }, "desktopTemplate": { "description": "Path to a custom desktop file Handlebars template.\n\n Available variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.", "type": [ "string", "null" ] }, "preInstallScript": { "description": "Path to script that will be executed before the package is unpacked. See\n ", "type": [ "string", "null" ] }, "postInstallScript": { "description": "Path to script that will be executed after the package is unpacked. See\n ", "type": [ "string", "null" ] }, "preRemoveScript": { "description": "Path to script that will be executed before the package is removed. See\n ", "type": [ "string", "null" ] }, "postRemoveScript": { "description": "Path to script that will be executed after the package is removed. See\n ", "type": [ "string", "null" ] } }, "additionalProperties": false }, "RpmConfig": { "description": "Configuration for RPM bundles.", "type": "object", "properties": { "depends": { "description": "The list of RPM dependencies your application relies on.", "type": [ "array", "null" ], "items": { "type": "string" } }, "provides": { "description": "The list of RPM dependencies your application provides.", "type": [ "array", "null" ], "items": { "type": "string" } }, "conflicts": { "description": "The list of RPM dependencies your application conflicts with. They must not be present\n in order for the package to be installed.", "type": [ "array", "null" ], "items": { "type": "string" } }, "obsoletes": { "description": "The list of RPM dependencies your application supersedes - if this package is installed,\n packages listed as “obsoletes” will be automatically removed (if they are present).", "type": [ "array", "null" ], "items": { "type": "string" } }, "release": { "description": "The RPM release tag.", "default": "1", "type": "string" }, "epoch": { "description": "The RPM epoch.", "default": 0, "type": "integer", "format": "uint32", "minimum": 0.0 }, "files": { "description": "The files to include on the package.", "default": {}, "type": "object", "additionalProperties": { "type": "string" } }, "desktopTemplate": { "description": "Path to a custom desktop file Handlebars template.\n\n Available variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.", "type": [ "string", "null" ] }, "preInstallScript": { "description": "Path to script that will be executed before the package is unpacked. See\n ", "type": [ "string", "null" ] }, "postInstallScript": { "description": "Path to script that will be executed after the package is unpacked. See\n ", "type": [ "string", "null" ] }, "preRemoveScript": { "description": "Path to script that will be executed before the package is removed. See\n ", "type": [ "string", "null" ] }, "postRemoveScript": { "description": "Path to script that will be executed after the package is removed. See\n ", "type": [ "string", "null" ] } }, "additionalProperties": false }, "MacConfig": { "description": "Configuration for the macOS bundles.\n\n See more: ", "type": "object", "properties": { "frameworks": { "description": "A list of strings indicating any macOS X frameworks that need to be bundled with the application.\n\n If a name is used, \".framework\" must be omitted and it will look for standard install locations. You may also use a path to a specific framework.", "type": [ "array", "null" ], "items": { "type": "string" } }, "files": { "description": "The files to include in the application relative to the Contents directory.", "default": {}, "type": "object", "additionalProperties": { "type": "string" } }, "minimumSystemVersion": { "description": "A version string indicating the minimum macOS X version that the bundled application supports. Defaults to `10.13`.\n\n Setting it to `null` completely removes the `LSMinimumSystemVersion` field on the bundle's `Info.plist`\n and the `MACOSX_DEPLOYMENT_TARGET` environment variable.\n\n An empty string is considered an invalid value so the default value is used.", "default": "10.13", "type": [ "string", "null" ] }, "exceptionDomain": { "description": "Allows your application to communicate with the outside world.\n It should be a lowercase, without port and protocol domain name.", "type": [ "string", "null" ] }, "signingIdentity": { "description": "Identity to use for code signing.", "type": [ "string", "null" ] }, "hardenedRuntime": { "description": "Whether the codesign should enable [hardened runtime] (for executables) or not.\n\n [hardened runtime]: ", "default": true, "type": "boolean" }, "providerShortName": { "description": "Provider short name for notarization.", "type": [ "string", "null" ] }, "entitlements": { "description": "Path to the entitlements file.", "type": [ "string", "null" ] }, "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" } ] } }, "additionalProperties": false }, "DmgConfig": { "description": "Configuration for Apple Disk Image (.dmg) bundles.\n\n See more: ", "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 }, "IosConfig": { "description": "General configuration for the iOS target.", "type": "object", "properties": { "template": { "description": "A custom [XcodeGen] project.yml template to use.\n\n [XcodeGen]: ", "type": [ "string", "null" ] }, "frameworks": { "description": "A list of strings indicating any iOS frameworks that need to be bundled with the application.\n\n Note that you need to recreate the iOS project for the changes to be applied.", "type": [ "array", "null" ], "items": { "type": "string" } }, "developmentTeam": { "description": "The development team. This value is required for iOS development because code signing is enforced.\n The `APPLE_DEVELOPMENT_TEAM` environment variable can be set to overwrite it.", "type": [ "string", "null" ] }, "minimumSystemVersion": { "description": "A version string indicating the minimum iOS version that the bundled application supports. Defaults to `13.0`.\n\n Maps to the IPHONEOS_DEPLOYMENT_TARGET value.", "default": "13.0", "type": "string" } }, "additionalProperties": false }, "AndroidConfig": { "description": "General configuration for the iOS target.", "type": "object", "properties": { "minSdkVersion": { "description": "The minimum API level required for the application to run.\n The Android system will prevent the user from installing the application if the system's API level is lower than the value specified.", "default": 24, "type": "integer", "format": "uint32", "minimum": 0.0 }, "versionCode": { "description": "The version code of the application.\n It is limited to 2,100,000,000 as per Google Play Store requirements.\n\n By default we use your configured version and perform the following math:\n versionCode = version.major * 1000000 + version.minor * 1000 + version.patch", "type": [ "integer", "null" ], "format": "uint32", "maximum": 2100000000.0, "minimum": 1.0 } }, "additionalProperties": false }, "PluginConfig": { "description": "The plugin configs holds a HashMap mapping a plugin name to its configuration object.\n\n See more: ", "type": "object", "additionalProperties": true } } } ================================================ FILE: crates/tauri-cli/tauri.gitignore ================================================ node_modules/ target/ .DS_Store ================================================ FILE: crates/tauri-cli/templates/app/src-tauri/.gitignore ================================================ # Generated by Cargo # will have compiled files and executables /target/ /gen/schemas ================================================ FILE: crates/tauri-cli/templates/app/src-tauri/Cargo.crate-manifest ================================================ [package] name = "app" version = "0.1.0" description = "A Tauri App" authors = ["you"] license = "" repository = "" edition = "2021" rust-version = "1.77.2" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] name = "app_lib" crate-type = ["staticlib", "cdylib", "rlib"] [build-dependencies] tauri-build = {{ tauri_build_dep }} [dependencies] serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } log = "0.4" tauri = {{ tauri_dep }} tauri-plugin-log = "2" {{#if patch_tauri_dep}} [patch.crates-io] tauri = {{ tauri_dep }} tauri-utils = {{ tauri_utils_dep }} tauri-plugin = {{ tauri_plugin_dep }} {{/if}} ================================================ FILE: crates/tauri-cli/templates/app/src-tauri/build.rs ================================================ fn main() { tauri_build::build() } ================================================ FILE: crates/tauri-cli/templates/app/src-tauri/capabilities/default.json ================================================ { "$schema": "../gen/schemas/desktop-schema.json", "identifier": "default", "description": "enables the default permissions", "windows": [ "main" ], "permissions": [ "core:default" ] } ================================================ FILE: crates/tauri-cli/templates/app/src-tauri/src/lib.rs ================================================ #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .setup(|app| { if cfg!(debug_assertions) { app.handle().plugin( tauri_plugin_log::Builder::default() .level(log::LevelFilter::Info) .build(), )?; } Ok(()) }) .run(tauri::generate_context!()) .expect("error while running tauri application"); } ================================================ FILE: crates/tauri-cli/templates/app/src-tauri/src/main.rs ================================================ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] fn main() { app_lib::run(); } ================================================ FILE: crates/tauri-cli/templates/app/src-tauri/tauri.conf.json ================================================ {{ tauri_config }} ================================================ FILE: crates/tauri-cli/templates/mobile/android/.editorconfig ================================================ # EditorConfig is awesome: https://EditorConfig.org # top-most EditorConfig file root = true [*] indent_style = space indent_size = 2 end_of_line = lf charset = utf-8 trim_trailing_whitespace = false insert_final_newline = false ================================================ FILE: crates/tauri-cli/templates/mobile/android/.gitignore ================================================ *.iml .gradle /local.properties /.idea/caches /.idea/libraries /.idea/modules.xml /.idea/workspace.xml /.idea/navEditor.xml /.idea/assetWizardSettings.xml .DS_Store build /captures .externalNativeBuild .cxx local.properties key.properties keystore.properties /.tauri /tauri.settings.gradle ================================================ FILE: crates/tauri-cli/templates/mobile/android/app/.gitignore ================================================ /src/main/**/generated /src/main/jniLibs/**/*.so /src/main/assets/tauri.conf.json /tauri.build.gradle.kts /proguard-tauri.pro /tauri.properties ================================================ FILE: crates/tauri-cli/templates/mobile/android/app/build.gradle.kts ================================================ import java.util.Properties plugins { id("com.android.application") id("org.jetbrains.kotlin.android") id("rust") {{~#each android-app-plugins}} id("{{this}}"){{/each}} } val tauriProperties = Properties().apply { val propFile = file("tauri.properties") if (propFile.exists()) { propFile.inputStream().use { load(it) } } } android { compileSdk = 36 namespace = "{{app.identifier}}" defaultConfig { manifestPlaceholders["usesCleartextTraffic"] = "false" applicationId = "{{app.identifier}}" minSdk = {{android.min-sdk-version}} targetSdk = 36 versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt() versionName = tauriProperties.getProperty("tauri.android.versionName", "1.0") } buildTypes { getByName("debug") { manifestPlaceholders["usesCleartextTraffic"] = "true" isDebuggable = true isJniDebuggable = true isMinifyEnabled = false packaging { {{~#each abi-list}} jniLibs.keepDebugSymbols.add("*/{{this}}/*.so") {{/each}} } } getByName("release") { isMinifyEnabled = true proguardFiles( *fileTree(".") { include("**/*.pro") } .plus(getDefaultProguardFile("proguard-android-optimize.txt")) .toList().toTypedArray() ) } } kotlinOptions { jvmTarget = "1.8" } buildFeatures { buildConfig = true } } rust { rootDirRel = "{{root-dir-rel}}" } dependencies { {{~#each android-app-dependencies-platform}} implementation(platform("{{this}}")){{/each}} {{~#each android-app-dependencies}} implementation("{{this}}"){{/each}} implementation("androidx.webkit:webkit:1.14.0") implementation("androidx.appcompat:appcompat:1.7.1") implementation("androidx.activity:activity-ktx:1.10.1") implementation("com.google.android.material:material:1.12.0") testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.4") androidTestImplementation("androidx.test.espresso:espresso-core:3.5.0") } apply(from = "tauri.build.gradle.kts") ================================================ FILE: crates/tauri-cli/templates/mobile/android/app/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the # proguardFiles setting in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} # Uncomment this to preserve the line number information for # debugging stack traces. #-keepattributes SourceFile,LineNumberTable # If you keep the line number information, uncomment this to # hide the original source file name. #-renamesourcefileattribute SourceFile ================================================ FILE: crates/tauri-cli/templates/mobile/android/app/src/main/AndroidManifest.xml ================================================ ================================================ FILE: crates/tauri-cli/templates/mobile/android/app/src/main/MainActivity.kt ================================================ package {{escape-kotlin-keyword app.identifier}} import android.os.Bundle import androidx.activity.enableEdgeToEdge class MainActivity : TauriActivity() { override fun onCreate(savedInstanceState: Bundle?) { enableEdgeToEdge() super.onCreate(savedInstanceState) } } ================================================ FILE: crates/tauri-cli/templates/mobile/android/app/src/main/res/drawable/ic_launcher_background.xml ================================================ ================================================ FILE: crates/tauri-cli/templates/mobile/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml ================================================ ================================================ FILE: crates/tauri-cli/templates/mobile/android/app/src/main/res/layout/activity_main.xml ================================================ ================================================ FILE: crates/tauri-cli/templates/mobile/android/app/src/main/res/values/colors.xml ================================================ #FFBB86FC #FF6200EE #FF3700B3 #FF03DAC5 #FF018786 #FF000000 #FFFFFFFF ================================================ FILE: crates/tauri-cli/templates/mobile/android/app/src/main/res/values/strings.xml ================================================ {{app.stylized-name}} {{app.stylized-name}} ================================================ FILE: crates/tauri-cli/templates/mobile/android/app/src/main/res/values/themes.xml ================================================ ================================================ FILE: crates/tauri-cli/templates/mobile/android/app/src/main/res/values-night/themes.xml ================================================ ================================================ FILE: crates/tauri-cli/templates/mobile/android/app/src/main/res/xml/file_paths.xml ================================================ ================================================ FILE: crates/tauri-cli/templates/mobile/android/build.gradle.kts ================================================ buildscript { repositories { google() mavenCentral() } dependencies { classpath("com.android.tools.build:gradle:8.11.0") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.25") {{~#each android-project-dependencies}} classpath("{{this}}"){{/each}} } } allprojects { repositories { google() mavenCentral() } } tasks.register("clean").configure { delete("build") } ================================================ FILE: crates/tauri-cli/templates/mobile/android/buildSrc/build.gradle.kts ================================================ plugins { `kotlin-dsl` } gradlePlugin { plugins { create("pluginsForCoolKids") { id = "rust" implementationClass = "RustPlugin" } } } repositories { google() mavenCentral() } dependencies { compileOnly(gradleApi()) implementation("com.android.tools.build:gradle:8.11.0") } ================================================ FILE: crates/tauri-cli/templates/mobile/android/buildSrc/src/main/kotlin/BuildTask.kt ================================================ import java.io.File import org.apache.tools.ant.taskdefs.condition.Os import org.gradle.api.DefaultTask import org.gradle.api.GradleException import org.gradle.api.logging.LogLevel import org.gradle.api.tasks.Input import org.gradle.api.tasks.TaskAction open class BuildTask : DefaultTask() { @Input var rootDirRel: String? = null @Input var target: String? = null @Input var release: Boolean? = null @TaskAction fun assemble() { val executable = """{{tauri-binary}}"""; try { runTauriCli(executable) } catch (e: Exception) { if (Os.isFamily(Os.FAMILY_WINDOWS)) { // Try different Windows-specific extensions val fallbacks = listOf( "$executable.exe", "$executable.cmd", "$executable.bat", ) var lastException: Exception = e for (fallback in fallbacks) { try { runTauriCli(fallback) return } catch (fallbackException: Exception) { lastException = fallbackException } } throw lastException } else { throw e; } } } fun runTauriCli(executable: String) { val rootDirRel = rootDirRel ?: throw GradleException("rootDirRel cannot be null") val target = target ?: throw GradleException("target cannot be null") val release = release ?: throw GradleException("release cannot be null") val args = listOf({{quote-and-join tauri-binary-args}}); project.exec { workingDir(File(project.projectDir, rootDirRel)) executable(executable) args(args) if (project.logger.isEnabled(LogLevel.DEBUG)) { args("-vv") } else if (project.logger.isEnabled(LogLevel.INFO)) { args("-v") } if (release) { args("--release") } args(listOf("--target", target)) }.assertNormalExitValue() } } ================================================ FILE: crates/tauri-cli/templates/mobile/android/buildSrc/src/main/kotlin/RustPlugin.kt ================================================ import com.android.build.api.dsl.ApplicationExtension import org.gradle.api.DefaultTask import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.kotlin.dsl.configure import org.gradle.kotlin.dsl.get const val TASK_GROUP = "rust" open class Config { lateinit var rootDirRel: String } open class RustPlugin : Plugin { private lateinit var config: Config override fun apply(project: Project) = with(project) { config = extensions.create("rust", Config::class.java) val defaultAbiList = listOf({{quote-and-join abi-list}}); val abiList = (findProperty("abiList") as? String)?.split(',') ?: defaultAbiList val defaultArchList = listOf({{quote-and-join arch-list}}); val archList = (findProperty("archList") as? String)?.split(',') ?: defaultArchList val targetsList = (findProperty("targetList") as? String)?.split(',') ?: listOf({{quote-and-join target-list}}) extensions.configure { @Suppress("UnstableApiUsage") flavorDimensions.add("abi") productFlavors { create("universal") { dimension = "abi" ndk { abiFilters += abiList } } defaultArchList.forEachIndexed { index, arch -> create(arch) { dimension = "abi" ndk { abiFilters.add(defaultAbiList[index]) } } } } } afterEvaluate { for (profile in listOf("debug", "release")) { val profileCapitalized = profile.replaceFirstChar { it.uppercase() } val buildTask = tasks.maybeCreate( "rustBuildUniversal$profileCapitalized", DefaultTask::class.java ).apply { group = TASK_GROUP description = "Build dynamic library in $profile mode for all targets" } tasks["mergeUniversal${profileCapitalized}JniLibFolders"].dependsOn(buildTask) for (targetPair in targetsList.withIndex()) { val targetName = targetPair.value val targetArch = archList[targetPair.index] val targetArchCapitalized = targetArch.replaceFirstChar { it.uppercase() } val targetBuildTask = project.tasks.maybeCreate( "rustBuild$targetArchCapitalized$profileCapitalized", BuildTask::class.java ).apply { group = TASK_GROUP description = "Build dynamic library in $profile mode for $targetArch" rootDirRel = config.rootDirRel target = targetName release = profile == "release" } buildTask.dependsOn(targetBuildTask) tasks["merge$targetArchCapitalized${profileCapitalized}JniLibFolders"].dependsOn( targetBuildTask ) } } } } } ================================================ FILE: crates/tauri-cli/templates/mobile/android/gradle/wrapper/gradle-wrapper.properties ================================================ #Tue May 10 19:22:52 CST 2022 distributionBase=GRADLE_USER_HOME distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME ================================================ FILE: crates/tauri-cli/templates/mobile/android/gradle.properties ================================================ # Project-wide Gradle settings. # IDE (e.g. Android Studio) users: # Gradle settings configured through the IDE *will override* # any settings specified in this file. # For more details on how to configure your build environment visit # http://www.gradle.org/docs/current/userguide/build_environment.html # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true # AndroidX package structure to make it clearer which packages are bundled with the # Android operating system, and which are packaged with your app"s APK # https://developer.android.com/topic/libraries/support-library/androidx-rn android.useAndroidX=true # Kotlin code style for this project: "official" or "obsolete": kotlin.code.style=official # Enables namespacing of each library's R class so that its R class includes only the # resources declared in the library itself and none from the library's dependencies, # thereby reducing the size of the R class for that library android.nonTransitiveRClass=true android.nonFinalResIds=false ================================================ FILE: crates/tauri-cli/templates/mobile/android/gradlew ================================================ #!/usr/bin/env sh # # Copyright 2015 the original author or authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################## ## ## Gradle start up script for UN*X ## ############################################################################## # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" # Need this for relative symlinks. while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname "$PRG"`"/$link" fi done SAVED="`pwd`" cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME="`pwd -P`" cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" warn () { echo "$*" } die () { echo echo "$*" echo exit 1 } # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false case "`uname`" in CYGWIN* ) cygwin=true ;; Darwin* ) darwin=true ;; MINGW* ) msys=true ;; NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD if [ $? -ne 0 ] ; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" fi fi # For Darwin, add options to specify how the application appears in the dock if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi # For Cygwin or MSYS, switch paths to Windows format before running java if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` SEP="" for dir in $ROOTDIRSRAW ; do ROOTDIRS="$ROOTDIRS$SEP$dir" SEP="|" done OURCYGPATTERN="(^($ROOTDIRS))" # Add a user-defined pattern to the cygpath arguments if [ "$GRADLE_CYGPATTERN" != "" ] ; then OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" fi # Now convert the arguments - kludge to limit ourselves to /bin/sh i=0 for arg in "$@" ; do CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` else eval `echo args$i`="\"$arg\"" fi i=`expr $i + 1` done case $i in 0) set -- ;; 1) set -- "$args0" ;; 2) set -- "$args0" "$args1" ;; 3) set -- "$args0" "$args1" "$args2" ;; 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi # Escape application args save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" exec "$JAVACMD" "$@" ================================================ FILE: crates/tauri-cli/templates/mobile/android/gradlew.bat ================================================ @rem @rem Copyright 2015 the original author or authors. @rem @rem Licensed under the Apache License, Version 2.0 (the "License"); @rem you may not use this file except in compliance with the License. @rem You may obtain a copy of the License at @rem @rem https://www.apache.org/licenses/LICENSE-2.0 @rem @rem Unless required by applicable law or agreed to in writing, software @rem distributed under the License is distributed on an "AS IS" BASIS, @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Resolve any "." and ".." in APP_HOME to make it shorter. for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 exit /b 1 :mainEnd if "%OS%"=="Windows_NT" endlocal :omega ================================================ FILE: crates/tauri-cli/templates/mobile/android/settings.gradle ================================================ include ':app' {{~#each asset-packs}} include ':{{this}}'{{/each}} apply from: 'tauri.settings.gradle' ================================================ FILE: crates/tauri-cli/templates/mobile/ios/.gitignore ================================================ xcuserdata/ build/ Externals/ ================================================ FILE: crates/tauri-cli/templates/mobile/ios/Assets.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "size" : "20x20", "idiom" : "iphone", "filename" : "AppIcon-20x20@2x.png", "scale" : "2x" }, { "size" : "20x20", "idiom" : "iphone", "filename" : "AppIcon-20x20@3x.png", "scale" : "3x" }, { "size" : "29x29", "idiom" : "iphone", "filename" : "AppIcon-29x29@2x-1.png", "scale" : "2x" }, { "size" : "29x29", "idiom" : "iphone", "filename" : "AppIcon-29x29@3x.png", "scale" : "3x" }, { "size" : "40x40", "idiom" : "iphone", "filename" : "AppIcon-40x40@2x.png", "scale" : "2x" }, { "size" : "40x40", "idiom" : "iphone", "filename" : "AppIcon-40x40@3x.png", "scale" : "3x" }, { "size" : "60x60", "idiom" : "iphone", "filename" : "AppIcon-60x60@2x.png", "scale" : "2x" }, { "size" : "60x60", "idiom" : "iphone", "filename" : "AppIcon-60x60@3x.png", "scale" : "3x" }, { "size" : "20x20", "idiom" : "ipad", "filename" : "AppIcon-20x20@1x.png", "scale" : "1x" }, { "size" : "20x20", "idiom" : "ipad", "filename" : "AppIcon-20x20@2x-1.png", "scale" : "2x" }, { "size" : "29x29", "idiom" : "ipad", "filename" : "AppIcon-29x29@1x.png", "scale" : "1x" }, { "size" : "29x29", "idiom" : "ipad", "filename" : "AppIcon-29x29@2x.png", "scale" : "2x" }, { "size" : "40x40", "idiom" : "ipad", "filename" : "AppIcon-40x40@1x.png", "scale" : "1x" }, { "size" : "40x40", "idiom" : "ipad", "filename" : "AppIcon-40x40@2x-1.png", "scale" : "2x" }, { "size" : "76x76", "idiom" : "ipad", "filename" : "AppIcon-76x76@1x.png", "scale" : "1x" }, { "size" : "76x76", "idiom" : "ipad", "filename" : "AppIcon-76x76@2x.png", "scale" : "2x" }, { "size" : "83.5x83.5", "idiom" : "ipad", "filename" : "AppIcon-83.5x83.5@2x.png", "scale" : "2x" }, { "size" : "1024x1024", "idiom" : "ios-marketing", "filename" : "AppIcon-512@2x.png", "scale" : "1x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: crates/tauri-cli/templates/mobile/ios/Assets.xcassets/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: crates/tauri-cli/templates/mobile/ios/ExportOptions.plist ================================================ method debugging ================================================ FILE: crates/tauri-cli/templates/mobile/ios/LaunchScreen.storyboard ================================================ ================================================ FILE: crates/tauri-cli/templates/mobile/ios/Podfile ================================================ # Uncomment the next line to define a global platform for your project target '{{app.name}}_iOS' do platform :ios, '{{apple.ios-version}}' # Pods for {{app.name}}_iOS {{~#each ios-pods}} pod '{{this.name}}'{{#if this.version}}, '{{this.version}}'{{/if}}{{/each}} end target '{{app.name}}_macOS' do platform :osx, '{{apple.macos-version}}' # Pods for {{app.name}}_macOS {{~#each macos-pods}} pod '{{this.name}}'{{#if this.version}}, '{{this.version}}'{{/if}}{{/each}} end # Delete the deployment target for iOS and macOS, causing it to be inherited from the Podfile post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET' config.build_settings.delete 'MACOSX_DEPLOYMENT_TARGET' end end end ================================================ FILE: crates/tauri-cli/templates/mobile/ios/Sources/{{app.name}}/bindings/bindings.h ================================================ #pragma once namespace ffi { extern "C" { void start_app(); } } ================================================ FILE: crates/tauri-cli/templates/mobile/ios/Sources/{{app.name}}/main.mm ================================================ #include "bindings/bindings.h" int main(int argc, char * argv[]) { ffi::start_app(); return 0; } ================================================ FILE: crates/tauri-cli/templates/mobile/ios/project.yml ================================================ name: {{app.name}} options: bundleIdPrefix: {{app.identifier}} deploymentTarget: iOS: {{apple.ios-version}} fileGroups: [{{join file-groups}}] configs: debug: debug release: release settingGroups: app: base: PRODUCT_NAME: {{app.stylized-name}} PRODUCT_BUNDLE_IDENTIFIER: {{app.identifier}} {{#if apple.development-team}} DEVELOPMENT_TEAM: {{apple.development-team}} {{/if}} targetTemplates: app: type: application sources: - path: Sources scheme: environmentVariables: RUST_BACKTRACE: full RUST_LOG: info settings: groups: [app] targets: {{app.name}}_iOS: type: application platform: iOS sources: - path: Sources - path: Assets.xcassets - path: Externals - path: {{app.name}}_iOS - path: {{app.asset-dir}} buildPhase: resources type: folder {{~#each asset-catalogs}} - {{prefix-path this}}{{/each}} {{~#each ios-additional-targets}} - path: {{prefix-path this}}{{/each}} - path: LaunchScreen.storyboard info: path: {{app.name}}_iOS/Info.plist properties: LSRequiresIPhoneOS: true UILaunchStoryboardName: LaunchScreen UIRequiredDeviceCapabilities: [arm64, metal] UISupportedInterfaceOrientations: - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad: - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight CFBundleShortVersionString: {{apple.bundle-version-short}} CFBundleVersion: "{{apple.bundle-version}}" {{~#each apple.plist-pairs}} {{this.key}}: {{this.value}}{{/each}} entitlements: path: {{app.name}}_iOS/{{app.name}}_iOS.entitlements scheme: environmentVariables: RUST_BACKTRACE: full RUST_LOG: info {{~#if ios-command-line-arguments}} commandLineArguments: {{~#each ios-command-line-arguments}} "{{this}}": true {{/each}}{{~/if}} settings: base: 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/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) ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES: true EXCLUDED_ARCHS[sdk=iphoneos*]: x86_64 groups: [app] dependencies: - framework: {{ lib-output-file-name }} embed: false {{~#each ios-libraries}} - framework: {{this}} embed: false{{/each}}{{#if ios-vendor-frameworks}}{{~#each ios-vendor-frameworks}} - framework: {{this}}{{/each}}{{/if}}{{#if ios-vendor-sdks}}{{~#each ios-vendor-sdks}} - sdk: {{prefix-path this}}{{/each}}{{/if}} - sdk: CoreGraphics.framework - sdk: Metal.framework - sdk: MetalKit.framework - sdk: QuartzCore.framework - sdk: Security.framework - sdk: UIKit.framework{{#if this.ios-frameworks}}{{~#each ios-frameworks}} - sdk: {{this}}.framework{{/each}}{{/if}} - sdk: WebKit.framework preBuildScripts: {{~#each ios-pre-build-scripts}}{{#if this.path}} - path {{this.path}}{{/if}}{{#if this.script}} - script: {{this.script}}{{/if}}{{#if this.name}} name: {{this.name}}{{/if}}{{#if this.input-files}} inputFiles: {{~#each this.input-files}} - {{this}}{{/each}}{{/if}}{{#if this.output-files}} outputFiles: {{~#each this.output-files}} - {{this}}{{/each}}{{/if}}{{#if this.input-file-lists}} inputFileLists: {{~#each this.output-files}} - {{this}}{{/each}}{{/if}}{{#if this.output-file-lists}} outputFileLists: {{~#each this.output-files}} - {{this}}{{/each}}{{/if}}{{#if this.shell}} shell: {{this.shell}}{{/if}}{{#if this.show-env-vars}} showEnvVars: {{this.show_env_vars}}{{/if}}{{#if this.run-only-when-installing}} runOnlyWhenInstalling: {{this.run-only-when-installing}}{{/if}}{{#if this.based-on-dependency-analysis}} basedOnDependencyAnalysis: {{this.based-on-dependency-analysis}}{{/if}}{{#if this.discovered-dependency-file}} discoveredDependencyFile: {{this.discovered-dependency-file}}{{/if}} {{~/each}} - script: {{ tauri-binary }} {{ tauri-binary-args-str }} -v --platform ${PLATFORM_DISPLAY_NAME:?} --sdk-root ${SDKROOT:?} --framework-search-paths "${FRAMEWORK_SEARCH_PATHS:?}" --header-search-paths "${HEADER_SEARCH_PATHS:?}" --gcc-preprocessor-definitions "${GCC_PREPROCESSOR_DEFINITIONS:-}" --configuration ${CONFIGURATION:?} ${FORCE_COLOR} ${ARCHS:?} name: Build Rust Code basedOnDependencyAnalysis: false outputFiles: - $(SRCROOT)/Externals/x86_64/${CONFIGURATION}/{{ lib-output-file-name }} - $(SRCROOT)/Externals/arm64/${CONFIGURATION}/{{ lib-output-file-name }} {{~#if ios-post-compile-scripts}} postCompileScripts: {{~#each ios-post-compile-scripts}}{{#if this.path}} - path {{this.path}}{{/if}}{{#if this.script}} - script: {{this.script}}{{/if}}{{#if this.name}} name: {{this.name}}{{/if}}{{#if this.input-files}} inputFiles: {{~#each this.input-files}} - {{this}}{{/each}}{{/if}}{{#if this.output-files}} outputFiles: {{~#each this.output-files}} - {{this}}{{/each}}{{/if}}{{#if this.input-file-lists}} inputFileLists: {{~#each this.output-files}} - {{this}}{{/each}}{{/if}}{{#if this.output-file-lists}} outputFileLists: {{~#each this.output-files}} - {{this}}{{/each}}{{/if}}{{#if this.shell}} shell: {{this.shell}}{{/if}}{{#if this.show-env-vars}} showEnvVars: {{this.show_env_vars}}{{/if}}{{#if this.run-only-when-installing}} runOnlyWhenInstalling: {{this.run-only-when-installing}}{{/if}}{{#if this.based-on-dependency-analysis}} basedOnDependencyAnalysis: {{this.based-on-dependency-analysis}}{{/if}}{{#if this.discovered-dependency-file}} discoveredDependencyFile: {{this.discovered-dependency-file}}{{/if}} {{~/each~}} {{~/if~}} {{~#if ios-post-build-scripts}} postBuildScripts: {{~#each ios-post-build-scripts}}{{#if this.path}} - path {{this.path}}{{/if}}{{#if this.script}} - script: {{this.script}}{{/if}}{{#if this.name}} name: {{this.name}}{{/if}}{{#if this.input-files}} inputFiles: {{~#each this.input-files}} - {{this}}{{/each}}{{/if}}{{#if this.output-files}} outputFiles: {{~#each this.output-files}} - {{this}}{{/each}}{{/if}}{{#if this.input-file-lists}} inputFileLists: {{~#each this.output-files}} - {{this}}{{/each}}{{/if}}{{#if this.output-file-lists}} outputFileLists: {{~#each this.output-files}} - {{this}}{{/each}}{{/if}}{{#if this.shell}} shell: {{this.shell}}{{/if}}{{#if this.show-env-vars}} showEnvVars: {{this.show_env_vars}}{{/if}}{{#if this.run-only-when-installing}} runOnlyWhenInstalling: {{this.run-only-when-installing}}{{/if}}{{#if this.based-on-dependency-analysis}} basedOnDependencyAnalysis: {{this.based-on-dependency-analysis}}{{/if}}{{#if this.discovered-dependency-file}} discoveredDependencyFile: {{this.discovered-dependency-file}}{{/if}} {{~/each~}} {{~/if}} ================================================ FILE: crates/tauri-cli/templates/mobile/ios/{{app.name}}.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings ================================================ {{#if apple.use-legacy-build-system}} BuildSystemType Original DisableBuildSystemDeprecationDiagnostic {{/if}} ================================================ FILE: crates/tauri-cli/templates/plugin/.github/workflows/audit.yml ================================================ {{{{raw}}}} name: Audit on: schedule: - cron: '0 0 * * *' push: branches: - main paths: - ".github/workflows/audit.yml" - "**/Cargo.lock" - "**/Cargo.toml" pull_request: branches: - main paths: - ".github/workflows/audit.yml" - "**/Cargo.lock" - "**/Cargo.toml" concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: audit: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: rustsec/audit-check@v1 with: token: ${{ secrets.GITHUB_TOKEN }} {{{{/raw}}}} ================================================ FILE: crates/tauri-cli/templates/plugin/.github/workflows/clippy.yml ================================================ {{{{raw}}}} name: Check on: push: branches: - main paths: - ".github/workflows/check.yml" - "**/*.rs" - "**/Cargo.toml" pull_request: branches: - main paths: - ".github/workflows/check.yml" - "**/*.rs" - "**/Cargo.toml" concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: fmt: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable with: components: rustfmt - run: cargo fmt --all -- --check clippy: strategy: fail-fast: false matrix: platform: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.platform }} steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable with: components: clippy - name: install webkit2gtk if: matrix.platform == 'ubuntu-latest' run: | sudo apt-get update sudo apt-get install -y webkit2gtk-4.1 - uses: Swatinem/rust-cache@v2 - run: cargo clippy --all-targets --all-features -- -D warnings {{{{/raw}}}} ================================================ FILE: crates/tauri-cli/templates/plugin/.github/workflows/test.yml ================================================ {{{{raw}}}} name: Test on: push: branches: - main pull_request: branches: - main concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: test: strategy: fail-fast: false matrix: platform: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.platform }} steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - name: install webkit2gtk if: matrix.platform == 'ubuntu-latest' run: | sudo apt-get update sudo apt-get install -y webkit2gtk-4.1 - uses: Swatinem/rust-cache@v2 - run: cargo test --all-targets --all-features -- -D warnings {{{{/raw}}}} ================================================ FILE: crates/tauri-cli/templates/plugin/.gitignore ================================================ /.vs .DS_Store .Thumbs.db *.sublime* .idea/ debug.log package-lock.json .vscode/settings.json yarn.lock /.tauri /target Cargo.lock node_modules/ dist-js dist ================================================ FILE: crates/tauri-cli/templates/plugin/Cargo.crate-manifest ================================================ [package] name = "tauri-plugin-{{ plugin_name }}" version = "0.1.0" authors = [ "{{ author }}" ] description = "" edition = "2021" rust-version = "1.77.2" exclude = ["/examples", "/dist-js", "/guest-js", "/node_modules"] links = "tauri-plugin-{{ plugin_name }}" [dependencies] tauri = {{ tauri_dep }} serde = "1.0" thiserror = "2" [build-dependencies] tauri-plugin = {{{ tauri_plugin_dep }}} ================================================ FILE: crates/tauri-cli/templates/plugin/README.md ================================================ # Tauri Plugin {{ plugin_name_original }} ================================================ FILE: crates/tauri-cli/templates/plugin/__example-api/tauri-app/.gitignore ================================================ # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* pnpm-debug.log* lerna-debug.log* node_modules dist dist-ssr *.local # Editor directories and files .vscode/* !.vscode/extensions.json .idea .DS_Store *.suo *.ntvs* *.njsproj *.sln *.sw? ================================================ FILE: crates/tauri-cli/templates/plugin/__example-api/tauri-app/.vscode/extensions.json ================================================ { "recommendations": [ "svelte.svelte-vscode", "tauri-apps.tauri-vscode", "rust-lang.rust-analyzer" ] } ================================================ FILE: crates/tauri-cli/templates/plugin/__example-api/tauri-app/README.md ================================================ # Svelte + Vite This template should help get you started developing with Tauri and Svelte in Vite. ## Recommended IDE Setup [VS Code](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer). ================================================ FILE: crates/tauri-cli/templates/plugin/__example-api/tauri-app/index.html ================================================ Tauri + Svelte
================================================ FILE: crates/tauri-cli/templates/plugin/__example-api/tauri-app/jsconfig.json ================================================ { "compilerOptions": { "moduleResolution": "bundler", "target": "ESNext", "module": "ESNext", /** * svelte-preprocess cannot figure out whether you have * a value or a type, so tell TypeScript to enforce using * `import type` instead of `import` for Types. */ "verbatimModuleSyntax": true, "isolatedModules": true, "resolveJsonModule": true, /** * To have warnings / errors of the Svelte compiler at the * correct position, enable source maps by default. */ "sourceMap": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "baseUrl": ".", /** * Typecheck JS in `.svelte` and `.js` files by default. * Disable this if you'd like to use dynamic types. */ "checkJs": true }, /** * Use global.d.ts instead of compilerOptions.types * to avoid limiting type declarations. */ "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"] } ================================================ FILE: crates/tauri-cli/templates/plugin/__example-api/tauri-app/package.json ================================================ { "name": "tauri-app", "private": true, "version": "0.1.0", "type": "module", "scripts": { "dev": "vite", "build": "vite build", "preview": "vite preview", "tauri": "tauri" }, "dependencies": { "@tauri-apps/api": "^2.0.0", "tauri-plugin-{{ plugin_name }}-api": "file:../../" }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "^7.0.0", "svelte": "^5.0.0", "vite": "^8.0.0", "@tauri-apps/cli": "^2.0.0" } } ================================================ FILE: crates/tauri-cli/templates/plugin/__example-api/tauri-app/src/App.svelte ================================================

Welcome to Tauri!

Click on the Tauri, Vite, and Svelte logos to learn more.

{@html response}
================================================ FILE: crates/tauri-cli/templates/plugin/__example-api/tauri-app/src/lib/Greet.svelte ================================================

{greetMsg}

================================================ FILE: crates/tauri-cli/templates/plugin/__example-api/tauri-app/src/main.js ================================================ import "./style.css"; import App from "./App.svelte"; import { mount } from 'svelte'; const app = mount(App, { target: document.getElementById("app"), }); export default app; ================================================ FILE: crates/tauri-cli/templates/plugin/__example-api/tauri-app/src/style.css ================================================ :root { font-family: Inter, Avenir, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 24px; font-weight: 400; color: #0f0f0f; background-color: #f6f6f6; font-synthesis: none; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-text-size-adjust: 100%; } .container { margin: 0; padding-top: 10vh; display: flex; flex-direction: column; justify-content: center; text-align: center; } .logo { height: 6em; padding: 1.5em; will-change: filter; transition: 0.75s; } .logo.tauri:hover { filter: drop-shadow(0 0 2em #24c8db); } .row { display: flex; justify-content: center; } a { font-weight: 500; color: #646cff; text-decoration: inherit; } a:hover { color: #535bf2; } h1 { text-align: center; } input, button { border-radius: 8px; border: 1px solid transparent; padding: 0.6em 1.2em; font-size: 1em; font-weight: 500; font-family: inherit; color: #0f0f0f; background-color: #ffffff; transition: border-color 0.25s; box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2); } button { cursor: pointer; } button:hover { border-color: #396cd8; } input, button { outline: none; } #greet-input { margin-right: 5px; } @media (prefers-color-scheme: dark) { :root { color: #f6f6f6; background-color: #2f2f2f; } a:hover { color: #24c8db; } input, button { color: #ffffff; background-color: #0f0f0f98; } } ================================================ FILE: crates/tauri-cli/templates/plugin/__example-api/tauri-app/src/vite-env.d.ts ================================================ /// /// ================================================ FILE: crates/tauri-cli/templates/plugin/__example-api/tauri-app/src-tauri/.gitignore ================================================ # Generated by Cargo # will have compiled files and executables /target/ ================================================ FILE: crates/tauri-cli/templates/plugin/__example-api/tauri-app/src-tauri/Cargo.crate-manifest ================================================ [package] name = "tauri-app" version = "0.1.0" description = "A Tauri App" authors = ["you"] license = "" repository = "" edition = "2021" rust-version = "1.77.2" [lib] name = "tauri_app_lib" crate-type = ["staticlib", "cdylib", "rlib"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [build-dependencies] tauri-build = {{ tauri_build_dep }} [dependencies] tauri = {{ tauri_example_dep }} tauri-plugin-{{ plugin_name }} = { path = "../../../" } ================================================ FILE: crates/tauri-cli/templates/plugin/__example-api/tauri-app/src-tauri/build.rs ================================================ fn main() { tauri_build::build() } ================================================ FILE: crates/tauri-cli/templates/plugin/__example-api/tauri-app/src-tauri/capabilities/default.json ================================================ { "$schema": "../gen/schemas/desktop-schema.json", "identifier": "default", "description": "enables the default permissions", "windows": [ "main" ], "permissions": [ "core:default", "{{ plugin_name }}:default" ] } ================================================ FILE: crates/tauri-cli/templates/plugin/__example-api/tauri-app/src-tauri/src/lib.rs ================================================ // Learn more about Tauri commands at https://v2.tauri.app/develop/calling-rust/#commands #[tauri::command] fn greet(name: &str) -> String { format!("Hello, {}! You've been greeted from Rust!", name) } #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .invoke_handler(tauri::generate_handler![greet]) .plugin(tauri_plugin_{{ plugin_name_snake_case }}::init()) .run(tauri::generate_context!()) .expect("error while running tauri application"); } ================================================ FILE: crates/tauri-cli/templates/plugin/__example-api/tauri-app/src-tauri/src/main.rs ================================================ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] fn main() { tauri_app_lib::run(); } ================================================ FILE: crates/tauri-cli/templates/plugin/__example-api/tauri-app/src-tauri/tauri.conf.json ================================================ { "productName": "tauri-app", "version": "0.1.0", "identifier": "com.tauri.dev", "build": { "beforeDevCommand": "pnpm dev", "beforeBuildCommand": "pnpm build", "devUrl": "http://localhost:1420", "frontendDist": "../dist" }, "app": { "withGlobalTauri": false, "security": { "csp": null }, "windows": [ { "fullscreen": false, "height": 600, "resizable": true, "title": "tauri-app", "width": 800 } ] }, "bundle": { "active": true, "targets": "all", "icon": [ "icons/32x32.png", "icons/128x128.png", "icons/128x128@2x.png", "icons/icon.icns", "icons/icon.ico" ] } } ================================================ FILE: crates/tauri-cli/templates/plugin/__example-api/tauri-app/vite.config.js ================================================ import { defineConfig } from "vite"; import { svelte } from "@sveltejs/vite-plugin-svelte"; const host = process.env.TAURI_DEV_HOST; // https://vite.dev/config/ export default defineConfig({ plugins: [svelte()], // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build` // prevent Vite from obscuring rust errors clearScreen: false, // tauri expects a fixed port, fail if that port is not available server: { host: host || false, port: 1420, strictPort: true, hmr: host ? { protocol: 'ws', host, port: 1421 } : undefined, }, }) ================================================ FILE: crates/tauri-cli/templates/plugin/__example-basic/vanilla/.gitignore ================================================ node_modules/ ================================================ FILE: crates/tauri-cli/templates/plugin/__example-basic/vanilla/package.json ================================================ { "name": "app", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "MIT", "dependencies": { "@tauri-apps/cli": "^2.0.0-alpha.17" } } ================================================ FILE: crates/tauri-cli/templates/plugin/__example-basic/vanilla/public/index.html ================================================
Plugin example
================================================ FILE: crates/tauri-cli/templates/plugin/__example-basic/vanilla/src-tauri/.gitignore ================================================ # Generated by Cargo # will have compiled files and executables /target/ ================================================ FILE: crates/tauri-cli/templates/plugin/__example-basic/vanilla/src-tauri/Cargo.crate-manifest ================================================ [package] name = "tauri-app" version = "0.1.0" description = "A Tauri App" authors = ["you"] license = "" repository = "" edition = "2021" rust-version = "1.77.2" [lib] name = "tauri_app_lib" crate-type = ["staticlib", "cdylib", "rlib"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [build-dependencies] tauri-build = {{ tauri_build_dep }} [dependencies] tauri = {{ tauri_example_dep }} tauri-plugin-{{ plugin_name }} = { path = "../../../" } ================================================ FILE: crates/tauri-cli/templates/plugin/__example-basic/vanilla/src-tauri/build.rs ================================================ fn main() { tauri_build::build() } ================================================ FILE: crates/tauri-cli/templates/plugin/__example-basic/vanilla/src-tauri/capabilities/default.json ================================================ { "$schema": "../gen/schemas/desktop-schema.json", "identifier": "default", "description": "enables the default permissions", "windows": [ "main" ], "permissions": [ "core:default", "{{ plugin_name }}:default" ] } ================================================ FILE: crates/tauri-cli/templates/plugin/__example-basic/vanilla/src-tauri/rustfmt.toml ================================================ max_width = 100 hard_tabs = false tab_spaces = 2 newline_style = "Auto" use_small_heuristics = "Default" reorder_imports = true reorder_modules = true remove_nested_parens = true edition = "2021" merge_derives = true use_try_shorthand = false use_field_init_shorthand = false force_explicit_abi = true imports_granularity = "Crate" ================================================ FILE: crates/tauri-cli/templates/plugin/__example-basic/vanilla/src-tauri/src/lib.rs ================================================ #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_{{ plugin_name_snake_case }}::init()) .run(tauri::generate_context!()) .expect("error while running tauri application"); } ================================================ FILE: crates/tauri-cli/templates/plugin/__example-basic/vanilla/src-tauri/src/main.rs ================================================ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] fn main() { tauri_app_lib::run(); } ================================================ FILE: crates/tauri-cli/templates/plugin/__example-basic/vanilla/src-tauri/tauri.conf.json ================================================ { "productName": "app", "version": "0.1.0", "identifier": "com.tauri.{{ plugin_name }}", "build": { "frontendDist": "../public" }, "app": { "windows": [ { "title": "app", "width": 800, "height": 600, "resizable": true, "fullscreen": false } ], "security": { "csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self' img-src: 'self'; connect-src ipc: http://ipc.localhost" } }, "bundle": { "active": true, "targets": "all", "icon": [ "icons/32x32.png", "icons/128x128.png", "icons/128x128@2x.png", "icons/icon.icns", "icons/icon.ico" ] } } ================================================ FILE: crates/tauri-cli/templates/plugin/android/.gitignore ================================================ /build /.tauri ================================================ FILE: crates/tauri-cli/templates/plugin/android/build.gradle.kts ================================================ plugins { id("com.android.library") id("org.jetbrains.kotlin.android") } android { namespace = "{{android_package_id}}" compileSdk = 36 defaultConfig { minSdk = 21 testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles("consumer-rules.pro") } buildTypes { release { isMinifyEnabled = false proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) } } compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = "1.8" } } dependencies { implementation("androidx.core:core-ktx:1.9.0") implementation("androidx.appcompat:appcompat:1.6.0") implementation("com.google.android.material:material:1.7.0") testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.5") androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") implementation(project(":tauri-android")) } ================================================ FILE: crates/tauri-cli/templates/plugin/android/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the # proguardFiles setting in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} # Uncomment this to preserve the line number information for # debugging stack traces. #-keepattributes SourceFile,LineNumberTable # If you keep the line number information, uncomment this to # hide the original source file name. #-renamesourcefileattribute SourceFile ================================================ FILE: crates/tauri-cli/templates/plugin/android/settings.gradle ================================================ pluginManagement { repositories { mavenCentral() gradlePluginPortal() google() } resolutionStrategy { eachPlugin { switch (requested.id.id) { case "com.android.library": useVersion("8.0.2") break case "org.jetbrains.kotlin.android": useVersion("1.8.20") break } } } } dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { mavenCentral() google() } } include ':tauri-android' project(':tauri-android').projectDir = new File('./.tauri/tauri-api') ================================================ FILE: crates/tauri-cli/templates/plugin/android/src/androidTest/java/ExampleInstrumentedTest.kt ================================================ package {{android_package_id}} import androidx.test.platform.app.InstrumentationRegistry import androidx.test.ext.junit.runners.AndroidJUnit4 import org.junit.Test import org.junit.runner.RunWith import org.junit.Assert.* /** * Instrumented test, which will execute on an Android device. * * See [testing documentation](http://d.android.com/tools/testing). */ @RunWith(AndroidJUnit4::class) class ExampleInstrumentedTest { @Test fun useAppContext() { // Context of the app under test. val appContext = InstrumentationRegistry.getInstrumentation().targetContext assertEquals("{{android_package_id}}", appContext.packageName) } } ================================================ FILE: crates/tauri-cli/templates/plugin/android/src/main/AndroidManifest.xml ================================================ ================================================ FILE: crates/tauri-cli/templates/plugin/android/src/main/java/Example.kt ================================================ package {{android_package_id}} import android.util.Log class Example { fun pong(value: String): String { Log.i("Pong", value) return value } } ================================================ FILE: crates/tauri-cli/templates/plugin/android/src/main/java/ExamplePlugin.kt ================================================ package {{android_package_id}} import android.app.Activity import app.tauri.annotation.Command import app.tauri.annotation.InvokeArg import app.tauri.annotation.TauriPlugin import app.tauri.plugin.JSObject import app.tauri.plugin.Plugin import app.tauri.plugin.Invoke @InvokeArg class PingArgs { var value: String? = null } @TauriPlugin class ExamplePlugin(private val activity: Activity): Plugin(activity) { private val implementation = Example() @Command fun ping(invoke: Invoke) { val args = invoke.parseArgs(PingArgs::class.java) val ret = JSObject() ret.put("value", implementation.pong(args.value ?: "default value :(")) invoke.resolve(ret) } } ================================================ FILE: crates/tauri-cli/templates/plugin/android/src/test/java/ExampleUnitTest.kt ================================================ package {{android_package_id}} import org.junit.Test import org.junit.Assert.* /** * Example local unit test, which will execute on the development machine (host). * * See [testing documentation](http://d.android.com/tools/testing). */ class ExampleUnitTest { @Test fun addition_isCorrect() { assertEquals(4, 2 + 2) } } ================================================ FILE: crates/tauri-cli/templates/plugin/build.rs ================================================ const COMMANDS: &[&str] = &["ping"]; fn main() { tauri_plugin::Builder::new(COMMANDS) .android_path("android") .ios_path("ios") .build(); } ================================================ FILE: crates/tauri-cli/templates/plugin/guest-js/index.ts ================================================ {{#if license_header}} {{ license_header }} {{/if}} import { invoke } from '@tauri-apps/api/core' export async function ping(value: string): Promise { return await invoke<{value?: string}>('plugin:{{ plugin_name }}|ping', { payload: { value, }, }).then((r) => (r.value ? r.value : null)); } ================================================ FILE: crates/tauri-cli/templates/plugin/ios-spm/.gitignore ================================================ .DS_Store /.build /Packages /*.xcodeproj xcuserdata/ DerivedData/ .swiftpm/config/registries.json .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata .netrc Package.resolved ================================================ FILE: crates/tauri-cli/templates/plugin/ios-spm/Package.swift ================================================ // swift-tools-version:5.3 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription let package = Package( name: "tauri-plugin-{{ plugin_name }}", platforms: [ .macOS(.v10_13), .iOS(.v13), ], products: [ // Products define the executables and libraries a package produces, and make them visible to other packages. .library( name: "tauri-plugin-{{ plugin_name }}", type: .static, targets: ["tauri-plugin-{{ plugin_name }}"]), ], dependencies: [ .package(name: "Tauri", path: "../.tauri/tauri-api") ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. // Targets can depend on other targets in this package, and on products in packages this package depends on. .target( name: "tauri-plugin-{{ plugin_name }}", dependencies: [ .byName(name: "Tauri") ], path: "Sources") ] ) ================================================ FILE: crates/tauri-cli/templates/plugin/ios-spm/README.md ================================================ # Tauri Plugin {{ plugin_name_original }} A description of this package. ================================================ FILE: crates/tauri-cli/templates/plugin/ios-spm/Sources/ExamplePlugin.swift ================================================ import SwiftRs import Tauri import UIKit import WebKit class PingArgs: Decodable { let value: String? } class ExamplePlugin: Plugin { @objc public func ping(_ invoke: Invoke) throws { let args = try invoke.parseArgs(PingArgs.self) invoke.resolve(["value": args.value ?? ""]) } } @_cdecl("init_plugin_{{ plugin_name_snake_case }}") func initPlugin() -> Plugin { return ExamplePlugin() } ================================================ FILE: crates/tauri-cli/templates/plugin/ios-spm/Tests/PluginTests/PluginTests.swift ================================================ import XCTest @testable import ExamplePlugin final class ExamplePluginTests: XCTestCase { func testExample() throws { let plugin = ExamplePlugin() } } ================================================ FILE: crates/tauri-cli/templates/plugin/ios-xcode/tauri-plugin-{{ plugin_name }}/ExamplePlugin.swift ================================================ import SwiftRs import Tauri import UIKit import WebKit class PingArgs: Decodable { let value: String? } class ExamplePlugin: Plugin { @objc public func ping(_ invoke: Invoke) throws { let args = try invoke.parseArgs(PingArgs.self) invoke.resolve(["value": args.value ?? ""]) } } @_cdecl("init_plugin_{{ plugin_name_snake_case }}") func initPlugin() -> Plugin { return ExamplePlugin() } ================================================ FILE: crates/tauri-cli/templates/plugin/ios-xcode/tauri-plugin-{{ plugin_name }}.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 60; objects = { /* Begin PBXBuildFile section */ A0E2115A2BF552D2003BCF4D /* ExamplePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0E211592BF552D2003BCF4D /* ExamplePlugin.swift */; }; A0E211622BF55305003BCF4D /* Tauri in Frameworks */ = {isa = PBXBuildFile; productRef = A0E211612BF55305003BCF4D /* Tauri */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ A0E211542BF552D2003BCF4D /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = "include/$(PRODUCT_NAME)"; dstSubfolderSpec = 16; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ A0E211562BF552D2003BCF4D /* libtauri-plugin-{{ plugin_name }}.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libtauri-plugin-{{ plugin_name }}.a"; sourceTree = BUILT_PRODUCTS_DIR; }; A0E211592BF552D2003BCF4D /* ExamplePlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExamplePlugin.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ A0E211532BF552D2003BCF4D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( A0E211622BF55305003BCF4D /* Tauri in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ A0E2114D2BF552D2003BCF4D = { isa = PBXGroup; children = ( A0E211582BF552D2003BCF4D /* tauri-plugin-{{ plugin_name }} */, A0E211572BF552D2003BCF4D /* Products */, ); sourceTree = ""; }; A0E211572BF552D2003BCF4D /* Products */ = { isa = PBXGroup; children = ( A0E211562BF552D2003BCF4D /* libtauri-plugin-{{ plugin_name }}.a */, ); name = Products; sourceTree = ""; }; A0E211582BF552D2003BCF4D /* tauri-plugin-{{ plugin_name }} */ = { isa = PBXGroup; children = ( A0E211592BF552D2003BCF4D /* ExamplePlugin.swift */, ); path = "tauri-plugin-{{ plugin_name }}"; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ A0E211552BF552D2003BCF4D /* tauri-plugin-{{ plugin_name }} */ = { isa = PBXNativeTarget; buildConfigurationList = A0E2115D2BF552D2003BCF4D /* Build configuration list for PBXNativeTarget "tauri-plugin-{{ plugin_name }}" */; buildPhases = ( A0E211522BF552D2003BCF4D /* Sources */, A0E211532BF552D2003BCF4D /* Frameworks */, A0E211542BF552D2003BCF4D /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); name = "tauri-plugin-{{ plugin_name }}"; packageProductDependencies = ( A0E211612BF55305003BCF4D /* Tauri */, ); productName = "tauri-plugin-{{ plugin_name }}"; productReference = A0E211562BF552D2003BCF4D /* libtauri-plugin-{{ plugin_name }}.a */; productType = "com.apple.product-type.library.static"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ A0E2114E2BF552D2003BCF4D /* Project object */ = { isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = 1; LastSwiftUpdateCheck = 1540; LastUpgradeCheck = 1540; TargetAttributes = { A0E211552BF552D2003BCF4D = { CreatedOnToolsVersion = 15.4; }; }; }; buildConfigurationList = A0E211512BF552D2003BCF4D /* Build configuration list for PBXProject "tauri-plugin-{{ plugin_name }}" */; compatibilityVersion = "Xcode 14.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = A0E2114D2BF552D2003BCF4D; packageReferences = ( A0E211602BF55305003BCF4D /* XCLocalSwiftPackageReference "../.tauri/tauri-api" */, ); productRefGroup = A0E211572BF552D2003BCF4D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( A0E211552BF552D2003BCF4D /* tauri-plugin-{{ plugin_name }} */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ A0E211522BF552D2003BCF4D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( A0E2115A2BF552D2003BCF4D /* ExamplePlugin.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ A0E2115B2BF552D2003BCF4D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 14.0; LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; A0E2115C2BF552D2003BCF4D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 14.0; LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; VALIDATE_PRODUCT = YES; }; name = Release; }; A0E2115E2BF552D2003BCF4D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; A0E2115F2BF552D2003BCF4D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ A0E211512BF552D2003BCF4D /* Build configuration list for PBXProject "tauri-plugin-{{ plugin_name }}" */ = { isa = XCConfigurationList; buildConfigurations = ( A0E2115B2BF552D2003BCF4D /* Debug */, A0E2115C2BF552D2003BCF4D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; A0E2115D2BF552D2003BCF4D /* Build configuration list for PBXNativeTarget "tauri-plugin-{{ plugin_name }}" */ = { isa = XCConfigurationList; buildConfigurations = ( A0E2115E2BF552D2003BCF4D /* Debug */, A0E2115F2BF552D2003BCF4D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ /* Begin XCLocalSwiftPackageReference section */ A0E211602BF55305003BCF4D /* XCLocalSwiftPackageReference "../.tauri/tauri-api" */ = { isa = XCLocalSwiftPackageReference; relativePath = "../.tauri/tauri-api"; }; /* End XCLocalSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ A0E211612BF55305003BCF4D /* Tauri */ = { isa = XCSwiftPackageProductDependency; productName = Tauri; }; /* End XCSwiftPackageProductDependency section */ }; rootObject = A0E2114E2BF552D2003BCF4D /* Project object */; } ================================================ FILE: crates/tauri-cli/templates/plugin/ios-xcode/tauri-plugin-{{ plugin_name }}.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: crates/tauri-cli/templates/plugin/ios-xcode/tauri-plugin-{{ plugin_name }}.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: crates/tauri-cli/templates/plugin/package.json ================================================ { "name": "tauri-plugin-{{ plugin_name }}-api", "version": "0.1.0", "author": "{{ author }}", "description": "", "type": "module", "types": "./dist-js/index.d.ts", "main": "./dist-js/index.cjs", "module": "./dist-js/index.js", "exports": { "types": "./dist-js/index.d.ts", "import": "./dist-js/index.js", "require": "./dist-js/index.cjs" }, "files": [ "dist-js", "README.md" ], "scripts": { "build": "rollup -c", "prepublishOnly": "pnpm build", "pretest": "pnpm build" }, "dependencies": { "@tauri-apps/api": "^2.0.0" }, "devDependencies": { "@rollup/plugin-typescript": "^12.0.0", "rollup": "^4.9.6", "typescript": "^5.3.3", "tslib": "^2.6.2" } } ================================================ FILE: crates/tauri-cli/templates/plugin/rollup.config.js ================================================ import { readFileSync } from 'node:fs' import { dirname, join } from 'node:path' import { cwd } from 'node:process' import typescript from '@rollup/plugin-typescript' const pkg = JSON.parse(readFileSync(join(cwd(), 'package.json'), 'utf8')) export default { input: 'guest-js/index.ts', output: [ { file: pkg.exports.import, format: 'esm' }, { file: pkg.exports.require, format: 'cjs' } ], plugins: [ typescript({ declaration: true, declarationDir: dirname(pkg.exports.import) }) ], external: [ /^@tauri-apps\/api/, ...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {}) ] } ================================================ FILE: crates/tauri-cli/templates/plugin/src/commands.rs ================================================ {{#if license_header}} {{ license_header }} {{/if}} use tauri::{AppHandle, command, Runtime}; use crate::models::*; use crate::Result; use crate::{{ plugin_name_pascal_case }}Ext; #[command] pub(crate) async fn ping( app: AppHandle, payload: PingRequest, ) -> Result { app.{{ plugin_name_snake_case }}().ping(payload) } ================================================ FILE: crates/tauri-cli/templates/plugin/src/desktop.rs ================================================ {{#if license_header}} {{ license_header }} {{/if}} use serde::de::DeserializeOwned; use tauri::{plugin::PluginApi, AppHandle, Runtime}; use crate::models::*; pub fn init( app: &AppHandle, _api: PluginApi, ) -> crate::Result<{{ plugin_name_pascal_case }}> { Ok({{ plugin_name_pascal_case }}(app.clone())) } /// Access to the {{ plugin_name }} APIs. pub struct {{ plugin_name_pascal_case }}(AppHandle); impl {{ plugin_name_pascal_case }} { pub fn ping(&self, payload: PingRequest) -> crate::Result { Ok(PingResponse { value: payload.value, }) } } ================================================ FILE: crates/tauri-cli/templates/plugin/src/error.rs ================================================ {{#if license_header}} {{ license_header }} {{/if}} use serde::{ser::Serializer, Serialize}; pub type Result = std::result::Result; #[derive(Debug, thiserror::Error)] pub enum Error { #[error(transparent)] Io(#[from] std::io::Error), #[cfg(mobile)] #[error(transparent)] PluginInvoke(#[from] tauri::plugin::mobile::PluginInvokeError), } impl Serialize for Error { fn serialize(&self, serializer: S) -> std::result::Result where S: Serializer, { serializer.serialize_str(self.to_string().as_ref()) } } ================================================ FILE: crates/tauri-cli/templates/plugin/src/lib.rs ================================================ {{#if license_header}} {{ license_header }} {{/if}} use tauri::{ plugin::{Builder, TauriPlugin}, Manager, Runtime, }; pub use models::*; #[cfg(desktop)] mod desktop; #[cfg(mobile)] mod mobile; mod commands; mod error; mod models; pub use error::{Error, Result}; #[cfg(desktop)] use desktop::{{ plugin_name_pascal_case }}; #[cfg(mobile)] use mobile::{{ plugin_name_pascal_case }}; /// Extensions to [`tauri::App`], [`tauri::AppHandle`] and [`tauri::Window`] to access the {{ plugin_name }} APIs. pub trait {{ plugin_name_pascal_case }}Ext { fn {{ plugin_name_snake_case }}(&self) -> &{{ plugin_name_pascal_case }}; } impl> crate::{{ plugin_name_pascal_case }}Ext for T { fn {{ plugin_name_snake_case }}(&self) -> &{{ plugin_name_pascal_case }} { self.state::<{{ plugin_name_pascal_case }}>().inner() } } /// Initializes the plugin. pub fn init() -> TauriPlugin { Builder::new("{{ plugin_name }}") .invoke_handler(tauri::generate_handler![commands::ping]) .setup(|app, api| { #[cfg(mobile)] let {{ plugin_name_snake_case }} = mobile::init(app, api)?; #[cfg(desktop)] let {{ plugin_name_snake_case }} = desktop::init(app, api)?; app.manage({{ plugin_name_snake_case }}); Ok(()) }) .build() } ================================================ FILE: crates/tauri-cli/templates/plugin/src/mobile.rs ================================================ {{#if license_header}} {{ license_header }} {{/if}} use serde::de::DeserializeOwned; use tauri::{ plugin::{PluginApi, PluginHandle}, AppHandle, Runtime, }; use crate::models::*; #[cfg(target_os = "ios")] tauri::ios_plugin_binding!(init_plugin_{{ plugin_name_snake_case }}); // initializes the Kotlin or Swift plugin classes pub fn init( _app: &AppHandle, api: PluginApi, ) -> crate::Result<{{ plugin_name_pascal_case }}> { #[cfg(target_os = "android")] let handle = api.register_android_plugin("{{ android_package_id }}", "ExamplePlugin")?; #[cfg(target_os = "ios")] let handle = api.register_ios_plugin(init_plugin_{{ plugin_name_snake_case }})?; Ok({{ plugin_name_pascal_case }}(handle)) } /// Access to the {{ plugin_name }} APIs. pub struct {{ plugin_name_pascal_case }}(PluginHandle); impl {{ plugin_name_pascal_case }} { pub fn ping(&self, payload: PingRequest) -> crate::Result { self .0 .run_mobile_plugin("ping", payload) .map_err(Into::into) } } ================================================ FILE: crates/tauri-cli/templates/plugin/src/models.rs ================================================ {{#if license_header}} {{ license_header }} {{/if}} use serde::{Deserialize, Serialize}; #[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct PingRequest { pub value: Option, } #[derive(Debug, Clone, Default, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct PingResponse { pub value: Option, } ================================================ FILE: crates/tauri-cli/templates/plugin/tsconfig.json ================================================ { "compilerOptions": { "target": "es2021", "module": "esnext", "moduleResolution": "bundler", "skipLibCheck": true, "strict": true, "noUnusedLocals": true, "noImplicitAny": true, "noEmit": true }, "include": ["guest-js/*.ts"], "exclude": ["dist-js", "node_modules"] } ================================================ FILE: crates/tauri-cli/templates/tauri.conf.json ================================================ { "$schema": "https://schema.tauri.app/config/2", "productName": "{{ app_name }}", "version": "0.1.0", "identifier": "com.tauri.dev", "build": { "frontendDist": "{{ frontend_dist }}"{{#if dev_url}}, "devUrl": "{{ dev_url }}"{{/if}}{{#if before_dev_command}}, "beforeDevCommand": "{{ before_dev_command }}"{{/if}}{{#if before_build_command}}, "beforeBuildCommand": "{{ before_build_command }}"{{/if}} }, "app": { "windows": [ { "title": "{{ window_title }}", "width": 800, "height": 600, "resizable": true, "fullscreen": false } ], "security": { "csp": null } }, "bundle": { "active": true, "targets": "all", "icon": [ "icons/32x32.png", "icons/128x128.png", "icons/128x128@2x.png", "icons/icon.icns", "icons/icon.ico" ] } } ================================================ FILE: crates/tauri-cli/tests/fixtures/pbxproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 54; objects = { /* Begin PBXBuildFile section */ 2B78BA327A38C76093D36092 /* libapi_lib.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A00E5F95D64FD14E47F85BD /* libapi_lib.a */; }; 3043432501C9BC2DB6B4CB95 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 71EB788DE4662CFC0D97F567 /* CoreGraphics.framework */; }; 328B4ADB3700C1873BEB7B10 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 90D3B673AFAB8D8AB561F616 /* main.mm */; }; 6F379F15DA085785BA2624D4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6B7E79E23E646BA7968B457C /* Assets.xcassets */; }; 9AADB041D25772D04E543F15 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 62601E25FA39E62BE119B74D /* Metal.framework */; }; 9DDA3BE70DD0E4013973FE38 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6082E363D51372A7658C351 /* UIKit.framework */; }; AC8BDC2C7A63FA3FDC5967F4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4B2D1B108AE002010BDEC6D2 /* LaunchScreen.storyboard */; }; AFA0CA286325FD7A34968CA2 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 384966E551417F94A02D2706 /* Security.framework */; }; B60763BD194DFACA215EC7DA /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC377692DC31A070A0188C9D /* QuartzCore.framework */; }; C6D80743F168BDF017B7769E /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 59CFE20DCF760BE67D9CE3D6 /* WebKit.framework */; }; DFFF888045C8D9D9FB69E8FD /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 338E66700FD330B99D434DD7 /* MetalKit.framework */; }; F86717F05E27C72C9FA1FB27 /* assets in Resources */ = {isa = PBXBuildFile; fileRef = 74A8FDFB350B966F5AAD4A24 /* assets */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 0E96CE07CD20273DD46BF325 /* main.rs */ = {isa = PBXFileReference; path = main.rs; sourceTree = ""; }; 1C1AB1B414CA2795AFBEDDB9 /* tray.rs */ = {isa = PBXFileReference; path = tray.rs; sourceTree = ""; }; 2F63E2AA460089BB58D40C79 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 338E66700FD330B99D434DD7 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; }; 384966E551417F94A02D2706 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; 3CA88F22095BE63D88585625 /* menu_plugin.rs */ = {isa = PBXFileReference; path = menu_plugin.rs; sourceTree = ""; }; 4A00E5F95D64FD14E47F85BD /* libapi_lib.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libapi_lib.a; sourceTree = ""; }; 4B2D1B108AE002010BDEC6D2 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; 59CFE20DCF760BE67D9CE3D6 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; 5AC703CEBA41A121596066F3 /* api_iOS.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = api_iOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; 62601E25FA39E62BE119B74D /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; 6B7E79E23E646BA7968B457C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 71EB788DE4662CFC0D97F567 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 74A8FDFB350B966F5AAD4A24 /* assets */ = {isa = PBXFileReference; lastKnownFileType = folder; path = assets; sourceTree = SOURCE_ROOT; }; 785D025E9542F7E098BF22B5 /* lib.rs */ = {isa = PBXFileReference; path = lib.rs; sourceTree = ""; }; 879941AE3DAA14534BBC6391 /* api_iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = api_iOS.entitlements; sourceTree = ""; }; 90D3B673AFAB8D8AB561F616 /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; B6082E363D51372A7658C351 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; DC377692DC31A070A0188C9D /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; EC8C7948C50C3C9B5D96CB61 /* bindings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bindings.h; sourceTree = ""; }; F835F52713CE8F029D5D252C /* cmd.rs */ = {isa = PBXFileReference; path = cmd.rs; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 11E18DCDB3ADFE87C18915EF /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 2B78BA327A38C76093D36092 /* libapi_lib.a in Frameworks */, 3043432501C9BC2DB6B4CB95 /* CoreGraphics.framework in Frameworks */, 9AADB041D25772D04E543F15 /* Metal.framework in Frameworks */, DFFF888045C8D9D9FB69E8FD /* MetalKit.framework in Frameworks */, B60763BD194DFACA215EC7DA /* QuartzCore.framework in Frameworks */, AFA0CA286325FD7A34968CA2 /* Security.framework in Frameworks */, 9DDA3BE70DD0E4013973FE38 /* UIKit.framework in Frameworks */, C6D80743F168BDF017B7769E /* WebKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 0677CEAF1F282F38CBA0F140 = { isa = PBXGroup; children = ( 74A8FDFB350B966F5AAD4A24 /* assets */, 6B7E79E23E646BA7968B457C /* Assets.xcassets */, 4B2D1B108AE002010BDEC6D2 /* LaunchScreen.storyboard */, F2116A6428EED18BE2A07E2B /* api_iOS */, 86D903732E10FAC4D300E8DF /* Externals */, 7A9A7AC155D9E22E54D6D847 /* Sources */, CF9AA87D2F6E9C389B7AB70B /* src */, 10C9FC3FA3E12D6A4A67999D /* Frameworks */, 4AC51E67B71E27F15B02C5CD /* Products */, ); sourceTree = ""; }; 07051859D6E2D8109C8FB128 /* bindings */ = { isa = PBXGroup; children = ( EC8C7948C50C3C9B5D96CB61 /* bindings.h */, ); path = bindings; sourceTree = ""; }; 10C9FC3FA3E12D6A4A67999D /* Frameworks */ = { isa = PBXGroup; children = ( 71EB788DE4662CFC0D97F567 /* CoreGraphics.framework */, 4A00E5F95D64FD14E47F85BD /* libapi_lib.a */, 62601E25FA39E62BE119B74D /* Metal.framework */, 338E66700FD330B99D434DD7 /* MetalKit.framework */, DC377692DC31A070A0188C9D /* QuartzCore.framework */, 384966E551417F94A02D2706 /* Security.framework */, B6082E363D51372A7658C351 /* UIKit.framework */, 59CFE20DCF760BE67D9CE3D6 /* WebKit.framework */, ); name = Frameworks; sourceTree = ""; }; 4AC51E67B71E27F15B02C5CD /* Products */ = { isa = PBXGroup; children = ( 5AC703CEBA41A121596066F3 /* api_iOS.app */, ); name = Products; sourceTree = ""; }; 7A9A7AC155D9E22E54D6D847 /* Sources */ = { isa = PBXGroup; children = ( A3574F52DBC5463B9C3D043D /* api */, ); path = Sources; sourceTree = ""; }; 86D903732E10FAC4D300E8DF /* Externals */ = { isa = PBXGroup; children = ( ); path = Externals; sourceTree = ""; }; A3574F52DBC5463B9C3D043D /* api */ = { isa = PBXGroup; children = ( 90D3B673AFAB8D8AB561F616 /* main.mm */, 07051859D6E2D8109C8FB128 /* bindings */, ); path = api; sourceTree = ""; }; CF9AA87D2F6E9C389B7AB70B /* src */ = { isa = PBXGroup; children = ( F835F52713CE8F029D5D252C /* cmd.rs */, 785D025E9542F7E098BF22B5 /* lib.rs */, 0E96CE07CD20273DD46BF325 /* main.rs */, 3CA88F22095BE63D88585625 /* menu_plugin.rs */, 1C1AB1B414CA2795AFBEDDB9 /* tray.rs */, ); name = src; path = ../../src; sourceTree = ""; }; F2116A6428EED18BE2A07E2B /* api_iOS */ = { isa = PBXGroup; children = ( 879941AE3DAA14534BBC6391 /* api_iOS.entitlements */, 2F63E2AA460089BB58D40C79 /* Info.plist */, ); path = api_iOS; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 54DC6E273C78071F3BA12EF3 /* api_iOS */ = { isa = PBXNativeTarget; buildConfigurationList = 01CBC40275452376830D79B1 /* Build configuration list for PBXNativeTarget "api_iOS" */; buildPhases = ( FF948951157DE71465B5BD5F /* Build Rust Code */, 71E73CC9AB5F1323EC1F6365 /* Sources */, CA2BEC44B6EDA1F21B6155CD /* Resources */, 11E18DCDB3ADFE87C18915EF /* Frameworks */, ); buildRules = ( ); dependencies = ( ); name = api_iOS; productName = api_iOS; productReference = 5AC703CEBA41A121596066F3 /* api_iOS.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 9BC88C3717DA5D4B78A51C15 /* Project object */ = { isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; LastUpgradeCheck = 1430; TargetAttributes = { 54DC6E273C78071F3BA12EF3 = { DevelopmentTeam = Q93MBH6S2F; }; }; }; buildConfigurationList = 8FA67D0F928A09CD639137D1 /* Build configuration list for PBXProject "api" */; compatibilityVersion = "Xcode 14.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( Base, en, ); mainGroup = 0677CEAF1F282F38CBA0F140; projectDirPath = ""; projectRoot = ""; targets = ( 54DC6E273C78071F3BA12EF3 /* api_iOS */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ CA2BEC44B6EDA1F21B6155CD /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 6F379F15DA085785BA2624D4 /* Assets.xcassets in Resources */, AC8BDC2C7A63FA3FDC5967F4 /* LaunchScreen.storyboard in Resources */, F86717F05E27C72C9FA1FB27 /* assets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ FF948951157DE71465B5BD5F /* Build Rust Code */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( ); name = "Build Rust Code"; outputFileListPaths = ( ); outputPaths = ( "$(SRCROOT)/Externals/x86_64/${CONFIGURATION}/libapi_lib.a", "$(SRCROOT)/Externals/arm64/${CONFIGURATION}/libapi_lib.a", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "cargo tauri ios xcode-script -v --platform ${PLATFORM_DISPLAY_NAME:?} --sdk-root ${SDKROOT:?} --framework-search-paths \"${FRAMEWORK_SEARCH_PATHS:?}\" --header-search-paths \"${HEADER_SEARCH_PATHS:?}\" --gcc-preprocessor-definitions \"${GCC_PREPROCESSOR_DEFINITIONS:-}\" --configuration ${CONFIGURATION:?} ${FORCE_COLOR} ${ARCHS:?}"; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 71E73CC9AB5F1323EC1F6365 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 328B4ADB3700C1873BEB7B10 /* main.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ A83F70B4C02DD0222038C7F1 /* release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 14.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; }; name = release; }; B6AD77E490F315562F75D3D7 /* debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "DEBUG=1", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 14.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; }; name = debug; }; BF284FE6E7AE0C8DDCCE398B /* debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ARCHS = ( arm64, ); ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = api_iOS/api_iOS.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; DEVELOPMENT_TEAM = Q93MBH6S2F; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphoneos*]" = "x86_64"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\".\"", ); INFOPLIST_FILE = api_iOS/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); "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=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)"; PRODUCT_BUNDLE_IDENTIFIER = com.tauri.api; PRODUCT_NAME = "Tauri API"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALID_ARCHS = "arm64"; }; name = debug; }; DB_0E254D0FD84970B57F6410 /* release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ARCHS = ( arm64, ); ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = api_iOS/api_iOS.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; DEVELOPMENT_TEAM = Q93MBH6S2F; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphoneos*]" = "x86_64"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\".\"", ); INFOPLIST_FILE = api_iOS/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); "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=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)"; PRODUCT_BUNDLE_IDENTIFIER = com.tauri.api; PRODUCT_NAME = "Tauri API"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALID_ARCHS = "arm64"; }; name = release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 01CBC40275452376830D79B1 /* Build configuration list for PBXNativeTarget "api_iOS" */ = { isa = XCConfigurationList; buildConfigurations = ( BF284FE6E7AE0C8DDCCE398B /* debug */, DB_0E254D0FD84970B57F6410 /* release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = debug; }; 8FA67D0F928A09CD639137D1 /* Build configuration list for PBXProject "api" */ = { isa = XCConfigurationList; buildConfigurations = ( B6AD77E490F315562F75D3D7 /* debug */, A83F70B4C02DD0222038C7F1 /* release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = debug; }; /* End XCConfigurationList section */ }; rootObject = 9BC88C3717DA5D4B78A51C15 /* Project object */; } ================================================ FILE: crates/tauri-cli/tests/fixtures/pbxproj/snapshots/tauri_cli__helpers__pbxproj__tests__project-modified.pbxproj.snap ================================================ --- source: crates/tauri-cli/src/helpers/pbxproj.rs expression: pbxproj.serialize() --- // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 54; objects = { /* Begin PBXBuildFile section */ 2B78BA327A38C76093D36092 /* libapi_lib.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A00E5F95D64FD14E47F85BD /* libapi_lib.a */; }; 3043432501C9BC2DB6B4CB95 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 71EB788DE4662CFC0D97F567 /* CoreGraphics.framework */; }; 328B4ADB3700C1873BEB7B10 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 90D3B673AFAB8D8AB561F616 /* main.mm */; }; 6F379F15DA085785BA2624D4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6B7E79E23E646BA7968B457C /* Assets.xcassets */; }; 9AADB041D25772D04E543F15 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 62601E25FA39E62BE119B74D /* Metal.framework */; }; 9DDA3BE70DD0E4013973FE38 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6082E363D51372A7658C351 /* UIKit.framework */; }; AC8BDC2C7A63FA3FDC5967F4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4B2D1B108AE002010BDEC6D2 /* LaunchScreen.storyboard */; }; AFA0CA286325FD7A34968CA2 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 384966E551417F94A02D2706 /* Security.framework */; }; B60763BD194DFACA215EC7DA /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC377692DC31A070A0188C9D /* QuartzCore.framework */; }; C6D80743F168BDF017B7769E /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 59CFE20DCF760BE67D9CE3D6 /* WebKit.framework */; }; DFFF888045C8D9D9FB69E8FD /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 338E66700FD330B99D434DD7 /* MetalKit.framework */; }; F86717F05E27C72C9FA1FB27 /* assets in Resources */ = {isa = PBXBuildFile; fileRef = 74A8FDFB350B966F5AAD4A24 /* assets */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 0E96CE07CD20273DD46BF325 /* main.rs */ = {isa = PBXFileReference; path = main.rs; sourceTree = ""; }; 1C1AB1B414CA2795AFBEDDB9 /* tray.rs */ = {isa = PBXFileReference; path = tray.rs; sourceTree = ""; }; 2F63E2AA460089BB58D40C79 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 338E66700FD330B99D434DD7 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; }; 384966E551417F94A02D2706 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; 3CA88F22095BE63D88585625 /* menu_plugin.rs */ = {isa = PBXFileReference; path = menu_plugin.rs; sourceTree = ""; }; 4A00E5F95D64FD14E47F85BD /* libapi_lib.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libapi_lib.a; sourceTree = ""; }; 4B2D1B108AE002010BDEC6D2 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; 59CFE20DCF760BE67D9CE3D6 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; 5AC703CEBA41A121596066F3 /* api_iOS.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = api_iOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; 62601E25FA39E62BE119B74D /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; 6B7E79E23E646BA7968B457C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 71EB788DE4662CFC0D97F567 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 74A8FDFB350B966F5AAD4A24 /* assets */ = {isa = PBXFileReference; lastKnownFileType = folder; path = assets; sourceTree = SOURCE_ROOT; }; 785D025E9542F7E098BF22B5 /* lib.rs */ = {isa = PBXFileReference; path = lib.rs; sourceTree = ""; }; 879941AE3DAA14534BBC6391 /* api_iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = api_iOS.entitlements; sourceTree = ""; }; 90D3B673AFAB8D8AB561F616 /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; B6082E363D51372A7658C351 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; DC377692DC31A070A0188C9D /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; EC8C7948C50C3C9B5D96CB61 /* bindings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bindings.h; sourceTree = ""; }; F835F52713CE8F029D5D252C /* cmd.rs */ = {isa = PBXFileReference; path = cmd.rs; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 11E18DCDB3ADFE87C18915EF /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 2B78BA327A38C76093D36092 /* libapi_lib.a in Frameworks */, 3043432501C9BC2DB6B4CB95 /* CoreGraphics.framework in Frameworks */, 9AADB041D25772D04E543F15 /* Metal.framework in Frameworks */, DFFF888045C8D9D9FB69E8FD /* MetalKit.framework in Frameworks */, B60763BD194DFACA215EC7DA /* QuartzCore.framework in Frameworks */, AFA0CA286325FD7A34968CA2 /* Security.framework in Frameworks */, 9DDA3BE70DD0E4013973FE38 /* UIKit.framework in Frameworks */, C6D80743F168BDF017B7769E /* WebKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 0677CEAF1F282F38CBA0F140 = { isa = PBXGroup; children = ( 74A8FDFB350B966F5AAD4A24 /* assets */, 6B7E79E23E646BA7968B457C /* Assets.xcassets */, 4B2D1B108AE002010BDEC6D2 /* LaunchScreen.storyboard */, F2116A6428EED18BE2A07E2B /* api_iOS */, 86D903732E10FAC4D300E8DF /* Externals */, 7A9A7AC155D9E22E54D6D847 /* Sources */, CF9AA87D2F6E9C389B7AB70B /* src */, 10C9FC3FA3E12D6A4A67999D /* Frameworks */, 4AC51E67B71E27F15B02C5CD /* Products */, ); sourceTree = ""; }; 07051859D6E2D8109C8FB128 /* bindings */ = { isa = PBXGroup; children = ( EC8C7948C50C3C9B5D96CB61 /* bindings.h */, ); path = bindings; sourceTree = ""; }; 10C9FC3FA3E12D6A4A67999D /* Frameworks */ = { isa = PBXGroup; children = ( 71EB788DE4662CFC0D97F567 /* CoreGraphics.framework */, 4A00E5F95D64FD14E47F85BD /* libapi_lib.a */, 62601E25FA39E62BE119B74D /* Metal.framework */, 338E66700FD330B99D434DD7 /* MetalKit.framework */, DC377692DC31A070A0188C9D /* QuartzCore.framework */, 384966E551417F94A02D2706 /* Security.framework */, B6082E363D51372A7658C351 /* UIKit.framework */, 59CFE20DCF760BE67D9CE3D6 /* WebKit.framework */, ); name = Frameworks; sourceTree = ""; }; 4AC51E67B71E27F15B02C5CD /* Products */ = { isa = PBXGroup; children = ( 5AC703CEBA41A121596066F3 /* api_iOS.app */, ); name = Products; sourceTree = ""; }; 7A9A7AC155D9E22E54D6D847 /* Sources */ = { isa = PBXGroup; children = ( A3574F52DBC5463B9C3D043D /* api */, ); path = Sources; sourceTree = ""; }; 86D903732E10FAC4D300E8DF /* Externals */ = { isa = PBXGroup; children = ( ); path = Externals; sourceTree = ""; }; A3574F52DBC5463B9C3D043D /* api */ = { isa = PBXGroup; children = ( 90D3B673AFAB8D8AB561F616 /* main.mm */, 07051859D6E2D8109C8FB128 /* bindings */, ); path = api; sourceTree = ""; }; CF9AA87D2F6E9C389B7AB70B /* src */ = { isa = PBXGroup; children = ( F835F52713CE8F029D5D252C /* cmd.rs */, 785D025E9542F7E098BF22B5 /* lib.rs */, 0E96CE07CD20273DD46BF325 /* main.rs */, 3CA88F22095BE63D88585625 /* menu_plugin.rs */, 1C1AB1B414CA2795AFBEDDB9 /* tray.rs */, ); name = src; path = ../../src; sourceTree = ""; }; F2116A6428EED18BE2A07E2B /* api_iOS */ = { isa = PBXGroup; children = ( 879941AE3DAA14534BBC6391 /* api_iOS.entitlements */, 2F63E2AA460089BB58D40C79 /* Info.plist */, ); path = api_iOS; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 54DC6E273C78071F3BA12EF3 /* api_iOS */ = { isa = PBXNativeTarget; buildConfigurationList = 01CBC40275452376830D79B1 /* Build configuration list for PBXNativeTarget "api_iOS" */; buildPhases = ( FF948951157DE71465B5BD5F /* Build Rust Code */, 71E73CC9AB5F1323EC1F6365 /* Sources */, CA2BEC44B6EDA1F21B6155CD /* Resources */, 11E18DCDB3ADFE87C18915EF /* Frameworks */, ); buildRules = ( ); dependencies = ( ); name = api_iOS; productName = api_iOS; productReference = 5AC703CEBA41A121596066F3 /* api_iOS.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 9BC88C3717DA5D4B78A51C15 /* Project object */ = { isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; LastUpgradeCheck = 1430; TargetAttributes = { 54DC6E273C78071F3BA12EF3 = { DevelopmentTeam = Q93MBH6S2F; }; }; }; buildConfigurationList = 8FA67D0F928A09CD639137D1 /* Build configuration list for PBXProject "api" */; compatibilityVersion = "Xcode 14.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( Base, en, ); mainGroup = 0677CEAF1F282F38CBA0F140; projectDirPath = ""; projectRoot = ""; targets = ( 54DC6E273C78071F3BA12EF3 /* api_iOS */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ CA2BEC44B6EDA1F21B6155CD /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 6F379F15DA085785BA2624D4 /* Assets.xcassets in Resources */, AC8BDC2C7A63FA3FDC5967F4 /* LaunchScreen.storyboard in Resources */, F86717F05E27C72C9FA1FB27 /* assets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ FF948951157DE71465B5BD5F /* Build Rust Code */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( ); name = "Build Rust Code"; outputFileListPaths = ( ); outputPaths = ( "$(SRCROOT)/Externals/x86_64/${CONFIGURATION}/libapi_lib.a", "$(SRCROOT)/Externals/arm64/${CONFIGURATION}/libapi_lib.a", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "cargo tauri ios xcode-script -v --platform ${PLATFORM_DISPLAY_NAME:?} --sdk-root ${SDKROOT:?} --framework-search-paths \"${FRAMEWORK_SEARCH_PATHS:?}\" --header-search-paths \"${HEADER_SEARCH_PATHS:?}\" --gcc-preprocessor-definitions \"${GCC_PREPROCESSOR_DEFINITIONS:-}\" --configuration ${CONFIGURATION:?} ${FORCE_COLOR} ${ARCHS:?}"; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 71E73CC9AB5F1323EC1F6365 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 328B4ADB3700C1873BEB7B10 /* main.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ A83F70B4C02DD0222038C7F1 /* release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 14.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; }; name = release; }; B6AD77E490F315562F75D3D7 /* debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "DEBUG=1", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 14.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; }; name = debug; }; BF284FE6E7AE0C8DDCCE398B /* debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ARCHS = ( arm64, ); ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = api_iOS/api_iOS.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; DEVELOPMENT_TEAM = Q93MBH6S2F; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphoneos*]" = "x86_64"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\".\"", ); INFOPLIST_FILE = api_iOS/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); "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=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)"; PRODUCT_BUNDLE_IDENTIFIER = com.tauri.api; PRODUCT_NAME = "Tauri API"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALID_ARCHS = "arm64"; }; name = debug; }; DB_0E254D0FD84970B57F6410 /* release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ARCHS = ( arm64, ); ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = api_iOS/api_iOS.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; DEVELOPMENT_TEAM = Q93MBH6S2F; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphoneos*]" = "x86_64"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\".\"", ); INFOPLIST_FILE = api_iOS/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); "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=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)"; PRODUCT_BUNDLE_IDENTIFIER = com.tauri.api; PRODUCT_NAME = "Tauri Test"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALID_ARCHS = "arm64"; UNKNOWN = 9283j49238h; }; name = release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 01CBC40275452376830D79B1 /* Build configuration list for PBXNativeTarget "api_iOS" */ = { isa = XCConfigurationList; buildConfigurations = ( BF284FE6E7AE0C8DDCCE398B /* debug */, DB_0E254D0FD84970B57F6410 /* release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = debug; }; 8FA67D0F928A09CD639137D1 /* Build configuration list for PBXProject "api" */ = { isa = XCConfigurationList; buildConfigurations = ( B6AD77E490F315562F75D3D7 /* debug */, A83F70B4C02DD0222038C7F1 /* release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = debug; }; /* End XCConfigurationList section */ }; rootObject = 9BC88C3717DA5D4B78A51C15 /* Project object */; } ================================================ FILE: crates/tauri-cli/tests/fixtures/pbxproj/snapshots/tauri_cli__helpers__pbxproj__tests__project.pbxproj.snap ================================================ --- source: crates/tauri-cli/src/helpers/pbxproj.rs expression: "super::parse(fixtures_path.join(\"project.pbxproj\")).expect(\"failed to parse pbxproj\")" --- Pbxproj { xc_build_configuration: { "A83F70B4C02DD0222038C7F1": XCBuildConfiguration { build_settings: [ BuildSettings { identation: "\t\t\t\t", line_number: 262, key: "ALWAYS_SEARCH_USER_PATHS", value: "NO", }, BuildSettings { identation: "\t\t\t\t", line_number: 263, key: "CLANG_ANALYZER_NONNULL", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 264, key: "CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION", value: "YES_AGGRESSIVE", }, BuildSettings { identation: "\t\t\t\t", line_number: 265, key: "CLANG_CXX_LANGUAGE_STANDARD", value: "\"gnu++14\"", }, BuildSettings { identation: "\t\t\t\t", line_number: 266, key: "CLANG_CXX_LIBRARY", value: "\"libc++\"", }, BuildSettings { identation: "\t\t\t\t", line_number: 267, key: "CLANG_ENABLE_MODULES", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 268, key: "CLANG_ENABLE_OBJC_ARC", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 269, key: "CLANG_ENABLE_OBJC_WEAK", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 270, key: "CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 271, key: "CLANG_WARN_BOOL_CONVERSION", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 272, key: "CLANG_WARN_COMMA", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 273, key: "CLANG_WARN_CONSTANT_CONVERSION", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 274, key: "CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 275, key: "CLANG_WARN_DIRECT_OBJC_ISA_USAGE", value: "YES_ERROR", }, BuildSettings { identation: "\t\t\t\t", line_number: 276, key: "CLANG_WARN_DOCUMENTATION_COMMENTS", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 277, key: "CLANG_WARN_EMPTY_BODY", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 278, key: "CLANG_WARN_ENUM_CONVERSION", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 279, key: "CLANG_WARN_INFINITE_RECURSION", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 280, key: "CLANG_WARN_INT_CONVERSION", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 281, key: "CLANG_WARN_NON_LITERAL_NULL_CONVERSION", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 282, key: "CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 283, key: "CLANG_WARN_OBJC_LITERAL_CONVERSION", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 284, key: "CLANG_WARN_OBJC_ROOT_CLASS", value: "YES_ERROR", }, BuildSettings { identation: "\t\t\t\t", line_number: 285, key: "CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 286, key: "CLANG_WARN_RANGE_LOOP_ANALYSIS", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 287, key: "CLANG_WARN_STRICT_PROTOTYPES", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 288, key: "CLANG_WARN_SUSPICIOUS_MOVE", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 289, key: "CLANG_WARN_UNGUARDED_AVAILABILITY", value: "YES_AGGRESSIVE", }, BuildSettings { identation: "\t\t\t\t", line_number: 290, key: "CLANG_WARN_UNREACHABLE_CODE", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 291, key: "CLANG_WARN__DUPLICATE_METHOD_MATCH", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 292, key: "COPY_PHASE_STRIP", value: "NO", }, BuildSettings { identation: "\t\t\t\t", line_number: 293, key: "DEBUG_INFORMATION_FORMAT", value: "\"dwarf-with-dsym\"", }, BuildSettings { identation: "\t\t\t\t", line_number: 294, key: "ENABLE_NS_ASSERTIONS", value: "NO", }, BuildSettings { identation: "\t\t\t\t", line_number: 295, key: "ENABLE_STRICT_OBJC_MSGSEND", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 296, key: "GCC_C_LANGUAGE_STANDARD", value: "gnu11", }, BuildSettings { identation: "\t\t\t\t", line_number: 297, key: "GCC_NO_COMMON_BLOCKS", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 298, key: "GCC_WARN_64_TO_32_BIT_CONVERSION", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 299, key: "GCC_WARN_ABOUT_RETURN_TYPE", value: "YES_ERROR", }, BuildSettings { identation: "\t\t\t\t", line_number: 300, key: "GCC_WARN_UNDECLARED_SELECTOR", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 301, key: "GCC_WARN_UNINITIALIZED_AUTOS", value: "YES_AGGRESSIVE", }, BuildSettings { identation: "\t\t\t\t", line_number: 302, key: "GCC_WARN_UNUSED_FUNCTION", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 303, key: "GCC_WARN_UNUSED_VARIABLE", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 304, key: "IPHONEOS_DEPLOYMENT_TARGET", value: "14.0", }, BuildSettings { identation: "\t\t\t\t", line_number: 305, key: "MTL_ENABLE_DEBUG_INFO", value: "NO", }, BuildSettings { identation: "\t\t\t\t", line_number: 306, key: "MTL_FAST_MATH", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 307, key: "PRODUCT_NAME", value: "\"$(TARGET_NAME)\"", }, BuildSettings { identation: "\t\t\t\t", line_number: 308, key: "SDKROOT", value: "iphoneos", }, BuildSettings { identation: "\t\t\t\t", line_number: 309, key: "SWIFT_COMPILATION_MODE", value: "wholemodule", }, BuildSettings { identation: "\t\t\t\t", line_number: 310, key: "SWIFT_OPTIMIZATION_LEVEL", value: "\"-O\"", }, BuildSettings { identation: "\t\t\t\t", line_number: 311, key: "SWIFT_VERSION", value: "5.0", }, ], }, "B6AD77E490F315562F75D3D7": XCBuildConfiguration { build_settings: [ BuildSettings { identation: "\t\t\t\t", line_number: 318, key: "ALWAYS_SEARCH_USER_PATHS", value: "NO", }, BuildSettings { identation: "\t\t\t\t", line_number: 319, key: "CLANG_ANALYZER_NONNULL", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 320, key: "CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION", value: "YES_AGGRESSIVE", }, BuildSettings { identation: "\t\t\t\t", line_number: 321, key: "CLANG_CXX_LANGUAGE_STANDARD", value: "\"gnu++14\"", }, BuildSettings { identation: "\t\t\t\t", line_number: 322, key: "CLANG_CXX_LIBRARY", value: "\"libc++\"", }, BuildSettings { identation: "\t\t\t\t", line_number: 323, key: "CLANG_ENABLE_MODULES", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 324, key: "CLANG_ENABLE_OBJC_ARC", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 325, key: "CLANG_ENABLE_OBJC_WEAK", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 326, key: "CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 327, key: "CLANG_WARN_BOOL_CONVERSION", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 328, key: "CLANG_WARN_COMMA", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 329, key: "CLANG_WARN_CONSTANT_CONVERSION", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 330, key: "CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 331, key: "CLANG_WARN_DIRECT_OBJC_ISA_USAGE", value: "YES_ERROR", }, BuildSettings { identation: "\t\t\t\t", line_number: 332, key: "CLANG_WARN_DOCUMENTATION_COMMENTS", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 333, key: "CLANG_WARN_EMPTY_BODY", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 334, key: "CLANG_WARN_ENUM_CONVERSION", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 335, key: "CLANG_WARN_INFINITE_RECURSION", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 336, key: "CLANG_WARN_INT_CONVERSION", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 337, key: "CLANG_WARN_NON_LITERAL_NULL_CONVERSION", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 338, key: "CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 339, key: "CLANG_WARN_OBJC_LITERAL_CONVERSION", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 340, key: "CLANG_WARN_OBJC_ROOT_CLASS", value: "YES_ERROR", }, BuildSettings { identation: "\t\t\t\t", line_number: 341, key: "CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 342, key: "CLANG_WARN_RANGE_LOOP_ANALYSIS", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 343, key: "CLANG_WARN_STRICT_PROTOTYPES", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 344, key: "CLANG_WARN_SUSPICIOUS_MOVE", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 345, key: "CLANG_WARN_UNGUARDED_AVAILABILITY", value: "YES_AGGRESSIVE", }, BuildSettings { identation: "\t\t\t\t", line_number: 346, key: "CLANG_WARN_UNREACHABLE_CODE", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 347, key: "CLANG_WARN__DUPLICATE_METHOD_MATCH", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 348, key: "COPY_PHASE_STRIP", value: "NO", }, BuildSettings { identation: "\t\t\t\t", line_number: 349, key: "DEBUG_INFORMATION_FORMAT", value: "dwarf", }, BuildSettings { identation: "\t\t\t\t", line_number: 350, key: "ENABLE_STRICT_OBJC_MSGSEND", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 351, key: "ENABLE_TESTABILITY", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 352, key: "GCC_C_LANGUAGE_STANDARD", value: "gnu11", }, BuildSettings { identation: "\t\t\t\t", line_number: 353, key: "GCC_DYNAMIC_NO_PIC", value: "NO", }, BuildSettings { identation: "\t\t\t\t", line_number: 354, key: "GCC_NO_COMMON_BLOCKS", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 355, key: "GCC_OPTIMIZATION_LEVEL", value: "0", }, BuildSettings { identation: "\t\t\t\t", line_number: 356, key: "GCC_PREPROCESSOR_DEFINITIONS", value: "(\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t);\n", }, BuildSettings { identation: "\t\t\t\t", line_number: 360, key: "GCC_WARN_64_TO_32_BIT_CONVERSION", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 361, key: "GCC_WARN_ABOUT_RETURN_TYPE", value: "YES_ERROR", }, BuildSettings { identation: "\t\t\t\t", line_number: 362, key: "GCC_WARN_UNDECLARED_SELECTOR", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 363, key: "GCC_WARN_UNINITIALIZED_AUTOS", value: "YES_AGGRESSIVE", }, BuildSettings { identation: "\t\t\t\t", line_number: 364, key: "GCC_WARN_UNUSED_FUNCTION", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 365, key: "GCC_WARN_UNUSED_VARIABLE", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 366, key: "IPHONEOS_DEPLOYMENT_TARGET", value: "14.0", }, BuildSettings { identation: "\t\t\t\t", line_number: 367, key: "MTL_ENABLE_DEBUG_INFO", value: "INCLUDE_SOURCE", }, BuildSettings { identation: "\t\t\t\t", line_number: 368, key: "MTL_FAST_MATH", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 369, key: "ONLY_ACTIVE_ARCH", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 370, key: "PRODUCT_NAME", value: "\"$(TARGET_NAME)\"", }, BuildSettings { identation: "\t\t\t\t", line_number: 371, key: "SDKROOT", value: "iphoneos", }, BuildSettings { identation: "\t\t\t\t", line_number: 372, key: "SWIFT_ACTIVE_COMPILATION_CONDITIONS", value: "DEBUG", }, BuildSettings { identation: "\t\t\t\t", line_number: 373, key: "SWIFT_OPTIMIZATION_LEVEL", value: "\"-Onone\"", }, BuildSettings { identation: "\t\t\t\t", line_number: 374, key: "SWIFT_VERSION", value: "5.0", }, ], }, "BF284FE6E7AE0C8DDCCE398B": XCBuildConfiguration { build_settings: [ BuildSettings { identation: "\t\t\t\t", line_number: 381, key: "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 382, key: "ARCHS", value: "(\t\t\t\t\tarm64,\n\t\t\t\t);\n", }, BuildSettings { identation: "\t\t\t\t", line_number: 385, key: "ASSETCATALOG_COMPILER_APPICON_NAME", value: "AppIcon", }, BuildSettings { identation: "\t\t\t\t", line_number: 386, key: "CODE_SIGN_ENTITLEMENTS", value: "api_iOS/api_iOS.entitlements", }, BuildSettings { identation: "\t\t\t\t", line_number: 387, key: "CODE_SIGN_IDENTITY", value: "\"iPhone Developer\"", }, BuildSettings { identation: "\t\t\t\t", line_number: 388, key: "DEVELOPMENT_TEAM", value: "Q93MBH6S2F", }, BuildSettings { identation: "\t\t\t\t", line_number: 389, key: "ENABLE_BITCODE", value: "NO", }, BuildSettings { identation: "\t\t\t\t", line_number: 390, key: "\"EXCLUDED_ARCHS[sdk=iphoneos*]\"", value: "\"x86_64\"", }, BuildSettings { identation: "\t\t\t\t", line_number: 391, key: "FRAMEWORK_SEARCH_PATHS", value: "(\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"\\\".\\\"\",\n\t\t\t\t);\n", }, BuildSettings { identation: "\t\t\t\t", line_number: 395, key: "INFOPLIST_FILE", value: "api_iOS/Info.plist", }, BuildSettings { identation: "\t\t\t\t", line_number: 396, key: "LD_RUNPATH_SEARCH_PATHS", value: "(\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t);\n", }, BuildSettings { identation: "\t\t\t\t", line_number: 400, key: "\"LIBRARY_SEARCH_PATHS[arch=arm64]\"", value: "\"$(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)\"", }, BuildSettings { identation: "\t\t\t\t", line_number: 401, key: "\"LIBRARY_SEARCH_PATHS[arch=x86_64]\"", value: "\"$(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)\"", }, BuildSettings { identation: "\t\t\t\t", line_number: 402, key: "PRODUCT_BUNDLE_IDENTIFIER", value: "com.tauri.api", }, BuildSettings { identation: "\t\t\t\t", line_number: 403, key: "PRODUCT_NAME", value: "\"Tauri API\"", }, BuildSettings { identation: "\t\t\t\t", line_number: 404, key: "SDKROOT", value: "iphoneos", }, BuildSettings { identation: "\t\t\t\t", line_number: 405, key: "TARGETED_DEVICE_FAMILY", value: "\"1,2\"", }, BuildSettings { identation: "\t\t\t\t", line_number: 406, key: "VALID_ARCHS", value: "\"arm64\"", }, ], }, "DB_0E254D0FD84970B57F6410": XCBuildConfiguration { build_settings: [ BuildSettings { identation: "\t\t\t\t", line_number: 413, key: "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", value: "YES", }, BuildSettings { identation: "\t\t\t\t", line_number: 414, key: "ARCHS", value: "(\t\t\t\t\tarm64,\n\t\t\t\t);\n", }, BuildSettings { identation: "\t\t\t\t", line_number: 417, key: "ASSETCATALOG_COMPILER_APPICON_NAME", value: "AppIcon", }, BuildSettings { identation: "\t\t\t\t", line_number: 418, key: "CODE_SIGN_ENTITLEMENTS", value: "api_iOS/api_iOS.entitlements", }, BuildSettings { identation: "\t\t\t\t", line_number: 419, key: "CODE_SIGN_IDENTITY", value: "\"iPhone Developer\"", }, BuildSettings { identation: "\t\t\t\t", line_number: 420, key: "DEVELOPMENT_TEAM", value: "Q93MBH6S2F", }, BuildSettings { identation: "\t\t\t\t", line_number: 421, key: "ENABLE_BITCODE", value: "NO", }, BuildSettings { identation: "\t\t\t\t", line_number: 422, key: "\"EXCLUDED_ARCHS[sdk=iphoneos*]\"", value: "\"x86_64\"", }, BuildSettings { identation: "\t\t\t\t", line_number: 423, key: "FRAMEWORK_SEARCH_PATHS", value: "(\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"\\\".\\\"\",\n\t\t\t\t);\n", }, BuildSettings { identation: "\t\t\t\t", line_number: 427, key: "INFOPLIST_FILE", value: "api_iOS/Info.plist", }, BuildSettings { identation: "\t\t\t\t", line_number: 428, key: "LD_RUNPATH_SEARCH_PATHS", value: "(\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t);\n", }, BuildSettings { identation: "\t\t\t\t", line_number: 432, key: "\"LIBRARY_SEARCH_PATHS[arch=arm64]\"", value: "\"$(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)\"", }, BuildSettings { identation: "\t\t\t\t", line_number: 433, key: "\"LIBRARY_SEARCH_PATHS[arch=x86_64]\"", value: "\"$(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)\"", }, BuildSettings { identation: "\t\t\t\t", line_number: 434, key: "PRODUCT_BUNDLE_IDENTIFIER", value: "com.tauri.api", }, BuildSettings { identation: "\t\t\t\t", line_number: 435, key: "PRODUCT_NAME", value: "\"Tauri API\"", }, BuildSettings { identation: "\t\t\t\t", line_number: 436, key: "SDKROOT", value: "iphoneos", }, BuildSettings { identation: "\t\t\t\t", line_number: 437, key: "TARGETED_DEVICE_FAMILY", value: "\"1,2\"", }, BuildSettings { identation: "\t\t\t\t", line_number: 438, key: "VALID_ARCHS", value: "\"arm64\"", }, ], }, }, xc_configuration_list: { "01CBC40275452376830D79B1": XCConfigurationList { comment: "/* Build configuration list for PBXNativeTarget \"api_iOS\" */", build_configurations: [ BuildConfigurationRef { id: "BF284FE6E7AE0C8DDCCE398B", comments: "/* debug */", }, BuildConfigurationRef { id: "DB_0E254D0FD84970B57F6410", comments: "/* release */", }, ], }, "8FA67D0F928A09CD639137D1": XCConfigurationList { comment: "/* Build configuration list for PBXProject \"api\" */", build_configurations: [ BuildConfigurationRef { id: "B6AD77E490F315562F75D3D7", comments: "/* debug */", }, BuildConfigurationRef { id: "A83F70B4C02DD0222038C7F1", comments: "/* release */", }, ], }, }, } ================================================ FILE: crates/tauri-codegen/CHANGELOG.md ================================================ # Changelog ## \[2.5.5] ### Dependencies - Upgraded to `tauri-utils@2.8.3` ## \[2.5.4] ### Bug Fixes - [`eb5d88427`](https://www.github.com/tauri-apps/tauri/commit/eb5d88427a7dcb347fb0feae9e816db05b101844) ([#14883](https://www.github.com/tauri-apps/tauri/pull/14883) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix `tauri::Context` code generation failing with `can't capture dynamic environment in a fn item` when custom assets are provided. ## \[2.5.3] ### Dependencies - Upgraded to `tauri-utils@2.8.2` ## \[2.5.2] ### Dependencies - Upgraded to `tauri-utils@2.8.1` ## \[2.5.1] ### Performance Improvements - [`8e3bd63db`](https://www.github.com/tauri-apps/tauri/commit/8e3bd63db919a4cf72bb3d28028033d8654deb34) ([#14457](https://www.github.com/tauri-apps/tauri/pull/14457) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Wrap the generated context code in a function to make rust analyzer faster ## \[2.5.0] ### Bug Fixes - [`c5008b829`](https://www.github.com/tauri-apps/tauri/commit/c5008b829dc779f0768089bff9b891fc76b11355) ([#14274](https://www.github.com/tauri-apps/tauri/pull/14274)) Do not hash empty scripts when generating the Content-Security-Policy SHA-256 hashes. - [`7b0d4e732`](https://www.github.com/tauri-apps/tauri/commit/7b0d4e73227e42d88732b6d9fe643499dd78ec4e) ([#14265](https://www.github.com/tauri-apps/tauri/pull/14265)) Fix JavaScript SHA256 hash generation on Windows not ignoring carriage return characters. ### Dependencies - Upgraded to `tauri-utils@2.8.0` - [`6aa7f2d85`](https://www.github.com/tauri-apps/tauri/commit/6aa7f2d852870aeba1d4dd0e07f8be2bc9b66286) Upgraded to `tauri-utils@2.8.0` ## \[2.4.0] ### Dependencies - Upgraded to `tauri-utils@2.7.0`. ## \[2.3.1] ### Dependencies - Upgraded to `tauri-utils@2.6.0` ## \[2.3.0] ### New Features - [`414619c36`](https://www.github.com/tauri-apps/tauri/commit/414619c36e94e21939534dd72c0438b93da75546) ([#13536](https://www.github.com/tauri-apps/tauri/pull/13536) by [@Tunglies](https://www.github.com/tauri-apps/tauri/../../Tunglies)) Added support for the `bundleName` property in the macOS bundler configuration. This allows specifying the `CFBundleName` value for generated macOS bundles. ### What's Changed - [`168629646`](https://www.github.com/tauri-apps/tauri/commit/168629646335f24cc7f1c4a61df22688b2198f98) ([#13418](https://www.github.com/tauri-apps/tauri/pull/13418) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Put dynamic ACL into a feature `dynamic-acl`, this is currently enabled by default to align with the previous behaviors, you can disable it through `default-features = false` to reduce the final binary size by not including the ACL references ### Dependencies - Upgraded to `tauri-utils@2.5.0` ## \[2.2.0] ### Dependencies - Upgraded to `tauri-utils@2.4.0` - [`48b12b440`](https://www.github.com/tauri-apps/tauri/commit/48b12b440478937c46fdfef9f9d95194be117020) Update to `tauri-utils@2.4.0` ## \[2.1.1] ### Dependencies - Upgraded to `tauri-utils@2.3.1` ## \[2.1.0] ### New Features - [`013f8f652`](https://www.github.com/tauri-apps/tauri/commit/013f8f652302f2d49c5ec0a075582033d8b074fb) ([#12890](https://www.github.com/tauri-apps/tauri/pull/12890) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Added `build > removeUnusedCommands` to trigger the build scripts and macros to remove unused commands based on the capabilities you defined. Note this won't be accounting for dynamically added ACLs so make sure to check it when using this. ### Dependencies - Upgraded to `tauri-utils@2.3.0` ## \[2.0.5] ### Dependencies - Upgraded to `tauri-utils@2.2.0` ## \[2.0.4] ### Dependencies - Upgraded to `tauri-utils@2.1.1` ## \[2.0.3] ### Dependencies - Upgraded to `tauri-utils@2.1.0` ## \[2.0.2] ### Dependencies - Upgraded to `tauri-utils@2.0.2` ## \[2.0.1] ### What's Changed - [`0ab2b3306`](https://www.github.com/tauri-apps/tauri/commit/0ab2b330644b6419f6cee1d5377bfb5cdda2ccf9) ([#11205](https://www.github.com/tauri-apps/tauri/pull/11205) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Downgrade MSRV to 1.77.2 to support Windows 7. ### Dependencies - Upgraded to `tauri-utils@2.0.1` ## \[2.0.0] ### What's Changed - [`382ed482b`](https://www.github.com/tauri-apps/tauri/commit/382ed482bd08157c39e62f9a0aaad8802f1092cb) Bump MSRV to 1.78. - [`637285790`](https://www.github.com/tauri-apps/tauri/commit/6372857905ae9c0aedb7f482ddf6cf9f9836c9f2) Promote to v2 stable! ### Dependencies - Upgraded to `tauri-utils@2.0.0` ## \[2.0.0-rc.13] ### Bug Fixes - [`1efa5e718`](https://www.github.com/tauri-apps/tauri/commit/1efa5e7184009537b688a395596c696173ae0231) ([#11099](https://www.github.com/tauri-apps/tauri/pull/11099) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Rerun build script if the platform-specific configuration file changes. ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.13` ## \[2.0.0-rc.12] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.12` ## \[2.0.0-rc.11] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.11` ## \[2.0.0-rc.10] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.10` ## \[2.0.0-rc.9] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.9` ## \[2.0.0-rc.8] ### What's Changed - [`27d018343`](https://www.github.com/tauri-apps/tauri/commit/27d01834312ee7953b6ccd5b0a368e7a69b225e9) ([#10844](https://www.github.com/tauri-apps/tauri/pull/10844) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Changes how the Info.plist is embedded on macOS development to avoid a clippy warning. ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.8` ## \[2.0.0-rc.7] ### Bug Fixes - [`88bc35732`](https://www.github.com/tauri-apps/tauri/commit/88bc357325ba278527d8cba956e828f5744c8a34) ([#10734](https://www.github.com/tauri-apps/tauri/pull/10734) by [@chippers](https://www.github.com/tauri-apps/tauri/../../chippers)) Generate context in a separate thread to prevent a stack overflow. ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.7` ## \[2.0.0-rc.6] ### What's Changed - [`f4d5241b3`](https://www.github.com/tauri-apps/tauri/commit/f4d5241b377d0f7a1b58100ee19f7843384634ac) ([#10731](https://www.github.com/tauri-apps/tauri/pull/10731) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Update documentation icon path. ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.6` ## \[2.0.0-rc.5] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.5` ## \[2.0.0-rc.4] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.4` ## \[2.0.0-rc.3] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.3` - [`0afee5ed8`](https://www.github.com/tauri-apps/tauri/commit/0afee5ed80265c95c4581e173c4886677cfed593) ([#10436](https://www.github.com/tauri-apps/tauri/pull/10436) by [@nyurik](https://www.github.com/tauri-apps/tauri/../../nyurik)) Updated brotli to v6. ## \[2.0.0-rc.2] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.2` ## \[2.0.0-rc.1] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.1` ## \[2.0.0-rc.0] ### Enhancements - [`1e0793b68`](https://www.github.com/tauri-apps/tauri/commit/1e0793b6821799829e380c88066b3415cc9006df) ([#10357](https://www.github.com/tauri-apps/tauri/pull/10357)) Enhance `AssetResolver::get` in development mode by reading distDir directly as a fallback to the embedded assets. ### Bug Fixes - [`24445d71d`](https://www.github.com/tauri-apps/tauri/commit/24445d71de92d526d0ccaecb54f13003ddc6f6b4)([#10432](https://www.github.com/tauri-apps/tauri/pull/10432)) Fixes asset resolving when not using the `compression` feature. ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.0` ## \[2.0.0-beta.19] ### Bug Fixes - [`5d2922985`](https://www.github.com/tauri-apps/tauri/commit/5d2922985801908e4b929a7a0e387806ff02ab89) ([#10268](https://www.github.com/tauri-apps/tauri/pull/10268) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix icon rewriting always triggering build to rerun due to conflicts between file names. ### What's Changed - [`4c239729c`](https://www.github.com/tauri-apps/tauri/commit/4c239729c3e1b899ecbc6793c3682848e8de1729) ([#10167](https://www.github.com/tauri-apps/tauri/pull/10167) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add support for `test = true` in `generate_context!` macro to skip some code generation that could affect some tests, for now it only skips empedding a plist on macOS. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.19` ## \[2.0.0-beta.18] ### New Features - [`5b769948a`](https://www.github.com/tauri-apps/tauri/commit/5b769948a81cac333f64c870a470ba6525bd5cd3) ([#9959](https://www.github.com/tauri-apps/tauri/pull/9959)) Add `include_image_codegen` function to help embedding instances of `Image` struct at compile-time in rust to be used with window, menu or tray icons. ### Bug Fixes - [`1f6e478c8`](https://www.github.com/tauri-apps/tauri/commit/1f6e478c842a16219798b9962718e9ddb969c041) ([#9878](https://www.github.com/tauri-apps/tauri/pull/9878)) Fixes Info.plist rewriting always triggering build to rerun. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.18` ## \[2.0.0-beta.17] ### What's Changed - [`ccc3ea729`](https://www.github.com/tauri-apps/tauri/commit/ccc3ea729de205ef467f737f1feeb5bf02d9cd72)([#9646](https://www.github.com/tauri-apps/tauri/pull/9646)) Use `TAURI_ENV_TARGET_TRIPLE` (which is set by `tauri-build`) to determine the target when reading the config file. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.17` ## \[2.0.0-beta.16] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.16` ## \[2.0.0-beta.15] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.15` ## \[2.0.0-beta.14] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.14` ## \[2.0.0-beta.13] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.13` ## \[2.0.0-beta.12] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.12` ## \[2.0.0-beta.11] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.11` ## \[2.0.0-beta.10] ### New Features - [`e227fe02f`](https://www.github.com/tauri-apps/tauri/commit/e227fe02f986e145c0731a64693e1c830a9eb5b0)([#9156](https://www.github.com/tauri-apps/tauri/pull/9156)) Allow plugins to define (at compile time) JavaScript that are initialized when `withGlobalTauri` is true. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.10` ## \[2.0.0-beta.9] ### New Features - [`ba0206d8a`](https://www.github.com/tauri-apps/tauri/commit/ba0206d8a30a9b43ec5090dcaabd1a23baa1420c)([#9141](https://www.github.com/tauri-apps/tauri/pull/9141)) The `Context` codegen now accepts a `assets` input to define a custom `tauri::Assets` implementation. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.9` ## \[2.0.0-beta.8] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.8` ### Breaking Changes - [`ed48e2b3c`](https://www.github.com/tauri-apps/tauri/commit/ed48e2b3c7fa914e4c9af432c02b8154f872c68a)([#9122](https://www.github.com/tauri-apps/tauri/pull/9122)) Expose `tauri::image` module to export the `JsImage` type and removed the `Image` root re-export. ## \[2.0.0-beta.7] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.7` ### Breaking Changes - [`d1e77acd8`](https://www.github.com/tauri-apps/tauri/commit/d1e77acd8dfdf554b90b542513a58a2de1ef2360)([#9011](https://www.github.com/tauri-apps/tauri/pull/9011)) Change the generated context code to use the new `Image` type in tauri. ## \[2.0.0-beta.6] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.6` ### Breaking Changes - [`3657ad82`](https://www.github.com/tauri-apps/tauri/commit/3657ad82f88ce528551d032d521c52eed3f396b4)([#9008](https://www.github.com/tauri-apps/tauri/pull/9008)) Allow defining permissions for the application commands via `tauri_build::Attributes::app_manifest`. ## \[2.0.0-beta.5] ### Enhancements - [`bc5b5e67`](https://www.github.com/tauri-apps/tauri/commit/bc5b5e671a546512f823f1c157421b4c3311dfc0)([#8984](https://www.github.com/tauri-apps/tauri/pull/8984)) Do not include a CSP tag in the application HTML and rely on the custom protocol response header instead. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.5` ## \[2.0.0-beta.4] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.4` ## \[2.0.0-beta.3] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.3` ## \[2.0.0-beta.2] ### Enhancements - [`83a68deb`](https://www.github.com/tauri-apps/tauri/commit/83a68deb5676d39cd4728d2e140f6b46d5f787ed)([#8797](https://www.github.com/tauri-apps/tauri/pull/8797)) Added a new configuration option `tauri.conf.json > app > security > capabilities` to reference existing capabilities and inline new ones. If it is empty, all capabilities are still included preserving the current behavior. - [`8d16a80d`](https://www.github.com/tauri-apps/tauri/commit/8d16a80d2fb2468667e7987d0cc99dbc7e3b9d0a)([#8802](https://www.github.com/tauri-apps/tauri/pull/8802)) The `generate_context` proc macro now accepts a `capabilities` attribute where the value is an array of file paths that can be [conditionally compiled](https://doc.rust-lang.org/reference/conditional-compilation.html). These capabilities are added to the application along the capabilities defined in the Tauri configuration file. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.2` ## \[2.0.0-beta.1] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.1` ## \[2.0.0-beta.0] ### New Features - [`74a2a603`](https://www.github.com/tauri-apps/tauri/commit/74a2a6036a5e57462f161d728cbd8a6f121028ca)([#8661](https://www.github.com/tauri-apps/tauri/pull/8661)) Implement access control list for IPC usage. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.0` ### Breaking Changes - [`8de308d1`](https://www.github.com/tauri-apps/tauri/commit/8de308d1bf6a855d7a26af58bd0e744938ba47d8)([#8723](https://www.github.com/tauri-apps/tauri/pull/8723)) Restructured Tauri config per [RFC#5](https://github.com/tauri-apps/rfcs/blob/f3e82a6b0c5390401e855850d47dc7b7d9afd684/texts/0005-tauri-config-restructure.md): - Moved `package.productName`, `package.version` and `tauri.bundle.identifier` fields to the top-level. - Removed `package` object. - Renamed `tauri` object to `app`. - Moved `tauri.bundle` object to the top-level. - Renamed `build.distDir` field to `frontendDist`. - Renamed `build.devPath` field to `devUrl` and will no longer accepts paths, it will only accept URLs. - Moved `tauri.pattern` to `app.security.pattern`. - Removed `tauri.bundle.updater` object, and its fields have been moved to the updater plugin under `plugins.updater` object. - Moved `build.withGlobalTauri` to `app.withGlobalTauri`. - Moved `tauri.bundle.dmg` object to `bundle.macOS.dmg`. - Moved `tauri.bundle.deb` object to `bundle.linux.deb`. - Moved `tauri.bundle.appimage` object to `bundle.linux.appimage`. - Removed all license fields from each bundle configuration object and instead added `bundle.license` and `bundle.licenseFile`. - Renamed `AppUrl` to `FrontendDist` and refactored its variants to be more explicit. ## \[2.0.0-alpha.13] ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.13` ## \[2.0.0-alpha.12] ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.12` ## \[2.0.0-alpha.11] ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.11` ## \[2.0.0-alpha.10] ### Enhancements - [`c6c59cf2`](https://www.github.com/tauri-apps/tauri/commit/c6c59cf2373258b626b00a26f4de4331765dd487) Pull changes from Tauri 1.5 release. ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.10` ## \[2.0.0-alpha.9] ### New Features - [`880266a7`](https://www.github.com/tauri-apps/tauri/commit/880266a7f697e1fe58d685de3bb6836ce5251e92)([#8031](https://www.github.com/tauri-apps/tauri/pull/8031)) Bump the MSRV to 1.70. ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.9` ### Breaking Changes - [`ebcc21e4`](https://www.github.com/tauri-apps/tauri/commit/ebcc21e4b95f4e8c27639fb1bca545b432f52d5e)([#8057](https://www.github.com/tauri-apps/tauri/pull/8057)) Renamed the beforeDevCommand, beforeBuildCommand and beforeBundleCommand hooks environment variables from `TAURI_PLATFORM, TAURI_ARCH, TAURI_FAMILY, TAURI_PLATFORM_VERSION, TAURI_PLATFORM_TYPE and TAURI_DEBUG` to `TAURI_ENV_PLATFORM, TAURI_ENV_ARCH, TAURI_ENV_FAMILY, TAURI_ENV_PLATFORM_VERSION, TAURI_ENV_PLATFORM_TYPE and TAURI_ENV_DEBUG` to differentiate the prefix with other CLI environment variables. ## \[2.0.0-alpha.8] ### Enhancements - [`100d9ede`](https://www.github.com/tauri-apps/tauri/commit/100d9ede35995d9db21d2087dd5606adfafb89a5)([#7802](https://www.github.com/tauri-apps/tauri/pull/7802)) Use `Target` enum from `tauri_utils::platform`. ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.8` ## \[2.0.0-alpha.7] ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.7` ## \[2.0.0-alpha.6] ### Dependencies - Updated to latest `tauri-utils` ## \[2.0.0-alpha.5] - [`96639ca2`](https://www.github.com/tauri-apps/tauri/commit/96639ca239c9e4f75142fc07868ac46822111cff)([#6749](https://www.github.com/tauri-apps/tauri/pull/6749)) Moved the `shell` functionality to its own plugin in the plugins-workspace repository. - [`3188f376`](https://www.github.com/tauri-apps/tauri/commit/3188f3764978c6d1452ee31d5a91469691e95094)([#6883](https://www.github.com/tauri-apps/tauri/pull/6883)) Bump the MSRV to 1.65. - [`ae102980`](https://www.github.com/tauri-apps/tauri/commit/ae102980fcdde3f55effdc0623ea425b48d07dd1)([#6719](https://www.github.com/tauri-apps/tauri/pull/6719)) Refactor the `Context` conditional fields and only parse the tray icon on desktop. ## \[2.0.0-alpha.4] - Added `android` configuration object under `tauri > bundle`. - Bumped due to a bump in tauri-utils. - [db4c9dc6](https://www.github.com/tauri-apps/tauri/commit/db4c9dc655e07ee2184fe04571f500f7910890cd) feat(core): add option to configure Android's minimum SDK version ([#6651](https://www.github.com/tauri-apps/tauri/pull/6651)) on 2023-04-07 ## \[2.0.0-alpha.3] - Pull changes from Tauri 1.3 release. - [](https://www.github.com/tauri-apps/tauri/commit/undefined) on undefined ## \[2.0.0-alpha.2] - Return `bool` in the invoke handler. - [05dad087](https://www.github.com/tauri-apps/tauri/commit/05dad0876842e2a7334431247d49365cee835d3e) feat: initial work for iOS plugins ([#6205](https://www.github.com/tauri-apps/tauri/pull/6205)) on 2023-02-11 ## \[2.0.0-alpha.1] - Bump the MSRV to 1.64. - [7eb9aa75](https://www.github.com/tauri-apps/tauri/commit/7eb9aa75cfd6a3176d3f566fdda02d88aa529b0f) Update gtk to 0.16 ([#6155](https://www.github.com/tauri-apps/tauri/pull/6155)) on 2023-01-30 - Added `crate_name` field on `PackageInfo`. - [630a7f4b](https://www.github.com/tauri-apps/tauri/commit/630a7f4b18cef169bfd48673609306fec434e397) refactor: remove mobile log initialization, ref [#6049](https://www.github.com/tauri-apps/tauri/pull/6049) ([#6081](https://www.github.com/tauri-apps/tauri/pull/6081)) on 2023-01-17 ## \[2.0.0-alpha.0] - Change `devPath` URL to use the local IP address on iOS and Android. - [6f061504](https://www.github.com/tauri-apps/tauri/commit/6f0615044d09ec58393a7ebca5e45bb175e20db3) feat(cli): add `android dev` and `ios dev` commands ([#4982](https://www.github.com/tauri-apps/tauri/pull/4982)) on 2022-08-20 - First mobile alpha release! - [fa3a1098](https://www.github.com/tauri-apps/tauri/commit/fa3a10988a03aed1b66fb17d893b1a9adb90f7cd) feat(ci): prepare 2.0.0-alpha.0 ([#5786](https://www.github.com/tauri-apps/tauri/pull/5786)) on 2022-12-08 ## \[1.4.2] ### Dependencies - Upgraded to `tauri-utils@1.5.2` ## \[1.4.1] ### Dependencies - Upgraded to `tauri-utils@1.5.0` ## \[1.4.0] ### Enhancements - [`17d5a4f5`](https://www.github.com/tauri-apps/tauri/commit/17d5a4f51f244d3ff42014b5d1b075fad7c636a5)([#6706](https://www.github.com/tauri-apps/tauri/pull/6706)) Early panic if the PNG icon is not RGBA. - [`d2710e9d`](https://www.github.com/tauri-apps/tauri/commit/d2710e9d2e8fd93975ef6494512370faa8cb3b7e)([#6944](https://www.github.com/tauri-apps/tauri/pull/6944)) Unpin `time`, `ignore`, and `winnow` crate versions. Developers now have to pin crates if needed themselves. A list of crates that need pinning to adhere to Tauri's MSRV will be visible in Tauri's GitHub workflow: https://github.com/tauri-apps/tauri/blob/dev/.github/workflows/test-core.yml#L85. ## \[1.3.0] - Bump minimum supported Rust version to 1.60. - [5fdc616d](https://www.github.com/tauri-apps/tauri/commit/5fdc616df9bea633810dcb814ac615911d77222c) feat: Use the zbus-backed of notify-rust ([#6332](https://www.github.com/tauri-apps/tauri/pull/6332)) on 2023-03-31 - Pin `time` to `0.3.15`. - [3d16461b](https://www.github.com/tauri-apps/tauri/commit/3d16461b68583ba7db037fbc217786e79b46ddf2) fix(core): pin time to 0.3.15 ([#6312](https://www.github.com/tauri-apps/tauri/pull/6312)) on 2023-02-19 ## \[1.2.1] - Fix `allowlist > app > show/hide` always disabled when `allowlist > app > all: false`. - Bumped due to a bump in tauri-utils. - [bb251087](https://www.github.com/tauri-apps/tauri/commit/bb2510876d0bdff736d36bf3a465cdbe4ad2b90c) fix(core): extend allowlist with `app`'s allowlist, closes [#5650](https://www.github.com/tauri-apps/tauri/pull/5650) ([#5652](https://www.github.com/tauri-apps/tauri/pull/5652)) on 2022-11-18 ## \[1.2.0] - Properly serialize HTML template tags. - [aec5537d](https://www.github.com/tauri-apps/tauri/commit/aec5537de0205f62b2ae5c89da04d21930a6fc2e) fix(codegen): serialize template tags, closes [#4410](https://www.github.com/tauri-apps/tauri/pull/4410) ([#5247](https://www.github.com/tauri-apps/tauri/pull/5247)) on 2022-09-28 - - [7d9aa398](https://www.github.com/tauri-apps/tauri/commit/7d9aa3987efce2d697179ffc33646d086c68030c) feat: bump MSRV to 1.59 ([#5296](https://www.github.com/tauri-apps/tauri/pull/5296)) on 2022-09-28 ## \[1.1.1] - Add missing allowlist config for `set_cursor_grab`, `set_cursor_visible`, `set_cursor_icon` and `set_cursor_position` APIs. - Bumped due to a bump in tauri-utils. - [c764408d](https://www.github.com/tauri-apps/tauri/commit/c764408da7fae123edd41115bda42fa75a4731d2) fix: Add missing allowlist config for cursor apis, closes [#5207](https://www.github.com/tauri-apps/tauri/pull/5207) ([#5211](https://www.github.com/tauri-apps/tauri/pull/5211)) on 2022-09-16 ## \[1.1.0] - Use `TARGET` environment variable for code generation inside build scripts. - [6ba99689](https://www.github.com/tauri-apps/tauri/commit/6ba99689aa7ed0ffa9072a1c8ab5db12c9bf95af) feat(codegen): use TARGET environment variable if set ([#4921](https://www.github.com/tauri-apps/tauri/pull/4921)) on 2022-08-12 - Added support to configuration files in TOML format (Tauri.toml file). - [ae83d008](https://www.github.com/tauri-apps/tauri/commit/ae83d008f9e1b89bfc8dddaca42aa5c1fbc36f6d) feat: add support to TOML config file `Tauri.toml`, closes [#4806](https://www.github.com/tauri-apps/tauri/pull/4806) ([#4813](https://www.github.com/tauri-apps/tauri/pull/4813)) on 2022-08-02 - Improve tray icon read error message. - [52f0c8bb](https://www.github.com/tauri-apps/tauri/commit/52f0c8bb836c6d50b7ce2393161394f4ce78f5ae) feat(core): improve tray icon read error messages ([#4850](https://www.github.com/tauri-apps/tauri/pull/4850)) on 2022-08-03 - Fix relative paths in `version` field of `tauri.config.json` not being correctly parsed by `generate_context!()`. - [accbc5e8](https://www.github.com/tauri-apps/tauri/commit/accbc5e8806a32efc555d019634fc2fa14d17f0a) fix(codegen): fix relative paths in `version` field of `tauri.config.json`, closes [#4723](https://www.github.com/tauri-apps/tauri/pull/4723) ([#4725](https://www.github.com/tauri-apps/tauri/pull/4725)) on 2022-07-24 - Only rewrite temporary icon files when the content change, avoid needless rebuilds. - [f957cbb5](https://www.github.com/tauri-apps/tauri/commit/f957cbb56ccbd8d1c047a978b4579946252a6fd2) fix(codegen): write output file when contents change ([#4889](https://www.github.com/tauri-apps/tauri/pull/4889)) on 2022-08-09 ## \[1.0.4] - Validate `__TAURI_ISOLATION_HOOK__` being set by a file in the isolation application. - [3b4ed970](https://www.github.com/tauri-apps/tauri/commit/3b4ed970e663f5bffbfe0358610f9c3f157c513f) feat(codegen): validate `__TAURI_ISOLATION_HOOK__` is referenced ([#4631](https://www.github.com/tauri-apps/tauri/pull/4631)) on 2022-07-11 ## \[1.0.3] - The `TAURI_CONFIG` environment variable now represents the configuration to be merged instead of the entire JSON. - [fa028ebf](https://www.github.com/tauri-apps/tauri/commit/fa028ebf3c8ca7b43a70d283a01dbea86217594f) refactor: do not pass entire config from CLI to core, send patch instead ([#4598](https://www.github.com/tauri-apps/tauri/pull/4598)) on 2022-07-06 ## \[1.0.2] - Expose `platform::windows_version` function. - Bumped due to a bump in tauri-utils. - [bf764e83](https://www.github.com/tauri-apps/tauri/commit/bf764e83e01e7443e6cc54572001e1c98c357465) feat(utils): expose `windows_version` function ([#4534](https://www.github.com/tauri-apps/tauri/pull/4534)) on 2022-06-30 ## \[1.0.1] - Set the bundle name and app metadata in the Info.plist file in development mode. - [38f5db6e](https://www.github.com/tauri-apps/tauri/commit/38f5db6e6a8b496b50d486db6fd8204266de3a69) feat(codegen): fill app metadata in development Info.plist on 2022-06-21 - Set the application icon in development mode on macOS. - [307c2ebf](https://www.github.com/tauri-apps/tauri/commit/307c2ebfb68238dacab6088f9c6ba310c727c68c) feat(core): set macOS app icon in development ([#4385](https://www.github.com/tauri-apps/tauri/pull/4385)) on 2022-06-19 ## \[1.0.0] - Upgrade to `stable`! - [f4bb30cc](https://www.github.com/tauri-apps/tauri/commit/f4bb30cc73d6ba9b9ef19ef004dc5e8e6bb901d3) feat(covector): prepare for v1 ([#4351](https://www.github.com/tauri-apps/tauri/pull/4351)) on 2022-06-15 ## \[1.0.0-rc.11] - Read the tray icon path relatively to the config directory. - [562e8ca2](https://www.github.com/tauri-apps/tauri/commit/562e8ca23facf1a8e5fa6c8cdf872357d3523a78) fix(codegen): tray icon path is relative to the config directory on 2022-06-15 ## \[1.0.0-rc.10] - **Breaking change:** The `TrayIcon` enum has been removed and now `Icon` is used instead. This allows you to use more image formats and use embedded icons on Linux. - [4ce8e228](https://www.github.com/tauri-apps/tauri/commit/4ce8e228134cd3f22973b74ef26ca0d165fbbbd9) refactor(core): use `Icon` for tray icons ([#4342](https://www.github.com/tauri-apps/tauri/pull/4342)) on 2022-06-14 ## \[1.0.0-rc.9] - Added a config flag to bundle the media framework used by webkit2gtk `tauri.conf.json > tauri > bundle > appimage > bundleMediaFramework`. - Bumped due to a bump in tauri-utils. - [d335fae9](https://www.github.com/tauri-apps/tauri/commit/d335fae92cdcbb0ee18aad4e54558914afa3e778) feat(bundler): bundle additional gstreamer files, closes [#4092](https://www.github.com/tauri-apps/tauri/pull/4092) ([#4271](https://www.github.com/tauri-apps/tauri/pull/4271)) on 2022-06-10 ## \[1.0.0-rc.8] - **Breaking change:** `PackageInfo::version` is now a `semver::Version` instead of a `String`. - [2badbd2d](https://www.github.com/tauri-apps/tauri/commit/2badbd2d7ed51bf33c1b547b4c837b600574bd4a) refactor: force semver versions, change updater `should_install` sig ([#4215](https://www.github.com/tauri-apps/tauri/pull/4215)) on 2022-05-25 - [a7388e23](https://www.github.com/tauri-apps/tauri/commit/a7388e23c3b9019d48b078cae00a75c74d74d11b) fix(ci): adjust change file to include tauri-utils and tauri-codegen on 2022-05-27 ## \[1.0.0-rc.7] - Allow configuring the display options for the MSI execution allowing quieter updates. - Bumped due to a bump in tauri-utils. - [9f2c3413](https://www.github.com/tauri-apps/tauri/commit/9f2c34131952ea83c3f8e383bc3cec7e1450429f) feat(core): configure msiexec display options, closes [#3951](https://www.github.com/tauri-apps/tauri/pull/3951) ([#4061](https://www.github.com/tauri-apps/tauri/pull/4061)) on 2022-05-15 ## \[1.0.0-rc.6] - The `dangerous_allow_asset_csp_modification` configuration value has been changed to allow a list of CSP directives to disable. - [164078c0](https://www.github.com/tauri-apps/tauri/commit/164078c0b719ccbc12e956fecf8a7d4a3c5044e1) feat: allow limiting dangerousDisableAssetCspModification, closes [#3831](https://www.github.com/tauri-apps/tauri/pull/3831) ([#4021](https://www.github.com/tauri-apps/tauri/pull/4021)) on 2022-05-02 ## \[1.0.0-rc.5] - Read platform-specific configuration files when generating code without the `TAURI_CONFIG` env var. - [edf85bc1](https://www.github.com/tauri-apps/tauri/commit/edf85bc1d18450c92aee17f7f99c163abe432ebd) fix(codegen): read platform-specific config file ([#3966](https://www.github.com/tauri-apps/tauri/pull/3966)) on 2022-04-25 ## \[1.0.0-rc.4] - Added an option to disable the CSP injection of distributable assets nonces and hashes. - [f6e32ee1](https://www.github.com/tauri-apps/tauri/commit/f6e32ee1880eb364ed76beb937c9d12e14d54910) feat(core): add dangerous option to disable compile time CSP injection ([#3775](https://www.github.com/tauri-apps/tauri/pull/3775)) on 2022-03-28 - Replace multiple dependencies who's C code compiled concurrently and caused the other ones to bloat compile time significantly. - `zstd` -> `brotli` - `blake3` -> a vendored version of the blake3 reference - `ring` -> `getrandom` See https://github.com/tauri-apps/tauri/pull/3773 for more information about these specific choices. - [8661e3e2](https://www.github.com/tauri-apps/tauri/commit/8661e3e24d96c399bfbcdee5d8e9d6beba2265a7) replace dependencies with long build times when used together (closes [#3571](https://www.github.com/tauri-apps/tauri/pull/3571)) ([#3773](https://www.github.com/tauri-apps/tauri/pull/3773)) on 2022-03-27 ## \[1.0.0-rc.3] - Parse window icons at compile time. - [8c935872](https://www.github.com/tauri-apps/tauri/commit/8c9358725a17dcc2acaf4d10c3f654afdff586b0) refactor(core): move `png` and `ico` behind Cargo features ([#3588](https://www.github.com/tauri-apps/tauri/pull/3588)) on 2022-03-05 ## \[1.0.0-rc.2] - Changed the default value for `tauri > bundle > macOS > minimumSystemVersion` to `10.13`. - Bumped due to a bump in tauri-utils. - [fce344b9](https://www.github.com/tauri-apps/tauri/commit/fce344b90b7227f8f5514853c2f885fb24d3648e) feat(core): set default value for `minimum_system_version` to 10.13 ([#3497](https://www.github.com/tauri-apps/tauri/pull/3497)) on 2022-02-17 ## \[1.0.0-rc.1] - Change default value for the `freezePrototype` configuration to `false`. - Bumped due to a bump in tauri-utils. - [3a4c0160](https://www.github.com/tauri-apps/tauri/commit/3a4c01606184be762adee055ddac803de0d28527) fix(core): change default `freezePrototype` to false, closes [#3416](https://www.github.com/tauri-apps/tauri/pull/3416) [#3406](https://www.github.com/tauri-apps/tauri/pull/3406) ([#3423](https://www.github.com/tauri-apps/tauri/pull/3423)) on 2022-02-12 ## \[1.0.0-rc.0] - Apply `nonce` to `script` and `style` tags and set them on the `CSP` (`script-src` and `style-src` fetch directives). - [cf54dcf9](https://www.github.com/tauri-apps/tauri/commit/cf54dcf9c81730e42c9171daa9c8aa474c95b522) feat: improve `CSP` security with nonces and hashes, add `devCsp` \[TRI-004] ([#8](https://www.github.com/tauri-apps/tauri/pull/8)) on 2022-01-09 - Added the `isolation` pattern. - [d5d6d2ab](https://www.github.com/tauri-apps/tauri/commit/d5d6d2abc17cd89c3a079d2ce01581193469dbc0) Isolation Pattern ([#43](https://www.github.com/tauri-apps/tauri/pull/43)) Co-authored-by: Ngo Iok Ui (Wu Yu Wei) Co-authored-by: Lucas Fernandes Nogueira on 2022-01-17 - Adds support for using JSON5 format for the `tauri.conf.json` file, along with also supporting the `.json5` extension. Here is the logic flow that determines if JSON or JSON5 will be used to parse the config: 1. Check if `tauri.conf.json` exists a. Parse it with `serde_json` b. Parse it with `json5` if `serde_json` fails c. Return original `serde_json` error if all above steps failed 2. Check if `tauri.conf.json5` exists a. Parse it with `json5` b. Return error if all above steps failed 3. Return error if all above steps failed - [995de57a](https://www.github.com/tauri-apps/tauri/commit/995de57a76cf51215277673e526d7ec32b86b564) Add seamless support for using JSON5 in the config file ([#47](https://www.github.com/tauri-apps/tauri/pull/47)) on 2022-02-03 - The minimum Rust version is now `1.56`. - [a9dfc015](https://www.github.com/tauri-apps/tauri/commit/a9dfc015505afe91281c2027954ffcc588b1a59c) feat: update to edition 2021 and set minimum rust to 1.56 ([#2789](https://www.github.com/tauri-apps/tauri/pull/2789)) on 2021-10-22 ## \[1.0.0-beta.4] - Embed Info.plist file contents on binary on dev. - [537ab1b6](https://www.github.com/tauri-apps/tauri/commit/537ab1b6d5a792c550a535619965c9e4126292e6) feat(core): inject src-tauri/Info.plist file on dev and merge on bundle, closes [#1570](https://www.github.com/tauri-apps/tauri/pull/1570) [#2338](https://www.github.com/tauri-apps/tauri/pull/2338) ([#2444](https://www.github.com/tauri-apps/tauri/pull/2444)) on 2021-08-15 - Fix ES Module detection for default imports with relative paths or scoped packages and exporting of async functions. - [b2b36cfe](https://www.github.com/tauri-apps/tauri/commit/b2b36cfe8dfcccb341638a4cb6dc23a514c54148) fix(core): fixes ES Module detection for default imports with relative paths or scoped packages ([#2380](https://www.github.com/tauri-apps/tauri/pull/2380)) on 2021-08-10 - [fbf8caf5](https://www.github.com/tauri-apps/tauri/commit/fbf8caf5c419cb4fc3d123be910e094a8e8c4bef) fix(core): ESM detection when using `export async function` ([#2425](https://www.github.com/tauri-apps/tauri/pull/2425)) on 2021-08-14 ## \[1.0.0-beta.3] - Improve ESM detection with regexes. - [4b0ec018](https://www.github.com/tauri-apps/tauri/commit/4b0ec0188078a8fefd4119fe5e19ebc30191f802) fix(core): improve JS ESM detection ([#2139](https://www.github.com/tauri-apps/tauri/pull/2139)) on 2021-07-02 - Inject invoke key on `script` tags with `type="module"`. - [f03eea9c](https://www.github.com/tauri-apps/tauri/commit/f03eea9c9b964709532afbc4d1dd343b3fd96081) feat(core): inject invoke key on ``). Maps a HTML path to a list of hashes. pub(crate) inline_scripts: HashMap>, /// A list of hashes of the contents of all `style` elements. pub(crate) styles: Vec, } impl CspHashes { /// Only add a CSP hash to the appropriate category if we think the file matches /// /// Note: this only checks the file extension, much like how a browser will assume a .js file is /// a JavaScript file unless HTTP headers tell it otherwise. pub fn add_if_applicable( &mut self, entry: &DirEntry, dangerous_disable_asset_csp_modification: &DisabledCspModificationKind, ) -> Result<(), EmbeddedAssetsError> { let path = entry.path(); // we only hash JavaScript files for now, may expand to other CSP hashable types in the future if let Some("js") | Some("mjs") = path.extension().and_then(|os| os.to_str()) { if dangerous_disable_asset_csp_modification.can_modify("script-src") { let mut hasher = Sha256::new(); hasher.update( &std::fs::read(path) .map(|b| tauri_utils::html::normalize_script_for_csp(&b)) .map_err(|error| EmbeddedAssetsError::AssetRead { path: path.to_path_buf(), error, })?, ); let hash = hasher.finalize(); self.scripts.push(format!( "'sha256-{}'", base64::engine::general_purpose::STANDARD.encode(hash) )); } } Ok(()) } } /// Options used to embed assets. #[derive(Default)] pub struct AssetOptions { pub(crate) csp: bool, pub(crate) pattern: PatternKind, pub(crate) freeze_prototype: bool, pub(crate) dangerous_disable_asset_csp_modification: DisabledCspModificationKind, #[cfg(feature = "isolation")] pub(crate) isolation_schema: String, } impl AssetOptions { /// Creates the default asset options. pub fn new(pattern: PatternKind) -> Self { Self { csp: false, pattern, freeze_prototype: false, dangerous_disable_asset_csp_modification: DisabledCspModificationKind::Flag(false), #[cfg(feature = "isolation")] isolation_schema: format!("isolation-{}", uuid::Uuid::new_v4()), } } /// Instruct the asset handler to inject the CSP token to HTML files (Linux only) and add asset nonces and hashes to the policy. #[must_use] pub fn with_csp(mut self) -> Self { self.csp = true; self } /// Instruct the asset handler to include a script to freeze the `Object.prototype` on all HTML files. #[must_use] pub fn freeze_prototype(mut self, freeze: bool) -> Self { self.freeze_prototype = freeze; self } /// Instruct the asset handler to **NOT** modify the CSP. This is **NOT** recommended. pub fn dangerous_disable_asset_csp_modification( mut self, dangerous_disable_asset_csp_modification: DisabledCspModificationKind, ) -> Self { self.dangerous_disable_asset_csp_modification = dangerous_disable_asset_csp_modification; self } } impl EmbeddedAssets { /// Compress a collection of files and directories, ready to be generated into [`Assets`]. /// /// [`Assets`]: tauri_utils::assets::Assets pub fn new( input: impl Into, options: &AssetOptions, mut map: impl FnMut( &AssetKey, &Path, &mut Vec, &mut CspHashes, ) -> Result<(), EmbeddedAssetsError>, ) -> Result { // we need to pre-compute all files now, so that we can inject data from all files into a few let RawEmbeddedAssets { paths, csp_hashes } = RawEmbeddedAssets::new(input.into(), options)?; struct CompressState { csp_hashes: CspHashes, assets: HashMap, } let CompressState { assets, csp_hashes } = paths.into_iter().try_fold( CompressState { csp_hashes, assets: HashMap::new(), }, move |mut state, (prefix, entry)| { let (key, asset) = Self::compress_file(&prefix, entry.path(), &mut map, &mut state.csp_hashes)?; state.assets.insert(key, asset); Result::<_, EmbeddedAssetsError>::Ok(state) }, )?; Ok(Self { assets, csp_hashes }) } /// Use highest compression level for release, the fastest one for everything else #[cfg(feature = "compression")] fn compression_settings() -> BrotliEncoderParams { let mut settings = BrotliEncoderParams::default(); // the following compression levels are hand-picked and are not min-maxed. // they have a good balance of runtime vs size for the respective profile goals. // see the "brotli" section of this comment https://github.com/tauri-apps/tauri/issues/3571#issuecomment-1054847558 if cfg!(debug_assertions) { settings.quality = 2 } else { settings.quality = 9 } settings } /// Compress a file and spit out the information in a [`HashMap`] friendly form. fn compress_file( prefix: &Path, path: &Path, map: &mut impl FnMut( &AssetKey, &Path, &mut Vec, &mut CspHashes, ) -> Result<(), EmbeddedAssetsError>, csp_hashes: &mut CspHashes, ) -> Result { let mut input = std::fs::read(path).map_err(|error| EmbeddedAssetsError::AssetRead { path: path.to_owned(), error, })?; // get a key to the asset path without the asset directory prefix let key = path .strip_prefix(prefix) .map(AssetKey::from) // format the path for use in assets .map_err(|_| EmbeddedAssetsError::PrefixInvalid { prefix: prefix.to_owned(), path: path.to_owned(), })?; // perform any caller-requested input manipulation map(&key, path, &mut input, csp_hashes)?; // we must canonicalize the base of our paths to allow long paths on windows let out_dir = std::env::var("OUT_DIR") .map_err(|_| EmbeddedAssetsError::OutDir) .map(PathBuf::from) .and_then(|p| p.canonicalize().map_err(|_| EmbeddedAssetsError::OutDir)) .map(|p| p.join(TARGET_PATH))?; // make sure that our output directory is created std::fs::create_dir_all(&out_dir).map_err(|_| EmbeddedAssetsError::OutDir)?; // get a hash of the input - allows for caching existing files let hash = crate::checksum(&input).map_err(EmbeddedAssetsError::Hex)?; // use the content hash to determine filename, keep extensions that exist let out_path = if let Some(ext) = path.extension().and_then(|e| e.to_str()) { out_dir.join(format!("{hash}.{ext}")) } else { out_dir.join(hash) }; // only compress and write to the file if it doesn't already exist. if !out_path.exists() { #[allow(unused_mut)] let mut out_file = File::create(&out_path).map_err(|error| EmbeddedAssetsError::AssetWrite { path: out_path.clone(), error, })?; #[cfg(not(feature = "compression"))] { use std::io::Write; out_file .write_all(&input) .map_err(|error| EmbeddedAssetsError::AssetWrite { path: path.to_owned(), error, })?; } #[cfg(feature = "compression")] { let mut input = std::io::Cursor::new(input); // entirely write input to the output file path with compression brotli::BrotliCompress(&mut input, &mut out_file, &Self::compression_settings()).map_err( |error| EmbeddedAssetsError::AssetWrite { path: path.to_owned(), error, }, )?; } } Ok((key, (path.into(), out_path))) } } impl ToTokens for EmbeddedAssets { fn to_tokens(&self, tokens: &mut TokenStream) { let mut assets = TokenStream::new(); for (key, (input, output)) in &self.assets { let key: &str = key.as_ref(); let input = input.display().to_string(); let output = output.display().to_string(); // add original asset as a compiler dependency, rely on dead code elimination to clean it up assets.append_all(quote!(#key => { const _: &[u8] = include_bytes!(#input); include_bytes!(#output) },)); } let mut global_hashes = TokenStream::new(); for script_hash in &self.csp_hashes.scripts { let hash = script_hash.as_str(); global_hashes.append_all(quote!(CspHash::Script(#hash),)); } for style_hash in &self.csp_hashes.styles { let hash = style_hash.as_str(); global_hashes.append_all(quote!(CspHash::Style(#hash),)); } let mut html_hashes = TokenStream::new(); for (path, hashes) in &self.csp_hashes.inline_scripts { let key = path.as_str(); let mut value = TokenStream::new(); for script_hash in hashes { let hash = script_hash.as_str(); value.append_all(quote!(CspHash::Script(#hash),)); } html_hashes.append_all(quote!(#key => &[#value],)); } // we expect phf related items to be in path when generating the path code tokens.append_all(quote! {{ #[allow(unused_imports)] use ::tauri::utils::assets::{CspHash, EmbeddedAssets, phf, phf::phf_map}; EmbeddedAssets::new(phf_map! { #assets }, &[#global_hashes], phf_map! { #html_hashes }) }}); } } pub(crate) fn ensure_out_dir() -> EmbeddedAssetsResult { let out_dir = std::env::var("OUT_DIR") .map_err(|_| EmbeddedAssetsError::OutDir) .map(PathBuf::from) .and_then(|p| p.canonicalize().map_err(|_| EmbeddedAssetsError::OutDir))?; // make sure that our output directory is created std::fs::create_dir_all(&out_dir).map_err(|_| EmbeddedAssetsError::OutDir)?; Ok(out_dir) } ================================================ FILE: crates/tauri-codegen/src/image.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use crate::{ embedded_assets::{EmbeddedAssetsError, EmbeddedAssetsResult}, Cached, }; use proc_macro2::TokenStream; use quote::{quote, ToTokens, TokenStreamExt}; use std::{ffi::OsStr, io::Cursor, path::Path}; /// The format the Icon is consumed as. pub(crate) enum IconFormat { /// The image, completely unmodified. Raw, /// RGBA raw data, meant to be consumed by [`tauri::image::Image`]. Image { width: u32, height: u32 }, } pub struct CachedIcon { cache: Cached, format: IconFormat, root: TokenStream, } impl CachedIcon { pub fn new(root: &TokenStream, icon: &Path) -> EmbeddedAssetsResult { match icon.extension().map(OsStr::to_string_lossy).as_deref() { Some("png") => Self::new_png(root, icon), Some("ico") => Self::new_ico(root, icon), unknown => Err(EmbeddedAssetsError::InvalidImageExtension { extension: unknown.unwrap_or_default().into(), path: icon.to_path_buf(), }), } } /// Cache the icon without any manipulation. pub fn new_raw(root: &TokenStream, icon: &Path) -> EmbeddedAssetsResult { let buf = Self::open(icon); Cached::try_from(buf).map(|cache| Self { cache, root: root.clone(), format: IconFormat::Raw, }) } /// Cache an ICO icon as RGBA data, see [`ImageFormat::Image`]. pub fn new_ico(root: &TokenStream, icon: &Path) -> EmbeddedAssetsResult { let buf = Self::open(icon); let icon_dir = ico::IconDir::read(Cursor::new(&buf)) .unwrap_or_else(|e| panic!("failed to parse icon {}: {}", icon.display(), e)); let entry = &icon_dir.entries()[0]; let rgba = entry .decode() .unwrap_or_else(|e| panic!("failed to decode icon {}: {}", icon.display(), e)) .rgba_data() .to_vec(); Cached::try_from(rgba).map(|cache| Self { cache, root: root.clone(), format: IconFormat::Image { width: entry.width(), height: entry.height(), }, }) } /// Cache a PNG icon as RGBA data, see [`ImageFormat::Image`]. pub fn new_png(root: &TokenStream, icon: &Path) -> EmbeddedAssetsResult { let buf = Self::open(icon); let decoder = png::Decoder::new(Cursor::new(&buf)); let mut reader = decoder .read_info() .unwrap_or_else(|e| panic!("failed to read icon {}: {}", icon.display(), e)); if reader.output_color_type().0 != png::ColorType::Rgba { panic!("icon {} is not RGBA", icon.display()); } let mut rgba = Vec::with_capacity(reader.output_buffer_size()); while let Ok(Some(row)) = reader.next_row() { rgba.extend(row.data()); } Cached::try_from(rgba).map(|cache| Self { cache, root: root.clone(), format: IconFormat::Image { width: reader.info().width, height: reader.info().height, }, }) } fn open(path: &Path) -> Vec { std::fs::read(path).unwrap_or_else(|e| panic!("failed to open icon {}: {}", path.display(), e)) } } impl ToTokens for CachedIcon { fn to_tokens(&self, tokens: &mut TokenStream) { let root = &self.root; let cache = &self.cache; let raw = quote!(::std::include_bytes!(#cache)); tokens.append_all(match self.format { IconFormat::Raw => raw, IconFormat::Image { width, height } => { quote!(#root::image::Image::new(#raw, #width, #height)) } }) } } ================================================ FILE: crates/tauri-codegen/src/lib.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT //! - Embed, hash, and compress assets, including icons for the app as well as the tray icon. //! - Parse `tauri.conf.json` at compile time and generate the Config struct. #![doc( html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png", html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png" )] pub use self::context::{context_codegen, ContextData}; use crate::embedded_assets::{ensure_out_dir, EmbeddedAssetsError}; use proc_macro2::TokenStream; use quote::{quote, ToTokens, TokenStreamExt}; use std::{ borrow::Cow, fmt::{self, Write}, path::{Path, PathBuf}, }; pub use tauri_utils::config::{parse::ConfigError, Config}; use tauri_utils::platform::Target; use tauri_utils::write_if_changed; mod context; pub mod embedded_assets; pub mod image; #[doc(hidden)] pub mod vendor; /// Represents all the errors that can happen while reading the config during codegen. #[derive(Debug, thiserror::Error)] #[non_exhaustive] pub enum CodegenConfigError { #[error("unable to access current working directory: {0}")] CurrentDir(std::io::Error), // this error should be "impossible" because we use std::env::current_dir() - cover it anyways #[error("Tauri config file has no parent, this shouldn't be possible. file an issue on https://github.com/tauri-apps/tauri - target {0}")] Parent(PathBuf), #[error("unable to parse inline JSON TAURI_CONFIG env var: {0}")] FormatInline(serde_json::Error), #[error(transparent)] Json(#[from] serde_json::Error), #[error("{0}")] ConfigError(#[from] ConfigError), } /// Get the [`Config`] from the `TAURI_CONFIG` environmental variable, or read from the passed path. /// /// If the passed path is relative, it should be relative to the current working directory of the /// compiling crate. pub fn get_config(path: &Path) -> Result<(Config, PathBuf), CodegenConfigError> { let path = if path.is_relative() { let cwd = std::env::current_dir().map_err(CodegenConfigError::CurrentDir)?; Cow::Owned(cwd.join(path)) } else { Cow::Borrowed(path) }; // this should be impossible because of the use of `current_dir()` above, but handle it anyways let parent = path .parent() .map(ToOwned::to_owned) .ok_or_else(|| CodegenConfigError::Parent(path.into_owned()))?; let target = std::env::var("TAURI_ENV_TARGET_TRIPLE") .as_deref() .map(Target::from_triple) .unwrap_or_else(|_| Target::current()); // in the future we may want to find a way to not need the TAURI_CONFIG env var so that // it is impossible for the content of two separate configs to get mixed up. The chances are // already unlikely unless the developer goes out of their way to run the cli on a different // project than the target crate. let mut config = serde_json::from_value(tauri_utils::config::parse::read_from(target, &parent)?.0)?; if let Ok(env) = std::env::var("TAURI_CONFIG") { let merge_config: serde_json::Value = serde_json::from_str(&env).map_err(CodegenConfigError::FormatInline)?; json_patch::merge(&mut config, &merge_config); } // Set working directory to where `tauri.config.json` is, so that relative paths in it are parsed correctly. let old_cwd = std::env::current_dir().map_err(CodegenConfigError::CurrentDir)?; std::env::set_current_dir(parent.clone()).map_err(CodegenConfigError::CurrentDir)?; let config = serde_json::from_value(config)?; // Reset working directory. std::env::set_current_dir(old_cwd).map_err(CodegenConfigError::CurrentDir)?; Ok((config, parent)) } /// Create a blake3 checksum of the passed bytes. fn checksum(bytes: &[u8]) -> Result { let mut hasher = vendor::blake3_reference::Hasher::default(); hasher.update(bytes); let mut bytes = [0u8; 32]; hasher.finalize(&mut bytes); let mut hex = String::with_capacity(2 * bytes.len()); for b in bytes { write!(hex, "{b:02x}")?; } Ok(hex) } /// Cache the data to `$OUT_DIR`, only if it does not already exist. /// /// Due to using a checksum as the filename, an existing file should be the exact same content /// as the data being checked. struct Cached { checksum: String, } impl TryFrom for Cached { type Error = EmbeddedAssetsError; fn try_from(value: String) -> Result { Self::try_from(Vec::from(value)) } } impl TryFrom> for Cached { type Error = EmbeddedAssetsError; fn try_from(content: Vec) -> Result { let checksum = checksum(content.as_ref()).map_err(EmbeddedAssetsError::Hex)?; let path = ensure_out_dir()?.join(&checksum); write_if_changed(&path, &content) .map(|_| Self { checksum }) .map_err(|error| EmbeddedAssetsError::AssetWrite { path, error }) } } impl ToTokens for Cached { fn to_tokens(&self, tokens: &mut TokenStream) { let path = &self.checksum; tokens.append_all(quote!(::std::concat!(::std::env!("OUT_DIR"), "/", #path))) } } ================================================ FILE: crates/tauri-codegen/src/vendor/blake3_reference.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT //! This is a lightly modified version of the BLAKE3 reference implementation. //! //! The changes applied are to remove unused item warnings due to using it //! vendored along with some minor clippy suggestions. No logic changes. I //! suggest diffing against the original to find all the changes. //! //! ## Original Header //! This is the reference implementation of BLAKE3. It is used for testing and //! as a readable example of the algorithms involved. Section 5.1 of [the BLAKE3 //! spec](https://github.com/BLAKE3-team/BLAKE3-specs/blob/master/blake3.pdf) //! discusses this implementation. You can render docs for this implementation //! by running `cargo doc --open` in this directory. //! //! # Example //! //! ``` //! let mut hasher = tauri_codegen::vendor::blake3_reference::Hasher::new(); //! hasher.update(b"abc"); //! hasher.update(b"def"); //! let mut hash = [0; 32]; //! hasher.finalize(&mut hash); //! let mut extended_hash = [0; 500]; //! hasher.finalize(&mut extended_hash); //! assert_eq!(hash, extended_hash[..32]); //! ``` //! //! CC0-1.0 OR Apache-2.0 use core::cmp::min; use core::convert::TryInto; const OUT_LEN: usize = 32; const BLOCK_LEN: usize = 64; const CHUNK_LEN: usize = 1024; const CHUNK_START: u32 = 1 << 0; const CHUNK_END: u32 = 1 << 1; const PARENT: u32 = 1 << 2; const ROOT: u32 = 1 << 3; const IV: [u32; 8] = [ 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19, ]; const MSG_PERMUTATION: [usize; 16] = [2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8]; // The mixing function, G, which mixes either a column or a diagonal. fn g(state: &mut [u32; 16], a: usize, b: usize, c: usize, d: usize, mx: u32, my: u32) { state[a] = state[a].wrapping_add(state[b]).wrapping_add(mx); state[d] = (state[d] ^ state[a]).rotate_right(16); state[c] = state[c].wrapping_add(state[d]); state[b] = (state[b] ^ state[c]).rotate_right(12); state[a] = state[a].wrapping_add(state[b]).wrapping_add(my); state[d] = (state[d] ^ state[a]).rotate_right(8); state[c] = state[c].wrapping_add(state[d]); state[b] = (state[b] ^ state[c]).rotate_right(7); } fn round(state: &mut [u32; 16], m: &[u32; 16]) { // Mix the columns. g(state, 0, 4, 8, 12, m[0], m[1]); g(state, 1, 5, 9, 13, m[2], m[3]); g(state, 2, 6, 10, 14, m[4], m[5]); g(state, 3, 7, 11, 15, m[6], m[7]); // Mix the diagonals. g(state, 0, 5, 10, 15, m[8], m[9]); g(state, 1, 6, 11, 12, m[10], m[11]); g(state, 2, 7, 8, 13, m[12], m[13]); g(state, 3, 4, 9, 14, m[14], m[15]); } fn permute(m: &mut [u32; 16]) { let mut permuted = [0; 16]; for i in 0..16 { permuted[i] = m[MSG_PERMUTATION[i]]; } *m = permuted; } fn compress( chaining_value: &[u32; 8], block_words: &[u32; 16], counter: u64, block_len: u32, flags: u32, ) -> [u32; 16] { let mut state = [ chaining_value[0], chaining_value[1], chaining_value[2], chaining_value[3], chaining_value[4], chaining_value[5], chaining_value[6], chaining_value[7], IV[0], IV[1], IV[2], IV[3], counter as u32, (counter >> 32) as u32, block_len, flags, ]; let mut block = *block_words; round(&mut state, &block); // round 1 permute(&mut block); round(&mut state, &block); // round 2 permute(&mut block); round(&mut state, &block); // round 3 permute(&mut block); round(&mut state, &block); // round 4 permute(&mut block); round(&mut state, &block); // round 5 permute(&mut block); round(&mut state, &block); // round 6 permute(&mut block); round(&mut state, &block); // round 7 for i in 0..8 { state[i] ^= state[i + 8]; state[i + 8] ^= chaining_value[i]; } state } fn first_8_words(compression_output: [u32; 16]) -> [u32; 8] { compression_output[0..8].try_into().unwrap() } fn words_from_little_endian_bytes(bytes: &[u8], words: &mut [u32]) { debug_assert_eq!(bytes.len(), 4 * words.len()); for (four_bytes, word) in bytes.chunks_exact(4).zip(words) { *word = u32::from_le_bytes(four_bytes.try_into().unwrap()); } } // Each chunk or parent node can produce either an 8-word chaining value or, by // setting the ROOT flag, any number of final output bytes. The Output struct // captures the state just prior to choosing between those two possibilities. struct Output { input_chaining_value: [u32; 8], block_words: [u32; 16], counter: u64, block_len: u32, flags: u32, } impl Output { fn chaining_value(&self) -> [u32; 8] { first_8_words(compress( &self.input_chaining_value, &self.block_words, self.counter, self.block_len, self.flags, )) } fn root_output_bytes(&self, out_slice: &mut [u8]) { for (output_block_counter, out_block) in (0u64..).zip(out_slice.chunks_mut(2 * OUT_LEN)) { let words = compress( &self.input_chaining_value, &self.block_words, output_block_counter, self.block_len, self.flags | ROOT, ); // The output length might not be a multiple of 4. for (word, out_word) in words.iter().zip(out_block.chunks_mut(4)) { out_word.copy_from_slice(&word.to_le_bytes()[..out_word.len()]); } } } } struct ChunkState { chaining_value: [u32; 8], chunk_counter: u64, block: [u8; BLOCK_LEN], block_len: u8, blocks_compressed: u8, flags: u32, } impl ChunkState { fn new(key_words: [u32; 8], chunk_counter: u64, flags: u32) -> Self { Self { chaining_value: key_words, chunk_counter, block: [0; BLOCK_LEN], block_len: 0, blocks_compressed: 0, flags, } } fn len(&self) -> usize { BLOCK_LEN * self.blocks_compressed as usize + self.block_len as usize } fn start_flag(&self) -> u32 { if self.blocks_compressed == 0 { CHUNK_START } else { 0 } } fn update(&mut self, mut input: &[u8]) { while !input.is_empty() { // If the block buffer is full, compress it and clear it. More // input is coming, so this compression is not CHUNK_END. if self.block_len as usize == BLOCK_LEN { let mut block_words = [0; 16]; words_from_little_endian_bytes(&self.block, &mut block_words); self.chaining_value = first_8_words(compress( &self.chaining_value, &block_words, self.chunk_counter, BLOCK_LEN as u32, self.flags | self.start_flag(), )); self.blocks_compressed += 1; self.block = [0; BLOCK_LEN]; self.block_len = 0; } // Copy input bytes into the block buffer. let want = BLOCK_LEN - self.block_len as usize; let take = min(want, input.len()); self.block[self.block_len as usize..][..take].copy_from_slice(&input[..take]); self.block_len += take as u8; input = &input[take..]; } } fn output(&self) -> Output { let mut block_words = [0; 16]; words_from_little_endian_bytes(&self.block, &mut block_words); Output { input_chaining_value: self.chaining_value, block_words, counter: self.chunk_counter, block_len: self.block_len as u32, flags: self.flags | self.start_flag() | CHUNK_END, } } } fn parent_output( left_child_cv: [u32; 8], right_child_cv: [u32; 8], key_words: [u32; 8], flags: u32, ) -> Output { let mut block_words = [0; 16]; block_words[..8].copy_from_slice(&left_child_cv); block_words[8..].copy_from_slice(&right_child_cv); Output { input_chaining_value: key_words, block_words, counter: 0, // Always 0 for parent nodes. block_len: BLOCK_LEN as u32, // Always BLOCK_LEN (64) for parent nodes. flags: PARENT | flags, } } fn parent_cv( left_child_cv: [u32; 8], right_child_cv: [u32; 8], key_words: [u32; 8], flags: u32, ) -> [u32; 8] { parent_output(left_child_cv, right_child_cv, key_words, flags).chaining_value() } /// An incremental hasher that can accept any number of writes. pub struct Hasher { chunk_state: ChunkState, key_words: [u32; 8], cv_stack: [[u32; 8]; 54], // Space for 54 subtree chaining values: cv_stack_len: u8, // 2^54 * CHUNK_LEN = 2^64 flags: u32, } impl Hasher { fn new_internal(key_words: [u32; 8], flags: u32) -> Self { Self { chunk_state: ChunkState::new(key_words, 0, flags), key_words, cv_stack: [[0; 8]; 54], cv_stack_len: 0, flags, } } /// Construct a new `Hasher` for the regular hash function. pub fn new() -> Self { Self::new_internal(IV, 0) } fn push_stack(&mut self, cv: [u32; 8]) { self.cv_stack[self.cv_stack_len as usize] = cv; self.cv_stack_len += 1; } fn pop_stack(&mut self) -> [u32; 8] { self.cv_stack_len -= 1; self.cv_stack[self.cv_stack_len as usize] } // Section 5.1.2 of the BLAKE3 spec explains this algorithm in more detail. fn add_chunk_chaining_value(&mut self, mut new_cv: [u32; 8], mut total_chunks: u64) { // This chunk might complete some subtrees. For each completed subtree, // its left child will be the current top entry in the CV stack, and // its right child will be the current value of `new_cv`. Pop each left // child off the stack, merge it with `new_cv`, and overwrite `new_cv` // with the result. After all these merges, push the final value of // `new_cv` onto the stack. The number of completed subtrees is given // by the number of trailing 0-bits in the new total number of chunks. while total_chunks & 1 == 0 { new_cv = parent_cv(self.pop_stack(), new_cv, self.key_words, self.flags); total_chunks >>= 1; } self.push_stack(new_cv); } /// Add input to the hash state. This can be called any number of times. pub fn update(&mut self, mut input: &[u8]) { while !input.is_empty() { // If the current chunk is complete, finalize it and reset the // chunk state. More input is coming, so this chunk is not ROOT. if self.chunk_state.len() == CHUNK_LEN { let chunk_cv = self.chunk_state.output().chaining_value(); let total_chunks = self.chunk_state.chunk_counter + 1; self.add_chunk_chaining_value(chunk_cv, total_chunks); self.chunk_state = ChunkState::new(self.key_words, total_chunks, self.flags); } // Compress input bytes into the current chunk state. let want = CHUNK_LEN - self.chunk_state.len(); let take = min(want, input.len()); self.chunk_state.update(&input[..take]); input = &input[take..]; } } /// Finalize the hash and write any number of output bytes. pub fn finalize(&self, out_slice: &mut [u8]) { // Starting with the Output from the current chunk, compute all the // parent chaining values along the right edge of the tree, until we // have the root Output. let mut output = self.chunk_state.output(); let mut parent_nodes_remaining = self.cv_stack_len as usize; while parent_nodes_remaining > 0 { parent_nodes_remaining -= 1; output = parent_output( self.cv_stack[parent_nodes_remaining], output.chaining_value(), self.key_words, self.flags, ); } output.root_output_bytes(out_slice); } } impl Default for Hasher { fn default() -> Self { Self::new() } } ================================================ FILE: crates/tauri-codegen/src/vendor/mod.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT //! Manual vendored dependencies - NOT STABLE. //! //! This module and all submodules are not considered part of the public //! api. They can and will change at any time for any reason in any //! version. pub mod blake3_reference; ================================================ FILE: crates/tauri-driver/CHANGELOG.md ================================================ # Changelog ## \[2.0.5] ### Bug Fixes - [`06f911aaf`](https://www.github.com/tauri-apps/tauri/commit/06f911aaff495121f08ebc77d9d1b41382298a1f) ([#14871](https://www.github.com/tauri-apps/tauri/pull/14871) by [@goosewobbler](https://www.github.com/tauri-apps/tauri/../../goosewobbler)) Prevent native WebDriver stdout from polluting tauri-driver's stdout used by test frameworks. ## \[2.0.4] ### Enhancements - [`0cf2d9933`](https://www.github.com/tauri-apps/tauri/commit/0cf2d9933f20375349f9f307b4dd7049690030d9) ([#13238](https://www.github.com/tauri-apps/tauri/pull/13238)) Automatically append the `.exe` extension on the application path in `tauri:options`. ### Bug Fixes - [`577c7ffc4`](https://www.github.com/tauri-apps/tauri/commit/577c7ffc45ef005403cdf698e595614038c7d1e1) ([#10108](https://www.github.com/tauri-apps/tauri/pull/10108)) Ensure the webdriver process is closed when the tauri-driver process finishes. ## \[2.0.3] ### Bug Fixes - [`fb294af8e`](https://www.github.com/tauri-apps/tauri/commit/fb294af8e3717d547029f3bbf9323318e0d9861a) ([#12383](https://www.github.com/tauri-apps/tauri/pull/12383) by [@bicarlsen](https://www.github.com/tauri-apps/tauri/../../bicarlsen)) Parse ms:edgeOptions separately to prevent `invalid argument` errors. ## \[2.0.2] ### Enhancements - [`70f96e322`](https://www.github.com/tauri-apps/tauri/commit/70f96e3222871a1931a18d6093d7efcbc59e7fee) ([#12240](https://www.github.com/tauri-apps/tauri/pull/12240) by [@getong](https://www.github.com/tauri-apps/tauri/../../getong)) Updated `hyper` to version 1. This won't affect the user facing API. ## \[2.0.1] ### What's Changed - [`0ab2b3306`](https://www.github.com/tauri-apps/tauri/commit/0ab2b330644b6419f6cee1d5377bfb5cdda2ccf9) ([#11205](https://www.github.com/tauri-apps/tauri/pull/11205) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Downgrade MSRV to 1.77.2 to support Windows 7. ## \[2.0.0] ### What's Changed - [`382ed482b`](https://www.github.com/tauri-apps/tauri/commit/382ed482bd08157c39e62f9a0aaad8802f1092cb) Bump MSRV to 1.78. - [`637285790`](https://www.github.com/tauri-apps/tauri/commit/6372857905ae9c0aedb7f482ddf6cf9f9836c9f2) Promote to v2 stable! ## \[0.1.5] ### Bug Fixes - [`5f64ed2b7`](https://www.github.com/tauri-apps/tauri/commit/5f64ed2b78201b7e379b6234f7a799d9695b11d7) ([#10738](https://www.github.com/tauri-apps/tauri/pull/10738) by [@chippers](https://www.github.com/tauri-apps/tauri/../../chippers)) support both 1.x and 2.x automation env vars in `tauri-driver` ### What's Changed - [`f4d5241b3`](https://www.github.com/tauri-apps/tauri/commit/f4d5241b377d0f7a1b58100ee19f7843384634ac) ([#10731](https://www.github.com/tauri-apps/tauri/pull/10731) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Update documentation icon path. ## \[0.1.4] ### New Features - [`435d7513`](https://www.github.com/tauri-apps/tauri/commit/435d7513e45eab8b512e9a7e695a1adef8a98a46)([#8609](https://www.github.com/tauri-apps/tauri/pull/8609)) Added `webviewOptions` object to the `tauri:options` capability to configure the [Edge webview options](https://learn.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options#webviewoptions-object) on Windows. ## \[0.1.3] ### What's Changed - [`9edebbba`](https://www.github.com/tauri-apps/tauri/commit/9edebbba4ec472772b2f6307232e8d256f62c8ba)([#7475](https://www.github.com/tauri-apps/tauri/pull/7475)) Update locked dependencies to fix a Windows build issue when using them with a recent Rust compiler. - [`9edebbba`](https://www.github.com/tauri-apps/tauri/commit/9edebbba4ec472772b2f6307232e8d256f62c8ba)([#7475](https://www.github.com/tauri-apps/tauri/pull/7475)) Bump minimum Rust version to `1.60` to be in line with the rest of the Tauri project. ## \[0.1.2] - Expose `native-host` option in tauri-driver and set default to `127.0.0.1`. - [cd9dfc7b](https://www.github.com/tauri-apps/tauri/commit/cd9dfc7b9a3fe0e04e40d9b0f9be674aefd0d725) fix(driver): expose native-host option and set default to 127.0.0.1 ([#3816](https://www.github.com/tauri-apps/tauri/pull/3816)) on 2022-03-31 ## \[0.1.1] - The minimum Rust version is now `1.56`. - [a9dfc015](https://www.github.com/tauri-apps/tauri/commit/a9dfc015505afe91281c2027954ffcc588b1a59c) feat: update to edition 2021 and set minimum rust to 1.56 ([#2789](https://www.github.com/tauri-apps/tauri/pull/2789)) on 2021-10-22 - Add `args` field (array of application CLI arguments) to the `tauri:options` capabilities. - [d0970e34](https://www.github.com/tauri-apps/tauri/commit/d0970e3499297a6c102a36f2dc479d3d657bfaf3) feat(driver): add `args` to `tauri:options` ([#3154](https://www.github.com/tauri-apps/tauri/pull/3154)) on 2022-01-03 ## \[0.1.0] - Initial release including Linux and Windows support. - [be76fb1d](https://www.github.com/tauri-apps/tauri/commit/be76fb1dfe73a1605cc2ad246418579f4c2e1999) WebDriver support ([#1972](https://www.github.com/tauri-apps/tauri/pull/1972)) on 2021-06-23 - [c22e5a7c](https://www.github.com/tauri-apps/tauri/commit/c22e5a7c2ebede41657973b80eff6b68106817fc) fix(covector): keep `tauri-driver` version as alpha on 2021-06-23 - [b4426eda](https://www.github.com/tauri-apps/tauri/commit/b4426eda9e64fcdd25a2d72e548b8b0fbfa09619) Revert "WebDriver support ([#1972](https://www.github.com/tauri-apps/tauri/pull/1972))" on 2021-06-23 - [4b2aa356](https://www.github.com/tauri-apps/tauri/commit/4b2aa35684632ed2afd7dec4ad848df5704868e4) Add back WebDriver support ([#2324](https://www.github.com/tauri-apps/tauri/pull/2324)) on 2021-08-01 ================================================ FILE: crates/tauri-driver/Cargo.toml ================================================ [package] name = "tauri-driver" version = "2.0.5" authors = ["Tauri Programme within The Commons Conservancy"] categories = ["gui", "web-programming"] license = "Apache-2.0 OR MIT" homepage = "https://tauri.app" repository = "https://github.com/tauri-apps/tauri" description = "Webdriver server for Tauri applications" readme = "README.md" edition = "2021" rust-version = "1.77.2" [dependencies] anyhow = "1" futures = "0.3" futures-util = "0.3" http-body-util = "0.1" hyper = { version = "1", features = ["client", "http1", "server"] } hyper-util = { version = "0.1", features = [ "client", "client-legacy", "http1", "server", "tokio", ] } pico-args = "0.5" serde = { version = "1", features = ["derive"] } serde_json = "1" tokio = { version = "1", features = ["macros"] } which = "8" [target."cfg(unix)".dependencies] signal-hook = "0.4" signal-hook-tokio = { version = "0.4", features = ["futures-v0_3"] } [target."cfg(windows)".dependencies] win32job = "2" ================================================ FILE: crates/tauri-driver/LICENSE.spdx ================================================ ../../LICENSE.spdx ================================================ FILE: crates/tauri-driver/LICENSE_APACHE-2.0 ================================================ ../../LICENSE_APACHE-2.0 ================================================ FILE: crates/tauri-driver/LICENSE_MIT ================================================ ../../LICENSE_MIT ================================================ FILE: crates/tauri-driver/README.md ================================================ # `tauri-driver` _(pre-alpha)_ Cross-platform WebDriver server for Tauri applications. This is a [WebDriver Intermediary Node] that wraps the native WebDriver server for platforms that [Tauri] supports. Your WebDriver client will connect to the running `tauri-driver` server, and `tauri-driver` will handle starting the native WebDriver server for you behind the scenes. It requires two separate ports to be used since two distinct [WebDriver Remote Ends] run. You can configure the ports used with arguments when starting the binary: - `--port` (default: `4444`) - `--native-port` (default: `4445`) Supported platforms: - Linux via `WebKitWebDriver` - Windows via [Microsoft Edge Driver] - **[Todo]** macOS via [Appium Mac2 Driver] (probably) _note: the (probably) items haven't been proof-of-concept'd yet, and if it is not possible to use the listed native webdriver, then a custom implementation will be used that wraps around [wry]._ ## Installation You can install tauri-driver using Cargo: ```sh cargo install tauri-driver --locked ``` ## Trying it out Check out the documentation at https://tauri.app/develop/tests/webdriver/, including a small example application with WebDriver tests. [WebDriver Intermediary Node]: https://www.w3.org/TR/webdriver/#dfn-intermediary-nodes [WebDriver Remote Ends]: https://www.w3.org/TR/webdriver/#dfn-remote-ends [Microsoft Edge Driver]: https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ [Appium Mac2 Driver]: https://github.com/appium/appium-mac2-driver [wry]: https://github.com/tauri-apps/wry [Tauri]: https://github.com/tauri-apps/tauri ================================================ FILE: crates/tauri-driver/src/cli.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use std::path::PathBuf; const HELP: &str = "\ USAGE: tauri-driver [FLAGS] [OPTIONS] FLAGS: -h, --help Prints help information OPTIONS: --port NUMBER Sets the tauri-driver intermediary port --native-port NUMBER Sets the port of the underlying WebDriver --native-host HOST Sets the host of the underlying WebDriver (Linux only) --native-driver PATH Sets the path to the native WebDriver binary "; #[derive(Debug, Clone)] pub struct Args { pub port: u16, pub native_port: u16, pub native_host: String, pub native_driver: Option, } impl From for Args { fn from(mut args: pico_args::Arguments) -> Self { // if the user wanted help, we don't care about parsing the rest of the args if args.contains(["-h", "--help"]) { println!("{HELP}"); std::process::exit(0); } let native_driver = match args.opt_value_from_str("--native-driver") { Ok(native_driver) => native_driver, Err(e) => { eprintln!("Error while parsing option --native-driver: {e}"); std::process::exit(1); } }; let parsed = Args { port: args.value_from_str("--port").unwrap_or(4444), native_port: args.value_from_str("--native-port").unwrap_or(4445), native_host: args .value_from_str("--native-host") .unwrap_or(String::from("127.0.0.1")), native_driver, }; // be strict about accepting args, error for anything extraneous let rest = args.finish(); if !rest.is_empty() { eprintln!("Error: unused arguments left: {rest:?}"); eprintln!("{HELP}"); std::process::exit(1); } parsed } } ================================================ FILE: crates/tauri-driver/src/main.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT //! Cross-platform WebDriver server for Tauri applications. //! //! This is a [WebDriver Intermediary Node](https://www.w3.org/TR/webdriver/#dfn-intermediary-nodes) that wraps the native WebDriver server for platforms that [Tauri](https://github.com/tauri-apps/tauri) supports. Your WebDriver client will connect to the running `tauri-driver` server, and `tauri-driver` will handle starting the native WebDriver server for you behind the scenes. It requires two separate ports to be used since two distinct [WebDriver Remote Ends](https://www.w3.org/TR/webdriver/#dfn-remote-ends) run. #![doc( html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png", html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png" )] #[cfg(any(target_os = "linux", windows))] mod cli; #[cfg(any(target_os = "linux", windows))] mod server; #[cfg(any(target_os = "linux", windows))] mod webdriver; #[cfg(not(any(target_os = "linux", windows)))] fn main() { println!("tauri-driver is not supported on this platform"); std::process::exit(1); } #[cfg(any(target_os = "linux", windows))] fn main() { let args = pico_args::Arguments::from_env().into(); #[cfg(windows)] let _job_handle = { let job = win32job::Job::create().unwrap(); let mut info = job.query_extended_limit_info().unwrap(); info.limit_kill_on_job_close(); job.set_extended_limit_info(&info).unwrap(); job.assign_current_process().unwrap(); job }; // start the native webdriver on the port specified in args let mut driver = webdriver::native(&args); let driver = driver .spawn() .expect("error while running native webdriver"); // start our webdriver intermediary node if let Err(e) = server::run(args, driver) { eprintln!("error while running server: {e}"); std::process::exit(1); } } ================================================ FILE: crates/tauri-driver/src/server.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use crate::cli::Args; use anyhow::Error; use futures_util::TryFutureExt; use http_body_util::{BodyExt, Full}; use hyper::{ body::{Bytes, Incoming}, header::CONTENT_LENGTH, http::uri::Authority, service::service_fn, Method, Request, Response, }; use hyper_util::{ client::legacy::{connect::HttpConnector, Client}, rt::{TokioExecutor, TokioIo}, server::conn::auto, }; use serde::Deserialize; use serde_json::{json, Map, Value}; use std::path::PathBuf; use std::process::Child; use tokio::net::TcpListener; const TAURI_OPTIONS: &str = "tauri:options"; #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] struct TauriOptions { application: PathBuf, #[serde(default)] args: Vec, #[cfg(target_os = "windows")] #[serde(default)] webview_options: Option, } impl TauriOptions { #[cfg(target_os = "linux")] fn into_native_object(self) -> Map { let mut map = Map::new(); map.insert( "webkitgtk:browserOptions".into(), json!({"binary": self.application, "args": self.args}), ); map } #[cfg(target_os = "windows")] fn into_native_object(self) -> Map { let mut ms_edge_options = Map::new(); ms_edge_options.insert( "binary".into(), json!(self.application.with_extension("exe")), ); ms_edge_options.insert("args".into(), self.args.into()); if let Some(webview_options) = self.webview_options { ms_edge_options.insert("webviewOptions".into(), webview_options); } let mut map = Map::new(); map.insert("ms:edgeChromium".into(), json!(true)); map.insert("browserName".into(), json!("webview2")); map.insert("ms:edgeOptions".into(), ms_edge_options.into()); map } } async fn handle( client: Client>, req: Request, args: Args, ) -> Result, Error> { // manipulate a new session to convert options to the native driver format let new_req: Request> = if let (&Method::POST, "/session") = (req.method(), req.uri().path()) { let (mut parts, body) = req.into_parts(); // get the body from the future stream and parse it as json let body = body.collect().await?.to_bytes().to_vec(); let json: Value = serde_json::from_slice(&body)?; // manipulate the json to convert from tauri option to native driver options let json = map_capabilities(json); // serialize json and update the content-length header to be accurate let bytes = serde_json::to_vec(&json)?; parts.headers.insert(CONTENT_LENGTH, bytes.len().into()); Request::from_parts(parts, Full::new(bytes.into())) } else { let (parts, body) = req.into_parts(); let body = body.collect().await?.to_bytes().to_vec(); Request::from_parts(parts, Full::new(body.into())) }; client .request(forward_to_native_driver(new_req, args)?) .err_into() .await } /// Transform the request to a request for the native webdriver server. fn forward_to_native_driver( mut req: Request>, args: Args, ) -> Result>, Error> { let host: Authority = { let headers = req.headers_mut(); headers.remove("host").expect("hyper request has host") } .to_str()? .parse()?; let path = req .uri() .path_and_query() .expect("hyper request has uri") .clone(); let uri = format!( "http://{}:{}{}", host.host(), args.native_port, path.as_str() ); let (mut parts, body) = req.into_parts(); parts.uri = uri.parse()?; Ok(Request::from_parts(parts, body)) } /// only happy path for now, no errors fn map_capabilities(mut json: Value) -> Value { let mut native = None; if let Some(capabilities) = json.get_mut("capabilities") { if let Some(always_match) = capabilities.get_mut("alwaysMatch") { if let Some(always_match) = always_match.as_object_mut() { if let Some(tauri_options) = always_match.remove(TAURI_OPTIONS) { if let Ok(options) = serde_json::from_value::(tauri_options) { native = Some(options.into_native_object()); } } if let Some(native) = native.clone() { always_match.extend(native); } } } } if let Some(native) = native { if let Some(desired) = json.get_mut("desiredCapabilities") { if let Some(desired) = desired.as_object_mut() { desired.remove(TAURI_OPTIONS); desired.extend(native); } } } json } #[tokio::main(flavor = "current_thread")] pub async fn run(args: Args, mut _driver: Child) -> Result<(), Error> { #[cfg(unix)] let (signals_handle, signals_task) = { use futures_util::StreamExt; use signal_hook::consts::signal::*; let signals = signal_hook_tokio::Signals::new([SIGTERM, SIGINT, SIGQUIT])?; let signals_handle = signals.handle(); let signals_task = tokio::spawn(async move { let mut signals = signals.fuse(); #[allow(clippy::never_loop)] while let Some(signal) = signals.next().await { match signal { SIGTERM | SIGINT | SIGQUIT => { _driver .kill() .expect("unable to kill native webdriver server"); std::process::exit(0); } _ => unreachable!(), } } }); (signals_handle, signals_task) }; let address = std::net::SocketAddr::from(([127, 0, 0, 1], args.port)); // the client we use to proxy requests to the native webdriver let client = Client::builder(TokioExecutor::new()) .http1_preserve_header_case(true) .http1_title_case_headers(true) .retry_canceled_requests(false) .build_http(); // set up a http1 server that uses the service we just created let srv = async move { if let Ok(listener) = TcpListener::bind(address).await { loop { let client = client.clone(); let args = args.clone(); if let Ok((stream, _)) = listener.accept().await { let io = TokioIo::new(stream); tokio::task::spawn(async move { if let Err(err) = auto::Builder::new(TokioExecutor::new()) .http1() .title_case_headers(true) .preserve_header_case(true) .serve_connection( io, service_fn(|request| handle(client.clone(), request, args.clone())), ) .await { println!("Error serving connection: {err:?}"); } }); } else { println!("accept new stream fail, ignore here"); } } } else { println!("can not listen to address: {address:?}"); } }; srv.await; #[cfg(unix)] { signals_handle.close(); signals_task.await?; } Ok(()) } ================================================ FILE: crates/tauri-driver/src/webdriver.rs ================================================ // Copyright 2019-2026 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use crate::cli::Args; use std::{ env::current_dir, process::{Command, Stdio}, }; // the name of the binary to find in $PATH #[cfg(target_os = "linux")] const DRIVER_BINARY: &str = "WebKitWebDriver"; #[cfg(target_os = "windows")] const DRIVER_BINARY: &str = "msedgedriver.exe"; /// Find the native driver binary in the PATH, or exits the process with an error. pub fn native(args: &Args) -> Command { let native_binary = match args.native_driver.as_deref() { Some(custom) => { if custom.exists() { custom.to_owned() } else { eprintln!( "can not find the supplied binary path {}. This is currently required.", custom.display() ); match current_dir() { Ok(cwd) => eprintln!("current working directory: {}", cwd.display()), Err(error) => eprintln!("can not find current working directory: {error}"), } std::process::exit(1); } } None => match which::which(DRIVER_BINARY) { Ok(binary) => binary, Err(error) => { eprintln!( "can not find binary {DRIVER_BINARY} in the PATH. This is currently required.\ You can also pass a custom path with --native-driver" ); eprintln!("{error:?}"); std::process::exit(1); } }, }; let mut cmd = Command::new(native_binary); cmd.env("TAURI_AUTOMATION", "true"); // 1.x cmd.env("TAURI_WEBVIEW_AUTOMATION", "true"); // 2.x cmd.arg(format!("--port={}", args.native_port)); cmd.arg(format!("--host={}", args.native_host)); // Don't inherit stdout from parent to prevent native WebDriver binary/HTTP protocol data // from corrupting tauri-driver's stdout (which gets captured by the test framework). // Keep stderr inherited so WebDriver logs/errors are still visible. cmd.stdout(Stdio::null()); cmd } ================================================ FILE: crates/tauri-macos-sign/CHANGELOG.md ================================================ # Changelog ## \[2.3.3] ### Dependencies - [`268bb339f`](https://www.github.com/tauri-apps/tauri/commit/268bb339f0c512f021cc94e102573432cf2696d0) ([#14766](https://www.github.com/tauri-apps/tauri/pull/14766) by [@sftse](https://www.github.com/tauri-apps/tauri/../../sftse)) Remove once-cell-regex from direct dependencies. ## \[2.3.2] ### Dependencies - [`514cf21e1`](https://www.github.com/tauri-apps/tauri/commit/514cf21e1417c7a78a0db494f891ba79d948b73d) ([#14591](https://www.github.com/tauri-apps/tauri/pull/14591) by [@Tunglies](https://www.github.com/tauri-apps/tauri/../../Tunglies)) Update num-bigint-dig from 0.8.4 to 0.8.6 ## \[2.3.1] ### Performance Improvements - [`ee3cc4a91`](https://www.github.com/tauri-apps/tauri/commit/ee3cc4a91bf1315ecaefe90f423ffd55ef6c40db) ([#14475](https://www.github.com/tauri-apps/tauri/pull/14475) by [@Tunglies](https://www.github.com/tauri-apps/tauri/../../Tunglies)) perf: remove needless clones in various files for improved performance. No user facing changes. ## \[2.3.0] ### Enhancements - [`f59bf9d53`](https://www.github.com/tauri-apps/tauri/commit/f59bf9d5392ffd209e26ce5259c26d1acc31c4ba) ([#14337](https://www.github.com/tauri-apps/tauri/pull/14337) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) **Potentially breaking change:** Export custom Error enum instead of using anyhow. The changes happened in https://github.com/tauri-apps/tauri/pull/14126. ## \[2.2.0] ### New Features - [`a9ec12843`](https://www.github.com/tauri-apps/tauri/commit/a9ec12843aa7d0eb774bd3a53e2e63da12cfa77b) ([#13521](https://www.github.com/tauri-apps/tauri/pull/13521) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Added a `--skip-stapling` option to make `tauri build|bundle` *not* wait for notarization to finish on macOS. ## \[2.1.0] ### Enhancements - [`d6520a21c`](https://www.github.com/tauri-apps/tauri/commit/d6520a21ce02c3e2be2955999946c2cb7bdb07aa) ([#12541](https://www.github.com/tauri-apps/tauri/pull/12541) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Updated `wry` to 0.50, `windows` to 0.60, `webview2-com` to 0.36, and `objc2` to 0.6. This can be a **breaking change** if you use the `with_webview` API! ## \[2.0.1] ### What's Changed - [`0ab2b3306`](https://www.github.com/tauri-apps/tauri/commit/0ab2b330644b6419f6cee1d5377bfb5cdda2ccf9) ([#11205](https://www.github.com/tauri-apps/tauri/pull/11205) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Downgrade MSRV to 1.77.2 to support Windows 7. ## \[2.0.0] ### What's Changed - [`382ed482b`](https://www.github.com/tauri-apps/tauri/commit/382ed482bd08157c39e62f9a0aaad8802f1092cb) Bump MSRV to 1.78. - [`637285790`](https://www.github.com/tauri-apps/tauri/commit/6372857905ae9c0aedb7f482ddf6cf9f9836c9f2) Promote to v2 stable! ## \[0.1.1-rc.1] ### Enhancements - [`f5d61822b`](https://www.github.com/tauri-apps/tauri/commit/f5d61822bf5988827776dd58bed75c19364e86bd) ([#11184](https://www.github.com/tauri-apps/tauri/pull/11184) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Added `Keychain::with_certificate_file` and `certificate::generate_self_signed`. ## \[0.1.1-rc.0] ### Bug Fixes - [`1b0c447fc`](https://www.github.com/tauri-apps/tauri/commit/1b0c447fcbc424e08e4260277ec178df86f45d1d) ([#10654](https://www.github.com/tauri-apps/tauri/pull/10654) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes output not visible when running on Node.js via NAPI. ## \[0.1.0-beta.0] ### New Features - [`7c7fa0964`](https://www.github.com/tauri-apps/tauri/commit/7c7fa0964db3403037fdb9a34de2b877ddb8df1c) ([#9963](https://www.github.com/tauri-apps/tauri/pull/9963) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Initial release. ================================================ FILE: crates/tauri-macos-sign/Cargo.toml ================================================ [package] name = "tauri-macos-sign" version = "2.3.3" authors = ["Tauri Programme within The Commons Conservancy"] license = "Apache-2.0 OR MIT" keywords = ["codesign", "signing", "macos", "ios", "tauri"] repository = "https://github.com/tauri-apps/tauri" description = "Code signing utilities for macOS and iOS apps" edition = "2021" rust-version = "1.77.2" [dependencies] thiserror = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" tempfile = "3" x509-certificate = "0.23" once_cell = "1" regex = "1" os_pipe = "1" plist = "1" rand = "0.9" dirs = "6" log = { version = "0.4.21", features = ["kv"] } apple-codesign = { version = "0.27", default-features = false } chrono = "0.4" p12 = "0.6" base64 = "0.22" ================================================ FILE: crates/tauri-macos-sign/README.md ================================================ # Tauri MacOS Sign Utilities for setting up macOS certificates, code signing and notarization for macOS and iOS apps. ================================================ FILE: crates/tauri-macos-sign/src/certificate.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use apple_codesign::create_self_signed_code_signing_certificate; use x509_certificate::{EcdsaCurve, KeyAlgorithm}; pub use apple_codesign::CertificateProfile; use crate::{Error, Result}; /// Self signed certificate options. pub struct SelfSignedCertificateRequest { /// Which key type to use pub algorithm: String, /// Profile pub profile: CertificateProfile, /// Team ID (this is a short string attached to your Apple Developer account) pub team_id: String, /// The name of the person this certificate is for pub person_name: String, /// Country Name (C) value for certificate identifier pub country_name: String, /// How many days the certificate should be valid for pub validity_days: i64, /// Certificate password. pub password: String, } pub fn generate_self_signed(request: SelfSignedCertificateRequest) -> Result> { let algorithm = match request.algorithm.as_str() { "ecdsa" => KeyAlgorithm::Ecdsa(EcdsaCurve::Secp256r1), "ed25519" => KeyAlgorithm::Ed25519, "rsa" => KeyAlgorithm::Rsa, value => panic!("algorithm values should have been validated by arg parser: {value}"), }; let validity_duration = chrono::Duration::days(request.validity_days); let (cert, key_pair) = create_self_signed_code_signing_certificate( algorithm, request.profile, &request.team_id, &request.person_name, &request.country_name, validity_duration, ) .map_err(|error| Error::FailedToCreateSelfSignedCertificate { error: Box::new(error), })?; let pfx = p12::PFX::new( &cert .encode_der() .map_err(|error| Error::FailedToEncodeDER { error })?, &key_pair.to_pkcs8_one_asymmetric_key_der(), None, &request.password, "code-signing", ) .ok_or(Error::FailedToCreatePFX)?; let der = pfx.to_der(); Ok(der) } ================================================ FILE: crates/tauri-macos-sign/src/keychain/identity.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use once_cell::sync::OnceCell; use regex::Regex; use std::{collections::BTreeSet, path::Path, process::Command}; use x509_certificate::certificate::X509Certificate; use crate::{Error, Result}; fn get_pem_list(keychain_path: &Path, name_substr: &str) -> Result { Command::new("security") .arg("find-certificate") .args(["-p", "-a"]) .arg("-c") .arg(name_substr) .arg(keychain_path) .stdin(os_pipe::dup_stdin().unwrap()) .stderr(os_pipe::dup_stderr().unwrap()) .output() .map_err(|error| Error::CommandFailed { command: "security find-certificate".to_string(), error, }) } #[derive(Debug, Clone, Eq, Ord, PartialEq, PartialOrd)] pub struct Team { pub name: String, pub certificate_name: String, pub id: String, pub cert_prefix: &'static str, } impl Team { fn from_x509(cert_prefix: &'static str, cert: X509Certificate) -> Result { let common_name = cert .subject_common_name() .ok_or(Error::CertificateMissingCommonName)?; let organization = cert .subject_name() .iter_organization() .next() .and_then(|v| v.to_string().ok()); let name = if let Some(organization) = organization { println!("found cert {common_name:?} with organization {organization:?}"); organization } else { println!( "found cert {common_name:?} but failed to get organization; falling back to displaying common name" ); static APPLE_DEV: OnceCell = OnceCell::new(); APPLE_DEV.get_or_init(|| Regex::new(r"Apple Develop\w+: (.*) \(.+\)").unwrap()) .captures(&common_name) .map(|caps| caps[1].to_owned()) .unwrap_or_else(|| { println!("regex failed to capture nice part of name in cert {common_name:?}; falling back to displaying full name"); common_name.clone() }) }; let id = cert .subject_name() .iter_organizational_unit() .next() .and_then(|v| v.to_string().ok()) .ok_or_else(|| Error::CertificateMissingOrganizationUnit { common_name: common_name.clone(), })?; Ok(Self { name, certificate_name: common_name, id, cert_prefix, }) } pub fn certificate_name(&self) -> String { self.certificate_name.clone() } } pub fn list(keychain_path: &Path) -> Result> { let certs = { let mut certs = Vec::new(); for cert_prefix in [ "iOS Distribution:", "Apple Distribution:", "Developer ID Application:", "Mac App Distribution:", "Apple Development:", "iOS App Development:", "Mac Development:", ] { let pem_list_out = get_pem_list(keychain_path, cert_prefix)?; let cert_list = X509Certificate::from_pem_multiple(pem_list_out.stdout) .map_err(|error| Error::X509Certificate { error })?; certs.extend(cert_list.into_iter().map(|cert| (cert_prefix, cert))); } certs }; Ok( certs .into_iter() .flat_map(|(cert_prefix, cert)| { Team::from_x509(cert_prefix, cert).map_err(|err| { log::error!("{err}"); err }) }) // Silly way to sort this and ensure no dupes .collect::>() .into_iter() .collect(), ) } ================================================ FILE: crates/tauri-macos-sign/src/keychain.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use std::{ ffi::OsString, path::{Path, PathBuf}, process::Command, }; use crate::{assert_command, CommandExt, Error, Result}; use rand::distr::{Alphanumeric, SampleString}; mod identity; pub use identity::Team; pub enum SigningIdentity { Team(Team), Identifier(String), } pub struct Keychain { // none means the default keychain must be used path: Option, signing_identity: SigningIdentity, } impl Drop for Keychain { fn drop(&mut self) { if let Some(path) = &self.path { let _ = Command::new("security") .arg("delete-keychain") .arg(path) .piped(); } } } impl Keychain { /// Use a certificate in the default keychain. pub fn with_signing_identity(identity: impl Into) -> Self { Self { path: None, signing_identity: SigningIdentity::Identifier(identity.into()), } } /// Import certificate from base64 string. /// certificate_encoded is the p12 certificate base64 encoded. /// By example you can use; openssl base64 -in MyCertificate.p12 -out MyCertificate-base64.txt /// Then use the value of the base64 as `certificate_encoded`. /// You need to set certificate_password to the password you set when you exported your certificate. /// see: `Export a signing certificate` pub fn with_certificate( certificate_encoded: &OsString, certificate_password: &OsString, ) -> Result { let tmp_dir = tempfile::tempdir().map_err(Error::TempDir)?; let cert_path = tmp_dir.path().join("cert.p12"); super::decode_base64(certificate_encoded, &cert_path)?; Self::with_certificate_file(&cert_path, certificate_password) } pub fn with_certificate_file(cert_path: &Path, certificate_password: &OsString) -> Result { let home_dir = dirs::home_dir().ok_or(Error::ResolveHomeDir)?; let keychain_path = home_dir.join("Library").join("Keychains").join(format!( "{}.keychain-db", Alphanumeric.sample_string(&mut rand::rng(), 16) )); let keychain_password = Alphanumeric.sample_string(&mut rand::rng(), 16); let keychain_list_output = Command::new("security") .args(["list-keychain", "-d", "user"]) .output() .map_err(|e| Error::CommandFailed { command: "security list-keychain -d user".to_string(), error: e, })?; assert_command( Command::new("security") .args(["create-keychain", "-p", &keychain_password]) .arg(&keychain_path) .piped(), "failed to create keychain", ) .map_err(|error| Error::CommandFailed { command: "security create-Keychain".to_string(), error, })?; assert_command( Command::new("security") .args(["unlock-keychain", "-p", &keychain_password]) .arg(&keychain_path) .piped(), "failed to set unlock keychain", ) .map_err(|error| Error::CommandFailed { command: "security unlock-keychain".to_string(), error, })?; assert_command( Command::new("security") .arg("import") .arg(cert_path) .arg("-P") .arg(certificate_password) .args([ "-T", "/usr/bin/codesign", "-T", "/usr/bin/pkgbuild", "-T", "/usr/bin/productbuild", ]) .arg("-k") .arg(&keychain_path) .piped(), "failed to import keychain certificate", ) .map_err(|error| Error::CommandFailed { command: "security import".to_string(), error, })?; assert_command( Command::new("security") .args(["set-keychain-settings", "-t", "3600", "-u"]) .arg(&keychain_path) .piped(), "failed to set keychain settings", ) .map_err(|error| Error::CommandFailed { command: "security set-keychain-settings".to_string(), error, })?; assert_command( Command::new("security") .args([ "set-key-partition-list", "-S", "apple-tool:,apple:,codesign:", "-s", "-k", &keychain_password, ]) .arg(&keychain_path) .piped(), "failed to set keychain settings", ) .map_err(|error| Error::CommandFailed { command: "security set-key-partition-list".to_string(), error, })?; let current_keychains = String::from_utf8_lossy(&keychain_list_output.stdout) .split('\n') .map(|line| { line .trim_matches(|c: char| c.is_whitespace() || c == '"') .to_string() }) .filter(|l| !l.is_empty()) .collect::>(); assert_command( Command::new("security") .args(["list-keychain", "-d", "user", "-s"]) .args(current_keychains) .arg(&keychain_path) .piped(), "failed to list keychain", ) .map_err(|error| Error::CommandFailed { command: "security list-keychain".to_string(), error, })?; let signing_identity = identity::list(&keychain_path) .map(|l| l.first().cloned())? .ok_or(Error::ResolveSigningIdentity)?; Ok(Self { path: Some(keychain_path), signing_identity: SigningIdentity::Team(signing_identity), }) } pub fn signing_identity(&self) -> String { match &self.signing_identity { SigningIdentity::Team(t) => t.certificate_name(), SigningIdentity::Identifier(i) => i.to_string(), } } pub fn team_id(&self) -> Option<&str> { match &self.signing_identity { SigningIdentity::Team(t) => Some(&t.id), SigningIdentity::Identifier(_) => None, } } pub fn sign( &self, path: &Path, entitlements_path: Option<&Path>, hardened_runtime: bool, ) -> Result<()> { let identity = match &self.signing_identity { SigningIdentity::Team(t) => t.certificate_name(), SigningIdentity::Identifier(i) => i.clone(), }; println!("Signing with identity \"{identity}\""); println!("Signing {}", path.display()); let mut args = vec!["--force", "-s", &identity]; if hardened_runtime { args.push("--options"); args.push("runtime"); } let mut codesign = Command::new("codesign"); codesign.args(args); if let Some(p) = &self.path { codesign.arg("--keychain").arg(p); } if let Some(entitlements_path) = entitlements_path { codesign.arg("--entitlements"); codesign.arg(entitlements_path); } codesign.arg(path); assert_command(codesign.piped(), "failed to sign app").map_err(|error| { Error::CommandFailed { command: "codesign".to_string(), error, } })?; Ok(()) } pub fn path(&self) -> Option<&Path> { self.path.as_deref() } } ================================================ FILE: crates/tauri-macos-sign/src/lib.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use std::{ ffi::{OsStr, OsString}, path::{Path, PathBuf}, process::{Command, ExitStatus}, }; use serde::Deserialize; pub mod certificate; mod keychain; mod provisioning_profile; pub use keychain::{Keychain, Team}; pub use provisioning_profile::ProvisioningProfile; #[derive(Debug, thiserror::Error)] pub enum Error { #[error("failed to create temp directory: {0}")] TempDir(std::io::Error), #[error("failed to resolve home dir")] ResolveHomeDir, #[error("failed to resolve signing identity")] ResolveSigningIdentity, #[error("failed to decode provisioning profile")] FailedToDecodeProvisioningProfile, #[error("could not find provisioning profile UUID")] FailedToFindProvisioningProfileUuid, #[error("{context} {path}: {error}")] Plist { context: &'static str, path: PathBuf, error: plist::Error, }, #[error("failed to upload app to Apple's notarization servers: {error}")] FailedToUploadApp { error: std::io::Error }, #[error("failed to notarize app: {0}")] Notarize(String), #[error("failed to parse notarytool output as JSON: {output}")] ParseNotarytoolOutput { output: String }, #[error("failed to run command {command}: {error}")] CommandFailed { command: String, error: std::io::Error, }, #[error("{context} {path}: {error}")] Fs { context: &'static str, path: PathBuf, error: std::io::Error, }, #[error("failed to parse X509 certificate: {error}")] X509Certificate { error: x509_certificate::X509CertificateError, }, #[error("failed to create PFX from self signed certificate")] FailedToCreatePFX, #[error("failed to create self signed certificate: {error}")] FailedToCreateSelfSignedCertificate { error: Box, }, #[error("failed to encode DER: {error}")] FailedToEncodeDER { error: std::io::Error }, #[error("failed to decode base64 certificate: {0}")] Base64Decode(base64::DecodeError), #[error("certificate missing common name")] CertificateMissingCommonName, #[error("certificate missing organization unit for common name {common_name}")] CertificateMissingOrganizationUnit { common_name: String }, } pub type Result = std::result::Result; trait CommandExt { // The `pipe` function sets the stdout and stderr to properly // show the command output in the Node.js wrapper. fn piped(&mut self) -> std::io::Result; } impl CommandExt for Command { fn piped(&mut self) -> std::io::Result { self.stdin(os_pipe::dup_stdin()?); self.stdout(os_pipe::dup_stdout()?); self.stderr(os_pipe::dup_stderr()?); let program = self.get_program().to_string_lossy().into_owned(); log::debug!(action = "Running"; "Command `{} {}`", program, self.get_args().map(|arg| arg.to_string_lossy()).fold(String::new(), |acc, arg| format!("{acc} {arg}"))); self.status() } } pub enum ApiKey { Path(PathBuf), Raw(Vec), } pub enum AppleNotarizationCredentials { AppleId { apple_id: OsString, password: OsString, team_id: OsString, }, ApiKey { issuer: OsString, key_id: OsString, key: ApiKey, }, } #[derive(Deserialize)] struct NotarytoolSubmitOutput { id: String, #[serde(default)] status: Option, message: String, } pub fn notarize( keychain: &Keychain, app_bundle_path: &Path, auth: &AppleNotarizationCredentials, ) -> Result<()> { notarize_inner(keychain, app_bundle_path, auth, true) } pub fn notarize_without_stapling( keychain: &Keychain, app_bundle_path: &Path, auth: &AppleNotarizationCredentials, ) -> Result<()> { notarize_inner(keychain, app_bundle_path, auth, false) } fn notarize_inner( keychain: &Keychain, app_bundle_path: &Path, auth: &AppleNotarizationCredentials, wait: bool, ) -> Result<()> { let bundle_stem = app_bundle_path .file_stem() .expect("failed to get bundle filename"); let tmp_dir = tempfile::tempdir().map_err(Error::TempDir)?; let zip_path = tmp_dir .path() .join(format!("{}.zip", bundle_stem.to_string_lossy())); let zip_args = vec![ "-c", "-k", "--keepParent", "--sequesterRsrc", app_bundle_path .to_str() .expect("failed to convert bundle_path to string"), zip_path .to_str() .expect("failed to convert zip_path to string"), ]; // use ditto to create a PKZip almost identical to Finder // this remove almost 99% of false alarm in notarization assert_command( Command::new("ditto").args(zip_args).piped(), "failed to zip app with ditto", ) .map_err(|error| Error::CommandFailed { command: "ditto".to_string(), error, })?; // sign the zip file keychain.sign(&zip_path, None, false)?; let mut notarize_args = vec![ "notarytool", "submit", zip_path .to_str() .expect("failed to convert zip_path to string"), "--output-format", "json", ]; if wait { notarize_args.push("--wait"); } let notarize_args = notarize_args; println!("Notarizing {}", app_bundle_path.display()); let output = Command::new("xcrun") .args(notarize_args) .notarytool_args(auth, tmp_dir.path())? .output() .map_err(|error| Error::FailedToUploadApp { error })?; if !output.status.success() { return Err(Error::Notarize( String::from_utf8_lossy(&output.stderr).into_owned(), )); } let output_str = String::from_utf8_lossy(&output.stdout); if let Ok(submit_output) = serde_json::from_str::(&output_str) { let log_message = format!( "{} with status {} for id {} ({})", if wait { "Finished" } else { "Submitted" }, submit_output.status.as_deref().unwrap_or("Pending"), submit_output.id, submit_output.message ); // status is empty when not waiting for the notarization to finish if submit_output.status.map_or(!wait, |s| s == "Accepted") { println!("Notarizing {log_message}"); if wait { println!("Stapling app..."); staple_app(app_bundle_path.to_path_buf())?; } else { println!("Not waiting for notarization to finish."); println!("You can use `xcrun notarytool log` to check the notarization progress."); println!( "When it's done you can optionally staple your app via `xcrun stapler staple {}`", app_bundle_path.display() ); } Ok(()) } else if let Ok(output) = Command::new("xcrun") .args(["notarytool", "log"]) .arg(&submit_output.id) .notarytool_args(auth, tmp_dir.path())? .output() { Err(Error::Notarize(format!( "{log_message}\nLog:\n{}", String::from_utf8_lossy(&output.stdout) ))) } else { Err(Error::Notarize(log_message)) } } else { Err(Error::ParseNotarytoolOutput { output: output_str.into_owned(), }) } } fn staple_app(mut app_bundle_path: PathBuf) -> Result<()> { let app_bundle_path_clone = app_bundle_path.clone(); let filename = app_bundle_path_clone .file_name() .expect("failed to get bundle filename") .to_str() .expect("failed to convert bundle filename to string"); app_bundle_path.pop(); Command::new("xcrun") .args(vec!["stapler", "staple", "-v", filename]) .current_dir(app_bundle_path) .output() .map_err(|error| Error::CommandFailed { command: "xcrun stapler staple".to_string(), error, })?; Ok(()) } pub trait NotarytoolCmdExt { fn notarytool_args( &mut self, auth: &AppleNotarizationCredentials, temp_dir: &Path, ) -> Result<&mut Self>; } impl NotarytoolCmdExt for Command { fn notarytool_args( &mut self, auth: &AppleNotarizationCredentials, temp_dir: &Path, ) -> Result<&mut Self> { match auth { AppleNotarizationCredentials::AppleId { apple_id, password, team_id, } => Ok( self .arg("--apple-id") .arg(apple_id) .arg("--password") .arg(password) .arg("--team-id") .arg(team_id), ), AppleNotarizationCredentials::ApiKey { key, key_id, issuer, } => { let key_path = match key { ApiKey::Raw(k) => { let key_path = temp_dir.join("AuthKey.p8"); std::fs::write(&key_path, k).map_err(|error| Error::Fs { context: "failed to write notarization API key to temp file", path: key_path.clone(), error, })?; key_path } ApiKey::Path(p) => p.to_owned(), }; Ok( self .arg("--key-id") .arg(key_id) .arg("--key") .arg(key_path) .arg("--issuer") .arg(issuer), ) } } } } fn decode_base64(base64_input: &OsStr, out_path: &Path) -> Result<()> { use base64::Engine; let input = base64_input .to_str() .expect("failed to convert base64 to string"); // strip whitespace before decoding let cleaned: String = input.chars().filter(|c| !c.is_ascii_whitespace()).collect(); let decoded = base64::engine::general_purpose::STANDARD .decode(&cleaned) .map_err(Error::Base64Decode)?; std::fs::write(out_path, &decoded).map_err(|error| Error::Fs { context: "failed to write decoded certificate", path: out_path.to_path_buf(), error, })?; Ok(()) } fn assert_command( response: std::result::Result, error_message: &str, ) -> std::io::Result<()> { let status = response.map_err(|e| std::io::Error::new(e.kind(), format!("{error_message}: {e}")))?; if !status.success() { Err(std::io::Error::other(error_message)) } else { Ok(()) } } ================================================ FILE: crates/tauri-macos-sign/src/provisioning_profile.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use std::{ffi::OsStr, path::PathBuf, process::Command}; use crate::{Error, Result}; use rand::distr::{Alphanumeric, SampleString}; pub struct ProvisioningProfile { path: PathBuf, } impl ProvisioningProfile { pub fn from_base64(base64: &OsStr) -> Result { let home_dir = dirs::home_dir().ok_or(Error::ResolveHomeDir)?; let provisioning_profiles_folder = home_dir .join("Library") .join("MobileDevice") .join("Provisioning Profiles"); std::fs::create_dir_all(&provisioning_profiles_folder).map_err(|error| Error::Fs { context: "failed to create provisioning profiles folder", path: provisioning_profiles_folder.clone(), error, })?; let provisioning_profile_path = provisioning_profiles_folder.join(format!( "{}.mobileprovision", Alphanumeric.sample_string(&mut rand::rng(), 16) )); super::decode_base64(base64, &provisioning_profile_path)?; Ok(Self { path: provisioning_profile_path, }) } pub fn uuid(&self) -> Result { let output = Command::new("security") .args(["cms", "-D", "-i"]) .arg(&self.path) .output() .map_err(|error| Error::CommandFailed { command: "security cms -D -i".to_string(), error, })?; if !output.status.success() { return Err(Error::FailedToDecodeProvisioningProfile); } let plist = plist::from_bytes::(&output.stdout).map_err(|error| Error::Plist { context: "failed to parse provisioning profile as plist", path: self.path.clone(), error, })?; plist .get("UUID") .and_then(|v| v.as_string().map(ToString::to_string)) .ok_or(Error::FailedToFindProvisioningProfileUuid) } } ================================================ FILE: crates/tauri-macros/CHANGELOG.md ================================================ # Changelog ## \[2.5.5] ### Dependencies - Upgraded to `tauri-utils@2.8.3` - Upgraded to `tauri-codegen@2.5.5` ## \[2.5.4] ### Dependencies - Upgraded to `tauri-codegen@2.5.4` ## \[2.5.3] ### Dependencies - Upgraded to `tauri-utils@2.8.2` - Upgraded to `tauri-codegen@2.5.3` ## \[2.5.2] ### Dependencies - Upgraded to `tauri-utils@2.8.1` - Upgraded to `tauri-codegen@2.5.2` ## \[2.5.1] ### Bug Fixes - [`4b00130b8`](https://www.github.com/tauri-apps/tauri/commit/4b00130b86a27b6f121bf57897b5e92d83bcc0fc) ([#14385](https://www.github.com/tauri-apps/tauri/pull/14385) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix iOS deadlock when running on the simulator from Xcode by properly piping stdout/stderr messages through the Xcode console and OSLog. ### Dependencies - Upgraded to `tauri-codegen@2.5.1` ## \[2.5.0] ### Bug Fixes - [`69476d8e2`](https://www.github.com/tauri-apps/tauri/commit/69476d8e2314b85bf46046140bc5495fe29b7d29) ([#14170](https://www.github.com/tauri-apps/tauri/pull/14170)) Fix the stack overflow when having too many commands in a single invoke handler in release build ### Dependencies - Upgraded to `tauri-utils@2.8.0` - Upgraded to `tauri-codegen@2.5.0` - [`6aa7f2d85`](https://www.github.com/tauri-apps/tauri/commit/6aa7f2d852870aeba1d4dd0e07f8be2bc9b66286) Upgraded to `tauri-utils@2.8.0` ## \[2.4.0] ### Dependencies - Upgraded to `tauri-utils@2.7.0`. - Upgraded to `tauri-codegen@2.4.0` ## \[2.3.2] ### Dependencies - Upgraded to `tauri-utils@2.6.0` - Upgraded to `tauri-codegen@2.3.1` ## \[2.3.1] ### Performance Improvements - [`0a552a868`](https://www.github.com/tauri-apps/tauri/commit/0a552a868c559d367d85c264bf052009b048bd8e) ([#13690](https://www.github.com/tauri-apps/tauri/pull/13690) by [@montyc1999](https://www.github.com/tauri-apps/tauri/../../montyc1999)) Cache `rustc -V` output in `#[tauri::command]` macros ## \[2.2.1] ### Dependencies - Upgraded to `tauri-codegen@2.3.0` - Upgraded to `tauri-utils@2.5.0` ## \[2.2.0] ### Dependencies - Upgraded to `tauri-utils@2.4.0` - Upgraded to `tauri-codegen@2.2.0` - [`48b12b440`](https://www.github.com/tauri-apps/tauri/commit/48b12b440478937c46fdfef9f9d95194be117020) Update to `tauri-utils@2.4.0` ## \[2.1.1] ### Dependencies - Upgraded to `tauri-utils@2.3.1` - Upgraded to `tauri-codegen@2.1.1` ## \[2.1.0] ### New Features - [`013f8f652`](https://www.github.com/tauri-apps/tauri/commit/013f8f652302f2d49c5ec0a075582033d8b074fb) ([#12890](https://www.github.com/tauri-apps/tauri/pull/12890) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Added `build > removeUnusedCommands` to trigger the build scripts and macros to remove unused commands based on the capabilities you defined. Note this won't be accounting for dynamically added ACLs so make sure to check it when using this. ### Dependencies - Upgraded to `tauri-utils@2.3.0` - Upgraded to `tauri-codegen@2.1.0` ## \[2.0.5] ### Dependencies - Upgraded to `tauri-utils@2.2.0` - Upgraded to `tauri-codegen@2.0.5` ## \[2.0.4] ### Dependencies - Upgraded to `tauri-utils@2.1.1` - Upgraded to `tauri-codegen@2.0.4` ## \[2.0.3] ### Enhancements - [`17c6952ae`](https://www.github.com/tauri-apps/tauri/commit/17c6952aec965fa41e6695ad68461a218afc20f1) ([#11522](https://www.github.com/tauri-apps/tauri/pull/11522) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Enhance the error message when using `async` commands with a reference. ### Dependencies - Upgraded to `tauri-utils@2.1.0` - Upgraded to `tauri-codegen@2.0.3` ## \[2.0.1] ### What's Changed - [`0ab2b3306`](https://www.github.com/tauri-apps/tauri/commit/0ab2b330644b6419f6cee1d5377bfb5cdda2ccf9) ([#11205](https://www.github.com/tauri-apps/tauri/pull/11205) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Downgrade MSRV to 1.77.2 to support Windows 7. ### Dependencies - Upgraded to `tauri-utils@2.0.1` - Upgraded to `tauri-codegen@2.0.1` ## \[2.0.0] ### What's Changed - [`382ed482b`](https://www.github.com/tauri-apps/tauri/commit/382ed482bd08157c39e62f9a0aaad8802f1092cb) Bump MSRV to 1.78. - [`637285790`](https://www.github.com/tauri-apps/tauri/commit/6372857905ae9c0aedb7f482ddf6cf9f9836c9f2) Promote to v2 stable! ### Dependencies - Upgraded to `tauri-utils@2.0.0` - Upgraded to `tauri-codegen@2.0.0` ## \[2.0.0-rc.12] ### New Features - [`1d8b67b29`](https://www.github.com/tauri-apps/tauri/commit/1d8b67b2970a09ec478093e127612fac823de805) ([#11162](https://www.github.com/tauri-apps/tauri/pull/11162) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Support async functions for `mobile_entry_point` macro ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.13` - Upgraded to `tauri-codegen@2.0.0-rc.13` ## \[2.0.0-rc.11] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.12` - Upgraded to `tauri-codegen@2.0.0-rc.12` ## \[2.0.0-rc.10] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.11` - Upgraded to `tauri-codegen@2.0.0-rc.11` ## \[2.0.0-rc.9] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.10` - Upgraded to `tauri-codegen@2.0.0-rc.10` ## \[2.0.0-rc.8] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.9` - Upgraded to `tauri-codegen@2.0.0-rc.9` ## \[2.0.0-rc.7] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.8` - Upgraded to `tauri-codegen@2.0.0-rc.8` ## \[2.0.0-rc.6] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.7` - Upgraded to `tauri-codegen@2.0.0-rc.7` ## \[2.0.0-rc.6] ### What's Changed - [`f4d5241b3`](https://www.github.com/tauri-apps/tauri/commit/f4d5241b377d0f7a1b58100ee19f7843384634ac) ([#10731](https://www.github.com/tauri-apps/tauri/pull/10731) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Update documentation icon path. ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.6` - Upgraded to `tauri-codegen@2.0.0-rc.6` ## \[2.0.0-rc.5] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.5` - Upgraded to `tauri-codegen@2.0.0-rc.5` ## \[2.0.0-rc.4] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.4` - Upgraded to `tauri-codegen@2.0.0-rc.4` ## \[2.0.0-rc.3] ### Dependencies - Upgraded to `tauri-codegen@2.0.0-rc.3` - Upgraded to `tauri-utils@2.0.0-rc.3` ## \[2.0.0-rc.2] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.2` - Upgraded to `tauri-codegen@2.0.0-rc.2` ## \[2.0.0-rc.1] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.1` - Upgraded to `tauri-codegen@2.0.0-rc.1` ## \[2.0.0-rc.0] ### Dependencies - Upgraded to `tauri-codegen@2.0.0-rc.0` - Upgraded to `tauri-utils@2.0.0-rc.0` ## \[2.0.0-beta.19] ### What's Changed - [`4c239729c`](https://www.github.com/tauri-apps/tauri/commit/4c239729c3e1b899ecbc6793c3682848e8de1729) ([#10167](https://www.github.com/tauri-apps/tauri/pull/10167) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add support for `test = true` in `generate_context!` macro to skip some code generation that could affect some tests, for now it only skips empedding a plist on macOS. ### Dependencies - Upgraded to `tauri-codegen@2.0.0-beta.19` - Upgraded to `tauri-utils@2.0.0-beta.19` ## \[2.0.0-beta.18] ### New Features - [`5b769948a`](https://www.github.com/tauri-apps/tauri/commit/5b769948a81cac333f64c870a470ba6525bd5cd3) ([#9959](https://www.github.com/tauri-apps/tauri/pull/9959)) Add `include_image` macro to help embedding instances of `Image` struct at compile-time in rust to be used with window, menu or tray icons. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.18` - Upgraded to `tauri-codegen@2.0.0-beta.18` ## \[2.0.0-beta.17] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.17` - Upgraded to `tauri-codegen@2.0.0-beta.17` ### Breaking Changes - [`1df5cdeb0`](https://www.github.com/tauri-apps/tauri/commit/1df5cdeb06f5464e0eec4055e21b7b7bc8739eed)([#9858](https://www.github.com/tauri-apps/tauri/pull/9858)) Use `tauri.conf.json > identifier` to set the `PackageName` in Android and `BundleId` in iOS. ## \[2.0.0-beta.16] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.16` - Upgraded to `tauri-codegen@2.0.0-beta.16` ## \[2.0.0-beta.15] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.15` - Upgraded to `tauri-codegen@2.0.0-beta.15` ## \[2.0.0-beta.14] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.14` - Upgraded to `tauri-codegen@2.0.0-beta.14` ## \[2.0.0-beta.13] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.13` - Upgraded to `tauri-codegen@2.0.0-beta.13` ## \[2.0.0-beta.12] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.12` - Upgraded to `tauri-codegen@2.0.0-beta.12` ## \[2.0.0-beta.11] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.11` - Upgraded to `tauri-codegen@2.0.0-beta.11` ## \[2.0.0-beta.10] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.10` - Upgraded to `tauri-codegen@2.0.0-beta.10` ## \[2.0.0-beta.9] ### New Features - [`ba0206d8a`](https://www.github.com/tauri-apps/tauri/commit/ba0206d8a30a9b43ec5090dcaabd1a23baa1420c)([#9141](https://www.github.com/tauri-apps/tauri/pull/9141)) The `Context` codegen now accepts a `assets` input to define a custom `tauri::Assets` implementation. ### Dependencies - Upgraded to `tauri-codegen@2.0.0-beta.9` - Upgraded to `tauri-utils@2.0.0-beta.9` ## \[2.0.0-beta.8] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.8` - Upgraded to `tauri-codegen@2.0.0-beta.8` ## \[2.0.0-beta.7] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.7` - Upgraded to `tauri-codegen@2.0.0-beta.7` ## \[2.0.0-beta.6] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.6` - Upgraded to `tauri-codegen@2.0.0-beta.6` ## \[2.0.0-beta.5] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.5` - Upgraded to `tauri-codegen@2.0.0-beta.5` ## \[2.0.0-beta.4] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.4` - Upgraded to `tauri-codegen@2.0.0-beta.4` ## \[2.0.0-beta.3] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.3` - Upgraded to `tauri-codegen@2.0.0-beta.3` ## \[2.0.0-beta.2] ### Enhancements - [`8d16a80d`](https://www.github.com/tauri-apps/tauri/commit/8d16a80d2fb2468667e7987d0cc99dbc7e3b9d0a)([#8802](https://www.github.com/tauri-apps/tauri/pull/8802)) The `generate_context` proc macro now accepts a `capabilities` attribute where the value is an array of file paths that can be [conditionally compiled](https://doc.rust-lang.org/reference/conditional-compilation.html). These capabilities are added to the application along the capabilities defined in the Tauri configuration file. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.2` - Upgraded to `tauri-codegen@2.0.0-beta.2` ## \[2.0.0-beta.1] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.1` - Upgraded to `tauri-codegen@2.0.0-beta.1` ## \[2.0.0-beta.0] ### New Features - [`74a2a603`](https://www.github.com/tauri-apps/tauri/commit/74a2a6036a5e57462f161d728cbd8a6f121028ca)([#8661](https://www.github.com/tauri-apps/tauri/pull/8661)) Implement access control list for IPC usage. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.0` - Upgraded to `tauri-codegen@2.0.0-beta.0` ## \[2.0.0-alpha.13] ### Enhancements - [`d621d343`](https://www.github.com/tauri-apps/tauri/commit/d621d3437ce3947175eecf345b2c6d1c4c7ce020)([#8607](https://www.github.com/tauri-apps/tauri/pull/8607)) Added tracing for window startup, plugins, `Window::eval`, events, IPC, updater and custom protocol request handlers behind the `tracing` feature flag. ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.13` - Upgraded to `tauri-codegen@2.0.0-alpha.13` ## \[2.0.0-alpha.12] ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.12` - Upgraded to `tauri-codegen@2.0.0-alpha.12` ## \[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 - [`c6c59cf2`](https://www.github.com/tauri-apps/tauri/commit/c6c59cf2373258b626b00a26f4de4331765dd487) Pull changes from Tauri 1.5 release. ### Dependencies - Upgraded to `tauri-codegen@2.0.0-alpha.10` - Upgraded to `tauri-utils@2.0.0-alpha.10` ## \[2.0.0-alpha.9] ### New Features - [`880266a7`](https://www.github.com/tauri-apps/tauri/commit/880266a7f697e1fe58d685de3bb6836ce5251e92)([#8031](https://www.github.com/tauri-apps/tauri/pull/8031)) Bump the MSRV to 1.70. ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.9` - Upgraded to `tauri-codegen@2.0.0-alpha.9` ### Breaking Changes - [`ebcc21e4`](https://www.github.com/tauri-apps/tauri/commit/ebcc21e4b95f4e8c27639fb1bca545b432f52d5e)([#8057](https://www.github.com/tauri-apps/tauri/pull/8057)) Renamed the beforeDevCommand, beforeBuildCommand and beforeBundleCommand hooks environment variables from `TAURI_PLATFORM, TAURI_ARCH, TAURI_FAMILY, TAURI_PLATFORM_VERSION, TAURI_PLATFORM_TYPE and TAURI_DEBUG` to `TAURI_ENV_PLATFORM, TAURI_ENV_ARCH, TAURI_ENV_FAMILY, TAURI_ENV_PLATFORM_VERSION, TAURI_ENV_PLATFORM_TYPE and TAURI_ENV_DEBUG` to differentiate the prefix with other CLI environment variables. ## \[2.0.0-alpha.8] ### Enhancements - [`100d9ede`](https://www.github.com/tauri-apps/tauri/commit/100d9ede35995d9db21d2087dd5606adfafb89a5)([#7802](https://www.github.com/tauri-apps/tauri/pull/7802)) Use `Target` enum from `tauri_utils::platform`. ### Dependencies - Upgraded to `tauri-codegen@2.0.0-alpha.8` - Upgraded to `tauri-utils@2.0.0-alpha.8` ## \[2.0.0-alpha.7] ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.7` - Upgraded to `tauri-codegen@2.0.0-alpha.7` ### Breaking Changes - [`fbeb5b91`](https://www.github.com/tauri-apps/tauri/commit/fbeb5b9185baeda19e865228179e3e44c165f1d9)([#7170](https://www.github.com/tauri-apps/tauri/pull/7170)) Moved `tauri::api::ipc` to `tauri::ipc` and refactored all types. ## \[2.0.0-alpha.6] ### Dependencies - Updated to latest `tauri-utils` ## \[2.0.0-alpha.5] - [`7a4b1fb9`](https://www.github.com/tauri-apps/tauri/commit/7a4b1fb96da475053c61960f362bbecf18cd00d4)([#6839](https://www.github.com/tauri-apps/tauri/pull/6839)) Added support to attibutes for each command path in the `generate_handler` macro. - [`96639ca2`](https://www.github.com/tauri-apps/tauri/commit/96639ca239c9e4f75142fc07868ac46822111cff)([#6749](https://www.github.com/tauri-apps/tauri/pull/6749)) Moved the `shell` functionality to its own plugin in the plugins-workspace repository. - [`3188f376`](https://www.github.com/tauri-apps/tauri/commit/3188f3764978c6d1452ee31d5a91469691e95094)([#6883](https://www.github.com/tauri-apps/tauri/pull/6883)) Bump the MSRV to 1.65. - [`9a79dc08`](https://www.github.com/tauri-apps/tauri/commit/9a79dc085870e0c1a5df13481ff271b8c6cc3b78)([#6947](https://www.github.com/tauri-apps/tauri/pull/6947)) Removed the module command macros. ## \[2.0.0-alpha.4] - Added `android` configuration object under `tauri > bundle`. - Bumped due to a bump in tauri-utils. - [db4c9dc6](https://www.github.com/tauri-apps/tauri/commit/db4c9dc655e07ee2184fe04571f500f7910890cd) feat(core): add option to configure Android's minimum SDK version ([#6651](https://www.github.com/tauri-apps/tauri/pull/6651)) on 2023-04-07 ## \[2.0.0-alpha.3] - Pull changes from Tauri 1.3 release. - [](https://www.github.com/tauri-apps/tauri/commit/undefined) on undefined ## \[2.0.0-alpha.2] - Resolve Android package name from single word bundle identifiers. - [60a8b07d](https://www.github.com/tauri-apps/tauri/commit/60a8b07dc7c56c9c45331cb57d9afb410e7eadf3) fix: handle single word bundle identifier when resolving Android domain ([#6313](https://www.github.com/tauri-apps/tauri/pull/6313)) on 2023-02-19 - Return `bool` in the invoke handler. - [05dad087](https://www.github.com/tauri-apps/tauri/commit/05dad0876842e2a7334431247d49365cee835d3e) feat: initial work for iOS plugins ([#6205](https://www.github.com/tauri-apps/tauri/pull/6205)) on 2023-02-11 - Refactored the implementation of the `mobile_entry_point` macro. - [9feab904](https://www.github.com/tauri-apps/tauri/commit/9feab904bf08b5c168d4779c21d0419409a68d30) feat(core): add API to call Android plugin ([#6239](https://www.github.com/tauri-apps/tauri/pull/6239)) on 2023-02-10 ## \[2.0.0-alpha.1] - Refactor mobile environment variables. - [dee9460f](https://www.github.com/tauri-apps/tauri/commit/dee9460f9c9bc92e9c638e7691e616849ac2085b) feat: keep CLI alive when iOS app exits, show logs, closes [#5855](https://www.github.com/tauri-apps/tauri/pull/5855) ([#5902](https://www.github.com/tauri-apps/tauri/pull/5902)) on 2022-12-27 - Bump the MSRV to 1.64. - [7eb9aa75](https://www.github.com/tauri-apps/tauri/commit/7eb9aa75cfd6a3176d3f566fdda02d88aa529b0f) Update gtk to 0.16 ([#6155](https://www.github.com/tauri-apps/tauri/pull/6155)) on 2023-01-30 - Removed mobile logging initialization, which will be handled by `tauri-plugin-log`. - [](https://www.github.com/tauri-apps/tauri/commit/undefined) on undefined ## \[2.0.0-alpha.0] - Added the `mobile_entry_point` macro. - [98904863](https://www.github.com/tauri-apps/tauri/commit/9890486321c9c79ccfb7c547fafee85b5c3ffa71) feat(core): add `mobile_entry_point` macro ([#4983](https://www.github.com/tauri-apps/tauri/pull/4983)) on 2022-08-21 - First mobile alpha release! - [fa3a1098](https://www.github.com/tauri-apps/tauri/commit/fa3a10988a03aed1b66fb17d893b1a9adb90f7cd) feat(ci): prepare 2.0.0-alpha.0 ([#5786](https://www.github.com/tauri-apps/tauri/pull/5786)) on 2022-12-08 ## \[1.4.3] ### Dependencies - Upgraded to `tauri-utils@1.5.2` - Upgraded to `tauri-codegen@1.4.2` ## \[1.4.2] ### Enhancements - [`5e05236b`](https://www.github.com/tauri-apps/tauri/commit/5e05236b4987346697c7caae0567d3c50714c198)([#8289](https://www.github.com/tauri-apps/tauri/pull/8289)) Added tracing for window startup, plugins, `Window::eval`, events, IPC, updater and custom protocol request handlers behind the `tracing` feature flag. ## \[1.4.1] ### Dependencies - Upgraded to `tauri-utils@1.5.0` - Upgraded to `tauri-codegen@1.4.1` ## \[1.4.0] ### Enhancements - [`d68a25e3`](https://www.github.com/tauri-apps/tauri/commit/d68a25e32e012e57a9e5225b589b9ecbea70a887)([#6124](https://www.github.com/tauri-apps/tauri/pull/6124)) Improve compiler error message when generating an async command that has a reference input and don't return a Result. ## \[1.3.0] - Bump minimum supported Rust version to 1.60. - [5fdc616d](https://www.github.com/tauri-apps/tauri/commit/5fdc616df9bea633810dcb814ac615911d77222c) feat: Use the zbus-backed of notify-rust ([#6332](https://www.github.com/tauri-apps/tauri/pull/6332)) on 2023-03-31 ## \[1.2.1] - Fix `allowlist > app > show/hide` always disabled when `allowlist > app > all: false`. - Bumped due to a bump in tauri-utils. - [bb251087](https://www.github.com/tauri-apps/tauri/commit/bb2510876d0bdff736d36bf3a465cdbe4ad2b90c) fix(core): extend allowlist with `app`'s allowlist, closes [#5650](https://www.github.com/tauri-apps/tauri/pull/5650) ([#5652](https://www.github.com/tauri-apps/tauri/pull/5652)) on 2022-11-18 ## \[1.2.0] - - [7d9aa398](https://www.github.com/tauri-apps/tauri/commit/7d9aa3987efce2d697179ffc33646d086c68030c) feat: bump MSRV to 1.59 ([#5296](https://www.github.com/tauri-apps/tauri/pull/5296)) on 2022-09-28 ## \[1.1.1] - Add missing allowlist config for `set_cursor_grab`, `set_cursor_visible`, `set_cursor_icon` and `set_cursor_position` APIs. - Bumped due to a bump in tauri-utils. - [c764408d](https://www.github.com/tauri-apps/tauri/commit/c764408da7fae123edd41115bda42fa75a4731d2) fix: Add missing allowlist config for cursor apis, closes [#5207](https://www.github.com/tauri-apps/tauri/pull/5207) ([#5211](https://www.github.com/tauri-apps/tauri/pull/5211)) on 2022-09-16 ## \[1.1.0] - Added support to configuration files in TOML format (Tauri.toml file). - [ae83d008](https://www.github.com/tauri-apps/tauri/commit/ae83d008f9e1b89bfc8dddaca42aa5c1fbc36f6d) feat: add support to TOML config file `Tauri.toml`, closes [#4806](https://www.github.com/tauri-apps/tauri/pull/4806) ([#4813](https://www.github.com/tauri-apps/tauri/pull/4813)) on 2022-08-02 ## \[1.0.4] - Adjust command imports to fix `items_after_statements` Clippy warning. - [d3e19e34](https://www.github.com/tauri-apps/tauri/commit/d3e19e3420a023cddc46173a2d1f1e6c5a390a1b) fix(macros): `items_after_statements` Clippy warning, closes [#4639](https://www.github.com/tauri-apps/tauri/pull/4639) on 2022-07-11 - Remove raw identifier (`r#`) prefix from command arguments. - [ac72800f](https://www.github.com/tauri-apps/tauri/commit/ac72800fb630738e2502569935ecdc83e3e78055) fix(macros): strip `r#` from command arguments, closes [#4654](https://www.github.com/tauri-apps/tauri/pull/4654) ([#4657](https://www.github.com/tauri-apps/tauri/pull/4657)) on 2022-07-12 ## \[1.0.3] - Add `#[doc(hidden)]` attribute to the `#[command]` generated macro. - [d4cdf807](https://www.github.com/tauri-apps/tauri/commit/d4cdf80781a7955ac620fe6d394e82d067178c4d) feat(macros): hide command macro from docs, closes [#4550](https://www.github.com/tauri-apps/tauri/pull/4550) ([#4556](https://www.github.com/tauri-apps/tauri/pull/4556)) on 2022-07-01 ## \[1.0.2] - Expose `platform::windows_version` function. - Bumped due to a bump in tauri-utils. - [bf764e83](https://www.github.com/tauri-apps/tauri/commit/bf764e83e01e7443e6cc54572001e1c98c357465) feat(utils): expose `windows_version` function ([#4534](https://www.github.com/tauri-apps/tauri/pull/4534)) on 2022-06-30 ## \[1.0.1] - Set the bundle name and app metadata in the Info.plist file in development mode. - [38f5db6e](https://www.github.com/tauri-apps/tauri/commit/38f5db6e6a8b496b50d486db6fd8204266de3a69) feat(codegen): fill app metadata in development Info.plist on 2022-06-21 - Set the application icon in development mode on macOS. - [307c2ebf](https://www.github.com/tauri-apps/tauri/commit/307c2ebfb68238dacab6088f9c6ba310c727c68c) feat(core): set macOS app icon in development ([#4385](https://www.github.com/tauri-apps/tauri/pull/4385)) on 2022-06-19 ## \[1.0.0] - Upgrade to `stable`! - [f4bb30cc](https://www.github.com/tauri-apps/tauri/commit/f4bb30cc73d6ba9b9ef19ef004dc5e8e6bb901d3) feat(covector): prepare for v1 ([#4351](https://www.github.com/tauri-apps/tauri/pull/4351)) on 2022-06-15 ## \[1.0.0-rc.11] - Read the tray icon path relatively to the config directory. - Bumped due to a bump in tauri-codegen. - [562e8ca2](https://www.github.com/tauri-apps/tauri/commit/562e8ca23facf1a8e5fa6c8cdf872357d3523a78) fix(codegen): tray icon path is relative to the config directory on 2022-06-15 ## \[1.0.0-rc.10] - **Breaking change:** The `TrayIcon` enum has been removed and now `Icon` is used instead. This allows you to use more image formats and use embedded icons on Linux. - Bumped due to a bump in tauri-codegen. - [4ce8e228](https://www.github.com/tauri-apps/tauri/commit/4ce8e228134cd3f22973b74ef26ca0d165fbbbd9) refactor(core): use `Icon` for tray icons ([#4342](https://www.github.com/tauri-apps/tauri/pull/4342)) on 2022-06-14 ## \[1.0.0-rc.9] - Added a config flag to bundle the media framework used by webkit2gtk `tauri.conf.json > tauri > bundle > appimage > bundleMediaFramework`. - Bumped due to a bump in tauri-utils. - [d335fae9](https://www.github.com/tauri-apps/tauri/commit/d335fae92cdcbb0ee18aad4e54558914afa3e778) feat(bundler): bundle additional gstreamer files, closes [#4092](https://www.github.com/tauri-apps/tauri/pull/4092) ([#4271](https://www.github.com/tauri-apps/tauri/pull/4271)) on 2022-06-10 ## \[1.0.0-rc.8] - **Breaking change:** `PackageInfo::version` is now a `semver::Version` instead of a `String`. - Bumped due to a bump in tauri-utils. - [2badbd2d](https://www.github.com/tauri-apps/tauri/commit/2badbd2d7ed51bf33c1b547b4c837b600574bd4a) refactor: force semver versions, change updater `should_install` sig ([#4215](https://www.github.com/tauri-apps/tauri/pull/4215)) on 2022-05-25 - [a7388e23](https://www.github.com/tauri-apps/tauri/commit/a7388e23c3b9019d48b078cae00a75c74d74d11b) fix(ci): adjust change file to include tauri-utils and tauri-codegen on 2022-05-27 ## \[1.0.0-rc.7] - Allow configuring the display options for the MSI execution allowing quieter updates. - Bumped due to a bump in tauri-utils. - [9f2c3413](https://www.github.com/tauri-apps/tauri/commit/9f2c34131952ea83c3f8e383bc3cec7e1450429f) feat(core): configure msiexec display options, closes [#3951](https://www.github.com/tauri-apps/tauri/pull/3951) ([#4061](https://www.github.com/tauri-apps/tauri/pull/4061)) on 2022-05-15 ## \[1.0.0-rc.6] - Added `$schema` support to `tauri.conf.json`. - Bumped due to a bump in tauri-utils. - [715cbde3](https://www.github.com/tauri-apps/tauri/commit/715cbde3842a916c4ebeab2cab348e1774b5c192) feat(config): add `$schema` to `tauri.conf.json`, closes [#3464](https://www.github.com/tauri-apps/tauri/pull/3464) ([#4031](https://www.github.com/tauri-apps/tauri/pull/4031)) on 2022-05-03 - The `dangerous_allow_asset_csp_modification` configuration value has been changed to allow a list of CSP directives to disable. - Bumped due to a bump in tauri-utils. - [164078c0](https://www.github.com/tauri-apps/tauri/commit/164078c0b719ccbc12e956fecf8a7d4a3c5044e1) feat: allow limiting dangerousDisableAssetCspModification, closes [#3831](https://www.github.com/tauri-apps/tauri/pull/3831) ([#4021](https://www.github.com/tauri-apps/tauri/pull/4021)) on 2022-05-02 ## \[1.0.0-rc.5] - Read platform-specific configuration files when generating code without the `TAURI_CONFIG` env var. - Bumped due to a bump in tauri-codegen. - [edf85bc1](https://www.github.com/tauri-apps/tauri/commit/edf85bc1d18450c92aee17f7f99c163abe432ebd) fix(codegen): read platform-specific config file ([#3966](https://www.github.com/tauri-apps/tauri/pull/3966)) on 2022-04-25 ## \[1.0.0-rc.4] - Replace multiple dependencies who's C code compiled concurrently and caused the other ones to bloat compile time significantly. - `zstd` -> `brotli` - `blake3` -> a vendored version of the blake3 reference - `ring` -> `getrandom` See for more information about these specific choices. - [8661e3e2](https://www.github.com/tauri-apps/tauri/commit/8661e3e24d96c399bfbcdee5d8e9d6beba2265a7) replace dependencies with long build times when used together (closes [#3571](https://www.github.com/tauri-apps/tauri/pull/3571)) ([#3773](https://www.github.com/tauri-apps/tauri/pull/3773)) on 2022-03-27 ## \[1.0.0-rc.3] - Parse window icons at compile time. - Bumped due to a bump in tauri-codegen. - [8c935872](https://www.github.com/tauri-apps/tauri/commit/8c9358725a17dcc2acaf4d10c3f654afdff586b0) refactor(core): move `png` and `ico` behind Cargo features ([#3588](https://www.github.com/tauri-apps/tauri/pull/3588)) on 2022-03-05 ## \[1.0.0-rc.2] - Changed the default value for `tauri > bundle > macOS > minimumSystemVersion` to `10.13`. - Bumped due to a bump in tauri-utils. - [fce344b9](https://www.github.com/tauri-apps/tauri/commit/fce344b90b7227f8f5514853c2f885fb24d3648e) feat(core): set default value for `minimum_system_version` to 10.13 ([#3497](https://www.github.com/tauri-apps/tauri/pull/3497)) on 2022-02-17 ## \[1.0.0-rc.1] - Change default value for the `freezePrototype` configuration to `false`. - Bumped due to a bump in tauri-utils. - [3a4c0160](https://www.github.com/tauri-apps/tauri/commit/3a4c01606184be762adee055ddac803de0d28527) fix(core): change default `freezePrototype` to false, closes [#3416](https://www.github.com/tauri-apps/tauri/pull/3416) [#3406](https://www.github.com/tauri-apps/tauri/pull/3406) ([#3423](https://www.github.com/tauri-apps/tauri/pull/3423)) on 2022-02-12 ## \[1.0.0-rc.0] - Adds support for using JSON5 format for the `tauri.conf.json` file, along with also supporting the `.json5` extension. Here is the logic flow that determines if JSON or JSON5 will be used to parse the config: 1. Check if `tauri.conf.json` exists a. Parse it with `serde_json` b. Parse it with `json5` if `serde_json` fails c. Return original `serde_json` error if all above steps failed 2. Check if `tauri.conf.json5` exists a. Parse it with `json5` b. Return error if all above steps failed 3. Return error if all above steps failed - [995de57a](https://www.github.com/tauri-apps/tauri/commit/995de57a76cf51215277673e526d7ec32b86b564) Add seamless support for using JSON5 in the config file ([#47](https://www.github.com/tauri-apps/tauri/pull/47)) on 2022-02-03 - The minimum Rust version is now `1.56`. - [a9dfc015](https://www.github.com/tauri-apps/tauri/commit/a9dfc015505afe91281c2027954ffcc588b1a59c) feat: update to edition 2021 and set minimum rust to 1.56 ([#2789](https://www.github.com/tauri-apps/tauri/pull/2789)) on 2021-10-22 ## \[1.0.0-beta.5] - Embed Info.plist file contents on binary on dev. - Bumped due to a bump in tauri-codegen. - [537ab1b6](https://www.github.com/tauri-apps/tauri/commit/537ab1b6d5a792c550a535619965c9e4126292e6) feat(core): inject src-tauri/Info.plist file on dev and merge on bundle, closes [#1570](https://www.github.com/tauri-apps/tauri/pull/1570) [#2338](https://www.github.com/tauri-apps/tauri/pull/2338) ([#2444](https://www.github.com/tauri-apps/tauri/pull/2444)) on 2021-08-15 - Fix ES Module detection for default imports with relative paths or scoped packages and exporting of async functions. - Bumped due to a bump in tauri-codegen. - [b2b36cfe](https://www.github.com/tauri-apps/tauri/commit/b2b36cfe8dfcccb341638a4cb6dc23a514c54148) fix(core): fixes ES Module detection for default imports with relative paths or scoped packages ([#2380](https://www.github.com/tauri-apps/tauri/pull/2380)) on 2021-08-10 - [fbf8caf5](https://www.github.com/tauri-apps/tauri/commit/fbf8caf5c419cb4fc3d123be910e094a8e8c4bef) fix(core): ESM detection when using `export async function` ([#2425](https://www.github.com/tauri-apps/tauri/pull/2425)) on 2021-08-14 ## \[1.0.0-beta.4] - `Params` has been removed, along with all the associated types on it. Functions that previously accepted those associated types now accept strings instead. Type that used a generic parameter `Params` now use `Runtime` instead. If you use the `wry` feature, then types with a `Runtime` generic parameter should default to `Wry`, letting you omit the explicit type and let the compiler infer it instead. `tauri`: - See `Params` note - If you were using `Params` inside a function parameter or definition, all references to it have been replaced with a simple runtime that defaults to `Wry`. If you are not using a custom runtime, just remove `Params` from the definition of functions/items that previously took it. If you are using a custom runtime, you *may* need to pass the runtime type to these functions. - If you were using custom types for `Params` (uncommon and if you don't understand you probably were not using it), all methods that were previously taking the custom type now takes an `Into` or a `&str`. The types were already required to be string-able, so just make sure to convert it into a string before passing it in if this breaking change affects you. `tauri-macros`: - (internal) Added private `default_runtime` proc macro to allow us to give item definitions a custom runtime only when the specified feature is enabled. `tauri-runtime`: - See `Params` note - Removed `Params`, `MenuId`, `Tag`, `TagRef`. - Added `menu::{MenuHash, MenuId, MenuIdRef}` as type aliases for the internal type that menu types now use. - All previous menu items that had a `MenuId` generic now use the underlying `MenuId` type without a generic. - `Runtime`, `RuntimeHandle`, and `Dispatch` have no more generic parameter on `create_window(...)` and instead use the `Runtime` type directly - `Runtime::system_tray` has no more `MenuId` generic and uses the string based `SystemTray` type directly. - (internal) `CustomMenuItem::id_value()` is now hashed on creation and exposed as the `id` field with type `MenuHash`. `tauri-runtime-wry`: - See `Params` note - update menu and runtime related types to the ones changed in `tauri-runtime`. `tauri-utils`: - `Assets::get` signature has changed to take a `&AssetKey` instead of `impl Into` to become trait object safe. - [fd8fab50](https://www.github.com/tauri-apps/tauri/commit/fd8fab507c8fa1b113b841af14c6693eb3955f6b) refactor(core): remove `Params` and replace with strings ([#2191](https://www.github.com/tauri-apps/tauri/pull/2191)) on 2021-07-15 ## \[1.0.0-beta.3] - Detect ESM scripts and inject the invoke key directly instead of using an IIFE. - Bumped due to a bump in tauri-codegen. - [7765c7fa](https://www.github.com/tauri-apps/tauri/commit/7765c7fa281853ddfb26b6b17534df95eaede804) fix(core): invoke key injection on ES module, improve performance ([#2094](https://www.github.com/tauri-apps/tauri/pull/2094)) on 2021-06-27 - Improve invoke key code injection performance time rewriting code at compile time. - Bumped due to a bump in tauri-codegen. - [7765c7fa](https://www.github.com/tauri-apps/tauri/commit/7765c7fa281853ddfb26b6b17534df95eaede804) fix(core): invoke key injection on ES module, improve performance ([#2094](https://www.github.com/tauri-apps/tauri/pull/2094)) on 2021-06-27 ## \[1.0.0-beta.2] - internal: Refactor all macro code that expects specific bindings to be passed Idents - [39f8f269](https://www.github.com/tauri-apps/tauri/commit/39f8f269164d2fda3d5b614a193b12bb266e4b4b) refactor(macros): explicitly pass idents ([#1812](https://www.github.com/tauri-apps/tauri/pull/1812)) on 2021-05-13 ## \[1.0.0-beta.1] - Fixes a name collision when the command function is named `invoke`. - [7862ec5](https://www.github.com/tauri-apps/tauri/commit/7862ec562fa70e3733263ce1f690d6cd2943c0b4) fix(macros): change invoke binding in generate handler ([#1804](https://www.github.com/tauri-apps/tauri/pull/1804)) on 2021-05-12 - Fixes a name collision when the command function is named `message` or `resolver`. - [0b87532](https://www.github.com/tauri-apps/tauri/commit/0b875327067ca825ff6f6f26c9b2ce6fcb001e79) fix(macros): fix rest of command collisions ([#1805](https://www.github.com/tauri-apps/tauri/pull/1805)) on 2021-05-12 - Fixes a name collision when the command function is named `cmd`. - [d36b726](https://www.github.com/tauri-apps/tauri/commit/d36b7269261d329dd7d7fcd4d5098f3fca167364) fix(macros): collision when command is named `cmd` ([#1802](https://www.github.com/tauri-apps/tauri/pull/1802)) on 2021-05-12 ## \[1.0.0-beta.0] - Only commands with a `async fn` are executed on a separate task. `#[command] fn command_name` runs on the main thread. - [bb8dafb](https://www.github.com/tauri-apps/tauri/commit/bb8dafbe1ea6edde7385631d41ac05e96a3309ef) feat(core): #\[command] return with autoref specialization workaround fix [#1672](https://www.github.com/tauri-apps/tauri/pull/1672) ([#1734](https://www.github.com/tauri-apps/tauri/pull/1734)) on 2021-05-09 - `#[command]` now generates a macro instead of a function to allow passing through `Params` and other generics. `generate_handler!` has been changed to consume the generated `#[command]` macro - [1453d4b](https://www.github.com/tauri-apps/tauri/commit/1453d4bf842ed6891ec604e0635344c930282189) feat(core): support generics (especially Param) in #\[command] ([#1622](https://www.github.com/tauri-apps/tauri/pull/1622)) on 2021-05-05 - Improves support for commands returning `Result`. - [bb8dafb](https://www.github.com/tauri-apps/tauri/commit/bb8dafbe1ea6edde7385631d41ac05e96a3309ef) feat(core): #\[command] return with autoref specialization workaround fix [#1672](https://www.github.com/tauri-apps/tauri/pull/1672) ([#1734](https://www.github.com/tauri-apps/tauri/pull/1734)) on 2021-05-09 - Adds support to command state, triggered when a command argument is `arg: State<'_, StateType>`. - [8b6f3de](https://www.github.com/tauri-apps/tauri/commit/8b6f3de0ad47684e72a2ae5f884d8675acfaeeac) feat(core): add state management, closes [#1655](https://www.github.com/tauri-apps/tauri/pull/1655) ([#1665](https://www.github.com/tauri-apps/tauri/pull/1665)) on 2021-05-02 ## \[1.0.0-beta-rc.1] - Fixes the Message `command` name value on plugin invoke handler. - [422dd5e](https://www.github.com/tauri-apps/tauri/commit/422dd5e2a0a03bb1556915c78f110bfab092c874) fix(core): command name on plugin invoke handler ([#1577](https://www.github.com/tauri-apps/tauri/pull/1577)) on 2021-04-21 - [f575aaa](https://www.github.com/tauri-apps/tauri/commit/f575aaad71f23d44b2f89cf9ee5d84817dc3bb7a) fix: change files not referencing core packages ([#1619](https://www.github.com/tauri-apps/tauri/pull/1619)) on 2021-04-25 ## \[1.0.0-beta-rc.0] - Update all code files to have our license header. - [bf82136](https://www.github.com/tauri-apps/tauri/commit/bf8213646689175f8a158b956911f3a43e360690) feat(license): SPDX Headers ([#1449](https://www.github.com/tauri-apps/tauri/pull/1449)) on 2021-04-11 - [a6def70](https://www.github.com/tauri-apps/tauri/commit/a6def7066eec19c889b0f14cc1e475bf209a332e) Refactor(tauri): move tauri-api and tauri-updater to tauri ([#1455](https://www.github.com/tauri-apps/tauri/pull/1455)) on 2021-04-11 - [aea6145](https://www.github.com/tauri-apps/tauri/commit/aea614587bddab930d552512b54e18624fbf573e) refactor(repo): add /tooling folder ([#1457](https://www.github.com/tauri-apps/tauri/pull/1457)) on 2021-04-12 - Added new macros to simplify the creation of commands that can be called by the webview. - [1f2e7a3](https://www.github.com/tauri-apps/tauri/commit/1f2e7a3226ccf0ee3e30ae0cba3c67f7e219d1f2) feat(core): improved command matching with macros, fixes [#1157](https://www.github.com/tauri-apps/tauri/pull/1157) ([#1301](https://www.github.com/tauri-apps/tauri/pull/1301)) on 2021-02-28 ================================================ FILE: crates/tauri-macros/Cargo.toml ================================================ [package] name = "tauri-macros" version = "2.5.5" description = "Macros for the tauri crate." exclude = ["CHANGELOG.md", "/target"] readme = "README.md" authors.workspace = true homepage.workspace = true repository.workspace = true categories.workspace = true license.workspace = true edition.workspace = true rust-version.workspace = true [lib] proc-macro = true [dependencies] proc-macro2 = { version = "1", features = ["span-locations"] } quote = "1" syn = { version = "2", features = ["full"] } heck = "0.5" tauri-codegen = { version = "2.5.5", default-features = false, path = "../tauri-codegen" } tauri-utils = { version = "2.8.3", path = "../tauri-utils" } [features] custom-protocol = [] compression = ["tauri-codegen/compression"] isolation = ["tauri-codegen/isolation"] config-json5 = ["tauri-codegen/config-json5", "tauri-utils/config-json5"] config-toml = ["tauri-codegen/config-toml", "tauri-utils/config-toml"] tracing = [] ================================================ FILE: crates/tauri-macros/LICENSE_APACHE-2.0 ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS ================================================ FILE: crates/tauri-macros/LICENSE_MIT ================================================ MIT License Copyright (c) 2017 - Present Tauri Apps Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: crates/tauri-macros/README.md ================================================ # tauri-macros [![status](https://img.shields.io/badge/status-stable-blue.svg)](https://github.com/tauri-apps/tauri/tree/dev) [![License](https://img.shields.io/badge/License-MIT%20or%20Apache%202-green.svg)](https://opencollective.com/tauri) [![test core](https://img.shields.io/github/actions/workflow/status/tauri-apps/tauri/test-core.yml?label=test%20core&logo=github)](https://github.com/tauri-apps/tauri/actions/workflows/test-core.yml) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Ftauri-apps%2Ftauri.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Ftauri-apps%2Ftauri?ref=badge_shield) [![Chat Server](https://img.shields.io/badge/chat-discord-7289da.svg)](https://discord.gg/SpmNs4S) [![website](https://img.shields.io/badge/website-tauri.app-purple.svg)](https://tauri.app) [![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) | Component | Version | | ------------ | ------------------------------------------------------------------------------------------------------------ | | tauri-macros | [![](https://img.shields.io/crates/v/tauri-macros?style=flat-square)](https://crates.io/crates/tauri-macros) | ## About Tauri Tauri is a polyglot and generic system that is very composable and allows engineers to make a wide variety of applications. It is used for building applications for Desktop Computers using a combination of Rust tools and HTML rendered in a Webview. Apps built with Tauri can ship with any number of pieces of an optional JS API / Rust API so that webviews can control the system via message passing. In fact, developers can extend the default API with their own functionality and bridge the Webview and Rust-based backend easily. Tauri apps can have custom menus and have tray-type interfaces. They can be updated, and are managed by the user's operating system as expected. They are very small, because they use the system's webview. They do not ship a runtime, since the final binary is compiled from rust. This makes the reversing of Tauri apps not a trivial task. ## This module Create macros for the context, handler, and commands by leveraging the `tauri-codegen` crate. 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. ## Semver **tauri** is following [Semantic Versioning 2.0](https://semver.org/). ## Licenses Code: (c) 2021 - The Tauri Programme within The Commons Conservancy. MIT or MIT/Apache 2.0 where applicable. Logo: CC-BY-NC-ND - Original Tauri Logo Designs by [Daniel Thompson-Yvetot](https://github.com/nothingismagick) and [Guillaume Chau](https://github.com/akryum) ================================================ FILE: crates/tauri-macros/src/command/handler.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use quote::format_ident; use syn::{ parse::{Parse, ParseBuffer, ParseStream}, Attribute, Ident, Path, Token, }; struct CommandDef { path: Path, attrs: Vec, } impl Parse for CommandDef { fn parse(input: ParseStream) -> syn::Result { let attrs = input.call(Attribute::parse_outer)?; let path = input.parse()?; Ok(CommandDef { path, attrs }) } } /// The items parsed from [`generate_handle!`](crate::generate_handle). pub struct Handler { command_defs: Vec, commands: Vec, wrappers: Vec, } impl Parse for Handler { fn parse(input: &ParseBuffer<'_>) -> syn::Result { let plugin_name = try_get_plugin_name(input)?; let mut command_defs = input .parse_terminated(CommandDef::parse, Token![,])? .into_iter() .collect(); filter_unused_commands(plugin_name, &mut command_defs); let mut commands = Vec::new(); let mut wrappers = Vec::new(); // parse the command names and wrappers from the passed paths for command_def in &command_defs { let mut wrapper = command_def.path.clone(); let last = super::path_to_command(&mut wrapper); // the name of the actual command function let command = last.ident.clone(); // set the path to the command function wrapper last.ident = super::format_command_wrapper(&command); commands.push(command); wrappers.push(wrapper); } Ok(Self { command_defs, commands, wrappers, }) } } /// Try to get the plugin name by parsing the input for a `#![plugin(...)]` attribute, /// if it's not present, try getting it from `CARGO_PKG_NAME` environment variable fn try_get_plugin_name(input: &ParseBuffer<'_>) -> Result, syn::Error> { if let Ok(attrs) = input.call(Attribute::parse_inner) { for attr in attrs { if attr.path().is_ident("plugin") { // Parse the content inside #![plugin(...)] let plugin_name = attr.parse_args::()?.to_string(); return Ok(Some(if plugin_name == "__TAURI_CHANNEL__" { // TODO: Remove this in v3 plugin_name } else { plugin_name.replace("_", "-") })); } } } Ok( std::env::var("CARGO_PKG_NAME") .ok() .and_then(|var| var.strip_prefix("tauri-plugin-").map(String::from)), ) } fn filter_unused_commands(plugin_name: Option, command_defs: &mut Vec) { let allowed_commands = tauri_utils::acl::read_allowed_commands(); let Some(allowed_commands) = allowed_commands else { return; }; // TODO: Remove this in v3 if plugin_name.as_deref() == Some("__TAURI_CHANNEL__") { // Always allowed return; } if plugin_name.is_none() && !allowed_commands.has_app_acl { // All application commands are allowed if we don't have an application ACL // // note that inline plugins without the #![plugin()] attribute would also get to this check // which means inline plugins must have an app manifest to get proper unused command removal return; } let mut unused_commands = Vec::new(); let command_prefix = if let Some(plugin_name) = &plugin_name { format!("plugin:{plugin_name}|") } else { "".into() }; command_defs.retain(|command_def| { let mut wrapper = command_def.path.clone(); let last = super::path_to_command(&mut wrapper); // the name of the actual command function let command_name = &last.ident; let command = format!("{command_prefix}{command_name}"); let is_allowed = allowed_commands.commands.contains(&command); if !is_allowed { unused_commands.push(command_name.to_string()); } is_allowed }); if !unused_commands.is_empty() { let plugin_display_name = plugin_name.as_deref().unwrap_or("application"); let unused_commands_display = unused_commands.join(", "); println!("Removed unused commands from {plugin_display_name}: {unused_commands_display}",); } } impl From for proc_macro::TokenStream { fn from( Handler { command_defs, commands, wrappers, }: Handler, ) -> Self { let cmd = format_ident!("__tauri_cmd__"); let invoke = format_ident!("__tauri_invoke__"); let (paths, attrs): (Vec, Vec>) = command_defs .into_iter() .map(|def| (def.path, def.attrs)) .unzip(); quote::quote!(move |#invoke| { let #cmd = #invoke.message.command(); match #cmd { #(#(#attrs)* stringify!(#commands) => #wrappers!(#paths, #invoke),)* _ => { return false; }, } }) .into() } } ================================================ FILE: crates/tauri-macros/src/command/mod.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use proc_macro2::Ident; use syn::{Path, PathSegment}; pub use self::{handler::Handler, wrapper::wrapper}; mod handler; mod wrapper; /// The autogenerated wrapper ident. fn format_command_wrapper(function: &Ident) -> Ident { quote::format_ident!("__cmd__{}", function) } /// This function will panic if the passed [`syn::Path`] does not have any segments. fn path_to_command(path: &mut Path) -> &mut PathSegment { path .segments .last_mut() .expect("parsed syn::Path has no segment") } ================================================ FILE: crates/tauri-macros/src/command/wrapper.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use std::{env::var, sync::OnceLock}; use heck::{ToLowerCamelCase, ToSnakeCase}; use proc_macro::TokenStream; use proc_macro2::{Ident, Span, TokenStream as TokenStream2}; use quote::{format_ident, quote, quote_spanned}; use syn::{ ext::IdentExt, parse::{Parse, ParseStream}, parse_macro_input, punctuated::Punctuated, spanned::Spanned, Expr, ExprLit, FnArg, ItemFn, Lit, Meta, Pat, Token, Visibility, }; use tauri_utils::acl::REMOVE_UNUSED_COMMANDS_ENV_VAR; #[allow(clippy::large_enum_variant)] 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, argument_case: ArgumentCase, } impl Parse for WrapperAttributes { fn parse(input: ParseStream) -> syn::Result { let mut wrapper_attributes = WrapperAttributes { root: quote!(::tauri), execution_context: ExecutionContext::Blocking, argument_case: ArgumentCase::Camel, }; 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 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, _ => { return Err(syn::Error::new( s.span(), "expected \"camelCase\" or \"snake_case\"", )) } }; } } else if v.path.is_ident("root") { if let Expr::Lit(ExprLit { lit: Lit::Str(s), attrs: _, }) = v.value { let lit = s.value(); wrapper_attributes.root = if lit == "crate" { quote!($crate) } else { let ident = Ident::new(&lit, Span::call_site()); quote!(#ident) }; } } } WrapperAttributeKind::Meta(Meta::Path(_)) => { return Err(syn::Error::new( input.span(), "unexpected input, expected one of `rename_all`, `root`, `async`", )); } WrapperAttributeKind::Async => { wrapper_attributes.execution_context = ExecutionContext::Async; } } } Ok(wrapper_attributes) } } /// The execution context of the command. enum ExecutionContext { Async, Blocking, } /// The case of each argument name. #[derive(Copy, Clone)] enum ArgumentCase { Snake, Camel, } /// The bindings we attach to `tauri::Invoke`. struct Invoke { message: Ident, resolver: Ident, acl: Ident, } /// 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(_) | Visibility::Restricted(_) => quote!(#[macro_export]), _ => TokenStream2::default(), }; let invoke = Invoke { message: format_ident!("__tauri_message__"), resolver: format_ident!("__tauri_resolver__"), acl: format_ident!("__tauri_acl__"), }; // Tauri currently doesn't support async commands that take a reference as input and don't return // a result. See: https://github.com/tauri-apps/tauri/issues/2533 // // For now, we provide an informative error message to the user in that case. Once #2533 is // resolved, this check can be removed. let mut async_command_check = TokenStream2::new(); if function.sig.asyncness.is_some() { // This check won't catch all possible problems but it should catch the most common ones. let mut ref_argument_span = None; for arg in &function.sig.inputs { if let syn::FnArg::Typed(pat) = arg { match &*pat.ty { syn::Type::Reference(_) => { ref_argument_span = Some(pat.span()); } syn::Type::Path(path) => { // Check if the type contains a lifetime argument let last = path.path.segments.last().unwrap(); if let syn::PathArguments::AngleBracketed(args) = &last.arguments { if args .args .iter() .any(|arg| matches!(arg, syn::GenericArgument::Lifetime(_))) { ref_argument_span = Some(pat.span()); } } } _ => {} } if let Some(span) = ref_argument_span { if let syn::ReturnType::Type(_, return_type) = &function.sig.output { // To check if the return type is `Result` we require it to check a trait that is // only implemented by `Result`. That way we don't exclude renamed result types // which we wouldn't otherwise be able to detect purely from the token stream. // The "error message" displayed to the user is simply the trait name. // // TODO: remove this check once our MSRV is high enough let diagnostic = if is_rustc_at_least(1, 78) { quote!(#[diagnostic::on_unimplemented(message = "async commands that contain references as inputs must return a `Result`")]) } else { quote!() }; async_command_check = quote_spanned! {return_type.span() => #[allow(unreachable_code, clippy::diverging_sub_expression, clippy::used_underscore_binding)] const _: () = if false { #diagnostic trait AsyncCommandMustReturnResult {} impl AsyncCommandMustReturnResult for ::std::result::Result {} let _check: #return_type = unreachable!(); let _: &dyn AsyncCommandMustReturnResult = &_check; }; }; } else { return quote_spanned! { span => compile_error!("async commands that contain references as inputs must return a `Result`"); }.into(); } } } } } let plugin_name = var("CARGO_PKG_NAME") .expect("missing `CARGO_PKG_NAME` environment variable") .strip_prefix("tauri-plugin-") .map(|name| quote!(::core::option::Option::Some(#name))) .unwrap_or_else(|| quote!(::core::option::Option::None)); let body = match attrs.execution_context { ExecutionContext::Async => body_async(&plugin_name, &function, &invoke, &attrs) .unwrap_or_else(syn::Error::into_compile_error), ExecutionContext::Blocking => body_blocking(&plugin_name, &function, &invoke, &attrs) .unwrap_or_else(syn::Error::into_compile_error), }; let Invoke { message, resolver, acl, } = invoke; let root = attrs.root; let kind = match attrs.execution_context { ExecutionContext::Async if function.sig.asyncness.is_none() => "sync_threadpool", ExecutionContext::Async => "async", ExecutionContext::Blocking => "sync", }; let loc = function.span().start(); let line = loc.line; let col = loc.column; let maybe_span = if cfg!(feature = "tracing") { quote!({ let _span = tracing::debug_span!( "ipc::request::handler", cmd = #message.command(), kind = #kind, loc.line = #line, loc.col = #col, is_internal = false, ) .entered(); }) } else { quote!() }; // Allow this to be unused when we're building with `build > removeUnusedCommands` for dead code elimination let maybe_allow_unused = if var(REMOVE_UNUSED_COMMANDS_ENV_VAR).is_ok() { quote!(#[allow(unused)]) } else { TokenStream2::default() }; // Rely on rust 2018 edition to allow importing a macro from a path. quote!( #async_command_check #maybe_allow_unused #function #maybe_allow_unused #maybe_macro_export #[doc(hidden)] macro_rules! #wrapper { // double braces because the item is expected to be a block expression ($path:path, $invoke:ident) => { // The IIFE here is for preventing stack overflow on Windows, // see https://github.com/tauri-apps/tauri/issues/12488 { move || { #[allow(unused_imports)] use #root::ipc::private::*; // prevent warnings when the body is a `compile_error!` or if the command has no arguments #[allow(unused_variables)] let #root::ipc::Invoke { message: #message, resolver: #resolver, acl: #acl } = $invoke; #maybe_span #body } }() }; } // allow the macro to be resolved with the same path as the command function #[allow(unused_imports)] #visibility use #wrapper; ) .into() } /// Generates an asynchronous command response from the arguments and return value of a function. /// /// See the [`tauri::command`] module for all the items and traits that make this possible. /// /// [`tauri::command`]: https://docs.rs/tauri/*/tauri/runtime/index.html fn body_async( plugin_name: &TokenStream2, function: &ItemFn, invoke: &Invoke, attributes: &WrapperAttributes, ) -> syn::Result { let Invoke { message, resolver, acl, } = invoke; parse_args(plugin_name, function, message, acl, attributes).map(|args| { #[cfg(feature = "tracing")] quote! { use tracing::Instrument; let span = tracing::debug_span!("ipc::request::run"); #resolver.respond_async_serialized(async move { let result = $path(#(#args?),*); let kind = (&result).async_kind(); kind.future(result).await } .instrument(span)); return true; } #[cfg(not(feature = "tracing"))] quote! { #resolver.respond_async_serialized(async move { let result = $path(#(#args?),*); let kind = (&result).async_kind(); kind.future(result).await }); return true; } }) } /// Generates a blocking command response from the arguments and return value of a function. /// /// See the [`tauri::command`] module for all the items and traits that make this possible. /// /// [`tauri::command`]: https://docs.rs/tauri/*/tauri/runtime/index.html fn body_blocking( plugin_name: &TokenStream2, function: &ItemFn, invoke: &Invoke, attributes: &WrapperAttributes, ) -> syn::Result { let Invoke { message, resolver, acl, } = invoke; let args = parse_args(plugin_name, function, message, acl, attributes)?; // the body of a `match` to early return any argument that wasn't successful in parsing. let match_body = quote!({ Ok(arg) => arg, Err(err) => { #resolver.invoke_error(err); return true }, }); let maybe_span = if cfg!(feature = "tracing") { quote!(let _span = tracing::debug_span!("ipc::request::run").entered();) } else { quote!() }; Ok(quote! { #maybe_span let result = $path(#(match #args #match_body),*); let kind = (&result).blocking_kind(); kind.block(result, #resolver); return true; }) } /// Parse all arguments for the command wrapper to use from the signature of the command function. fn parse_args( plugin_name: &TokenStream2, function: &ItemFn, message: &Ident, acl: &Ident, attributes: &WrapperAttributes, ) -> syn::Result> { function .sig .inputs .iter() .map(|arg| { parse_arg( plugin_name, &function.sig.ident, arg, message, acl, attributes, ) }) .collect() } /// Transform a [`FnArg`] into a command argument. fn parse_arg( plugin_name: &TokenStream2, command: &Ident, arg: &FnArg, message: &Ident, acl: &Ident, attributes: &WrapperAttributes, ) -> syn::Result { // we have no use for self arguments let mut arg = match arg { FnArg::Typed(arg) => arg.pat.as_ref().clone(), FnArg::Receiver(arg) => { return Err(syn::Error::new( arg.span(), "unable to use self as a command function parameter", )) } }; // we only support patterns that allow us to extract some sort of keyed identifier let mut key = match &mut arg { Pat::Ident(arg) => arg.ident.unraw().to_string(), Pat::Wild(_) => "".into(), // we always convert to camelCase, so "_" will end up empty anyways Pat::Struct(s) => super::path_to_command(&mut s.path).ident.to_string(), Pat::TupleStruct(s) => super::path_to_command(&mut s.path).ident.to_string(), err => { return Err(syn::Error::new( err.span(), "only named, wildcard, struct, and tuple struct arguments allowed", )) } }; // also catch self arguments that use FnArg::Typed syntax if key == "self" { return Err(syn::Error::new( key.span(), "unable to use self as a command function parameter", )); } match attributes.argument_case { ArgumentCase::Camel => { key = key.to_lower_camel_case(); } ArgumentCase::Snake => { key = key.to_snake_case(); } } let root = &attributes.root; Ok(quote!(#root::ipc::CommandArg::from_command( #root::ipc::CommandItem { plugin: #plugin_name, name: stringify!(#command), key: #key, message: &#message, acl: &#acl, } ))) } fn is_rustc_at_least(major: u32, minor: u32) -> bool { let version = rustc_version(); version.0 >= major && version.1 >= minor } fn rustc_version() -> &'static (u32, u32) { static RUSTC_VERSION: OnceLock<(u32, u32)> = OnceLock::new(); RUSTC_VERSION.get_or_init(|| { cross_command("rustc") .arg("-V") .output() .ok() .and_then(|o| { let version = String::from_utf8_lossy(&o.stdout) .trim() .split(' ') .nth(1) .unwrap_or_default() .split('.') .take(2) .flat_map(|p| p.parse::().ok()) .collect::>(); version .first() .and_then(|major| version.get(1).map(|minor| (*major, *minor))) }) .unwrap_or((1, 0)) }) } fn cross_command(bin: &str) -> std::process::Command { #[cfg(target_os = "windows")] let cmd = { let mut cmd = std::process::Command::new("cmd"); cmd.arg("/c").arg(bin); cmd }; #[cfg(not(target_os = "windows"))] let cmd = std::process::Command::new(bin); cmd } ================================================ FILE: crates/tauri-macros/src/context.rs ================================================ // Copyright 2019-2024 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, ToTokens}; use std::path::PathBuf; use syn::{ parse::{Parse, ParseBuffer}, punctuated::Punctuated, Expr, ExprLit, Lit, LitBool, LitStr, Meta, PathArguments, PathSegment, Token, }; use tauri_codegen::{context_codegen, get_config, ContextData}; use tauri_utils::{config::parse::does_supported_file_name_exist, platform::Target}; pub(crate) struct ContextItems { config_file: PathBuf, root: syn::Path, capabilities: Option>, assets: Option, test: bool, } impl Parse for ContextItems { fn parse(input: &ParseBuffer<'_>) -> syn::parse::Result { let target = std::env::var("TARGET") .or_else(|_| std::env::var("TAURI_ENV_TARGET_TRIPLE")) .as_deref() .map(Target::from_triple) .unwrap_or_else(|_| Target::current()); let mut root = None; let mut capabilities = None; let mut assets = None; let mut test = false; let config_file = input.parse::().ok().map(|raw| { let _ = input.parse::(); let path = PathBuf::from(raw.value()); if path.is_relative() { std::env::var("CARGO_MANIFEST_DIR") .map(|m| PathBuf::from(m).join(path)) .map_err(|e| e.to_string()) } else { Ok(path) } .and_then(|path| { if does_supported_file_name_exist(target, &path) { Ok(path) } else { Err(format!( "no file at path {} exists, expected tauri config file", path.display() )) } }) }); while let Ok(meta) = input.parse::() { match meta { Meta::Path(p) => { root.replace(p); } Meta::NameValue(v) => { let ident = v.path.require_ident()?; match ident.to_string().as_str() { "capabilities" => { if let Expr::Array(array) = v.value { capabilities.replace( array .elems .into_iter() .map(|e| { if let Expr::Lit(ExprLit { attrs: _, lit: Lit::Str(s), }) = e { Ok(s.value().into()) } else { Err(syn::Error::new( input.span(), "unexpected expression for capability", )) } }) .collect::, syn::Error>>()?, ); } else { return Err(syn::Error::new( input.span(), "unexpected value for capabilities", )); } } "assets" => { assets.replace(v.value); } "test" => { if let Expr::Lit(ExprLit { lit: Lit::Bool(LitBool { value, .. }), .. }) = v.value { test = value; } else { return Err(syn::Error::new(input.span(), "unexpected value for test")); } } name => { return Err(syn::Error::new( input.span(), format!("unknown attribute {name}"), )); } } } Meta::List(_) => { return Err(syn::Error::new(input.span(), "unexpected list input")); } } let _ = input.parse::(); } Ok(Self { config_file: config_file .unwrap_or_else(|| { std::env::var("CARGO_MANIFEST_DIR") .map(|m| PathBuf::from(m).join("tauri.conf.json")) .map_err(|e| e.to_string()) }) .map_err(|e| input.error(e))?, root: root.unwrap_or_else(|| { let mut segments = Punctuated::new(); segments.push(PathSegment { ident: Ident::new("tauri", Span::call_site()), arguments: PathArguments::None, }); syn::Path { leading_colon: Some(Token![::](Span::call_site())), segments, } }), capabilities, assets, test, }) } } pub(crate) fn generate_context(context: ContextItems) -> TokenStream { let context = get_config(&context.config_file) .map_err(|e| e.to_string()) .map(|(config, config_parent)| ContextData { dev: cfg!(not(feature = "custom-protocol")), config, config_parent, root: context.root.to_token_stream(), capabilities: context.capabilities, assets: context.assets, test: context.test, }) .and_then(|data| context_codegen(data).map_err(|e| e.to_string())); match context { Ok(code) => code, Err(error) => quote!(compile_error!(#error)), } } ================================================ FILE: crates/tauri-macros/src/lib.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT //! Create macros for `tauri::Context`, invoke handler and commands leveraging the `tauri-codegen` crate. #![doc( html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png", html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png" )] use std::path::PathBuf; use crate::context::ContextItems; use proc_macro::TokenStream; use quote::{quote, ToTokens}; use syn::{parse2, parse_macro_input, LitStr}; use tauri_codegen::image::CachedIcon; mod command; mod menu; mod mobile; mod runtime; #[macro_use] mod context; /// Mark a function as a command handler. It creates a wrapper function with the necessary glue code. /// /// # Stability /// The output of this macro is managed internally by Tauri, /// and should not be accessed directly on normal applications. /// It may have breaking changes in the future. #[proc_macro_attribute] pub fn command(attributes: TokenStream, item: TokenStream) -> TokenStream { command::wrapper(attributes, item) } #[proc_macro_attribute] pub fn mobile_entry_point(attributes: TokenStream, item: TokenStream) -> TokenStream { mobile::entry_point(attributes, item) } /// Accepts a list of command functions. Creates a handler that allows commands to be called from JS with invoke(). /// /// You can optionally annotate the commands with a inner attribute tag `#![plugin(your_plugin_name)]` /// for `build > removeUnusedCommands` to work for plugins not defined in a standalone crate like `tauri-plugin-fs` /// /// # Examples /// /// ```rust,ignore /// use tauri_macros::{command, generate_handler}; /// #[command] /// fn command_one() { /// println!("command one called"); /// } /// #[command] /// fn command_two() { /// println!("command two called"); /// } /// fn main() { /// let _handler = generate_handler![command_one, command_two]; /// } /// ``` /// /// # Stability /// /// The output of this macro is managed internally by Tauri, /// and should not be accessed directly on normal applications. /// It may have breaking changes in the future. #[proc_macro] pub fn generate_handler(item: TokenStream) -> TokenStream { parse_macro_input!(item as command::Handler).into() } /// Reads a Tauri config file and generates a `::tauri::Context` based on the content. /// /// # Stability /// The output of this macro is managed internally by Tauri, /// and should not be accessed directly on normal applications. /// It may have breaking changes in the future. #[proc_macro] pub fn generate_context(items: TokenStream) -> TokenStream { // this macro is exported from the context module let path = parse_macro_input!(items as ContextItems); context::generate_context(path).into() } /// Adds the default type for the last parameter (assumed to be runtime) for a specific feature. /// /// e.g. To default the runtime generic to type `crate::Wry` when the `wry` feature is enabled, the /// syntax would look like `#[default_runtime(crate::Wry, wry)`. This is **always** set for the last /// generic, so make sure the last generic is the runtime when using this macro. #[doc(hidden)] #[proc_macro_attribute] pub fn default_runtime(attributes: TokenStream, input: TokenStream) -> TokenStream { let attributes = parse_macro_input!(attributes as runtime::Attributes); let input = parse_macro_input!(input as runtime::Input); 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 5th parameter to select which item kinds /// to match against, by providing a `|` separated list of item kinds /// ```ignore /// do_menu_item!(resources_table, rid, kind, |i| i.set_text(text), Check | Submenu); /// ``` /// You could also provide a negated list /// ```ignore /// do_menu_item!(resources_table, rid, kind, |i| i.set_text(text), !Check); /// do_menu_item!(resources_table, rid, kind, |i| i.set_text(text), !Check | !Submenu); /// ``` /// but you can't have mixed negations and positive kinds. /// ```ignore /// do_menu_item!(resources_table, rid, kind, |i| i.set_text(text), !Check | Submenu); /// ``` /// /// #### Example /// /// ```ignore /// let rid = 23; /// let kind = ItemKind::Check; /// let resources_table = app.resources_table(); /// do_menu_item!(resources_table, rid, kind, |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() } /// Convert a .png or .ico icon to an Image /// for things like `tauri::tray::TrayIconBuilder` to consume, /// relative paths are resolved from `CARGO_MANIFEST_DIR`, not current file /// /// ### Examples /// /// ```ignore /// const APP_ICON: Image<'_> = include_image!("./icons/32x32.png"); /// /// // then use it with tray /// TrayIconBuilder::new().icon(APP_ICON).build().unwrap(); /// /// // or with window /// WebviewWindowBuilder::new(app, "main", WebviewUrl::default()) /// .icon(APP_ICON) /// .unwrap() /// .build() /// .unwrap(); /// /// // or with any other functions that takes `Image` struct /// ``` /// /// Note: this stores the image in raw pixels to the final binary, /// so keep the icon size (width and height) small /// or else it's going to bloat your final executable #[proc_macro] pub fn include_image(tokens: TokenStream) -> TokenStream { let path = match parse2::(tokens.into()) { Ok(path) => path, Err(err) => return err.into_compile_error().into(), }; let path = PathBuf::from(path.value()); let resolved_path = if path.is_relative() { if let Ok(base_dir) = std::env::var("CARGO_MANIFEST_DIR").map(PathBuf::from) { base_dir.join(path) } else { return quote!(compile_error!("$CARGO_MANIFEST_DIR is not defined")).into(); } } else { path }; if !resolved_path.exists() { let error_string = format!( "Provided Image path \"{}\" doesn't exists", resolved_path.display() ); return quote!(compile_error!(#error_string)).into(); } match CachedIcon::new("e!(::tauri), &resolved_path).map_err(|error| error.to_string()) { Ok(icon) => icon.into_token_stream(), Err(error) => quote!(compile_error!(#error)), } .into() } ================================================ FILE: crates/tauri-macros/src/menu.rs ================================================ // Copyright 2019-2024 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 { negated: bool, ident: Ident, } impl NegatedIdent { fn new(ident: &str) -> Self { Self { negated: false, ident: Ident::new(ident, Span::call_site()), } } fn is_negated(&self) -> bool { self.negated } } impl Parse for NegatedIdent { fn parse(input: ParseStream) -> syn::Result { let negated_token = input.parse::(); let ident: Ident = input.parse()?; Ok(NegatedIdent { negated: negated_token.is_ok(), ident, }) } } 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::new("Submenu"), NegatedIdent::new("MenuItem"), NegatedIdent::new("Predefined"), NegatedIdent::new("Check"), NegatedIdent::new("Icon"), ]; if kinds.is_empty() { kinds.extend(defaults.clone()); } let has_negated = kinds.iter().any(|n| n.is_negated()); if has_negated { kinds.extend(defaults); kinds.sort_by(|a, b| a.ident.cmp(&b.ident)); kinds.dedup_by(|a, b| a.ident == b.ident); } let (kinds, types): (Vec, Vec) = kinds .into_iter() .filter_map(|nident| { if nident.is_negated() { None } else { match nident.ident { 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!(), } } } ================================================ FILE: crates/tauri-macros/src/mobile.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use proc_macro::TokenStream; use proc_macro2::TokenStream as TokenStream2; use quote::{format_ident, quote}; use std::env::var; use syn::{parse_macro_input, spanned::Spanned, ItemFn}; fn get_env_var(name: &str, error: &mut Option, function: &ItemFn) -> TokenStream2 { match var(name) { Ok(value) => { let ident = format_ident!("{value}"); quote!(#ident) } Err(_) => { error.replace( syn::Error::new( function.span(), format!("`{name}` env var not set, do you have a build script with tauri-build?",), ) .into_compile_error(), ); quote!() } } } pub fn entry_point(_attributes: TokenStream, item: TokenStream) -> TokenStream { let function = parse_macro_input!(item as ItemFn); let function_name = function.sig.ident.clone(); let mut error = None; let domain = get_env_var("TAURI_ANDROID_PACKAGE_NAME_PREFIX", &mut error, &function); let app_name = get_env_var("TAURI_ANDROID_PACKAGE_NAME_APP_NAME", &mut error, &function); let (wrapper, wrapper_name) = if function.sig.asyncness.is_some() { let wrapper_name = syn::Ident::new(&format!("{function_name}_wrapper"), function_name.span()); ( quote! { #function fn #wrapper_name() { ::tauri::async_runtime::block_on(#function_name()); } }, wrapper_name, ) } else { ( quote! { #function }, function_name, ) }; if let Some(e) = error { quote!(#e).into() } else { quote!( fn stop_unwind T, T>(f: F) -> T { match std::panic::catch_unwind(std::panic::AssertUnwindSafe(f)) { Ok(t) => t, Err(err) => { eprintln!("attempt to unwind out of `rust` with err: {:?}", err); std::process::abort() } } } #wrapper fn _start_app() { #[cfg(target_os = "ios")] ::tauri::log_stdout(); #[cfg(target_os = "android")] { ::tauri::android_binding!(#domain, #app_name, _start_app, ::tauri::wry); } stop_unwind(#wrapper_name); } // be careful when renaming this, the `start_app` symbol is checked by the CLI #[cfg(not(target_os = "android"))] #[no_mangle] #[inline(never)] pub extern "C" fn start_app() { _start_app() } ) .into() } } ================================================ FILE: crates/tauri-macros/src/runtime.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use proc_macro2::TokenStream; use quote::{quote, ToTokens}; use syn::parse::{Parse, ParseStream}; use syn::{ parse_quote, DeriveInput, Error, GenericParam, Ident, ItemTrait, ItemType, Token, Type, TypeParam, }; #[derive(Clone)] pub(crate) enum Input { Derive(DeriveInput), Trait(ItemTrait), Type(ItemType), } impl Parse for Input { fn parse(input: ParseStream) -> syn::Result { input .parse::() .map(Self::Derive) .or_else(|_| input.parse().map(Self::Trait)) .or_else(|_| input.parse().map(Self::Type)) .map_err(|_| { Error::new( input.span(), "default_runtime only supports `struct`, `enum`, `type`, or `trait` definitions", ) }) } } impl Input { fn last_param_mut(&mut self) -> Option<&mut GenericParam> { match self { Input::Derive(d) => d.generics.params.last_mut(), Input::Trait(t) => t.generics.params.last_mut(), Input::Type(t) => t.generics.params.last_mut(), } } } impl ToTokens for Input { fn to_tokens(&self, tokens: &mut TokenStream) { match self { Input::Derive(d) => d.to_tokens(tokens), Input::Trait(t) => t.to_tokens(tokens), Input::Type(t) => t.to_tokens(tokens), } } } /// The default runtime type to enable when the provided feature is enabled. pub(crate) struct Attributes { default_type: Type, feature: Ident, } impl Parse for Attributes { fn parse(input: ParseStream<'_>) -> syn::Result { let default_type = input.parse()?; input.parse::()?; Ok(Attributes { default_type, feature: input.parse()?, }) } } pub(crate) fn default_runtime(attributes: Attributes, input: Input) -> TokenStream { // create a new copy to manipulate for the wry feature flag let mut wry = input.clone(); let wry_runtime = wry .last_param_mut() .expect("default_runtime requires the item to have at least 1 generic parameter"); // set the default value of the last generic parameter to the provided runtime type match wry_runtime { GenericParam::Type( param @ TypeParam { eq_token: None, default: None, .. }, ) => { param.eq_token = Some(parse_quote!(=)); param.default = Some(attributes.default_type); } _ => { panic!("DefaultRuntime requires the last parameter to not have a default value") } }; let feature = attributes.feature.to_string(); quote!( #[cfg(feature = #feature)] #wry #[cfg(not(feature = #feature))] #input ) } ================================================ FILE: crates/tauri-plugin/CHANGELOG.md ================================================ # Changelog ## \[2.5.4] ### Dependencies - Upgraded to `tauri-utils@2.8.3` ## \[2.5.3] ### Dependencies - Upgraded to `tauri-utils@2.8.2` ## \[2.5.2] ### Dependencies - Upgraded to `tauri-utils@2.8.1` ## \[2.5.1] ### Bug Fixes - [`4b6b8690a`](https://www.github.com/tauri-apps/tauri/commit/4b6b8690ab886ebdf1307951cffbe03e31280baa) ([#14347](https://www.github.com/tauri-apps/tauri/pull/14347) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused docs.rs builds to fail. No user facing changes. ## \[2.5.0] ### Dependencies - Upgraded to `tauri-utils@2.8.0` - [`6aa7f2d85`](https://www.github.com/tauri-apps/tauri/commit/6aa7f2d852870aeba1d4dd0e07f8be2bc9b66286) Upgraded to `tauri-utils@2.8.0` ## \[2.4.0] ### New Features - [`a0113a8c6`](https://www.github.com/tauri-apps/tauri/commit/a0113a8c6471eccc43b3202cc009901a04e41baa) ([#13888](https://www.github.com/tauri-apps/tauri/pull/13888) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Added `build::mobile::update_info_plist` to allow a plugin to update the iOS project Info.plist file. ### Dependencies - Upgraded to `tauri-utils@2.7.0` ## \[2.3.1] ### Dependencies - Upgraded to `tauri-utils@2.6.0` ## \[2.2.1] ### Dependencies - Upgraded to `tauri-utils@2.5.0` ## \[2.2.0] ### Dependencies - Upgraded to `tauri-utils@2.4.0` - [`48b12b440`](https://www.github.com/tauri-apps/tauri/commit/48b12b440478937c46fdfef9f9d95194be117020) Update to `tauri-utils@2.4.0` ## \[2.1.1] ### Dependencies - Upgraded to `tauri-utils@2.3.1` ## \[2.1.0] ### New Features - [`013f8f652`](https://www.github.com/tauri-apps/tauri/commit/013f8f652302f2d49c5ec0a075582033d8b074fb) ([#12890](https://www.github.com/tauri-apps/tauri/pull/12890) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Added `build > removeUnusedCommands` to trigger the build scripts and macros to remove unused commands based on the capabilities you defined. Note this won't be accounting for dynamically added ACLs so make sure to check it when using this. ### Performance Improvements - [`1cd8f55ee`](https://www.github.com/tauri-apps/tauri/commit/1cd8f55eed326d61860fee62ba2d2f4464bdcfcc) ([#13033](https://www.github.com/tauri-apps/tauri/pull/13033) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Don't ship global `bundle.global.js` if `app > withGlobalTauri` is set to false ### Dependencies - Upgraded to `tauri-utils@2.3.0` ## \[2.0.5] ### Dependencies - Upgraded to `tauri-utils@2.2.0` ## \[2.0.4] ### Dependencies - Upgraded to `tauri-utils@2.1.1` ## \[2.0.3] ### Dependencies - Upgraded to `tauri-utils@2.1.0` ## \[2.0.2] ### Dependencies - Upgraded to `tauri-utils@2.0.2` ## \[2.0.1] ### What's Changed - [`0ab2b3306`](https://www.github.com/tauri-apps/tauri/commit/0ab2b330644b6419f6cee1d5377bfb5cdda2ccf9) ([#11205](https://www.github.com/tauri-apps/tauri/pull/11205) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Downgrade MSRV to 1.77.2 to support Windows 7. ### Dependencies - Upgraded to `tauri-utils@2.0.1` ## \[2.0.0] ### What's Changed - [`382ed482b`](https://www.github.com/tauri-apps/tauri/commit/382ed482bd08157c39e62f9a0aaad8802f1092cb) Bump MSRV to 1.78. - [`637285790`](https://www.github.com/tauri-apps/tauri/commit/6372857905ae9c0aedb7f482ddf6cf9f9836c9f2) Promote to v2 stable! ### Dependencies - Upgraded to `tauri-utils@2.0.0` ## \[2.0.0-rc.13] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.13` ## \[2.0.0-rc.12] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.12` ## \[2.0.0-rc.11] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.11` ## \[2.0.0-rc.10] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.10` ## \[2.0.0-rc.9] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.9` ## \[2.0.0-rc.8] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.8` ## \[2.0.0-rc.7] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.7` ## \[2.0.0-rc.6] ### What's Changed - [`f4d5241b3`](https://www.github.com/tauri-apps/tauri/commit/f4d5241b377d0f7a1b58100ee19f7843384634ac) ([#10731](https://www.github.com/tauri-apps/tauri/pull/10731) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Update documentation icon path. ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.6` ## \[2.0.0-rc.5] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.5` ## \[2.0.0-rc.4] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.4` ## \[2.0.0-rc.3] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.3` ## \[2.0.0-rc.2] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.2` ## \[2.0.0-rc.1] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.1` ## \[2.0.0-rc.0] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.0` ### Breaking Changes - [`758d28c8a`](https://www.github.com/tauri-apps/tauri/commit/758d28c8a2d5c9567158e339326b765f72da983e) ([#10390](https://www.github.com/tauri-apps/tauri/pull/10390)) Core plugin permissions are now prefixed with `core:`, the `core:default` permission set can now be used and the `core` plugin name is reserved. The `tauri migrate` tool will automate the migration process, which involves prefixing all `app`, `event`, `image`, `menu`, `path`, `resources`, `tray`, `webview` and `window` permissions with `core:`. ## \[2.0.0-beta.19] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.19` ## \[2.0.0-beta.18] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.18` ## \[2.0.0-beta.17] ### New Features - [`8a1ae2dea`](https://www.github.com/tauri-apps/tauri/commit/8a1ae2deaf3086e531ada25b1627f900e2e421fb)([#9843](https://www.github.com/tauri-apps/tauri/pull/9843)) Added an option to use a Xcode project for the iOS plugin instead of a plain SwiftPM project. ### What's Changed - [`9ac930380`](https://www.github.com/tauri-apps/tauri/commit/9ac930380a5df3fe700e68e75df8684d261ca292)([#9850](https://www.github.com/tauri-apps/tauri/pull/9850)) Emit `cargo:rustc-check-cfg` instruction so Cargo validates custom cfg attributes on Rust 1.80 (or nightly-2024-05-05). ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.17` ## \[2.0.0-beta.16] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.16` ## \[2.0.0-beta.15] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.15` ## \[2.0.0-beta.14] ### Enhancements - [`bf2635ab6`](https://www.github.com/tauri-apps/tauri/commit/bf2635ab6241a5b82569eafc939046d6e245f3ad)([#9632](https://www.github.com/tauri-apps/tauri/pull/9632)) Improve the error message that is shown when the `links` property is missing from a Tauri Plugin. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.14` ## \[2.0.0-beta.13] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.13` ## \[2.0.0-beta.12] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.12` ## \[2.0.0-beta.11] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.11` ## \[2.0.0-beta.10] ### New Features - [`e227fe02f`](https://www.github.com/tauri-apps/tauri/commit/e227fe02f986e145c0731a64693e1c830a9eb5b0)([#9156](https://www.github.com/tauri-apps/tauri/pull/9156)) Allow plugins to define (at compile time) JavaScript that are initialized when `withGlobalTauri` is true. - [`e227fe02f`](https://www.github.com/tauri-apps/tauri/commit/e227fe02f986e145c0731a64693e1c830a9eb5b0)([#9156](https://www.github.com/tauri-apps/tauri/pull/9156)) Added `Builder::global_api_script_path` to define a JavaScript file containing the initialization script for the plugin API bindings when `withGlobalTauri` is used. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.10` ## \[2.0.0-beta.9] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.9` ## \[2.0.0-beta.8] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.8` ## \[2.0.0-beta.7] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.7` ## \[2.0.0-beta.6] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.6` ### Breaking Changes - [`3657ad82`](https://www.github.com/tauri-apps/tauri/commit/3657ad82f88ce528551d032d521c52eed3f396b4)([#9008](https://www.github.com/tauri-apps/tauri/pull/9008)) Allow defining permissions for the application commands via `tauri_build::Attributes::app_manifest`. ## \[2.0.0-beta.5] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.5` ## \[2.0.0-beta.4] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.4` ## \[2.0.0-beta.3] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.3` ## \[2.0.0-beta.2] ### Enhancements - [`dd7571a7`](https://www.github.com/tauri-apps/tauri/commit/dd7571a7808676c8063a4983b9c6687dfaf03a09)([#8815](https://www.github.com/tauri-apps/tauri/pull/8815)) Do not generate JSON schema and markdown reference file if the plugin does not define any permissions and delete those files if they exist. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.2` ## \[2.0.0-beta.1] ### Bug Fixes - [`4e101f80`](https://www.github.com/tauri-apps/tauri/commit/4e101f801657e7d01ce8c22f9c6468067d0caab2)([#8756](https://www.github.com/tauri-apps/tauri/pull/8756)) Rerun build script when a new permission is added. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.1` ## \[2.0.0-beta.0] ### New Features - [`74a2a603`](https://www.github.com/tauri-apps/tauri/commit/74a2a6036a5e57462f161d728cbd8a6f121028ca)([#8661](https://www.github.com/tauri-apps/tauri/pull/8661)) Implement access control list for IPC usage. ================================================ FILE: crates/tauri-plugin/Cargo.toml ================================================ [package] name = "tauri-plugin" version = "2.5.4" description = "Build script and runtime Tauri plugin definitions" authors.workspace = true homepage.workspace = true repository.workspace = true categories.workspace = true license.workspace = true edition.workspace = true rust-version.workspace = true [package.metadata.docs.rs] features = ["build", "runtime"] [features] build = [ "dep:anyhow", "dep:serde", "dep:serde_json", "dep:glob", "dep:plist", "dep:walkdir", ] runtime = [] [dependencies] anyhow = { version = "1", optional = true } serde = { version = "1", optional = true } tauri-utils = { version = "2.8.3", default-features = false, features = [ "build", ], path = "../tauri-utils" } serde_json = { version = "1", optional = true } glob = { version = "0.3", optional = true } # Our code requires at least 0.8.21 so don't simplify this to 0.8 schemars = { version = "0.8.21", features = ["preserve_order"] } walkdir = { version = "2", optional = true } [target."cfg(target_os = \"macos\")".dependencies] plist = { version = "1", optional = true } ================================================ FILE: crates/tauri-plugin/src/build/mobile.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT //! Mobile-specific build utilities. use std::{ env::var_os, fs::{copy, create_dir, create_dir_all, read_to_string, remove_dir_all, write}, path::{Path, PathBuf}, }; use anyhow::{Context, Result}; use super::{build_var, cfg_alias}; #[cfg(target_os = "macos")] pub fn update_entitlements(f: F) -> Result<()> { if let (Some(project_path), Ok(app_name)) = ( var_os("TAURI_IOS_PROJECT_PATH").map(PathBuf::from), std::env::var("TAURI_IOS_APP_NAME"), ) { update_plist_file( project_path .join(format!("{app_name}_iOS")) .join(format!("{app_name}_iOS.entitlements")), f, )?; } Ok(()) } #[cfg(target_os = "macos")] pub fn update_info_plist(f: F) -> Result<()> { if let (Some(project_path), Ok(app_name)) = ( var_os("TAURI_IOS_PROJECT_PATH").map(PathBuf::from), std::env::var("TAURI_IOS_APP_NAME"), ) { update_plist_file( project_path .join(format!("{app_name}_iOS")) .join("Info.plist"), f, )?; } Ok(()) } pub fn update_android_manifest(block_identifier: &str, parent: &str, insert: String) -> Result<()> { if let Some(project_path) = var_os("TAURI_ANDROID_PROJECT_PATH").map(PathBuf::from) { let manifest_path = project_path.join("app/src/main/AndroidManifest.xml"); let manifest = read_to_string(&manifest_path)?; let rewritten = insert_into_xml(&manifest, block_identifier, parent, &insert); if rewritten != manifest { write(manifest_path, rewritten)?; } } Ok(()) } pub(crate) fn setup( android_path: Option, #[allow(unused_variables)] ios_path: Option, ) -> Result<()> { let target_os = build_var("CARGO_CFG_TARGET_OS")?; let mobile = target_os == "android" || target_os == "ios"; cfg_alias("mobile", mobile); cfg_alias("desktop", !mobile); match target_os.as_str() { "android" => { if let Some(path) = android_path { let manifest_dir = build_var("CARGO_MANIFEST_DIR").map(PathBuf::from)?; let source = manifest_dir.join(path); let tauri_library_path = std::env::var("DEP_TAURI_ANDROID_LIBRARY_PATH") .expect("missing `DEP_TAURI_ANDROID_LIBRARY_PATH` environment variable. Make sure `tauri` is a dependency of the plugin."); println!("cargo:rerun-if-env-changed=DEP_TAURI_ANDROID_LIBRARY_PATH"); create_dir_all(source.join(".tauri")).context("failed to create .tauri directory")?; copy_folder( Path::new(&tauri_library_path), &source.join(".tauri").join("tauri-api"), &[], ) .context("failed to copy tauri-api to the plugin project")?; println!("cargo:android_library_path={}", source.display()); } } #[cfg(target_os = "macos")] "ios" => { if let Some(path) = ios_path { let manifest_dir = std::env::var("CARGO_MANIFEST_DIR") .map(PathBuf::from) .unwrap(); let tauri_library_path = std::env::var("DEP_TAURI_IOS_LIBRARY_PATH") .expect("missing `DEP_TAURI_IOS_LIBRARY_PATH` environment variable. Make sure `tauri` is a dependency of the plugin."); let tauri_dep_path = path.parent().unwrap().join(".tauri"); create_dir_all(&tauri_dep_path).context("failed to create .tauri directory")?; copy_folder( Path::new(&tauri_library_path), &tauri_dep_path.join("tauri-api"), &[".build", "Package.resolved", "Tests"], ) .context("failed to copy tauri-api to the plugin project")?; tauri_utils::build::link_apple_library( &std::env::var("CARGO_PKG_NAME").unwrap(), manifest_dir.join(path), ); } } _ => (), } Ok(()) } fn copy_folder(source: &Path, target: &Path, ignore_paths: &[&str]) -> Result<()> { let _ = remove_dir_all(target); for entry in walkdir::WalkDir::new(source) { let entry = entry?; let rel_path = entry.path().strip_prefix(source)?; let rel_path_str = rel_path.to_string_lossy(); if ignore_paths .iter() .any(|path| rel_path_str.starts_with(path)) { continue; } let dest_path = target.join(rel_path); if entry.file_type().is_dir() { create_dir(&dest_path) .with_context(|| format!("failed to create directory {}", dest_path.display()))?; } else { copy(entry.path(), &dest_path).with_context(|| { format!( "failed to copy {} to {}", entry.path().display(), dest_path.display() ) })?; println!("cargo:rerun-if-changed={}", entry.path().display()); } } Ok(()) } #[cfg(target_os = "macos")] fn update_plist_file, F: FnOnce(&mut plist::Dictionary)>( path: P, f: F, ) -> Result<()> { use std::io::Cursor; let path = path.as_ref(); if path.exists() { let plist_str = read_to_string(path)?; let mut plist = plist::Value::from_reader(Cursor::new(&plist_str))?; if let Some(dict) = plist.as_dictionary_mut() { f(dict); let mut plist_buf = Vec::new(); let writer = Cursor::new(&mut plist_buf); plist::to_writer_xml(writer, &plist)?; let new_plist_str = String::from_utf8(plist_buf)?; if new_plist_str != plist_str { write(path, new_plist_str)?; } } } Ok(()) } fn xml_block_comment(id: &str) -> String { format!("") } fn insert_into_xml(xml: &str, block_identifier: &str, parent_tag: &str, contents: &str) -> String { let block_comment = xml_block_comment(block_identifier); let mut rewritten = Vec::new(); let mut found_block = false; let parent_closing_tag = format!(""); for line in xml.split('\n') { if line.contains(&block_comment) { found_block = !found_block; continue; } // found previous block which should be removed if found_block { continue; } if let Some(index) = line.find(&parent_closing_tag) { let indentation = " ".repeat(index + 4); rewritten.push(format!("{indentation}{block_comment}")); for l in contents.split('\n') { rewritten.push(format!("{indentation}{l}")); } rewritten.push(format!("{indentation}{block_comment}")); } rewritten.push(line.to_string()); } rewritten.join("\n") } #[cfg(test)] mod tests { #[test] fn insert_into_xml() { let manifest = r#" "#; let id = "tauritest"; let new = super::insert_into_xml(manifest, id, "application", ""); let block_id_comment = super::xml_block_comment(id); let expected = format!( r#" {block_id_comment} {block_id_comment} "# ); assert_eq!(new, expected); // assert it's still the same after an empty update let new = super::insert_into_xml(&expected, id, "application", ""); assert_eq!(new, expected); } } ================================================ FILE: crates/tauri-plugin/src/build/mod.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use std::{ collections::BTreeMap, path::{Path, PathBuf}, }; use anyhow::Result; use tauri_utils::acl::{self, Error}; pub mod mobile; use serde::de::DeserializeOwned; use std::{env, io::Cursor}; const RESERVED_PLUGIN_NAMES: &[&str] = &["core", "tauri"]; pub fn plugin_config(name: &str) -> Option { let config_env_var_name = format!( "TAURI_{}_PLUGIN_CONFIG", name.to_uppercase().replace('-', "_") ); if let Ok(config_str) = env::var(&config_env_var_name) { println!("cargo:rerun-if-env-changed={config_env_var_name}"); serde_json::from_reader(Cursor::new(config_str)) .map(Some) .expect("failed to parse configuration") } else { None } } pub struct Builder<'a> { commands: &'a [&'static str], global_scope_schema: Option, global_api_script_path: Option, android_path: Option, ios_path: Option, } impl<'a> Builder<'a> { pub fn new(commands: &'a [&'static str]) -> Self { Self { commands, global_scope_schema: None, global_api_script_path: None, android_path: None, ios_path: None, } } /// Sets the global scope JSON schema. pub fn global_scope_schema(mut self, schema: schemars::schema::RootSchema) -> Self { self.global_scope_schema.replace(schema); self } /// Sets the path to the script that is injected in the webview when the `withGlobalTauri` configuration is set to true. /// /// This is usually an IIFE that injects the plugin API JavaScript bindings to `window.__TAURI__`. pub fn global_api_script_path>(mut self, path: P) -> Self { self.global_api_script_path.replace(path.into()); self } /// Sets the Android project path. pub fn android_path>(mut self, android_path: P) -> Self { self.android_path.replace(android_path.into()); self } /// Sets the iOS project path. pub fn ios_path>(mut self, ios_path: P) -> Self { self.ios_path.replace(ios_path.into()); self } /// [`Self::try_build`] but will exit automatically if an error is found. pub fn build(self) { if let Err(error) = self.try_build() { println!("{}: {error:#}", env!("CARGO_PKG_NAME")); std::process::exit(1); } } /// Ensure this crate is properly configured to be a Tauri plugin. /// /// # Errors /// /// Errors will occur if environmental variables expected to be set inside of [build scripts] /// are not found, or if the crate violates Tauri plugin conventions. pub fn try_build(self) -> Result<()> { // convention: plugin names should not use underscores let name = build_var("CARGO_PKG_NAME")?; if name.contains('_') { anyhow::bail!("plugin names cannot contain underscores"); } if RESERVED_PLUGIN_NAMES.contains(&name.as_str()) { anyhow::bail!("plugin name `{name}` is reserved"); } let out_dir = PathBuf::from(build_var("OUT_DIR")?); // requirement: links MUST be set and MUST match the name let _links = std::env::var("CARGO_MANIFEST_LINKS").map_err(|_| Error::LinksMissing)?; let autogenerated = Path::new("permissions").join(acl::build::AUTOGENERATED_FOLDER_NAME); std::fs::create_dir_all(&autogenerated).expect("unable to create permissions dir"); let commands_dir = autogenerated.join("commands"); if !self.commands.is_empty() { acl::build::autogenerate_command_permissions(&commands_dir, self.commands, "", true); } println!("cargo:rerun-if-changed=permissions"); let permissions = acl::build::define_permissions("./permissions/**/*.*", &name, &out_dir, |_| true)?; if permissions.is_empty() { let _ = std::fs::remove_file(format!( "./permissions/{}/{}", acl::PERMISSION_SCHEMAS_FOLDER_NAME, acl::PERMISSION_SCHEMA_FILE_NAME )); let _ = std::fs::remove_file(autogenerated.join(acl::build::PERMISSION_DOCS_FILE_NAME)); } else { acl::schema::generate_permissions_schema(&permissions, "./permissions")?; acl::build::generate_docs( &permissions, &autogenerated, name.strip_prefix("tauri-plugin-").unwrap_or(&name), )?; } let mut permissions_map = BTreeMap::new(); permissions_map.insert(name.clone(), permissions); tauri_utils::acl::build::generate_allowed_commands(&out_dir, None, permissions_map)?; if let Some(global_scope_schema) = self.global_scope_schema { acl::build::define_global_scope_schema(global_scope_schema, &name, &out_dir)?; } if let Some(path) = self.global_api_script_path { tauri_utils::plugin::define_global_api_script_path(&path); } mobile::setup(self.android_path, self.ios_path)?; Ok(()) } } fn cfg_alias(alias: &str, has_feature: bool) { println!("cargo:rustc-check-cfg=cfg({alias})"); if has_feature { println!("cargo:rustc-cfg={alias}"); } } /// Grab an env var that is expected to be set inside of build scripts. fn build_var(key: &'static str) -> Result { std::env::var(key).map_err(|_| Error::BuildVar(key)) } ================================================ FILE: crates/tauri-plugin/src/lib.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT //! Interface for building Tauri plugins. #![doc( html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png", html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png" )] #![cfg_attr(docsrs, feature(doc_cfg))] #[cfg(feature = "build")] mod build; #[cfg(feature = "runtime")] mod runtime; #[cfg(feature = "build")] #[cfg_attr(docsrs, doc(feature = "build"))] pub use build::*; #[cfg(feature = "runtime")] #[cfg_attr(docsrs, doc(feature = "runtime"))] #[allow(unused)] pub use runtime::*; ================================================ FILE: crates/tauri-plugin/src/runtime.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT ================================================ FILE: crates/tauri-runtime/CHANGELOG.md ================================================ # Changelog ## \[2.10.1] ### Dependencies - Upgraded to `tauri-utils@2.8.3` ## \[2.10.0] ### Bug Fixes - [`9b242e40c`](https://www.github.com/tauri-apps/tauri/commit/9b242e40c844189c877a91e513ae6196202d5ae9) ([#14700](https://www.github.com/tauri-apps/tauri/pull/14700) by [@mewi99](https://www.github.com/tauri-apps/tauri/../../mewi99)) Fix compilation errors when targeting BSD. ### Dependencies - Upgraded to `tauri-utils@2.8.2` - [`75057c7c0`](https://www.github.com/tauri-apps/tauri/commit/75057c7c08f0d4d3dd8d10cea4e2217e5d61fe1a) ([#14778](https://www.github.com/tauri-apps/tauri/pull/14778) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) **Breaking Change** for `with_webview` users: Updated webkit2gtk-rs crates to `v2.0.2`. ## \[2.9.2] ### Dependencies - Upgraded to `tauri-utils@2.8.1` ## \[2.9.1] ### Bug Fixes - [`4b6b8690a`](https://www.github.com/tauri-apps/tauri/commit/4b6b8690ab886ebdf1307951cffbe03e31280baa) ([#14347](https://www.github.com/tauri-apps/tauri/pull/14347) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused docs.rs builds to fail. No user facing changes. ## \[2.9.0] ### New Features - [`f5851ee00`](https://www.github.com/tauri-apps/tauri/commit/f5851ee00d6d1f4d560a220ca5a728fedd525092) ([#14089](https://www.github.com/tauri-apps/tauri/pull/14089)) Adds the `scroll_bar_style` option to the Webview and WebviewWindow builders. The possible values for this option are gated behind conditional compilation flags, and will need to be applied using conditional compilation if customised. ### Dependencies - Upgraded to `tauri-utils@2.8.0` ## \[2.8.0] ### New Features - [`68874c68c`](https://www.github.com/tauri-apps/tauri/commit/68874c68c566638b4c21a3aa67844d1bdaeb6dab) ([#13564](https://www.github.com/tauri-apps/tauri/pull/13564) by [@robertrpf](https://www.github.com/tauri-apps/tauri/../../robertrpf)) Add window focusable attribute and set_focusable API. - [`22d6bcacb`](https://www.github.com/tauri-apps/tauri/commit/22d6bcacbb2001eb292ebd8c5d021447700f9512) ([#14008](https://www.github.com/tauri-apps/tauri/pull/14008) by [@WSH032](https://www.github.com/tauri-apps/tauri/../../WSH032)) Implement `App::set_device_event_filter` for `AppHandle` also. - [`33d0b3f0c`](https://www.github.com/tauri-apps/tauri/commit/33d0b3f0c133edebb1c716e2f5942d70509ae347) ([#13876](https://www.github.com/tauri-apps/tauri/pull/13876) by [@thlstsul](https://www.github.com/tauri-apps/tauri/../../thlstsul)) Added `WebviewBuilder::on_document_title_changed` and `WebviewWindowBuilder::on_document_title_changed`. - [`33d0b3f0c`](https://www.github.com/tauri-apps/tauri/commit/33d0b3f0c133edebb1c716e2f5942d70509ae347) ([#13876](https://www.github.com/tauri-apps/tauri/pull/13876) by [@thlstsul](https://www.github.com/tauri-apps/tauri/../../thlstsul)) Added `WebviewBuilder::on_new_window` and `WebviewWindowBuilder::on_new_window`. - [`dfadcb764`](https://www.github.com/tauri-apps/tauri/commit/dfadcb764bdf84089a5487005a7b4f3b7cf09494) ([#13661](https://www.github.com/tauri-apps/tauri/pull/13661) by [@WSH032](https://www.github.com/tauri-apps/tauri/../../WSH032)) Added `WebviewDispatch::set_cookie()` and `WebviewDispatch::delete_cookie()`. - [`5110a762e`](https://www.github.com/tauri-apps/tauri/commit/5110a762e9db978a28a15400bf76e3c864da2a86) ([#13830](https://www.github.com/tauri-apps/tauri/pull/13830) by [@Sky-walkerX](https://www.github.com/tauri-apps/tauri/../../Sky-walkerX)) Added `Window::set_simple_fullscreen`. ### Dependencies - Upgraded to `tauri-utils@2.7.0` ## \[2.7.1] ### Dependencies - Upgraded to `tauri-utils@2.6.0` ## \[2.7.0] ### Dependencies - Upgraded to `tauri-utils@2.5.0` - [`9c16eefa3`](https://www.github.com/tauri-apps/tauri/commit/9c16eefa319b4697bac1d1019bbb5f93eca63173) ([#13629](https://www.github.com/tauri-apps/tauri/pull/13629)) Update html5ever to 0.29 and kuchikiki to version 0.8.8-speedreader. ## \[2.6.0] ### New Features - [`dd4f13ce4`](https://www.github.com/tauri-apps/tauri/commit/dd4f13ce4b3cd89cde2fa3f18a063c272f215621) ([#13185](https://www.github.com/tauri-apps/tauri/pull/13185)) MacOS: Add `set_dock_visibility` method to support setting the visibility of the application in the dock. - [`8cf662e34`](https://www.github.com/tauri-apps/tauri/commit/8cf662e34bf738a0d16bb7b9aeb35667e2e4984b) ([#13076](https://www.github.com/tauri-apps/tauri/pull/13076)) - add API to run initialization scripts on all frames \- `WebviewBuilder::initialization_script_on_all_frames` \- `WebviewWindowBuilder::initialization_script_on_all_frames` \- `WebviewAttributes::initialization_script_on_all_frames` - [`ea36294cb`](https://www.github.com/tauri-apps/tauri/commit/ea36294cbca98f7725c91d1464fd92e77c89698a) ([#13208](https://www.github.com/tauri-apps/tauri/pull/13208)) Added `WebviewAttributes::input_accessory_view_builder` on iOS. - [`c1cd0a2dd`](https://www.github.com/tauri-apps/tauri/commit/c1cd0a2ddb5bc3e99451cbe399b5fc9f0035f571) ([#13090](https://www.github.com/tauri-apps/tauri/pull/13090)) macOS/iOS: add option to disable or enable link previews when building a webview (the webkit api has it enabled by default) - `WebViewBuilder.allow_link_preview(allow_link_preview: bool)` - `WebviewWindowBuilder.allow_link_preview(allow_link_preview: bool)` - [`b072e2b29`](https://www.github.com/tauri-apps/tauri/commit/b072e2b2967640ae4fa1af466ae878c156551edd) ([#9687](https://www.github.com/tauri-apps/tauri/pull/9687)) Add `preventOverflow` config option to prevent the window from overflowing the monitor size on creation ### Dependencies - Upgraded to `tauri-utils@2.4.0` - [`bb5faa21f`](https://www.github.com/tauri-apps/tauri/commit/bb5faa21f418dd765ce81b495b56e9c519251b6d) ([#13163](https://www.github.com/tauri-apps/tauri/pull/13163)) Update windows to 0.61. ## \[2.5.1] ### Dependencies - Upgraded to `tauri-utils@2.3.1` ## \[2.5.0] ### New Features - [`be2e6b85f`](https://www.github.com/tauri-apps/tauri/commit/be2e6b85fed226732b4a98f68cc5d72b4f8f5a13) ([#12944](https://www.github.com/tauri-apps/tauri/pull/12944) by [@Simon-Laux](https://www.github.com/tauri-apps/tauri/../../Simon-Laux)) add `Window.is_always_on_top()` and `WebviewWindow.is_always_on_top()` - [`658e5f5d1`](https://www.github.com/tauri-apps/tauri/commit/658e5f5d1dc1bd970ae572a42447448d064a7fee) ([#12668](https://www.github.com/tauri-apps/tauri/pull/12668) by [@thomaseizinger](https://www.github.com/tauri-apps/tauri/../../thomaseizinger)) Add `App::run_return` function. Contrary to `App::run`, this will **not** exit the process but instead return the requested exit-code. This allows the host app to perform further cleanup after Tauri has exited. `App::run_return` is not available on iOS and fallbacks to the regular `App::run` functionality. The `App::run_iteration` function is deprecated as part of this because calling it in a loop - as suggested by the name - will cause a busy-loop. - [`30f5a1553`](https://www.github.com/tauri-apps/tauri/commit/30f5a1553d3c0ce460c9006764200a9210915a44) ([#12366](https://www.github.com/tauri-apps/tauri/pull/12366) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Added `trafficLightPosition` window configuration to set the traffic light buttons position on macOS. - [`30f5a1553`](https://www.github.com/tauri-apps/tauri/commit/30f5a1553d3c0ce460c9006764200a9210915a44) ([#12366](https://www.github.com/tauri-apps/tauri/pull/12366) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Added `traffic_light_position` window builder method to set the traffic light buttons position on macOS. - [`cedb24d49`](https://www.github.com/tauri-apps/tauri/commit/cedb24d494b84111daa3206c05196c8b89f1e994) ([#12665](https://www.github.com/tauri-apps/tauri/pull/12665) by [@charrondev](https://www.github.com/tauri-apps/tauri/../../charrondev)) Added `WebviewDispatch::cookies()` and `WebviewDispatch::cookies_for_url()`. ### Dependencies - Upgraded to `tauri-utils@2.3.0` ## \[2.4.0] ### Enhancements - [`a2d36b8c3`](https://www.github.com/tauri-apps/tauri/commit/a2d36b8c34a8dcfc6736797ca5cd4665faf75e7e) ([#12181](https://www.github.com/tauri-apps/tauri/pull/12181) by [@bastiankistner](https://www.github.com/tauri-apps/tauri/../../bastiankistner)) Add an option to change the default background throttling policy (currently for WebKit only). - [`d6520a21c`](https://www.github.com/tauri-apps/tauri/commit/d6520a21ce02c3e2be2955999946c2cb7bdb07aa) ([#12541](https://www.github.com/tauri-apps/tauri/pull/12541) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Updated `wry` to 0.50, `windows` to 0.60, `webview2-com` to 0.36, and `objc2` to 0.6. This can be a **breaking change** if you use the `with_webview` API! ### Dependencies - Upgraded to `tauri-utils@2.2.0` ## \[2.3.0] ### New Features - [`18bd639f6`](https://www.github.com/tauri-apps/tauri/commit/18bd639f6e22c0188aa219739f367b5bf5ab0398) ([#11798](https://www.github.com/tauri-apps/tauri/pull/11798) by [@lars-berger](https://www.github.com/tauri-apps/tauri/../../lars-berger)) Add `WebviewWindowBuilder/WebviewBuilder::data_store_identifier` on macOS. - [`dc4d79477`](https://www.github.com/tauri-apps/tauri/commit/dc4d79477665bc3bfefb4048772414cf5d78e3df) ([#11628](https://www.github.com/tauri-apps/tauri/pull/11628) by [@SpikeHD](https://www.github.com/tauri-apps/tauri/../../SpikeHD)) Add `WebviewWindowBuilder/WebviewBuilder::extensions_path` on Linux and Windows. - [`020ea0556`](https://www.github.com/tauri-apps/tauri/commit/020ea05561348dcd6d2a7df358f8a5190f661ba2) ([#11661](https://www.github.com/tauri-apps/tauri/pull/11661) by [@ahqsoftwares](https://www.github.com/tauri-apps/tauri/../../ahqsoftwares)) Add badging APIs: - `Window/WebviewWindow::set_badge_count` for Linux, macOS and IOS. - `Window/WebviewWindow::set_overlay_icon` for Windows Only. - `Window/WebviewWindow::set_badge_label`for macOS Only. ### Dependencies - Upgraded to `tauri-utils@2.1.1` ## \[2.2.0] ### New Features - [`4d545ab3c`](https://www.github.com/tauri-apps/tauri/commit/4d545ab3ca228c8a21b966b709f84a0da2864479) ([#11486](https://www.github.com/tauri-apps/tauri/pull/11486) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Added `Window::set_background_color` and `WindowBuilder::background_color`. - [`f37e97d41`](https://www.github.com/tauri-apps/tauri/commit/f37e97d410c4a219e99f97692da05ca9d8e0ba3a) ([#11477](https://www.github.com/tauri-apps/tauri/pull/11477) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `WebviewWindowBuilder/WebviewBuilder::use_https_scheme` to choose whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android - [`cbc095ec5`](https://www.github.com/tauri-apps/tauri/commit/cbc095ec5fe7de29b5c9265576d4e071ec159c1c) ([#11451](https://www.github.com/tauri-apps/tauri/pull/11451) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `WebviewWindowBuilder::devtools` and `WebviewBuilder::devtools` to enable or disable devtools for a specific webview. - [`2a75c64b5`](https://www.github.com/tauri-apps/tauri/commit/2a75c64b5431284e7340e8743d4ea56a62c75466) ([#11469](https://www.github.com/tauri-apps/tauri/pull/11469) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Added `WindowBuilder/WebviewWindowBuilder::window_classname` method to specify the name of the window class on Windows. ### Bug Fixes - [`129414faa`](https://www.github.com/tauri-apps/tauri/commit/129414faa4e027c9035d56614682cacc0335a6a0) ([#11569](https://www.github.com/tauri-apps/tauri/pull/11569) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix webview not focused by default. ### Dependencies - Upgraded to `tauri-utils@2.1.0` ## \[2.1.1] ### Dependencies - Upgraded to `tauri-utils@2.0.2` ## \[2.1.0] ### Bug Fixes - [`2d087ee4b`](https://www.github.com/tauri-apps/tauri/commit/2d087ee4b7d3e8849933f81284e4f5ed1aaa6455) ([#11268](https://www.github.com/tauri-apps/tauri/pull/11268) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) On Linux, fix commands, that use `Webview` or `WebviewWindow` as an argument, receiving an incorrect webview when using multi webviews. - [`2d087ee4b`](https://www.github.com/tauri-apps/tauri/commit/2d087ee4b7d3e8849933f81284e4f5ed1aaa6455) ([#11268](https://www.github.com/tauri-apps/tauri/pull/11268) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) On Linux, fix events only emitted to first webview only when using multi webviews. - [`2d087ee4b`](https://www.github.com/tauri-apps/tauri/commit/2d087ee4b7d3e8849933f81284e4f5ed1aaa6455) ([#11268](https://www.github.com/tauri-apps/tauri/pull/11268) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) On Linux, fix custom protocols receiving an incorrect webview label when using multi webviews ## \[2.0.1] ### What's Changed - [`0ab2b3306`](https://www.github.com/tauri-apps/tauri/commit/0ab2b330644b6419f6cee1d5377bfb5cdda2ccf9) ([#11205](https://www.github.com/tauri-apps/tauri/pull/11205) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Downgrade MSRV to 1.77.2 to support Windows 7. ### Dependencies - Upgraded to `tauri-utils@2.0.1` ## \[2.0.0] ### What's Changed - [`382ed482b`](https://www.github.com/tauri-apps/tauri/commit/382ed482bd08157c39e62f9a0aaad8802f1092cb) Bump MSRV to 1.78. - [`637285790`](https://www.github.com/tauri-apps/tauri/commit/6372857905ae9c0aedb7f482ddf6cf9f9836c9f2) Promote to v2 stable! ### Dependencies - Upgraded to `tauri-utils@2.0.0` ## \[2.0.0-rc.13] ### New Features - [`a247170e1`](https://www.github.com/tauri-apps/tauri/commit/a247170e1f620a9b012274b11cfe51e90327d6e9) ([#11056](https://www.github.com/tauri-apps/tauri/pull/11056) by [@SpikeHD](https://www.github.com/tauri-apps/tauri/../../SpikeHD)) Expose the ability to enabled browser extensions in WebView2 on Windows. - [`9014a3f17`](https://www.github.com/tauri-apps/tauri/commit/9014a3f1765ca406ea5c3e5224267a79c52cd53d) ([#11066](https://www.github.com/tauri-apps/tauri/pull/11066) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `WebviewWindow::clear_all_browsing_data` and `Webview::clear_all_browsing_data` to clear the webview browsing data. - [`95df53a2e`](https://www.github.com/tauri-apps/tauri/commit/95df53a2ed96873cd35a4b14a5e312d07e4e3004) ([#11143](https://www.github.com/tauri-apps/tauri/pull/11143) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Add the ability to set theme dynamically using `Window::set_theme`, `App::set_theme` - [`d9d2502b4`](https://www.github.com/tauri-apps/tauri/commit/d9d2502b41e39efde679e30c8955006e2ba9ea64) ([#11140](https://www.github.com/tauri-apps/tauri/pull/11140) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `WebviewDispatch::hide` and `WebviewDispatch::show` methods. - [`de7414aab`](https://www.github.com/tauri-apps/tauri/commit/de7414aab935e45540594ea930eb60bae4dbc979) ([#11154](https://www.github.com/tauri-apps/tauri/pull/11154) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `Window::set_enabled` and `Window::is_enabled` methods ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.13` ## \[2.0.0-rc.12] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.12` ## \[2.0.0-rc.11] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.11` ## \[2.0.0-rc.10] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.10` ## \[2.0.0-rc.9] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.9` ## \[2.0.0-rc.8] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.8` ## \[2.0.0-rc.7] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.7` ## \[2.0.0-rc.6] ### What's Changed - [`f4d5241b3`](https://www.github.com/tauri-apps/tauri/commit/f4d5241b377d0f7a1b58100ee19f7843384634ac) ([#10731](https://www.github.com/tauri-apps/tauri/pull/10731) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Update documentation icon path. ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.6` ## \[2.0.0-rc.5] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.5` ## \[2.0.0-rc.4] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.4` ## \[2.0.0-rc.3] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.3` - [`d39c392b7`](https://www.github.com/tauri-apps/tauri/commit/d39c392b7cec746da423211f9c74632abe4b6af5) ([#10655](https://www.github.com/tauri-apps/tauri/pull/10655) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Update `tao` to 0.29 and `wry` to 0.42. ## \[2.0.0-rc.2] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.2` ## \[2.0.0-rc.1] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.1` ## \[2.0.0-rc.0] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.0` ## \[2.0.0-beta.21] ### What's Changed - [`da25f7353`](https://www.github.com/tauri-apps/tauri/commit/da25f7353070477ba969851e974379d7666d6806) ([#10242](https://www.github.com/tauri-apps/tauri/pull/10242) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `inner_size_constraints` method on `WindowBuilder` trait and `set_size_constraints` method on `WindowDispatch` trait. ## \[2.0.0-beta.20] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.19` ## \[2.0.0-beta.19] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.18` - [`d4c908cfb`](https://www.github.com/tauri-apps/tauri/commit/d4c908cfb8c567abdaf99b85f65f482ea81967e5) ([#10048](https://www.github.com/tauri-apps/tauri/pull/10048)) Update `windows` crate to version `0.57` and `webview2-com` crate to version `0.31` ## \[2.0.0-beta.18] ### Enhancements - [`276c4b143`](https://www.github.com/tauri-apps/tauri/commit/276c4b14385e17cff15a2e5b57fd2a7cddef9f08)([#9832](https://www.github.com/tauri-apps/tauri/pull/9832)) Added `WindowBuilder::get_theme`. ### What's Changed - [`9ac930380`](https://www.github.com/tauri-apps/tauri/commit/9ac930380a5df3fe700e68e75df8684d261ca292)([#9850](https://www.github.com/tauri-apps/tauri/pull/9850)) Emit `cargo:rustc-check-cfg` instruction so Cargo validates custom cfg attributes on Rust 1.80 (or nightly-2024-05-05). ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.17` ## \[2.0.0-beta.17] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.16` ## \[2.0.0-beta.16] ### New Features - [`78839b6d2`](https://www.github.com/tauri-apps/tauri/commit/78839b6d2f1005a5e6e1a54b0305136bae0c3a7c)([#4865](https://www.github.com/tauri-apps/tauri/pull/4865)) Add `RunEvent::Reopen` for handle click on dock icon on macOS. ### What's Changed - [`783ef0f2d`](https://www.github.com/tauri-apps/tauri/commit/783ef0f2d331f520fa827c3112f36c0b519b9292)([#9647](https://www.github.com/tauri-apps/tauri/pull/9647)) Changed `WebviewDispatch::url` getter to return a result. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.15` ## \[2.0.0-beta.15] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.14` ## \[2.0.0-beta.14] ### New Features - [`477bb8cd4`](https://www.github.com/tauri-apps/tauri/commit/477bb8cd4ea88ade3f6c1f268ad1701a68150161)([#9297](https://www.github.com/tauri-apps/tauri/pull/9297)) Add `App/AppHandle/Window/Webview/WebviewWindow::cursor_position` getter to get the current cursor position. ## \[2.0.0-beta.13] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.13` ## \[2.0.0-beta.12] ### New Features - [`58a7a552d`](https://www.github.com/tauri-apps/tauri/commit/58a7a552d739b77b71d61af11c53f7f2dc7a6e7e)([#9378](https://www.github.com/tauri-apps/tauri/pull/9378)) Added the `set_zoom` function to the webview API. - [`58a7a552d`](https://www.github.com/tauri-apps/tauri/commit/58a7a552d739b77b71d61af11c53f7f2dc7a6e7e)([#9378](https://www.github.com/tauri-apps/tauri/pull/9378)) Add `zoom_hotkeys_enabled` to enable browser native zoom controls on creating webviews. - [`4973d73a2`](https://www.github.com/tauri-apps/tauri/commit/4973d73a237dc5c60618c1011e202278e7a29b5c)([#9386](https://www.github.com/tauri-apps/tauri/pull/9386)) Provide a basic zoom hotkey polyfill for non-Windows platforms ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.12` ## \[2.0.0-beta.11] ### What's Changed - [`06833f4fa`](https://www.github.com/tauri-apps/tauri/commit/06833f4fa8e63ecc55fe3fc874a9e397e77a5709)([#9100](https://www.github.com/tauri-apps/tauri/pull/9100)) Updated `http` crate to `1.1` ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.11` ### Breaking Changes - [`06833f4fa`](https://www.github.com/tauri-apps/tauri/commit/06833f4fa8e63ecc55fe3fc874a9e397e77a5709)([#9100](https://www.github.com/tauri-apps/tauri/pull/9100)) The IPC handler closure now receives a `http::Request` instead of a String representing the request body. - [`06833f4fa`](https://www.github.com/tauri-apps/tauri/commit/06833f4fa8e63ecc55fe3fc874a9e397e77a5709)([#9100](https://www.github.com/tauri-apps/tauri/pull/9100)) Rename `FileDrop` to `DragDrop` on structs, enums and enum variants. Also renamed `file_drop` to `drag_drop` on fields and function names. - [`06833f4fa`](https://www.github.com/tauri-apps/tauri/commit/06833f4fa8e63ecc55fe3fc874a9e397e77a5709)([#9100](https://www.github.com/tauri-apps/tauri/pull/9100)) Moved `window::dpi` module to the root of the crate. ## \[2.0.0-beta.10] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.10` ## \[2.0.0-beta.9] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.9` ## \[2.0.0-beta.8] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.8` ## \[2.0.0-beta.7] ### New Features - [`46de49aaa`](https://www.github.com/tauri-apps/tauri/commit/46de49aaad4a148fafc31d591be0e2ed12256507)([#9059](https://www.github.com/tauri-apps/tauri/pull/9059)) Added `set_auto_resize` method for the webview. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.7` ### Breaking Changes - [`d1e77acd8`](https://www.github.com/tauri-apps/tauri/commit/d1e77acd8dfdf554b90b542513a58a2de1ef2360)([#9011](https://www.github.com/tauri-apps/tauri/pull/9011)) Add a lifetime parameter for `Icon` type. Also changed `rgba` field to be `Cow<'a, [u8]>` ## \[2.0.0-beta.6] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.6` ## \[2.0.0-beta.5] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.5` ## \[2.0.0-beta.4] ### New Features - [`fdcaf935`](https://www.github.com/tauri-apps/tauri/commit/fdcaf935fa75ecfa2806939c4faad4fe9e880386)([#8939](https://www.github.com/tauri-apps/tauri/pull/8939)) Added the `reparent` function to the webview API. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.4` ## \[2.0.0-beta.3] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.3` ## \[2.0.0-beta.2] ### What's Changed - [`16e550ec`](https://www.github.com/tauri-apps/tauri/commit/16e550ec1503765158cdc3bb2a20e70ec710e981)([#8844](https://www.github.com/tauri-apps/tauri/pull/8844)) Add `WebviewEvent`, `RunEvent::WebviewEvent` and `WebviewDispatch::on_webview_event`. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.2` ### Breaking Changes - [`2f55bfec`](https://www.github.com/tauri-apps/tauri/commit/2f55bfecbf0244f3b5aa1ad7622182fca3fcdcbb)([#8795](https://www.github.com/tauri-apps/tauri/pull/8795)) Update raw-window-handle to 0.6. ## \[2.0.0-beta.1] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.1` ## \[2.0.0-beta.0] ### New Features - [`af610232`](https://www.github.com/tauri-apps/tauri/commit/af6102327376884364b2075b468bdf08ee0d02aa)([#8710](https://www.github.com/tauri-apps/tauri/pull/8710)) Added `Window::destroy` to force close a window. - [`c77b4032`](https://www.github.com/tauri-apps/tauri/commit/c77b40324ea9bf580871fc11aed69ba0c9b6b8cf)([#8280](https://www.github.com/tauri-apps/tauri/pull/8280)) Add multiwebview support behind the `unstable` feature flag. See `WindowBuilder` and `WebviewBuilder` for more information. - [`00e15675`](https://www.github.com/tauri-apps/tauri/commit/00e1567584721644797b587205187f9cbe4e5cd1)([#8708](https://www.github.com/tauri-apps/tauri/pull/8708)) Added `RuntimeHandle::request_exit` function. ### Bug Fixes - [`95da1a27`](https://www.github.com/tauri-apps/tauri/commit/95da1a27476e01e06f6ce0335df8535b662dd9c4)([#8713](https://www.github.com/tauri-apps/tauri/pull/8713)) Fix calling `set_activation_policy` when the event loop is running. ### What's Changed - [`9eaeb5a8`](https://www.github.com/tauri-apps/tauri/commit/9eaeb5a8cd95ae24b5e66205bdc2763cb7f965ce)([#8622](https://www.github.com/tauri-apps/tauri/pull/8622)) Added `WindowBuilder::transient_for` and Renamed `WindowBuilder::owner_window` to `WindowBuilder::owner` and `WindowBuilder::parent_window` to `WindowBuilder::parent`. - [`7f033f6d`](https://www.github.com/tauri-apps/tauri/commit/7f033f6dcd54c69a4193765a5c1584755ba92c61)([#8537](https://www.github.com/tauri-apps/tauri/pull/8537)) Add `Window::start_resize_dragging` and `ResizeDirection` enum. - [`6639a579`](https://www.github.com/tauri-apps/tauri/commit/6639a579c76d45210f33a72d37e21d4c5a9d334b)([#8441](https://www.github.com/tauri-apps/tauri/pull/8441)) Added the `WindowConfig::proxy_url` `WebviewBuilder::proxy_url() / WebviewWindowBuilder::proxy_url()` options when creating a webview. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.0` ### Breaking Changes - [`9eaeb5a8`](https://www.github.com/tauri-apps/tauri/commit/9eaeb5a8cd95ae24b5e66205bdc2763cb7f965ce)([#8622](https://www.github.com/tauri-apps/tauri/pull/8622)) Changed `WindowBuilder::with_config` to take a reference to a `WindowConfig` instead of an owned value. ## \[1.0.0-alpha.8] ### New Features - [`29ced5ce`](https://www.github.com/tauri-apps/tauri/commit/29ced5ceec40b2934094ade2db9a8855f294e1d1)([#8159](https://www.github.com/tauri-apps/tauri/pull/8159)) Added download event closure via `PendingWindow::download_handler`. ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.13` ## \[1.0.0-alpha.7] ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.12` ## \[1.0.0-alpha.6] ### Dependencies - [\`\`](https://www.github.com/tauri-apps/tauri/commit/undefined) Update dependencies. ## \[1.0.0-alpha.5] ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.11` ## \[1.0.0-alpha.4] ### New Features - [`74d2464d`](https://www.github.com/tauri-apps/tauri/commit/74d2464d0e490fae341ad73bdf2964cf215fe6c5)([#8116](https://www.github.com/tauri-apps/tauri/pull/8116)) Added `on_page_load` hook for `PendingWindow`. ### Enhancements - [`c6c59cf2`](https://www.github.com/tauri-apps/tauri/commit/c6c59cf2373258b626b00a26f4de4331765dd487) Pull changes from Tauri 1.5 release. ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.10` - [`9580df1d`](https://www.github.com/tauri-apps/tauri/commit/9580df1d7b027befb9e5f025ea2cbaf2dcc82c8e)([#8084](https://www.github.com/tauri-apps/tauri/pull/8084)) Upgrade `gtk` to 0.18. - [`c7c2507d`](https://www.github.com/tauri-apps/tauri/commit/c7c2507da16a9beb71bf06745fe7ac1325ab7c2a)([#8035](https://www.github.com/tauri-apps/tauri/pull/8035)) Update `windows` to version `0.51` and `webview2-com` to version `0.27` ## \[1.0.0-alpha.3] ### New Features - [`c085adda`](https://www.github.com/tauri-apps/tauri/commit/c085addab58ba851398373c6fd13f9cb026d71e8)([#8009](https://www.github.com/tauri-apps/tauri/pull/8009)) Added `set_progress_bar` to `Window`. - [`c1ec0f15`](https://www.github.com/tauri-apps/tauri/commit/c1ec0f155118527361dd5645d920becbc8afd569)([#7933](https://www.github.com/tauri-apps/tauri/pull/7933)) Added `Window::set_always_on_bottom` and the `always_on_bottom` option when creating a window. - [`880266a7`](https://www.github.com/tauri-apps/tauri/commit/880266a7f697e1fe58d685de3bb6836ce5251e92)([#8031](https://www.github.com/tauri-apps/tauri/pull/8031)) Bump the MSRV to 1.70. ### Enhancements - [`46dcb941`](https://www.github.com/tauri-apps/tauri/commit/46dcb94110ac16d0d4328fa149bb86975b658f59)([#8006](https://www.github.com/tauri-apps/tauri/pull/8006)) Include mobile on docs.rs targets. ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.9` ### Breaking Changes - [`2558fab8`](https://www.github.com/tauri-apps/tauri/commit/2558fab861006936296e8511e43ccd69a38f61b0)([#7939](https://www.github.com/tauri-apps/tauri/pull/7939)) Added `WindowEventId` type and Changed `Dispatch::on_window_event` return type from `Uuid` to `WindowEventId` ## \[1.0.0-alpha.2] ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.8` ## \[1.0.0-alpha.1] ### Enhancements - [`0d63732b`](https://www.github.com/tauri-apps/tauri/commit/0d63732b962e71b98430f8d7b34ea5b59a2e8bb4)([#7754](https://www.github.com/tauri-apps/tauri/pull/7754)) Changed custom protocol closure type to enable asynchronous usage. ### What's Changed - [`6177150b`](https://www.github.com/tauri-apps/tauri/commit/6177150b6f83b52ca359d6e20f7e540f7554e4eb)([#7601](https://www.github.com/tauri-apps/tauri/pull/7601)) Changed `FileDropEvent` to include drop and hover position. ### Breaking Changes - [`0d63732b`](https://www.github.com/tauri-apps/tauri/commit/0d63732b962e71b98430f8d7b34ea5b59a2e8bb4)([#7754](https://www.github.com/tauri-apps/tauri/pull/7754)) `tauri-runtime` no longer implements its own HTTP types and relies on the `http` crate instead. ## \[1.0.0-alpha.0] ### New Features - [`4db363a0`](https://www.github.com/tauri-apps/tauri/commit/4db363a03c182349f8491f46ced258d84723b11f)([#6589](https://www.github.com/tauri-apps/tauri/pull/6589)) Added `visible_on_all_workspaces` configuration option to `WindowBuilder`, `Window`, and `WindowConfig`. - [`84c41597`](https://www.github.com/tauri-apps/tauri/commit/84c4159754b2e59244211ed9e1fc702d851a0562)([#6394](https://www.github.com/tauri-apps/tauri/pull/6394)) Added `primary_monitor` and `available_monitors` to `Runtime` and `RuntimeHandle`. - [`2a000e15`](https://www.github.com/tauri-apps/tauri/commit/2a000e150d02dff28c8b20ad097b29e209160045)([#7235](https://www.github.com/tauri-apps/tauri/pull/7235)) Added `navigate` function to `Dispatch` trait. - [`3b98141a`](https://www.github.com/tauri-apps/tauri/commit/3b98141aa26f74c641a4090874247b97079bd58a)([#3736](https://www.github.com/tauri-apps/tauri/pull/3736)) Added the `Opened` variant to `RunEvent`. ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.7` ### Breaking Changes - [`7fb419c3`](https://www.github.com/tauri-apps/tauri/commit/7fb419c326aaf72ecd556d8404377444ebb200e7)([#7535](https://www.github.com/tauri-apps/tauri/pull/7535)) `Dispatch::create_window`, `Runtime::create_window` and `RuntimeHandle::create_window` has been changed to accept a 3rd parameter which is a closure that takes `RawWindow` and to be executed right after the window is created and before the webview is added to the window. - [`7fb419c3`](https://www.github.com/tauri-apps/tauri/commit/7fb419c326aaf72ecd556d8404377444ebb200e7)([#7535](https://www.github.com/tauri-apps/tauri/pull/7535)) System tray and menu related APIs and structs have all been removed and are now implemented in tauri outside of the runtime-space. - [`3a2c3e74`](https://www.github.com/tauri-apps/tauri/commit/3a2c3e74710bef9a14932dce74c351cca6215429)([#7306](https://www.github.com/tauri-apps/tauri/pull/7306)) The `PendingWindow#navigation_handler` closure now receives a `&Url` argument instead of `Url`. - [`7fb419c3`](https://www.github.com/tauri-apps/tauri/commit/7fb419c326aaf72ecd556d8404377444ebb200e7)([#7535](https://www.github.com/tauri-apps/tauri/pull/7535)) `Runtime::new` and `Runtime::new_any_thread` now accept a `RuntimeInitArgs`. - [`7fb419c3`](https://www.github.com/tauri-apps/tauri/commit/7fb419c326aaf72ecd556d8404377444ebb200e7)([#7535](https://www.github.com/tauri-apps/tauri/pull/7535)) Removed `system-tray` feature flag ## \[0.13.0-alpha.6] ### New Features - [`e0f0dce2`](https://www.github.com/tauri-apps/tauri/commit/e0f0dce220730e2822fc202463aedf0166145de7)([#6442](https://www.github.com/tauri-apps/tauri/pull/6442)) Added the `window_effects` option when creating a window and `Window::set_effects` to change it at runtime. ## \[0.13.0-alpha.5] - [`39f1b04f`](https://www.github.com/tauri-apps/tauri/commit/39f1b04f7be4966488484829cd54c8ce72a04200)([#6943](https://www.github.com/tauri-apps/tauri/pull/6943)) Moved the `event` JS APIs to a plugin. - [`3188f376`](https://www.github.com/tauri-apps/tauri/commit/3188f3764978c6d1452ee31d5a91469691e95094)([#6883](https://www.github.com/tauri-apps/tauri/pull/6883)) Bump the MSRV to 1.65. - [`cebd7526`](https://www.github.com/tauri-apps/tauri/commit/cebd75261ac71b98976314a450cb292eeeec1515)([#6728](https://www.github.com/tauri-apps/tauri/pull/6728)) Moved the `clipboard` feature to its own plugin in the plugins-workspace repository. - [`3f17ee82`](https://www.github.com/tauri-apps/tauri/commit/3f17ee82f6ff21108806edb7b00500b8512b8dc7)([#6737](https://www.github.com/tauri-apps/tauri/pull/6737)) Moved the `global-shortcut` feature to its own plugin in the plugins-workspace repository. ## \[0.13.0-alpha.4] - Added `android` configuration object under `tauri > bundle`. - Bumped due to a bump in tauri-utils. - [db4c9dc6](https://www.github.com/tauri-apps/tauri/commit/db4c9dc655e07ee2184fe04571f500f7910890cd) feat(core): add option to configure Android's minimum SDK version ([#6651](https://www.github.com/tauri-apps/tauri/pull/6651)) on 2023-04-07 ## \[0.13.0-alpha.3] - Pull changes from Tauri 1.3 release. - [](https://www.github.com/tauri-apps/tauri/commit/undefined) on undefined ## \[0.13.0-alpha.2] - Add `find_class`, `run_on_android_context` on `RuntimeHandle`. - [05dad087](https://www.github.com/tauri-apps/tauri/commit/05dad0876842e2a7334431247d49365cee835d3e) feat: initial work for iOS plugins ([#6205](https://www.github.com/tauri-apps/tauri/pull/6205)) on 2023-02-11 - Added the `shadow` option when creating a window and `Window::set_shadow`. - [a81750d7](https://www.github.com/tauri-apps/tauri/commit/a81750d779bc72f0fdb7de90b7fbddfd8049b328) feat(core): add shadow APIs ([#6206](https://www.github.com/tauri-apps/tauri/pull/6206)) on 2023-02-08 - Implemented `with_webview` on Android and iOS. - [05dad087](https://www.github.com/tauri-apps/tauri/commit/05dad0876842e2a7334431247d49365cee835d3e) feat: initial work for iOS plugins ([#6205](https://www.github.com/tauri-apps/tauri/pull/6205)) on 2023-02-11 ## \[0.13.0-alpha.1] - Update gtk to 0.16. - [7eb9aa75](https://www.github.com/tauri-apps/tauri/commit/7eb9aa75cfd6a3176d3f566fdda02d88aa529b0f) Update gtk to 0.16 ([#6155](https://www.github.com/tauri-apps/tauri/pull/6155)) on 2023-01-30 - Bump the MSRV to 1.64. - [7eb9aa75](https://www.github.com/tauri-apps/tauri/commit/7eb9aa75cfd6a3176d3f566fdda02d88aa529b0f) Update gtk to 0.16 ([#6155](https://www.github.com/tauri-apps/tauri/pull/6155)) on 2023-01-30 ## \[0.13.0-alpha.0] - Parse `android` and `ios` Tauri configuration files. - Bumped due to a bump in tauri-utils. - [b3a3afc7](https://www.github.com/tauri-apps/tauri/commit/b3a3afc7de8de4021d73559288f5192732a706cf) feat(core): detect android and ios platform configuration files ([#4997](https://www.github.com/tauri-apps/tauri/pull/4997)) on 2022-08-22 - First mobile alpha release! - Bumped due to a bump in tauri-utils. - [fa3a1098](https://www.github.com/tauri-apps/tauri/commit/fa3a10988a03aed1b66fb17d893b1a9adb90f7cd) feat(ci): prepare 2.0.0-alpha.0 ([#5786](https://www.github.com/tauri-apps/tauri/pull/5786)) on 2022-12-08 ## \[0.14.2] ### Dependencies - Upgraded to `tauri-utils@1.5.2` ## \[0.14.1] ### Enhancements - [`9aa34ada`](https://www.github.com/tauri-apps/tauri/commit/9aa34ada5769dbefa7dfe5f7a6288b3d20b294e4)([#7645](https://www.github.com/tauri-apps/tauri/pull/7645)) Add setting to switch to `http://.localhost/` for custom protocols on Windows. ### Dependencies - Upgraded to `tauri-utils@1.5.0` ## \[0.14.0] ### New Features - [`c4d6fb4b`](https://www.github.com/tauri-apps/tauri/commit/c4d6fb4b1ea8acf02707a9fe5dcab47c1c5bae7b)([#2353](https://www.github.com/tauri-apps/tauri/pull/2353)) Added the `maximizable`, `minimizable` and `closable` methods to `WindowBuilder`. - [`c4d6fb4b`](https://www.github.com/tauri-apps/tauri/commit/c4d6fb4b1ea8acf02707a9fe5dcab47c1c5bae7b)([#2353](https://www.github.com/tauri-apps/tauri/pull/2353)) Added `set_maximizable`, `set_minimizable`, `set_closable`, `is_maximizable`, `is_minimizable` and `is_closable` methods to the `Dispatch` trait. - [`000104bc`](https://www.github.com/tauri-apps/tauri/commit/000104bc3bc0c9ff3d20558ab9cf2080f126e9e0)([#6472](https://www.github.com/tauri-apps/tauri/pull/6472)) Add `Window::is_focused` getter. ### Enhancements - [`d2710e9d`](https://www.github.com/tauri-apps/tauri/commit/d2710e9d2e8fd93975ef6494512370faa8cb3b7e)([#6944](https://www.github.com/tauri-apps/tauri/pull/6944)) Unpin `time`, `ignore`, and `winnow` crate versions. Developers now have to pin crates if needed themselves. A list of crates that need pinning to adhere to Tauri's MSRV will be visible in Tauri's GitHub workflow: https://github.com/tauri-apps/tauri/blob/dev/.github/workflows/test-core.yml#L85. ### Bug Fixes - [`2b487c94`](https://www.github.com/tauri-apps/tauri/commit/2b487c946737352187d7e042dd6142873e62a4ca)([#7012](https://www.github.com/tauri-apps/tauri/pull/7012)) Fixes typo in `CursorIcon` deserialization of the `ZoomIn` variant. ### What's Changed - [`076e1a81`](https://www.github.com/tauri-apps/tauri/commit/076e1a81a50468e3dfb34ae9ca7e77c5e1758daa)([#7119](https://www.github.com/tauri-apps/tauri/pull/7119)) Use `u32` instead of `u64` for js event listener ids - [`ff5e4dbb`](https://www.github.com/tauri-apps/tauri/commit/ff5e4dbbb01bf3fc9c5143df732c75eef6fd98cb)([#6794](https://www.github.com/tauri-apps/tauri/pull/6794)) impl `From<&WindowConfig>` for `WebviewAttributes`. ## \[0.13.0] - Added the `additional_browser_args` option when creating a window. - [3dc38b15](https://www.github.com/tauri-apps/tauri/commit/3dc38b150ea8c59c8ba67fd586f921016928f47c) feat(core): expose additional_browser_args to window config (fix: [#5757](https://www.github.com/tauri-apps/tauri/pull/5757)) ([#5799](https://www.github.com/tauri-apps/tauri/pull/5799)) on 2022-12-14 - Added the `content_protected` option when creating a window and `Window::set_content_protected` to change it at runtime. - [4ab5545b](https://www.github.com/tauri-apps/tauri/commit/4ab5545b7a831c549f3c65e74de487ede3ab7ce5) feat: add content protection api, closes [#5132](https://www.github.com/tauri-apps/tauri/pull/5132) ([#5513](https://www.github.com/tauri-apps/tauri/pull/5513)) on 2022-12-13 - Added `Builder::device_event_filter` and `App::set_device_event_filter` methods. - [73fd60ee](https://www.github.com/tauri-apps/tauri/commit/73fd60eef2b60f5dc84525ef9c315f4d80c4414f) expose set_device_event_filter in tauri ([#5562](https://www.github.com/tauri-apps/tauri/pull/5562)) on 2022-12-13 - Add `is_minimized()` window method. - [62144ef3](https://www.github.com/tauri-apps/tauri/commit/62144ef3be63b237869e511826edfb938e2c7174) feat: add is_minimized (fix [#3878](https://www.github.com/tauri-apps/tauri/pull/3878)) ([#5618](https://www.github.com/tauri-apps/tauri/pull/5618)) on 2022-12-13 - Bump minimum supported Rust version to 1.60. - [5fdc616d](https://www.github.com/tauri-apps/tauri/commit/5fdc616df9bea633810dcb814ac615911d77222c) feat: Use the zbus-backed of notify-rust ([#6332](https://www.github.com/tauri-apps/tauri/pull/6332)) on 2023-03-31 - Pin raw-window-handle to 0.5.0 to keep MSRV. - [c46c09f3](https://www.github.com/tauri-apps/tauri/commit/c46c09f31d9f5169ca8a7e62406a9ea170e3a5c5) fix(deps): pin raw-window-handle to 0.5.0 ([#6480](https://www.github.com/tauri-apps/tauri/pull/6480)) on 2023-03-17 - Added `navigation_handler` field on `PendingWindow`. - [3f35b452](https://www.github.com/tauri-apps/tauri/commit/3f35b452637ef1c794a423f1eda62a15d2ddaf42) Expose wry navigation_handler via WindowBuilder closes [#4080](https://www.github.com/tauri-apps/tauri/pull/4080) ([#5686](https://www.github.com/tauri-apps/tauri/pull/5686)) on 2022-12-27 - Add `title` getter on window. - [233e43b0](https://www.github.com/tauri-apps/tauri/commit/233e43b0c34fada1ca025378533a0b76931a6540) feat: add `title` getter on window, closes [#5023](https://www.github.com/tauri-apps/tauri/pull/5023) ([#5515](https://www.github.com/tauri-apps/tauri/pull/5515)) on 2022-12-13 - Added `TrayHandle::set_tooltip` and `SystemTray::with_tooltip`. - [2265e097](https://www.github.com/tauri-apps/tauri/commit/2265e09718f6ebfeb1d200f11e1e1e069075af6e) feat(windows): implement `with_tooltip` ([#5938](https://www.github.com/tauri-apps/tauri/pull/5938)) on 2023-01-01 - Added window's `url()` getter. - [d17027e1](https://www.github.com/tauri-apps/tauri/commit/d17027e1a0db3e8c5ae81fc4f472c5918fbce611) feat: expose url method ([#5914](https://www.github.com/tauri-apps/tauri/pull/5914)) on 2022-12-26 - On Windows, change webview theme based on Window theme for more accurate `prefers-color-scheme` support. - [7a8d570d](https://www.github.com/tauri-apps/tauri/commit/7a8d570db72667367eb24b75ddc5dd07a968f7c0) fix: sync webview theme with window theme on Windows, closes [#5802](https://www.github.com/tauri-apps/tauri/pull/5802) ([#5874](https://www.github.com/tauri-apps/tauri/pull/5874)) on 2022-12-27 ## \[0.12.2] - Block remote URLs from accessing the IPC. - [9c0593c33](https://www.github.com/tauri-apps/tauri/commit/9c0593c33af52cd9e00ec784d15f63efebdf039c) feat(core): block remote URLs from accessing the IPC on 2023-04-12 ## \[0.12.1] - Fix `allowlist > app > show/hide` always disabled when `allowlist > app > all: false`. - Bumped due to a bump in tauri-utils. - [bb251087](https://www.github.com/tauri-apps/tauri/commit/bb2510876d0bdff736d36bf3a465cdbe4ad2b90c) fix(core): extend allowlist with `app`'s allowlist, closes [#5650](https://www.github.com/tauri-apps/tauri/pull/5650) ([#5652](https://www.github.com/tauri-apps/tauri/pull/5652)) on 2022-11-18 ## \[0.12.0] - Readd the option to create an unfocused window via the `focused` method. The `focus` function has been deprecated. - [4036e15f](https://www.github.com/tauri-apps/tauri/commit/4036e15f5af933bdc0d0913508b5103958afc143) feat(core): reimplement window initial focus flag, closes [#5120](https://www.github.com/tauri-apps/tauri/pull/5120) ([#5338](https://www.github.com/tauri-apps/tauri/pull/5338)) on 2022-10-08 - Added `Runtime::show()`, `RuntimeHandle::show()`, `Runtime::hide()`, `RuntimeHandle::hide()` for hiding/showing the entire application on macOS. - [39bf895b](https://www.github.com/tauri-apps/tauri/commit/39bf895b73ec6b53f5758815396ba85dda6b9c67) feat(macOS): Add application `show` and `hide` methods ([#3689](https://www.github.com/tauri-apps/tauri/pull/3689)) on 2022-10-03 - - [7d9aa398](https://www.github.com/tauri-apps/tauri/commit/7d9aa3987efce2d697179ffc33646d086c68030c) feat: bump MSRV to 1.59 ([#5296](https://www.github.com/tauri-apps/tauri/pull/5296)) on 2022-09-28 - Added `tabbing_identifier` to the window builder on macOS. - [4137ab44](https://www.github.com/tauri-apps/tauri/commit/4137ab44a81d739556cbc7583485887e78952bf1) feat(macos): add `tabbing_identifier` option, closes [#2804](https://www.github.com/tauri-apps/tauri/pull/2804), [#3912](https://www.github.com/tauri-apps/tauri/pull/3912) ([#5399](https://www.github.com/tauri-apps/tauri/pull/5399)) on 2022-10-19 - Added methods to set the system tray title on macOS. - [8f1ace77](https://www.github.com/tauri-apps/tauri/commit/8f1ace77956ac3477826ceb059a191e55b3fff93) feat: expose `set_title` for MacOS tray ([#5182](https://www.github.com/tauri-apps/tauri/pull/5182)) on 2022-09-30 - Added the `user_agent` option when creating a window. - [a6c94119](https://www.github.com/tauri-apps/tauri/commit/a6c94119d8545d509723b147c273ca5edfe3729f) feat(core): expose user_agent to window config ([#5317](https://www.github.com/tauri-apps/tauri/pull/5317)) on 2022-10-02 ## \[0.11.2] - Block remote URLs from accessing the IPC. - [58ea0b452](https://www.github.com/tauri-apps/tauri/commit/58ea0b45268dbd46cbac0ebb0887353d057ca767) feat(core): block remote URLs from accessing the IPC on 2023-04-12 ## \[0.11.1] - Add missing allowlist config for `set_cursor_grab`, `set_cursor_visible`, `set_cursor_icon` and `set_cursor_position` APIs. - Bumped due to a bump in tauri-utils. - [c764408d](https://www.github.com/tauri-apps/tauri/commit/c764408da7fae123edd41115bda42fa75a4731d2) fix: Add missing allowlist config for cursor apis, closes [#5207](https://www.github.com/tauri-apps/tauri/pull/5207) ([#5211](https://www.github.com/tauri-apps/tauri/pull/5211)) on 2022-09-16 ## \[0.11.0] - Added APIs to create a system tray at runtime. - [4d063ae9](https://www.github.com/tauri-apps/tauri/commit/4d063ae9ee9538cd6fa5e01b80070c6edf8eaeb9) feat(core): create system tray at runtime, closes [#2278](https://www.github.com/tauri-apps/tauri/pull/2278) ([#4862](https://www.github.com/tauri-apps/tauri/pull/4862)) on 2022-08-09 - Update windows to 0.39.0 and webview2-com to 0.19.1. - [e6d9b670](https://www.github.com/tauri-apps/tauri/commit/e6d9b670b0b314ed667b0e164f2c8d27048e678f) refactor: remove unneeded focus code ([#5065](https://www.github.com/tauri-apps/tauri/pull/5065)) on 2022-09-03 ## \[0.10.3] - Block remote URLs from accessing the IPC. - [fa90214b0](https://www.github.com/tauri-apps/tauri/commit/fa90214b052b1a5d38d54fbf1ca422b4c37cfd1f) feat(core): block remote URLs from accessing the IPC on 2023-04-12 ## \[0.10.2] - Added option to disable tray menu on left click on macOS. - [f8a3becb](https://www.github.com/tauri-apps/tauri/commit/f8a3becb287942db7f7b551b5db6aeb5a2e939ee) feat(core): add option to disable tray menu on left click, closes [#4584](https://www.github.com/tauri-apps/tauri/pull/4584) ([#4587](https://www.github.com/tauri-apps/tauri/pull/4587)) on 2022-07-05 ## \[0.10.1] - Expose `platform::windows_version` function. - Bumped due to a bump in tauri-utils. - [bf764e83](https://www.github.com/tauri-apps/tauri/commit/bf764e83e01e7443e6cc54572001e1c98c357465) feat(utils): expose `windows_version` function ([#4534](https://www.github.com/tauri-apps/tauri/pull/4534)) on 2022-06-30 ## \[0.10.0] - Added `fn new` constructors for `PhysicalSize`, `LogicalSize`, `PhysicalPosition` and `LogicalPosition` and missing conversion methods. - [c7d13a1c](https://www.github.com/tauri-apps/tauri/commit/c7d13a1c60cdbe0c42834ea059321d7a3a7f01a0) feat(core): add missing methods to the dpi module ([#4393](https://www.github.com/tauri-apps/tauri/pull/4393)) on 2022-06-19 - Implement `raw_window_handle::HasRawWindowHandle` on Linux. - [3efbc67f](https://www.github.com/tauri-apps/tauri/commit/3efbc67f7469ce65a2d9ea4ff2b60b51d2a36aa5) feat: implement `raw_window_handle` on Linux ([#4469](https://www.github.com/tauri-apps/tauri/pull/4469)) on 2022-06-26 - Removed the `hwnd` and `ns_window` functions from `Dispatch` in favor of `raw_window_handle`. - [3efbc67f](https://www.github.com/tauri-apps/tauri/commit/3efbc67f7469ce65a2d9ea4ff2b60b51d2a36aa5) feat: implement `raw_window_handle` on Linux ([#4469](https://www.github.com/tauri-apps/tauri/pull/4469)) on 2022-06-26 - The theme API is now implemented on macOS 10.14+. - [6d94ce42](https://www.github.com/tauri-apps/tauri/commit/6d94ce42353204a02fe9c82ed397d349439f75ef) feat(core): theme is now implemented on macOS ([#4380](https://www.github.com/tauri-apps/tauri/pull/4380)) on 2022-06-17 ## \[0.9.0] - Upgrade to `stable`! - Bumped due to a bump in tauri-utils. - [f4bb30cc](https://www.github.com/tauri-apps/tauri/commit/f4bb30cc73d6ba9b9ef19ef004dc5e8e6bb901d3) feat(covector): prepare for v1 ([#4351](https://www.github.com/tauri-apps/tauri/pull/4351)) on 2022-06-15 ## \[0.8.1] - Add `Menu::os_default` which will create a menu filled with default menu items and submenus. - [4c4acc30](https://www.github.com/tauri-apps/tauri/commit/4c4acc3094218dd9cee0f1ad61810c979e0b41fa) feat: implement `Default` for `Menu`, closes [#2398](https://www.github.com/tauri-apps/tauri/pull/2398) ([#4291](https://www.github.com/tauri-apps/tauri/pull/4291)) on 2022-06-15 ## \[0.8.0] - Removed `TrayIcon` and renamed `WindowIcon` to `Icon`, a shared type for both icons. - [4ce8e228](https://www.github.com/tauri-apps/tauri/commit/4ce8e228134cd3f22973b74ef26ca0d165fbbbd9) refactor(core): use `Icon` for tray icons ([#4342](https://www.github.com/tauri-apps/tauri/pull/4342)) on 2022-06-14 ## \[0.7.0] - Added a config flag to bundle the media framework used by webkit2gtk `tauri.conf.json > tauri > bundle > appimage > bundleMediaFramework`. - Bumped due to a bump in tauri-utils. - [d335fae9](https://www.github.com/tauri-apps/tauri/commit/d335fae92cdcbb0ee18aad4e54558914afa3e778) feat(bundler): bundle additional gstreamer files, closes [#4092](https://www.github.com/tauri-apps/tauri/pull/4092) ([#4271](https://www.github.com/tauri-apps/tauri/pull/4271)) on 2022-06-10 ## \[0.6.0] - Update `windows-rs` to `0.37.0`, which requires Rust 1.61.0+. - [2326be39](https://www.github.com/tauri-apps/tauri/commit/2326be39821890cdd4de76e7029a531424dcb26f) feat(core): update windows-rs to 0.37.0 ([#4199](https://www.github.com/tauri-apps/tauri/pull/4199)) on 2022-05-24 ## \[0.5.1] - Fix `.mjs` not being recognised as a file extension for JavaScript files (`text/javascript`). - [45c45253](https://www.github.com/tauri-apps/tauri/commit/45c45253866ce0de317a6a547af3ea0434d4bcac) fix: add mjs mime type (fix: [#4098](https://www.github.com/tauri-apps/tauri/pull/4098)) ([#4108](https://www.github.com/tauri-apps/tauri/pull/4108)) on 2022-05-13 ## \[0.5.0] - Expose methods to access the underlying native handles of the webview. - [c82b4761](https://www.github.com/tauri-apps/tauri/commit/c82b4761e1660592472dc55308ad69d9efc5855b) feat(core): expose `with_webview` API to access the platform webview ([#4058](https://www.github.com/tauri-apps/tauri/pull/4058)) on 2022-05-04 ## \[0.4.0] - The `AboutMetadata` string setters now take `impl Into`. - [b14aa896](https://www.github.com/tauri-apps/tauri/commit/b14aa89673c3563522e5c04baf9630fa1c4739b0) feat(core): improve `AboutMetadata` setters on 2022-03-29 - \**Breaking change::* Added the `clipboard` Cargo feature. - [24e4ff20](https://www.github.com/tauri-apps/tauri/commit/24e4ff208ee0fe1a4cc5b10667ea0922ac63dfb5) refactor(core): add clipboard Cargo feature, enhancing binary size ([#3957](https://www.github.com/tauri-apps/tauri/pull/3957)) on 2022-04-24 - Expose Window cursor APIs `set_cursor_grab`, `set_cursor_visible`, `set_cursor_icon` and `set_cursor_position`. - [c54ddfe9](https://www.github.com/tauri-apps/tauri/commit/c54ddfe9338e7eb90b4d5b02dfde687d432d5bc1) feat: expose window cursor APIs, closes [#3888](https://www.github.com/tauri-apps/tauri/pull/3888) [#3890](https://www.github.com/tauri-apps/tauri/pull/3890) ([#3935](https://www.github.com/tauri-apps/tauri/pull/3935)) on 2022-04-21 - \**Breaking change::* Added the `global-shortcut` Cargo feature. - [e11878bc](https://www.github.com/tauri-apps/tauri/commit/e11878bcf7174b261a1fa146fc7d564d12e6312a) refactor(core): add global-shortcut Cargo feature, enhancing binary size ([#3956](https://www.github.com/tauri-apps/tauri/pull/3956)) on 2022-04-24 - Added `WindowEvent::ThemeChanged(theme)`. - [4cebcf6d](https://www.github.com/tauri-apps/tauri/commit/4cebcf6da7cad1953e0f01b426afac3b5ef1f81e) feat: expose theme APIs, closes [#3903](https://www.github.com/tauri-apps/tauri/pull/3903) ([#3937](https://www.github.com/tauri-apps/tauri/pull/3937)) on 2022-04-21 - Added `theme` getter on `Window`. - [4cebcf6d](https://www.github.com/tauri-apps/tauri/commit/4cebcf6da7cad1953e0f01b426afac3b5ef1f81e) feat: expose theme APIs, closes [#3903](https://www.github.com/tauri-apps/tauri/pull/3903) ([#3937](https://www.github.com/tauri-apps/tauri/pull/3937)) on 2022-04-21 - Added `theme` setter to the WindowBuilder. - [4cebcf6d](https://www.github.com/tauri-apps/tauri/commit/4cebcf6da7cad1953e0f01b426afac3b5ef1f81e) feat: expose theme APIs, closes [#3903](https://www.github.com/tauri-apps/tauri/pull/3903) ([#3937](https://www.github.com/tauri-apps/tauri/pull/3937)) on 2022-04-21 ## \[0.3.4] - Added `close_devtools` and `is_devtools_open` APIs to the `Dispatch` trait. - [e05d718a](https://www.github.com/tauri-apps/tauri/commit/e05d718a7b46476d1fe4817c169008080e84f959) feat(core): add hotkey to toggle devtools, closes [#3776](https://www.github.com/tauri-apps/tauri/pull/3776) ([#3791](https://www.github.com/tauri-apps/tauri/pull/3791)) on 2022-03-28 - **Breaking change:** The `MenuItem::About` variant is now associated with a tuple value `(String, AboutMetadata)`. - [5fb74332](https://www.github.com/tauri-apps/tauri/commit/5fb74332ab9210ac062d96b0e9afd1c942ee2911) chore(deps): update wry to 0.14, tao to 0.7 ([#3790](https://www.github.com/tauri-apps/tauri/pull/3790)) on 2022-03-28 - Support window parenting on macOS - [4e807a53](https://www.github.com/tauri-apps/tauri/commit/4e807a53e2d6d3f3cd5293d90013d5cdded5454e) Support window parenting on macOS, closes [#3751](https://www.github.com/tauri-apps/tauri/pull/3751) ([#3754](https://www.github.com/tauri-apps/tauri/pull/3754)) on 2022-03-23 - The file drop event is now part of the `WindowEvent` enum instead of a having a dedicated handler. - [07d1584c](https://www.github.com/tauri-apps/tauri/commit/07d1584cf06ea326aa45d8044bee1b77ecba5006) feat(core): add `WindowEvent::FileDrop`, closes [#3664](https://www.github.com/tauri-apps/tauri/pull/3664) ([#3686](https://www.github.com/tauri-apps/tauri/pull/3686)) on 2022-03-13 - **Breaking change:** Use the dedicated `WindowEvent` enum on `RunEvent`. - [edad9f4f](https://www.github.com/tauri-apps/tauri/commit/edad9f4f55dcc69a06cd9d6d5a5068c94ecb77dd) refactor(core): add `RunEvent::WindowEvent` ([#3793](https://www.github.com/tauri-apps/tauri/pull/3793)) on 2022-03-28 - Added `create_proxy` to the `Runtime` and `RuntimeHandle` traits. - [5d538ec2](https://www.github.com/tauri-apps/tauri/commit/5d538ec27c246274df4ff5b8057ff78b6364a43f) refactor(core): use the event loop proxy to send updater events ([#3687](https://www.github.com/tauri-apps/tauri/pull/3687)) on 2022-03-15 - Force `Error` boxed errors to be `Sync`. - [da1e8793](https://www.github.com/tauri-apps/tauri/commit/da1e879358895f7b190b1c1b20d23da23666a74b) feat(core): improve and cleanup the `Error` enum ([#3748](https://www.github.com/tauri-apps/tauri/pull/3748)) on 2022-03-22 - **Breaking change:** Move the `FileDropEvent` struct to the `window` module. - [07d1584c](https://www.github.com/tauri-apps/tauri/commit/07d1584cf06ea326aa45d8044bee1b77ecba5006) feat(core): add `WindowEvent::FileDrop`, closes [#3664](https://www.github.com/tauri-apps/tauri/pull/3664) ([#3686](https://www.github.com/tauri-apps/tauri/pull/3686)) on 2022-03-13 - Allow specifying a user event type for the event loop message. - [5d538ec2](https://www.github.com/tauri-apps/tauri/commit/5d538ec27c246274df4ff5b8057ff78b6364a43f) refactor(core): use the event loop proxy to send updater events ([#3687](https://www.github.com/tauri-apps/tauri/pull/3687)) on 2022-03-15 - Added the `WindowEvent::FileDrop` variant. - [07d1584c](https://www.github.com/tauri-apps/tauri/commit/07d1584cf06ea326aa45d8044bee1b77ecba5006) feat(core): add `WindowEvent::FileDrop`, closes [#3664](https://www.github.com/tauri-apps/tauri/pull/3664) ([#3686](https://www.github.com/tauri-apps/tauri/pull/3686)) on 2022-03-13 ## \[0.3.3] - **Breaking change:** Move `ico` and `png` parsing behind `icon-ico` and `icon-png` Cargo features. - [8c935872](https://www.github.com/tauri-apps/tauri/commit/8c9358725a17dcc2acaf4d10c3f654afdff586b0) refactor(core): move `png` and `ico` behind Cargo features ([#3588](https://www.github.com/tauri-apps/tauri/pull/3588)) on 2022-03-05 - The `PendingWindow::new` and `PendingWindow::with_config` functions now return `Result` validating the window label. - [64e00542](https://www.github.com/tauri-apps/tauri/commit/64e0054299c95f10ef5a1a9d3f914bbaeff3d73f) refactor(core): do not panic on invalid window labels,[#3544](https://www.github.com/tauri-apps/tauri/pull/3544) ([#3596](https://www.github.com/tauri-apps/tauri/pull/3596)) on 2022-03-03 ## \[0.3.2] - Fix requirements for `RuntimeHandle`, `ClipboardManager`, `GlobalShortcutHandle` and `TrayHandle`. - [84895a9c](https://www.github.com/tauri-apps/tauri/commit/84895a9cd270fc743e236d0f4d4cd6210b24a30f) fix(runtime): trait requirements ([#3489](https://www.github.com/tauri-apps/tauri/pull/3489)) on 2022-02-17 ## \[0.3.1] - Change default value for the `freezePrototype` configuration to `false`. - Bumped due to a bump in tauri-utils. - [3a4c0160](https://www.github.com/tauri-apps/tauri/commit/3a4c01606184be762adee055ddac803de0d28527) fix(core): change default `freezePrototype` to false, closes [#3416](https://www.github.com/tauri-apps/tauri/pull/3416) [#3406](https://www.github.com/tauri-apps/tauri/pull/3406) ([#3423](https://www.github.com/tauri-apps/tauri/pull/3423)) on 2022-02-12 ## \[0.3.0] - Replace `WindowBuilder`'s `has_menu` with `get_menu`. - [ac37b56e](https://www.github.com/tauri-apps/tauri/commit/ac37b56ef43c9e97039967a5fd99f0d2dccb5b5a) fix(core): menu id map not reflecting the current window menu ([#2726](https://www.github.com/tauri-apps/tauri/pull/2726)) on 2021-10-08 - The `run_return` API is now available on Linux. - [8483fde9](https://www.github.com/tauri-apps/tauri/commit/8483fde975aac8833d2ce426e42fb40aeaeecba9) feat(core): expose `run_return` on Linux ([#3352](https://www.github.com/tauri-apps/tauri/pull/3352)) on 2022-02-07 - Add `Menu::with_items` constructor, taking an iterator of `MenuEntry`. - [7cc95e10](https://www.github.com/tauri-apps/tauri/commit/7cc95e10ec66d8b155e9bb7f89cf73df56d1f107) feat(core): add `Menu::with_items`, closes [#2807](https://www.github.com/tauri-apps/tauri/pull/2807) ([#2966](https://www.github.com/tauri-apps/tauri/pull/2966)) on 2021-12-27 - Change event loop callbacks definition to allow callers to move in mutable values. - [bdbf905e](https://www.github.com/tauri-apps/tauri/commit/bdbf905e5d802b58693d2bd27582ce4269faf79c) Transformed event-loop callback to FnMut to allow mutable values ([#2667](https://www.github.com/tauri-apps/tauri/pull/2667)) on 2021-09-27 - Added `any_thread` constructor on the `Runtime` trait (only possible on Linux and Windows). - [af44bf81](https://www.github.com/tauri-apps/tauri/commit/af44bf8168310cf77fbe102a53e7c433f11641a3) feat(core): allow app run on any thread on Linux & Windows, closes [#3172](https://www.github.com/tauri-apps/tauri/pull/3172) ([#3353](https://www.github.com/tauri-apps/tauri/pull/3353)) on 2022-02-07 - Added `run_on_main_thread` API on `RuntimeHandle`. - [53fdfe52](https://www.github.com/tauri-apps/tauri/commit/53fdfe52bb30d52653c72ca9f42506c3863dcf4a) feat(core): expose `run_on_main_thread` API ([#2711](https://www.github.com/tauri-apps/tauri/pull/2711)) on 2021-10-04 - **Breaking change:** Renamed the `RPC` interface to `IPC`. - [3420aa50](https://www.github.com/tauri-apps/tauri/commit/3420aa5031b3274a95c6c5fa0f8683ca13213396) refactor: IPC handler \[TRI-019] ([#9](https://www.github.com/tauri-apps/tauri/pull/9)) on 2022-01-09 - Added `open_devtools` to the `Dispatcher` trait. - [55aa22de](https://www.github.com/tauri-apps/tauri/commit/55aa22de80c3de873e29bcffcb5b2fe236a637a6) feat(core): add `Window#open_devtools` API, closes [#1213](https://www.github.com/tauri-apps/tauri/pull/1213) ([#3350](https://www.github.com/tauri-apps/tauri/pull/3350)) on 2022-02-07 - The minimum Rust version is now `1.56`. - [a9dfc015](https://www.github.com/tauri-apps/tauri/commit/a9dfc015505afe91281c2027954ffcc588b1a59c) feat: update to edition 2021 and set minimum rust to 1.56 ([#2789](https://www.github.com/tauri-apps/tauri/pull/2789)) on 2021-10-22 - The window label is now validated and must be alphanumeric, resulting in a panic if it isn't. - [680554de](https://www.github.com/tauri-apps/tauri/commit/680554de3ef6b7fccf87c441ad355cfef7aab6fe) feat: validate window label \[TRI-021] ([#13](https://www.github.com/tauri-apps/tauri/pull/13)) on 2021-10-23 - Added `clipboard` field on the `WebviewAttributes` struct, which must be set to `true` to enable clipboard access on the webview. - [d42ccfb3](https://www.github.com/tauri-apps/tauri/commit/d42ccfb34f71851dfeb22fe74c83a8bdbddb5550) feat: add `clipboard` flag to `WebviewAttributes` \[TRI-032] ([#12](https://www.github.com/tauri-apps/tauri/pull/12)) on 2021-10-23 - Replace all of the `winapi` crate references with the `windows` crate, and replace `webview2` and `webview2-sys` with `webview2-com` and `webview2-com-sys` built with the `windows` crate. This goes along with updates to the TAO and WRY `next` branches. - [bb00d5bd](https://www.github.com/tauri-apps/tauri/commit/bb00d5bd6c9dfcb6bdd0d308dadb70e6c6aafe5c) Replace winapi with windows crate and use webview2-com instead of webview2 ([#2615](https://www.github.com/tauri-apps/tauri/pull/2615)) on 2021-09-24 - Update the `windows` crate to 0.25.0, which comes with pre-built libraries. WRY and Tao can both reference the same types directly from the `windows` crate instead of sharing bindings in `webview2-com-sys`. - [34be6cf3](https://www.github.com/tauri-apps/tauri/commit/34be6cf37a98ee7cbd66623ebddae08e5a6520fd) Update webview2-com and windows crates ([#2875](https://www.github.com/tauri-apps/tauri/pull/2875)) on 2021-11-11 ## \[0.2.1] - **Breaking change:** Removed `register_uri_scheme_protocol` from the `WebviewAttributes` struct and renamed `register_global_uri_scheme_protocol` to `register_uri_scheme_protocol` on the `Builder` struct, which now takes a `Fn(&AppHandle, &http::Request) -> http::Response` closure. - [539e4489](https://www.github.com/tauri-apps/tauri/commit/539e4489e0bac7029d86917e9982ea49e02fe489) refactor: custom protocol ([#2503](https://www.github.com/tauri-apps/tauri/pull/2503)) on 2021-08-23 - Migrate to latest custom protocol allowing `Partial content` streaming and Header parsing. - [539e4489](https://www.github.com/tauri-apps/tauri/commit/539e4489e0bac7029d86917e9982ea49e02fe489) refactor: custom protocol ([#2503](https://www.github.com/tauri-apps/tauri/pull/2503)) on 2021-08-23 ## \[0.2.0] - Fix blur/focus events being incorrect on Windows. - [d832d575](https://www.github.com/tauri-apps/tauri/commit/d832d575d9b03a0ff78accabe4631cc638c08c3b) fix(windows): use webview events on windows ([#2277](https://www.github.com/tauri-apps/tauri/pull/2277)) on 2021-07-23 - Add `ExitRequested` event that allows preventing the app from exiting when all windows are closed, and an `AppHandle.exit()` function to exit the app manually. - [892c63a0](https://www.github.com/tauri-apps/tauri/commit/892c63a0538f8d62680dce5848657128ad6b7af3) feat([#2287](https://www.github.com/tauri-apps/tauri/pull/2287)): Add `ExitRequested` event to let users prevent app from exiting ([#2293](https://www.github.com/tauri-apps/tauri/pull/2293)) on 2021-08-09 - Fixes minimum window height being used as maximum height. - [e3f99165](https://www.github.com/tauri-apps/tauri/commit/e3f9916526b226866137cb663e5cafab2b6a0e01) fix(core) minHeight being used as maxHeight ([#2247](https://www.github.com/tauri-apps/tauri/pull/2247)) on 2021-07-19 - Update gtk and its related libraries to v0.14. This also remove requirements of `clang` as build dependency. - [63ad3039](https://www.github.com/tauri-apps/tauri/commit/63ad303903bbee7c9a7382413b342e2a05d3ea75) chore(linux): bump gtk to v0.14 ([#2361](https://www.github.com/tauri-apps/tauri/pull/2361)) on 2021-08-07 - Implement `Debug` on public API structs and enums. - [fa9341ba](https://www.github.com/tauri-apps/tauri/commit/fa9341ba18ba227735341530900714dba0f27291) feat(core): implement `Debug` on public API structs/enums, closes [#2292](https://www.github.com/tauri-apps/tauri/pull/2292) ([#2387](https://www.github.com/tauri-apps/tauri/pull/2387)) on 2021-08-11 - Panic when a dispatcher getter method (`Window`, `GlobalShortcutHandle`, `ClipboardManager` and `MenuHandle` APIs) is called on the main thread. - [50ffdc06](https://www.github.com/tauri-apps/tauri/commit/50ffdc06fbde56aba32b4291fd130104935d1408) feat(core): panic when a dispatcher getter is used on the main thread ([#2455](https://www.github.com/tauri-apps/tauri/pull/2455)) on 2021-08-16 - Remove menu feature flag since there's no package dependency need to be installed on any platform anymore. - [f81ebddf](https://www.github.com/tauri-apps/tauri/commit/f81ebddfcc1aea0d4989706aef43538e8ea98bea) feat: remove menu feature flag ([#2415](https://www.github.com/tauri-apps/tauri/pull/2415)) on 2021-08-13 - Adds `Resumed` and `MainEventsCleared` variants to the `RunEvent` enum. - [6be3f433](https://www.github.com/tauri-apps/tauri/commit/6be3f4339168651fe4e003b09f7d181fd12cd5a8) feat(core): add `Resumed` and `MainEventsCleared` events, closes [#2127](https://www.github.com/tauri-apps/tauri/pull/2127) ([#2439](https://www.github.com/tauri-apps/tauri/pull/2439)) on 2021-08-15 - Adds `set_activation_policy` API to the `Runtime` trait (macOS only). - [4a031add](https://www.github.com/tauri-apps/tauri/commit/4a031add69014a1f3823f4ea19b172a2557f6794) feat(core): expose `set_activation_policy`, closes [#2258](https://www.github.com/tauri-apps/tauri/pull/2258) ([#2420](https://www.github.com/tauri-apps/tauri/pull/2420)) on 2021-08-13 - Allow creation of empty Window with `create_tao_window()` and management with `send_tao_window_event()` on the AppHandler. - [88080855](https://www.github.com/tauri-apps/tauri/commit/8808085541a629b8e22b612a06cef01cf9b3722e) feat(window): Allow creation of Window without `wry` ([#2321](https://www.github.com/tauri-apps/tauri/pull/2321)) on 2021-07-29 - [15566cfd](https://www.github.com/tauri-apps/tauri/commit/15566cfd64f5072fa4980a6ce5b33259958e9021) feat(core): add API to send wry window message to the event loop ([#2339](https://www.github.com/tauri-apps/tauri/pull/2339)) on 2021-08-02 - - Support [macOS tray icon template](https://developer.apple.com/documentation/appkit/nsimage/1520017-template?language=objc) to adjust automatically based on taskbar color. - Images you mark as template images should consist of only black and clear colors. You can use the alpha channel in the image to adjust the opacity of black content, however. - [426a6b49](https://www.github.com/tauri-apps/tauri/commit/426a6b49962de8faf061db2e820ac10fcbb300d6) feat(macOS): Implement tray icon template ([#2322](https://www.github.com/tauri-apps/tauri/pull/2322)) on 2021-07-29 - Add `Event::Ready` on the `run()` callback. Triggered once when the event loop is ready. - [28c6b7ad](https://www.github.com/tauri-apps/tauri/commit/28c6b7adfe98e701b158e936eafb7541ddc700e0) feat: add `Event::Ready` ([#2433](https://www.github.com/tauri-apps/tauri/pull/2433)) on 2021-08-15 ## \[0.1.4] - Allow preventing window close when the user requests it. - [8157a68a](https://www.github.com/tauri-apps/tauri/commit/8157a68af1d94de1b90a14aa44139bb123b3436b) feat(core): allow listening to event loop events & prevent window close ([#2131](https://www.github.com/tauri-apps/tauri/pull/2131)) on 2021-07-06 - Expose `gtk_window` getter. - [e0a8e09c](https://www.github.com/tauri-apps/tauri/commit/e0a8e09cab6799eeb9ec524b5f7780d1e5a84299) feat(core): expose `gtk_window`, closes [#2083](https://www.github.com/tauri-apps/tauri/pull/2083) ([#2141](https://www.github.com/tauri-apps/tauri/pull/2141)) on 2021-07-02 - `Params` has been removed, along with all the associated types on it. Functions that previously accepted those associated types now accept strings instead. Type that used a generic parameter `Params` now use `Runtime` instead. If you use the `wry` feature, then types with a `Runtime` generic parameter should default to `Wry`, letting you omit the explicit type and let the compiler infer it instead. `tauri`: - See `Params` note - If you were using `Params` inside a function parameter or definition, all references to it have been replaced with a simple runtime that defaults to `Wry`. If you are not using a custom runtime, just remove `Params` from the definition of functions/items that previously took it. If you are using a custom runtime, you *may* need to pass the runtime type to these functions. - If you were using custom types for `Params` (uncommon and if you don't understand you probably were not using it), all methods that were previously taking the custom type now takes an `Into` or a `&str`. The types were already required to be string-able, so just make sure to convert it into a string before passing it in if this breaking change affects you. `tauri-macros`: - (internal) Added private `default_runtime` proc macro to allow us to give item definitions a custom runtime only when the specified feature is enabled. `tauri-runtime`: - See `Params` note - Removed `Params`, `MenuId`, `Tag`, `TagRef`. - Added `menu::{MenuHash, MenuId, MenuIdRef}` as type aliases for the internal type that menu types now use. - All previous menu items that had a `MenuId` generic now use the underlying `MenuId` type without a generic. - `Runtime`, `RuntimeHandle`, and `Dispatch` have no more generic parameter on `create_window(...)` and instead use the `Runtime` type directly - `Runtime::system_tray` has no more `MenuId` generic and uses the string based `SystemTray` type directly. - (internal) `CustomMenuItem::id_value()` is now hashed on creation and exposed as the `id` field with type `MenuHash`. `tauri-runtime-wry`: - See `Params` note - update menu and runtime related types to the ones changed in `tauri-runtime`. `tauri-utils`: - `Assets::get` signature has changed to take a `&AssetKey` instead of `impl Into` to become trait object safe. - [fd8fab50](https://www.github.com/tauri-apps/tauri/commit/fd8fab507c8fa1b113b841af14c6693eb3955f6b) refactor(core): remove `Params` and replace with strings ([#2191](https://www.github.com/tauri-apps/tauri/pull/2191)) on 2021-07-15 ## \[0.1.3] - `Window` is now `Send + Sync` on Windows. - [fe32afcc](https://www.github.com/tauri-apps/tauri/commit/fe32afcc933920d6282ae1d63b041b182278a031) fix(core): `Window` must be `Send + Sync` on Windows, closes [#2078](https://www.github.com/tauri-apps/tauri/pull/2078) ([#2093](https://www.github.com/tauri-apps/tauri/pull/2093)) on 2021-06-27 ## \[0.1.2] - Adds `clipboard` APIs (write and read text). - [285bf64b](https://www.github.com/tauri-apps/tauri/commit/285bf64bf9569efb2df904c69c6df405ff0d62e2) feat(core): add clipboard writeText and readText APIs ([#2035](https://www.github.com/tauri-apps/tauri/pull/2035)) on 2021-06-21 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Adds `focus` API to the WindowBuilder. - [5f351622](https://www.github.com/tauri-apps/tauri/commit/5f351622c7812ad1bb56ddb37364ccaa4124c24b) feat(core): add focus API to the WindowBuilder and WindowOptions, [#1737](https://www.github.com/tauri-apps/tauri/pull/1737) on 2021-05-30 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Adds `is_decorated` getter on Window. - [f58a2114](https://www.github.com/tauri-apps/tauri/commit/f58a2114fbfd5307c349f05c88f2e08fd8baa8aa) feat(core): add `is_decorated` Window getter on 2021-05-30 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Adds `is_resizable` getter on Window. - [1e8af280](https://www.github.com/tauri-apps/tauri/commit/1e8af280c27f381828d6209722b10e889082fa00) feat(core): add `is_resizable` Window getter on 2021-05-30 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Adds `is_visible` getter on Window. - [36506c96](https://www.github.com/tauri-apps/tauri/commit/36506c967de82bc7ff453d11e6104ecf66d7a588) feat(core): add `is_visible` API on 2021-05-30 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Adds `accelerator` method to the `CustomMenuItem` struct to define a keyboard shortcut for the menu item. - [034c2601](https://www.github.com/tauri-apps/tauri/commit/034c26013bce0c7bbe6db067ea7fd24a53a5c998) feat(core): add `accelerator` method to `CustomMenuItem` ([#2043](https://www.github.com/tauri-apps/tauri/pull/2043)) on 2021-06-22 - Adds global shortcut interfaces. - [3280c4aa](https://www.github.com/tauri-apps/tauri/commit/3280c4aa91e50a8ccdd561a8b48a12a4a13ea8d5) refactor(core): global shortcut is now provided by `tao` ([#2031](https://www.github.com/tauri-apps/tauri/pull/2031)) on 2021-06-21 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Adds `request_user_attention` API to the `Dispatcher` trait. - [7dcca6e9](https://www.github.com/tauri-apps/tauri/commit/7dcca6e9281182b11ad3d4a79871f09b30b9b419) feat(core): add `request_user_attention` API, closes [#2023](https://www.github.com/tauri-apps/tauri/pull/2023) ([#2026](https://www.github.com/tauri-apps/tauri/pull/2026)) on 2021-06-20 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Adds `fn run_iteration` (macOS and Windows only) to the Runtime trait. - [8c0d0739](https://www.github.com/tauri-apps/tauri/commit/8c0d0739eebf7286b64a5380e922746411eb52c6) feat(core): add `run_iteration`, `parent_window` and `owner_window` APIs, closes [#1872](https://www.github.com/tauri-apps/tauri/pull/1872) ([#1874](https://www.github.com/tauri-apps/tauri/pull/1874)) on 2021-05-21 - Adds `show_menu`, `hide_menu` and `is_menu_visible` APIs to the `Dispatcher` trait. - [954460c5](https://www.github.com/tauri-apps/tauri/commit/954460c5205d57444ef4b1412051fbedf3e38676) feat(core): MenuHandle `show`, `hide`, `is_visible` and `toggle` APIs ([#1958](https://www.github.com/tauri-apps/tauri/pull/1958)) on 2021-06-15 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Adds `set_focus` API on Window. - [bb6992f8](https://www.github.com/tauri-apps/tauri/commit/bb6992f888196ca7c87bb2fe74ad2bd8bf393e05) feat(core): add `set_focus` window API, fixes [#1737](https://www.github.com/tauri-apps/tauri/pull/1737) on 2021-05-30 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Adds `set_skip_taskbar` API on Window. - [e06aa277](https://www.github.com/tauri-apps/tauri/commit/e06aa277384450cfef617c0e57b0d5d403bb1e7f) feat(core): add `set_skip_taskbar` API on 2021-05-30 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Adds `skip_taskbar` API to the WindowBuilder. - [5525b03a](https://www.github.com/tauri-apps/tauri/commit/5525b03a78a2232c650043fbd9894ce1553cad41) feat(core): add `skip_taskbar` API to the WindowBuilder/WindowOptions on 2021-05-30 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Adds `Window#center` and `WindowBuilder#center` APIs. - [5cba6eb4](https://www.github.com/tauri-apps/tauri/commit/5cba6eb4d28d53f06855d60d4d0eae6b95233ccf) feat(core): add window `center` API, closes [#1822](https://www.github.com/tauri-apps/tauri/pull/1822) ([#1954](https://www.github.com/tauri-apps/tauri/pull/1954)) on 2021-06-05 - Adds `parent_window` and `owner_window` setters to the `WindowBuilder` (Windows only). - [8c0d0739](https://www.github.com/tauri-apps/tauri/commit/8c0d0739eebf7286b64a5380e922746411eb52c6) feat(core): add `run_iteration`, `parent_window` and `owner_window` APIs, closes [#1872](https://www.github.com/tauri-apps/tauri/pull/1872) ([#1874](https://www.github.com/tauri-apps/tauri/pull/1874)) on 2021-05-21 - Adds window native handle getter (HWND on Windows). - [abf78c58](https://www.github.com/tauri-apps/tauri/commit/abf78c5860cdc52fbfd2bc5dbca29a864e2da8f9) fix(core): set parent window handle on dialogs, closes [#1876](https://www.github.com/tauri-apps/tauri/pull/1876) ([#1889](https://www.github.com/tauri-apps/tauri/pull/1889)) on 2021-05-21 ## \[0.1.1] - Fixes `system-tray` feature usage. - [1ab8dd9](https://www.github.com/tauri-apps/tauri/commit/1ab8dd93e670d2a2d070c7a6ec48308a0ab32f1a) fix(core): `system-tray` cargo feature usage, fixes [#1798](https://www.github.com/tauri-apps/tauri/pull/1798) ([#1801](https://www.github.com/tauri-apps/tauri/pull/1801)) on 2021-05-12 ## \[0.1.0] - **Breaking:** `Context` fields are now private, and is expected to be created through `Context::new(...)`. All fields previously available through `Context` are now public methods. - [5542359](https://www.github.com/tauri-apps/tauri/commit/55423590ddbf560684dab6a0214acf95aadfa8d2) refactor(core): Context fields now private, Icon used on all platforms ([#1774](https://www.github.com/tauri-apps/tauri/pull/1774)) on 2021-05-11 - `tauri-runtime` crate initial release. - [665ec1d](https://www.github.com/tauri-apps/tauri/commit/665ec1d4a199ad06e369221da187dc838da71cbf) refactor: move runtime to `tauri-runtime` crate ([#1751](https://www.github.com/tauri-apps/tauri/pull/1751)) on 2021-05-09 - [45a7a11](https://www.github.com/tauri-apps/tauri/commit/45a7a111e0cf9d9956d713cc9a99fa7a5313eec7) feat(core): add `tauri-wry` crate ([#1756](https://www.github.com/tauri-apps/tauri/pull/1756)) on 2021-05-09 ================================================ FILE: crates/tauri-runtime/Cargo.toml ================================================ [package] name = "tauri-runtime" version = "2.10.1" description = "Runtime for Tauri applications" exclude = ["CHANGELOG.md", "/target"] readme = "README.md" authors.workspace = true homepage.workspace = true repository.workspace = true categories.workspace = true license.workspace = true edition.workspace = true rust-version.workspace = true [package.metadata.docs.rs] all-features = true default-target = "x86_64-unknown-linux-gnu" targets = [ "x86_64-pc-windows-msvc", "x86_64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-linux-android", "x86_64-apple-ios", ] [dependencies] serde = { version = "1", features = ["derive"] } serde_json = "1" thiserror = "2" tauri-utils = { version = "2.8.3", path = "../tauri-utils" } http = "1" raw-window-handle = "0.6" url = { version = "2" } dpi = { version = "0.1", features = ["serde"] } # WARNING: cookie::Cookie is re-exported so bumping this is a breaking change, documented to be done as a minor bump cookie = "0.18" [target."cfg(windows)".dependencies.windows] version = "0.61" features = ["Win32_Foundation", "Win32_System_WinRT"] [target."cfg(windows)".dependencies] webview2-com = "0.38" [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"] } webkit2gtk = { version = "=2.0", features = ["v2_40"] } [target."cfg(target_os = \"android\")".dependencies] jni = "0.21" [target.'cfg(all(target_vendor = "apple", not(target_os = "macos")))'.dependencies] objc2 = "0.6" objc2-ui-kit = { version = "0.3.0", default-features = false, features = [ "UIView", "UIResponder", ] } [target."cfg(target_os = \"macos\")".dependencies] url = "2" objc2 = "0.6" objc2-web-kit = { version = "0.3", default-features = false, features = [ "objc2-app-kit", "WKWebView", "WKWebViewConfiguration", ] } [features] devtools = [] macos-private-api = [] ================================================ FILE: crates/tauri-runtime/LICENSE_APACHE-2.0 ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS ================================================ FILE: crates/tauri-runtime/LICENSE_MIT ================================================ MIT License Copyright (c) 2017 - Present Tauri Apps Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: crates/tauri-runtime/README.md ================================================ # tauri-runtime [![status](https://img.shields.io/badge/Status-Beta-green.svg)](https://github.com/tauri-apps/tauri) [![Chat Server](https://img.shields.io/badge/chat-on%20discord-7289da.svg)](https://discord.gg/SpmNs4S) [![test core](https://img.shields.io/github/actions/workflow/status/tauri-apps/tauri/test-core.yml?label=test%20core&logo=github)](https://github.com/tauri-apps/tauri/actions/workflows/test-core.yml) [![website](https://img.shields.io/badge/website-tauri.app-purple.svg)](https://tauri.app) [![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-Opencollective-blue.svg)](https://opencollective.com/tauri) | Component | Version | | ------------- | -------------------------------------------------------------------------------------------------------------- | | tauri-runtime | [![](https://img.shields.io/crates/v/tauri-runtime?style=flat-square)](https://crates.io/crates/tauri-runtime) | ## About Tauri Tauri is a polyglot and generic system that is very composable and allows engineers to make a wide variety of applications. It is used for building applications for Desktop Computers using a combination of Rust tools and HTML rendered in a Webview. Apps built with Tauri can ship with any number of pieces of an optional JS API / Rust API so that webviews can control the system via message passing. In fact, developers can extend the default API with their own functionality and bridge the Webview and Rust-based backend easily. Tauri apps can have custom menus and have tray-type interfaces. They can be updated, and are managed by the user's operating system as expected. They are very small, because they use the system's webview. They do not ship a runtime, since the final binary is compiled from rust. This makes the reversing of Tauri apps not a trivial task. ## This module This is the glue layer between tauri itself and lower level webview libraries. None of the exposed API of this crate is stable, and it may break semver compatibility in the future. The major version only signifies the intended Tauri version. To learn more about the details of how all of these pieces fit together, please consult this [ARCHITECTURE.md](https://github.com/tauri-apps/tauri/blob/dev/ARCHITECTURE.md) document. ## Semver **tauri** is following [Semantic Versioning 2.0](https://semver.org/). ## Licenses Code: (c) 2021 - The Tauri Programme within The Commons Conservancy. MIT or MIT/Apache 2.0 where applicable. Logo: CC-BY-NC-ND - Original Tauri Logo Designs by [Daniel Thompson-Yvetot](https://github.com/nothingismagick) and [Guillaume Chau](https://github.com/akryum) ================================================ FILE: crates/tauri-runtime/build.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT // creates a cfg alias if `has_feature` is true. // `alias` must be a snake case string. fn alias(alias: &str, has_feature: bool) { println!("cargo:rustc-check-cfg=cfg({alias})"); if has_feature { println!("cargo:rustc-cfg={alias}"); } } fn main() { let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap(); let mobile = target_os == "ios" || target_os == "android"; alias("desktop", !mobile); alias("mobile", mobile); } ================================================ FILE: crates/tauri-runtime/src/dpi.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT pub use dpi::*; use serde::Serialize; /// A rectangular region. #[derive(Clone, Copy, Debug, Serialize)] pub struct Rect { /// Rect position. pub position: dpi::Position, /// Rect size. pub size: dpi::Size, } impl Default for Rect { fn default() -> Self { Self { position: Position::Logical((0, 0).into()), size: Size::Logical((0, 0).into()), } } } /// A rectangular region in physical pixels. #[derive(Clone, Copy, Debug, Serialize)] pub struct PhysicalRect { /// Rect position. pub position: dpi::PhysicalPosition

, /// Rect size. pub size: dpi::PhysicalSize, } impl Default for PhysicalRect { fn default() -> Self { Self { position: (0, 0).into(), size: (0, 0).into(), } } } /// A rectangular region in logical pixels. #[derive(Clone, Copy, Debug, Serialize)] pub struct LogicalRect { /// Rect position. pub position: dpi::LogicalPosition

, /// Rect size. pub size: dpi::LogicalSize, } impl Default for LogicalRect { fn default() -> Self { Self { position: (0, 0).into(), size: (0, 0).into(), } } } ================================================ FILE: crates/tauri-runtime/src/lib.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT //! Internal runtime between Tauri and the underlying webview runtime. //! //! None of the exposed API of this crate is stable, and it may break semver //! compatibility in the future. The major version only signifies the intended Tauri version. #![doc( html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png", html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png" )] #![cfg_attr(docsrs, feature(doc_cfg))] use raw_window_handle::DisplayHandle; use serde::Deserialize; use std::{borrow::Cow, fmt::Debug, sync::mpsc::Sender}; use tauri_utils::config::Color; use tauri_utils::Theme; use url::Url; use webview::{DetachedWebview, PendingWebview}; /// UI scaling utilities. pub mod dpi; /// Types useful for interacting with a user's monitors. pub mod monitor; pub mod webview; pub mod window; use dpi::{PhysicalPosition, PhysicalSize, Position, Rect, Size}; use monitor::Monitor; use window::{ CursorIcon, DetachedWindow, PendingWindow, RawWindow, WebviewEvent, WindowEvent, WindowSizeConstraints, }; use window::{WindowBuilder, WindowId}; use http::{ header::{InvalidHeaderName, InvalidHeaderValue}, method::InvalidMethod, status::InvalidStatusCode, }; /// Cookie extraction pub use cookie::Cookie; pub type WindowEventId = u32; pub type WebviewEventId = u32; /// Progress bar status. #[derive(Debug, Clone, Copy, Deserialize)] #[serde(rename_all = "camelCase")] pub enum ProgressBarStatus { /// Hide progress bar. None, /// Normal state. Normal, /// Indeterminate state. **Treated as Normal on Linux and macOS** Indeterminate, /// Paused state. **Treated as Normal on Linux** Paused, /// Error state. **Treated as Normal on Linux** Error, } /// Progress Bar State #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ProgressBarState { /// The progress bar status. pub status: Option, /// The progress bar progress. This can be a value ranging from `0` to `100` pub progress: Option, /// The `.desktop` filename with the Unity desktop window manager, for example `myapp.desktop` **Linux Only** pub desktop_filename: Option, } /// Type of user attention requested on a window. #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)] #[serde(tag = "type")] pub enum UserAttentionType { /// ## Platform-specific /// - **macOS:** Bounces the dock icon until the application is in focus. /// - **Windows:** Flashes both the window and the taskbar button until the application is in focus. Critical, /// ## Platform-specific /// - **macOS:** Bounces the dock icon once. /// - **Windows:** Flashes the taskbar button until the application is in focus. Informational, } #[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Deserialize)] #[serde(tag = "type")] pub enum DeviceEventFilter { /// Always filter out device events. Always, /// Filter out device events while the window is not focused. #[default] Unfocused, /// Report all device events regardless of window focus. Never, } /// Defines the orientation that a window resize will be performed. #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)] pub enum ResizeDirection { East, North, NorthEast, NorthWest, South, SouthEast, SouthWest, West, } #[derive(Debug, thiserror::Error)] #[non_exhaustive] pub enum Error { /// Failed to create webview. #[error("failed to create webview: {0}")] CreateWebview(Box), // TODO: Make it take an error like `CreateWebview` in v3 /// Failed to create window. #[error("failed to create window")] CreateWindow, /// The given window label is invalid. #[error("Window labels must only include alphanumeric characters, `-`, `/`, `:` and `_`.")] InvalidWindowLabel, /// Failed to send message to webview. #[error("failed to send message to the webview")] FailedToSendMessage, /// Failed to receive message from webview. #[error("failed to receive message from webview")] FailedToReceiveMessage, /// Failed to serialize/deserialize. #[error("JSON error: {0}")] Json(#[from] serde_json::Error), /// Failed to load window icon. #[error("invalid icon: {0}")] InvalidIcon(Box), /// Failed to get monitor on window operation. #[error("failed to get monitor")] FailedToGetMonitor, /// Failed to get cursor position. #[error("failed to get cursor position")] FailedToGetCursorPosition, #[error("Invalid header name: {0}")] InvalidHeaderName(#[from] InvalidHeaderName), #[error("Invalid header value: {0}")] InvalidHeaderValue(#[from] InvalidHeaderValue), #[error("Invalid status code: {0}")] InvalidStatusCode(#[from] InvalidStatusCode), #[error("Invalid method: {0}")] InvalidMethod(#[from] InvalidMethod), #[error("Infallible error, something went really wrong: {0}")] Infallible(#[from] std::convert::Infallible), #[error("the event loop has been closed")] EventLoopClosed, #[error("Invalid proxy url")] InvalidProxyUrl, #[error("window not found")] WindowNotFound, #[cfg(any(target_os = "macos", target_os = "ios"))] #[error("failed to remove data store")] FailedToRemoveDataStore, #[error("Could not find the webview runtime, make sure it is installed")] WebviewRuntimeNotInstalled, } /// Result type. pub type Result = std::result::Result; /// Window icon. #[derive(Debug, Clone)] pub struct Icon<'a> { /// RGBA bytes of the icon. pub rgba: Cow<'a, [u8]>, /// Icon width. pub width: u32, /// Icon height. pub height: u32, } /// A type that can be used as an user event. pub trait UserEvent: Debug + Clone + Send + 'static {} impl UserEvent for T {} /// Event triggered on the event loop run. #[derive(Debug)] #[non_exhaustive] pub enum RunEvent { /// Event loop is exiting. Exit, /// Event loop is about to exit ExitRequested { /// The exit code. code: Option, tx: Sender, }, /// An event associated with a window. WindowEvent { /// The window label. label: String, /// The detailed event. event: WindowEvent, }, /// An event associated with a webview. WebviewEvent { /// The webview label. label: String, /// The detailed event. event: WebviewEvent, }, /// Application ready. Ready, /// Sent if the event loop is being resumed. Resumed, /// Emitted when all of the event loop's input events have been processed and redraw processing is about to begin. /// /// This event is useful as a place to put your code that should be run after all state-changing events have been handled and you want to do stuff (updating state, performing calculations, etc) that happens as the "main body" of your event loop. MainEventsCleared, /// Emitted when the user wants to open the specified resource with the app. #[cfg(any(target_os = "macos", target_os = "ios"))] Opened { urls: Vec }, /// Emitted when the NSApplicationDelegate's applicationShouldHandleReopen gets called #[cfg(target_os = "macos")] Reopen { /// Indicates whether the NSApplication object found any visible windows in your application. has_visible_windows: bool, }, /// A custom event defined by the user. UserEvent(T), } /// Action to take when the event loop is about to exit #[derive(Debug)] pub enum ExitRequestedEventAction { /// Prevent the event loop from exiting Prevent, } /// Application's activation policy. Corresponds to NSApplicationActivationPolicy. #[cfg(target_os = "macos")] #[cfg_attr(docsrs, doc(cfg(target_os = "macos")))] #[non_exhaustive] pub enum ActivationPolicy { /// Corresponds to NSApplicationActivationPolicyRegular. Regular, /// Corresponds to NSApplicationActivationPolicyAccessory. Accessory, /// Corresponds to NSApplicationActivationPolicyProhibited. Prohibited, } /// A [`Send`] handle to the runtime. pub trait RuntimeHandle: Debug + Clone + Send + Sync + Sized + 'static { type Runtime: Runtime; /// Creates an `EventLoopProxy` that can be used to dispatch user events to the main event loop. fn create_proxy(&self) -> >::EventLoopProxy; /// Sets the activation policy for the application. #[cfg(target_os = "macos")] #[cfg_attr(docsrs, doc(cfg(target_os = "macos")))] fn set_activation_policy(&self, activation_policy: ActivationPolicy) -> Result<()>; /// Sets the dock visibility for the application. #[cfg(target_os = "macos")] #[cfg_attr(docsrs, doc(cfg(target_os = "macos")))] fn set_dock_visibility(&self, visible: bool) -> Result<()>; /// Requests an exit of the event loop. fn request_exit(&self, code: i32) -> Result<()>; /// Create a new window. fn create_window( &self, pending: PendingWindow, after_window_creation: Option, ) -> Result>; /// Create a new webview. fn create_webview( &self, window_id: WindowId, pending: PendingWebview, ) -> Result>; /// Run a task on the main thread. fn run_on_main_thread(&self, f: F) -> Result<()>; /// Get a handle to the display controller of the windowing system. fn display_handle( &self, ) -> std::result::Result, raw_window_handle::HandleError>; /// Returns the primary monitor of the system. /// /// Returns None if it can't identify any monitor as a primary one. fn primary_monitor(&self) -> Option; /// Returns the monitor that contains the given point. fn monitor_from_point(&self, x: f64, y: f64) -> Option; /// Returns the list of all the monitors available on the system. fn available_monitors(&self) -> Vec; /// Get the cursor position relative to the top-left hand corner of the desktop. fn cursor_position(&self) -> Result>; /// Sets the app theme. fn set_theme(&self, theme: Option); /// Shows the application, but does not automatically focus it. #[cfg(target_os = "macos")] #[cfg_attr(docsrs, doc(cfg(target_os = "macos")))] fn show(&self) -> Result<()>; /// Hides the application. #[cfg(target_os = "macos")] #[cfg_attr(docsrs, doc(cfg(target_os = "macos")))] fn hide(&self) -> Result<()>; /// Change the device event filter mode. /// /// See [Runtime::set_device_event_filter] for details. /// /// ## Platform-specific /// /// See [Runtime::set_device_event_filter] for details. fn set_device_event_filter(&self, filter: DeviceEventFilter); /// Finds an Android class in the project scope. #[cfg(target_os = "android")] fn find_class<'a>( &self, env: &mut jni::JNIEnv<'a>, activity: &jni::objects::JObject<'_>, name: impl Into, ) -> std::result::Result, jni::errors::Error>; /// Dispatch a closure to run on the Android context. /// /// The closure takes the JNI env, the Android activity instance and the possibly null webview. #[cfg(target_os = "android")] fn run_on_android_context(&self, f: F) where F: FnOnce(&mut jni::JNIEnv, &jni::objects::JObject, &jni::objects::JObject) + Send + 'static; #[cfg(any(target_os = "macos", target_os = "ios"))] #[cfg_attr(docsrs, doc(cfg(any(target_os = "macos", target_os = "ios"))))] fn fetch_data_store_identifiers) + Send + 'static>( &self, cb: F, ) -> Result<()>; #[cfg(any(target_os = "macos", target_os = "ios"))] #[cfg_attr(docsrs, doc(cfg(any(target_os = "macos", target_os = "ios"))))] fn remove_data_store) + Send + 'static>( &self, uuid: [u8; 16], cb: F, ) -> Result<()>; } pub trait EventLoopProxy: Debug + Clone + Send + Sync { fn send_event(&self, event: T) -> Result<()>; } #[derive(Default)] pub struct RuntimeInitArgs { #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] pub app_id: Option, #[cfg(windows)] pub msg_hook: Option bool + 'static>>, } /// The webview runtime interface. pub trait Runtime: Debug + Sized + 'static { /// The window message dispatcher. type WindowDispatcher: WindowDispatch; /// The webview message dispatcher. type WebviewDispatcher: WebviewDispatch; /// The runtime handle type. type Handle: RuntimeHandle; /// The proxy type. type EventLoopProxy: EventLoopProxy; /// Creates a new webview runtime. Must be used on the main thread. fn new(args: RuntimeInitArgs) -> Result; /// Creates a new webview runtime on any thread. #[cfg(any( windows, target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] #[cfg_attr( docsrs, doc(cfg(any( windows, target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))) )] fn new_any_thread(args: RuntimeInitArgs) -> Result; /// Creates an `EventLoopProxy` that can be used to dispatch user events to the main event loop. fn create_proxy(&self) -> Self::EventLoopProxy; /// Gets a runtime handle. fn handle(&self) -> Self::Handle; /// Create a new window. fn create_window( &self, pending: PendingWindow, after_window_creation: Option, ) -> Result>; /// Create a new webview. fn create_webview( &self, window_id: WindowId, pending: PendingWebview, ) -> Result>; /// Returns the primary monitor of the system. /// /// Returns None if it can't identify any monitor as a primary one. fn primary_monitor(&self) -> Option; /// Returns the monitor that contains the given point. fn monitor_from_point(&self, x: f64, y: f64) -> Option; /// Returns the list of all the monitors available on the system. fn available_monitors(&self) -> Vec; /// Get the cursor position relative to the top-left hand corner of the desktop. fn cursor_position(&self) -> Result>; /// Sets the app theme. fn set_theme(&self, theme: Option); /// Sets the activation policy for the application. #[cfg(target_os = "macos")] #[cfg_attr(docsrs, doc(cfg(target_os = "macos")))] fn set_activation_policy(&mut self, activation_policy: ActivationPolicy); /// Sets the dock visibility for the application. #[cfg(target_os = "macos")] #[cfg_attr(docsrs, doc(cfg(target_os = "macos")))] fn set_dock_visibility(&mut self, visible: bool); /// Shows the application, but does not automatically focus it. #[cfg(target_os = "macos")] #[cfg_attr(docsrs, doc(cfg(target_os = "macos")))] fn show(&self); /// Hides the application. #[cfg(target_os = "macos")] #[cfg_attr(docsrs, doc(cfg(target_os = "macos")))] fn hide(&self); /// Change the device event filter mode. /// /// Since the DeviceEvent capture can lead to high CPU usage for unfocused windows, [`tao`] /// will ignore them by default for unfocused windows on Windows. This method allows changing /// the filter to explicitly capture them again. /// /// ## Platform-specific /// /// - ** Linux / macOS / iOS / Android**: Unsupported. /// /// [`tao`]: https://crates.io/crates/tao fn set_device_event_filter(&mut self, filter: DeviceEventFilter); /// Runs an iteration of the runtime event loop and returns control flow to the caller. #[cfg(desktop)] fn run_iteration) + 'static>(&mut self, callback: F); /// Equivalent to [`Runtime::run`] but returns the exit code instead of exiting the process. fn run_return) + 'static>(self, callback: F) -> i32; /// Run the webview runtime. fn run) + 'static>(self, callback: F); } /// Webview dispatcher. A thread-safe handle to the webview APIs. pub trait WebviewDispatch: Debug + Clone + Send + Sync + Sized + 'static { /// The runtime this [`WebviewDispatch`] runs under. type Runtime: Runtime; /// Run a task on the main thread. fn run_on_main_thread(&self, f: F) -> Result<()>; /// Registers a webview event handler. fn on_webview_event(&self, f: F) -> WebviewEventId; /// Runs a closure with the platform webview object as argument. fn with_webview) + Send + 'static>(&self, f: F) -> Result<()>; /// Open the web inspector which is usually called devtools. #[cfg(any(debug_assertions, feature = "devtools"))] fn open_devtools(&self); /// Close the web inspector which is usually called devtools. #[cfg(any(debug_assertions, feature = "devtools"))] fn close_devtools(&self); /// Gets the devtools window's current open state. #[cfg(any(debug_assertions, feature = "devtools"))] fn is_devtools_open(&self) -> Result; // GETTERS /// Returns the webview's current URL. fn url(&self) -> Result; /// Returns the webview's bounds. fn bounds(&self) -> Result; /// Returns the position of the top-left hand corner of the webviews's client area relative to the top-left hand corner of the window. fn position(&self) -> Result>; /// Returns the physical size of the webviews's client area. fn size(&self) -> Result>; // SETTER /// Navigate to the given URL. fn navigate(&self, url: Url) -> Result<()>; /// Reloads the current page. fn reload(&self) -> Result<()>; /// Opens the dialog to prints the contents of the webview. fn print(&self) -> Result<()>; /// Closes the webview. fn close(&self) -> Result<()>; /// Sets the webview's bounds. fn set_bounds(&self, bounds: Rect) -> Result<()>; /// Resizes the webview. fn set_size(&self, size: Size) -> Result<()>; /// Updates the webview position. fn set_position(&self, position: Position) -> Result<()>; /// Bring the window to front and focus the webview. fn set_focus(&self) -> Result<()>; /// Hide the webview fn hide(&self) -> Result<()>; /// Show the webview fn show(&self) -> Result<()>; /// Executes javascript on the window this [`WindowDispatch`] represents. fn eval_script>(&self, script: S) -> Result<()>; /// Moves the webview to the given window. fn reparent(&self, window_id: WindowId) -> Result<()>; /// Get cookies for a particular url. /// /// # Stability /// /// See [WebviewDispatch::cookies]. fn cookies_for_url(&self, url: Url) -> Result>>; /// Return all cookies in the cookie store. /// /// # Stability /// /// The return value of this function leverages [`cookie::Cookie`] which re-exports the cookie crate. /// This dependency might receive updates in minor Tauri releases. fn cookies(&self) -> Result>>; /// Set a cookie for the webview. /// /// # Stability /// /// See [WebviewDispatch::cookies]. fn set_cookie(&self, cookie: cookie::Cookie<'_>) -> Result<()>; /// Delete a cookie for the webview. /// /// # Stability /// /// See [WebviewDispatch::cookies]. fn delete_cookie(&self, cookie: cookie::Cookie<'_>) -> Result<()>; /// Sets whether the webview should automatically grow and shrink its size and position when the parent window resizes. fn set_auto_resize(&self, auto_resize: bool) -> Result<()>; /// Set the webview zoom level fn set_zoom(&self, scale_factor: f64) -> Result<()>; /// Set the webview background. fn set_background_color(&self, color: Option) -> Result<()>; /// Clear all browsing data for this webview. fn clear_all_browsing_data(&self) -> Result<()>; } /// Window dispatcher. A thread-safe handle to the window APIs. pub trait WindowDispatch: Debug + Clone + Send + Sync + Sized + 'static { /// The runtime this [`WindowDispatch`] runs under. type Runtime: Runtime; /// The window builder type. type WindowBuilder: WindowBuilder; /// Run a task on the main thread. fn run_on_main_thread(&self, f: F) -> Result<()>; /// Registers a window event handler. fn on_window_event(&self, f: F) -> WindowEventId; // GETTERS /// Returns the scale factor that can be used to map logical pixels to physical pixels, and vice versa. fn scale_factor(&self) -> Result; /// Returns the position of the top-left hand corner of the window's client area relative to the top-left hand corner of the desktop. fn inner_position(&self) -> Result>; /// Returns the position of the top-left hand corner of the window relative to the top-left hand corner of the desktop. fn outer_position(&self) -> Result>; /// Returns the physical size of the window's client area. /// /// The client area is the content of the window, excluding the title bar and borders. fn inner_size(&self) -> Result>; /// Returns the physical size of the entire window. /// /// These dimensions include the title bar and borders. If you don't want that (and you usually don't), use inner_size instead. fn outer_size(&self) -> Result>; /// Gets the window's current fullscreen state. fn is_fullscreen(&self) -> Result; /// Gets the window's current minimized state. fn is_minimized(&self) -> Result; /// Gets the window's current maximized state. fn is_maximized(&self) -> Result; /// Gets the window's current focus state. fn is_focused(&self) -> Result; /// Gets the window's current decoration state. fn is_decorated(&self) -> Result; /// Gets the window's current resizable state. fn is_resizable(&self) -> Result; /// Gets the window's native maximize button state. /// /// ## Platform-specific /// /// - **Linux / iOS / Android:** Unsupported. fn is_maximizable(&self) -> Result; /// Gets the window's native minimize button state. /// /// ## Platform-specific /// /// - **Linux / iOS / Android:** Unsupported. fn is_minimizable(&self) -> Result; /// Gets the window's native close button state. /// /// ## Platform-specific /// /// - **iOS / Android:** Unsupported. fn is_closable(&self) -> Result; /// Gets the window's current visibility state. fn is_visible(&self) -> Result; /// Whether the window is enabled or disable. fn is_enabled(&self) -> Result; /// Gets the window alwaysOnTop flag state. /// /// ## Platform-specific /// /// - **iOS / Android:** Unsupported. fn is_always_on_top(&self) -> Result; /// Gets the window's current title. fn title(&self) -> Result; /// Returns the monitor on which the window currently resides. /// /// Returns None if current monitor can't be detected. fn current_monitor(&self) -> Result>; /// Returns the primary monitor of the system. /// /// Returns None if it can't identify any monitor as a primary one. fn primary_monitor(&self) -> Result>; /// Returns the monitor that contains the given point. fn monitor_from_point(&self, x: f64, y: f64) -> Result>; /// Returns the list of all the monitors available on the system. fn available_monitors(&self) -> Result>; /// Returns the `ApplicationWindow` from gtk crate that is used by this window. #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] fn gtk_window(&self) -> Result; /// Returns the vertical [`gtk::Box`] that is added by default as the sole child of this window. #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] fn default_vbox(&self) -> Result; /// Raw window handle. fn window_handle( &self, ) -> std::result::Result, raw_window_handle::HandleError>; /// Returns the current window theme. fn theme(&self) -> Result; // SETTERS /// Centers the window. fn center(&self) -> Result<()>; /// Requests user attention to the window. /// /// Providing `None` will unset the request for user attention. fn request_user_attention(&self, request_type: Option) -> Result<()>; /// Create a new window. fn create_window( &mut self, pending: PendingWindow, after_window_creation: Option, ) -> Result>; /// Create a new webview. fn create_webview( &mut self, pending: PendingWebview, ) -> Result>; /// Updates the window resizable flag. fn set_resizable(&self, resizable: bool) -> Result<()>; /// Enable or disable the window. /// /// ## Platform-specific /// /// - **Android / iOS**: Unsupported. fn set_enabled(&self, enabled: bool) -> Result<()>; /// Updates the window's native maximize button state. /// /// ## Platform-specific /// /// - **macOS:** Disables the "zoom" button in the window titlebar, which is also used to enter fullscreen mode. /// - **Linux / iOS / Android:** Unsupported. fn set_maximizable(&self, maximizable: bool) -> Result<()>; /// Updates the window's native minimize button state. /// /// ## Platform-specific /// /// - **Linux / iOS / Android:** Unsupported. fn set_minimizable(&self, minimizable: bool) -> Result<()>; /// Updates the window's native close button state. /// /// ## Platform-specific /// /// - **Linux:** "GTK+ will do its best to convince the window manager not to show a close button. /// Depending on the system, this function may not have any effect when called on a window that is already visible" /// - **iOS / Android:** Unsupported. fn set_closable(&self, closable: bool) -> Result<()>; /// Updates the window title. fn set_title>(&self, title: S) -> Result<()>; /// Maximizes the window. fn maximize(&self) -> Result<()>; /// Unmaximizes the window. fn unmaximize(&self) -> Result<()>; /// Minimizes the window. fn minimize(&self) -> Result<()>; /// Unminimizes the window. fn unminimize(&self) -> Result<()>; /// Shows the window. fn show(&self) -> Result<()>; /// Hides the window. fn hide(&self) -> Result<()>; /// Closes the window. fn close(&self) -> Result<()>; /// Destroys the window. fn destroy(&self) -> Result<()>; /// Updates the decorations flag. fn set_decorations(&self, decorations: bool) -> Result<()>; /// Updates the shadow flag. fn set_shadow(&self, enable: bool) -> Result<()>; /// Updates the window alwaysOnBottom flag. fn set_always_on_bottom(&self, always_on_bottom: bool) -> Result<()>; /// Updates the window alwaysOnTop flag. fn set_always_on_top(&self, always_on_top: bool) -> Result<()>; /// Updates the window visibleOnAllWorkspaces flag. fn set_visible_on_all_workspaces(&self, visible_on_all_workspaces: bool) -> Result<()>; /// Set the window background. fn set_background_color(&self, color: Option) -> Result<()>; /// Prevents the window contents from being captured by other apps. fn set_content_protected(&self, protected: bool) -> Result<()>; /// Resizes the window. fn set_size(&self, size: Size) -> Result<()>; /// Updates the window min inner size. fn set_min_size(&self, size: Option) -> Result<()>; /// Updates the window max inner size. fn set_max_size(&self, size: Option) -> Result<()>; /// Sets this window's minimum inner width. fn set_size_constraints(&self, constraints: WindowSizeConstraints) -> Result<()>; /// Updates the window position. fn set_position(&self, position: Position) -> Result<()>; /// Updates the window fullscreen state. fn set_fullscreen(&self, fullscreen: bool) -> Result<()>; #[cfg(target_os = "macos")] fn set_simple_fullscreen(&self, enable: bool) -> Result<()>; /// Bring the window to front and focus. fn set_focus(&self) -> Result<()>; /// Sets whether the window can be focused. fn set_focusable(&self, focusable: bool) -> Result<()>; /// Updates the window icon. fn set_icon(&self, icon: Icon) -> Result<()>; /// Whether to hide the window icon from the taskbar or not. fn set_skip_taskbar(&self, skip: bool) -> Result<()>; /// Grabs the cursor, preventing it from leaving the window. /// /// There's no guarantee that the cursor will be hidden. You should /// hide it by yourself if you want so. fn set_cursor_grab(&self, grab: bool) -> Result<()>; /// Modifies the cursor's visibility. /// /// If `false`, this will hide the cursor. If `true`, this will show the cursor. fn set_cursor_visible(&self, visible: bool) -> Result<()>; // Modifies the cursor icon of the window. fn set_cursor_icon(&self, icon: CursorIcon) -> Result<()>; /// Changes the position of the cursor in window coordinates. fn set_cursor_position>(&self, position: Pos) -> Result<()>; /// Ignores the window cursor events. fn set_ignore_cursor_events(&self, ignore: bool) -> Result<()>; /// Starts dragging the window. fn start_dragging(&self) -> Result<()>; /// Starts resize-dragging the window. fn start_resize_dragging(&self, direction: ResizeDirection) -> Result<()>; /// Sets the badge count on the taskbar /// The badge count appears as a whole for the application /// Using `0` or using `None` will remove the badge /// /// ## Platform-specific /// - **Windows:** Unsupported, use [`WindowDispatch::set_overlay_icon`] instead. /// - **Android:** Unsupported. /// - **iOS:** iOS expects i32, if the value is larger than i32::MAX, it will be clamped to i32::MAX. fn set_badge_count(&self, count: Option, desktop_filename: Option) -> Result<()>; /// Sets the badge count on the taskbar **macOS only**. Using `None` will remove the badge fn set_badge_label(&self, label: Option) -> Result<()>; /// Sets the overlay icon on the taskbar **Windows only**. Using `None` will remove the icon /// /// The overlay icon can be unique for each window. fn set_overlay_icon(&self, icon: Option) -> Result<()>; /// Sets the taskbar progress state. /// /// ## Platform-specific /// /// - **Linux / macOS**: Progress bar is app-wide and not specific to this window. Only supported desktop environments with `libunity` (e.g. GNOME). /// - **iOS / Android:** Unsupported. fn set_progress_bar(&self, progress_state: ProgressBarState) -> Result<()>; /// Sets the title bar style. Available on macOS only. /// /// ## Platform-specific /// /// - **Linux / Windows / iOS / Android:** Unsupported. fn set_title_bar_style(&self, style: tauri_utils::TitleBarStyle) -> Result<()>; /// Change the position of the window controls. Available on macOS only. /// /// Requires titleBarStyle: Overlay and decorations: true. /// /// ## Platform-specific /// /// - **Linux / Windows / iOS / Android:** Unsupported. fn set_traffic_light_position(&self, position: Position) -> Result<()>; /// Sets the theme for this window. /// /// ## Platform-specific /// /// - **Linux / macOS**: Theme is app-wide and not specific to this window. /// - **iOS / Android:** Unsupported. fn set_theme(&self, theme: Option) -> Result<()>; } ================================================ FILE: crates/tauri-runtime/src/monitor.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use crate::dpi::{PhysicalPosition, PhysicalRect, PhysicalSize}; /// Monitor descriptor. #[derive(Debug, Clone)] pub struct Monitor { /// A human-readable name of the monitor. /// `None` if the monitor doesn't exist anymore. pub name: Option, /// The monitor's resolution. pub size: PhysicalSize, /// The top-left corner position of the monitor relative to the larger full screen area. pub position: PhysicalPosition, /// The monitor's work_area. pub work_area: PhysicalRect, /// Returns the scale factor that can be used to map logical pixels to physical pixels, and vice versa. pub scale_factor: f64, } ================================================ FILE: crates/tauri-runtime/src/webview.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT //! A layer between raw [`Runtime`] webviews and Tauri. //! #[cfg(not(any(target_os = "android", target_os = "ios")))] use crate::window::WindowId; use crate::{window::is_label_valid, Rect, Runtime, UserEvent}; use http::Request; use tauri_utils::config::{ BackgroundThrottlingPolicy, Color, ScrollBarStyle as ConfigScrollBarStyle, WebviewUrl, WindowConfig, WindowEffectsConfig, }; use url::Url; use std::{ borrow::Cow, collections::HashMap, hash::{Hash, Hasher}, path::PathBuf, sync::Arc, }; type UriSchemeProtocolHandler = dyn Fn(&str, http::Request>, Box>) + Send>) + Send + Sync + 'static; type WebResourceRequestHandler = dyn Fn(http::Request>, &mut http::Response>) + Send + Sync; type NavigationHandler = dyn Fn(&Url) -> bool + Send; type NewWindowHandler = dyn Fn(Url, NewWindowFeatures) -> NewWindowResponse + Send + Sync; type OnPageLoadHandler = dyn Fn(Url, PageLoadEvent) + Send; type DocumentTitleChangedHandler = dyn Fn(String) + Send + 'static; type DownloadHandler = dyn Fn(DownloadEvent) -> bool + Send + Sync; #[cfg(target_os = "ios")] type InputAccessoryViewBuilderFn = dyn Fn(&objc2_ui_kit::UIView) -> Option> + Send + Sync + 'static; /// Download event. pub enum DownloadEvent<'a> { /// Download requested. Requested { /// The url being downloaded. url: Url, /// Represents where the file will be downloaded to. /// Can be used to set the download location by assigning a new path to it. /// The assigned path _must_ be absolute. destination: &'a mut PathBuf, }, /// Download finished. Finished { /// The URL of the original download request. url: Url, /// Potentially representing the filesystem path the file was downloaded to. path: Option, /// Indicates if the download succeeded or not. success: bool, }, } #[cfg(target_os = "android")] pub struct CreationContext<'a, 'b> { pub env: &'a mut jni::JNIEnv<'b>, pub activity: &'a jni::objects::JObject<'b>, pub webview: &'a jni::objects::JObject<'b>, } /// Kind of event for the page load handler. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum PageLoadEvent { /// Page started to load. Started, /// Page finished loading. Finished, } /// Information about the webview that initiated a new window request. #[derive(Debug)] pub struct NewWindowOpener { /// The instance of the webview that initiated the new window request. /// /// This must be set as the related view of the new webview. See [`WebviewAttributes::related_view`]. #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", ))] pub webview: webkit2gtk::WebView, /// The instance of the webview that initiated the new window request. /// /// The target webview environment **MUST** match the environment of the opener webview. See [`WebviewAttributes::environment`]. #[cfg(windows)] pub webview: webview2_com::Microsoft::Web::WebView2::Win32::ICoreWebView2, #[cfg(windows)] pub environment: webview2_com::Microsoft::Web::WebView2::Win32::ICoreWebView2Environment, /// The instance of the webview that initiated the new window request. #[cfg(target_os = "macos")] pub webview: objc2::rc::Retained, /// Configuration of the target webview. /// /// This **MUST** be used when creating the target webview. See [`WebviewAttributes::webview_configuration`]. #[cfg(target_os = "macos")] pub target_configuration: objc2::rc::Retained, } /// Window features of a window requested to open. #[derive(Debug)] pub struct NewWindowFeatures { pub(crate) size: Option>, pub(crate) position: Option>, pub(crate) opener: NewWindowOpener, } impl NewWindowFeatures { pub fn new( size: Option>, position: Option>, opener: NewWindowOpener, ) -> Self { Self { size, position, opener, } } /// Specifies the size of the content area /// as defined by the user's operating system where the new window will be generated. pub fn size(&self) -> Option> { self.size } /// Specifies the position of the window relative to the work area /// as defined by the user's operating system where the new window will be generated. pub fn position(&self) -> Option> { self.position } /// Returns information about the webview that initiated a new window request. pub fn opener(&self) -> &NewWindowOpener { &self.opener } } /// Response for the new window request handler. pub enum NewWindowResponse { /// Allow the window to be opened with the default implementation. Allow, /// Allow the window to be opened, with the given window. /// /// ## Platform-specific: /// /// **Linux**: The webview must be related to the caller webview. See [`WebviewAttributes::related_view`]. /// **Windows**: The webview must use the same environment as the caller webview. See [`WebviewAttributes::environment`]. #[cfg(not(any(target_os = "android", target_os = "ios")))] Create { window_id: WindowId }, /// Deny the window from being opened. Deny, } /// The scrollbar style to use in the webview. /// /// ## Platform-specific /// /// - **Windows**: This option must be given the same value for all webviews that target the same data directory. #[non_exhaustive] #[derive(Debug, Clone, Copy, Default)] pub enum ScrollBarStyle { #[default] /// The default scrollbar style for the webview. Default, #[cfg(windows)] /// Fluent UI style overlay scrollbars. **Windows Only** /// /// Requires WebView2 Runtime version 125.0.2535.41 or higher, does nothing on older versions, /// see https://learn.microsoft.com/en-us/microsoft-edge/webview2/release-notes/?tabs=dotnetcsharp#10253541 FluentOverlay, } /// A webview that has yet to be built. pub struct PendingWebview> { /// The label that the webview will be named. pub label: String, /// The [`WebviewAttributes`] that the webview will be created with. pub webview_attributes: WebviewAttributes, /// Custom protocols to register on the webview pub uri_scheme_protocols: HashMap>, /// How to handle IPC calls on the webview. pub ipc_handler: Option>, /// A handler to decide if incoming url is allowed to navigate. pub navigation_handler: Option>, pub new_window_handler: Option>, pub document_title_changed_handler: Option>, /// The resolved URL to load on the webview. pub url: String, #[cfg(target_os = "android")] #[allow(clippy::type_complexity)] pub on_webview_created: Option) -> Result<(), jni::errors::Error> + Send>>, pub web_resource_request_handler: Option>, pub on_page_load_handler: Option>, pub download_handler: Option>, } impl> PendingWebview { /// Create a new [`PendingWebview`] with a label from the given [`WebviewAttributes`]. pub fn new( webview_attributes: WebviewAttributes, label: impl Into, ) -> crate::Result { let label = label.into(); if !is_label_valid(&label) { Err(crate::Error::InvalidWindowLabel) } else { Ok(Self { webview_attributes, uri_scheme_protocols: Default::default(), label, ipc_handler: None, navigation_handler: None, new_window_handler: None, document_title_changed_handler: None, url: "tauri://localhost".to_string(), #[cfg(target_os = "android")] on_webview_created: None, web_resource_request_handler: None, on_page_load_handler: None, download_handler: None, }) } } pub fn register_uri_scheme_protocol< N: Into, H: Fn(&str, http::Request>, Box>) + Send>) + Send + Sync + 'static, >( &mut self, uri_scheme: N, protocol_handler: H, ) { let uri_scheme = uri_scheme.into(); self .uri_scheme_protocols .insert(uri_scheme, Box::new(protocol_handler)); } #[cfg(target_os = "android")] pub fn on_webview_created< F: Fn(CreationContext<'_, '_>) -> Result<(), jni::errors::Error> + Send + 'static, >( mut self, f: F, ) -> Self { self.on_webview_created.replace(Box::new(f)); self } } /// A webview that is not yet managed by Tauri. #[derive(Debug)] pub struct DetachedWebview> { /// Name of the window pub label: String, /// The [`crate::WebviewDispatch`] associated with the window. pub dispatcher: R::WebviewDispatcher, } impl> Clone for DetachedWebview { fn clone(&self) -> Self { Self { label: self.label.clone(), dispatcher: self.dispatcher.clone(), } } } impl> Hash for DetachedWebview { /// Only use the [`DetachedWebview`]'s label to represent its hash. fn hash(&self, state: &mut H) { self.label.hash(state) } } impl> Eq for DetachedWebview {} impl> PartialEq for DetachedWebview { /// Only use the [`DetachedWebview`]'s label to compare equality. fn eq(&self, other: &Self) -> bool { self.label.eq(&other.label) } } /// The attributes used to create an webview. #[derive(Debug)] pub struct WebviewAttributes { pub url: WebviewUrl, pub user_agent: Option, /// A list of initialization javascript scripts to run when loading new pages. /// When webview load a new page, this initialization code will be executed. /// It is guaranteed that code is executed before `window.onload`. /// /// ## Platform-specific /// /// - **Windows:** scripts are always added to subframes. /// - **Android:** When [addDocumentStartJavaScript] is not supported, /// we prepend initialization scripts to each HTML head (implementation only supported on custom protocol URLs). /// For remote URLs, we use [onPageStarted] which is not guaranteed to run before other scripts. /// /// [addDocumentStartJavaScript]: https://developer.android.com/reference/androidx/webkit/WebViewCompat#addDocumentStartJavaScript(android.webkit.WebView,java.lang.String,java.util.Set%3Cjava.lang.String%3E) /// [onPageStarted]: https://developer.android.com/reference/android/webkit/WebViewClient#onPageStarted(android.webkit.WebView,%20java.lang.String,%20android.graphics.Bitmap) pub initialization_scripts: Vec, pub data_directory: Option, pub drag_drop_handler_enabled: bool, pub clipboard: bool, pub accept_first_mouse: bool, pub additional_browser_args: Option, pub window_effects: Option, pub incognito: bool, pub transparent: bool, pub focus: bool, pub bounds: Option, pub auto_resize: bool, pub proxy_url: Option, pub zoom_hotkeys_enabled: bool, pub browser_extensions_enabled: bool, pub extensions_path: Option, pub data_store_identifier: Option<[u8; 16]>, pub use_https_scheme: bool, pub devtools: Option, pub background_color: Option, pub traffic_light_position: Option, pub background_throttling: Option, pub javascript_disabled: bool, /// on macOS and iOS there is a link preview on long pressing links, this is enabled by default. /// see https://docs.rs/objc2-web-kit/latest/objc2_web_kit/struct.WKWebView.html#method.allowsLinkPreview pub allow_link_preview: bool, pub scroll_bar_style: ScrollBarStyle, /// Allows overriding the keyboard accessory view on iOS. /// Returning `None` effectively removes the view. /// /// The closure parameter is the webview instance. /// /// The accessory view is the view that appears above the keyboard when a text input element is focused. /// It usually displays a view with "Done", "Next" buttons. /// /// # Stability /// /// This relies on [`objc2_ui_kit`] which does not provide a stable API yet, so it can receive breaking changes in minor releases. #[cfg(target_os = "ios")] pub input_accessory_view_builder: Option, /// Set the environment for the webview. /// Useful if you need to share the same environment, for instance when using the [`PendingWebview::new_window_handler`]. #[cfg(windows)] pub environment: Option, /// Creates a new webview sharing the same web process with the provided webview. /// Useful if you need to link a webview to another, for instance when using the [`PendingWebview::new_window_handler`]. #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", ))] pub related_view: Option, #[cfg(target_os = "macos")] pub webview_configuration: Option>, } unsafe impl Send for WebviewAttributes {} unsafe impl Sync for WebviewAttributes {} #[cfg(target_os = "ios")] #[non_exhaustive] pub struct InputAccessoryViewBuilder(pub Box); #[cfg(target_os = "ios")] impl std::fmt::Debug for InputAccessoryViewBuilder { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { f.debug_struct("InputAccessoryViewBuilder").finish() } } #[cfg(target_os = "ios")] impl InputAccessoryViewBuilder { pub fn new(builder: Box) -> Self { Self(builder) } } impl From<&WindowConfig> for WebviewAttributes { fn from(config: &WindowConfig) -> Self { let mut builder = Self::new(config.url.clone()) .incognito(config.incognito) .focused(config.focus) .zoom_hotkeys_enabled(config.zoom_hotkeys_enabled) .use_https_scheme(config.use_https_scheme) .browser_extensions_enabled(config.browser_extensions_enabled) .background_throttling(config.background_throttling.clone()) .devtools(config.devtools) .scroll_bar_style(match config.scroll_bar_style { ConfigScrollBarStyle::Default => ScrollBarStyle::Default, #[cfg(windows)] ConfigScrollBarStyle::FluentOverlay => ScrollBarStyle::FluentOverlay, _ => ScrollBarStyle::Default, }); #[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))] { builder = builder.transparent(config.transparent); } #[cfg(target_os = "macos")] { if let Some(position) = &config.traffic_light_position { builder = builder.traffic_light_position(dpi::LogicalPosition::new(position.x, position.y).into()); } } builder = builder.accept_first_mouse(config.accept_first_mouse); if !config.drag_drop_enabled { builder = builder.disable_drag_drop_handler(); } if let Some(user_agent) = &config.user_agent { builder = builder.user_agent(user_agent); } if let Some(additional_browser_args) = &config.additional_browser_args { builder = builder.additional_browser_args(additional_browser_args); } if let Some(effects) = &config.window_effects { builder = builder.window_effects(effects.clone()); } if let Some(url) = &config.proxy_url { builder = builder.proxy_url(url.to_owned()); } if let Some(color) = config.background_color { builder = builder.background_color(color); } builder.javascript_disabled = config.javascript_disabled; builder.allow_link_preview = config.allow_link_preview; #[cfg(target_os = "ios")] if config.disable_input_accessory_view { builder .input_accessory_view_builder .replace(InputAccessoryViewBuilder::new(Box::new(|_webview| None))); } builder } } impl WebviewAttributes { /// Initializes the default attributes for a webview. pub fn new(url: WebviewUrl) -> Self { Self { url, user_agent: None, initialization_scripts: Vec::new(), data_directory: None, drag_drop_handler_enabled: true, clipboard: false, accept_first_mouse: false, additional_browser_args: None, window_effects: None, incognito: false, transparent: false, focus: true, bounds: None, auto_resize: false, proxy_url: None, zoom_hotkeys_enabled: false, browser_extensions_enabled: false, data_store_identifier: None, extensions_path: None, use_https_scheme: false, devtools: None, background_color: None, traffic_light_position: None, background_throttling: None, javascript_disabled: false, allow_link_preview: true, scroll_bar_style: ScrollBarStyle::Default, #[cfg(target_os = "ios")] input_accessory_view_builder: None, #[cfg(windows)] environment: None, #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", ))] related_view: None, #[cfg(target_os = "macos")] webview_configuration: None, } } /// Sets the user agent #[must_use] pub fn user_agent(mut self, user_agent: &str) -> Self { self.user_agent = Some(user_agent.to_string()); self } /// Adds an init script for the main frame. /// /// When webview load a new page, this initialization code will be executed. /// It is guaranteed that code is executed before `window.onload`. /// /// This is executed only on the main frame. /// If you only want to run it in all frames, use [`Self::initialization_script_on_all_frames`] instead. /// /// ## Platform-specific /// /// - **Windows:** scripts are always added to subframes. /// - **Android:** When [addDocumentStartJavaScript] is not supported, /// we prepend initialization scripts to each HTML head (implementation only supported on custom protocol URLs). /// For remote URLs, we use [onPageStarted] which is not guaranteed to run before other scripts. /// /// [addDocumentStartJavaScript]: https://developer.android.com/reference/androidx/webkit/WebViewCompat#addDocumentStartJavaScript(android.webkit.WebView,java.lang.String,java.util.Set%3Cjava.lang.String%3E) /// [onPageStarted]: https://developer.android.com/reference/android/webkit/WebViewClient#onPageStarted(android.webkit.WebView,%20java.lang.String,%20android.graphics.Bitmap) #[must_use] pub fn initialization_script(mut self, script: impl Into) -> Self { self.initialization_scripts.push(InitializationScript { script: script.into(), for_main_frame_only: true, }); self } /// Adds an init script for all frames. /// /// When webview load a new page, this initialization code will be executed. /// It is guaranteed that code is executed before `window.onload`. /// /// This is executed on all frames, main frame and also sub frames. /// If you only want to run it in the main frame, use [`Self::initialization_script`] instead. /// /// ## Platform-specific /// /// - **Windows:** scripts are always added to subframes. /// - **Android:** When [addDocumentStartJavaScript] is not supported, /// we prepend initialization scripts to each HTML head (implementation only supported on custom protocol URLs). /// For remote URLs, we use [onPageStarted] which is not guaranteed to run before other scripts. /// /// [addDocumentStartJavaScript]: https://developer.android.com/reference/androidx/webkit/WebViewCompat#addDocumentStartJavaScript(android.webkit.WebView,java.lang.String,java.util.Set%3Cjava.lang.String%3E) /// [onPageStarted]: https://developer.android.com/reference/android/webkit/WebViewClient#onPageStarted(android.webkit.WebView,%20java.lang.String,%20android.graphics.Bitmap) #[must_use] pub fn initialization_script_on_all_frames(mut self, script: impl Into) -> Self { self.initialization_scripts.push(InitializationScript { script: script.into(), for_main_frame_only: false, }); self } /// Data directory for the webview. #[must_use] pub fn data_directory(mut self, data_directory: PathBuf) -> Self { self.data_directory.replace(data_directory); self } /// Disables the drag and drop handler. This is required to use HTML5 drag and drop APIs on the frontend on Windows. #[must_use] pub fn disable_drag_drop_handler(mut self) -> Self { self.drag_drop_handler_enabled = false; self } /// Enables clipboard access for the page rendered on **Linux** and **Windows**. /// /// **macOS** doesn't provide such method and is always enabled by default, /// but you still need to add menu item accelerators to use shortcuts. #[must_use] pub fn enable_clipboard_access(mut self) -> Self { self.clipboard = true; self } /// Sets whether clicking an inactive window also clicks through to the webview. #[must_use] pub fn accept_first_mouse(mut self, accept: bool) -> Self { self.accept_first_mouse = accept; self } /// Sets additional browser arguments. **Windows Only** #[must_use] pub fn additional_browser_args(mut self, additional_args: &str) -> Self { self.additional_browser_args = Some(additional_args.to_string()); self } /// Sets window effects #[must_use] pub fn window_effects(mut self, effects: WindowEffectsConfig) -> Self { self.window_effects = Some(effects); self } /// Enable or disable incognito mode for the WebView. #[must_use] pub fn incognito(mut self, incognito: bool) -> Self { self.incognito = incognito; self } /// Enable or disable transparency for the WebView. #[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))] #[must_use] pub fn transparent(mut self, transparent: bool) -> Self { self.transparent = transparent; self } /// Whether the webview should be focused or not. #[must_use] pub fn focused(mut self, focus: bool) -> Self { self.focus = focus; self } /// Sets the webview to automatically grow and shrink its size and position when the parent window resizes. #[must_use] pub fn auto_resize(mut self) -> Self { self.auto_resize = true; self } /// Enable proxy for the WebView #[must_use] pub fn proxy_url(mut self, url: Url) -> Self { self.proxy_url = Some(url); self } /// Whether page zooming by hotkeys is enabled /// /// ## Platform-specific: /// /// - **Windows**: Controls WebView2's [`IsZoomControlEnabled`](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/microsoft_web_webview2_core/corewebview2settings?view=webview2-winrt-1.0.2420.47#iszoomcontrolenabled) setting. /// - **MacOS / Linux**: Injects a polyfill that zooms in and out with `ctrl/command` + `-/=`, /// 20% in each step, ranging from 20% to 1000%. Requires `webview:allow-set-webview-zoom` permission /// /// - **Android / iOS**: Unsupported. #[must_use] pub fn zoom_hotkeys_enabled(mut self, enabled: bool) -> Self { self.zoom_hotkeys_enabled = enabled; self } /// Whether browser extensions can be installed for the webview process /// /// ## Platform-specific: /// /// - **Windows**: Enables the WebView2 environment's [`AreBrowserExtensionsEnabled`](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/microsoft_web_webview2_core/corewebview2environmentoptions?view=webview2-winrt-1.0.2739.15#arebrowserextensionsenabled) /// - **MacOS / Linux / iOS / Android** - Unsupported. #[must_use] pub fn browser_extensions_enabled(mut self, enabled: bool) -> Self { self.browser_extensions_enabled = enabled; self } /// Sets whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android. Defaults to `false`. /// /// ## Note /// /// Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux. /// /// ## Warning /// /// Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access the old data. #[must_use] pub fn use_https_scheme(mut self, enabled: bool) -> Self { self.use_https_scheme = enabled; self } /// Whether web inspector, which is usually called browser devtools, is enabled or not. Enabled by default. /// /// This API works in **debug** builds, but requires `devtools` feature flag to enable it in **release** builds. /// /// ## Platform-specific /// /// - macOS: This will call private functions on **macOS**. /// - Android: Open `chrome://inspect/#devices` in Chrome to get the devtools window. Wry's `WebView` devtools API isn't supported on Android. /// - iOS: Open Safari > Develop > [Your Device Name] > [Your WebView] to get the devtools window. #[must_use] pub fn devtools(mut self, enabled: Option) -> Self { self.devtools = enabled; self } /// Set the window and webview background color. /// ## Platform-specific: /// /// - **Windows**: On Windows 7, alpha channel is ignored for the webview layer. /// - **Windows**: On Windows 8 and newer, if alpha channel is not `0`, it will be ignored. #[must_use] pub fn background_color(mut self, color: Color) -> Self { self.background_color = Some(color); self } /// Change the position of the window controls. Available on macOS only. /// /// Requires titleBarStyle: Overlay and decorations: true. /// /// ## Platform-specific /// /// - **Linux / Windows / iOS / Android:** Unsupported. #[must_use] pub fn traffic_light_position(mut self, position: dpi::Position) -> Self { self.traffic_light_position = Some(position); self } /// Whether to show a link preview when long pressing on links. Available on macOS and iOS only. /// /// Default is true. /// /// See https://docs.rs/objc2-web-kit/latest/objc2_web_kit/struct.WKWebView.html#method.allowsLinkPreview /// /// ## Platform-specific /// /// - **Linux / Windows / Android:** Unsupported. #[must_use] pub fn allow_link_preview(mut self, allow_link_preview: bool) -> Self { self.allow_link_preview = allow_link_preview; self } /// Change the default background throttling behavior. /// /// By default, browsers use a suspend policy that will throttle timers and even unload /// the whole tab (view) to free resources after roughly 5 minutes when a view became /// minimized or hidden. This will pause all tasks until the documents visibility state /// changes back from hidden to visible by bringing the view back to the foreground. /// /// ## Platform-specific /// /// - **Linux / Windows / Android**: Unsupported. Workarounds like a pending WebLock transaction might suffice. /// - **iOS**: Supported since version 17.0+. /// - **macOS**: Supported since version 14.0+. /// /// see https://github.com/tauri-apps/tauri/issues/5250#issuecomment-2569380578 #[must_use] pub fn background_throttling(mut self, policy: Option) -> Self { self.background_throttling = policy; self } /// Specifies the native scrollbar style to use with the webview. /// CSS styles that modify the scrollbar are applied on top of the native appearance configured here. /// /// Defaults to [`ScrollBarStyle::Default`], which is the browser default. /// /// ## Platform-specific /// /// - **Windows**: /// - [`ScrollBarStyle::FluentOverlay`] requires WebView2 Runtime version 125.0.2535.41 or higher, /// and does nothing on older versions. /// - This option must be given the same value for all webviews that target the same data directory. Use /// [`WebviewAttributes::data_directory`] to change data directories if needed. /// - **Linux / Android / iOS / macOS**: Unsupported. Only supports `Default` and performs no operation. #[must_use] pub fn scroll_bar_style(mut self, style: ScrollBarStyle) -> Self { self.scroll_bar_style = style; self } } /// IPC handler. pub type WebviewIpcHandler = Box, Request) + Send>; /// An initialization script #[derive(Debug, Clone)] pub struct InitializationScript { /// The script to run pub script: String, /// Whether the script should be injected to main frame only pub for_main_frame_only: bool, } ================================================ FILE: crates/tauri-runtime/src/window.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT //! A layer between raw [`Runtime`] windows and Tauri. use crate::{ webview::{DetachedWebview, PendingWebview}, Icon, Runtime, UserEvent, WindowDispatch, }; use dpi::PixelUnit; use serde::{Deserialize, Deserializer, Serialize}; use tauri_utils::{ config::{Color, WindowConfig}, Theme, }; #[cfg(windows)] use windows::Win32::Foundation::HWND; use std::{ hash::{Hash, Hasher}, marker::PhantomData, path::PathBuf, sync::mpsc::Sender, }; /// An event from a window. #[derive(Debug, Clone)] pub enum WindowEvent { /// The size of the window has changed. Contains the client area's new dimensions. Resized(dpi::PhysicalSize), /// The position of the window has changed. Contains the window's new position. Moved(dpi::PhysicalPosition), /// The window has been requested to close. CloseRequested { /// A signal sender. If a `true` value is emitted, the window won't be closed. signal_tx: Sender, }, /// The window has been destroyed. Destroyed, /// The window gained or lost focus. /// /// The parameter is true if the window has gained focus, and false if it has lost focus. Focused(bool), /// The window's scale factor has changed. /// /// The following user actions can cause DPI changes: /// /// - Changing the display's resolution. /// - Changing the display's scale factor (e.g. in Control Panel on Windows). /// - Moving the window to a display with a different scale factor. ScaleFactorChanged { /// The new scale factor. scale_factor: f64, /// The window inner size. new_inner_size: dpi::PhysicalSize, }, /// An event associated with the drag and drop action. DragDrop(DragDropEvent), /// The system window theme has changed. /// /// Applications might wish to react to this to change the theme of the content of the window when the system changes the window theme. ThemeChanged(Theme), } /// An event from a window. #[derive(Debug, Clone)] pub enum WebviewEvent { /// An event associated with the drag and drop action. DragDrop(DragDropEvent), } /// The drag drop event payload. #[derive(Debug, Clone)] #[non_exhaustive] pub enum DragDropEvent { /// A drag operation has entered the webview. Enter { /// List of paths that are being dragged onto the webview. paths: Vec, /// The position of the mouse cursor. position: dpi::PhysicalPosition, }, /// A drag operation is moving over the webview. Over { /// The position of the mouse cursor. position: dpi::PhysicalPosition, }, /// The file(s) have been dropped onto the webview. Drop { /// List of paths that are being dropped onto the window. paths: Vec, /// The position of the mouse cursor. position: dpi::PhysicalPosition, }, /// The drag operation has been cancelled or left the window. Leave, } /// Describes the appearance of the mouse cursor. #[non_exhaustive] #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash)] pub enum CursorIcon { /// The platform-dependent default cursor. #[default] Default, /// A simple crosshair. Crosshair, /// A hand (often used to indicate links in web browsers). Hand, /// Self explanatory. Arrow, /// Indicates something is to be moved. Move, /// Indicates text that may be selected or edited. Text, /// Program busy indicator. Wait, /// Help indicator (often rendered as a "?") Help, /// Progress indicator. Shows that processing is being done. But in contrast /// with "Wait" the user may still interact with the program. Often rendered /// as a spinning beach ball, or an arrow with a watch or hourglass. Progress, /// Cursor showing that something cannot be done. NotAllowed, ContextMenu, Cell, VerticalText, Alias, Copy, NoDrop, /// Indicates something can be grabbed. Grab, /// Indicates something is grabbed. Grabbing, AllScroll, ZoomIn, ZoomOut, /// Indicate that some edge is to be moved. For example, the 'SeResize' cursor /// is used when the movement starts from the south-east corner of the box. EResize, NResize, NeResize, NwResize, SResize, SeResize, SwResize, WResize, EwResize, NsResize, NeswResize, NwseResize, ColResize, RowResize, } impl<'de> Deserialize<'de> for CursorIcon { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { let s = String::deserialize(deserializer)?; Ok(match s.to_lowercase().as_str() { "default" => CursorIcon::Default, "crosshair" => CursorIcon::Crosshair, "hand" => CursorIcon::Hand, "arrow" => CursorIcon::Arrow, "move" => CursorIcon::Move, "text" => CursorIcon::Text, "wait" => CursorIcon::Wait, "help" => CursorIcon::Help, "progress" => CursorIcon::Progress, "notallowed" => CursorIcon::NotAllowed, "contextmenu" => CursorIcon::ContextMenu, "cell" => CursorIcon::Cell, "verticaltext" => CursorIcon::VerticalText, "alias" => CursorIcon::Alias, "copy" => CursorIcon::Copy, "nodrop" => CursorIcon::NoDrop, "grab" => CursorIcon::Grab, "grabbing" => CursorIcon::Grabbing, "allscroll" => CursorIcon::AllScroll, "zoomin" => CursorIcon::ZoomIn, "zoomout" => CursorIcon::ZoomOut, "eresize" => CursorIcon::EResize, "nresize" => CursorIcon::NResize, "neresize" => CursorIcon::NeResize, "nwresize" => CursorIcon::NwResize, "sresize" => CursorIcon::SResize, "seresize" => CursorIcon::SeResize, "swresize" => CursorIcon::SwResize, "wresize" => CursorIcon::WResize, "ewresize" => CursorIcon::EwResize, "nsresize" => CursorIcon::NsResize, "neswresize" => CursorIcon::NeswResize, "nwseresize" => CursorIcon::NwseResize, "colresize" => CursorIcon::ColResize, "rowresize" => CursorIcon::RowResize, _ => CursorIcon::Default, }) } } /// Window size constraints #[derive(Clone, Copy, PartialEq, Debug, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct WindowSizeConstraints { /// The minimum width a window can be, If this is `None`, the window will have no minimum width. /// /// The default is `None`. pub min_width: Option, /// The minimum height a window can be, If this is `None`, the window will have no minimum height. /// /// The default is `None`. pub min_height: Option, /// The maximum width a window can be, If this is `None`, the window will have no maximum width. /// /// The default is `None`. pub max_width: Option, /// The maximum height a window can be, If this is `None`, the window will have no maximum height. /// /// The default is `None`. pub max_height: Option, } /// Do **NOT** implement this trait except for use in a custom [`Runtime`] /// /// This trait is separate from [`WindowBuilder`] to prevent "accidental" implementation. pub trait WindowBuilderBase: std::fmt::Debug + Clone + Sized {} /// A builder for all attributes related to a single window. /// /// This trait is only meant to be implemented by a custom [`Runtime`] /// and not by applications. pub trait WindowBuilder: WindowBuilderBase { /// Initializes a new window attributes builder. fn new() -> Self; /// Initializes a new window builder from a [`WindowConfig`] fn with_config(config: &WindowConfig) -> Self; /// Show window in the center of the screen. #[must_use] fn center(self) -> Self; /// The initial position of the window in logical pixels. #[must_use] fn position(self, x: f64, y: f64) -> Self; /// Window size in logical pixels. #[must_use] fn inner_size(self, width: f64, height: f64) -> Self; /// Window min inner size in logical pixels. #[must_use] fn min_inner_size(self, min_width: f64, min_height: f64) -> Self; /// Window max inner size in logical pixels. #[must_use] fn max_inner_size(self, max_width: f64, max_height: f64) -> Self; /// Window inner size constraints. #[must_use] fn inner_size_constraints(self, constraints: WindowSizeConstraints) -> Self; /// Prevent the window from overflowing the working area (e.g. monitor size - taskbar size) on creation /// /// ## Platform-specific /// /// - **iOS / Android:** Unsupported. #[must_use] fn prevent_overflow(self) -> Self; /// Prevent the window from overflowing the working area (e.g. monitor size - taskbar size) /// on creation with a margin /// /// ## Platform-specific /// /// - **iOS / Android:** Unsupported. #[must_use] fn prevent_overflow_with_margin(self, margin: dpi::Size) -> Self; /// Whether the window is resizable or not. /// When resizable is set to false, native window's maximize button is automatically disabled. #[must_use] fn resizable(self, resizable: bool) -> Self; /// Whether the window's native maximize button is enabled or not. /// If resizable is set to false, this setting is ignored. /// /// ## Platform-specific /// /// - **macOS:** Disables the "zoom" button in the window titlebar, which is also used to enter fullscreen mode. /// - **Linux / iOS / Android:** Unsupported. #[must_use] fn maximizable(self, maximizable: bool) -> Self; /// Whether the window's native minimize button is enabled or not. /// /// ## Platform-specific /// /// - **Linux / iOS / Android:** Unsupported. #[must_use] fn minimizable(self, minimizable: bool) -> Self; /// Whether the window's native close button is enabled or not. /// /// ## Platform-specific /// /// - **Linux:** "GTK+ will do its best to convince the window manager not to show a close button. /// Depending on the system, this function may not have any effect when called on a window that is already visible" /// - **iOS / Android:** Unsupported. #[must_use] fn closable(self, closable: bool) -> Self; /// The title of the window in the title bar. #[must_use] fn title>(self, title: S) -> Self; /// Whether to start the window in fullscreen or not. #[must_use] fn fullscreen(self, fullscreen: bool) -> Self; /// Whether the window will be initially focused or not. #[must_use] fn focused(self, focused: bool) -> Self; /// Whether the window will be focusable or not. #[must_use] fn focusable(self, focusable: bool) -> Self; /// Whether the window should be maximized upon creation. #[must_use] fn maximized(self, maximized: bool) -> Self; /// Whether the window should be immediately visible upon creation. #[must_use] fn visible(self, visible: bool) -> Self; /// Whether the window should be transparent. If this is true, writing colors /// with alpha values different than `1.0` will produce a transparent window. #[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))] #[cfg_attr( docsrs, doc(cfg(any(not(target_os = "macos"), feature = "macos-private-api"))) )] #[must_use] fn transparent(self, transparent: bool) -> Self; /// Whether the window should have borders and bars. #[must_use] fn decorations(self, decorations: bool) -> Self; /// Whether the window should always be below other windows. #[must_use] fn always_on_bottom(self, always_on_bottom: bool) -> Self; /// Whether the window should always be on top of other windows. #[must_use] fn always_on_top(self, always_on_top: bool) -> Self; /// Whether the window should be visible on all workspaces or virtual desktops. #[must_use] fn visible_on_all_workspaces(self, visible_on_all_workspaces: bool) -> Self; /// Prevents the window contents from being captured by other apps. #[must_use] fn content_protected(self, protected: bool) -> Self; /// Sets the window icon. fn icon(self, icon: Icon) -> crate::Result; /// Sets whether or not the window icon should be added to the taskbar. #[must_use] fn skip_taskbar(self, skip: bool) -> Self; /// Set the window background color. #[must_use] fn background_color(self, color: Color) -> Self; /// Sets whether or not the window has shadow. /// /// ## Platform-specific /// /// - **Windows:** /// - `false` has no effect on decorated window, shadows are always ON. /// - `true` will make undecorated window have a 1px white border, /// and on Windows 11, it will have a rounded corners. /// - **Linux:** Unsupported. #[must_use] fn shadow(self, enable: bool) -> Self; /// Set an owner to the window to be created. /// /// From MSDN: /// - An owned window is always above its owner in the z-order. /// - The system automatically destroys an owned window when its owner is destroyed. /// - An owned window is hidden when its owner is minimized. /// /// For more information, see #[cfg(windows)] #[must_use] fn owner(self, owner: HWND) -> Self; /// Sets a parent to the window to be created. /// /// A child window has the WS_CHILD style and is confined to the client area of its parent window. /// /// For more information, see #[cfg(windows)] #[must_use] fn parent(self, parent: HWND) -> Self; /// Sets a parent to the window to be created. /// /// See #[cfg(target_os = "macos")] #[must_use] fn parent(self, parent: *mut std::ffi::c_void) -> Self; /// Sets the window to be created transient for parent. /// /// See #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] fn transient_for(self, parent: &impl gtk::glib::IsA) -> Self; /// Enables or disables drag and drop support. #[cfg(windows)] #[must_use] fn drag_and_drop(self, enabled: bool) -> Self; /// Hide the titlebar. Titlebar buttons will still be visible. #[cfg(target_os = "macos")] #[must_use] fn title_bar_style(self, style: tauri_utils::TitleBarStyle) -> Self; /// Change the position of the window controls on macOS. /// /// Requires titleBarStyle: Overlay and decorations: true. #[cfg(target_os = "macos")] #[must_use] fn traffic_light_position>(self, position: P) -> Self; /// Hide the window title. #[cfg(target_os = "macos")] #[must_use] fn hidden_title(self, hidden: bool) -> Self; /// Defines the window [tabbing identifier] for macOS. /// /// Windows with matching tabbing identifiers will be grouped together. /// If the tabbing identifier is not set, automatic tabbing will be disabled. /// /// [tabbing identifier]: #[cfg(target_os = "macos")] #[must_use] fn tabbing_identifier(self, identifier: &str) -> Self; /// Forces a theme or uses the system settings if None was provided. fn theme(self, theme: Option) -> Self; /// Whether the icon was set or not. fn has_icon(&self) -> bool; fn get_theme(&self) -> Option; /// Sets custom name for Windows' window class. **Windows only**. #[must_use] fn window_classname>(self, window_classname: S) -> Self; } /// A window that has yet to be built. pub struct PendingWindow> { /// The label that the window will be named. pub label: String, /// The [`WindowBuilder`] that the window will be created with. pub window_builder: >::WindowBuilder, /// The webview that gets added to the window. Optional in case you want to use child webviews or other window content instead. pub webview: Option>, } pub fn is_label_valid(label: &str) -> bool { label .chars() .all(|c| char::is_alphanumeric(c) || c == '-' || c == '/' || c == ':' || c == '_') } pub fn assert_label_is_valid(label: &str) { assert!( is_label_valid(label), "Window label must include only alphanumeric characters, `-`, `/`, `:` and `_`." ); } impl> PendingWindow { /// Create a new [`PendingWindow`] with a label from the given [`WindowBuilder`]. pub fn new( window_builder: >::WindowBuilder, label: impl Into, ) -> crate::Result { let label = label.into(); if !is_label_valid(&label) { Err(crate::Error::InvalidWindowLabel) } else { Ok(Self { window_builder, label, webview: None, }) } } /// Sets a webview to be created on the window. pub fn set_webview(&mut self, webview: PendingWebview) -> &mut Self { self.webview.replace(webview); self } } /// Identifier of a window. #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd)] pub struct WindowId(u32); impl From for WindowId { fn from(value: u32) -> Self { Self(value) } } /// A window that is not yet managed by Tauri. #[derive(Debug)] pub struct DetachedWindow> { /// The identifier of the window. pub id: WindowId, /// Name of the window pub label: String, /// The [`WindowDispatch`] associated with the window. pub dispatcher: R::WindowDispatcher, /// The webview dispatcher in case this window has an attached webview. pub webview: Option>, } /// A detached webview associated with a window. #[derive(Debug)] pub struct DetachedWindowWebview> { pub webview: DetachedWebview, pub use_https_scheme: bool, } impl> Clone for DetachedWindowWebview { fn clone(&self) -> Self { Self { webview: self.webview.clone(), use_https_scheme: self.use_https_scheme, } } } impl> Clone for DetachedWindow { fn clone(&self) -> Self { Self { id: self.id, label: self.label.clone(), dispatcher: self.dispatcher.clone(), webview: self.webview.clone(), } } } impl> Hash for DetachedWindow { /// Only use the [`DetachedWindow`]'s label to represent its hash. fn hash(&self, state: &mut H) { self.label.hash(state) } } impl> Eq for DetachedWindow {} impl> PartialEq for DetachedWindow { /// Only use the [`DetachedWindow`]'s label to compare equality. fn eq(&self, other: &Self) -> bool { self.label.eq(&other.label) } } /// A raw window type that contains fields to access /// the HWND on Windows, gtk::ApplicationWindow on Linux pub struct RawWindow<'a> { #[cfg(windows)] pub hwnd: isize, #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] pub gtk_window: &'a gtk::ApplicationWindow, #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] pub default_vbox: Option<&'a gtk::Box>, pub _marker: &'a PhantomData<()>, } ================================================ FILE: crates/tauri-runtime-wry/CHANGELOG.md ================================================ # Changelog ## \[2.10.1] ### Dependencies - Upgraded to `tauri-utils@2.8.3` - Upgraded to `tauri-runtime@2.10.1` ## \[2.10.0] ### Bug Fixes - [`c1d82eb3a`](https://www.github.com/tauri-apps/tauri/commit/c1d82eb3a3fa4b555745ba699edf1cc532030117) ([#14628](https://www.github.com/tauri-apps/tauri/pull/14628) by [@KushalMeghani1644](https://www.github.com/tauri-apps/tauri/../../KushalMeghani1644)) On Linux, keep the WebContext alive to prevent zombie WebKit processes after repeatedly closing all windows and re-opening them. - [`9b242e40c`](https://www.github.com/tauri-apps/tauri/commit/9b242e40c844189c877a91e513ae6196202d5ae9) ([#14700](https://www.github.com/tauri-apps/tauri/pull/14700) by [@mewi99](https://www.github.com/tauri-apps/tauri/../../mewi99)) Fix compilation errors when targeting BSD. ### Dependencies - Upgraded to `tauri-utils@2.8.2` - Upgraded to `tauri-runtime@2.10.0` - [`75057c7c0`](https://www.github.com/tauri-apps/tauri/commit/75057c7c08f0d4d3dd8d10cea4e2217e5d61fe1a) ([#14778](https://www.github.com/tauri-apps/tauri/pull/14778) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) **Breaking Change** for `with_webview` users: Updated webkit2gtk-rs crates to `v2.0.2`. - [`75057c7c0`](https://www.github.com/tauri-apps/tauri/commit/75057c7c08f0d4d3dd8d10cea4e2217e5d61fe1a) ([#14778](https://www.github.com/tauri-apps/tauri/pull/14778) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Update wry to `v0.54`. ## \[2.9.3] ### Bug Fixes - [`251203b89`](https://www.github.com/tauri-apps/tauri/commit/251203b8963419cb3b40741767393e8f3c909ef9) ([#14637](https://www.github.com/tauri-apps/tauri/pull/14637) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix `Monitor::work_area` returns logical position and size inside the `PhysicalRect` on Linux ## \[2.9.2] ### Dependencies - Upgraded to `tauri-utils@2.8.1` - Upgraded to `tauri-runtime@2.9.2` ## \[2.9.1] ### Bug Fixes - [`4b6b8690a`](https://www.github.com/tauri-apps/tauri/commit/4b6b8690ab886ebdf1307951cffbe03e31280baa) ([#14347](https://www.github.com/tauri-apps/tauri/pull/14347) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused docs.rs builds to fail. No user facing changes. ### Dependencies - Upgraded to `tauri-runtime@2.9.1` ## \[2.9.0] ### New Features - [`f5851ee00`](https://www.github.com/tauri-apps/tauri/commit/f5851ee00d6d1f4d560a220ca5a728fedd525092) ([#14089](https://www.github.com/tauri-apps/tauri/pull/14089)) Adds the `scroll_bar_style` option to the Webview and WebviewWindow builders. The possible values for this option are gated behind conditional compilation flags, and will need to be applied using conditional compilation if customised. ### Bug Fixes - [`684791efa`](https://www.github.com/tauri-apps/tauri/commit/684791efa6f3c671a0435d456ac208bca871d8c1) ([#14276](https://www.github.com/tauri-apps/tauri/pull/14276)) Always try to create macOS WebKit webview, even if webkit runtime doesn't get detected correctly ### Dependencies - Upgraded to `tauri-utils@2.8.0` - Upgraded to `tauri-runtime@2.9.0` ## \[2.8.1] ### Bug Fixes - [`03e7c1193`](https://www.github.com/tauri-apps/tauri/commit/03e7c1193208716170f120a1d4a39cea0bc21064) ([#14080](https://www.github.com/tauri-apps/tauri/pull/14080) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Ignore initial navigation to `about:blank` so `on_new_window` does not give a warning on first navigation on macOS. ## \[2.8.0] ### New Features - [`68874c68c`](https://www.github.com/tauri-apps/tauri/commit/68874c68c566638b4c21a3aa67844d1bdaeb6dab) ([#13564](https://www.github.com/tauri-apps/tauri/pull/13564) by [@robertrpf](https://www.github.com/tauri-apps/tauri/../../robertrpf)) Add window focusable attribute and set_focusable API. - [`22d6bcacb`](https://www.github.com/tauri-apps/tauri/commit/22d6bcacbb2001eb292ebd8c5d021447700f9512) ([#14008](https://www.github.com/tauri-apps/tauri/pull/14008) by [@WSH032](https://www.github.com/tauri-apps/tauri/../../WSH032)) Implement `App::set_device_event_filter` for `AppHandle` also. - [`33d0b3f0c`](https://www.github.com/tauri-apps/tauri/commit/33d0b3f0c133edebb1c716e2f5942d70509ae347) ([#13876](https://www.github.com/tauri-apps/tauri/pull/13876) by [@thlstsul](https://www.github.com/tauri-apps/tauri/../../thlstsul)) Added `WebviewBuilder::on_document_title_changed` and `WebviewWindowBuilder::on_document_title_changed`. - [`33d0b3f0c`](https://www.github.com/tauri-apps/tauri/commit/33d0b3f0c133edebb1c716e2f5942d70509ae347) ([#13876](https://www.github.com/tauri-apps/tauri/pull/13876) by [@thlstsul](https://www.github.com/tauri-apps/tauri/../../thlstsul)) Added `WebviewBuilder::on_new_window` and `WebviewWindowBuilder::on_new_window`. - [`dfadcb764`](https://www.github.com/tauri-apps/tauri/commit/dfadcb764bdf84089a5487005a7b4f3b7cf09494) ([#13661](https://www.github.com/tauri-apps/tauri/pull/13661) by [@WSH032](https://www.github.com/tauri-apps/tauri/../../WSH032)) Added `WebviewDispatch::set_cookie()` and `WebviewDispatch::delete_cookie()`. - [`5110a762e`](https://www.github.com/tauri-apps/tauri/commit/5110a762e9db978a28a15400bf76e3c864da2a86) ([#13830](https://www.github.com/tauri-apps/tauri/pull/13830) by [@Sky-walkerX](https://www.github.com/tauri-apps/tauri/../../Sky-walkerX)) Added `Window::set_simple_fullscreen`. ### Bug Fixes - [`82e264552`](https://www.github.com/tauri-apps/tauri/commit/82e264552ed3e1d62135edc5803a2c5d92f9c5c7) ([#13968](https://www.github.com/tauri-apps/tauri/pull/13968) by [@s5bug](https://www.github.com/tauri-apps/tauri/../../s5bug)) Use WM_NCDESTROY instead of WM_DESTROY to free window userdata, fixing a double-free occurring in the Windows resizing handler for undecorated windows which caused STATUS_HEAP_CORRUPTION - [`196ace3c0`](https://www.github.com/tauri-apps/tauri/commit/196ace3c048f81b20ab4d38f09c2f200978722b8) ([#13970](https://www.github.com/tauri-apps/tauri/pull/13970) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Return `tauri_runtime::Error::CreateWindow` instead of panic on window creation failed ### Dependencies - Upgraded to `tauri-utils@2.7.0` - Upgraded to `tauri-runtime@2.8.0` ## \[2.7.2] ### What's Changed - [`3025d9095`](https://www.github.com/tauri-apps/tauri/commit/3025d90951bfa152fc6f4255ac5a3fdd0f6353ca) ([#13822](https://www.github.com/tauri-apps/tauri/pull/13822) by [@clearlysid](https://www.github.com/tauri-apps/tauri/../../clearlysid)) Makes some methods on `WindowIdStore`, `WindowsStore` and `WindowWrapper` public ### Dependencies - Upgraded to `tauri-utils@2.6.0` - Upgraded to `tauri-runtime@2.7.1` ## \[2.7.1] ### Bug Fixes - [`f010ca5e9`](https://www.github.com/tauri-apps/tauri/commit/f010ca5e9199e6baae65990ab75a83ea29e4fe18) ([#13719](https://www.github.com/tauri-apps/tauri/pull/13719) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed a compile error when using tauri without the `common-controls-v6` feature enabled. ## \[2.7.0] ### New Features - [`9c16eefa3`](https://www.github.com/tauri-apps/tauri/commit/9c16eefa319b4697bac1d1019bbb5f93eca63173) ([#13629](https://www.github.com/tauri-apps/tauri/pull/13629) by [@sftse](https://www.github.com/tauri-apps/tauri/../../sftse)) Added `x11` Cargo feature (enabled by default). Disabling it is useful for apps that only support Wayland, reducing its size. **NOTE**: When manually disabling tauri default features, you must enable the `x11` feature to support it. ### Enhancements - [`96ecfca42`](https://www.github.com/tauri-apps/tauri/commit/96ecfca428e4e5d9ff5d5eeed3f94a06a466ed02) ([#13406](https://www.github.com/tauri-apps/tauri/pull/13406) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Check if the webview runtime is accessible when creating a webview, returning an error if it doesn't. ### Bug Fixes - [`f0662e41f`](https://www.github.com/tauri-apps/tauri/commit/f0662e41f4f78ec5a3f88aa76a7367d37d740291) ([#13365](https://www.github.com/tauri-apps/tauri/pull/13365) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix monitor check on the window prevent overflow implementation. - [`4acae1ec0`](https://www.github.com/tauri-apps/tauri/commit/4acae1ec02f2e0b0501d6b79b0bb862893296abd) ([#13443](https://www.github.com/tauri-apps/tauri/pull/13443) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix `AppHandle::set_theme` crashes or has no effect on macOS if not ran on main thread - [`78d15e892`](https://www.github.com/tauri-apps/tauri/commit/78d15e892d30fb3f8494f0c00685fb455740a181) ([#13558](https://www.github.com/tauri-apps/tauri/pull/13558) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Allow web fullscreen APIs to work on Windows (e.g. `video.requestFullscreen` and `document.exitFullscreen`) ### Dependencies - Upgraded to `tauri-utils@2.5.0` - Upgraded to `tauri-runtime@2.7.0` - [`9c16eefa3`](https://www.github.com/tauri-apps/tauri/commit/9c16eefa319b4697bac1d1019bbb5f93eca63173) ([#13629](https://www.github.com/tauri-apps/tauri/pull/13629) by [@sftse](https://www.github.com/tauri-apps/tauri/../../sftse)) Updated tao to 0.34, wry to 0.52 and webview2-com to 0.38. ## \[2.6.0] ### New Features - [`dd4f13ce4`](https://www.github.com/tauri-apps/tauri/commit/dd4f13ce4b3cd89cde2fa3f18a063c272f215621) ([#13185](https://www.github.com/tauri-apps/tauri/pull/13185)) MacOS: Add `set_dock_visibility` method to support setting the visibility of the application in the dock. - [`ea36294cb`](https://www.github.com/tauri-apps/tauri/commit/ea36294cbca98f7725c91d1464fd92e77c89698a) ([#13208](https://www.github.com/tauri-apps/tauri/pull/13208)) Added `WebviewAttributes::input_accessory_view_builder` on iOS. - [`c1cd0a2dd`](https://www.github.com/tauri-apps/tauri/commit/c1cd0a2ddb5bc3e99451cbe399b5fc9f0035f571) ([#13090](https://www.github.com/tauri-apps/tauri/pull/13090)) macOS/iOS: add option to disable or enable link previews when building a webview (the webkit api has it enabled by default) - `WebViewBuilder.allow_link_preview(allow_link_preview: bool)` - `WebviewWindowBuilder.allow_link_preview(allow_link_preview: bool)` - [`b072e2b29`](https://www.github.com/tauri-apps/tauri/commit/b072e2b2967640ae4fa1af466ae878c156551edd) ([#9687](https://www.github.com/tauri-apps/tauri/pull/9687)) Add `preventOverflow` config option to prevent the window from overflowing the monitor size on creation ### Bug Fixes - [`07953fb9c`](https://www.github.com/tauri-apps/tauri/commit/07953fb9c3dc09e86657aa16020978e89b03ed56) ([#13222](https://www.github.com/tauri-apps/tauri/pull/13222)) Emit `WindowEvent::Focused` events when using the multiwebview (unstable feature flag) mode on Windows. ### Dependencies - Upgraded to `tauri-utils@2.4.0` - Upgraded to `tauri-runtime@2.6.0` - [`bb5faa21f`](https://www.github.com/tauri-apps/tauri/commit/bb5faa21f418dd765ce81b495b56e9c519251b6d) ([#13163](https://www.github.com/tauri-apps/tauri/pull/13163)) Update tao to 0.33. - [`bb5faa21f`](https://www.github.com/tauri-apps/tauri/commit/bb5faa21f418dd765ce81b495b56e9c519251b6d) ([#13163](https://www.github.com/tauri-apps/tauri/pull/13163)) Update webview2-com to 0.37. - [`bb5faa21f`](https://www.github.com/tauri-apps/tauri/commit/bb5faa21f418dd765ce81b495b56e9c519251b6d) ([#13163](https://www.github.com/tauri-apps/tauri/pull/13163)) Update windows to 0.61. - [`bb5faa21f`](https://www.github.com/tauri-apps/tauri/commit/bb5faa21f418dd765ce81b495b56e9c519251b6d) ([#13163](https://www.github.com/tauri-apps/tauri/pull/13163)) Update wry to 0.51. ## \[2.5.1] ### Dependencies - Upgraded to `tauri-utils@2.3.1` - Upgraded to `tauri-runtime@2.5.1` ## \[2.5.0] ### New Features - [`be2e6b85f`](https://www.github.com/tauri-apps/tauri/commit/be2e6b85fed226732b4a98f68cc5d72b4f8f5a13) ([#12944](https://www.github.com/tauri-apps/tauri/pull/12944) by [@Simon-Laux](https://www.github.com/tauri-apps/tauri/../../Simon-Laux)) add `Window.is_always_on_top()` and `WebviewWindow.is_always_on_top()` - [`20c190691`](https://www.github.com/tauri-apps/tauri/commit/20c19069125c89b2d45a2127278c9ffc2df35fc2) ([#12821](https://www.github.com/tauri-apps/tauri/pull/12821) by [@Simon-Laux](https://www.github.com/tauri-apps/tauri/../../Simon-Laux)) Add `WebviewBuilder.disable_javascript` and `WebviewWindowBuilder.disable_javascript` api to disable JavaScript. - [`658e5f5d1`](https://www.github.com/tauri-apps/tauri/commit/658e5f5d1dc1bd970ae572a42447448d064a7fee) ([#12668](https://www.github.com/tauri-apps/tauri/pull/12668) by [@thomaseizinger](https://www.github.com/tauri-apps/tauri/../../thomaseizinger)) Add `App::run_return` function. Contrary to `App::run`, this will **not** exit the process but instead return the requested exit-code. This allows the host app to perform further cleanup after Tauri has exited. `App::run_return` is not available on iOS and fallbacks to the regular `App::run` functionality. The `App::run_iteration` function is deprecated as part of this because calling it in a loop - as suggested by the name - will cause a busy-loop. - [`c698a6d6f`](https://www.github.com/tauri-apps/tauri/commit/c698a6d6f3e02548444a4aa0e5220bbc6fc05c74) ([#12818](https://www.github.com/tauri-apps/tauri/pull/12818) by [@Simon-Laux](https://www.github.com/tauri-apps/tauri/../../Simon-Laux)) feat: add `Webview.reload` and `WebviewWindow.reload` - [`30f5a1553`](https://www.github.com/tauri-apps/tauri/commit/30f5a1553d3c0ce460c9006764200a9210915a44) ([#12366](https://www.github.com/tauri-apps/tauri/pull/12366) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Added `trafficLightPosition` window configuration to set the traffic light buttons position on macOS. - [`30f5a1553`](https://www.github.com/tauri-apps/tauri/commit/30f5a1553d3c0ce460c9006764200a9210915a44) ([#12366](https://www.github.com/tauri-apps/tauri/pull/12366) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Added `traffic_light_position` window builder method to set the traffic light buttons position on macOS. - [`cedb24d49`](https://www.github.com/tauri-apps/tauri/commit/cedb24d494b84111daa3206c05196c8b89f1e994) ([#12665](https://www.github.com/tauri-apps/tauri/pull/12665) by [@charrondev](https://www.github.com/tauri-apps/tauri/../../charrondev)) Added `WebviewDispatch::cookies()` and `WebviewDispatch::cookies_for_url()`. ### Dependencies - Upgraded to `tauri-runtime@2.5.0` - Upgraded to `tauri-utils@2.3.0` ## \[2.4.1] ### Bug Fixes - [`e103e87f1`](https://www.github.com/tauri-apps/tauri/commit/e103e87f155cf7fa51baa0a48a476463216c0d62) ([#12848](https://www.github.com/tauri-apps/tauri/pull/12848) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix crash on Windows because of missing functions on older Windows systems, regression in 2.3.0 ## \[2.4.0] ### Enhancements - [`a2d36b8c3`](https://www.github.com/tauri-apps/tauri/commit/a2d36b8c34a8dcfc6736797ca5cd4665faf75e7e) ([#12181](https://www.github.com/tauri-apps/tauri/pull/12181) by [@bastiankistner](https://www.github.com/tauri-apps/tauri/../../bastiankistner)) Add an option to change the default background throttling policy (currently for WebKit only). - [`d6520a21c`](https://www.github.com/tauri-apps/tauri/commit/d6520a21ce02c3e2be2955999946c2cb7bdb07aa) ([#12541](https://www.github.com/tauri-apps/tauri/pull/12541) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Updated `wry` to 0.50, `windows` to 0.60, `webview2-com` to 0.36, and `objc2` to 0.6. This can be a **breaking change** if you use the `with_webview` API! ### Dependencies - Upgraded to `tauri-runtime@2.4.0` - Upgraded to `tauri-utils@2.2.0` ## \[2.3.0] ### New Features - [`18bd639f6`](https://www.github.com/tauri-apps/tauri/commit/18bd639f6e22c0188aa219739f367b5bf5ab0398) ([#11798](https://www.github.com/tauri-apps/tauri/pull/11798) by [@lars-berger](https://www.github.com/tauri-apps/tauri/../../lars-berger)) Add `WebviewWindowBuilder/WebviewBuilder::data_store_identifier` on macOS. - [`dc4d79477`](https://www.github.com/tauri-apps/tauri/commit/dc4d79477665bc3bfefb4048772414cf5d78e3df) ([#11628](https://www.github.com/tauri-apps/tauri/pull/11628) by [@SpikeHD](https://www.github.com/tauri-apps/tauri/../../SpikeHD)) Add `WebviewWindowBuilder/WebviewBuilder::extensions_path` on Linux and Windows. - [`020ea0556`](https://www.github.com/tauri-apps/tauri/commit/020ea05561348dcd6d2a7df358f8a5190f661ba2) ([#11661](https://www.github.com/tauri-apps/tauri/pull/11661) by [@ahqsoftwares](https://www.github.com/tauri-apps/tauri/../../ahqsoftwares)) Add badging APIs: - `Window/WebviewWindow::set_badge_count` for Linux, macOS and IOS. - `Window/WebviewWindow::set_overlay_icon` for Windows Only. - `Window/WebviewWindow::set_badge_label`for macOS Only. ### Dependencies - Upgraded to `tauri-runtime@2.3.0` - Upgraded to `tauri-utils@2.1.1` ## \[2.2.0] ### New Features - [`4d545ab3c`](https://www.github.com/tauri-apps/tauri/commit/4d545ab3ca228c8a21b966b709f84a0da2864479) ([#11486](https://www.github.com/tauri-apps/tauri/pull/11486) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Added `Window::set_background_color` and `WindowBuilder::background_color`. - [`f37e97d41`](https://www.github.com/tauri-apps/tauri/commit/f37e97d410c4a219e99f97692da05ca9d8e0ba3a) ([#11477](https://www.github.com/tauri-apps/tauri/pull/11477) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `WebviewWindowBuilder/WebviewBuilder::use_https_scheme` to choose whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android - [`cbc095ec5`](https://www.github.com/tauri-apps/tauri/commit/cbc095ec5fe7de29b5c9265576d4e071ec159c1c) ([#11451](https://www.github.com/tauri-apps/tauri/pull/11451) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `WebviewWindowBuilder::devtools` and `WebviewBuilder::devtools` to enable or disable devtools for a specific webview. - [`2a75c64b5`](https://www.github.com/tauri-apps/tauri/commit/2a75c64b5431284e7340e8743d4ea56a62c75466) ([#11469](https://www.github.com/tauri-apps/tauri/pull/11469) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Added `WindowBuilder/WebviewWindowBuilder::window_classname` method to specify the name of the window class on Windows. ### Bug Fixes - [`229d7f8e2`](https://www.github.com/tauri-apps/tauri/commit/229d7f8e220cc8d5ca06eff1ed85cb7d047c1d6c) ([#11616](https://www.github.com/tauri-apps/tauri/pull/11616) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix regression in creating child webviews on macOS and Windows, covering the whole window. - [`8c6d1e8e6`](https://www.github.com/tauri-apps/tauri/commit/8c6d1e8e6c852667bb223b5f4823948868c26d98) ([#11401](https://www.github.com/tauri-apps/tauri/pull/11401) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix `App/AppHandle/Window/Webview/WebviewWindow::cursor_position` getter method failing on Linux with `GDK may only be used from the main thread`. - [`129414faa`](https://www.github.com/tauri-apps/tauri/commit/129414faa4e027c9035d56614682cacc0335a6a0) ([#11569](https://www.github.com/tauri-apps/tauri/pull/11569) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix webview not focused by default. ### Dependencies - Upgraded to `tauri-utils@2.1.0` - Upgraded to `tauri-runtime@2.2.0` ## \[2.1.2] ### Dependencies - Upgraded to `tauri-utils@2.0.2` ## \[2.1.1] ### Bug Fixes - [`ef2482dde`](https://www.github.com/tauri-apps/tauri/commit/ef2482ddecf533181211ee435931fac650495bc5) ([#11366](https://www.github.com/tauri-apps/tauri/pull/11366)) Update wry to 0.46.1 to fix a crash on macOS older than Sequoia. ## \[2.1.0] ### Bug Fixes - [`2d087ee4b`](https://www.github.com/tauri-apps/tauri/commit/2d087ee4b7d3e8849933f81284e4f5ed1aaa6455) ([#11268](https://www.github.com/tauri-apps/tauri/pull/11268) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) On Linux, fix commands, that use `Webview` or `WebviewWindow` as an argument, receiving an incorrect webview when using multi webviews. - [`2d087ee4b`](https://www.github.com/tauri-apps/tauri/commit/2d087ee4b7d3e8849933f81284e4f5ed1aaa6455) ([#11268](https://www.github.com/tauri-apps/tauri/pull/11268) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) On Linux, fix events only emitted to first webview only when using multi webviews. - [`2d087ee4b`](https://www.github.com/tauri-apps/tauri/commit/2d087ee4b7d3e8849933f81284e4f5ed1aaa6455) ([#11268](https://www.github.com/tauri-apps/tauri/pull/11268) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) On Linux, fix custom protocols receiving an incorrect webview label when using multi webviews ### Dependencies - Upgraded to `tauri-runtime@2.1.0` ## \[2.0.1] ### What's Changed - [`0ab2b3306`](https://www.github.com/tauri-apps/tauri/commit/0ab2b330644b6419f6cee1d5377bfb5cdda2ccf9) ([#11205](https://www.github.com/tauri-apps/tauri/pull/11205) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Downgrade MSRV to 1.77.2 to support Windows 7. ### Dependencies - Upgraded to `tauri-utils@2.0.1` - Upgraded to `tauri-runtime@2.0.1` ## \[2.0.0] ### What's Changed - [`382ed482b`](https://www.github.com/tauri-apps/tauri/commit/382ed482bd08157c39e62f9a0aaad8802f1092cb) Bump MSRV to 1.78. - [`637285790`](https://www.github.com/tauri-apps/tauri/commit/6372857905ae9c0aedb7f482ddf6cf9f9836c9f2) Promote to v2 stable! ### Dependencies - Upgraded to `tauri-utils@2.0.0` - Upgraded to `tauri-runtime@2.0.0` ## \[2.0.0-rc.14] ### New Features - [`a247170e1`](https://www.github.com/tauri-apps/tauri/commit/a247170e1f620a9b012274b11cfe51e90327d6e9) ([#11056](https://www.github.com/tauri-apps/tauri/pull/11056) by [@SpikeHD](https://www.github.com/tauri-apps/tauri/../../SpikeHD)) Expose the ability to enabled browser extensions in WebView2 on Windows. - [`9014a3f17`](https://www.github.com/tauri-apps/tauri/commit/9014a3f1765ca406ea5c3e5224267a79c52cd53d) ([#11066](https://www.github.com/tauri-apps/tauri/pull/11066) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `WebviewWindow::clear_all_browsing_data` and `Webview::clear_all_browsing_data` to clear the webview browsing data. - [`95df53a2e`](https://www.github.com/tauri-apps/tauri/commit/95df53a2ed96873cd35a4b14a5e312d07e4e3004) ([#11143](https://www.github.com/tauri-apps/tauri/pull/11143) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Add the ability to set theme dynamically using `Window::set_theme`, `App::set_theme` - [`d9d2502b4`](https://www.github.com/tauri-apps/tauri/commit/d9d2502b41e39efde679e30c8955006e2ba9ea64) ([#11140](https://www.github.com/tauri-apps/tauri/pull/11140) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `WebviewDispatch::hide` and `WebviewDispatch::show` methods. - [`de7414aab`](https://www.github.com/tauri-apps/tauri/commit/de7414aab935e45540594ea930eb60bae4dbc979) ([#11154](https://www.github.com/tauri-apps/tauri/pull/11154) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `Window::set_enabled` and `Window::is_enabled` methods ### Bug Fixes - [`62b3a5cd1`](https://www.github.com/tauri-apps/tauri/commit/62b3a5cd1c804440c2130ab36cc3eadb3baf61cb) ([#11043](https://www.github.com/tauri-apps/tauri/pull/11043) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix `localStorage` not shared between webviews that use the same data directory. ### Dependencies - Upgraded to `tauri-runtime@2.0.0-rc.13` - Upgraded to `tauri-utils@2.0.0-rc.13` ## \[2.0.0-rc.13] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.12` - Upgraded to `tauri-runtime@2.0.0-rc.12` ## \[2.0.0-rc.12] ### Enhancements - [`bc4804d48`](https://www.github.com/tauri-apps/tauri/commit/bc4804d4841efefd57fd1f3e147550a3340e2b31) ([#10924](https://www.github.com/tauri-apps/tauri/pull/10924) by [@madsmtm](https://www.github.com/tauri-apps/tauri/../../madsmtm)) Use `objc2` internally and in examples, leading to better memory safety. ### Breaking Changes - [`bc4804d48`](https://www.github.com/tauri-apps/tauri/commit/bc4804d4841efefd57fd1f3e147550a3340e2b31) ([#10924](https://www.github.com/tauri-apps/tauri/pull/10924) by [@madsmtm](https://www.github.com/tauri-apps/tauri/../../madsmtm)) Change the pointer type of `PlatformWebview`'s `inner`, `controller`, `ns_window` and `view_controller` to `c_void`, to avoid publically depending on `objc`. ## \[2.0.0-rc.11] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.11` - Upgraded to `tauri-runtime@2.0.0-rc.11` ## \[2.0.0-rc.10] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.10` - Upgraded to `tauri-runtime@2.0.0-rc.10` ## \[2.0.0-rc.9] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.9` - Upgraded to `tauri-runtime@2.0.0-rc.9` ## \[2.0.0-rc.8] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.8` - Upgraded to `tauri-runtime@2.0.0-rc.8` - [`77056b194`](https://www.github.com/tauri-apps/tauri/commit/77056b194a2aa8be1b9865d707b741a6ed72ec56) ([#10895](https://www.github.com/tauri-apps/tauri/pull/10895) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Update tao to 0.30 and wry to 0.43. ### Breaking Changes - [`5048a7293`](https://www.github.com/tauri-apps/tauri/commit/5048a7293b87b5b93aaefd42dedc0e551e08086c) ([#10840](https://www.github.com/tauri-apps/tauri/pull/10840) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) The `linux-ipc-protocol` feature is now always enabled, so the Cargo feature flag was removed. This increases the minimum webkit2gtk version to a release that does not affect the minimum target Linux distros for Tauri apps. ## \[2.0.0-rc.7] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.7` - Upgraded to `tauri-runtime@2.0.0-rc.7` ## \[2.0.0-rc.6] ### Bug Fixes - [`793ee0531`](https://www.github.com/tauri-apps/tauri/commit/793ee0531730597e6008c9c0dedabbab7a2bef53) ([#10700](https://www.github.com/tauri-apps/tauri/pull/10700) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Allow hyphens and underscores on app identifiers. ### What's Changed - [`f4d5241b3`](https://www.github.com/tauri-apps/tauri/commit/f4d5241b377d0f7a1b58100ee19f7843384634ac) ([#10731](https://www.github.com/tauri-apps/tauri/pull/10731) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Update documentation icon path. ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.6` - Upgraded to `tauri-runtime@2.0.0-rc.6` ## \[2.0.0-rc.5] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.5` - Upgraded to `tauri-runtime@2.0.0-rc.5` ## \[2.0.0-rc.4] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.4` - Upgraded to `tauri-runtime@2.0.0-rc.4` ## \[2.0.0-rc.3] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.3` - Upgraded to `tauri-runtime@2.0.0-rc.3` - [`d39c392b7`](https://www.github.com/tauri-apps/tauri/commit/d39c392b7cec746da423211f9c74632abe4b6af5) ([#10655](https://www.github.com/tauri-apps/tauri/pull/10655) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Update `tao` to 0.29 and `wry` to 0.42. ## \[2.0.0-rc.2] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.2` - Upgraded to `tauri-runtime@2.0.0-rc.2` ## \[2.0.0-rc.1] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.1` - Upgraded to `tauri-runtime@2.0.0-rc.1` ## \[2.0.0-rc.0] ### Dependencies - Upgraded to `tauri-utils@2.0.0-rc.0` - Upgraded to `tauri-runtime@2.0.0-rc.0` ## \[2.0.0-beta.21] ### What's Changed - [`9546548ec`](https://www.github.com/tauri-apps/tauri/commit/9546548ec0c83ba620b1bc9d1d424a7009d0b423) ([#10297](https://www.github.com/tauri-apps/tauri/pull/10297) by [@pewsheen](https://www.github.com/tauri-apps/tauri/../../pewsheen)) On macOS, set default titlebar style to `Visible` to prevent webview move out of the view. - [`da25f7353`](https://www.github.com/tauri-apps/tauri/commit/da25f7353070477ba969851e974379d7666d6806) ([#10242](https://www.github.com/tauri-apps/tauri/pull/10242) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `inner_size_constraints` method on `WindowBuilder` trait and `set_size_constraints` method on `WindowDispatch` trait. ### Dependencies - Upgraded to `tauri-runtime@2.0.0-beta.21` ## \[2.0.0-beta.20] ### Bug Fixes - [`afb102c59`](https://www.github.com/tauri-apps/tauri/commit/afb102c59ba0de27e330589269001e0d2a01576d) ([#10211](https://www.github.com/tauri-apps/tauri/pull/10211) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix window edge not working after setting resizable false and decorated false dynamically ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.19` - Upgraded to `tauri-runtime@2.0.0-beta.20` ## \[2.0.0-beta.19] ### Bug Fixes - [`f29b78811`](https://www.github.com/tauri-apps/tauri/commit/f29b78811080bc8313459f34545152d939c62bf6) ([#9862](https://www.github.com/tauri-apps/tauri/pull/9862)) On Windows, handle resizing undecorated windows natively which improves performance and fixes a couple of annoyances with previous JS implementation: - No more cursor flickering when moving the cursor across an edge. - Can resize from top even when `data-tauri-drag-region` element exists there. - Upon starting rezing, clicks don't go through elements behind it so no longer accidental clicks. ### What's Changed - [`669b9c6b5`](https://www.github.com/tauri-apps/tauri/commit/669b9c6b5af791129b77ee440dacaa98288c906b) ([#9621](https://www.github.com/tauri-apps/tauri/pull/9621)) Set the gtk application to the identifier defined in `tauri.conf.json` to ensure the app uniqueness. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.18` - Upgraded to `tauri-runtime@2.0.0-beta.19` - [`d4c908cfb`](https://www.github.com/tauri-apps/tauri/commit/d4c908cfb8c567abdaf99b85f65f482ea81967e5) ([#10048](https://www.github.com/tauri-apps/tauri/pull/10048)) Update `windows` crate to version `0.57` and `webview2-com` crate to version `0.31` ## \[2.0.0-beta.18] ### Enhancements - [`276c4b143`](https://www.github.com/tauri-apps/tauri/commit/276c4b14385e17cff15a2e5b57fd2a7cddef9f08)([#9832](https://www.github.com/tauri-apps/tauri/pull/9832)) Added `WindowBuilder::get_theme`. ### What's Changed - [`9ac930380`](https://www.github.com/tauri-apps/tauri/commit/9ac930380a5df3fe700e68e75df8684d261ca292)([#9850](https://www.github.com/tauri-apps/tauri/pull/9850)) Emit `cargo:rustc-check-cfg` instruction so Cargo validates custom cfg attributes on Rust 1.80 (or nightly-2024-05-05). ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.17` - Upgraded to `tauri-runtime@2.0.0-beta.18` ## \[2.0.0-beta.17] ### Security fixes - [`d950ac123`](https://www.github.com/tauri-apps/tauri/commit/d950ac1239817d17324c035e5c4769ee71fc197d) Only process IPC commands from the main frame. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.16` - Upgraded to `tauri-runtime@2.0.0-beta.17` ## \[2.0.0-beta.16] ### New Features - [`78839b6d2`](https://www.github.com/tauri-apps/tauri/commit/78839b6d2f1005a5e6e1a54b0305136bae0c3a7c)([#4865](https://www.github.com/tauri-apps/tauri/pull/4865)) Add `RunEvent::Reopen` for handle click on dock icon on macOS. ### Bug Fixes - [`c0bcc6c0b`](https://www.github.com/tauri-apps/tauri/commit/c0bcc6c0b74ef7167de85002a5c29b6f731bae41)([#9717](https://www.github.com/tauri-apps/tauri/pull/9717)) Fixes redraw tracing span not closing. ### What's Changed - [`783ef0f2d`](https://www.github.com/tauri-apps/tauri/commit/783ef0f2d331f520fa827c3112f36c0b519b9292)([#9647](https://www.github.com/tauri-apps/tauri/pull/9647)) Changed `WebviewDispatch::url` getter to return a result. ### Dependencies - Upgraded to `tauri-runtime@2.0.0-beta.16` - Upgraded to `tauri-utils@2.0.0-beta.15` ## \[2.0.0-beta.15] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.14` - Upgraded to `tauri-runtime@2.0.0-beta.15` ## \[2.0.0-beta.14] ### New Features - [`477bb8cd4`](https://www.github.com/tauri-apps/tauri/commit/477bb8cd4ea88ade3f6c1f268ad1701a68150161)([#9297](https://www.github.com/tauri-apps/tauri/pull/9297)) Add `App/AppHandle/Window/Webview/WebviewWindow::cursor_position` getter to get the current cursor position. ### Dependencies - Upgraded to `tauri-runtime@2.0.0-beta.14` ## \[2.0.0-beta.13] ### What's Changed - [`005fe8ce1`](https://www.github.com/tauri-apps/tauri/commit/005fe8ce1ef71ea46a7d86f98bdf397ca81eb920)([#9410](https://www.github.com/tauri-apps/tauri/pull/9410)) Fix `closable`, `maximizable` and `minimizable` options not taking effect when used in tauri.conf.json or from JS APIs. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.13` - Upgraded to `tauri-runtime@2.0.0-beta.13` ## \[2.0.0-beta.12] ### New Features - [`58a7a552d`](https://www.github.com/tauri-apps/tauri/commit/58a7a552d739b77b71d61af11c53f7f2dc7a6e7e)([#9378](https://www.github.com/tauri-apps/tauri/pull/9378)) Added the `set_zoom` function to the webview API. - [`58a7a552d`](https://www.github.com/tauri-apps/tauri/commit/58a7a552d739b77b71d61af11c53f7f2dc7a6e7e)([#9378](https://www.github.com/tauri-apps/tauri/pull/9378)) Add `zoom_hotkeys_enabled` to enable browser native zoom controls on creating webviews. ### Bug Fixes - [`2f20fdf1d`](https://www.github.com/tauri-apps/tauri/commit/2f20fdf1d6b92fa8b9b38caf7321c3ce3e895f1b)([#9361](https://www.github.com/tauri-apps/tauri/pull/9361)) Fixes an issue causing compilation to fail for i686 and armv7 32-bit targets. - [`4c2e7477e`](https://www.github.com/tauri-apps/tauri/commit/4c2e7477e6869e2ce0578265825bbd42a5f28393)([#9309](https://www.github.com/tauri-apps/tauri/pull/9309)) Fix window centering not taking taskbar into account on Windows - [`02eaf0787`](https://www.github.com/tauri-apps/tauri/commit/02eaf07872b90225eead22ecdd6ff0a9ed5dd0ff)([#9428](https://www.github.com/tauri-apps/tauri/pull/9428)) Fixes `inner_size` crash when the window has no webviews. - [`f22ea2998`](https://www.github.com/tauri-apps/tauri/commit/f22ea2998619cc09c2d426f7b42211a80eed578e)([#9465](https://www.github.com/tauri-apps/tauri/pull/9465)) Revert the [fix](https://github.com/tauri-apps/tauri/pull/9246) for webview's visibility doesn't change with the app window on Windows as it caused white flashes on show/restore. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.12` - Upgraded to `tauri-runtime@2.0.0-beta.12` ## \[2.0.0-beta.11] ### Bug Fixes - [`4c0c780e0`](https://www.github.com/tauri-apps/tauri/commit/4c0c780e00d8851be38cb1c22f636d9e4ed34a23)([#2690](https://www.github.com/tauri-apps/tauri/pull/2690)) Fix window inner size evaluation on macOS. - [`5bd47b446`](https://www.github.com/tauri-apps/tauri/commit/5bd47b44673f74b1b4e8d704b7a95539915ede76)([#9246](https://www.github.com/tauri-apps/tauri/pull/9246)) Fix webview's visibility doesn't change with the app window ### What's Changed - [`06833f4fa`](https://www.github.com/tauri-apps/tauri/commit/06833f4fa8e63ecc55fe3fc874a9e397e77a5709)([#9100](https://www.github.com/tauri-apps/tauri/pull/9100)) Updated `http` crate to `1.1` ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.11` - Upgraded to `tauri-runtime@2.0.0-beta.11` - [`06833f4fa`](https://www.github.com/tauri-apps/tauri/commit/06833f4fa8e63ecc55fe3fc874a9e397e77a5709)([#9100](https://www.github.com/tauri-apps/tauri/pull/9100)) Upgraded to `wry@0.38.0` ### Breaking Changes - [`06833f4fa`](https://www.github.com/tauri-apps/tauri/commit/06833f4fa8e63ecc55fe3fc874a9e397e77a5709)([#9100](https://www.github.com/tauri-apps/tauri/pull/9100)) The IPC handler closure now receives a `http::Request` instead of a String representing the request body. - [`06833f4fa`](https://www.github.com/tauri-apps/tauri/commit/06833f4fa8e63ecc55fe3fc874a9e397e77a5709)([#9100](https://www.github.com/tauri-apps/tauri/pull/9100)) Rename `FileDrop` to `DragDrop` on structs, enums and enum variants. Also renamed `file_drop` to `drag_drop` on fields and function names. ## \[2.0.0-beta.10] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.10` - Upgraded to `tauri-runtime@2.0.0-beta.10` ## \[2.0.0-beta.9] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.9` - Upgraded to `tauri-runtime@2.0.0-beta.9` ## \[2.0.0-beta.8] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.8` - Upgraded to `tauri-runtime@2.0.0-beta.8` ## \[2.0.0-beta.7] ### New Features - [`46de49aaa`](https://www.github.com/tauri-apps/tauri/commit/46de49aaad4a148fafc31d591be0e2ed12256507)([#9059](https://www.github.com/tauri-apps/tauri/pull/9059)) Added `set_auto_resize` method for the webview. ### Enhancements - [`46de49aaa`](https://www.github.com/tauri-apps/tauri/commit/46de49aaad4a148fafc31d591be0e2ed12256507)([#9059](https://www.github.com/tauri-apps/tauri/pull/9059)) When using the `unstable` feature flag, `WebviewWindow` will internally use the child webview interface for flexibility. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.7` - Upgraded to `tauri-runtime@2.0.0-beta.7` ## \[2.0.0-beta.6] ### Bug Fixes - [`222a96b7`](https://www.github.com/tauri-apps/tauri/commit/222a96b74b145fb48d3f0c109897962d56fae57a)([#8999](https://www.github.com/tauri-apps/tauri/pull/8999)) Fixes auto resize and positioning when using the multiwebview mode. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.6` - Upgraded to `tauri-runtime@2.0.0-beta.6` ## \[2.0.0-beta.5] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.5` - Upgraded to `tauri-runtime@2.0.0-beta.5` ## \[2.0.0-beta.4] ### New Features - [`fdcaf935`](https://www.github.com/tauri-apps/tauri/commit/fdcaf935fa75ecfa2806939c4faad4fe9e880386)([#8939](https://www.github.com/tauri-apps/tauri/pull/8939)) Added the `reparent` function to the webview API. ### Bug Fixes - [`6e3bd4b9`](https://www.github.com/tauri-apps/tauri/commit/6e3bd4b9f815ddde8b5eaf9f69991d4de80bb584)([#8942](https://www.github.com/tauri-apps/tauri/pull/8942)) Fix window centering not taking monitor scale into account ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.4` - Upgraded to `tauri-runtime@2.0.0-beta.4` - [`d75713ac`](https://www.github.com/tauri-apps/tauri/commit/d75713ac6c6115534e520303f5c38aa78704de69)([#8936](https://www.github.com/tauri-apps/tauri/pull/8936)) Upgraded to `wry@0.37.0` ## \[2.0.0-beta.3] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.3` - Upgraded to `tauri-runtime@2.0.0-beta.3` ## \[2.0.0-beta.2] ### What's Changed - [`76ce9f61`](https://www.github.com/tauri-apps/tauri/commit/76ce9f61dd3c5bdd589c7557543894e1f770dd16)([#3002](https://www.github.com/tauri-apps/tauri/pull/3002)) Enhance centering a newly created window, it will no longer jump to center after being visible. - [`16e550ec`](https://www.github.com/tauri-apps/tauri/commit/16e550ec1503765158cdc3bb2a20e70ec710e981)([#8844](https://www.github.com/tauri-apps/tauri/pull/8844)) Add `WebviewEvent`, `RunEvent::WebviewEvent` and `WebviewDispatch::on_webview_event`. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.2` - Upgraded to `tauri-runtime@2.0.0-beta.2` - [`2f55bfec`](https://www.github.com/tauri-apps/tauri/commit/2f55bfecbf0244f3b5aa1ad7622182fca3fcdcbb)([#8795](https://www.github.com/tauri-apps/tauri/pull/8795)) Update `wry` to 0.36. ### Breaking Changes - [`2f55bfec`](https://www.github.com/tauri-apps/tauri/commit/2f55bfecbf0244f3b5aa1ad7622182fca3fcdcbb)([#8795](https://www.github.com/tauri-apps/tauri/pull/8795)) Update raw-window-handle to 0.6. ## \[2.0.0-beta.1] ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.1` - Upgraded to `tauri-runtime@2.0.0-beta.1` ## \[2.0.0-beta.0] ### New Features - [`af610232`](https://www.github.com/tauri-apps/tauri/commit/af6102327376884364b2075b468bdf08ee0d02aa)([#8710](https://www.github.com/tauri-apps/tauri/pull/8710)) Added `Window::destroy` to force close a window. - [`c77b4032`](https://www.github.com/tauri-apps/tauri/commit/c77b40324ea9bf580871fc11aed69ba0c9b6b8cf)([#8280](https://www.github.com/tauri-apps/tauri/pull/8280)) Add multiwebview support behind the `unstable` feature flag. See `WindowBuilder` and `WebviewBuilder` for more information. - [`00e15675`](https://www.github.com/tauri-apps/tauri/commit/00e1567584721644797b587205187f9cbe4e5cd1)([#8708](https://www.github.com/tauri-apps/tauri/pull/8708)) Added `RuntimeHandle::request_exit` function. ### Bug Fixes - [`95da1a27`](https://www.github.com/tauri-apps/tauri/commit/95da1a27476e01e06f6ce0335df8535b662dd9c4)([#8713](https://www.github.com/tauri-apps/tauri/pull/8713)) Fix calling `set_activation_policy` when the event loop is running. ### What's Changed - [`9f8037c2`](https://www.github.com/tauri-apps/tauri/commit/9f8037c2882abac19582025001675370f0d7b669)([#8633](https://www.github.com/tauri-apps/tauri/pull/8633)) On Windows, fix decorated window not transparent initially until resized. - [`9eaeb5a8`](https://www.github.com/tauri-apps/tauri/commit/9eaeb5a8cd95ae24b5e66205bdc2763cb7f965ce)([#8622](https://www.github.com/tauri-apps/tauri/pull/8622)) Added `WindowBuilder::transient_for` and Renamed `WindowBuilder::owner_window` to `WindowBuilder::owner` and `WindowBuilder::parent_window` to `WindowBuilder::parent`. - [`7f033f6d`](https://www.github.com/tauri-apps/tauri/commit/7f033f6dcd54c69a4193765a5c1584755ba92c61)([#8537](https://www.github.com/tauri-apps/tauri/pull/8537)) Add `Window::start_resize_dragging` and `ResizeDirection` enum. - [`6639a579`](https://www.github.com/tauri-apps/tauri/commit/6639a579c76d45210f33a72d37e21d4c5a9d334b)([#8441](https://www.github.com/tauri-apps/tauri/pull/8441)) Added the `WindowConfig::proxy_url` `WebviewBuilder::proxy_url() / WebviewWindowBuilder::proxy_url()` options when creating a webview. ### Dependencies - Upgraded to `tauri-utils@2.0.0-beta.0` - Upgraded to `tauri-runtime@2.0.0-beta.0` - Upgrated to `tao@0.25`. ### Breaking Changes - [`af610232`](https://www.github.com/tauri-apps/tauri/commit/af6102327376884364b2075b468bdf08ee0d02aa)([#8710](https://www.github.com/tauri-apps/tauri/pull/8710)) `WindowDispatch::close` now triggers the `CloseRequested` flow. - [`9eaeb5a8`](https://www.github.com/tauri-apps/tauri/commit/9eaeb5a8cd95ae24b5e66205bdc2763cb7f965ce)([#8622](https://www.github.com/tauri-apps/tauri/pull/8622)) Changed `WindowBuilder::with_config` to take a reference to a `WindowConfig` instead of an owned value. ## \[1.0.0-alpha.9] ### New Features - [`29ced5ce`](https://www.github.com/tauri-apps/tauri/commit/29ced5ceec40b2934094ade2db9a8855f294e1d1)([#8159](https://www.github.com/tauri-apps/tauri/pull/8159)) Added download event closure via `PendingWindow::download_handler`. ### Enhancements - [`d621d343`](https://www.github.com/tauri-apps/tauri/commit/d621d3437ce3947175eecf345b2c6d1c4c7ce020)([#8607](https://www.github.com/tauri-apps/tauri/pull/8607)) Added tracing for window startup, plugins, `Window::eval`, events, IPC, updater and custom protocol request handlers behind the `tracing` feature flag. ### What's Changed - [`cb640c8e`](https://www.github.com/tauri-apps/tauri/commit/cb640c8e949a3d78d78162e2e61b51bf8afae983)([#8393](https://www.github.com/tauri-apps/tauri/pull/8393)) Fix `RunEvent::WindowEvent(event: WindowEvent::FileDrop(FileDropEvent))` never triggered and always prevent default OS behavior when `disable_file_drop_handler` is not used. ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.13` - Upgraded to `tauri-runtime@1.0.0-alpha.8` ## \[1.0.0-alpha.8] ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.12` - Upgraded to `tauri-runtime@1.0.0-alpha.7` ## \[1.0.0-alpha.7] ### Dependencies - Upgraded to `tauri-runtime@1.0.0-alpha.6` - [\`\`](https://www.github.com/tauri-apps/tauri/commit/undefined) Update to wry v0.35. ## \[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 - [`74d2464d`](https://www.github.com/tauri-apps/tauri/commit/74d2464d0e490fae341ad73bdf2964cf215fe6c5)([#8116](https://www.github.com/tauri-apps/tauri/pull/8116)) Added `on_page_load` hook for `PendingWindow`. ### Enhancements - [`c6c59cf2`](https://www.github.com/tauri-apps/tauri/commit/c6c59cf2373258b626b00a26f4de4331765dd487) Pull changes from Tauri 1.5 release. ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.10` - Upgraded to `tauri-runtime@1.0.0-alpha.4` - [`9580df1d`](https://www.github.com/tauri-apps/tauri/commit/9580df1d7b027befb9e5f025ea2cbaf2dcc82c8e)([#8084](https://www.github.com/tauri-apps/tauri/pull/8084)) Upgrade `gtk` to 0.18. - [`c7c2507d`](https://www.github.com/tauri-apps/tauri/commit/c7c2507da16a9beb71bf06745fe7ac1325ab7c2a)([#8035](https://www.github.com/tauri-apps/tauri/pull/8035)) Update `windows` to version `0.51` and `webview2-com` to version `0.27` - [`9580df1d`](https://www.github.com/tauri-apps/tauri/commit/9580df1d7b027befb9e5f025ea2cbaf2dcc82c8e)([#8084](https://www.github.com/tauri-apps/tauri/pull/8084)) Updated to wry@0.34, removing the `dox` feature flag. ## \[1.0.0-alpha.4] ### New Features - [`c085adda`](https://www.github.com/tauri-apps/tauri/commit/c085addab58ba851398373c6fd13f9cb026d71e8)([#8009](https://www.github.com/tauri-apps/tauri/pull/8009)) Added `set_progress_bar` to `Window`. - [`c1ec0f15`](https://www.github.com/tauri-apps/tauri/commit/c1ec0f155118527361dd5645d920becbc8afd569)([#7933](https://www.github.com/tauri-apps/tauri/pull/7933)) Added `Window::set_always_on_bottom` and the `always_on_bottom` option when creating a window. - [`880266a7`](https://www.github.com/tauri-apps/tauri/commit/880266a7f697e1fe58d685de3bb6836ce5251e92)([#8031](https://www.github.com/tauri-apps/tauri/pull/8031)) Bump the MSRV to 1.70. ### Dependencies - Upgraded to `tauri-runtime@1.0.0-alpha.3` - Upgraded to `tauri-utils@2.0.0-alpha.9` ### Breaking Changes - [`8b166e9b`](https://www.github.com/tauri-apps/tauri/commit/8b166e9bf82e69ddb3200a3a825614980bd8d433)([#7949](https://www.github.com/tauri-apps/tauri/pull/7949)) Check if automation is enabled with the `TAURI_WEBVIEW_AUTOMATION` environment variable instead of `TAURI_AUTOMATION`. - [`2558fab8`](https://www.github.com/tauri-apps/tauri/commit/2558fab861006936296e8511e43ccd69a38f61b0)([#7939](https://www.github.com/tauri-apps/tauri/pull/7939)) Changed `WebviewId` to be an alias for `u32` instead of `u64` ## \[1.0.0-alpha.3] ### Dependencies - Upgraded to `tauri-utils@2.0.0-alpha.8` - Upgraded to `tauri-runtime@1.0.0-alpha.2` ## \[1.0.0-alpha.2] ### Bug Fixes - [`d5074af5`](https://www.github.com/tauri-apps/tauri/commit/d5074af562b2b5cb6c5711442097c4058af32db6)([#7801](https://www.github.com/tauri-apps/tauri/pull/7801)) Fixes custom protocol not working on Windows. ## \[1.0.0-alpha.1] ### Enhancements - [`0d63732b`](https://www.github.com/tauri-apps/tauri/commit/0d63732b962e71b98430f8d7b34ea5b59a2e8bb4)([#7754](https://www.github.com/tauri-apps/tauri/pull/7754)) Update wry to 0.32 to include asynchronous custom protocol support. ### What's Changed - [`6177150b`](https://www.github.com/tauri-apps/tauri/commit/6177150b6f83b52ca359d6e20f7e540f7554e4eb)([#7601](https://www.github.com/tauri-apps/tauri/pull/7601)) Changed `FileDropEvent` to include drop and hover position. ### Dependencies - Upgraded to `tauri-runtime@1.0.0-alpha.1` ### Breaking Changes - [`0d63732b`](https://www.github.com/tauri-apps/tauri/commit/0d63732b962e71b98430f8d7b34ea5b59a2e8bb4)([#7754](https://www.github.com/tauri-apps/tauri/pull/7754)) `tauri-runtime` no longer implements its own HTTP types and relies on the `http` crate instead. ## \[1.0.0-alpha.0] ### New Features - [`7fb419c3`](https://www.github.com/tauri-apps/tauri/commit/7fb419c326aaf72ecd556d8404377444ebb200e7)([#7535](https://www.github.com/tauri-apps/tauri/pull/7535)) Add `Dispatch::default_vbox` - [`84c41597`](https://www.github.com/tauri-apps/tauri/commit/84c4159754b2e59244211ed9e1fc702d851a0562)([#6394](https://www.github.com/tauri-apps/tauri/pull/6394)) Added `primary_monitor` and `available_monitors` to `Runtime` and `RuntimeHandle`. - [`3b98141a`](https://www.github.com/tauri-apps/tauri/commit/3b98141aa26f74c641a4090874247b97079bd58a)([#3736](https://www.github.com/tauri-apps/tauri/pull/3736)) Added the `Opened` variant to `RunEvent`. - [`2a000e15`](https://www.github.com/tauri-apps/tauri/commit/2a000e150d02dff28c8b20ad097b29e209160045)([#7235](https://www.github.com/tauri-apps/tauri/pull/7235)) Implement navigate method ### Dependencies - Upgraded to `tauri-runtime@1.0.0-alpha.0` - Upgraded to `tauri-utils@2.0.0-alpha.7` ### Breaking Changes - [`fbeb5b91`](https://www.github.com/tauri-apps/tauri/commit/fbeb5b9185baeda19e865228179e3e44c165f1d9)([#7170](https://www.github.com/tauri-apps/tauri/pull/7170)) Removed the `linux-headers` feature (now always enabled) and added `linux-protocol-body`. - [`7fb419c3`](https://www.github.com/tauri-apps/tauri/commit/7fb419c326aaf72ecd556d8404377444ebb200e7)([#7535](https://www.github.com/tauri-apps/tauri/pull/7535)) `Dispatch::create_window`, `Runtime::create_window` and `RuntimeHandle::create_window` has been changed to accept a 3rd parameter which is a closure that takes `RawWindow` and to be executed right after the window is created and before the webview is added to the window. - [`7fb419c3`](https://www.github.com/tauri-apps/tauri/commit/7fb419c326aaf72ecd556d8404377444ebb200e7)([#7535](https://www.github.com/tauri-apps/tauri/pull/7535)) System tray and menu related APIs and structs have all been removed and are now implemented in tauri outside of the runtime-space. - [`7fb419c3`](https://www.github.com/tauri-apps/tauri/commit/7fb419c326aaf72ecd556d8404377444ebb200e7)([#7535](https://www.github.com/tauri-apps/tauri/pull/7535)) `Runtime::new` and `Runtime::new_any_thread` now accept a `RuntimeInitArgs`. - [`7fb419c3`](https://www.github.com/tauri-apps/tauri/commit/7fb419c326aaf72ecd556d8404377444ebb200e7)([#7535](https://www.github.com/tauri-apps/tauri/pull/7535)) Removed `system-tray` feature flag ## \[0.13.0-alpha.6] ### New Features - [`e0f0dce2`](https://www.github.com/tauri-apps/tauri/commit/e0f0dce220730e2822fc202463aedf0166145de7)([#6442](https://www.github.com/tauri-apps/tauri/pull/6442)) Added the `window_effects` option when creating a window and `Window::set_effects` to change it at runtime. ## \[0.13.0-alpha.5] - [`39f1b04f`](https://www.github.com/tauri-apps/tauri/commit/39f1b04f7be4966488484829cd54c8ce72a04200)([#6943](https://www.github.com/tauri-apps/tauri/pull/6943)) Moved the `event` JS APIs to a plugin. - [`3188f376`](https://www.github.com/tauri-apps/tauri/commit/3188f3764978c6d1452ee31d5a91469691e95094)([#6883](https://www.github.com/tauri-apps/tauri/pull/6883)) Bump the MSRV to 1.65. - [`cebd7526`](https://www.github.com/tauri-apps/tauri/commit/cebd75261ac71b98976314a450cb292eeeec1515)([#6728](https://www.github.com/tauri-apps/tauri/pull/6728)) Moved the `clipboard` feature to its own plugin in the plugins-workspace repository. - [`3f17ee82`](https://www.github.com/tauri-apps/tauri/commit/3f17ee82f6ff21108806edb7b00500b8512b8dc7)([#6737](https://www.github.com/tauri-apps/tauri/pull/6737)) Moved the `global-shortcut` feature to its own plugin in the plugins-workspace repository. - [`31444ac1`](https://www.github.com/tauri-apps/tauri/commit/31444ac196add770f2ad18012d7c18bce7538f22)([#6725](https://www.github.com/tauri-apps/tauri/pull/6725)) Update `wry` to `0.28` ## \[0.13.0-alpha.4] - Added `android` configuration object under `tauri > bundle`. - Bumped due to a bump in tauri-utils. - [db4c9dc6](https://www.github.com/tauri-apps/tauri/commit/db4c9dc655e07ee2184fe04571f500f7910890cd) feat(core): add option to configure Android's minimum SDK version ([#6651](https://www.github.com/tauri-apps/tauri/pull/6651)) on 2023-04-07 ## \[0.13.0-alpha.3] - Pull changes from Tauri 1.3 release. - [](https://www.github.com/tauri-apps/tauri/commit/undefined) on undefined ## \[0.13.0-alpha.2] - Add `find_class`, `run_on_android_context` on `RuntimeHandle`. - [05dad087](https://www.github.com/tauri-apps/tauri/commit/05dad0876842e2a7334431247d49365cee835d3e) feat: initial work for iOS plugins ([#6205](https://www.github.com/tauri-apps/tauri/pull/6205)) on 2023-02-11 - Allow a wry plugin to be registered at runtime. - [ae296f3d](https://www.github.com/tauri-apps/tauri/commit/ae296f3de16fb6a8badbad5555075a5861681fe5) refactor(tauri-runtime-wry): register runtime plugin after run() ([#6478](https://www.github.com/tauri-apps/tauri/pull/6478)) on 2023-03-17 - Added the `shadow` option when creating a window and `Window::set_shadow`. - [a81750d7](https://www.github.com/tauri-apps/tauri/commit/a81750d779bc72f0fdb7de90b7fbddfd8049b328) feat(core): add shadow APIs ([#6206](https://www.github.com/tauri-apps/tauri/pull/6206)) on 2023-02-08 - Implemented `with_webview` on Android and iOS. - [05dad087](https://www.github.com/tauri-apps/tauri/commit/05dad0876842e2a7334431247d49365cee835d3e) feat: initial work for iOS plugins ([#6205](https://www.github.com/tauri-apps/tauri/pull/6205)) on 2023-02-11 ## \[0.13.0-alpha.1] - Update gtk to 0.16. - [7eb9aa75](https://www.github.com/tauri-apps/tauri/commit/7eb9aa75cfd6a3176d3f566fdda02d88aa529b0f) Update gtk to 0.16 ([#6155](https://www.github.com/tauri-apps/tauri/pull/6155)) on 2023-01-30 - Bump the MSRV to 1.64. - [7eb9aa75](https://www.github.com/tauri-apps/tauri/commit/7eb9aa75cfd6a3176d3f566fdda02d88aa529b0f) Update gtk to 0.16 ([#6155](https://www.github.com/tauri-apps/tauri/pull/6155)) on 2023-01-30 - Update wry to 0.26. - [f0a1d9cd](https://www.github.com/tauri-apps/tauri/commit/f0a1d9cdbcfb645ce1c5f1cdd597f764991772cd) chore: update rfd and wry versions ([#6174](https://www.github.com/tauri-apps/tauri/pull/6174)) on 2023-02-03 ## \[0.13.0-alpha.0] - Support `with_webview` for Android platform alowing execution of JNI code in context. - [8ea87e9c](https://www.github.com/tauri-apps/tauri/commit/8ea87e9c9ca8ba4c7017c8281f78aacd08f45785) feat(android): with_webview access for jni execution ([#5148](https://www.github.com/tauri-apps/tauri/pull/5148)) on 2022-09-08 ## \[0.14.5] ### What's Changed - [`d42668ce`](https://www.github.com/tauri-apps/tauri/commit/d42668ce17494ab778f436aaa9b216d6db3f0b31)([#9003](https://www.github.com/tauri-apps/tauri/pull/9003)) Fix panic during intialization on wayland when using `clipboard` feature, instead propagate the error during API usage. ## \[0.14.4] ### Bug Fixes - [`24210735`](https://www.github.com/tauri-apps/tauri/commit/2421073576a6d45783176be57b0188668558aff7)([#8117](https://www.github.com/tauri-apps/tauri/pull/8117)) Fixes a crash on macOS when accessing the windows map. - [`510b6226`](https://www.github.com/tauri-apps/tauri/commit/510b62261c70331ce3f5bfd24137dac1bc4a0bbe)([#8822](https://www.github.com/tauri-apps/tauri/pull/8822)) Add missing `arboard` feature flag to prevent panics in wayland session. ## \[0.14.3] ### Bug Fixes - [`0d0501cb`](https://www.github.com/tauri-apps/tauri/commit/0d0501cb7b5e767c51a3697a148acfe84211a7ad)([#8394](https://www.github.com/tauri-apps/tauri/pull/8394)) Use `arboard` instead of `tao` clipboard implementation to prevent a crash. - [`b2f83f03`](https://www.github.com/tauri-apps/tauri/commit/b2f83f03a872baa91e2b6bbb22a3e7a5cd975dc0)([#8402](https://www.github.com/tauri-apps/tauri/pull/8402)) Use `Arc` instead of `Rc` to prevent crashes on macOS. ### Dependencies - Upgraded to `tauri-utils@1.5.2` - Upgraded to `tauri-runtime@0.14.2` ## \[0.14.2] ### Enhancements - [`5e05236b`](https://www.github.com/tauri-apps/tauri/commit/5e05236b4987346697c7caae0567d3c50714c198)([#8289](https://www.github.com/tauri-apps/tauri/pull/8289)) Added tracing for window startup, plugins, `Window::eval`, events, IPC, updater and custom protocol request handlers behind the `tracing` feature flag. ## \[0.14.1] ### Enhancements - [`9aa34ada`](https://www.github.com/tauri-apps/tauri/commit/9aa34ada5769dbefa7dfe5f7a6288b3d20b294e4)([#7645](https://www.github.com/tauri-apps/tauri/pull/7645)) Add setting to switch to `http://.localhost/` for custom protocols on Windows. ### Bug Fixes - [`4bf1e85e`](https://www.github.com/tauri-apps/tauri/commit/4bf1e85e6bf85a7ec92d50c8465bc0588a6399d8)([#7722](https://www.github.com/tauri-apps/tauri/pull/7722)) Properly respect the `focused` option when creating the webview. ### Dependencies - Upgraded to `tauri-utils@1.5.0` - Upgraded to `tauri-runtime@0.14.1` ## \[0.14.0] ### New Features - [`c4d6fb4b`](https://www.github.com/tauri-apps/tauri/commit/c4d6fb4b1ea8acf02707a9fe5dcab47c1c5bae7b)([#2353](https://www.github.com/tauri-apps/tauri/pull/2353)) Added the `maximizable`, `minimizable` and `closable` methods to `WindowBuilder`. - [`c4d6fb4b`](https://www.github.com/tauri-apps/tauri/commit/c4d6fb4b1ea8acf02707a9fe5dcab47c1c5bae7b)([#2353](https://www.github.com/tauri-apps/tauri/pull/2353)) Added `set_maximizable`, `set_minimizable`, `set_closable`, `is_maximizable`, `is_minimizable` and `is_closable` methods to the `Dispatch` trait. - [`000104bc`](https://www.github.com/tauri-apps/tauri/commit/000104bc3bc0c9ff3d20558ab9cf2080f126e9e0)([#6472](https://www.github.com/tauri-apps/tauri/pull/6472)) Add `Window::is_focused` getter. ### Enhancements - [`d2710e9d`](https://www.github.com/tauri-apps/tauri/commit/d2710e9d2e8fd93975ef6494512370faa8cb3b7e)([#6944](https://www.github.com/tauri-apps/tauri/pull/6944)) Unpin `time`, `ignore`, and `winnow` crate versions. Developers now have to pin crates if needed themselves. A list of crates that need pinning to adhere to Tauri's MSRV will be visible in Tauri's GitHub workflow: https://github.com/tauri-apps/tauri/blob/dev/.github/workflows/test-core.yml#L85. ### Bug Fixes - [`b41b57eb`](https://www.github.com/tauri-apps/tauri/commit/b41b57ebb27befd366db5befaafb6043c18fdfef)([#7105](https://www.github.com/tauri-apps/tauri/pull/7105)) Fix panics when registering an invalid global shortcuts or checking it is registered and return proper errors instead. ### What's Changed - [`076e1a81`](https://www.github.com/tauri-apps/tauri/commit/076e1a81a50468e3dfb34ae9ca7e77c5e1758daa)([#7119](https://www.github.com/tauri-apps/tauri/pull/7119)) Use `u32` instead of `u64` for js event listener ids ## \[0.13.0] - Added the `additional_browser_args` option when creating a window. - [3dc38b15](https://www.github.com/tauri-apps/tauri/commit/3dc38b150ea8c59c8ba67fd586f921016928f47c) feat(core): expose additional_browser_args to window config (fix: [#5757](https://www.github.com/tauri-apps/tauri/pull/5757)) ([#5799](https://www.github.com/tauri-apps/tauri/pull/5799)) on 2022-12-14 - Added the `content_protected` option when creating a window and `Window::set_content_protected` to change it at runtime. - [4ab5545b](https://www.github.com/tauri-apps/tauri/commit/4ab5545b7a831c549f3c65e74de487ede3ab7ce5) feat: add content protection api, closes [#5132](https://www.github.com/tauri-apps/tauri/pull/5132) ([#5513](https://www.github.com/tauri-apps/tauri/pull/5513)) on 2022-12-13 - Added `Builder::device_event_filter` and `App::set_device_event_filter` methods. - [73fd60ee](https://www.github.com/tauri-apps/tauri/commit/73fd60eef2b60f5dc84525ef9c315f4d80c4414f) expose set_device_event_filter in tauri ([#5562](https://www.github.com/tauri-apps/tauri/pull/5562)) on 2022-12-13 - Fixes tray events not being delivered. - [138cb8d7](https://www.github.com/tauri-apps/tauri/commit/138cb8d739b15bccdb388e555c20f17ffe16318c) fix(tauri-runtime-wry): tray event listener not registered ([#6270](https://www.github.com/tauri-apps/tauri/pull/6270)) on 2023-02-14 - Add `is_minimized()` window method. - [62144ef3](https://www.github.com/tauri-apps/tauri/commit/62144ef3be63b237869e511826edfb938e2c7174) feat: add is_minimized (fix [#3878](https://www.github.com/tauri-apps/tauri/pull/3878)) ([#5618](https://www.github.com/tauri-apps/tauri/pull/5618)) on 2022-12-13 - Disable cursor mouse events on Linux. - [8c842a54](https://www.github.com/tauri-apps/tauri/commit/8c842a54a6f3dc5327b4d737df7123dcddaa5769) feature: disable mouse event when building windows on Linux, closes [#5913](https://www.github.com/tauri-apps/tauri/pull/5913) ([#6025](https://www.github.com/tauri-apps/tauri/pull/6025)) on 2023-01-16 - Bump minimum supported Rust version to 1.60. - [5fdc616d](https://www.github.com/tauri-apps/tauri/commit/5fdc616df9bea633810dcb814ac615911d77222c) feat: Use the zbus-backed of notify-rust ([#6332](https://www.github.com/tauri-apps/tauri/pull/6332)) on 2023-03-31 - Pin raw-window-handle to 0.5.0 to keep MSRV. - [c46c09f3](https://www.github.com/tauri-apps/tauri/commit/c46c09f31d9f5169ca8a7e62406a9ea170e3a5c5) fix(deps): pin raw-window-handle to 0.5.0 ([#6480](https://www.github.com/tauri-apps/tauri/pull/6480)) on 2023-03-17 - Add `title` getter on window. - [233e43b0](https://www.github.com/tauri-apps/tauri/commit/233e43b0c34fada1ca025378533a0b76931a6540) feat: add `title` getter on window, closes [#5023](https://www.github.com/tauri-apps/tauri/pull/5023) ([#5515](https://www.github.com/tauri-apps/tauri/pull/5515)) on 2022-12-13 - Added `TrayHandle::set_tooltip` and `SystemTray::with_tooltip`. - [2265e097](https://www.github.com/tauri-apps/tauri/commit/2265e09718f6ebfeb1d200f11e1e1e069075af6e) feat(windows): implement `with_tooltip` ([#5938](https://www.github.com/tauri-apps/tauri/pull/5938)) on 2023-01-01 - Added window's `url()` getter. - [d17027e1](https://www.github.com/tauri-apps/tauri/commit/d17027e1a0db3e8c5ae81fc4f472c5918fbce611) feat: expose url method ([#5914](https://www.github.com/tauri-apps/tauri/pull/5914)) on 2022-12-26 - On Windows, change webview theme based on Window theme for more accurate `prefers-color-scheme` support. - [7a8d570d](https://www.github.com/tauri-apps/tauri/commit/7a8d570db72667367eb24b75ddc5dd07a968f7c0) fix: sync webview theme with window theme on Windows, closes [#5802](https://www.github.com/tauri-apps/tauri/pull/5802) ([#5874](https://www.github.com/tauri-apps/tauri/pull/5874)) on 2022-12-27 - On Windows, Fix missing `WindowEvent::Focused` in `App::run` callback. - [ff4ea1ea](https://www.github.com/tauri-apps/tauri/commit/ff4ea1eabbf2874b113c6b4698002929bbac737a) fix: dispatch focus event to app.run on Windows, closes [#6460](https://www.github.com/tauri-apps/tauri/pull/6460) ([#6504](https://www.github.com/tauri-apps/tauri/pull/6504)) on 2023-03-31 - Implement the webview navigation handler. - [3f35b452](https://www.github.com/tauri-apps/tauri/commit/3f35b452637ef1c794a423f1eda62a15d2ddaf42) Expose wry navigation_handler via WindowBuilder closes [#4080](https://www.github.com/tauri-apps/tauri/pull/4080) ([#5686](https://www.github.com/tauri-apps/tauri/pull/5686)) on 2022-12-27 ## \[0.12.3] - Block remote URLs from accessing the IPC. - [9c0593c33](https://www.github.com/tauri-apps/tauri/commit/9c0593c33af52cd9e00ec784d15f63efebdf039c) feat(core): block remote URLs from accessing the IPC on 2023-04-12 ## \[0.12.2] - Fix compatibility with older Linux distributions. - [b490308c](https://www.github.com/tauri-apps/tauri/commit/b490308c8897b893292951754607c2253abbc6e1) fix(core): compilation error on older Linux versions, fixes [#5684](https://www.github.com/tauri-apps/tauri/pull/5684) ([#5697](https://www.github.com/tauri-apps/tauri/pull/5697)) on 2022-11-28 - Update wry to 0.23. - [fdcd7733](https://www.github.com/tauri-apps/tauri/commit/fdcd77338c1a3a7ef8a8ea1907351c5c350ea7ba) chore(deps): update wry to 0.23 on 2022-12-08 ## \[0.12.1] - Fix `allowlist > app > show/hide` always disabled when `allowlist > app > all: false`. - Bumped due to a bump in tauri-utils. - [bb251087](https://www.github.com/tauri-apps/tauri/commit/bb2510876d0bdff736d36bf3a465cdbe4ad2b90c) fix(core): extend allowlist with `app`'s allowlist, closes [#5650](https://www.github.com/tauri-apps/tauri/pull/5650) ([#5652](https://www.github.com/tauri-apps/tauri/pull/5652)) on 2022-11-18 ## \[0.12.0] - Add `accept_first_mouse` option for macOS windows. - [95f467ad](https://www.github.com/tauri-apps/tauri/commit/95f467add51448319983c54e2f382c7c09fb72d6) feat(core): add window `accept_first_mouse` option, closes [#5347](https://www.github.com/tauri-apps/tauri/pull/5347) ([#5374](https://www.github.com/tauri-apps/tauri/pull/5374)) on 2022-10-17 - Disable automatic window tabbing on macOS when the `tabbing_identifier` option is not defined, the window is transparent or does not have decorations. - [4137ab44](https://www.github.com/tauri-apps/tauri/commit/4137ab44a81d739556cbc7583485887e78952bf1) feat(macos): add `tabbing_identifier` option, closes [#2804](https://www.github.com/tauri-apps/tauri/pull/2804), [#3912](https://www.github.com/tauri-apps/tauri/pull/3912) ([#5399](https://www.github.com/tauri-apps/tauri/pull/5399)) on 2022-10-19 - Drop the WebContext when the WebView is dropped. - [9d8b3774](https://www.github.com/tauri-apps/tauri/commit/9d8b377481abf975dc37f9050d2ac7b63ce353e9) feat(tauri-runtime-wry): drop the WebContext on WebView drop ([#5240](https://www.github.com/tauri-apps/tauri/pull/5240)) on 2022-10-19 - Readd the option to create an unfocused window via the `focused` method. The `focus` function has been deprecated. - [4036e15f](https://www.github.com/tauri-apps/tauri/commit/4036e15f5af933bdc0d0913508b5103958afc143) feat(core): reimplement window initial focus flag, closes [#5120](https://www.github.com/tauri-apps/tauri/pull/5120) ([#5338](https://www.github.com/tauri-apps/tauri/pull/5338)) on 2022-10-08 - Add `hidden_title` option for macOS windows. - [321f3fed](https://www.github.com/tauri-apps/tauri/commit/321f3fed19df40c1223099bce953332b7f00f7a9) feat(macos): `title_bar_style` and `hidden_title` window options, closes [#2663](https://www.github.com/tauri-apps/tauri/pull/2663) ([#3965](https://www.github.com/tauri-apps/tauri/pull/3965)) on 2022-09-30 - Custom protocol headers are now implemented on Linux when running on webkit2gtk 2.36 or above. - [357480f4](https://www.github.com/tauri-apps/tauri/commit/357480f4ae43aa8da99f7ba61ae2ee51b4552c60) feat(core): custom protocol headers on Linux, closes [#4496](https://www.github.com/tauri-apps/tauri/pull/4496) ([#5421](https://www.github.com/tauri-apps/tauri/pull/5421)) on 2022-10-17 - Added `Runtime::show()`, `RuntimeHandle::show()`, `Runtime::hide()`, `RuntimeHandle::hide()` for hiding/showing the entire application on macOS. - [39bf895b](https://www.github.com/tauri-apps/tauri/commit/39bf895b73ec6b53f5758815396ba85dda6b9c67) feat(macOS): Add application `show` and `hide` methods ([#3689](https://www.github.com/tauri-apps/tauri/pull/3689)) on 2022-10-03 - Fix regression in `SystemTray::with_menu_on_left_click` - [f8a3becb](https://www.github.com/tauri-apps/tauri/commit/f8a3becb287942db7f7b551b5db6aeb5a2e939ee) feat(core): add option to disable tray menu on left click, closes [#4584](https://www.github.com/tauri-apps/tauri/pull/4584) ([#4587](https://www.github.com/tauri-apps/tauri/pull/4587)) on 2022-07-05 - [7bbf167c](https://www.github.com/tauri-apps/tauri/commit/7bbf167c1c84493ea6e2353f720edafd7daa47e4) Apply Version Updates From Current Changes ([#4560](https://www.github.com/tauri-apps/tauri/pull/4560)) on 2022-07-06 - [63011ca8](https://www.github.com/tauri-apps/tauri/commit/63011ca84e7a22c8c0d8bd1c1be6592140f93ff2) fix(macos): fix regression in `with_menu_on_left_click`, closes [#5220](https://www.github.com/tauri-apps/tauri/pull/5220) ([#5235](https://www.github.com/tauri-apps/tauri/pull/5235)) on 2022-09-30 - - [7d9aa398](https://www.github.com/tauri-apps/tauri/commit/7d9aa3987efce2d697179ffc33646d086c68030c) feat: bump MSRV to 1.59 ([#5296](https://www.github.com/tauri-apps/tauri/pull/5296)) on 2022-09-28 - Added `tabbing_identifier` to the window builder on macOS. - [4137ab44](https://www.github.com/tauri-apps/tauri/commit/4137ab44a81d739556cbc7583485887e78952bf1) feat(macos): add `tabbing_identifier` option, closes [#2804](https://www.github.com/tauri-apps/tauri/pull/2804), [#3912](https://www.github.com/tauri-apps/tauri/pull/3912) ([#5399](https://www.github.com/tauri-apps/tauri/pull/5399)) on 2022-10-19 - Add `title_bar_style` option for macOS windows. - [321f3fed](https://www.github.com/tauri-apps/tauri/commit/321f3fed19df40c1223099bce953332b7f00f7a9) feat(macos): `title_bar_style` and `hidden_title` window options, closes [#2663](https://www.github.com/tauri-apps/tauri/pull/2663) ([#3965](https://www.github.com/tauri-apps/tauri/pull/3965)) on 2022-09-30 - Fix regression introduce in tauri@1.1 which prevented removing tray icon when the app exits on Windows. - [f756cd5e](https://www.github.com/tauri-apps/tauri/commit/f756cd5e7ecc86f178f8d602eded1e1b6ecb51f3) fix(core): wait for tray cleanup before exiting app, closes [#5244](https://www.github.com/tauri-apps/tauri/pull/5244) ([#5245](https://www.github.com/tauri-apps/tauri/pull/5245)) on 2022-10-04 - Added methods to set the system tray title on macOS. - [8f1ace77](https://www.github.com/tauri-apps/tauri/commit/8f1ace77956ac3477826ceb059a191e55b3fff93) feat: expose `set_title` for MacOS tray ([#5182](https://www.github.com/tauri-apps/tauri/pull/5182)) on 2022-09-30 - Added the `user_agent` option when creating a window. - [a6c94119](https://www.github.com/tauri-apps/tauri/commit/a6c94119d8545d509723b147c273ca5edfe3729f) feat(core): expose user_agent to window config ([#5317](https://www.github.com/tauri-apps/tauri/pull/5317)) on 2022-10-02 ## \[0.11.2] - Block remote URLs from accessing the IPC. - [58ea0b452](https://www.github.com/tauri-apps/tauri/commit/58ea0b45268dbd46cbac0ebb0887353d057ca767) feat(core): block remote URLs from accessing the IPC on 2023-04-12 ## \[0.11.1] - Add missing allowlist config for `set_cursor_grab`, `set_cursor_visible`, `set_cursor_icon` and `set_cursor_position` APIs. - Bumped due to a bump in tauri-utils. - [c764408d](https://www.github.com/tauri-apps/tauri/commit/c764408da7fae123edd41115bda42fa75a4731d2) fix: Add missing allowlist config for cursor apis, closes [#5207](https://www.github.com/tauri-apps/tauri/pull/5207) ([#5211](https://www.github.com/tauri-apps/tauri/pull/5211)) on 2022-09-16 ## \[0.11.0] - Ignore window events with unknown IDs. - [0668dd42](https://www.github.com/tauri-apps/tauri/commit/0668dd42204b163f11aaf31f45106c8551f15942) fix(tauri-runtime-wry): ignore events on unknown windows on 2022-08-29 - Implement theme APIs for Linux. - [f21cbecd](https://www.github.com/tauri-apps/tauri/commit/f21cbecdeb3571ac4ad971b9a865ff62a131a176) feat(core): implement theme APIs for Linux ([#4808](https://www.github.com/tauri-apps/tauri/pull/4808)) on 2022-08-02 - Changed `windows` map to be stored in a `RefCell` instead of a `Mutex`. - [64546cb9](https://www.github.com/tauri-apps/tauri/commit/64546cb9cca2fe56cf81cfc4aaf85c4e1d58877c) refactor: use RefCell instead of Mutex for windows map, closes [#4870](https://www.github.com/tauri-apps/tauri/pull/4870) ([#4909](https://www.github.com/tauri-apps/tauri/pull/4909)) on 2022-08-10 - Added APIs to create a system tray at runtime. - [4d063ae9](https://www.github.com/tauri-apps/tauri/commit/4d063ae9ee9538cd6fa5e01b80070c6edf8eaeb9) feat(core): create system tray at runtime, closes [#2278](https://www.github.com/tauri-apps/tauri/pull/2278) ([#4862](https://www.github.com/tauri-apps/tauri/pull/4862)) on 2022-08-09 - Update windows to 0.39.0 and webview2-com to 0.19.1. - [e6d9b670](https://www.github.com/tauri-apps/tauri/commit/e6d9b670b0b314ed667b0e164f2c8d27048e678f) refactor: remove unneeded focus code ([#5065](https://www.github.com/tauri-apps/tauri/pull/5065)) on 2022-09-03 ## \[0.10.3] - Block remote URLs from accessing the IPC. - [fa90214b0](https://www.github.com/tauri-apps/tauri/commit/fa90214b052b1a5d38d54fbf1ca422b4c37cfd1f) feat(core): block remote URLs from accessing the IPC on 2023-04-12 ## \[0.10.2] - Disable drag-n-drop of tao based on `fileDropEnabled` value. - [a1d569bb](https://www.github.com/tauri-apps/tauri/commit/a1d569bbc9cfdd58258916df594911e1c512a75e) fix(core): disable tao's drag-n-drop based on `fileDropEnabled`, closes [#4580](https://www.github.com/tauri-apps/tauri/pull/4580) ([#4592](https://www.github.com/tauri-apps/tauri/pull/4592)) on 2022-07-05 - Added option to disable tray menu on left click on macOS. - [f8a3becb](https://www.github.com/tauri-apps/tauri/commit/f8a3becb287942db7f7b551b5db6aeb5a2e939ee) feat(core): add option to disable tray menu on left click, closes [#4584](https://www.github.com/tauri-apps/tauri/pull/4584) ([#4587](https://www.github.com/tauri-apps/tauri/pull/4587)) on 2022-07-05 ## \[0.10.1] - Fixes a deadlock on the file drop handler. - [23a48007](https://www.github.com/tauri-apps/tauri/commit/23a48007c0df7346fa45c76dfaf9235a157f59ec) fix(tauri-runtime-wry): deadlock on file drop, closes [#4527](https://www.github.com/tauri-apps/tauri/pull/4527) ([#4535](https://www.github.com/tauri-apps/tauri/pull/4535)) on 2022-06-30 - Send theme value only once on the getter function implementation on macOS. - [63841c10](https://www.github.com/tauri-apps/tauri/commit/63841c10609c3d7337ba6cd68ae126b18987014d) fix(tauri-runtime-wry): do not send theme twice on macOS, closes [#4532](https://www.github.com/tauri-apps/tauri/pull/4532) ([#4540](https://www.github.com/tauri-apps/tauri/pull/4540)) on 2022-06-30 - Fixes a deadlock when the window focus change on Windows. - [185b0e31](https://www.github.com/tauri-apps/tauri/commit/185b0e314ece9563cd7c83a16466b2b8b9167eb3) fix(tauri-runtime-wry): deadlock when window focus change, closes [#4533](https://www.github.com/tauri-apps/tauri/pull/4533) ([#4539](https://www.github.com/tauri-apps/tauri/pull/4539)) on 2022-06-30 ## \[0.10.0] - Implement `raw_window_handle::HasRawWindowHandle` on Linux. - [3efbc67f](https://www.github.com/tauri-apps/tauri/commit/3efbc67f7469ce65a2d9ea4ff2b60b51d2a36aa5) feat: implement `raw_window_handle` on Linux ([#4469](https://www.github.com/tauri-apps/tauri/pull/4469)) on 2022-06-26 - Moved the window and menu event listeners to the window struct. - [46196fe9](https://www.github.com/tauri-apps/tauri/commit/46196fe922f4f1b38057155c6113236cfa4b3597) refactor(tauri-runtime-wry): move window and menu listeners to window ([#4485](https://www.github.com/tauri-apps/tauri/pull/4485)) on 2022-06-27 - Refactored the `tauri-runtime-wry` plugin interface. - [e39e2999](https://www.github.com/tauri-apps/tauri/commit/e39e2999e0ab1843a8195ba83aea3d6de705c3d8) refactor(tauri-runtime-wry): enhance plugin interface ([#4476](https://www.github.com/tauri-apps/tauri/pull/4476)) on 2022-06-27 - Removed the `hwnd` and `ns_window` functions from `Dispatch` in favor of `raw_window_handle`. - [3efbc67f](https://www.github.com/tauri-apps/tauri/commit/3efbc67f7469ce65a2d9ea4ff2b60b51d2a36aa5) feat: implement `raw_window_handle` on Linux ([#4469](https://www.github.com/tauri-apps/tauri/pull/4469)) on 2022-06-26 - The theme API is now implemented on macOS 10.14+. - [6d94ce42](https://www.github.com/tauri-apps/tauri/commit/6d94ce42353204a02fe9c82ed397d349439f75ef) feat(core): theme is now implemented on macOS ([#4380](https://www.github.com/tauri-apps/tauri/pull/4380)) on 2022-06-17 - Suppress unused variable warning in release builds. - [45981851](https://www.github.com/tauri-apps/tauri/commit/45981851e35119266c1a079e1ff27a39f1fdfaed) chore(lint): unused variable warnings for release builds ([#4411](https://www.github.com/tauri-apps/tauri/pull/4411)) on 2022-06-22 - Update tao to 0.12 and wry to 0.19. - [f6edc6df](https://www.github.com/tauri-apps/tauri/commit/f6edc6df29b1c45b483fa87c481a3b95730b131b) chore(deps): update tao to 0.12, wry to 0.19, closes [#3220](https://www.github.com/tauri-apps/tauri/pull/3220) ([#4502](https://www.github.com/tauri-apps/tauri/pull/4502)) on 2022-06-28 - Fixes deadlocks when using window setters in the main thread. - [123f6e69](https://www.github.com/tauri-apps/tauri/commit/123f6e69f60ca6d4b2fd738ca3ff5cf016d8e814) fix(tauri-runtime-wry): release windows lock immediately, closes [#4390](https://www.github.com/tauri-apps/tauri/pull/4390) ([#4392](https://www.github.com/tauri-apps/tauri/pull/4392)) on 2022-06-19 ## \[0.9.0] - Upgrade to `stable`! - Bumped due to a bump in tauri-utils. - [f4bb30cc](https://www.github.com/tauri-apps/tauri/commit/f4bb30cc73d6ba9b9ef19ef004dc5e8e6bb901d3) feat(covector): prepare for v1 ([#4351](https://www.github.com/tauri-apps/tauri/pull/4351)) on 2022-06-15 ## \[0.8.1] - Add `Menu::os_default` which will create a menu filled with default menu items and submenus. - Bumped due to a bump in tauri-runtime. - [4c4acc30](https://www.github.com/tauri-apps/tauri/commit/4c4acc3094218dd9cee0f1ad61810c979e0b41fa) feat: implement `Default` for `Menu`, closes [#2398](https://www.github.com/tauri-apps/tauri/pull/2398) ([#4291](https://www.github.com/tauri-apps/tauri/pull/4291)) on 2022-06-15 ## \[0.8.0] - Removed `TrayIcon` and renamed `WindowIcon` to `Icon`, a shared type for both icons. - [4ce8e228](https://www.github.com/tauri-apps/tauri/commit/4ce8e228134cd3f22973b74ef26ca0d165fbbbd9) refactor(core): use `Icon` for tray icons ([#4342](https://www.github.com/tauri-apps/tauri/pull/4342)) on 2022-06-14 ## \[0.7.0] - **Breaking change**: Removed the `gtk-tray` and `ayatana-tray` Cargo features. - [6216eb49](https://www.github.com/tauri-apps/tauri/commit/6216eb49e72863bfb6d4c9edb8827b21406ac393) refactor(core): drop `ayatana-tray` and `gtk-tray` Cargo features ([#4247](https://www.github.com/tauri-apps/tauri/pull/4247)) on 2022-06-02 ## \[0.6.0] - Account the monitor position when centering a window. - [a7a9fde1](https://www.github.com/tauri-apps/tauri/commit/a7a9fde16fb7c35d48d4f97e83ff95b8baf9e090) fix(core): account for monitor position when centering window ([#4166](https://www.github.com/tauri-apps/tauri/pull/4166)) on 2022-05-21 - Update `windows-rs` to `0.37.0`, which requires Rust 1.61.0+. - [2326be39](https://www.github.com/tauri-apps/tauri/commit/2326be39821890cdd4de76e7029a531424dcb26f) feat(core): update windows-rs to 0.37.0 ([#4199](https://www.github.com/tauri-apps/tauri/pull/4199)) on 2022-05-24 ## \[0.5.2] - Use the event loop proxy to create a window so it doesn't deadlock on Windows. - [61e37652](https://www.github.com/tauri-apps/tauri/commit/61e37652b931520424d6a93a134e67893703d992) fix(core): deadlock when creating window from IPC handler, closes [#4121](https://www.github.com/tauri-apps/tauri/pull/4121) ([#4123](https://www.github.com/tauri-apps/tauri/pull/4123)) on 2022-05-13 ## \[0.5.1] - Added the `plugin` method to the `Wry` runtime, allowing extensions to the event loop. - [c8e0e5b9](https://www.github.com/tauri-apps/tauri/commit/c8e0e5b97d542e549b37be08b545515c862af0e5) feat(tauri-runtime-wry): add plugin API ([#4094](https://www.github.com/tauri-apps/tauri/pull/4094)) on 2022-05-10 - Update wry to 0.16.2 and webkit2gtk to 0.18.0. - [71a553b7](https://www.github.com/tauri-apps/tauri/commit/71a553b715312e2bcceb963c83e42cffca7a63bc) chore(deps): update wry to 0.16.2, webkit2gtk to 0.18.0 ([#4099](https://www.github.com/tauri-apps/tauri/pull/4099)) on 2022-05-10 ## \[0.5.0] - The file drop event payloads are now percent-decoded. - [a0ecd81a](https://www.github.com/tauri-apps/tauri/commit/a0ecd81a934e1aa8935151a74cad686786054204) fix(core): percent decode file drop payloads, closes [#4034](https://www.github.com/tauri-apps/tauri/pull/4034) ([#4035](https://www.github.com/tauri-apps/tauri/pull/4035)) on 2022-05-03 - Fixes a crash when using the menu with the inspector window focused on macOS. In this case the `window_id` will be the id of the first app window. - [891eb748](https://www.github.com/tauri-apps/tauri/commit/891eb748cf590895dc3f1666f8dbd6082b21e04e) fix(tauri-runtime-wry): menu even panic on macOS inspector, closes [#3875](https://www.github.com/tauri-apps/tauri/pull/3875) ([#4027](https://www.github.com/tauri-apps/tauri/pull/4027)) on 2022-05-02 - Fixes a freeze when calling `set_size` in the main thread on Windows. - [8f259f4e](https://www.github.com/tauri-apps/tauri/commit/8f259f4ef89be3da11b57222c8b66af9487ab736) fix(core): use EventLoopProxy to prevent set_size freeze closes [#3990](https://www.github.com/tauri-apps/tauri/pull/3990) ([#4014](https://www.github.com/tauri-apps/tauri/pull/4014)) on 2022-04-30 - Expose methods to access the underlying native handles of the webview. - [c82b4761](https://www.github.com/tauri-apps/tauri/commit/c82b4761e1660592472dc55308ad69d9efc5855b) feat(core): expose `with_webview` API to access the platform webview ([#4058](https://www.github.com/tauri-apps/tauri/pull/4058)) on 2022-05-04 ## \[0.4.0] - \**Breaking change::* Added the `clipboard` Cargo feature. - [24e4ff20](https://www.github.com/tauri-apps/tauri/commit/24e4ff208ee0fe1a4cc5b10667ea0922ac63dfb5) refactor(core): add clipboard Cargo feature, enhancing binary size ([#3957](https://www.github.com/tauri-apps/tauri/pull/3957)) on 2022-04-24 - Expose Window cursor APIs `set_cursor_grab`, `set_cursor_visible`, `set_cursor_icon` and `set_cursor_position`. - [c54ddfe9](https://www.github.com/tauri-apps/tauri/commit/c54ddfe9338e7eb90b4d5b02dfde687d432d5bc1) feat: expose window cursor APIs, closes [#3888](https://www.github.com/tauri-apps/tauri/pull/3888) [#3890](https://www.github.com/tauri-apps/tauri/pull/3890) ([#3935](https://www.github.com/tauri-apps/tauri/pull/3935)) on 2022-04-21 - Fixes a panic when using the `create_tao_window` API. - [320329a9](https://www.github.com/tauri-apps/tauri/commit/320329a9a7d8a249c0fc9dee6db5669057ca8b39) fix(core): insert to webview_id_map on tao window creation, closes [#3883](https://www.github.com/tauri-apps/tauri/pull/3883) ([#3932](https://www.github.com/tauri-apps/tauri/pull/3932)) on 2022-04-21 - Fixes a panic when a menu event is triggered when all windows are minimized on macOS. - [70ff55c1](https://www.github.com/tauri-apps/tauri/commit/70ff55c1aa69ed59cd2a78d865e1cb398ef2a4ba) fix(core): panic on menu event with minimized windows, closes [#3902](https://www.github.com/tauri-apps/tauri/pull/3902) ([#3918](https://www.github.com/tauri-apps/tauri/pull/3918)) on 2022-04-20 - Fixes a rendering issue when resizing the window with the devtools open. - [80b714af](https://www.github.com/tauri-apps/tauri/commit/80b714af6b31365b9026bc92f8631b1721950447) fix: rendering issue when resizing with devtools open closes [#3914](https://www.github.com/tauri-apps/tauri/pull/3914) [#3814](https://www.github.com/tauri-apps/tauri/pull/3814) ([#3915](https://www.github.com/tauri-apps/tauri/pull/3915)) on 2022-04-19 - \**Breaking change::* Added the `global-shortcut` Cargo feature. - [e11878bc](https://www.github.com/tauri-apps/tauri/commit/e11878bcf7174b261a1fa146fc7d564d12e6312a) refactor(core): add global-shortcut Cargo feature, enhancing binary size ([#3956](https://www.github.com/tauri-apps/tauri/pull/3956)) on 2022-04-24 - Added `WindowEvent::ThemeChanged(theme)`. - [4cebcf6d](https://www.github.com/tauri-apps/tauri/commit/4cebcf6da7cad1953e0f01b426afac3b5ef1f81e) feat: expose theme APIs, closes [#3903](https://www.github.com/tauri-apps/tauri/pull/3903) ([#3937](https://www.github.com/tauri-apps/tauri/pull/3937)) on 2022-04-21 - Added `theme` getter on `Window`. - [4cebcf6d](https://www.github.com/tauri-apps/tauri/commit/4cebcf6da7cad1953e0f01b426afac3b5ef1f81e) feat: expose theme APIs, closes [#3903](https://www.github.com/tauri-apps/tauri/pull/3903) ([#3937](https://www.github.com/tauri-apps/tauri/pull/3937)) on 2022-04-21 - Added `theme` setter to the WindowBuilder. - [4cebcf6d](https://www.github.com/tauri-apps/tauri/commit/4cebcf6da7cad1953e0f01b426afac3b5ef1f81e) feat: expose theme APIs, closes [#3903](https://www.github.com/tauri-apps/tauri/pull/3903) ([#3937](https://www.github.com/tauri-apps/tauri/pull/3937)) on 2022-04-21 - Create webview immediately when executed in the main thread. - [fa2baba7](https://www.github.com/tauri-apps/tauri/commit/fa2baba76c8f59c81f2a2f7139033a09d14d89da) feat(core): create webview immediately when running in main thread ([#3891](https://www.github.com/tauri-apps/tauri/pull/3891)) on 2022-04-12 ## \[0.3.5] - Fixes `WindowEvent::Destroyed` not firing. - [169b5035](https://www.github.com/tauri-apps/tauri/commit/169b5035a93e3f33a420d4b2b0f8943e6404e07f) fix(core): actually fire `WindowEvent::Destroyed` ([#3797](https://www.github.com/tauri-apps/tauri/pull/3797)) on 2022-03-28 ## \[0.3.4] - Added `close_devtools` and `is_devtools_open` APIs to the `Dispatch` trait. - [e05d718a](https://www.github.com/tauri-apps/tauri/commit/e05d718a7b46476d1fe4817c169008080e84f959) feat(core): add hotkey to toggle devtools, closes [#3776](https://www.github.com/tauri-apps/tauri/pull/3776) ([#3791](https://www.github.com/tauri-apps/tauri/pull/3791)) on 2022-03-28 - Emit `RunEvent::Exit` on `tao::event::Event::LoopDestroyed` instead of after `RunEvent::ExitRequested`. - [3c4ee7c9](https://www.github.com/tauri-apps/tauri/commit/3c4ee7c997fa3ff696bcfd5b8c82fecaca16bf49) refactor(wry): emit `RunEvent::Exit` on `Event::LoopDestroyed` ([#3785](https://www.github.com/tauri-apps/tauri/pull/3785)) on 2022-03-27 - **Breaking change:** The `MenuItem::About` variant is now associated with a tuple value `(String, AboutMetadata)`. - [5fb74332](https://www.github.com/tauri-apps/tauri/commit/5fb74332ab9210ac062d96b0e9afd1c942ee2911) chore(deps): update wry to 0.14, tao to 0.7 ([#3790](https://www.github.com/tauri-apps/tauri/pull/3790)) on 2022-03-28 - Support window parenting on macOS - [4e807a53](https://www.github.com/tauri-apps/tauri/commit/4e807a53e2d6d3f3cd5293d90013d5cdded5454e) Support window parenting on macOS, closes [#3751](https://www.github.com/tauri-apps/tauri/pull/3751) ([#3754](https://www.github.com/tauri-apps/tauri/pull/3754)) on 2022-03-23 - The file drop event is now part of the `WindowEvent` enum instead of a having a dedicated handler. - [07d1584c](https://www.github.com/tauri-apps/tauri/commit/07d1584cf06ea326aa45d8044bee1b77ecba5006) feat(core): add `WindowEvent::FileDrop`, closes [#3664](https://www.github.com/tauri-apps/tauri/pull/3664) ([#3686](https://www.github.com/tauri-apps/tauri/pull/3686)) on 2022-03-13 - **Breaking change:** Use the dedicated `WindowEvent` enum on `RunEvent`. - [edad9f4f](https://www.github.com/tauri-apps/tauri/commit/edad9f4f55dcc69a06cd9d6d5a5068c94ecb77dd) refactor(core): add `RunEvent::WindowEvent` ([#3793](https://www.github.com/tauri-apps/tauri/pull/3793)) on 2022-03-28 - Added `create_proxy` to the `Runtime` and `RuntimeHandle` traits. - [5d538ec2](https://www.github.com/tauri-apps/tauri/commit/5d538ec27c246274df4ff5b8057ff78b6364a43f) refactor(core): use the event loop proxy to send updater events ([#3687](https://www.github.com/tauri-apps/tauri/pull/3687)) on 2022-03-15 - Allow specifying a user event type for the event loop message. - [5d538ec2](https://www.github.com/tauri-apps/tauri/commit/5d538ec27c246274df4ff5b8057ff78b6364a43f) refactor(core): use the event loop proxy to send updater events ([#3687](https://www.github.com/tauri-apps/tauri/pull/3687)) on 2022-03-15 - Use a random window id instead of `tao::window::WindowId` to not block the thread waiting for the event loop to process the window creation. - [7cd39c70](https://www.github.com/tauri-apps/tauri/commit/7cd39c70c9ecd62cc9b60d0ab93f10ce0a6dd8b4) refactor(core): use random window id to simplify window creation, closes [#3645](https://www.github.com/tauri-apps/tauri/pull/3645) [#3597](https://www.github.com/tauri-apps/tauri/pull/3597) ([#3684](https://www.github.com/tauri-apps/tauri/pull/3684)) on 2022-03-15 - Update `wry` to `0.14` and `tao` to `0.7`. - [f2d24ef2](https://www.github.com/tauri-apps/tauri/commit/f2d24ef2fbd95ec7d3433ba651964f4aa3b7f48c) chore(deps): update wry ([#1482](https://www.github.com/tauri-apps/tauri/pull/1482)) on 2021-04-14 - [e267ebf1](https://www.github.com/tauri-apps/tauri/commit/e267ebf1f1009b99829e0a7d71519925f5792f9f) Apply Version Updates From Current Changes ([#1486](https://www.github.com/tauri-apps/tauri/pull/1486)) on 2021-04-14 - [5fb74332](https://www.github.com/tauri-apps/tauri/commit/5fb74332ab9210ac062d96b0e9afd1c942ee2911) chore(deps): update wry to 0.14, tao to 0.7 ([#3790](https://www.github.com/tauri-apps/tauri/pull/3790)) on 2022-03-28 - Added the `WindowEvent::FileDrop` variant. - [07d1584c](https://www.github.com/tauri-apps/tauri/commit/07d1584cf06ea326aa45d8044bee1b77ecba5006) feat(core): add `WindowEvent::FileDrop`, closes [#3664](https://www.github.com/tauri-apps/tauri/pull/3664) ([#3686](https://www.github.com/tauri-apps/tauri/pull/3686)) on 2022-03-13 ## \[0.3.3] - Fixes a deadlock on the `Focused` event when the window is not visible. - [c08cc6d5](https://www.github.com/tauri-apps/tauri/commit/c08cc6d50041ec887d3070c41bb2c793dbac5155) fix(core): deadlock on focus events with invisible window,[#3534](https://www.github.com/tauri-apps/tauri/pull/3534) ([#3622](https://www.github.com/tauri-apps/tauri/pull/3622)) on 2022-03-06 - **Breaking change:** Move `ico` and `png` parsing behind `icon-ico` and `icon-png` Cargo features. - [8c935872](https://www.github.com/tauri-apps/tauri/commit/8c9358725a17dcc2acaf4d10c3f654afdff586b0) refactor(core): move `png` and `ico` behind Cargo features ([#3588](https://www.github.com/tauri-apps/tauri/pull/3588)) on 2022-03-05 - Print a warning to stderr if the window transparency has been set to true but `macos-private-api` is not enabled. - [080755b5](https://www.github.com/tauri-apps/tauri/commit/080755b5377a3c0a17adf1d03e63555350422f0a) feat(core): warn if private APIs are not enabled, closes [#3481](https://www.github.com/tauri-apps/tauri/pull/3481) ([#3511](https://www.github.com/tauri-apps/tauri/pull/3511)) on 2022-02-19 ## \[0.3.2] - Fix requirements for `RuntimeHandle`, `ClipboardManager`, `GlobalShortcutHandle` and `TrayHandle`. - Bumped due to a bump in tauri-runtime. - [84895a9c](https://www.github.com/tauri-apps/tauri/commit/84895a9cd270fc743e236d0f4d4cd6210b24a30f) fix(runtime): trait requirements ([#3489](https://www.github.com/tauri-apps/tauri/pull/3489)) on 2022-02-17 ## \[0.3.1] - Change default value for the `freezePrototype` configuration to `false`. - Bumped due to a bump in tauri-utils. - [3a4c0160](https://www.github.com/tauri-apps/tauri/commit/3a4c01606184be762adee055ddac803de0d28527) fix(core): change default `freezePrototype` to false, closes [#3416](https://www.github.com/tauri-apps/tauri/pull/3416) [#3406](https://www.github.com/tauri-apps/tauri/pull/3406) ([#3423](https://www.github.com/tauri-apps/tauri/pull/3423)) on 2022-02-12 ## \[0.3.0] - Fix `window.center` panic when window size is bigger than screen size. - [76ce9f61](https://www.github.com/tauri-apps/tauri/commit/76ce9f61dd3c5bdd589c7557543894e1f770dd16) fix(core): fix `window.center` panic when window size > screen, closes [#2978](https://www.github.com/tauri-apps/tauri/pull/2978) ([#3002](https://www.github.com/tauri-apps/tauri/pull/3002)) on 2021-12-09 - Enable non-session cookie persistence on Linux. - [d7c02a30](https://www.github.com/tauri-apps/tauri/commit/d7c02a30a56de79100804969138b379e703f0e07) feat(core): persist non-session cookies on Linux ([#3052](https://www.github.com/tauri-apps/tauri/pull/3052)) on 2021-12-09 - Fixes a deadlock when creating a window from a menu event handler. - [9c82006b](https://www.github.com/tauri-apps/tauri/commit/9c82006b2fe166d20510183e36cee099bf96e8d9) fix(core): deadlock when creating window from menu handler, closes [#3110](https://www.github.com/tauri-apps/tauri/pull/3110) ([#3126](https://www.github.com/tauri-apps/tauri/pull/3126)) on 2021-12-28 - Fixes `WindowEvent::Focus` and `WindowEvent::Blur` events not firing. - [3b33d67a](https://www.github.com/tauri-apps/tauri/commit/3b33d67aa4f48dcf4e32b3b8a5f45e83808efc2d) fix: re-adding focus/blur events for linux and macos (fix [#2485](https://www.github.com/tauri-apps/tauri/pull/2485)) ([#2489](https://www.github.com/tauri-apps/tauri/pull/2489)) on 2021-08-24 - Use webview's inner_size instead of window's value to get the correct size on macOS. - [4c0c780e](https://www.github.com/tauri-apps/tauri/commit/4c0c780e00d8851be38cb1c22f636d9e4ed34a23) fix(core): window's inner_size usage, closes [#2187](https://www.github.com/tauri-apps/tauri/pull/2187) ([#2690](https://www.github.com/tauri-apps/tauri/pull/2690)) on 2021-09-29 - Reimplement `remove_system_tray` on Windows to drop the `SystemTray` to run its cleanup code. - [a03b8554](https://www.github.com/tauri-apps/tauri/commit/a03b85545a4b0b61a598a43eabe96e03565dcaf0) fix(core): tray not closing on Windows ([#3351](https://www.github.com/tauri-apps/tauri/pull/3351)) on 2022-02-07 - Replace `WindowBuilder`'s `has_menu` with `get_menu`. - [ac37b56e](https://www.github.com/tauri-apps/tauri/commit/ac37b56ef43c9e97039967a5fd99f0d2dccb5b5a) fix(core): menu id map not reflecting the current window menu ([#2726](https://www.github.com/tauri-apps/tauri/pull/2726)) on 2021-10-08 - Fix empty header from CORS on Linux. - [b48487e6](https://www.github.com/tauri-apps/tauri/commit/b48487e6a7b33f5a352e542fae21a2efd53ce295) Fix empty header from CORS on Linux, closes [#2327](https://www.github.com/tauri-apps/tauri/pull/2327) ([#2762](https://www.github.com/tauri-apps/tauri/pull/2762)) on 2021-10-18 - The `run_return` API is now available on Linux. - [8483fde9](https://www.github.com/tauri-apps/tauri/commit/8483fde975aac8833d2ce426e42fb40aeaeecba9) feat(core): expose `run_return` on Linux ([#3352](https://www.github.com/tauri-apps/tauri/pull/3352)) on 2022-02-07 - Allow window, global shortcut and clipboard APIs to be called on the main thread. - [2812c446](https://www.github.com/tauri-apps/tauri/commit/2812c4464b93a365ab955935d05b5cea8cb03aab) feat(core): window, shortcut and clipboard API calls on main thread ([#2659](https://www.github.com/tauri-apps/tauri/pull/2659)) on 2021-09-26 - [d24fd8d1](https://www.github.com/tauri-apps/tauri/commit/d24fd8d10242da3da143a971d976b42ec4de6079) feat(tauri-runtime-wry): allow window creation and closing on the main thread ([#2668](https://www.github.com/tauri-apps/tauri/pull/2668)) on 2021-09-27 - Change event loop callbacks definition to allow callers to move in mutable values. - [bdbf905e](https://www.github.com/tauri-apps/tauri/commit/bdbf905e5d802b58693d2bd27582ce4269faf79c) Transformed event-loop callback to FnMut to allow mutable values ([#2667](https://www.github.com/tauri-apps/tauri/pull/2667)) on 2021-09-27 - **Breaking change:** Add `macos-private-api` feature flag, enabled via `tauri.conf.json > tauri > macOSPrivateApi`. - [6ac21b3c](https://www.github.com/tauri-apps/tauri/commit/6ac21b3cef7f14358df38cc69ea3d277011accaf) feat: add private api feature flag ([#7](https://www.github.com/tauri-apps/tauri/pull/7)) on 2022-01-09 - Refactor `create_tao_window` API to return `Weak` instead of `Arc`. - [c1494b35](https://www.github.com/tauri-apps/tauri/commit/c1494b353233c6a9552d7ace962fdf8d5b1f199a) refactor: return Weak on create_tao_window on 2021-08-31 - Added `any_thread` constructor on the `Runtime` trait (only possible on Linux and Windows). - [af44bf81](https://www.github.com/tauri-apps/tauri/commit/af44bf8168310cf77fbe102a53e7c433f11641a3) feat(core): allow app run on any thread on Linux & Windows, closes [#3172](https://www.github.com/tauri-apps/tauri/pull/3172) ([#3353](https://www.github.com/tauri-apps/tauri/pull/3353)) on 2022-02-07 - Added `run_on_main_thread` API on `RuntimeHandle`. - [53fdfe52](https://www.github.com/tauri-apps/tauri/commit/53fdfe52bb30d52653c72ca9f42506c3863dcf4a) feat(core): expose `run_on_main_thread` API ([#2711](https://www.github.com/tauri-apps/tauri/pull/2711)) on 2021-10-04 - **Breaking change:** Renamed the `RPC` interface to `IPC`. - [3420aa50](https://www.github.com/tauri-apps/tauri/commit/3420aa5031b3274a95c6c5fa0f8683ca13213396) refactor: IPC handler \[TRI-019] ([#9](https://www.github.com/tauri-apps/tauri/pull/9)) on 2022-01-09 - Added `open_devtools` to the `Dispatcher` trait. - [55aa22de](https://www.github.com/tauri-apps/tauri/commit/55aa22de80c3de873e29bcffcb5b2fe236a637a6) feat(core): add `Window#open_devtools` API, closes [#1213](https://www.github.com/tauri-apps/tauri/pull/1213) ([#3350](https://www.github.com/tauri-apps/tauri/pull/3350)) on 2022-02-07 - The minimum Rust version is now `1.56`. - [a9dfc015](https://www.github.com/tauri-apps/tauri/commit/a9dfc015505afe91281c2027954ffcc588b1a59c) feat: update to edition 2021 and set minimum rust to 1.56 ([#2789](https://www.github.com/tauri-apps/tauri/pull/2789)) on 2021-10-22 - Replace all of the `winapi` crate references with the `windows` crate, and replace `webview2` and `webview2-sys` with `webview2-com` and `webview2-com-sys` built with the `windows` crate. This goes along with updates to the TAO and WRY `next` branches. - [bb00d5bd](https://www.github.com/tauri-apps/tauri/commit/bb00d5bd6c9dfcb6bdd0d308dadb70e6c6aafe5c) Replace winapi with windows crate and use webview2-com instead of webview2 ([#2615](https://www.github.com/tauri-apps/tauri/pull/2615)) on 2021-09-24 - Update the `windows` crate to 0.25.0, which comes with pre-built libraries. WRY and Tao can both reference the same types directly from the `windows` crate instead of sharing bindings in `webview2-com-sys`. - [34be6cf3](https://www.github.com/tauri-apps/tauri/commit/34be6cf37a98ee7cbd66623ebddae08e5a6520fd) Update webview2-com and windows crates ([#2875](https://www.github.com/tauri-apps/tauri/pull/2875)) on 2021-11-11 - This is a temporary fix of null pointer crash on `get_content` of web resource request. We will switch it back once upstream is updated. - [84f6e3e8](https://www.github.com/tauri-apps/tauri/commit/84f6e3e84a34b01b7fa04f5c4719acb921ef4263) Switch to next branch of wry ([#2574](https://www.github.com/tauri-apps/tauri/pull/2574)) on 2021-09-10 - Update wry to 0.13. - [343ea3e2](https://www.github.com/tauri-apps/tauri/commit/343ea3e2e8d51bac63ab651289295c26fcc841d8) Update wry to 0.13 ([#3336](https://www.github.com/tauri-apps/tauri/pull/3336)) on 2022-02-06 ## \[0.2.1] - Migrate to latest custom protocol allowing `Partial content` streaming and Header parsing. - [539e4489](https://www.github.com/tauri-apps/tauri/commit/539e4489e0bac7029d86917e9982ea49e02fe489) refactor: custom protocol ([#2503](https://www.github.com/tauri-apps/tauri/pull/2503)) on 2021-08-23 ## \[0.2.0] - Fix blur/focus events being incorrect on Windows. - [d832d575](https://www.github.com/tauri-apps/tauri/commit/d832d575d9b03a0ff78accabe4631cc638c08c3b) fix(windows): use webview events on windows ([#2277](https://www.github.com/tauri-apps/tauri/pull/2277)) on 2021-07-23 - Add `ExitRequested` event that allows preventing the app from exiting when all windows are closed, and an `AppHandle.exit()` function to exit the app manually. - [892c63a0](https://www.github.com/tauri-apps/tauri/commit/892c63a0538f8d62680dce5848657128ad6b7af3) feat([#2287](https://www.github.com/tauri-apps/tauri/pull/2287)): Add `ExitRequested` event to let users prevent app from exiting ([#2293](https://www.github.com/tauri-apps/tauri/pull/2293)) on 2021-08-09 - Update gtk and its related libraries to v0.14. This also remove requirements of `clang` as build dependency. - [63ad3039](https://www.github.com/tauri-apps/tauri/commit/63ad303903bbee7c9a7382413b342e2a05d3ea75) chore(linux): bump gtk to v0.14 ([#2361](https://www.github.com/tauri-apps/tauri/pull/2361)) on 2021-08-07 - Implement `Debug` on public API structs and enums. - [fa9341ba](https://www.github.com/tauri-apps/tauri/commit/fa9341ba18ba227735341530900714dba0f27291) feat(core): implement `Debug` on public API structs/enums, closes [#2292](https://www.github.com/tauri-apps/tauri/pull/2292) ([#2387](https://www.github.com/tauri-apps/tauri/pull/2387)) on 2021-08-11 - Fix the error "cannot find type MenuHash in this scope" - [226414d1](https://www.github.com/tauri-apps/tauri/commit/226414d1a588c8bc2b540a71fcd84c318319d6af) "cannot find type `MenuHash` in this scope" ([#2240](https://www.github.com/tauri-apps/tauri/pull/2240)) on 2021-07-20 - Panic when a dispatcher getter method (`Window`, `GlobalShortcutHandle`, `ClipboardManager` and `MenuHandle` APIs) is called on the main thread. - [50ffdc06](https://www.github.com/tauri-apps/tauri/commit/50ffdc06fbde56aba32b4291fd130104935d1408) feat(core): panic when a dispatcher getter is used on the main thread ([#2455](https://www.github.com/tauri-apps/tauri/pull/2455)) on 2021-08-16 - Remove menu feature flag since there's no package dependency need to be installed on any platform anymore. - [f81ebddf](https://www.github.com/tauri-apps/tauri/commit/f81ebddfcc1aea0d4989706aef43538e8ea98bea) feat: remove menu feature flag ([#2415](https://www.github.com/tauri-apps/tauri/pull/2415)) on 2021-08-13 - Adds `Resumed` and `MainEventsCleared` variants to the `RunEvent` enum. - [6be3f433](https://www.github.com/tauri-apps/tauri/commit/6be3f4339168651fe4e003b09f7d181fd12cd5a8) feat(core): add `Resumed` and `MainEventsCleared` events, closes [#2127](https://www.github.com/tauri-apps/tauri/pull/2127) ([#2439](https://www.github.com/tauri-apps/tauri/pull/2439)) on 2021-08-15 - Adds `set_activation_policy` API to the `Runtime` trait (macOS only). - [4a031add](https://www.github.com/tauri-apps/tauri/commit/4a031add69014a1f3823f4ea19b172a2557f6794) feat(core): expose `set_activation_policy`, closes [#2258](https://www.github.com/tauri-apps/tauri/pull/2258) ([#2420](https://www.github.com/tauri-apps/tauri/pull/2420)) on 2021-08-13 - Allow creation of empty Window with `create_tao_window()` and management with `send_tao_window_event()` on the AppHandler. - [88080855](https://www.github.com/tauri-apps/tauri/commit/8808085541a629b8e22b612a06cef01cf9b3722e) feat(window): Allow creation of Window without `wry` ([#2321](https://www.github.com/tauri-apps/tauri/pull/2321)) on 2021-07-29 - [15566cfd](https://www.github.com/tauri-apps/tauri/commit/15566cfd64f5072fa4980a6ce5b33259958e9021) feat(core): add API to send wry window message to the event loop ([#2339](https://www.github.com/tauri-apps/tauri/pull/2339)) on 2021-08-02 - - Support [macOS tray icon template](https://developer.apple.com/documentation/appkit/nsimage/1520017-template?language=objc) to adjust automatically based on taskbar color. - Images you mark as template images should consist of only black and clear colors. You can use the alpha channel in the image to adjust the opacity of black content, however. - [426a6b49](https://www.github.com/tauri-apps/tauri/commit/426a6b49962de8faf061db2e820ac10fcbb300d6) feat(macOS): Implement tray icon template ([#2322](https://www.github.com/tauri-apps/tauri/pull/2322)) on 2021-07-29 - Add `Event::Ready` on the `run()` callback. Triggered once when the event loop is ready. - [28c6b7ad](https://www.github.com/tauri-apps/tauri/commit/28c6b7adfe98e701b158e936eafb7541ddc700e0) feat: add `Event::Ready` ([#2433](https://www.github.com/tauri-apps/tauri/pull/2433)) on 2021-08-15 - Add webdriver support to Tauri. - [be76fb1d](https://www.github.com/tauri-apps/tauri/commit/be76fb1dfe73a1605cc2ad246418579f4c2e1999) WebDriver support ([#1972](https://www.github.com/tauri-apps/tauri/pull/1972)) on 2021-06-23 - [b4426eda](https://www.github.com/tauri-apps/tauri/commit/b4426eda9e64fcdd25a2d72e548b8b0fbfa09619) Revert "WebDriver support ([#1972](https://www.github.com/tauri-apps/tauri/pull/1972))" on 2021-06-23 - [4b2aa356](https://www.github.com/tauri-apps/tauri/commit/4b2aa35684632ed2afd7dec4ad848df5704868e4) Add back WebDriver support ([#2324](https://www.github.com/tauri-apps/tauri/pull/2324)) on 2021-08-01 ## \[0.1.4] - Allow preventing window close when the user requests it. - [8157a68a](https://www.github.com/tauri-apps/tauri/commit/8157a68af1d94de1b90a14aa44139bb123b3436b) feat(core): allow listening to event loop events & prevent window close ([#2131](https://www.github.com/tauri-apps/tauri/pull/2131)) on 2021-07-06 - Fixes SVG loading on custom protocol. - [e663bdd5](https://www.github.com/tauri-apps/tauri/commit/e663bdd5938830ab4eba961e69c3985191b499dd) fix(core): svg mime type ([#2129](https://www.github.com/tauri-apps/tauri/pull/2129)) on 2021-06-30 - Fixes `center` and `focus` not being allowed in `tauri.conf.json > tauri > windows` and ignored in `WindowBuilderWrapper`. - [bc2c331d](https://www.github.com/tauri-apps/tauri/commit/bc2c331dec3dec44c79e659b082b5fb6b65cc5ea) fix: center and focus not being allowed in config ([#2199](https://www.github.com/tauri-apps/tauri/pull/2199)) on 2021-07-12 - Expose `gtk_window` getter. - [e0a8e09c](https://www.github.com/tauri-apps/tauri/commit/e0a8e09cab6799eeb9ec524b5f7780d1e5a84299) feat(core): expose `gtk_window`, closes [#2083](https://www.github.com/tauri-apps/tauri/pull/2083) ([#2141](https://www.github.com/tauri-apps/tauri/pull/2141)) on 2021-07-02 - Remove a few locks requirement in tauri-runtime-wry - [6569c2bf](https://www.github.com/tauri-apps/tauri/commit/6569c2bf5caf24b009cad1e2cffba25418d6bb68) refactor(wry): remove a few locks requirements ([#2137](https://www.github.com/tauri-apps/tauri/pull/2137)) on 2021-07-02 - Fix macOS high CPU usage. - [a280ee90](https://www.github.com/tauri-apps/tauri/commit/a280ee90af0749ce18d6d0b00939b06473717bc9) Fix high cpu usage on mac, fix [#2074](https://www.github.com/tauri-apps/tauri/pull/2074) ([#2125](https://www.github.com/tauri-apps/tauri/pull/2125)) on 2021-06-30 - Bump `wry` 0.11 and fix focus integration to make it compatible with tao 0.4. - [f0a8db62](https://www.github.com/tauri-apps/tauri/commit/f0a8db62e445dbbc5770e7addf0390ce3844c1ea) core(deps): bump `wry` to `0.11` ([#2210](https://www.github.com/tauri-apps/tauri/pull/2210)) on 2021-07-15 - `Params` has been removed, along with all the associated types on it. Functions that previously accepted those associated types now accept strings instead. Type that used a generic parameter `Params` now use `Runtime` instead. If you use the `wry` feature, then types with a `Runtime` generic parameter should default to `Wry`, letting you omit the explicit type and let the compiler infer it instead. `tauri`: - See `Params` note - If you were using `Params` inside a function parameter or definition, all references to it have been replaced with a simple runtime that defaults to `Wry`. If you are not using a custom runtime, just remove `Params` from the definition of functions/items that previously took it. If you are using a custom runtime, you *may* need to pass the runtime type to these functions. - If you were using custom types for `Params` (uncommon and if you don't understand you probably were not using it), all methods that were previously taking the custom type now takes an `Into` or a `&str`. The types were already required to be string-able, so just make sure to convert it into a string before passing it in if this breaking change affects you. `tauri-macros`: - (internal) Added private `default_runtime` proc macro to allow us to give item definitions a custom runtime only when the specified feature is enabled. `tauri-runtime`: - See `Params` note - Removed `Params`, `MenuId`, `Tag`, `TagRef`. - Added `menu::{MenuHash, MenuId, MenuIdRef}` as type aliases for the internal type that menu types now use. - All previous menu items that had a `MenuId` generic now use the underlying `MenuId` type without a generic. - `Runtime`, `RuntimeHandle`, and `Dispatch` have no more generic parameter on `create_window(...)` and instead use the `Runtime` type directly - `Runtime::system_tray` has no more `MenuId` generic and uses the string based `SystemTray` type directly. - (internal) `CustomMenuItem::id_value()` is now hashed on creation and exposed as the `id` field with type `MenuHash`. `tauri-runtime-wry`: - See `Params` note - update menu and runtime related types to the ones changed in `tauri-runtime`. `tauri-utils`: - `Assets::get` signature has changed to take a `&AssetKey` instead of `impl Into` to become trait object safe. - [fd8fab50](https://www.github.com/tauri-apps/tauri/commit/fd8fab507c8fa1b113b841af14c6693eb3955f6b) refactor(core): remove `Params` and replace with strings ([#2191](https://www.github.com/tauri-apps/tauri/pull/2191)) on 2021-07-15 ## \[0.1.3] - `Window` is now `Send + Sync` on Windows. - [fe32afcc](https://www.github.com/tauri-apps/tauri/commit/fe32afcc933920d6282ae1d63b041b182278a031) fix(core): `Window` must be `Send + Sync` on Windows, closes [#2078](https://www.github.com/tauri-apps/tauri/pull/2078) ([#2093](https://www.github.com/tauri-apps/tauri/pull/2093)) on 2021-06-27 ## \[0.1.2] - Adds `clipboard` APIs (write and read text). - [285bf64b](https://www.github.com/tauri-apps/tauri/commit/285bf64bf9569efb2df904c69c6df405ff0d62e2) feat(core): add clipboard writeText and readText APIs ([#2035](https://www.github.com/tauri-apps/tauri/pull/2035)) on 2021-06-21 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Fixes window event being emitted to all windows listeners. - [fca97640](https://www.github.com/tauri-apps/tauri/commit/fca976404e6bec373a81332572458c4c44f7bb3a) fix(wry): window event listeners being emitted to all windows ([#2056](https://www.github.com/tauri-apps/tauri/pull/2056)) on 2021-06-23 - Panic on window getters usage on the main thread when the event loop is not running and document it. - [ab3eb44b](https://www.github.com/tauri-apps/tauri/commit/ab3eb44bac7a3bf73a4985df38ccc2b87a913be7) fix(core): deadlock on window getters, fixes [#1893](https://www.github.com/tauri-apps/tauri/pull/1893) ([#1998](https://www.github.com/tauri-apps/tauri/pull/1998)) on 2021-06-16 - Adds `focus` API to the WindowBuilder. - [5f351622](https://www.github.com/tauri-apps/tauri/commit/5f351622c7812ad1bb56ddb37364ccaa4124c24b) feat(core): add focus API to the WindowBuilder and WindowOptions, [#1737](https://www.github.com/tauri-apps/tauri/pull/1737) on 2021-05-30 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Adds support to PNG icons. - [40b717ed](https://www.github.com/tauri-apps/tauri/commit/40b717edc57288a1393fad0529390e101ab903c1) feat(core): set window icon on Linux, closes [#1922](https://www.github.com/tauri-apps/tauri/pull/1922) ([#1937](https://www.github.com/tauri-apps/tauri/pull/1937)) on 2021-06-01 - Adds `is_decorated` getter on Window. - [f58a2114](https://www.github.com/tauri-apps/tauri/commit/f58a2114fbfd5307c349f05c88f2e08fd8baa8aa) feat(core): add `is_decorated` Window getter on 2021-05-30 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Adds `is_resizable` getter on Window. - [1e8af280](https://www.github.com/tauri-apps/tauri/commit/1e8af280c27f381828d6209722b10e889082fa00) feat(core): add `is_resizable` Window getter on 2021-05-30 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Adds `is_visible` getter on Window. - [36506c96](https://www.github.com/tauri-apps/tauri/commit/36506c967de82bc7ff453d11e6104ecf66d7a588) feat(core): add `is_visible` API on 2021-05-30 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Removes `image` dependency. For now only `.ico` icons on Windows are supported, and we'll implement other types on demand to optimize bundle size. - [1be37a3f](https://www.github.com/tauri-apps/tauri/commit/1be37a3f30ff789d9396ec9009f9c0dd0bb928a7) refactor(core): remove `image` dependency ([#1859](https://www.github.com/tauri-apps/tauri/pull/1859)) on 2021-05-18 - The `run_on_main_thread` API now uses WRY's UserEvent, so it wakes the event loop. - [9bf82f0d](https://www.github.com/tauri-apps/tauri/commit/9bf82f0d9261808f58bdb5b5dbd6a255e5dcd333) fix(core): `run_on_main_thread` now wakes the event loop ([#1949](https://www.github.com/tauri-apps/tauri/pull/1949)) on 2021-06-04 - Adds global shortcut interfaces. - [3280c4aa](https://www.github.com/tauri-apps/tauri/commit/3280c4aa91e50a8ccdd561a8b48a12a4a13ea8d5) refactor(core): global shortcut is now provided by `tao` ([#2031](https://www.github.com/tauri-apps/tauri/pull/2031)) on 2021-06-21 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Adds `request_user_attention` API to the `Dispatcher` trait. - [7dcca6e9](https://www.github.com/tauri-apps/tauri/commit/7dcca6e9281182b11ad3d4a79871f09b30b9b419) feat(core): add `request_user_attention` API, closes [#2023](https://www.github.com/tauri-apps/tauri/pull/2023) ([#2026](https://www.github.com/tauri-apps/tauri/pull/2026)) on 2021-06-20 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Adds `fn run_iteration` (macOS and Windows only) to the Runtime trait. - [8c0d0739](https://www.github.com/tauri-apps/tauri/commit/8c0d0739eebf7286b64a5380e922746411eb52c6) feat(core): add `run_iteration`, `parent_window` and `owner_window` APIs, closes [#1872](https://www.github.com/tauri-apps/tauri/pull/1872) ([#1874](https://www.github.com/tauri-apps/tauri/pull/1874)) on 2021-05-21 - Adds `show_menu`, `hide_menu` and `is_menu_visible` APIs to the `Dispatcher` trait. - [954460c5](https://www.github.com/tauri-apps/tauri/commit/954460c5205d57444ef4b1412051fbedf3e38676) feat(core): MenuHandle `show`, `hide`, `is_visible` and `toggle` APIs ([#1958](https://www.github.com/tauri-apps/tauri/pull/1958)) on 2021-06-15 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Adds `set_focus` API on Window. - [bb6992f8](https://www.github.com/tauri-apps/tauri/commit/bb6992f888196ca7c87bb2fe74ad2bd8bf393e05) feat(core): add `set_focus` window API, fixes [#1737](https://www.github.com/tauri-apps/tauri/pull/1737) on 2021-05-30 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Adds `set_skip_taskbar` API on Window. - [e06aa277](https://www.github.com/tauri-apps/tauri/commit/e06aa277384450cfef617c0e57b0d5d403bb1e7f) feat(core): add `set_skip_taskbar` API on 2021-05-30 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Update `wry` to v0.10.0 and replace the removed `dispatch_script` and `evaluate_script` methods with the new `evaluate_script` method in `handle_event_loop`. - [cca8115d](https://www.github.com/tauri-apps/tauri/commit/cca8115d9c813d13efb30a38445d5bda009a7f97) refactor: update wry, simplify script eval ([#1965](https://www.github.com/tauri-apps/tauri/pull/1965)) on 2021-06-16 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Adds `skip_taskbar` API to the WindowBuilder. - [5525b03a](https://www.github.com/tauri-apps/tauri/commit/5525b03a78a2232c650043fbd9894ce1553cad41) feat(core): add `skip_taskbar` API to the WindowBuilder/WindowOptions on 2021-05-30 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - Adds `Window#center` and `WindowBuilder#center` APIs. - [5cba6eb4](https://www.github.com/tauri-apps/tauri/commit/5cba6eb4d28d53f06855d60d4d0eae6b95233ccf) feat(core): add window `center` API, closes [#1822](https://www.github.com/tauri-apps/tauri/pull/1822) ([#1954](https://www.github.com/tauri-apps/tauri/pull/1954)) on 2021-06-05 - Adds `parent_window` and `owner_window` setters to the `WindowBuilder` (Windows only). - [8c0d0739](https://www.github.com/tauri-apps/tauri/commit/8c0d0739eebf7286b64a5380e922746411eb52c6) feat(core): add `run_iteration`, `parent_window` and `owner_window` APIs, closes [#1872](https://www.github.com/tauri-apps/tauri/pull/1872) ([#1874](https://www.github.com/tauri-apps/tauri/pull/1874)) on 2021-05-21 - Adds window native handle getter (HWND on Windows). - [abf78c58](https://www.github.com/tauri-apps/tauri/commit/abf78c5860cdc52fbfd2bc5dbca29a864e2da8f9) fix(core): set parent window handle on dialogs, closes [#1876](https://www.github.com/tauri-apps/tauri/pull/1876) ([#1889](https://www.github.com/tauri-apps/tauri/pull/1889)) on 2021-05-21 ## \[0.1.1] - Fixes `system-tray` feature usage. - [1ab8dd9](https://www.github.com/tauri-apps/tauri/commit/1ab8dd93e670d2a2d070c7a6ec48308a0ab32f1a) fix(core): `system-tray` cargo feature usage, fixes [#1798](https://www.github.com/tauri-apps/tauri/pull/1798) ([#1801](https://www.github.com/tauri-apps/tauri/pull/1801)) on 2021-05-12 - Fixes webview transparency. - [f5a480f](https://www.github.com/tauri-apps/tauri/commit/f5a480fea34ab3a75751f1ca760a38b3e53da2cc) fix(core): window transparency ([#1800](https://www.github.com/tauri-apps/tauri/pull/1800)) on 2021-05-12 ## \[0.1.0] - **Breaking:** `Context` fields are now private, and is expected to be created through `Context::new(...)`. All fields previously available through `Context` are now public methods. - [5542359](https://www.github.com/tauri-apps/tauri/commit/55423590ddbf560684dab6a0214acf95aadfa8d2) refactor(core): Context fields now private, Icon used on all platforms ([#1774](https://www.github.com/tauri-apps/tauri/pull/1774)) on 2021-05-11 - `tauri-runtime-wry` initial release. - [45a7a11](https://www.github.com/tauri-apps/tauri/commit/45a7a111e0cf9d9956d713cc9a99fa7a5313eec7) feat(core): add `tauri-wry` crate ([#1756](https://www.github.com/tauri-apps/tauri/pull/1756)) on 2021-05-09 ================================================ FILE: crates/tauri-runtime-wry/Cargo.toml ================================================ [package] name = "tauri-runtime-wry" version = "2.10.1" description = "Wry bindings to the Tauri runtime" exclude = ["CHANGELOG.md", "/target"] readme = "README.md" authors.workspace = true homepage.workspace = true repository.workspace = true categories.workspace = true license.workspace = true edition.workspace = true rust-version.workspace = true [dependencies] wry = { version = "0.54.0", default-features = false, features = [ "drag-drop", "protocol", "os-webview", "linux-body", ] } tao = { version = "0.34.5", default-features = false, features = ["rwh_06"] } tauri-runtime = { version = "2.10.1", path = "../tauri-runtime" } tauri-utils = { version = "2.8.3", path = "../tauri-utils" } raw-window-handle = "0.6" http = "1" url = "2" tracing = { version = "0.1", optional = true } log = "0.4.21" [target."cfg(windows)".dependencies] webview2-com = "0.38" softbuffer = { version = "0.4", default-features = false } once_cell = "1.20" [target."cfg(windows)".dependencies.windows] version = "0.61" features = ["Win32_Foundation", "Win32_Graphics_Dwm"] [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"] } webkit2gtk = { version = "=2.0", features = ["v2_40"] } percent-encoding = "2" [target.'cfg(target_vendor = "apple")'.dependencies] objc2 = "0.6" [target.'cfg(target_os = "macos")'.dependencies] objc2-app-kit = { version = "0.3", default-features = false, features = [ "block2", "NSApplication", "NSResponder", "NSView", "NSWindow", "NSScreen", "NSGraphics", ] } [target."cfg(target_os = \"android\")".dependencies] jni = "0.21" [features] default = ["x11"] devtools = ["wry/devtools", "tauri-runtime/devtools"] x11 = ["tao/x11", "wry/x11"] macos-private-api = [ "wry/fullscreen", "wry/transparent", "tauri-runtime/macos-private-api", ] # TODO: Remove in v3 - wry does not have this feature anymore objc-exception = [] tracing = ["dep:tracing", "wry/tracing"] macos-proxy = ["wry/mac-proxy"] unstable = [] common-controls-v6 = [] ================================================ FILE: crates/tauri-runtime-wry/LICENSE_APACHE-2.0 ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS ================================================ FILE: crates/tauri-runtime-wry/LICENSE_MIT ================================================ MIT License Copyright (c) 2017 - Present Tauri Apps Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: crates/tauri-runtime-wry/README.md ================================================ # tauri-runtime-wry [![status](https://img.shields.io/badge/Status-Beta-green.svg)](https://github.com/tauri-apps/tauri) [![Chat Server](https://img.shields.io/badge/chat-on%20discord-7289da.svg)](https://discord.gg/SpmNs4S) [![test core](https://img.shields.io/github/actions/workflow/status/tauri-apps/tauri/test-core.yml?label=test%20core&logo=github)](https://github.com/tauri-apps/tauri/actions/workflows/test-core.yml) [![website](https://img.shields.io/badge/website-tauri.app-purple.svg)](https://tauri.app) [![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-Opencollective-blue.svg)](https://opencollective.com/tauri) | Component | Version | | ----------------- | ---------------------------------------------------------------------------------------------------------------------- | | tauri-runtime-wry | [![](https://img.shields.io/crates/v/tauri-runtime-wry?style=flat-square)](https://crates.io/crates/tauri-runtime-wry) | ## About Tauri Tauri is a polyglot and generic system that is very composable and allows engineers to make a wide variety of applications. It is used for building applications for Desktop Computers using a combination of Rust tools and HTML rendered in a Webview. Apps built with Tauri can ship with any number of pieces of an optional JS API / Rust API so that webviews can control the system via message passing. In fact, developers can extend the default API with their own functionality and bridge the Webview and Rust-based backend easily. Tauri apps can have custom menus and have tray-type interfaces. They can be updated, and are managed by the user's operating system as expected. They are very small, because they use the system's webview. They do not ship a runtime, since the final binary is compiled from rust. This makes the reversing of Tauri apps not a trivial task. ## This module This crate opens up direct systems-level interactions specifically for WRY, such as printing, monitor detection, and other windowing related tasks. `tauri-runtime` implementation for WRY. None of the exposed API of this crate is stable, and it may break semver compatibility in the future. The major version only signifies the intended Tauri version. To learn more about the details of how all of these pieces fit together, please consult this [ARCHITECTURE.md](https://github.com/tauri-apps/tauri/blob/dev/ARCHITECTURE.md) document. ## Semver **tauri** is following [Semantic Versioning 2.0](https://semver.org/). ## Licenses Code: (c) 2021 - The Tauri Programme within The Commons Conservancy. MIT or MIT/Apache 2.0 where applicable. Logo: CC-BY-NC-ND - Original Tauri Logo Designs by [Daniel Thompson-Yvetot](https://github.com/nothingismagick) and [Guillaume Chau](https://github.com/akryum) ================================================ FILE: crates/tauri-runtime-wry/build.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT // creates a cfg alias if `has_feature` is true. // `alias` must be a snake case string. fn alias(alias: &str, has_feature: bool) { println!("cargo:rustc-check-cfg=cfg({alias})"); if has_feature { println!("cargo:rustc-cfg={alias}"); } } fn main() { let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap(); let mobile = target_os == "ios" || target_os == "android"; alias("desktop", !mobile); alias("mobile", mobile); } ================================================ FILE: crates/tauri-runtime-wry/src/dialog/mod.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT #[cfg(windows)] mod windows; pub fn error>(err: S) { #[cfg(windows)] windows::error(err); #[cfg(not(windows))] { unimplemented!("Error dialog is not implemented for this platform"); } } ================================================ FILE: crates/tauri-runtime-wry/src/dialog/windows.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use windows::core::{w, HSTRING}; enum Level { Error, #[allow(unused)] Warning, #[allow(unused)] Info, } pub fn error>(err: S) { dialog_inner(err.as_ref(), Level::Error); } fn dialog_inner(err: &str, level: Level) { let title = match level { Level::Warning => w!("Warning"), Level::Error => w!("Error"), Level::Info => w!("Info"), }; #[cfg(not(feature = "common-controls-v6"))] { use windows::Win32::UI::WindowsAndMessaging::*; let err = remove_hyperlink(err); let err = HSTRING::from(err); unsafe { MessageBoxW( None, &err, title, match level { Level::Warning => MB_ICONWARNING, Level::Error => MB_ICONERROR, Level::Info => MB_ICONINFORMATION, }, ) }; } #[cfg(feature = "common-controls-v6")] { use windows::core::{HRESULT, PCWSTR}; use windows::Win32::Foundation::*; use windows::Win32::UI::Controls::*; use windows::Win32::UI::Shell::*; use windows::Win32::UI::WindowsAndMessaging::*; extern "system" fn task_dialog_callback( _hwnd: HWND, msg: TASKDIALOG_NOTIFICATIONS, _wparam: WPARAM, lparam: LPARAM, _data: isize, ) -> HRESULT { if msg == TDN_HYPERLINK_CLICKED { let link = PCWSTR(lparam.0 as _); let _ = unsafe { ShellExecuteW(None, None, link, None, None, SW_SHOWNORMAL) }; } S_OK } let err = HSTRING::from(err); let err = PCWSTR(err.as_ptr()); let task_dialog_config = TASKDIALOGCONFIG { cbSize: std::mem::size_of::() as u32, dwFlags: TDF_ALLOW_DIALOG_CANCELLATION | TDF_ENABLE_HYPERLINKS, pszWindowTitle: title, pszContent: err, Anonymous1: TASKDIALOGCONFIG_0 { pszMainIcon: match level { Level::Warning => TD_WARNING_ICON, Level::Error => TD_ERROR_ICON, Level::Info => TD_INFORMATION_ICON, }, }, dwCommonButtons: TDCBF_OK_BUTTON, pfCallback: Some(task_dialog_callback), ..Default::default() }; let _ = unsafe { TaskDialogIndirect(&task_dialog_config, None, None, None) }; } } #[cfg(not(feature = "common-controls-v6"))] fn remove_hyperlink(str: &str) -> String { let mut result = String::new(); let mut in_hyperlink = false; for c in str.chars() { if c == '<' { in_hyperlink = true; } else if c == '>' { in_hyperlink = false; } else if !in_hyperlink { result.push(c); } } result } #[cfg(test)] #[cfg(not(feature = "common-controls-v6"))] mod tests { use super::*; #[test] fn test_remove_hyperlink() { let input = "This is a test string."; let expected = "This is a test string."; let result = remove_hyperlink(input); assert_eq!(result, expected); } } ================================================ FILE: crates/tauri-runtime-wry/src/lib.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT //! The [`wry`] Tauri [`Runtime`]. //! //! None of the exposed API of this crate is stable, and it may break semver //! compatibility in the future. The major version only signifies the intended Tauri version. #![doc( html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png", html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png" )] use self::monitor::MonitorExt; use http::Request; #[cfg(target_os = "macos")] use objc2::ClassType; use raw_window_handle::{DisplayHandle, HasDisplayHandle, HasWindowHandle}; #[cfg(windows)] use tauri_runtime::webview::ScrollBarStyle; use tauri_runtime::{ dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size}, monitor::Monitor, webview::{DetachedWebview, DownloadEvent, PendingWebview, WebviewIpcHandler}, window::{ CursorIcon, DetachedWindow, DetachedWindowWebview, DragDropEvent, PendingWindow, RawWindow, WebviewEvent, WindowBuilder, WindowBuilderBase, WindowEvent, WindowId, WindowSizeConstraints, }, Cookie, DeviceEventFilter, Error, EventLoopProxy, ExitRequestedEventAction, Icon, ProgressBarState, ProgressBarStatus, Result, RunEvent, Runtime, RuntimeHandle, RuntimeInitArgs, UserAttentionType, UserEvent, WebviewDispatch, WebviewEventId, WindowDispatch, WindowEventId, }; #[cfg(target_vendor = "apple")] use objc2::rc::Retained; #[cfg(target_os = "macos")] use tao::platform::macos::{EventLoopWindowTargetExtMacOS, WindowBuilderExtMacOS}; #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] use tao::platform::unix::{WindowBuilderExtUnix, WindowExtUnix}; #[cfg(windows)] use tao::platform::windows::{WindowBuilderExtWindows, WindowExtWindows}; #[cfg(windows)] use webview2_com::{ContainsFullScreenElementChangedEventHandler, FocusChangedEventHandler}; #[cfg(windows)] use windows::Win32::Foundation::HWND; #[cfg(target_os = "ios")] use wry::WebViewBuilderExtIos; #[cfg(target_os = "macos")] use wry::WebViewBuilderExtMacos; #[cfg(windows)] use wry::WebViewBuilderExtWindows; #[cfg(target_vendor = "apple")] use wry::{WebViewBuilderExtDarwin, WebViewExtDarwin}; 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(desktop)] use tauri_utils::config::PreventOverflowConfig; #[cfg(target_os = "macos")] use tauri_utils::TitleBarStyle; use tauri_utils::{ config::{Color, WindowConfig}, Theme, }; use url::Url; #[cfg(windows)] use wry::ScrollBarStyle as WryScrollBarStyle; use wry::{ DragDropEvent as WryDragDropEvent, ProxyConfig, ProxyEndpoint, WebContext as WryWebContext, WebView, WebViewBuilder, }; pub use tao; pub use tao::window::{Window, WindowBuilder as TaoWindowBuilder, WindowId as TaoWindowId}; pub use wry; pub use wry::webview_version; #[cfg(windows)] use wry::WebViewExtWindows; #[cfg(target_os = "android")] use wry::{ prelude::{dispatch, find_class}, WebViewBuilderExtAndroid, WebViewExtAndroid, }; #[cfg(not(any( target_os = "windows", target_os = "macos", target_os = "ios", target_os = "android" )))] use wry::{WebViewBuilderExtUnix, WebViewExtUnix}; #[cfg(target_os = "ios")] pub use tao::platform::ios::WindowExtIOS; #[cfg(target_os = "macos")] pub use tao::platform::macos::{ ActivationPolicy as TaoActivationPolicy, EventLoopExtMacOS, WindowExtMacOS, }; #[cfg(target_os = "macos")] use tauri_runtime::ActivationPolicy; use std::{ cell::RefCell, collections::{ hash_map::Entry::{Occupied, Vacant}, BTreeMap, HashMap, HashSet, }, fmt, ops::Deref, path::PathBuf, rc::Rc, sync::{ atomic::{AtomicBool, AtomicU32, Ordering}, mpsc::{channel, Sender}, Arc, Mutex, Weak, }, thread::{current as current_thread, ThreadId}, }; pub type WebviewId = u32; type IpcHandler = dyn Fn(Request) + 'static; #[cfg(not(debug_assertions))] mod dialog; mod monitor; #[cfg(any( windows, target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] mod undecorated_resizing; mod util; mod webview; mod window; pub use webview::Webview; use window::WindowExt as _; #[derive(Debug)] pub struct WebContext { pub inner: WryWebContext, pub referenced_by_webviews: HashSet, // on Linux the custom protocols are associated with the context // and you cannot register a URI scheme more than once pub registered_custom_protocols: HashSet, } pub type WebContextStore = Arc, WebContext>>>; // window pub type WindowEventHandler = Box; pub type WindowEventListeners = Arc>>; pub type WebviewEventHandler = Box; pub type WebviewEventListeners = Arc>>; #[derive(Debug, Clone, Default)] pub struct WindowIdStore(Arc>>); impl WindowIdStore { pub fn insert(&self, w: TaoWindowId, id: WindowId) { self.0.lock().unwrap().insert(w, id); } pub fn get(&self, w: &TaoWindowId) -> Option { self.0.lock().unwrap().get(w).copied() } } #[macro_export] macro_rules! getter { ($self: ident, $rx: expr, $message: expr) => {{ $crate::send_user_message(&$self.context, $message)?; $rx .recv() .map_err(|_| $crate::Error::FailedToReceiveMessage) }}; } macro_rules! window_getter { ($self: ident, $message: expr) => {{ let (tx, rx) = channel(); getter!($self, rx, Message::Window($self.window_id, $message(tx))) }}; } macro_rules! event_loop_window_getter { ($self: ident, $message: expr) => {{ let (tx, rx) = channel(); getter!($self, rx, Message::EventLoopWindowTarget($message(tx))) }}; } macro_rules! webview_getter { ($self: ident, $message: expr) => {{ let (tx, rx) = channel(); getter!( $self, rx, Message::Webview( *$self.window_id.lock().unwrap(), $self.webview_id, $message(tx) ) ) }}; } pub(crate) fn send_user_message( context: &Context, message: Message, ) -> Result<()> { if current_thread().id() == context.main_thread_id { handle_user_message( &context.main_thread.window_target, message, UserMessageContext { window_id_map: context.window_id_map.clone(), windows: context.main_thread.windows.clone(), }, ); Ok(()) } else { context .proxy .send_event(message) .map_err(|_| Error::FailedToSendMessage) } } #[derive(Clone)] pub struct Context { pub window_id_map: WindowIdStore, main_thread_id: ThreadId, pub proxy: TaoEventLoopProxy>, main_thread: DispatcherMainThreadContext, plugins: Arc + Send>>>>, next_window_id: Arc, next_webview_id: Arc, next_window_event_id: Arc, next_webview_event_id: Arc, webview_runtime_installed: bool, } impl Context { pub fn run_threaded(&self, f: F) -> R where F: FnOnce(Option<&DispatcherMainThreadContext>) -> R, { f(if current_thread().id() == self.main_thread_id { Some(&self.main_thread) } else { None }) } fn next_window_id(&self) -> WindowId { self.next_window_id.fetch_add(1, Ordering::Relaxed).into() } fn next_webview_id(&self) -> WebviewId { self.next_webview_id.fetch_add(1, Ordering::Relaxed) } fn next_window_event_id(&self) -> u32 { self.next_window_event_id.fetch_add(1, Ordering::Relaxed) } fn next_webview_event_id(&self) -> u32 { self.next_webview_event_id.fetch_add(1, Ordering::Relaxed) } } impl Context { fn create_window( &self, pending: PendingWindow>, after_window_creation: Option, ) -> Result>> { let label = pending.label.clone(); let context = self.clone(); let window_id = self.next_window_id(); let (webview_id, use_https_scheme) = pending .webview .as_ref() .map(|w| { ( Some(context.next_webview_id()), w.webview_attributes.use_https_scheme, ) }) .unwrap_or((None, false)); send_user_message( self, Message::CreateWindow( window_id, Box::new(move |event_loop| { create_window( window_id, webview_id.unwrap_or_default(), event_loop, &context, pending, after_window_creation, ) }), ), )?; let dispatcher = WryWindowDispatcher { window_id, context: self.clone(), }; let detached_webview = webview_id.map(|id| { let webview = DetachedWebview { label: label.clone(), dispatcher: WryWebviewDispatcher { window_id: Arc::new(Mutex::new(window_id)), webview_id: id, context: self.clone(), }, }; DetachedWindowWebview { webview, use_https_scheme, } }); Ok(DetachedWindow { id: window_id, label, dispatcher, webview: detached_webview, }) } fn create_webview( &self, window_id: WindowId, pending: PendingWebview>, ) -> Result>> { let label = pending.label.clone(); let context = self.clone(); let webview_id = self.next_webview_id(); let window_id_wrapper = Arc::new(Mutex::new(window_id)); let window_id_wrapper_ = window_id_wrapper.clone(); send_user_message( self, Message::CreateWebview( window_id, Box::new(move |window, options| { create_webview( WebviewKind::WindowChild, window, window_id_wrapper_, webview_id, &context, pending, options.focused_webview, ) }), ), )?; let dispatcher = WryWebviewDispatcher { window_id: window_id_wrapper, webview_id, context: self.clone(), }; Ok(DetachedWebview { label, dispatcher }) } } #[cfg(feature = "tracing")] #[derive(Debug, Clone, Default)] pub struct ActiveTraceSpanStore(Rc>>); #[cfg(feature = "tracing")] impl ActiveTraceSpanStore { pub fn remove_window_draw(&self) { self .0 .borrow_mut() .retain(|t| !matches!(t, ActiveTracingSpan::WindowDraw { id: _, span: _ })); } } #[cfg(feature = "tracing")] #[derive(Debug)] pub enum ActiveTracingSpan { WindowDraw { id: TaoWindowId, span: tracing::span::EnteredSpan, }, } #[derive(Debug)] pub struct WindowsStore(pub RefCell>); // SAFETY: we ensure this type is only used on the main thread. #[allow(clippy::non_send_fields_in_send_ty)] unsafe impl Send for WindowsStore {} // SAFETY: we ensure this type is only used on the main thread. #[allow(clippy::non_send_fields_in_send_ty)] unsafe impl Sync for WindowsStore {} #[derive(Debug, Clone)] pub struct DispatcherMainThreadContext { pub window_target: EventLoopWindowTarget>, pub web_context: WebContextStore, // changing this to an Rc will cause frequent app crashes. pub windows: Arc, #[cfg(feature = "tracing")] pub active_tracing_spans: ActiveTraceSpanStore, } // SAFETY: we ensure this type is only used on the main thread. #[allow(clippy::non_send_fields_in_send_ty)] unsafe impl Send for DispatcherMainThreadContext {} // SAFETY: we ensure this type is only used on the main thread. #[allow(clippy::non_send_fields_in_send_ty)] unsafe impl Sync for DispatcherMainThreadContext {} impl fmt::Debug for Context { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Context") .field("main_thread_id", &self.main_thread_id) .field("proxy", &self.proxy) .field("main_thread", &self.main_thread) .finish() } } pub struct DeviceEventFilterWrapper(pub TaoDeviceEventFilter); impl From for DeviceEventFilterWrapper { fn from(item: DeviceEventFilter) -> Self { match item { DeviceEventFilter::Always => Self(TaoDeviceEventFilter::Always), DeviceEventFilter::Never => Self(TaoDeviceEventFilter::Never), DeviceEventFilter::Unfocused => Self(TaoDeviceEventFilter::Unfocused), } } } pub struct RectWrapper(pub wry::Rect); impl From for RectWrapper { fn from(value: tauri_runtime::dpi::Rect) -> Self { RectWrapper(wry::Rect { position: value.position, size: value.size, }) } } /// Wrapper around a [`tao::window::Icon`] that can be created from an [`Icon`]. pub struct TaoIcon(pub TaoWindowIcon); impl TryFrom> for TaoIcon { type Error = Error; fn try_from(icon: Icon<'_>) -> std::result::Result { TaoWindowIcon::from_rgba(icon.rgba.to_vec(), icon.width, icon.height) .map(Self) .map_err(|e| Error::InvalidIcon(Box::new(e))) } } pub struct WindowEventWrapper(pub Option); impl WindowEventWrapper { fn map_from_tao( event: &TaoWindowEvent<'_>, #[allow(unused_variables)] window: &WindowWrapper, ) -> Self { let event = match event { TaoWindowEvent::Resized(size) => WindowEvent::Resized(PhysicalSizeWrapper(*size).into()), TaoWindowEvent::Moved(position) => { WindowEvent::Moved(PhysicalPositionWrapper(*position).into()) } TaoWindowEvent::Destroyed => WindowEvent::Destroyed, TaoWindowEvent::ScaleFactorChanged { scale_factor, new_inner_size, } => WindowEvent::ScaleFactorChanged { scale_factor: *scale_factor, new_inner_size: PhysicalSizeWrapper(**new_inner_size).into(), }, TaoWindowEvent::Focused(focused) => { #[cfg(not(windows))] return Self(Some(WindowEvent::Focused(*focused))); // on multiwebview mode, if there's no focused webview, it means we're receiving a direct window focus change // (without receiving a webview focus, such as when clicking the taskbar app icon or using Alt + Tab) // in this case we must send the focus change event here #[cfg(windows)] if window.has_children.load(Ordering::Relaxed) { const FOCUSED_WEBVIEW_MARKER: &str = "__tauriWindow?"; let mut focused_webview = window.focused_webview.lock().unwrap(); // when we focus a webview and the window was previously focused, we get a blur event here // so on blur we should only send events if the current focus is owned by the window if !*focused && focused_webview .as_deref() .is_some_and(|w| w != FOCUSED_WEBVIEW_MARKER) { return Self(None); } // reset focused_webview on blur, or set to a dummy value on focus // (to prevent double focus event when we click a webview after focusing a window) *focused_webview = (*focused).then(|| FOCUSED_WEBVIEW_MARKER.to_string()); return Self(Some(WindowEvent::Focused(*focused))); } else { // when not on multiwebview mode, we handle focus change events on the webview (add_GotFocus and add_LostFocus) return Self(None); } } TaoWindowEvent::ThemeChanged(theme) => WindowEvent::ThemeChanged(map_theme(theme)), _ => return Self(None), }; Self(Some(event)) } fn parse(window: &WindowWrapper, event: &TaoWindowEvent<'_>) -> Self { match event { // resized event from tao doesn't include a reliable size on macOS // because wry replaces the NSView TaoWindowEvent::Resized(_) => { if let Some(w) = &window.inner { let size = inner_size( w, &window.webviews, window.has_children.load(Ordering::Relaxed), ); Self(Some(WindowEvent::Resized(PhysicalSizeWrapper(size).into()))) } else { Self(None) } } e => Self::map_from_tao(e, window), } } } pub fn map_theme(theme: &TaoTheme) -> Theme { match theme { TaoTheme::Light => Theme::Light, TaoTheme::Dark => Theme::Dark, _ => Theme::Light, } } #[cfg(target_os = "macos")] fn tao_activation_policy(activation_policy: ActivationPolicy) -> TaoActivationPolicy { match activation_policy { ActivationPolicy::Regular => TaoActivationPolicy::Regular, ActivationPolicy::Accessory => TaoActivationPolicy::Accessory, ActivationPolicy::Prohibited => TaoActivationPolicy::Prohibited, _ => unimplemented!(), } } pub struct MonitorHandleWrapper(pub MonitorHandle); impl From for Monitor { fn from(monitor: MonitorHandleWrapper) -> Monitor { Self { name: monitor.0.name(), position: PhysicalPositionWrapper(monitor.0.position()).into(), size: PhysicalSizeWrapper(monitor.0.size()).into(), work_area: monitor.0.work_area(), scale_factor: monitor.0.scale_factor(), } } } pub struct PhysicalPositionWrapper(pub TaoPhysicalPosition); impl From> for PhysicalPosition { fn from(position: PhysicalPositionWrapper) -> Self { Self { x: position.0.x, y: position.0.y, } } } impl From> for PhysicalPositionWrapper { fn from(position: PhysicalPosition) -> Self { Self(TaoPhysicalPosition { x: position.x, y: position.y, }) } } struct LogicalPositionWrapper(TaoLogicalPosition); impl From> for LogicalPositionWrapper { fn from(position: LogicalPosition) -> Self { Self(TaoLogicalPosition { x: position.x, y: position.y, }) } } pub struct PhysicalSizeWrapper(pub TaoPhysicalSize); impl From> for PhysicalSize { fn from(size: PhysicalSizeWrapper) -> Self { Self { width: size.0.width, height: size.0.height, } } } impl From> for PhysicalSizeWrapper { fn from(size: PhysicalSize) -> Self { Self(TaoPhysicalSize { width: size.width, height: size.height, }) } } struct LogicalSizeWrapper(TaoLogicalSize); impl From> for LogicalSizeWrapper { fn from(size: LogicalSize) -> Self { Self(TaoLogicalSize { width: size.width, height: size.height, }) } } pub struct SizeWrapper(pub TaoSize); impl From for SizeWrapper { fn from(size: Size) -> Self { match size { Size::Logical(s) => Self(TaoSize::Logical(LogicalSizeWrapper::from(s).0)), Size::Physical(s) => Self(TaoSize::Physical(PhysicalSizeWrapper::from(s).0)), } } } pub struct PositionWrapper(pub TaoPosition); impl From for PositionWrapper { fn from(position: Position) -> Self { match position { 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 TaoUserAttentionType); impl From for UserAttentionTypeWrapper { fn from(request_type: UserAttentionType) -> Self { let o = match request_type { UserAttentionType::Critical => TaoUserAttentionType::Critical, UserAttentionType::Informational => TaoUserAttentionType::Informational, }; Self(o) } } #[derive(Debug)] pub struct CursorIconWrapper(pub TaoCursorIcon); impl From for CursorIconWrapper { fn from(icon: CursorIcon) -> Self { use CursorIcon::*; let i = match icon { 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 TaoProgressState); impl From for ProgressStateWrapper { fn from(status: ProgressBarStatus) -> Self { let state = match status { 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 TaoProgressBarState); impl From for ProgressBarStateWrapper { fn from(progress_state: ProgressBarState) -> Self { Self(TaoProgressBarState { progress: progress_state.progress, state: progress_state .status .map(|state| ProgressStateWrapper::from(state).0), desktop_filename: progress_state.desktop_filename, }) } } #[derive(Clone, Default)] pub struct WindowBuilderWrapper { inner: TaoWindowBuilder, center: bool, prevent_overflow: Option, #[cfg(target_os = "macos")] tabbing_identifier: Option, } impl std::fmt::Debug for WindowBuilderWrapper { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut s = f.debug_struct("WindowBuilderWrapper"); s.field("inner", &self.inner) .field("center", &self.center) .field("prevent_overflow", &self.prevent_overflow); #[cfg(target_os = "macos")] { s.field("tabbing_identifier", &self.tabbing_identifier); } s.finish() } } // SAFETY: this type is `Send` since `menu_items` are read only here #[allow(clippy::non_send_fields_in_send_ty)] unsafe impl Send for WindowBuilderWrapper {} impl WindowBuilderBase for WindowBuilderWrapper {} impl WindowBuilder for WindowBuilderWrapper { fn new() -> Self { #[allow(unused_mut)] let mut builder = Self::default().focused(true); #[cfg(target_os = "macos")] { // TODO: find a proper way to prevent webview being pushed out of the window. // Workround for issue: https://github.com/tauri-apps/tauri/issues/10225 // The window requires `NSFullSizeContentViewWindowMask` flag to prevent devtools // pushing the content view out of the window. // By setting the default style to `TitleBarStyle::Visible` should fix the issue for most of the users. builder = builder.title_bar_style(TitleBarStyle::Visible); } builder = builder.title("Tauri App"); #[cfg(windows)] { builder = builder.window_classname("Tauri Window"); } builder } fn with_config(config: &WindowConfig) -> Self { let mut window = WindowBuilderWrapper::new(); #[cfg(target_os = "macos")] { window = window .hidden_title(config.hidden_title) .title_bar_style(config.title_bar_style); if let Some(identifier) = &config.tabbing_identifier { window = window.tabbing_identifier(identifier); } if let Some(position) = &config.traffic_light_position { window = window.traffic_light_position(tauri_runtime::dpi::LogicalPosition::new( position.x, position.y, )); } } #[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))] { window = window.transparent(config.transparent); } #[cfg(all( target_os = "macos", not(feature = "macos-private-api"), debug_assertions ))] if config.transparent { eprintln!( "The window is set to be transparent but the `macos-private-api` is not enabled. This can be enabled via the `tauri.macOSPrivateApi` configuration property "); } #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] { // Mouse event is disabled on Linux since sudden event bursts could block event loop. window.inner = window.inner.with_cursor_moved_event(false); } #[cfg(desktop)] { window = window .title(config.title.to_string()) .inner_size(config.width, config.height) .focused(config.focus) .focusable(config.focusable) .visible(config.visible) .resizable(config.resizable) .fullscreen(config.fullscreen) .decorations(config.decorations) .maximized(config.maximized) .always_on_bottom(config.always_on_bottom) .always_on_top(config.always_on_top) .visible_on_all_workspaces(config.visible_on_all_workspaces) .content_protected(config.content_protected) .skip_taskbar(config.skip_taskbar) .theme(config.theme) .closable(config.closable) .maximizable(config.maximizable) .minimizable(config.minimizable) .shadow(config.shadow); let mut constraints = WindowSizeConstraints::default(); if let Some(min_width) = config.min_width { constraints.min_width = Some(tao::dpi::LogicalUnit::new(min_width).into()); } if let Some(min_height) = config.min_height { constraints.min_height = Some(tao::dpi::LogicalUnit::new(min_height).into()); } if let Some(max_width) = config.max_width { constraints.max_width = Some(tao::dpi::LogicalUnit::new(max_width).into()); } if let Some(max_height) = config.max_height { constraints.max_height = Some(tao::dpi::LogicalUnit::new(max_height).into()); } if let Some(color) = config.background_color { window = window.background_color(color); } window = window.inner_size_constraints(constraints); if let (Some(x), Some(y)) = (config.x, config.y) { window = window.position(x, y); } if config.center { window = window.center(); } if let Some(window_classname) = &config.window_classname { window = window.window_classname(window_classname); } if let Some(prevent_overflow) = &config.prevent_overflow { window = match prevent_overflow { PreventOverflowConfig::Enable(true) => window.prevent_overflow(), PreventOverflowConfig::Margin(margin) => window .prevent_overflow_with_margin(TaoPhysicalSize::new(margin.width, margin.height).into()), _ => window, }; } } window } fn center(mut self) -> Self { self.center = true; self } fn position(mut self, x: f64, y: f64) -> Self { 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(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(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(TaoLogicalSize::new(max_width, max_height)); self } fn inner_size_constraints(mut self, constraints: WindowSizeConstraints) -> Self { self.inner.window.inner_size_constraints = tao::window::WindowSizeConstraints { min_width: constraints.min_width, min_height: constraints.min_height, max_width: constraints.max_width, max_height: constraints.max_height, }; self } /// Prevent the window from overflowing the working area (e.g. monitor size - taskbar size) on creation /// /// ## Platform-specific /// /// - **iOS / Android:** Unsupported. fn prevent_overflow(mut self) -> Self { self .prevent_overflow .replace(PhysicalSize::new(0, 0).into()); self } /// Prevent the window from overflowing the working area (e.g. monitor size - taskbar size) /// on creation with a margin /// /// ## Platform-specific /// /// - **iOS / Android:** Unsupported. fn prevent_overflow_with_margin(mut self, margin: Size) -> Self { self.prevent_overflow.replace(margin); self } fn resizable(mut self, resizable: bool) -> Self { self.inner = self.inner.with_resizable(resizable); self } fn maximizable(mut self, maximizable: bool) -> Self { self.inner = self.inner.with_maximizable(maximizable); self } fn minimizable(mut self, minimizable: bool) -> Self { self.inner = self.inner.with_minimizable(minimizable); self } fn closable(mut self, closable: bool) -> Self { self.inner = self.inner.with_closable(closable); self } fn title>(mut self, title: S) -> Self { self.inner = self.inner.with_title(title.into()); self } fn fullscreen(mut self, fullscreen: bool) -> Self { self.inner = if fullscreen { self .inner .with_fullscreen(Some(Fullscreen::Borderless(None))) } else { self.inner.with_fullscreen(None) }; self } fn focused(mut self, focused: bool) -> Self { self.inner = self.inner.with_focused(focused); self } fn focusable(mut self, focusable: bool) -> Self { self.inner = self.inner.with_focusable(focusable); self } fn maximized(mut self, maximized: bool) -> Self { self.inner = self.inner.with_maximized(maximized); self } fn visible(mut self, visible: bool) -> Self { self.inner = self.inner.with_visible(visible); self } #[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))] fn transparent(mut self, transparent: bool) -> Self { self.inner = self.inner.with_transparent(transparent); self } fn decorations(mut self, decorations: bool) -> Self { self.inner = self.inner.with_decorations(decorations); self } fn always_on_bottom(mut self, always_on_bottom: bool) -> Self { self.inner = self.inner.with_always_on_bottom(always_on_bottom); self } fn always_on_top(mut self, always_on_top: bool) -> Self { self.inner = self.inner.with_always_on_top(always_on_top); self } fn visible_on_all_workspaces(mut self, visible_on_all_workspaces: bool) -> Self { self.inner = self .inner .with_visible_on_all_workspaces(visible_on_all_workspaces); self } fn content_protected(mut self, protected: bool) -> Self { self.inner = self.inner.with_content_protection(protected); self } fn shadow(#[allow(unused_mut)] mut self, _enable: bool) -> Self { #[cfg(windows)] { self.inner = self.inner.with_undecorated_shadow(_enable); } #[cfg(target_os = "macos")] { self.inner = self.inner.with_has_shadow(_enable); } self } #[cfg(windows)] fn owner(mut self, owner: HWND) -> Self { self.inner = self.inner.with_owner_window(owner.0 as _); self } #[cfg(windows)] fn parent(mut self, parent: HWND) -> Self { self.inner = self.inner.with_parent_window(parent.0 as _); self } #[cfg(target_os = "macos")] fn parent(mut self, parent: *mut std::ffi::c_void) -> Self { self.inner = self.inner.with_parent_window(parent); self } #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] fn transient_for(mut self, parent: &impl gtk::glib::IsA) -> Self { self.inner = self.inner.with_transient_for(parent); self } #[cfg(windows)] fn drag_and_drop(mut self, enabled: bool) -> Self { self.inner = self.inner.with_drag_and_drop(enabled); self } #[cfg(target_os = "macos")] fn title_bar_style(mut self, style: TitleBarStyle) -> Self { match style { TitleBarStyle::Visible => { self.inner = self.inner.with_titlebar_transparent(false); // Fixes rendering issue when resizing window with devtools open (https://github.com/tauri-apps/tauri/issues/3914) self.inner = self.inner.with_fullsize_content_view(true); } TitleBarStyle::Transparent => { self.inner = self.inner.with_titlebar_transparent(true); self.inner = self.inner.with_fullsize_content_view(false); } TitleBarStyle::Overlay => { self.inner = self.inner.with_titlebar_transparent(true); self.inner = self.inner.with_fullsize_content_view(true); } unknown => { #[cfg(feature = "tracing")] tracing::warn!("unknown title bar style applied: {unknown}"); #[cfg(not(feature = "tracing"))] eprintln!("unknown title bar style applied: {unknown}"); } } self } #[cfg(target_os = "macos")] fn traffic_light_position>(mut self, position: P) -> Self { self.inner = self.inner.with_traffic_light_inset(position.into()); self } #[cfg(target_os = "macos")] fn hidden_title(mut self, hidden: bool) -> Self { self.inner = self.inner.with_title_hidden(hidden); self } #[cfg(target_os = "macos")] fn tabbing_identifier(mut self, identifier: &str) -> Self { self.inner = self.inner.with_tabbing_identifier(identifier); self.tabbing_identifier.replace(identifier.into()); self } fn icon(mut self, icon: Icon) -> Result { self.inner = self .inner .with_window_icon(Some(TaoIcon::try_from(icon)?.0)); Ok(self) } fn background_color(mut self, color: Color) -> Self { self.inner = self.inner.with_background_color(color.into()); self } #[cfg(any( windows, target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] fn skip_taskbar(mut self, skip: bool) -> Self { self.inner = self.inner.with_skip_taskbar(skip); self } #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android"))] fn skip_taskbar(self, _skip: bool) -> Self { self } fn theme(mut self, theme: Option) -> Self { self.inner = self.inner.with_theme(if let Some(t) = theme { match t { Theme::Dark => Some(TaoTheme::Dark), _ => Some(TaoTheme::Light), } } else { None }); self } fn has_icon(&self) -> bool { self.inner.window.window_icon.is_some() } fn get_theme(&self) -> Option { self.inner.window.preferred_theme.map(|theme| match theme { TaoTheme::Dark => Theme::Dark, _ => Theme::Light, }) } #[cfg(windows)] fn window_classname>(mut self, window_classname: S) -> Self { self.inner = self.inner.with_window_classname(window_classname); self } #[cfg(not(windows))] fn window_classname>(self, _window_classname: S) -> Self { self } } #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] pub struct GtkWindow(pub gtk::ApplicationWindow); #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] #[allow(clippy::non_send_fields_in_send_ty)] unsafe impl Send for GtkWindow {} #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] pub struct GtkBox(pub gtk::Box); #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] #[allow(clippy::non_send_fields_in_send_ty)] unsafe impl Send for GtkBox {} pub struct SendRawWindowHandle(pub raw_window_handle::RawWindowHandle); unsafe impl Send for SendRawWindowHandle {} pub enum ApplicationMessage { #[cfg(target_os = "macos")] Show, #[cfg(target_os = "macos")] Hide, #[cfg(any(target_os = "macos", target_os = "ios"))] FetchDataStoreIdentifiers(Box) + Send + 'static>), #[cfg(any(target_os = "macos", target_os = "ios"))] RemoveDataStore([u8; 16], Box) + Send + 'static>), } pub enum WindowMessage { AddEventListener(WindowEventId, Box), // Getters ScaleFactor(Sender), InnerPosition(Sender>>), OuterPosition(Sender>>), InnerSize(Sender>), OuterSize(Sender>), IsFullscreen(Sender), IsMinimized(Sender), IsMaximized(Sender), IsFocused(Sender), IsDecorated(Sender), IsResizable(Sender), IsMaximizable(Sender), IsMinimizable(Sender), IsClosable(Sender), IsVisible(Sender), Title(Sender), CurrentMonitor(Sender>), PrimaryMonitor(Sender>), MonitorFromPoint(Sender>, (f64, f64)), AvailableMonitors(Sender>), #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] GtkWindow(Sender), #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] GtkBox(Sender), RawWindowHandle(Sender>), Theme(Sender), IsEnabled(Sender), IsAlwaysOnTop(Sender), // Setters Center, RequestUserAttention(Option), SetEnabled(bool), SetResizable(bool), SetMaximizable(bool), SetMinimizable(bool), SetClosable(bool), SetTitle(String), Maximize, Unmaximize, Minimize, Unminimize, Show, Hide, Close, Destroy, SetDecorations(bool), SetShadow(bool), SetAlwaysOnBottom(bool), SetAlwaysOnTop(bool), SetVisibleOnAllWorkspaces(bool), SetContentProtected(bool), SetSize(Size), SetMinSize(Option), SetMaxSize(Option), SetSizeConstraints(WindowSizeConstraints), SetPosition(Position), SetFullscreen(bool), #[cfg(target_os = "macos")] SetSimpleFullscreen(bool), SetFocus, SetFocusable(bool), SetIcon(TaoWindowIcon), SetSkipTaskbar(bool), SetCursorGrab(bool), SetCursorVisible(bool), SetCursorIcon(CursorIcon), SetCursorPosition(Position), SetIgnoreCursorEvents(bool), SetBadgeCount(Option, Option), SetBadgeLabel(Option), SetOverlayIcon(Option), SetProgressBar(ProgressBarState), SetTitleBarStyle(tauri_utils::TitleBarStyle), SetTrafficLightPosition(Position), SetTheme(Option), SetBackgroundColor(Option), DragWindow, ResizeDragWindow(tauri_runtime::ResizeDirection), RequestRedraw, } #[derive(Debug, Clone)] pub enum SynthesizedWindowEvent { Focused(bool), DragDrop(DragDropEvent), } impl From for WindowEventWrapper { fn from(event: SynthesizedWindowEvent) -> Self { let event = match event { SynthesizedWindowEvent::Focused(focused) => WindowEvent::Focused(focused), SynthesizedWindowEvent::DragDrop(event) => WindowEvent::DragDrop(event), }; Self(Some(event)) } } pub enum WebviewMessage { AddEventListener(WebviewEventId, Box), #[cfg(not(all(feature = "tracing", not(target_os = "android"))))] EvaluateScript(String), #[cfg(all(feature = "tracing", not(target_os = "android")))] EvaluateScript(String, Sender<()>, tracing::Span), CookiesForUrl(Url, Sender>>>), Cookies(Sender>>>), SetCookie(tauri_runtime::Cookie<'static>), DeleteCookie(tauri_runtime::Cookie<'static>), WebviewEvent(WebviewEvent), SynthesizedWindowEvent(SynthesizedWindowEvent), Navigate(Url), Reload, Print, Close, Show, Hide, SetPosition(Position), SetSize(Size), SetBounds(tauri_runtime::dpi::Rect), SetFocus, Reparent(WindowId, Sender>), SetAutoResize(bool), SetZoom(f64), SetBackgroundColor(Option), ClearAllBrowsingData, // Getters Url(Sender>), Bounds(Sender>), Position(Sender>>), Size(Sender>>), WithWebview(Box), // Devtools #[cfg(any(debug_assertions, feature = "devtools"))] OpenDevTools, #[cfg(any(debug_assertions, feature = "devtools"))] CloseDevTools, #[cfg(any(debug_assertions, feature = "devtools"))] IsDevToolsOpen(Sender), } pub enum EventLoopWindowTargetMessage { CursorPosition(Sender>>), SetTheme(Option), SetDeviceEventFilter(DeviceEventFilter), } pub type CreateWindowClosure = Box>) -> Result + Send>; pub type CreateWebviewClosure = Box Result + Send>; pub struct CreateWebviewOptions { pub focused_webview: Arc>>, } pub enum Message { Task(Box), #[cfg(target_os = "macos")] SetActivationPolicy(ActivationPolicy), #[cfg(target_os = "macos")] SetDockVisibility(bool), RequestExit(i32), Application(ApplicationMessage), Window(WindowId, WindowMessage), Webview(WindowId, WebviewId, WebviewMessage), EventLoopWindowTarget(EventLoopWindowTargetMessage), CreateWebview(WindowId, CreateWebviewClosure), CreateWindow(WindowId, CreateWindowClosure), CreateRawWindow( WindowId, Box (String, TaoWindowBuilder) + Send>, Sender>>, ), UserEvent(T), } impl Clone for Message { fn clone(&self) -> Self { match self { Self::UserEvent(t) => Self::UserEvent(t.clone()), _ => unimplemented!(), } } } /// The Tauri [`WebviewDispatch`] for [`Wry`]. #[derive(Debug, Clone)] pub struct WryWebviewDispatcher { window_id: Arc>, webview_id: WebviewId, context: Context, } impl WebviewDispatch for WryWebviewDispatcher { type Runtime = Wry; fn run_on_main_thread(&self, f: F) -> Result<()> { send_user_message(&self.context, Message::Task(Box::new(f))) } fn on_webview_event(&self, f: F) -> WindowEventId { let id = self.context.next_webview_event_id(); let _ = self.context.proxy.send_event(Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::AddEventListener(id, Box::new(f)), )); id } fn with_webview) + Send + 'static>(&self, f: F) -> Result<()> { send_user_message( &self.context, Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::WithWebview(Box::new(move |webview| f(Box::new(webview)))), ), ) } #[cfg(any(debug_assertions, feature = "devtools"))] fn open_devtools(&self) { let _ = send_user_message( &self.context, Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::OpenDevTools, ), ); } #[cfg(any(debug_assertions, feature = "devtools"))] fn close_devtools(&self) { let _ = send_user_message( &self.context, Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::CloseDevTools, ), ); } /// Gets the devtools window's current open state. #[cfg(any(debug_assertions, feature = "devtools"))] fn is_devtools_open(&self) -> Result { webview_getter!(self, WebviewMessage::IsDevToolsOpen) } // Getters fn url(&self) -> Result { webview_getter!(self, WebviewMessage::Url)? } fn bounds(&self) -> Result { webview_getter!(self, WebviewMessage::Bounds)? } fn position(&self) -> Result> { webview_getter!(self, WebviewMessage::Position)? } fn size(&self) -> Result> { webview_getter!(self, WebviewMessage::Size)? } // Setters fn navigate(&self, url: Url) -> Result<()> { send_user_message( &self.context, Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::Navigate(url), ), ) } fn reload(&self) -> Result<()> { send_user_message( &self.context, Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::Reload, ), ) } fn print(&self) -> Result<()> { send_user_message( &self.context, Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::Print, ), ) } fn close(&self) -> Result<()> { send_user_message( &self.context, Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::Close, ), ) } fn set_bounds(&self, bounds: tauri_runtime::dpi::Rect) -> Result<()> { send_user_message( &self.context, Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::SetBounds(bounds), ), ) } fn set_size(&self, size: Size) -> Result<()> { send_user_message( &self.context, Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::SetSize(size), ), ) } fn set_position(&self, position: Position) -> Result<()> { send_user_message( &self.context, Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::SetPosition(position), ), ) } fn set_focus(&self) -> Result<()> { send_user_message( &self.context, Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::SetFocus, ), ) } fn reparent(&self, window_id: WindowId) -> Result<()> { let mut current_window_id = self.window_id.lock().unwrap(); let (tx, rx) = channel(); send_user_message( &self.context, Message::Webview( *current_window_id, self.webview_id, WebviewMessage::Reparent(window_id, tx), ), )?; rx.recv().unwrap()?; *current_window_id = window_id; Ok(()) } fn cookies_for_url(&self, url: Url) -> Result>> { let current_window_id = self.window_id.lock().unwrap(); let (tx, rx) = channel(); send_user_message( &self.context, Message::Webview( *current_window_id, self.webview_id, WebviewMessage::CookiesForUrl(url, tx), ), )?; rx.recv().unwrap() } fn cookies(&self) -> Result>> { webview_getter!(self, WebviewMessage::Cookies)? } fn set_cookie(&self, cookie: Cookie<'_>) -> Result<()> { send_user_message( &self.context, Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::SetCookie(cookie.into_owned()), ), )?; Ok(()) } fn delete_cookie(&self, cookie: Cookie<'_>) -> Result<()> { send_user_message( &self.context, Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::DeleteCookie(cookie.into_owned()), ), )?; Ok(()) } fn set_auto_resize(&self, auto_resize: bool) -> Result<()> { send_user_message( &self.context, Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::SetAutoResize(auto_resize), ), ) } #[cfg(all(feature = "tracing", not(target_os = "android")))] fn eval_script>(&self, script: S) -> Result<()> { // use a channel so the EvaluateScript task uses the current span as parent let (tx, rx) = channel(); getter!( self, rx, Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::EvaluateScript(script.into(), tx, tracing::Span::current()), ) ) } #[cfg(not(all(feature = "tracing", not(target_os = "android"))))] fn eval_script>(&self, script: S) -> Result<()> { send_user_message( &self.context, Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::EvaluateScript(script.into()), ), ) } fn set_zoom(&self, scale_factor: f64) -> Result<()> { send_user_message( &self.context, Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::SetZoom(scale_factor), ), ) } fn clear_all_browsing_data(&self) -> Result<()> { send_user_message( &self.context, Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::ClearAllBrowsingData, ), ) } fn hide(&self) -> Result<()> { send_user_message( &self.context, Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::Hide, ), ) } fn show(&self) -> Result<()> { send_user_message( &self.context, Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::Show, ), ) } fn set_background_color(&self, color: Option) -> Result<()> { send_user_message( &self.context, Message::Webview( *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::SetBackgroundColor(color), ), ) } } /// The Tauri [`WindowDispatch`] for [`Wry`]. #[derive(Debug, Clone)] pub struct WryWindowDispatcher { window_id: WindowId, context: Context, } // SAFETY: this is safe since the `Context` usage is guarded on `send_user_message`. #[allow(clippy::non_send_fields_in_send_ty)] unsafe impl Sync for WryWindowDispatcher {} fn get_raw_window_handle( dispatcher: &WryWindowDispatcher, ) -> Result> { window_getter!(dispatcher, WindowMessage::RawWindowHandle) } impl WindowDispatch for WryWindowDispatcher { type Runtime = Wry; type WindowBuilder = WindowBuilderWrapper; fn run_on_main_thread(&self, f: F) -> Result<()> { send_user_message(&self.context, Message::Task(Box::new(f))) } fn on_window_event(&self, f: F) -> WindowEventId { let id = self.context.next_window_event_id(); let _ = self.context.proxy.send_event(Message::Window( self.window_id, WindowMessage::AddEventListener(id, Box::new(f)), )); id } // Getters fn scale_factor(&self) -> Result { window_getter!(self, WindowMessage::ScaleFactor) } fn inner_position(&self) -> Result> { window_getter!(self, WindowMessage::InnerPosition)? } fn outer_position(&self) -> Result> { window_getter!(self, WindowMessage::OuterPosition)? } fn inner_size(&self) -> Result> { window_getter!(self, WindowMessage::InnerSize) } fn outer_size(&self) -> Result> { window_getter!(self, WindowMessage::OuterSize) } fn is_fullscreen(&self) -> Result { window_getter!(self, WindowMessage::IsFullscreen) } fn is_minimized(&self) -> Result { window_getter!(self, WindowMessage::IsMinimized) } fn is_maximized(&self) -> Result { window_getter!(self, WindowMessage::IsMaximized) } fn is_focused(&self) -> Result { window_getter!(self, WindowMessage::IsFocused) } /// Gets the window's current decoration state. fn is_decorated(&self) -> Result { window_getter!(self, WindowMessage::IsDecorated) } /// Gets the window's current resizable state. fn is_resizable(&self) -> Result { window_getter!(self, WindowMessage::IsResizable) } /// Gets the current native window's maximize button state fn is_maximizable(&self) -> Result { window_getter!(self, WindowMessage::IsMaximizable) } /// Gets the current native window's minimize button state fn is_minimizable(&self) -> Result { window_getter!(self, WindowMessage::IsMinimizable) } /// Gets the current native window's close button state fn is_closable(&self) -> Result { window_getter!(self, WindowMessage::IsClosable) } fn is_visible(&self) -> Result { window_getter!(self, WindowMessage::IsVisible) } fn title(&self) -> Result { window_getter!(self, WindowMessage::Title) } fn current_monitor(&self) -> Result> { Ok(window_getter!(self, WindowMessage::CurrentMonitor)?.map(|m| MonitorHandleWrapper(m).into())) } fn primary_monitor(&self) -> Result> { Ok(window_getter!(self, WindowMessage::PrimaryMonitor)?.map(|m| MonitorHandleWrapper(m).into())) } fn monitor_from_point(&self, x: f64, y: f64) -> Result> { let (tx, rx) = channel(); let _ = send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::MonitorFromPoint(tx, (x, y))), ); Ok( rx.recv() .map_err(|_| crate::Error::FailedToReceiveMessage)? .map(|m| MonitorHandleWrapper(m).into()), ) } fn available_monitors(&self) -> Result> { Ok( window_getter!(self, WindowMessage::AvailableMonitors)? .into_iter() .map(|m| MonitorHandleWrapper(m).into()) .collect(), ) } fn theme(&self) -> Result { window_getter!(self, WindowMessage::Theme) } fn is_enabled(&self) -> Result { window_getter!(self, WindowMessage::IsEnabled) } fn is_always_on_top(&self) -> Result { window_getter!(self, WindowMessage::IsAlwaysOnTop) } #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] fn gtk_window(&self) -> Result { window_getter!(self, WindowMessage::GtkWindow).map(|w| w.0) } #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] fn default_vbox(&self) -> Result { window_getter!(self, WindowMessage::GtkBox).map(|w| w.0) } fn window_handle( &self, ) -> std::result::Result, raw_window_handle::HandleError> { get_raw_window_handle(self) .map_err(|_| raw_window_handle::HandleError::Unavailable) .and_then(|r| r.map(|h| unsafe { raw_window_handle::WindowHandle::borrow_raw(h.0) })) } // Setters fn center(&self) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::Center), ) } fn request_user_attention(&self, request_type: Option) -> Result<()> { send_user_message( &self.context, Message::Window( self.window_id, WindowMessage::RequestUserAttention(request_type.map(Into::into)), ), ) } // Creates a window by dispatching a message to the event loop. // Note that this must be called from a separate thread, otherwise the channel will introduce a deadlock. fn create_window( &mut self, pending: PendingWindow, after_window_creation: Option, ) -> Result> { self.context.create_window(pending, after_window_creation) } // Creates a webview by dispatching a message to the event loop. // Note that this must be called from a separate thread, otherwise the channel will introduce a deadlock. fn create_webview( &mut self, pending: PendingWebview, ) -> Result> { self.context.create_webview(self.window_id, pending) } fn set_resizable(&self, resizable: bool) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetResizable(resizable)), ) } fn set_enabled(&self, enabled: bool) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetEnabled(enabled)), ) } fn set_maximizable(&self, maximizable: bool) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetMaximizable(maximizable)), ) } fn set_minimizable(&self, minimizable: bool) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetMinimizable(minimizable)), ) } fn set_closable(&self, closable: bool) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetClosable(closable)), ) } fn set_title>(&self, title: S) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetTitle(title.into())), ) } fn maximize(&self) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::Maximize), ) } fn unmaximize(&self) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::Unmaximize), ) } fn minimize(&self) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::Minimize), ) } fn unminimize(&self) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::Unminimize), ) } fn show(&self) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::Show), ) } fn hide(&self) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::Hide), ) } fn close(&self) -> Result<()> { // NOTE: close cannot use the `send_user_message` function because it accesses the event loop callback self .context .proxy .send_event(Message::Window(self.window_id, WindowMessage::Close)) .map_err(|_| Error::FailedToSendMessage) } fn destroy(&self) -> Result<()> { // NOTE: destroy cannot use the `send_user_message` function because it accesses the event loop callback self .context .proxy .send_event(Message::Window(self.window_id, WindowMessage::Destroy)) .map_err(|_| Error::FailedToSendMessage) } fn set_decorations(&self, decorations: bool) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetDecorations(decorations)), ) } fn set_shadow(&self, enable: bool) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetShadow(enable)), ) } fn set_always_on_bottom(&self, always_on_bottom: bool) -> Result<()> { send_user_message( &self.context, Message::Window( self.window_id, WindowMessage::SetAlwaysOnBottom(always_on_bottom), ), ) } fn set_always_on_top(&self, always_on_top: bool) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetAlwaysOnTop(always_on_top)), ) } fn set_visible_on_all_workspaces(&self, visible_on_all_workspaces: bool) -> Result<()> { send_user_message( &self.context, Message::Window( self.window_id, WindowMessage::SetVisibleOnAllWorkspaces(visible_on_all_workspaces), ), ) } fn set_content_protected(&self, protected: bool) -> Result<()> { send_user_message( &self.context, Message::Window( self.window_id, WindowMessage::SetContentProtected(protected), ), ) } fn set_size(&self, size: Size) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetSize(size)), ) } fn set_min_size(&self, size: Option) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetMinSize(size)), ) } fn set_max_size(&self, size: Option) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetMaxSize(size)), ) } fn set_size_constraints(&self, constraints: WindowSizeConstraints) -> Result<()> { send_user_message( &self.context, Message::Window( self.window_id, WindowMessage::SetSizeConstraints(constraints), ), ) } fn set_position(&self, position: Position) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetPosition(position)), ) } fn set_fullscreen(&self, fullscreen: bool) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetFullscreen(fullscreen)), ) } #[cfg(target_os = "macos")] fn set_simple_fullscreen(&self, enable: bool) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetSimpleFullscreen(enable)), ) } fn set_focus(&self) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetFocus), ) } fn set_focusable(&self, focusable: bool) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetFocusable(focusable)), ) } fn set_icon(&self, icon: Icon) -> Result<()> { send_user_message( &self.context, Message::Window( self.window_id, WindowMessage::SetIcon(TaoIcon::try_from(icon)?.0), ), ) } fn set_skip_taskbar(&self, skip: bool) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetSkipTaskbar(skip)), ) } fn set_cursor_grab(&self, grab: bool) -> crate::Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetCursorGrab(grab)), ) } fn set_cursor_visible(&self, visible: bool) -> crate::Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetCursorVisible(visible)), ) } fn set_cursor_icon(&self, icon: CursorIcon) -> crate::Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetCursorIcon(icon)), ) } fn set_cursor_position>(&self, position: Pos) -> crate::Result<()> { send_user_message( &self.context, Message::Window( self.window_id, WindowMessage::SetCursorPosition(position.into()), ), ) } fn set_ignore_cursor_events(&self, ignore: bool) -> crate::Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetIgnoreCursorEvents(ignore)), ) } fn start_dragging(&self) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::DragWindow), ) } fn start_resize_dragging(&self, direction: tauri_runtime::ResizeDirection) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::ResizeDragWindow(direction)), ) } fn set_badge_count(&self, count: Option, desktop_filename: Option) -> Result<()> { send_user_message( &self.context, Message::Window( self.window_id, WindowMessage::SetBadgeCount(count, desktop_filename), ), ) } fn set_badge_label(&self, label: Option) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetBadgeLabel(label)), ) } fn set_overlay_icon(&self, icon: Option) -> Result<()> { let icon: Result> = icon.map_or(Ok(None), |x| Ok(Some(TaoIcon::try_from(x)?))); send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetOverlayIcon(icon?)), ) } fn set_progress_bar(&self, progress_state: ProgressBarState) -> Result<()> { send_user_message( &self.context, Message::Window( self.window_id, WindowMessage::SetProgressBar(progress_state), ), ) } fn set_title_bar_style(&self, style: tauri_utils::TitleBarStyle) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetTitleBarStyle(style)), ) } fn set_traffic_light_position(&self, position: Position) -> Result<()> { send_user_message( &self.context, Message::Window( self.window_id, WindowMessage::SetTrafficLightPosition(position), ), ) } fn set_theme(&self, theme: Option) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetTheme(theme)), ) } fn set_background_color(&self, color: Option) -> Result<()> { send_user_message( &self.context, Message::Window(self.window_id, WindowMessage::SetBackgroundColor(color)), ) } } #[derive(Clone)] pub struct WebviewWrapper { label: String, id: WebviewId, inner: Rc, context_store: WebContextStore, webview_event_listeners: WebviewEventListeners, // the key of the WebContext if it's not shared context_key: Option, bounds: Arc>>, } impl Deref for WebviewWrapper { type Target = WebView; #[inline(always)] fn deref(&self) -> &Self::Target { &self.inner } } impl Drop for WebviewWrapper { fn drop(&mut self) { if Rc::get_mut(&mut self.inner).is_some() { let mut context_store = self.context_store.lock().unwrap(); if let Some(web_context) = context_store.get_mut(&self.context_key) { web_context.referenced_by_webviews.remove(&self.label); // https://github.com/tauri-apps/tauri/issues/14626 // Because WebKit does not close its network process even when no webviews are running, // we need to ensure to re-use the existing process on Linux by keeping the WebContext // alive for the lifetime of the app. // WebKit on macOS handles this itself. #[cfg(not(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" )))] if web_context.referenced_by_webviews.is_empty() { context_store.remove(&self.context_key); } } } } } pub struct WindowWrapper { label: String, inner: Option>, // whether this window has child webviews // or it's just a container for a single webview has_children: AtomicBool, webviews: Vec, window_event_listeners: WindowEventListeners, #[cfg(windows)] background_color: Option, #[cfg(windows)] is_window_transparent: bool, #[cfg(windows)] surface: Option, Arc>>, focused_webview: Arc>>, } impl WindowWrapper { pub fn label(&self) -> &str { &self.label } } impl fmt::Debug for WindowWrapper { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("WindowWrapper") .field("label", &self.label) .field("inner", &self.inner) .finish() } } #[derive(Debug, Clone)] pub struct EventProxy(TaoEventLoopProxy>); #[cfg(target_os = "ios")] #[allow(clippy::non_send_fields_in_send_ty)] unsafe impl Sync for EventProxy {} impl EventLoopProxy for EventProxy { fn send_event(&self, event: T) -> Result<()> { self .0 .send_event(Message::UserEvent(event)) .map_err(|_| Error::EventLoopClosed) } } pub trait PluginBuilder { type Plugin: Plugin; fn build(self, context: Context) -> Self::Plugin; } pub trait Plugin { fn on_event( &mut self, event: &Event>, event_loop: &EventLoopWindowTarget>, proxy: &TaoEventLoopProxy>, control_flow: &mut ControlFlow, context: EventLoopIterationContext<'_, T>, web_context: &WebContextStore, ) -> bool; } /// A Tauri [`Runtime`] wrapper around wry. pub struct Wry { context: Context, event_loop: EventLoop>, } impl fmt::Debug for Wry { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Wry") .field("main_thread_id", &self.context.main_thread_id) .field("event_loop", &self.event_loop) .field("windows", &self.context.main_thread.windows) .field("web_context", &self.context.main_thread.web_context) .finish() } } /// A handle to the Wry runtime. #[derive(Debug, Clone)] pub struct WryHandle { context: Context, } // SAFETY: this is safe since the `Context` usage is guarded on `send_user_message`. #[allow(clippy::non_send_fields_in_send_ty)] 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, TaoWindowBuilder) + Send + 'static>( &self, f: F, ) -> Result> { let id = self.context.next_window_id(); let (tx, rx) = channel(); send_user_message(&self.context, Message::CreateRawWindow(id, Box::new(f), tx))?; rx.recv().unwrap() } /// Gets the [`WebviewId'] associated with the given [`WindowId`]. pub fn window_id(&self, window_id: TaoWindowId) -> WindowId { *self .context .window_id_map .0 .lock() .unwrap() .get(&window_id) .unwrap() } /// Send a message to the event loop. pub fn send_event(&self, message: Message) -> Result<()> { self .context .proxy .send_event(message) .map_err(|_| Error::FailedToSendMessage)?; Ok(()) } pub fn plugin + 'static>(&mut self, plugin: P) where

>::Plugin: Send, { self .context .plugins .lock() .unwrap() .push(Box::new(plugin.build(self.context.clone()))); } } impl RuntimeHandle for WryHandle { type Runtime = Wry; fn create_proxy(&self) -> EventProxy { EventProxy(self.context.proxy.clone()) } #[cfg(target_os = "macos")] fn set_activation_policy(&self, activation_policy: ActivationPolicy) -> Result<()> { send_user_message( &self.context, Message::SetActivationPolicy(activation_policy), ) } #[cfg(target_os = "macos")] fn set_dock_visibility(&self, visible: bool) -> Result<()> { send_user_message(&self.context, Message::SetDockVisibility(visible)) } fn request_exit(&self, code: i32) -> Result<()> { // NOTE: request_exit cannot use the `send_user_message` function because it accesses the event loop callback self .context .proxy .send_event(Message::RequestExit(code)) .map_err(|_| Error::FailedToSendMessage) } // Creates a window by dispatching a message to the event loop. // Note that this must be called from a separate thread, otherwise the channel will introduce a deadlock. fn create_window( &self, pending: PendingWindow, after_window_creation: Option, ) -> Result> { self.context.create_window(pending, after_window_creation) } // Creates a webview by dispatching a message to the event loop. // Note that this must be called from a separate thread, otherwise the channel will introduce a deadlock. fn create_webview( &self, window_id: WindowId, pending: PendingWebview, ) -> Result> { self.context.create_webview(window_id, pending) } fn run_on_main_thread(&self, f: F) -> Result<()> { send_user_message(&self.context, Message::Task(Box::new(f))) } fn display_handle( &self, ) -> std::result::Result, raw_window_handle::HandleError> { self.context.main_thread.window_target.display_handle() } fn primary_monitor(&self) -> Option { self .context .main_thread .window_target .primary_monitor() .map(|m| MonitorHandleWrapper(m).into()) } fn monitor_from_point(&self, x: f64, y: f64) -> Option { self .context .main_thread .window_target .monitor_from_point(x, y) .map(|m| MonitorHandleWrapper(m).into()) } fn available_monitors(&self) -> Vec { self .context .main_thread .window_target .available_monitors() .map(|m| MonitorHandleWrapper(m).into()) .collect() } fn cursor_position(&self) -> Result> { event_loop_window_getter!(self, EventLoopWindowTargetMessage::CursorPosition)? .map(PhysicalPositionWrapper) .map(Into::into) .map_err(|_| Error::FailedToGetCursorPosition) } fn set_theme(&self, theme: Option) { let _ = send_user_message( &self.context, Message::EventLoopWindowTarget(EventLoopWindowTargetMessage::SetTheme(theme)), ); } #[cfg(target_os = "macos")] fn show(&self) -> tauri_runtime::Result<()> { send_user_message( &self.context, Message::Application(ApplicationMessage::Show), ) } #[cfg(target_os = "macos")] fn hide(&self) -> tauri_runtime::Result<()> { send_user_message( &self.context, Message::Application(ApplicationMessage::Hide), ) } fn set_device_event_filter(&self, filter: DeviceEventFilter) { let _ = send_user_message( &self.context, Message::EventLoopWindowTarget(EventLoopWindowTargetMessage::SetDeviceEventFilter(filter)), ); } #[cfg(target_os = "android")] fn find_class<'a>( &self, env: &mut jni::JNIEnv<'a>, activity: &jni::objects::JObject<'_>, name: impl Into, ) -> std::result::Result, jni::errors::Error> { find_class(env, activity, name.into()) } #[cfg(target_os = "android")] fn run_on_android_context(&self, f: F) where F: FnOnce(&mut jni::JNIEnv, &jni::objects::JObject, &jni::objects::JObject) + Send + 'static, { dispatch(f) } #[cfg(any(target_os = "macos", target_os = "ios"))] fn fetch_data_store_identifiers) + Send + 'static>( &self, cb: F, ) -> Result<()> { send_user_message( &self.context, Message::Application(ApplicationMessage::FetchDataStoreIdentifiers(Box::new(cb))), ) } #[cfg(any(target_os = "macos", target_os = "ios"))] fn remove_data_store) + Send + 'static>( &self, uuid: [u8; 16], cb: F, ) -> Result<()> { send_user_message( &self.context, Message::Application(ApplicationMessage::RemoveDataStore(uuid, Box::new(cb))), ) } } impl Wry { fn init_with_builder( mut event_loop_builder: EventLoopBuilder>, #[allow(unused_variables)] args: RuntimeInitArgs, ) -> Result { #[cfg(windows)] if let Some(hook) = args.msg_hook { use tao::platform::windows::EventLoopBuilderExtWindows; event_loop_builder.with_msg_hook(hook); } #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] if let Some(app_id) = args.app_id { use tao::platform::unix::EventLoopBuilderExtUnix; event_loop_builder.with_app_id(app_id); } Self::init(event_loop_builder.build()) } fn init(event_loop: EventLoop>) -> Result { let main_thread_id = current_thread().id(); let web_context = WebContextStore::default(); let windows = Arc::new(WindowsStore(RefCell::new(BTreeMap::default()))); let window_id_map = WindowIdStore::default(); let context = Context { window_id_map, main_thread_id, proxy: event_loop.create_proxy(), main_thread: DispatcherMainThreadContext { window_target: event_loop.deref().clone(), web_context, windows, #[cfg(feature = "tracing")] active_tracing_spans: Default::default(), }, plugins: Default::default(), next_window_id: Default::default(), next_webview_id: Default::default(), next_window_event_id: Default::default(), next_webview_event_id: Default::default(), webview_runtime_installed: wry::webview_version().is_ok(), }; Ok(Self { context, event_loop, }) } } impl Runtime for Wry { type WindowDispatcher = WryWindowDispatcher; type WebviewDispatcher = WryWebviewDispatcher; type Handle = WryHandle; type EventLoopProxy = EventProxy; fn new(args: RuntimeInitArgs) -> Result { Self::init_with_builder(EventLoopBuilder::>::with_user_event(), args) } #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] fn new_any_thread(args: RuntimeInitArgs) -> Result { 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) } #[cfg(windows)] fn new_any_thread(args: RuntimeInitArgs) -> Result { 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) } fn create_proxy(&self) -> EventProxy { EventProxy(self.event_loop.create_proxy()) } fn handle(&self) -> Self::Handle { WryHandle { context: self.context.clone(), } } fn create_window( &self, pending: PendingWindow, after_window_creation: Option, ) -> Result> { let label = pending.label.clone(); let window_id = self.context.next_window_id(); let (webview_id, use_https_scheme) = pending .webview .as_ref() .map(|w| { ( Some(self.context.next_webview_id()), w.webview_attributes.use_https_scheme, ) }) .unwrap_or((None, false)); let window = create_window( window_id, webview_id.unwrap_or_default(), &self.event_loop, &self.context, pending, after_window_creation, )?; let dispatcher = WryWindowDispatcher { window_id, context: self.context.clone(), }; self .context .main_thread .windows .0 .borrow_mut() .insert(window_id, window); let detached_webview = webview_id.map(|id| { let webview = DetachedWebview { label: label.clone(), dispatcher: WryWebviewDispatcher { window_id: Arc::new(Mutex::new(window_id)), webview_id: id, context: self.context.clone(), }, }; DetachedWindowWebview { webview, use_https_scheme, } }); Ok(DetachedWindow { id: window_id, label, dispatcher, webview: detached_webview, }) } fn create_webview( &self, window_id: WindowId, pending: PendingWebview, ) -> Result> { let label = pending.label.clone(); let window = self .context .main_thread .windows .0 .borrow() .get(&window_id) .map(|w| (w.inner.clone(), w.focused_webview.clone())); if let Some((Some(window), focused_webview)) = window { let window_id_wrapper = Arc::new(Mutex::new(window_id)); let webview_id = self.context.next_webview_id(); let webview = create_webview( WebviewKind::WindowChild, &window, window_id_wrapper.clone(), webview_id, &self.context, pending, focused_webview, )?; #[allow(unknown_lints, clippy::manual_inspect)] self .context .main_thread .windows .0 .borrow_mut() .get_mut(&window_id) .map(|w| { w.webviews.push(webview); w.has_children.store(true, Ordering::Relaxed); w }); let dispatcher = WryWebviewDispatcher { window_id: window_id_wrapper, webview_id, context: self.context.clone(), }; Ok(DetachedWebview { label, dispatcher }) } else { Err(Error::WindowNotFound) } } fn primary_monitor(&self) -> Option { self .context .main_thread .window_target .primary_monitor() .map(|m| MonitorHandleWrapper(m).into()) } fn monitor_from_point(&self, x: f64, y: f64) -> Option { self .context .main_thread .window_target .monitor_from_point(x, y) .map(|m| MonitorHandleWrapper(m).into()) } fn available_monitors(&self) -> Vec { self .context .main_thread .window_target .available_monitors() .map(|m| MonitorHandleWrapper(m).into()) .collect() } fn cursor_position(&self) -> Result> { self .context .main_thread .window_target .cursor_position() .map(PhysicalPositionWrapper) .map(Into::into) .map_err(|_| Error::FailedToGetCursorPosition) } fn set_theme(&self, theme: Option) { self.event_loop.set_theme(to_tao_theme(theme)); } #[cfg(target_os = "macos")] fn set_activation_policy(&mut self, activation_policy: ActivationPolicy) { self .event_loop .set_activation_policy(tao_activation_policy(activation_policy)); } #[cfg(target_os = "macos")] fn set_dock_visibility(&mut self, visible: bool) { self.event_loop.set_dock_visibility(visible); } #[cfg(target_os = "macos")] fn show(&self) { self.event_loop.show_application(); } #[cfg(target_os = "macos")] fn hide(&self) { self.event_loop.hide_application(); } fn set_device_event_filter(&mut self, filter: DeviceEventFilter) { self .event_loop .set_device_event_filter(DeviceEventFilterWrapper::from(filter).0); } #[cfg(desktop)] fn run_iteration) + 'static>(&mut self, mut callback: F) { use tao::platform::run_return::EventLoopExtRunReturn; let windows = self.context.main_thread.windows.clone(); let window_id_map = self.context.window_id_map.clone(); let web_context = &self.context.main_thread.web_context; let plugins = self.context.plugins.clone(); #[cfg(feature = "tracing")] let active_tracing_spans = self.context.main_thread.active_tracing_spans.clone(); let proxy = self.event_loop.create_proxy(); self .event_loop .run_return(|event, event_loop, control_flow| { *control_flow = ControlFlow::Wait; if let Event::MainEventsCleared = &event { *control_flow = ControlFlow::Exit; } for p in plugins.lock().unwrap().iter_mut() { let prevent_default = p.on_event( &event, event_loop, &proxy, control_flow, EventLoopIterationContext { callback: &mut callback, window_id_map: window_id_map.clone(), windows: windows.clone(), #[cfg(feature = "tracing")] active_tracing_spans: active_tracing_spans.clone(), }, web_context, ); if prevent_default { return; } } handle_event_loop( event, event_loop, control_flow, EventLoopIterationContext { callback: &mut callback, windows: windows.clone(), window_id_map: window_id_map.clone(), #[cfg(feature = "tracing")] active_tracing_spans: active_tracing_spans.clone(), }, ); }); } fn run) + 'static>(self, callback: F) { let event_handler = make_event_handler(&self, callback); self.event_loop.run(event_handler) } #[cfg(not(target_os = "ios"))] fn run_return) + 'static>(mut self, callback: F) -> i32 { use tao::platform::run_return::EventLoopExtRunReturn; let event_handler = make_event_handler(&self, callback); self.event_loop.run_return(event_handler) } #[cfg(target_os = "ios")] fn run_return) + 'static>(self, callback: F) -> i32 { self.run(callback); 0 } } fn make_event_handler( runtime: &Wry, mut callback: F, ) -> impl FnMut(Event<'_, Message>, &EventLoopWindowTarget>, &mut ControlFlow) where T: UserEvent, F: FnMut(RunEvent) + 'static, { let windows = runtime.context.main_thread.windows.clone(); let window_id_map = runtime.context.window_id_map.clone(); let web_context = runtime.context.main_thread.web_context.clone(); let plugins = runtime.context.plugins.clone(); #[cfg(feature = "tracing")] let active_tracing_spans = runtime.context.main_thread.active_tracing_spans.clone(); let proxy = runtime.event_loop.create_proxy(); move |event, event_loop, control_flow| { for p in plugins.lock().unwrap().iter_mut() { let prevent_default = p.on_event( &event, event_loop, &proxy, control_flow, EventLoopIterationContext { callback: &mut callback, window_id_map: window_id_map.clone(), windows: windows.clone(), #[cfg(feature = "tracing")] active_tracing_spans: active_tracing_spans.clone(), }, &web_context, ); if prevent_default { return; } } handle_event_loop( event, event_loop, control_flow, EventLoopIterationContext { callback: &mut callback, window_id_map: window_id_map.clone(), windows: windows.clone(), #[cfg(feature = "tracing")] active_tracing_spans: active_tracing_spans.clone(), }, ); } } pub struct EventLoopIterationContext<'a, T: UserEvent> { pub callback: &'a mut (dyn FnMut(RunEvent) + 'static), pub window_id_map: WindowIdStore, pub windows: Arc, #[cfg(feature = "tracing")] pub active_tracing_spans: ActiveTraceSpanStore, } struct UserMessageContext { windows: Arc, window_id_map: WindowIdStore, } fn handle_user_message( event_loop: &EventLoopWindowTarget>, message: Message, context: UserMessageContext, ) { let UserMessageContext { window_id_map, windows, } = context; match message { Message::Task(task) => task(), #[cfg(target_os = "macos")] Message::SetActivationPolicy(activation_policy) => { event_loop.set_activation_policy_at_runtime(tao_activation_policy(activation_policy)) } #[cfg(target_os = "macos")] Message::SetDockVisibility(visible) => event_loop.set_dock_visibility(visible), Message::RequestExit(_code) => panic!("cannot handle RequestExit on the main thread"), Message::Application(application_message) => match application_message { #[cfg(target_os = "macos")] ApplicationMessage::Show => { event_loop.show_application(); } #[cfg(target_os = "macos")] ApplicationMessage::Hide => { event_loop.hide_application(); } #[cfg(any(target_os = "macos", target_os = "ios"))] ApplicationMessage::FetchDataStoreIdentifiers(cb) => { if let Err(e) = WebView::fetch_data_store_identifiers(cb) { // this shouldn't ever happen because we're running on the main thread // but let's be safe and warn here log::error!("failed to fetch data store identifiers: {e}"); } } #[cfg(any(target_os = "macos", target_os = "ios"))] ApplicationMessage::RemoveDataStore(uuid, cb) => { WebView::remove_data_store(&uuid, move |res| { cb(res.map_err(|_| Error::FailedToRemoveDataStore)) }) } }, Message::Window(id, window_message) => { let w = windows.0.borrow().get(&id).map(|w| { ( w.inner.clone(), w.webviews.clone(), w.has_children.load(Ordering::Relaxed), w.window_event_listeners.clone(), ) }); if let Some((Some(window), webviews, has_children, window_event_listeners)) = w { match window_message { WindowMessage::AddEventListener(id, listener) => { window_event_listeners.lock().unwrap().insert(id, listener); } // Getters WindowMessage::ScaleFactor(tx) => tx.send(window.scale_factor()).unwrap(), WindowMessage::InnerPosition(tx) => tx .send( window .inner_position() .map(|p| PhysicalPositionWrapper(p).into()) .map_err(|_| Error::FailedToSendMessage), ) .unwrap(), WindowMessage::OuterPosition(tx) => tx .send( window .outer_position() .map(|p| PhysicalPositionWrapper(p).into()) .map_err(|_| Error::FailedToSendMessage), ) .unwrap(), WindowMessage::InnerSize(tx) => tx .send(PhysicalSizeWrapper(inner_size(&window, &webviews, has_children)).into()) .unwrap(), WindowMessage::OuterSize(tx) => tx .send(PhysicalSizeWrapper(window.outer_size()).into()) .unwrap(), WindowMessage::IsFullscreen(tx) => tx.send(window.fullscreen().is_some()).unwrap(), WindowMessage::IsMinimized(tx) => tx.send(window.is_minimized()).unwrap(), WindowMessage::IsMaximized(tx) => tx.send(window.is_maximized()).unwrap(), WindowMessage::IsFocused(tx) => tx.send(window.is_focused()).unwrap(), WindowMessage::IsDecorated(tx) => tx.send(window.is_decorated()).unwrap(), WindowMessage::IsResizable(tx) => tx.send(window.is_resizable()).unwrap(), WindowMessage::IsMaximizable(tx) => tx.send(window.is_maximizable()).unwrap(), WindowMessage::IsMinimizable(tx) => tx.send(window.is_minimizable()).unwrap(), WindowMessage::IsClosable(tx) => tx.send(window.is_closable()).unwrap(), WindowMessage::IsVisible(tx) => tx.send(window.is_visible()).unwrap(), WindowMessage::Title(tx) => tx.send(window.title()).unwrap(), WindowMessage::CurrentMonitor(tx) => tx.send(window.current_monitor()).unwrap(), WindowMessage::PrimaryMonitor(tx) => tx.send(window.primary_monitor()).unwrap(), WindowMessage::MonitorFromPoint(tx, (x, y)) => { tx.send(window.monitor_from_point(x, y)).unwrap() } WindowMessage::AvailableMonitors(tx) => { tx.send(window.available_monitors().collect()).unwrap() } #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] WindowMessage::GtkWindow(tx) => tx.send(GtkWindow(window.gtk_window().clone())).unwrap(), #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] WindowMessage::GtkBox(tx) => tx .send(GtkBox(window.default_vbox().unwrap().clone())) .unwrap(), WindowMessage::RawWindowHandle(tx) => tx .send( window .window_handle() .map(|h| SendRawWindowHandle(h.as_raw())), ) .unwrap(), WindowMessage::Theme(tx) => { tx.send(map_theme(&window.theme())).unwrap(); } WindowMessage::IsEnabled(tx) => tx.send(window.is_enabled()).unwrap(), WindowMessage::IsAlwaysOnTop(tx) => tx.send(window.is_always_on_top()).unwrap(), // Setters WindowMessage::Center => window.center(), WindowMessage::RequestUserAttention(request_type) => { window.request_user_attention(request_type.map(|r| r.0)); } WindowMessage::SetResizable(resizable) => { window.set_resizable(resizable); #[cfg(windows)] if !resizable { undecorated_resizing::detach_resize_handler(window.hwnd()); } else if !window.is_decorated() { undecorated_resizing::attach_resize_handler( window.hwnd(), window.has_undecorated_shadow(), ); } } WindowMessage::SetMaximizable(maximizable) => window.set_maximizable(maximizable), WindowMessage::SetMinimizable(minimizable) => window.set_minimizable(minimizable), WindowMessage::SetClosable(closable) => window.set_closable(closable), WindowMessage::SetTitle(title) => window.set_title(&title), WindowMessage::Maximize => window.set_maximized(true), WindowMessage::Unmaximize => window.set_maximized(false), WindowMessage::Minimize => window.set_minimized(true), WindowMessage::Unminimize => window.set_minimized(false), WindowMessage::SetEnabled(enabled) => window.set_enabled(enabled), WindowMessage::Show => window.set_visible(true), WindowMessage::Hide => window.set_visible(false), WindowMessage::Close => { panic!("cannot handle `WindowMessage::Close` on the main thread") } WindowMessage::Destroy => { panic!("cannot handle `WindowMessage::Destroy` on the main thread") } WindowMessage::SetDecorations(decorations) => { window.set_decorations(decorations); #[cfg(windows)] if decorations { undecorated_resizing::detach_resize_handler(window.hwnd()); } else if window.is_resizable() { undecorated_resizing::attach_resize_handler( window.hwnd(), window.has_undecorated_shadow(), ); } } WindowMessage::SetShadow(_enable) => { #[cfg(windows)] { window.set_undecorated_shadow(_enable); undecorated_resizing::update_drag_hwnd_rgn_for_undecorated(window.hwnd(), _enable); } #[cfg(target_os = "macos")] window.set_has_shadow(_enable); } WindowMessage::SetAlwaysOnBottom(always_on_bottom) => { window.set_always_on_bottom(always_on_bottom) } WindowMessage::SetAlwaysOnTop(always_on_top) => window.set_always_on_top(always_on_top), WindowMessage::SetVisibleOnAllWorkspaces(visible_on_all_workspaces) => { window.set_visible_on_all_workspaces(visible_on_all_workspaces) } WindowMessage::SetContentProtected(protected) => window.set_content_protection(protected), WindowMessage::SetSize(size) => { window.set_inner_size(SizeWrapper::from(size).0); } WindowMessage::SetMinSize(size) => { window.set_min_inner_size(size.map(|s| SizeWrapper::from(s).0)); } WindowMessage::SetMaxSize(size) => { window.set_max_inner_size(size.map(|s| SizeWrapper::from(s).0)); } WindowMessage::SetSizeConstraints(constraints) => { window.set_inner_size_constraints(tao::window::WindowSizeConstraints { min_width: constraints.min_width, min_height: constraints.min_height, max_width: constraints.max_width, max_height: constraints.max_height, }); } WindowMessage::SetPosition(position) => { window.set_outer_position(PositionWrapper::from(position).0) } WindowMessage::SetFullscreen(fullscreen) => { if fullscreen { window.set_fullscreen(Some(Fullscreen::Borderless(None))) } else { window.set_fullscreen(None) } } #[cfg(target_os = "macos")] WindowMessage::SetSimpleFullscreen(enable) => { window.set_simple_fullscreen(enable); } WindowMessage::SetFocus => { window.set_focus(); } WindowMessage::SetFocusable(focusable) => { window.set_focusable(focusable); } WindowMessage::SetIcon(icon) => { window.set_window_icon(Some(icon)); } #[allow(unused_variables)] WindowMessage::SetSkipTaskbar(skip) => { #[cfg(any( windows, target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] let _ = window.set_skip_taskbar(skip); } WindowMessage::SetCursorGrab(grab) => { let _ = window.set_cursor_grab(grab); } WindowMessage::SetCursorVisible(visible) => { window.set_cursor_visible(visible); } WindowMessage::SetCursorIcon(icon) => { window.set_cursor_icon(CursorIconWrapper::from(icon).0); } WindowMessage::SetCursorPosition(position) => { let _ = window.set_cursor_position(PositionWrapper::from(position).0); } WindowMessage::SetIgnoreCursorEvents(ignore) => { let _ = window.set_ignore_cursor_events(ignore); } WindowMessage::DragWindow => { let _ = window.drag_window(); } WindowMessage::ResizeDragWindow(direction) => { let _ = window.drag_resize_window(match direction { tauri_runtime::ResizeDirection::East => tao::window::ResizeDirection::East, tauri_runtime::ResizeDirection::North => tao::window::ResizeDirection::North, tauri_runtime::ResizeDirection::NorthEast => tao::window::ResizeDirection::NorthEast, tauri_runtime::ResizeDirection::NorthWest => tao::window::ResizeDirection::NorthWest, tauri_runtime::ResizeDirection::South => tao::window::ResizeDirection::South, tauri_runtime::ResizeDirection::SouthEast => tao::window::ResizeDirection::SouthEast, tauri_runtime::ResizeDirection::SouthWest => tao::window::ResizeDirection::SouthWest, tauri_runtime::ResizeDirection::West => tao::window::ResizeDirection::West, }); } WindowMessage::RequestRedraw => { window.request_redraw(); } WindowMessage::SetBadgeCount(_count, _desktop_filename) => { #[cfg(target_os = "ios")] window.set_badge_count( _count.map_or(0, |x| x.clamp(i32::MIN as i64, i32::MAX as i64) as i32), ); #[cfg(target_os = "macos")] window.set_badge_label(_count.map(|x| x.to_string())); #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] window.set_badge_count(_count, _desktop_filename); } WindowMessage::SetBadgeLabel(_label) => { #[cfg(target_os = "macos")] window.set_badge_label(_label); } WindowMessage::SetOverlayIcon(_icon) => { #[cfg(windows)] window.set_overlay_icon(_icon.map(|x| x.0).as_ref()); } WindowMessage::SetProgressBar(progress_state) => { window.set_progress_bar(ProgressBarStateWrapper::from(progress_state).0); } WindowMessage::SetTitleBarStyle(_style) => { #[cfg(target_os = "macos")] match _style { TitleBarStyle::Visible => { window.set_titlebar_transparent(false); window.set_fullsize_content_view(true); } TitleBarStyle::Transparent => { window.set_titlebar_transparent(true); window.set_fullsize_content_view(false); } TitleBarStyle::Overlay => { window.set_titlebar_transparent(true); window.set_fullsize_content_view(true); } unknown => { #[cfg(feature = "tracing")] tracing::warn!("unknown title bar style applied: {unknown}"); #[cfg(not(feature = "tracing"))] eprintln!("unknown title bar style applied: {unknown}"); } }; } WindowMessage::SetTrafficLightPosition(_position) => { #[cfg(target_os = "macos")] window.set_traffic_light_inset(_position); } WindowMessage::SetTheme(theme) => { window.set_theme(to_tao_theme(theme)); } WindowMessage::SetBackgroundColor(color) => { window.set_background_color(color.map(Into::into)) } } } } Message::Webview(window_id, webview_id, webview_message) => { #[cfg(any( target_os = "macos", windows, target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] if let WebviewMessage::Reparent(new_parent_window_id, tx) = webview_message { let webview_handle = windows.0.borrow_mut().get_mut(&window_id).and_then(|w| { w.webviews .iter() .position(|w| w.id == webview_id) .map(|webview_index| w.webviews.remove(webview_index)) }); if let Some(webview) = webview_handle { if let Some((Some(new_parent_window), new_parent_window_webviews)) = windows .0 .borrow_mut() .get_mut(&new_parent_window_id) .map(|w| (w.inner.clone(), &mut w.webviews)) { #[cfg(target_os = "macos")] let reparent_result = { use wry::WebViewExtMacOS; webview.inner.reparent(new_parent_window.ns_window() as _) }; #[cfg(windows)] let reparent_result = { webview.inner.reparent(new_parent_window.hwnd()) }; #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] let reparent_result = { if let Some(container) = new_parent_window.default_vbox() { webview.inner.reparent(container) } else { Err(wry::Error::MessageSender) } }; match reparent_result { Ok(_) => { new_parent_window_webviews.push(webview); tx.send(Ok(())).unwrap(); } Err(e) => { log::error!("failed to reparent webview: {e}"); tx.send(Err(Error::FailedToSendMessage)).unwrap(); } } } } else { tx.send(Err(Error::FailedToSendMessage)).unwrap(); } return; } let webview_handle = windows.0.borrow().get(&window_id).map(|w| { ( w.inner.clone(), w.webviews.iter().find(|w| w.id == webview_id).cloned(), ) }); if let Some((Some(window), Some(webview))) = webview_handle { match webview_message { WebviewMessage::WebviewEvent(_) => { /* already handled */ } WebviewMessage::SynthesizedWindowEvent(_) => { /* already handled */ } WebviewMessage::Reparent(_window_id, _tx) => { /* already handled */ } WebviewMessage::AddEventListener(id, listener) => { webview .webview_event_listeners .lock() .unwrap() .insert(id, listener); } #[cfg(all(feature = "tracing", not(target_os = "android")))] WebviewMessage::EvaluateScript(script, tx, span) => { let _span = span.entered(); if let Err(e) = webview.evaluate_script(&script) { log::error!("{e}"); } tx.send(()).unwrap(); } #[cfg(not(all(feature = "tracing", not(target_os = "android"))))] WebviewMessage::EvaluateScript(script) => { if let Err(e) = webview.evaluate_script(&script) { log::error!("{e}"); } } WebviewMessage::Navigate(url) => { if let Err(e) = webview.load_url(url.as_str()) { log::error!("failed to navigate to url {}: {}", url, e); } } WebviewMessage::Reload => { if let Err(e) = webview.reload() { log::error!("failed to reload: {e}"); } } WebviewMessage::Show => { if let Err(e) = webview.set_visible(true) { log::error!("failed to change webview visibility: {e}"); } } WebviewMessage::Hide => { if let Err(e) = webview.set_visible(false) { log::error!("failed to change webview visibility: {e}"); } } WebviewMessage::Print => { let _ = webview.print(); } WebviewMessage::Close => { #[allow(unknown_lints, clippy::manual_inspect)] windows.0.borrow_mut().get_mut(&window_id).map(|window| { if let Some(i) = window.webviews.iter().position(|w| w.id == webview.id) { window.webviews.remove(i); } window }); } WebviewMessage::SetBounds(bounds) => { let bounds: RectWrapper = bounds.into(); let bounds = bounds.0; if let Some(b) = &mut *webview.bounds.lock().unwrap() { let scale_factor = window.scale_factor(); let size = bounds.size.to_logical::(scale_factor); let position = bounds.position.to_logical::(scale_factor); let window_size = window.inner_size().to_logical::(scale_factor); b.width_rate = size.width / window_size.width; b.height_rate = size.height / window_size.height; b.x_rate = position.x / window_size.width; b.y_rate = position.y / window_size.height; } if let Err(e) = webview.set_bounds(bounds) { log::error!("failed to set webview size: {e}"); } } WebviewMessage::SetSize(size) => match webview.bounds() { Ok(mut bounds) => { bounds.size = size; let scale_factor = window.scale_factor(); let size = size.to_logical::(scale_factor); if let Some(b) = &mut *webview.bounds.lock().unwrap() { let window_size = window.inner_size().to_logical::(scale_factor); b.width_rate = size.width / window_size.width; b.height_rate = size.height / window_size.height; } if let Err(e) = webview.set_bounds(bounds) { log::error!("failed to set webview size: {e}"); } } Err(e) => { log::error!("failed to get webview bounds: {e}"); } }, WebviewMessage::SetPosition(position) => match webview.bounds() { Ok(mut bounds) => { bounds.position = position; let scale_factor = window.scale_factor(); let position = position.to_logical::(scale_factor); if let Some(b) = &mut *webview.bounds.lock().unwrap() { let window_size = window.inner_size().to_logical::(scale_factor); b.x_rate = position.x / window_size.width; b.y_rate = position.y / window_size.height; } if let Err(e) = webview.set_bounds(bounds) { log::error!("failed to set webview position: {e}"); } } Err(e) => { log::error!("failed to get webview bounds: {e}"); } }, WebviewMessage::SetZoom(scale_factor) => { if let Err(e) = webview.zoom(scale_factor) { log::error!("failed to set webview zoom: {e}"); } } WebviewMessage::SetBackgroundColor(color) => { if let Err(e) = webview.set_background_color(color.map(Into::into).unwrap_or((255, 255, 255, 255))) { log::error!("failed to set webview background color: {e}"); } } WebviewMessage::ClearAllBrowsingData => { if let Err(e) = webview.clear_all_browsing_data() { log::error!("failed to clear webview browsing data: {e}"); } } // Getters WebviewMessage::Url(tx) => { tx.send( webview .url() .map(|u| u.parse().expect("invalid webview URL")) .map_err(|_| Error::FailedToSendMessage), ) .unwrap(); } WebviewMessage::Cookies(tx) => { tx.send(webview.cookies().map_err(|_| Error::FailedToSendMessage)) .unwrap(); } WebviewMessage::SetCookie(cookie) => { if let Err(e) = webview.set_cookie(&cookie) { log::error!("failed to set webview cookie: {e}"); } } WebviewMessage::DeleteCookie(cookie) => { if let Err(e) = webview.delete_cookie(&cookie) { log::error!("failed to delete webview cookie: {e}"); } } WebviewMessage::CookiesForUrl(url, tx) => { let webview_cookies = webview .cookies_for_url(url.as_str()) .map_err(|_| Error::FailedToSendMessage); tx.send(webview_cookies).unwrap(); } WebviewMessage::Bounds(tx) => { tx.send( webview .bounds() .map(|bounds| tauri_runtime::dpi::Rect { size: bounds.size, position: bounds.position, }) .map_err(|_| Error::FailedToSendMessage), ) .unwrap(); } WebviewMessage::Position(tx) => { tx.send( webview .bounds() .map(|bounds| bounds.position.to_physical(window.scale_factor())) .map_err(|_| Error::FailedToSendMessage), ) .unwrap(); } WebviewMessage::Size(tx) => { tx.send( webview .bounds() .map(|bounds| bounds.size.to_physical(window.scale_factor())) .map_err(|_| Error::FailedToSendMessage), ) .unwrap(); } WebviewMessage::SetFocus => { if let Err(e) = webview.focus() { log::error!("failed to focus webview: {e}"); } } WebviewMessage::SetAutoResize(auto_resize) => match webview.bounds() { Ok(bounds) => { let scale_factor = window.scale_factor(); let window_size = window.inner_size().to_logical::(scale_factor); *webview.bounds.lock().unwrap() = if auto_resize { let size = bounds.size.to_logical::(scale_factor); let position = bounds.position.to_logical::(scale_factor); Some(WebviewBounds { x_rate: position.x / window_size.width, y_rate: position.y / window_size.height, width_rate: size.width / window_size.width, height_rate: size.height / window_size.height, }) } else { None }; } Err(e) => { log::error!("failed to get webview bounds: {e}"); } }, WebviewMessage::WithWebview(f) => { #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] { f(webview.webview()); } #[cfg(target_os = "macos")] { use wry::WebViewExtMacOS; f(Webview { webview: Retained::into_raw(webview.webview()) as *mut objc2::runtime::AnyObject as *mut std::ffi::c_void, manager: Retained::into_raw(webview.manager()) as *mut objc2::runtime::AnyObject as *mut std::ffi::c_void, ns_window: Retained::into_raw(webview.ns_window()) as *mut objc2::runtime::AnyObject as *mut std::ffi::c_void, }); } #[cfg(target_os = "ios")] { use wry::WebViewExtIOS; f(Webview { webview: Retained::into_raw(webview.inner.webview()) as *mut objc2::runtime::AnyObject as *mut std::ffi::c_void, manager: Retained::into_raw(webview.inner.manager()) as *mut objc2::runtime::AnyObject as *mut std::ffi::c_void, view_controller: window.ui_view_controller(), }); } #[cfg(windows)] { f(Webview { controller: webview.controller(), environment: webview.environment(), }); } #[cfg(target_os = "android")] { f(webview.handle()) } } #[cfg(any(debug_assertions, feature = "devtools"))] WebviewMessage::OpenDevTools => { webview.open_devtools(); } #[cfg(any(debug_assertions, feature = "devtools"))] WebviewMessage::CloseDevTools => { webview.close_devtools(); } #[cfg(any(debug_assertions, feature = "devtools"))] WebviewMessage::IsDevToolsOpen(tx) => { tx.send(webview.is_devtools_open()).unwrap(); } } } } Message::CreateWebview(window_id, handler) => { let window = windows .0 .borrow() .get(&window_id) .map(|w| (w.inner.clone(), w.focused_webview.clone())); if let Some((Some(window), focused_webview)) = window { match handler(&window, CreateWebviewOptions { focused_webview }) { Ok(webview) => { #[allow(unknown_lints, clippy::manual_inspect)] windows.0.borrow_mut().get_mut(&window_id).map(|w| { w.webviews.push(webview); w.has_children.store(true, Ordering::Relaxed); w }); } Err(e) => { log::error!("{e}"); } } } } Message::CreateWindow(window_id, handler) => match handler(event_loop) { // wait for borrow_mut to be available - on Windows we might poll for the window to be inserted Ok(webview) => loop { if let Ok(mut windows) = windows.0.try_borrow_mut() { windows.insert(window_id, webview); break; } }, Err(e) => { log::error!("{e}"); } }, Message::CreateRawWindow(window_id, handler, sender) => { let (label, builder) = handler(); #[cfg(windows)] let background_color = builder.window.background_color; #[cfg(windows)] let is_window_transparent = builder.window.transparent; if let Ok(window) = builder.build(event_loop) { window_id_map.insert(window.id(), window_id); let window = Arc::new(window); #[cfg(windows)] let surface = if is_window_transparent { if let Ok(context) = softbuffer::Context::new(window.clone()) { if let Ok(mut surface) = softbuffer::Surface::new(&context, window.clone()) { window.draw_surface(&mut surface, background_color); Some(surface) } else { None } } else { None } } else { None }; windows.0.borrow_mut().insert( window_id, WindowWrapper { label, has_children: AtomicBool::new(false), inner: Some(window.clone()), window_event_listeners: Default::default(), webviews: Vec::new(), #[cfg(windows)] background_color, #[cfg(windows)] is_window_transparent, #[cfg(windows)] surface, focused_webview: Default::default(), }, ); sender.send(Ok(Arc::downgrade(&window))).unwrap(); } else { sender.send(Err(Error::CreateWindow)).unwrap(); } } Message::UserEvent(_) => (), Message::EventLoopWindowTarget(message) => match message { EventLoopWindowTargetMessage::CursorPosition(sender) => { let pos = event_loop .cursor_position() .map_err(|_| Error::FailedToSendMessage); sender.send(pos).unwrap(); } EventLoopWindowTargetMessage::SetTheme(theme) => { event_loop.set_theme(to_tao_theme(theme)); } EventLoopWindowTargetMessage::SetDeviceEventFilter(filter) => { event_loop.set_device_event_filter(DeviceEventFilterWrapper::from(filter).0); } }, } } fn handle_event_loop( event: Event<'_, Message>, event_loop: &EventLoopWindowTarget>, control_flow: &mut ControlFlow, context: EventLoopIterationContext<'_, T>, ) { let EventLoopIterationContext { callback, window_id_map, windows, #[cfg(feature = "tracing")] active_tracing_spans, } = context; if *control_flow != ControlFlow::Exit { *control_flow = ControlFlow::Wait; } match event { Event::NewEvents(StartCause::Init) => { callback(RunEvent::Ready); } Event::NewEvents(StartCause::Poll) => { callback(RunEvent::Resumed); } Event::MainEventsCleared => { callback(RunEvent::MainEventsCleared); } Event::LoopDestroyed => { callback(RunEvent::Exit); } #[cfg(windows)] Event::RedrawRequested(id) => { if let Some(window_id) = window_id_map.get(&id) { let mut windows_ref = windows.0.borrow_mut(); if let Some(window) = windows_ref.get_mut(&window_id) { if window.is_window_transparent { let background_color = window.background_color; if let Some(surface) = &mut window.surface { if let Some(window) = &window.inner { window.draw_surface(surface, background_color); } } } } } } #[cfg(feature = "tracing")] Event::RedrawEventsCleared => { active_tracing_spans.remove_window_draw(); } Event::UserEvent(Message::Webview( window_id, webview_id, WebviewMessage::WebviewEvent(event), )) => { let windows_ref = windows.0.borrow(); if let Some(window) = windows_ref.get(&window_id) { if let Some(webview) = window.webviews.iter().find(|w| w.id == webview_id) { let label = webview.label.clone(); let webview_event_listeners = webview.webview_event_listeners.clone(); drop(windows_ref); callback(RunEvent::WebviewEvent { label, event: event.clone(), }); let listeners = webview_event_listeners.lock().unwrap(); let handlers = listeners.values(); for handler in handlers { handler(&event); } } } } Event::UserEvent(Message::Webview( window_id, _webview_id, WebviewMessage::SynthesizedWindowEvent(event), )) => { if let Some(event) = WindowEventWrapper::from(event).0 { let windows_ref = windows.0.borrow(); let window = windows_ref.get(&window_id); if let Some(window) = window { let label = window.label.clone(); let window_event_listeners = window.window_event_listeners.clone(); drop(windows_ref); callback(RunEvent::WindowEvent { label, event: event.clone(), }); let listeners = window_event_listeners.lock().unwrap(); let handlers = listeners.values(); for handler in handlers { handler(&event); } } } } Event::WindowEvent { event, window_id, .. } => { if let Some(window_id) = window_id_map.get(&window_id) { { let windows_ref = windows.0.borrow(); if let Some(window) = windows_ref.get(&window_id) { if let Some(event) = WindowEventWrapper::parse(window, &event).0 { let label = window.label.clone(); let window_event_listeners = window.window_event_listeners.clone(); drop(windows_ref); callback(RunEvent::WindowEvent { label, event: event.clone(), }); let listeners = window_event_listeners.lock().unwrap(); let handlers = listeners.values(); for handler in handlers { handler(&event); } } } } match event { #[cfg(windows)] TaoWindowEvent::ThemeChanged(theme) => { if let Some(window) = windows.0.borrow().get(&window_id) { for webview in &window.webviews { let theme = match theme { TaoTheme::Dark => wry::Theme::Dark, TaoTheme::Light => wry::Theme::Light, _ => wry::Theme::Light, }; if let Err(e) = webview.set_theme(theme) { log::error!("failed to set theme: {e}"); } } } } TaoWindowEvent::CloseRequested => { on_close_requested(callback, window_id, windows); } TaoWindowEvent::Destroyed => { let removed = windows.0.borrow_mut().remove(&window_id).is_some(); if removed { let is_empty = windows.0.borrow().is_empty(); if is_empty { let (tx, rx) = channel(); callback(RunEvent::ExitRequested { code: None, tx }); let recv = rx.try_recv(); let should_prevent = matches!(recv, Ok(ExitRequestedEventAction::Prevent)); if !should_prevent { *control_flow = ControlFlow::Exit; } } } } TaoWindowEvent::Resized(size) => { if let Some((Some(window), webviews)) = windows .0 .borrow() .get(&window_id) .map(|w| (w.inner.clone(), w.webviews.clone())) { let size = size.to_logical::(window.scale_factor()); for webview in webviews { if let Some(b) = &*webview.bounds.lock().unwrap() { if let Err(e) = webview.set_bounds(wry::Rect { position: LogicalPosition::new(size.width * b.x_rate, size.height * b.y_rate) .into(), size: LogicalSize::new(size.width * b.width_rate, size.height * b.height_rate) .into(), }) { log::error!("failed to autoresize webview: {e}"); } } } } } _ => {} } } } Event::UserEvent(message) => match message { Message::RequestExit(code) => { let (tx, rx) = channel(); callback(RunEvent::ExitRequested { code: Some(code), tx, }); let recv = rx.try_recv(); let should_prevent = matches!(recv, Ok(ExitRequestedEventAction::Prevent)); if !should_prevent { *control_flow = ControlFlow::Exit; } } Message::Window(id, WindowMessage::Close) => { on_close_requested(callback, id, windows); } Message::Window(id, WindowMessage::Destroy) => { on_window_close(id, windows); } Message::UserEvent(t) => callback(RunEvent::UserEvent(t)), message => { handle_user_message( event_loop, message, UserMessageContext { window_id_map, windows, }, ); } }, #[cfg(any(target_os = "macos", target_os = "ios"))] Event::Opened { urls } => { callback(RunEvent::Opened { urls }); } #[cfg(target_os = "macos")] Event::Reopen { has_visible_windows, .. } => callback(RunEvent::Reopen { has_visible_windows, }), _ => (), } } fn on_close_requested<'a, T: UserEvent>( callback: &'a mut (dyn FnMut(RunEvent) + 'static), window_id: WindowId, windows: Arc, ) { let (tx, rx) = channel(); let windows_ref = windows.0.borrow(); if let Some(w) = windows_ref.get(&window_id) { let label = w.label.clone(); let window_event_listeners = w.window_event_listeners.clone(); drop(windows_ref); let listeners = window_event_listeners.lock().unwrap(); let handlers = listeners.values(); for handler in handlers { handler(&WindowEvent::CloseRequested { signal_tx: tx.clone(), }); } callback(RunEvent::WindowEvent { label, event: WindowEvent::CloseRequested { signal_tx: tx }, }); if let Ok(true) = rx.try_recv() { } else { on_window_close(window_id, windows); } } } fn on_window_close(window_id: WindowId, windows: Arc) { if let Some(window_wrapper) = windows.0.borrow_mut().get_mut(&window_id) { window_wrapper.inner = None; #[cfg(windows)] window_wrapper.surface.take(); } } fn parse_proxy_url(url: &Url) -> Result { let host = url.host().map(|h| h.to_string()).unwrap_or_default(); let port = url.port().map(|p| p.to_string()).unwrap_or_default(); if url.scheme() == "http" { let config = ProxyConfig::Http(ProxyEndpoint { host, port }); Ok(config) } else if url.scheme() == "socks5" { let config = ProxyConfig::Socks5(ProxyEndpoint { host, port }); Ok(config) } else { Err(Error::InvalidProxyUrl) } } fn create_window( window_id: WindowId, webview_id: u32, event_loop: &EventLoopWindowTarget>, context: &Context, pending: PendingWindow>, after_window_creation: Option, ) -> Result { #[allow(unused_mut)] let PendingWindow { mut window_builder, label, webview, } = pending; #[cfg(feature = "tracing")] let _webview_create_span = tracing::debug_span!("wry::webview::create").entered(); #[cfg(feature = "tracing")] let window_draw_span = tracing::debug_span!("wry::window::draw").entered(); #[cfg(feature = "tracing")] let window_create_span = tracing::debug_span!(parent: &window_draw_span, "wry::window::create").entered(); let window_event_listeners = WindowEventListeners::default(); #[cfg(windows)] let background_color = window_builder.inner.window.background_color; #[cfg(windows)] let is_window_transparent = window_builder.inner.window.transparent; #[cfg(target_os = "macos")] { if window_builder.tabbing_identifier.is_none() || window_builder.inner.window.transparent || !window_builder.inner.window.decorations { window_builder.inner = window_builder.inner.with_automatic_window_tabbing(false); } } #[cfg(desktop)] if window_builder.prevent_overflow.is_some() || window_builder.center { let monitor = if let Some(window_position) = &window_builder.inner.window.position { event_loop.available_monitors().find(|m| { let monitor_pos = m.position(); let monitor_size = m.size(); // type annotations required for 32bit targets. let window_position = window_position.to_physical::(m.scale_factor()); monitor_pos.x <= window_position.x && window_position.x < monitor_pos.x + monitor_size.width as i32 && monitor_pos.y <= window_position.y && window_position.y < monitor_pos.y + monitor_size.height as i32 }) } else { event_loop.primary_monitor() }; if let Some(monitor) = monitor { let scale_factor = monitor.scale_factor(); let desired_size = window_builder .inner .window .inner_size .unwrap_or_else(|| TaoPhysicalSize::new(800, 600).into()); let mut inner_size = window_builder .inner .window .inner_size_constraints .clamp(desired_size, scale_factor) .to_physical::(scale_factor); let mut window_size = inner_size; #[allow(unused_mut)] // Left and right window shadow counts as part of the window on Windows // We need to include it when calculating positions, but not size let mut shadow_width = 0; #[cfg(windows)] if window_builder.inner.window.decorations { use windows::Win32::UI::WindowsAndMessaging::{AdjustWindowRect, WS_OVERLAPPEDWINDOW}; let mut rect = windows::Win32::Foundation::RECT::default(); let result = unsafe { AdjustWindowRect(&mut rect, WS_OVERLAPPEDWINDOW, false) }; if result.is_ok() { shadow_width = (rect.right - rect.left) as u32; // rect.bottom is made out of shadow, and we don't care about it window_size.height += -rect.top as u32; } } if let Some(margin) = window_builder.prevent_overflow { let work_area = monitor.work_area(); let margin = margin.to_physical::(scale_factor); let constraint = PhysicalSize::new( work_area.size.width - margin.width, work_area.size.height - margin.height, ); if window_size.width > constraint.width || window_size.height > constraint.height { if window_size.width > constraint.width { inner_size.width = inner_size .width .saturating_sub(window_size.width - constraint.width); window_size.width = constraint.width; } if window_size.height > constraint.height { inner_size.height = inner_size .height .saturating_sub(window_size.height - constraint.height); window_size.height = constraint.height; } window_builder.inner.window.inner_size = Some(inner_size.into()); } } if window_builder.center { window_size.width += shadow_width; let position = window::calculate_window_center_position(window_size, monitor); let logical_position = position.to_logical::(scale_factor); window_builder = window_builder.position(logical_position.x, logical_position.y); } } }; let window = window_builder .inner .build(event_loop) .map_err(|_| Error::CreateWindow)?; #[cfg(feature = "tracing")] { drop(window_create_span); context .main_thread .active_tracing_spans .0 .borrow_mut() .push(ActiveTracingSpan::WindowDraw { id: window.id(), span: window_draw_span, }); } context.window_id_map.insert(window.id(), window_id); if let Some(handler) = after_window_creation { let raw = RawWindow { #[cfg(windows)] hwnd: window.hwnd(), #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] gtk_window: window.gtk_window(), #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] default_vbox: window.default_vbox(), _marker: &std::marker::PhantomData, }; handler(raw); } let mut webviews = Vec::new(); let focused_webview = Arc::new(Mutex::new(None)); if let Some(webview) = webview { webviews.push(create_webview( #[cfg(feature = "unstable")] WebviewKind::WindowChild, #[cfg(not(feature = "unstable"))] WebviewKind::WindowContent, &window, Arc::new(Mutex::new(window_id)), webview_id, context, webview, focused_webview.clone(), )?); } let window = Arc::new(window); #[cfg(windows)] let surface = if is_window_transparent { if let Ok(context) = softbuffer::Context::new(window.clone()) { if let Ok(mut surface) = softbuffer::Surface::new(&context, window.clone()) { window.draw_surface(&mut surface, background_color); Some(surface) } else { None } } else { None } } else { None }; Ok(WindowWrapper { label, has_children: AtomicBool::new(false), inner: Some(window), webviews, window_event_listeners, #[cfg(windows)] background_color, #[cfg(windows)] is_window_transparent, #[cfg(windows)] surface, focused_webview, }) } /// the kind of the webview #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] enum WebviewKind { // webview is the entire window content WindowContent, // webview is a child of the window, which can contain other webviews too WindowChild, } #[derive(Debug, Clone)] struct WebviewBounds { x_rate: f32, y_rate: f32, width_rate: f32, height_rate: f32, } fn create_webview( kind: WebviewKind, window: &Window, window_id: Arc>, id: WebviewId, context: &Context, pending: PendingWebview>, #[allow(unused_variables)] focused_webview: Arc>>, ) -> Result { if !context.webview_runtime_installed { #[cfg(all(not(debug_assertions), windows))] dialog::error( r#"Could not find the WebView2 Runtime. Make sure it is installed or download it from https://developer.microsoft.com/en-us/microsoft-edge/webview2 You may have it installed on another user account, but it is not available for this one. "#, ); if cfg!(target_os = "macos") { log::warn!("WebKit webview runtime not found, attempting to create webview anyway."); } else { return Err(Error::WebviewRuntimeNotInstalled); } } #[allow(unused_mut)] let PendingWebview { webview_attributes, uri_scheme_protocols, label, ipc_handler, url, .. } = pending; let mut web_context = context .main_thread .web_context .lock() .expect("poisoned WebContext store"); let is_first_context = web_context.is_empty(); // the context must be stored on the HashMap because it must outlive the WebView on macOS let automation_enabled = std::env::var("TAURI_WEBVIEW_AUTOMATION").as_deref() == Ok("true"); let web_context_key = webview_attributes.data_directory; let entry = web_context.entry(web_context_key.clone()); let web_context = match entry { Occupied(occupied) => { let occupied = occupied.into_mut(); occupied.referenced_by_webviews.insert(label.clone()); occupied } Vacant(vacant) => { let mut web_context = WryWebContext::new(web_context_key.clone()); web_context.set_allows_automation(if automation_enabled { is_first_context } else { false }); vacant.insert(WebContext { inner: web_context, referenced_by_webviews: [label.clone()].into(), registered_custom_protocols: HashSet::new(), }) } }; let mut webview_builder = WebViewBuilder::new_with_web_context(&mut web_context.inner) .with_id(&label) .with_focused(webview_attributes.focus) .with_transparent(webview_attributes.transparent) .with_accept_first_mouse(webview_attributes.accept_first_mouse) .with_incognito(webview_attributes.incognito) .with_clipboard(webview_attributes.clipboard) .with_hotkeys_zoom(webview_attributes.zoom_hotkeys_enabled); if url != "about:blank" { webview_builder = webview_builder.with_url(&url); } #[cfg(target_os = "macos")] if let Some(webview_configuration) = webview_attributes.webview_configuration { webview_builder = webview_builder.with_webview_configuration(webview_configuration); } #[cfg(any(target_os = "windows", target_os = "android"))] { webview_builder = webview_builder.with_https_scheme(webview_attributes.use_https_scheme); } if let Some(background_throttling) = webview_attributes.background_throttling { webview_builder = webview_builder.with_background_throttling(match background_throttling { tauri_utils::config::BackgroundThrottlingPolicy::Disabled => { wry::BackgroundThrottlingPolicy::Disabled } tauri_utils::config::BackgroundThrottlingPolicy::Suspend => { wry::BackgroundThrottlingPolicy::Suspend } tauri_utils::config::BackgroundThrottlingPolicy::Throttle => { wry::BackgroundThrottlingPolicy::Throttle } }); } if webview_attributes.javascript_disabled { webview_builder = webview_builder.with_javascript_disabled(); } if let Some(color) = webview_attributes.background_color { webview_builder = webview_builder.with_background_color(color.into()); } if webview_attributes.drag_drop_handler_enabled { let proxy = context.proxy.clone(); let window_id_ = window_id.clone(); webview_builder = webview_builder.with_drag_drop_handler(move |event| { let event = match event { WryDragDropEvent::Enter { paths, position: (x, y), } => DragDropEvent::Enter { paths, position: PhysicalPosition::new(x as _, y as _), }, WryDragDropEvent::Over { position: (x, y) } => DragDropEvent::Over { position: PhysicalPosition::new(x as _, y as _), }, WryDragDropEvent::Drop { paths, position: (x, y), } => DragDropEvent::Drop { paths, position: PhysicalPosition::new(x as _, y as _), }, WryDragDropEvent::Leave => DragDropEvent::Leave, _ => unimplemented!(), }; let message = if kind == WebviewKind::WindowContent { WebviewMessage::SynthesizedWindowEvent(SynthesizedWindowEvent::DragDrop(event)) } else { WebviewMessage::WebviewEvent(WebviewEvent::DragDrop(event)) }; let _ = proxy.send_event(Message::Webview(*window_id_.lock().unwrap(), id, message)); true }); } if let Some(navigation_handler) = pending.navigation_handler { webview_builder = webview_builder.with_navigation_handler(move |url| { url .parse() .map(|url| navigation_handler(&url)) .unwrap_or(true) }); } if let Some(new_window_handler) = pending.new_window_handler { #[cfg(desktop)] let context = context.clone(); webview_builder = webview_builder.with_new_window_req_handler(move |url, features| { url .parse() .map(|url| { let response = new_window_handler( url, tauri_runtime::webview::NewWindowFeatures::new( features.size, features.position, tauri_runtime::webview::NewWindowOpener { #[cfg(desktop)] webview: features.opener.webview, #[cfg(windows)] environment: features.opener.environment, #[cfg(target_os = "macos")] target_configuration: features.opener.target_configuration, }, ), ); match response { tauri_runtime::webview::NewWindowResponse::Allow => wry::NewWindowResponse::Allow, #[cfg(desktop)] tauri_runtime::webview::NewWindowResponse::Create { window_id } => { let windows = &context.main_thread.windows.0; let webview = loop { if let Some(webview) = windows.try_borrow().ok().and_then(|windows| { windows .get(&window_id) .map(|window| window.webviews.first().unwrap().clone()) }) { break webview; } else { // on Windows the window is created async so we should wait for it to be available std::thread::sleep(std::time::Duration::from_millis(50)); continue; }; }; #[cfg(desktop)] wry::NewWindowResponse::Create { #[cfg(target_os = "macos")] webview: wry::WebViewExtMacOS::webview(&*webview).as_super().into(), #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", ))] webview: webview.webview(), #[cfg(windows)] webview: webview.webview(), } } tauri_runtime::webview::NewWindowResponse::Deny => wry::NewWindowResponse::Deny, } }) .unwrap_or(wry::NewWindowResponse::Deny) }); } if let Some(document_title_changed_handler) = pending.document_title_changed_handler { webview_builder = webview_builder.with_document_title_changed_handler(document_title_changed_handler) } let webview_bounds = if let Some(bounds) = webview_attributes.bounds { let bounds: RectWrapper = bounds.into(); let bounds = bounds.0; let scale_factor = window.scale_factor(); let position = bounds.position.to_logical::(scale_factor); let size = bounds.size.to_logical::(scale_factor); webview_builder = webview_builder.with_bounds(bounds); let window_size = window.inner_size().to_logical::(scale_factor); if webview_attributes.auto_resize { Some(WebviewBounds { x_rate: position.x / window_size.width, y_rate: position.y / window_size.height, width_rate: size.width / window_size.width, height_rate: size.height / window_size.height, }) } else { None } } else { #[cfg(feature = "unstable")] { webview_builder = webview_builder.with_bounds(wry::Rect { position: LogicalPosition::new(0, 0).into(), size: window.inner_size().into(), }); Some(WebviewBounds { x_rate: 0., y_rate: 0., width_rate: 1., height_rate: 1., }) } #[cfg(not(feature = "unstable"))] None }; if let Some(download_handler) = pending.download_handler { let download_handler_ = download_handler.clone(); webview_builder = webview_builder.with_download_started_handler(move |url, path| { if let Ok(url) = url.parse() { download_handler_(DownloadEvent::Requested { url, destination: path, }) } else { false } }); webview_builder = webview_builder.with_download_completed_handler(move |url, path, success| { if let Ok(url) = url.parse() { download_handler(DownloadEvent::Finished { url, path, success }); } }); } if let Some(page_load_handler) = pending.on_page_load_handler { webview_builder = webview_builder.with_on_page_load_handler(move |event, url| { let _ = url.parse().map(|url| { page_load_handler( url, match event { wry::PageLoadEvent::Started => tauri_runtime::webview::PageLoadEvent::Started, wry::PageLoadEvent::Finished => tauri_runtime::webview::PageLoadEvent::Finished, }, ) }); }); } if let Some(user_agent) = webview_attributes.user_agent { webview_builder = webview_builder.with_user_agent(&user_agent); } if let Some(proxy_url) = webview_attributes.proxy_url { let config = parse_proxy_url(&proxy_url)?; webview_builder = webview_builder.with_proxy_config(config); } #[cfg(windows)] { if let Some(additional_browser_args) = webview_attributes.additional_browser_args { webview_builder = webview_builder.with_additional_browser_args(&additional_browser_args); } if let Some(environment) = webview_attributes.environment { webview_builder = webview_builder.with_environment(environment); } webview_builder = webview_builder.with_theme(match window.theme() { TaoTheme::Dark => wry::Theme::Dark, TaoTheme::Light => wry::Theme::Light, _ => wry::Theme::Light, }); webview_builder = webview_builder.with_scroll_bar_style(match webview_attributes.scroll_bar_style { ScrollBarStyle::Default => WryScrollBarStyle::Default, ScrollBarStyle::FluentOverlay => WryScrollBarStyle::FluentOverlay, _ => unreachable!(), }); } #[cfg(windows)] { webview_builder = webview_builder .with_browser_extensions_enabled(webview_attributes.browser_extensions_enabled); } #[cfg(any( windows, target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] { if let Some(path) = &webview_attributes.extensions_path { webview_builder = webview_builder.with_extensions_path(path); } } #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] { if let Some(related_view) = webview_attributes.related_view { webview_builder = webview_builder.with_related_view(related_view); } } #[cfg(any(target_os = "macos", target_os = "ios"))] { if let Some(data_store_identifier) = &webview_attributes.data_store_identifier { webview_builder = webview_builder.with_data_store_identifier(*data_store_identifier); } webview_builder = webview_builder.with_allow_link_preview(webview_attributes.allow_link_preview); } #[cfg(target_os = "ios")] { if let Some(input_accessory_view_builder) = webview_attributes.input_accessory_view_builder { webview_builder = webview_builder .with_input_accessory_view_builder(move |webview| input_accessory_view_builder.0(webview)); } } #[cfg(target_os = "macos")] { if let Some(position) = &webview_attributes.traffic_light_position { webview_builder = webview_builder.with_traffic_light_inset(*position); } } webview_builder = webview_builder.with_ipc_handler(create_ipc_handler( kind, window_id.clone(), id, context.clone(), label.clone(), ipc_handler, )); for script in webview_attributes.initialization_scripts { webview_builder = webview_builder .with_initialization_script_for_main_only(script.script, script.for_main_frame_only); } for (scheme, protocol) in uri_scheme_protocols { // on Linux the custom protocols are associated with the web context // and you cannot register a scheme more than once #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] { if web_context.registered_custom_protocols.contains(&scheme) { continue; } web_context .registered_custom_protocols .insert(scheme.clone()); } webview_builder = webview_builder.with_asynchronous_custom_protocol( scheme, move |webview_id, request, responder| { protocol( webview_id, request, Box::new(move |response| responder.respond(response)), ) }, ); } #[cfg(any(debug_assertions, feature = "devtools"))] { webview_builder = webview_builder.with_devtools(webview_attributes.devtools.unwrap_or(true)); } #[cfg(target_os = "android")] { if let Some(on_webview_created) = pending.on_webview_created { webview_builder = webview_builder.on_webview_created(move |ctx| { on_webview_created(tauri_runtime::webview::CreationContext { env: ctx.env, activity: ctx.activity, webview: ctx.webview, }) }); } } let webview = match kind { #[cfg(not(any( target_os = "windows", target_os = "macos", target_os = "ios", target_os = "android" )))] WebviewKind::WindowChild => { // only way to account for menu bar height, and also works for multiwebviews :) let vbox = window.default_vbox().unwrap(); webview_builder.build_gtk(vbox) } #[cfg(any( target_os = "windows", target_os = "macos", target_os = "ios", target_os = "android" ))] WebviewKind::WindowChild => webview_builder.build_as_child(&window), WebviewKind::WindowContent => { #[cfg(any( target_os = "windows", target_os = "macos", target_os = "ios", target_os = "android" ))] let builder = webview_builder.build(&window); #[cfg(not(any( target_os = "windows", target_os = "macos", target_os = "ios", target_os = "android" )))] let builder = { let vbox = window.default_vbox().unwrap(); webview_builder.build_gtk(vbox) }; builder } } .map_err(|e| Error::CreateWebview(Box::new(e)))?; if kind == WebviewKind::WindowContent { #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] undecorated_resizing::attach_resize_handler(&webview); #[cfg(windows)] if window.is_resizable() && !window.is_decorated() { undecorated_resizing::attach_resize_handler(window.hwnd(), window.has_undecorated_shadow()); } } #[cfg(windows)] { let controller = webview.controller(); let proxy_clone = context.proxy.clone(); let window_id_ = window_id.clone(); let mut token = 0; unsafe { let label_ = label.clone(); let focused_webview_ = focused_webview.clone(); controller.add_GotFocus( &FocusChangedEventHandler::create(Box::new(move |_, _| { let mut focused_webview = focused_webview_.lock().unwrap(); // when using multiwebview mode, we should check if the focus change is actually a "webview focus change" // instead of a window focus change (here we're patching window events, so we only care about the actual window changing focus) let already_focused = focused_webview.is_some(); focused_webview.replace(label_.clone()); if !already_focused { let _ = proxy_clone.send_event(Message::Webview( *window_id_.lock().unwrap(), id, WebviewMessage::SynthesizedWindowEvent(SynthesizedWindowEvent::Focused(true)), )); } Ok(()) })), &mut token, ) } .unwrap(); unsafe { let label_ = label.clone(); let window_id_ = window_id.clone(); let proxy_clone = context.proxy.clone(); controller.add_LostFocus( &FocusChangedEventHandler::create(Box::new(move |_, _| { let mut focused_webview = focused_webview.lock().unwrap(); // when using multiwebview mode, we should handle webview focus changes // so we check is the currently focused webview matches this webview's // (in this case, it means we lost the window focus) // // on multiwebview mode if we change focus to a different webview // we get the gotFocus event of the other webview before the lostFocus // so this check makes sense let lost_window_focus = focused_webview.as_ref().map_or(true, |w| w == &label_); if lost_window_focus { // only reset when we lost window focus - otherwise some other webview is focused *focused_webview = None; let _ = proxy_clone.send_event(Message::Webview( *window_id_.lock().unwrap(), id, WebviewMessage::SynthesizedWindowEvent(SynthesizedWindowEvent::Focused(false)), )); } Ok(()) })), &mut token, ) } .unwrap(); if let Ok(webview) = unsafe { controller.CoreWebView2() } { let proxy_clone = context.proxy.clone(); unsafe { let _ = webview.add_ContainsFullScreenElementChanged( &ContainsFullScreenElementChangedEventHandler::create(Box::new(move |sender, _| { let mut contains_fullscreen_element = windows::core::BOOL::default(); sender .ok_or_else(windows::core::Error::empty)? .ContainsFullScreenElement(&mut contains_fullscreen_element)?; let _ = proxy_clone.send_event(Message::Window( *window_id.lock().unwrap(), WindowMessage::SetFullscreen(contains_fullscreen_element.as_bool()), )); Ok(()) })), &mut token, ); } } } Ok(WebviewWrapper { label, id, inner: Rc::new(webview), context_store: context.main_thread.web_context.clone(), webview_event_listeners: Default::default(), context_key: if automation_enabled { None } else { web_context_key }, bounds: Arc::new(Mutex::new(webview_bounds)), }) } /// Create a wry ipc handler from a tauri ipc handler. fn create_ipc_handler( _kind: WebviewKind, window_id: Arc>, webview_id: WebviewId, context: Context, label: String, ipc_handler: Option>>, ) -> Box { Box::new(move |request| { if let Some(handler) = &ipc_handler { handler( DetachedWebview { label: label.clone(), dispatcher: WryWebviewDispatcher { window_id: window_id.clone(), webview_id, context: context.clone(), }, }, request, ); } }) } #[cfg(target_os = "macos")] fn inner_size( window: &Window, webviews: &[WebviewWrapper], has_children: bool, ) -> TaoPhysicalSize { if !has_children && !webviews.is_empty() { use wry::WebViewExtMacOS; let webview = webviews.first().unwrap(); let view = unsafe { Retained::cast_unchecked::(webview.webview()) }; let view_frame = view.frame(); let logical: TaoLogicalSize = (view_frame.size.width, view_frame.size.height).into(); return logical.to_physical(window.scale_factor()); } window.inner_size() } #[cfg(not(target_os = "macos"))] #[allow(unused_variables)] fn inner_size( window: &Window, webviews: &[WebviewWrapper], has_children: bool, ) -> TaoPhysicalSize { window.inner_size() } fn to_tao_theme(theme: Option) -> Option { match theme { Some(Theme::Light) => Some(TaoTheme::Light), Some(Theme::Dark) => Some(TaoTheme::Dark), _ => None, } } ================================================ FILE: crates/tauri-runtime-wry/src/monitor/linux.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use gtk::prelude::MonitorExt; use tao::platform::unix::MonitorHandleExtUnix; use tauri_runtime::dpi::{LogicalPosition, LogicalSize, PhysicalRect}; impl super::MonitorExt for tao::monitor::MonitorHandle { fn work_area(&self) -> PhysicalRect { let rect = self.gdk_monitor().workarea(); let scale_factor = self.scale_factor(); PhysicalRect { size: LogicalSize::new(rect.width() as u32, rect.height() as u32).to_physical(scale_factor), position: LogicalPosition::new(rect.x(), rect.y()).to_physical(scale_factor), } } } ================================================ FILE: crates/tauri-runtime-wry/src/monitor/macos.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use tauri_runtime::dpi::{LogicalSize, PhysicalRect}; impl super::MonitorExt for tao::monitor::MonitorHandle { fn work_area(&self) -> PhysicalRect { use objc2_app_kit::NSScreen; use tao::platform::macos::MonitorHandleExtMacOS; if let Some(ns_screen) = self.ns_screen() { let ns_screen: &NSScreen = unsafe { &*ns_screen.cast() }; let screen_frame = ns_screen.frame(); let visible_frame = ns_screen.visibleFrame(); let scale_factor = self.scale_factor(); let mut position = self.position().to_logical::(scale_factor); position.x += visible_frame.origin.x - screen_frame.origin.x; PhysicalRect { size: LogicalSize::new(visible_frame.size.width, visible_frame.size.height) .to_physical(scale_factor), position: position.to_physical(scale_factor), } } else { PhysicalRect { size: self.size(), position: self.position(), } } } } ================================================ FILE: crates/tauri-runtime-wry/src/monitor/mod.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use tauri_runtime::dpi::PhysicalRect; #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] mod linux; #[cfg(target_os = "macos")] mod macos; #[cfg(windows)] mod windows; pub trait MonitorExt { /// Get the work area of this monitor /// /// ## Platform-specific: /// /// - **Android / iOS**: Unsupported. fn work_area(&self) -> PhysicalRect; } #[cfg(mobile)] impl MonitorExt for tao::monitor::MonitorHandle { fn work_area(&self) -> PhysicalRect { PhysicalRect { size: self.size(), position: self.position(), } } } ================================================ FILE: crates/tauri-runtime-wry/src/monitor/windows.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use tao::dpi::{PhysicalPosition, PhysicalSize}; use tauri_runtime::dpi::PhysicalRect; impl super::MonitorExt for tao::monitor::MonitorHandle { fn work_area(&self) -> PhysicalRect { use tao::platform::windows::MonitorHandleExtWindows; use windows::Win32::Graphics::Gdi::{GetMonitorInfoW, HMONITOR, MONITORINFO}; let mut monitor_info = MONITORINFO { cbSize: std::mem::size_of::() as u32, ..Default::default() }; let status = unsafe { GetMonitorInfoW(HMONITOR(self.hmonitor() as _), &mut monitor_info) }; if status.as_bool() { PhysicalRect { size: PhysicalSize::new( (monitor_info.rcWork.right - monitor_info.rcWork.left) as u32, (monitor_info.rcWork.bottom - monitor_info.rcWork.top) as u32, ), position: PhysicalPosition::new(monitor_info.rcWork.left, monitor_info.rcWork.top), } } else { PhysicalRect { size: self.size(), position: self.position(), } } } } ================================================ FILE: crates/tauri-runtime-wry/src/undecorated_resizing.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT #![cfg(any( windows, target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] const CLIENT: isize = 0b0000; const LEFT: isize = 0b0001; const RIGHT: isize = 0b0010; const TOP: isize = 0b0100; const BOTTOM: isize = 0b1000; const TOPLEFT: isize = TOP | LEFT; const TOPRIGHT: isize = TOP | RIGHT; const BOTTOMLEFT: isize = BOTTOM | LEFT; const BOTTOMRIGHT: isize = BOTTOM | RIGHT; #[cfg(not(windows))] pub use self::gtk::*; #[cfg(windows)] pub use self::windows::*; #[cfg(windows)] type WindowPositions = i32; #[cfg(not(windows))] type WindowPositions = f64; #[derive(Debug, PartialEq, Eq, Clone, Copy)] enum HitTestResult { Client, Left, Right, Top, Bottom, TopLeft, TopRight, BottomLeft, BottomRight, NoWhere, } #[allow(clippy::too_many_arguments)] fn hit_test( left: WindowPositions, top: WindowPositions, right: WindowPositions, bottom: WindowPositions, cx: WindowPositions, cy: WindowPositions, border_x: WindowPositions, border_y: WindowPositions, ) -> HitTestResult { #[rustfmt::skip] let result = (LEFT * (cx < left + border_x) as isize) | (RIGHT * (cx >= right - border_x) as isize) | (TOP * (cy < top + border_y) as isize) | (BOTTOM * (cy >= bottom - border_y) as isize); match result { CLIENT => HitTestResult::Client, LEFT => HitTestResult::Left, RIGHT => HitTestResult::Right, TOP => HitTestResult::Top, BOTTOM => HitTestResult::Bottom, TOPLEFT => HitTestResult::TopLeft, TOPRIGHT => HitTestResult::TopRight, BOTTOMLEFT => HitTestResult::BottomLeft, BOTTOMRIGHT => HitTestResult::BottomRight, _ => HitTestResult::NoWhere, } } #[cfg(windows)] mod windows { use crate::util; use super::{hit_test, HitTestResult}; use windows::core::*; use windows::Win32::System::LibraryLoader::*; use windows::Win32::UI::WindowsAndMessaging::*; use windows::Win32::{Foundation::*, UI::Shell::SetWindowSubclass}; use windows::Win32::{Graphics::Gdi::*, UI::Shell::DefSubclassProc}; impl HitTestResult { fn to_win32(self) -> i32 { match self { HitTestResult::Left => HTLEFT as _, HitTestResult::Right => HTRIGHT as _, HitTestResult::Top => HTTOP as _, HitTestResult::Bottom => HTBOTTOM as _, HitTestResult::TopLeft => HTTOPLEFT as _, HitTestResult::TopRight => HTTOPRIGHT as _, HitTestResult::BottomLeft => HTBOTTOMLEFT as _, HitTestResult::BottomRight => HTBOTTOMRIGHT as _, _ => HTTRANSPARENT, } } } const CLASS_NAME: PCWSTR = w!("TAURI_DRAG_RESIZE_BORDERS"); const WINDOW_NAME: PCWSTR = w!("TAURI_DRAG_RESIZE_WINDOW"); const WM_UPDATE_UNDECORATED_SHADOWS: u32 = WM_USER + 100; struct UndecoratedResizingData { child: HWND, has_undecorated_shadows: bool, } pub fn attach_resize_handler(hwnd: isize, has_undecorated_shadows: bool) { let parent = HWND(hwnd as _); // return early if we already attached if unsafe { FindWindowExW(Some(parent), None, CLASS_NAME, WINDOW_NAME) }.is_ok() { return; } let class = WNDCLASSEXW { cbSize: std::mem::size_of::() as u32, style: WNDCLASS_STYLES::default(), lpfnWndProc: Some(drag_resize_window_proc), cbClsExtra: 0, cbWndExtra: 0, hInstance: unsafe { HINSTANCE(GetModuleHandleW(PCWSTR::null()).unwrap_or_default().0) }, hIcon: HICON::default(), hCursor: HCURSOR::default(), hbrBackground: HBRUSH::default(), lpszMenuName: PCWSTR::null(), lpszClassName: CLASS_NAME, hIconSm: HICON::default(), }; unsafe { RegisterClassExW(&class) }; let mut rect = RECT::default(); unsafe { GetClientRect(parent, &mut rect).unwrap() }; let width = rect.right - rect.left; let height = rect.bottom - rect.top; let data = UndecoratedResizingData { child: HWND::default(), has_undecorated_shadows, }; let Ok(drag_window) = (unsafe { CreateWindowExW( WINDOW_EX_STYLE::default(), CLASS_NAME, WINDOW_NAME, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, 0, 0, width, height, Some(parent), None, GetModuleHandleW(None).ok().map(|h| HINSTANCE(h.0)), Some(Box::into_raw(Box::new(data)) as _), ) }) else { return; }; unsafe { set_drag_hwnd_rgn(drag_window, width, height, has_undecorated_shadows); let _ = SetWindowPos( drag_window, Some(HWND_TOP), 0, 0, 0, 0, SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOSIZE, ); let data = UndecoratedResizingData { child: drag_window, has_undecorated_shadows, }; let _ = SetWindowSubclass( parent, Some(subclass_parent), (WM_USER + 1) as _, Box::into_raw(Box::new(data)) as _, ); } } unsafe extern "system" fn subclass_parent( parent: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM, _: usize, data: usize, ) -> LRESULT { match msg { WM_SIZE => { let data = data as *mut UndecoratedResizingData; let data = &*data; let child = data.child; let has_undecorated_shadows = data.has_undecorated_shadows; // when parent is maximized, remove the undecorated window drag resize region if is_maximized(parent).unwrap_or(false) { let _ = SetWindowPos( child, Some(HWND_TOP), 0, 0, 0, 0, SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE, ); } else { // otherwise updat the cutout region let mut rect = RECT::default(); if GetClientRect(parent, &mut rect).is_ok() { let width = rect.right - rect.left; let height = rect.bottom - rect.top; let _ = SetWindowPos( child, Some(HWND_TOP), 0, 0, width, height, SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE, ); set_drag_hwnd_rgn(child, width, height, has_undecorated_shadows); } } } WM_UPDATE_UNDECORATED_SHADOWS => { let data = data as *mut UndecoratedResizingData; let data = &mut *data; data.has_undecorated_shadows = wparam.0 != 0; } WM_NCDESTROY => { let data = data as *mut UndecoratedResizingData; drop(Box::from_raw(data)); } _ => {} } DefSubclassProc(parent, msg, wparam, lparam) } unsafe extern "system" fn drag_resize_window_proc( child: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM, ) -> LRESULT { match msg { WM_CREATE => { let data = lparam.0 as *mut CREATESTRUCTW; let data = (*data).lpCreateParams as *mut UndecoratedResizingData; (*data).child = child; SetWindowLongPtrW(child, GWLP_USERDATA, data as _); } WM_NCHITTEST => { let data = GetWindowLongPtrW(child, GWLP_USERDATA); let data = &*(data as *mut UndecoratedResizingData); let Ok(parent) = GetParent(child) else { return DefWindowProcW(child, msg, wparam, lparam); }; let style = GetWindowLongPtrW(parent, GWL_STYLE); let style = WINDOW_STYLE(style as u32); let is_resizable = (style & WS_SIZEBOX).0 != 0; if !is_resizable { return DefWindowProcW(child, msg, wparam, lparam); } // if the window has undecorated shadows, // it should always be the top border, // ensured by the cutout drag window if data.has_undecorated_shadows { return LRESULT(HTTOP as _); } let mut rect = RECT::default(); if GetWindowRect(child, &mut rect).is_err() { return DefWindowProcW(child, msg, wparam, lparam); } let (cx, cy) = (GET_X_LPARAM(lparam) as i32, GET_Y_LPARAM(lparam) as i32); let dpi = unsafe { util::hwnd_dpi(child) }; let border_x = util::get_system_metrics_for_dpi(SM_CXFRAME, dpi); let border_y = util::get_system_metrics_for_dpi(SM_CYFRAME, dpi); let res = hit_test( rect.left, rect.top, rect.right, rect.bottom, cx, cy, border_x, border_y, ); return LRESULT(res.to_win32() as _); } WM_NCLBUTTONDOWN => { let data = GetWindowLongPtrW(child, GWLP_USERDATA); let data = &*(data as *mut UndecoratedResizingData); let Ok(parent) = GetParent(child) else { return DefWindowProcW(child, msg, wparam, lparam); }; let style = GetWindowLongPtrW(parent, GWL_STYLE); let style = WINDOW_STYLE(style as u32); let is_resizable = (style & WS_SIZEBOX).0 != 0; if !is_resizable { return DefWindowProcW(child, msg, wparam, lparam); } let (cx, cy) = (GET_X_LPARAM(lparam) as i32, GET_Y_LPARAM(lparam) as i32); // if the window has undecorated shadows, // it should always be the top border, // ensured by the cutout drag window let res = if data.has_undecorated_shadows { HitTestResult::Top } else { let mut rect = RECT::default(); if GetWindowRect(child, &mut rect).is_err() { return DefWindowProcW(child, msg, wparam, lparam); } let dpi = unsafe { util::hwnd_dpi(child) }; let border_x = util::get_system_metrics_for_dpi(SM_CXFRAME, dpi); let border_y = util::get_system_metrics_for_dpi(SM_CYFRAME, dpi); hit_test( rect.left, rect.top, rect.right, rect.bottom, cx, cy, border_x, border_y, ) }; if res != HitTestResult::NoWhere { let points = POINTS { x: cx as i16, y: cy as i16, }; let _ = PostMessageW( Some(parent), WM_NCLBUTTONDOWN, WPARAM(res.to_win32() as _), LPARAM(&points as *const _ as _), ); } return LRESULT(0); } WM_UPDATE_UNDECORATED_SHADOWS => { let data = GetWindowLongPtrW(child, GWLP_USERDATA); let data = &mut *(data as *mut UndecoratedResizingData); data.has_undecorated_shadows = wparam.0 != 0; } WM_NCDESTROY => { let data = GetWindowLongPtrW(child, GWLP_USERDATA); let data = data as *mut UndecoratedResizingData; drop(Box::from_raw(data)); } _ => {} } DefWindowProcW(child, msg, wparam, lparam) } pub fn detach_resize_handler(hwnd: isize) { let hwnd = HWND(hwnd as _); let Ok(child) = (unsafe { FindWindowExW(Some(hwnd), None, CLASS_NAME, WINDOW_NAME) }) else { return; }; let _ = unsafe { DestroyWindow(child) }; } unsafe fn set_drag_hwnd_rgn(hwnd: HWND, width: i32, height: i32, only_top: bool) { // The window used for drag resizing an undecorated window // is a child HWND that covers the whole window // and so we need create a cut out in the middle for the parent and other child // windows like the webview can receive mouse events. let dpi = unsafe { util::hwnd_dpi(hwnd) }; let border_x = util::get_system_metrics_for_dpi(SM_CXFRAME, dpi); let border_y = util::get_system_metrics_for_dpi(SM_CYFRAME, dpi); // hrgn1 must be mutable to call .free() later let mut hrgn1 = CreateRectRgn(0, 0, width, height); let x1 = if only_top { 0 } else { border_x }; let y1 = border_y; let x2 = if only_top { width } else { width - border_x }; let y2 = if only_top { height } else { height - border_y }; // Wrap hrgn2 in Owned so it is automatically freed when going out of scope let hrgn2 = Owned::new(CreateRectRgn(x1, y1, x2, y2)); CombineRgn(Some(hrgn1), Some(hrgn1), Some(*hrgn2), RGN_DIFF); // Try to set the window region if SetWindowRgn(hwnd, Some(hrgn1), true) == 0 { // If it fails, we must free hrgn1 manually hrgn1.free(); } } pub fn update_drag_hwnd_rgn_for_undecorated(hwnd: isize, has_undecorated_shadows: bool) { let hwnd = HWND(hwnd as _); let mut rect = RECT::default(); let Ok(_) = (unsafe { GetClientRect(hwnd, &mut rect) }) else { return; }; let width = rect.right - rect.left; let height = rect.bottom - rect.top; let Ok(child) = (unsafe { FindWindowExW(Some(hwnd), None, CLASS_NAME, WINDOW_NAME) }) else { return; }; unsafe { set_drag_hwnd_rgn(child, width, height, has_undecorated_shadows) }; unsafe { SendMessageW( hwnd, WM_UPDATE_UNDECORATED_SHADOWS, None, Some(LPARAM(has_undecorated_shadows as _)), ) }; unsafe { SendMessageW( child, WM_UPDATE_UNDECORATED_SHADOWS, None, Some(LPARAM(has_undecorated_shadows as _)), ) }; } fn is_maximized(window: HWND) -> windows::core::Result { let mut placement = WINDOWPLACEMENT { length: std::mem::size_of::() as u32, ..WINDOWPLACEMENT::default() }; unsafe { GetWindowPlacement(window, &mut placement)? }; Ok(placement.showCmd == SW_MAXIMIZE.0 as u32) } /// Implementation of the `GET_X_LPARAM` macro. #[allow(non_snake_case)] #[inline] fn GET_X_LPARAM(lparam: LPARAM) -> i16 { ((lparam.0 as usize) & 0xFFFF) as u16 as i16 } /// Implementation of the `GET_Y_LPARAM` macro. #[allow(non_snake_case)] #[inline] fn GET_Y_LPARAM(lparam: LPARAM) -> i16 { (((lparam.0 as usize) & 0xFFFF_0000) >> 16) as u16 as i16 } } #[cfg(not(windows))] mod gtk { use super::{hit_test, HitTestResult}; const BORDERLESS_RESIZE_INSET: i32 = 5; impl HitTestResult { fn to_gtk_edge(self) -> gtk::gdk::WindowEdge { match self { HitTestResult::Client | HitTestResult::NoWhere => gtk::gdk::WindowEdge::__Unknown(0), HitTestResult::Left => gtk::gdk::WindowEdge::West, HitTestResult::Right => gtk::gdk::WindowEdge::East, HitTestResult::Top => gtk::gdk::WindowEdge::North, HitTestResult::Bottom => gtk::gdk::WindowEdge::South, HitTestResult::TopLeft => gtk::gdk::WindowEdge::NorthWest, HitTestResult::TopRight => gtk::gdk::WindowEdge::NorthEast, HitTestResult::BottomLeft => gtk::gdk::WindowEdge::SouthWest, HitTestResult::BottomRight => gtk::gdk::WindowEdge::SouthEast, } } } pub fn attach_resize_handler(webview: &wry::WebView) { use gtk::{ gdk::{prelude::*, WindowEdge}, glib::Propagation, prelude::*, }; use wry::WebViewExtUnix; let webview = webview.webview(); webview.add_events( gtk::gdk::EventMask::BUTTON1_MOTION_MASK | gtk::gdk::EventMask::BUTTON_PRESS_MASK | gtk::gdk::EventMask::TOUCH_MASK, ); webview.connect_button_press_event( move |webview: &webkit2gtk::WebView, event: >k::gdk::EventButton| { if event.button() == 1 { // This one should be GtkBox if let Some(window) = webview.parent().and_then(|w| w.parent()) { // Safe to unwrap unless this is not from tao let window: gtk::Window = window.downcast().unwrap(); if !window.is_decorated() && window.is_resizable() && !window.is_maximized() { if let Some(window) = window.window() { let (root_x, root_y) = event.root(); let (window_x, window_y) = window.position(); let (client_x, client_y) = (root_x - window_x as f64, root_y - window_y as f64); let border = window.scale_factor() * BORDERLESS_RESIZE_INSET; let edge = hit_test( 0.0, 0.0, window.width() as f64, window.height() as f64, client_x, client_y, border as _, border as _, ) .to_gtk_edge(); // we ignore the `__Unknown` variant so the webview receives the click correctly if it is not on the edges. match edge { WindowEdge::__Unknown(_) => (), _ => { window.begin_resize_drag(edge, 1, root_x as i32, root_y as i32, event.time()) } } } } } } Propagation::Proceed }, ); webview.connect_touch_event( move |webview: &webkit2gtk::WebView, event: >k::gdk::Event| { // This one should be GtkBox if let Some(window) = webview.parent().and_then(|w| w.parent()) { // Safe to unwrap unless this is not from tao let window: gtk::Window = window.downcast().unwrap(); if !window.is_decorated() && window.is_resizable() && !window.is_maximized() { if let Some(window) = window.window() { if let Some((root_x, root_y)) = event.root_coords() { if let Some(device) = event.device() { let (window_x, window_y) = window.position(); let (client_x, client_y) = (root_x - window_x as f64, root_y - window_y as f64); let border = window.scale_factor() * BORDERLESS_RESIZE_INSET; let edge = hit_test( 0.0, 0.0, window.width() as f64, window.height() as f64, client_x, client_y, border as _, border as _, ) .to_gtk_edge(); // we ignore the `__Unknown` variant so the window receives the click correctly if it is not on the edges. match edge { WindowEdge::__Unknown(_) => (), _ => window.begin_resize_drag_for_device( edge, &device, 0, root_x as i32, root_y as i32, event.time(), ), } } } } } } Propagation::Proceed }, ); } } ================================================ FILE: crates/tauri-runtime-wry/src/util.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT #[cfg_attr(not(windows), allow(unused_imports))] pub use imp::*; #[cfg(not(windows))] mod imp {} #[cfg(windows)] mod imp { use std::{iter::once, os::windows::ffi::OsStrExt}; use once_cell::sync::Lazy; use windows::{ core::{HRESULT, PCSTR, PCWSTR}, Win32::{ Foundation::*, Graphics::Gdi::*, System::LibraryLoader::{GetProcAddress, LoadLibraryW}, UI::{HiDpi::*, WindowsAndMessaging::*}, }, }; pub 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 zero-terminated. pub(super) fn get_function_impl(library: &str, function: &str) -> FARPROC { let library = encode_wide(library); assert_eq!(function.chars().last(), Some('\0')); // 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() { return None; } unsafe { GetProcAddress(module, PCSTR::from_raw(function.as_ptr())) } } macro_rules! get_function { ($lib:expr, $func:ident) => { $crate::util::get_function_impl($lib, concat!(stringify!($func), '\0')) .map(|f| unsafe { std::mem::transmute::<_, $func>(f) }) }; } type GetDpiForWindow = unsafe extern "system" fn(hwnd: HWND) -> u32; type GetDpiForMonitor = unsafe extern "system" fn( hmonitor: HMONITOR, dpi_type: MONITOR_DPI_TYPE, dpi_x: *mut u32, dpi_y: *mut u32, ) -> HRESULT; type GetSystemMetricsForDpi = unsafe extern "system" fn(nindex: SYSTEM_METRICS_INDEX, dpi: u32) -> i32; static GET_DPI_FOR_WINDOW: Lazy> = Lazy::new(|| get_function!("user32.dll", GetDpiForWindow)); static GET_DPI_FOR_MONITOR: Lazy> = Lazy::new(|| get_function!("shcore.dll", GetDpiForMonitor)); static GET_SYSTEM_METRICS_FOR_DPI: Lazy> = Lazy::new(|| get_function!("user32.dll", GetSystemMetricsForDpi)); #[allow(non_snake_case)] pub unsafe fn hwnd_dpi(hwnd: HWND) -> u32 { let hdc = GetDC(Some(hwnd)); if hdc.is_invalid() { return USER_DEFAULT_SCREEN_DPI; } if let Some(GetDpiForWindow) = *GET_DPI_FOR_WINDOW { // We are on Windows 10 Anniversary Update (1607) or later. match GetDpiForWindow(hwnd) { 0 => USER_DEFAULT_SCREEN_DPI, // 0 is returned if hwnd is invalid dpi => dpi, } } else if let Some(GetDpiForMonitor) = *GET_DPI_FOR_MONITOR { // We are on Windows 8.1 or later. let monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); if monitor.is_invalid() { return USER_DEFAULT_SCREEN_DPI; } let mut dpi_x = 0; let mut dpi_y = 0; if GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &mut dpi_x, &mut dpi_y).is_ok() { dpi_x } else { USER_DEFAULT_SCREEN_DPI } } else { // We are on Vista or later. if IsProcessDPIAware().as_bool() { // If the process is DPI aware, then scaling must be handled by the application using // this DPI value. GetDeviceCaps(Some(hdc), LOGPIXELSX) as u32 } else { // If the process is DPI unaware, then scaling is performed by the OS; we thus return // 96 (scale factor 1.0) to prevent the window from being re-scaled by both the // application and the WM. USER_DEFAULT_SCREEN_DPI } } } #[allow(non_snake_case)] pub unsafe fn get_system_metrics_for_dpi(nindex: SYSTEM_METRICS_INDEX, dpi: u32) -> i32 { if let Some(GetSystemMetricsForDpi) = *GET_SYSTEM_METRICS_FOR_DPI { GetSystemMetricsForDpi(nindex, dpi) } else { GetSystemMetrics(nindex) } } } ================================================ FILE: crates/tauri-runtime-wry/src/webview.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] mod imp { pub type Webview = webkit2gtk::WebView; } #[cfg(target_vendor = "apple")] mod imp { use std::ffi::c_void; pub struct Webview { pub webview: *mut c_void, pub manager: *mut c_void, #[cfg(target_os = "macos")] pub ns_window: *mut c_void, #[cfg(target_os = "ios")] pub view_controller: *mut c_void, } } #[cfg(windows)] mod imp { use webview2_com::Microsoft::Web::WebView2::Win32::{ ICoreWebView2Controller, ICoreWebView2Environment, }; pub struct Webview { pub controller: ICoreWebView2Controller, pub environment: ICoreWebView2Environment, } } #[cfg(target_os = "android")] mod imp { use wry::JniHandle; pub type Webview = JniHandle; } pub use imp::*; ================================================ FILE: crates/tauri-runtime-wry/src/window/linux.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use gtk::prelude::*; #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] use tao::platform::unix::WindowExtUnix; impl super::WindowExt for tao::window::Window { fn set_enabled(&self, enabled: bool) { self.gtk_window().set_sensitive(enabled); } fn is_enabled(&self) -> bool { self.gtk_window().is_sensitive() } fn center(&self) { if let Some(monitor) = self.current_monitor() { let window_size = self.outer_size(); let new_pos = super::calculate_window_center_position(window_size, monitor); self.set_outer_position(new_pos); } } } ================================================ FILE: crates/tauri-runtime-wry/src/window/macos.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use objc2::MainThreadMarker; use objc2_app_kit::{NSBackingStoreType, NSWindow, NSWindowStyleMask}; use tao::platform::macos::WindowExtMacOS; impl super::WindowExt for tao::window::Window { // based on electron implementation // https://github.com/electron/electron/blob/15db63e26df3e3d59ce6281f030624f746518511/shell/browser/native_window_mac.mm#L474 fn set_enabled(&self, enabled: bool) { let ns_window: &NSWindow = unsafe { &*self.ns_window().cast() }; if !enabled { let frame = ns_window.frame(); let mtm = MainThreadMarker::new() .expect("`Window::set_enabled` can only be called on the main thread"); let sheet = unsafe { NSWindow::initWithContentRect_styleMask_backing_defer( mtm.alloc(), frame, NSWindowStyleMask::Titled, NSBackingStoreType::Buffered, false, ) }; unsafe { sheet.setAlphaValue(0.5) }; unsafe { ns_window.beginSheet_completionHandler(&sheet, None) }; } else if let Some(attached) = unsafe { ns_window.attachedSheet() } { unsafe { ns_window.endSheet(&attached) }; } } fn is_enabled(&self) -> bool { let ns_window: &NSWindow = unsafe { &*self.ns_window().cast() }; unsafe { ns_window.attachedSheet() }.is_none() } fn center(&self) { let ns_window: &NSWindow = unsafe { &*self.ns_window().cast() }; ns_window.center(); } } ================================================ FILE: crates/tauri-runtime-wry/src/window/mod.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT #[cfg(any( target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] mod linux; #[cfg(target_os = "macos")] mod macos; #[cfg(windows)] mod windows; use crate::monitor::MonitorExt; pub trait WindowExt { /// Enable or disable the window /// /// ## Platform-specific: /// /// - **Android / iOS**: Unsupported. fn set_enabled(&self, enabled: bool); /// Whether the window is enabled or disabled. /// /// ## Platform-specific: /// /// - **Android / iOS**: Unsupported, always returns `true`. fn is_enabled(&self) -> bool; /// Center the window /// /// ## Platform-specific: /// /// - **Android / iOS**: Unsupported. fn center(&self) {} /// Clears the window surface. i.e make it transparent. #[cfg(windows)] fn draw_surface( &self, surface: &mut softbuffer::Surface< std::sync::Arc, std::sync::Arc, >, background_color: Option, ); } #[cfg(mobile)] impl WindowExt for tao::window::Window { fn set_enabled(&self, _: bool) {} fn is_enabled(&self) -> bool { true } } pub fn calculate_window_center_position( window_size: tao::dpi::PhysicalSize, target_monitor: tao::monitor::MonitorHandle, ) -> tao::dpi::PhysicalPosition { let work_area = target_monitor.work_area(); tao::dpi::PhysicalPosition::new( (work_area.size.width as i32 - window_size.width as i32) / 2 + work_area.position.x, (work_area.size.height as i32 - window_size.height as i32) / 2 + work_area.position.y, ) } ================================================ FILE: crates/tauri-runtime-wry/src/window/windows.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use windows::Win32::{ Foundation::{HWND, RECT}, Graphics::Dwm::{DwmGetWindowAttribute, DWMWA_EXTENDED_FRAME_BOUNDS}, UI::Input::KeyboardAndMouse::{EnableWindow, IsWindowEnabled}, }; use tao::platform::windows::WindowExtWindows; impl super::WindowExt for tao::window::Window { fn set_enabled(&self, enabled: bool) { let _ = unsafe { EnableWindow(HWND(self.hwnd() as _), enabled) }; } fn is_enabled(&self) -> bool { unsafe { IsWindowEnabled(HWND(self.hwnd() as _)) }.as_bool() } fn center(&self) { if let Some(monitor) = self.current_monitor() { let mut window_size = self.outer_size(); if self.is_decorated() { let mut rect = RECT::default(); let result = unsafe { DwmGetWindowAttribute( HWND(self.hwnd() as _), DWMWA_EXTENDED_FRAME_BOUNDS, &mut rect as *mut _ as *mut _, std::mem::size_of::() as u32, ) }; if result.is_ok() { window_size.height = (rect.bottom - rect.top) as u32; } } let new_pos = super::calculate_window_center_position(window_size, monitor); self.set_outer_position(new_pos); } } fn draw_surface( &self, surface: &mut softbuffer::Surface< std::sync::Arc, std::sync::Arc, >, background_color: Option, ) { let size = self.inner_size(); if let (Some(width), Some(height)) = ( std::num::NonZeroU32::new(size.width), std::num::NonZeroU32::new(size.height), ) { surface.resize(width, height).unwrap(); let mut buffer = surface.buffer_mut().unwrap(); let color = background_color .map(|(r, g, b, _)| (b as u32) | ((g as u32) << 8) | ((r as u32) << 16)) .unwrap_or(0); buffer.fill(color); let _ = buffer.present(); } } } ================================================ FILE: crates/tauri-schema-generator/Cargo.toml ================================================ [package] name = "tauri-schema-generator" version = "0.0.0" edition = "2021" publish = false [build-dependencies] tauri-utils = { features = ["schema"], path = "../tauri-utils" } schemars = { version = "0.8.21", features = ["url", "preserve_order"] } serde = { version = "1", features = ["derive"] } serde_json = "1" url = { version = "2", features = ["serde"] } ================================================ FILE: crates/tauri-schema-generator/README.md ================================================ # tauri-schema-generator This crate is part of the tauri monorepo workspace and its sole purpose is to generate JSON schema for various tauri config files. ================================================ FILE: crates/tauri-schema-generator/build.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use std::{error::Error, path::PathBuf}; use serde::Deserialize; use tauri_utils::{ acl::{capability::Capability, Permission, Scopes}, config::Config, write_if_changed, }; macro_rules! schema { ($name:literal, $path:ty) => { (concat!($name, ".schema.json"), schemars::schema_for!($path)) }; } #[derive(Deserialize)] pub struct VersionMetadata { tauri: String, } pub fn main() -> Result<(), Box> { let schemas = [ schema!("capability", Capability), schema!("permission", Permission), schema!("scope", Scopes), ]; let out = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR")?); let schemas_dir = out.join("schemas"); std::fs::create_dir_all(&schemas_dir)?; for (filename, schema) in schemas { let schema = serde_json::to_string_pretty(&schema)?; write_if_changed(schemas_dir.join(filename), &schema)?; } // write config schema file { let metadata = include_str!("../tauri-cli/metadata-v2.json"); let tauri_ver = serde_json::from_str::(metadata)?.tauri; // set id for generated schema let (filename, mut config_schema) = schema!("config", Config); let schema_metadata = config_schema.schema.metadata.as_mut().unwrap(); schema_metadata.id = Some(format!("https://schema.tauri.app/config/{tauri_ver}")); let config_schema = serde_json::to_string_pretty(&config_schema)?; write_if_changed(schemas_dir.join(filename), &config_schema)?; write_if_changed(out.join("../tauri-cli/config.schema.json"), config_schema)?; } Ok(()) } ================================================ FILE: crates/tauri-schema-generator/schemas/capability.schema.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Capability", "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows' and webviews' fine grained access\n to the Tauri core, application, or plugin commands.\n If a webview or its window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programmatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n ],\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```", "type": "object", "required": [ "identifier", "permissions" ], "properties": { "identifier": { "description": "Identifier of the capability.\n\n ## Example\n\n `main-user-files-write`", "type": "string" }, "description": { "description": "Description of what the capability is intended to allow on associated windows.\n\n It should contain a description of what the grouped permissions should allow.\n\n ## Example\n\n This capability allows the `main` window access to `filesystem` write related\n commands and `dialog` commands to enable programmatic access to files selected by the user.", "default": "", "type": "string" }, "remote": { "description": "Configure remote URLs that can use the capability permissions.\n\n This setting is optional and defaults to not being set, as our\n default use case is that the content is served from our local application.\n\n :::caution\n Make sure you understand the security implications of providing remote\n sources with local system access.\n :::\n\n ## Example\n\n ```json\n {\n \"urls\": [\"https://*.mydomain.dev\"]\n }\n ```", "anyOf": [ { "$ref": "#/definitions/CapabilityRemote" }, { "type": "null" } ] }, "local": { "description": "Whether this capability is enabled for local app URLs or not. Defaults to `true`.", "default": true, "type": "boolean" }, "windows": { "description": "List of windows that are affected by this capability. Can be a glob pattern.\n\n If a window label matches any of the patterns in this list,\n the capability will be enabled on all the webviews of that window,\n regardless of the value of [`Self::webviews`].\n\n On multiwebview windows, prefer specifying [`Self::webviews`] and omitting [`Self::windows`]\n for a fine grained access control.\n\n ## Example\n\n `[\"main\"]`", "type": "array", "items": { "type": "string" } }, "webviews": { "description": "List of webviews that are affected by this capability. Can be a glob pattern.\n\n The capability will be enabled on all the webviews\n whose label matches any of the patterns in this list,\n regardless of whether the webview's window label matches a pattern in [`Self::windows`].\n\n ## Example\n\n `[\"sub-webview-one\", \"sub-webview-two\"]`", "type": "array", "items": { "type": "string" } }, "permissions": { "description": "List of permissions attached to this capability.\n\n Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.\n For commands directly implemented in the application itself only `${permission-name}`\n is required.\n\n ## Example\n\n ```json\n [\n \"core:default\",\n \"shell:allow-open\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n }\n ]\n ```", "type": "array", "items": { "$ref": "#/definitions/PermissionEntry" }, "uniqueItems": true }, "platforms": { "description": "Limit which target platforms this capability applies to.\n\n By default all platforms are targeted.\n\n ## Example\n\n `[\"macOS\",\"windows\"]`", "type": [ "array", "null" ], "items": { "$ref": "#/definitions/Target" } } }, "definitions": { "CapabilityRemote": { "description": "Configuration for remote URLs that are associated with the capability.", "type": "object", "required": [ "urls" ], "properties": { "urls": { "description": "Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).\n\n ## Examples\n\n - \"https://*.mydomain.dev\": allows subdomains of mydomain.dev\n - \"https://mydomain.dev/api/*\": allows any subpath of mydomain.dev/api", "type": "array", "items": { "type": "string" } } } }, "PermissionEntry": { "description": "An entry for a permission value in a [`Capability`] can be either a raw permission [`Identifier`]\n or an object that references a permission and extends its scope.", "anyOf": [ { "description": "Reference a permission or permission set by identifier.", "allOf": [ { "$ref": "#/definitions/Identifier" } ] }, { "description": "Reference a permission or permission set by identifier and extends its scope.", "type": "object", "required": [ "identifier" ], "properties": { "identifier": { "description": "Identifier of the permission or permission set.", "allOf": [ { "$ref": "#/definitions/Identifier" } ] }, "allow": { "description": "Data that defines what is allowed by the scope.", "type": [ "array", "null" ], "items": { "$ref": "#/definitions/Value" } }, "deny": { "description": "Data that defines what is denied by the scope. This should be prioritized by validation logic.", "type": [ "array", "null" ], "items": { "$ref": "#/definitions/Value" } } } } ] }, "Identifier": { "type": "string" }, "Value": { "description": "All supported ACL values.", "anyOf": [ { "description": "Represents a null JSON value.", "type": "null" }, { "description": "Represents a [`bool`].", "type": "boolean" }, { "description": "Represents a valid ACL [`Number`].", "allOf": [ { "$ref": "#/definitions/Number" } ] }, { "description": "Represents a [`String`].", "type": "string" }, { "description": "Represents a list of other [`Value`]s.", "type": "array", "items": { "$ref": "#/definitions/Value" } }, { "description": "Represents a map of [`String`] keys to [`Value`]s.", "type": "object", "additionalProperties": { "$ref": "#/definitions/Value" } } ] }, "Number": { "description": "A valid ACL number.", "anyOf": [ { "description": "Represents an [`i64`].", "type": "integer", "format": "int64" }, { "description": "Represents a [`f64`].", "type": "number", "format": "double" } ] }, "Target": { "description": "Platform target.", "oneOf": [ { "description": "MacOS.", "type": "string", "enum": [ "macOS" ] }, { "description": "Windows.", "type": "string", "enum": [ "windows" ] }, { "description": "Linux.", "type": "string", "enum": [ "linux" ] }, { "description": "Android.", "type": "string", "enum": [ "android" ] }, { "description": "iOS.", "type": "string", "enum": [ "iOS" ] } ] } } } ================================================ FILE: crates/tauri-schema-generator/schemas/config.schema.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$id": "https://schema.tauri.app/config/2.10.3", "title": "Config", "description": "The Tauri configuration object.\n It is read from a file where you can define your frontend assets,\n configure the bundler and define a tray icon.\n\n The configuration file is generated by the\n [`tauri init`](https://v2.tauri.app/reference/cli/#init) command that lives in\n your Tauri application source directory (src-tauri).\n\n Once generated, you may modify it at will to customize your Tauri application.\n\n ## File Formats\n\n By default, the configuration is defined as a JSON file named `tauri.conf.json`.\n\n Tauri also supports JSON5 and TOML files via the `config-json5` and `config-toml` Cargo features, respectively.\n The JSON5 file name must be either `tauri.conf.json` or `tauri.conf.json5`.\n The TOML file name is `Tauri.toml`.\n\n ## Platform-Specific Configuration\n\n In addition to the default configuration file, Tauri can\n read a platform-specific configuration from `tauri.linux.conf.json`,\n `tauri.windows.conf.json`, `tauri.macos.conf.json`, `tauri.android.conf.json` and `tauri.ios.conf.json`\n (or `Tauri.linux.toml`, `Tauri.windows.toml`, `Tauri.macos.toml`, `Tauri.android.toml` and `Tauri.ios.toml` if the `Tauri.toml` format is used),\n which gets merged with the main configuration object.\n\n ## Configuration Structure\n\n The configuration is composed of the following objects:\n\n - [`app`](#appconfig): The Tauri configuration\n - [`build`](#buildconfig): The build configuration\n - [`bundle`](#bundleconfig): The bundle configurations\n - [`plugins`](#pluginconfig): The plugins configuration\n\n Example tauri.config.json file:\n\n ```json\n {\n \"productName\": \"tauri-app\",\n \"version\": \"0.1.0\",\n \"build\": {\n \"beforeBuildCommand\": \"\",\n \"beforeDevCommand\": \"\",\n \"devUrl\": \"http://localhost:3000\",\n \"frontendDist\": \"../dist\"\n },\n \"app\": {\n \"security\": {\n \"csp\": null\n },\n \"windows\": [\n {\n \"fullscreen\": false,\n \"height\": 600,\n \"resizable\": true,\n \"title\": \"Tauri App\",\n \"width\": 800\n }\n ]\n },\n \"bundle\": {},\n \"plugins\": {}\n }\n ```", "type": "object", "required": [ "identifier" ], "properties": { "$schema": { "description": "The JSON schema for the Tauri config.", "type": [ "string", "null" ] }, "productName": { "description": "App name.", "type": [ "string", "null" ], "pattern": "^[^/\\:*?\"<>|]+$" }, "mainBinaryName": { "description": "Overrides app's main binary filename.\n\n By default, Tauri uses the output binary from `cargo`, by setting this, we will rename that binary in `tauri-cli`'s\n `tauri build` command, and target `tauri bundle` to it\n\n If possible, change the [`package name`] or set the [`name field`] instead,\n and if that's not enough and you're using nightly, consider using the [`different-binary-name`] feature instead\n\n Note: this config should not include the binary extension (e.g. `.exe`), we'll add that for you\n\n [`package name`]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-name-field\n [`name field`]: https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-name-field\n [`different-binary-name`]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#different-binary-name", "type": [ "string", "null" ] }, "version": { "description": "App version. It is a semver version number or a path to a `package.json` file containing the `version` field.\n\n If removed the version number from `Cargo.toml` is used.\n It's recommended to manage the app versioning in the Tauri config.\n\n ## Platform-specific\n\n - **macOS**: Translates to the bundle's CFBundleShortVersionString property and is used as the default CFBundleVersion.\n You can set an specific bundle version using [`bundle > macOS > bundleVersion`](MacConfig::bundle_version).\n - **iOS**: Translates to the bundle's CFBundleShortVersionString property and is used as the default CFBundleVersion.\n You can set an specific bundle version using [`bundle > iOS > bundleVersion`](IosConfig::bundle_version).\n The `tauri ios build` CLI command has a `--build-number ` option that lets you append a build number to the app version.\n - **Android**: By default version 1.0 is used. You can set a version code using [`bundle > android > versionCode`](AndroidConfig::version_code).\n\n By default version 1.0 is used on Android.", "type": [ "string", "null" ] }, "identifier": { "description": "The application identifier in reverse domain name notation (e.g. `com.tauri.example`).\n This string must be unique across applications since it is used in system configurations like\n the bundle ID and path to the webview data directory.\n This string must contain only alphanumeric characters (A-Z, a-z, and 0-9), hyphens (-),\n and periods (.).", "type": "string" }, "app": { "description": "The App configuration.", "default": { "enableGTKAppId": false, "macOSPrivateApi": false, "security": { "assetProtocol": { "enable": false, "scope": [] }, "capabilities": [], "dangerousDisableAssetCspModification": false, "freezePrototype": false, "pattern": { "use": "brownfield" } }, "windows": [], "withGlobalTauri": false }, "allOf": [ { "$ref": "#/definitions/AppConfig" } ] }, "build": { "description": "The build configuration.", "default": { "additionalWatchFolders": [], "removeUnusedCommands": false }, "allOf": [ { "$ref": "#/definitions/BuildConfig" } ] }, "bundle": { "description": "The bundler configuration.", "default": { "active": false, "android": { "autoIncrementVersionCode": false, "minSdkVersion": 24 }, "createUpdaterArtifacts": false, "iOS": { "minimumSystemVersion": "14.0" }, "icon": [], "linux": { "appimage": { "bundleMediaFramework": false, "files": {} }, "deb": { "files": {} }, "rpm": { "epoch": 0, "files": {}, "release": "1" } }, "macOS": { "dmg": { "appPosition": { "x": 180, "y": 170 }, "applicationFolderPosition": { "x": 480, "y": 170 }, "windowSize": { "height": 400, "width": 660 } }, "files": {}, "hardenedRuntime": true, "minimumSystemVersion": "10.13" }, "targets": "all", "useLocalToolsDir": false, "windows": { "allowDowngrades": true, "certificateThumbprint": null, "digestAlgorithm": null, "nsis": null, "signCommand": null, "timestampUrl": null, "tsp": false, "webviewInstallMode": { "silent": true, "type": "downloadBootstrapper" }, "wix": null } }, "allOf": [ { "$ref": "#/definitions/BundleConfig" } ] }, "plugins": { "description": "The plugins config.", "default": {}, "allOf": [ { "$ref": "#/definitions/PluginConfig" } ] } }, "additionalProperties": false, "definitions": { "AppConfig": { "description": "The App configuration object.\n\n See more: ", "type": "object", "properties": { "windows": { "description": "The app windows configuration.\n\n ## Example:\n\n To create a window at app startup\n\n ```json\n {\n \"app\": {\n \"windows\": [\n { \"width\": 800, \"height\": 600 }\n ]\n }\n }\n ```\n\n If not specified, the window's label (its identifier) defaults to \"main\",\n you can use this label to get the window through\n `app.get_webview_window` in Rust or `WebviewWindow.getByLabel` in JavaScript\n\n When working with multiple windows, each window will need an unique label\n\n ```json\n {\n \"app\": {\n \"windows\": [\n { \"label\": \"main\", \"width\": 800, \"height\": 600 },\n { \"label\": \"secondary\", \"width\": 800, \"height\": 600 }\n ]\n }\n }\n ```\n\n You can also set `create` to false and use this config through the Rust APIs\n\n ```json\n {\n \"app\": {\n \"windows\": [\n { \"create\": false, \"width\": 800, \"height\": 600 }\n ]\n }\n }\n ```\n\n and use it like this\n\n ```rust\n tauri::Builder::default()\n .setup(|app| {\n tauri::WebviewWindowBuilder::from_config(app.handle(), &app.config().app.windows[0])?.build()?;\n Ok(())\n });\n ```", "default": [], "type": "array", "items": { "$ref": "#/definitions/WindowConfig" } }, "security": { "description": "Security configuration.", "default": { "assetProtocol": { "enable": false, "scope": [] }, "capabilities": [], "dangerousDisableAssetCspModification": false, "freezePrototype": false, "pattern": { "use": "brownfield" } }, "allOf": [ { "$ref": "#/definitions/SecurityConfig" } ] }, "trayIcon": { "description": "Configuration for app tray icon.", "anyOf": [ { "$ref": "#/definitions/TrayIconConfig" }, { "type": "null" } ] }, "macOSPrivateApi": { "description": "MacOS private API configuration. Enables the transparent background API and sets the `fullScreenEnabled` preference to `true`.", "default": false, "type": "boolean" }, "withGlobalTauri": { "description": "Whether we should inject the Tauri API on `window.__TAURI__` or not.", "default": false, "type": "boolean" }, "enableGTKAppId": { "description": "If set to true \"identifier\" will be set as GTK app ID (on systems that use GTK).", "default": false, "type": "boolean" } }, "additionalProperties": false }, "WindowConfig": { "description": "The window configuration object.\n\n See more: ", "type": "object", "properties": { "label": { "description": "The window identifier. It must be alphanumeric.", "default": "main", "type": "string" }, "create": { "description": "Whether Tauri should create this window at app startup or not.\n\n When this is set to `false` you must manually grab the config object via `app.config().app.windows`\n and create it with [`WebviewWindowBuilder::from_config`](https://docs.rs/tauri/2/tauri/webview/struct.WebviewWindowBuilder.html#method.from_config).\n\n ## Example:\n\n ```rust\n tauri::Builder::default()\n .setup(|app| {\n tauri::WebviewWindowBuilder::from_config(app.handle(), &app.config().app.windows[0])?.build()?;\n Ok(())\n });\n ```", "default": true, "type": "boolean" }, "url": { "description": "The window webview URL.", "default": "index.html", "allOf": [ { "$ref": "#/definitions/WebviewUrl" } ] }, "userAgent": { "description": "The user agent for the webview", "type": [ "string", "null" ] }, "dragDropEnabled": { "description": "Whether the drag and drop is enabled or not on the webview. By default it is enabled.\n\n Disabling it is required to use HTML5 drag and drop on the frontend on Windows.", "default": true, "type": "boolean" }, "center": { "description": "Whether or not the window starts centered or not.", "default": false, "type": "boolean" }, "x": { "description": "The horizontal position of the window's top left corner in logical pixels", "type": [ "number", "null" ], "format": "double" }, "y": { "description": "The vertical position of the window's top left corner in logical pixels", "type": [ "number", "null" ], "format": "double" }, "width": { "description": "The window width in logical pixels.", "default": 800.0, "type": "number", "format": "double" }, "height": { "description": "The window height in logical pixels.", "default": 600.0, "type": "number", "format": "double" }, "minWidth": { "description": "The min window width in logical pixels.", "type": [ "number", "null" ], "format": "double" }, "minHeight": { "description": "The min window height in logical pixels.", "type": [ "number", "null" ], "format": "double" }, "maxWidth": { "description": "The max window width in logical pixels.", "type": [ "number", "null" ], "format": "double" }, "maxHeight": { "description": "The max window height in logical pixels.", "type": [ "number", "null" ], "format": "double" }, "preventOverflow": { "description": "Whether or not to prevent the window from overflowing the workarea\n\n ## Platform-specific\n\n - **iOS / Android:** Unsupported.", "anyOf": [ { "$ref": "#/definitions/PreventOverflowConfig" }, { "type": "null" } ] }, "resizable": { "description": "Whether the window is resizable or not. When resizable is set to false, native window's maximize button is automatically disabled.", "default": true, "type": "boolean" }, "maximizable": { "description": "Whether the window's native maximize button is enabled or not.\n If resizable is set to false, this setting is ignored.\n\n ## Platform-specific\n\n - **macOS:** Disables the \"zoom\" button in the window titlebar, which is also used to enter fullscreen mode.\n - **Linux / iOS / Android:** Unsupported.", "default": true, "type": "boolean" }, "minimizable": { "description": "Whether the window's native minimize button is enabled or not.\n\n ## Platform-specific\n\n - **Linux / iOS / Android:** Unsupported.", "default": true, "type": "boolean" }, "closable": { "description": "Whether the window's native close button is enabled or not.\n\n ## Platform-specific\n\n - **Linux:** \"GTK+ will do its best to convince the window manager not to show a close button.\n Depending on the system, this function may not have any effect when called on a window that is already visible\"\n - **iOS / Android:** Unsupported.", "default": true, "type": "boolean" }, "title": { "description": "The window title.", "default": "Tauri App", "type": "string" }, "fullscreen": { "description": "Whether the window starts as fullscreen or not.", "default": false, "type": "boolean" }, "focus": { "description": "Whether the window will be initially focused or not.", "default": true, "type": "boolean" }, "focusable": { "description": "Whether the window will be focusable or not.", "default": true, "type": "boolean" }, "transparent": { "description": "Whether the window is transparent or not.\n\n Note that on `macOS` this requires the `macos-private-api` feature flag, enabled under `tauri > macOSPrivateApi`.\n WARNING: Using private APIs on `macOS` prevents your application from being accepted to the `App Store`.", "default": false, "type": "boolean" }, "maximized": { "description": "Whether the window is maximized or not.", "default": false, "type": "boolean" }, "visible": { "description": "Whether the window is visible or not.", "default": true, "type": "boolean" }, "decorations": { "description": "Whether the window should have borders and bars.", "default": true, "type": "boolean" }, "alwaysOnBottom": { "description": "Whether the window should always be below other windows.", "default": false, "type": "boolean" }, "alwaysOnTop": { "description": "Whether the window should always be on top of other windows.", "default": false, "type": "boolean" }, "visibleOnAllWorkspaces": { "description": "Whether the window should be visible on all workspaces or virtual desktops.\n\n ## Platform-specific\n\n - **Windows / iOS / Android:** Unsupported.", "default": false, "type": "boolean" }, "contentProtected": { "description": "Prevents the window contents from being captured by other apps.", "default": false, "type": "boolean" }, "skipTaskbar": { "description": "If `true`, hides the window icon from the taskbar on Windows and Linux.", "default": false, "type": "boolean" }, "windowClassname": { "description": "The name of the window class created on Windows to create the window. **Windows only**.", "type": [ "string", "null" ] }, "theme": { "description": "The initial window theme. Defaults to the system theme. Only implemented on Windows and macOS 10.14+.", "anyOf": [ { "$ref": "#/definitions/Theme" }, { "type": "null" } ] }, "titleBarStyle": { "description": "The style of the macOS title bar.", "default": "Visible", "allOf": [ { "$ref": "#/definitions/TitleBarStyle" } ] }, "trafficLightPosition": { "description": "The position of the window controls on macOS.\n\n Requires titleBarStyle: Overlay and decorations: true.", "anyOf": [ { "$ref": "#/definitions/LogicalPosition" }, { "type": "null" } ] }, "hiddenTitle": { "description": "If `true`, sets the window title to be hidden on macOS.", "default": false, "type": "boolean" }, "acceptFirstMouse": { "description": "Whether clicking an inactive window also clicks through to the webview on macOS.", "default": false, "type": "boolean" }, "tabbingIdentifier": { "description": "Defines the window [tabbing identifier] for macOS.\n\n Windows with matching tabbing identifiers will be grouped together.\n If the tabbing identifier is not set, automatic tabbing will be disabled.\n\n [tabbing identifier]: ", "type": [ "string", "null" ] }, "additionalBrowserArgs": { "description": "Defines additional browser arguments on Windows. By default wry passes `--disable-features=msWebOOUI,msPdfOOUI,msSmartScreenProtection`\n so if you use this method, you also need to disable these components by yourself if you want.", "type": [ "string", "null" ] }, "shadow": { "description": "Whether or not the window has shadow.\n\n ## Platform-specific\n\n - **Windows:**\n - `false` has no effect on decorated window, shadow are always ON.\n - `true` will make undecorated window have a 1px white border,\n and on Windows 11, it will have a rounded corners.\n - **Linux:** Unsupported.", "default": true, "type": "boolean" }, "windowEffects": { "description": "Window effects.\n\n Requires the window to be transparent.\n\n ## Platform-specific:\n\n - **Windows**: If using decorations or shadows, you may want to try this workaround \n - **Linux**: Unsupported", "anyOf": [ { "$ref": "#/definitions/WindowEffectsConfig" }, { "type": "null" } ] }, "incognito": { "description": "Whether or not the webview should be launched in incognito mode.\n\n ## Platform-specific:\n\n - **Android**: Unsupported.", "default": false, "type": "boolean" }, "parent": { "description": "Sets the window associated with this label to be the parent of the window to be created.\n\n ## Platform-specific\n\n - **Windows**: This sets the passed parent as an owner window to the window to be created.\n From [MSDN owned windows docs](https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#owned-windows):\n - An owned window is always above its owner in the z-order.\n - The system automatically destroys an owned window when its owner is destroyed.\n - An owned window is hidden when its owner is minimized.\n - **Linux**: This makes the new window transient for parent, see \n - **macOS**: This adds the window as a child of parent, see ", "type": [ "string", "null" ] }, "proxyUrl": { "description": "The proxy URL for the WebView for all network requests.\n\n Must be either a `http://` or a `socks5://` URL.\n\n ## Platform-specific\n\n - **macOS**: Requires the `macos-proxy` feature flag and only compiles for macOS 14+.", "type": [ "string", "null" ], "format": "uri" }, "zoomHotkeysEnabled": { "description": "Whether page zooming by hotkeys is enabled\n\n ## Platform-specific:\n\n - **Windows**: Controls WebView2's [`IsZoomControlEnabled`](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/microsoft_web_webview2_core/corewebview2settings?view=webview2-winrt-1.0.2420.47#iszoomcontrolenabled) setting.\n - **MacOS / Linux**: Injects a polyfill that zooms in and out with `ctrl/command` + `-/=`,\n 20% in each step, ranging from 20% to 1000%. Requires `webview:allow-set-webview-zoom` permission\n\n - **Android / iOS**: Unsupported.", "default": false, "type": "boolean" }, "browserExtensionsEnabled": { "description": "Whether browser extensions can be installed for the webview process\n\n ## Platform-specific:\n\n - **Windows**: Enables the WebView2 environment's [`AreBrowserExtensionsEnabled`](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/microsoft_web_webview2_core/corewebview2environmentoptions?view=webview2-winrt-1.0.2739.15#arebrowserextensionsenabled)\n - **MacOS / Linux / iOS / Android** - Unsupported.", "default": false, "type": "boolean" }, "useHttpsScheme": { "description": "Sets whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android. Defaults to `false`.\n\n ## Note\n\n Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux.\n\n ## Warning\n\n Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access the old data.", "default": false, "type": "boolean" }, "devtools": { "description": "Enable web inspector which is usually called browser devtools. Enabled by default.\n\n This API works in **debug** builds, but requires `devtools` feature flag to enable it in **release** builds.\n\n ## Platform-specific\n\n - macOS: This will call private functions on **macOS**.\n - Android: Open `chrome://inspect/#devices` in Chrome to get the devtools window. Wry's `WebView` devtools API isn't supported on Android.\n - iOS: Open Safari > Develop > [Your Device Name] > [Your WebView] to get the devtools window.", "type": [ "boolean", "null" ] }, "backgroundColor": { "description": "Set the window and webview background color.\n\n ## Platform-specific:\n\n - **Windows**: alpha channel is ignored for the window layer.\n - **Windows**: On Windows 7, alpha channel is ignored for the webview layer.\n - **Windows**: On Windows 8 and newer, if alpha channel is not `0`, it will be ignored for the webview layer.", "anyOf": [ { "$ref": "#/definitions/Color" }, { "type": "null" } ] }, "backgroundThrottling": { "description": "Change the default background throttling behaviour.\n\n By default, browsers use a suspend policy that will throttle timers and even unload\n the whole tab (view) to free resources after roughly 5 minutes when a view became\n minimized or hidden. This will pause all tasks until the documents visibility state\n changes back from hidden to visible by bringing the view back to the foreground.\n\n ## Platform-specific\n\n - **Linux / Windows / Android**: Unsupported. Workarounds like a pending WebLock transaction might suffice.\n - **iOS**: Supported since version 17.0+.\n - **macOS**: Supported since version 14.0+.\n\n see https://github.com/tauri-apps/tauri/issues/5250#issuecomment-2569380578", "anyOf": [ { "$ref": "#/definitions/BackgroundThrottlingPolicy" }, { "type": "null" } ] }, "javascriptDisabled": { "description": "Whether we should disable JavaScript code execution on the webview or not.", "default": false, "type": "boolean" }, "allowLinkPreview": { "description": "on macOS and iOS there is a link preview on long pressing links, this is enabled by default.\n see https://docs.rs/objc2-web-kit/latest/objc2_web_kit/struct.WKWebView.html#method.allowsLinkPreview", "default": true, "type": "boolean" }, "disableInputAccessoryView": { "description": "Allows disabling the input accessory view on iOS.\n\n The accessory view is the view that appears above the keyboard when a text input element is focused.\n It usually displays a view with \"Done\", \"Next\" buttons.", "default": false, "type": "boolean" }, "dataDirectory": { "description": "Set a custom path for the webview's data directory (localStorage, cache, etc.) **relative to [`appDataDir()`]/${label}**.\n\n To set absolute paths, use [`WebviewWindowBuilder::data_directory`](https://docs.rs/tauri/2/tauri/webview/struct.WebviewWindowBuilder.html#method.data_directory)\n\n #### Platform-specific:\n\n - **Windows**: WebViews with different values for settings like `additionalBrowserArgs`, `browserExtensionsEnabled` or `scrollBarStyle` must have different data directories.\n - **macOS / iOS**: Unsupported, use `dataStoreIdentifier` instead.\n - **Android**: Unsupported.", "type": [ "string", "null" ] }, "dataStoreIdentifier": { "description": "Initialize the WebView with a custom data store identifier. This can be seen as a replacement for `dataDirectory` which is unavailable in WKWebView.\n See https://developer.apple.com/documentation/webkit/wkwebsitedatastore/init(foridentifier:)?language=objc\n\n The array must contain 16 u8 numbers.\n\n #### Platform-specific:\n\n - **iOS**: Supported since version 17.0+.\n - **macOS**: Supported since version 14.0+.\n - **Windows / Linux / Android**: Unsupported.", "type": [ "array", "null" ], "items": { "type": "integer", "format": "uint8", "minimum": 0.0 }, "maxItems": 16, "minItems": 16 }, "scrollBarStyle": { "description": "Specifies the native scrollbar style to use with the webview.\n CSS styles that modify the scrollbar are applied on top of the native appearance configured here.\n\n Defaults to `default`, which is the browser default.\n\n ## Platform-specific\n\n - **Windows**:\n - `fluentOverlay` requires WebView2 Runtime version 125.0.2535.41 or higher,\n and does nothing on older versions.\n - This option must be given the same value for all webviews that target the same data directory.\n - **Linux / Android / iOS / macOS**: Unsupported. Only supports `Default` and performs no operation.", "default": "default", "allOf": [ { "$ref": "#/definitions/ScrollBarStyle" } ] } }, "additionalProperties": false }, "WebviewUrl": { "description": "An URL to open on a Tauri webview window.", "anyOf": [ { "description": "An external URL. Must use either the `http` or `https` schemes.", "type": "string", "format": "uri" }, { "description": "The path portion of an app URL.\n For instance, to load `tauri://localhost/users/john`,\n you can simply provide `users/john` in this configuration.", "type": "string" }, { "description": "A custom protocol url, for example, `doom://index.html`", "type": "string", "format": "uri" } ] }, "PreventOverflowConfig": { "description": "Prevent overflow with a margin", "anyOf": [ { "description": "Enable prevent overflow or not", "type": "boolean" }, { "description": "Enable prevent overflow with a margin\n so that the window's size + this margin won't overflow the workarea", "allOf": [ { "$ref": "#/definitions/PreventOverflowMargin" } ] } ] }, "PreventOverflowMargin": { "description": "Enable prevent overflow with a margin\n so that the window's size + this margin won't overflow the workarea", "type": "object", "required": [ "height", "width" ], "properties": { "width": { "description": "Horizontal margin in physical pixels", "type": "integer", "format": "uint32", "minimum": 0.0 }, "height": { "description": "Vertical margin in physical pixels", "type": "integer", "format": "uint32", "minimum": 0.0 } }, "additionalProperties": false }, "Theme": { "description": "System theme.", "oneOf": [ { "description": "Light theme.", "type": "string", "enum": [ "Light" ] }, { "description": "Dark theme.", "type": "string", "enum": [ "Dark" ] } ] }, "TitleBarStyle": { "description": "How the window title bar should be displayed on macOS.", "oneOf": [ { "description": "A normal title bar.", "type": "string", "enum": [ "Visible" ] }, { "description": "Makes the title bar transparent, so the window background color is shown instead.\n\n Useful if you don't need to have actual HTML under the title bar. This lets you avoid the caveats of using `TitleBarStyle::Overlay`. Will be more useful when Tauri lets you set a custom window background color.", "type": "string", "enum": [ "Transparent" ] }, { "description": "Shows the title bar as a transparent overlay over the window's content.\n\n Keep in mind:\n - The height of the title bar is different on different OS versions, which can lead to window the controls and title not being where you don't expect.\n - You need to define a custom drag region to make your window draggable, however due to a limitation you can't drag the window when it's not in focus .\n - The color of the window title depends on the system theme.", "type": "string", "enum": [ "Overlay" ] } ] }, "LogicalPosition": { "description": "Position coordinates struct.", "type": "object", "required": [ "x", "y" ], "properties": { "x": { "description": "X coordinate.", "type": "number", "format": "double" }, "y": { "description": "Y coordinate.", "type": "number", "format": "double" } }, "additionalProperties": false }, "WindowEffectsConfig": { "description": "The window effects configuration object", "type": "object", "required": [ "effects" ], "properties": { "effects": { "description": "List of Window effects to apply to the Window.\n Conflicting effects will apply the first one and ignore the rest.", "type": "array", "items": { "$ref": "#/definitions/WindowEffect" } }, "state": { "description": "Window effect state **macOS Only**", "anyOf": [ { "$ref": "#/definitions/WindowEffectState" }, { "type": "null" } ] }, "radius": { "description": "Window effect corner radius **macOS Only**", "type": [ "number", "null" ], "format": "double" }, "color": { "description": "Window effect color. Affects [`WindowEffect::Blur`] and [`WindowEffect::Acrylic`] only\n on Windows 10 v1903+. Doesn't have any effect on Windows 7 or Windows 11.", "anyOf": [ { "$ref": "#/definitions/Color" }, { "type": "null" } ] } }, "additionalProperties": false }, "WindowEffect": { "description": "Platform-specific window effects", "oneOf": [ { "description": "A default material appropriate for the view's effectiveAppearance. **macOS 10.14-**", "deprecated": true, "type": "string", "enum": [ "appearanceBased" ] }, { "description": "**macOS 10.14-**", "deprecated": true, "type": "string", "enum": [ "light" ] }, { "description": "**macOS 10.14-**", "deprecated": true, "type": "string", "enum": [ "dark" ] }, { "description": "**macOS 10.14-**", "deprecated": true, "type": "string", "enum": [ "mediumLight" ] }, { "description": "**macOS 10.14-**", "deprecated": true, "type": "string", "enum": [ "ultraDark" ] }, { "description": "**macOS 10.10+**", "type": "string", "enum": [ "titlebar" ] }, { "description": "**macOS 10.10+**", "type": "string", "enum": [ "selection" ] }, { "description": "**macOS 10.11+**", "type": "string", "enum": [ "menu" ] }, { "description": "**macOS 10.11+**", "type": "string", "enum": [ "popover" ] }, { "description": "**macOS 10.11+**", "type": "string", "enum": [ "sidebar" ] }, { "description": "**macOS 10.14+**", "type": "string", "enum": [ "headerView" ] }, { "description": "**macOS 10.14+**", "type": "string", "enum": [ "sheet" ] }, { "description": "**macOS 10.14+**", "type": "string", "enum": [ "windowBackground" ] }, { "description": "**macOS 10.14+**", "type": "string", "enum": [ "hudWindow" ] }, { "description": "**macOS 10.14+**", "type": "string", "enum": [ "fullScreenUI" ] }, { "description": "**macOS 10.14+**", "type": "string", "enum": [ "tooltip" ] }, { "description": "**macOS 10.14+**", "type": "string", "enum": [ "contentBackground" ] }, { "description": "**macOS 10.14+**", "type": "string", "enum": [ "underWindowBackground" ] }, { "description": "**macOS 10.14+**", "type": "string", "enum": [ "underPageBackground" ] }, { "description": "Mica effect that matches the system dark preference **Windows 11 Only**", "type": "string", "enum": [ "mica" ] }, { "description": "Mica effect with dark mode but only if dark mode is enabled on the system **Windows 11 Only**", "type": "string", "enum": [ "micaDark" ] }, { "description": "Mica effect with light mode **Windows 11 Only**", "type": "string", "enum": [ "micaLight" ] }, { "description": "Tabbed effect that matches the system dark preference **Windows 11 Only**", "type": "string", "enum": [ "tabbed" ] }, { "description": "Tabbed effect with dark mode but only if dark mode is enabled on the system **Windows 11 Only**", "type": "string", "enum": [ "tabbedDark" ] }, { "description": "Tabbed effect with light mode **Windows 11 Only**", "type": "string", "enum": [ "tabbedLight" ] }, { "description": "**Windows 7/10/11(22H1) Only**\n\n ## Notes\n\n This effect has bad performance when resizing/dragging the window on Windows 11 build 22621.", "type": "string", "enum": [ "blur" ] }, { "description": "**Windows 10/11 Only**\n\n ## Notes\n\n This effect has bad performance when resizing/dragging the window on Windows 10 v1903+ and Windows 11 build 22000.", "type": "string", "enum": [ "acrylic" ] } ] }, "WindowEffectState": { "description": "Window effect state **macOS only**\n\n ", "oneOf": [ { "description": "Make window effect state follow the window's active state", "type": "string", "enum": [ "followsWindowActiveState" ] }, { "description": "Make window effect state always active", "type": "string", "enum": [ "active" ] }, { "description": "Make window effect state always inactive", "type": "string", "enum": [ "inactive" ] } ] }, "Color": { "anyOf": [ { "description": "Color hex string, for example: #fff, #ffffff, or #ffffffff.", "type": "string", "pattern": "^#?([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$" }, { "description": "Array of RGB colors. Each value has minimum of 0 and maximum of 255.", "type": "array", "items": [ { "type": "integer", "format": "uint8", "minimum": 0.0 }, { "type": "integer", "format": "uint8", "minimum": 0.0 }, { "type": "integer", "format": "uint8", "minimum": 0.0 } ], "maxItems": 3, "minItems": 3 }, { "description": "Array of RGBA colors. Each value has minimum of 0 and maximum of 255.", "type": "array", "items": [ { "type": "integer", "format": "uint8", "minimum": 0.0 }, { "type": "integer", "format": "uint8", "minimum": 0.0 }, { "type": "integer", "format": "uint8", "minimum": 0.0 }, { "type": "integer", "format": "uint8", "minimum": 0.0 } ], "maxItems": 4, "minItems": 4 }, { "description": "Object of red, green, blue, alpha color values. Each value has minimum of 0 and maximum of 255.", "type": "object", "required": [ "blue", "green", "red" ], "properties": { "red": { "type": "integer", "format": "uint8", "minimum": 0.0 }, "green": { "type": "integer", "format": "uint8", "minimum": 0.0 }, "blue": { "type": "integer", "format": "uint8", "minimum": 0.0 }, "alpha": { "default": 255, "type": "integer", "format": "uint8", "minimum": 0.0 } } } ] }, "BackgroundThrottlingPolicy": { "description": "Background throttling policy.", "oneOf": [ { "description": "A policy where background throttling is disabled", "type": "string", "enum": [ "disabled" ] }, { "description": "A policy where a web view that's not in a window fully suspends tasks. This is usually the default behavior in case no policy is set.", "type": "string", "enum": [ "suspend" ] }, { "description": "A policy where a web view that's not in a window limits processing, but does not fully suspend tasks.", "type": "string", "enum": [ "throttle" ] } ] }, "ScrollBarStyle": { "description": "The scrollbar style to use in the webview.\n\n ## Platform-specific\n\n - **Windows**: This option must be given the same value for all webviews that target the same data directory.", "oneOf": [ { "description": "The scrollbar style to use in the webview.", "type": "string", "enum": [ "default" ] }, { "description": "Fluent UI style overlay scrollbars. **Windows Only**\n\n Requires WebView2 Runtime version 125.0.2535.41 or higher, does nothing on older versions,\n see https://learn.microsoft.com/en-us/microsoft-edge/webview2/release-notes/?tabs=dotnetcsharp#10253541", "type": "string", "enum": [ "fluentOverlay" ] } ] }, "SecurityConfig": { "description": "Security configuration.\n\n See more: ", "type": "object", "properties": { "csp": { "description": "The Content Security Policy that will be injected on all HTML files on the built application.\n If [`dev_csp`](#SecurityConfig.devCsp) is not specified, this value is also injected on dev.\n\n This is a really important part of the configuration since it helps you ensure your WebView is secured.\n See .", "anyOf": [ { "$ref": "#/definitions/Csp" }, { "type": "null" } ] }, "devCsp": { "description": "The Content Security Policy that will be injected on all HTML files on development.\n\n This is a really important part of the configuration since it helps you ensure your WebView is secured.\n See .", "anyOf": [ { "$ref": "#/definitions/Csp" }, { "type": "null" } ] }, "freezePrototype": { "description": "Freeze the `Object.prototype` when using the custom protocol.", "default": false, "type": "boolean" }, "dangerousDisableAssetCspModification": { "description": "Disables the Tauri-injected CSP sources.\n\n At compile time, Tauri parses all the frontend assets and changes the Content-Security-Policy\n to only allow loading of your own scripts and styles by injecting nonce and hash sources.\n This stricts your CSP, which may introduce issues when using along with other flexing sources.\n\n This configuration option allows both a boolean and a list of strings as value.\n A boolean instructs Tauri to disable the injection for all CSP injections,\n and a list of strings indicates the CSP directives that Tauri cannot inject.\n\n **WARNING:** Only disable this if you know what you are doing and have properly configured the CSP.\n Your application might be vulnerable to XSS attacks without this Tauri protection.", "default": false, "allOf": [ { "$ref": "#/definitions/DisabledCspModificationKind" } ] }, "assetProtocol": { "description": "Custom protocol config.", "default": { "enable": false, "scope": [] }, "allOf": [ { "$ref": "#/definitions/AssetProtocolConfig" } ] }, "pattern": { "description": "The pattern to use.", "default": { "use": "brownfield" }, "allOf": [ { "$ref": "#/definitions/PatternKind" } ] }, "capabilities": { "description": "List of capabilities that are enabled on the application.\n\n By default (not set or empty list), all capability files from `./capabilities/` are included,\n by setting values in this entry, you have fine grained control over which capabilities are included\n\n You can either reference a capability file defined in `./capabilities/` with its identifier or inline a [`Capability`]\n\n ### Example\n\n ```json\n {\n \"app\": {\n \"capabilities\": [\n \"main-window\",\n {\n \"identifier\": \"drag-window\",\n \"permissions\": [\"core:window:allow-start-dragging\"]\n }\n ]\n }\n }\n ```", "default": [], "type": "array", "items": { "$ref": "#/definitions/CapabilityEntry" } }, "headers": { "description": "The headers, which are added to every http response from tauri to the web view\n This doesn't include IPC Messages and error responses", "anyOf": [ { "$ref": "#/definitions/HeaderConfig" }, { "type": "null" } ] } }, "additionalProperties": false }, "Csp": { "description": "A Content-Security-Policy definition.\n See .", "anyOf": [ { "description": "The entire CSP policy in a single text string.", "type": "string" }, { "description": "An object mapping a directive with its sources values as a list of strings.", "type": "object", "additionalProperties": { "$ref": "#/definitions/CspDirectiveSources" } } ] }, "CspDirectiveSources": { "description": "A Content-Security-Policy directive source list.\n See .", "anyOf": [ { "description": "An inline list of CSP sources. Same as [`Self::List`], but concatenated with a space separator.", "type": "string" }, { "description": "A list of CSP sources. The collection will be concatenated with a space separator for the CSP string.", "type": "array", "items": { "type": "string" } } ] }, "DisabledCspModificationKind": { "description": "The possible values for the `dangerous_disable_asset_csp_modification` config option.", "anyOf": [ { "description": "If `true`, disables all CSP modification.\n `false` is the default value and it configures Tauri to control the CSP.", "type": "boolean" }, { "description": "Disables the given list of CSP directives modifications.", "type": "array", "items": { "type": "string" } } ] }, "AssetProtocolConfig": { "description": "Config for the asset custom protocol.\n\n See more: ", "type": "object", "properties": { "scope": { "description": "The access scope for the asset protocol.", "default": [], "allOf": [ { "$ref": "#/definitions/FsScope" } ] }, "enable": { "description": "Enables the asset protocol.", "default": false, "type": "boolean" } }, "additionalProperties": false }, "FsScope": { "description": "Protocol scope definition.\n It is a list of glob patterns that restrict the API access from the webview.\n\n Each pattern can start with a variable that resolves to a system base directory.\n The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`,\n `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`,\n `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$TEMP`,\n `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.", "anyOf": [ { "description": "A list of paths that are allowed by this scope.", "type": "array", "items": { "type": "string" } }, { "description": "A complete scope configuration.", "type": "object", "properties": { "allow": { "description": "A list of paths that are allowed by this scope.", "default": [], "type": "array", "items": { "type": "string" } }, "deny": { "description": "A list of paths that are not allowed by this scope.\n This gets precedence over the [`Self::Scope::allow`] list.", "default": [], "type": "array", "items": { "type": "string" } }, "requireLiteralLeadingDot": { "description": "Whether or not paths that contain components that start with a `.`\n will require that `.` appears literally in the pattern; `*`, `?`, `**`,\n or `[...]` will not match. This is useful because such files are\n conventionally considered hidden on Unix systems and it might be\n desirable to skip them when listing files.\n\n Defaults to `true` on Unix systems and `false` on Windows", "type": [ "boolean", "null" ] } } } ] }, "PatternKind": { "description": "The application pattern.", "oneOf": [ { "description": "Brownfield pattern.", "type": "object", "required": [ "use" ], "properties": { "use": { "type": "string", "enum": [ "brownfield" ] } } }, { "description": "Isolation pattern. Recommended for security purposes.", "type": "object", "required": [ "options", "use" ], "properties": { "use": { "type": "string", "enum": [ "isolation" ] }, "options": { "type": "object", "required": [ "dir" ], "properties": { "dir": { "description": "The dir containing the index.html file that contains the secure isolation application.", "type": "string" } } } } } ] }, "CapabilityEntry": { "description": "A capability entry which can be either an inlined capability or a reference to a capability defined on its own file.", "anyOf": [ { "description": "An inlined capability.", "allOf": [ { "$ref": "#/definitions/Capability" } ] }, { "description": "Reference to a capability identifier.", "type": "string" } ] }, "Capability": { "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows' and webviews' fine grained access\n to the Tauri core, application, or plugin commands.\n If a webview or its window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programmatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n ],\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```", "type": "object", "required": [ "identifier", "permissions" ], "properties": { "identifier": { "description": "Identifier of the capability.\n\n ## Example\n\n `main-user-files-write`", "type": "string" }, "description": { "description": "Description of what the capability is intended to allow on associated windows.\n\n It should contain a description of what the grouped permissions should allow.\n\n ## Example\n\n This capability allows the `main` window access to `filesystem` write related\n commands and `dialog` commands to enable programmatic access to files selected by the user.", "default": "", "type": "string" }, "remote": { "description": "Configure remote URLs that can use the capability permissions.\n\n This setting is optional and defaults to not being set, as our\n default use case is that the content is served from our local application.\n\n :::caution\n Make sure you understand the security implications of providing remote\n sources with local system access.\n :::\n\n ## Example\n\n ```json\n {\n \"urls\": [\"https://*.mydomain.dev\"]\n }\n ```", "anyOf": [ { "$ref": "#/definitions/CapabilityRemote" }, { "type": "null" } ] }, "local": { "description": "Whether this capability is enabled for local app URLs or not. Defaults to `true`.", "default": true, "type": "boolean" }, "windows": { "description": "List of windows that are affected by this capability. Can be a glob pattern.\n\n If a window label matches any of the patterns in this list,\n the capability will be enabled on all the webviews of that window,\n regardless of the value of [`Self::webviews`].\n\n On multiwebview windows, prefer specifying [`Self::webviews`] and omitting [`Self::windows`]\n for a fine grained access control.\n\n ## Example\n\n `[\"main\"]`", "type": "array", "items": { "type": "string" } }, "webviews": { "description": "List of webviews that are affected by this capability. Can be a glob pattern.\n\n The capability will be enabled on all the webviews\n whose label matches any of the patterns in this list,\n regardless of whether the webview's window label matches a pattern in [`Self::windows`].\n\n ## Example\n\n `[\"sub-webview-one\", \"sub-webview-two\"]`", "type": "array", "items": { "type": "string" } }, "permissions": { "description": "List of permissions attached to this capability.\n\n Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.\n For commands directly implemented in the application itself only `${permission-name}`\n is required.\n\n ## Example\n\n ```json\n [\n \"core:default\",\n \"shell:allow-open\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n }\n ]\n ```", "type": "array", "items": { "$ref": "#/definitions/PermissionEntry" }, "uniqueItems": true }, "platforms": { "description": "Limit which target platforms this capability applies to.\n\n By default all platforms are targeted.\n\n ## Example\n\n `[\"macOS\",\"windows\"]`", "type": [ "array", "null" ], "items": { "$ref": "#/definitions/Target" } } } }, "CapabilityRemote": { "description": "Configuration for remote URLs that are associated with the capability.", "type": "object", "required": [ "urls" ], "properties": { "urls": { "description": "Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).\n\n ## Examples\n\n - \"https://*.mydomain.dev\": allows subdomains of mydomain.dev\n - \"https://mydomain.dev/api/*\": allows any subpath of mydomain.dev/api", "type": "array", "items": { "type": "string" } } } }, "PermissionEntry": { "description": "An entry for a permission value in a [`Capability`] can be either a raw permission [`Identifier`]\n or an object that references a permission and extends its scope.", "anyOf": [ { "description": "Reference a permission or permission set by identifier.", "allOf": [ { "$ref": "#/definitions/Identifier" } ] }, { "description": "Reference a permission or permission set by identifier and extends its scope.", "type": "object", "required": [ "identifier" ], "properties": { "identifier": { "description": "Identifier of the permission or permission set.", "allOf": [ { "$ref": "#/definitions/Identifier" } ] }, "allow": { "description": "Data that defines what is allowed by the scope.", "type": [ "array", "null" ], "items": { "$ref": "#/definitions/Value" } }, "deny": { "description": "Data that defines what is denied by the scope. This should be prioritized by validation logic.", "type": [ "array", "null" ], "items": { "$ref": "#/definitions/Value" } } } } ] }, "Identifier": { "type": "string" }, "Value": { "description": "All supported ACL values.", "anyOf": [ { "description": "Represents a null JSON value.", "type": "null" }, { "description": "Represents a [`bool`].", "type": "boolean" }, { "description": "Represents a valid ACL [`Number`].", "allOf": [ { "$ref": "#/definitions/Number" } ] }, { "description": "Represents a [`String`].", "type": "string" }, { "description": "Represents a list of other [`Value`]s.", "type": "array", "items": { "$ref": "#/definitions/Value" } }, { "description": "Represents a map of [`String`] keys to [`Value`]s.", "type": "object", "additionalProperties": { "$ref": "#/definitions/Value" } } ] }, "Number": { "description": "A valid ACL number.", "anyOf": [ { "description": "Represents an [`i64`].", "type": "integer", "format": "int64" }, { "description": "Represents a [`f64`].", "type": "number", "format": "double" } ] }, "Target": { "description": "Platform target.", "oneOf": [ { "description": "MacOS.", "type": "string", "enum": [ "macOS" ] }, { "description": "Windows.", "type": "string", "enum": [ "windows" ] }, { "description": "Linux.", "type": "string", "enum": [ "linux" ] }, { "description": "Android.", "type": "string", "enum": [ "android" ] }, { "description": "iOS.", "type": "string", "enum": [ "iOS" ] } ] }, "HeaderConfig": { "description": "A struct, where the keys are some specific http header names.\n\n If the values to those keys are defined, then they will be send as part of a response message.\n This does not include error messages and ipc messages\n\n ## Example configuration\n ```javascript\n {\n //..\n app:{\n //..\n security: {\n headers: {\n \"Cross-Origin-Opener-Policy\": \"same-origin\",\n \"Cross-Origin-Embedder-Policy\": \"require-corp\",\n \"Timing-Allow-Origin\": [\n \"https://developer.mozilla.org\",\n \"https://example.com\",\n ],\n \"Access-Control-Expose-Headers\": \"Tauri-Custom-Header\",\n \"Tauri-Custom-Header\": {\n \"key1\": \"'value1' 'value2'\",\n \"key2\": \"'value3'\"\n }\n },\n csp: \"default-src 'self'; connect-src ipc: http://ipc.localhost\",\n }\n //..\n }\n //..\n }\n ```\n In this example `Cross-Origin-Opener-Policy` and `Cross-Origin-Embedder-Policy` are set to allow for the use of [`SharedArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer).\n The result is, that those headers are then set on every response sent via the `get_response` function in crates/tauri/src/protocol/tauri.rs.\n The Content-Security-Policy header is defined separately, because it is also handled separately.\n\n For the helloworld example, this config translates into those response headers:\n ```http\n access-control-allow-origin: http://tauri.localhost\n access-control-expose-headers: Tauri-Custom-Header\n content-security-policy: default-src 'self'; connect-src ipc: http://ipc.localhost; script-src 'self' 'sha256-Wjjrs6qinmnr+tOry8x8PPwI77eGpUFR3EEGZktjJNs='\n content-type: text/html\n cross-origin-embedder-policy: require-corp\n cross-origin-opener-policy: same-origin\n tauri-custom-header: key1 'value1' 'value2'; key2 'value3'\n timing-allow-origin: https://developer.mozilla.org, https://example.com\n ```\n Since the resulting header values are always 'string-like'. So depending on the what data type the HeaderSource is, they need to be converted.\n - `String`(JS/Rust): stay the same for the resulting header value\n - `Array`(JS)/`Vec\\`(Rust): Item are joined by \", \" for the resulting header value\n - `Object`(JS)/ `Hashmap\\`(Rust): Items are composed from: key + space + value. Item are then joined by \"; \" for the resulting header value", "type": "object", "properties": { "Access-Control-Allow-Credentials": { "description": "The Access-Control-Allow-Credentials response header tells browsers whether the\n server allows cross-origin HTTP requests to include credentials.\n\n See ", "anyOf": [ { "$ref": "#/definitions/HeaderSource" }, { "type": "null" } ] }, "Access-Control-Allow-Headers": { "description": "The Access-Control-Allow-Headers response header is used in response\n to a preflight request which includes the Access-Control-Request-Headers\n to indicate which HTTP headers can be used during the actual request.\n\n This header is required if the request has an Access-Control-Request-Headers header.\n\n See ", "anyOf": [ { "$ref": "#/definitions/HeaderSource" }, { "type": "null" } ] }, "Access-Control-Allow-Methods": { "description": "The Access-Control-Allow-Methods response header specifies one or more methods\n allowed when accessing a resource in response to a preflight request.\n\n See ", "anyOf": [ { "$ref": "#/definitions/HeaderSource" }, { "type": "null" } ] }, "Access-Control-Expose-Headers": { "description": "The Access-Control-Expose-Headers response header allows a server to indicate\n which response headers should be made available to scripts running in the browser,\n in response to a cross-origin request.\n\n See ", "anyOf": [ { "$ref": "#/definitions/HeaderSource" }, { "type": "null" } ] }, "Access-Control-Max-Age": { "description": "The Access-Control-Max-Age response header indicates how long the results of a\n preflight request (that is the information contained in the\n Access-Control-Allow-Methods and Access-Control-Allow-Headers headers) can\n be cached.\n\n See ", "anyOf": [ { "$ref": "#/definitions/HeaderSource" }, { "type": "null" } ] }, "Cross-Origin-Embedder-Policy": { "description": "The HTTP Cross-Origin-Embedder-Policy (COEP) response header configures embedding\n cross-origin resources into the document.\n\n See ", "anyOf": [ { "$ref": "#/definitions/HeaderSource" }, { "type": "null" } ] }, "Cross-Origin-Opener-Policy": { "description": "The HTTP Cross-Origin-Opener-Policy (COOP) response header allows you to ensure a\n top-level document does not share a browsing context group with cross-origin documents.\n COOP will process-isolate your document and potential attackers can't access your global\n object if they were to open it in a popup, preventing a set of cross-origin attacks dubbed XS-Leaks.\n\n See ", "anyOf": [ { "$ref": "#/definitions/HeaderSource" }, { "type": "null" } ] }, "Cross-Origin-Resource-Policy": { "description": "The HTTP Cross-Origin-Resource-Policy response header conveys a desire that the\n browser blocks no-cors cross-origin/cross-site requests to the given resource.\n\n See ", "anyOf": [ { "$ref": "#/definitions/HeaderSource" }, { "type": "null" } ] }, "Permissions-Policy": { "description": "The HTTP Permissions-Policy header provides a mechanism to allow and deny the\n use of browser features in a document or within any \\ elements in the document.\n\n See ", "anyOf": [ { "$ref": "#/definitions/HeaderSource" }, { "type": "null" } ] }, "Service-Worker-Allowed": { "description": "The HTTP Service-Worker-Allowed response header is used to broaden the path restriction for a\n service worker's default scope.\n\n By default, the scope for a service worker registration is the directory where the service\n worker script is located. For example, if the script `sw.js` is located in `/js/sw.js`,\n it can only control URLs under `/js/` by default. Servers can use the `Service-Worker-Allowed`\n header to allow a service worker to control URLs outside of its own directory.\n\n See ", "anyOf": [ { "$ref": "#/definitions/HeaderSource" }, { "type": "null" } ] }, "Timing-Allow-Origin": { "description": "The Timing-Allow-Origin response header specifies origins that are allowed to see values\n of attributes retrieved via features of the Resource Timing API, which would otherwise be\n reported as zero due to cross-origin restrictions.\n\n See ", "anyOf": [ { "$ref": "#/definitions/HeaderSource" }, { "type": "null" } ] }, "X-Content-Type-Options": { "description": "The X-Content-Type-Options response HTTP header is a marker used by the server to indicate\n that the MIME types advertised in the Content-Type headers should be followed and not be\n changed. The header allows you to avoid MIME type sniffing by saying that the MIME types\n are deliberately configured.\n\n See ", "anyOf": [ { "$ref": "#/definitions/HeaderSource" }, { "type": "null" } ] }, "Tauri-Custom-Header": { "description": "A custom header field Tauri-Custom-Header, don't use it.\n Remember to set Access-Control-Expose-Headers accordingly\n\n **NOT INTENDED FOR PRODUCTION USE**", "anyOf": [ { "$ref": "#/definitions/HeaderSource" }, { "type": "null" } ] } }, "additionalProperties": false }, "HeaderSource": { "description": "definition of a header source\n\n The header value to a header name", "anyOf": [ { "description": "string version of the header Value", "type": "string" }, { "description": "list version of the header value. Item are joined by \",\" for the real header value", "type": "array", "items": { "type": "string" } }, { "description": "(Rust struct | Json | JavaScript Object) equivalent of the header value. Items are composed from: key + space + value. Item are then joined by \";\" for the real header value", "type": "object", "additionalProperties": { "type": "string" } } ] }, "TrayIconConfig": { "description": "Configuration for application tray icon.\n\n See more: ", "type": "object", "required": [ "iconPath" ], "properties": { "id": { "description": "Set an id for this tray icon so you can reference it later, defaults to `main`.", "type": [ "string", "null" ] }, "iconPath": { "description": "Path to the default icon to use for the tray icon.\n\n Note: this stores the image in raw pixels to the final binary,\n so keep the icon size (width and height) small\n or else it's going to bloat your final executable", "type": "string" }, "iconAsTemplate": { "description": "A Boolean value that determines whether the image represents a [template](https://developer.apple.com/documentation/appkit/nsimage/1520017-template?language=objc) image on macOS.", "default": false, "type": "boolean" }, "menuOnLeftClick": { "description": "A Boolean value that determines whether the menu should appear when the tray icon receives a left click.\n\n ## Platform-specific:\n\n - **Linux**: Unsupported.", "default": true, "deprecated": true, "type": "boolean" }, "showMenuOnLeftClick": { "description": "A Boolean value that determines whether the menu should appear when the tray icon receives a left click.\n\n ## Platform-specific:\n\n - **Linux**: Unsupported.", "default": true, "type": "boolean" }, "title": { "description": "Title for MacOS tray", "type": [ "string", "null" ] }, "tooltip": { "description": "Tray icon tooltip on Windows and macOS", "type": [ "string", "null" ] } }, "additionalProperties": false }, "BuildConfig": { "description": "The Build configuration object.\n\n See more: ", "type": "object", "properties": { "runner": { "description": "The binary used to build and run the application.", "anyOf": [ { "$ref": "#/definitions/RunnerConfig" }, { "type": "null" } ] }, "devUrl": { "description": "The URL to load in development.\n\n This is usually an URL to a dev server, which serves your application assets with hot-reload and HMR.\n Most modern JavaScript bundlers like [Vite](https://vite.dev/guide/) provides a way to start a dev server by default.\n\n If you don't have a dev server or don't want to use one, ignore this option and use [`frontendDist`](BuildConfig::frontend_dist)\n and point to a web assets directory, and Tauri CLI will run its built-in dev server and provide a simple hot-reload experience.", "type": [ "string", "null" ], "format": "uri" }, "frontendDist": { "description": "The path to the application assets (usually the `dist` folder of your javascript bundler)\n or a URL that could be either a custom protocol registered in the tauri app (for example: `myprotocol://`)\n or a remote URL (for example: `https://site.com/app`).\n\n When a path relative to the configuration file is provided,\n it is read recursively and all files are embedded in the application binary.\n Tauri then looks for an `index.html` and serves it as the default entry point for your application.\n\n You can also provide a list of paths to be embedded, which allows granular control over what files are added to the binary.\n In this case, all files are added to the root and you must reference it that way in your HTML files.\n\n When a URL is provided, the application won't have bundled assets\n and the application will load that URL by default.", "anyOf": [ { "$ref": "#/definitions/FrontendDist" }, { "type": "null" } ] }, "beforeDevCommand": { "description": "A shell command to run before `tauri dev` kicks in.\n\n The TAURI_ENV_PLATFORM, TAURI_ENV_ARCH, TAURI_ENV_FAMILY, TAURI_ENV_PLATFORM_VERSION, TAURI_ENV_PLATFORM_TYPE and TAURI_ENV_DEBUG environment variables are set if you perform conditional compilation.", "anyOf": [ { "$ref": "#/definitions/BeforeDevCommand" }, { "type": "null" } ] }, "beforeBuildCommand": { "description": "A shell command to run before `tauri build` kicks in.\n\n The TAURI_ENV_PLATFORM, TAURI_ENV_ARCH, TAURI_ENV_FAMILY, TAURI_ENV_PLATFORM_VERSION, TAURI_ENV_PLATFORM_TYPE and TAURI_ENV_DEBUG environment variables are set if you perform conditional compilation.", "anyOf": [ { "$ref": "#/definitions/HookCommand" }, { "type": "null" } ] }, "beforeBundleCommand": { "description": "A shell command to run before the bundling phase in `tauri build` kicks in.\n\n The TAURI_ENV_PLATFORM, TAURI_ENV_ARCH, TAURI_ENV_FAMILY, TAURI_ENV_PLATFORM_VERSION, TAURI_ENV_PLATFORM_TYPE and TAURI_ENV_DEBUG environment variables are set if you perform conditional compilation.", "anyOf": [ { "$ref": "#/definitions/HookCommand" }, { "type": "null" } ] }, "features": { "description": "Features passed to `cargo` commands.", "type": [ "array", "null" ], "items": { "type": "string" } }, "removeUnusedCommands": { "description": "Try to remove unused commands registered from plugins base on the ACL list during `tauri build`,\n the way it works is that tauri-cli will read this and set the environment variables for the build script and macros,\n and they'll try to get all the allowed commands and remove the rest\n\n Note:\n - This won't be accounting for dynamically added ACLs when you use features from the `dynamic-acl` (currently enabled by default) feature flag, so make sure to check it when using this\n - This feature requires tauri-plugin 2.1 and tauri 2.4", "default": false, "type": "boolean" }, "additionalWatchFolders": { "description": "Additional paths to watch for changes when running `tauri dev`.", "default": [], "type": "array", "items": { "type": "string" } } }, "additionalProperties": false }, "RunnerConfig": { "description": "The runner configuration.", "anyOf": [ { "description": "A string specifying the binary to run.", "type": "string" }, { "description": "An object with advanced configuration options.", "type": "object", "required": [ "cmd" ], "properties": { "cmd": { "description": "The binary to run.", "type": "string" }, "cwd": { "description": "The current working directory to run the command from.", "type": [ "string", "null" ] }, "args": { "description": "Arguments to pass to the command.", "type": [ "array", "null" ], "items": { "type": "string" } } } } ] }, "FrontendDist": { "description": "Defines the URL or assets to embed in the application.", "anyOf": [ { "description": "An external URL that should be used as the default application URL. No assets are embedded in the app in this case.", "type": "string", "format": "uri" }, { "description": "Path to a directory containing the frontend dist assets.", "type": "string" }, { "description": "An array of files to embed in the app.", "type": "array", "items": { "type": "string" } } ] }, "BeforeDevCommand": { "description": "Describes the shell command to run before `tauri dev`.", "anyOf": [ { "description": "Run the given script with the default options.", "type": "string" }, { "description": "Run the given script with custom options.", "type": "object", "required": [ "script" ], "properties": { "script": { "description": "The script to execute.", "type": "string" }, "cwd": { "description": "The current working directory.", "type": [ "string", "null" ] }, "wait": { "description": "Whether `tauri dev` should wait for the command to finish or not. Defaults to `false`.", "default": false, "type": "boolean" } } } ] }, "HookCommand": { "description": "Describes a shell command to be executed when a CLI hook is triggered.", "anyOf": [ { "description": "Run the given script with the default options.", "type": "string" }, { "description": "Run the given script with custom options.", "type": "object", "required": [ "script" ], "properties": { "script": { "description": "The script to execute.", "type": "string" }, "cwd": { "description": "The current working directory.", "type": [ "string", "null" ] } } } ] }, "BundleConfig": { "description": "Configuration for tauri-bundler.\n\n See more: ", "type": "object", "properties": { "active": { "description": "Whether Tauri should bundle your application or just output the executable.", "default": false, "type": "boolean" }, "targets": { "description": "The bundle targets, currently supports [\"deb\", \"rpm\", \"appimage\", \"nsis\", \"msi\", \"app\", \"dmg\"] or \"all\".", "default": "all", "allOf": [ { "$ref": "#/definitions/BundleTarget" } ] }, "createUpdaterArtifacts": { "description": "Produce updaters and their signatures or not", "default": false, "allOf": [ { "$ref": "#/definitions/Updater" } ] }, "publisher": { "description": "The application's publisher. Defaults to the second element in the identifier string.\n\n Currently maps to the Manufacturer property of the Windows Installer\n and the Maintainer field of debian packages if the Cargo.toml does not have the authors field.", "type": [ "string", "null" ] }, "homepage": { "description": "A url to the home page of your application. If unset, will\n fallback to `homepage` defined in `Cargo.toml`.\n\n Supported bundle targets: `deb`, `rpm`, `nsis` and `msi`.", "type": [ "string", "null" ] }, "icon": { "description": "The app's icons", "default": [], "type": "array", "items": { "type": "string" } }, "resources": { "description": "App resources to bundle.\n Each resource is a path to a file or directory.\n Glob patterns are supported.\n\n ## Examples\n\n To include a list of files:\n\n ```json\n {\n \"bundle\": {\n \"resources\": [\n \"./path/to/some-file.txt\",\n \"/absolute/path/to/textfile.txt\",\n \"../relative/path/to/jsonfile.json\",\n \"some-folder/\",\n \"resources/**/*.md\"\n ]\n }\n }\n ```\n\n The bundled files will be in `$RESOURCES/` with the original directory structure preserved,\n for example: `./path/to/some-file.txt` -> `$RESOURCE/path/to/some-file.txt`\n\n To fine control where the files will get copied to, use a map instead\n\n ```json\n {\n \"bundle\": {\n \"resources\": {\n \"/absolute/path/to/textfile.txt\": \"resources/textfile.txt\",\n \"relative/path/to/jsonfile.json\": \"resources/jsonfile.json\",\n \"resources/\": \"\",\n \"docs/**/*md\": \"website-docs/\"\n }\n }\n }\n ```\n\n Note that when using glob pattern in this case, the original directory structure is not preserved,\n everything gets copied to the target directory directly\n\n See more: ", "anyOf": [ { "$ref": "#/definitions/BundleResources" }, { "type": "null" } ] }, "copyright": { "description": "A copyright string associated with your application.", "type": [ "string", "null" ] }, "license": { "description": "The package's license identifier to be included in the appropriate bundles.\n If not set, defaults to the license from the Cargo.toml file.", "type": [ "string", "null" ] }, "licenseFile": { "description": "The path to the license file to be included in the appropriate bundles.", "type": [ "string", "null" ] }, "category": { "description": "The application kind.\n\n Should be one of the following:\n Business, DeveloperTool, Education, Entertainment, Finance, Game, ActionGame, AdventureGame, ArcadeGame, BoardGame, CardGame, CasinoGame, DiceGame, EducationalGame, FamilyGame, KidsGame, MusicGame, PuzzleGame, RacingGame, RolePlayingGame, SimulationGame, SportsGame, StrategyGame, TriviaGame, WordGame, GraphicsAndDesign, HealthcareAndFitness, Lifestyle, Medical, Music, News, Photography, Productivity, Reference, SocialNetworking, Sports, Travel, Utility, Video, Weather.", "type": [ "string", "null" ] }, "fileAssociations": { "description": "File types to associate with the application.", "type": [ "array", "null" ], "items": { "$ref": "#/definitions/FileAssociation" } }, "shortDescription": { "description": "A short description of your application.", "type": [ "string", "null" ] }, "longDescription": { "description": "A longer, multi-line description of the application.", "type": [ "string", "null" ] }, "useLocalToolsDir": { "description": "Whether to use the project's `target` directory, for caching build tools (e.g., Wix and NSIS) when building this application. Defaults to `false`.\n\n If true, tools will be cached in `target/.tauri/`.\n If false, tools will be cached in the current user's platform-specific cache directory.\n\n An example where it can be appropriate to set this to `true` is when building this application as a Windows System user (e.g., AWS EC2 workloads),\n because the Window system's app data directory is restricted.", "default": false, "type": "boolean" }, "externalBin": { "description": "A list of—either absolute or relative—paths to binaries to embed with your application.\n\n Note that Tauri will look for system-specific binaries following the pattern \"binary-name{-target-triple}{.system-extension}\".\n\n E.g. for the external binary \"my-binary\", Tauri looks for:\n\n - \"my-binary-x86_64-pc-windows-msvc.exe\" for Windows\n - \"my-binary-x86_64-apple-darwin\" for macOS\n - \"my-binary-x86_64-unknown-linux-gnu\" for Linux\n\n so don't forget to provide binaries for all targeted platforms.", "type": [ "array", "null" ], "items": { "type": "string" } }, "windows": { "description": "Configuration for the Windows bundles.", "default": { "allowDowngrades": true, "certificateThumbprint": null, "digestAlgorithm": null, "nsis": null, "signCommand": null, "timestampUrl": null, "tsp": false, "webviewInstallMode": { "silent": true, "type": "downloadBootstrapper" }, "wix": null }, "allOf": [ { "$ref": "#/definitions/WindowsConfig" } ] }, "linux": { "description": "Configuration for the Linux bundles.", "default": { "appimage": { "bundleMediaFramework": false, "files": {} }, "deb": { "files": {} }, "rpm": { "epoch": 0, "files": {}, "release": "1" } }, "allOf": [ { "$ref": "#/definitions/LinuxConfig" } ] }, "macOS": { "description": "Configuration for the macOS bundles.", "default": { "dmg": { "appPosition": { "x": 180, "y": 170 }, "applicationFolderPosition": { "x": 480, "y": 170 }, "windowSize": { "height": 400, "width": 660 } }, "files": {}, "hardenedRuntime": true, "minimumSystemVersion": "10.13" }, "allOf": [ { "$ref": "#/definitions/MacConfig" } ] }, "iOS": { "description": "iOS configuration.", "default": { "minimumSystemVersion": "14.0" }, "allOf": [ { "$ref": "#/definitions/IosConfig" } ] }, "android": { "description": "Android configuration.", "default": { "autoIncrementVersionCode": false, "minSdkVersion": 24 }, "allOf": [ { "$ref": "#/definitions/AndroidConfig" } ] } }, "additionalProperties": false }, "BundleTarget": { "description": "Targets to bundle. Each value is case insensitive.", "anyOf": [ { "description": "Bundle all targets.", "const": "all" }, { "description": "A list of bundle targets.", "type": "array", "items": { "$ref": "#/definitions/BundleType" } }, { "description": "A single bundle target.", "allOf": [ { "$ref": "#/definitions/BundleType" } ] } ] }, "BundleType": { "description": "A bundle referenced by tauri-bundler.", "oneOf": [ { "description": "The debian bundle (.deb).", "type": "string", "enum": [ "deb" ] }, { "description": "The RPM bundle (.rpm).", "type": "string", "enum": [ "rpm" ] }, { "description": "The AppImage bundle (.appimage).", "type": "string", "enum": [ "appimage" ] }, { "description": "The Microsoft Installer bundle (.msi).", "type": "string", "enum": [ "msi" ] }, { "description": "The NSIS bundle (.exe).", "type": "string", "enum": [ "nsis" ] }, { "description": "The macOS application bundle (.app).", "type": "string", "enum": [ "app" ] }, { "description": "The Apple Disk Image bundle (.dmg).", "type": "string", "enum": [ "dmg" ] } ] }, "Updater": { "description": "Updater type", "anyOf": [ { "description": "Generates legacy zipped v1 compatible updaters", "allOf": [ { "$ref": "#/definitions/V1Compatible" } ] }, { "description": "Produce updaters and their signatures or not", "type": "boolean" } ] }, "V1Compatible": { "description": "Generates legacy zipped v1 compatible updaters", "oneOf": [ { "description": "Generates legacy zipped v1 compatible updaters", "type": "string", "enum": [ "v1Compatible" ] } ] }, "BundleResources": { "description": "Definition for bundle resources.\n Can be either a list of paths to include or a map of source to target paths.", "anyOf": [ { "description": "A list of paths to include.", "type": "array", "items": { "type": "string" } }, { "description": "A map of source to target paths.", "type": "object", "additionalProperties": { "type": "string" } } ] }, "FileAssociation": { "description": "File association", "type": "object", "required": [ "ext" ], "properties": { "ext": { "description": "File extensions to associate with this app. e.g. 'png'", "type": "array", "items": { "$ref": "#/definitions/AssociationExt" } }, "contentTypes": { "description": "Declare support to a file with the given content type. Maps to `LSItemContentTypes` on macOS.\n\n This allows supporting any file format declared by another application that conforms to this type.\n Declaration of new types can be done with [`Self::exported_type`] and linking to certain content types are done via [`ExportedFileAssociation::conforms_to`].", "type": [ "array", "null" ], "items": { "type": "string" } }, "name": { "description": "The name. Maps to `CFBundleTypeName` on macOS. Default to `ext[0]`", "type": [ "string", "null" ] }, "description": { "description": "The association description. Windows-only. It is displayed on the `Type` column on Windows Explorer.", "type": [ "string", "null" ] }, "role": { "description": "The app's role with respect to the type. Maps to `CFBundleTypeRole` on macOS.", "default": "Editor", "allOf": [ { "$ref": "#/definitions/BundleTypeRole" } ] }, "mimeType": { "description": "The mime-type e.g. 'image/png' or 'text/plain'. Linux-only.", "type": [ "string", "null" ] }, "rank": { "description": "The ranking of this app among apps that declare themselves as editors or viewers of the given file type. Maps to `LSHandlerRank` on macOS.", "default": "Default", "allOf": [ { "$ref": "#/definitions/HandlerRank" } ] }, "exportedType": { "description": "The exported type definition. Maps to a `UTExportedTypeDeclarations` entry on macOS.\n\n You should define this if the associated file is a custom file type defined by your application.", "anyOf": [ { "$ref": "#/definitions/ExportedFileAssociation" }, { "type": "null" } ] } }, "additionalProperties": false }, "AssociationExt": { "description": "An extension for a [`FileAssociation`].\n\n A leading `.` is automatically stripped.", "type": "string" }, "BundleTypeRole": { "description": "macOS-only. Corresponds to CFBundleTypeRole", "oneOf": [ { "description": "CFBundleTypeRole.Editor. Files can be read and edited.", "type": "string", "enum": [ "Editor" ] }, { "description": "CFBundleTypeRole.Viewer. Files can be read.", "type": "string", "enum": [ "Viewer" ] }, { "description": "CFBundleTypeRole.Shell", "type": "string", "enum": [ "Shell" ] }, { "description": "CFBundleTypeRole.QLGenerator", "type": "string", "enum": [ "QLGenerator" ] }, { "description": "CFBundleTypeRole.None", "type": "string", "enum": [ "None" ] } ] }, "HandlerRank": { "description": "Corresponds to LSHandlerRank", "oneOf": [ { "description": "LSHandlerRank.Default. This app is an opener of files of this type; this value is also used if no rank is specified.", "type": "string", "enum": [ "Default" ] }, { "description": "LSHandlerRank.Owner. This app is the primary creator of files of this type.", "type": "string", "enum": [ "Owner" ] }, { "description": "LSHandlerRank.Alternate. This app is a secondary viewer of files of this type.", "type": "string", "enum": [ "Alternate" ] }, { "description": "LSHandlerRank.None. This app is never selected to open files of this type, but it accepts drops of files of this type.", "type": "string", "enum": [ "None" ] } ] }, "ExportedFileAssociation": { "description": "The exported type definition. Maps to a `UTExportedTypeDeclarations` entry on macOS.", "type": "object", "required": [ "identifier" ], "properties": { "identifier": { "description": "The unique identifier for the exported type. Maps to `UTTypeIdentifier`.", "type": "string" }, "conformsTo": { "description": "The types that this type conforms to. Maps to `UTTypeConformsTo`.\n\n Examples are `public.data`, `public.image`, `public.json` and `public.database`.", "type": [ "array", "null" ], "items": { "type": "string" } } }, "additionalProperties": false }, "WindowsConfig": { "description": "Windows bundler configuration.\n\n See more: ", "type": "object", "properties": { "digestAlgorithm": { "description": "Specifies the file digest algorithm to use for creating file signatures.\n Required for code signing. SHA-256 is recommended.", "type": [ "string", "null" ] }, "certificateThumbprint": { "description": "Specifies the SHA1 hash of the signing certificate.", "type": [ "string", "null" ] }, "timestampUrl": { "description": "Server to use during timestamping.", "type": [ "string", "null" ] }, "tsp": { "description": "Whether to use Time-Stamp Protocol (TSP, a.k.a. RFC 3161) for the timestamp server. Your code signing provider may\n use a TSP timestamp server, like e.g. SSL.com does. If so, enable TSP by setting to true.", "default": false, "type": "boolean" }, "webviewInstallMode": { "description": "The installation mode for the Webview2 runtime.", "default": { "silent": true, "type": "downloadBootstrapper" }, "allOf": [ { "$ref": "#/definitions/WebviewInstallMode" } ] }, "allowDowngrades": { "description": "Validates a second app installation, blocking the user from installing an older version if set to `false`.\n\n For instance, if `1.2.1` is installed, the user won't be able to install app version `1.2.0` or `1.1.5`.\n\n The default value of this flag is `true`.", "default": true, "type": "boolean" }, "wix": { "description": "Configuration for the MSI generated with WiX.", "anyOf": [ { "$ref": "#/definitions/WixConfig" }, { "type": "null" } ] }, "nsis": { "description": "Configuration for the installer generated with NSIS.", "anyOf": [ { "$ref": "#/definitions/NsisConfig" }, { "type": "null" } ] }, "signCommand": { "description": "Specify a custom command to sign the binaries.\n This command needs to have a `%1` in args which is just a placeholder for the binary path,\n which we will detect and replace before calling the command.\n\n By Default we use `signtool.exe` which can be found only on Windows so\n if you are on another platform and want to cross-compile and sign you will\n need to use another tool like `osslsigncode`.", "anyOf": [ { "$ref": "#/definitions/CustomSignCommandConfig" }, { "type": "null" } ] } }, "additionalProperties": false }, "WebviewInstallMode": { "description": "Install modes for the Webview2 runtime.\n Note that for the updater bundle [`Self::DownloadBootstrapper`] is used.\n\n For more information see .", "oneOf": [ { "description": "Do not install the Webview2 as part of the Windows Installer.", "type": "object", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "skip" ] } }, "additionalProperties": false }, { "description": "Download the bootstrapper and run it.\n Requires an internet connection.\n Results in a smaller installer size, but is not recommended on Windows 7.", "type": "object", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "downloadBootstrapper" ] }, "silent": { "description": "Instructs the installer to run the bootstrapper in silent mode. Defaults to `true`.", "default": true, "type": "boolean" } }, "additionalProperties": false }, { "description": "Embed the bootstrapper and run it.\n Requires an internet connection.\n Increases the installer size by around 1.8MB, but offers better support on Windows 7.", "type": "object", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "embedBootstrapper" ] }, "silent": { "description": "Instructs the installer to run the bootstrapper in silent mode. Defaults to `true`.", "default": true, "type": "boolean" } }, "additionalProperties": false }, { "description": "Embed the offline installer and run it.\n Does not require an internet connection.\n Increases the installer size by around 127MB.", "type": "object", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "offlineInstaller" ] }, "silent": { "description": "Instructs the installer to run the installer in silent mode. Defaults to `true`.", "default": true, "type": "boolean" } }, "additionalProperties": false }, { "description": "Embed a fixed webview2 version and use it at runtime.\n Increases the installer size by around 180MB.", "type": "object", "required": [ "path", "type" ], "properties": { "type": { "type": "string", "enum": [ "fixedRuntime" ] }, "path": { "description": "The path to the fixed runtime to use.\n\n The fixed version can be downloaded [on the official website](https://developer.microsoft.com/en-us/microsoft-edge/webview2/#download-section).\n The `.cab` file must be extracted to a folder and this folder path must be defined on this field.", "type": "string" } }, "additionalProperties": false } ] }, "WixConfig": { "description": "Configuration for the MSI bundle using WiX.\n\n See more: ", "type": "object", "properties": { "version": { "description": "MSI installer version in the format `major.minor.patch.build` (build is optional).\n\n Because a valid version is required for MSI installer, it will be derived from [`Config::version`] if this field is not set.\n\n The first field is the major version and has a maximum value of 255. The second field is the minor version and has a maximum value of 255.\n The third and fourth fields have a maximum value of 65,535.\n\n See for more info.", "type": [ "string", "null" ] }, "upgradeCode": { "description": "A GUID upgrade code for MSI installer. This code **_must stay the same across all of your updates_**,\n otherwise, Windows will treat your update as a different app and your users will have duplicate versions of your app.\n\n By default, tauri generates this code by generating a Uuid v5 using the string `.exe.app.x64` in the DNS namespace.\n You can use Tauri's CLI to generate and print this code for you, run `tauri inspect wix-upgrade-code`.\n\n It is recommended that you set this value in your tauri config file to avoid accidental changes in your upgrade code\n whenever you want to change your product name.", "type": [ "string", "null" ], "format": "uuid" }, "language": { "description": "The installer languages to build. See .", "default": "en-US", "allOf": [ { "$ref": "#/definitions/WixLanguage" } ] }, "template": { "description": "A custom .wxs template to use.", "type": [ "string", "null" ] }, "fragmentPaths": { "description": "A list of paths to .wxs files with WiX fragments to use.", "default": [], "type": "array", "items": { "type": "string" } }, "componentGroupRefs": { "description": "The ComponentGroup element ids you want to reference from the fragments.", "default": [], "type": "array", "items": { "type": "string" } }, "componentRefs": { "description": "The Component element ids you want to reference from the fragments.", "default": [], "type": "array", "items": { "type": "string" } }, "featureGroupRefs": { "description": "The FeatureGroup element ids you want to reference from the fragments.", "default": [], "type": "array", "items": { "type": "string" } }, "featureRefs": { "description": "The Feature element ids you want to reference from the fragments.", "default": [], "type": "array", "items": { "type": "string" } }, "mergeRefs": { "description": "The Merge element ids you want to reference from the fragments.", "default": [], "type": "array", "items": { "type": "string" } }, "enableElevatedUpdateTask": { "description": "Create an elevated update task within Windows Task Scheduler.", "default": false, "type": "boolean" }, "bannerPath": { "description": "Path to a bitmap file to use as the installation user interface banner.\n This bitmap will appear at the top of all but the first page of the installer.\n\n The required dimensions are 493px × 58px.", "type": [ "string", "null" ] }, "dialogImagePath": { "description": "Path to a bitmap file to use on the installation user interface dialogs.\n It is used on the welcome and completion dialogs.\n\n The required dimensions are 493px × 312px.", "type": [ "string", "null" ] }, "fipsCompliant": { "description": "Enables FIPS compliant algorithms.\n Can also be enabled via the `TAURI_BUNDLER_WIX_FIPS_COMPLIANT` env var.", "default": false, "type": "boolean" } }, "additionalProperties": false }, "WixLanguage": { "description": "The languages to build using WiX.", "anyOf": [ { "description": "A single language to build, without configuration.", "type": "string" }, { "description": "A list of languages to build, without configuration.", "type": "array", "items": { "type": "string" } }, { "description": "A map of languages and its configuration.", "type": "object", "additionalProperties": { "$ref": "#/definitions/WixLanguageConfig" } } ] }, "WixLanguageConfig": { "description": "Configuration for a target language for the WiX build.\n\n See more: ", "type": "object", "properties": { "localePath": { "description": "The path to a locale (`.wxl`) file. See .", "type": [ "string", "null" ] } }, "additionalProperties": false }, "NsisConfig": { "description": "Configuration for the Installer bundle using NSIS.", "type": "object", "properties": { "template": { "description": "A custom .nsi template to use.", "type": [ "string", "null" ] }, "headerImage": { "description": "The path to a bitmap file to display on the header of installers pages.\n\n The recommended dimensions are 150px x 57px.", "type": [ "string", "null" ] }, "sidebarImage": { "description": "The path to a bitmap file for the Welcome page and the Finish page.\n\n The recommended dimensions are 164px x 314px.", "type": [ "string", "null" ] }, "installerIcon": { "description": "The path to an icon file used as the installer icon.", "type": [ "string", "null" ] }, "installMode": { "description": "Whether the installation will be for all users or just the current user.", "default": "currentUser", "allOf": [ { "$ref": "#/definitions/NSISInstallerMode" } ] }, "languages": { "description": "A list of installer languages.\n By default the OS language is used. If the OS language is not in the list of languages, the first language will be used.\n To allow the user to select the language, set `display_language_selector` to `true`.\n\n See for the complete list of languages.", "type": [ "array", "null" ], "items": { "type": "string" } }, "customLanguageFiles": { "description": "A key-value pair where the key is the language and the\n value is the path to a custom `.nsh` file that holds the translated text for tauri's custom messages.\n\n See for an example `.nsh` file.\n\n **Note**: the key must be a valid NSIS language and it must be added to [`NsisConfig`] languages array,", "type": [ "object", "null" ], "additionalProperties": { "type": "string" } }, "displayLanguageSelector": { "description": "Whether to display a language selector dialog before the installer and uninstaller windows are rendered or not.\n By default the OS language is selected, with a fallback to the first language in the `languages` array.", "default": false, "type": "boolean" }, "compression": { "description": "Set the compression algorithm used to compress files in the installer.\n\n See ", "default": "lzma", "allOf": [ { "$ref": "#/definitions/NsisCompression" } ] }, "startMenuFolder": { "description": "Set the folder name for the start menu shortcut.\n\n Use this option if you have multiple apps and wish to group their shortcuts under one folder\n or if you generally prefer to set your shortcut inside a folder.\n\n Examples:\n - `AwesomePublisher`, shortcut will be placed in `%AppData%\\Microsoft\\Windows\\Start Menu\\Programs\\AwesomePublisher\\.lnk`\n - If unset, shortcut will be placed in `%AppData%\\Microsoft\\Windows\\Start Menu\\Programs\\.lnk`", "type": [ "string", "null" ] }, "installerHooks": { "description": "A path to a `.nsh` file that contains special NSIS macros to be hooked into the\n main installer.nsi script.\n\n Supported hooks are:\n\n - `NSIS_HOOK_PREINSTALL`: This hook runs before copying files, setting registry key values and creating shortcuts.\n - `NSIS_HOOK_POSTINSTALL`: This hook runs after the installer has finished copying all files, setting the registry keys and created shortcuts.\n - `NSIS_HOOK_PREUNINSTALL`: This hook runs before removing any files, registry keys and shortcuts.\n - `NSIS_HOOK_POSTUNINSTALL`: This hook runs after files, registry keys and shortcuts have been removed.\n\n ### Example\n\n ```nsh\n !macro NSIS_HOOK_PREINSTALL\n MessageBox MB_OK \"PreInstall\"\n !macroend\n\n !macro NSIS_HOOK_POSTINSTALL\n MessageBox MB_OK \"PostInstall\"\n !macroend\n\n !macro NSIS_HOOK_PREUNINSTALL\n MessageBox MB_OK \"PreUnInstall\"\n !macroend\n\n !macro NSIS_HOOK_POSTUNINSTALL\n MessageBox MB_OK \"PostUninstall\"\n !macroend\n ```", "type": [ "string", "null" ] }, "minimumWebview2Version": { "description": "Try to ensure that the WebView2 version is equal to or newer than this version,\n if the user's WebView2 is older than this version,\n the installer will try to trigger a WebView2 update.", "type": [ "string", "null" ] } }, "additionalProperties": false }, "NSISInstallerMode": { "description": "Install Modes for the NSIS installer.", "oneOf": [ { "description": "Default mode for the installer.\n\n Install the app by default in a directory that doesn't require Administrator access.\n\n Installer metadata will be saved under the `HKCU` registry path.", "type": "string", "enum": [ "currentUser" ] }, { "description": "Install the app by default in the `Program Files` folder directory requires Administrator\n access for the installation.\n\n Installer metadata will be saved under the `HKLM` registry path.", "type": "string", "enum": [ "perMachine" ] }, { "description": "Combines both modes and allows the user to choose at install time\n whether to install for the current user or per machine. Note that this mode\n will require Administrator access even if the user wants to install it for the current user only.\n\n Installer metadata will be saved under the `HKLM` or `HKCU` registry path based on the user's choice.", "type": "string", "enum": [ "both" ] } ] }, "NsisCompression": { "description": "Compression algorithms used in the NSIS installer.\n\n See ", "oneOf": [ { "description": "ZLIB uses the deflate algorithm, it is a quick and simple method. With the default compression level it uses about 300 KB of memory.", "type": "string", "enum": [ "zlib" ] }, { "description": "BZIP2 usually gives better compression ratios than ZLIB, but it is a bit slower and uses more memory. With the default compression level it uses about 4 MB of memory.", "type": "string", "enum": [ "bzip2" ] }, { "description": "LZMA (default) is a new compression method that gives very good compression ratios. The decompression speed is high (10-20 MB/s on a 2 GHz CPU), the compression speed is lower. The memory size that will be used for decompression is the dictionary size plus a few KBs, the default is 8 MB.", "type": "string", "enum": [ "lzma" ] }, { "description": "Disable compression", "type": "string", "enum": [ "none" ] } ] }, "CustomSignCommandConfig": { "description": "Custom Signing Command configuration.", "anyOf": [ { "description": "A string notation of the script to execute.\n\n \"%1\" will be replaced with the path to the binary to be signed.\n\n This is a simpler notation for the command.\n Tauri will split the string with `' '` and use the first element as the command name and the rest as arguments.\n\n If you need to use whitespace in the command or arguments, use the object notation [`Self::CommandWithOptions`].", "type": "string" }, { "description": "An object notation of the command.\n\n This is more complex notation for the command but\n this allows you to use whitespace in the command and arguments.", "type": "object", "required": [ "args", "cmd" ], "properties": { "cmd": { "description": "The command to run to sign the binary.", "type": "string" }, "args": { "description": "The arguments to pass to the command.\n\n \"%1\" will be replaced with the path to the binary to be signed.", "type": "array", "items": { "type": "string" } } }, "additionalProperties": false } ] }, "LinuxConfig": { "description": "Configuration for Linux bundles.\n\n See more: ", "type": "object", "properties": { "appimage": { "description": "Configuration for the AppImage bundle.", "default": { "bundleMediaFramework": false, "files": {} }, "allOf": [ { "$ref": "#/definitions/AppImageConfig" } ] }, "deb": { "description": "Configuration for the Debian bundle.", "default": { "files": {} }, "allOf": [ { "$ref": "#/definitions/DebConfig" } ] }, "rpm": { "description": "Configuration for the RPM bundle.", "default": { "epoch": 0, "files": {}, "release": "1" }, "allOf": [ { "$ref": "#/definitions/RpmConfig" } ] } }, "additionalProperties": false }, "AppImageConfig": { "description": "Configuration for AppImage bundles.\n\n See more: ", "type": "object", "properties": { "bundleMediaFramework": { "description": "Include additional gstreamer dependencies needed for audio and video playback.\n This increases the bundle size by ~15-35MB depending on your build system.", "default": false, "type": "boolean" }, "files": { "description": "The files to include in the Appimage Binary.", "default": {}, "type": "object", "additionalProperties": { "type": "string" } } }, "additionalProperties": false }, "DebConfig": { "description": "Configuration for Debian (.deb) bundles.\n\n See more: ", "type": "object", "properties": { "depends": { "description": "The list of deb dependencies your application relies on.", "type": [ "array", "null" ], "items": { "type": "string" } }, "recommends": { "description": "The list of deb dependencies your application recommends.", "type": [ "array", "null" ], "items": { "type": "string" } }, "provides": { "description": "The list of dependencies the package provides.", "type": [ "array", "null" ], "items": { "type": "string" } }, "conflicts": { "description": "The list of package conflicts.", "type": [ "array", "null" ], "items": { "type": "string" } }, "replaces": { "description": "The list of package replaces.", "type": [ "array", "null" ], "items": { "type": "string" } }, "files": { "description": "The files to include on the package.", "default": {}, "type": "object", "additionalProperties": { "type": "string" } }, "section": { "description": "Define the section in Debian Control file. See : https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections", "type": [ "string", "null" ] }, "priority": { "description": "Change the priority of the Debian Package. By default, it is set to `optional`.\n Recognized Priorities as of now are : `required`, `important`, `standard`, `optional`, `extra`", "type": [ "string", "null" ] }, "changelog": { "description": "Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See\n ", "type": [ "string", "null" ] }, "desktopTemplate": { "description": "Path to a custom desktop file Handlebars template.\n\n Available variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.", "type": [ "string", "null" ] }, "preInstallScript": { "description": "Path to script that will be executed before the package is unpacked. See\n ", "type": [ "string", "null" ] }, "postInstallScript": { "description": "Path to script that will be executed after the package is unpacked. See\n ", "type": [ "string", "null" ] }, "preRemoveScript": { "description": "Path to script that will be executed before the package is removed. See\n ", "type": [ "string", "null" ] }, "postRemoveScript": { "description": "Path to script that will be executed after the package is removed. See\n ", "type": [ "string", "null" ] } }, "additionalProperties": false }, "RpmConfig": { "description": "Configuration for RPM bundles.", "type": "object", "properties": { "depends": { "description": "The list of RPM dependencies your application relies on.", "type": [ "array", "null" ], "items": { "type": "string" } }, "recommends": { "description": "The list of RPM dependencies your application recommends.", "type": [ "array", "null" ], "items": { "type": "string" } }, "provides": { "description": "The list of RPM dependencies your application provides.", "type": [ "array", "null" ], "items": { "type": "string" } }, "conflicts": { "description": "The list of RPM dependencies your application conflicts with. They must not be present\n in order for the package to be installed.", "type": [ "array", "null" ], "items": { "type": "string" } }, "obsoletes": { "description": "The list of RPM dependencies your application supersedes - if this package is installed,\n packages listed as \"obsoletes\" will be automatically removed (if they are present).", "type": [ "array", "null" ], "items": { "type": "string" } }, "release": { "description": "The RPM release tag.", "default": "1", "type": "string" }, "epoch": { "description": "The RPM epoch.", "default": 0, "type": "integer", "format": "uint32", "minimum": 0.0 }, "files": { "description": "The files to include on the package.", "default": {}, "type": "object", "additionalProperties": { "type": "string" } }, "desktopTemplate": { "description": "Path to a custom desktop file Handlebars template.\n\n Available variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.", "type": [ "string", "null" ] }, "preInstallScript": { "description": "Path to script that will be executed before the package is unpacked. See\n ", "type": [ "string", "null" ] }, "postInstallScript": { "description": "Path to script that will be executed after the package is unpacked. See\n ", "type": [ "string", "null" ] }, "preRemoveScript": { "description": "Path to script that will be executed before the package is removed. See\n ", "type": [ "string", "null" ] }, "postRemoveScript": { "description": "Path to script that will be executed after the package is removed. See\n ", "type": [ "string", "null" ] }, "compression": { "description": "Compression algorithm and level. Defaults to `Gzip` with level 6.", "anyOf": [ { "$ref": "#/definitions/RpmCompression" }, { "type": "null" } ] } }, "additionalProperties": false }, "RpmCompression": { "description": "Compression algorithms used when bundling RPM packages.", "oneOf": [ { "description": "Gzip compression", "type": "object", "required": [ "level", "type" ], "properties": { "type": { "type": "string", "enum": [ "gzip" ] }, "level": { "description": "Gzip compression level", "type": "integer", "format": "uint32", "minimum": 0.0 } }, "additionalProperties": false }, { "description": "Zstd compression", "type": "object", "required": [ "level", "type" ], "properties": { "type": { "type": "string", "enum": [ "zstd" ] }, "level": { "description": "Zstd compression level", "type": "integer", "format": "int32" } }, "additionalProperties": false }, { "description": "Xz compression", "type": "object", "required": [ "level", "type" ], "properties": { "type": { "type": "string", "enum": [ "xz" ] }, "level": { "description": "Xz compression level", "type": "integer", "format": "uint32", "minimum": 0.0 } }, "additionalProperties": false }, { "description": "Bzip2 compression", "type": "object", "required": [ "level", "type" ], "properties": { "type": { "type": "string", "enum": [ "bzip2" ] }, "level": { "description": "Bzip2 compression level", "type": "integer", "format": "uint32", "minimum": 0.0 } }, "additionalProperties": false }, { "description": "Disable compression", "type": "object", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "none" ] } }, "additionalProperties": false } ] }, "MacConfig": { "description": "Configuration for the macOS bundles.\n\n See more: ", "type": "object", "properties": { "frameworks": { "description": "A list of strings indicating any macOS X frameworks that need to be bundled with the application.\n\n If a name is used, \".framework\" must be omitted and it will look for standard install locations. You may also use a path to a specific framework.", "type": [ "array", "null" ], "items": { "type": "string" } }, "files": { "description": "The files to include in the application relative to the Contents directory.", "default": {}, "type": "object", "additionalProperties": { "type": "string" } }, "bundleVersion": { "description": "The version of the build that identifies an iteration of the bundle.\n\n Translates to the bundle's CFBundleVersion property.", "type": [ "string", "null" ] }, "bundleName": { "description": "The name of the builder that built the bundle.\n\n Translates to the bundle's CFBundleName property.\n\n If not set, defaults to the package's product name.", "type": [ "string", "null" ] }, "minimumSystemVersion": { "description": "A version string indicating the minimum macOS X version that the bundled application supports. Defaults to `10.13`.\n\n Setting it to `null` completely removes the `LSMinimumSystemVersion` field on the bundle's `Info.plist`\n and the `MACOSX_DEPLOYMENT_TARGET` environment variable.\n\n Ignored in `tauri dev`.\n\n An empty string is considered an invalid value so the default value is used.", "default": "10.13", "type": [ "string", "null" ] }, "exceptionDomain": { "description": "Allows your application to communicate with the outside world.\n It should be a lowercase, without port and protocol domain name.", "type": [ "string", "null" ] }, "signingIdentity": { "description": "Identity to use for code signing.", "type": [ "string", "null" ] }, "hardenedRuntime": { "description": "Whether the codesign should enable [hardened runtime](https://developer.apple.com/documentation/security/hardened_runtime) (for executables) or not.", "default": true, "type": "boolean" }, "providerShortName": { "description": "Provider short name for notarization.", "type": [ "string", "null" ] }, "entitlements": { "description": "Path to the entitlements file.", "type": [ "string", "null" ] }, "infoPlist": { "description": "Path to a Info.plist file to merge with the default Info.plist.\n\n Note that Tauri also looks for a `Info.plist` file in the same directory as the Tauri configuration file.", "type": [ "string", "null" ] }, "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" } ] } }, "additionalProperties": false }, "DmgConfig": { "description": "Configuration for Apple Disk Image (.dmg) bundles.\n\n See more: ", "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 }, "IosConfig": { "description": "General configuration for the iOS target.", "type": "object", "properties": { "template": { "description": "A custom [XcodeGen] project.yml template to use.\n\n [XcodeGen]: ", "type": [ "string", "null" ] }, "frameworks": { "description": "A list of strings indicating any iOS frameworks that need to be bundled with the application.\n\n Note that you need to recreate the iOS project for the changes to be applied.", "type": [ "array", "null" ], "items": { "type": "string" } }, "developmentTeam": { "description": "The development team. This value is required for iOS development because code signing is enforced.\n The `APPLE_DEVELOPMENT_TEAM` environment variable can be set to overwrite it.", "type": [ "string", "null" ] }, "bundleVersion": { "description": "The version of the build that identifies an iteration of the bundle.\n\n Translates to the bundle's CFBundleVersion property.", "type": [ "string", "null" ] }, "minimumSystemVersion": { "description": "A version string indicating the minimum iOS version that the bundled application supports. Defaults to `13.0`.\n\n Maps to the IPHONEOS_DEPLOYMENT_TARGET value.", "default": "14.0", "type": "string" }, "infoPlist": { "description": "Path to a Info.plist file to merge with the default Info.plist.\n\n Note that Tauri also looks for a `Info.plist` and `Info.ios.plist` file in the same directory as the Tauri configuration file.", "type": [ "string", "null" ] } }, "additionalProperties": false }, "AndroidConfig": { "description": "General configuration for the Android target.", "type": "object", "properties": { "minSdkVersion": { "description": "The minimum API level required for the application to run.\n The Android system will prevent the user from installing the application if the system's API level is lower than the value specified.", "default": 24, "type": "integer", "format": "uint32", "minimum": 0.0 }, "versionCode": { "description": "The version code of the application.\n It is limited to 2,100,000,000 as per Google Play Store requirements.\n\n By default we use your configured version and perform the following math:\n versionCode = version.major * 1000000 + version.minor * 1000 + version.patch", "type": [ "integer", "null" ], "format": "uint32", "maximum": 2100000000.0, "minimum": 1.0 }, "autoIncrementVersionCode": { "description": "Whether to automatically increment the `versionCode` on each build.\n\n - If `true`, the generator will try to read the last `versionCode` from\n `tauri.properties` and increment it by 1 for every build.\n - If `false` or not set, it falls back to `version_code` or semver-derived logic.\n\n Note that to use this feature, you should remove `/tauri.properties` from `src-tauri/gen/android/app/.gitignore` so the current versionCode is committed to the repository.", "default": false, "type": "boolean" } }, "additionalProperties": false }, "PluginConfig": { "description": "The plugin configs holds a HashMap mapping a plugin name to its configuration object.\n\n See more: ", "type": "object", "additionalProperties": true } } } ================================================ FILE: crates/tauri-schema-generator/schemas/permission.schema.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Permission", "description": "Descriptions of explicit privileges of commands.\n\n It can enable commands to be accessible in the frontend of the application.\n\n If the scope is defined it can be used to fine grain control the access of individual or multiple commands.", "type": "object", "required": [ "identifier" ], "properties": { "version": { "description": "The version of the permission.", "type": [ "integer", "null" ], "format": "uint64", "minimum": 1.0 }, "identifier": { "description": "A unique identifier for the permission.", "type": "string" }, "description": { "description": "Human-readable description of what the permission does.\n Tauri internal convention is to use `

` headings in markdown content\n for Tauri documentation generation purposes.", "type": [ "string", "null" ] }, "commands": { "description": "Allowed or denied commands when using this permission.", "default": { "allow": [], "deny": [] }, "allOf": [ { "$ref": "#/definitions/Commands" } ] }, "scope": { "description": "Allowed or denied scoped when using this permission.", "allOf": [ { "$ref": "#/definitions/Scopes" } ] }, "platforms": { "description": "Target platforms this permission applies. By default all platforms are affected by this permission.", "type": [ "array", "null" ], "items": { "$ref": "#/definitions/Target" } } }, "definitions": { "Commands": { "description": "Allowed and denied commands inside a permission.\n\n If two commands clash inside of `allow` and `deny`, it should be denied by default.", "type": "object", "properties": { "allow": { "description": "Allowed command.", "default": [], "type": "array", "items": { "type": "string" } }, "deny": { "description": "Denied command, which takes priority.", "default": [], "type": "array", "items": { "type": "string" } } } }, "Scopes": { "description": "An argument for fine grained behavior control of Tauri commands.\n\n It can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command.\n The configured scope is passed to the command and will be enforced by the command implementation.\n\n ## Example\n\n ```json\n {\n \"allow\": [{ \"path\": \"$HOME/**\" }],\n \"deny\": [{ \"path\": \"$HOME/secret.txt\" }]\n }\n ```", "type": "object", "properties": { "allow": { "description": "Data that defines what is allowed by the scope.", "type": [ "array", "null" ], "items": { "$ref": "#/definitions/Value" } }, "deny": { "description": "Data that defines what is denied by the scope. This should be prioritized by validation logic.", "type": [ "array", "null" ], "items": { "$ref": "#/definitions/Value" } } } }, "Value": { "description": "All supported ACL values.", "anyOf": [ { "description": "Represents a null JSON value.", "type": "null" }, { "description": "Represents a [`bool`].", "type": "boolean" }, { "description": "Represents a valid ACL [`Number`].", "allOf": [ { "$ref": "#/definitions/Number" } ] }, { "description": "Represents a [`String`].", "type": "string" }, { "description": "Represents a list of other [`Value`]s.", "type": "array", "items": { "$ref": "#/definitions/Value" } }, { "description": "Represents a map of [`String`] keys to [`Value`]s.", "type": "object", "additionalProperties": { "$ref": "#/definitions/Value" } } ] }, "Number": { "description": "A valid ACL number.", "anyOf": [ { "description": "Represents an [`i64`].", "type": "integer", "format": "int64" }, { "description": "Represents a [`f64`].", "type": "number", "format": "double" } ] }, "Target": { "description": "Platform target.", "oneOf": [ { "description": "MacOS.", "type": "string", "enum": [ "macOS" ] }, { "description": "Windows.", "type": "string", "enum": [ "windows" ] }, { "description": "Linux.", "type": "string", "enum": [ "linux" ] }, { "description": "Android.", "type": "string", "enum": [ "android" ] }, { "description": "iOS.", "type": "string", "enum": [ "iOS" ] } ] } } } ================================================ FILE: crates/tauri-schema-generator/schemas/scope.schema.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Scopes", "description": "An argument for fine grained behavior control of Tauri commands.\n\n It can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command.\n The configured scope is passed to the command and will be enforced by the command implementation.\n\n ## Example\n\n ```json\n {\n \"allow\": [{ \"path\": \"$HOME/**\" }],\n \"deny\": [{ \"path\": \"$HOME/secret.txt\" }]\n }\n ```", "type": "object", "properties": { "allow": { "description": "Data that defines what is allowed by the scope.", "type": [ "array", "null" ], "items": { "$ref": "#/definitions/Value" } }, "deny": { "description": "Data that defines what is denied by the scope. This should be prioritized by validation logic.", "type": [ "array", "null" ], "items": { "$ref": "#/definitions/Value" } } }, "definitions": { "Value": { "description": "All supported ACL values.", "anyOf": [ { "description": "Represents a null JSON value.", "type": "null" }, { "description": "Represents a [`bool`].", "type": "boolean" }, { "description": "Represents a valid ACL [`Number`].", "allOf": [ { "$ref": "#/definitions/Number" } ] }, { "description": "Represents a [`String`].", "type": "string" }, { "description": "Represents a list of other [`Value`]s.", "type": "array", "items": { "$ref": "#/definitions/Value" } }, { "description": "Represents a map of [`String`] keys to [`Value`]s.", "type": "object", "additionalProperties": { "$ref": "#/definitions/Value" } } ] }, "Number": { "description": "A valid ACL number.", "anyOf": [ { "description": "Represents an [`i64`].", "type": "integer", "format": "int64" }, { "description": "Represents a [`f64`].", "type": "number", "format": "double" } ] } } } ================================================ FILE: crates/tauri-schema-generator/src/main.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT //! Hosts the schema for the Tauri configuration file. #![doc( html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png", html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png" )] fn main() {} ================================================ FILE: crates/tauri-schema-worker/.gitignore ================================================ /target /node_modules /.wrangler /build ================================================ FILE: crates/tauri-schema-worker/Cargo.toml ================================================ [package] name = "tauri-schema-worker" version = "0.0.0" edition = "2021" publish = false [lib] crate-type = ["cdylib"] [dependencies] worker = { version = "0.7", features = ['http', 'axum'] } worker-macros = { version = "0.7", features = ['http'] } console_error_panic_hook = { version = "0.1" } axum = { version = "0.8", default-features = false } tower-service = "0.3" semver = { version = "1", features = ["serde"] } serde = { version = "1", features = ["derive"] } anyhow = "1" [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = [ 'cfg(wasm_bindgen_unstable_test_coverage)', ] } # https://github.com/rustwasm/wasm-pack/issues/1501 [package.metadata.wasm-pack.profile.release] wasm-opt = ["--enable-bulk-memory", "--enable-nontrapping-float-to-int"] ================================================ FILE: crates/tauri-schema-worker/README.md ================================================ # schema.tauri.app worker Source code for `https://schema.tauri.app` cloudflare worker. ================================================ FILE: crates/tauri-schema-worker/package.json ================================================ { "name": "tauri-schema-worker", "version": "0.0.0", "license": "Apache-2.0 OR MIT", "private": "true", "scripts": { "deploy": "wrangler deploy", "dev": "wrangler dev" }, "devDependencies": { "wrangler": "^4.75.0" } } ================================================ FILE: crates/tauri-schema-worker/src/config.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use anyhow::Context; use axum::{ extract::Path, http::{header, StatusCode}, response::Result, routing::get, Router, }; use semver::{Version, VersionReq}; use serde::Deserialize; use worker::*; #[derive(Deserialize)] pub struct CrateReleases { pub versions: Vec, } #[derive(Debug, Deserialize)] pub struct CrateRelease { #[serde(alias = "num")] pub version: Version, pub yanked: Option, } #[derive(Deserialize)] pub struct CrateMetadataFull { #[serde(rename = "crate")] pub crate_: CrateMetadata, } #[derive(Deserialize)] pub struct CrateMetadata { pub max_stable_version: Version, } const USERAGENT: &str = "tauri-schema-worker (contact@tauri.app)"; pub fn router() -> Router { Router::new() .route("/config", get(stable_schema)) .route("/config/latest", get(stable_schema)) .route("/config/stable", get(stable_schema)) .route("/config/next", get(next_schema)) // pre-releases versions, (rc, alpha and beta) .route("/config/{version}", get(schema_for_version)) } async fn schema_for_version(Path(version): Path) -> Result { try_schema_for_version(version) .await .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string())) .map_err(Into::into) } async fn stable_schema() -> Result { try_stable_schema() .await .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string())) .map_err(Into::into) } async fn next_schema() -> Result { try_next_schema() .await .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string())) .map_err(Into::into) } #[worker::send] async fn try_schema_for_version(version: String) -> anyhow::Result { let version = version.parse::()?; let releases = crate_releases("tauri").await?; if releases.is_empty() { return try_stable_schema().await; } let Some(version) = releases.into_iter().find(|r| version.matches(&r.version)) else { return try_stable_schema().await; }; schema_file_for_version(version.version).await } #[worker::send] async fn try_stable_schema() -> anyhow::Result { let max = stable_version("tauri").await?; schema_file_for_version(max).await } #[worker::send] async fn try_next_schema() -> anyhow::Result { let releases = crate_releases("tauri").await?; let version = releases .into_iter() .filter(|r| !r.version.pre.is_empty()) .map(|r| r.version) .max() .context("Couldn't find latest pre-release")?; schema_file_for_version(version).await } async fn schema_file_for_version(version: Version) -> anyhow::Result { let cache = Cache::open("schema".to_string()).await; let cache_key = format!("https://schema.tauri.app/config/{version}"); if let Some(mut cached) = cache.get(cache_key.clone(), true).await? { console_log!("Serving schema for {version} from cache"); return cached.text().await.map_err(Into::into); } console_log!("Fetching schema for {version} from remote"); let path = if version.major >= 2 { "crates/tauri-schema-generator/schemas/config.schema.json" } else { "core/tauri-config-schema/schema.json" }; let url = format!("https://raw.githubusercontent.com/tauri-apps/tauri/tauri-v{version}/{path}"); let mut res = Fetch::Request(fetch_req(&url)?).send().await?; cache.put(cache_key, res.cloned()?).await?; res.text().await.map_err(Into::into) } async fn crate_releases(crate_: &str) -> anyhow::Result> { let url = format!("https://crates.io/api/v1/crates/{crate_}/versions"); let mut res = Fetch::Request(fetch_req(&url)?).send().await?; let versions: CrateReleases = res.json().await?; let versions = versions.versions; let flt = |r: &CrateRelease| r.yanked == Some(false); Ok(versions.into_iter().filter(flt).collect()) } async fn stable_version(crate_: &str) -> anyhow::Result { let url = format!("https://crates.io/api/v1/crates/{crate_}"); let mut res = Fetch::Request(fetch_req(&url)?).send().await?; let metadata: CrateMetadataFull = res.json().await?; Ok(metadata.crate_.max_stable_version) } fn fetch_req(url: &str) -> anyhow::Result { let headers = Headers::new(); headers.append(header::USER_AGENT.as_str(), USERAGENT)?; worker::Request::new_with_init( url, &RequestInit { method: Method::Get, headers, cf: CfProperties { cache_ttl: Some(86400), cache_everything: Some(true), cache_ttl_by_status: Some( [ ("200-299".to_string(), 86400), ("404".to_string(), 1), ("500-599".to_string(), 0), ] .into(), ), ..Default::default() }, ..Default::default() }, ) .map_err(Into::into) } ================================================ FILE: crates/tauri-schema-worker/src/lib.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use axum::{routing::get, Router}; use tower_service::Service; use worker::*; mod config; #[worker::event(fetch)] async fn main( req: HttpRequest, _env: Env, _ctx: Context, ) -> worker::Result> { console_error_panic_hook::set_once(); Ok(router().call(req).await?) } fn router() -> Router { Router::new().route("/", get(root)).merge(config::router()) } async fn root() -> &'static str { "tauri schema worker" } ================================================ FILE: crates/tauri-schema-worker/wrangler.toml ================================================ # Copyright 2019-2022 Tauri Programme within The Commons Conservancy # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT name = "tauri-schema" main = "build/worker/shim.mjs" compatibility_date = "2023-08-23" send_metrics = false # The minor version of worker-build must match worker/worker-macros in Cargo.toml! [build] command = "cargo install -q worker-build@^0.7 && worker-build --release" [observability] enabled = true head_sampling_rate = 1 ================================================ FILE: crates/tauri-utils/CHANGELOG.md ================================================ # Changelog ## \[2.8.3] ### Bug Fixes - [`7b16dafb1`](https://www.github.com/tauri-apps/tauri/commit/7b16dafb1dc417536ebb62df8eb66154dd97109d) ([#14986](https://www.github.com/tauri-apps/tauri/pull/14986) by [@montyc1999](https://www.github.com/tauri-apps/tauri/../../montyc1999)) Sort csp/plugin/header configs when generating HashMap constructors so that `generate_context!` is deterministic. See: https://github.com/tauri-apps/tauri/issues/14978 for more information - [`c3cbff3f7`](https://www.github.com/tauri-apps/tauri/commit/c3cbff3f7430161715f80f82128b345a6f7140c9) ([#14662](https://www.github.com/tauri-apps/tauri/pull/14662) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix resource path handles `./` path differently (e.g. `./some-folder` should be the same as `some-folder`) ## \[2.8.2] ### Enhancements - [`2d28e3143`](https://www.github.com/tauri-apps/tauri/commit/2d28e3143ee3d97d7570ea03877aa00a0d6e47d0) ([#14632](https://www.github.com/tauri-apps/tauri/pull/14632) by [@sftse](https://www.github.com/tauri-apps/tauri/../../sftse)) Small code refactors for improved code readability. No user facing changes. ## \[2.8.1] ### Bug Fixes - [`1573c7240`](https://www.github.com/tauri-apps/tauri/commit/1573c72402352949d1fd3ca5c6fdbee46fe69fbb) ([#14561](https://www.github.com/tauri-apps/tauri/pull/14561) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused schema files to have `\r` characters on Windows. ## \[2.8.0] ### New Features - [`f5851ee00`](https://www.github.com/tauri-apps/tauri/commit/f5851ee00d6d1f4d560a220ca5a728fedd525092) ([#14089](https://www.github.com/tauri-apps/tauri/pull/14089)) Adds the `scrollBarStyle` option to the window configuration. - [`3b4fac201`](https://www.github.com/tauri-apps/tauri/commit/3b4fac2017832d426dd07c5e24e26684eda57f7b) ([#14194](https://www.github.com/tauri-apps/tauri/pull/14194)) Add `tauri.conf.json > bundle > android > autoIncrementVersionCode` config option to automatically increment the Android version code. - [`3d6868d09`](https://www.github.com/tauri-apps/tauri/commit/3d6868d09c323d68a152f3c3f8c7256311bd020a) ([#14128](https://www.github.com/tauri-apps/tauri/pull/14128)) Added `FileAssociation::exported_type` and `FileAssociation::content_types` for better support to defining custom types on macOS. - [`ed7c9a410`](https://www.github.com/tauri-apps/tauri/commit/ed7c9a4100e08c002212265549d12130d021ad1e) ([#14108](https://www.github.com/tauri-apps/tauri/pull/14108)) Added `bundle > macOS > infoPlist` and `bundle > iOS > infoPlist` configurations to allow defining custom Info.plist extensions. - [`7b0d4e732`](https://www.github.com/tauri-apps/tauri/commit/7b0d4e73227e42d88732b6d9fe643499dd78ec4e) ([#14265](https://www.github.com/tauri-apps/tauri/pull/14265)) Added `html::normalize_script_for_csp`. - [`cc8c0b531`](https://www.github.com/tauri-apps/tauri/commit/cc8c0b53171173dbd1d01781a50de1a3ea159031) ([#14031](https://www.github.com/tauri-apps/tauri/pull/14031)) Added support to universal app links on macOS with the `plugins > deep-link > desktop > domains` configuration. ### Enhancements - [`59089723f`](https://www.github.com/tauri-apps/tauri/commit/59089723fc20d66f3f305f2008adeb279bf87462) ([#14091](https://www.github.com/tauri-apps/tauri/pull/14091)) Added a config to set a data_directory relative to the app-specific data dir in JavaScript and `tauri.conf.json`. ## \[2.7.0] ### New Features - [`91508c0b8`](https://www.github.com/tauri-apps/tauri/commit/91508c0b8d16ec61c7706e93b711c5a85aaffb4a) ([#13881](https://www.github.com/tauri-apps/tauri/pull/13881) by [@pepperoni505](https://www.github.com/tauri-apps/tauri/../../pepperoni505)) Introduces a new configuration option that allows you to specify custom folders to watch for changes when running `tauri dev`. - [`0c402bfb6`](https://www.github.com/tauri-apps/tauri/commit/0c402bfb6bd0bec24d928fcabe2ffef1f5cff19a) ([#13997](https://www.github.com/tauri-apps/tauri/pull/13997) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Increase default iOS deployment target iOS to 14.0. ### Enhancements - [`9300b59f6`](https://www.github.com/tauri-apps/tauri/commit/9300b59f65156a37f7bf9a629b69da6761ae734a) ([#13787](https://www.github.com/tauri-apps/tauri/pull/13787) by [@JakenHerman](https://www.github.com/tauri-apps/tauri/../../JakenHerman)) Added `fips_compliant` field to `WixConfig` so that it can be configured via `tauri.conf.json` as well. - [`72b4226ee`](https://www.github.com/tauri-apps/tauri/commit/72b4226ee9932b4dafa4837a49420b2c02d14bb7) ([#13809](https://www.github.com/tauri-apps/tauri/pull/13809) by [@Beanow](https://www.github.com/tauri-apps/tauri/../../Beanow)) Reduced `Debug` format size for binary buffers. ### Bug Fixes - [`1a3d1a024`](https://www.github.com/tauri-apps/tauri/commit/1a3d1a024ebb2a3dd5d15849523a55246d78fda6) ([#13995](https://www.github.com/tauri-apps/tauri/pull/13995) by [@will3942](https://www.github.com/tauri-apps/tauri/../../will3942)) Fix Tauri iOS build with binary XCFramework dependencies, allows extracting binaryTargets that are zipped and also not including XCFrameworks when linking. ## \[2.6.0] ### New Features - [`232265c70`](https://www.github.com/tauri-apps/tauri/commit/232265c70e1c213bbb3f84b5541ddc07d330fce1) ([#13209](https://www.github.com/tauri-apps/tauri/pull/13209) by [@kandrelczyk](https://www.github.com/tauri-apps/tauri/../../kandrelczyk)) Added `platform::bundle_type`. - [`33d079392`](https://www.github.com/tauri-apps/tauri/commit/33d079392ac4a5a153b7d8a6d82fefd6f54a2bdf) ([#13811](https://www.github.com/tauri-apps/tauri/pull/13811) by [@mhbagheri-99](https://www.github.com/tauri-apps/tauri/../../mhbagheri-99)) Allow runner configuration to be an object with cmd, cwd, and args properties. The runner can now be configured as `{ "cmd": "my_runner", "cwd": "/path", "args": ["--quiet"] }` while maintaining backwards compatibility with the existing string format. ## \[2.5.0] ### New Features - [`414619c36`](https://www.github.com/tauri-apps/tauri/commit/414619c36e94e21939534dd72c0438b93da75546) ([#13536](https://www.github.com/tauri-apps/tauri/pull/13536) by [@Tunglies](https://www.github.com/tauri-apps/tauri/../../Tunglies)) Added support for the `bundleName` property in the macOS bundler configuration. This allows specifying the `CFBundleName` value for generated macOS bundles. - [`09c19932d`](https://www.github.com/tauri-apps/tauri/commit/09c19932d2ddf05f28bcdc73796a966532e7ca1c) ([#13304](https://www.github.com/tauri-apps/tauri/pull/13304) by [@39zde](https://www.github.com/tauri-apps/tauri/../../39zde)) Adds the option to configure the HTTP `Service-Worker-Allowed` response header in `app > security > headers` ### Bug Fixes - [`eb3f0248c`](https://www.github.com/tauri-apps/tauri/commit/eb3f0248c25f1d259cf0fa9448b3c7c2b75b24a7) ([#13646](https://www.github.com/tauri-apps/tauri/pull/13646) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Only write `This default permission set includes the following` to the reference if the default permission set is not empty - [`c8a30a61d`](https://www.github.com/tauri-apps/tauri/commit/c8a30a61d20552b43afd6f21cb66d18185314148) ([#13476](https://www.github.com/tauri-apps/tauri/pull/13476) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix capability filtering via `tauri.conf.json > app > security > capabilities` not working when generating allowed commands. - [`b52da29d5`](https://www.github.com/tauri-apps/tauri/commit/b52da29d5dbdb675ddba438a335e6a59f620e536) ([#13429](https://www.github.com/tauri-apps/tauri/pull/13429) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix `mainBinaryName` doesn't work when there's `.` in it ### What's Changed - [`168629646`](https://www.github.com/tauri-apps/tauri/commit/168629646335f24cc7f1c4a61df22688b2198f98) ([#13418](https://www.github.com/tauri-apps/tauri/pull/13418) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Put dynamic ACL into a feature `dynamic-acl`, this is currently enabled by default to align with the previous behaviors, you can disable it through `default-features = false` to reduce the final binary size by not including the ACL references ### Dependencies - [`9c16eefa3`](https://www.github.com/tauri-apps/tauri/commit/9c16eefa319b4697bac1d1019bbb5f93eca63173) ([#13629](https://www.github.com/tauri-apps/tauri/pull/13629) by [@sftse](https://www.github.com/tauri-apps/tauri/../../sftse)) Update html5ever to 0.29 and kuchikiki to version 0.8.8-speedreader. ### Breaking Changes - [`b7cdb3b39`](https://www.github.com/tauri-apps/tauri/commit/b7cdb3b39ef7e84773ce9312535825801350fa20) ([#13410](https://www.github.com/tauri-apps/tauri/pull/13410) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Feature gated the HTML manipulation code in `tauri-utils` behined a flag to reduce compile time ## \[2.4.0] ### New Features - [`ea36294cb`](https://www.github.com/tauri-apps/tauri/commit/ea36294cbca98f7725c91d1464fd92e77c89698a) ([#13208](https://www.github.com/tauri-apps/tauri/pull/13208)) Added `disableInputAccessoryView: bool` config for iOS. - [`0aa48fb9e`](https://www.github.com/tauri-apps/tauri/commit/0aa48fb9e4b9d7b5bf3522000a76ebc1836394ed) ([#13030](https://www.github.com/tauri-apps/tauri/pull/13030)) Added `bundleVersion` to iOS and macOS configuration to support specifying a `CFBundleVersion`. - [`b072e2b29`](https://www.github.com/tauri-apps/tauri/commit/b072e2b2967640ae4fa1af466ae878c156551edd) ([#9687](https://www.github.com/tauri-apps/tauri/pull/9687)) Add `preventOverflow` config option to prevent the window from overflowing the monitor size on creation ### Bug Fixes - [`2dccfab53`](https://www.github.com/tauri-apps/tauri/commit/2dccfab5321fef55d45f3a4c674b6151b1c4424a) ([#13236](https://www.github.com/tauri-apps/tauri/pull/13236)) Fix `fileAssociations` missing `LSHandlerRank` on macOS. ## \[2.3.1] ### Enhancements - [`a851b6597`](https://www.github.com/tauri-apps/tauri/commit/a851b6597f7e37d12f9e4632945e8466800eb5ff) ([#13057](https://www.github.com/tauri-apps/tauri/pull/13057) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Enhanced the description of generated docs and schema for permission sets to include list of permissions within. ### Bug Fixes - [`4ae14bf2f`](https://www.github.com/tauri-apps/tauri/commit/4ae14bf2f20546c0990c48dc465832ffc46a7247) ([#13093](https://www.github.com/tauri-apps/tauri/pull/13093) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Suppress deprecated warning in `TrayIconConfig`'s codegen ## \[2.3.0] ### New Features - [`013f8f652`](https://www.github.com/tauri-apps/tauri/commit/013f8f652302f2d49c5ec0a075582033d8b074fb) ([#12890](https://www.github.com/tauri-apps/tauri/pull/12890) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Added `build > removeUnusedCommands` to trigger the build scripts and macros to remove unused commands based on the capabilities you defined. Note this won't be accounting for dynamically added ACLs so make sure to check it when using this. - [`30f5a1553`](https://www.github.com/tauri-apps/tauri/commit/30f5a1553d3c0ce460c9006764200a9210915a44) ([#12366](https://www.github.com/tauri-apps/tauri/pull/12366) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Added `trafficLightPosition` window configuration to set the traffic light buttons position on macOS. ### Enhancements - [`f981a5ee8`](https://www.github.com/tauri-apps/tauri/commit/f981a5ee8b292b9ea09329f60cecc7f688dda734) ([#12602](https://www.github.com/tauri-apps/tauri/pull/12602) by [@kxxt](https://www.github.com/tauri-apps/tauri/../../kxxt)) Add basic support for linux riscv64 platform. ### Bug Fixes - [`3cc4ad3c3`](https://www.github.com/tauri-apps/tauri/commit/3cc4ad3c381ee081cfcf0df28ea51507ad5c9b95) ([#12884](https://www.github.com/tauri-apps/tauri/pull/12884) by [@oscartbeaumont](https://www.github.com/tauri-apps/tauri/../../oscartbeaumont)) fix: allow double `--` in permissions as command can have double `__` ### Performance Improvements - [`1cd8f55ee`](https://www.github.com/tauri-apps/tauri/commit/1cd8f55eed326d61860fee62ba2d2f4464bdcfcc) ([#13033](https://www.github.com/tauri-apps/tauri/pull/13033) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Don't ship global `bundle.global.js` if `app > withGlobalTauri` is set to false ## \[2.2.0] ### Enhancements - [`a2d36b8c3`](https://www.github.com/tauri-apps/tauri/commit/a2d36b8c34a8dcfc6736797ca5cd4665faf75e7e) ([#12181](https://www.github.com/tauri-apps/tauri/pull/12181) by [@bastiankistner](https://www.github.com/tauri-apps/tauri/../../bastiankistner)) Add an option to change the default background throttling policy (currently for WebKit only). ## \[2.1.1] ### Bug Fixes - [`46935212b`](https://www.github.com/tauri-apps/tauri/commit/46935212b61da44dc82dfeb803fceebf5659f7b7) ([#11658](https://www.github.com/tauri-apps/tauri/pull/11658) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix `.json5` capability files not recognized even with `config-json5` feature enabled ## \[2.1.0] ### New Features - [`fabc2f283`](https://www.github.com/tauri-apps/tauri/commit/fabc2f283e38b62c721326e44645d47138418cbc) ([#11485](https://www.github.com/tauri-apps/tauri/pull/11485) by [@39zde](https://www.github.com/tauri-apps/tauri/../../39zde)) Adds a new configuration option `app > security > headers` to define headers that will be added to every http response from tauri to the web view. This doesn't include IPC messages and error responses. - [`4d545ab3c`](https://www.github.com/tauri-apps/tauri/commit/4d545ab3ca228c8a21b966b709f84a0da2864479) ([#11486](https://www.github.com/tauri-apps/tauri/pull/11486) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Added `Window::set_background_color` and `WindowBuilder::background_color`. - [`cbc095ec5`](https://www.github.com/tauri-apps/tauri/commit/cbc095ec5fe7de29b5c9265576d4e071ec159c1c) ([#11451](https://www.github.com/tauri-apps/tauri/pull/11451) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `app > windows > devtools` config option and when creating the webview from JS, to enable or disable devtools for a specific webview. - [`058c0db72`](https://www.github.com/tauri-apps/tauri/commit/058c0db72f43fbe1574d0db654560e693755cd7e) ([#11584](https://www.github.com/tauri-apps/tauri/pull/11584) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `bundle > linux > rpm > compression` config option to control RPM bundle compression type and level. - [`f37e97d41`](https://www.github.com/tauri-apps/tauri/commit/f37e97d410c4a219e99f97692da05ca9d8e0ba3a) ([#11477](https://www.github.com/tauri-apps/tauri/pull/11477) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `app > windows > useHttpsScheme` config option to choose whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android - [`2a75c64b5`](https://www.github.com/tauri-apps/tauri/commit/2a75c64b5431284e7340e8743d4ea56a62c75466) ([#11469](https://www.github.com/tauri-apps/tauri/pull/11469) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Added `app > windows > windowClassname` config option to specify the name of the window class on Windows. ### Enhancements - [`c33bbf457`](https://www.github.com/tauri-apps/tauri/commit/c33bbf45740274b6918ea6c647f366fb6008e459) ([#11575](https://www.github.com/tauri-apps/tauri/pull/11575) by [@kornelski](https://www.github.com/tauri-apps/tauri/../../kornelski)) Include the path in ACL I/O errors. ### Bug Fixes - [`378142914`](https://www.github.com/tauri-apps/tauri/commit/37814291475814b4a24cc77b6fa457ec9ba7a779) ([#11429](https://www.github.com/tauri-apps/tauri/pull/11429) by [@griffi-gh](https://www.github.com/tauri-apps/tauri/../../griffi-gh)) Enhance resource directory resolution to support running on distros like NixOS. ## \[2.0.2] ### New Features - Add `bundler > windows > wix > version` to manually specify a wix-compatible version. ## \[2.0.1] ### What's Changed - [`0ab2b3306`](https://www.github.com/tauri-apps/tauri/commit/0ab2b330644b6419f6cee1d5377bfb5cdda2ccf9) ([#11205](https://www.github.com/tauri-apps/tauri/pull/11205) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Downgrade MSRV to 1.77.2 to support Windows 7. ## \[2.0.0] ### What's Changed - [`382ed482b`](https://www.github.com/tauri-apps/tauri/commit/382ed482bd08157c39e62f9a0aaad8802f1092cb) Bump MSRV to 1.78. - [`637285790`](https://www.github.com/tauri-apps/tauri/commit/6372857905ae9c0aedb7f482ddf6cf9f9836c9f2) Promote to v2 stable! ## \[2.0.0-rc.13] ### New Features - [`a247170e1`](https://www.github.com/tauri-apps/tauri/commit/a247170e1f620a9b012274b11cfe51e90327d6e9) ([#11056](https://www.github.com/tauri-apps/tauri/pull/11056) by [@SpikeHD](https://www.github.com/tauri-apps/tauri/../../SpikeHD)) Expose the ability to enabled browser extensions in WebView2 on Windows. - [`f57a729cd`](https://www.github.com/tauri-apps/tauri/commit/f57a729cd8f7e10d8daf0b9d5b85f9c7ad530496) ([#11039](https://www.github.com/tauri-apps/tauri/pull/11039) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `upgradeCode` in `wix` configuration to set an upgrade code for your MSI installer. This is recommended to be set if you plan to change your `productName`. ### Bug Fixes - [`1efa5e718`](https://www.github.com/tauri-apps/tauri/commit/1efa5e7184009537b688a395596c696173ae0231) ([#11099](https://www.github.com/tauri-apps/tauri/pull/11099) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Rerun build script if the platform-specific configuration file changes. ## \[2.0.0-rc.12] ### New Features - [`ad294d274`](https://www.github.com/tauri-apps/tauri/commit/ad294d274dd81d2ef91ed73af9163b6e9b8eb964) ([#11032](https://www.github.com/tauri-apps/tauri/pull/11032) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `app > windows > create` option to choose whether to create this window at app startup or not. ## \[2.0.0-rc.11] ### New Features - [`35bd9dd3d`](https://www.github.com/tauri-apps/tauri/commit/35bd9dd3dc3d8972bbc4aa5f4a6c6fa14354e9bf) ([#10977](https://www.github.com/tauri-apps/tauri/pull/10977) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `mainBinaryName` config option to set the file name for the main binary. ## \[2.0.0-rc.10] ### Bug Fixes - [`0a47bf043`](https://www.github.com/tauri-apps/tauri/commit/0a47bf04302ca8502d3da21b3bc27818720fe34a) ([#10946](https://www.github.com/tauri-apps/tauri/pull/10946) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that made the `identifier` in `tauri.conf.json` optional while it was actually required. ## \[2.0.0-rc.9] ### Dependencies - [`d9c8d3cc8`](https://www.github.com/tauri-apps/tauri/commit/d9c8d3cc8d5ca67cd767ffc7a521f801b41ce201) ([#10902](https://www.github.com/tauri-apps/tauri/pull/10902) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Update infer to 0.16, tray icon to 0.17, urlpattern to 0.3, image to 0.25 ### Breaking Changes - [`faa259bac`](https://www.github.com/tauri-apps/tauri/commit/faa259bacf1ace670af763982c6903190faf163a) ([#10907](https://www.github.com/tauri-apps/tauri/pull/10907) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) The `Assets::iter` function now must return a iterator with `Item = (Cow<'_, str>, Cow<'_, [u8]>)` to be more flexible on contexts where the assets are not `'static`. ## \[2.0.0-rc.8] ### Enhancements - [`f0acf504a`](https://www.github.com/tauri-apps/tauri/commit/f0acf504a2a972c063188a00143d8bf2b887691d) ([#10858](https://www.github.com/tauri-apps/tauri/pull/10858) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Validate duplicate capability identifier. ## \[2.0.0-rc.7] ### New Features - [`58dda44a5`](https://www.github.com/tauri-apps/tauri/commit/58dda44a59b915f091602cdfc53385a148469793) ([#10339](https://www.github.com/tauri-apps/tauri/pull/10339) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Add a new option `minimumWebview2Version` for Windows NSIS installer to trigger a webview2 update if the user's webview2 is older than this version ### Bug Fixes - [`03f2a5098`](https://www.github.com/tauri-apps/tauri/commit/03f2a50981b8c01b1c196811fce9d93f1bf0820d) ([#10718](https://www.github.com/tauri-apps/tauri/pull/10718) by [@rdlabo](https://www.github.com/tauri-apps/tauri/../../rdlabo)) Update swift-rs fixing a plugin build when native dependencies are used. ### Breaking Changes - [`073bb4f45`](https://www.github.com/tauri-apps/tauri/commit/073bb4f459a923541b94970dfa7e087bccaa2cfd) ([#10772](https://www.github.com/tauri-apps/tauri/pull/10772) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Removed the deprecated `webview_fixed_runtime_path` config option, use the `webview_install_mode` instead. ## \[2.0.0-rc.6] ### Bug Fixes - [`9bcff3cd7`](https://www.github.com/tauri-apps/tauri/commit/9bcff3cd7997fe13425a21b577f93317831f77fa) ([#10703](https://www.github.com/tauri-apps/tauri/pull/10703) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Properly remove isolation script on Android. ### What's Changed - [`f4d5241b3`](https://www.github.com/tauri-apps/tauri/commit/f4d5241b377d0f7a1b58100ee19f7843384634ac) ([#10731](https://www.github.com/tauri-apps/tauri/pull/10731) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Update documentation icon path. ## \[2.0.0-rc.5] ### Bug Fixes - [`da381e07f`](https://www.github.com/tauri-apps/tauri/commit/da381e07f3770988fe6d0859a02331b87cc6723f) ([#10696](https://www.github.com/tauri-apps/tauri/pull/10696) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Implemented `resource_dir` on Android, which returns a URI that needs to be resolved using [AssetManager::open](https://developer.android.com/reference/android/content/res/AssetManager#open\(java.lang.String,%20int\)). This will be handled by the file system plugin. - [`da381e07f`](https://www.github.com/tauri-apps/tauri/commit/da381e07f3770988fe6d0859a02331b87cc6723f) ([#10696](https://www.github.com/tauri-apps/tauri/pull/10696) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix `resource_dir` on iOS. ## \[2.0.0-rc.4] ### New Features - [`8d148a9e2`](https://www.github.com/tauri-apps/tauri/commit/8d148a9e2566edebfea2d75f32df7c9396d765a4) ([#10634](https://www.github.com/tauri-apps/tauri/pull/10634) by [@anatawa12](https://www.github.com/tauri-apps/tauri/../../anatawa12)) Custom sign command with object notation for whitespaces in the command path and arguments. ### Bug Fixes - [`5c335ae9a`](https://www.github.com/tauri-apps/tauri/commit/5c335ae9ad88e46c2135a557390f6e808c9a6088) ([#10648](https://www.github.com/tauri-apps/tauri/pull/10648) by [@Flakebi](https://www.github.com/tauri-apps/tauri/../../Flakebi)) Prevent build script from rerunning unnecessarily by only writing files when the content changes. ## \[2.0.0-rc.3] ### Enhancements - [`0bb7b0f35`](https://www.github.com/tauri-apps/tauri/commit/0bb7b0f352960fb5111a40157c0953d19e76f1fd) ([#10559](https://www.github.com/tauri-apps/tauri/pull/10559) by [@Norbiros](https://www.github.com/tauri-apps/tauri/../../Norbiros)) Return autogenerated permissions from `autogenerate_command_permissions`. ### Bug Fixes - [`9e891933d`](https://www.github.com/tauri-apps/tauri/commit/9e891933d8ac7a67e37770a149d0a5dd385ee625) ([#10293](https://www.github.com/tauri-apps/tauri/pull/10293) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix `ResourcePaths` iterator returning an unexpected result for mapped resources, for example `"../resources/user.json": "resources/user.json"` generates this resource `resources/user.json/user.json` where it should generate just `resources/user.json`. - [`9fe846615`](https://www.github.com/tauri-apps/tauri/commit/9fe846615b7c4f310f07897ded881c239e3df30a) ([#10547](https://www.github.com/tauri-apps/tauri/pull/10547) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix plugin permissions documentation heading for permissions table. ### Dependencies - [`0afee5ed8`](https://www.github.com/tauri-apps/tauri/commit/0afee5ed80265c95c4581e173c4886677cfed593) ([#10436](https://www.github.com/tauri-apps/tauri/pull/10436) by [@nyurik](https://www.github.com/tauri-apps/tauri/../../nyurik)) Updated brotli to v6. ## \[2.0.0-rc.2] ### Bug Fixes - [`f5dfc0280`](https://www.github.com/tauri-apps/tauri/commit/f5dfc02800dbd3bdee671b032454c49ac7102fb4) ([#10533](https://www.github.com/tauri-apps/tauri/pull/10533) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue causing `tauri ios init` to fail if `iOS.minimumSystemVersion` was not configured explicitly. ## \[2.0.0-rc.1] ### New Features - [`8dc81b6cc`](https://www.github.com/tauri-apps/tauri/commit/8dc81b6cc2b8235b11f74a971d6aa3a5df5e9f68) ([#10496](https://www.github.com/tauri-apps/tauri/pull/10496) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Added `bundle > ios > template` configuration option for custom Xcode project YML Handlebars template using XcodeGen. - [`02c00abc6`](https://www.github.com/tauri-apps/tauri/commit/02c00abc63cf86e9bf9179cbb143d5145a9397b6) ([#10495](https://www.github.com/tauri-apps/tauri/pull/10495) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Added `bundle > ios > minimumSystemVersion` configuration option. ### Bug Fixes - [`7e810cb2a`](https://www.github.com/tauri-apps/tauri/commit/7e810cb2a3fd934017ae973e737864dfa4bdf64e) ([#10485](https://www.github.com/tauri-apps/tauri/pull/10485) by [@anatawa12](https://www.github.com/tauri-apps/tauri/../../anatawa12)) Fixed an issue where permission files will be generated with ':' in the file path. ## \[2.0.0-rc.0] ### New Features - [`a5bfbaa62`](https://www.github.com/tauri-apps/tauri/commit/a5bfbaa62b8cd0aacbb33f730d4e30b43c461fe1)([#9962](https://www.github.com/tauri-apps/tauri/pull/9962)) Added `bundle > iOS > frameworks` configuration to define a list of frameworks that are linked to the Xcode project when it is generated. ### Enhancements - [`7aeac39e7`](https://www.github.com/tauri-apps/tauri/commit/7aeac39e7fb97dc57ca278f1c097058275c20aa2) ([#10397](https://www.github.com/tauri-apps/tauri/pull/10397)) Make the set of gtk application id optional, to allow more then one instance of the app running at the same time. ### Bug Fixes - [`498f405ca`](https://www.github.com/tauri-apps/tauri/commit/498f405ca80440447823dd3c9cd53c0f79d655b5) ([#10404](https://www.github.com/tauri-apps/tauri/pull/10404)) Fixed an issue where configuration parsing errors always displayed 'tauri.conf.json' as the file path, even when using 'Tauri.toml' or 'tauri.conf.json5'. The error messages now correctly shows the actual config file being used. ### Security fixes - [`426d14bb4`](https://www.github.com/tauri-apps/tauri/commit/426d14bb4164290d93b5a0f61e925cb2dfc4aafa) ([#10423](https://www.github.com/tauri-apps/tauri/pull/10423)) Explicitly check that the main frame's origin is the sender of Isolation Payloads ## \[2.0.0-beta.19] ### New Features - [`4c239729c`](https://www.github.com/tauri-apps/tauri/commit/4c239729c3e1b899ecbc6793c3682848e8de1729) ([#10167](https://www.github.com/tauri-apps/tauri/pull/10167) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `RawIsolationPayload::content_type` method. ## \[2.0.0-beta.18] ### New Features - [`fafc238f7`](https://www.github.com/tauri-apps/tauri/commit/fafc238f7288548975ca7d3e5207b925c0295c91) ([#9977](https://www.github.com/tauri-apps/tauri/pull/9977)) Add `bundle > homepage` option, if unset, it will fallback to `homepage` defined in `Cargo.toml`. - [`656a64974`](https://www.github.com/tauri-apps/tauri/commit/656a64974468bc207bf39537e02ae179bdee9b83) ([#9318](https://www.github.com/tauri-apps/tauri/pull/9318)) Added a configuration option to disable hardened runtime on macOS codesign. - [`5b769948a`](https://www.github.com/tauri-apps/tauri/commit/5b769948a81cac333f64c870a470ba6525bd5cd3) ([#9959](https://www.github.com/tauri-apps/tauri/pull/9959)) Add `include_image` macro to help embedding instances of `Image` struct at compile-time in rust to be used with window, menu or tray icons. - [`3ab170917`](https://www.github.com/tauri-apps/tauri/commit/3ab170917ed535fc9013f0a9255631fb34493e18) ([#9932](https://www.github.com/tauri-apps/tauri/pull/9932)) Add an option to disable NSIS compression `bundle > nsis > compression: "none"` - [`f21029b1b`](https://www.github.com/tauri-apps/tauri/commit/f21029b1bc25f5cb987e1a25de94c2d364e3e462) ([#9994](https://www.github.com/tauri-apps/tauri/pull/9994)) Add `bundle > nsis > startMenuFolder` option to customize start menu folder for NSIS installer ### Enhancements - [`878198777`](https://www.github.com/tauri-apps/tauri/commit/878198777ef693efdbd394cb4be4b234e8a7ed3d) ([#9999](https://www.github.com/tauri-apps/tauri/pull/9999)) Mark ACL `permissions` array with unique items ### Breaking Changes - [`3ab170917`](https://www.github.com/tauri-apps/tauri/commit/3ab170917ed535fc9013f0a9255631fb34493e18) ([#9932](https://www.github.com/tauri-apps/tauri/pull/9932)) Changed `NsisSettings::compression` field from `Option` to just `NsisCompression` - [`911242f09`](https://www.github.com/tauri-apps/tauri/commit/911242f0928e0a2add3595fa9de27850fb875fa6) ([#9883](https://www.github.com/tauri-apps/tauri/pull/9883)) Move updater target from `bundle > targets` to a separate field `bundle > createUpdaterArtifacts` - [`3ab170917`](https://www.github.com/tauri-apps/tauri/commit/3ab170917ed535fc9013f0a9255631fb34493e18) ([#9932](https://www.github.com/tauri-apps/tauri/pull/9932)) Changed `NsisConfig::compression` field from `Option` to just `NsisCompression` ## \[2.0.0-beta.17] ### New Features - [`8a1ae2dea`](https://www.github.com/tauri-apps/tauri/commit/8a1ae2deaf3086e531ada25b1627f900e2e421fb)([#9843](https://www.github.com/tauri-apps/tauri/pull/9843)) Added an option to use a Xcode project for the iOS plugin instead of a plain SwiftPM project. - [`5462e5cad`](https://www.github.com/tauri-apps/tauri/commit/5462e5cadc73c1b9083d852061d7c7f982cfbe53)([#9731](https://www.github.com/tauri-apps/tauri/pull/9731)) Add `installer_hooks` NSIS configuration field - [`d6d3efbd1`](https://www.github.com/tauri-apps/tauri/commit/d6d3efbd125489cb46642b6d013cdc1eb7fc1a66)([#9865](https://www.github.com/tauri-apps/tauri/pull/9865)) Add `sign_command` in `WindowsConfig` ### Breaking Changes - [`fc1543c65`](https://www.github.com/tauri-apps/tauri/commit/fc1543c65e736622bed93543dcc6504c43e200bb)([#9864](https://www.github.com/tauri-apps/tauri/pull/9864)) Removed `skip_webview_install` (`skipWebviewInstall`) option from config, which has been deprecated for a while now and planned to be removed in v2. Use `webview_install_mode` (`webviewInstallMode`) instead. - [`265c23886`](https://www.github.com/tauri-apps/tauri/commit/265c23886ee5efbcc6d7188ff5c84cb32fa82aea)([#9375](https://www.github.com/tauri-apps/tauri/pull/9375)) Removed `Config::binary_name` and `PackageInfo::package_name` ## \[2.0.0-beta.16] ### Bug Fixes - [`be95d8d37`](https://www.github.com/tauri-apps/tauri/commit/be95d8d37c4b1a420c0d28a83b7efa40ab0b0ab5)([#9782](https://www.github.com/tauri-apps/tauri/pull/9782)) Fixes the `ToTokens` implementation for `Capability`. ## \[2.0.0-beta.15] ### Bug Fixes - [`a5205f179`](https://www.github.com/tauri-apps/tauri/commit/a5205f179e577cce5c05b710b597da8f4e1d0780)([#9691](https://www.github.com/tauri-apps/tauri/pull/9691)) Fixes the ToTokens implementation of the window configuration `proxy_url` field. ## \[2.0.0-beta.14] ### Bug Fixes - [`3fbc1703f`](https://www.github.com/tauri-apps/tauri/commit/3fbc1703f107dfb2c5a75e848805dcf60d449eb1)([#9676](https://www.github.com/tauri-apps/tauri/pull/9676)) Fixes `schemars` compilation issue. ## \[2.0.0-beta.13] ### Bug Fixes - [`a1e0e268f`](https://www.github.com/tauri-apps/tauri/commit/a1e0e268f02f7e2934bec48de4cac0dc00529a2b)([#9477](https://www.github.com/tauri-apps/tauri/pull/9477)) Replace `tauri:` prefix with `tauri-` for temporary permission file names ## \[2.0.0-beta.12] ### New Features - [`36b4c1249`](https://www.github.com/tauri-apps/tauri/commit/36b4c12497fbe636066f4848c6877b3ab6cc892e)([#9331](https://www.github.com/tauri-apps/tauri/pull/9331)) Added support for `provides`, `conflicts` and `replaces` (`obsoletes` for RPM) options for `bundler > deb` and `bundler > rpm` configs. ## \[2.0.0-beta.11] ### New Features - [`259d84529`](https://www.github.com/tauri-apps/tauri/commit/259d845290dde40639537258b2810567910f47f3)([#9209](https://www.github.com/tauri-apps/tauri/pull/9209)) Added `preInstallScript`, `postInstallScript`, `preRemoveScript` and `postRemoveScript` options for `bundler > deb` and `bundler > rpm` configs. ### Enhancements - [`7c334cb18`](https://www.github.com/tauri-apps/tauri/commit/7c334cb1851ab034a3cfb472dd99dfc61ad3ca7f)([#9327](https://www.github.com/tauri-apps/tauri/pull/9327)) Make the isolation pattern encrypt key unextractable. - [`a804a70a7`](https://www.github.com/tauri-apps/tauri/commit/a804a70a7aa1dc40fa9043206ad2265c6a5a437b)([#9328](https://www.github.com/tauri-apps/tauri/pull/9328)) The isolation iframe script now removes itself after execution. ### Breaking Changes - [`06833f4fa`](https://www.github.com/tauri-apps/tauri/commit/06833f4fa8e63ecc55fe3fc874a9e397e77a5709)([#9100](https://www.github.com/tauri-apps/tauri/pull/9100)) Rename `FileDrop` to `DragDrop` on structs, enums and enum variants. Also renamed `file_drop` to `drag_drop` on fields and function names. ## \[2.0.0-beta.10] ### New Features - [`e227fe02f`](https://www.github.com/tauri-apps/tauri/commit/e227fe02f986e145c0731a64693e1c830a9eb5b0)([#9156](https://www.github.com/tauri-apps/tauri/pull/9156)) Added the `plugin` module. ### Enhancements - [`7213b9e47`](https://www.github.com/tauri-apps/tauri/commit/7213b9e47242bef814aa7257e0bf84631bf5fe7e)([#9124](https://www.github.com/tauri-apps/tauri/pull/9124)) Fallback to an empty permission set if the plugin did not define its `default` permissions. ## \[2.0.0-beta.9] ### Breaking Changes - [`490a6b424`](https://www.github.com/tauri-apps/tauri/commit/490a6b424e81714524150aef96fbf6cf7004b940)([#9147](https://www.github.com/tauri-apps/tauri/pull/9147)) Removed the `assets::Assets` trait which is now part of the `tauri` crate. ## \[2.0.0-beta.8] ### Enhancements - [`3e472d0af`](https://www.github.com/tauri-apps/tauri/commit/3e472d0afcd67545dd6d9f18d304580a3b2759a8)([#9115](https://www.github.com/tauri-apps/tauri/pull/9115)) Changed the permission and capability platforms to be optional. ### Breaking Changes - [`4ef17d083`](https://www.github.com/tauri-apps/tauri/commit/4ef17d08336a2e0df4a7ef9adea746d7419710b6)([#9116](https://www.github.com/tauri-apps/tauri/pull/9116)) The ACL configuration for remote URLs now uses the URLPattern standard instead of glob patterns. ## \[2.0.0-beta.7] ### Bug Fixes - [`86fa339de`](https://www.github.com/tauri-apps/tauri/commit/86fa339de7b176efafa9b3e89f94dcad5fcd03da)([#9071](https://www.github.com/tauri-apps/tauri/pull/9071)) Fix compile time error in context generation when using `app.windows.windowEffects.color` - [`6c0683224`](https://www.github.com/tauri-apps/tauri/commit/6c068322460300e9d56a4fac5b018d4c437daa9e)([#9068](https://www.github.com/tauri-apps/tauri/pull/9068)) Fixes scope resolution grouping scopes for all windows. - [`c68218b36`](https://www.github.com/tauri-apps/tauri/commit/c68218b362c417b62e56c7a2b5b32c13fe035a83)([#8990](https://www.github.com/tauri-apps/tauri/pull/8990)) Fix `BundleTarget::to_vec` returning an empty vec for `BundleTarget::All` variant. - [`c68218b36`](https://www.github.com/tauri-apps/tauri/commit/c68218b362c417b62e56c7a2b5b32c13fe035a83)([#8990](https://www.github.com/tauri-apps/tauri/pull/8990)) Add `BundleType::all` method to return all possible `BundleType` variants. ### Breaking Changes - [`9aa0d6e95`](https://www.github.com/tauri-apps/tauri/commit/9aa0d6e959269a9d99ff474e7f12bd397ea75fcd)([#9069](https://www.github.com/tauri-apps/tauri/pull/9069)) Removed `debug_eprintln!` and `consume_unused_variable` macros. - [`bb23511ea`](https://www.github.com/tauri-apps/tauri/commit/bb23511ea80bcaffbdebf057301e463fff268c90)([#9079](https://www.github.com/tauri-apps/tauri/pull/9079)) Changed `CapabiltyFile::List` enum variant to be a tuple-struct and added `CapabiltyFile::NamedList`. This allows more flexibility when parsing capabilties from JSON files. ## \[2.0.0-beta.6] ### New Features - [`d7f56fef`](https://www.github.com/tauri-apps/tauri/commit/d7f56fef85cac3af4e2dbac1eac40e5567b1f160)([#9014](https://www.github.com/tauri-apps/tauri/pull/9014)) Allow defining a permission that only applies to a set of target platforms via the `platforms` configuration option. ### Enhancements - [`04440edc`](https://www.github.com/tauri-apps/tauri/commit/04440edce870f9d06055616034941d79443d5a87)([#9019](https://www.github.com/tauri-apps/tauri/pull/9019)) Changed plugin markdown docs generation to table format. ### Breaking Changes - [`3657ad82`](https://www.github.com/tauri-apps/tauri/commit/3657ad82f88ce528551d032d521c52eed3f396b4)([#9008](https://www.github.com/tauri-apps/tauri/pull/9008)) Allow defining permissions for the application commands via `tauri_build::Attributes::app_manifest`. ## \[2.0.0-beta.5] ### Enhancements - [`bc5b5e67`](https://www.github.com/tauri-apps/tauri/commit/bc5b5e671a546512f823f1c157421b4c3311dfc0)([#8984](https://www.github.com/tauri-apps/tauri/pull/8984)) Do not include a CSP tag in the application HTML and rely on the custom protocol response header instead. ## \[2.0.0-beta.4] ### Breaking Changes - [`a76fb118`](https://www.github.com/tauri-apps/tauri/commit/a76fb118ce2de22e1bdb4216bf0ac01dfc3e5799)([#8950](https://www.github.com/tauri-apps/tauri/pull/8950)) Changed the capability format to allow configuring both `remote: { urls: Vec }` and `local: bool (default: true)` instead of choosing one on the `context` field. ## \[2.0.0-beta.3] ### Breaking Changes - [`361ec37f`](https://www.github.com/tauri-apps/tauri/commit/361ec37fd4a5caa5b6630b9563ef079f53c6c336)([#8932](https://www.github.com/tauri-apps/tauri/pull/8932)) Moved `ProgressBarState` from `tauri-utils` to the `tauri::window` module and removed the `unity_uri` field. ## \[2.0.0-beta.2] ### Enhancements - [`0cb0a15c`](https://www.github.com/tauri-apps/tauri/commit/0cb0a15ce22af3d649cf219ac04188c14c5f4905)([#8789](https://www.github.com/tauri-apps/tauri/pull/8789)) Add `webviews` array on the capability for usage on multiwebview contexts. - [`83a68deb`](https://www.github.com/tauri-apps/tauri/commit/83a68deb5676d39cd4728d2e140f6b46d5f787ed)([#8797](https://www.github.com/tauri-apps/tauri/pull/8797)) Added a new configuration option `tauri.conf.json > app > security > capabilities` to reference existing capabilities and inline new ones. If it is empty, all capabilities are still included preserving the current behavior. - [`8d16a80d`](https://www.github.com/tauri-apps/tauri/commit/8d16a80d2fb2468667e7987d0cc99dbc7e3b9d0a)([#8802](https://www.github.com/tauri-apps/tauri/pull/8802)) The `Context` struct now includes the runtime authority instead of the resolved ACL. This does not impact most applications. - [`28fb036c`](https://www.github.com/tauri-apps/tauri/commit/28fb036ce476c6f22815c35385f923135212c6f3)([#8852](https://www.github.com/tauri-apps/tauri/pull/8852)) Enhance resource directory resolution on development. - [`dd7571a7`](https://www.github.com/tauri-apps/tauri/commit/dd7571a7808676c8063a4983b9c6687dfaf03a09)([#8815](https://www.github.com/tauri-apps/tauri/pull/8815)) Do not generate JSON schema and markdown reference file if the plugin does not define any permissions and delete those files if they exist. - [`5618f6d2`](https://www.github.com/tauri-apps/tauri/commit/5618f6d2ffc9ebf40710145538b06bebfa55f878)([#8856](https://www.github.com/tauri-apps/tauri/pull/8856)) Relax requirements on plugin's identifiers to be alphanumeric and `-` instead of only lower alpha and `-`. - [`8d16a80d`](https://www.github.com/tauri-apps/tauri/commit/8d16a80d2fb2468667e7987d0cc99dbc7e3b9d0a)([#8802](https://www.github.com/tauri-apps/tauri/pull/8802)) Refactored the capability types and resolution algorithm. ### Bug Fixes - [`ae0fe47c`](https://www.github.com/tauri-apps/tauri/commit/ae0fe47c4c35fa87c77acf42af32ef3f0615cb08)([#8774](https://www.github.com/tauri-apps/tauri/pull/8774)) Fix compile error when `tauri.conf.json` had `bundle > license` set. ### Breaking Changes - [`f284f9c5`](https://www.github.com/tauri-apps/tauri/commit/f284f9c545deeb77d15b6e8b1d0d05f49c40634c)([#8898](https://www.github.com/tauri-apps/tauri/pull/8898)) Changed the capability `remote` configuration to take a list of `urls` instead of `domains` for more flexibility. ## \[2.0.0-beta.1] ### Enhancements - [`4e101f80`](https://www.github.com/tauri-apps/tauri/commit/4e101f801657e7d01ce8c22f9c6468067d0caab2)([#8756](https://www.github.com/tauri-apps/tauri/pull/8756)) Moved the capability JSON schema to the `src-tauri/gen` folder so it's easier to track changes on the `capabilities` folder. ### Bug Fixes - [`4e101f80`](https://www.github.com/tauri-apps/tauri/commit/4e101f801657e7d01ce8c22f9c6468067d0caab2)([#8756](https://www.github.com/tauri-apps/tauri/pull/8756)) Rerun build script when a new permission is added. ## \[2.0.0-beta.0] ### New Features - [`74a2a603`](https://www.github.com/tauri-apps/tauri/commit/74a2a6036a5e57462f161d728cbd8a6f121028ca)([#8661](https://www.github.com/tauri-apps/tauri/pull/8661)) Implement access control list for IPC usage. - [`9eaeb5a8`](https://www.github.com/tauri-apps/tauri/commit/9eaeb5a8cd95ae24b5e66205bdc2763cb7f965ce)([#8622](https://www.github.com/tauri-apps/tauri/pull/8622)) Add `parent` option for window config. - [`58fe2e81`](https://www.github.com/tauri-apps/tauri/commit/58fe2e812a85b9f4eba105286a63f271ea637836)([#8670](https://www.github.com/tauri-apps/tauri/pull/8670)) Add `WebviewUrl::CustomProtocol` enum variant. ### What's Changed - [`6639a579`](https://www.github.com/tauri-apps/tauri/commit/6639a579c76d45210f33a72d37e21d4c5a9d334b)([#8441](https://www.github.com/tauri-apps/tauri/pull/8441)) Added the `WindowConfig::proxy_url` `WebviewBuilder::proxy_url() / WebviewWindowBuilder::proxy_url()` options when creating a webview. ### Breaking Changes - [`8de308d1`](https://www.github.com/tauri-apps/tauri/commit/8de308d1bf6a855d7a26af58bd0e744938ba47d8)([#8723](https://www.github.com/tauri-apps/tauri/pull/8723)) Restructured Tauri config per [RFC#5](https://github.com/tauri-apps/rfcs/blob/f3e82a6b0c5390401e855850d47dc7b7d9afd684/texts/0005-tauri-config-restructure.md): - Moved `package.productName`, `package.version` and `tauri.bundle.identifier` fields to the top-level. - Removed `package` object. - Renamed `tauri` object to `app`. - Moved `tauri.bundle` object to the top-level. - Renamed `build.distDir` field to `frontendDist`. - Renamed `build.devPath` field to `devUrl` and will no longer accepts paths, it will only accept URLs. - Moved `tauri.pattern` to `app.security.pattern`. - Removed `tauri.bundle.updater` object, and its fields have been moved to the updater plugin under `plugins.updater` object. - Moved `build.withGlobalTauri` to `app.withGlobalTauri`. - Moved `tauri.bundle.dmg` object to `bundle.macOS.dmg`. - Moved `tauri.bundle.deb` object to `bundle.linux.deb`. - Moved `tauri.bundle.appimage` object to `bundle.linux.appimage`. - Removed all license fields from each bundle configuration object and instead added `bundle.license` and `bundle.licenseFile`. - Renamed `AppUrl` to `FrontendDist` and refactored its variants to be more explicit. - [`c77b4032`](https://www.github.com/tauri-apps/tauri/commit/c77b40324ea9bf580871fc11aed69ba0c9b6b8cf)([#8280](https://www.github.com/tauri-apps/tauri/pull/8280)) Renamed `config::WindowUrl` to `config::WebviewUrl`. - [`a093682d`](https://www.github.com/tauri-apps/tauri/commit/a093682d2df7169b024bb4f736c7f1fd2ea8b327)([#8621](https://www.github.com/tauri-apps/tauri/pull/8621)) Changed `error` field in `ConfigError::FormatToml` to be boxed `Box` to reduce the enum `ConfigError` size in memory. - [`58fe2e81`](https://www.github.com/tauri-apps/tauri/commit/58fe2e812a85b9f4eba105286a63f271ea637836)([#8670](https://www.github.com/tauri-apps/tauri/pull/8670)) Changed `dist_dir` and `dev_path` config options to be optional. ## \[2.0.0-alpha.13] ### Bug Fixes - [`9b230de7`](https://www.github.com/tauri-apps/tauri/commit/9b230de7bc6690c2733f5324d50b999af1f7a6ef)([#8407](https://www.github.com/tauri-apps/tauri/pull/8407)) Fix compile error when parsing config that includes float values. ## \[2.0.0-alpha.12] ### New Features - [\`\`](https://www.github.com/tauri-apps/tauri/commit/undefined) Add bundle DMG configuration options. ## \[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 - [`c6c59cf2`](https://www.github.com/tauri-apps/tauri/commit/c6c59cf2373258b626b00a26f4de4331765dd487) Pull changes from Tauri 1.5 release. ### Dependencies - [`c7c2507d`](https://www.github.com/tauri-apps/tauri/commit/c7c2507da16a9beb71bf06745fe7ac1325ab7c2a)([#8035](https://www.github.com/tauri-apps/tauri/pull/8035)) Update `windows` to version `0.51` and `webview2-com` to version `0.27` ## \[2.0.0-alpha.9] ### New Features - [`c085adda`](https://www.github.com/tauri-apps/tauri/commit/c085addab58ba851398373c6fd13f9cb026d71e8)([#8009](https://www.github.com/tauri-apps/tauri/pull/8009)) Added `set_progress_bar` to `Window`. - [`c1ec0f15`](https://www.github.com/tauri-apps/tauri/commit/c1ec0f155118527361dd5645d920becbc8afd569)([#7933](https://www.github.com/tauri-apps/tauri/pull/7933)) Added the `always_on_bottom` option to the window configuration. - [`880266a7`](https://www.github.com/tauri-apps/tauri/commit/880266a7f697e1fe58d685de3bb6836ce5251e92)([#8031](https://www.github.com/tauri-apps/tauri/pull/8031)) Bump the MSRV to 1.70. - [`ed32257d`](https://www.github.com/tauri-apps/tauri/commit/ed32257d044f90b5eb15053efd1667125def2d2b)([#7794](https://www.github.com/tauri-apps/tauri/pull/7794)) On Windows, add `WindowEffect::Tabbed`,`WindowEffect::TabbedDark` and `WindowEffect::TabbedLight` ### Breaking Changes - [`ebcc21e4`](https://www.github.com/tauri-apps/tauri/commit/ebcc21e4b95f4e8c27639fb1bca545b432f52d5e)([#8057](https://www.github.com/tauri-apps/tauri/pull/8057)) Renamed the beforeDevCommand, beforeBuildCommand and beforeBundleCommand hooks environment variables from `TAURI_PLATFORM, TAURI_ARCH, TAURI_FAMILY, TAURI_PLATFORM_VERSION, TAURI_PLATFORM_TYPE and TAURI_DEBUG` to `TAURI_ENV_PLATFORM, TAURI_ENV_ARCH, TAURI_ENV_FAMILY, TAURI_ENV_PLATFORM_VERSION, TAURI_ENV_PLATFORM_TYPE and TAURI_ENV_DEBUG` to differentiate the prefix with other CLI environment variables. ## \[2.0.0-alpha.8] ### Enhancements - Add an option to specify `id` for the tray icon in the tauri configuration file. ### Breaking Changes - [`100d9ede`](https://www.github.com/tauri-apps/tauri/commit/100d9ede35995d9db21d2087dd5606adfafb89a5)([#7802](https://www.github.com/tauri-apps/tauri/pull/7802)) Follow file name conventions set by desktop for mobile Tauri configuration files. Added `target` argument on most `config::parse` methods. ## \[2.0.0-alpha.7] ### New Features - [`4db363a0`](https://www.github.com/tauri-apps/tauri/commit/4db363a03c182349f8491f46ced258d84723b11f)([#6589](https://www.github.com/tauri-apps/tauri/pull/6589)) Added `visible_on_all_workspaces` configuration option to `WindowBuilder`, `Window`, and `WindowConfig`. - [`7fb419c3`](https://www.github.com/tauri-apps/tauri/commit/7fb419c326aaf72ecd556d8404377444ebb200e7)([#7535](https://www.github.com/tauri-apps/tauri/pull/7535)) Add option to specify a tooltip text for the tray icon in the config. - [`74b1f4fc`](https://www.github.com/tauri-apps/tauri/commit/74b1f4fc6625d5b4f9b86f70e4eebd6551c61809)([#7384](https://www.github.com/tauri-apps/tauri/pull/7384)) Add `WindowEffect::MicaDark` and `WindowEffect::MicaLight` - [`3b98141a`](https://www.github.com/tauri-apps/tauri/commit/3b98141aa26f74c641a4090874247b97079bd58a)([#3736](https://www.github.com/tauri-apps/tauri/pull/3736)) Add a configuration object for file associations under `BundleConfig`. ### Enhancements - [`fbeb5b91`](https://www.github.com/tauri-apps/tauri/commit/fbeb5b9185baeda19e865228179e3e44c165f1d9)([#7170](https://www.github.com/tauri-apps/tauri/pull/7170)) Use custom protocols on the IPC implementation to enhance performance. ### Security fixes - [`43c6285e`](https://www.github.com/tauri-apps/tauri/commit/43c6285e9006fb84066461d57fe09ea8db76d636)([#7359](https://www.github.com/tauri-apps/tauri/pull/7359)) Changed HTML implementation from unmaintained `kuchiki` to `kuchikiki`. ### Breaking Changes - [`7fb419c3`](https://www.github.com/tauri-apps/tauri/commit/7fb419c326aaf72ecd556d8404377444ebb200e7)([#7535](https://www.github.com/tauri-apps/tauri/pull/7535)) `systemTray` config option has been renamed to `trayIcon`. ## \[2.0.0-alpha.6] ### New Features - [`e0f0dce2`](https://www.github.com/tauri-apps/tauri/commit/e0f0dce220730e2822fc202463aedf0166145de7)([#6442](https://www.github.com/tauri-apps/tauri/pull/6442)) Added the `window_effects` option to the window configuration. ## \[2.0.0-alpha.5] - [`9a79dc08`](https://www.github.com/tauri-apps/tauri/commit/9a79dc085870e0c1a5df13481ff271b8c6cc3b78)([#6947](https://www.github.com/tauri-apps/tauri/pull/6947)) Remove `enable_tauri_api` from the IPC scope. - [`09376af5`](https://www.github.com/tauri-apps/tauri/commit/09376af59424cc27803fa2820d2ac0d4cdc90a6d)([#6704](https://www.github.com/tauri-apps/tauri/pull/6704)) Moved the `cli` feature to its own plugin in the plugins-workspace repository. - [`e1e85dc2`](https://www.github.com/tauri-apps/tauri/commit/e1e85dc2a5f656fc37867e278cae8042037740ac)([#6925](https://www.github.com/tauri-apps/tauri/pull/6925)) Moved the `protocol` scope configuration to the `asset_protocol` field in `SecurityConfig`. - [`e1e85dc2`](https://www.github.com/tauri-apps/tauri/commit/e1e85dc2a5f656fc37867e278cae8042037740ac)([#6925](https://www.github.com/tauri-apps/tauri/pull/6925)) Moved the updater configuration to the `BundleConfig`. - [`b072daa3`](https://www.github.com/tauri-apps/tauri/commit/b072daa3bd3e38b808466666619ddb885052c5b2)([#6919](https://www.github.com/tauri-apps/tauri/pull/6919)) Moved the `updater` feature to its own plugin in the plugins-workspace repository. - [`3188f376`](https://www.github.com/tauri-apps/tauri/commit/3188f3764978c6d1452ee31d5a91469691e95094)([#6883](https://www.github.com/tauri-apps/tauri/pull/6883)) Bump the MSRV to 1.65. - [`e1e85dc2`](https://www.github.com/tauri-apps/tauri/commit/e1e85dc2a5f656fc37867e278cae8042037740ac)([#6925](https://www.github.com/tauri-apps/tauri/pull/6925)) Removed the allowlist configuration. - [`2d5378bf`](https://www.github.com/tauri-apps/tauri/commit/2d5378bfc1ba817ee2f331b41738a90e5997e5e8)([#6717](https://www.github.com/tauri-apps/tauri/pull/6717)) Remove the updater's dialog option. ## \[2.0.0-alpha.4] - Added `android` configuration object under `tauri > bundle`. - [db4c9dc6](https://www.github.com/tauri-apps/tauri/commit/db4c9dc655e07ee2184fe04571f500f7910890cd) feat(core): add option to configure Android's minimum SDK version ([#6651](https://www.github.com/tauri-apps/tauri/pull/6651)) on 2023-04-07 ## \[2.0.0-alpha.3] - Pull changes from Tauri 1.3 release. - [](https://www.github.com/tauri-apps/tauri/commit/undefined) on undefined ## \[2.0.0-alpha.2] - Added the `shadow` option to the window configuration and `set_shadow` option to the `window` allow list. - [a81750d7](https://www.github.com/tauri-apps/tauri/commit/a81750d779bc72f0fdb7de90b7fbddfd8049b328) feat(core): add shadow APIs ([#6206](https://www.github.com/tauri-apps/tauri/pull/6206)) on 2023-02-08 ## \[2.0.0-alpha.1] - Bump the MSRV to 1.64. - [7eb9aa75](https://www.github.com/tauri-apps/tauri/commit/7eb9aa75cfd6a3176d3f566fdda02d88aa529b0f) Update gtk to 0.16 ([#6155](https://www.github.com/tauri-apps/tauri/pull/6155)) on 2023-01-30 - Added `crate_name` field on `PackageInfo`. - [630a7f4b](https://www.github.com/tauri-apps/tauri/commit/630a7f4b18cef169bfd48673609306fec434e397) refactor: remove mobile log initialization, ref [#6049](https://www.github.com/tauri-apps/tauri/pull/6049) ([#6081](https://www.github.com/tauri-apps/tauri/pull/6081)) on 2023-01-17 ## \[2.0.0-alpha.0] - Parse `android` and `ios` Tauri configuration files. - [b3a3afc7](https://www.github.com/tauri-apps/tauri/commit/b3a3afc7de8de4021d73559288f5192732a706cf) feat(core): detect android and ios platform configuration files ([#4997](https://www.github.com/tauri-apps/tauri/pull/4997)) on 2022-08-22 - First mobile alpha release! - [fa3a1098](https://www.github.com/tauri-apps/tauri/commit/fa3a10988a03aed1b66fb17d893b1a9adb90f7cd) feat(ci): prepare 2.0.0-alpha.0 ([#5786](https://www.github.com/tauri-apps/tauri/pull/5786)) on 2022-12-08 ## \[1.5.3] ### New features - [`7aa30dec`](https://www.github.com/tauri-apps/tauri/commit/7aa30dec85a17c3d3faaf3841b93e10991b991b0)([#8620](https://www.github.com/tauri-apps/tauri/pull/8620)) Add `priority`, `section` and `changelog` options in Debian config. ## \[1.5.2] ### Bug Fixes - [`9b230de7`](https://www.github.com/tauri-apps/tauri/commit/9b230de7bc6690c2733f5324d50b999af1f7a6ef)([#8407](https://www.github.com/tauri-apps/tauri/pull/8407)) Fix compile error when parsing config that includes float values. ## \[1.5.3] ### New Features - [`b3e53e72`](https://www.github.com/tauri-apps/tauri/commit/b3e53e7243311a2659b7569dddc20c56ac9f9d8e)([#8288](https://www.github.com/tauri-apps/tauri/pull/8288)) Added `Assets::iter` to iterate on all embedded assets. ## \[1.5.0] ### New Features - [`4dd4893d`](https://www.github.com/tauri-apps/tauri/commit/4dd4893d7d166ac3a3b6dc2e3bd2540326352a78)([#5950](https://www.github.com/tauri-apps/tauri/pull/5950)) Allow specifying resources as a map specifying source and target paths. ### Enhancements - [`9aa34ada`](https://www.github.com/tauri-apps/tauri/commit/9aa34ada5769dbefa7dfe5f7a6288b3d20b294e4)([#7645](https://www.github.com/tauri-apps/tauri/pull/7645)) Add setting to switch to `http://.localhost/` for custom protocols on Windows. ### Bug Fixes - [`a6b52e44`](https://www.github.com/tauri-apps/tauri/commit/a6b52e44f22844009e273fb0250368d7a463f095)([#6519](https://www.github.com/tauri-apps/tauri/pull/6519)) Fix `io::read_line` not including the new line character `\n`. ### Security fixes - [`eeff1784`](https://www.github.com/tauri-apps/tauri/commit/eeff1784e1ffa568e4ba024e17dd611f8e086784)([#7367](https://www.github.com/tauri-apps/tauri/pull/7367)) Changed HTML implementation from unmaintained `kuchiki` to `kuchikiki`. ## \[1.4.0] ### New Features - [`acc36fe1`](https://www.github.com/tauri-apps/tauri/commit/acc36fe1176cc8aa9063bde932abeb94796c5c72)([#6158](https://www.github.com/tauri-apps/tauri/pull/6158)) Add option to configure `require_literal_leading_dot` on `fs` and `asset` protocol scopes. - [`35cd751a`](https://www.github.com/tauri-apps/tauri/commit/35cd751adc6fef1f792696fa0cfb471b0bf99374)([#5176](https://www.github.com/tauri-apps/tauri/pull/5176)) Added the `desktop_template` option on `tauri.conf.json > tauri > bundle > deb`. - [`c4d6fb4b`](https://www.github.com/tauri-apps/tauri/commit/c4d6fb4b1ea8acf02707a9fe5dcab47c1c5bae7b)([#2353](https://www.github.com/tauri-apps/tauri/pull/2353)) Added the `maximizable`, `minimizable` and `closable` options to the window configuration. - [`3cb7a3e6`](https://www.github.com/tauri-apps/tauri/commit/3cb7a3e642bb10ee90dc1d24daa48b8c8c15c9ce)([#6997](https://www.github.com/tauri-apps/tauri/pull/6997)) Add `MimeType::parse_with_fallback` and `MimeType::parse_from_uri_with_fallback` - [`29488205`](https://www.github.com/tauri-apps/tauri/commit/2948820579d20dfaa0861c2f0a58bd7737a7ffd1)([#6867](https://www.github.com/tauri-apps/tauri/pull/6867)) Allow specifying custom language files of Tauri's custom messages for the NSIS installer - [`e092f799`](https://www.github.com/tauri-apps/tauri/commit/e092f799469ff32c7d1595d0f07d06fd2dab5c29)([#6887](https://www.github.com/tauri-apps/tauri/pull/6887)) Add `nsis > template` option to specify custom NSIS installer template. - [`cd3846c8`](https://www.github.com/tauri-apps/tauri/commit/cd3846c8ce61ab2879b3911e831525e6242aaab2)([#6955](https://www.github.com/tauri-apps/tauri/pull/6955)) Add `WindowsUpdateInstallMode::nsis_args` - [`85e77fb7`](https://www.github.com/tauri-apps/tauri/commit/85e77fb797ec17882f55d0944578d929fc6c9c1f)([#6762](https://www.github.com/tauri-apps/tauri/pull/6762)) Correctly determine MIME type of `.txt` files. ## \[1.3.0] - Added the `additional_browser_args` option to the window configuration. - [3dc38b15](https://www.github.com/tauri-apps/tauri/commit/3dc38b150ea8c59c8ba67fd586f921016928f47c) feat(core): expose additional_browser_args to window config (fix: [#5757](https://www.github.com/tauri-apps/tauri/pull/5757)) ([#5799](https://www.github.com/tauri-apps/tauri/pull/5799)) on 2022-12-14 - Added the `content_protected` option to the window configuration. - [4ab5545b](https://www.github.com/tauri-apps/tauri/commit/4ab5545b7a831c549f3c65e74de487ede3ab7ce5) feat: add content protection api, closes [#5132](https://www.github.com/tauri-apps/tauri/pull/5132) ([#5513](https://www.github.com/tauri-apps/tauri/pull/5513)) on 2022-12-13 - Correctly determine mime type of `.less`, `.sass` and `.styl` files. - [5fdf8dcb](https://www.github.com/tauri-apps/tauri/commit/5fdf8dcb8ed171d06121dceb32078a7e4f86cc64) fix(core): mime type of .less, .sass and .styl files ([#6316](https://www.github.com/tauri-apps/tauri/pull/6316)) on 2023-02-19 - Bump minimum supported Rust version to 1.60. - [5fdc616d](https://www.github.com/tauri-apps/tauri/commit/5fdc616df9bea633810dcb814ac615911d77222c) feat: Use the zbus-backed of notify-rust ([#6332](https://www.github.com/tauri-apps/tauri/pull/6332)) on 2023-03-31 - Add initial support for building `nsis` bundles on non-Windows platforms. - [60e6f6c3](https://www.github.com/tauri-apps/tauri/commit/60e6f6c3f1605f3064b5bb177992530ff788ccf0) feat(bundler): Add support for creating NSIS bundles on unix hosts ([#5788](https://www.github.com/tauri-apps/tauri/pull/5788)) on 2023-01-19 - Add `nsis` bundle target - [c94e1326](https://www.github.com/tauri-apps/tauri/commit/c94e1326a7c0767a13128a8b1d327a00156ece12) feat(bundler): add `nsis`, closes [#4450](https://www.github.com/tauri-apps/tauri/pull/4450), closes [#2319](https://www.github.com/tauri-apps/tauri/pull/2319) ([#4674](https://www.github.com/tauri-apps/tauri/pull/4674)) on 2023-01-03 - Added configuration to specify remote URLs allowed to access the IPC. - [ee71c31f](https://www.github.com/tauri-apps/tauri/commit/ee71c31fd09cc5427da6d29d37c003a914547696) feat(core): allow configuring remote domains with IPC access, closes [#5088](https://www.github.com/tauri-apps/tauri/pull/5088) ([#5918](https://www.github.com/tauri-apps/tauri/pull/5918)) on 2023-04-11 ## \[1.2.1] - Fix `allowlist > app > show/hide` always disabled when `allowlist > app > all: false`. - [bb251087](https://www.github.com/tauri-apps/tauri/commit/bb2510876d0bdff736d36bf3a465cdbe4ad2b90c) fix(core): extend allowlist with `app`'s allowlist, closes [#5650](https://www.github.com/tauri-apps/tauri/pull/5650) ([#5652](https://www.github.com/tauri-apps/tauri/pull/5652)) on 2022-11-18 ## \[1.2.0] - Validate `package > productName` in the tauri config and produce errors if it contains one of the following characters `/\:*?\"<>|` - [b9316a64](https://www.github.com/tauri-apps/tauri/commit/b9316a64eaa9348c79efafb8b94960d9b4d5b27a) fix(cli): validate `productName` in config, closes [#5233](https://www.github.com/tauri-apps/tauri/pull/5233) ([#5262](https://www.github.com/tauri-apps/tauri/pull/5262)) on 2022-09-28 - Properly serialize HTML template tags. - [aec5537d](https://www.github.com/tauri-apps/tauri/commit/aec5537de0205f62b2ae5c89da04d21930a6fc2e) fix(codegen): serialize template tags, closes [#4410](https://www.github.com/tauri-apps/tauri/pull/4410) ([#5247](https://www.github.com/tauri-apps/tauri/pull/5247)) on 2022-09-28 - `PatternKind::Isolation` is now defined even without the `isolation` feature. - [a178f95d](https://www.github.com/tauri-apps/tauri/commit/a178f95d68b773779b40235a3a22115a5e36aa6a) feat: config schema generator ([#5193](https://www.github.com/tauri-apps/tauri/pull/5193)) on 2022-10-28 - Added the `app` allowlist module. - [39bf895b](https://www.github.com/tauri-apps/tauri/commit/39bf895b73ec6b53f5758815396ba85dda6b9c67) feat(macOS): Add application `show` and `hide` methods ([#3689](https://www.github.com/tauri-apps/tauri/pull/3689)) on 2022-10-03 - - [7d9aa398](https://www.github.com/tauri-apps/tauri/commit/7d9aa3987efce2d697179ffc33646d086c68030c) feat: bump MSRV to 1.59 ([#5296](https://www.github.com/tauri-apps/tauri/pull/5296)) on 2022-09-28 - Add `tauri.conf.json > bundle > publisher` field to specify the app publisher. - [628285c1](https://www.github.com/tauri-apps/tauri/commit/628285c1cf43f03ed62378f3b6cc0c991317526f) feat(bundler): add `publisher` field, closes [#5273](https://www.github.com/tauri-apps/tauri/pull/5273) ([#5283](https://www.github.com/tauri-apps/tauri/pull/5283)) on 2022-09-28 - Canonicalize the return value of `platform::resource_dir`. - [a06dc699](https://www.github.com/tauri-apps/tauri/commit/a06dc6993148f10ff7623c9dcc81f313dd960ad0) fix(core): canonicalize resource dir to fix scope check, closes [#5196](https://www.github.com/tauri-apps/tauri/pull/5196) ([#5218](https://www.github.com/tauri-apps/tauri/pull/5218)) on 2022-09-29 - Added `title` option on the system tray configuration (macOS only). - [8f1ace77](https://www.github.com/tauri-apps/tauri/commit/8f1ace77956ac3477826ceb059a191e55b3fff93) feat: expose `set_title` for MacOS tray ([#5182](https://www.github.com/tauri-apps/tauri/pull/5182)) on 2022-09-30 - Added the `user_agent` option to the window configuration. - [a6c94119](https://www.github.com/tauri-apps/tauri/commit/a6c94119d8545d509723b147c273ca5edfe3729f) feat(core): expose user_agent to window config ([#5317](https://www.github.com/tauri-apps/tauri/pull/5317)) on 2022-10-02 - Add `mime_type` module. - [54c337e0](https://www.github.com/tauri-apps/tauri/commit/54c337e06f3bc624c4780cf002bc54790f446c90) feat(cli): hotreload support for frontend static files, closes [#2173](https://www.github.com/tauri-apps/tauri/pull/2173) ([#5256](https://www.github.com/tauri-apps/tauri/pull/5256)) on 2022-09-28 ## \[1.1.1] - Add missing allowlist config for `set_cursor_grab`, `set_cursor_visible`, `set_cursor_icon` and `set_cursor_position` APIs. - [c764408d](https://www.github.com/tauri-apps/tauri/commit/c764408da7fae123edd41115bda42fa75a4731d2) fix: Add missing allowlist config for cursor apis, closes [#5207](https://www.github.com/tauri-apps/tauri/pull/5207) ([#5211](https://www.github.com/tauri-apps/tauri/pull/5211)) on 2022-09-16 ## \[1.1.0] - Allow adding `build > beforeBundleCommand` in tauri.conf.json to run a shell command before the bundling phase. - [57ab9847](https://www.github.com/tauri-apps/tauri/commit/57ab9847eb2d8c9a5da584b873b7c072e9ee26bf) feat(cli): add `beforeBundleCommand`, closes [#4879](https://www.github.com/tauri-apps/tauri/pull/4879) ([#4893](https://www.github.com/tauri-apps/tauri/pull/4893)) on 2022-08-09 - Change `before_dev_command` and `before_build_command` config value to allow configuring the current working directory. - [d6f7d3cf](https://www.github.com/tauri-apps/tauri/commit/d6f7d3cfe8a7ec8d68c8341016c4e0a3103da587) Add cwd option to `before` commands, add wait option to dev [#4740](https://www.github.com/tauri-apps/tauri/pull/4740) [#3551](https://www.github.com/tauri-apps/tauri/pull/3551) ([#4834](https://www.github.com/tauri-apps/tauri/pull/4834)) on 2022-08-02 - Allow configuring the `before_dev_command` to force the CLI to wait for the command to finish before proceeding. - [d6f7d3cf](https://www.github.com/tauri-apps/tauri/commit/d6f7d3cfe8a7ec8d68c8341016c4e0a3103da587) Add cwd option to `before` commands, add wait option to dev [#4740](https://www.github.com/tauri-apps/tauri/pull/4740) [#3551](https://www.github.com/tauri-apps/tauri/pull/3551) ([#4834](https://www.github.com/tauri-apps/tauri/pull/4834)) on 2022-08-02 - Added support to configuration files in TOML format (Tauri.toml file). - [ae83d008](https://www.github.com/tauri-apps/tauri/commit/ae83d008f9e1b89bfc8dddaca42aa5c1fbc36f6d) feat: add support to TOML config file `Tauri.toml`, closes [#4806](https://www.github.com/tauri-apps/tauri/pull/4806) ([#4813](https://www.github.com/tauri-apps/tauri/pull/4813)) on 2022-08-02 - Refactored the `config::parse` module. - [ae83d008](https://www.github.com/tauri-apps/tauri/commit/ae83d008f9e1b89bfc8dddaca42aa5c1fbc36f6d) feat: add support to TOML config file `Tauri.toml`, closes [#4806](https://www.github.com/tauri-apps/tauri/pull/4806) ([#4813](https://www.github.com/tauri-apps/tauri/pull/4813)) on 2022-08-02 - Update windows to 0.39.0 and webview2-com to 0.19.1. - [e6d9b670](https://www.github.com/tauri-apps/tauri/commit/e6d9b670b0b314ed667b0e164f2c8d27048e678f) refactor: remove unneeded focus code ([#5065](https://www.github.com/tauri-apps/tauri/pull/5065)) on 2022-09-03 ## \[1.0.3] - Added `menu_on_left_click: bool` to the `SystemTrayConfig`. - [f8a3becb](https://www.github.com/tauri-apps/tauri/commit/f8a3becb287942db7f7b551b5db6aeb5a2e939ee) feat(core): add option to disable tray menu on left click, closes [#4584](https://www.github.com/tauri-apps/tauri/pull/4584) ([#4587](https://www.github.com/tauri-apps/tauri/pull/4587)) on 2022-07-05 - Added `config::parse::read_platform` and `config::parse::get_platform_config_filename`. - [8e3e7fc6](https://www.github.com/tauri-apps/tauri/commit/8e3e7fc64641afc7a6833bc93205e6f525562545) feat(cli): improve bundle identifier validation, closes [#4589](https://www.github.com/tauri-apps/tauri/pull/4589) ([#4596](https://www.github.com/tauri-apps/tauri/pull/4596)) on 2022-07-05 ## \[1.0.2] - Expose `platform::windows_version` function. - [bf764e83](https://www.github.com/tauri-apps/tauri/commit/bf764e83e01e7443e6cc54572001e1c98c357465) feat(utils): expose `windows_version` function ([#4534](https://www.github.com/tauri-apps/tauri/pull/4534)) on 2022-06-30 ## \[1.0.1] - Changed the `BundleConfig::targets` to a `BundleTarget` enum to enhance generated documentation. - [31c15cd2](https://www.github.com/tauri-apps/tauri/commit/31c15cd2bd94dbe39fb94982a15cbe02ac5d8925) docs(config): enhance documentation for bundle targets, closes [#3251](https://www.github.com/tauri-apps/tauri/pull/3251) ([#4418](https://www.github.com/tauri-apps/tauri/pull/4418)) on 2022-06-21 - Added `platform::is_windows_7`. - [57039fb2](https://www.github.com/tauri-apps/tauri/commit/57039fb2166571de85271b014a8711a29f06be1a) fix(core): add windows 7 notification support ([#4491](https://www.github.com/tauri-apps/tauri/pull/4491)) on 2022-06-28 - Suppress unused variable warning in release builds. - [45981851](https://www.github.com/tauri-apps/tauri/commit/45981851e35119266c1a079e1ff27a39f1fdfaed) chore(lint): unused variable warnings for release builds ([#4411](https://www.github.com/tauri-apps/tauri/pull/4411)) on 2022-06-22 - Added webview install mode options. - [2ca762d2](https://www.github.com/tauri-apps/tauri/commit/2ca762d207030a892a6d128b519e150e2d733468) feat(bundler): extend webview2 installation options, closes [#2882](https://www.github.com/tauri-apps/tauri/pull/2882) [#2452](https://www.github.com/tauri-apps/tauri/pull/2452) ([#4466](https://www.github.com/tauri-apps/tauri/pull/4466)) on 2022-06-26 ## \[1.0.0] - Upgrade to `stable`! - [f4bb30cc](https://www.github.com/tauri-apps/tauri/commit/f4bb30cc73d6ba9b9ef19ef004dc5e8e6bb901d3) feat(covector): prepare for v1 ([#4351](https://www.github.com/tauri-apps/tauri/pull/4351)) on 2022-06-15 ## \[1.0.0-rc.9] - Added a config flag to bundle the media framework used by webkit2gtk `tauri.conf.json > tauri > bundle > appimage > bundleMediaFramework`. - [d335fae9](https://www.github.com/tauri-apps/tauri/commit/d335fae92cdcbb0ee18aad4e54558914afa3e778) feat(bundler): bundle additional gstreamer files, closes [#4092](https://www.github.com/tauri-apps/tauri/pull/4092) ([#4271](https://www.github.com/tauri-apps/tauri/pull/4271)) on 2022-06-10 ## \[1.0.0-rc.8] - **Breaking change:** `PackageInfo::version` is now a `semver::Version` instead of a `String`. - [2badbd2d](https://www.github.com/tauri-apps/tauri/commit/2badbd2d7ed51bf33c1b547b4c837b600574bd4a) refactor: force semver versions, change updater `should_install` sig ([#4215](https://www.github.com/tauri-apps/tauri/pull/4215)) on 2022-05-25 - [a7388e23](https://www.github.com/tauri-apps/tauri/commit/a7388e23c3b9019d48b078cae00a75c74d74d11b) fix(ci): adjust change file to include tauri-utils and tauri-codegen on 2022-05-27 ## \[1.0.0-rc.7] - Allow configuring the display options for the MSI execution allowing quieter updates. - [9f2c3413](https://www.github.com/tauri-apps/tauri/commit/9f2c34131952ea83c3f8e383bc3cec7e1450429f) feat(core): configure msiexec display options, closes [#3951](https://www.github.com/tauri-apps/tauri/pull/3951) ([#4061](https://www.github.com/tauri-apps/tauri/pull/4061)) on 2022-05-15 ## \[1.0.0-rc.6] - Added `$schema` support to `tauri.conf.json`. - [715cbde3](https://www.github.com/tauri-apps/tauri/commit/715cbde3842a916c4ebeab2cab348e1774b5c192) feat(config): add `$schema` to `tauri.conf.json`, closes [#3464](https://www.github.com/tauri-apps/tauri/pull/3464) ([#4031](https://www.github.com/tauri-apps/tauri/pull/4031)) on 2022-05-03 - The `dangerous_allow_asset_csp_modification` configuration value has been changed to allow a list of CSP directives to disable. - [164078c0](https://www.github.com/tauri-apps/tauri/commit/164078c0b719ccbc12e956fecf8a7d4a3c5044e1) feat: allow limiting dangerousDisableAssetCspModification, closes [#3831](https://www.github.com/tauri-apps/tauri/pull/3831) ([#4021](https://www.github.com/tauri-apps/tauri/pull/4021)) on 2022-05-02 ## \[1.0.0-rc.5] - Added the `io` module with the `read_line` method. - [b5622882](https://www.github.com/tauri-apps/tauri/commit/b5622882cf3748e1e5a90915f415c0cd922aaaf8) fix(cli): exit on non-compilation Cargo errors, closes [#3930](https://www.github.com/tauri-apps/tauri/pull/3930) ([#3942](https://www.github.com/tauri-apps/tauri/pull/3942)) on 2022-04-22 - **Breaking change:** Removed the `useBootstrapper` option. Use https://github.com/tauri-apps/fix-path-env-rs instead. - [6a5ff08c](https://www.github.com/tauri-apps/tauri/commit/6a5ff08ce9052b656aa40accedfd4315825164a3) refactor: remove bootstrapper, closes [#3786](https://www.github.com/tauri-apps/tauri/pull/3786) ([#3832](https://www.github.com/tauri-apps/tauri/pull/3832)) on 2022-03-31 ## \[1.0.0-rc.4] - Added an option to disable the CSP injection of distributable assets nonces and hashes. - [f6e32ee1](https://www.github.com/tauri-apps/tauri/commit/f6e32ee1880eb364ed76beb937c9d12e14d54910) feat(core): add dangerous option to disable compile time CSP injection ([#3775](https://www.github.com/tauri-apps/tauri/pull/3775)) on 2022-03-28 - Use the default value for `MacConfig.minimumSystemVersion` if the value is set to an empty string. - [c81534eb](https://www.github.com/tauri-apps/tauri/commit/c81534ebd873c358e0346c7949aeb171803149a5) feat(cli): use default macOS minimum system version when it is empty ([#3658](https://www.github.com/tauri-apps/tauri/pull/3658)) on 2022-03-13 - Replace multiple dependencies who's C code compiled concurrently and caused the other ones to bloat compile time significantly. - `zstd` -> `brotli` - `blake3` -> a vendored version of the blake3 reference - `ring` -> `getrandom` See https://github.com/tauri-apps/tauri/pull/3773 for more information about these specific choices. - [8661e3e2](https://www.github.com/tauri-apps/tauri/commit/8661e3e24d96c399bfbcdee5d8e9d6beba2265a7) replace dependencies with long build times when used together (closes [#3571](https://www.github.com/tauri-apps/tauri/pull/3571)) ([#3773](https://www.github.com/tauri-apps/tauri/pull/3773)) on 2022-03-27 ## \[1.0.0-rc.3] - Use `is_symlink` API compatible with Rust v1.57 instead of std/fs/struct.Metadata.html#method.is_symlink. - [73388119](https://www.github.com/tauri-apps/tauri/commit/73388119e653e7902b19beef2ab6d7c5f8a7b83a) use older symlink check function ([#3579](https://www.github.com/tauri-apps/tauri/pull/3579)) on 2022-03-01 ## \[1.0.0-rc.2] - Changed the default value for `tauri > bundle > macOS > minimumSystemVersion` to `10.13`. - [fce344b9](https://www.github.com/tauri-apps/tauri/commit/fce344b90b7227f8f5514853c2f885fb24d3648e) feat(core): set default value for `minimum_system_version` to 10.13 ([#3497](https://www.github.com/tauri-apps/tauri/pull/3497)) on 2022-02-17 ## \[1.0.0-rc.1] - Change default value for the `freezePrototype` configuration to `false`. - [3a4c0160](https://www.github.com/tauri-apps/tauri/commit/3a4c01606184be762adee055ddac803de0d28527) fix(core): change default `freezePrototype` to false, closes [#3416](https://www.github.com/tauri-apps/tauri/pull/3416) [#3406](https://www.github.com/tauri-apps/tauri/pull/3406) ([#3423](https://www.github.com/tauri-apps/tauri/pull/3423)) on 2022-02-12 ## \[1.0.0-rc.0] - The `allowlist` configuration now includes a `clipboard` object, controlling the exposure of the `writeText` and `readText` APIs. - [d660cab3](https://www.github.com/tauri-apps/tauri/commit/d660cab38d7d703e8b2bb85a3e9462d9e28b086b) feat: enhance allowlist configuration \[TRI-027] ([#11](https://www.github.com/tauri-apps/tauri/pull/11)) on 2022-01-09 - The dialog allowlist now includes flags for the `message`, `ask` and `confirm` APIs. - [d660cab3](https://www.github.com/tauri-apps/tauri/commit/d660cab38d7d703e8b2bb85a3e9462d9e28b086b) feat: enhance allowlist configuration \[TRI-027] ([#11](https://www.github.com/tauri-apps/tauri/pull/11)) on 2022-01-09 - The `allowlist` configuration now includes a `process` object, controlling the exposure of the `relaunch` and `exit` APIs. - [d660cab3](https://www.github.com/tauri-apps/tauri/commit/d660cab38d7d703e8b2bb85a3e9462d9e28b086b) feat: enhance allowlist configuration \[TRI-027] ([#11](https://www.github.com/tauri-apps/tauri/pull/11)) on 2022-01-09 - The `window` allowlist now includes options to enable all window modification APIs: `center`, `close`, `create`, `hide`, `maximize`, `minimize`, `print`, `requestUserAttention`, `setAlwaysOnTop`, `setDecorations`, `setFocus`, `setFullscreen`, `setIcon`, `setMaxSize`, `setMinSize`, `setPosition`, `setResizable`, `setSize`, `setSkipTaskbar`, `setTitle`, `show`, `startDragging`, `unmaximize` and `unminimize`. - [d660cab3](https://www.github.com/tauri-apps/tauri/commit/d660cab38d7d703e8b2bb85a3e9462d9e28b086b) feat: enhance allowlist configuration \[TRI-027] ([#11](https://www.github.com/tauri-apps/tauri/pull/11)) on 2022-01-09 - Added `asset` allowlist configuration, which enables the `asset` protocol and defines it access scope. - [7920ff14](https://www.github.com/tauri-apps/tauri/commit/7920ff14e6424079c48ea5645d9aa13e7a272b87) feat: scope the `fs` API and the `asset` protocol \[TRI-026] \[TRI-010] \[TRI-011] ([#10](https://www.github.com/tauri-apps/tauri/pull/10)) on 2022-01-09 - Change `CliArg` numeric types from `u64` to `usize`. - [1f988535](https://www.github.com/tauri-apps/tauri/commit/1f98853573a837dd0cfc2161b206a5033ec2da5e) chore(deps) Update Tauri Core ([#2480](https://www.github.com/tauri-apps/tauri/pull/2480)) on 2021-08-24 - Apply `nonce` to `script` and `style` tags and set them on the `CSP` (`script-src` and `style-src` fetch directives). - [cf54dcf9](https://www.github.com/tauri-apps/tauri/commit/cf54dcf9c81730e42c9171daa9c8aa474c95b522) feat: improve `CSP` security with nonces and hashes, add `devCsp` \[TRI-004] ([#8](https://www.github.com/tauri-apps/tauri/pull/8)) on 2022-01-09 - The path returned from `tauri::api::process::current_binary` is now cached when loading the binary. - [7c3db7a3](https://www.github.com/tauri-apps/tauri/commit/7c3db7a3811fd4de3e71c78cfd00894fa51ab786) cache current binary path much sooner ([#45](https://www.github.com/tauri-apps/tauri/pull/45)) on 2022-02-01 - Added `dev_csp` to the `security` configuration object. - [cf54dcf9](https://www.github.com/tauri-apps/tauri/commit/cf54dcf9c81730e42c9171daa9c8aa474c95b522) feat: improve `CSP` security with nonces and hashes, add `devCsp` \[TRI-004] ([#8](https://www.github.com/tauri-apps/tauri/pull/8)) on 2022-01-09 - Fixes resource directory resolution on Linux. - [1a28904b](https://www.github.com/tauri-apps/tauri/commit/1a28904b8ebea92e143d5dc21ebd209e9edec531) fix(core): resource path resolution on Linux, closes [#2493](https://www.github.com/tauri-apps/tauri/pull/2493) on 2021-08-22 - Allow using a fixed version for the Webview2 runtime via the `tauri > bundle > windows > webviewFixedRuntimePath` config option. - [85df94f2](https://www.github.com/tauri-apps/tauri/commit/85df94f2b0d40255812b42c5e32a70c4b45392df) feat(core): config for fixed webview2 runtime version path ([#27](https://www.github.com/tauri-apps/tauri/pull/27)) on 2021-11-02 - The updater `pubkey` is now a required field for security reasons. Sign your updates with the `tauri signer` command. - [d95cc831](https://www.github.com/tauri-apps/tauri/commit/d95cc83105dda52df7514e30e54f3676cdb374ee) feat: enforce updater public key \[TRI-015] ([#42](https://www.github.com/tauri-apps/tauri/pull/42)) on 2022-01-09 - Added the `isolation` pattern. - [d5d6d2ab](https://www.github.com/tauri-apps/tauri/commit/d5d6d2abc17cd89c3a079d2ce01581193469dbc0) Isolation Pattern ([#43](https://www.github.com/tauri-apps/tauri/pull/43)) Co-authored-by: Ngo Iok Ui (Wu Yu Wei) Co-authored-by: Lucas Fernandes Nogueira on 2022-01-17 - Adds support for using JSON5 format for the `tauri.conf.json` file, along with also supporting the `.json5` extension. Here is the logic flow that determines if JSON or JSON5 will be used to parse the config: 1. Check if `tauri.conf.json` exists a. Parse it with `serde_json` b. Parse it with `json5` if `serde_json` fails c. Return original `serde_json` error if all above steps failed 2. Check if `tauri.conf.json5` exists a. Parse it with `json5` b. Return error if all above steps failed 3. Return error if all above steps failed - [995de57a](https://www.github.com/tauri-apps/tauri/commit/995de57a76cf51215277673e526d7ec32b86b564) Add seamless support for using JSON5 in the config file ([#47](https://www.github.com/tauri-apps/tauri/pull/47)) on 2022-02-03 - Move the copying of resources and sidecars from `cli.rs` to `tauri-build` so using the Cargo CLI directly processes the files for the application execution in development. - [5eb72c24](https://www.github.com/tauri-apps/tauri/commit/5eb72c24deddf5a01093bea96b90c0d8806afc3f) refactor: copy resources and sidecars on the Cargo build script ([#3357](https://www.github.com/tauri-apps/tauri/pull/3357)) on 2022-02-08 - **Breaking change**\* Remove default webview window when `tauri.conf.json > tauri > windows` is not set. - [c119060e](https://www.github.com/tauri-apps/tauri/commit/c119060e3d9a5a824639fb6b3c45a87e7a62e4e2) refactor(core): empty default value for config > tauri > windows ([#3380](https://www.github.com/tauri-apps/tauri/pull/3380)) on 2022-02-10 - The minimum Rust version is now `1.56`. - [a9dfc015](https://www.github.com/tauri-apps/tauri/commit/a9dfc015505afe91281c2027954ffcc588b1a59c) feat: update to edition 2021 and set minimum rust to 1.56 ([#2789](https://www.github.com/tauri-apps/tauri/pull/2789)) on 2021-10-22 - Adds `scope` glob array config under `tauri > allowlist > fs`. Adds `assetScope` glob array config under `tauri > allowlist > protocol`. Adds `scope` URL array config under `tauri > allowlist > http`. - [7920ff14](https://www.github.com/tauri-apps/tauri/commit/7920ff14e6424079c48ea5645d9aa13e7a272b87) feat: scope the `fs` API and the `asset` protocol \[TRI-026] \[TRI-010] \[TRI-011] ([#10](https://www.github.com/tauri-apps/tauri/pull/10)) on 2022-01-09 - [0ad1c651](https://www.github.com/tauri-apps/tauri/commit/0ad1c6515f696fadefddbf133a9561836b3d5934) feat(core): add `http` allowlist scope \[TRI-008] ([#24](https://www.github.com/tauri-apps/tauri/pull/24)) on 2021-10-29 - The `shell` allowlist now includes a `sidecar` flag, which enables the use of the `shell` API to execute sidecars. - [eed01728](https://www.github.com/tauri-apps/tauri/commit/eed017287fed2ade689af4268e8b63b9c9f2e585) feat(core): add `shell > sidecar` allowlist and `process` feature flag \[TRI-037] ([#18](https://www.github.com/tauri-apps/tauri/pull/18)) on 2021-10-24 - Force updater endpoint URL to use `https` on release builds. - [c077f449](https://www.github.com/tauri-apps/tauri/commit/c077f449270cffbf7956b1af81e1fb237ebf564a) feat: force endpoint URL to use https on release \[TRI-015] ([#41](https://www.github.com/tauri-apps/tauri/pull/41)) on 2022-01-09 ## \[1.0.0-beta.3] - Fixes minimum window height being used as maximum height. - [e3f99165](https://www.github.com/tauri-apps/tauri/commit/e3f9916526b226866137cb663e5cafab2b6a0e01) fix(core) minHeight being used as maxHeight ([#2247](https://www.github.com/tauri-apps/tauri/pull/2247)) on 2021-07-19 - Implement `Debug` on public API structs and enums. - [fa9341ba](https://www.github.com/tauri-apps/tauri/commit/fa9341ba18ba227735341530900714dba0f27291) feat(core): implement `Debug` on public API structs/enums, closes [#2292](https://www.github.com/tauri-apps/tauri/pull/2292) ([#2387](https://www.github.com/tauri-apps/tauri/pull/2387)) on 2021-08-11 - Keep original value on `config > package > productName` on Linux (previously converted to kebab-case). - [3f039cb8](https://www.github.com/tauri-apps/tauri/commit/3f039cb8a308b0f18deaa37d7cfb1cc50d308d0e) fix: keep original `productName` for .desktop `Name` field, closes [#2295](https://www.github.com/tauri-apps/tauri/pull/2295) ([#2384](https://www.github.com/tauri-apps/tauri/pull/2384)) on 2021-08-10 - Inject the invoke key on regular `` tags. - [d0142e87](https://www.github.com/tauri-apps/tauri/commit/d0142e87ddf5231fd46e2cbe4769bb16f3fe01e9) fix(core): invoke key injection on regular JS scripts, closes [#2342](https://www.github.com/tauri-apps/tauri/pull/2342) ([#2344](https://www.github.com/tauri-apps/tauri/pull/2344)) on 2021-08-03 ## \[1.0.0-beta.2] - Inject invoke key on `script` tags with `type="module"`. - [f03eea9c](https://www.github.com/tauri-apps/tauri/commit/f03eea9c9b964709532afbc4d1dd343b3fd96081) feat(core): inject invoke key on ` ================================================ FILE: examples/api/isolation-dist/index.html ================================================ Isolation Secure Script ================================================ FILE: examples/api/isolation-dist/index.js ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT window.__TAURI_ISOLATION_HOOK__ = (payload, options) => { return payload } ================================================ FILE: examples/api/jsconfig.json ================================================ { "compilerOptions": { "moduleResolution": "bundler", "target": "ESNext", "module": "ESNext", /** * svelte-preprocess cannot figure out whether you have * a value or a type, so tell TypeScript to enforce using * `import type` instead of `import` for Types. */ "verbatimModuleSyntax": true, "isolatedModules": true, "resolveJsonModule": true, /** * To have warnings / errors of the Svelte compiler at the * correct position, enable source maps by default. */ "sourceMap": true, "esModuleInterop": true, "skipLibCheck": true, /** * Typecheck JS in `.svelte` and `.js` files by default. * Disable this if you'd like to use dynamic types. */ "checkJs": true }, /** * Use global.d.ts instead of compilerOptions.types * to avoid limiting type declarations. */ "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"] } ================================================ FILE: examples/api/package.json ================================================ { "name": "api", "private": true, "version": "1.0.0", "type": "module", "scripts": { "dev": "vite", "build": "vite build", "preview": "vite preview", "tauri": "node ../../packages/cli/tauri.js" }, "dependencies": { "@tauri-apps/api": "../../packages/api/dist" }, "devDependencies": { "@iconify-json/codicon": "^1.2.49", "@iconify-json/ph": "^1.2.2", "@sveltejs/vite-plugin-svelte": "^7.0.0", "@unocss/extractor-svelte": "^66.6.6", "svelte": "^5.53.11", "unocss": "^66.6.6", "vite": "^8.0.0" } } ================================================ FILE: examples/api/src/App.svelte ================================================

{selected.label}

Console

(e.key === 'Enter' ? clear() : {})} onclick={clear} >
{#each $messages as r} {@html r.html} {/each}
================================================ FILE: examples/api/src/app.css ================================================ :root { line-height: 1.5; } input, select { min-width: 0; } *:not(h1, h2, h3, h4, h5, h6) { margin: 0; padding: 0; } * { box-sizing: border-box; font-family: 'Rubik', sans-serif; } ::-webkit-scrollbar { width: 0.25rem; height: 3px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { border-radius: 0.25rem; } code { padding: 0.05rem 0.25rem; } code.code-block { padding: 0.5rem; } #sidebar { width: 18.75rem; } @media screen and (max-width: 640px) { #sidebar { --translate-x: -18.75rem; transform: translateX(var(--translate-x)); } } ================================================ FILE: examples/api/src/components/MenuBuilder.svelte ================================================
{#each items as item}

{itemToString(item)}

{/each}
================================================ FILE: examples/api/src/components/MenuItemBuilder.svelte ================================================
{#each itemKinds as itemKind, i}
{/each}
{#if kind == 'Normal' || kind == 'Icon' || kind == 'Check'} {/if} {#if kind == 'Icon'} {:else if kind == 'Check'}
{:else if kind == 'Predefined'}
{#each predefinedOptions as predefinedOption, i}
{/each}
{/if}
================================================ FILE: examples/api/src/main.js ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import 'uno.css' import './app.css' import App from './App.svelte' import { mount } from 'svelte' const app = mount(App, { target: document.querySelector('#app') }) export default app ================================================ FILE: examples/api/src/views/App.svelte ================================================
================================================ FILE: examples/api/src/views/Communication.svelte ================================================
================================================ FILE: examples/api/src/views/Menu.svelte ================================================
================================================ FILE: examples/api/src/views/Tray.svelte ================================================
================================================ FILE: examples/api/src/views/WebRTC.svelte ================================================
Not available for Linux
================================================ FILE: examples/api/src/views/Welcome.svelte ================================================

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.

    App name: {appName}
    App version: {version}
    Tauri version: {tauriVersion}
    Bundle type: {bundleType}
  
================================================ FILE: examples/api/src/views/Window.svelte ================================================
{#if Object.keys(webviewMap).length >= 1}

Selected Window

{/if}

Create New Window

{ createWebviewWindow() ev.preventDefault() }} >
{#if webviewMap[selectedWebview]}

Change Window Icon

{ changeIcon() ev.preventDefault() }} >

Set Window Title

{ setTitle() ev.preventDefault() }} >
Height
Inner Size
Width: {innerSize.width} Height: {innerSize.height}
Outer Size
Width: {outerSize.width} Height: {outerSize.height}
Inner Logical Size
Width: {innerSize.toLogical(scaleFactor).width.toFixed(3)} Height: {innerSize.toLogical(scaleFactor).height.toFixed(3)}
Outer Logical Size
Width: {outerSize.toLogical(scaleFactor).width.toFixed(3)} Height: {outerSize.toLogical(scaleFactor).height.toFixed(3)}
Inner Position
x: {innerPosition.x} y: {innerPosition.y}
Outer Position
x: {outerPosition.x} y: {outerPosition.y}
Inner Logical Position
x: {innerPosition.toLogical(scaleFactor).x.toFixed(3)} y: {innerPosition.toLogical(scaleFactor).y.toFixed(3)}
Outer Logical Position
x: {outerPosition.toLogical(scaleFactor).x.toFixed(3)} y: {outerPosition.toLogical(scaleFactor).y.toFixed(3)}

Cursor

{#if isWindows || isMacOS}
Applied effects: {effects.length ? effects.join(', ') : 'None'}
{/if} {/if}
================================================ FILE: examples/api/src/vite-env.d.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT /// /// ================================================ FILE: examples/api/src-tauri/.gitignore ================================================ # Generated by Cargo # will have compiled files and executables /target/ # cargo-mobile /gen ================================================ FILE: examples/api/src-tauri/.taurignore ================================================ tauri-plugin-sample/ ================================================ FILE: examples/api/src-tauri/Cargo.toml ================================================ [package] name = "api" version = "0.1.0" description = "An example Tauri Application showcasing the api" edition = "2021" rust-version = "1.77.2" license = "Apache-2.0 OR MIT" [lib] name = "api_lib" crate-type = ["staticlib", "cdylib", "rlib"] [build-dependencies] tauri-build = { path = "../../../crates/tauri-build", features = [ "codegen", "isolation", ] } [dependencies] serde_json = "1" serde = { version = "1", features = ["derive"] } tiny_http = "0.11" log = "0.4.21" tauri-plugin-sample = { path = "./tauri-plugin-sample/" } tauri-plugin-log = "2" [dependencies.tauri] path = "../../../crates/tauri" features = [ "protocol-asset", "image-ico", "image-png", "isolation", "macos-private-api", "tray-icon", ] [dev-dependencies.tauri] path = "../../../crates/tauri" features = ["test"] [features] prod = ["tauri/custom-protocol"] ================================================ FILE: examples/api/src-tauri/Cross.toml ================================================ [build.env] # must set ICONS_VOLUME, DIST_VOLUME, ISOLATION_VOLUME and WORKSPACE_VOLUME environment variables # ICONS_VOLUME: absolute path to the .icons folder # DIST_VOLUME: absolute path to the dist folder # ISOLATION_VOLUME: absolute path to the isolation dist folder # WORKSPACE_VOLUME: absolute path to the workspace # this can be done running `$ . .setup-cross.sh` in the examples/api folder volumes = [ "ICONS_VOLUME", "DIST_VOLUME", "ISOLATION_VOLUME", "WORKSPACE_VOLUME", ] [target.aarch64-unknown-linux-gnu] image = "aarch64-unknown-linux-gnu:latest" #image = "ghcr.io/tauri-apps/tauri/aarch64-unknown-linux-gnu:latest" ================================================ FILE: examples/api/src-tauri/Info.plist ================================================ NSCameraUsageDescription Request camera access for WebRTC NSMicrophoneUsageDescription Request microphone access for WebRTC ================================================ FILE: examples/api/src-tauri/build.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use tauri_build::WindowsAttributes; fn main() { tauri_build::try_build( tauri_build::Attributes::new() .codegen(tauri_build::CodegenContext::new()) .windows_attributes(WindowsAttributes::new_without_app_manifest()) .plugin( "app-menu", tauri_build::InlinedPlugin::new().commands(&["toggle", "popup"]), ) .app_manifest(tauri_build::AppManifest::new().commands(&[ "log_operation", "perform_request", "echo", "spam", ])), ) .expect("failed to run tauri-build"); #[cfg(windows)] { // workaround needed to prevent `STATUS_ENTRYPOINT_NOT_FOUND` error in tests // see https://github.com/tauri-apps/tauri/pull/4383#issuecomment-1212221864 let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap(); let target_env = std::env::var("CARGO_CFG_TARGET_ENV"); let is_tauri_workspace = std::env::var("__TAURI_WORKSPACE__").is_ok_and(|v| v == "true"); if is_tauri_workspace && target_os == "windows" && Ok("msvc") == target_env.as_deref() { embed_manifest_for_tests(); } } } #[cfg(windows)] fn embed_manifest_for_tests() { static WINDOWS_MANIFEST_FILE: &str = "windows-app-manifest.xml"; let manifest = std::env::current_dir() .unwrap() .join("../../../crates/tauri-build/src") .join(WINDOWS_MANIFEST_FILE); println!("cargo:rerun-if-changed={}", manifest.display()); // Embed the Windows application manifest file. println!("cargo:rustc-link-arg=/MANIFEST:EMBED"); println!( "cargo:rustc-link-arg=/MANIFESTINPUT:{}", manifest.to_str().unwrap() ); // Turn linker warnings into errors. println!("cargo:rustc-link-arg=/WX"); } ================================================ FILE: examples/api/src-tauri/capabilities/.gitignore ================================================ schemas/ ================================================ FILE: examples/api/src-tauri/capabilities/main.json ================================================ { "$schema": "../gen/schemas/desktop-schema.json", "identifier": "secondary-window", "description": "capability for secondary window", "windows": ["main-*"], "permissions": [ { "identifier": "sample:allow-ping", "deny": [ { "path": "tauri.app" } ] } ] } ================================================ FILE: examples/api/src-tauri/capabilities/run-app.json ================================================ { "$schema": "../gen/schemas/desktop-schema.json", "identifier": "run-app", "description": "permissions to run the app", "windows": ["main", "main-*"], "permissions": [ "core:window:allow-is-enabled", "core:window:allow-set-enabled", { "identifier": "allow-log-operation", "allow": [ { "event": "tauri-click" } ] }, "allow-perform-request", "allow-echo", "allow-spam", "app-menu:default", "sample:allow-ping-scoped", "sample:global-scope", "core:default", "core:app:allow-app-hide", "core:app:allow-app-show", "core:app:allow-set-app-theme", "core:app:allow-set-dock-visibility", "core:app:allow-default-window-icon", "core:window:allow-set-theme", "core:window:allow-center", "core:window:allow-request-user-attention", "core:window:allow-set-resizable", "core:window:allow-set-maximizable", "core:window:allow-set-minimizable", "core:window:allow-set-closable", "core:window:allow-set-title", "core:window:allow-maximize", "core:window:allow-unmaximize", "core:window:allow-minimize", "core:window:allow-unminimize", "core:window:allow-show", "core:window:allow-hide", "core:window:allow-close", "core:window:allow-set-decorations", "core:window:allow-set-shadow", "core:window:allow-set-effects", "core:window:allow-set-always-on-top", "core:window:allow-set-always-on-bottom", "core:window:allow-set-content-protected", "core:window:allow-set-size", "core:window:allow-set-min-size", "core:window:allow-set-max-size", "core:window:allow-set-position", "core:window:allow-set-fullscreen", "core:window:allow-set-simple-fullscreen", "core:window:allow-set-focus", "core:window:allow-set-focusable", "core:window:allow-set-skip-taskbar", "core:window:allow-set-cursor-grab", "core:window:allow-set-cursor-visible", "core:window:allow-set-cursor-icon", "core:window:allow-set-cursor-position", "core:window:allow-set-ignore-cursor-events", "core:window:allow-start-dragging", "core:window:allow-set-progress-bar", "core:window:allow-set-icon", "core:window:allow-toggle-maximize", "core:webview:allow-create-webview-window", "core:webview:allow-print" ] } ================================================ FILE: examples/api/src-tauri/locales/pt-BR.wxl ================================================ Executar Tauri API Uma versão mais recente de Tauri API está instalada. Adiciona o caminho do executável de Tauri API para a variável de ambiente PATH. Isso permite Tauri API ser executado pela linha de comando. Instala Tauri API. ================================================ FILE: examples/api/src-tauri/permissions/app-menu/default.toml ================================================ [default] description = "Default permissions for the plugin" permissions = ["allow-toggle", "allow-popup"] ================================================ FILE: examples/api/src-tauri/permissions/autogenerated/echo.toml ================================================ # Automatically generated - DO NOT EDIT! [[permission]] identifier = "allow-echo" description = "Enables the echo command without any pre-configured scope." commands.allow = ["echo"] [[permission]] identifier = "deny-echo" description = "Denies the echo command without any pre-configured scope." commands.deny = ["echo"] ================================================ FILE: examples/api/src-tauri/permissions/autogenerated/log_operation.toml ================================================ # Automatically generated - DO NOT EDIT! [[permission]] identifier = "allow-log-operation" description = "Enables the log_operation command without any pre-configured scope." commands.allow = ["log_operation"] [[permission]] identifier = "deny-log-operation" description = "Denies the log_operation command without any pre-configured scope." commands.deny = ["log_operation"] ================================================ FILE: examples/api/src-tauri/permissions/autogenerated/perform_request.toml ================================================ # Automatically generated - DO NOT EDIT! [[permission]] identifier = "allow-perform-request" description = "Enables the perform_request command without any pre-configured scope." commands.allow = ["perform_request"] [[permission]] identifier = "deny-perform-request" description = "Denies the perform_request command without any pre-configured scope." commands.deny = ["perform_request"] ================================================ FILE: examples/api/src-tauri/permissions/autogenerated/spam.toml ================================================ # Automatically generated - DO NOT EDIT! [[permission]] identifier = "allow-spam" description = "Enables the spam command without any pre-configured scope." commands.allow = ["spam"] [[permission]] identifier = "deny-spam" description = "Denies the spam command without any pre-configured scope." commands.deny = ["spam"] ================================================ FILE: examples/api/src-tauri/src/cmd.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use serde::{Deserialize, Serialize}; use tauri::{ command, ipc::{Channel, CommandScope}, }; #[derive(Debug, Deserialize)] #[allow(unused)] pub struct RequestBody { id: i32, name: String, } #[derive(Debug, Deserialize)] pub struct LogScope { event: String, } #[command] pub fn log_operation( event: String, payload: Option, command_scope: CommandScope, ) -> Result<(), &'static str> { if command_scope.denies().iter().any(|s| s.event == event) { Err("denied") } else if !command_scope.allows().iter().any(|s| s.event == event) { Err("not allowed") } else { log::info!("{event} {payload:?}"); Ok(()) } } #[derive(Serialize)] pub struct ApiResponse { message: String, } #[command] pub fn perform_request(endpoint: String, body: RequestBody) -> ApiResponse { println!("{endpoint} {body:?}"); ApiResponse { message: "message response".into(), } } #[command] pub fn echo(request: tauri::ipc::Request<'_>) -> tauri::ipc::Response { tauri::ipc::Response::new(request.body().clone()) } #[command] pub fn spam(channel: Channel) -> tauri::Result<()> { for i in 1..=1_000 { channel.send(i)?; } Ok(()) } ================================================ FILE: examples/api/src-tauri/src/lib.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT mod cmd; #[cfg(desktop)] mod menu_plugin; #[cfg(desktop)] mod tray; use serde::Serialize; use tauri::{ ipc::Channel, webview::{PageLoadEvent, WebviewWindowBuilder}, App, Emitter, Listener, Runtime, WebviewUrl, }; #[allow(unused)] use tauri::{Manager, RunEvent}; use tauri_plugin_sample::{PingRequest, SampleExt}; #[derive(Clone, Serialize)] struct Reply { data: String, } #[cfg(target_os = "macos")] pub struct AppMenu(pub std::sync::Mutex>>); #[cfg(all(desktop, not(test)))] pub struct PopupMenu(tauri::menu::Menu); #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { run_app(tauri::Builder::default(), |_app| {}) } pub fn run_app) + Send + 'static>( builder: tauri::Builder, setup: F, ) { #[allow(unused_mut)] let mut builder = builder .plugin( tauri_plugin_log::Builder::default() .level(log::LevelFilter::Info) .build(), ) .plugin(tauri_plugin_sample::init()) .setup(move |app| { #[cfg(all(desktop, not(test)))] { let handle = app.handle(); tray::create_tray(handle)?; handle.plugin(menu_plugin::init())?; } #[cfg(target_os = "macos")] app.manage(AppMenu::(Default::default())); #[cfg(all(desktop, not(test)))] app.manage(PopupMenu( tauri::menu::MenuBuilder::new(app) .check("check", "Tauri is awesome!") .text("text", "Do something") .copy() .build()?, )); let mut window_builder = WebviewWindowBuilder::new(app, "main", WebviewUrl::default()) .on_document_title_changed(|_window, title| { println!("document title changed: {title}"); }); #[cfg(all(desktop, not(test)))] { let app_ = app.handle().clone(); let mut created_window_count = std::sync::atomic::AtomicUsize::new(0); window_builder = window_builder .title("Tauri API Validation") .inner_size(1000., 800.) .min_inner_size(600., 400.) .menu(tauri::menu::Menu::default(app.handle())?) .on_new_window(move |url, features| { println!("new window requested: {url:?} {features:?}"); let number = created_window_count.fetch_add(1, std::sync::atomic::Ordering::Relaxed); let builder = tauri::WebviewWindowBuilder::new( &app_, format!("new-{number}"), tauri::WebviewUrl::External("about:blank".parse().unwrap()), ) .window_features(features) .on_document_title_changed(|window, title| { window.set_title(&title).unwrap(); }) .title(url.as_str()); let window = builder.build().unwrap(); tauri::webview::NewWindowResponse::Create { window } }); } let webview = window_builder.build()?; #[cfg(debug_assertions)] webview.open_devtools(); let value = Some("test".to_string()); let response = app.sample().ping(PingRequest { value: value.clone(), on_event: Channel::new(|event| { println!("got channel event: {event:?}"); Ok(()) }), }); log::info!("got response: {:?}", response); // when #[cfg(desktop)], Rust will detect pattern as irrefutable #[allow(irrefutable_let_patterns)] if let Ok(res) = response { assert_eq!(res.value, value); } #[cfg(desktop)] std::thread::spawn(|| { let server = match tiny_http::Server::http("localhost:3003") { Ok(s) => s, Err(e) => { eprintln!("{e}"); std::process::exit(1); } }; loop { if let Ok(mut request) = server.recv() { let mut body = Vec::new(); let _ = request.as_reader().read_to_end(&mut body); let response = tiny_http::Response::new( tiny_http::StatusCode(200), request.headers().to_vec(), std::io::Cursor::new(body), request.body_length(), None, ); let _ = request.respond(response); } } }); setup(app); Ok(()) }) .on_page_load(|webview, payload| { if payload.event() == PageLoadEvent::Finished { let webview_ = webview.clone(); webview.listen("js-event", move |event| { println!("got js-event with message '{:?}'", event.payload()); let reply = Reply { data: "something else".to_string(), }; webview_ .emit("rust-event", Some(reply)) .expect("failed to emit"); }); } }); #[allow(unused_mut)] let mut app = builder .invoke_handler(tauri::generate_handler![ cmd::log_operation, cmd::perform_request, cmd::echo, cmd::spam, ]) .build(tauri::tauri_build_context!()) .expect("error while building tauri application"); #[cfg(target_os = "macos")] app.set_activation_policy(tauri::ActivationPolicy::Regular); app.run(move |_app_handle, _event| { #[cfg(all(desktop, not(test)))] match &_event { RunEvent::ExitRequested { api, code, .. } => { // Keep the event loop running even if all windows are closed // This allow us to catch tray icon events when there is no window // if we manually requested an exit (code is Some(_)) we will let it go through if code.is_none() { api.prevent_exit(); } } RunEvent::WindowEvent { event: tauri::WindowEvent::CloseRequested { api, .. }, label, .. } => { println!("closing window..."); // run the window destroy manually just for fun :) // usually you'd show a dialog here to ask for confirmation or whatever api.prevent_close(); _app_handle .get_webview_window(label) .unwrap() .destroy() .unwrap(); } _ => (), } }) } #[cfg(test)] mod tests { use tauri::Manager; #[test] fn run_app() { super::run_app(tauri::test::mock_builder(), |app| { let window = app.get_webview_window("main").unwrap(); std::thread::spawn(move || { std::thread::sleep(std::time::Duration::from_secs(1)); window.close().unwrap(); }); }) } } ================================================ FILE: examples/api/src-tauri/src/main.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] fn main() { api_lib::run(); } ================================================ FILE: examples/api/src-tauri/src/menu_plugin.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT #![cfg(all(desktop, not(test)))] use tauri::{ command, plugin::{Builder, TauriPlugin}, Runtime, }; #[cfg(not(target_os = "macos"))] #[command] pub fn toggle(window: tauri::Window) { if window.is_menu_visible().unwrap_or_default() { let _ = window.hide_menu(); } else { let _ = window.show_menu(); } } #[cfg(target_os = "macos")] #[command] pub fn toggle( app: tauri::AppHandle, app_menu: tauri::State<'_, crate::AppMenu>, ) { if let Some(menu) = app.remove_menu().unwrap() { app_menu.0.lock().unwrap().replace(menu); } else { app .set_menu(app_menu.0.lock().unwrap().clone().expect("no app menu")) .unwrap(); } } #[command] pub fn popup( window: tauri::Window, popup_menu: tauri::State<'_, crate::PopupMenu>, ) { window.popup_menu(&popup_menu.0).unwrap(); } pub fn init() -> TauriPlugin { Builder::new("app-menu") .invoke_handler(tauri::generate_handler![ #![plugin(app_menu)] popup, toggle ]) .build() } ================================================ FILE: examples/api/src-tauri/src/tray.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT #![cfg(all(desktop, not(test)))] use std::sync::atomic::{AtomicBool, Ordering}; use tauri::{ include_image, menu::{Menu, MenuItem}, tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent}, Manager, Runtime, WebviewUrl, }; pub fn create_tray(app: &tauri::AppHandle) -> tauri::Result<()> { let toggle_i = MenuItem::with_id(app, "toggle", "Toggle", true, None::<&str>)?; let new_window_i = MenuItem::with_id(app, "new-window", "New window", true, None::<&str>)?; let icon_i_1 = MenuItem::with_id(app, "icon-1", "Icon 1", true, None::<&str>)?; let icon_i_2 = MenuItem::with_id(app, "icon-2", "Icon 2", true, None::<&str>)?; #[cfg(target_os = "macos")] let set_title_i = MenuItem::with_id(app, "set-title", "Set Title", true, None::<&str>)?; let switch_i = MenuItem::with_id(app, "switch-menu", "Switch Menu", true, None::<&str>)?; let quit_i = MenuItem::with_id(app, "quit", "Quit", true, None::<&str>)?; let remove_tray_i = MenuItem::with_id(app, "remove-tray", "Remove Tray icon", true, None::<&str>)?; let menu1 = Menu::with_items( app, &[ &toggle_i, &new_window_i, &icon_i_1, &icon_i_2, #[cfg(target_os = "macos")] &set_title_i, &switch_i, &quit_i, &remove_tray_i, ], )?; let menu2 = Menu::with_items( app, &[&toggle_i, &new_window_i, &switch_i, &quit_i, &remove_tray_i], )?; let is_menu1 = AtomicBool::new(true); let _ = TrayIconBuilder::with_id("tray-1") .tooltip("Tauri") .icon(app.default_window_icon().unwrap().clone()) .menu(&menu1) .show_menu_on_left_click(false) .on_menu_event(move |app, event| match event.id.as_ref() { "quit" => { app.exit(0); } "remove-tray" => { app.remove_tray_by_id("tray-1"); } "toggle" => { if let Some(window) = app.get_webview_window("main") { let new_title = if window.is_visible().unwrap_or_default() { let _ = window.hide(); "Show" } else { let _ = window.show(); let _ = window.set_focus(); "Hide" }; toggle_i.set_text(new_title).unwrap(); } } "new-window" => { let _webview = tauri::WebviewWindowBuilder::new(app, "new", WebviewUrl::App("index.html".into())) .title("Tauri") .build() .unwrap(); } #[cfg(target_os = "macos")] "set-title" => { if let Some(tray) = app.tray_by_id("tray-1") { let _ = tray.set_title(Some("Tauri")); } } i @ "icon-1" | i @ "icon-2" => { if let Some(tray) = app.tray_by_id("tray-1") { let icon = if i == "icon-1" { include_image!("../../.icons/icon.ico") } else { include_image!("../../.icons/tray_icon_with_transparency.png") }; let _ = tray.set_icon(Some(icon)); } } "switch-menu" => { let flag = is_menu1.load(Ordering::Relaxed); let (menu, tooltip) = if flag { (menu2.clone(), "Menu 2") } else { (menu1.clone(), "Tauri") }; if let Some(tray) = app.tray_by_id("tray-1") { let _ = tray.set_menu(Some(menu)); let _ = tray.set_tooltip(Some(tooltip)); } is_menu1.store(!flag, Ordering::Relaxed); } _ => {} }) .on_tray_icon_event(|tray, event| { if let TrayIconEvent::Click { button: MouseButton::Left, button_state: MouseButtonState::Up, .. } = event { let app = tray.app_handle(); if let Some(window) = app.get_webview_window("main") { let _ = window.unminimize(); let _ = window.show(); let _ = window.set_focus(); } } }) .build(app); Ok(()) } ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/.gitignore ================================================ .tauri ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/Cargo.toml ================================================ [package] name = "tauri-plugin-sample" version = "0.1.0" edition = "2021" links = "tauri-plugin-sample" [dependencies] tauri = { path = "../../../../crates/tauri" } log = "0.4" serde = "1" thiserror = "2" [build-dependencies] tauri-plugin = { path = "../../../../crates/tauri-plugin", features = [ "build", ] } ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/android/.gitignore ================================================ /build .tauri ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/android/build.gradle.kts ================================================ plugins { id("com.android.library") id("org.jetbrains.kotlin.android") } android { namespace = "com.plugin.sample" compileSdk = 36 defaultConfig { minSdk = 21 testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles("consumer-rules.pro") } buildTypes { release { isMinifyEnabled = false proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) } } compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = "1.8" } } dependencies { implementation("androidx.core:core-ktx:1.9.0") implementation("androidx.appcompat:appcompat:1.6.0") implementation("com.google.android.material:material:1.7.0") testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.5") androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") implementation(project(":tauri-android")) } ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/android/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the # proguardFiles setting in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} # Uncomment this to preserve the line number information for # debugging stack traces. #-keepattributes SourceFile,LineNumberTable # If you keep the line number information, uncomment this to # hide the original source file name. #-renamesourcefileattribute SourceFile ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/android/settings.gradle ================================================ pluginManagement { repositories { mavenCentral() gradlePluginPortal() google() } resolutionStrategy { eachPlugin { switch (requested.id.id) { case "com.android.library": useVersion("8.0.2") break case "org.jetbrains.kotlin.android": useVersion("1.8.20") break } } } } dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { mavenCentral() google() } } include ':tauri-android' project(':tauri-android').projectDir = new File('./.tauri/tauri-api') ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/android/src/androidTest/java/com/plugin/sample/ExampleInstrumentedTest.kt ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT package com.plugin.sample import androidx.test.platform.app.InstrumentationRegistry import androidx.test.ext.junit.runners.AndroidJUnit4 import org.junit.Test import org.junit.runner.RunWith import org.junit.Assert.* /** * Instrumented test, which will execute on an Android device. * * See [testing documentation](http://d.android.com/tools/testing). */ @RunWith(AndroidJUnit4::class) class ExampleInstrumentedTest { @Test fun useAppContext() { // Context of the app under test. val appContext = InstrumentationRegistry.getInstrumentation().targetContext assertEquals("com.plugin.sample", appContext.packageName) } } ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/android/src/main/AndroidManifest.xml ================================================ ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/android/src/main/java/com/plugin/sample/Example.kt ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT package com.plugin.sample import android.util.Log class Example { fun pong(value: String): String { Log.i("Pong", value) return value } } ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/android/src/main/java/com/plugin/sample/ExamplePlugin.kt ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT package com.plugin.sample import android.app.Activity import app.tauri.annotation.Command import app.tauri.annotation.InvokeArg import app.tauri.annotation.TauriPlugin import app.tauri.plugin.Channel import app.tauri.plugin.JSObject import app.tauri.plugin.Plugin import app.tauri.plugin.Invoke @InvokeArg class PingArgs { var value: String? = null var onEvent: Channel? = null } @TauriPlugin class ExamplePlugin(private val activity: Activity): Plugin(activity) { private val implementation = Example() @Command fun ping(invoke: Invoke) { val args = invoke.parseArgs(PingArgs::class.java) val event = JSObject() event.put("kind", "ping") args.onEvent?.send(event) val ret = JSObject() ret.put("value", implementation.pong(args.value ?: "default value :(")) invoke.resolve(ret) } } ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/android/src/test/java/com/plugin/sample/ExampleUnitTest.kt ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT package com.plugin.sample import org.junit.Test import org.junit.Assert.* /** * Example local unit test, which will execute on the development machine (host). * * See [testing documentation](http://d.android.com/tools/testing). */ class ExampleUnitTest { @Test fun addition_isCorrect() { assertEquals(4, 2 + 2) } } ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/api-iife.js ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT if ('__TAURI__' in window) { window.__TAURI__.sample = {} } ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/build.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT const COMMANDS: &[&str] = &["ping"]; fn main() { tauri_plugin::Builder::new(COMMANDS) .android_path("android") .ios_path("ios") .global_api_script_path("./api-iife.js") .build(); } ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/ios/.gitignore ================================================ .DS_Store /.build /Packages /*.xcodeproj xcuserdata/ DerivedData/ .swiftpm/config/registries.json .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata .netrc Package.resolved ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/ios/Package.swift ================================================ // swift-tools-version:5.3 // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import PackageDescription let package = Package( name: "tauri-plugin-sample", platforms: [ .macOS(.v10_13), .iOS(.v13), ], products: [ // Products define the executables and libraries a package produces, and make them visible to other packages. .library( name: "tauri-plugin-sample", type: .static, targets: ["tauri-plugin-sample"]), ], dependencies: [ // Dependencies declare other packages that this package depends on. .package(name: "Tauri", path: "../../../../../crates/tauri/mobile/ios-api") ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. // Targets can depend on other targets in this package, and on products in packages this package depends on. .target( name: "tauri-plugin-sample", dependencies: [ .byName(name: "Tauri") ], path: "Sources") ] ) ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/ios/README.md ================================================ # Tauri Plugin sample A description of this package. ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/ios/Sources/ExamplePlugin.swift ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import SwiftRs import Tauri import UIKit import WebKit class PingArgs: Decodable { let value: String? let onEvent: Channel? } class ExamplePlugin: Plugin { @objc public func ping(_ invoke: Invoke) throws { let args = try invoke.parseArgs(PingArgs.self) try args.onEvent?.send(["kind": "ping"]) invoke.resolve(["value": args.value ?? ""]) } } @_cdecl("init_plugin_sample") func initPlugin() -> Plugin { return ExamplePlugin() } ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/ios/Tests/PluginTests/PluginTests.swift ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import XCTest @testable import ExamplePlugin final class ExamplePluginTests: XCTestCase { func testExample() throws { let plugin = ExamplePlugin() } } ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/permissions/.gitignore ================================================ schemas/ ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/permissions/autogenerated/commands/ping.toml ================================================ # Automatically generated - DO NOT EDIT! "$schema" = "../../schemas/schema.json" [[permission]] identifier = "allow-ping" description = "Enables the ping command without any pre-configured scope." commands.allow = ["ping"] [[permission]] identifier = "deny-ping" description = "Denies the ping command without any pre-configured scope." commands.deny = ["ping"] ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/permissions/autogenerated/reference.md ================================================ ## Permission Table
Identifier Description
`sample:allow-ping` Enables the ping command without any pre-configured scope.
`sample:deny-ping` Denies the ping command without any pre-configured scope.
`sample:global-scope` Sets a global scope.
`sample:allow-ping-scoped` Enables the ping command with a test scope.
================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/permissions/global-scope.toml ================================================ "$schema" = "schemas/schema.json" [[permission]] identifier = "global-scope" description = "Sets a global scope." [[permission.scope.allow]] path = "global" ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/permissions/ping-scoped.toml ================================================ "$schema" = "schemas/schema.json" [[permission]] identifier = "allow-ping-scoped" description = "Enables the ping command with a test scope." commands.allow = ["ping"] [[permission.scope.allow]] path = "x" ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/src/desktop.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use serde::de::DeserializeOwned; use tauri::{plugin::PluginApi, AppHandle, Runtime}; use crate::models::*; pub fn init( app: &AppHandle, _api: PluginApi, ) -> crate::Result> { Ok(Sample(app.clone())) } /// A helper class to access the sample APIs. pub struct Sample(AppHandle); impl Sample { pub fn ping(&self, payload: PingRequest) -> crate::Result { payload.on_event.send(Event { kind: "ping".to_string(), value: payload.value.clone(), })?; Ok(PingResponse { value: payload.value, }) } } ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/src/error.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT #[derive(Debug, thiserror::Error)] pub enum Error { #[cfg(mobile)] #[error(transparent)] PluginInvoke(#[from] tauri::plugin::mobile::PluginInvokeError), #[error(transparent)] Tauri(#[from] tauri::Error), } pub type Result = std::result::Result; ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/src/lib.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use serde::Deserialize; use std::path::PathBuf; use tauri::{ plugin::{Builder, TauriPlugin}, Manager, Runtime, }; pub use models::*; #[cfg(desktop)] mod desktop; #[cfg(mobile)] mod mobile; mod error; mod models; #[cfg(desktop)] use desktop::Sample; #[cfg(mobile)] use mobile::Sample; pub use error::*; /// Extensions to [`tauri::App`], [`tauri::AppHandle`] and [`tauri::Window`] to access the sample APIs. pub trait SampleExt { fn sample(&self) -> &Sample; } impl> crate::SampleExt for T { fn sample(&self) -> &Sample { self.state::>().inner() } } #[allow(dead_code)] #[derive(Debug, Deserialize)] struct PingScope { path: PathBuf, } #[allow(dead_code)] #[derive(Debug, Deserialize)] struct SampleScope { path: PathBuf, } #[tauri::command] fn ping( app: tauri::AppHandle, value: Option, scope: tauri::ipc::CommandScope, global_scope: tauri::ipc::GlobalScope, ) -> std::result::Result { println!("local scope {scope:?}"); println!("global scope {global_scope:?}"); app .sample() .ping(PingRequest { value, on_event: tauri::ipc::Channel::new(|_| Ok(())), }) .map_err(|e| e.to_string()) } pub fn init() -> TauriPlugin { Builder::new("sample") .setup(|app, api| { #[cfg(mobile)] let sample = mobile::init(app, api)?; #[cfg(desktop)] let sample = desktop::init(app, api)?; app.manage(sample); Ok(()) }) .invoke_handler(tauri::generate_handler![ping]) .on_navigation(|window, url| { println!("navigation {} {url}", window.label()); true }) .build() } ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/src/mobile.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use serde::de::DeserializeOwned; use tauri::{ plugin::{PluginApi, PluginHandle}, AppHandle, Runtime, }; use crate::models::*; #[cfg(target_os = "android")] const PLUGIN_IDENTIFIER: &str = "com.plugin.sample"; #[cfg(target_os = "ios")] tauri::ios_plugin_binding!(init_plugin_sample); // initializes the Kotlin or Swift plugin classes pub fn init( _app: &AppHandle, api: PluginApi, ) -> crate::Result> { #[cfg(target_os = "android")] let handle = api.register_android_plugin(PLUGIN_IDENTIFIER, "ExamplePlugin")?; #[cfg(target_os = "ios")] let handle = api.register_ios_plugin(init_plugin_sample)?; Ok(Sample(handle)) } /// A helper class to access the sample APIs. pub struct Sample(PluginHandle); impl Sample { pub fn ping(&self, payload: PingRequest) -> crate::Result { self .0 .run_mobile_plugin("ping", payload) .map_err(Into::into) } } ================================================ FILE: examples/api/src-tauri/tauri-plugin-sample/src/models.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use serde::{Deserialize, Serialize}; use tauri::ipc::Channel; #[derive(Serialize)] pub struct Event { pub kind: String, pub value: Option, } #[derive(Serialize)] #[serde(rename_all = "camelCase")] pub struct PingRequest { pub value: Option, pub on_event: Channel, } #[derive(Debug, Clone, Default, Deserialize, Serialize)] pub struct PingResponse { pub value: Option, } ================================================ FILE: examples/api/src-tauri/tauri.conf.json ================================================ { "$schema": "../../../crates/tauri-schema-generator/schemas/config.schema.json", "productName": "Tauri API", "version": "1.0.0", "identifier": "com.tauri.api", "build": { "frontendDist": "../dist", "devUrl": "http://localhost:1420", "beforeDevCommand": "pnpm dev", "beforeBuildCommand": "pnpm build", "removeUnusedCommands": true }, "app": { "withGlobalTauri": true, "macOSPrivateApi": true, "security": { "pattern": { "use": "isolation", "options": { "dir": "../isolation-dist/" } }, "csp": { "default-src": "'self' customprotocol: asset:", "connect-src": "ipc: http://ipc.localhost", "font-src": ["https://fonts.gstatic.com"], "img-src": "'self' asset: http://asset.localhost blob: data:", "style-src": "'unsafe-inline' 'self' https://fonts.googleapis.com" }, "freezePrototype": true, "assetProtocol": { "enable": true, "scope": { "allow": ["$APPDATA/db/**", "$RESOURCE/**"], "deny": ["$APPDATA/db/*.stronghold"] } } } }, "plugins": { "cli": { "description": "Tauri API example", "args": [ { "short": "c", "name": "config", "takesValue": true, "description": "Config path" }, { "short": "t", "name": "theme", "takesValue": true, "description": "App theme", "possibleValues": ["light", "dark", "system"] }, { "short": "v", "name": "verbose", "description": "Verbosity level" } ], "subcommands": { "update": { "description": "Updates the app", "args": [ { "short": "b", "name": "background", "description": "Update in background" } ] } } } }, "bundle": { "active": true, "icon": [ "../../.icons/32x32.png", "../../.icons/128x128.png", "../../.icons/128x128@2x.png", "../../.icons/icon.icns", "../../.icons/icon.ico" ], "windows": { "wix": { "language": { "en-US": {}, "pt-BR": { "localePath": "locales/pt-BR.wxl" } } }, "nsis": { "compression": "none" } } } } ================================================ FILE: examples/api/svelte.config.js ================================================ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' export default { // Consult https://svelte.dev/docs#compile-time-svelte-preprocess // for more information about preprocessors preprocess: vitePreprocess() } ================================================ FILE: examples/api/unocss.config.js ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import { defineConfig, presetIcons, presetWind3, presetWebFonts } from 'unocss' import extractorSvelte from '@unocss/extractor-svelte' export default defineConfig({ theme: { colors: { primary: '#FFFFFF', primaryLighter: '#e9ecef', darkPrimary: '#1B1B1D', darkPrimaryLighter: '#242526', primaryText: '#1C1E21', darkPrimaryText: '#E3E3E3', secondaryText: '#858A91', darkSecondaryText: '#C2C5CA', accent: '#3578E5', accentDark: '#306cce', accentDarker: '#2d66c3', accentDarkest: '#2554a0', accentLight: '#538ce9', accentLighter: '#72a1ed', accentLightest: '#9abcf2', accentText: '#FFFFFF', darkAccent: '#67d6ed', darkAccentDark: '#49cee9', darkAccentDarker: '#39cae8', darkAccentDarkest: '#19b5d5', darkAccentLight: '#85def1', darkAccentLighter: '#95e2f2', darkAccentLightest: '#c2eff8', darkAccentText: '#1C1E21', code: '#d6d8da', codeDark: '#282a2e', hoverOverlay: 'rgba(0,0,0,.05)', hoverOverlayDarker: 'rgba(0,0,0,.1)', darkHoverOverlay: 'hsla(0,0%,100%,.05)', darkHoverOverlayDarker: 'hsla(0,0%,100%,.1)' } }, preflights: [ { getCSS: ({ theme }) => ` ::-webkit-scrollbar-thumb { background-color: ${theme.colors.accent}; } .dark ::-webkit-scrollbar-thumb { background-color: ${theme.colors.darkAccent}; } code { font-size: ${theme.fontSize.xs[0]}; font-family: ${theme.fontFamily.mono}; border-radius: ${theme.borderRadius['DEFAULT']}; background-color: ${theme.colors.code}; } .code-block { font-family: ${theme.fontFamily.mono}; font-size: ${theme.fontSize.sm[0]}; } .dark code { background-color: ${theme.colors.codeDark}; } ` } ], shortcuts: { btn: `select-none outline-none shadow-md p-2 rd-1 text-primaryText border-none font-400 dark:font-600 bg-accent hover:bg-accentDarker active:bg-accentDarkest text-accentText dark:bg-darkAccent dark:hover:bg-darkAccentDarker dark:active:bg-darkAccentDarkest dark:text-darkAccentText`, nv: `decoration-none flex items-center relative p-2 rd-1 transition-all-125 ease text-darkSecondaryText hover:text-accent dark:hover:text-darkAccent hover:bg-darkHoverOverlay hover:border-l-4`, nv_selected: `nv bg-darkHoverOverlay text-accent dark:text-darkAccent border-l-4`, note: `decoration-none flex-inline items-center relative p-2 rd-1 border-l-4 border-accent dark:border-darkAccent bg-accent/10 dark:bg-darkAccent/10`, 'note-red': 'note bg-red-700/10 dark:bg-red-700/10 after:bg-red-700 dark:after:bg-red-700', input: 'flex items-center outline-none border-none py-3 px-2 rd-1 shadow-md bg-primaryLighter dark:bg-darkPrimaryLighter text-primaryText dark:text-darkPrimaryText', checkbox: 'accent-accent' }, presets: [ presetWind3(), presetIcons(), presetWebFonts({ fonts: { sans: 'Rubik', mono: ['Fira Code', 'Fira Mono:400,700'] } }) ], extractors: [extractorSvelte] }) ================================================ FILE: examples/api/vite.config.js ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import { defineConfig } from 'vite' import Unocss from 'unocss/vite' import { svelte } from '@sveltejs/vite-plugin-svelte' const host = process.env.TAURI_DEV_HOST // https://vite.dev/config/ export default defineConfig({ plugins: [Unocss(), svelte()], build: { emptyOutDir: false, rollupOptions: { output: { entryFileNames: `assets/[name].js`, chunkFileNames: `assets/[name].js`, assetFileNames: `assets/[name].[ext]` } } }, // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build` // prevent Vite from obscuring rust errors clearScreen: false, // tauri expects a fixed port, fail if that port is not available server: { host: host ?? false, port: 1420, strictPort: true, hmr: host ? { protocol: 'ws', host: host, port: 1430 } : undefined, fs: { allow: ['.', '../../packages/api/dist'] } } }) ================================================ FILE: examples/commands/README.md ================================================ # Commands Example A simple Tauri Application showcasing the command API. To execute run the following on the root directory of the repository: `cargo run --example commands`. ================================================ FILE: examples/commands/commands.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT use tauri::{command, State}; #[command] pub fn cmd(_argument: String) {} #[command] pub fn invoke(_argument: String) {} #[command] pub fn message(_argument: String) {} #[command] pub fn resolver(_argument: String) {} #[command] pub fn simple_command(the_argument: String) { println!("{the_argument}"); } #[command] pub fn stateful_command(the_argument: Option, state: State<'_, super::MyState>) { println!("{:?} {:?}", the_argument, state.inner()); } ================================================ FILE: examples/commands/index.html ================================================ Tauri

Tauri Commands

Response:
Without Args:
================================================ FILE: examples/commands/main.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // we move some basic commands to a separate module just to show it works mod commands; use commands::{cmd, invoke, message, resolver}; use serde::Deserialize; use tauri::{ command, ipc::{Request, Response}, State, Window, }; #[derive(Debug)] pub struct MyState { #[allow(dead_code)] value: u64, #[allow(dead_code)] label: String, } #[derive(Debug, serde::Serialize)] enum MyError { FooError, } // ------------------------ Commands using Window ------------------------ #[command] fn window_label(window: Window) { println!("window label: {}", window.label()); } // Async commands #[command] async fn async_simple_command(the_argument: String) { println!("{the_argument}"); } #[command(rename_all = "snake_case")] async fn async_simple_command_snake(the_argument: String) { println!("{the_argument}"); } #[command] async fn async_stateful_command( the_argument: Option, state: State<'_, MyState>, ) -> Result<(), ()> { println!("{:?} {:?}", the_argument, state.inner()); Ok(()) } // ------------------------ Raw future commands ------------------------ #[command(async)] fn future_simple_command(the_argument: String) -> impl std::future::Future { println!("{the_argument}"); std::future::ready(()) } #[command(async)] fn future_simple_command_with_return( the_argument: String, ) -> impl std::future::Future { println!("{the_argument}"); std::future::ready(the_argument) } #[command(async)] fn future_simple_command_with_result( the_argument: String, ) -> impl std::future::Future> { println!("{the_argument}"); std::future::ready(Ok(the_argument)) } #[command(async)] fn force_async(the_argument: String) -> String { the_argument } #[command(async)] fn force_async_with_result(the_argument: &str) -> Result<&str, MyError> { (!the_argument.is_empty()) .then_some(the_argument) .ok_or(MyError::FooError) } // ------------------------ Raw future commands - snake_case ------------------------ #[command(async, rename_all = "snake_case")] fn future_simple_command_snake(the_argument: String) -> impl std::future::Future { println!("{the_argument}"); std::future::ready(()) } #[command(async, rename_all = "snake_case")] fn future_simple_command_with_return_snake( the_argument: String, ) -> impl std::future::Future { println!("{the_argument}"); std::future::ready(the_argument) } #[command(async, rename_all = "snake_case")] fn future_simple_command_with_result_snake( the_argument: String, ) -> impl std::future::Future> { println!("{the_argument}"); std::future::ready(Ok(the_argument)) } #[command(async, rename_all = "snake_case")] fn force_async_snake(the_argument: String) -> String { the_argument } #[command(rename_all = "snake_case", async)] fn force_async_with_result_snake(the_argument: &str) -> Result<&str, MyError> { (!the_argument.is_empty()) .then_some(the_argument) .ok_or(MyError::FooError) } // ------------------------ Commands returning Result ------------------------ #[command] fn simple_command_with_result(the_argument: String) -> Result { println!("{the_argument}"); (!the_argument.is_empty()) .then_some(the_argument) .ok_or(MyError::FooError) } #[command] fn stateful_command_with_result( the_argument: Option, state: State<'_, MyState>, ) -> Result { println!("{:?} {:?}", the_argument, state.inner()); dbg!(the_argument.ok_or(MyError::FooError)) } // ------------------------ Commands returning Result - snake_case ------------------------ #[command(rename_all = "snake_case")] fn simple_command_with_result_snake(the_argument: String) -> Result { println!("{the_argument}"); (!the_argument.is_empty()) .then_some(the_argument) .ok_or(MyError::FooError) } #[command(rename_all = "snake_case")] fn stateful_command_with_result_snake( the_argument: Option, state: State<'_, MyState>, ) -> Result { println!("{:?} {:?}", the_argument, state.inner()); dbg!(the_argument.ok_or(MyError::FooError)) } // Async commands #[command] async fn async_simple_command_with_result(the_argument: String) -> Result { println!("{the_argument}"); Ok(the_argument) } #[command] async fn async_stateful_command_with_result( the_argument: Option, state: State<'_, MyState>, ) -> Result { println!("{:?} {:?}", the_argument, state.inner()); Ok(the_argument.unwrap_or_default()) } // Non-Ident command function arguments #[command] fn command_arguments_wild(_: Window) { println!("we saw the wildcard!") } #[derive(Deserialize)] struct Person<'a> { name: &'a str, age: u8, } #[command] fn command_arguments_struct(Person { name, age }: Person<'_>) { println!("received person struct with name: {name} | age: {age}") } #[derive(Deserialize)] struct InlinePerson<'a>(&'a str, u8); #[command] fn command_arguments_tuple_struct(InlinePerson(name, age): InlinePerson<'_>) { println!("received person tuple with name: {name} | age: {age}") } #[command] fn borrow_cmd(the_argument: &str) -> &str { the_argument } #[command] fn borrow_cmd_async(the_argument: &str) -> &str { the_argument } #[command] fn raw_request(request: Request<'_>) -> Response { println!("{request:?}"); Response::new(include_bytes!("./README.md").to_vec()) } fn main() { tauri::Builder::default() .manage(MyState { value: 0, label: "Tauri!".into(), }) .invoke_handler(tauri::generate_handler![ borrow_cmd, borrow_cmd_async, raw_request, window_label, force_async, force_async_with_result, commands::simple_command, commands::stateful_command, cmd, invoke, message, resolver, async_simple_command, future_simple_command, async_stateful_command, command_arguments_wild, command_arguments_struct, simple_command_with_result, async_simple_command_snake, future_simple_command_snake, future_simple_command_with_return_snake, future_simple_command_with_result_snake, force_async_snake, force_async_with_result_snake, simple_command_with_result_snake, stateful_command_with_result_snake, stateful_command_with_result, command_arguments_tuple_struct, async_simple_command_with_result, future_simple_command_with_return, future_simple_command_with_result, async_stateful_command_with_result, ]) .run(tauri::generate_context!( "../../examples/commands/tauri.conf.json" )) .expect("error while running tauri application"); } ================================================ FILE: examples/commands/tauri.conf.json ================================================ { "$schema": "../../crates/tauri-schema-generator/schemas/config.schema.json", "productName": "Commands", "version": "0.1.0", "identifier": "com.tauri.dev", "build": { "frontendDist": ["index.html"] }, "app": { "withGlobalTauri": true, "windows": [ { "title": "Welcome to Tauri!", "width": 800, "height": 600, "resizable": true, "fullscreen": false } ], "security": { "csp": "default-src 'self'; connect-src ipc: http://ipc.localhost" } }, "bundle": { "active": true, "targets": "all", "icon": [ "../.icons/32x32.png", "../.icons/128x128.png", "../.icons/128x128@2x.png", "../.icons/icon.icns", "../.icons/icon.ico" ] } } ================================================ FILE: examples/file-associations/README.md ================================================ # File Associations Example This example demonstrates how to make associations between the application and certain file types. This feature is commonly used for functionality such as previewing or editing files. ## Running the example 1. Run the following inside `examples/file-associations/src-tauri` ``` cargo build --features tauri/protocol-asset ``` ## Associations This example creates associations with PNG, JPG, JPEG and GIF files. Additionally, it defines two new extensions - `taurid` (derives from a raw data file) and `taurijson` (derives from JSON). They have special treatment on macOS (see `exportedType` in `src-tauri/tauri.conf.json`). ================================================ FILE: examples/file-associations/index.html ================================================ File Associations

File Associations



    
  



================================================
FILE: examples/file-associations/package.json
================================================
{
  "name": "file-associations",
  "version": "1.0.0",
  "pkg": {
    "assets": [
      "src/**/*"
    ]
  },
  "scripts": {
    "tauri": "node ../../packages/cli/tauri.js"
  },
  "devDependencies": {}
}


================================================
FILE: examples/file-associations/src-tauri/.license_template
================================================
// Copyright {20\d{2}(-20\d{2})?} Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

================================================
FILE: examples/file-associations/src-tauri/Cargo.toml
================================================
[package]
name = "tauri-file-associations-demo"
version = "0.1.0"
description = "A Tauri application that associate file types"
edition = "2021"
rust-version = "1.77.2"

[build-dependencies]
tauri-build = { path = "../../../crates/tauri-build", features = ["codegen"] }

[dependencies]
serde_json = "1"
serde = { version = "1", features = ["derive"] }
tauri = { path = "../../../crates/tauri", features = ["protocol-asset"] }
url = "2"


================================================
FILE: examples/file-associations/src-tauri/Info.plist
================================================




    
        CFBundleURLTypes
        
            
                CFBundleURLName
                
                com.tauri.dev-file-associations-demo
                CFBundleURLSchemes
                
                    
                    myapp
                    myscheme
                
            
        
    



================================================
FILE: examples/file-associations/src-tauri/build.rs
================================================
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

fn main() {
  tauri_build::build()
}


================================================
FILE: examples/file-associations/src-tauri/src/main.rs
================================================
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

#![cfg_attr(
  all(not(debug_assertions), target_os = "windows"),
  windows_subsystem = "windows"
)]

use std::path::PathBuf;
use tauri::{AppHandle, Manager};

fn handle_file_associations(app: AppHandle, files: Vec) {
  // -- Scope handling start --

  // You can remove this block if you only want to know about the paths, but not actually "use" them in the frontend.

  // This requires the `fs` tauri plugin and is required to make the plugin's frontend work:
  // use tauri_plugin_fs::FsExt;
  // let fs_scope = app.fs_scope();

  // This is for the `asset:` protocol to work:
  let asset_protocol_scope = app.asset_protocol_scope();

  for file in &files {
    // This requires the `fs` plugin:
    // let _ = fs_scope.allow_file(file);

    // This is for the `asset:` protocol:
    let _ = asset_protocol_scope.allow_file(file);
  }

  // -- Scope handling end --

  let files = files
    .into_iter()
    .map(|f| {
      let file = f.to_string_lossy().replace('\\', "\\\\"); // escape backslash
      format!("\"{file}\"",) // wrap in quotes for JS array
    })
    .collect::>()
    .join(",");

  tauri::WebviewWindowBuilder::new(&app, "main", Default::default())
    .initialization_script(format!("window.openedFiles = [{files}]"))
    .build()
    .unwrap();
}

fn main() {
  tauri::Builder::default()
    .setup(|#[allow(unused_variables)] app| {
      #[cfg(any(windows, target_os = "linux"))]
      {
        let mut files = Vec::new();

        // NOTICE: `args` may include URL protocol (`your-app-protocol://`)
        // or arguments (`--`) if your app supports them.
        // files may also be passed as `file://path/to/file`
        for maybe_file in std::env::args().skip(1) {
          // skip flags like -f or --flag
          if maybe_file.starts_with('-') {
            continue;
          }

          // handle `file://` path urls and skip other urls
          if let Ok(url) = url::Url::parse(&maybe_file) {
            if let Ok(path) = url.to_file_path() {
              files.push(path);
            }
          } else {
            files.push(PathBuf::from(maybe_file))
          }
        }

        handle_file_associations(app.handle().clone(), files);
      }

      Ok(())
    })
    .build(tauri::generate_context!())
    .expect("error while running tauri application")
    .run(
      #[allow(unused_variables)]
      |app, event| {
        #[cfg(any(target_os = "macos", target_os = "ios"))]
        if let tauri::RunEvent::Opened { urls } = event {
          let files = urls
            .into_iter()
            .filter_map(|url| url.to_file_path().ok())
            .collect::>();

          handle_file_associations(app.clone(), files);
        }
      },
    );
}


================================================
FILE: examples/file-associations/src-tauri/tauri.conf.json
================================================
{
  "$schema": "../../../crates/tauri-cli/config.schema.json",
  "identifier": "com.tauri.dev-file-associations-demo",
  "build": {
    "frontendDist": ["../index.html"]
  },
  "app": {
    "security": {
      "csp": "default-src 'self'",
      "assetProtocol": {
        "enable": true
      }
    }
  },
  "bundle": {
    "active": true,
    "targets": "all",
    "icon": [
      "../../.icons/32x32.png",
      "../../.icons/128x128.png",
      "../../.icons/128x128@2x.png",
      "../../.icons/icon.icns",
      "../../.icons/icon.ico"
    ],
    "fileAssociations": [
      {
        "ext": ["png"],
        "mimeType": "image/png",
        "rank": "Default"
      },
      {
        "ext": ["jpg", "jpeg"],
        "mimeType": "image/jpeg",
        "rank": "Alternate"
      },
      {
        "ext": ["gif"],
        "mimeType": "image/gif",
        "rank": "Owner"
      },
      {
        "ext": ["taurijson"],
        "exportedType": {
          "identifier": "com.tauri.dev-file-associations-demo.taurijson",
          "conformsTo": ["public.json"]
        }
      },
      {
        "ext": ["taurid"],
        "exportedType": {
          "identifier": "com.tauri.dev-file-associations-demo.tauridata",
          "conformsTo": ["public.data"]
        }
      }
    ]
  }
}


================================================
FILE: examples/helloworld/README.md
================================================
# Hello World Example

To execute run the following on the root directory of the repository: `cargo run --example helloworld`.


================================================
FILE: examples/helloworld/index.html
================================================


  
    
    
    Welcome to Tauri!
  
  
    

Welcome to Tauri!

================================================ FILE: examples/helloworld/main.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] #[tauri::command] fn greet(name: &str) -> String { format!("Hello {name}, You have been greeted from Rust!") } fn main() { tauri::Builder::default() .invoke_handler(tauri::generate_handler![greet]) .run(tauri::generate_context!( "../../examples/helloworld/tauri.conf.json" )) .expect("error while running tauri application"); } ================================================ FILE: examples/helloworld/tauri.conf.json ================================================ { "$schema": "../../crates/tauri-schema-generator/schemas/config.schema.json", "productName": "Hello World", "version": "0.1.0", "identifier": "com.tauri.dev", "build": { "frontendDist": ["index.html"] }, "app": { "withGlobalTauri": true, "windows": [ { "title": "Welcome to Tauri!", "width": 800, "height": 600, "resizable": true, "fullscreen": false } ], "security": { "csp": "default-src 'self'; connect-src ipc: http://ipc.localhost" } }, "bundle": { "active": true, "targets": "all", "icon": [ "../.icons/32x32.png", "../.icons/128x128.png", "../.icons/128x128@2x.png", "../.icons/icon.icns", "../.icons/icon.ico" ] } } ================================================ FILE: examples/isolation/README.md ================================================ # Isolation Example To execute run the following on the root directory of the repository: `cargo run --example isolation --features isolation`. ================================================ FILE: examples/isolation/dist/index.html ================================================ Hello Tauri!

Hello, Tauri!

================================================ FILE: examples/isolation/dist/linked.js ================================================ console.log("linked", window.__TAURI_INTERNALS__.__TAURI_PATTERN__); ================================================ FILE: examples/isolation/isolation-dist/index.html ================================================ Isolation Secure Script ================================================ FILE: examples/isolation/isolation-dist/index.js ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT window.__TAURI_ISOLATION_HOOK__ = (payload, options) => { console.log('hook', payload, options) return payload } ================================================ FILE: examples/isolation/main.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] #[tauri::command] fn ping() { println!("ping: {:?}", std::time::Instant::now()); } fn main() { tauri::Builder::default() .invoke_handler(tauri::generate_handler![ping]) .run(tauri::generate_context!( "../../examples/isolation/tauri.conf.json" )) .expect("error while running tauri application"); } ================================================ FILE: examples/isolation/tauri.conf.json ================================================ { "$schema": "../../crates/tauri-schema-generator/schemas/config.schema.json", "productName": "Isolation", "version": "0.1.0", "identifier": "com.tauri.dev", "build": { "frontendDist": "dist", "beforeDevCommand": "", "beforeBuildCommand": "" }, "app": { "withGlobalTauri": true, "windows": [ { "title": "Isolation", "width": 800, "height": 600, "resizable": true, "fullscreen": false } ], "security": { "csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self' img-src: 'self'; connect-src ipc: http://ipc.localhost", "pattern": { "use": "isolation", "options": { "dir": "isolation-dist" } } } }, "bundle": { "active": true, "targets": "all", "icon": [ "../.icons/32x32.png", "../.icons/128x128.png", "../.icons/128x128@2x.png", "../.icons/icon.icns", "../.icons/icon.ico" ] } } ================================================ FILE: examples/multiwebview/README.md ================================================ # Hello World Example To execute run the following on the root directory of the repository: `cargo run --example multiwebview --features unstable`. ================================================ FILE: examples/multiwebview/index.html ================================================ Welcome to Tauri!

Welcome to Tauri!

================================================ FILE: examples/multiwebview/main.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] use tauri::{LogicalPosition, LogicalSize, WebviewUrl}; fn main() { tauri::Builder::default() .setup(|app| { let width = 800.; let height = 600.; let window = tauri::window::WindowBuilder::new(app, "main") .inner_size(width, height) .build()?; let _webview1 = window.add_child( tauri::webview::WebviewBuilder::new("main1", WebviewUrl::App(Default::default())) .auto_resize(), LogicalPosition::new(0., 0.), LogicalSize::new(width / 2., height / 2.), )?; let _webview2 = window.add_child( tauri::webview::WebviewBuilder::new( "main2", WebviewUrl::External("https://github.com/tauri-apps/tauri".parse().unwrap()), ) .auto_resize(), LogicalPosition::new(width / 2., 0.), LogicalSize::new(width / 2., height / 2.), )?; let _webview3 = window.add_child( tauri::webview::WebviewBuilder::new( "main3", WebviewUrl::External("https://tauri.app".parse().unwrap()), ) .auto_resize(), LogicalPosition::new(0., height / 2.), LogicalSize::new(width / 2., height / 2.), )?; let _webview4 = window.add_child( tauri::webview::WebviewBuilder::new( "main4", WebviewUrl::External("https://twitter.com/TauriApps".parse().unwrap()), ) .auto_resize(), LogicalPosition::new(width / 2., height / 2.), LogicalSize::new(width / 2., height / 2.), )?; Ok(()) }) .run(tauri::generate_context!( "../../examples/multiwebview/tauri.conf.json" )) .expect("error while running tauri application"); } ================================================ FILE: examples/multiwebview/tauri.conf.json ================================================ { "productName": "MultiWebview", "version": "0.1.0", "identifier": "com.tauri.dev", "$schema": "../../crates/tauri-schema-generator/schemas/config.schema.json", "build": { "frontendDist": ["index.html"] }, "app": { "security": { "csp": "default-src 'self'; connect-src ipc: http://ipc.localhost" } }, "bundle": { "active": true, "targets": "all", "icon": [ "../.icons/32x32.png", "../.icons/128x128.png", "../.icons/128x128@2x.png", "../.icons/icon.icns", "../.icons/icon.ico" ] } } ================================================ FILE: examples/multiwindow/README.md ================================================ # Multi-Window Example An example Tauri Multi-Window Application. To execute run the following on the root directory of the repository: `cargo run --example multiwindow`. ================================================ FILE: examples/multiwindow/index.html ================================================

Send a message to a window using its label:


Create new window


Messages received from other windows:



  
    
  



================================================
FILE: examples/multiwindow/main.rs
================================================
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

use tauri::WebviewWindowBuilder;

fn main() {
  tauri::Builder::default()
    .setup(|app| {
      WebviewWindowBuilder::new(app, "Third", tauri::WebviewUrl::default())
        .title("Tauri - Third")
        .build()?;

      Ok(())
    })
    .run(generate_context())
    .expect("failed to run tauri application");
}

fn generate_context() -> tauri::Context {
  let mut context = tauri::generate_context!("../../examples/multiwindow/tauri.conf.json");
  for cmd in [
    "plugin:event|listen",
    "plugin:event|emit",
    "plugin:event|emit_to",
    "plugin:webview|create_webview_window",
  ] {
    context
      .runtime_authority_mut()
      .__allow_command(cmd.to_string(), tauri_utils::acl::ExecutionContext::Local);
  }
  context
}


================================================
FILE: examples/multiwindow/tauri.conf.json
================================================
{
  "$schema": "../../crates/tauri-schema-generator/schemas/config.schema.json",
  "productName": "Multi Window",
  "version": "0.1.0",
  "identifier": "com.tauri.dev",
  "build": {
    "frontendDist": ["index.html"]
  },
  "app": {
    "withGlobalTauri": true,
    "windows": [
      {
        "label": "Main",
        "title": "Tauri - Main",
        "tabbingIdentifier": "Main",
        "width": 800,
        "height": 600
      },
      {
        "label": "Secondary",
        "title": "Tauri - Secondary",
        "tabbingIdentifier": "Secondary",
        "width": 600,
        "height": 400
      }
    ],
    "security": {
      "csp": "default-src 'self'; connect-src ipc: http://ipc.localhost"
    }
  },
  "bundle": {
    "active": true,
    "targets": "all",
    "icon": [
      "../.icons/32x32.png",
      "../.icons/128x128.png",
      "../.icons/128x128@2x.png",
      "../.icons/icon.icns",
      "../.icons/icon.ico"
    ],
    "resources": [],
    "externalBin": [],
    "copyright": "",
    "category": "DeveloperTool"
  }
}


================================================
FILE: examples/resources/README.md
================================================
# Resource example

This example demonstrates the Tauri bundle resources functionality. The example adds `src-tauri/assets/index.js` as a resource (defined on `tauri.conf.json > bundle > resources`) and executes it using `Node.js`, locating the JavaScript file using the `tauri::App::path_resolver` APIs.

## Running the example

- Compile Tauri
  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/resources/`)

```bash
$ pnpm i
```

- Run the app in development mode (Run inside of this folder `examples/resources/`)

```bash
$ pnpm tauri dev
```

- Build an run the release app (Run inside of this folder `examples/resources/`)

```bash
$ pnpm tauri build
$ ./src-tauri/target/release/app
```


================================================
FILE: examples/resources/index.html
================================================


  
    
    
  

  
    
Resource `assets/index.js` path:
Resource `assets/index.js` content:


    
  



================================================
FILE: examples/resources/package.json
================================================
{
  "name": "resources",
  "version": "0.1.0",
  "scripts": {
    "tauri": "node ../../packages/cli/tauri.js"
  }
}


================================================
FILE: examples/resources/src-tauri/Cargo.toml
================================================
[package]
name = "resources"
version = "0.1.0"
description = "A Tauri application that uses Node.js with app resources"
edition = "2021"
rust-version = "1.77.2"

[build-dependencies]
tauri-build = { path = "../../../crates/tauri-build", features = ["codegen"] }

[dependencies]
serde_json = "1"
serde = { version = "1", features = ["derive"] }
tauri = { path = "../../../crates/tauri", features = [] }


================================================
FILE: examples/resources/src-tauri/assets/index.js
================================================
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

console.log('hello world')


================================================
FILE: examples/resources/src-tauri/build.rs
================================================
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

fn main() {
  tauri_build::build()
}


================================================
FILE: examples/resources/src-tauri/capabilities/app.json
================================================
{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "app",
  "permissions": ["core:path:default"],
  "windows": ["main"]
}


================================================
FILE: examples/resources/src-tauri/src/main.rs
================================================
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

use tauri::Manager;

#[tauri::command]
fn read_to_string(path: &str) -> String {
  std::fs::read_to_string(path).unwrap_or_default()
}

fn main() {
  tauri::Builder::default()
    .setup(move |app| {
      let path = app
        .path()
        .resolve("assets/index.js", tauri::path::BaseDirectory::Resource)
        .unwrap();

      let content = std::fs::read_to_string(&path).unwrap();

      println!("Resource `assets/index.js` path: {}", path.display());
      println!("Resource `assets/index.js` content:\n{content}\n");

      Ok(())
    })
    .invoke_handler(tauri::generate_handler![read_to_string])
    .run(tauri::generate_context!())
    .expect("error while running tauri application");
}


================================================
FILE: examples/resources/src-tauri/tauri.conf.json
================================================
{
  "$schema": "../../../crates/tauri-schema-generator/schemas/config.schema.json",
  "productName": "Resources",
  "version": "0.1.0",
  "identifier": "com.tauri.resources",
  "build": {
    "frontendDist": ["../index.html"]
  },
  "app": {
    "withGlobalTauri": true,

    "windows": [
      {
        "title": "Welcome to Tauri!",
        "width": 800,
        "height": 600,
        "resizable": true,
        "fullscreen": false
      }
    ],
    "security": {
      "csp": "default-src 'self'; connect-src ipc: http://ipc.localhost"
    }
  },
  "bundle": {
    "active": true,
    "targets": "all",
    "icon": [
      "../../.icons/32x32.png",
      "../../.icons/128x128.png",
      "../../.icons/128x128@2x.png",
      "../../.icons/icon.icns",
      "../../.icons/icon.ico"
    ],
    "resources": ["assets/*"]
  }
}


================================================
FILE: examples/run-return/README.md
================================================
# Run Return Example

To execute run the following on the root directory of the repository: `cargo run --example run-return`.


================================================
FILE: examples/run-return/index.html
================================================


  
    
    
    Welcome to Tauri!
  
  
    

Welcome to Tauri!

================================================ FILE: examples/run-return/main.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] fn main() { let app = tauri::Builder::default() .build(tauri::generate_context!( "../../examples/run-return/tauri.conf.json" )) .expect("error while building tauri application"); let exit_code = app.run_return(|_app, _event| { //println!("{:?}", _event); }); println!("I run after exit"); std::process::exit(exit_code); } ================================================ FILE: examples/run-return/tauri.conf.json ================================================ { "$schema": "../../crates/tauri-schema-generator/schemas/config.schema.json", "productName": "RunReturn", "version": "0.1.0", "identifier": "com.tauri.dev", "build": { "frontendDist": ["index.html"] }, "app": { "windows": [ { "title": "Welcome to Tauri!", "width": 800, "height": 600, "resizable": true, "fullscreen": false } ], "security": { "csp": "default-src 'self'; connect-src ipc: http://ipc.localhost" } }, "bundle": { "active": true, "targets": "all", "icon": [ "../.icons/32x32.png", "../.icons/128x128.png", "../.icons/128x128@2x.png", "../.icons/icon.icns", "../.icons/icon.ico" ] } } ================================================ FILE: examples/splashscreen/README.md ================================================ # Splashscreen example This example demonstrates how a splashscreen can be implemented when waiting on an initialization code on Rust or on the UI. ## Running the example Run the following scripts on the root directory of the repository: ```bash $ cargo run --example splashscreen ``` ================================================ FILE: examples/splashscreen/dist/index.html ================================================

This is the main window!

================================================ FILE: examples/splashscreen/dist/splashscreen.html ================================================ Splashscreen
================================================ FILE: examples/splashscreen/main.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] use tauri::{AppHandle, Manager}; #[tauri::command] fn close_splashscreen(app: AppHandle) { // Close splashscreen app .get_webview_window("splashscreen") .unwrap() .close() .unwrap(); // Show main window app.get_webview_window("main").unwrap().show().unwrap(); } fn main() { tauri::Builder::default() .menu(tauri::menu::Menu::default) .invoke_handler(tauri::generate_handler![close_splashscreen]) .run(tauri::generate_context!( "../../examples/splashscreen/tauri.conf.json" )) .expect("error while running tauri application"); } ================================================ FILE: examples/splashscreen/tauri.conf.json ================================================ { "$schema": "../../crates/tauri-schema-generator/schemas/config.schema.json", "productName": "Splashscreen", "version": "0.1.0", "identifier": "com.tauri.dev", "build": { "frontendDist": "dist" }, "app": { "withGlobalTauri": true, "windows": [ { "label": "main", "title": "Tauri", "width": 800, "height": 600, "visible": false }, { "label": "splashscreen", "width": 400, "height": 200, "decorations": false, "resizable": false, "url": "splashscreen.html" } ], "security": { "csp": "default-src 'self'; connect-src ipc: http://ipc.localhost" } }, "bundle": { "active": true, "targets": "all", "icon": [ "../.icons/32x32.png", "../.icons/128x128.png", "../.icons/128x128@2x.png", "../.icons/icon.icns", "../.icons/icon.ico" ] } } ================================================ FILE: examples/state/README.md ================================================ # State example A simple Tauri Application showcase the application State usage. To execute run the following on the root directory of the repository: `cargo run --example state` ================================================ FILE: examples/state/index.html ================================================ Tauri

Counter:

Press Ctrl+R to reload and see the state persist.

================================================ FILE: examples/state/main.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] use std::sync::Mutex; use tauri::State; struct Counter(Mutex); #[tauri::command] fn increment(counter: State<'_, Counter>) -> isize { let mut c = counter.0.lock().unwrap(); *c += 1; *c } #[tauri::command] fn decrement(counter: State<'_, Counter>) -> isize { let mut c = counter.0.lock().unwrap(); *c -= 1; *c } #[tauri::command] fn reset(counter: State<'_, Counter>) -> isize { let mut c = counter.0.lock().unwrap(); *c = 0; *c } #[tauri::command] fn get(counter: State<'_, Counter>) -> isize { *counter.0.lock().unwrap() } fn main() { tauri::Builder::default() .manage(Counter(Mutex::new(0))) .invoke_handler(tauri::generate_handler![increment, decrement, reset, get]) .run(tauri::generate_context!( "../../examples/state/tauri.conf.json" )) .expect("error while running tauri application"); } ================================================ FILE: examples/state/tauri.conf.json ================================================ { "$schema": "../../crates/tauri-schema-generator/schemas/config.schema.json", "productName": "State", "version": "0.1.0", "identifier": "com.tauri.dev", "build": { "frontendDist": ["index.html"] }, "app": { "withGlobalTauri": true, "windows": [ { "title": "Welcome to Tauri!", "width": 800, "height": 600, "resizable": true, "fullscreen": false } ], "security": { "csp": "default-src 'self'; connect-src ipc: http://ipc.localhost" } }, "bundle": { "active": true, "targets": "all", "icon": [ "../.icons/32x32.png", "../.icons/128x128.png", "../.icons/128x128@2x.png", "../.icons/icon.icns", "../.icons/icon.ico" ] } } ================================================ FILE: examples/streaming/README.md ================================================ # Streaming example A simple Tauri Application showcase how to stream video through custom protocol but can be adapted to stream any type of files. To execute run the following on the root directory of the repository: `cargo run --example streaming`. ### Note Tauri has a built-in `asset` protocol that implements this streaming functionality so you don't need to. This example just exists as a reference. ================================================ FILE: examples/streaming/index.html ================================================ ================================================ FILE: examples/streaming/main.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] use http::{header::*, response::Builder as ResponseBuilder, status::StatusCode}; use http_range::HttpRange; use std::{ io::{Read, Seek, SeekFrom, Write}, path::PathBuf, process::{Command, Stdio}, }; fn get_stream_response( request: http::Request>, ) -> Result>, Box> { // skip leading `/` let path = percent_encoding::percent_decode(&request.uri().path().as_bytes()[1..]) .decode_utf8_lossy() .to_string(); // return error 404 if it's not our video if path != "streaming_example_test_video.mp4" { return Ok(ResponseBuilder::new().status(404).body(Vec::new())?); } let mut file = std::fs::File::open(&path)?; // get file length let len = { let old_pos = file.stream_position()?; let len = file.seek(SeekFrom::End(0))?; file.seek(SeekFrom::Start(old_pos))?; len }; let mut resp = ResponseBuilder::new().header(CONTENT_TYPE, "video/mp4"); // if the webview sent a range header, we need to send a 206 in return let http_response = if let Some(range_header) = request.headers().get("range") { let not_satisfiable = || { ResponseBuilder::new() .status(StatusCode::RANGE_NOT_SATISFIABLE) .header(CONTENT_RANGE, format!("bytes */{len}")) .body(vec![]) }; // parse range header let ranges = if let Ok(ranges) = HttpRange::parse(range_header.to_str()?, len) { ranges .iter() // map the output back to spec range , example: 0-499 .map(|r| (r.start, r.start + r.length - 1)) .collect::>() } else { return Ok(not_satisfiable()?); }; /// The Maximum bytes we send in one range const MAX_LEN: u64 = 1000 * 1024; if ranges.len() == 1 { let &(start, mut end) = ranges.first().unwrap(); // check if a range is not satisfiable // // this should be already taken care of by HttpRange::parse // but checking here again for extra assurance if start >= len || end >= len || end < start { return Ok(not_satisfiable()?); } // adjust end byte for MAX_LEN end = start + (end - start).min(len - start).min(MAX_LEN - 1); // calculate number of bytes needed to be read let bytes_to_read = end + 1 - start; // allocate a buf with a suitable capacity let mut buf = Vec::with_capacity(bytes_to_read as usize); // seek the file to the starting byte file.seek(SeekFrom::Start(start))?; // read the needed bytes file.take(bytes_to_read).read_to_end(&mut buf)?; resp = resp.header(CONTENT_RANGE, format!("bytes {start}-{end}/{len}")); resp = resp.header(CONTENT_LENGTH, end + 1 - start); resp = resp.status(StatusCode::PARTIAL_CONTENT); resp.body(buf) } else { let mut buf = Vec::new(); let ranges = ranges .iter() .filter_map(|&(start, mut end)| { // filter out unsatisfiable ranges // // this should be already taken care of by HttpRange::parse // but checking here again for extra assurance if start >= len || end >= len || end < start { None } else { // adjust end byte for MAX_LEN end = start + (end - start).min(len - start).min(MAX_LEN - 1); Some((start, end)) } }) .collect::>(); let boundary = random_boundary(); let boundary_sep = format!("\r\n--{boundary}\r\n"); let boundary_closer = format!("\r\n--{boundary}\r\n"); resp = resp.header( CONTENT_TYPE, format!("multipart/byteranges; boundary={boundary}"), ); for (start, end) in ranges { // a new range is being written, write the range boundary buf.write_all(boundary_sep.as_bytes())?; // write the needed headers `Content-Type` and `Content-Range` buf.write_all(format!("{CONTENT_TYPE}: video/mp4\r\n").as_bytes())?; buf.write_all(format!("{CONTENT_RANGE}: bytes {start}-{end}/{len}\r\n").as_bytes())?; // write the separator to indicate the start of the range body buf.write_all("\r\n".as_bytes())?; // calculate number of bytes needed to be read let bytes_to_read = end + 1 - start; let mut local_buf = vec![0_u8; bytes_to_read as usize]; file.seek(SeekFrom::Start(start))?; file.read_exact(&mut local_buf)?; buf.extend_from_slice(&local_buf); } // all ranges have been written, write the closing boundary buf.write_all(boundary_closer.as_bytes())?; resp.body(buf) } } else { resp = resp.header(CONTENT_LENGTH, len); let mut buf = Vec::with_capacity(len as usize); file.read_to_end(&mut buf)?; resp.body(buf) }; http_response.map_err(Into::into) } fn random_boundary() -> String { let mut x = [0_u8; 30]; getrandom::fill(&mut x).expect("failed to get random bytes"); (x[..]) .iter() .map(|&x| format!("{x:x}")) .fold(String::new(), |mut a, x| { a.push_str(x.as_str()); a }) } fn download_video() { let video_file = PathBuf::from("streaming_example_test_video.mp4"); if !video_file.exists() { let video_url = "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"; // Downloading with curl this saves us from adding // a Rust HTTP client dependency. println!("Downloading {video_url}"); let status = Command::new("curl") .arg("-L") .arg("-o") .arg(&video_file) .arg(video_url) .stdout(Stdio::inherit()) .stderr(Stdio::inherit()) .output() .unwrap(); assert!(status.status.success()); assert!(video_file.exists()); } } fn main() { download_video(); tauri::Builder::default() .register_asynchronous_uri_scheme_protocol("stream", move |_ctx, request, responder| { match get_stream_response(request) { Ok(http_response) => responder.respond(http_response), Err(e) => responder.respond( ResponseBuilder::new() .status(StatusCode::INTERNAL_SERVER_ERROR) .header(CONTENT_TYPE, "text/plain") .body(e.to_string().as_bytes().to_vec()) .unwrap(), ), } }) .run(tauri::generate_context!( "../../examples/streaming/tauri.conf.json" )) .expect("error while running tauri application"); } ================================================ FILE: examples/streaming/tauri.conf.json ================================================ { "$schema": "../../crates/tauri-schema-generator/schemas/config.schema.json", "productName": "Streaming", "version": "0.1.0", "identifier": "com.tauri.dev", "build": { "frontendDist": ["index.html"] }, "app": { "withGlobalTauri": true, "windows": [ { "title": "Stream video using custom protocol", "width": 800, "height": 600 } ], "security": { "csp": "default-src 'self'; connect-src ipc: http://ipc.localhost; media-src stream: http://stream.localhost", "assetProtocol": { "scope": ["**/streaming_example_test_video.mp4"] } } }, "bundle": { "active": true, "targets": "all", "icon": [ "../.icons/32x32.png", "../.icons/128x128.png", "../.icons/128x128@2x.png", "../.icons/icon.icns", "../.icons/icon.ico" ] } } ================================================ FILE: package.json ================================================ { "name": "tauri-workspace", "version": "0.0.0", "license": "Apache-2.0 OR MIT", "private": true, "contributors": [ "Tauri Programme within The Commons Conservancy" ], "repository": { "type": "git", "url": "https://github.com/tauri-apps/tauri.git" }, "scripts": { "format": "prettier --write .", "format:check": "prettier --check .", "eslint:check": "pnpm run -r eslint:check", "ts:check": "pnpm run -r ts:check", "build": "pnpm run -F !api build && pnpm run -F api build", "build:debug": "pnpm run -F !api build:debug && pnpm run -F api build:debug", "build:api": "pnpm run --filter \"@tauri-apps/api\" build", "build:api:debug": "pnpm run --filter \"@tauri-apps/api\" build:debug", "build:cli": "pnpm run --filter \"@tauri-apps/cli\" build", "build:cli:debug": "pnpm run --filter \"@tauri-apps/cli\" build:debug", "test": "pnpm run -r test", "example:api:dev": "pnpm run --filter \"api\" tauri dev" }, "devDependencies": { "prettier": "^3.8.1" }, "minimumReleaseAge": 4320, "packageManager": "pnpm@10.30.3" } ================================================ FILE: packages/api/.gitignore ================================================ # Build output /dist/ ================================================ FILE: packages/api/CHANGELOG.md ================================================ # Changelog ## \[2.10.1] ### Bug Fixes - Re-release of `2.10.0` with working assets. ## \[2.10.0] ### Dependencies - [`517b81e97`](https://www.github.com/tauri-apps/tauri/commit/517b81e97005d087ca5fc4538d954982fce0f4ac) ([#14876](https://www.github.com/tauri-apps/tauri/pull/14876)) Upgraded to `tauri@2.10` ## \[2.9.1] ### Bug Fixes - [`ad1dec2e2`](https://www.github.com/tauri-apps/tauri/commit/ad1dec2e2488fe5c0a004b69f1bd290dfc593bf8) ([#14464](https://www.github.com/tauri-apps/tauri/pull/14464) by [@funnydino](https://www.github.com/tauri-apps/tauri/../../funnydino)) Fix `addPluginListener` fallback added in https://github.com/tauri-apps/tauri/pull/14132 didn't work properly ## \[2.9.0] ### New Features - [`f5851ee00`](https://www.github.com/tauri-apps/tauri/commit/f5851ee00d6d1f4d560a220ca5a728fedd525092) ([#14089](https://www.github.com/tauri-apps/tauri/pull/14089)) Adds the `scrollBarStyle` option to the Webview and WebviewBuilder constructors. - [`3397fd9bf`](https://www.github.com/tauri-apps/tauri/commit/3397fd9bfe5f6b1337110149f6c34731b8a44bb3) ([#14133](https://www.github.com/tauri-apps/tauri/pull/14133)) Added `app > onBackButtonPress` for Android back button handling. ### Enhancements - [`59089723f`](https://www.github.com/tauri-apps/tauri/commit/59089723fc20d66f3f305f2008adeb279bf87462) ([#14091](https://www.github.com/tauri-apps/tauri/pull/14091)) Added a config to set a data_directory relative to the app-specific data dir in JavaScript and `tauri.conf.json`. ### Bug Fixes - [`08bda64c2`](https://www.github.com/tauri-apps/tauri/commit/08bda64c25008bd45c5b58d06ff14649081a2f5d) ([#14132](https://www.github.com/tauri-apps/tauri/pull/14132)) Fix `core > addPluginListener` failing on command permission check. ## \[2.8.0] ### New Features - [`68874c68c`](https://www.github.com/tauri-apps/tauri/commit/68874c68c566638b4c21a3aa67844d1bdaeb6dab) ([#13564](https://www.github.com/tauri-apps/tauri/pull/13564) by [@robertrpf](https://www.github.com/tauri-apps/tauri/../../robertrpf)) Add window focusable attribute and set_focusable API. - [`5110a762e`](https://www.github.com/tauri-apps/tauri/commit/5110a762e9db978a28a15400bf76e3c864da2a86) ([#13830](https://www.github.com/tauri-apps/tauri/pull/13830) by [@Sky-walkerX](https://www.github.com/tauri-apps/tauri/../../Sky-walkerX)) Added `Window::setSimpleFullscreen`. ### Enhancements - [`5ba1c3faa`](https://www.github.com/tauri-apps/tauri/commit/5ba1c3faa468073512bdb5035a01f7f99720fcf0) ([#13722](https://www.github.com/tauri-apps/tauri/pull/13722) by [@s00d](https://www.github.com/tauri-apps/tauri/../../s00d)) Added icon (icon and nativeIcon) support for Submenu: - In the Rust API (`tauri`), you can now set an icon for submenus via the builder and dedicated methods. - In the JS/TS API (`@tauri-apps/api`), `SubmenuOptions` now has an `icon` field, and the `Submenu` class provides `setIcon` and `setNativeIcon` methods. - Usage examples are added to the documentation and demo app. This is a backwards-compatible feature. Submenus can now display icons just like regular menu items. ## \[2.7.0] ### New Features - [`232265c70`](https://www.github.com/tauri-apps/tauri/commit/232265c70e1c213bbb3f84b5541ddc07d330fce1) ([#13209](https://www.github.com/tauri-apps/tauri/pull/13209) by [@kandrelczyk](https://www.github.com/tauri-apps/tauri/../../kandrelczyk)) Added `getBundleType` to the app module. ### Enhancements - [`96391467e`](https://www.github.com/tauri-apps/tauri/commit/96391467e967c1e3c6475ce75166c58a326116a3) ([#13783](https://www.github.com/tauri-apps/tauri/pull/13783) by [@JosephBrooksbank](https://www.github.com/tauri-apps/tauri/../../JosephBrooksbank)) Allow events emitted with `emit` to be handled correctly by `listen` callbacks when in a mocked environment ### Bug Fixes - [`152d971bc`](https://www.github.com/tauri-apps/tauri/commit/152d971bcd6c1fdc5716f7d5417dd4df5ce7479f) ([#13744](https://www.github.com/tauri-apps/tauri/pull/13744) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Expose `unregisterCallback`, `runCallback`, `callbacks` in `mockIPC` - [`b821796ad`](https://www.github.com/tauri-apps/tauri/commit/b821796add33cca4de72f48882684af487936d02) ([#13810](https://www.github.com/tauri-apps/tauri/pull/13810) by [@asdolo](https://www.github.com/tauri-apps/tauri/../../asdolo)) Add missing `trafficLightPosition` TypeScript type definition ## \[2.6.0] ### New Features - [`50ebddaa2`](https://www.github.com/tauri-apps/tauri/commit/50ebddaa2d83033a393a176ba07ef28352b98210) ([#13319](https://www.github.com/tauri-apps/tauri/pull/13319) by [@kingsword09](https://www.github.com/tauri-apps/tauri/../../kingsword09)) Expose the `setAutoResize` API for webviews in `@tauri-apps/api`. - [`267368fd4`](https://www.github.com/tauri-apps/tauri/commit/267368fd4f83e0a71dfb1b72a66d56592a2066bc) ([#13276](https://www.github.com/tauri-apps/tauri/pull/13276) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `Monitor.workArea` field. ### Bug Fixes - [`23b9da75b`](https://www.github.com/tauri-apps/tauri/commit/23b9da75b91379cca9520bc53b10fdf39ebae241) ([#13324](https://www.github.com/tauri-apps/tauri/pull/13324) by [@kingsword09](https://www.github.com/tauri-apps/tauri/../../kingsword09)) Fixed path joining behavior where `path.join('', 'a')` incorrectly returns "/a" instead of "a". - [`b985eaf0a`](https://www.github.com/tauri-apps/tauri/commit/b985eaf0a231ea570e36d686c665cddbc76ab4f6) ([#13306](https://www.github.com/tauri-apps/tauri/pull/13306) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Immediately unregister event listener when the unlisten function is called. ### What's Changed - [`b5c549d18`](https://www.github.com/tauri-apps/tauri/commit/b5c549d1898ecdb712822c02dc665cc6771fbd07) ([#13325](https://www.github.com/tauri-apps/tauri/pull/13325) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) `transformCallback` now registers the callbacks inside `window.__TAURI_INTERNALS__.callbacks` instead of directly on `window['_{id}']` ## \[2.5.0] ### New Features - [`66e6325f4`](https://www.github.com/tauri-apps/tauri/commit/66e6325f43efa49ec2165c45afec911a1a14ecfb) ([#13136](https://www.github.com/tauri-apps/tauri/pull/13136)) Allow passing the callback as the parameter of constructor of `Channel` so you can use it like this `new Channel((message) => console.log(message))` - [`ea36294cb`](https://www.github.com/tauri-apps/tauri/commit/ea36294cbca98f7725c91d1464fd92e77c89698a) ([#13208](https://www.github.com/tauri-apps/tauri/pull/13208)) Added `disableInputAccessoryView: bool` config for iOS. - [`c1cd0a2dd`](https://www.github.com/tauri-apps/tauri/commit/c1cd0a2ddb5bc3e99451cbe399b5fc9f0035f571) ([#13090](https://www.github.com/tauri-apps/tauri/pull/13090)) macOS/iOS: add option to disable or enable link previews when building a webview (the webkit api has it enabled by default) - `WindowOptions::allowLinkPreview` - `WebviewOptions::allowLinkPreview` - [`b072e2b29`](https://www.github.com/tauri-apps/tauri/commit/b072e2b2967640ae4fa1af466ae878c156551edd) ([#9687](https://www.github.com/tauri-apps/tauri/pull/9687)) Add `preventOverflow` config option to prevent the window from overflowing the monitor size on creation - [`dd4f13ce4`](https://www.github.com/tauri-apps/tauri/commit/dd4f13ce4b3cd89cde2fa3f18a063c272f215621) ([#13185](https://www.github.com/tauri-apps/tauri/pull/13185)) Added `app.setDockVisibility` for macOS. ### Enhancements - [`b8f86669a`](https://www.github.com/tauri-apps/tauri/commit/b8f86669ab05f7dbdd15839a20999e63dc43bda6) ([#13145](https://www.github.com/tauri-apps/tauri/pull/13145)) `core.isTauri` now leverages `globalThis` instead of `window` in order to be used in unit tests. ### Bug Fixes - [`66e6325f4`](https://www.github.com/tauri-apps/tauri/commit/66e6325f43efa49ec2165c45afec911a1a14ecfb) ([#13136](https://www.github.com/tauri-apps/tauri/pull/13136)) Fix `Channel`'s callback attached to `window` never cleaned up ## \[2.4.1] ### Enhancements - [`dd1372833`](https://www.github.com/tauri-apps/tauri/commit/dd137283341ce0e6aabfd158d07d77c6feeb920e) ([#13066](https://www.github.com/tauri-apps/tauri/pull/13066) by [@ahaoboy](https://www.github.com/tauri-apps/tauri/../../ahaoboy)) Add a generic to `emit` and `emitTo` functions for the `payload` instead of the previously used type (`unknown`). ## \[2.4.0] ### New Features - [`d8059bad3`](https://www.github.com/tauri-apps/tauri/commit/d8059bad3cc922dc369c39ca1cfa49aaec31322e) ([#12900](https://www.github.com/tauri-apps/tauri/pull/12900) by [@Simon-Laux](https://www.github.com/tauri-apps/tauri/../../Simon-Laux)) add `AppHandle.fetch_data_store_identifiers` and `AppHandle.remove_data_store` (macOS and iOS only) - [`20c190691`](https://www.github.com/tauri-apps/tauri/commit/20c19069125c89b2d45a2127278c9ffc2df35fc2) ([#12821](https://www.github.com/tauri-apps/tauri/pull/12821) by [@Simon-Laux](https://www.github.com/tauri-apps/tauri/../../Simon-Laux)) Added `WindowOptions::javascriptDisabled` and `WebviewOptions::javascriptDisabled`. - [`060de5bbd`](https://www.github.com/tauri-apps/tauri/commit/060de5bbdddca384e3965a8938d89840f27c581d) ([#12837](https://www.github.com/tauri-apps/tauri/pull/12837) by [@niladrix719](https://www.github.com/tauri-apps/tauri/../../niladrix719)) Added `getIdentifier()` function to get the application identifier configured in tauri.conf.json - [`be2e6b85f`](https://www.github.com/tauri-apps/tauri/commit/be2e6b85fed226732b4a98f68cc5d72b4f8f5a13) ([#12944](https://www.github.com/tauri-apps/tauri/pull/12944) by [@Simon-Laux](https://www.github.com/tauri-apps/tauri/../../Simon-Laux)) Added `Window#isAlwaysOnTop` and `WebviewWindow#isAlwaysOnTop` methods. - [`bcdd51025`](https://www.github.com/tauri-apps/tauri/commit/bcdd510254ebe37827e22a5ffeb944321361e97c) ([#13012](https://www.github.com/tauri-apps/tauri/pull/13012) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) The `path` basename and extname APIs now accept Android content URIs, such as the paths returned by the dialog plugin. ### Bug Fixes - [`3a74dc8f3`](https://www.github.com/tauri-apps/tauri/commit/3a74dc8f3421112b1d0a32b6a432606b1f33cc25) ([#12935](https://www.github.com/tauri-apps/tauri/pull/12935) by [@tk103331](https://www.github.com/tauri-apps/tauri/../../tk103331)) Fix `Webview.close` always fail with command not found ## \[2.3.0] ### Enhancements - [`a2d36b8c3`](https://www.github.com/tauri-apps/tauri/commit/a2d36b8c34a8dcfc6736797ca5cd4665faf75e7e) ([#12181](https://www.github.com/tauri-apps/tauri/pull/12181) by [@bastiankistner](https://www.github.com/tauri-apps/tauri/../../bastiankistner)) Add an option to change the default background throttling policy (currently for WebKit only). ## \[2.2.0] ### New Features - [`020ea0556`](https://www.github.com/tauri-apps/tauri/commit/020ea05561348dcd6d2a7df358f8a5190f661ba2) ([#11661](https://www.github.com/tauri-apps/tauri/pull/11661) by [@ahqsoftwares](https://www.github.com/tauri-apps/tauri/../../ahqsoftwares)) Add badging APIs: - `Window/WebviewWindow::set_badge_count` for Linux, macOS and IOS. - `Window/WebviewWindow::set_overlay_icon` for Windows Only. - `Window/WebviewWindow::set_badge_label`for macOS Only. - [`fc30b20be`](https://www.github.com/tauri-apps/tauri/commit/fc30b20bea125f647db00ca824663f8e1da4d61f) ([#11726](https://www.github.com/tauri-apps/tauri/pull/11726) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `TrayIcon.setShowMenuOnLeftClick` method and deprecate `TrayIcon.setMenuOnLeftClick` to match the Rust API. - [`fc30b20be`](https://www.github.com/tauri-apps/tauri/commit/fc30b20bea125f647db00ca824663f8e1da4d61f) ([#11726](https://www.github.com/tauri-apps/tauri/pull/11726) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `TrayIconOptions.showMenuOnLeftClick` field and deprecate `TrayIconOptions.menuOnLeftClick` to match the Rust API. ### Enhancements - [`fc30b20be`](https://www.github.com/tauri-apps/tauri/commit/fc30b20bea125f647db00ca824663f8e1da4d61f) ([#11726](https://www.github.com/tauri-apps/tauri/pull/11726) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add support for `TrayIconOptions.menuOnLeftClick` option and `TrayIcon.setMenuOnLeftClick` on Windows. ### Bug Fixes - [`a16796a55`](https://www.github.com/tauri-apps/tauri/commit/a16796a55592cf5be80043edfbb630dd2e32efab) ([#12069](https://www.github.com/tauri-apps/tauri/pull/12069) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix `Channel` never calls `onmessage` in some cases - [`12a48d1e2`](https://www.github.com/tauri-apps/tauri/commit/12a48d1e26a83c3915eaa0687b196fbc8f2d457a) ([#11741](https://www.github.com/tauri-apps/tauri/pull/11741) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix error when calling `PredefinedMenuItem.new` to create an `About` menu item that uses an `Image` instance for the about icon. - [`12a48d1e2`](https://www.github.com/tauri-apps/tauri/commit/12a48d1e26a83c3915eaa0687b196fbc8f2d457a) ([#11741](https://www.github.com/tauri-apps/tauri/pull/11741) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix error when calling `IconMenuItem.new` using an `Image` instance for the icon. - [`b63262cd4`](https://www.github.com/tauri-apps/tauri/commit/b63262cd4d6a3667ca1664607a0a5444ad79fe0e) ([#11724](https://www.github.com/tauri-apps/tauri/pull/11724) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Removed the generic in the type of the callback function argument in `mockIPC` which prevented its proper use in tests using TypeScript. - [`a6e84f7d2`](https://www.github.com/tauri-apps/tauri/commit/a6e84f7d2c1d5fdc65901fce683502be3f47833f) ([#11835](https://www.github.com/tauri-apps/tauri/pull/11835) by [@ilittlebig](https://www.github.com/tauri-apps/tauri/../../ilittlebig)) Fix error where using `isAbsolute` would return `Command not found`. ## \[2.1.1] ### Bug Fixes - [`7f81f0523`](https://www.github.com/tauri-apps/tauri/commit/7f81f052365675721312aafba297a7b67fb872d2) Fix regression in `toLogical` and `toPhysical` for position types in `dpi` module returning incorrect `y` value. - [`e8a50f6d7`](https://www.github.com/tauri-apps/tauri/commit/e8a50f6d760fad4529e7abb400302a1b487f11dd) ([#11645](https://www.github.com/tauri-apps/tauri/pull/11645)) Fix integer values of `BasDirectory.Home` and `BaseDirectory.Font` regression which broke path APIs in JS. ## \[2.1.0] ### New Features - [`5c4b83084`](https://www.github.com/tauri-apps/tauri/commit/5c4b830843ab085f8ff9db9e08d832223b027e4e) ([#11191](https://www.github.com/tauri-apps/tauri/pull/11191) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Improved support for `dpi` module types to allow these types to be used without manual conversions with `invoke`: - Added `SERIALIZE_TO_IPC_FN` const in `core` module which can be used to implement custom IPC serialization for types passed to `invoke`. - Added `Size` and `Position` classes in `dpi` module. - Implementd `SERIALIZE_TO_IPC_FN` method on `PhysicalSize`, `PhysicalPosition`, `LogicalSize` and `LogicalPosition` to convert it into a valid IPC-compatible value that can be deserialized correctly on the Rust side into its equivalent struct. - [`4d545ab3c`](https://www.github.com/tauri-apps/tauri/commit/4d545ab3ca228c8a21b966b709f84a0da2864479) ([#11486](https://www.github.com/tauri-apps/tauri/pull/11486) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Added `Webview::setBackgroundColor`, `WebviewWindow::setBackgroundColor` APIs to set the window background color dynamically and a `backgroundColor` window option to set the background color on window creation. - [`cbc095ec5`](https://www.github.com/tauri-apps/tauri/commit/cbc095ec5fe7de29b5c9265576d4e071ec159c1c) ([#11451](https://www.github.com/tauri-apps/tauri/pull/11451) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `app > windows > devtools` config option and when creating the webview from JS, to enable or disable devtools for a specific webview. - [`2a75c64b5`](https://www.github.com/tauri-apps/tauri/commit/2a75c64b5431284e7340e8743d4ea56a62c75466) ([#11469](https://www.github.com/tauri-apps/tauri/pull/11469) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Added `windowClassname` option, when constructing a `Webview` or `WebviewWindow`, to specify the name of the window class on Windows. ### Bug Fixes - [`54cbf59b5`](https://www.github.com/tauri-apps/tauri/commit/54cbf59b5a572570a47237a3b5e6505f2a9e5d5d) ([#11441](https://www.github.com/tauri-apps/tauri/pull/11441) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix submenu created as a menu item instead of a submenu when created by using an object in the `items` field in the options object passed to `Menu.new` or `Submenu.new`. ## \[2.0.3] ### Bug Fixes - [`fbb45c674`](https://www.github.com/tauri-apps/tauri/commit/fbb45c674ca92fbbe04f1a8360e5f2e477dd4297) ([#11423](https://www.github.com/tauri-apps/tauri/pull/11423) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes `addPluginListener` not working. ### What's Changed - [`2e88633ba`](https://www.github.com/tauri-apps/tauri/commit/2e88633ba4da8fc289c6d8a29c36f3327f9b576e) ([#11369](https://www.github.com/tauri-apps/tauri/pull/11369) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Remove references to no longer used `__TAURI_INTERNALS__.metadata.windows` and `__TAURI_INTERNALS__.metadata.webviews`. ## \[2.0.2] ### What's Changed - [`e968b3d25`](https://www.github.com/tauri-apps/tauri/commit/e968b3d2527b8edf7653e6cf7284dc4a8889b5fe) ([#11219](https://www.github.com/tauri-apps/tauri/pull/11219) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Actually publish package with the latest tag. ## \[2.0.1] ### What's Changed - [`be683e2ac`](https://www.github.com/tauri-apps/tauri/commit/be683e2ac36df9c51a5c050d9d500247bd019090) ([#11199](https://www.github.com/tauri-apps/tauri/pull/11199) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Publish package with the latest NPM tag. ## \[2.0.0] ### What's Changed - [`637285790`](https://www.github.com/tauri-apps/tauri/commit/6372857905ae9c0aedb7f482ddf6cf9f9836c9f2) Promote to v2 stable! ## \[2.0.0-rc.6] ### New Features - [`9014a3f17`](https://www.github.com/tauri-apps/tauri/commit/9014a3f1765ca406ea5c3e5224267a79c52cd53d) ([#11066](https://www.github.com/tauri-apps/tauri/pull/11066) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `WebviewWindow.clearAllBrowsingData` and `Webview.clearAllBrowsingData` to clear the webview browsing data. - [`95df53a2e`](https://www.github.com/tauri-apps/tauri/commit/95df53a2ed96873cd35a4b14a5e312d07e4e3004) ([#11143](https://www.github.com/tauri-apps/tauri/pull/11143) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Add the ability to set theme dynamically using `Window.setTheme` or `setTheme` function from the `app` module - [`d9d2502b4`](https://www.github.com/tauri-apps/tauri/commit/d9d2502b41e39efde679e30c8955006e2ba9ea64) ([#11140](https://www.github.com/tauri-apps/tauri/pull/11140) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `Webview.hide` and `Webview.show` methods. - [`de7414aab`](https://www.github.com/tauri-apps/tauri/commit/de7414aab935e45540594ea930eb60bae4dbc979) ([#11154](https://www.github.com/tauri-apps/tauri/pull/11154) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `Window::setEnabled` and `Window::isEnabled` methods ### Bug Fixes - [`948772a65`](https://www.github.com/tauri-apps/tauri/commit/948772a657eb3caf20843628abac9109e3b67d41) ([#11114](https://www.github.com/tauri-apps/tauri/pull/11114) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Change the `button_state` tray event field to camelCase `buttonState`. ### Breaking Changes - [`0b4495996`](https://www.github.com/tauri-apps/tauri/commit/0b4495996d3131a5ee80fbb2c71a28203e491ee7) ([#11121](https://www.github.com/tauri-apps/tauri/pull/11121) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Simplified emitted tray event JS value and updated `TrayIconEvent` type definition to match it. ## \[2.0.0-rc.5] ### New Features - [`ddf69157b`](https://www.github.com/tauri-apps/tauri/commit/ddf69157b54249f3321ca72db6703812019f1ab9) ([#11031](https://www.github.com/tauri-apps/tauri/pull/11031) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `toPhysical` method on `LogicalPositon` and `LogicalSize` classes. ## \[2.0.0-rc.4] ### Enhancements - [`f81929e25`](https://www.github.com/tauri-apps/tauri/commit/f81929e25104aa1091e464bd012c80649dedf9e5) ([#10799](https://www.github.com/tauri-apps/tauri/pull/10799) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Added `PermissionState`, `checkPermissions` and `requestPermissions` base APIs to the core module, designed for plugin authors to extend. ### Bug Fixes - [`fbe76a955`](https://www.github.com/tauri-apps/tauri/commit/fbe76a955a63af9fb33f66d5f747caf858cf179b) ([#10797](https://www.github.com/tauri-apps/tauri/pull/10797) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Uint8Arrays and ArrayBuffers are now properly serialized as an array of numbers. ## \[2.0.0-rc.3] ### What's Changed - [`f4d5241b3`](https://www.github.com/tauri-apps/tauri/commit/f4d5241b377d0f7a1b58100ee19f7843384634ac) ([#10731](https://www.github.com/tauri-apps/tauri/pull/10731) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Update documentation icon path. ## \[2.0.0-rc.2] ### Bug Fixes - [`c689521a7`](https://www.github.com/tauri-apps/tauri/commit/c689521a7674b6562b5dfd4f5cacd12138d99d85) ([#10681](https://www.github.com/tauri-apps/tauri/pull/10681) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix tslib path in dist. ## \[2.0.0-rc.1] ### Breaking Changes - [`b6dca99ff`](https://www.github.com/tauri-apps/tauri/commit/b6dca99fff73816a39380b288c299b47b493cfdb) ([#10630](https://www.github.com/tauri-apps/tauri/pull/10630) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Changed `WebviewWindow.getAll`, `WebviewWindow.getByLabel`, `getAllWebviewWindows`, `Window.getAll`, `Window.getByLabel`, `getAllWindows`, `Webview.getAll`, `Webview.getByLabel`, `getAllWebviews` to be async so their return value are synchronized with the state from the Rust side, meaning new and destroyed windows are reflected. ## \[2.0.0-rc.0] ### Changes - Promoted to RC! ## \[2.0.0-beta.16] ### New Features - [`da25f7353`](https://www.github.com/tauri-apps/tauri/commit/da25f7353070477ba969851e974379d7666d6806) ([#10242](https://www.github.com/tauri-apps/tauri/pull/10242) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add APIs to enable setting window size constraints separately: - Added `WindowSizeConstraints` interface in `window` and `webviewWindow` modules. - Added `Window.setSizeConstraints` and `WebviewWindow.setSizeConstraints` ### Bug Fixes - [`3c17fb64f`](https://www.github.com/tauri-apps/tauri/commit/3c17fb64fd822597d5cc16ee7e7b3f9e1023637b) ([#10277](https://www.github.com/tauri-apps/tauri/pull/10277) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix `Webview.reparent` pointing to `set_webview_focus` instead of `reparent` Rust API - [`da25f7353`](https://www.github.com/tauri-apps/tauri/commit/da25f7353070477ba969851e974379d7666d6806) ([#10242](https://www.github.com/tauri-apps/tauri/pull/10242) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Apply `minWidth`, `minHieght`, `maxWidth` and `maxHeight` constraints separately, which fixes a long standing bug where these constraints were never applied unless width and height were constrained together. ## \[2.0.0-beta.15] ### New Features - [`7bc6a2a1d`](https://www.github.com/tauri-apps/tauri/commit/7bc6a2a1d6d2c5406d91cac94d33bce76443c28f) ([#9788](https://www.github.com/tauri-apps/tauri/pull/9788) by [@pewsheen](https://www.github.com/tauri-apps/tauri/../../pewsheen)) Add a new method to set title bar style dynamically on macOS. ### Enhancements - [`080b6e127`](https://www.github.com/tauri-apps/tauri/commit/080b6e12720b89d839c686d7067cc94d276ed7e4) ([#10246](https://www.github.com/tauri-apps/tauri/pull/10246) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Use `EventName` on `Window`, `Webview` and `WebviewWindow`'s `once` so you can get auto complete for tauri's built-in events ### Bug Fixes - [`080b6e127`](https://www.github.com/tauri-apps/tauri/commit/080b6e12720b89d839c686d7067cc94d276ed7e4) ([#10246](https://www.github.com/tauri-apps/tauri/pull/10246) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix `once` doesn't detached after one callback if event handler throws ### Breaking Changes - [`261c9f942`](https://www.github.com/tauri-apps/tauri/commit/261c9f942de9a598b5c6cc504de6bddd1306113b) ([#10170](https://www.github.com/tauri-apps/tauri/pull/10170) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Renamed drag and drop events in `TauriEvent` enum to better convey when they are triggered: - `TauriEvent.DRAG` -> `TauriEvent.DRAG_ENTER` - `TauriEvent.DROP_OVER` -> `TauriEvent.DRAG_OVER` - `TauriEvent.DROP` -> `TauriEvent.DRAG_DROP` - `TauriEvent.DROP_CANCELLED` -> `TauriEvent::DRAG_LEAVE` Also the `type` field values in `Window/Webview/WebviewWindow.onDropEvent` and `DragDropEvent` have changed: - `dragged` -> `enter` - `dragOver` -> `over` - `dropped` -> `drop` - `cancelled` -> `leave` - [`2b1ceb40d`](https://www.github.com/tauri-apps/tauri/commit/2b1ceb40d345aef42dd79438fa69ca7989ee0194) ([#10229](https://www.github.com/tauri-apps/tauri/pull/10229) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Renamed the JS `getCurrent` and `getAll` functions to a clearer name to avoid ambiguity: - `getCurrent` in `window` module has been renamed to `getCurrentWindow` - `getCurrent` in `webview` module has been renamed to `getCurrentWebview` - `getCurrent` in `webviewWindow` module has been renamed to `getCurrentWebviewWindow` - `getAll` in `window` module has been renamed to `getAllWindows` - `getAll` in `webview` module has been renamed to `getAllWebviews` - `getAll` in `webviewWindow` module has been renamed to `getAllWebviewWindows` ## \[2.0.0-beta.14] ### New Features - [`148f04887`](https://www.github.com/tauri-apps/tauri/commit/148f048871caee21498b236c058b8890f2b66cc7) ([#9979](https://www.github.com/tauri-apps/tauri/pull/9979)) Add `defaultWindowIcon` to the JS `app` module to retrieve the default window icon in JS. ### Bug Fixes - [`c98f385cb`](https://www.github.com/tauri-apps/tauri/commit/c98f385cb5da4d72968df24b1fc0b58212d59653) ([#10044](https://www.github.com/tauri-apps/tauri/pull/10044)) Export `mocks` module in `@tauri-apps/api` npm package. ## \[2.0.0-beta.13] ### Breaking Changes - [`c4410daa8`](https://www.github.com/tauri-apps/tauri/commit/c4410daa85616340e911c8243fdaa69e6906fd49)([#9777](https://www.github.com/tauri-apps/tauri/pull/9777)) This release contains breaking changes to the tray event structure because of newly added events: - Changed `TrayIconEvent` to be an enum instead of a struct. - Added `MouseButtonState` and `MouseButton` enums. - Removed `ClickType` enum and replaced it with `MouseButton` enum. - Added `MouseButtonState` enum. ## \[2.0.0-beta.12] ### New Features - [`ec0e092ec`](https://www.github.com/tauri-apps/tauri/commit/ec0e092ecd23b547c756c7476f23a0d95be6db80)([#9770](https://www.github.com/tauri-apps/tauri/pull/9770)) Add `monitorFromPoint` function in `window` module to get the monitor from a given point. ## \[2.0.0-beta.11] ### Bug Fixes - [`aa080696e`](https://www.github.com/tauri-apps/tauri/commit/aa080696e0952abff416dd9088d519eaf2587a3a)([#9618](https://www.github.com/tauri-apps/tauri/pull/9618)) Fix `isTauri` incorrect return type. ## \[2.0.0-beta.10] ### New Features - [`477bb8cd4`](https://www.github.com/tauri-apps/tauri/commit/477bb8cd4ea88ade3f6c1f268ad1701a68150161)([#9297](https://www.github.com/tauri-apps/tauri/pull/9297)) Add `cursorPosition` function in `window` module to get the current cursor position. ## \[2.0.0-beta.9] ### New Features - [`70c51371e`](https://www.github.com/tauri-apps/tauri/commit/70c51371e01184223312de3dba8030394a5a9406)([#9539](https://www.github.com/tauri-apps/tauri/pull/9539)) Add `isTauri` function in `core` module to check whether running inside tauri or not. ### Bug Fixes - [`be7eab209`](https://www.github.com/tauri-apps/tauri/commit/be7eab209c60c45e140f7bcb4bab1037d62d4c03)([#9486](https://www.github.com/tauri-apps/tauri/pull/9486)) Set the `exports > types` package.json field. - [`cf615e8e4`](https://www.github.com/tauri-apps/tauri/commit/cf615e8e4d5008ee1ac3f77e530ba26fb91e8977)([#9463](https://www.github.com/tauri-apps/tauri/pull/9463)) Fixes a bug when processing channel messages out of order. - [`35b25f7e5`](https://www.github.com/tauri-apps/tauri/commit/35b25f7e5c0fe03af4ed3582e22a626863f035f0)([#9530](https://www.github.com/tauri-apps/tauri/pull/9530)) Do not use JS optional chaining to prevent script errors on older webviews such as macOS 10.14. ## \[2.0.0-beta.8] ### New Features - [`58a7a552d`](https://www.github.com/tauri-apps/tauri/commit/58a7a552d739b77b71d61af11c53f7f2dc7a6e7e)([#9378](https://www.github.com/tauri-apps/tauri/pull/9378)) Added the `set_zoom` function to the webview API. - [`58a7a552d`](https://www.github.com/tauri-apps/tauri/commit/58a7a552d739b77b71d61af11c53f7f2dc7a6e7e)([#9378](https://www.github.com/tauri-apps/tauri/pull/9378)) Add `zoom_hotkeys_enabled` to enable browser native zoom controls on creating webviews. ### Bug Fixes - [`48a7a78f8`](https://www.github.com/tauri-apps/tauri/commit/48a7a78f8094d08e5e403e88050391642d29151b)([#9376](https://www.github.com/tauri-apps/tauri/pull/9376)) Fix `Window/Webview/WebviewWindow.setSize`, `Window/Webview/WebviewWindow.setPostion`, `Window/WebviewWindow.setMinSize`, `Window/WebviewWindow.setMaxSize`, `Window/WebviewWindow.setCursorPosition` and `Menu/Submenu.popup` methods failing with invalid args. ## \[2.0.0-beta.7] ### Bug Fixes - [`c33f6e6cf`](https://www.github.com/tauri-apps/tauri/commit/c33f6e6cf35a0d34b5598875a2e5b642a01c8b38)([#9211](https://www.github.com/tauri-apps/tauri/pull/9211)) Re-added the `TauriEvent.WINDOW_CREATED` (`tauri://window-created`) event. ### Breaking Changes - [`06833f4fa`](https://www.github.com/tauri-apps/tauri/commit/06833f4fa8e63ecc55fe3fc874a9e397e77a5709)([#9100](https://www.github.com/tauri-apps/tauri/pull/9100)) Rename `FileDrop` to `DragDrop` on structs, enums and enum variants. Also renamed `file_drop` to `drag_drop` on fields and function names. ## \[2.0.0-beta.6] ### New Features - [`acdd76833`](https://www.github.com/tauri-apps/tauri/commit/acdd76833db6d81f4012418133d0042220de100b)([#9155](https://www.github.com/tauri-apps/tauri/pull/9155)) Add `TrayIcon.getById` and `TrayIcon.removeById` static methods. ### Enhancements - [`ea0242db4`](https://www.github.com/tauri-apps/tauri/commit/ea0242db4aa6c127d2bb4a2e275000ba47c9e68c)([#9179](https://www.github.com/tauri-apps/tauri/pull/9179)) The `Image` constructor is now public (for internal use only). ### Bug Fixes - [`379cc2b35`](https://www.github.com/tauri-apps/tauri/commit/379cc2b3547395474d4b66b4222679cf4538428d)([#9165](https://www.github.com/tauri-apps/tauri/pull/9165)) Fix `basename(path, 'ext')` JS API when removing all occurances of `ext` where it should only remove the last one. ### Breaking Changes - [`ea0242db4`](https://www.github.com/tauri-apps/tauri/commit/ea0242db4aa6c127d2bb4a2e275000ba47c9e68c)([#9179](https://www.github.com/tauri-apps/tauri/pull/9179)) `Image::rgba()` now returns `Promise`. - [`ea0242db4`](https://www.github.com/tauri-apps/tauri/commit/ea0242db4aa6c127d2bb4a2e275000ba47c9e68c)([#9179](https://www.github.com/tauri-apps/tauri/pull/9179)) Removed `width` and `height` methods on the JS `Image` class, use `size` instead. ## \[2.0.0-beta.5] ### Breaking Changes - [`db0a24a97`](https://www.github.com/tauri-apps/tauri/commit/db0a24a973191752aeecfbd556faa254b0f17e79)([#9132](https://www.github.com/tauri-apps/tauri/pull/9132)) Remove the `Image.fromPngBytes` and `Image.fromIcoBytes` APIs. Use `Image.fromBytes` instead. ## \[2.0.0-beta.4] ### New Features - [`d1e77acd8`](https://www.github.com/tauri-apps/tauri/commit/d1e77acd8dfdf554b90b542513a58a2de1ef2360)([#9011](https://www.github.com/tauri-apps/tauri/pull/9011)) Add a new `Image` type in Rust and JS. ### Enhancements - [`e62ca4ee9`](https://www.github.com/tauri-apps/tauri/commit/e62ca4ee95f4308a6ad128d0f100c85634e28223)([#9070](https://www.github.com/tauri-apps/tauri/pull/9070)) Added a mechanism to preserve channel message order. ## \[2.0.0-beta.3] ### New Features - [`fdcaf935`](https://www.github.com/tauri-apps/tauri/commit/fdcaf935fa75ecfa2806939c4faad4fe9e880386)([#8939](https://www.github.com/tauri-apps/tauri/pull/8939)) Added the `reparent` function to the webview API. ## \[2.0.0-beta.2] ### Breaking Changes - [`361ec37f`](https://www.github.com/tauri-apps/tauri/commit/361ec37fd4a5caa5b6630b9563ef079f53c6c336)([#8932](https://www.github.com/tauri-apps/tauri/pull/8932)) Removed the `unityUri` option from the progress bar state, no longer required. ## \[2.0.0-beta.1] ### New Features - [`16e550ec`](https://www.github.com/tauri-apps/tauri/commit/16e550ec1503765158cdc3bb2a20e70ec710e981)([#8844](https://www.github.com/tauri-apps/tauri/pull/8844)) Add a new `webviewWindow` module that exports `WebviewWindow` class and related methods such as `getCurrent` and `getAll`. - [`16e550ec`](https://www.github.com/tauri-apps/tauri/commit/16e550ec1503765158cdc3bb2a20e70ec710e981)([#8844](https://www.github.com/tauri-apps/tauri/pull/8844)) Add `Window.onFileDropEvent` method. ### Breaking Changes - [`16e550ec`](https://www.github.com/tauri-apps/tauri/commit/16e550ec1503765158cdc3bb2a20e70ec710e981)([#8844](https://www.github.com/tauri-apps/tauri/pull/8844)) Renamed the following enum variants of `TauriEvent` enum: - `TauriEvent.WEBVIEW_FILE_DROP` -> `TauriEvent.FILE_DROP` - `TauriEvent.WEBVIEW_FILE_DROP_HOVER` -> `TauriEvent.FILE_DROP_HOVER` - `TauriEvent.WEBVIEW_FILE_DROP_CANCELLED` -> `TauriEvent.FILE_DROP_CANCELLED` - [`16e550ec`](https://www.github.com/tauri-apps/tauri/commit/16e550ec1503765158cdc3bb2a20e70ec710e981)([#8844](https://www.github.com/tauri-apps/tauri/pull/8844)) Move `WebviewWindow` class from `webview` module to a new `webviewWindow` module. ## \[2.0.0-beta.0] ### New Features - [`74a2a603`](https://www.github.com/tauri-apps/tauri/commit/74a2a6036a5e57462f161d728cbd8a6f121028ca)([#8661](https://www.github.com/tauri-apps/tauri/pull/8661)) Implement access control list for IPC usage. - [`a093682d`](https://www.github.com/tauri-apps/tauri/commit/a093682d2df7169b024bb4f736c7f1fd2ea8b327)([#8621](https://www.github.com/tauri-apps/tauri/pull/8621)) Added `emitTo` api to `event` module which is equivalent to the rust `emit_to` method. Also added `emitTo` method on `Window`, `Webivew` and `WebviewWindow` classes. - [`a2fc3a63`](https://www.github.com/tauri-apps/tauri/commit/a2fc3a63579ca739646d696870cbecbb3a169d33)([#8657](https://www.github.com/tauri-apps/tauri/pull/8657)) Add `visibleOnAllWorkspaces` option when creating the window in JS and `Window.setVisibleOnAllWorkspaces` method. - [`7f033f6d`](https://www.github.com/tauri-apps/tauri/commit/7f033f6dcd54c69a4193765a5c1584755ba92c61)([#8537](https://www.github.com/tauri-apps/tauri/pull/8537)) Add `Window.startResizeDragging`. - [`9eaeb5a8`](https://www.github.com/tauri-apps/tauri/commit/9eaeb5a8cd95ae24b5e66205bdc2763cb7f965ce)([#8622](https://www.github.com/tauri-apps/tauri/pull/8622)) Add `parent` option when creating a window. - [`af610232`](https://www.github.com/tauri-apps/tauri/commit/af6102327376884364b2075b468bdf08ee0d02aa)([#8710](https://www.github.com/tauri-apps/tauri/pull/8710)) Added `Window::destroy` to force close a window. - [`c77b4032`](https://www.github.com/tauri-apps/tauri/commit/c77b40324ea9bf580871fc11aed69ba0c9b6b8cf)([#8280](https://www.github.com/tauri-apps/tauri/pull/8280)) Added support to multiwebview via the new `window` and `webview` modules. ### Breaking Changes - [`c77b4032`](https://www.github.com/tauri-apps/tauri/commit/c77b40324ea9bf580871fc11aed69ba0c9b6b8cf)([#8280](https://www.github.com/tauri-apps/tauri/pull/8280)) Removed event callback's `windowLabel`. - [`c77b4032`](https://www.github.com/tauri-apps/tauri/commit/c77b40324ea9bf580871fc11aed69ba0c9b6b8cf)([#8280](https://www.github.com/tauri-apps/tauri/pull/8280)) The event target is now an object so you can target either a window or a webview. - [`c77b4032`](https://www.github.com/tauri-apps/tauri/commit/c77b40324ea9bf580871fc11aed69ba0c9b6b8cf)([#8280](https://www.github.com/tauri-apps/tauri/pull/8280)) Moved webview-specific APIs from the `Window` class to the `Webview` class. - [`c77b4032`](https://www.github.com/tauri-apps/tauri/commit/c77b40324ea9bf580871fc11aed69ba0c9b6b8cf)([#8280](https://www.github.com/tauri-apps/tauri/pull/8280)) Renamed `TauriEvent.WINDOW_FILE_DROP` to `TauriEvent.WEBVIEW_FILE_DROP`, `TauriEvent.WINDOW_FILE_DROP_HOVER` to `TauriEvent.WEBVIEW_FILE_DROP_HOVER` and `TauriEvent.WINDOW_FILE_DROP_CANCELLED` to `TauriEvent.WEBVIEW_FILE_DROP_CANCELLED`. - [`c77b4032`](https://www.github.com/tauri-apps/tauri/commit/c77b40324ea9bf580871fc11aed69ba0c9b6b8cf)([#8280](https://www.github.com/tauri-apps/tauri/pull/8280)) Added back the `WebviewWindow` API that exposes functionality of a window that hosts a single webview. The dedicated `Window` and `Webview` types are exposed for multiwebview features. - [`af610232`](https://www.github.com/tauri-apps/tauri/commit/af6102327376884364b2075b468bdf08ee0d02aa)([#8710](https://www.github.com/tauri-apps/tauri/pull/8710)) `Window::close` now triggers a close requested event instead of forcing the window to be closed. ## \[2.0.0-alpha.14] - [`97e33412`](https://www.github.com/tauri-apps/tauri/commit/97e334129956159bbd60e1c531b6acd3bc6139a6)([#8534](https://www.github.com/tauri-apps/tauri/pull/8534)) `mockIPC` and `mockWindows` no longer crash if `window.__TAURI_INTERNALS__` is undefined. ## \[2.0.0-alpha.13] ### New Features - [`428ea652`](https://www.github.com/tauri-apps/tauri/commit/428ea6524c70545be33aac96d7c22b21f25caa4c)([#8370](https://www.github.com/tauri-apps/tauri/pull/8370)) Exposed `Resource` class which should be extended for Rust-backed resources created through `tauri::Manager::resources_table`. ### Bug Fixes - [`ef21b681`](https://www.github.com/tauri-apps/tauri/commit/ef21b681e237a80592c9118b9c023c1d57231bac)([#8391](https://www.github.com/tauri-apps/tauri/pull/8391)) Fix a regression where typescript could not find types when using `"moduleResolution": "node"` - [`46451aee`](https://www.github.com/tauri-apps/tauri/commit/46451aee1318f63a6cd861a12b63929b38c64eb6)([#8268](https://www.github.com/tauri-apps/tauri/pull/8268)) Add top-level `main`, `module` and `types` fields in `package.json` to be compliant with typescripts's `"moduleResolution": "node"` ### Breaking Changes - [`c2ad4d28`](https://www.github.com/tauri-apps/tauri/commit/c2ad4d28c481b2d7ed643458db56210cd44a2e0c)([#8273](https://www.github.com/tauri-apps/tauri/pull/8273)) Changed former `tauri` module from `primitives` to `core`. ## \[2.0.0-alpha.12] ### New Features - [`f93148ea`](https://www.github.com/tauri-apps/tauri/commit/f93148eac05a1428e038bd9351a8149b2464ff4c)([#7709](https://www.github.com/tauri-apps/tauri/pull/7709)) Add `tray` and `menu` modules to create and manage tray icons and menus from Javascript. ### Enhancements - [`b7add750`](https://www.github.com/tauri-apps/tauri/commit/b7add750ef9f32d959de613ab35063ff240281c2)([#8204](https://www.github.com/tauri-apps/tauri/pull/8204)) Added `position` field to the `FileDropEvent` payload. ## \[2.0.0-alpha.11] ### Bug Fixes - [`822bf15d`](https://www.github.com/tauri-apps/tauri/commit/822bf15d6b258556b689ca55ac2ac224897e913a)([#8130](https://www.github.com/tauri-apps/tauri/pull/8130)) Fix tslib missing in the distributed api package. ## \[2.0.0-alpha.10] ### Enhancements - [`c6c59cf2`](https://www.github.com/tauri-apps/tauri/commit/c6c59cf2373258b626b00a26f4de4331765dd487) Pull changes from Tauri 1.5 release. ### Bug Fixes - [`287066b2`](https://www.github.com/tauri-apps/tauri/commit/287066b279f503dd09bfd43d5da37d1f471451fb)([#8071](https://www.github.com/tauri-apps/tauri/pull/8071)) No longer crashing in tests without mocks when `clearMocks` is defined in `afterEach` hook. ## \[2.0.0-alpha.9] ### New Features - [`c1ec0f15`](https://www.github.com/tauri-apps/tauri/commit/c1ec0f155118527361dd5645d920becbc8afd569)([#7933](https://www.github.com/tauri-apps/tauri/pull/7933)) Added `setAlwaysOnBottom` function on `Window` and the `alwaysOnBottom` option when creating a window. - [`fb10b879`](https://www.github.com/tauri-apps/tauri/commit/fb10b87970a43320ef4d14564f45e7579b774eaf)([#8039](https://www.github.com/tauri-apps/tauri/pull/8039)) Add the `app` module back. - [`ed32257d`](https://www.github.com/tauri-apps/tauri/commit/ed32257d044f90b5eb15053efd1667125def2d2b)([#7794](https://www.github.com/tauri-apps/tauri/pull/7794)) On Windows, add `Effect.Tabbed`,`Effect.TabbedDark` and `Effect.TabbedLight` effects. - [`c9a9246c`](https://www.github.com/tauri-apps/tauri/commit/c9a9246c37bdf190661355c8ee406dac6c427344)([#8007](https://www.github.com/tauri-apps/tauri/pull/8007)) Add the `window` module back. - [`c085adda`](https://www.github.com/tauri-apps/tauri/commit/c085addab58ba851398373c6fd13f9cb026d71e8)([#8009](https://www.github.com/tauri-apps/tauri/pull/8009)) Added the `setProgressBar` API on the `Window` class. ### What's Changed - [`5c0eeb40`](https://www.github.com/tauri-apps/tauri/commit/5c0eeb40c1003583290ff3aebfa02e2b5f5b9c41)([#7638](https://www.github.com/tauri-apps/tauri/pull/7638)) Updated minimum Node.js version to 18. ### Breaking Changes - [`a63e71f9`](https://www.github.com/tauri-apps/tauri/commit/a63e71f9799e9bbc82521d2f17b5238fbf690e89)([#7942](https://www.github.com/tauri-apps/tauri/pull/7942)) Changed `tauri` module to `primitives` and removed the undocumented `invoke` export from the root module. ## \[2.0.0-alpha.8] ### Breaking Changes - [`d5074af5`](https://www.github.com/tauri-apps/tauri/commit/d5074af562b2b5cb6c5711442097c4058af32db6)([#7801](https://www.github.com/tauri-apps/tauri/pull/7801)) The custom protocol on Android now uses the `http` scheme instead of `https`. ## \[2.0.0-alpha.7] ### Breaking Changes - [`4cb51a2d`](https://www.github.com/tauri-apps/tauri/commit/4cb51a2d56cfcae0749062c79ede5236bd8c02c2)([#7779](https://www.github.com/tauri-apps/tauri/pull/7779)) The custom protocol on Windows now uses the `http` scheme instead of `https`. ## \[2.0.0-alpha.6] ### New Features - [`4af5c5a8`](https://www.github.com/tauri-apps/tauri/commit/4af5c5a8293263c16f8a65e8d232f2de52f41701)([#7170](https://www.github.com/tauri-apps/tauri/pull/7170)) Change the IPC call to align with the new format for the custom protocol based API. ## \[2.0.0-alpha.5] ### New Features - [`e0f0dce2`](https://www.github.com/tauri-apps/tauri/commit/e0f0dce220730e2822fc202463aedf0166145de7)([#6442](https://www.github.com/tauri-apps/tauri/pull/6442)) Added the `windowEffects` option when creating a window and `setWindowEffects` method to change it at runtime. ### Enhancements - [`9e3a18e0`](https://www.github.com/tauri-apps/tauri/commit/9e3a18e04672edad15d0ec654bd8632544871967)([#7132](https://www.github.com/tauri-apps/tauri/pull/7132)) Expose the window target option on event APIs. - [`6d3f3138`](https://www.github.com/tauri-apps/tauri/commit/6d3f3138b9e2f41cda712c7d9caba0f0e65dfd3c)([#7160](https://www.github.com/tauri-apps/tauri/pull/7160)) Changed `sep` and `delimiter` from `path` module into functions to fix import in frameworks like `next.js` - [`4652c446`](https://www.github.com/tauri-apps/tauri/commit/4652c446b361a801252bcf45e9da39813bf85482)([#7144](https://www.github.com/tauri-apps/tauri/pull/7144)) Add `tempDir` function to `path` module ## \[2.0.0-alpha.4] - [`0ab5f40d`](https://www.github.com/tauri-apps/tauri/commit/0ab5f40d3a4207f20e4440587b41c4e78f91d233)([#6813](https://www.github.com/tauri-apps/tauri/pull/6813)) Add channel API for sending data across the IPC. - [`3245d14b`](https://www.github.com/tauri-apps/tauri/commit/3245d14b9eb256a5c5675c7030bac7082855df47)([#6895](https://www.github.com/tauri-apps/tauri/pull/6895)) Moved the `app` feature to its own plugin in the plugins-workspace repository. - [`09376af5`](https://www.github.com/tauri-apps/tauri/commit/09376af59424cc27803fa2820d2ac0d4cdc90a6d)([#6704](https://www.github.com/tauri-apps/tauri/pull/6704)) Moved the `cli` feature to its own plugin in the plugins-workspace repository. - [`2d5378bf`](https://www.github.com/tauri-apps/tauri/commit/2d5378bfc1ba817ee2f331b41738a90e5997e5e8)([#6717](https://www.github.com/tauri-apps/tauri/pull/6717)) Moved the dialog APIs to its own plugin in the plugins-workspace repository. - [`39f1b04f`](https://www.github.com/tauri-apps/tauri/commit/39f1b04f7be4966488484829cd54c8ce72a04200)([#6943](https://www.github.com/tauri-apps/tauri/pull/6943)) Moved the `event` JS APIs to a plugin. - [`fc4d687e`](https://www.github.com/tauri-apps/tauri/commit/fc4d687ef0ef2ea069ed73c40916da733b5dcb8f)([#6716](https://www.github.com/tauri-apps/tauri/pull/6716)) Moved the file system APIs to its own plugin in the plugins-workspace repository. - [`f78a3783`](https://www.github.com/tauri-apps/tauri/commit/f78a378344bbec48533641661d865920a8f46f8f)([#6742](https://www.github.com/tauri-apps/tauri/pull/6742)) Moved the `http` feature to its own plugin in the plugins-workspace repository. - [`29ce9ce2`](https://www.github.com/tauri-apps/tauri/commit/29ce9ce2ce7dfb260d556d5cffd075e8fe06660c)([#6902](https://www.github.com/tauri-apps/tauri/pull/6902)) Moved the `os` feature to its own plugin in the plugins-workspace repository. - [`60cf9ed2`](https://www.github.com/tauri-apps/tauri/commit/60cf9ed2fcd7be4df41e86cf18735efe9b6cb254)([#6905](https://www.github.com/tauri-apps/tauri/pull/6905)) Moved the `process` feature to its own plugin in the plugins-workspace repository. - [`96639ca2`](https://www.github.com/tauri-apps/tauri/commit/96639ca239c9e4f75142fc07868ac46822111cff)([#6749](https://www.github.com/tauri-apps/tauri/pull/6749)) Moved the `shell` functionality to its own plugin in the plugins-workspace repository. - [`b072daa3`](https://www.github.com/tauri-apps/tauri/commit/b072daa3bd3e38b808466666619ddb885052c5b2)([#6919](https://www.github.com/tauri-apps/tauri/pull/6919)) Moved the `updater` feature to its own plugin in the plugins-workspace repository. - [`cebd7526`](https://www.github.com/tauri-apps/tauri/commit/cebd75261ac71b98976314a450cb292eeeec1515)([#6728](https://www.github.com/tauri-apps/tauri/pull/6728)) Moved the `clipboard` feature to its own plugin in the plugins-workspace repository. - [`3f17ee82`](https://www.github.com/tauri-apps/tauri/commit/3f17ee82f6ff21108806edb7b00500b8512b8dc7)([#6737](https://www.github.com/tauri-apps/tauri/pull/6737)) Moved the `global-shortcut` feature to its own plugin in the plugins-workspace repository. - [`9a79dc08`](https://www.github.com/tauri-apps/tauri/commit/9a79dc085870e0c1a5df13481ff271b8c6cc3b78)([#6947](https://www.github.com/tauri-apps/tauri/pull/6947)) Moved the `window` JS APIs to its own plugin in the plugins-workspace repository. ## \[2.0.0-alpha.3] - Overload the dialog `open` function to have better TS result types. - [1eacd51d](https://www.github.com/tauri-apps/tauri/commit/1eacd51d185ba69a3c3cb2cc93c792e2d5929843) overloaded the open function for convenient type inference ([#5619](https://www.github.com/tauri-apps/tauri/pull/5619)) on 2023-04-07 ## \[2.0.0-alpha.2] - Added `raw` encoding option to read stdout and stderr raw bytes. - [f992e7f5](https://www.github.com/tauri-apps/tauri/commit/f992e7f58bf975c654a3daf36780b31a32bac064) chore(changes): readd change file on 2023-04-03 - Removed shell's `Command` constructor and added the `Command.create` static function instead. - [509d4678](https://www.github.com/tauri-apps/tauri/commit/509d4678b12816c1dd08a9a5efa71ba556d91c27) Support sending raw byte data to the "data" event for child command's stdout and stderr ([#5789](https://www.github.com/tauri-apps/tauri/pull/5789)) on 2023-03-31 ## \[2.0.0-alpha.1] - Added the `shadow` option when creating a window and `setShadow` function. - [a81750d7](https://www.github.com/tauri-apps/tauri/commit/a81750d779bc72f0fdb7de90b7fbddfd8049b328) feat(core): add shadow APIs ([#6206](https://www.github.com/tauri-apps/tauri/pull/6206)) on 2023-02-08 ## \[2.0.0-alpha.0] - First mobile alpha release! - [fa3a1098](https://www.github.com/tauri-apps/tauri/commit/fa3a10988a03aed1b66fb17d893b1a9adb90f7cd) feat(ci): prepare 2.0.0-alpha.0 ([#5786](https://www.github.com/tauri-apps/tauri/pull/5786)) on 2022-12-08 ## \[1.5.3] ### Bug Fixes - [`1c582a94`](https://www.github.com/tauri-apps/tauri/commit/1c582a942e345a066b65620e4db9f688ec142bb9)([#8392](https://www.github.com/tauri-apps/tauri/pull/8392)) Fix a regression where typescript could not find types when using `"moduleResolution": "node"` ## \[1.5.2] ### Bug Fixes - [`50462702`](https://www.github.com/tauri-apps/tauri/commit/504627027303ef5a0e855aab2abea64c6964223b)([#8267](https://www.github.com/tauri-apps/tauri/pull/8267)) Add top-level `main`, `module` and `types` fields in `package.json` to be compliant with typescripts's `"moduleResolution": "node"` - [`14544e4b`](https://www.github.com/tauri-apps/tauri/commit/14544e4b87269c06c89fed3647d80f492e0a1d34)([#8219](https://www.github.com/tauri-apps/tauri/pull/8219)) Avoid crashing in `clearMocks` ## \[1.5.1] ### New Features - [`2b0212af`](https://www.github.com/tauri-apps/tauri/commit/2b0212af49c386e52bb2357381813d6d435ec4af)([#7961](https://www.github.com/tauri-apps/tauri/pull/7961)) Add `mockConvertFileSrc` in `mocks` module, to mock `convertFileSrc` function. ## \[1.5.0] ### New Features - [`6c408b73`](https://www.github.com/tauri-apps/tauri/commit/6c408b736c7aa2a0a91f0a40d45a2b7a7dedfe78)([#7269](https://www.github.com/tauri-apps/tauri/pull/7269)) Add option to specify notification sound. ### Enhancements - [`58d6b899`](https://www.github.com/tauri-apps/tauri/commit/58d6b899e21d37bb42810890d289deb57f2273bd)([#7636](https://www.github.com/tauri-apps/tauri/pull/7636)) Add `append` option to `FsOptions` in the `fs` JS module, used in `writeTextFile` and `writeBinaryFile`, to be able to append to existing files instead of overwriting it. ### Bug Fixes - [`2eab1505`](https://www.github.com/tauri-apps/tauri/commit/2eab1505632ff71431d4c31c49b5afc78fa5b9dd)([#7394](https://www.github.com/tauri-apps/tauri/pull/7394)) Fix `Body.form` static not reading and sending entries of type `Blob` (including subclasses such as `File`) ## \[1.4.0] ### New Features - [`359058ce`](https://www.github.com/tauri-apps/tauri/commit/359058cecca44a9c30b65140c44a8bb3a6dd3be8)([#5939](https://www.github.com/tauri-apps/tauri/pull/5939)) Add `locale` function in the `os` module to get the system locale. - [`c4d6fb4b`](https://www.github.com/tauri-apps/tauri/commit/c4d6fb4b1ea8acf02707a9fe5dcab47c1c5bae7b)([#2353](https://www.github.com/tauri-apps/tauri/pull/2353)) Added the `maximizable`, `minimizable` and `closable` fields on `WindowOptions`. - [`c4d6fb4b`](https://www.github.com/tauri-apps/tauri/commit/c4d6fb4b1ea8acf02707a9fe5dcab47c1c5bae7b)([#2353](https://www.github.com/tauri-apps/tauri/pull/2353)) Added the `setMaximizable`, `setMinimizable`, `setClosable`, `isMaximizable`, `isMinimizable` and `isClosable` methods. - [`000104bc`](https://www.github.com/tauri-apps/tauri/commit/000104bc3bc0c9ff3d20558ab9cf2080f126e9e0)([#6472](https://www.github.com/tauri-apps/tauri/pull/6472)) Add `WebviewWindow.is_focused` and `WebviewWindow.getFocusedWindow` getters. ## \[1.3.0] - Return correct type for `event.payload` in `onResized` and `onMoved` window event handlers. - [0b46637e](https://www.github.com/tauri-apps/tauri/commit/0b46637ebaba54403afa32a1cb466f09df2db999) fix(api): construct correct object for onResized and onMoved, closes [#6507](https://www.github.com/tauri-apps/tauri/pull/6507) ([#6509](https://www.github.com/tauri-apps/tauri/pull/6509)) on 2023-04-03 - Added the `WindowOptions::contentProtected` option and `WebviewWindow#setContentProtected` to change it at runtime. - [4ab5545b](https://www.github.com/tauri-apps/tauri/commit/4ab5545b7a831c549f3c65e74de487ede3ab7ce5) feat: add content protection api, closes [#5132](https://www.github.com/tauri-apps/tauri/pull/5132) ([#5513](https://www.github.com/tauri-apps/tauri/pull/5513)) on 2022-12-13 - Allow setting the text of the dialog buttons. - [00e1efaa](https://www.github.com/tauri-apps/tauri/commit/00e1efaa9b33876d41dd360624b69971e70d3856) feat: customize button texts of message dialog ([#4383](https://www.github.com/tauri-apps/tauri/pull/4383)) on 2022-12-28 - Add `is_minimized()` window method. - [62144ef3](https://www.github.com/tauri-apps/tauri/commit/62144ef3be63b237869e511826edfb938e2c7174) feat: add is_minimized (fix [#3878](https://www.github.com/tauri-apps/tauri/pull/3878)) ([#5618](https://www.github.com/tauri-apps/tauri/pull/5618)) on 2022-12-13 - Add `title` getter on window. - [233e43b0](https://www.github.com/tauri-apps/tauri/commit/233e43b0c34fada1ca025378533a0b76931a6540) feat: add `title` getter on window, closes [#5023](https://www.github.com/tauri-apps/tauri/pull/5023) ([#5515](https://www.github.com/tauri-apps/tauri/pull/5515)) on 2022-12-13 ## \[1.2.0] - Added the `acceptFirstMouse` window option. - [95f467ad](https://www.github.com/tauri-apps/tauri/commit/95f467add51448319983c54e2f382c7c09fb72d6) feat(core): add window `accept_first_mouse` option, closes [#5347](https://www.github.com/tauri-apps/tauri/pull/5347) ([#5374](https://www.github.com/tauri-apps/tauri/pull/5374)) on 2022-10-17 - Fix incorrect return type on `fs/exists` - [ca3cd8b3](https://www.github.com/tauri-apps/tauri/commit/ca3cd8b3d11beb9b6102da40b7d27f6dbe6cd2d0) fix(api): fs/exists return type previously set to void when it should be boolean ([#5252](https://www.github.com/tauri-apps/tauri/pull/5252)) on 2022-09-29 - Initialize `Monitor` instances with the correct classes for `position` and `size` fields instead of plain object. - [6f41a271](https://www.github.com/tauri-apps/tauri/commit/6f41a2712445ac41a5ed84bbcd40af3b76c8b1d8) fix(api.js): fix `Monitor` initialization, closes [#4672](https://www.github.com/tauri-apps/tauri/pull/4672) ([#5314](https://www.github.com/tauri-apps/tauri/pull/5314)) on 2022-09-30 - **Breaking change:** Node.js v12 is no longer supported. - [1129f4f5](https://www.github.com/tauri-apps/tauri/commit/1129f4f575dd02f746abe8e66472c88c8f9fe63d) refactor: simplify api.js bundling ([#4277](https://www.github.com/tauri-apps/tauri/pull/4277)) on 2022-10-04 - Add new app-specific `BaseDirectory` enum variants `AppConfig`, `AppData`, `AppLocalData`, `AppCache` and `AppLog` along with equivalent functions in `path` module and deprecated ambiguous variants `Log` and `App` along with their equivalent functions in `path` module. - [5d89905e](https://www.github.com/tauri-apps/tauri/commit/5d89905e39ce0e6eaaec50a693679335449edb32) feat(api): add app-specific directory APIs, closes [#5263](https://www.github.com/tauri-apps/tauri/pull/5263) ([#5272](https://www.github.com/tauri-apps/tauri/pull/5272)) on 2022-09-28 - Fix `dialog.save` return type - [8357ce5b](https://www.github.com/tauri-apps/tauri/commit/8357ce5b2efdd6f92c7944822542e48ba0e303ce) Fix dialog.save return type ([#5373](https://www.github.com/tauri-apps/tauri/pull/5373)) on 2022-10-08 - Added support to `FormData` on the `Body.form` function. - [aa119f28](https://www.github.com/tauri-apps/tauri/commit/aa119f28364f8ffbc64c6bcdfc77483613076a20) feat(api): add FormData support on Body.form, closes [#5545](https://www.github.com/tauri-apps/tauri/pull/5545) ([#5546](https://www.github.com/tauri-apps/tauri/pull/5546)) on 2022-11-04 - Added `show` and `hide` methods on the `app` module. - [39bf895b](https://www.github.com/tauri-apps/tauri/commit/39bf895b73ec6b53f5758815396ba85dda6b9c67) feat(macOS): Add application `show` and `hide` methods ([#3689](https://www.github.com/tauri-apps/tauri/pull/3689)) on 2022-10-03 - Added `tabbingIdentifier` window option for macOS. - [4137ab44](https://www.github.com/tauri-apps/tauri/commit/4137ab44a81d739556cbc7583485887e78952bf1) feat(macos): add `tabbing_identifier` option, closes [#2804](https://www.github.com/tauri-apps/tauri/pull/2804), [#3912](https://www.github.com/tauri-apps/tauri/pull/3912) ([#5399](https://www.github.com/tauri-apps/tauri/pull/5399)) on 2022-10-19 - Added `tabbing_identifier` to the window builder on macOS. - [4137ab44](https://www.github.com/tauri-apps/tauri/commit/4137ab44a81d739556cbc7583485887e78952bf1) feat(macos): add `tabbing_identifier` option, closes [#2804](https://www.github.com/tauri-apps/tauri/pull/2804), [#3912](https://www.github.com/tauri-apps/tauri/pull/3912) ([#5399](https://www.github.com/tauri-apps/tauri/pull/5399)) on 2022-10-19 - Added the `user_agent` option when creating a window. - [a6c94119](https://www.github.com/tauri-apps/tauri/commit/a6c94119d8545d509723b147c273ca5edfe3729f) feat(core): expose user_agent to window config ([#5317](https://www.github.com/tauri-apps/tauri/pull/5317)) on 2022-10-02 ## \[1.1.0] - Update `mockIPC()` handler signature to allow async handler functions. - [4fa968dc](https://www.github.com/tauri-apps/tauri/commit/4fa968dc0e74b5206bfcd54e704d180c16b67b08) fix(api): add async `mockIPC()` handler signature ([#5056](https://www.github.com/tauri-apps/tauri/pull/5056)) on 2022-08-26 - Improve shell's `Command`, `Command.stdout` and `Command.stderr` events with new `once`, `off`, `listenerCount`, `prependListener`, `prependOnceListener` and `removeAllListeners` functions. - [aa9f1243](https://www.github.com/tauri-apps/tauri/commit/aa9f1243e6c1629972a82e469f20c8399741740e) Improved EventEmitter for tauri api shell ([#4697](https://www.github.com/tauri-apps/tauri/pull/4697)) on 2022-07-26 - Added the `encoding` option to the `Command` options. - [d8cf9f9f](https://www.github.com/tauri-apps/tauri/commit/d8cf9f9fcd617ac24fa418952fd4a32c08804f5c) Command support for specified character encoding, closes [#4644](https://www.github.com/tauri-apps/tauri/pull/4644) ([#4772](https://www.github.com/tauri-apps/tauri/pull/4772)) on 2022-07-28 - Add `exists` function to the fs module. - [3c62dbc9](https://www.github.com/tauri-apps/tauri/commit/3c62dbc902c904d35a7472ce72a969084c95fbbe) feat(api): Add `exists` function to the fs module. ([#5060](https://www.github.com/tauri-apps/tauri/pull/5060)) on 2022-09-15 ## \[1.0.2] - Added helper functions to listen to updater and window events. - [b02fc90f](https://www.github.com/tauri-apps/tauri/commit/b02fc90f450ff9e9d8a35ee55dc1beced4957869) feat(api): add abstractions to updater and window event listeners ([#4569](https://www.github.com/tauri-apps/tauri/pull/4569)) on 2022-07-05 - Add support to `ArrayBuffer` in `Body.bytes` and `writeBinaryFile`. - [92aca55a](https://www.github.com/tauri-apps/tauri/commit/92aca55a6f1f899d5c0c3a6aae9ac9cb0a7e9a86) feat(api): add support to ArrayBuffer ([#4579](https://www.github.com/tauri-apps/tauri/pull/4579)) on 2022-07-05 - Use `toString()` on message/confirm/ask dialogs title and message values. - [b8cd2a79](https://www.github.com/tauri-apps/tauri/commit/b8cd2a7993cd2aa5b71b30c545b3307245d254bf) feat(api): call `toString()` on dialog title and message, closes [#4583](https://www.github.com/tauri-apps/tauri/pull/4583) ([#4588](https://www.github.com/tauri-apps/tauri/pull/4588)) on 2022-07-04 - Remove the `type-fest` dependency, changing the OS types to the specific enum instead of allowing any string. - [d5e910eb](https://www.github.com/tauri-apps/tauri/commit/d5e910ebcc6c8d7f055ab0691286722b140ffcd4) chore(api): remove `type-fest` ([#4605](https://www.github.com/tauri-apps/tauri/pull/4605)) on 2022-07-06 ## \[1.0.1] - Fixes the `writeBinaryFile` sending an empty file contents when only the first argument is passed. - [ea43cf52](https://www.github.com/tauri-apps/tauri/commit/ea43cf52db8541d20a6397ef3ecd40f0f2bd6113) fix(api): `writeBinaryFile` sends an empty contents with only one arg ([#4368](https://www.github.com/tauri-apps/tauri/pull/4368)) on 2022-06-16 ## \[1.0.0] - Allow choosing multiple folders in `dialog.open`. - [4e51dce6](https://www.github.com/tauri-apps/tauri/commit/4e51dce6ca21c7664de779bc78a04be1051371f7) fix: dialog open supports multiple dirs, fixes [#4091](https://www.github.com/tauri-apps/tauri/pull/4091) ([#4354](https://www.github.com/tauri-apps/tauri/pull/4354)) on 2022-06-15 - Upgrade to `stable`! - [f4bb30cc](https://www.github.com/tauri-apps/tauri/commit/f4bb30cc73d6ba9b9ef19ef004dc5e8e6bb901d3) feat(covector): prepare for v1 ([#4351](https://www.github.com/tauri-apps/tauri/pull/4351)) on 2022-06-15 ## \[1.0.0-rc.7] - Fix `FilePart` usage in `http.Body.form` by renaming the `value` property to `file`. - [55f89d5f](https://www.github.com/tauri-apps/tauri/commit/55f89d5f9d429252ad3fd557b1d6233b256495e0) fix(api): Rename FormPart `value` to `file` to match docs and endpoint ([#4307](https://www.github.com/tauri-apps/tauri/pull/4307)) on 2022-06-09 - Fixes a memory leak in the command system. - [f72cace3](https://www.github.com/tauri-apps/tauri/commit/f72cace36821dc675a6d25268ae85a21bdbd6296) fix: never remove ipc callback & mem never be released ([#4274](https://www.github.com/tauri-apps/tauri/pull/4274)) on 2022-06-05 - The notification's `isPermissionGranted` function now returns `boolean` instead of `boolean | null`. The response is never `null` because we won't check the permission for now, always returning `true` instead. - [f482b094](https://www.github.com/tauri-apps/tauri/commit/f482b0942276e9402ab3725957535039bacb4fef) fix: remove notification permission prompt ([#4302](https://www.github.com/tauri-apps/tauri/pull/4302)) on 2022-06-09 - Added the `resolveResource` API to the path module. - [7bba8db8](https://www.github.com/tauri-apps/tauri/commit/7bba8db83ead92e9bd9c4be7863742e71ac47513) feat(api): add `resolveResource` API to the path module ([#4234](https://www.github.com/tauri-apps/tauri/pull/4234)) on 2022-05-29 - Renamed `writeFile` to `writeTextFile` but kept the original function for backwards compatibility. - [3f998ca2](https://www.github.com/tauri-apps/tauri/commit/3f998ca29445a349489078a74dd068e157a4d68e) feat(api): add `writeTextFile` and `(path, contents, options)` overload ([#4228](https://www.github.com/tauri-apps/tauri/pull/4228)) on 2022-05-29 - Added `(path, contents[, options])` overload to the `writeTextFile` and `writeBinaryFile` APIs. - [3f998ca2](https://www.github.com/tauri-apps/tauri/commit/3f998ca29445a349489078a74dd068e157a4d68e) feat(api): add `writeTextFile` and `(path, contents, options)` overload ([#4228](https://www.github.com/tauri-apps/tauri/pull/4228)) on 2022-05-29 ## \[1.0.0-rc.6] - Expose option to set the dialog type. - [f46175d5](https://www.github.com/tauri-apps/tauri/commit/f46175d5d46fa3eae66ad2415a0eb1efb7d31da2) feat(core): expose option to set dialog type, closes [#4183](https://www.github.com/tauri-apps/tauri/pull/4183) ([#4187](https://www.github.com/tauri-apps/tauri/pull/4187)) on 2022-05-21 - Expose `title` option in the message dialog API. - [ae99f991](https://www.github.com/tauri-apps/tauri/commit/ae99f991674d77c322a2240d10ed4b78ed2f4d4b) feat(core): expose message dialog's title option, ref [#4183](https://www.github.com/tauri-apps/tauri/pull/4183) ([#4186](https://www.github.com/tauri-apps/tauri/pull/4186)) on 2022-05-21 ## \[1.0.0-rc.5] - Fixes the type of `http > connectTimeout`. - [f3c5ca89](https://www.github.com/tauri-apps/tauri/commit/f3c5ca89e79d429183c4e15a9e7cebada2b493a0) fix(core): http api `connect_timeout` deserialization, closes [#4004](https://www.github.com/tauri-apps/tauri/pull/4004) ([#4006](https://www.github.com/tauri-apps/tauri/pull/4006)) on 2022-04-29 ## \[1.0.0-rc.4] - Encode the file path in the `convertFileSrc` function. - [42e8d9cf](https://www.github.com/tauri-apps/tauri/commit/42e8d9cf925089e9ad591198ee04b0cc0a0eed48) fix(api): encode file path in `convertFileSrc` function, closes [#3841](https://www.github.com/tauri-apps/tauri/pull/3841) ([#3846](https://www.github.com/tauri-apps/tauri/pull/3846)) on 2022-04-02 - Added `theme` getter to `WebviewWindow`. - [4cebcf6d](https://www.github.com/tauri-apps/tauri/commit/4cebcf6da7cad1953e0f01b426afac3b5ef1f81e) feat: expose theme APIs, closes [#3903](https://www.github.com/tauri-apps/tauri/pull/3903) ([#3937](https://www.github.com/tauri-apps/tauri/pull/3937)) on 2022-04-21 - Added `theme` field to `WindowOptions`. - [4cebcf6d](https://www.github.com/tauri-apps/tauri/commit/4cebcf6da7cad1953e0f01b426afac3b5ef1f81e) feat: expose theme APIs, closes [#3903](https://www.github.com/tauri-apps/tauri/pull/3903) ([#3937](https://www.github.com/tauri-apps/tauri/pull/3937)) on 2022-04-21 - Added the `setCursorGrab`, `setCursorVisible`, `setCursorIcon` and `setCursorPosition` methods to the `WebviewWindow` class. - [c54ddfe9](https://www.github.com/tauri-apps/tauri/commit/c54ddfe9338e7eb90b4d5b02dfde687d432d5bc1) feat: expose window cursor APIs, closes [#3888](https://www.github.com/tauri-apps/tauri/pull/3888) [#3890](https://www.github.com/tauri-apps/tauri/pull/3890) ([#3935](https://www.github.com/tauri-apps/tauri/pull/3935)) on 2022-04-21 - **Breaking change:** The process Command API stdio lines now includes the trailing `\r`. - [b5622882](https://www.github.com/tauri-apps/tauri/commit/b5622882cf3748e1e5a90915f415c0cd922aaaf8) fix(cli): exit on non-compilation Cargo errors, closes [#3930](https://www.github.com/tauri-apps/tauri/pull/3930) ([#3942](https://www.github.com/tauri-apps/tauri/pull/3942)) on 2022-04-22 - Added the `tauri://theme-changed` event. - [4cebcf6d](https://www.github.com/tauri-apps/tauri/commit/4cebcf6da7cad1953e0f01b426afac3b5ef1f81e) feat: expose theme APIs, closes [#3903](https://www.github.com/tauri-apps/tauri/pull/3903) ([#3937](https://www.github.com/tauri-apps/tauri/pull/3937)) on 2022-04-21 ## \[1.0.0-rc.3] - Properly define the `appWindow` type. - [1deeb03e](https://www.github.com/tauri-apps/tauri/commit/1deeb03ef6c7cbea8cf585864424a3d66f184a02) fix(api.js): appWindow shown as type `any`, fixes [#3747](https://www.github.com/tauri-apps/tauri/pull/3747) ([#3772](https://www.github.com/tauri-apps/tauri/pull/3772)) on 2022-03-24 - Added `Temp` to the `BaseDirectory` enum. - [266156a0](https://www.github.com/tauri-apps/tauri/commit/266156a0b08150b21140dd552c8bc252fe413cdd) feat(core): add `BaseDirectory::Temp` and `$TEMP` variable ([#3763](https://www.github.com/tauri-apps/tauri/pull/3763)) on 2022-03-24 ## \[1.0.0-rc.2] - Do not crash if `__TAURI_METADATA__` is not set, log an error instead. - [9cb1059a](https://www.github.com/tauri-apps/tauri/commit/9cb1059aa3f81521ccc6da655243acfe0327cd98) fix(api): do not throw an exception if **TAURI_METADATA** is not set, fixes [#3554](https://www.github.com/tauri-apps/tauri/pull/3554) ([#3572](https://www.github.com/tauri-apps/tauri/pull/3572)) on 2022-03-03 - Reimplement endpoint to read file as string for performance. - [834ccc51](https://www.github.com/tauri-apps/tauri/commit/834ccc51539401d36a7dfa1c0982623c9c446a4c) feat(core): reimplement `readTextFile` for performance ([#3631](https://www.github.com/tauri-apps/tauri/pull/3631)) on 2022-03-07 - Fixes a regression on the `unlisten` command. - [76c791bd](https://www.github.com/tauri-apps/tauri/commit/76c791bd2b836d2055410e37e71716172a3f81ef) fix(core): regression on the unlisten function ([#3623](https://www.github.com/tauri-apps/tauri/pull/3623)) on 2022-03-06 ## \[1.0.0-rc.1] - Provide functions to mock IPC calls during testing and static site generation. - [7e04c072](https://www.github.com/tauri-apps/tauri/commit/7e04c072c4ee2278c648f44575c6c4710ac047f3) feat: add mock functions for testing and SSG ([#3437](https://www.github.com/tauri-apps/tauri/pull/3437)) on 2022-02-14 - [6f5ed2e6](https://www.github.com/tauri-apps/tauri/commit/6f5ed2e69cb7ffa0d5c8eb5a744fbf94ed6010d4) fix: change file on 2022-02-14 ## \[1.0.0-rc.0] - Add `fileDropEnabled` property to `WindowOptions` so you can now disable it when creating windows from js. - [1bfc32a3](https://www.github.com/tauri-apps/tauri/commit/1bfc32a3b2f31b962ce8a5c611b60cb008360923) fix(api.js): add `fileDropEnabled` to `WindowOptions`, closes [#2968](https://www.github.com/tauri-apps/tauri/pull/2968) ([#2989](https://www.github.com/tauri-apps/tauri/pull/2989)) on 2021-12-09 - Add `logDir` function to the `path` module to access the suggested log directory. Add `BaseDirectory.Log` to the `fs` module. - [acbb3ae7](https://www.github.com/tauri-apps/tauri/commit/acbb3ae7bb0165846b9456aea103269f027fc548) feat: add Log directory ([#2736](https://www.github.com/tauri-apps/tauri/pull/2736)) on 2021-10-16 - [62c7a8ad](https://www.github.com/tauri-apps/tauri/commit/62c7a8ad30fd3031b8679960590e5ef3eef8e4da) chore(covector): prepare for `rc` release ([#3376](https://www.github.com/tauri-apps/tauri/pull/3376)) on 2022-02-10 - Expose `ask`, `message` and `confirm` APIs on the dialog module. - [e98c1af4](https://www.github.com/tauri-apps/tauri/commit/e98c1af44279a5ff6c8a6f0a506ecc219c9f77af) feat(core): expose message dialog APIs, fix window.confirm, implement HasRawWindowHandle for Window, closes [#2535](https://www.github.com/tauri-apps/tauri/pull/2535) ([#2700](https://www.github.com/tauri-apps/tauri/pull/2700)) on 2021-10-02 - Event `emit` now automatically serialize non-string types. - [06000996](https://www.github.com/tauri-apps/tauri/commit/060009969627890fa9018e2f1105bad13299394c) feat(api): support unknown types for event emit payload, closes [#2929](https://www.github.com/tauri-apps/tauri/pull/2929) ([#2964](https://www.github.com/tauri-apps/tauri/pull/2964)) on 2022-01-07 - Fix `http.fetch` throwing error if the response is successful but the body is empty. - [50c63900](https://www.github.com/tauri-apps/tauri/commit/50c63900c7313064037e2ceb798a6432fcd1bcda) fix(api.js): fix `http.fetch` throwing error if response body is empty, closes [#2831](https://www.github.com/tauri-apps/tauri/pull/2831) ([#3008](https://www.github.com/tauri-apps/tauri/pull/3008)) on 2021-12-09 - Add `title` option to file open/save dialogs. - [e1d6a6e6](https://www.github.com/tauri-apps/tauri/commit/e1d6a6e6445637723e2331ca799a662e720e15a8) Create api-file-dialog-title.md ([#3235](https://www.github.com/tauri-apps/tauri/pull/3235)) on 2022-01-16 - [62c7a8ad](https://www.github.com/tauri-apps/tauri/commit/62c7a8ad30fd3031b8679960590e5ef3eef8e4da) chore(covector): prepare for `rc` release ([#3376](https://www.github.com/tauri-apps/tauri/pull/3376)) on 2022-02-10 - Fix `os.platform` returning `macos` and `windows` instead of `darwin` and `win32`. - [3924c3d8](https://www.github.com/tauri-apps/tauri/commit/3924c3d85365df30b376a1ec6c2d933460d66af0) fix(api.js): fix `os.platform` return on macos and windows, closes [#2698](https://www.github.com/tauri-apps/tauri/pull/2698) ([#2699](https://www.github.com/tauri-apps/tauri/pull/2699)) on 2021-10-02 - The `formatCallback` helper function now returns a number instead of a string. - [a48b8b18](https://www.github.com/tauri-apps/tauri/commit/a48b8b18d428bcc404d489daa690bbefe1f57311) feat(core): validate callbacks and event names \[TRI-038] \[TRI-020] ([#21](https://www.github.com/tauri-apps/tauri/pull/21)) on 2022-01-09 - Added `rawHeaders` to `http > Response`. - [b7a2345b](https://www.github.com/tauri-apps/tauri/commit/b7a2345b06ca0306988b4ba3d3deadd449e65af9) feat(core): add raw headers to HTTP API, closes [#2695](https://www.github.com/tauri-apps/tauri/pull/2695) ([#3053](https://www.github.com/tauri-apps/tauri/pull/3053)) on 2022-01-07 - Removed the `currentDir` API from the `path` module. - [a08509c6](https://www.github.com/tauri-apps/tauri/commit/a08509c641f43695e25944a2dd47697b18cd83e2) fix(api): remove `currentDir` API from the `path` module on 2022-02-04 - Remove `.ts` files on the published package. - [0f321ac0](https://www.github.com/tauri-apps/tauri/commit/0f321ac08d56412edd5bc9d166201fbc95d887d8) fix(api): do not ship TS files, closes [#2598](https://www.github.com/tauri-apps/tauri/pull/2598) ([#2645](https://www.github.com/tauri-apps/tauri/pull/2645)) on 2021-09-23 - **Breaking change:** Replaces all usages of `number[]` with `Uint8Array` to be closer aligned with the wider JS ecosystem. - [9b19a805](https://www.github.com/tauri-apps/tauri/commit/9b19a805aa8efa64b22f2dfef193a144b8e0cee3) fix(api.js) Replace `number[]`with `Uint8Array`. fixes [#3306](https://www.github.com/tauri-apps/tauri/pull/3306) ([#3305](https://www.github.com/tauri-apps/tauri/pull/3305)) on 2022-02-05 - `WindowManager` methods `innerPosition` `outerPosition` now correctly return instance of `PhysicalPosition`. `WindowManager` methods `innerSize` `outerSize` now correctly return instance of `PhysicalSize`. - [cc8b1468](https://www.github.com/tauri-apps/tauri/commit/cc8b1468c821df53ceb771061c919409a9c80978) Fix(api): Window size and position returning wrong class (fix: [#2599](https://www.github.com/tauri-apps/tauri/pull/2599)) ([#2621](https://www.github.com/tauri-apps/tauri/pull/2621)) on 2021-09-22 - Change the `event` field of the `Event` interface to type `EventName` instead of `string`. - [b5d9bcb4](https://www.github.com/tauri-apps/tauri/commit/b5d9bcb402380abc86ae1fa1a77c629af2275f9d) Consistent event name usage ([#3228](https://www.github.com/tauri-apps/tauri/pull/3228)) on 2022-01-15 - [62c7a8ad](https://www.github.com/tauri-apps/tauri/commit/62c7a8ad30fd3031b8679960590e5ef3eef8e4da) chore(covector): prepare for `rc` release ([#3376](https://www.github.com/tauri-apps/tauri/pull/3376)) on 2022-02-10 - Now `resolve()`, `join()` and `normalize()` from the `path` module, won't throw errors if the path doesn't exist, which matches NodeJS behavior. - [fe381a0b](https://www.github.com/tauri-apps/tauri/commit/fe381a0bde86ebf4014007f6e21af4c1a9e58cef) fix: `join` no longer cares if path doesn't exist, closes [#2499](https://www.github.com/tauri-apps/tauri/pull/2499) ([#2548](https://www.github.com/tauri-apps/tauri/pull/2548)) on 2021-09-21 - Fixes the dialog `defaultPath` usage on Linux. - [2212bd5d](https://www.github.com/tauri-apps/tauri/commit/2212bd5d75146f5a2df27cc2157a057642f626da) fix: dialog default path on Linux, closes [#3091](https://www.github.com/tauri-apps/tauri/pull/3091) ([#3123](https://www.github.com/tauri-apps/tauri/pull/3123)) on 2021-12-27 - Fixes `window.label` property returning null instead of the actual label. - [f5109e0c](https://www.github.com/tauri-apps/tauri/commit/f5109e0c962e3d25404995194968bade1be33b16) fix(api): window label null instead of actual value, closes [#3295](https://www.github.com/tauri-apps/tauri/pull/3295) ([#3332](https://www.github.com/tauri-apps/tauri/pull/3332)) on 2022-02-04 - Remove the `BaseDirectory::Current` enum variant for security reasons. - [696dca58](https://www.github.com/tauri-apps/tauri/commit/696dca58a9f8ee127a1cf857eb848e09f5845d18) refactor(core): remove `BaseDirectory::Current` variant on 2022-01-26 - Change `WindowLabel` type to `string`. - [f68603ae](https://www.github.com/tauri-apps/tauri/commit/f68603aee4e16500dff9e385b217f5dd8b1b39e8) chore(docs): simplify event system documentation on 2021-09-27 - When building Universal macOS Binaries through the virtual target `universal-apple-darwin`: - Expect a universal binary to be created by the user - Ensure that binary is bundled and accessed correctly at runtime - [3035e458](https://www.github.com/tauri-apps/tauri/commit/3035e4581c161ec7f0bd6d9b42e9015cf1dd1d77) Remove target triple from sidecar bin paths, closes [#3355](https://www.github.com/tauri-apps/tauri/pull/3355) ([#3356](https://www.github.com/tauri-apps/tauri/pull/3356)) on 2022-02-07 ## \[1.0.0-beta.8] - Revert target back to ES5. - [657c7dac](https://www.github.com/tauri-apps/tauri/commit/657c7dac734661956b87d021ff531ba530dd92a3) fix(api): revert ES2021 target on 2021-08-23 ## \[1.0.0-beta.7] - Fix missing asset protocol path.Now the protocol is `https://asset.localhost/path/to/file` on Windows. Linux and macOS is still `asset://path/to/file`. - [994b5325](https://www.github.com/tauri-apps/tauri/commit/994b5325dd385f564b37fe1530c5d798dc925fff) fix: missing asset protocol path ([#2484](https://www.github.com/tauri-apps/tauri/pull/2484)) on 2021-08-23 ## \[1.0.0-beta.6] - `bundle` now exports `clipboard` module so you can `import { clipboard } from "@tauri-apps/api"`. - [4f88c3fb](https://www.github.com/tauri-apps/tauri/commit/4f88c3fb94286f3daafb906e3513c9210ecfa76b) fix(api.js): `bundle` now exports `clipboard` mod, closes [#2243](https://www.github.com/tauri-apps/tauri/pull/2243) ([#2244](https://www.github.com/tauri-apps/tauri/pull/2244)) on 2021-07-19 - Fix double window creation - [9fbcc024](https://www.github.com/tauri-apps/tauri/commit/9fbcc024542d87f71afd364acdcf2302cf82912c) fix(api.js): fix double window creation, closes [#2284](https://www.github.com/tauri-apps/tauri/pull/2284) ([#2285](https://www.github.com/tauri-apps/tauri/pull/2285)) on 2021-07-23 - Add `os` module which exports `EOL`, `platform()`, `version()`, `type()`, `arch()`, `tempdir()` - [05e679a6](https://www.github.com/tauri-apps/tauri/commit/05e679a6d2aca5642c780052bcf1384c49a462de) feat(api.js): add `os` module ([#2299](https://www.github.com/tauri-apps/tauri/pull/2299)) on 2021-07-28 - - Add new nodejs-inspired functions which are `join`, `resolve`, `normalize`, `dirname`, `basename` and `extname`. - Add `sep` and `delimiter` constants. - Removed `resolvePath` API, use `resolve` instead. - [05b9d81e](https://www.github.com/tauri-apps/tauri/commit/05b9d81ee6bcc920defca76cff00178b301fffe8) feat(api.js): add nodejs-inspired functions in `path` module ([#2310](https://www.github.com/tauri-apps/tauri/pull/2310)) on 2021-08-02 - Change target to ES2021. - [97bc52ee](https://www.github.com/tauri-apps/tauri/commit/97bc52ee03dec0b67cc1cced23305a4c53e9eb62) Tooling: \[API] Changed target in tsconfig to es6 ([#2362](https://www.github.com/tauri-apps/tauri/pull/2362)) on 2021-08-09 - Add `toggleMaximize()` function to the `WebviewWindow` class. - [1a510066](https://www.github.com/tauri-apps/tauri/commit/1a510066732d5f61c88c0ceed1c5f5cc559faf7d) fix(core): `data-tauri-drag-region` didn't respect resizable, closes [#2314](https://www.github.com/tauri-apps/tauri/pull/2314) ([#2316](https://www.github.com/tauri-apps/tauri/pull/2316)) on 2021-08-02 - Fix `@ts-expect` error usage - [dd52e738](https://www.github.com/tauri-apps/tauri/commit/dd52e738f1fd323bd8d185d6e650f412eb031200) fix(api.js): fix `@ts-expect-error` usage, closes [#2249](https://www.github.com/tauri-apps/tauri/pull/2249) ([#2250](https://www.github.com/tauri-apps/tauri/pull/2250)) on 2021-07-20 - Fixes file drop events being swapped (`file-drop-hover` on drop and `file-drop` on hover). - [c2b0fe1c](https://www.github.com/tauri-apps/tauri/commit/c2b0fe1ce58e54dbcfdb63162ad17d7e6d8774d9) fix(core): fix wrong file drop events ([#2300](https://www.github.com/tauri-apps/tauri/pull/2300)) on 2021-07-31 - Fixes the global bundle UMD code. - [268450b1](https://www.github.com/tauri-apps/tauri/commit/268450b1329a4b55f2043890c565a8563f890c3a) fix(api): global bundle broken code, closes [#2289](https://www.github.com/tauri-apps/tauri/pull/2289) ([#2297](https://www.github.com/tauri-apps/tauri/pull/2297)) on 2021-07-26 - - Fixes monitor api not working. - Fixes window.print() not working on macOS. - [0f63f5e7](https://www.github.com/tauri-apps/tauri/commit/0f63f5e757873f1787a1ae07ca531340d0d45ec3) fix(api): Fix monitor functions, closes [#2294](https://www.github.com/tauri-apps/tauri/pull/2294) ([#2301](https://www.github.com/tauri-apps/tauri/pull/2301)) on 2021-07-29 - Improve `EventName` type using `type-fest`'s `LiteralUnion`. - [8e480297](https://www.github.com/tauri-apps/tauri/commit/8e48029790857b38988da4d291aa7458f51bb265) feat(api): improve `EventName` type definition ([#2379](https://www.github.com/tauri-apps/tauri/pull/2379)) on 2021-08-10 - Update protocol url path with wry 0.12.1 on Windows. - [88382fe1](https://www.github.com/tauri-apps/tauri/commit/88382fe147ebcb3f59308cc529e5562a04970876) chore(api): update protocol url path with wry 0.12.1 on Windows ([#2409](https://www.github.com/tauri-apps/tauri/pull/2409)) on 2021-08-13 ## \[1.0.0-beta.5] - Adds `convertFileSrc` helper to the `tauri` module, simplifying the process of using file paths as webview source (`img`, `video`, etc). - [51a5cfe4](https://www.github.com/tauri-apps/tauri/commit/51a5cfe4b5e9890fb6f639c9c929657fd747a595) feat(api): add `convertFileSrc` helper ([#2138](https://www.github.com/tauri-apps/tauri/pull/2138)) on 2021-07-02 - You can now use `emit`, `listen` and `once` using the `appWindow` exported by the window module. - [5d7626f8](https://www.github.com/tauri-apps/tauri/commit/5d7626f89781a6ebccceb9ab3b2e8335aa7a0392) feat(api): WindowManager extends WebviewWindowHandle, add events docs ([#2146](https://www.github.com/tauri-apps/tauri/pull/2146)) on 2021-07-03 - Allow manipulating a spawned window directly using `WebviewWindow`, which now extends `WindowManager`. - [d69b1cf6](https://www.github.com/tauri-apps/tauri/commit/d69b1cf6d7c13297073073d753e30fe1a22a09cb) feat(api): allow managing windows created on JS ([#2154](https://www.github.com/tauri-apps/tauri/pull/2154)) on 2021-07-05 ## \[1.0.0-beta.4] - Add asset custom protocol to access local file system. - [ee60e424](https://www.github.com/tauri-apps/tauri/commit/ee60e424221559d3d725716b0003c5566ef2b5cd) feat: asset custom protocol to access local file system ([#2104](https://www.github.com/tauri-apps/tauri/pull/2104)) on 2021-06-28 ## \[1.0.0-beta.3] - Export `Response` and `ResponseType` as value instead of type. - [394b6e05](https://www.github.com/tauri-apps/tauri/commit/394b6e0572e7a0a92e103e462a7f603f7d569319) fix(api): http `ResponseType` export type error ([#2065](https://www.github.com/tauri-apps/tauri/pull/2065)) on 2021-06-24 ## \[1.0.0-beta.2] - Export `BaseDirectory` in `path` module - [277f5ca5](https://www.github.com/tauri-apps/tauri/commit/277f5ca5a8ae227bbdccee1ad52bdd88b4a5b11b) feat(api): export `BaseDirectory` in `path` module ([#1885](https://www.github.com/tauri-apps/tauri/pull/1885)) on 2021-05-30 - Use `export type` to export TS types, enums and interfaces. - [9a662d26](https://www.github.com/tauri-apps/tauri/commit/9a662d2601b01d712c6bd205f8db1b674f56dfa7) fix: Monitor if --isolatedModules is enabled ([#1825](https://www.github.com/tauri-apps/tauri/pull/1825)) on 2021-05-13 - [612cd8ec](https://www.github.com/tauri-apps/tauri/commit/612cd8ecb8e02954f3696b9e138cbc7d2c228fad) feat(api): finalize `export type` usage ([#1847](https://www.github.com/tauri-apps/tauri/pull/1847)) on 2021-05-17 - Adds `focus?: boolean` to the WindowOptions interface. - [5f351622](https://www.github.com/tauri-apps/tauri/commit/5f351622c7812ad1bb56ddb37364ccaa4124c24b) feat(core): add focus API to the WindowBuilder and WindowOptions, [#1737](https://www.github.com/tauri-apps/tauri/pull/1737) on 2021-05-30 - Adds `isDecorated` getter on the window API. - [f58a2114](https://www.github.com/tauri-apps/tauri/commit/f58a2114fbfd5307c349f05c88f2e08fd8baa8aa) feat(core): add `is_decorated` Window getter on 2021-05-30 - Adds `isResizable` getter on the window API. - [1e8af280](https://www.github.com/tauri-apps/tauri/commit/1e8af280c27f381828d6209722b10e889082fa00) feat(core): add `is_resizable` Window getter on 2021-05-30 - Adds `isVisible` getter on the window API. - [36506c96](https://www.github.com/tauri-apps/tauri/commit/36506c967de82bc7ff453d11e6104ecf66d7a588) feat(core): add `is_visible` API on 2021-05-30 - Adds `requestUserAttention` API to the `window` module. - [7dcca6e9](https://www.github.com/tauri-apps/tauri/commit/7dcca6e9281182b11ad3d4a79871f09b30b9b419) feat(core): add `request_user_attention` API, closes [#2023](https://www.github.com/tauri-apps/tauri/pull/2023) ([#2026](https://www.github.com/tauri-apps/tauri/pull/2026)) on 2021-06-20 - Adds `setFocus` to the window API. - [bb6992f8](https://www.github.com/tauri-apps/tauri/commit/bb6992f888196ca7c87bb2fe74ad2bd8bf393e05) feat(core): add `set_focus` window API, fixes [#1737](https://www.github.com/tauri-apps/tauri/pull/1737) on 2021-05-30 - Adds `setSkipTaskbar` to the window API. - [e06aa277](https://www.github.com/tauri-apps/tauri/commit/e06aa277384450cfef617c0e57b0d5d403bb1e7f) feat(core): add `set_skip_taskbar` API on 2021-05-30 - Adds `skipTaskbar?: boolean` to the WindowOptions interface. - [5525b03a](https://www.github.com/tauri-apps/tauri/commit/5525b03a78a2232c650043fbd9894ce1553cad41) feat(core): add `skip_taskbar` API to the WindowBuilder/WindowOptions on 2021-05-30 - Adds `center?: boolean` to `WindowOptions` and `center()` API to the `appWindow`. - [5cba6eb4](https://www.github.com/tauri-apps/tauri/commit/5cba6eb4d28d53f06855d60d4d0eae6b95233ccf) feat(core): add window `center` API, closes [#1822](https://www.github.com/tauri-apps/tauri/pull/1822) ([#1954](https://www.github.com/tauri-apps/tauri/pull/1954)) on 2021-06-05 - Adds `clipboard` APIs (write and read text). - [285bf64b](https://www.github.com/tauri-apps/tauri/commit/285bf64bf9569efb2df904c69c6df405ff0d62e2) feat(core): add clipboard writeText and readText APIs ([#2035](https://www.github.com/tauri-apps/tauri/pull/2035)) on 2021-06-21 - [dee71ad5](https://www.github.com/tauri-apps/tauri/commit/dee71ad58349f699995cc9077b79032bacc6afcb) fix(workflows): update docs workflow syntax ([#2054](https://www.github.com/tauri-apps/tauri/pull/2054)) on 2021-06-23 - The `http` APIs now resolve the returned promise when the API call finishes with an error status code. - [47f75584](https://www.github.com/tauri-apps/tauri/commit/47f7558417cc654bdb1d018127e8900bc4eac622) fix(core): resolve HTTP API on non-ok status code, fix binary response, closes [#2046](https://www.github.com/tauri-apps/tauri/pull/2046) ([#2053](https://www.github.com/tauri-apps/tauri/pull/2053)) on 2021-06-23 - Improve RPC security by requiring a numeric code to invoke commands. The codes are generated by the Rust side and injected into the app's code using a closure, so external scripts can't access the backend. This change doesn't protect `withGlobalTauri` (`window.__TAURI__`) usage. - [160fb052](https://www.github.com/tauri-apps/tauri/commit/160fb0529fd31d755574ae30fbdf01fa221a2acb) feat(core): improve RPC security, closes [#814](https://www.github.com/tauri-apps/tauri/pull/814) ([#2047](https://www.github.com/tauri-apps/tauri/pull/2047)) on 2021-06-22 - Mark the `WebviewWindow` constructor as public. - [4aeb936e](https://www.github.com/tauri-apps/tauri/commit/4aeb936e9b60b895d383597dc698ee5d638436f9) fix(api): `WebviewWindow` constructor is public ([#1888](https://www.github.com/tauri-apps/tauri/pull/1888)) on 2021-05-21 - Validate arguments on the window `setLocation`, `setSize`, `setMinSize` and `setMaxSize` API. - [7616e6cc](https://www.github.com/tauri-apps/tauri/commit/7616e6cc7bcd49f688b0d00fdc33c94b7b93713d) feat(api): validate window API `size` and `location` arguments ([#1846](https://www.github.com/tauri-apps/tauri/pull/1846)) on 2021-05-17 ## \[1.0.0-beta.1] - Adds `package.json` to the `exports` object. - [ab1ea96](https://www.github.com/tauri-apps/tauri/commit/ab1ea964786e1781c922582b059c555b6072f1a0) chore(api): add `package.json` to the `exports` field ([#1807](https://www.github.com/tauri-apps/tauri/pull/1807)) on 2021-05-12 ## \[1.0.0-beta.0] - CommonJS chunks are now properly exported with `.cjs` extension - [ddcd923](https://www.github.com/tauri-apps/tauri/commit/ddcd9233bd6f499aa7f22484d6c151b01778bc1b) fix(api): export commonjs chunks with `.cjs` extension, fix [#1625](https://www.github.com/tauri-apps/tauri/pull/1625) ([#1627](https://www.github.com/tauri-apps/tauri/pull/1627)) on 2021-04-26 - Adds `transparent?: boolean` to the `WindowOptions` interface. - [08c1c5c](https://www.github.com/tauri-apps/tauri/commit/08c1c5ca5c0ebe17ea98689a5fe3b7e47a98e955) fix(api): missing `transparent` flag on `WindowOptions` ([#1764](https://www.github.com/tauri-apps/tauri/pull/1764)) on 2021-05-10 - Adds `options` argument to the shell command API (`env` and `cwd` configuration). - [721e98f](https://www.github.com/tauri-apps/tauri/commit/721e98f175567b360c86f30565ab1b9d08e7cf85) feat(core): add env, cwd to the command API, closes [#1634](https://www.github.com/tauri-apps/tauri/pull/1634) ([#1635](https://www.github.com/tauri-apps/tauri/pull/1635)) on 2021-04-28 - Adds `startDragging` API on the window module. - [c31f097](https://www.github.com/tauri-apps/tauri/commit/c31f0978c535f794fffb75a121e69a323e70b06e) refactor: update to wry 0.9 ([#1630](https://www.github.com/tauri-apps/tauri/pull/1630)) on 2021-04-28 - Move `exit` and `relaunch` APIs from `app` to `process` module. - [b0bb796](https://www.github.com/tauri-apps/tauri/commit/b0bb796a42e2560233aea47ce6ced54ac238eb53) refactor: rename `command` mod to `process`, move restart_application ([#1667](https://www.github.com/tauri-apps/tauri/pull/1667)) on 2021-04-30 - The window management API was refactored: removed `setX`, `setY`, `setWidth`, `setHeight` APIs, renamed `resize` to `setSize` and the size and position APIs now allow defining both logical and physical values. - [6bfac86](https://www.github.com/tauri-apps/tauri/commit/6bfac866a703f1499a64237fb29b2625703f4e22) refactor(core): add window getters, physical & logical sizes/positions ([#1723](https://www.github.com/tauri-apps/tauri/pull/1723)) on 2021-05-05 - Adds window getters. - [6bfac86](https://www.github.com/tauri-apps/tauri/commit/6bfac866a703f1499a64237fb29b2625703f4e22) refactor(core): add window getters, physical & logical sizes/positions ([#1723](https://www.github.com/tauri-apps/tauri/pull/1723)) on 2021-05-05 ## \[1.0.0-beta-rc.3] - Fixes distribution of the `@tauri-apps/api` package for older bundlers. - [7f998d0](https://www.github.com/tauri-apps/tauri/commit/7f998d08e3ab8823c99190fa283bdfa2c4f2749b) fix(api): distribution ([#1582](https://www.github.com/tauri-apps/tauri/pull/1582)) on 2021-04-22 - Update minimum Node.js version to v12.13.0 - [1f089fb](https://www.github.com/tauri-apps/tauri/commit/1f089fb4f964c673dcab5784bdf1da2833487a7c) chore: update minimum nodejs version to 12.13.0 ([#1562](https://www.github.com/tauri-apps/tauri/pull/1562)) on 2021-04-21 ## \[1.0.0-beta-rc.2] - TS was wrongly re-exporting the module. - [fcb3b48](https://www.github.com/tauri-apps/tauri/commit/fcb3b4857efa17d2a3717f32457e88b24520cc9b) fix: [#1512](https://www.github.com/tauri-apps/tauri/pull/1512) ([#1517](https://www.github.com/tauri-apps/tauri/pull/1517)) on 2021-04-19 - [ae14a3f](https://www.github.com/tauri-apps/tauri/commit/ae14a3ff51a742b6ab6f76bbfc21f385310f1dc6) fix: [#1517](https://www.github.com/tauri-apps/tauri/pull/1517) had the wrong package reference in the changefile ([#1538](https://www.github.com/tauri-apps/tauri/pull/1538)) on 2021-04-19 ## \[1.0.0-beta-rc.1] - Missing the `files` property in the package.json which mean that the `dist` directory was not published and used. - [b2569a7](https://www.github.com/tauri-apps/tauri/commit/b2569a729a3caa88bdba62abc31f0665e1323aaa) fix(js-api): dist ([#1498](https://www.github.com/tauri-apps/tauri/pull/1498)) on 2021-04-15 ## \[1.0.0-beta-rc.0] - Add current working directory to the path api module. - [52c2baf](https://www.github.com/tauri-apps/tauri/commit/52c2baf940773cf7c51647fb6f20d0f7df126115) feat: add current working directory to path api module ([#1375](https://www.github.com/tauri-apps/tauri/pull/1375)) on 2021-03-23 - [a6def70](https://www.github.com/tauri-apps/tauri/commit/a6def7066eec19c889b0f14cc1e475bf209a332e) Refactor(tauri): move tauri-api and tauri-updater to tauri ([#1455](https://www.github.com/tauri-apps/tauri/pull/1455)) on 2021-04-11 - The shell process spawning API was rewritten and now includes stream access. - [3713066](https://www.github.com/tauri-apps/tauri/commit/3713066e451bd30d0cc6f57bb437f08276f4c4ad) refactor(core): rewrite shell execute API, closes [#1229](https://www.github.com/tauri-apps/tauri/pull/1229) ([#1408](https://www.github.com/tauri-apps/tauri/pull/1408)) on 2021-03-31 - The file dialog API now uses [rfd](https://github.com/PolyMeilex/rfd). The filter option is now an array of `{ name: string, extensions: string[] }`. - [2326bcd](https://www.github.com/tauri-apps/tauri/commit/2326bcd399411f7f0eabdb7ade910be473adadae) refactor(core): use `nfd` for file dialogs, closes [#1251](https://www.github.com/tauri-apps/tauri/pull/1251) ([#1257](https://www.github.com/tauri-apps/tauri/pull/1257)) on 2021-02-18 - [a6def70](https://www.github.com/tauri-apps/tauri/commit/a6def7066eec19c889b0f14cc1e475bf209a332e) Refactor(tauri): move tauri-api and tauri-updater to tauri ([#1455](https://www.github.com/tauri-apps/tauri/pull/1455)) on 2021-04-11 - The HTTP API was improved with client caching and better payload and response types. - [a7bc472](https://www.github.com/tauri-apps/tauri/commit/a7bc472e994730071f960d09a12ac85296a080ae) refactor(core): improve HTTP API, closes [#1098](https://www.github.com/tauri-apps/tauri/pull/1098) ([#1237](https://www.github.com/tauri-apps/tauri/pull/1237)) on 2021-02-15 - [a6def70](https://www.github.com/tauri-apps/tauri/commit/a6def7066eec19c889b0f14cc1e475bf209a332e) Refactor(tauri): move tauri-api and tauri-updater to tauri ([#1455](https://www.github.com/tauri-apps/tauri/pull/1455)) on 2021-04-11 - Update all code files to have our license header. - [bf82136](https://www.github.com/tauri-apps/tauri/commit/bf8213646689175f8a158b956911f3a43e360690) feat(license): SPDX Headers ([#1449](https://www.github.com/tauri-apps/tauri/pull/1449)) on 2021-04-11 - [a6def70](https://www.github.com/tauri-apps/tauri/commit/a6def7066eec19c889b0f14cc1e475bf209a332e) Refactor(tauri): move tauri-api and tauri-updater to tauri ([#1455](https://www.github.com/tauri-apps/tauri/pull/1455)) on 2021-04-11 - [aea6145](https://www.github.com/tauri-apps/tauri/commit/aea614587bddab930d552512b54e18624fbf573e) refactor(repo): add /tooling folder ([#1457](https://www.github.com/tauri-apps/tauri/pull/1457)) on 2021-04-12 - Use secure RNG on callback function names. - [c8992bb](https://www.github.com/tauri-apps/tauri/commit/c8992bb0bfb8eaeae8ebed444719f9c9372d39d4) refactor(api): use secure RNG, closes [#1356](https://www.github.com/tauri-apps/tauri/pull/1356) ([#1398](https://www.github.com/tauri-apps/tauri/pull/1398)) on 2021-03-30 - The invoke function can now be called with the cmd as the first parameter and the args as the second. - [427d170](https://www.github.com/tauri-apps/tauri/commit/427d170930ab711fd0ca82f7a73b524d6fdc222f) feat(api/invoke): separate cmd arg ([#1321](https://www.github.com/tauri-apps/tauri/pull/1321)) on 2021-03-04 - Adds a global shortcut API. - [855effa](https://www.github.com/tauri-apps/tauri/commit/855effadd9ebfb6bc1a3555ac7fc733f6f766b7a) feat(core): globalShortcut API ([#1232](https://www.github.com/tauri-apps/tauri/pull/1232)) on 2021-02-14 - [a6def70](https://www.github.com/tauri-apps/tauri/commit/a6def7066eec19c889b0f14cc1e475bf209a332e) Refactor(tauri): move tauri-api and tauri-updater to tauri ([#1455](https://www.github.com/tauri-apps/tauri/pull/1455)) on 2021-04-11 - Added window management and window creation APIs. - [a3d6dff](https://www.github.com/tauri-apps/tauri/commit/a3d6dff2163c7a45842253edd81dbc62248dc65d) feat(core): window API ([#1225](https://www.github.com/tauri-apps/tauri/pull/1225)) on 2021-02-13 - [641374b](https://www.github.com/tauri-apps/tauri/commit/641374b15343518cd835bd5ada811941c65dcf2e) feat(core): window creation at runtime ([#1249](https://www.github.com/tauri-apps/tauri/pull/1249)) on 2021-02-17 ================================================ FILE: packages/api/LICENSE_APACHE-2.0 ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS ================================================ FILE: packages/api/LICENSE_MIT ================================================ MIT License Copyright (c) 2017 - Present Tauri Apps Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: packages/api/README.md ================================================ # @tauri-apps/api [![status](https://img.shields.io/badge/status-stable-blue.svg)](https://github.com/tauri-apps/tauri/tree/dev) [![License](https://img.shields.io/badge/License-MIT%20or%20Apache%202-green.svg)](https://opencollective.com/tauri) [![lint js](https://img.shields.io/github/actions/workflow/status/tauri-apps/tauri/lint-js.yml?label=lint%20js&logo=github)](https://github.com/tauri-apps/tauri/actions/workflows/lint-js.yml) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Ftauri-apps%2Ftauri.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Ftauri-apps%2Ftauri?ref=badge_shield) [![Chat Server](https://img.shields.io/badge/chat-discord-7289da.svg)](https://discord.gg/SpmNs4S) [![website](https://img.shields.io/badge/website-tauri.app-purple.svg)](https://tauri.app) [![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) | Component | Version | | --------------- | ----------------------------------------------------- | | @tauri-apps/api | ![](https://img.shields.io/npm/v/@tauri-apps/api.svg) | ## About Tauri Tauri is a polyglot and generic system that is very composable and allows engineers to make a wide variety of applications. It is used for building applications for Desktop Computers using a combination of Rust tools and HTML rendered in a Webview. Apps built with Tauri can ship with any number of pieces of an optional JS API / Rust API so that webviews can control the system via message passing. In fact, developers can extend the default API with their own functionality and bridge the Webview and Rust-based backend easily. Tauri apps can have custom menus and have tray-type interfaces. They can be updated, and are managed by the user's operating system as expected. They are very small, because they use the system's webview. They do not ship a runtime, since the final binary is compiled from rust. This makes the reversing of Tauri apps not a trivial task. ## This module This is a typescript library that creates `cjs` and `esm` JavaScript endpoints for you to import into your Frontend framework so that the Webview can call and listen to backend activity. We also ship the pure typescript, because for some frameworks this is more optimal. It uses the message passing of webviews to their hosts. 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. ## Installation The preferred method is to install this module locally as a dependency: ``` $ pnpm add @tauri-apps/api $ yarn add @tauri-apps/api $ npm add @tauri-apps/api ``` ## Semver **tauri** is following [Semantic Versioning 2.0](https://semver.org/). ## Licenses Code: (c) 2019 - 2021 - The Tauri Programme within The Commons Conservancy. MIT or MIT/Apache 2.0 where applicable. Logo: CC-BY-NC-ND - Original Tauri Logo Designs by [Daniel Thompson-Yvetot](https://github.com/nothingismagick) and [Guillaume Chau](https://github.com/akryum) ================================================ FILE: packages/api/eslint.config.js ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import globals from 'globals' import eslint from '@eslint/js' import prettierConfig from 'eslint-config-prettier' import securityPlugin from 'eslint-plugin-security' import tseslint from 'typescript-eslint' /** @type {import('eslint').Linter.Config} */ export default [ eslint.configs.recommended, prettierConfig, securityPlugin.configs.recommended, ...tseslint.configs.recommendedTypeChecked, { languageOptions: { globals: { ...globals.node, ...globals.jest, __statics: true, process: true }, parserOptions: { project: true, tsconfigRootDir: import.meta.dirname } }, rules: { 'no-console': 'error', 'no-debugger': 'error', 'no-process-exit': 'off', 'security/detect-non-literal-fs-filename': 'warn', 'security/detect-unsafe-regex': 'error', 'security/detect-buffer-noassert': 'error', 'security/detect-child-process': 'warn', 'security/detect-disable-mustache-escape': 'error', 'security/detect-eval-with-expression': 'error', 'security/detect-no-csrf-before-method-override': 'error', 'security/detect-non-literal-regexp': 'error', 'security/detect-non-literal-require': 'warn', 'security/detect-object-injection': 'warn', 'security/detect-possible-timing-attacks': 'error', 'security/detect-pseudoRandomBytes': 'error', 'space-before-function-paren': 'off', '@typescript-eslint/default-param-last': 'off', '@typescript-eslint/strict-boolean-expressions': 0, 'no-return-await': 'warn', '@typescript-eslint/return-await': 'off', '@typescript-eslint/no-unused-vars': [ 'error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_' } ] } } ] ================================================ FILE: packages/api/package.json ================================================ { "name": "@tauri-apps/api", "version": "2.10.1", "description": "Tauri API definitions", "funding": { "type": "opencollective", "url": "https://opencollective.com/tauri" }, "repository": { "type": "git", "url": "git+https://github.com/tauri-apps/tauri.git" }, "contributors": [ "Tauri Programme within The Commons Conservancy" ], "license": "Apache-2.0 OR MIT", "bugs": { "url": "https://github.com/tauri-apps/tauri/issues" }, "homepage": "https://github.com/tauri-apps/tauri#readme", "type": "module", "main": "./index.cjs", "module": "./index.js", "types": "./index.d.ts", "exports": { ".": { "import": "./index.js", "require": "./index.cjs", "types": "./index.d.ts" }, "./*": { "import": "./*.js", "require": "./*.cjs", "types": "./*.d.ts" }, "./package.json": "./package.json" }, "scripts": { "build": "rollup -c --configPlugin typescript", "build:debug": "rollup -c --configPlugin typescript", "npm-pack": "pnpm build && cd ./dist && npm pack", "npm-publish": "pnpm build && cd ./dist && pnpm publish --access public --loglevel silly --no-git-checks", "ts:check": "tsc --noEmit", "eslint:check": "eslint src/**/*.ts", "eslint:fix": "eslint src/**/*.ts --fix" }, "devDependencies": { "@eslint/js": "^10.0.1", "@rollup/plugin-terser": "1.0.0", "@rollup/plugin-typescript": "12.3.0", "@types/eslint": "^9.6.1", "@types/node": "^24.11.0", "eslint": "^10.0.2", "eslint-config-prettier": "10.1.8", "eslint-plugin-security": "4.0.0", "fast-glob": "3.3.3", "globals": "^17.4.0", "rollup": "4.59.0", "tslib": "^2.8.1", "typescript": "^5.9.3", "typescript-eslint": "^8.56.1" } } ================================================ FILE: packages/api/rollup.config.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import { defineConfig, Plugin, RollupLog } from 'rollup' import typescript from '@rollup/plugin-typescript' import terser from '@rollup/plugin-terser' import fg from 'fast-glob' import { basename, dirname, join } from 'path' import { copyFileSync, opendirSync, rmSync, Dir } from 'fs' import { fileURLToPath } from 'url' // cleanup dist dir const __dirname = fileURLToPath(new URL('.', import.meta.url)) cleanDir(join(__dirname, './dist')) const modules = fg.sync(['!./src/*.d.ts', './src/*.ts']) export default defineConfig([ { input: Object.fromEntries(modules.map((p) => [basename(p, '.ts'), p])), output: [ { format: 'esm', dir: './dist', preserveModules: true, preserveModulesRoot: 'src', entryFileNames: (chunkInfo) => { if (chunkInfo.name.includes('node_modules')) { return externalLibPath(chunkInfo.name) + '.js' } return '[name].js' } }, { format: 'cjs', dir: './dist', preserveModules: true, preserveModulesRoot: 'src', entryFileNames: (chunkInfo) => { if (chunkInfo.name.includes('node_modules')) { return externalLibPath(chunkInfo.name) + '.cjs' } return '[name].cjs' } } ], plugins: [ typescript({ declaration: true, declarationDir: './dist', rootDir: 'src' }), makeFlatPackageInDist() ], onwarn }, { input: 'src/index.ts', output: { format: 'iife', name: '__TAURI_IIFE__', footer: 'window.__TAURI__ = __TAURI_IIFE__', file: '../../crates/tauri/scripts/bundle.global.js' }, plugins: [typescript(), terser()], onwarn } ]) function externalLibPath(path: string) { return `external/${basename(dirname(path))}/${basename(path)}` } function onwarn(warning: RollupLog) { // deny warnings by default throw Object.assign(new Error(), warning) } function makeFlatPackageInDist(): Plugin { return { name: 'makeFlatPackageInDist', writeBundle() { // copy necessary files like `CHANGELOG.md` , `README.md` and Licenses to `./dist` fg.sync('(LICENSE*|*.md|package.json)').forEach((f) => copyFileSync(f, `dist/${f}`) ) } } } function cleanDir(path: string) { let dir: Dir try { dir = opendirSync(path) } catch (err: any) { switch (err.code) { case 'ENOENT': return // Noop when directory don't exists. case 'ENOTDIR': throw new Error(`'${path}' is not a directory.`) default: throw err } } let file = dir.readSync() while (file) { const filePath = join(path, file.name) rmSync(filePath, { recursive: true }) file = dir.readSync() } dir.closeSync() } ================================================ FILE: packages/api/src/app.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import { addPluginListener, invoke, PluginListener } from './core' import { Image } from './image' import { Theme } from './window' /** * Identifier type used for data stores on macOS and iOS. * * Represents a 128-bit identifier, commonly expressed as a 16-byte UUID. */ export type DataStoreIdentifier = [ number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number ] /** * Bundle type of the current application. */ export enum BundleType { /** Windows NSIS */ Nsis = 'nsis', /** Windows MSI */ Msi = 'msi', /** Linux Debian package */ Deb = 'deb', /** Linux RPM */ Rpm = 'rpm', /** Linux AppImage */ AppImage = 'appimage', /** macOS app bundle */ App = 'app' } /** * Application metadata and related APIs. * * @module */ /** * Gets the application version. * @example * ```typescript * import { getVersion } from '@tauri-apps/api/app'; * const appVersion = await getVersion(); * ``` * * @since 1.0.0 */ async function getVersion(): Promise { return invoke('plugin:app|version') } /** * Gets the application name. * @example * ```typescript * import { getName } from '@tauri-apps/api/app'; * const appName = await getName(); * ``` * * @since 1.0.0 */ async function getName(): Promise { return invoke('plugin:app|name') } /** * Gets the Tauri framework version used by this application. * * @example * ```typescript * import { getTauriVersion } from '@tauri-apps/api/app'; * const tauriVersion = await getTauriVersion(); * ``` * * @since 1.0.0 */ async function getTauriVersion(): Promise { return invoke('plugin:app|tauri_version') } /** * Gets the application identifier. * @example * ```typescript * import { getIdentifier } from '@tauri-apps/api/app'; * const identifier = await getIdentifier(); * ``` * * @returns The application identifier as configured in `tauri.conf.json`. * * @since 2.4.0 */ async function getIdentifier(): Promise { return invoke('plugin:app|identifier') } /** * Shows the application on macOS. This function does not automatically * focus any specific app window. * * @example * ```typescript * import { show } from '@tauri-apps/api/app'; * await show(); * ``` * * @since 1.2.0 */ async function show(): Promise { return invoke('plugin:app|app_show') } /** * Hides the application on macOS. * * @example * ```typescript * import { hide } from '@tauri-apps/api/app'; * await hide(); * ``` * * @since 1.2.0 */ async function hide(): Promise { return invoke('plugin:app|app_hide') } /** * Fetches the data store identifiers on macOS and iOS. * * See https://developer.apple.com/documentation/webkit/wkwebsitedatastore for more information. * * @example * ```typescript * import { fetchDataStoreIdentifiers } from '@tauri-apps/api/app'; * const ids = await fetchDataStoreIdentifiers(); * ``` * * @since 2.4.0 */ async function fetchDataStoreIdentifiers(): Promise { return invoke('plugin:app|fetch_data_store_identifiers') } /** * Removes the data store with the given identifier. * * Note that any webview using this data store should be closed before running this API. * * See https://developer.apple.com/documentation/webkit/wkwebsitedatastore for more information. * * @example * ```typescript * import { fetchDataStoreIdentifiers, removeDataStore } from '@tauri-apps/api/app'; * for (const id of (await fetchDataStoreIdentifiers())) { * await removeDataStore(id); * } * ``` * * @since 2.4.0 */ async function removeDataStore(uuid: DataStoreIdentifier): Promise { return invoke('plugin:app|remove_data_store', { uuid }) } /** * Gets the default window icon. * * @example * ```typescript * import { defaultWindowIcon } from '@tauri-apps/api/app'; * const icon = await defaultWindowIcon(); * ``` * * @since 2.0.0 */ async function defaultWindowIcon(): Promise { return invoke('plugin:app|default_window_icon').then((rid) => rid ? new Image(rid) : null ) } /** * Sets the application's theme. Pass in `null` or `undefined` to follow * the system theme. * * @example * ```typescript * import { setTheme } from '@tauri-apps/api/app'; * await setTheme('dark'); * ``` * * #### Platform-specific * * - **iOS / Android:** Unsupported. * * @since 2.0.0 */ async function setTheme(theme?: Theme | null): Promise { return invoke('plugin:app|set_app_theme', { theme }) } /** * Sets the dock visibility for the application on macOS. * * @param visible - Whether the dock should be visible or not. * * @example * ```typescript * import { setDockVisibility } from '@tauri-apps/api/app'; * await setDockVisibility(false); * ``` * * @since 2.5.0 */ async function setDockVisibility(visible: boolean): Promise { return invoke('plugin:app|set_dock_visibility', { visible }) } /** * Gets the application bundle type. * * @example * ```typescript * import { getBundleType } from '@tauri-apps/api/app'; * const type = await getBundleType(); * ``` * * @since 2.5.0 */ async function getBundleType(): Promise { return invoke('plugin:app|bundle_type') } /** * Payload for the onBackButtonPress event. */ type OnBackButtonPressPayload = { /** Whether the webview canGoBack property is true. */ canGoBack: boolean } /** * Listens to the backButton event on Android. * @param handler */ async function onBackButtonPress( handler: (payload: OnBackButtonPressPayload) => void ): Promise { return addPluginListener( 'app', 'back-button', handler ) } export { getName, getVersion, getTauriVersion, getIdentifier, show, hide, defaultWindowIcon, setTheme, fetchDataStoreIdentifiers, removeDataStore, setDockVisibility, getBundleType, type OnBackButtonPressPayload, onBackButtonPress } ================================================ FILE: packages/api/src/core.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT /** * Invoke your custom commands. * * This package is also accessible with `window.__TAURI__.core` when [`app.withGlobalTauri`](https://v2.tauri.app/reference/config/#withglobaltauri) in `tauri.conf.json` is set to `true`. * @module */ /** * A key to be used to implement a special function * on your types that define how your type should be serialized * when passing across the IPC. * @example * Given a type in Rust that looks like this * ```rs * #[derive(serde::Serialize, serde::Deserialize) * enum UserId { * String(String), * Number(u32), * } * ``` * `UserId::String("id")` would be serialized into `{ String: "id" }` * and so we need to pass the same structure back to Rust * ```ts * import { SERIALIZE_TO_IPC_FN } from "@tauri-apps/api/core" * * class UserIdString { * id * constructor(id) { * this.id = id * } * * [SERIALIZE_TO_IPC_FN]() { * return { String: this.id } * } * } * * class UserIdNumber { * id * constructor(id) { * this.id = id * } * * [SERIALIZE_TO_IPC_FN]() { * return { Number: this.id } * } * } * * type UserId = UserIdString | UserIdNumber * ``` * */ // if this value changes, make sure to update it in: // 1. ipc.js // 2. process-ipc-message-fn.js export const SERIALIZE_TO_IPC_FN = '__TAURI_TO_IPC_KEY__' /** * Stores the callback in a known location, and returns an identifier that can be passed to the backend. * The backend uses the identifier to `eval()` the callback. * * @return An unique identifier associated with the callback function. * * @since 1.0.0 */ function transformCallback( // TODO: Make this not optional in v3 callback?: (response: T) => void, once = false ): number { return window.__TAURI_INTERNALS__.transformCallback(callback, once) } class Channel { /** The callback id returned from {@linkcode transformCallback} */ id: number #onmessage: (response: T) => void // the index is used as a mechanism to preserve message order #nextMessageIndex = 0 #pendingMessages: T[] = [] #messageEndIndex: number | undefined constructor(onmessage?: (response: T) => void) { this.#onmessage = onmessage || (() => {}) this.id = transformCallback< // Normal message | { message: T; index: number } // Message when the channel gets dropped in the rust side | { end: true; index: number } >((rawMessage) => { const index = rawMessage.index if ('end' in rawMessage) { if (index == this.#nextMessageIndex) { this.cleanupCallback() } else { this.#messageEndIndex = index } return } const message = rawMessage.message // Process the message if we're at the right order if (index == this.#nextMessageIndex) { this.#onmessage(message) this.#nextMessageIndex += 1 // process pending messages while (this.#nextMessageIndex in this.#pendingMessages) { const message = this.#pendingMessages[this.#nextMessageIndex] this.#onmessage(message) // eslint-disable-next-line @typescript-eslint/no-array-delete delete this.#pendingMessages[this.#nextMessageIndex] this.#nextMessageIndex += 1 } if (this.#nextMessageIndex === this.#messageEndIndex) { this.cleanupCallback() } } // Queue the message if we're not else { // eslint-disable-next-line security/detect-object-injection this.#pendingMessages[index] = message } }) } private cleanupCallback() { window.__TAURI_INTERNALS__.unregisterCallback(this.id) } set onmessage(handler: (response: T) => void) { this.#onmessage = handler } get onmessage(): (response: T) => void { return this.#onmessage } [SERIALIZE_TO_IPC_FN]() { return `__CHANNEL__:${this.id}` } toJSON(): string { // eslint-disable-next-line security/detect-object-injection return this[SERIALIZE_TO_IPC_FN]() } } class PluginListener { plugin: string event: string channelId: number constructor(plugin: string, event: string, channelId: number) { this.plugin = plugin this.event = event this.channelId = channelId } async unregister(): Promise { return invoke(`plugin:${this.plugin}|remove_listener`, { event: this.event, channelId: this.channelId }) } } /** * Adds a listener to a plugin event. * * @returns The listener object to stop listening to the events. * * @since 2.0.0 */ async function addPluginListener( plugin: string, event: string, cb: (payload: T) => void ): Promise { const handler = new Channel(cb) try { await invoke(`plugin:${plugin}|register_listener`, { event, handler }) return new PluginListener(plugin, event, handler.id) } catch { // TODO(v3): remove this fallback // note: we must try with camelCase here for backwards compatibility await invoke(`plugin:${plugin}|registerListener`, { event, handler }) return new PluginListener(plugin, event, handler.id) } } type PermissionState = 'granted' | 'denied' | 'prompt' | 'prompt-with-rationale' /** * Get permission state for a plugin. * * This should be used by plugin authors to wrap their actual implementation. */ async function checkPermissions(plugin: string): Promise { return invoke(`plugin:${plugin}|check_permissions`) } /** * Request permissions. * * This should be used by plugin authors to wrap their actual implementation. */ async function requestPermissions(plugin: string): Promise { return invoke(`plugin:${plugin}|request_permissions`) } /** * Command arguments. * * @since 1.0.0 */ type InvokeArgs = Record | number[] | ArrayBuffer | Uint8Array /** * @since 2.0.0 */ interface InvokeOptions { headers: HeadersInit } /** * Sends a message to the backend. * @example * ```typescript * import { invoke } from '@tauri-apps/api/core'; * await invoke('login', { user: 'tauri', password: 'poiwe3h4r5ip3yrhtew9ty' }); * ``` * * @param cmd The command name. * @param args The optional arguments to pass to the command. * @param options The request options. * @return A promise resolving or rejecting to the backend response. * * @since 1.0.0 */ async function invoke( cmd: string, args: InvokeArgs = {}, options?: InvokeOptions ): Promise { return window.__TAURI_INTERNALS__.invoke(cmd, args, options) } /** * Convert a device file path to an URL that can be loaded by the webview. * Note that `asset:` and `http://asset.localhost` must be added to [`app.security.csp`](https://v2.tauri.app/reference/config/#csp-1) in `tauri.conf.json`. * Example CSP value: `"csp": "default-src 'self' ipc: http://ipc.localhost; img-src 'self' asset: http://asset.localhost"` to use the asset protocol on image sources. * * Additionally, `"enable" : "true"` must be added to [`app.security.assetProtocol`](https://v2.tauri.app/reference/config/#assetprotocolconfig) * in `tauri.conf.json` and its access scope must be defined on the `scope` array on the same `assetProtocol` object. * * @param filePath The file path. * @param protocol The protocol to use. Defaults to `asset`. You only need to set this when using a custom protocol. * @example * ```typescript * import { appDataDir, join } from '@tauri-apps/api/path'; * import { convertFileSrc } from '@tauri-apps/api/core'; * const appDataDirPath = await appDataDir(); * const filePath = await join(appDataDirPath, 'assets/video.mp4'); * const assetUrl = convertFileSrc(filePath); * * const video = document.getElementById('my-video'); * const source = document.createElement('source'); * source.type = 'video/mp4'; * source.src = assetUrl; * video.appendChild(source); * video.load(); * ``` * * @return the URL that can be used as source on the webview. * * @since 1.0.0 */ function convertFileSrc(filePath: string, protocol = 'asset'): string { return window.__TAURI_INTERNALS__.convertFileSrc(filePath, protocol) } /** * A rust-backed resource stored through `tauri::Manager::resources_table` API. * * The resource lives in the main process and does not exist * in the Javascript world, and thus will not be cleaned up automatically * except on application exit. If you want to clean it up early, call {@linkcode Resource.close} * * @example * ```typescript * import { Resource, invoke } from '@tauri-apps/api/core'; * export class DatabaseHandle extends Resource { * static async open(path: string): Promise { * const rid: number = await invoke('open_db', { path }); * return new DatabaseHandle(rid); * } * * async execute(sql: string): Promise { * await invoke('execute_sql', { rid: this.rid, sql }); * } * } * ``` */ export class Resource { readonly #rid: number get rid(): number { return this.#rid } constructor(rid: number) { this.#rid = rid } /** * Destroys and cleans up this resource from memory. * **You should not call any method on this object anymore and should drop any reference to it.** */ async close(): Promise { return invoke('plugin:resources|close', { rid: this.rid }) } } function isTauri(): boolean { // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access return !!((globalThis as any) || window).isTauri } export type { InvokeArgs, InvokeOptions } export { transformCallback, Channel, PluginListener, addPluginListener, PermissionState, checkPermissions, requestPermissions, invoke, convertFileSrc, isTauri } ================================================ FILE: packages/api/src/dpi.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import { SERIALIZE_TO_IPC_FN } from './core' /** * A size represented in logical pixels. * Logical pixels are scaled according to the window's DPI scale. * Most browser APIs (i.e. `MouseEvent`'s `clientX`) will return logical pixels. * * For logical-pixel-based position, see {@linkcode LogicalPosition}. * * @since 2.0.0 */ class LogicalSize { readonly type = 'Logical' width: number height: number constructor(width: number, height: number) constructor(object: { Logical: { width: number; height: number } }) constructor(object: { width: number; height: number }) constructor( ...args: | [number, number] | [{ width: number; height: number }] | [{ Logical: { width: number; height: number } }] ) { if (args.length === 1) { if ('Logical' in args[0]) { this.width = args[0].Logical.width this.height = args[0].Logical.height } else { this.width = args[0].width this.height = args[0].height } } else { this.width = args[0] this.height = args[1] } } /** * Converts the logical size to a physical one. * @example * ```typescript * import { LogicalSize } from '@tauri-apps/api/dpi'; * import { getCurrentWindow } from '@tauri-apps/api/window'; * * const appWindow = getCurrentWindow(); * const factor = await appWindow.scaleFactor(); * const size = new LogicalSize(400, 500); * const physical = size.toPhysical(factor); * ``` * * @since 2.0.0 */ toPhysical(scaleFactor: number): PhysicalSize { return new PhysicalSize(this.width * scaleFactor, this.height * scaleFactor) } [SERIALIZE_TO_IPC_FN]() { return { width: this.width, height: this.height } } toJSON() { // eslint-disable-next-line security/detect-object-injection return this[SERIALIZE_TO_IPC_FN]() } } /** * A size represented in physical pixels. * * Physical pixels represent actual screen pixels, and are DPI-independent. * For high-DPI windows, this means that any point in the window on the screen * will have a different position in logical pixels {@linkcode LogicalSize}. * * For physical-pixel-based position, see {@linkcode PhysicalPosition}. * * @since 2.0.0 */ class PhysicalSize { readonly type = 'Physical' width: number height: number constructor(width: number, height: number) constructor(object: { Physical: { width: number; height: number } }) constructor(object: { width: number; height: number }) constructor( ...args: | [number, number] | [{ width: number; height: number }] | [{ Physical: { width: number; height: number } }] ) { if (args.length === 1) { if ('Physical' in args[0]) { this.width = args[0].Physical.width this.height = args[0].Physical.height } else { this.width = args[0].width this.height = args[0].height } } else { this.width = args[0] this.height = args[1] } } /** * Converts the physical size to a logical one. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * const appWindow = getCurrentWindow(); * const factor = await appWindow.scaleFactor(); * const size = await appWindow.innerSize(); // PhysicalSize * const logical = size.toLogical(factor); * ``` */ toLogical(scaleFactor: number): LogicalSize { return new LogicalSize(this.width / scaleFactor, this.height / scaleFactor) } [SERIALIZE_TO_IPC_FN]() { return { width: this.width, height: this.height } } toJSON() { // eslint-disable-next-line security/detect-object-injection return this[SERIALIZE_TO_IPC_FN]() } } /** * A size represented either in physical or in logical pixels. * * This type is basically a union type of {@linkcode LogicalSize} and {@linkcode PhysicalSize} * but comes in handy when using `tauri::Size` in Rust as an argument to a command, as this class * automatically serializes into a valid format so it can be deserialized correctly into `tauri::Size` * * So instead of * ```typescript * import { invoke } from '@tauri-apps/api/core'; * import { LogicalSize, PhysicalSize } from '@tauri-apps/api/dpi'; * * const size: LogicalSize | PhysicalSize = someFunction(); // where someFunction returns either LogicalSize or PhysicalSize * const validSize = size instanceof LogicalSize * ? { Logical: { width: size.width, height: size.height } } * : { Physical: { width: size.width, height: size.height } } * await invoke("do_something_with_size", { size: validSize }); * ``` * * You can just use {@linkcode Size} * ```typescript * import { invoke } from '@tauri-apps/api/core'; * import { LogicalSize, PhysicalSize, Size } from '@tauri-apps/api/dpi'; * * const size: LogicalSize | PhysicalSize = someFunction(); // where someFunction returns either LogicalSize or PhysicalSize * const validSize = new Size(size); * await invoke("do_something_with_size", { size: validSize }); * ``` * * @since 2.1.0 */ class Size { size: LogicalSize | PhysicalSize constructor(size: LogicalSize | PhysicalSize) { this.size = size } toLogical(scaleFactor: number): LogicalSize { return this.size instanceof LogicalSize ? this.size : this.size.toLogical(scaleFactor) } toPhysical(scaleFactor: number): PhysicalSize { return this.size instanceof PhysicalSize ? this.size : this.size.toPhysical(scaleFactor) } [SERIALIZE_TO_IPC_FN]() { return { [`${this.size.type}`]: { width: this.size.width, height: this.size.height } } } toJSON() { // eslint-disable-next-line security/detect-object-injection return this[SERIALIZE_TO_IPC_FN]() } } /** * A position represented in logical pixels. * For an explanation of what logical pixels are, see description of {@linkcode LogicalSize}. * * @since 2.0.0 */ class LogicalPosition { readonly type = 'Logical' x: number y: number constructor(x: number, y: number) constructor(object: { Logical: { x: number; y: number } }) constructor(object: { x: number; y: number }) constructor( ...args: | [number, number] | [{ x: number; y: number }] | [{ Logical: { x: number; y: number } }] ) { if (args.length === 1) { if ('Logical' in args[0]) { this.x = args[0].Logical.x this.y = args[0].Logical.y } else { this.x = args[0].x this.y = args[0].y } } else { this.x = args[0] this.y = args[1] } } /** * Converts the logical position to a physical one. * @example * ```typescript * import { LogicalPosition } from '@tauri-apps/api/dpi'; * import { getCurrentWindow } from '@tauri-apps/api/window'; * * const appWindow = getCurrentWindow(); * const factor = await appWindow.scaleFactor(); * const position = new LogicalPosition(400, 500); * const physical = position.toPhysical(factor); * ``` * * @since 2.0.0 */ toPhysical(scaleFactor: number): PhysicalPosition { return new PhysicalPosition(this.x * scaleFactor, this.y * scaleFactor) } [SERIALIZE_TO_IPC_FN]() { return { x: this.x, y: this.y } } toJSON() { // eslint-disable-next-line security/detect-object-injection return this[SERIALIZE_TO_IPC_FN]() } } /** * A position represented in physical pixels. * * For an explanation of what physical pixels are, see description of {@linkcode PhysicalSize}. * * @since 2.0.0 */ class PhysicalPosition { readonly type = 'Physical' x: number y: number constructor(x: number, y: number) constructor(object: { Physical: { x: number; y: number } }) constructor(object: { x: number; y: number }) constructor( ...args: | [number, number] | [{ x: number; y: number }] | [{ Physical: { x: number; y: number } }] ) { if (args.length === 1) { if ('Physical' in args[0]) { this.x = args[0].Physical.x this.y = args[0].Physical.y } else { this.x = args[0].x this.y = args[0].y } } else { this.x = args[0] this.y = args[1] } } /** * Converts the physical position to a logical one. * @example * ```typescript * import { PhysicalPosition } from '@tauri-apps/api/dpi'; * import { getCurrentWindow } from '@tauri-apps/api/window'; * * const appWindow = getCurrentWindow(); * const factor = await appWindow.scaleFactor(); * const position = new PhysicalPosition(400, 500); * const physical = position.toLogical(factor); * ``` * * @since 2.0.0 */ toLogical(scaleFactor: number): LogicalPosition { return new LogicalPosition(this.x / scaleFactor, this.y / scaleFactor) } [SERIALIZE_TO_IPC_FN]() { return { x: this.x, y: this.y } } toJSON() { // eslint-disable-next-line security/detect-object-injection return this[SERIALIZE_TO_IPC_FN]() } } /** * A position represented either in physical or in logical pixels. * * This type is basically a union type of {@linkcode LogicalSize} and {@linkcode PhysicalSize} * but comes in handy when using `tauri::Position` in Rust as an argument to a command, as this class * automatically serializes into a valid format so it can be deserialized correctly into `tauri::Position` * * So instead of * ```typescript * import { invoke } from '@tauri-apps/api/core'; * import { LogicalPosition, PhysicalPosition } from '@tauri-apps/api/dpi'; * * const position: LogicalPosition | PhysicalPosition = someFunction(); // where someFunction returns either LogicalPosition or PhysicalPosition * const validPosition = position instanceof LogicalPosition * ? { Logical: { x: position.x, y: position.y } } * : { Physical: { x: position.x, y: position.y } } * await invoke("do_something_with_position", { position: validPosition }); * ``` * * You can just use {@linkcode Position} * ```typescript * import { invoke } from '@tauri-apps/api/core'; * import { LogicalPosition, PhysicalPosition, Position } from '@tauri-apps/api/dpi'; * * const position: LogicalPosition | PhysicalPosition = someFunction(); // where someFunction returns either LogicalPosition or PhysicalPosition * const validPosition = new Position(position); * await invoke("do_something_with_position", { position: validPosition }); * ``` * * @since 2.1.0 */ class Position { position: LogicalPosition | PhysicalPosition constructor(position: LogicalPosition | PhysicalPosition) { this.position = position } toLogical(scaleFactor: number): LogicalPosition { return this.position instanceof LogicalPosition ? this.position : this.position.toLogical(scaleFactor) } toPhysical(scaleFactor: number): PhysicalPosition { return this.position instanceof PhysicalPosition ? this.position : this.position.toPhysical(scaleFactor) } [SERIALIZE_TO_IPC_FN]() { return { [`${this.position.type}`]: { x: this.position.x, y: this.position.y } } } toJSON() { // eslint-disable-next-line security/detect-object-injection return this[SERIALIZE_TO_IPC_FN]() } } export { LogicalPosition, LogicalSize, Size, PhysicalPosition, PhysicalSize, Position } ================================================ FILE: packages/api/src/event.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT /** * The event system allows you to emit events to the backend and listen to events from it. * * This package is also accessible with `window.__TAURI__.event` when [`app.withGlobalTauri`](https://v2.tauri.app/reference/config/#withglobaltauri) in `tauri.conf.json` is set to `true`. * @module */ import { invoke, transformCallback } from './core' declare global { interface Window { __TAURI_EVENT_PLUGIN_INTERNALS__: { unregisterListener: (event: string, eventId: number) => void } } } type EventTarget = | { kind: 'Any' } | { kind: 'AnyLabel'; label: string } | { kind: 'App' } | { kind: 'Window'; label: string } | { kind: 'Webview'; label: string } | { kind: 'WebviewWindow'; label: string } interface Event { /** Event name */ event: EventName /** Event identifier used to unlisten */ id: number /** Event payload */ payload: T } type EventCallback = (event: Event) => void // TODO(v3): mark this as Promise type UnlistenFn = () => void type EventName = `${TauriEvent}` | (string & Record) interface Options { /** * The event target to listen to, defaults to `{ kind: 'Any' }`, see {@link EventTarget}. * * If a string is provided, {@link EventTarget.AnyLabel} is used. */ target?: string | EventTarget } /** * @since 1.1.0 */ enum TauriEvent { WINDOW_RESIZED = 'tauri://resize', WINDOW_MOVED = 'tauri://move', WINDOW_CLOSE_REQUESTED = 'tauri://close-requested', WINDOW_DESTROYED = 'tauri://destroyed', WINDOW_FOCUS = 'tauri://focus', WINDOW_BLUR = 'tauri://blur', WINDOW_SCALE_FACTOR_CHANGED = 'tauri://scale-change', WINDOW_THEME_CHANGED = 'tauri://theme-changed', WINDOW_CREATED = 'tauri://window-created', WEBVIEW_CREATED = 'tauri://webview-created', DRAG_ENTER = 'tauri://drag-enter', DRAG_OVER = 'tauri://drag-over', DRAG_DROP = 'tauri://drag-drop', DRAG_LEAVE = 'tauri://drag-leave' } /** * Unregister the event listener associated with the given name and id. * * @ignore * @param event The event name * @param eventId Event identifier * @returns */ async function _unlisten(event: string, eventId: number): Promise { window.__TAURI_EVENT_PLUGIN_INTERNALS__.unregisterListener(event, eventId) await invoke('plugin:event|unlisten', { event, eventId }) } /** * Listen to an emitted event to any {@link EventTarget|target}. * * @example * ```typescript * import { listen } from '@tauri-apps/api/event'; * const unlisten = await listen('error', (event) => { * console.log(`Got error, payload: ${event.payload}`); * }); * * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted * unlisten(); * ``` * * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`. * @param handler Event handler callback. * @param options Event listening options. * @returns A promise resolving to a function to unlisten to the event. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted. * * @since 1.0.0 */ async function listen( event: EventName, handler: EventCallback, options?: Options ): Promise { const target: EventTarget = typeof options?.target === 'string' ? { kind: 'AnyLabel', label: options.target } : (options?.target ?? { kind: 'Any' }) return invoke('plugin:event|listen', { event, target, handler: transformCallback(handler) }).then((eventId) => { return async () => _unlisten(event, eventId) }) } /** * Listens once to an emitted event to any {@link EventTarget|target}. * * @example * ```typescript * import { once } from '@tauri-apps/api/event'; * interface LoadedPayload { * loggedIn: boolean, * token: string * } * const unlisten = await once('loaded', (event) => { * console.log(`App is loaded, loggedIn: ${event.payload.loggedIn}, token: ${event.payload.token}`); * }); * * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted * unlisten(); * ``` * * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`. * @param handler Event handler callback. * @param options Event listening options. * @returns A promise resolving to a function to unlisten to the event. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted. * * @since 1.0.0 */ async function once( event: EventName, handler: EventCallback, options?: Options ): Promise { return listen( event, (eventData) => { void _unlisten(event, eventData.id) handler(eventData) }, options ) } /** * Emits an event to all {@link EventTarget|targets}. * * @example * ```typescript * import { emit } from '@tauri-apps/api/event'; * await emit('frontend-loaded', { loggedIn: true, token: 'authToken' }); * ``` * * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`. * @param payload Event payload. * * @since 1.0.0 */ async function emit(event: string, payload?: T): Promise { await invoke('plugin:event|emit', { event, payload }) } /** * Emits an event to all {@link EventTarget|targets} matching the given target. * * @example * ```typescript * import { emitTo } from '@tauri-apps/api/event'; * await emitTo('main', 'frontend-loaded', { loggedIn: true, token: 'authToken' }); * ``` * * @param target Label of the target Window/Webview/WebviewWindow or raw {@link EventTarget} object. * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`. * @param payload Event payload. * * @since 2.0.0 */ async function emitTo( target: EventTarget | string, event: string, payload?: T ): Promise { const eventTarget: EventTarget = typeof target === 'string' ? { kind: 'AnyLabel', label: target } : target await invoke('plugin:event|emit_to', { target: eventTarget, event, payload }) } export type { Event, EventTarget, EventCallback, UnlistenFn, EventName, Options } export { listen, once, emit, emitTo, TauriEvent } ================================================ FILE: packages/api/src/global.d.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT /** @ignore */ import type { invoke, transformCallback, convertFileSrc } from './core' /** @ignore */ declare global { interface Window { __TAURI_INTERNALS__: { invoke: typeof invoke transformCallback: typeof transformCallback unregisterCallback: (id: number) => void runCallback: (id: number, data: unknown) => void callbacks: Map void> convertFileSrc: typeof convertFileSrc ipc: (message: { cmd: string callback: number error: number payload: unknown options?: InvokeOptions }) => void metadata: { currentWindow: WindowDef currentWebview: WebviewDef } plugins: { path: { sep: string delimiter: string } } } __TAURI_EVENT_PLUGIN_INTERNALS__: { unregisterListener: (event: string, eventId: number) => void } } } /** @ignore */ interface WebviewDef { windowLabel: string label: string } /** @ignore */ interface WindowDef { label: string } ================================================ FILE: packages/api/src/image.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import { Resource, invoke } from './core' import { NativeIcon } from './menu/iconMenuItem' /// Image dimensions type. export interface ImageSize { /// Image width. width: number /// Image height. height: number } /** A type that represents an icon that can be used in menu items. */ export type MenuIcon = | NativeIcon | string | Image | Uint8Array | ArrayBuffer | number[] /** An RGBA Image in row-major order from top to bottom. */ export class Image extends Resource { /** * Creates an Image from a resource ID. For internal use only. * * @ignore */ constructor(rid: number) { super(rid) } /** Creates a new Image using RGBA data, in row-major order from top to bottom, and with specified width and height. */ static async new( rgba: number[] | Uint8Array | ArrayBuffer, width: number, height: number ): Promise { return invoke('plugin:image|new', { rgba: transformImage(rgba), width, height }).then((rid) => new Image(rid)) } /** * Creates a new image using the provided bytes by inferring the file format. * If the format is known, prefer [@link Image.fromPngBytes] or [@link Image.fromIcoBytes]. * * Only `ico` and `png` are supported (based on activated feature flag). * * Note that you need the `image-ico` or `image-png` Cargo features to use this API. * To enable it, change your Cargo.toml file: * ```toml * [dependencies] * tauri = { version = "...", features = ["...", "image-png"] } * ``` */ static async fromBytes( bytes: number[] | Uint8Array | ArrayBuffer ): Promise { return invoke('plugin:image|from_bytes', { bytes: transformImage(bytes) }).then((rid) => new Image(rid)) } /** * Creates a new image using the provided path. * * Only `ico` and `png` are supported (based on activated feature flag). * * Note that you need the `image-ico` or `image-png` Cargo features to use this API. * To enable it, change your Cargo.toml file: * ```toml * [dependencies] * tauri = { version = "...", features = ["...", "image-png"] } * ``` */ static async fromPath(path: string): Promise { return invoke('plugin:image|from_path', { path }).then( (rid) => new Image(rid) ) } /** Returns the RGBA data for this image, in row-major order from top to bottom. */ async rgba(): Promise { return invoke('plugin:image|rgba', { rid: this.rid }).then((buffer) => new Uint8Array(buffer)) } /** Returns the size of this image. */ async size(): Promise { return invoke('plugin:image|size', { rid: this.rid }) } } /** * Transforms image from various types into a type acceptable by Rust. * * See [tauri::image::JsImage](https://docs.rs/tauri/2/tauri/image/enum.JsImage.html) for more information. * Note the API signature is not stable and might change. */ export function transformImage( image: string | Image | Uint8Array | ArrayBuffer | number[] | null ): T { const ret = image == null ? null : typeof image === 'string' ? image : image instanceof Image ? image.rid : image return ret as T } ================================================ FILE: packages/api/src/index.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT /** * The Tauri API allows you to interface with the backend layer. * * This module exposes all other modules as an object where the key is the module name, and the value is the module exports. * @example * ```typescript * import { event, window, path } from '@tauri-apps/api' * ``` * * ### Vanilla JS API * * The above import syntax is for JavaScript/TypeScript with a bundler. If you're using vanilla JavaScript, you can use the global `window.__TAURI__` object instead. It requires `app.withGlobalTauri` configuration option enabled. * * @example * ```js * const { event, window: tauriWindow, path } = window.__TAURI__; * ``` * * @module */ import * as app from './app' import * as core from './core' import * as dpi from './dpi' import * as event from './event' import * as image from './image' import * as menu from './menu' import * as mocks from './mocks' import * as path from './path' import * as tray from './tray' import * as webview from './webview' import * as webviewWindow from './webviewWindow' import * as window from './window' export { app, core, dpi, event, image, menu, mocks, path, tray, webview, webviewWindow, window } ================================================ FILE: packages/api/src/menu/base.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import { Channel, invoke, Resource } from '../core' import { transformImage } from '../image' import { CheckMenuItemOptions } from './checkMenuItem' import { IconMenuItemOptions } from './iconMenuItem' import { MenuOptions } from './menu' import { MenuItemOptions } from './menuItem' import { PredefinedMenuItemOptions } from './predefinedMenuItem' import { SubmenuOptions } from './submenu' export type ItemKind = | 'MenuItem' | 'Predefined' | 'Check' | 'Icon' | 'Submenu' | 'Menu' type MenuItemOptionsAlias = | MenuItemOptions | SubmenuOptions | IconMenuItemOptions | PredefinedMenuItemOptions | CheckMenuItemOptions function injectChannel(i: MenuItemOptionsAlias): MenuItemOptionsAlias & { handler?: Channel } { if ('items' in i) { i.items = i.items?.map((item) => 'rid' in item ? item : injectChannel(item) ) } else if ('action' in i && i.action) { const handler = new Channel() handler.onmessage = i.action delete i.action return { ...i, handler } } return i } export async function newMenu( kind: ItemKind, opts?: | MenuOptions | MenuItemOptions | SubmenuOptions | PredefinedMenuItemOptions | CheckMenuItemOptions | IconMenuItemOptions ): Promise<[number, string]> { const handler = new Channel() if (opts && typeof opts === 'object') { if ('action' in opts && opts.action) { handler.onmessage = opts.action delete opts.action } // about predefined menu item icon if ( 'item' in opts && opts.item && typeof opts.item === 'object' && 'About' in opts.item && opts.item.About && typeof opts.item.About === 'object' && 'icon' in opts.item.About && opts.item.About.icon ) { opts.item.About.icon = transformImage(opts.item.About.icon) } // icon menu item icon if ('icon' in opts && opts.icon) { opts.icon = transformImage(opts.icon) } // submenu items if ('items' in opts && opts.items) { function prepareItem( i: { rid: number; kind: string } | MenuItemOptionsAlias ): [number, string] | MenuItemOptionsAlias { if ('rid' in i) { return [i.rid, i.kind] } if ('item' in i && typeof i.item === 'object' && i.item.About?.icon) { i.item.About.icon = transformImage(i.item.About.icon) } if ('icon' in i && i.icon) { i.icon = transformImage(i.icon) } if ('items' in i && i.items) { // @ts-expect-error the `prepareItem` return doesn't exactly match // this is fine, because the difference is in `[number, string]` variant i.items = i.items.map(prepareItem) } return injectChannel(i) } // @ts-expect-error the `prepareItem` return doesn't exactly match // this is fine, because the difference is in `[number, string]` variant opts.items = opts.items.map(prepareItem) } } return invoke('plugin:menu|new', { kind, options: opts, handler }) } export class MenuItemBase extends Resource { /** @ignore */ readonly #id: string /** @ignore */ readonly #kind: ItemKind /** The id of this item. */ get id(): string { return this.#id } /** @ignore */ get kind(): string { return this.#kind } /** @ignore */ protected constructor(rid: number, id: string, kind: ItemKind) { super(rid) this.#id = id this.#kind = kind } } ================================================ FILE: packages/api/src/menu/checkMenuItem.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import { MenuItemBase, newMenu } from './base' import { invoke } from '../core' import { type MenuItemOptions } from '../menu' /** Options for creating a new check menu item. */ export interface CheckMenuItemOptions extends MenuItemOptions { /** Whether the new check menu item is enabled or not. */ checked?: boolean } /** * A check menu item inside a {@linkcode Menu} or {@linkcode Submenu} * and usually contains a text and a check mark or a similar toggle * that corresponds to a checked and unchecked states. */ export class CheckMenuItem extends MenuItemBase { /** @ignore */ protected constructor(rid: number, id: string) { super(rid, id, 'Check') } /** Create a new check menu item. */ static async new(opts: CheckMenuItemOptions): Promise { return newMenu('Check', opts).then( ([rid, id]) => new CheckMenuItem(rid, id) ) } /** Returns the text of this check menu item. */ async text(): Promise { return invoke('plugin:menu|text', { rid: this.rid, kind: this.kind }) } /** Sets the text for this check menu item. */ async setText(text: string): Promise { return invoke('plugin:menu|set_text', { rid: this.rid, kind: this.kind, text }) } /** Returns whether this check menu item is enabled or not. */ async isEnabled(): Promise { return invoke('plugin:menu|is_enabled', { rid: this.rid, kind: this.kind }) } /** Sets whether this check menu item is enabled or not. */ async setEnabled(enabled: boolean): Promise { return invoke('plugin:menu|set_enabled', { rid: this.rid, kind: this.kind, enabled }) } /** Sets the accelerator for this check menu item. */ async setAccelerator(accelerator: string | null): Promise { return invoke('plugin:menu|set_accelerator', { rid: this.rid, kind: this.kind, accelerator }) } /** Returns whether this check menu item is checked or not. */ async isChecked(): Promise { return invoke('plugin:menu|is_checked', { rid: this.rid }) } /** Sets whether this check menu item is checked or not. */ async setChecked(checked: boolean): Promise { return invoke('plugin:menu|set_checked', { rid: this.rid, checked }) } } ================================================ FILE: packages/api/src/menu/iconMenuItem.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import { MenuItemBase, newMenu } from './base' import { type MenuItemOptions } from '../menu' import { invoke } from '../core' import { transformImage, MenuIcon } from '../image' /** * A native Icon to be used for the menu item * * #### Platform-specific: * * - **Windows / Linux**: Unsupported. */ export enum NativeIcon { /** An add item template image. */ Add = 'Add', /** Advanced preferences toolbar icon for the preferences window. */ Advanced = 'Advanced', /** A Bluetooth template image. */ Bluetooth = 'Bluetooth', /** Bookmarks image suitable for a template. */ Bookmarks = 'Bookmarks', /** A caution image. */ Caution = 'Caution', /** A color panel toolbar icon. */ ColorPanel = 'ColorPanel', /** A column view mode template image. */ ColumnView = 'ColumnView', /** A computer icon. */ Computer = 'Computer', /** An enter full-screen mode template image. */ EnterFullScreen = 'EnterFullScreen', /** Permissions for all users. */ Everyone = 'Everyone', /** An exit full-screen mode template image. */ ExitFullScreen = 'ExitFullScreen', /** A cover flow view mode template image. */ FlowView = 'FlowView', /** A folder image. */ Folder = 'Folder', /** A burnable folder icon. */ FolderBurnable = 'FolderBurnable', /** A smart folder icon. */ FolderSmart = 'FolderSmart', /** A link template image. */ FollowLinkFreestanding = 'FollowLinkFreestanding', /** A font panel toolbar icon. */ FontPanel = 'FontPanel', /** A `go back` template image. */ GoLeft = 'GoLeft', /** A `go forward` template image. */ GoRight = 'GoRight', /** Home image suitable for a template. */ Home = 'Home', /** An iChat Theater template image. */ IChatTheater = 'IChatTheater', /** An icon view mode template image. */ IconView = 'IconView', /** An information toolbar icon. */ Info = 'Info', /** A template image used to denote invalid data. */ InvalidDataFreestanding = 'InvalidDataFreestanding', /** A generic left-facing triangle template image. */ LeftFacingTriangle = 'LeftFacingTriangle', /** A list view mode template image. */ ListView = 'ListView', /** A locked padlock template image. */ LockLocked = 'LockLocked', /** An unlocked padlock template image. */ LockUnlocked = 'LockUnlocked', /** A horizontal dash, for use in menus. */ MenuMixedState = 'MenuMixedState', /** A check mark template image, for use in menus. */ MenuOnState = 'MenuOnState', /** A MobileMe icon. */ MobileMe = 'MobileMe', /** A drag image for multiple items. */ MultipleDocuments = 'MultipleDocuments', /** A network icon. */ Network = 'Network', /** A path button template image. */ Path = 'Path', /** General preferences toolbar icon for the preferences window. */ PreferencesGeneral = 'PreferencesGeneral', /** A Quick Look template image. */ QuickLook = 'QuickLook', /** A refresh template image. */ RefreshFreestanding = 'RefreshFreestanding', /** A refresh template image. */ Refresh = 'Refresh', /** A remove item template image. */ Remove = 'Remove', /** A reveal contents template image. */ RevealFreestanding = 'RevealFreestanding', /** A generic right-facing triangle template image. */ RightFacingTriangle = 'RightFacingTriangle', /** A share view template image. */ Share = 'Share', /** A slideshow template image. */ Slideshow = 'Slideshow', /** A badge for a `smart` item. */ SmartBadge = 'SmartBadge', /** Small green indicator, similar to iChat's available image. */ StatusAvailable = 'StatusAvailable', /** Small clear indicator. */ StatusNone = 'StatusNone', /** Small yellow indicator, similar to iChat's idle image. */ StatusPartiallyAvailable = 'StatusPartiallyAvailable', /** Small red indicator, similar to iChat's unavailable image. */ StatusUnavailable = 'StatusUnavailable', /** A stop progress template image. */ StopProgressFreestanding = 'StopProgressFreestanding', /** A stop progress button template image. */ StopProgress = 'StopProgress', /** An image of the empty trash can. */ TrashEmpty = 'TrashEmpty', /** An image of the full trash can. */ TrashFull = 'TrashFull', /** Permissions for a single user. */ User = 'User', /** User account toolbar icon for the preferences window. */ UserAccounts = 'UserAccounts', /** Permissions for a group of users. */ UserGroup = 'UserGroup', /** Permissions for guests. */ UserGuest = 'UserGuest' } /** Options for creating a new icon menu item. */ export interface IconMenuItemOptions extends MenuItemOptions { /** * Icon to be used for the new icon menu item. * * Note that you may need the `image-ico` or `image-png` Cargo features to use this API. * To enable it, change your Cargo.toml file: * ```toml * [dependencies] * tauri = { version = "...", features = ["...", "image-png"] } * ``` */ icon?: MenuIcon } /** * An icon menu item inside a {@linkcode Menu} or {@linkcode Submenu} * and usually contains an icon and a text. */ export class IconMenuItem extends MenuItemBase { /** @ignore */ protected constructor(rid: number, id: string) { super(rid, id, 'Icon') } /** Create a new icon menu item. */ static async new(opts: IconMenuItemOptions): Promise { return newMenu('Icon', opts).then(([rid, id]) => new IconMenuItem(rid, id)) } /** Returns the text of this icon menu item. */ async text(): Promise { return invoke('plugin:menu|text', { rid: this.rid, kind: this.kind }) } /** Sets the text for this icon menu item. */ async setText(text: string): Promise { return invoke('plugin:menu|set_text', { rid: this.rid, kind: this.kind, text }) } /** Returns whether this icon menu item is enabled or not. */ async isEnabled(): Promise { return invoke('plugin:menu|is_enabled', { rid: this.rid, kind: this.kind }) } /** Sets whether this icon menu item is enabled or not. */ async setEnabled(enabled: boolean): Promise { return invoke('plugin:menu|set_enabled', { rid: this.rid, kind: this.kind, enabled }) } /** Sets the accelerator for this icon menu item. */ async setAccelerator(accelerator: string | null): Promise { return invoke('plugin:menu|set_accelerator', { rid: this.rid, kind: this.kind, accelerator }) } /** Sets an icon for this icon menu item */ async setIcon(icon: MenuIcon | null): Promise { return invoke('plugin:menu|set_icon', { rid: this.rid, kind: this.kind, icon: transformImage(icon) }) } } ================================================ FILE: packages/api/src/menu/menu.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import { MenuItemOptions, SubmenuOptions, IconMenuItemOptions, PredefinedMenuItemOptions, CheckMenuItemOptions } from '../menu' import { MenuItem } from './menuItem' import { CheckMenuItem } from './checkMenuItem' import { IconMenuItem } from './iconMenuItem' import { PredefinedMenuItem } from './predefinedMenuItem' import { itemFromKind, Submenu } from './submenu' import { type LogicalPosition, PhysicalPosition, Position } from '../dpi' import { type Window } from '../window' import { invoke } from '../core' import { type ItemKind, MenuItemBase, newMenu } from './base' /** Options for creating a new menu. */ export interface MenuOptions { /** Specify an id to use for the new menu. */ id?: string /** List of items to add to the new menu. */ items?: Array< | Submenu | MenuItem | PredefinedMenuItem | CheckMenuItem | IconMenuItem | MenuItemOptions | SubmenuOptions | IconMenuItemOptions | PredefinedMenuItemOptions | CheckMenuItemOptions > } /** A type that is either a menu bar on the window * on Windows and Linux or as a global menu in the menubar on macOS. * * #### Platform-specific: * * - **macOS**: if using {@linkcode Menu} for the global menubar, it can only contain {@linkcode Submenu}s. */ export class Menu extends MenuItemBase { /** @ignore */ protected constructor(rid: number, id: string) { super(rid, id, 'Menu') } /** Create a new menu. */ static async new(opts?: MenuOptions): Promise { return newMenu('Menu', opts).then(([rid, id]) => new Menu(rid, id)) } /** Create a default menu. */ static async default(): Promise { return invoke<[number, string]>('plugin:menu|create_default').then( ([rid, id]) => new Menu(rid, id) ) } /** * Add a menu item to the end of this menu. * * #### Platform-specific: * * - **macOS:** Only {@linkcode Submenu}s can be added to a {@linkcode Menu}. */ async append< T extends | Submenu | MenuItem | PredefinedMenuItem | CheckMenuItem | IconMenuItem | MenuItemOptions | SubmenuOptions | IconMenuItemOptions | PredefinedMenuItemOptions | CheckMenuItemOptions >(items: T | T[]): Promise { return invoke('plugin:menu|append', { rid: this.rid, kind: this.kind, items: (Array.isArray(items) ? items : [items]).map((i) => 'rid' in i ? [i.rid, i.kind] : i ) }) } /** * Add a menu item to the beginning of this menu. * * #### Platform-specific: * * - **macOS:** Only {@linkcode Submenu}s can be added to a {@linkcode Menu}. */ async prepend< T extends | Submenu | MenuItem | PredefinedMenuItem | CheckMenuItem | IconMenuItem | MenuItemOptions | SubmenuOptions | IconMenuItemOptions | PredefinedMenuItemOptions | CheckMenuItemOptions >(items: T | T[]): Promise { return invoke('plugin:menu|prepend', { rid: this.rid, kind: this.kind, items: (Array.isArray(items) ? items : [items]).map((i) => 'rid' in i ? [i.rid, i.kind] : i ) }) } /** * Add a menu item to the specified position in this menu. * * #### Platform-specific: * * - **macOS:** Only {@linkcode Submenu}s can be added to a {@linkcode Menu}. */ async insert< T extends | Submenu | MenuItem | PredefinedMenuItem | CheckMenuItem | IconMenuItem | MenuItemOptions | SubmenuOptions | IconMenuItemOptions | PredefinedMenuItemOptions | CheckMenuItemOptions >(items: T | T[], position: number): Promise { return invoke('plugin:menu|insert', { rid: this.rid, kind: this.kind, items: (Array.isArray(items) ? items : [items]).map((i) => 'rid' in i ? [i.rid, i.kind] : i ), position }) } /** Remove a menu item from this menu. */ async remove( item: Submenu | MenuItem | PredefinedMenuItem | CheckMenuItem | IconMenuItem ): Promise { return invoke('plugin:menu|remove', { rid: this.rid, kind: this.kind, item: [item.rid, item.kind] }) } /** Remove a menu item from this menu at the specified position. */ async removeAt( position: number ): Promise< | Submenu | MenuItem | PredefinedMenuItem | CheckMenuItem | IconMenuItem | null > { return invoke<[number, string, ItemKind]>('plugin:menu|remove_at', { rid: this.rid, kind: this.kind, position }).then(itemFromKind) } /** Returns a list of menu items that has been added to this menu. */ async items(): Promise< Array< Submenu | MenuItem | PredefinedMenuItem | CheckMenuItem | IconMenuItem > > { return invoke>('plugin:menu|items', { rid: this.rid, kind: this.kind }).then((i) => i.map(itemFromKind)) } /** Retrieves the menu item matching the given identifier. */ async get( id: string ): Promise< | Submenu | MenuItem | PredefinedMenuItem | CheckMenuItem | IconMenuItem | null > { return invoke<[number, string, ItemKind] | null>('plugin:menu|get', { rid: this.rid, kind: this.kind, id }).then((r) => (r ? itemFromKind(r) : null)) } /** * Popup this menu as a context menu on the specified window. * * @param at If a position is provided, it is relative to the window's top-left corner. * If there isn't one provided, the menu will pop up at the current location of the mouse. */ async popup( at?: PhysicalPosition | LogicalPosition | Position, window?: Window ): Promise { return invoke('plugin:menu|popup', { rid: this.rid, kind: this.kind, window: window?.label ?? null, at: at instanceof Position ? at : at ? new Position(at) : null }) } /** * Sets the app-wide menu and returns the previous one. * * If a window was not created with an explicit menu or had one set explicitly, * this menu will be assigned to it. */ async setAsAppMenu(): Promise { return invoke<[number, string] | null>('plugin:menu|set_as_app_menu', { rid: this.rid }).then((r) => (r ? new Menu(r[0], r[1]) : null)) } /** * Sets the window menu and returns the previous one. * * #### Platform-specific: * * - **macOS:** Unsupported. The menu on macOS is app-wide and not specific to one * window, if you need to set it, use {@linkcode Menu.setAsAppMenu} instead. */ async setAsWindowMenu(window?: Window): Promise { return invoke<[number, string] | null>('plugin:menu|set_as_window_menu', { rid: this.rid, window: window?.label ?? null }).then((r) => (r ? new Menu(r[0], r[1]) : null)) } } ================================================ FILE: packages/api/src/menu/menuItem.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import { MenuItemBase, newMenu } from './base' import { invoke } from '../core' /** Options for creating a new menu item. */ export interface MenuItemOptions { /** Specify an id to use for the new menu item. */ id?: string /** The text of the new menu item. */ text: string /** Whether the new menu item is enabled or not. */ enabled?: boolean /** Specify an accelerator for the new menu item. */ accelerator?: string /** Specify a handler to be called when this menu item is activated. */ action?: (id: string) => void } /** A menu item inside a {@linkcode Menu} or {@linkcode Submenu} and contains only text. */ export class MenuItem extends MenuItemBase { /** @ignore */ protected constructor(rid: number, id: string) { super(rid, id, 'MenuItem') } /** Create a new menu item. */ static async new(opts: MenuItemOptions): Promise { return newMenu('MenuItem', opts).then(([rid, id]) => new MenuItem(rid, id)) } /** Returns the text of this menu item. */ async text(): Promise { return invoke('plugin:menu|text', { rid: this.rid, kind: this.kind }) } /** Sets the text for this menu item. */ async setText(text: string): Promise { return invoke('plugin:menu|set_text', { rid: this.rid, kind: this.kind, text }) } /** Returns whether this menu item is enabled or not. */ async isEnabled(): Promise { return invoke('plugin:menu|is_enabled', { rid: this.rid, kind: this.kind }) } /** Sets whether this menu item is enabled or not. */ async setEnabled(enabled: boolean): Promise { return invoke('plugin:menu|set_enabled', { rid: this.rid, kind: this.kind, enabled }) } /** Sets the accelerator for this menu item. */ async setAccelerator(accelerator: string | null): Promise { return invoke('plugin:menu|set_accelerator', { rid: this.rid, kind: this.kind, accelerator }) } } ================================================ FILE: packages/api/src/menu/predefinedMenuItem.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import { MenuItemBase, newMenu } from './base' import { invoke } from '../core' import { Image } from '../image' /** A metadata for the about predefined menu item. */ export interface AboutMetadata { /** Sets the application name. */ name?: string /** The application version. */ version?: string /** * The short version, e.g. "1.0". * * #### Platform-specific * * - **Windows / Linux:** Appended to the end of `version` in parentheses. */ shortVersion?: string /** * The authors of the application. * * #### Platform-specific * * - **macOS:** Unsupported. */ authors?: string[] /** * Application comments. * * #### Platform-specific * * - **macOS:** Unsupported. */ comments?: string /** The copyright of the application. */ copyright?: string /** * The license of the application. * * #### Platform-specific * * - **macOS:** Unsupported. */ license?: string /** * The application website. * * #### Platform-specific * * - **macOS:** Unsupported. */ website?: string /** * The website label. * * #### Platform-specific * * - **macOS:** Unsupported. */ websiteLabel?: string /** * The credits. * * #### Platform-specific * * - **Windows / Linux:** Unsupported. */ credits?: string /** * The application icon. * * #### Platform-specific * * - **Windows:** Unsupported. */ icon?: string | Uint8Array | ArrayBuffer | number[] | Image } /** Options for creating a new predefined menu item. */ export interface PredefinedMenuItemOptions { /** The text of the new predefined menu item. */ text?: string /** The predefined item type */ item: | 'Separator' | 'Copy' | 'Cut' | 'Paste' | 'SelectAll' | 'Undo' | 'Redo' | 'Minimize' | 'Maximize' | 'Fullscreen' | 'Hide' | 'HideOthers' | 'ShowAll' | 'CloseWindow' | 'Quit' | 'Services' | { About: AboutMetadata | null } } /** A predefined (native) menu item which has a predefined behavior by the OS or by tauri. */ export class PredefinedMenuItem extends MenuItemBase { /** @ignore */ protected constructor(rid: number, id: string) { super(rid, id, 'Predefined') } /** Create a new predefined menu item. */ static async new( opts?: PredefinedMenuItemOptions ): Promise { return newMenu('Predefined', opts).then( ([rid, id]) => new PredefinedMenuItem(rid, id) ) } /** Returns the text of this predefined menu item. */ async text(): Promise { return invoke('plugin:menu|text', { rid: this.rid, kind: this.kind }) } /** Sets the text for this predefined menu item. */ async setText(text: string): Promise { return invoke('plugin:menu|set_text', { rid: this.rid, kind: this.kind, text }) } } ================================================ FILE: packages/api/src/menu/submenu.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import { IconMenuItemOptions, PredefinedMenuItemOptions, CheckMenuItemOptions } from '../menu' import { MenuItem, type MenuItemOptions } from './menuItem' import { CheckMenuItem } from './checkMenuItem' import { IconMenuItem } from './iconMenuItem' import { PredefinedMenuItem } from './predefinedMenuItem' import { invoke } from '../core' import { type LogicalPosition, PhysicalPosition, type Window } from '../window' import { type ItemKind, MenuItemBase, newMenu } from './base' import { type MenuOptions } from './menu' import { Position } from '../dpi' import { transformImage, MenuIcon } from '../image' /** @ignore */ export function itemFromKind([rid, id, kind]: [number, string, ItemKind]): | Submenu | MenuItem | PredefinedMenuItem | CheckMenuItem | IconMenuItem { /* eslint-disable @typescript-eslint/no-unsafe-return */ switch (kind) { case 'Submenu': // @ts-expect-error constructor is protected for external usage only, safe for us to use return new Submenu(rid, id) case 'Predefined': // @ts-expect-error constructor is protected for external usage only, safe for us to use return new PredefinedMenuItem(rid, id) case 'Check': // @ts-expect-error constructor is protected for external usage only, safe for us to use return new CheckMenuItem(rid, id) case 'Icon': // @ts-expect-error constructor is protected for external usage only, safe for us to use return new IconMenuItem(rid, id) case 'MenuItem': default: // @ts-expect-error constructor is protected for external usage only, safe for us to use return new MenuItem(rid, id) } /* eslint-enable @typescript-eslint/no-unsafe-return */ } export type SubmenuOptions = (Omit & MenuOptions) & { /** * Icon to be used for the submenu. * Note: you may need the `image-ico` or `image-png` Cargo features to use this API. */ icon?: MenuIcon } /** A type that is a submenu inside a {@linkcode Menu} or {@linkcode Submenu}. */ export class Submenu extends MenuItemBase { /** @ignore */ protected constructor(rid: number, id: string) { super(rid, id, 'Submenu') } /** Create a new submenu. */ static async new(opts: SubmenuOptions): Promise { return newMenu('Submenu', opts).then(([rid, id]) => new Submenu(rid, id)) } /** Returns the text of this submenu. */ async text(): Promise { return invoke('plugin:menu|text', { rid: this.rid, kind: this.kind }) } /** Sets the text for this submenu. */ async setText(text: string): Promise { return invoke('plugin:menu|set_text', { rid: this.rid, kind: this.kind, text }) } /** Returns whether this submenu is enabled or not. */ async isEnabled(): Promise { return invoke('plugin:menu|is_enabled', { rid: this.rid, kind: this.kind }) } /** Sets whether this submenu is enabled or not. */ async setEnabled(enabled: boolean): Promise { return invoke('plugin:menu|set_enabled', { rid: this.rid, kind: this.kind, enabled }) } /** * Add a menu item to the end of this submenu. * * #### Platform-specific: * * - **macOS:** Only {@linkcode Submenu}s can be added to a {@linkcode Menu}. */ async append< T extends | Submenu | MenuItem | PredefinedMenuItem | CheckMenuItem | IconMenuItem | MenuItemOptions | SubmenuOptions | IconMenuItemOptions | PredefinedMenuItemOptions | CheckMenuItemOptions >(items: T | T[]): Promise { return invoke('plugin:menu|append', { rid: this.rid, kind: this.kind, items: (Array.isArray(items) ? items : [items]).map((i) => 'rid' in i ? [i.rid, i.kind] : i ) }) } /** * Add a menu item to the beginning of this submenu. * * #### Platform-specific: * * - **macOS:** Only {@linkcode Submenu}s can be added to a {@linkcode Menu}. */ async prepend< T extends | Submenu | MenuItem | PredefinedMenuItem | CheckMenuItem | IconMenuItem | MenuItemOptions | SubmenuOptions | IconMenuItemOptions | PredefinedMenuItemOptions | CheckMenuItemOptions >(items: T | T[]): Promise { return invoke('plugin:menu|prepend', { rid: this.rid, kind: this.kind, items: (Array.isArray(items) ? items : [items]).map((i) => 'rid' in i ? [i.rid, i.kind] : i ) }) } /** * Add a menu item to the specified position in this submenu. * * #### Platform-specific: * * - **macOS:** Only {@linkcode Submenu}s can be added to a {@linkcode Menu}. */ async insert< T extends | Submenu | MenuItem | PredefinedMenuItem | CheckMenuItem | IconMenuItem | MenuItemOptions | SubmenuOptions | IconMenuItemOptions | PredefinedMenuItemOptions | CheckMenuItemOptions >(items: T | T[], position: number): Promise { return invoke('plugin:menu|insert', { rid: this.rid, kind: this.kind, items: (Array.isArray(items) ? items : [items]).map((i) => 'rid' in i ? [i.rid, i.kind] : i ), position }) } /** Remove a menu item from this submenu. */ async remove( item: Submenu | MenuItem | PredefinedMenuItem | CheckMenuItem | IconMenuItem ): Promise { return invoke('plugin:menu|remove', { rid: this.rid, kind: this.kind, item: [item.rid, item.kind] }) } /** Remove a menu item from this submenu at the specified position. */ async removeAt( position: number ): Promise< | Submenu | MenuItem | PredefinedMenuItem | CheckMenuItem | IconMenuItem | null > { return invoke<[number, string, ItemKind]>('plugin:menu|remove_at', { rid: this.rid, kind: this.kind, position }).then(itemFromKind) } /** Returns a list of menu items that has been added to this submenu. */ async items(): Promise< Array< Submenu | MenuItem | PredefinedMenuItem | CheckMenuItem | IconMenuItem > > { return invoke>('plugin:menu|items', { rid: this.rid, kind: this.kind }).then((i) => i.map(itemFromKind)) } /** Retrieves the menu item matching the given identifier. */ async get( id: string ): Promise< | Submenu | MenuItem | PredefinedMenuItem | CheckMenuItem | IconMenuItem | null > { return invoke<[number, string, ItemKind] | null>('plugin:menu|get', { rid: this.rid, kind: this.kind, id }).then((r) => (r ? itemFromKind(r) : null)) } /** * Popup this submenu as a context menu on the specified window. * * If the position, is provided, it is relative to the window's top-left corner. */ async popup( at?: PhysicalPosition | LogicalPosition, window?: Window ): Promise { return invoke('plugin:menu|popup', { rid: this.rid, kind: this.kind, window: window?.label ?? null, at: at instanceof Position ? at : at ? new Position(at) : null }) } /** * Set this submenu as the Window menu for the application on macOS. * * This will cause macOS to automatically add window-switching items and * certain other items to the menu. * * #### Platform-specific: * * - **Windows / Linux**: Unsupported. */ async setAsWindowsMenuForNSApp(): Promise { return invoke('plugin:menu|set_as_windows_menu_for_nsapp', { rid: this.rid }) } /** * Set this submenu as the Help menu for the application on macOS. * * This will cause macOS to automatically add a search box to the menu. * * If no menu is set as the Help menu, macOS will automatically use any menu * which has a title matching the localized word "Help". * * #### Platform-specific: * * - **Windows / Linux**: Unsupported. */ async setAsHelpMenuForNSApp(): Promise { return invoke('plugin:menu|set_as_help_menu_for_nsapp', { rid: this.rid }) } /** Sets an icon for this submenu */ async setIcon(icon: MenuIcon | null): Promise { return invoke('plugin:menu|set_icon', { rid: this.rid, kind: this.kind, icon: transformImage(icon) }) } } ================================================ FILE: packages/api/src/menu.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT export * from './menu/submenu' export * from './menu/menuItem' export * from './menu/menu' export * from './menu/checkMenuItem' export * from './menu/iconMenuItem' export * from './menu/predefinedMenuItem' /** * Menu types and utilities. * * This package is also accessible with `window.__TAURI__.menu` when [`app.withGlobalTauri`](https://v2.tauri.app/reference/config/#withglobaltauri) in `tauri.conf.json` is set to `true`. * @module */ ================================================ FILE: packages/api/src/mocks.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import type { InvokeArgs, InvokeOptions } from './core' import { EventName } from './event' function mockInternals() { window.__TAURI_INTERNALS__ = window.__TAURI_INTERNALS__ ?? {} window.__TAURI_EVENT_PLUGIN_INTERNALS__ = window.__TAURI_EVENT_PLUGIN_INTERNALS__ ?? {} } /** * Options for `mockIPC`. * * # Options * `shouldMockEvents`: If true, the `listen` and `emit` functions will be mocked, allowing you to test event handling without a real backend. * **This will consume any events emitted with the `plugin:event` prefix.** * * @since 2.7.0 */ export interface MockIPCOptions { shouldMockEvents?: boolean } /** * Intercepts all IPC requests with the given mock handler. * * This function can be used when testing tauri frontend applications or when running the frontend in a Node.js context during static site generation. * * # Examples * * Testing setup using Vitest: * ```ts * import { mockIPC, clearMocks } from "@tauri-apps/api/mocks" * import { invoke } from "@tauri-apps/api/core" * * afterEach(() => { * clearMocks() * }) * * test("mocked command", () => { * mockIPC((cmd, payload) => { * switch (cmd) { * case "add": * return (payload.a as number) + (payload.b as number); * default: * break; * } * }); * * expect(invoke('add', { a: 12, b: 15 })).resolves.toBe(27); * }) * ``` * * The callback function can also return a Promise: * ```js * import { mockIPC, clearMocks } from "@tauri-apps/api/mocks" * import { invoke } from "@tauri-apps/api/core" * * afterEach(() => { * clearMocks() * }) * * test("mocked command", () => { * mockIPC((cmd, payload) => { * if(cmd === "get_data") { * return fetch("https://example.com/data.json") * .then((response) => response.json()) * } * }); * * expect(invoke('get_data')).resolves.toBe({ foo: 'bar' }); * }) * ``` * * `listen` can also be mocked with direct calls to the `emit` function. This functionality is opt-in via the `shouldMockEvents` option: * ```js * import { mockIPC, clearMocks } from "@tauri-apps/api/mocks" * import { emit, listen } from "@tauri-apps/api/event" * * afterEach(() => { * clearMocks() * }) * * test("mocked event", () => { * mockIPC(() => {}, { shouldMockEvents: true }); // enable event mocking * * const eventHandler = vi.fn(); * listen('test-event', eventHandler); // typically in component setup or similar * * emit('test-event', { foo: 'bar' }); * expect(eventHandler).toHaveBeenCalledWith({ * event: 'test-event', * payload: { foo: 'bar' } * }); * }) * ``` * `emitTo` is currently **not** supported by this mock implementation. * * @since 1.0.0 */ export function mockIPC( cb: (cmd: string, payload?: InvokeArgs) => unknown, options?: MockIPCOptions ): void { mockInternals() function isEventPluginInvoke(cmd: string): boolean { return cmd.startsWith('plugin:event|') } function handleEventPlugin(cmd: string, args?: InvokeArgs): unknown { switch (cmd) { case 'plugin:event|listen': return handleListen(args as { event: EventName; handler: number }) case 'plugin:event|emit': return handleEmit(args as { event: EventName; payload?: unknown }) case 'plugin:event|unlisten': return handleRemoveListener(args as { event: EventName; id: number }) } } const listeners = new Map() function handleListen(args: { event: EventName; handler: number }) { if (!listeners.has(args.event)) { listeners.set(args.event, []) } listeners.get(args.event)!.push(args.handler) return args.handler } function handleEmit(args: { event: EventName; payload?: unknown }) { const eventListeners = listeners.get(args.event) || [] for (const handler of eventListeners) { runCallback(handler, args) } return null } function handleRemoveListener(args: { event: EventName; id: number }) { const eventListeners = listeners.get(args.event) if (eventListeners) { const index = eventListeners.indexOf(args.id) if (index !== -1) { eventListeners.splice(index, 1) } } } // eslint-disable-next-line @typescript-eslint/require-await async function invoke( cmd: string, args?: InvokeArgs, _options?: InvokeOptions ): Promise { if (options?.shouldMockEvents && isEventPluginInvoke(cmd)) { return handleEventPlugin(cmd, args) as T } return cb(cmd, args) as T } const callbacks = new Map void>() function registerCallback( callback?: (response: T) => void, once = false ) { const identifier = window.crypto.getRandomValues(new Uint32Array(1))[0] callbacks.set(identifier, (data) => { if (once) { unregisterCallback(identifier) } return callback && callback(data as T) }) return identifier } function unregisterCallback(id: number) { callbacks.delete(id) } function runCallback(id: number, data: unknown) { const callback = callbacks.get(id) if (callback) { callback(data) } else { // eslint-disable-next-line no-console console.warn( `[TAURI] Couldn't find callback id ${id}. This might happen when the app is reloaded while Rust is running an asynchronous operation.` ) } } function unregisterListener(event: EventName, id: number) { unregisterCallback(id) } window.__TAURI_INTERNALS__.invoke = invoke window.__TAURI_INTERNALS__.transformCallback = registerCallback window.__TAURI_INTERNALS__.unregisterCallback = unregisterCallback window.__TAURI_INTERNALS__.runCallback = runCallback window.__TAURI_INTERNALS__.callbacks = callbacks window.__TAURI_EVENT_PLUGIN_INTERNALS__.unregisterListener = unregisterListener } /** * Mocks one or many window labels. * In non-tauri context it is required to call this function *before* using the `@tauri-apps/api/window` module. * * This function only mocks the *presence* of windows, * window properties (e.g. width and height) can be mocked like regular IPC calls using the `mockIPC` function. * * # Examples * * ```js * import { mockWindows } from "@tauri-apps/api/mocks"; * import { getCurrentWindow } from "@tauri-apps/api/window"; * * mockWindows("main", "second", "third"); * * const win = getCurrentWindow(); * * win.label // "main" * ``` * * ```js * import { mockWindows } from "@tauri-apps/api/mocks"; * * mockWindows("main", "second", "third"); * * mockIPC((cmd, args) => { * if (cmd === "plugin:event|emit") { * console.log('emit event', args?.event, args?.payload); * } * }); * * const { emit } = await import("@tauri-apps/api/event"); * await emit('loaded'); // this will cause the mocked IPC handler to log to the console. * ``` * * @param current Label of window this JavaScript context is running in. * * @since 1.0.0 */ export function mockWindows( current: string, ..._additionalWindows: string[] ): void { mockInternals() window.__TAURI_INTERNALS__.metadata = { currentWindow: { label: current }, currentWebview: { windowLabel: current, label: current } } } /** * Mock `convertFileSrc` function * * * @example * ```js * import { mockConvertFileSrc } from "@tauri-apps/api/mocks"; * import { convertFileSrc } from "@tauri-apps/api/core"; * * mockConvertFileSrc("windows") * * const url = convertFileSrc("C:\\Users\\user\\file.txt") * ``` * * @param osName The operating system to mock, can be one of linux, macos, or windows * * @since 1.6.0 */ export function mockConvertFileSrc(osName: string): void { mockInternals() window.__TAURI_INTERNALS__.convertFileSrc = function ( filePath, protocol = 'asset' ) { const path = encodeURIComponent(filePath) return osName === 'windows' ? `http://${protocol}.localhost/${path}` : `${protocol}://localhost/${path}` } } /** * Clears mocked functions/data injected by the other functions in this module. * When using a test runner that doesn't provide a fresh window object for each test, calling this function will reset tauri specific properties. * * # Example * * ```js * import { mockWindows, clearMocks } from "@tauri-apps/api/mocks" * * afterEach(() => { * clearMocks() * }) * * test("mocked windows", () => { * mockWindows("main", "second", "third"); * * expect(window.__TAURI_INTERNALS__).toHaveProperty("metadata") * }) * * test("no mocked windows", () => { * expect(window.__TAURI_INTERNALS__).not.toHaveProperty("metadata") * }) * ``` * * @since 1.0.0 */ export function clearMocks(): void { if (typeof window.__TAURI_INTERNALS__ !== 'object') { return } // @ts-expect-error "The operand of a 'delete' operator must be optional." does not matter in this case delete window.__TAURI_INTERNALS__.invoke // @ts-expect-error "The operand of a 'delete' operator must be optional." does not matter in this case delete window.__TAURI_INTERNALS__.transformCallback // @ts-expect-error "The operand of a 'delete' operator must be optional." does not matter in this case delete window.__TAURI_INTERNALS__.unregisterCallback // @ts-expect-error "The operand of a 'delete' operator must be optional." does not matter in this case delete window.__TAURI_INTERNALS__.runCallback // @ts-expect-error "The operand of a 'delete' operator must be optional." does not matter in this case delete window.__TAURI_INTERNALS__.callbacks // @ts-expect-error "The operand of a 'delete' operator must be optional." does not matter in this case delete window.__TAURI_INTERNALS__.convertFileSrc // @ts-expect-error "The operand of a 'delete' operator must be optional." does not matter in this case delete window.__TAURI_INTERNALS__.metadata if (typeof window.__TAURI_EVENT_PLUGIN_INTERNALS__ !== 'object') { return } // @ts-expect-error "The operand of a 'delete' operator must be optional." does not matter in this case delete window.__TAURI_EVENT_PLUGIN_INTERNALS__.unregisterListener } ================================================ FILE: packages/api/src/path.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT /** * The path module provides utilities for working with file and directory paths. * * This package is also accessible with `window.__TAURI__.path` when [`app.withGlobalTauri`](https://v2.tauri.app/reference/config/#withglobaltauri) in `tauri.conf.json` is set to `true`. * * It is recommended to allowlist only the APIs you use for optimal bundle size and security. * @module */ import { invoke } from './core' /** * @since 2.0.0 */ enum BaseDirectory { /** * @see {@link audioDir} for more information. */ Audio = 1, /** * @see {@link cacheDir} for more information. */ Cache = 2, /** * @see {@link configDir} for more information. */ Config = 3, /** * @see {@link dataDir} for more information. */ Data = 4, /** * @see {@link localDataDir} for more information. */ LocalData = 5, /** * @see {@link documentDir} for more information. */ Document = 6, /** * @see {@link downloadDir} for more information. */ Download = 7, /** * @see {@link pictureDir} for more information. */ Picture = 8, /** * @see {@link publicDir} for more information. */ Public = 9, /** * @see {@link videoDir} for more information. */ Video = 10, /** * @see {@link resourceDir} for more information. */ Resource = 11, /** * @see {@link tempDir} for more information. */ Temp = 12, /** * @see {@link appConfigDir} for more information. */ AppConfig = 13, /** * @see {@link appDataDir} for more information. */ AppData = 14, /** * @see {@link appLocalDataDir} for more information. */ AppLocalData = 15, /** * @see {@link appCacheDir} for more information. */ AppCache = 16, /** * @see {@link appLogDir} for more information. */ AppLog = 17, /** * @see {@link desktopDir} for more information. */ Desktop = 18, /** * @see {@link executableDir} for more information. */ Executable = 19, /** * @see {@link fontDir} for more information. */ Font = 20, /** * @see {@link homeDir} for more information. */ Home = 21, /** * @see {@link runtimeDir} for more information. */ Runtime = 22, /** * @see {@link templateDir} for more information. */ Template = 23 } /** * Returns the path to the suggested directory for your app's config files. * Resolves to `${configDir}/${bundleIdentifier}`, where `bundleIdentifier` is the [`identifier`](https://v2.tauri.app/reference/config/#identifier) value configured in `tauri.conf.json`. * @example * ```typescript * import { appConfigDir } from '@tauri-apps/api/path'; * const appConfigDirPath = await appConfigDir(); * ``` * * @since 1.2.0 */ async function appConfigDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.AppConfig }) } /** * Returns the path to the suggested directory for your app's data files. * Resolves to `${dataDir}/${bundleIdentifier}`, where `bundleIdentifier` is the [`identifier`](https://v2.tauri.app/reference/config/#identifier) value configured in `tauri.conf.json`. * @example * ```typescript * import { appDataDir } from '@tauri-apps/api/path'; * const appDataDirPath = await appDataDir(); * ``` * * @since 1.2.0 */ async function appDataDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.AppData }) } /** * Returns the path to the suggested directory for your app's local data files. * Resolves to `${localDataDir}/${bundleIdentifier}`, where `bundleIdentifier` is the [`identifier`](https://v2.tauri.app/reference/config/#identifier) value configured in `tauri.conf.json`. * @example * ```typescript * import { appLocalDataDir } from '@tauri-apps/api/path'; * const appLocalDataDirPath = await appLocalDataDir(); * ``` * * @since 1.2.0 */ async function appLocalDataDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.AppLocalData }) } /** * Returns the path to the suggested directory for your app's cache files. * Resolves to `${cacheDir}/${bundleIdentifier}`, where `bundleIdentifier` is the [`identifier`](https://v2.tauri.app/reference/config/#identifier) value configured in `tauri.conf.json`. * @example * ```typescript * import { appCacheDir } from '@tauri-apps/api/path'; * const appCacheDirPath = await appCacheDir(); * ``` * * @since 1.2.0 */ async function appCacheDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.AppCache }) } /** * Returns the path to the user's audio directory. * * #### Platform-specific * * - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_MUSIC_DIR`. * - **macOS:** Resolves to `$HOME/Music`. * - **Windows:** Resolves to `{FOLDERID_Music}`. * @example * ```typescript * import { audioDir } from '@tauri-apps/api/path'; * const audioDirPath = await audioDir(); * ``` * * @since 1.0.0 */ async function audioDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.Audio }) } /** * Returns the path to the user's cache directory. * * #### Platform-specific * * - **Linux:** Resolves to `$XDG_CACHE_HOME` or `$HOME/.cache`. * - **macOS:** Resolves to `$HOME/Library/Caches`. * - **Windows:** Resolves to `{FOLDERID_LocalAppData}`. * @example * ```typescript * import { cacheDir } from '@tauri-apps/api/path'; * const cacheDirPath = await cacheDir(); * ``` * * @since 1.0.0 */ async function cacheDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.Cache }) } /** * Returns the path to the user's config directory. * * #### Platform-specific * * - **Linux:** Resolves to `$XDG_CONFIG_HOME` or `$HOME/.config`. * - **macOS:** Resolves to `$HOME/Library/Application Support`. * - **Windows:** Resolves to `{FOLDERID_RoamingAppData}`. * @example * ```typescript * import { configDir } from '@tauri-apps/api/path'; * const configDirPath = await configDir(); * ``` * * @since 1.0.0 */ async function configDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.Config }) } /** * Returns the path to the user's data directory. * * #### Platform-specific * * - **Linux:** Resolves to `$XDG_DATA_HOME` or `$HOME/.local/share`. * - **macOS:** Resolves to `$HOME/Library/Application Support`. * - **Windows:** Resolves to `{FOLDERID_RoamingAppData}`. * @example * ```typescript * import { dataDir } from '@tauri-apps/api/path'; * const dataDirPath = await dataDir(); * ``` * * @since 1.0.0 */ async function dataDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.Data }) } /** * Returns the path to the user's desktop directory. * * #### Platform-specific * * - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_DESKTOP_DIR`. * - **macOS:** Resolves to `$HOME/Desktop`. * - **Windows:** Resolves to `{FOLDERID_Desktop}`. * @example * ```typescript * import { desktopDir } from '@tauri-apps/api/path'; * const desktopPath = await desktopDir(); * ``` * * @since 1.0.0 */ async function desktopDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.Desktop }) } /** * Returns the path to the user's document directory. * @example * ```typescript * import { documentDir } from '@tauri-apps/api/path'; * const documentDirPath = await documentDir(); * ``` * * #### Platform-specific * * - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_DOCUMENTS_DIR`. * - **macOS:** Resolves to `$HOME/Documents`. * - **Windows:** Resolves to `{FOLDERID_Documents}`. * * @since 1.0.0 */ async function documentDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.Document }) } /** * Returns the path to the user's download directory. * * #### Platform-specific * * - **Linux**: Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_DOWNLOAD_DIR`. * - **macOS**: Resolves to `$HOME/Downloads`. * - **Windows**: Resolves to `{FOLDERID_Downloads}`. * @example * ```typescript * import { downloadDir } from '@tauri-apps/api/path'; * const downloadDirPath = await downloadDir(); * ``` * * @since 1.0.0 */ async function downloadDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.Download }) } /** * Returns the path to the user's executable directory. * * #### Platform-specific * * - **Linux:** Resolves to `$XDG_BIN_HOME/../bin` or `$XDG_DATA_HOME/../bin` or `$HOME/.local/bin`. * - **macOS:** Not supported. * - **Windows:** Not supported. * @example * ```typescript * import { executableDir } from '@tauri-apps/api/path'; * const executableDirPath = await executableDir(); * ``` * * @since 1.0.0 */ async function executableDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.Executable }) } /** * Returns the path to the user's font directory. * * #### Platform-specific * * - **Linux:** Resolves to `$XDG_DATA_HOME/fonts` or `$HOME/.local/share/fonts`. * - **macOS:** Resolves to `$HOME/Library/Fonts`. * - **Windows:** Not supported. * @example * ```typescript * import { fontDir } from '@tauri-apps/api/path'; * const fontDirPath = await fontDir(); * ``` * * @since 1.0.0 */ async function fontDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.Font }) } /** * Returns the path to the user's home directory. * * #### Platform-specific * * - **Linux:** Resolves to `$HOME`. * - **macOS:** Resolves to `$HOME`. * - **Windows:** Resolves to `{FOLDERID_Profile}`. * @example * ```typescript * import { homeDir } from '@tauri-apps/api/path'; * const homeDirPath = await homeDir(); * ``` * * @since 1.0.0 */ async function homeDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.Home }) } /** * Returns the path to the user's local data directory. * * #### Platform-specific * * - **Linux:** Resolves to `$XDG_DATA_HOME` or `$HOME/.local/share`. * - **macOS:** Resolves to `$HOME/Library/Application Support`. * - **Windows:** Resolves to `{FOLDERID_LocalAppData}`. * @example * ```typescript * import { localDataDir } from '@tauri-apps/api/path'; * const localDataDirPath = await localDataDir(); * ``` * * @since 1.0.0 */ async function localDataDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.LocalData }) } /** * Returns the path to the user's picture directory. * * #### Platform-specific * * - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_PICTURES_DIR`. * - **macOS:** Resolves to `$HOME/Pictures`. * - **Windows:** Resolves to `{FOLDERID_Pictures}`. * @example * ```typescript * import { pictureDir } from '@tauri-apps/api/path'; * const pictureDirPath = await pictureDir(); * ``` * * @since 1.0.0 */ async function pictureDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.Picture }) } /** * Returns the path to the user's public directory. * * #### Platform-specific * * - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_PUBLICSHARE_DIR`. * - **macOS:** Resolves to `$HOME/Public`. * - **Windows:** Resolves to `{FOLDERID_Public}`. * @example * ```typescript * import { publicDir } from '@tauri-apps/api/path'; * const publicDirPath = await publicDir(); * ``` * * @since 1.0.0 */ async function publicDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.Public }) } /** * Returns the path to the application's resource directory. * To resolve a resource path, see {@linkcode resolveResource}. * * ## Platform-specific * * Although we provide the exact path where this function resolves to, * this is not a contract and things might change in the future * * - **Windows:** Resolves to the directory that contains the main executable. * - **Linux:** When running in an AppImage, the `APPDIR` variable will be set to * the mounted location of the app, and the resource dir will be `${APPDIR}/usr/lib/${exe_name}`. * If not running in an AppImage, the path is `/usr/lib/${exe_name}`. * When running the app from `src-tauri/target/(debug|release)/`, the path is `${exe_dir}/../lib/${exe_name}`. * - **macOS:** Resolves to `${exe_dir}/../Resources` (inside .app). * - **iOS:** Resolves to `${exe_dir}/assets`. * - **Android:** Currently the resources are stored in the APK as assets so it's not a normal file system path, * we return a special URI prefix `asset://localhost/` here that can be used with the [file system plugin](https://tauri.app/plugin/file-system/), * * @example * ```typescript * import { resourceDir } from '@tauri-apps/api/path'; * const resourceDirPath = await resourceDir(); * ``` * * @since 1.0.0 */ async function resourceDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.Resource }) } /** * Resolve the path to a resource file. * @example * ```typescript * import { resolveResource } from '@tauri-apps/api/path'; * const resourcePath = await resolveResource('script.sh'); * ``` * * @param resourcePath The path to the resource. * Must follow the same syntax as defined in `tauri.conf.json > bundle > resources`, i.e. keeping subfolders and parent dir components (`../`). * @returns The full path to the resource. * * @since 1.0.0 */ async function resolveResource(resourcePath: string): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.Resource, path: resourcePath }) } /** * Returns the path to the user's runtime directory. * * #### Platform-specific * * - **Linux:** Resolves to `$XDG_RUNTIME_DIR`. * - **macOS:** Not supported. * - **Windows:** Not supported. * @example * ```typescript * import { runtimeDir } from '@tauri-apps/api/path'; * const runtimeDirPath = await runtimeDir(); * ``` * * @since 1.0.0 */ async function runtimeDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.Runtime }) } /** * Returns the path to the user's template directory. * * #### Platform-specific * * - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_TEMPLATES_DIR`. * - **macOS:** Not supported. * - **Windows:** Resolves to `{FOLDERID_Templates}`. * @example * ```typescript * import { templateDir } from '@tauri-apps/api/path'; * const templateDirPath = await templateDir(); * ``` * * @since 1.0.0 */ async function templateDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.Template }) } /** * Returns the path to the user's video directory. * * #### Platform-specific * * - **Linux:** Resolves to [`xdg-user-dirs`](https://www.freedesktop.org/wiki/Software/xdg-user-dirs/)' `XDG_VIDEOS_DIR`. * - **macOS:** Resolves to `$HOME/Movies`. * - **Windows:** Resolves to `{FOLDERID_Videos}`. * @example * ```typescript * import { videoDir } from '@tauri-apps/api/path'; * const videoDirPath = await videoDir(); * ``` * * @since 1.0.0 */ async function videoDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.Video }) } /** * Returns the path to the suggested directory for your app's log files. * * #### Platform-specific * * - **Linux:** Resolves to `${configDir}/${bundleIdentifier}/logs`. * - **macOS:** Resolves to `${homeDir}/Library/Logs/{bundleIdentifier}` * - **Windows:** Resolves to `${configDir}/${bundleIdentifier}/logs`. * @example * ```typescript * import { appLogDir } from '@tauri-apps/api/path'; * const appLogDirPath = await appLogDir(); * ``` * * @since 1.2.0 */ async function appLogDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.AppLog }) } /** * Returns a temporary directory. * @example * ```typescript * import { tempDir } from '@tauri-apps/api/path'; * const temp = await tempDir(); * ``` * * @since 2.0.0 */ async function tempDir(): Promise { return invoke('plugin:path|resolve_directory', { directory: BaseDirectory.Temp }) } /** * Returns the platform-specific path segment separator: * - `\` on Windows * - `/` on POSIX * * @since 2.0.0 */ function sep(): string { return window.__TAURI_INTERNALS__.plugins.path.sep } /** * Returns the platform-specific path segment delimiter: * - `;` on Windows * - `:` on POSIX * * @since 2.0.0 */ function delimiter(): string { return window.__TAURI_INTERNALS__.plugins.path.delimiter } /** * Resolves a sequence of `paths` or `path` segments into an absolute path. * @example * ```typescript * import { resolve, appDataDir } from '@tauri-apps/api/path'; * const appDataDirPath = await appDataDir(); * const path = await resolve(appDataDirPath, '..', 'users', 'tauri', 'avatar.png'); * ``` * * @since 1.0.0 */ async function resolve(...paths: string[]): Promise { return invoke('plugin:path|resolve', { paths }) } /** * Normalizes the given `path`, resolving `'..'` and `'.'` segments and resolve symbolic links. * @example * ```typescript * import { normalize, appDataDir } from '@tauri-apps/api/path'; * const appDataDirPath = await appDataDir(); * const path = await normalize(`${appDataDirPath}/../users/tauri/avatar.png`); * ``` * * @since 1.0.0 */ async function normalize(path: string): Promise { return invoke('plugin:path|normalize', { path }) } /** * Joins all given `path` segments together using the platform-specific separator as a delimiter, then normalizes the resulting path. * @example * ```typescript * import { join, appDataDir } from '@tauri-apps/api/path'; * const appDataDirPath = await appDataDir(); * const path = await join(appDataDirPath, 'users', 'tauri', 'avatar.png'); * ``` * * @since 1.0.0 */ async function join(...paths: string[]): Promise { return invoke('plugin:path|join', { paths }) } /** * Returns the parent directory of a given `path`. Trailing directory separators are ignored. * @example * ```typescript * import { dirname } from '@tauri-apps/api/path'; * const dir = await dirname('/path/to/somedir/'); * assert(dir === '/path/to'); * ``` * * @since 1.0.0 */ async function dirname(path: string): Promise { return invoke('plugin:path|dirname', { path }) } /** * Returns the extension of the `path`. * @example * ```typescript * import { extname } from '@tauri-apps/api/path'; * const ext = await extname('/path/to/file.html'); * assert(ext === 'html'); * ``` * * @since 1.0.0 */ async function extname(path: string): Promise { return invoke('plugin:path|extname', { path }) } /** * Returns the last portion of a `path`. Trailing directory separators are ignored. * @example * ```typescript * import { basename } from '@tauri-apps/api/path'; * const base = await basename('path/to/app.conf'); * assert(base === 'app.conf'); * ``` * @param ext An optional file extension to be removed from the returned path. * * @since 1.0.0 */ async function basename(path: string, ext?: string): Promise { return invoke('plugin:path|basename', { path, ext }) } /** * Returns whether the path is absolute or not. * @example * ```typescript * import { isAbsolute } from '@tauri-apps/api/path'; * assert(await isAbsolute('/home/tauri')); * ``` * * @since 1.0.0 */ async function isAbsolute(path: string): Promise { return invoke('plugin:path|is_absolute', { path }) } export { BaseDirectory, appConfigDir, appDataDir, appLocalDataDir, appCacheDir, appLogDir, audioDir, cacheDir, configDir, dataDir, desktopDir, documentDir, downloadDir, executableDir, fontDir, homeDir, localDataDir, pictureDir, publicDir, resourceDir, resolveResource, runtimeDir, templateDir, videoDir, sep, delimiter, resolve, normalize, join, dirname, extname, basename, isAbsolute, tempDir } ================================================ FILE: packages/api/src/tray.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import type { Menu, Submenu } from './menu' import { Channel, invoke, Resource } from './core' import { Image, transformImage } from './image' import { PhysicalPosition, PhysicalSize } from './dpi' export type MouseButtonState = 'Up' | 'Down' export type MouseButton = 'Left' | 'Right' | 'Middle' export type TrayIconEventType = | 'Click' | 'DoubleClick' | 'Enter' | 'Move' | 'Leave' export type TrayIconEventBase = { /** The tray icon event type */ type: T /** Id of the tray icon which triggered this event. */ id: string /** Physical position of the click the triggered this event. */ position: PhysicalPosition /** Position and size of the tray icon. */ rect: { position: PhysicalPosition size: PhysicalSize } } export type TrayIconClickEvent = { /** Mouse button that triggered this event. */ button: MouseButton /** Mouse button state when this event was triggered. */ buttonState: MouseButtonState } /** * Describes a tray icon event. * * #### Platform-specific: * * - **Linux**: Unsupported. The event is not emitted even though the icon is shown, * the icon will still show a context menu on right click. */ export type TrayIconEvent = | (TrayIconEventBase<'Click'> & TrayIconClickEvent) | (TrayIconEventBase<'DoubleClick'> & Omit) | TrayIconEventBase<'Enter'> | TrayIconEventBase<'Move'> | TrayIconEventBase<'Leave'> type RustTrayIconEvent = Omit & { rect: { position: { Physical: { x: number; y: number } } size: { Physical: { width: number; height: number } } } } /** * Tray icon types and utilities. * * This package is also accessible with `window.__TAURI__.tray` when [`app.withGlobalTauri`](https://v2.tauri.app/reference/config/#withglobaltauri) in `tauri.conf.json` is set to `true`. * @module */ /** {@link TrayIcon.new|`TrayIcon`} creation options */ export interface TrayIconOptions { /** The tray icon id. If undefined, a random one will be assigned */ id?: string /** The tray icon menu */ menu?: Menu | Submenu /** * The tray icon which could be icon bytes or path to the icon file. * * Note that you may need the `image-ico` or `image-png` Cargo features to use this API. * To enable it, change your Cargo.toml file: * ```toml * [dependencies] * tauri = { version = "...", features = ["...", "image-png"] } * ``` */ icon?: string | Uint8Array | ArrayBuffer | number[] | Image /** The tray icon tooltip */ tooltip?: string /** * The tray title * * #### Platform-specific * * - **Linux:** The title will not be shown unless there is an icon * as well. The title is useful for numerical and other frequently * updated information. In general, it shouldn't be shown unless a * user requests it as it can take up a significant amount of space * on the user's panel. This may not be shown in all visualizations. * - **Windows:** Unsupported. */ title?: string /** * The tray icon temp dir path. **Linux only**. * * On Linux, we need to write the icon to the disk and usually it will * be `$XDG_RUNTIME_DIR/tray-icon` or `$TEMP/tray-icon`. */ tempDirPath?: string /** * Use the icon as a [template](https://developer.apple.com/documentation/appkit/nsimage/1520017-template?language=objc). **macOS only**. */ iconAsTemplate?: boolean /** * Whether to show the tray menu on left click or not, default is `true`. * * #### Platform-specific: * * - **Linux**: Unsupported. * * @deprecated use {@linkcode TrayIconOptions.showMenuOnLeftClick} instead. */ menuOnLeftClick?: boolean /** * Whether to show the tray menu on left click or not, default is `true`. * * #### Platform-specific: * * - **Linux**: Unsupported. * * @since 2.2.0 */ showMenuOnLeftClick?: boolean /** A handler for an event on the tray icon. */ action?: (event: TrayIconEvent) => void } /** * Tray icon class and associated methods. This type constructor is private, * instead, you should use the static method {@linkcode TrayIcon.new}. * * #### Warning * * Unlike Rust, javascript does not have any way to run cleanup code * when an object is being removed by garbage collection, but this tray icon * will be cleaned up when the tauri app exists, however if you want to cleanup * this object early, you need to call {@linkcode TrayIcon.close}. * * @example * ```ts * import { TrayIcon } from '@tauri-apps/api/tray'; * const tray = await TrayIcon.new({ tooltip: 'awesome tray tooltip' }); * tray.set_tooltip('new tooltip'); * ``` */ export class TrayIcon extends Resource { /** The id associated with this tray icon. */ public id: string private constructor(rid: number, id: string) { super(rid) this.id = id } /** Gets a tray icon using the provided id. */ static async getById(id: string): Promise { return invoke('plugin:tray|get_by_id', { id }).then((rid) => rid ? new TrayIcon(rid, id) : null ) } /** * Removes a tray icon using the provided id from tauri's internal state. * * Note that this may cause the tray icon to disappear * if it wasn't cloned somewhere else or referenced by JS. */ static async removeById(id: string): Promise { return invoke('plugin:tray|remove_by_id', { id }) } /** * Creates a new {@linkcode TrayIcon} * * #### Platform-specific: * * - **Linux:** Sometimes the icon won't be visible unless a menu is set. * Setting an empty {@linkcode Menu} is enough. */ static async new(options?: TrayIconOptions): Promise { if (options?.menu) { // @ts-expect-error we only need the rid and kind options.menu = [options.menu.rid, options.menu.kind] } if (options?.icon) { options.icon = transformImage(options.icon) } const handler = new Channel() if (options?.action) { const action = options.action handler.onmessage = (e) => action(mapEvent(e)) delete options.action } return invoke<[number, string]>('plugin:tray|new', { options: options ?? {}, handler }).then(([rid, id]) => new TrayIcon(rid, id)) } /** * Sets a new tray icon. If `null` is provided, it will remove the icon. * * Note that you may need the `image-ico` or `image-png` Cargo features to use this API. * To enable it, change your Cargo.toml file: * ```toml * [dependencies] * tauri = { version = "...", features = ["...", "image-png"] } * ``` */ async setIcon( icon: string | Image | Uint8Array | ArrayBuffer | number[] | null ): Promise { let trayIcon = null if (icon) { trayIcon = transformImage(icon) } return invoke('plugin:tray|set_icon', { rid: this.rid, icon: trayIcon }) } /** * Sets a new tray menu. * * #### Platform-specific: * * - **Linux**: once a menu is set it cannot be removed so `null` has no effect */ async setMenu(menu: Menu | Submenu | null): Promise { if (menu) { // @ts-expect-error we only need the rid and kind menu = [menu.rid, menu.kind] } return invoke('plugin:tray|set_menu', { rid: this.rid, menu }) } /** * Sets the tooltip for this tray icon. * * #### Platform-specific: * * - **Linux:** Unsupported */ async setTooltip(tooltip: string | null): Promise { return invoke('plugin:tray|set_tooltip', { rid: this.rid, tooltip }) } /** * Sets the tooltip for this tray icon. * * #### Platform-specific: * * - **Linux:** The title will not be shown unless there is an icon * as well. The title is useful for numerical and other frequently * updated information. In general, it shouldn't be shown unless a * user requests it as it can take up a significant amount of space * on the user's panel. This may not be shown in all visualizations. * - **Windows:** Unsupported */ async setTitle(title: string | null): Promise { return invoke('plugin:tray|set_title', { rid: this.rid, title }) } /** Show or hide this tray icon. */ async setVisible(visible: boolean): Promise { return invoke('plugin:tray|set_visible', { rid: this.rid, visible }) } /** * Sets the tray icon temp dir path. **Linux only**. * * On Linux, we need to write the icon to the disk and usually it will * be `$XDG_RUNTIME_DIR/tray-icon` or `$TEMP/tray-icon`. */ async setTempDirPath(path: string | null): Promise { return invoke('plugin:tray|set_temp_dir_path', { rid: this.rid, path }) } /** Sets the current icon as a [template](https://developer.apple.com/documentation/appkit/nsimage/1520017-template?language=objc). **macOS only** */ async setIconAsTemplate(asTemplate: boolean): Promise { return invoke('plugin:tray|set_icon_as_template', { rid: this.rid, asTemplate }) } /** * Disable or enable showing the tray menu on left click. * * #### Platform-specific: * * - **Linux**: Unsupported. * * @deprecated use {@linkcode TrayIcon.setShowMenuOnLeftClick} instead. */ async setMenuOnLeftClick(onLeft: boolean): Promise { return invoke('plugin:tray|set_show_menu_on_left_click', { rid: this.rid, onLeft }) } /** * Disable or enable showing the tray menu on left click. * * #### Platform-specific: * * - **Linux**: Unsupported. * * @since 2.2.0 */ async setShowMenuOnLeftClick(onLeft: boolean): Promise { return invoke('plugin:tray|set_show_menu_on_left_click', { rid: this.rid, onLeft }) } } function mapEvent(e: RustTrayIconEvent): TrayIconEvent { const out = e as unknown as TrayIconEvent out.position = new PhysicalPosition(e.position) out.rect.position = new PhysicalPosition(e.rect.position) out.rect.size = new PhysicalSize(e.rect.size) return out } ================================================ FILE: packages/api/src/webview.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT /** * Provides APIs to create webviews, communicate with other webviews and manipulate the current webview. * * #### Webview events * * Events can be listened to using {@link Webview.listen}: * ```typescript * import { getCurrentWebview } from "@tauri-apps/api/webview"; * getCurrentWebview().listen("my-webview-event", ({ event, payload }) => { }); * ``` * * @module */ import { PhysicalPosition, PhysicalSize } from './dpi' import type { LogicalPosition, LogicalSize } from './dpi' import { Position, Size } from './dpi' import type { EventName, EventCallback, UnlistenFn } from './event' import { TauriEvent, // imported for documentation purposes type EventTarget, emit, emitTo, listen, once } from './event' import { invoke } from './core' import { BackgroundThrottlingPolicy, ScrollBarStyle, Color, Window, getCurrentWindow } from './window' import { WebviewWindow } from './webviewWindow' /** The drag and drop event types. */ type DragDropEvent = | { type: 'enter'; paths: string[]; position: PhysicalPosition } | { type: 'over'; position: PhysicalPosition } | { type: 'drop'; paths: string[]; position: PhysicalPosition } | { type: 'leave' } /** * Get an instance of `Webview` for the current webview. * * @since 2.0.0 */ function getCurrentWebview(): Webview { return new Webview( getCurrentWindow(), window.__TAURI_INTERNALS__.metadata.currentWebview.label, { // @ts-expect-error `skip` is not defined in the public API but it is handled by the constructor skip: true } ) } /** * Gets a list of instances of `Webview` for all available webviews. * * @since 2.0.0 */ async function getAllWebviews(): Promise { return invoke>( 'plugin:webview|get_all_webviews' ).then((webviews) => webviews.map( (w) => new Webview( new Window(w.windowLabel, { // @ts-expect-error `skip` is not defined in the public API but it is handled by the constructor skip: true }), w.label, { // @ts-expect-error `skip` is not defined in the public API but it is handled by the constructor skip: true } ) ) ) } /** @ignore */ // events that are emitted right here instead of by the created webview const localTauriEvents = ['tauri://created', 'tauri://error'] /** @ignore */ export type WebviewLabel = string /** * Create new webview or get a handle to an existing one. * * Webviews are identified by a *label* a unique identifier that can be used to reference it later. * It may only contain alphanumeric characters `a-zA-Z` plus the following special characters `-`, `/`, `:` and `_`. * * @example * ```typescript * import { Window } from "@tauri-apps/api/window" * import { Webview } from "@tauri-apps/api/webview" * * const appWindow = new Window('uniqueLabel'); * * appWindow.once('tauri://created', async function () { * // `new Webview` Should be called after the window is successfully created, * // or webview may not be attached to the window since window is not created yet. * * // loading embedded asset: * const webview = new Webview(appWindow, 'theUniqueLabel', { * url: 'path/to/page.html', * * // create a webview with specific logical position and size * x: 0, * y: 0, * width: 800, * height: 600, * }); * // alternatively, load a remote URL: * const webview = new Webview(appWindow, 'theUniqueLabel', { * url: 'https://github.com/tauri-apps/tauri', * * // create a webview with specific logical position and size * x: 0, * y: 0, * width: 800, * height: 600, * }); * * webview.once('tauri://created', function () { * // webview successfully created * }); * webview.once('tauri://error', function (e) { * // an error happened creating the webview * }); * * * // emit an event to the backend * await webview.emit("some-event", "data"); * // listen to an event from the backend * const unlisten = await webview.listen("event-name", e => { }); * unlisten(); * }); * ``` * * @since 2.0.0 */ class Webview { /** The webview label. It is a unique identifier for the webview, can be used to reference it later. */ label: WebviewLabel /** The window hosting this webview. */ window: Window /** Local event listeners. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any listeners: Record>> /** * Creates a new Webview. * @example * ```typescript * import { Window } from '@tauri-apps/api/window' * import { Webview } from '@tauri-apps/api/webview' * const appWindow = new Window('my-label') * * appWindow.once('tauri://created', async function() { * const webview = new Webview(appWindow, 'my-label', { * url: 'https://github.com/tauri-apps/tauri', * * // create a webview with specific logical position and size * x: 0, * y: 0, * width: 800, * height: 600, * }); * * webview.once('tauri://created', function () { * // webview successfully created * }); * webview.once('tauri://error', function (e) { * // an error happened creating the webview * }); * }); * ``` * * @param window the window to add this webview to. * @param label The unique webview label. Must be alphanumeric: `a-zA-Z-/:_`. * @returns The {@link Webview} instance to communicate with the webview. */ constructor(window: Window, label: WebviewLabel, options: WebviewOptions) { this.window = window this.label = label // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment this.listeners = Object.create(null) // @ts-expect-error `skip` is not a public API so it is not defined in WebviewOptions if (!options?.skip) { invoke('plugin:webview|create_webview', { windowLabel: window.label, options: { ...options, label } }) .then(async () => this.emit('tauri://created')) .catch(async (e: string) => this.emit('tauri://error', e)) } } /** * Gets the Webview for the webview associated with the given label. * @example * ```typescript * import { Webview } from '@tauri-apps/api/webview'; * const mainWebview = Webview.getByLabel('main'); * ``` * * @param label The webview label. * @returns The Webview instance to communicate with the webview or null if the webview doesn't exist. */ static async getByLabel(label: string): Promise { return (await getAllWebviews()).find((w) => w.label === label) ?? null } /** * Get an instance of `Webview` for the current webview. */ static getCurrent(): Webview { return getCurrentWebview() } /** * Gets a list of instances of `Webview` for all available webviews. */ static async getAll(): Promise { return getAllWebviews() } /** * Listen to an emitted event on this webview. * * @example * ```typescript * import { getCurrentWebview } from '@tauri-apps/api/webview'; * const unlisten = await getCurrentWebview().listen('state-changed', (event) => { * console.log(`Got error: ${payload}`); * }); * * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted * unlisten(); * ``` * * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`. * @param handler Event handler. * @returns A promise resolving to a function to unlisten to the event. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted. */ async listen( event: EventName, handler: EventCallback ): Promise { if (this._handleTauriEvent(event, handler)) { return () => { // eslint-disable-next-line security/detect-object-injection const listeners = this.listeners[event] listeners.splice(listeners.indexOf(handler), 1) } } return listen(event, handler, { target: { kind: 'Webview', label: this.label } }) } /** * Listen to an emitted event on this webview only once. * * @example * ```typescript * import { getCurrentWebview } from '@tauri-apps/api/webview'; * const unlisten = await getCurrent().once('initialized', (event) => { * console.log(`Webview initialized!`); * }); * * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted * unlisten(); * ``` * * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`. * @param handler Event handler. * @returns A promise resolving to a function to unlisten to the event. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted. */ async once( event: EventName, handler: EventCallback ): Promise { if (this._handleTauriEvent(event, handler)) { return () => { // eslint-disable-next-line security/detect-object-injection const listeners = this.listeners[event] listeners.splice(listeners.indexOf(handler), 1) } } return once(event, handler, { target: { kind: 'Webview', label: this.label } }) } /** * Emits an event to all {@link EventTarget|targets}. * * @example * ```typescript * import { getCurrentWebview } from '@tauri-apps/api/webview'; * await getCurrentWebview().emit('webview-loaded', { loggedIn: true, token: 'authToken' }); * ``` * * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`. * @param payload Event payload. */ async emit(event: string, payload?: T): Promise { if (localTauriEvents.includes(event)) { // eslint-disable-next-line for (const handler of this.listeners[event] || []) { handler({ event, id: -1, payload }) } return } return emit(event, payload) } /** * Emits an event to all {@link EventTarget|targets} matching the given target. * * @example * ```typescript * import { getCurrentWebview } from '@tauri-apps/api/webview'; * await getCurrentWebview().emitTo('main', 'webview-loaded', { loggedIn: true, token: 'authToken' }); * ``` * * @param target Label of the target Window/Webview/WebviewWindow or raw {@link EventTarget} object. * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`. * @param payload Event payload. */ async emitTo( target: string | EventTarget, event: string, payload?: T ): Promise { if (localTauriEvents.includes(event)) { // eslint-disable-next-line for (const handler of this.listeners[event] || []) { handler({ event, id: -1, payload }) } return } return emitTo(target, event, payload) } /** @ignore */ _handleTauriEvent(event: string, handler: EventCallback): boolean { if (localTauriEvents.includes(event)) { if (!(event in this.listeners)) { // eslint-disable-next-line security/detect-object-injection this.listeners[event] = [handler] } else { // eslint-disable-next-line security/detect-object-injection this.listeners[event].push(handler) } return true } return false } // Getters /** * The position of the top-left hand corner of the webview's client area relative to the top-left hand corner of the desktop. * @example * ```typescript * import { getCurrentWebview } from '@tauri-apps/api/webview'; * const position = await getCurrentWebview().position(); * ``` * * @returns The webview's position. */ async position(): Promise { return invoke<{ x: number; y: number }>('plugin:webview|webview_position', { label: this.label }).then((p) => new PhysicalPosition(p)) } /** * The physical size of the webview's client area. * The client area is the content of the webview, excluding the title bar and borders. * @example * ```typescript * import { getCurrentWebview } from '@tauri-apps/api/webview'; * const size = await getCurrentWebview().size(); * ``` * * @returns The webview's size. */ async size(): Promise { return invoke<{ width: number; height: number }>( 'plugin:webview|webview_size', { label: this.label } ).then((s) => new PhysicalSize(s)) } // Setters /** * Closes the webview. * @example * ```typescript * import { getCurrentWebview } from '@tauri-apps/api/webview'; * await getCurrentWebview().close(); * ``` * * @returns A promise indicating the success or failure of the operation. */ async close(): Promise { return invoke('plugin:webview|webview_close', { label: this.label }) } /** * Resizes the webview. * @example * ```typescript * import { getCurrent, LogicalSize } from '@tauri-apps/api/webview'; * await getCurrentWebview().setSize(new LogicalSize(600, 500)); * ``` * * @param size The logical or physical size. * @returns A promise indicating the success or failure of the operation. */ async setSize(size: LogicalSize | PhysicalSize | Size): Promise { return invoke('plugin:webview|set_webview_size', { label: this.label, value: size instanceof Size ? size : new Size(size) }) } /** * Sets the webview position. * @example * ```typescript * import { getCurrent, LogicalPosition } from '@tauri-apps/api/webview'; * await getCurrentWebview().setPosition(new LogicalPosition(600, 500)); * ``` * * @param position The new position, in logical or physical pixels. * @returns A promise indicating the success or failure of the operation. */ async setPosition( position: LogicalPosition | PhysicalPosition | Position ): Promise { return invoke('plugin:webview|set_webview_position', { label: this.label, value: position instanceof Position ? position : new Position(position) }) } /** * Bring the webview to front and focus. * @example * ```typescript * import { getCurrentWebview } from '@tauri-apps/api/webview'; * await getCurrentWebview().setFocus(); * ``` * * @returns A promise indicating the success or failure of the operation. */ async setFocus(): Promise { return invoke('plugin:webview|set_webview_focus', { label: this.label }) } /** * Sets whether the webview should automatically grow and shrink its size and position when the parent window resizes. * @example * ```typescript * import { getCurrentWebview } from '@tauri-apps/api/webview'; * await getCurrentWebview().setAutoResize(true); * ``` * * @returns A promise indicating the success or failure of the operation. */ async setAutoResize(autoResize: boolean): Promise { return invoke('plugin:webview|set_webview_auto_resize', { label: this.label, value: autoResize }) } /** * Hide the webview. * @example * ```typescript * import { getCurrentWebview } from '@tauri-apps/api/webview'; * await getCurrentWebview().hide(); * ``` * * @returns A promise indicating the success or failure of the operation. */ async hide(): Promise { return invoke('plugin:webview|webview_hide', { label: this.label }) } /** * Show the webview. * @example * ```typescript * import { getCurrentWebview } from '@tauri-apps/api/webview'; * await getCurrentWebview().show(); * ``` * * @returns A promise indicating the success or failure of the operation. */ async show(): Promise { return invoke('plugin:webview|webview_show', { label: this.label }) } /** * Set webview zoom level. * @example * ```typescript * import { getCurrentWebview } from '@tauri-apps/api/webview'; * await getCurrentWebview().setZoom(1.5); * ``` * * @returns A promise indicating the success or failure of the operation. */ async setZoom(scaleFactor: number): Promise { return invoke('plugin:webview|set_webview_zoom', { label: this.label, value: scaleFactor }) } /** * Moves this webview to the given label. * @example * ```typescript * import { getCurrentWebview } from '@tauri-apps/api/webview'; * await getCurrentWebview().reparent('other-window'); * ``` * * @returns A promise indicating the success or failure of the operation. */ async reparent(window: Window | WebviewWindow | string): Promise { return invoke('plugin:webview|reparent', { label: this.label, window: typeof window === 'string' ? window : window.label }) } /** * Clears all browsing data for this webview. * @example * ```typescript * import { getCurrentWebview } from '@tauri-apps/api/webview'; * await getCurrentWebview().clearAllBrowsingData(); * ``` * * @returns A promise indicating the success or failure of the operation. */ async clearAllBrowsingData(): Promise { return invoke('plugin:webview|clear_all_browsing_data') } /** * Specify the webview background color. * * #### Platfrom-specific: * * - **macOS / iOS**: Not implemented. * - **Windows**: * - On Windows 7, transparency is not supported and the alpha value will be ignored. * - On Windows higher than 7: translucent colors are not supported so any alpha value other than `0` will be replaced by `255` * * @returns A promise indicating the success or failure of the operation. * * @since 2.1.0 */ async setBackgroundColor(color: Color | null): Promise { return invoke('plugin:webview|set_webview_background_color', { color }) } // Listeners /** * Listen to a file drop event. * The listener is triggered when the user hovers the selected files on the webview, * drops the files or cancels the operation. * * @example * ```typescript * import { getCurrentWebview } from "@tauri-apps/api/webview"; * const unlisten = await getCurrentWebview().onDragDropEvent((event) => { * if (event.payload.type === 'over') { * console.log('User hovering', event.payload.position); * } else if (event.payload.type === 'drop') { * console.log('User dropped', event.payload.paths); * } else { * console.log('File drop cancelled'); * } * }); * * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted * unlisten(); * ``` * * When the debugger panel is open, the drop position of this event may be inaccurate due to a known limitation. * To retrieve the correct drop position, please detach the debugger. * * @returns A promise resolving to a function to unlisten to the event. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted. */ async onDragDropEvent( handler: EventCallback ): Promise { type DragPayload = { paths: string[]; position: PhysicalPosition } const unlistenDragEnter = await this.listen( TauriEvent.DRAG_ENTER, (event) => { handler({ ...event, payload: { type: 'enter', paths: event.payload.paths, position: new PhysicalPosition(event.payload.position) } }) } ) const unlistenDragOver = await this.listen( TauriEvent.DRAG_OVER, (event) => { handler({ ...event, payload: { type: 'over', position: new PhysicalPosition(event.payload.position) } }) } ) const unlistenDragDrop = await this.listen( TauriEvent.DRAG_DROP, (event) => { handler({ ...event, payload: { type: 'drop', paths: event.payload.paths, position: new PhysicalPosition(event.payload.position) } }) } ) const unlistenDragLeave = await this.listen( TauriEvent.DRAG_LEAVE, (event) => { handler({ ...event, payload: { type: 'leave' } }) } ) return () => { unlistenDragEnter() unlistenDragDrop() unlistenDragOver() unlistenDragLeave() } } } /** * Configuration for the webview to create. * * @since 2.0.0 */ interface WebviewOptions { /** * Remote URL or local file path to open. * * - URL such as `https://github.com/tauri-apps` is opened directly on a Tauri webview. * - data: URL such as `data:text/html,...` is only supported with the `webview-data-url` Cargo feature for the `tauri` dependency. * - local file path or route such as `/path/to/page.html` or `/users` is appended to the application URL (the devServer URL on development, or `tauri://localhost/` and `https://tauri.localhost/` on production). */ url?: string /** The initial vertical position in logical pixels. */ x: number /** The initial horizontal position in logical pixels. */ y: number /** The initial width in logical pixels. */ width: number /** The initial height in logical pixels. */ height: number /** * Whether the webview is transparent or not. * Note that on `macOS` this requires the `macos-private-api` feature flag, enabled under `tauri.conf.json > app > macOSPrivateApi`. * WARNING: Using private APIs on `macOS` prevents your application from being accepted to the `App Store`. */ transparent?: boolean /** * Whether the webview should have focus or not * * @since 2.1.0 */ focus?: boolean /** * Whether the drag and drop is enabled or not on the webview. By default it is enabled. * * Disabling it is required to use HTML5 drag and drop on the frontend on Windows. */ dragDropEnabled?: boolean /** * Whether clicking an inactive webview also clicks through to the webview on macOS. */ acceptFirstMouse?: boolean /** * The user agent for the webview. */ userAgent?: string /** * Whether or not the webview should be launched in incognito mode. * * #### Platform-specific * * - **Android:** Unsupported. */ incognito?: boolean /** * The proxy URL for the WebView for all network requests. * * Must be either a `http://` or a `socks5://` URL. * * #### Platform-specific * * - **macOS**: Requires the `macos-proxy` feature flag and only compiles for macOS 14+. * */ proxyUrl?: string /** * Whether page zooming by hotkeys is enabled * * #### Platform-specific: * * - **Windows**: Controls WebView2's [`IsZoomControlEnabled`](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/microsoft_web_webview2_core/corewebview2settings?view=webview2-winrt-1.0.2420.47#iszoomcontrolenabled) setting. * - **MacOS / Linux**: Injects a polyfill that zooms in and out with `ctrl/command` + `-/=`, * 20% in each step, ranging from 20% to 1000%. Requires `webview:allow-set-webview-zoom` permission * * - **Android / iOS**: Unsupported. */ zoomHotkeysEnabled?: boolean /** * Sets whether the custom protocols should use `https://.localhost` instead of the default `http://.localhost` on Windows and Android. Defaults to `false`. * * #### Note * * Using a `https` scheme will NOT allow mixed content when trying to fetch `http` endpoints and therefore will not match the behavior of the `://localhost` protocols used on macOS and Linux. * * #### Warning * * Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access them. * * @since 2.1.0 */ useHttpsScheme?: boolean /** * Whether web inspector, which is usually called browser devtools, is enabled or not. Enabled by default. * * This API works in **debug** builds, but requires `devtools` feature flag to enable it in **release** builds. * * #### Platform-specific * * - macOS: This will call private functions on **macOS**. * - Android: Open `chrome://inspect/#devices` in Chrome to get the devtools window. Wry's `WebView` devtools API isn't supported on Android. * - iOS: Open Safari > Develop > [Your Device Name] > [Your WebView] to get the devtools window. * * @since 2.1.0 */ devtools?: boolean /** * Set the window and webview background color. * * #### Platform-specific: * * - **macOS / iOS**: Not implemented. * - **Windows**: * - On Windows 7, alpha channel is ignored. * - On Windows 8 and newer, if alpha channel is not `0`, it will be ignored. * * @since 2.1.0 */ backgroundColor?: Color /** Change the default background throttling behaviour. * * By default, browsers use a suspend policy that will throttle timers and even unload * the whole tab (view) to free resources after roughly 5 minutes when a view became * minimized or hidden. This will pause all tasks until the documents visibility state * changes back from hidden to visible by bringing the view back to the foreground. * * ## Platform-specific * * - **Linux / Windows / Android**: Unsupported. Workarounds like a pending WebLock transaction might suffice. * - **iOS**: Supported since version 17.0+. * - **macOS**: Supported since version 14.0+. * * see https://github.com/tauri-apps/tauri/issues/5250#issuecomment-2569380578 * * @since 2.3.0 */ backgroundThrottling?: BackgroundThrottlingPolicy /** * Whether we should disable JavaScript code execution on the webview or not. */ javascriptDisabled?: boolean /** * on macOS and iOS there is a link preview on long pressing links, this is enabled by default. * see https://docs.rs/objc2-web-kit/latest/objc2_web_kit/struct.WKWebView.html#method.allowsLinkPreview */ allowLinkPreview?: boolean /** * Allows disabling the input accessory view on iOS. * * The accessory view is the view that appears above the keyboard when a text input element is focused. * It usually displays a view with "Done", "Next" buttons. */ disableInputAccessoryView?: boolean /** * Set a custom path for the webview's data directory (localStorage, cache, etc.) **relative to [`appDataDir()`]/${label}**. * For security reasons, paths outside of that location can only be configured on the Rust side. * * #### Platform-specific: * * - **Windows**: WebViews with different values for settings like `additionalBrowserArgs`, `browserExtensionsEnabled` or `scrollBarStyle` must have different data directories. * - **macOS / iOS**: Unsupported, use `dataStoreIdentifier` instead. * - **Android**: Unsupported. * * @since 2.9.0 */ dataDirectory?: string /** * Initialize the WebView with a custom data store identifier. This can be seen as a replacement for `dataDirectory` which is unavailable in WKWebView. * See https://developer.apple.com/documentation/webkit/wkwebsitedatastore/init(foridentifier:)?language=objc * * The array must contain 16 u8 numbers. * * #### Platform-specific: * * - **macOS / iOS**: Available on macOS >= 14 and iOS >= 17 * - **Windows / Linux / Android**: Unsupported. * * @since 2.9.0 */ dataStoreIdentifier?: number[] /** * Specifies the native scrollbar style to use with the webview. * CSS styles that modify the scrollbar are applied on top of the native appearance configured here. * * Defaults to `default`, which is the browser default. * * ## Platform-specific * * - **Windows**: * - `fluentOverlay` requires WebView2 Runtime version 125.0.2535.41 or higher, and does nothing * on older versions. * - This option must be given the same value for all webviews. * - **Linux / Android / iOS / macOS**: Unsupported. Only supports `Default` and performs no operation. */ scrollBarStyle?: ScrollBarStyle } export { Webview, getCurrentWebview, getAllWebviews } export type { DragDropEvent, WebviewOptions, Color } ================================================ FILE: packages/api/src/webviewWindow.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import { getCurrentWebview, Webview, WebviewLabel, WebviewOptions } from './webview' import type { WindowOptions } from './window' import { Window } from './window' import { listen, once } from './event' import type { EventName, EventCallback, UnlistenFn } from './event' import { invoke } from './core' import type { Color, DragDropEvent } from './webview' /** * Get an instance of `Webview` for the current webview window. * * @since 2.0.0 */ function getCurrentWebviewWindow(): WebviewWindow { const webview = getCurrentWebview() // @ts-expect-error `skip` is not defined in the public API but it is handled by the constructor return new WebviewWindow(webview.label, { skip: true }) } /** * Gets a list of instances of `Webview` for all available webview windows. * * @since 2.0.0 */ async function getAllWebviewWindows(): Promise { return invoke('plugin:window|get_all_windows').then((windows) => windows.map( (w) => new WebviewWindow(w, { // @ts-expect-error `skip` is not defined in the public API but it is handled by the constructor skip: true }) ) ) } // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging interface WebviewWindow extends Webview, Window {} // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging class WebviewWindow { label: string /** Local event listeners. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any listeners: Record>> /** * Creates a new {@link Window} hosting a {@link Webview}. * @example * ```typescript * import { WebviewWindow } from '@tauri-apps/api/webviewWindow' * const webview = new WebviewWindow('my-label', { * url: 'https://github.com/tauri-apps/tauri' * }); * webview.once('tauri://created', function () { * // webview successfully created * }); * webview.once('tauri://error', function (e) { * // an error happened creating the webview * }); * ``` * * @param label The unique webview label. Must be alphanumeric: `a-zA-Z-/:_`. * @returns The {@link WebviewWindow} instance to communicate with the window and webview. */ constructor( label: WebviewLabel, options: Omit & WindowOptions = {} ) { this.label = label // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment this.listeners = Object.create(null) // @ts-expect-error `skip` is not a public API so it is not defined in WebviewOptions if (!options?.skip) { invoke('plugin:webview|create_webview_window', { options: { ...options, parent: typeof options.parent === 'string' ? options.parent : options.parent?.label, label } }) .then(async () => this.emit('tauri://created')) .catch(async (e: string) => this.emit('tauri://error', e)) } } /** * Gets the Webview for the webview associated with the given label. * @example * ```typescript * import { WebviewWindow } from '@tauri-apps/api/webviewWindow'; * const mainWebview = WebviewWindow.getByLabel('main'); * ``` * * @param label The webview label. * @returns The Webview instance to communicate with the webview or null if the webview doesn't exist. */ static async getByLabel(label: string): Promise { const webview = (await getAllWebviewWindows()).find((w) => w.label === label) ?? null if (webview) { // @ts-expect-error `skip` is not defined in the public API but it is handled by the constructor return new WebviewWindow(webview.label, { skip: true }) } return null } /** * Get an instance of `Webview` for the current webview. */ static getCurrent(): WebviewWindow { return getCurrentWebviewWindow() } /** * Gets a list of instances of `Webview` for all available webviews. */ static async getAll(): Promise { return getAllWebviewWindows() } /** * Listen to an emitted event on this webview window. * * @example * ```typescript * import { WebviewWindow } from '@tauri-apps/api/webviewWindow'; * const unlisten = await WebviewWindow.getCurrent().listen('state-changed', (event) => { * console.log(`Got error: ${payload}`); * }); * * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted * unlisten(); * ``` * * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`. * @param handler Event handler. * @returns A promise resolving to a function to unlisten to the event. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted. */ async listen( event: EventName, handler: EventCallback ): Promise { if (this._handleTauriEvent(event, handler)) { return () => { // eslint-disable-next-line security/detect-object-injection const listeners = this.listeners[event] listeners.splice(listeners.indexOf(handler), 1) } } return listen(event, handler, { target: { kind: 'WebviewWindow', label: this.label } }) } /** * Listen to an emitted event on this webview window only once. * * @example * ```typescript * import { WebviewWindow } from '@tauri-apps/api/webviewWindow'; * const unlisten = await WebviewWindow.getCurrent().once('initialized', (event) => { * console.log(`Webview initialized!`); * }); * * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted * unlisten(); * ``` * * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`. * @param handler Event handler. * @returns A promise resolving to a function to unlisten to the event. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted. */ async once( event: EventName, handler: EventCallback ): Promise { if (this._handleTauriEvent(event, handler)) { return () => { // eslint-disable-next-line security/detect-object-injection const listeners = this.listeners[event] listeners.splice(listeners.indexOf(handler), 1) } } return once(event, handler, { target: { kind: 'WebviewWindow', label: this.label } }) } /** * Set the window and webview background color. * * #### Platform-specific: * * - **Android / iOS:** Unsupported for the window layer. * - **macOS / iOS**: Not implemented for the webview layer. * - **Windows**: * - alpha channel is ignored for the window layer. * - On Windows 7, alpha channel is ignored for the webview layer. * - On Windows 8 and newer, if alpha channel is not `0`, it will be ignored. * * @returns A promise indicating the success or failure of the operation. * * @since 2.1.0 */ async setBackgroundColor(color: Color): Promise { return invoke('plugin:window|set_background_color', { color }).then(() => { return invoke('plugin:webview|set_webview_background_color', { color }) }) } } // Order matters, we use window APIs by default applyMixins(WebviewWindow, [Window, Webview]) /** Extends a base class by other specified classes, without overriding existing properties */ function applyMixins( baseClass: { prototype: unknown }, extendedClasses: unknown ): void { ;(Array.isArray(extendedClasses) ? extendedClasses : [extendedClasses] ).forEach((extendedClass: { prototype: unknown }) => { Object.getOwnPropertyNames(extendedClass.prototype).forEach((name) => { if ( typeof baseClass.prototype === 'object' && baseClass.prototype && name in baseClass.prototype ) return Object.defineProperty( baseClass.prototype, name, // eslint-disable-next-line Object.getOwnPropertyDescriptor(extendedClass.prototype, name) ?? Object.create(null) ) }) }) } export { WebviewWindow, getCurrentWebviewWindow, getAllWebviewWindows } export type { DragDropEvent, Color } ================================================ FILE: packages/api/src/window.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT /** * Provides APIs to create windows, communicate with other windows and manipulate the current window. * * #### Window events * * Events can be listened to using {@link Window.listen}: * ```typescript * import { getCurrentWindow } from "@tauri-apps/api/window"; * getCurrentWindow().listen("my-window-event", ({ event, payload }) => { }); * ``` * * @module */ import { LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size } from './dpi' import type { Event, EventName, EventCallback, UnlistenFn } from './event' import { TauriEvent, // imported for documentation purposes type EventTarget, emit, emitTo, listen, once } from './event' import { invoke } from './core' import { WebviewWindow } from './webviewWindow' import type { DragDropEvent } from './webview' import { Image, transformImage } from './image' /** * Allows you to retrieve information about a given monitor. * * @since 1.0.0 */ export interface Monitor { /** Human-readable name of the monitor */ name: string | null /** The monitor's resolution. */ size: PhysicalSize /** the Top-left corner position of the monitor relative to the larger full screen area. */ position: PhysicalPosition /** The monitor's work area. */ workArea: { position: PhysicalPosition size: PhysicalSize } /** The scale factor that can be used to map physical pixels to logical pixels. */ scaleFactor: number } type Theme = 'light' | 'dark' type TitleBarStyle = 'visible' | 'transparent' | 'overlay' type ResizeDirection = | 'East' | 'North' | 'NorthEast' | 'NorthWest' | 'South' | 'SouthEast' | 'SouthWest' | 'West' /** * The payload for the `scaleChange` event. * * @since 1.0.2 */ interface ScaleFactorChanged { /** The new window scale factor. */ scaleFactor: number /** The new window size */ size: PhysicalSize } /** * Attention type to request on a window. * * @since 1.0.0 */ enum UserAttentionType { /** * #### Platform-specific * - **macOS:** Bounces the dock icon until the application is in focus. * - **Windows:** Flashes both the window and the taskbar button until the application is in focus. */ Critical = 1, /** * #### Platform-specific * - **macOS:** Bounces the dock icon once. * - **Windows:** Flashes the taskbar button until the application is in focus. */ Informational } class CloseRequestedEvent { /** Event name */ event: EventName /** Event identifier used to unlisten */ id: number private _preventDefault = false constructor(event: Event) { this.event = event.event this.id = event.id } preventDefault(): void { this._preventDefault = true } isPreventDefault(): boolean { return this._preventDefault } } export type CursorIcon = | 'default' | 'crosshair' | 'hand' | 'arrow' | 'move' | 'text' | 'wait' | 'help' | 'progress' // something cannot be done | 'notAllowed' | 'contextMenu' | 'cell' | 'verticalText' | 'alias' | 'copy' | 'noDrop' // something can be grabbed | 'grab' /// something is grabbed | 'grabbing' | 'allScroll' | 'zoomIn' | 'zoomOut' // edge is to be moved | 'eResize' | 'nResize' | 'neResize' | 'nwResize' | 'sResize' | 'seResize' | 'swResize' | 'wResize' | 'ewResize' | 'nsResize' | 'neswResize' | 'nwseResize' | 'colResize' | 'rowResize' export enum ProgressBarStatus { /** * Hide progress bar. */ None = 'none', /** * Normal state. */ Normal = 'normal', /** * Indeterminate state. **Treated as Normal on Linux and macOS** */ Indeterminate = 'indeterminate', /** * Paused state. **Treated as Normal on Linux** */ Paused = 'paused', /** * Error state. **Treated as Normal on linux** */ Error = 'error' } export interface WindowSizeConstraints { minWidth?: number minHeight?: number maxWidth?: number maxHeight?: number } export interface ProgressBarState { /** * The progress bar status. */ status?: ProgressBarStatus /** * The progress bar progress. This can be a value ranging from `0` to `100` */ progress?: number } /** * Get an instance of `Window` for the current window. * * @since 1.0.0 */ function getCurrentWindow(): Window { return new Window(window.__TAURI_INTERNALS__.metadata.currentWindow.label, { // @ts-expect-error `skip` is not defined in the public API but it is handled by the constructor skip: true }) } /** * Gets a list of instances of `Window` for all available windows. * * @since 1.0.0 */ async function getAllWindows(): Promise { return invoke('plugin:window|get_all_windows').then((windows) => windows.map( (w) => new Window(w, { // @ts-expect-error `skip` is not defined in the public API but it is handled by the constructor skip: true }) ) ) } /** @ignore */ // events that are emitted right here instead of by the created window const localTauriEvents = ['tauri://created', 'tauri://error'] /** @ignore */ export type WindowLabel = string /** * Create new window or get a handle to an existing one. * * Windows are identified by a *label* a unique identifier that can be used to reference it later. * It may only contain alphanumeric characters `a-zA-Z` plus the following special characters `-`, `/`, `:` and `_`. * * @example * ```typescript * import { Window } from "@tauri-apps/api/window" * * const appWindow = new Window('theUniqueLabel'); * * appWindow.once('tauri://created', function () { * // window successfully created * }); * appWindow.once('tauri://error', function (e) { * // an error happened creating the window * }); * * // emit an event to the backend * await appWindow.emit("some-event", "data"); * // listen to an event from the backend * const unlisten = await appWindow.listen("event-name", e => {}); * unlisten(); * ``` * * @since 2.0.0 */ class Window { /** The window label. It is a unique identifier for the window, can be used to reference it later. */ label: WindowLabel /** Local event listeners. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any listeners: Record>> /** * Creates a new Window. * @example * ```typescript * import { Window } from '@tauri-apps/api/window'; * const appWindow = new Window('my-label'); * appWindow.once('tauri://created', function () { * // window successfully created * }); * appWindow.once('tauri://error', function (e) { * // an error happened creating the window * }); * ``` * * @param label The unique window label. Must be alphanumeric: `a-zA-Z-/:_`. * @returns The {@link Window} instance to communicate with the window. */ constructor(label: WindowLabel, options: WindowOptions = {}) { this.label = label // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment this.listeners = Object.create(null) // @ts-expect-error `skip` is not a public API so it is not defined in WindowOptions if (!options?.skip) { invoke('plugin:window|create', { options: { ...options, parent: typeof options.parent === 'string' ? options.parent : options.parent?.label, label } }) .then(async () => this.emit('tauri://created')) .catch(async (e: string) => this.emit('tauri://error', e)) } } /** * Gets the Window associated with the given label. * @example * ```typescript * import { Window } from '@tauri-apps/api/window'; * const mainWindow = Window.getByLabel('main'); * ``` * * @param label The window label. * @returns The Window instance to communicate with the window or null if the window doesn't exist. */ static async getByLabel(label: string): Promise { return (await getAllWindows()).find((w) => w.label === label) ?? null } /** * Get an instance of `Window` for the current window. */ static getCurrent(): Window { return getCurrentWindow() } /** * Gets a list of instances of `Window` for all available windows. */ static async getAll(): Promise { return getAllWindows() } /** * Gets the focused window. * @example * ```typescript * import { Window } from '@tauri-apps/api/window'; * const focusedWindow = Window.getFocusedWindow(); * ``` * * @returns The Window instance or `undefined` if there is not any focused window. */ static async getFocusedWindow(): Promise { for (const w of await getAllWindows()) { if (await w.isFocused()) { return w } } return null } /** * Listen to an emitted event on this window. * * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * const unlisten = await getCurrentWindow().listen('state-changed', (event) => { * console.log(`Got error: ${payload}`); * }); * * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted * unlisten(); * ``` * * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`. * @param handler Event handler. * @returns A promise resolving to a function to unlisten to the event. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted. */ async listen( event: EventName, handler: EventCallback ): Promise { if (this._handleTauriEvent(event, handler)) { return () => { // eslint-disable-next-line security/detect-object-injection const listeners = this.listeners[event] listeners.splice(listeners.indexOf(handler), 1) } } return listen(event, handler, { target: { kind: 'Window', label: this.label } }) } /** * Listen to an emitted event on this window only once. * * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * const unlisten = await getCurrentWindow().once('initialized', (event) => { * console.log(`Window initialized!`); * }); * * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted * unlisten(); * ``` * * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`. * @param handler Event handler. * @returns A promise resolving to a function to unlisten to the event. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted. */ async once( event: EventName, handler: EventCallback ): Promise { if (this._handleTauriEvent(event, handler)) { return () => { // eslint-disable-next-line security/detect-object-injection const listeners = this.listeners[event] listeners.splice(listeners.indexOf(handler), 1) } } return once(event, handler, { target: { kind: 'Window', label: this.label } }) } /** * Emits an event to all {@link EventTarget|targets}. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().emit('window-loaded', { loggedIn: true, token: 'authToken' }); * ``` * * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`. * @param payload Event payload. */ async emit(event: string, payload?: T): Promise { if (localTauriEvents.includes(event)) { // eslint-disable-next-line for (const handler of this.listeners[event] || []) { handler({ event, id: -1, payload }) } return } return emit(event, payload) } /** * Emits an event to all {@link EventTarget|targets} matching the given target. * * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().emit('main', 'window-loaded', { loggedIn: true, token: 'authToken' }); * ``` * @param target Label of the target Window/Webview/WebviewWindow or raw {@link EventTarget} object. * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`. * @param payload Event payload. */ async emitTo( target: string | EventTarget, event: string, payload?: T ): Promise { if (localTauriEvents.includes(event)) { // eslint-disable-next-line security/detect-object-injection for (const handler of this.listeners[event] || []) { handler({ event, id: -1, payload }) } return } return emitTo(target, event, payload) } /** @ignore */ _handleTauriEvent(event: string, handler: EventCallback): boolean { if (localTauriEvents.includes(event)) { if (!(event in this.listeners)) { // eslint-disable-next-line this.listeners[event] = [handler] } else { // eslint-disable-next-line this.listeners[event].push(handler) } return true } return false } // Getters /** * The scale factor that can be used to map physical pixels to logical pixels. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * const factor = await getCurrentWindow().scaleFactor(); * ``` * * @returns The window's monitor scale factor. */ async scaleFactor(): Promise { return invoke('plugin:window|scale_factor', { label: this.label }) } /** * The position of the top-left hand corner of the window's client area relative to the top-left hand corner of the desktop. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * const position = await getCurrentWindow().innerPosition(); * ``` * * @returns The window's inner position. */ async innerPosition(): Promise { return invoke<{ x: number; y: number }>('plugin:window|inner_position', { label: this.label }).then((p) => new PhysicalPosition(p)) } /** * The position of the top-left hand corner of the window relative to the top-left hand corner of the desktop. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * const position = await getCurrentWindow().outerPosition(); * ``` * * @returns The window's outer position. */ async outerPosition(): Promise { return invoke<{ x: number; y: number }>('plugin:window|outer_position', { label: this.label }).then((p) => new PhysicalPosition(p)) } /** * The physical size of the window's client area. * The client area is the content of the window, excluding the title bar and borders. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * const size = await getCurrentWindow().innerSize(); * ``` * * @returns The window's inner size. */ async innerSize(): Promise { return invoke<{ width: number; height: number }>( 'plugin:window|inner_size', { label: this.label } ).then((s) => new PhysicalSize(s)) } /** * The physical size of the entire window. * These dimensions include the title bar and borders. If you don't want that (and you usually don't), use inner_size instead. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * const size = await getCurrentWindow().outerSize(); * ``` * * @returns The window's outer size. */ async outerSize(): Promise { return invoke<{ width: number; height: number }>( 'plugin:window|outer_size', { label: this.label } ).then((s) => new PhysicalSize(s)) } /** * Gets the window's current fullscreen state. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * const fullscreen = await getCurrentWindow().isFullscreen(); * ``` * * @returns Whether the window is in fullscreen mode or not. */ async isFullscreen(): Promise { return invoke('plugin:window|is_fullscreen', { label: this.label }) } /** * Gets the window's current minimized state. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * const minimized = await getCurrentWindow().isMinimized(); * ``` */ async isMinimized(): Promise { return invoke('plugin:window|is_minimized', { label: this.label }) } /** * Gets the window's current maximized state. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * const maximized = await getCurrentWindow().isMaximized(); * ``` * * @returns Whether the window is maximized or not. */ async isMaximized(): Promise { return invoke('plugin:window|is_maximized', { label: this.label }) } /** * Gets the window's current focus state. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * const focused = await getCurrentWindow().isFocused(); * ``` * * @returns Whether the window is focused or not. */ async isFocused(): Promise { return invoke('plugin:window|is_focused', { label: this.label }) } /** * Gets the window's current decorated state. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * const decorated = await getCurrentWindow().isDecorated(); * ``` * * @returns Whether the window is decorated or not. */ async isDecorated(): Promise { return invoke('plugin:window|is_decorated', { label: this.label }) } /** * Gets the window's current resizable state. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * const resizable = await getCurrentWindow().isResizable(); * ``` * * @returns Whether the window is resizable or not. */ async isResizable(): Promise { return invoke('plugin:window|is_resizable', { label: this.label }) } /** * Gets the window's native maximize button state. * * #### Platform-specific * * - **Linux / iOS / Android:** Unsupported. * * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * const maximizable = await getCurrentWindow().isMaximizable(); * ``` * * @returns Whether the window's native maximize button is enabled or not. */ async isMaximizable(): Promise { return invoke('plugin:window|is_maximizable', { label: this.label }) } /** * Gets the window's native minimize button state. * * #### Platform-specific * * - **Linux / iOS / Android:** Unsupported. * * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * const minimizable = await getCurrentWindow().isMinimizable(); * ``` * * @returns Whether the window's native minimize button is enabled or not. */ async isMinimizable(): Promise { return invoke('plugin:window|is_minimizable', { label: this.label }) } /** * Gets the window's native close button state. * * #### Platform-specific * * - **iOS / Android:** Unsupported. * * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * const closable = await getCurrentWindow().isClosable(); * ``` * * @returns Whether the window's native close button is enabled or not. */ async isClosable(): Promise { return invoke('plugin:window|is_closable', { label: this.label }) } /** * Gets the window's current visible state. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * const visible = await getCurrentWindow().isVisible(); * ``` * * @returns Whether the window is visible or not. */ async isVisible(): Promise { return invoke('plugin:window|is_visible', { label: this.label }) } /** * Gets the window's current title. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * const title = await getCurrentWindow().title(); * ``` */ async title(): Promise { return invoke('plugin:window|title', { label: this.label }) } /** * Gets the window's current theme. * * #### Platform-specific * * - **macOS:** Theme was introduced on macOS 10.14. Returns `light` on macOS 10.13 and below. * * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * const theme = await getCurrentWindow().theme(); * ``` * * @returns The window theme. */ async theme(): Promise { return invoke('plugin:window|theme', { label: this.label }) } /** * Whether the window is configured to be always on top of other windows or not. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * const alwaysOnTop = await getCurrentWindow().isAlwaysOnTop(); * ``` * * @returns Whether the window is visible or not. */ async isAlwaysOnTop(): Promise { return invoke('plugin:window|is_always_on_top', { label: this.label }) } // Setters /** * Centers the window. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().center(); * ``` * * @returns A promise indicating the success or failure of the operation. */ async center(): Promise { return invoke('plugin:window|center', { label: this.label }) } /** * Requests user attention to the window, this has no effect if the application * is already focused. How requesting for user attention manifests is platform dependent, * see `UserAttentionType` for details. * * Providing `null` will unset the request for user attention. Unsetting the request for * user attention might not be done automatically by the WM when the window receives input. * * #### Platform-specific * * - **macOS:** `null` has no effect. * - **Linux:** Urgency levels have the same effect. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().requestUserAttention(); * ``` * * @returns A promise indicating the success or failure of the operation. */ async requestUserAttention( requestType: UserAttentionType | null ): Promise { let requestType_ = null if (requestType) { if (requestType === UserAttentionType.Critical) { requestType_ = { type: 'Critical' } } else { requestType_ = { type: 'Informational' } } } return invoke('plugin:window|request_user_attention', { label: this.label, value: requestType_ }) } /** * Updates the window resizable flag. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setResizable(false); * ``` * * @returns A promise indicating the success or failure of the operation. */ async setResizable(resizable: boolean): Promise { return invoke('plugin:window|set_resizable', { label: this.label, value: resizable }) } /** * Enable or disable the window. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setEnabled(false); * ``` * * @returns A promise indicating the success or failure of the operation. * * @since 2.0.0 */ async setEnabled(enabled: boolean): Promise { return invoke('plugin:window|set_enabled', { label: this.label, value: enabled }) } /** * Whether the window is enabled or disabled. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setEnabled(false); * ``` * * @returns A promise indicating the success or failure of the operation. * * @since 2.0.0 */ async isEnabled(): Promise { return invoke('plugin:window|is_enabled', { label: this.label }) } /** * Sets whether the window's native maximize button is enabled or not. * If resizable is set to false, this setting is ignored. * * #### Platform-specific * * - **macOS:** Disables the "zoom" button in the window titlebar, which is also used to enter fullscreen mode. * - **Linux / iOS / Android:** Unsupported. * * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setMaximizable(false); * ``` * * @returns A promise indicating the success or failure of the operation. */ async setMaximizable(maximizable: boolean): Promise { return invoke('plugin:window|set_maximizable', { label: this.label, value: maximizable }) } /** * Sets whether the window's native minimize button is enabled or not. * * #### Platform-specific * * - **Linux / iOS / Android:** Unsupported. * * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setMinimizable(false); * ``` * * @returns A promise indicating the success or failure of the operation. */ async setMinimizable(minimizable: boolean): Promise { return invoke('plugin:window|set_minimizable', { label: this.label, value: minimizable }) } /** * Sets whether the window's native close button is enabled or not. * * #### Platform-specific * * - **Linux:** GTK+ will do its best to convince the window manager not to show a close button. Depending on the system, this function may not have any effect when called on a window that is already visible * - **iOS / Android:** Unsupported. * * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setClosable(false); * ``` * * @returns A promise indicating the success or failure of the operation. */ async setClosable(closable: boolean): Promise { return invoke('plugin:window|set_closable', { label: this.label, value: closable }) } /** * Sets the window title. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setTitle('Tauri'); * ``` * * @param title The new title * @returns A promise indicating the success or failure of the operation. */ async setTitle(title: string): Promise { return invoke('plugin:window|set_title', { label: this.label, value: title }) } /** * Maximizes the window. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().maximize(); * ``` * * @returns A promise indicating the success or failure of the operation. */ async maximize(): Promise { return invoke('plugin:window|maximize', { label: this.label }) } /** * Unmaximizes the window. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().unmaximize(); * ``` * * @returns A promise indicating the success or failure of the operation. */ async unmaximize(): Promise { return invoke('plugin:window|unmaximize', { label: this.label }) } /** * Toggles the window maximized state. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().toggleMaximize(); * ``` * * @returns A promise indicating the success or failure of the operation. */ async toggleMaximize(): Promise { return invoke('plugin:window|toggle_maximize', { label: this.label }) } /** * Minimizes the window. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().minimize(); * ``` * * @returns A promise indicating the success or failure of the operation. */ async minimize(): Promise { return invoke('plugin:window|minimize', { label: this.label }) } /** * Unminimizes the window. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().unminimize(); * ``` * * @returns A promise indicating the success or failure of the operation. */ async unminimize(): Promise { return invoke('plugin:window|unminimize', { label: this.label }) } /** * Sets the window visibility to true. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().show(); * ``` * * @returns A promise indicating the success or failure of the operation. */ async show(): Promise { return invoke('plugin:window|show', { label: this.label }) } /** * Sets the window visibility to false. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().hide(); * ``` * * @returns A promise indicating the success or failure of the operation. */ async hide(): Promise { return invoke('plugin:window|hide', { label: this.label }) } /** * Closes the window. * * Note this emits a closeRequested event so you can intercept it. To force window close, use {@link Window.destroy}. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().close(); * ``` * * @returns A promise indicating the success or failure of the operation. */ async close(): Promise { return invoke('plugin:window|close', { label: this.label }) } /** * Destroys the window. Behaves like {@link Window.close} but forces the window close instead of emitting a closeRequested event. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().destroy(); * ``` * * @returns A promise indicating the success or failure of the operation. */ async destroy(): Promise { return invoke('plugin:window|destroy', { label: this.label }) } /** * Whether the window should have borders and bars. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setDecorations(false); * ``` * * @param decorations Whether the window should have borders and bars. * @returns A promise indicating the success or failure of the operation. */ async setDecorations(decorations: boolean): Promise { return invoke('plugin:window|set_decorations', { label: this.label, value: decorations }) } /** * Whether or not the window should have shadow. * * #### Platform-specific * * - **Windows:** * - `false` has no effect on decorated window, shadows are always ON. * - `true` will make undecorated window have a 1px white border, * and on Windows 11, it will have a rounded corners. * - **Linux:** Unsupported. * * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setShadow(false); * ``` * * @returns A promise indicating the success or failure of the operation. */ async setShadow(enable: boolean): Promise { return invoke('plugin:window|set_shadow', { label: this.label, value: enable }) } /** * Set window effects. */ async setEffects(effects: Effects): Promise { return invoke('plugin:window|set_effects', { label: this.label, value: effects }) } /** * Clear any applied effects if possible. */ async clearEffects(): Promise { return invoke('plugin:window|set_effects', { label: this.label, value: null }) } /** * Whether the window should always be on top of other windows. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setAlwaysOnTop(true); * ``` * * @param alwaysOnTop Whether the window should always be on top of other windows or not. * @returns A promise indicating the success or failure of the operation. */ async setAlwaysOnTop(alwaysOnTop: boolean): Promise { return invoke('plugin:window|set_always_on_top', { label: this.label, value: alwaysOnTop }) } /** * Whether the window should always be below other windows. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setAlwaysOnBottom(true); * ``` * * @param alwaysOnBottom Whether the window should always be below other windows or not. * @returns A promise indicating the success or failure of the operation. */ async setAlwaysOnBottom(alwaysOnBottom: boolean): Promise { return invoke('plugin:window|set_always_on_bottom', { label: this.label, value: alwaysOnBottom }) } /** * Prevents the window contents from being captured by other apps. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setContentProtected(true); * ``` * * @returns A promise indicating the success or failure of the operation. */ async setContentProtected(protected_: boolean): Promise { return invoke('plugin:window|set_content_protected', { label: this.label, value: protected_ }) } /** * Resizes the window with a new inner size. * @example * ```typescript * import { getCurrentWindow, LogicalSize } from '@tauri-apps/api/window'; * await getCurrentWindow().setSize(new LogicalSize(600, 500)); * ``` * * @param size The logical or physical inner size. * @returns A promise indicating the success or failure of the operation. */ async setSize(size: LogicalSize | PhysicalSize | Size): Promise { return invoke('plugin:window|set_size', { label: this.label, value: size instanceof Size ? size : new Size(size) }) } /** * Sets the window minimum inner size. If the `size` argument is not provided, the constraint is unset. * @example * ```typescript * import { getCurrentWindow, PhysicalSize } from '@tauri-apps/api/window'; * await getCurrentWindow().setMinSize(new PhysicalSize(600, 500)); * ``` * * @param size The logical or physical inner size, or `null` to unset the constraint. * @returns A promise indicating the success or failure of the operation. */ async setMinSize( size: LogicalSize | PhysicalSize | Size | null | undefined ): Promise { return invoke('plugin:window|set_min_size', { label: this.label, value: size instanceof Size ? size : size ? new Size(size) : null }) } /** * Sets the window maximum inner size. If the `size` argument is undefined, the constraint is unset. * @example * ```typescript * import { getCurrentWindow, LogicalSize } from '@tauri-apps/api/window'; * await getCurrentWindow().setMaxSize(new LogicalSize(600, 500)); * ``` * * @param size The logical or physical inner size, or `null` to unset the constraint. * @returns A promise indicating the success or failure of the operation. */ async setMaxSize( size: LogicalSize | PhysicalSize | Size | null | undefined ): Promise { return invoke('plugin:window|set_max_size', { label: this.label, value: size instanceof Size ? size : size ? new Size(size) : null }) } /** * Sets the window inner size constraints. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setSizeConstraints({ minWidth: 300 }); * ``` * * @param constraints The logical or physical inner size, or `null` to unset the constraint. * @returns A promise indicating the success or failure of the operation. */ async setSizeConstraints( constraints: WindowSizeConstraints | null | undefined ): Promise { function logical(pixel?: number): { Logical: number } | null { return pixel ? { Logical: pixel } : null } return invoke('plugin:window|set_size_constraints', { label: this.label, value: { minWidth: logical(constraints?.minWidth), minHeight: logical(constraints?.minHeight), maxWidth: logical(constraints?.maxWidth), maxHeight: logical(constraints?.maxHeight) } }) } /** * Sets the window outer position. * @example * ```typescript * import { getCurrentWindow, LogicalPosition } from '@tauri-apps/api/window'; * await getCurrentWindow().setPosition(new LogicalPosition(600, 500)); * ``` * * @param position The new position, in logical or physical pixels. * @returns A promise indicating the success or failure of the operation. */ async setPosition( position: LogicalPosition | PhysicalPosition | Position ): Promise { return invoke('plugin:window|set_position', { label: this.label, value: position instanceof Position ? position : new Position(position) }) } /** * Sets the window fullscreen state. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setFullscreen(true); * ``` * * @param fullscreen Whether the window should go to fullscreen or not. * @returns A promise indicating the success or failure of the operation. */ async setFullscreen(fullscreen: boolean): Promise { return invoke('plugin:window|set_fullscreen', { label: this.label, value: fullscreen }) } /** * On macOS, Toggles a fullscreen mode that doesn’t require a new macOS space. Returns a boolean indicating whether the transition was successful (this won’t work if the window was already in the native fullscreen). * This is how fullscreen used to work on macOS in versions before Lion. And allows the user to have a fullscreen window without using another space or taking control over the entire monitor. * * On other platforms, this is the same as {@link Window.setFullscreen}. * * @param fullscreen Whether the window should go to simple fullscreen or not. * @returns A promise indicating the success or failure of the operation. */ async setSimpleFullscreen(fullscreen: boolean): Promise { return invoke('plugin:window|set_simple_fullscreen', { label: this.label, value: fullscreen }) } /** * Bring the window to front and focus. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setFocus(); * ``` * * @returns A promise indicating the success or failure of the operation. */ async setFocus(): Promise { return invoke('plugin:window|set_focus', { label: this.label }) } /** * Sets whether the window can be focused. * * #### Platform-specific * * - **macOS**: If the window is already focused, it is not possible to unfocus it after calling `set_focusable(false)`. * In this case, you might consider calling {@link Window.setFocus} but it will move the window to the back i.e. at the bottom in terms of z-order. * * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setFocusable(true); * ``` * * @param focusable Whether the window can be focused. * @returns A promise indicating the success or failure of the operation. */ async setFocusable(focusable: boolean): Promise { return invoke('plugin:window|set_focusable', { label: this.label, value: focusable }) } /** * Sets the window icon. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setIcon('/tauri/awesome.png'); * ``` * * Note that you may need the `image-ico` or `image-png` Cargo features to use this API. * To enable it, change your Cargo.toml file: * ```toml * [dependencies] * tauri = { version = "...", features = ["...", "image-png"] } * ``` * * @param icon Icon bytes or path to the icon file. * @returns A promise indicating the success or failure of the operation. */ async setIcon( icon: string | Image | Uint8Array | ArrayBuffer | number[] ): Promise { return invoke('plugin:window|set_icon', { label: this.label, value: transformImage(icon) }) } /** * Whether the window icon should be hidden from the taskbar or not. * * #### Platform-specific * * - **macOS:** Unsupported. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setSkipTaskbar(true); * ``` * * @param skip true to hide window icon, false to show it. * @returns A promise indicating the success or failure of the operation. */ async setSkipTaskbar(skip: boolean): Promise { return invoke('plugin:window|set_skip_taskbar', { label: this.label, value: skip }) } /** * Grabs the cursor, preventing it from leaving the window. * * There's no guarantee that the cursor will be hidden. You should * hide it by yourself if you want so. * * #### Platform-specific * * - **Linux:** Unsupported. * - **macOS:** This locks the cursor in a fixed location, which looks visually awkward. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setCursorGrab(true); * ``` * * @param grab `true` to grab the cursor icon, `false` to release it. * @returns A promise indicating the success or failure of the operation. */ async setCursorGrab(grab: boolean): Promise { return invoke('plugin:window|set_cursor_grab', { label: this.label, value: grab }) } /** * Modifies the cursor's visibility. * * #### Platform-specific * * - **Windows:** The cursor is only hidden within the confines of the window. * - **macOS:** The cursor is hidden as long as the window has input focus, even if the cursor is * outside of the window. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setCursorVisible(false); * ``` * * @param visible If `false`, this will hide the cursor. If `true`, this will show the cursor. * @returns A promise indicating the success or failure of the operation. */ async setCursorVisible(visible: boolean): Promise { return invoke('plugin:window|set_cursor_visible', { label: this.label, value: visible }) } /** * Modifies the cursor icon of the window. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setCursorIcon('help'); * ``` * * @param icon The new cursor icon. * @returns A promise indicating the success or failure of the operation. */ async setCursorIcon(icon: CursorIcon): Promise { return invoke('plugin:window|set_cursor_icon', { label: this.label, value: icon }) } /** * Sets the window background color. * * #### Platform-specific: * * - **Windows:** alpha channel is ignored. * - **iOS / Android:** Unsupported. * * @returns A promise indicating the success or failure of the operation. * * @since 2.1.0 */ async setBackgroundColor(color: Color): Promise { return invoke('plugin:window|set_background_color', { color }) } /** * Changes the position of the cursor in window coordinates. * @example * ```typescript * import { getCurrentWindow, LogicalPosition } from '@tauri-apps/api/window'; * await getCurrentWindow().setCursorPosition(new LogicalPosition(600, 300)); * ``` * * @param position The new cursor position. * @returns A promise indicating the success or failure of the operation. */ async setCursorPosition( position: LogicalPosition | PhysicalPosition | Position ): Promise { return invoke('plugin:window|set_cursor_position', { label: this.label, value: position instanceof Position ? position : new Position(position) }) } /** * Changes the cursor events behavior. * * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setIgnoreCursorEvents(true); * ``` * * @param ignore `true` to ignore the cursor events; `false` to process them as usual. * @returns A promise indicating the success or failure of the operation. */ async setIgnoreCursorEvents(ignore: boolean): Promise { return invoke('plugin:window|set_ignore_cursor_events', { label: this.label, value: ignore }) } /** * Starts dragging the window. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().startDragging(); * ``` * * @return A promise indicating the success or failure of the operation. */ async startDragging(): Promise { return invoke('plugin:window|start_dragging', { label: this.label }) } /** * Starts resize-dragging the window. * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().startResizeDragging(); * ``` * * @return A promise indicating the success or failure of the operation. */ async startResizeDragging(direction: ResizeDirection): Promise { return invoke('plugin:window|start_resize_dragging', { label: this.label, value: direction }) } /** * Sets the badge count. It is app wide and not specific to this window. * * #### Platform-specific * * - **Windows**: Unsupported. Use @{linkcode Window.setOverlayIcon} instead. * * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setBadgeCount(5); * ``` * * @param count The badge count. Use `undefined` to remove the badge. * @return A promise indicating the success or failure of the operation. */ async setBadgeCount(count?: number): Promise { return invoke('plugin:window|set_badge_count', { label: this.label, value: count }) } /** * Sets the badge cont **macOS only**. * * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setBadgeLabel("Hello"); * ``` * * @param label The badge label. Use `undefined` to remove the badge. * @return A promise indicating the success or failure of the operation. */ async setBadgeLabel(label?: string): Promise { return invoke('plugin:window|set_badge_label', { label: this.label, value: label }) } /** * Sets the overlay icon. **Windows only** * The overlay icon can be set for every window. * * * Note that you may need the `image-ico` or `image-png` Cargo features to use this API. * To enable it, change your Cargo.toml file: * * ```toml * [dependencies] * tauri = { version = "...", features = ["...", "image-png"] } * ``` * * @example * ```typescript * import { getCurrentWindow } from '@tauri-apps/api/window'; * await getCurrentWindow().setOverlayIcon("/tauri/awesome.png"); * ``` * * @param icon Icon bytes or path to the icon file. Use `undefined` to remove the overlay icon. * @return A promise indicating the success or failure of the operation. */ async setOverlayIcon( icon?: string | Image | Uint8Array | ArrayBuffer | number[] ): Promise { return invoke('plugin:window|set_overlay_icon', { label: this.label, value: icon ? transformImage(icon) : undefined }) } /** * Sets the taskbar progress state. * * #### Platform-specific * * - **Linux / macOS**: Progress bar is app-wide and not specific to this window. * - **Linux**: Only supported desktop environments with `libunity` (e.g. GNOME). * * @example * ```typescript * import { getCurrentWindow, ProgressBarStatus } from '@tauri-apps/api/window'; * await getCurrentWindow().setProgressBar({ * status: ProgressBarStatus.Normal, * progress: 50, * }); * ``` * * @return A promise indicating the success or failure of the operation. */ async setProgressBar(state: ProgressBarState): Promise { return invoke('plugin:window|set_progress_bar', { label: this.label, value: state }) } /** * Sets whether the window should be visible on all workspaces or virtual desktops. * * #### Platform-specific * * - **Windows / iOS / Android:** Unsupported. * * @since 2.0.0 */ async setVisibleOnAllWorkspaces(visible: boolean): Promise { return invoke('plugin:window|set_visible_on_all_workspaces', { label: this.label, value: visible }) } /** * Sets the title bar style. **macOS only**. * * @since 2.0.0 */ async setTitleBarStyle(style: TitleBarStyle): Promise { return invoke('plugin:window|set_title_bar_style', { label: this.label, value: style }) } /** * Set window theme, pass in `null` or `undefined` to follow system theme * * #### Platform-specific * * - **Linux / macOS**: Theme is app-wide and not specific to this window. * - **iOS / Android:** Unsupported. * * @since 2.0.0 */ async setTheme(theme?: Theme | null): Promise { return invoke('plugin:window|set_theme', { label: this.label, value: theme }) } // Listeners /** * Listen to window resize. * * @example * ```typescript * import { getCurrentWindow } from "@tauri-apps/api/window"; * const unlisten = await getCurrentWindow().onResized(({ payload: size }) => { * console.log('Window resized', size); * }); * * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted * unlisten(); * ``` * * @returns A promise resolving to a function to unlisten to the event. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted. */ async onResized(handler: EventCallback): Promise { return this.listen(TauriEvent.WINDOW_RESIZED, (e) => { e.payload = new PhysicalSize(e.payload) handler(e) }) } /** * Listen to window move. * * @example * ```typescript * import { getCurrentWindow } from "@tauri-apps/api/window"; * const unlisten = await getCurrentWindow().onMoved(({ payload: position }) => { * console.log('Window moved', position); * }); * * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted * unlisten(); * ``` * * @returns A promise resolving to a function to unlisten to the event. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted. */ async onMoved(handler: EventCallback): Promise { return this.listen(TauriEvent.WINDOW_MOVED, (e) => { e.payload = new PhysicalPosition(e.payload) handler(e) }) } /** * Listen to window close requested. Emitted when the user requests to closes the window. * * @example * ```typescript * import { getCurrentWindow } from "@tauri-apps/api/window"; * import { confirm } from '@tauri-apps/api/dialog'; * const unlisten = await getCurrentWindow().onCloseRequested(async (event) => { * const confirmed = await confirm('Are you sure?'); * if (!confirmed) { * // user did not confirm closing the window; let's prevent it * event.preventDefault(); * } * }); * * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted * unlisten(); * ``` * * @returns A promise resolving to a function to unlisten to the event. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted. */ async onCloseRequested( handler: (event: CloseRequestedEvent) => void | Promise ): Promise { // eslint-disable-next-line @typescript-eslint/no-misused-promises return this.listen(TauriEvent.WINDOW_CLOSE_REQUESTED, async (event) => { const evt = new CloseRequestedEvent(event) await handler(evt) if (!evt.isPreventDefault()) { await this.destroy() } }) } /** * Listen to a file drop event. * The listener is triggered when the user hovers the selected files on the webview, * drops the files or cancels the operation. * * @example * ```typescript * import { getCurrentWindow } from "@tauri-apps/api/webview"; * const unlisten = await getCurrentWindow().onDragDropEvent((event) => { * if (event.payload.type === 'over') { * console.log('User hovering', event.payload.position); * } else if (event.payload.type === 'drop') { * console.log('User dropped', event.payload.paths); * } else { * console.log('File drop cancelled'); * } * }); * * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted * unlisten(); * ``` * * @returns A promise resolving to a function to unlisten to the event. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted. */ async onDragDropEvent( handler: EventCallback ): Promise { type DragPayload = { paths: string[]; position: PhysicalPosition } const unlistenDrag = await this.listen( TauriEvent.DRAG_ENTER, (event) => { handler({ ...event, payload: { type: 'enter', paths: event.payload.paths, position: new PhysicalPosition(event.payload.position) } }) } ) const unlistenDragOver = await this.listen( TauriEvent.DRAG_OVER, (event) => { handler({ ...event, payload: { type: 'over', position: new PhysicalPosition(event.payload.position) } }) } ) const unlistenDrop = await this.listen( TauriEvent.DRAG_DROP, (event) => { handler({ ...event, payload: { type: 'drop', paths: event.payload.paths, position: new PhysicalPosition(event.payload.position) } }) } ) const unlistenCancel = await this.listen( TauriEvent.DRAG_LEAVE, (event) => { handler({ ...event, payload: { type: 'leave' } }) } ) return () => { unlistenDrag() unlistenDrop() unlistenDragOver() unlistenCancel() } } /** * Listen to window focus change. * * @example * ```typescript * import { getCurrentWindow } from "@tauri-apps/api/window"; * const unlisten = await getCurrentWindow().onFocusChanged(({ payload: focused }) => { * console.log('Focus changed, window is focused? ' + focused); * }); * * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted * unlisten(); * ``` * * @returns A promise resolving to a function to unlisten to the event. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted. */ async onFocusChanged(handler: EventCallback): Promise { const unlistenFocus = await this.listen( TauriEvent.WINDOW_FOCUS, (event) => { handler({ ...event, payload: true }) } ) const unlistenBlur = await this.listen( TauriEvent.WINDOW_BLUR, (event) => { handler({ ...event, payload: false }) } ) return () => { unlistenFocus() unlistenBlur() } } /** * Listen to window scale change. Emitted when the window's scale factor has changed. * The following user actions can cause DPI changes: * - Changing the display's resolution. * - Changing the display's scale factor (e.g. in Control Panel on Windows). * - Moving the window to a display with a different scale factor. * * @example * ```typescript * import { getCurrentWindow } from "@tauri-apps/api/window"; * const unlisten = await getCurrentWindow().onScaleChanged(({ payload }) => { * console.log('Scale changed', payload.scaleFactor, payload.size); * }); * * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted * unlisten(); * ``` * * @returns A promise resolving to a function to unlisten to the event. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted. */ async onScaleChanged( handler: EventCallback ): Promise { return this.listen( TauriEvent.WINDOW_SCALE_FACTOR_CHANGED, handler ) } /** * Listen to the system theme change. * * @example * ```typescript * import { getCurrentWindow } from "@tauri-apps/api/window"; * const unlisten = await getCurrentWindow().onThemeChanged(({ payload: theme }) => { * console.log('New theme: ' + theme); * }); * * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted * unlisten(); * ``` * * @returns A promise resolving to a function to unlisten to the event. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted. */ async onThemeChanged(handler: EventCallback): Promise { return this.listen(TauriEvent.WINDOW_THEME_CHANGED, handler) } } /** * An RGBA color. Each value has minimum of 0 and maximum of 255. * * It can be either a string `#ffffff`, an array of 3 or 4 elements or an object. * * @since 2.0.0 */ type Color = | [number, number, number] | [number, number, number, number] | { red: number; green: number; blue: number; alpha: number } | string /** * Background throttling policy * * @since 2.0.0 */ enum BackgroundThrottlingPolicy { Disabled = 'disabled', Throttle = 'throttle', Suspend = 'suspend' } /** * The scrollbar style to use in the webview. * * ## Platform-specific * * **Windows**: This option must be given the same value for all webviews. * * @since 2.8.0 */ enum ScrollBarStyle { /** * The default scrollbar style for the webview. */ Default = 'default', /** * Fluent UI style overlay scrollbars. **Windows Only** * * Requires WebView2 Runtime version 125.0.2535.41 or higher, does nothing on older versions, * see https://learn.microsoft.com/en-us/microsoft-edge/webview2/release-notes/?tabs=dotnetcsharp#10253541 */ FluentOverlay = 'fluentOverlay' } /** * Platform-specific window effects * * @since 2.0.0 */ enum Effect { /** * A default material appropriate for the view's effectiveAppearance. **macOS 10.14-** * * @deprecated since macOS 10.14. You should instead choose an appropriate semantic material. */ AppearanceBased = 'appearanceBased', /** * **macOS 10.14-** * * @deprecated since macOS 10.14. Use a semantic material instead. */ Light = 'light', /** * **macOS 10.14-** * * @deprecated since macOS 10.14. Use a semantic material instead. */ Dark = 'dark', /** * **macOS 10.14-** * * @deprecated since macOS 10.14. Use a semantic material instead. */ MediumLight = 'mediumLight', /** * **macOS 10.14-** * * @deprecated since macOS 10.14. Use a semantic material instead. */ UltraDark = 'ultraDark', /** * **macOS 10.10+** */ Titlebar = 'titlebar', /** * **macOS 10.10+** */ Selection = 'selection', /** * **macOS 10.11+** */ Menu = 'menu', /** * **macOS 10.11+** */ Popover = 'popover', /** * **macOS 10.11+** */ Sidebar = 'sidebar', /** * **macOS 10.14+** */ HeaderView = 'headerView', /** * **macOS 10.14+** */ Sheet = 'sheet', /** * **macOS 10.14+** */ WindowBackground = 'windowBackground', /** * **macOS 10.14+** */ HudWindow = 'hudWindow', /** * **macOS 10.14+** */ FullScreenUI = 'fullScreenUI', /** * **macOS 10.14+** */ Tooltip = 'tooltip', /** * **macOS 10.14+** */ ContentBackground = 'contentBackground', /** * **macOS 10.14+** */ UnderWindowBackground = 'underWindowBackground', /** * **macOS 10.14+** */ UnderPageBackground = 'underPageBackground', /** * **Windows 11 Only** */ Mica = 'mica', /** * **Windows 7/10/11(22H1) Only** * * #### Notes * * This effect has bad performance when resizing/dragging the window on Windows 11 build 22621. */ Blur = 'blur', /** * **Windows 10/11** * * #### Notes * * This effect has bad performance when resizing/dragging the window on Windows 10 v1903+ and Windows 11 build 22000. */ Acrylic = 'acrylic', /** * Tabbed effect that matches the system dark preference **Windows 11 Only** */ Tabbed = 'tabbed', /** * Tabbed effect with dark mode but only if dark mode is enabled on the system **Windows 11 Only** */ TabbedDark = 'tabbedDark', /** * Tabbed effect with light mode **Windows 11 Only** */ TabbedLight = 'tabbedLight' } /** * Window effect state **macOS only** * * @see https://developer.apple.com/documentation/appkit/nsvisualeffectview/state * * @since 2.0.0 */ enum EffectState { /** * Make window effect state follow the window's active state **macOS only** */ FollowsWindowActiveState = 'followsWindowActiveState', /** * Make window effect state always active **macOS only** */ Active = 'active', /** * Make window effect state always inactive **macOS only** */ Inactive = 'inactive' } /** The window effects configuration object * * @since 2.0.0 */ interface Effects { /** * List of Window effects to apply to the Window. * Conflicting effects will apply the first one and ignore the rest. */ effects: Effect[] /** * Window effect state **macOS Only** */ state?: EffectState /** * Window effect corner radius **macOS Only** */ radius?: number /** * Window effect color. Affects {@link Effect.Blur} and {@link Effect.Acrylic} only * on Windows 10 v1903+. Doesn't have any effect on Windows 7 or Windows 11. */ color?: Color } /** * Minimum margin to work area */ interface PreventOverflowMargin { width: number height: number } /** * Configuration for the window to create. * * @since 1.0.0 */ interface WindowOptions { /** Show window in the center of the screen.. */ center?: boolean /** The initial vertical position in logical pixels. Only applies if `y` is also set. */ x?: number /** The initial horizontal position in logical pixels. Only applies if `x` is also set. */ y?: number /** The initial width in logical pixels. */ width?: number /** The initial height in logical pixels. */ height?: number /** The minimum width in logical pixels. Only applies if `minHeight` is also set. */ minWidth?: number /** The minimum height in logical pixels. Only applies if `minWidth` is also set. */ minHeight?: number /** The maximum width in logical pixels. Only applies if `maxHeight` is also set. */ maxWidth?: number /** The maximum height in logical pixels. Only applies if `maxWidth` is also set. */ maxHeight?: number /** * Prevent the window from overflowing the working area (e.g. monitor size - taskbar size) * on creation, which means the window size will be limited to `monitor size - taskbar size` * * Can either be set to `true` or to a {@link PreventOverflowMargin} object to set an additional margin * that should be considered to determine the working area * (in this case the window size will be limited to `monitor size - taskbar size - margin`) * * **NOTE**: The overflow check is only performed on window creation, resizes can still overflow * * #### Platform-specific * * - **iOS / Android:** Unsupported. */ preventOverflow?: boolean | PreventOverflowMargin /** Whether the window is resizable or not. */ resizable?: boolean /** Window title. */ title?: string /** Whether the window is in fullscreen mode or not. */ fullscreen?: boolean /** Whether the window will be initially focused or not. */ focus?: boolean /** Whether the window can be focused or not. */ focusable?: boolean /** * Whether the window is transparent or not. * Note that on `macOS` this requires the `macos-private-api` feature flag, enabled under `tauri.conf.json > app > macOSPrivateApi`. * WARNING: Using private APIs on `macOS` prevents your application from being accepted to the `App Store`. */ transparent?: boolean /** Whether the window should be maximized upon creation or not. */ maximized?: boolean /** Whether the window should be immediately visible upon creation or not. */ visible?: boolean /** Whether the window should have borders and bars or not. */ decorations?: boolean /** Whether the window should always be on top of other windows or not. */ alwaysOnTop?: boolean /** Whether the window should always be below other windows. */ alwaysOnBottom?: boolean /** Prevents the window contents from being captured by other apps. */ contentProtected?: boolean /** Whether or not the window icon should be added to the taskbar. */ skipTaskbar?: boolean /** * Whether or not the window has shadow. * * #### Platform-specific * * - **Windows:** * - `false` has no effect on decorated window, shadows are always ON. * - `true` will make undecorated window have a 1px white border, * and on Windows 11, it will have a rounded corners. * - **Linux:** Unsupported. * * @since 2.0.0 */ shadow?: boolean /** * The initial window theme. Defaults to the system theme. * * Only implemented on Windows and macOS 10.14+. */ theme?: Theme /** * The style of the macOS title bar. */ titleBarStyle?: TitleBarStyle /** * The position of the window controls on macOS. * * Requires `titleBarStyle: 'overlay'` and `decorations: true`. * * @since 2.4.0 */ trafficLightPosition?: LogicalPosition /** * If `true`, sets the window title to be hidden on macOS. */ hiddenTitle?: boolean /** * Defines the window [tabbing identifier](https://developer.apple.com/documentation/appkit/nswindow/1644704-tabbingidentifier) on macOS. * * Windows with the same tabbing identifier will be grouped together. * If the tabbing identifier is not set, automatic tabbing will be disabled. */ tabbingIdentifier?: string /** * Whether the window's native maximize button is enabled or not. Defaults to `true`. */ maximizable?: boolean /** * Whether the window's native minimize button is enabled or not. Defaults to `true`. */ minimizable?: boolean /** * Whether the window's native close button is enabled or not. Defaults to `true`. */ closable?: boolean /** * Sets a parent to the window to be created. Can be either a {@linkcode Window} or a label of the window. * * #### Platform-specific * * - **Windows**: This sets the passed parent as an owner window to the window to be created. * From [MSDN owned windows docs](https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#owned-windows): * - An owned window is always above its owner in the z-order. * - The system automatically destroys an owned window when its owner is destroyed. * - An owned window is hidden when its owner is minimized. * - **Linux**: This makes the new window transient for parent, see * - **macOS**: This adds the window as a child of parent, see */ parent?: Window | WebviewWindow | string /** Whether the window should be visible on all workspaces or virtual desktops. * * #### Platform-specific * * - **Windows / iOS / Android:** Unsupported. * * @since 2.0.0 */ visibleOnAllWorkspaces?: boolean /** * Window effects. * * Requires the window to be transparent. * * #### Platform-specific: * * - **Windows**: If using decorations or shadows, you may want to try this workaround * - **Linux**: Unsupported */ windowEffects?: Effects /** * Set the window background color. * * #### Platform-specific: * * - **Android / iOS:** Unsupported. * - **Windows**: alpha channel is ignored. * * @since 2.1.0 */ backgroundColor?: Color /** Change the default background throttling behaviour. * * ## Platform-specific * * - **Linux / Windows / Android**: Unsupported. Workarounds like a pending WebLock transaction might suffice. * - **iOS**: Supported since version 17.0+. * - **macOS**: Supported since version 14.0+. * * see https://github.com/tauri-apps/tauri/issues/5250#issuecomment-2569380578 * * @since 2.3.0 */ backgroundThrottling?: BackgroundThrottlingPolicy /** * Whether we should disable JavaScript code execution on the webview or not. */ javascriptDisabled?: boolean /** * on macOS and iOS there is a link preview on long pressing links, this is enabled by default. * see https://docs.rs/objc2-web-kit/latest/objc2_web_kit/struct.WKWebView.html#method.allowsLinkPreview */ allowLinkPreview?: boolean /** * Allows disabling the input accessory view on iOS. * * The accessory view is the view that appears above the keyboard when a text input element is focused. * It usually displays a view with "Done", "Next" buttons. */ disableInputAccessoryView?: boolean /** * Specifies the native scrollbar style to use with the webview. * CSS styles that modify the scrollbar are applied on top of the native appearance configured here. * * Defaults to `default`, which is the browser default. * * ## Platform-specific * * - **Windows**: * - `fluentOverlay` requires WebView2 Runtime version 125.0.2535.41 or higher, and does nothing * on older versions. * - This option must be given the same value for all webviews. * - **Linux / Android / iOS / macOS**: Unsupported. Only supports `Default` and performs no operation. */ scrollBarStyle?: ScrollBarStyle } function mapMonitor(m: Monitor | null): Monitor | null { return m === null ? null : { name: m.name, scaleFactor: m.scaleFactor, position: new PhysicalPosition(m.position), size: new PhysicalSize(m.size), workArea: { position: new PhysicalPosition(m.workArea.position), size: new PhysicalSize(m.workArea.size) } } } /** * Returns the monitor on which the window currently resides. * Returns `null` if current monitor can't be detected. * @example * ```typescript * import { currentMonitor } from '@tauri-apps/api/window'; * const monitor = await currentMonitor(); * ``` * * @since 1.0.0 */ async function currentMonitor(): Promise { return invoke('plugin:window|current_monitor').then( mapMonitor ) } /** * Returns the primary monitor of the system. * Returns `null` if it can't identify any monitor as a primary one. * @example * ```typescript * import { primaryMonitor } from '@tauri-apps/api/window'; * const monitor = await primaryMonitor(); * ``` * * @since 1.0.0 */ async function primaryMonitor(): Promise { return invoke('plugin:window|primary_monitor').then( mapMonitor ) } /** * Returns the monitor that contains the given point. Returns `null` if can't find any. * @example * ```typescript * import { monitorFromPoint } from '@tauri-apps/api/window'; * const monitor = await monitorFromPoint(100.0, 200.0); * ``` * * @since 1.0.0 */ async function monitorFromPoint(x: number, y: number): Promise { return invoke('plugin:window|monitor_from_point', { x, y }).then(mapMonitor) } /** * Returns the list of all the monitors available on the system. * @example * ```typescript * import { availableMonitors } from '@tauri-apps/api/window'; * const monitors = await availableMonitors(); * ``` * * @since 1.0.0 */ async function availableMonitors(): Promise { return invoke('plugin:window|available_monitors').then( (ms) => ms.map(mapMonitor) as Monitor[] ) } /** * Get the cursor position relative to the top-left hand corner of the desktop. * * Note that the top-left hand corner of the desktop is not necessarily the same as the screen. * If the user uses a desktop with multiple monitors, * the top-left hand corner of the desktop is the top-left hand corner of the main monitor on Windows and macOS * or the top-left of the leftmost monitor on X11. * * The coordinates can be negative if the top-left hand corner of the window is outside of the visible screen region. */ async function cursorPosition(): Promise { return invoke('plugin:window|cursor_position').then( (v) => new PhysicalPosition(v) ) } export { Window, CloseRequestedEvent, getCurrentWindow, getAllWindows, LogicalSize, PhysicalSize, LogicalPosition, PhysicalPosition, UserAttentionType, Effect, EffectState, currentMonitor, monitorFromPoint, primaryMonitor, availableMonitors, cursorPosition } export type { Effects, Theme, TitleBarStyle, ScaleFactorChanged, WindowOptions, Color, BackgroundThrottlingPolicy, DragDropEvent, ScrollBarStyle } ================================================ FILE: packages/api/tsconfig.json ================================================ { "compilerOptions": { "target": "es2019", "module": "esnext", "moduleResolution": "bundler", "skipLibCheck": true, "strict": true, "noUnusedLocals": true, "noImplicitAny": true, "noEmit": true } } ================================================ FILE: packages/cli/.cargo/config.toml ================================================ # napi-rs can't handle custom target-dir configs yet so we make sure it's set to the default [build] target-dir = "target" [target.aarch64-unknown-linux-gnu] linker = "aarch64-linux-gnu-gcc" [target.aarch64-unknown-linux-musl] linker = "aarch64-linux-musl-gcc" rustflags = ["-C", "target-feature=-crt-static"] [target.armv7-unknown-linux-gnueabihf] linker = "arm-linux-gnueabihf-gcc" [target.riscv64gc-unknown-linux-gnu] linker = "riscv64-linux-gnu-gcc" [target.x86_64-pc-windows-msvc] rustflags = ["-C", "target-feature=+crt-static"] [target.i686-pc-windows-msvc] rustflags = ["-C", "target-feature=+crt-static"] [target.aarch64-pc-windows-msvc] rustflags = ["-C", "target-feature=+crt-static"] ================================================ FILE: packages/cli/.gitignore ================================================ # debug builds of NAPI *.node ================================================ FILE: packages/cli/.npmignore ================================================ target Cargo.lock .cargo .github npm test .eslintrc .prettierignore rustfmt.toml *.node __tests__ src Cargo.toml build.rs ================================================ FILE: packages/cli/CHANGELOG.md ================================================ # Changelog ## \[2.10.1] ### Bug Fixes - [`35c35f27a`](https://www.github.com/tauri-apps/tauri/commit/35c35f27aedc430b602ec74059b271128c15ad36) ([#14931](https://www.github.com/tauri-apps/tauri/pull/14931) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Support comma-separated list of Cargo features on all commands. - [`0d1cb83ba`](https://www.github.com/tauri-apps/tauri/commit/0d1cb83bab2aa482c7d73116893fd7ff6aa56283) ([#14932](https://www.github.com/tauri-apps/tauri/pull/14932) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix missing Cargo args when running mobile dev and build commands. - [`33754ae5e`](https://www.github.com/tauri-apps/tauri/commit/33754ae5e3740d022483b6164511c5c001a3c24b) ([#15022](https://www.github.com/tauri-apps/tauri/pull/15022) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix updater signing private keys generated using `tauri signer generate` with empty password can't be used (The keys generated during tauri were broken between v2.9.3 and v2.10.0, you'll need to regenerate them) ### What's Changed - [`7be58a1c6`](https://www.github.com/tauri-apps/tauri/commit/7be58a1c643a7ed6d0f484a7e1134022618eb2b2) ([#14894](https://www.github.com/tauri-apps/tauri/pull/14894) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Log patching bundle type information again ### Dependencies - Upgraded to `tauri-cli@2.10.1` ## \[2.10.0] ### Enhancements - [`f82594410`](https://www.github.com/tauri-apps/tauri/commit/f82594410cd57d6f794f58d4afea0ed335aa796f) ([#13253](https://www.github.com/tauri-apps/tauri/pull/13253) by [@Armaldio](https://www.github.com/tauri-apps/tauri/../../Armaldio)) Allow electron to run the CLI directly - [`a2abe2e6b`](https://www.github.com/tauri-apps/tauri/commit/a2abe2e6bcb9e1eed8484240dfdb76a5bc28ae58) ([#14607](https://www.github.com/tauri-apps/tauri/pull/14607) by [@sftse](https://www.github.com/tauri-apps/tauri/../../sftse)) Simplified internal representation of `features: Option>` with `Vec`, no user facing changes - [`84b04c4a8`](https://www.github.com/tauri-apps/tauri/commit/84b04c4a8d3310b7a7091d10e36244bf94996e51) ([#14759](https://www.github.com/tauri-apps/tauri/pull/14759) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Added new environment variables for `tauri signer sign` command, to align with existing environment variables used in `tauri build`, `tauri bundle` and `tauri signer generate` - `TAURI_SIGNING_PRIVATE_KEY` - `TAURI_SIGNING_PRIVATE_KEY_PATH` - `TAURI_SIGNING_PRIVATE_KEY_PASSWORD` The old environment variables are deprecated and will be removed in a future release. - `TAURI_PRIVATE_KEY` - `TAURI_PRIVATE_KEY_PATH` - `TAURI_PRIVATE_KEY_PASSWORD` ### Bug Fixes - [`62aa13a12`](https://www.github.com/tauri-apps/tauri/commit/62aa13a124ef46bb5ce9887a2a574dd35ef86d4f) ([#14629](https://www.github.com/tauri-apps/tauri/pull/14629) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix `android build`'s `--aab` and `--apk` flags requiring a value to be provided. - [`eccff9758`](https://www.github.com/tauri-apps/tauri/commit/eccff97588232055bd0cafd83e6ee03d11a501fb) ([#14779](https://www.github.com/tauri-apps/tauri/pull/14779) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix empty associated-domains entitlements when domains are not configured for deep links. - [`ea31b07f1`](https://www.github.com/tauri-apps/tauri/commit/ea31b07f19e0aa467ed0f921f60575cfe09809c8) ([#14789](https://www.github.com/tauri-apps/tauri/pull/14789) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fixed the command description for `tauri inspect` - [`7fca58230`](https://www.github.com/tauri-apps/tauri/commit/7fca58230f97c3e6834134419514a0c7dbbe784b) ([#14830](https://www.github.com/tauri-apps/tauri/pull/14830) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Updated `nsis_tauri_utils` to 0.5.3: - Use an alternative method `CreateProcessWithTokenW` to run programs as user, this fixed a problem that the program launched with the previous method can't query its own handle - [`53611c4d7`](https://www.github.com/tauri-apps/tauri/commit/53611c4d7bdaf89b9a5d7c46a9c4bf4e34216148) ([#14747](https://www.github.com/tauri-apps/tauri/pull/14747) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Only watch dependent workspace members when running `tauri dev` instead of watching on all members - [`1b0e335d3`](https://www.github.com/tauri-apps/tauri/commit/1b0e335d3f3445948d6590f7e074275d97cd9859) ([#14713](https://www.github.com/tauri-apps/tauri/pull/14713) by [@wasuaje](https://www.github.com/tauri-apps/tauri/../../wasuaje)) `tauri signer sign` doesn't work for files without an extension ### What's Changed - [`e3fdcb500`](https://www.github.com/tauri-apps/tauri/commit/e3fdcb5002b362b46cde2a1971e4e7f2a1161208) ([#14836](https://www.github.com/tauri-apps/tauri/pull/14836) by [@sftse](https://www.github.com/tauri-apps/tauri/../../sftse)) Continued refactors of tauri-cli, fix too weak atomics. - [`0575dd287`](https://www.github.com/tauri-apps/tauri/commit/0575dd287e021b61d2aedf64d62ae84a2c925fb4) ([#14521](https://www.github.com/tauri-apps/tauri/pull/14521) by [@kandrelczyk](https://www.github.com/tauri-apps/tauri/../../kandrelczyk)) Change the way bundle type information is added to binary files. Instead of looking up the value of a variable we simply look for the default value. - [`7f7d9aac2`](https://www.github.com/tauri-apps/tauri/commit/7f7d9aac214e22d9492490543f7a9bcae0a6659e) ([#14668](https://www.github.com/tauri-apps/tauri/pull/14668) by [@sftse](https://www.github.com/tauri-apps/tauri/../../sftse)) Refactored internal use of static on config and directory resolvings, no user facing changes, please report any regressions if you encounter any ### Dependencies - Upgraded to `tauri-cli@2.10.0` ## \[2.9.6] ### Dependencies - Upgraded to `tauri-cli@2.9.6` ## \[2.9.5] ### Bug Fixes - [`f855caf8a`](https://www.github.com/tauri-apps/tauri/commit/f855caf8a3830aa5dd6d0b039312866a5d9c3606) ([#14481](https://www.github.com/tauri-apps/tauri/pull/14481) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fixed the mismatched tauri package versions check didn't work for pnpm ### Performance Improvements - [`ce98d87ce`](https://www.github.com/tauri-apps/tauri/commit/ce98d87ce0aaa907285852eb80691197424e03c3) ([#14474](https://www.github.com/tauri-apps/tauri/pull/14474) by [@Tunglies](https://www.github.com/tauri-apps/tauri/../../Tunglies)) refactor: remove needless collect. No user facing changes. ### Dependencies - Upgraded to `tauri-cli@2.9.5` ## \[2.9.4] ### Bug Fixes - [`b586ecf1f`](https://www.github.com/tauri-apps/tauri/commit/b586ecf1f4b3b087f9aa6c4668c2c18b1b7925f4) ([#14416](https://www.github.com/tauri-apps/tauri/pull/14416) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Premultiply Alpha before Resizing which gets rid of the gray fringe around the icons for svg images. ### Dependencies - Upgraded to `tauri-cli@2.9.4` ## \[2.9.3] ### Bug Fixes - [`fd8c30b4f`](https://www.github.com/tauri-apps/tauri/commit/fd8c30b4f1bca8dd7165c5c0ebe7fbfd17662153) ([#14353](https://www.github.com/tauri-apps/tauri/pull/14353) by [@ChaseKnowlden](https://www.github.com/tauri-apps/tauri/../../ChaseKnowlden)) Premultiply Alpha before Resizing which gets rid of the gray fringe around the icons. ### Dependencies - Upgraded to `tauri-cli@2.9.3` ## \[2.9.2] ### Dependencies - Upgraded to `tauri-cli@2.9.2` ## \[2.9.1] ### Dependencies - Upgraded to `tauri-cli@2.9.1` ## \[2.9.0] ### New Features - [`3b4fac201`](https://www.github.com/tauri-apps/tauri/commit/3b4fac2017832d426dd07c5e24e26684eda57f7b) ([#14194](https://www.github.com/tauri-apps/tauri/pull/14194)) Add `tauri.conf.json > bundle > android > autoIncrementVersionCode` config option to automatically increment the Android version code. - [`673867aa0`](https://www.github.com/tauri-apps/tauri/commit/673867aa0e1ccd766ee879ffe96aba58c758613c) ([#14094](https://www.github.com/tauri-apps/tauri/pull/14094)) Try to detect ANDROID_HOME and NDK_HOME environment variables from default system locations and install them if needed using the Android Studio command line tools. - [`3d6868d09`](https://www.github.com/tauri-apps/tauri/commit/3d6868d09c323d68a152f3c3f8c7256311bd020a) ([#14128](https://www.github.com/tauri-apps/tauri/pull/14128)) Added support to defining the content type of the declared file association on macOS (maps to LSItemContentTypes property). - [`3d6868d09`](https://www.github.com/tauri-apps/tauri/commit/3d6868d09c323d68a152f3c3f8c7256311bd020a) ([#14128](https://www.github.com/tauri-apps/tauri/pull/14128)) Added support to defining the metadata for custom types declared in `tauri.conf.json > bundle > fileAssociations > exportedType` via the `UTExportedTypeDeclarations` Info.plist property. - [`ed7c9a410`](https://www.github.com/tauri-apps/tauri/commit/ed7c9a4100e08c002212265549d12130d021ad1e) ([#14108](https://www.github.com/tauri-apps/tauri/pull/14108)) Added `bundle > macOS > infoPlist` and `bundle > iOS > infoPlist` configurations to allow defining custom Info.plist extensions. - [`75082cc5b`](https://www.github.com/tauri-apps/tauri/commit/75082cc5b340e30e2c4b4cd4bd6a1fe5382164aa) ([#14120](https://www.github.com/tauri-apps/tauri/pull/14120)) Added `ios run` and `android run` commands to run the app in production mode. - [`cc8c0b531`](https://www.github.com/tauri-apps/tauri/commit/cc8c0b53171173dbd1d01781a50de1a3ea159031) ([#14031](https://www.github.com/tauri-apps/tauri/pull/14031)) Added support to universal app links on macOS with the `plugins > deep-link > desktop > domains` configuration. ### Enhancements - [`b5aa01870`](https://www.github.com/tauri-apps/tauri/commit/b5aa018702bf45dc98297698f9b7d238705865a6) ([#14268](https://www.github.com/tauri-apps/tauri/pull/14268)) Update cargo-mobile2 to 0.21, enhancing error messages and opening Xcode when multiple apps are installed. - [`55453e845`](https://www.github.com/tauri-apps/tauri/commit/55453e8453d927b8197f1ba9f26fd944482938f7) ([#14262](https://www.github.com/tauri-apps/tauri/pull/14262)) Check mismatched versions in `tauri info` - [`1a6627ee7`](https://www.github.com/tauri-apps/tauri/commit/1a6627ee7d085a4e66784e2705254714d68c7244) ([#14122](https://www.github.com/tauri-apps/tauri/pull/14122)) Set a default log level filter when running `tauri add log`. - [`b06b3bd09`](https://www.github.com/tauri-apps/tauri/commit/b06b3bd091b0fed26cdcfb23cacb0462a7a9cc2d) ([#14126](https://www.github.com/tauri-apps/tauri/pull/14126)) Improve error messages with more context. - [`f6622a3e3`](https://www.github.com/tauri-apps/tauri/commit/f6622a3e342f5dd5fb3cf6e0f79fb309a10e9b3d) ([#14129](https://www.github.com/tauri-apps/tauri/pull/14129)) Prompt to install the iOS platform if it isn't installed yet. - [`6bbb530fd`](https://www.github.com/tauri-apps/tauri/commit/6bbb530fd5edfc07b180a4f3782b8566872ca3b1) ([#14105](https://www.github.com/tauri-apps/tauri/pull/14105)) Warn if productName is empty when initializing mobile project. ### Bug Fixes - [`19fb6f7cb`](https://www.github.com/tauri-apps/tauri/commit/19fb6f7cb0d702cb2f25f6f2d1e11014d9dada5d) ([#14146](https://www.github.com/tauri-apps/tauri/pull/14146)) Strip Windows-only extensions from the binary path so an Android project initialized on Windows can be used on UNIX systems. - [`19fb6f7cb`](https://www.github.com/tauri-apps/tauri/commit/19fb6f7cb0d702cb2f25f6f2d1e11014d9dada5d) ([#14146](https://www.github.com/tauri-apps/tauri/pull/14146)) Enhance Android build script usage on Windows by attempting to run cmd, bat and exe formats. - [`28a2f9bc5`](https://www.github.com/tauri-apps/tauri/commit/28a2f9bc55f658eb71ef1a970ff9f791346f7682) ([#14101](https://www.github.com/tauri-apps/tauri/pull/14101)) Fix iOS CLI usage after modifying the package name. - [`d2938486e`](https://www.github.com/tauri-apps/tauri/commit/d2938486e9d974debd90c15d7160b8a17bf4d763) ([#14261](https://www.github.com/tauri-apps/tauri/pull/14261)) Replaced the non-standard nerd font character with ` ⱼₛ ` in `tarui info` - [`25e920e16`](https://www.github.com/tauri-apps/tauri/commit/25e920e169db900ca4f07c2bb9eb290e9f9f2c7d) ([#14298](https://www.github.com/tauri-apps/tauri/pull/14298)) Wait for dev server to exit before exiting the CLI when the app is closed on `tauri dev --no-watch`. - [`b0012424c`](https://www.github.com/tauri-apps/tauri/commit/b0012424c5f432debfa42ba145e2672966d5f6d5) ([#14115](https://www.github.com/tauri-apps/tauri/pull/14115)) Resolve local IP address when `tauri.conf.json > build > devUrl` host is `0.0.0.0`. - [`abf7e8850`](https://www.github.com/tauri-apps/tauri/commit/abf7e8850ba41e7173e9e9a3fdd6dfb8f357d72d) ([#14118](https://www.github.com/tauri-apps/tauri/pull/14118)) Fixes mobile project initialization when using `pnpx` or `pnpm dlx`. ### Dependencies - Upgraded to `tauri-cli@2.9.0` ## \[2.8.4] ### Enhancements - [`f70b28529`](https://www.github.com/tauri-apps/tauri/commit/f70b28529d226a2dec2f41709d8934f8f5adab25) ([#14093](https://www.github.com/tauri-apps/tauri/pull/14093) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Ensure Rust targets for mobile are installed when running the dev and build commands (previously only checked on init). - [`a9b342125`](https://www.github.com/tauri-apps/tauri/commit/a9b342125d5ac1bc9a4b2e8b5f73e8ca3cbcb8b2) ([#14114](https://www.github.com/tauri-apps/tauri/pull/14114) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix iOS dev and build targeting the simulator on Intel machines. - [`61b9b681e`](https://www.github.com/tauri-apps/tauri/commit/61b9b681e88067a53b79d2318ae005dc25addcd6) ([#14111](https://www.github.com/tauri-apps/tauri/pull/14111) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Retain `RUST_*` environment variables when running the mobile commands. - [`c23bec62d`](https://www.github.com/tauri-apps/tauri/commit/c23bec62d6d5724798869681aa1534423aae28e2) ([#14083](https://www.github.com/tauri-apps/tauri/pull/14083) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Tauri now ignores `macOS.minimumSystemVersion` in `tauri dev` to prevent forced rebuilds of macOS specific dependencies when using something like `rust-analyzer` at the same time as `tauri dev`. ### Bug Fixes - [`c37a29833`](https://www.github.com/tauri-apps/tauri/commit/c37a298331d6d744b15d32d55a2db83c884a3d6a) ([#14112](https://www.github.com/tauri-apps/tauri/pull/14112) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix usage with Deno failing with `ReferenceError: require is not defined`. - [`bcf000c0a`](https://www.github.com/tauri-apps/tauri/commit/bcf000c0a8607eedf488fb949b982f519abda43d) ([#14110](https://www.github.com/tauri-apps/tauri/pull/14110) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes running `ios` commands with `deno` crashing due to incorrect current working directory resolution. - [`7db7142f9`](https://www.github.com/tauri-apps/tauri/commit/7db7142f9ff7dc2f5719602e199b77129ceb19d3) ([#14119](https://www.github.com/tauri-apps/tauri/pull/14119) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes empty device name when using an Android emulator causing the emulator to never be detected as running. - [`956b4fd6f`](https://www.github.com/tauri-apps/tauri/commit/956b4fd6ffbb4312123b107ca96c87a001359b9d) ([#14106](https://www.github.com/tauri-apps/tauri/pull/14106) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Use the correct export method on Xcode < 15.4. ### Dependencies - Upgraded to `tauri-cli@2.8.4` ## \[2.8.3] ### Bug Fixes - [`0ac89d3b6`](https://www.github.com/tauri-apps/tauri/commit/0ac89d3b6c8c4a4826a4c42726e4f4a8941b3fde) ([#14078](https://www.github.com/tauri-apps/tauri/pull/14078) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Updated `cargo-mobile2` to allow running on iOS simulators that have a higher version than the XCode SDK. This fixes compatiblity issues with Apple's recent "iOS 18.5 + iOS 18.6 Simulator" platform support component. ### Dependencies - Upgraded to `tauri-cli@2.8.3` ## \[2.8.2] ### Dependencies - Upgraded to `tauri-cli@2.8.1` ## \[2.8.1] ### Bug Fixes - [`f0172a454`](https://www.github.com/tauri-apps/tauri/commit/f0172a454aea101cb699233be3d73dbf86e64a31) ([#14038](https://www.github.com/tauri-apps/tauri/pull/14038) by [@KushalMeghani1644](https://www.github.com/tauri-apps/tauri/../../KushalMeghani1644)) Fixes `removeDataStore` return type. ## \[2.8.0] ### New Features - [`91508c0b8`](https://www.github.com/tauri-apps/tauri/commit/91508c0b8d16ec61c7706e93b711c5a85aaffb4a) ([#13881](https://www.github.com/tauri-apps/tauri/pull/13881) by [@pepperoni505](https://www.github.com/tauri-apps/tauri/../../pepperoni505)) Introduces a new configuration option that allows you to specify custom folders to watch for changes when running `tauri dev`. - [`bc4afe7dd`](https://www.github.com/tauri-apps/tauri/commit/bc4afe7dd4780f02c2d4b1f07d97185fbc5d2bba) ([#13993](https://www.github.com/tauri-apps/tauri/pull/13993) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Check installed plugin NPM/crate versions for incompatible releases. - [`0c402bfb6`](https://www.github.com/tauri-apps/tauri/commit/0c402bfb6bd0bec24d928fcabe2ffef1f5cff19a) ([#13997](https://www.github.com/tauri-apps/tauri/pull/13997) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Increase default iOS deployment target iOS to 14.0. - [`d6d5f3707`](https://www.github.com/tauri-apps/tauri/commit/d6d5f3707768a094ff7e961ae75ba0398d772655) ([#13358](https://www.github.com/tauri-apps/tauri/pull/13358) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Added `--root-certificate-path` option to `android dev` and `ios dev` to be able to connect to HTTPS dev servers. ### Enhancements - [`8b465a12b`](https://www.github.com/tauri-apps/tauri/commit/8b465a12ba73e94d7a3995defd9cc362d15eeebe) ([#13913](https://www.github.com/tauri-apps/tauri/pull/13913) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) The bundler now pulls the latest AppImage linuxdeploy plugin instead of using the built-in one. This should remove the libfuse requirement. - [`390cb9c36`](https://www.github.com/tauri-apps/tauri/commit/390cb9c36a4e2416891b64514e7ad5fc0a85ccf2) ([#13953](https://www.github.com/tauri-apps/tauri/pull/13953) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Reduced the log level of the binary patcher crate `goblin` to only show its debug logs in `-vv` and above. - [`4475e93e1`](https://www.github.com/tauri-apps/tauri/commit/4475e93e136e9e2bd5f3c7817fa2040924f630f6) ([#13824](https://www.github.com/tauri-apps/tauri/pull/13824) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) The bundler and cli will now read TLS Certificates installed on the system when downloading tools and checking versions. ### Bug Fixes - [`f0dcf9637`](https://www.github.com/tauri-apps/tauri/commit/f0dcf9637cc0d42eda05fed7dd6c5ff98bbf19ae) ([#13980](https://www.github.com/tauri-apps/tauri/pull/13980) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix the generated plugin init code of `tauri add` for `tauri-plugin-autostart` and `tauri-plugin-single-instance` - [`4d270a96a`](https://www.github.com/tauri-apps/tauri/commit/4d270a96a891ae83f7df751abcbe12b7072212d5) ([#13943](https://www.github.com/tauri-apps/tauri/pull/13943) by [@acx0](https://www.github.com/tauri-apps/tauri/../../acx0)) Fix codesigning verification failures caused by binary-patching during bundling - [`b21d86a8a`](https://www.github.com/tauri-apps/tauri/commit/b21d86a8a3ef29f16628b7d4de17ce1214e9bf49) ([#13981](https://www.github.com/tauri-apps/tauri/pull/13981) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix `tauri permission add` could add duplicated permissions to the capability files - [`9c938be45`](https://www.github.com/tauri-apps/tauri/commit/9c938be4520fce9204361f3b59439844bc5c91e8) ([#13912](https://www.github.com/tauri-apps/tauri/pull/13912) by [@takecchi](https://www.github.com/tauri-apps/tauri/../../takecchi)) Properly migrate svelte to v5 in the plugin example template ### Dependencies - Upgraded to `tauri-cli@2.8.0` ## \[2.7.1] ### Dependencies - Upgraded to `tauri-cli@2.7.1` ## \[2.7.0] ### New Features - [`33d079392`](https://www.github.com/tauri-apps/tauri/commit/33d079392ac4a5a153b7d8a6d82fefd6f54a2bdf) ([#13811](https://www.github.com/tauri-apps/tauri/pull/13811) by [@mhbagheri-99](https://www.github.com/tauri-apps/tauri/../../mhbagheri-99)) Allow runner configuration to be an object with cmd, cwd, and args properties. The runner can now be configured as `{ "cmd": "my_runner", "cwd": "/path", "args": ["--quiet"] }` while maintaining backwards compatibility with the existing string format. ### Enhancements - [`232265c70`](https://www.github.com/tauri-apps/tauri/commit/232265c70e1c213bbb3f84b5541ddc07d330fce1) ([#13209](https://www.github.com/tauri-apps/tauri/pull/13209) by [@kandrelczyk](https://www.github.com/tauri-apps/tauri/../../kandrelczyk)) Binaries are patched before bundling to add the type of a bundle they will placed in. This information will be used during update process to select the correct target. ### Bug Fixes - [`916aeaa48`](https://www.github.com/tauri-apps/tauri/commit/916aeaa48646a483a78e51cfe1633800ee62c37c) ([#13781](https://www.github.com/tauri-apps/tauri/pull/13781) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes Android dev and build commands reading `tauri.ios.conf.json` instead of `tauri.android.conf.json` to merge platform-specific configuration. - [`0f248b111`](https://www.github.com/tauri-apps/tauri/commit/0f248b111ffb8af934eaf64bd8f4591e628da786) ([#13799](https://www.github.com/tauri-apps/tauri/pull/13799) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Install iOS dependencies when needed. - [`7a6fd5b75`](https://www.github.com/tauri-apps/tauri/commit/7a6fd5b75d61071e2771f6277c0376ec206d302a) ([#13863](https://www.github.com/tauri-apps/tauri/pull/13863) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) The AppImage bundler now pulls the AppRun binaries from our GitHub mirror, fixing 404 errors. - [`bda830410`](https://www.github.com/tauri-apps/tauri/commit/bda8304107da7ca60caaba5674faa793491898c6) ([#13833](https://www.github.com/tauri-apps/tauri/pull/13833) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fail with an error when trying to migrate from v2 alpha - [`bda830410`](https://www.github.com/tauri-apps/tauri/commit/bda8304107da7ca60caaba5674faa793491898c6) ([#13833](https://www.github.com/tauri-apps/tauri/pull/13833) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Use v2 stable instead of v2-rc when migrating from v2-beta ### Dependencies - Upgraded to `tauri-cli@2.7.0` ## \[2.6.2] ### Bug Fixes - [`cbd962972`](https://www.github.com/tauri-apps/tauri/commit/cbd9629729ed6eb208ba2234d014c11c4e9f1c8c) ([#13730](https://www.github.com/tauri-apps/tauri/pull/13730) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Load `--config` arguments when running the Xcode and Android Studio build scripts. ### Dependencies - Upgraded to `tauri-cli@2.6.2` ## \[2.6.1] ### Dependencies - Upgraded to `tauri-cli@2.6.1` ## \[2.6.0] ### New Features - [`414619c36`](https://www.github.com/tauri-apps/tauri/commit/414619c36e94e21939534dd72c0438b93da75546) ([#13536](https://www.github.com/tauri-apps/tauri/pull/13536) by [@Tunglies](https://www.github.com/tauri-apps/tauri/../../Tunglies)) Added support for the `bundleName` property in the macOS bundler configuration. This allows specifying the `CFBundleName` value for generated macOS bundles. - [`3242e1c94`](https://www.github.com/tauri-apps/tauri/commit/3242e1c946c441b58665ba5d612f3a3f1eafe0b6) ([#13659](https://www.github.com/tauri-apps/tauri/pull/13659) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Allow passing Cargo arguments to mobile dev and build commands. - [`d1ce9af62`](https://www.github.com/tauri-apps/tauri/commit/d1ce9af62881e3f7d86a495c9c40df5b7f9d1c04) ([#13660](https://www.github.com/tauri-apps/tauri/pull/13660) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Allow passing `--config` arguments to the `ios init` and `android init` commands to tweak the configuration used to initialize the mobile projects. - [`7322f0579`](https://www.github.com/tauri-apps/tauri/commit/7322f057923aaec88960ad5556776774b745762f) ([#13502](https://www.github.com/tauri-apps/tauri/pull/13502) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Allow using `CheckIfAppIsRunning` macro inside NSIS hooks, for example `!insertmacro CheckIfAppIsRunning "another-executable.exe" "Another Executable"`. - [`4a880ca69`](https://www.github.com/tauri-apps/tauri/commit/4a880ca697bab6d63a2a51ea94e1988cc8c4ea4a) ([#13658](https://www.github.com/tauri-apps/tauri/pull/13658) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Synchronize Tauri config productName changes with the iOS Xcode project. - [`8ee14a864`](https://www.github.com/tauri-apps/tauri/commit/8ee14a86480510c15823586cf28084e615cb7a9c) ([#13618](https://www.github.com/tauri-apps/tauri/pull/13618) by [@Sky-walkerX](https://www.github.com/tauri-apps/tauri/../../Sky-walkerX)) Warn the user that the app id shouldn't end in `.app` because it conflicts with the application bundle extension on macOS ### Bug Fixes - [`35aa7e121`](https://www.github.com/tauri-apps/tauri/commit/35aa7e1218f34d0805e280e3ec32529d0cb0d733) ([#13294](https://www.github.com/tauri-apps/tauri/pull/13294) by [@kingsword09](https://www.github.com/tauri-apps/tauri/../../kingsword09)) fix: allow the target directory to be inside frontendDir as long as it is not the Rust target directory inside frontendDir. - [`ec6065fa4`](https://www.github.com/tauri-apps/tauri/commit/ec6065fa4a6427266ecfb0c0f62f008574bb7880) ([#13625](https://www.github.com/tauri-apps/tauri/pull/13625) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes Android and iOS dev/build commands not working when the app identifier is being modified by the `--config` option. - [`5a5291d66`](https://www.github.com/tauri-apps/tauri/commit/5a5291d66cb8a955c9d4f8e975782646ac0cc6e7) ([#13483](https://www.github.com/tauri-apps/tauri/pull/13483) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix simulator build detection on Xcode. ### Dependencies - Upgraded to `tauri-cli@2.6.0` - [`9c16eefa3`](https://www.github.com/tauri-apps/tauri/commit/9c16eefa319b4697bac1d1019bbb5f93eca63173) ([#13629](https://www.github.com/tauri-apps/tauri/pull/13629) by [@sftse](https://www.github.com/tauri-apps/tauri/../../sftse)) Update html5ever to 0.29 and kuchikiki to version 0.8.8-speedreader. ## \[2.5.0] ### New Features - [`0aa48fb9e`](https://www.github.com/tauri-apps/tauri/commit/0aa48fb9e4b9d7b5bf3522000a76ebc1836394ed) ([#13030](https://www.github.com/tauri-apps/tauri/pull/13030)) Added `bundleVersion` to iOS and macOS configuration to support specifying a `CFBundleVersion`. ### Enhancements - [`ad3fd3890`](https://www.github.com/tauri-apps/tauri/commit/ad3fd3890f1fa26a9f9be04ff1bc156d6dd2a8bc) ([#13152](https://www.github.com/tauri-apps/tauri/pull/13152)) Detect package manager from environment variable `npm_config_user_agent` first - [`82406c61e`](https://www.github.com/tauri-apps/tauri/commit/82406c61e0fbb775ef00791ccab45349325bdd45) ([#13231](https://www.github.com/tauri-apps/tauri/pull/13231)) Improve iOS simulator usage, checking if Xcode iOS SDK is installed and allowing usage of Simulator for older iOS releases (previously only supported when running on Xcode via `ios dev --open`). ### Bug Fixes - [`2dccfab53`](https://www.github.com/tauri-apps/tauri/commit/2dccfab5321fef55d45f3a4c674b6151b1c4424a) ([#13236](https://www.github.com/tauri-apps/tauri/pull/13236)) Fix `fileAssociations` missing `LSHandlerRank` on macOS. - [`080252903`](https://www.github.com/tauri-apps/tauri/commit/0802529031c4fd309edff374a8694e93ddec161d) ([#13210](https://www.github.com/tauri-apps/tauri/pull/13210)) Fixes iOS dev not working on Xcode 16.3 simulators. To apply the fix, either regenerate the Xcode project with `rm -r src-tauri/gen/apple && tauri ios init` or remove the `arm64-sim` architecture from the Xcode project. ### Dependencies - Upgraded to `tauri-cli@2.5.0` ## \[2.4.1] ### Enhancements - [`f805061d1`](https://www.github.com/tauri-apps/tauri/commit/f805061d1152bc4790dbdb9475a506afcdd1de75) ([#13079](https://www.github.com/tauri-apps/tauri/pull/13079) by [@Pietagorh](https://www.github.com/tauri-apps/tauri/../../Pietagorh)) Add support for passing TOML and JSON5 config files to `--config` arg ### Bug Fixes - [`794af778e`](https://www.github.com/tauri-apps/tauri/commit/794af778e4915ffb6a4fe9bae8fba04bc880503d) ([#13117](https://www.github.com/tauri-apps/tauri/pull/13117) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix setting merge config value to null with `--config` arg no longer works ### Dependencies - Upgraded to `tauri-cli@2.4.1` ## \[2.4.0] ### New Features - [`d91bfa5cb`](https://www.github.com/tauri-apps/tauri/commit/d91bfa5cb921a078758edd45ef3eaff71358d1eb) ([#12970](https://www.github.com/tauri-apps/tauri/pull/12970) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Allow merging multiple configuration values on `tauri dev`, `tauri build`, `tauri bundle`, `tauri android dev`, `tauri android build`, `tauri ios dev` and `tauri ios build`. - [`30f5a1553`](https://www.github.com/tauri-apps/tauri/commit/30f5a1553d3c0ce460c9006764200a9210915a44) ([#12366](https://www.github.com/tauri-apps/tauri/pull/12366) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Added `trafficLightPosition` window configuration to set the traffic light buttons position on macOS. ### Enhancements - [`f981a5ee8`](https://www.github.com/tauri-apps/tauri/commit/f981a5ee8b292b9ea09329f60cecc7f688dda734) ([#12602](https://www.github.com/tauri-apps/tauri/pull/12602) by [@kxxt](https://www.github.com/tauri-apps/tauri/../../kxxt)) Add basic support for linux riscv64 platform. ### Bug Fixes - [`0c4700e99`](https://www.github.com/tauri-apps/tauri/commit/0c4700e9907f242eabe579eb6149a1d75174185c) ([#12985](https://www.github.com/tauri-apps/tauri/pull/12985) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) The cli will now accept `--bundles updater` again. It's still no-op as it has been for all v2 versions. If you want to build updater artifacts, enable `createUpdaterArtifacts` in `tauri.conf.json`. - [`b83921226`](https://www.github.com/tauri-apps/tauri/commit/b83921226cb3084992bb5357e7e39a09ea97843e) ([#12977](https://www.github.com/tauri-apps/tauri/pull/12977) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix `tauri ios` commands using the wrong working directory with `bun@>1.2`. - [`f268b3dbd`](https://www.github.com/tauri-apps/tauri/commit/f268b3dbdf313484c85b4a1f69cd7cec63049f35) ([#12871](https://www.github.com/tauri-apps/tauri/pull/12871) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Ignore parent .gitignore files on the Tauri project path detection. ### Dependencies - Upgraded to `tauri-cli@2.4.0` ## \[2.3.1] ### Dependencies - Upgraded to `tauri-cli@2.3.1` ## \[2.3.0] ### Enhancements - [`a2d36b8c3`](https://www.github.com/tauri-apps/tauri/commit/a2d36b8c34a8dcfc6736797ca5cd4665faf75e7e) ([#12181](https://www.github.com/tauri-apps/tauri/pull/12181) by [@bastiankistner](https://www.github.com/tauri-apps/tauri/../../bastiankistner)) Add an option to change the default background throttling policy (currently for WebKit only). ### Dependencies - Upgraded to `tauri-cli@2.3.0` ## \[2.2.7] ### Bug Fixes - [`8e9134c4a`](https://www.github.com/tauri-apps/tauri/commit/8e9134c4a2047329be0dbb868b7ae061a9d3f190) ([#12511](https://www.github.com/tauri-apps/tauri/pull/12511) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused `tauri dev` to fail because of an incorrect `--bins` flag. ### Dependencies - Upgraded to `tauri-cli@2.2.7` ## \[2.2.6] ### Enhancements - [`1a86974aa`](https://www.github.com/tauri-apps/tauri/commit/1a86974aa3d09957c6b1142a17bbfed9998798fd) ([#12406](https://www.github.com/tauri-apps/tauri/pull/12406) by [@bradleat](https://www.github.com/tauri-apps/tauri/../../bradleat)) `ios build --open` will now let xcode start the rust build process. - [`0b79af711`](https://www.github.com/tauri-apps/tauri/commit/0b79af711430934362602fb950c3e4cb5b59cf9c) ([#12438](https://www.github.com/tauri-apps/tauri/pull/12438) by [@3lpsy](https://www.github.com/tauri-apps/tauri/../../3lpsy)) Log the command used to start the rust app in development. ### Dependencies - Upgraded to `tauri-cli@2.2.6` ## \[2.2.5] ### Dependencies - Upgraded to `tauri-cli@2.2.5` ## \[2.2.4] ### Bug Fixes - [`cad550445`](https://www.github.com/tauri-apps/tauri/commit/cad5504455ffa53e297cebff473c113b1afa5d29) ([#12354](https://www.github.com/tauri-apps/tauri/pull/12354) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed and issue that caused `tauri add` to try to install incorrect npm packages. ### Dependencies - Upgraded to `tauri-cli@2.2.4` ## \[2.2.3] ### Enhancements - [`a0f2c84d5`](https://www.github.com/tauri-apps/tauri/commit/a0f2c84d51f5086c5055867d6f61ea90c463a26c) ([#12204](https://www.github.com/tauri-apps/tauri/pull/12204) by [@pjf-dev](https://www.github.com/tauri-apps/tauri/../../pjf-dev)) Enhance `tauri icon` command by including 64x64 png size in default icon sizes. ### Bug Fixes - [`98f62e65a`](https://www.github.com/tauri-apps/tauri/commit/98f62e65a27a375272c6b4d9f34c23e142b9d3a6) ([#12246](https://www.github.com/tauri-apps/tauri/pull/12246) by [@marcomq](https://www.github.com/tauri-apps/tauri/../../marcomq)) Properly add NPM packages for community plugins when using the `tauri add` command. - [`b9a99a5c6`](https://www.github.com/tauri-apps/tauri/commit/b9a99a5c69d8a2a1a3ff30e500b46872258dca15) ([#12297](https://www.github.com/tauri-apps/tauri/pull/12297) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused the built-in dev server to constantly refresh on Linux. This only affected users who do not have `devUrl` point to a URL. - [`ef21ed9ac`](https://www.github.com/tauri-apps/tauri/commit/ef21ed9ac1c045c38b0c04e3d71a441694abc257) ([#12290](https://www.github.com/tauri-apps/tauri/pull/12290) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix iOS build failing when the development team contains spaces. ### Dependencies - Upgraded to `tauri-cli@2.2.3` ## \[2.2.2] ### Bug Fixes - [`26fc9558f`](https://www.github.com/tauri-apps/tauri/commit/26fc9558fe7b2fe649f61926da88f36110dd5707) ([#12178](https://www.github.com/tauri-apps/tauri/pull/12178) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused the `tauri dev` file watcher to exit after detecting file changes. ### Dependencies - Upgraded to `tauri-cli@2.2.2` ## \[2.2.1] ### Bug Fixes - [`881729448`](https://www.github.com/tauri-apps/tauri/commit/881729448c9abd0d0c7941a8a31c94119ce827af) ([#12164](https://www.github.com/tauri-apps/tauri/pull/12164) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused `tauri dev` to crash before showing the app on Linux. ### Dependencies - Upgraded to `tauri-cli@2.2.1` ## \[2.2.0] ### New Features - [`cccb308c7`](https://www.github.com/tauri-apps/tauri/commit/cccb308c7b559b0838138d6cea280665f060c925) ([#11562](https://www.github.com/tauri-apps/tauri/pull/11562) by [@jLynx](https://www.github.com/tauri-apps/tauri/../../jLynx)) Generate signature for `.deb` packages when `createUpdaterArtifacts` option is enabled. - [`74212d40d`](https://www.github.com/tauri-apps/tauri/commit/74212d40d80dba4501b3d4ae30104fa3d447bdf9) ([#11653](https://www.github.com/tauri-apps/tauri/pull/11653) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Include Linux destkop environment and session type in `tauri info` command. ### Enhancements - [`93a3a043d`](https://www.github.com/tauri-apps/tauri/commit/93a3a043d39cc96515d51d98beeb14261d3a246b) ([#11727](https://www.github.com/tauri-apps/tauri/pull/11727) by [@Kiyozz](https://www.github.com/tauri-apps/tauri/../../Kiyozz)) Add support for `Portuguese` language for NSIS windows installer. ### Bug Fixes - [`c8700656b`](https://www.github.com/tauri-apps/tauri/commit/c8700656be3001a0cc6e087f23aebd482430a85b) ([#11985](https://www.github.com/tauri-apps/tauri/pull/11985) by [@ShaunSHamilton](https://www.github.com/tauri-apps/tauri/../../ShaunSHamilton)) Fix `tauri remove` from removing object type (`{}`) permissions. - [`0ae06c5ca`](https://www.github.com/tauri-apps/tauri/commit/0ae06c5ca89cecd24154affdc69668f5e1e67d85) ([#11914](https://www.github.com/tauri-apps/tauri/pull/11914) by [@wtto00](https://www.github.com/tauri-apps/tauri/../../wtto00)) Fix the exclude path in file `Cargo.toml` of plugin template generated by cli. Path changed in [#9346](https://github.com/tauri-apps/tauri/pull/9346) ### Dependencies - Upgraded to `tauri-cli@2.2.0` ## \[2.1.0] ### New Features - [`6bf917941`](https://www.github.com/tauri-apps/tauri/commit/6bf917941ff0fcc49e86b3ba427340b75f3ce49c) ([#11322](https://www.github.com/tauri-apps/tauri/pull/11322) by [@ShaunSHamilton](https://www.github.com/tauri-apps/tauri/../../ShaunSHamilton)) Add `tauri remove` to remove plugins from projects. - [`058c0db72`](https://www.github.com/tauri-apps/tauri/commit/058c0db72f43fbe1574d0db654560e693755cd7e) ([#11584](https://www.github.com/tauri-apps/tauri/pull/11584) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `bundle > linux > rpm > compression` config option to control RPM bundle compression type and level. ### Enhancements - [`1f311832a`](https://www.github.com/tauri-apps/tauri/commit/1f311832ab5b2d62a533dfcf9b1d78bddf249ae8) ([#11405](https://www.github.com/tauri-apps/tauri/pull/11405) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add more context for errors when decoding secret and public keys for signing updater artifacts. - [`e0d1307d3`](https://www.github.com/tauri-apps/tauri/commit/e0d1307d3f78987d0059921a5ab01ea4b26e0ef1) ([#11414](https://www.github.com/tauri-apps/tauri/pull/11414) by [@Czxck001](https://www.github.com/tauri-apps/tauri/../../Czxck001)) Migrate the `$schema` Tauri configuration to the v2 format. - [`c43d5df15`](https://www.github.com/tauri-apps/tauri/commit/c43d5df15828ecffa606482ea2b60350c488c981) ([#11512](https://www.github.com/tauri-apps/tauri/pull/11512) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Associate a newly created capability file with the `main` window on the `tauri add` and `tauri permission add` commands. ### Bug Fixes - [`7af01ff2c`](https://www.github.com/tauri-apps/tauri/commit/7af01ff2ce623d727cd13a4c8a549c1c80031882) ([#11523](https://www.github.com/tauri-apps/tauri/pull/11523) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix `tauri migrate` failing to install NPM depenencies when running from Deno. - [`100a4455a`](https://www.github.com/tauri-apps/tauri/commit/100a4455aa48df508510bbc08273215bdf70c012) ([#11529](https://www.github.com/tauri-apps/tauri/pull/11529) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix detecting yarn berry (v2 and higher) in various tauri cli commands. - [`60e86d5f6`](https://www.github.com/tauri-apps/tauri/commit/60e86d5f6e0f0c769d34ef368cd8801a918d796d) ([#11624](https://www.github.com/tauri-apps/tauri/pull/11624) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Use the public network IP address on `android dev` by default on Windows. ### Dependencies - Upgraded to `tauri-cli@2.1.0` ## \[2.0.4] ### Enhancements - [`e4c9268b1`](https://www.github.com/tauri-apps/tauri/commit/e4c9268b19c614dc9ebb0895448fd16de7efee80) ([#11258](https://www.github.com/tauri-apps/tauri/pull/11258) by [@regexident](https://www.github.com/tauri-apps/tauri/../../regexident)) Support custom project directory structure where the Tauri app folder is not a subfolder of the frontend project. The frontend and Tauri app project paths can be set with the `TAURI_FRONTEND_PATH` and the `TAURI_APP_PATH` environment variables respectively. ### Dependencies - Upgraded to `tauri-cli@2.0.4` ## \[2.0.3] ### New Features - [`eda5713ea`](https://www.github.com/tauri-apps/tauri/commit/eda5713eab78d28182071ea25ceca5f1994f37ea) ([#11242](https://www.github.com/tauri-apps/tauri/pull/11242) by [@alex-sandri](https://www.github.com/tauri-apps/tauri/../../alex-sandri)) Add `Italian` to supported NSIS installer languages - [`b3563e3d6`](https://www.github.com/tauri-apps/tauri/commit/b3563e3d6ae8dc90ee68f25f575cd5538ab1915b) ([#11304](https://www.github.com/tauri-apps/tauri/pull/11304) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add Deno support in tauri-cli operations. ### Bug Fixes - [`d609bef9f`](https://www.github.com/tauri-apps/tauri/commit/d609bef9fd7cd6eeb2bd701558100bd9cfb6e6f6) ([#11314](https://www.github.com/tauri-apps/tauri/pull/11314) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix android invalid proguard file when using an `identifier` that contains a component that is a reserved kotlin keyword, like `in`, `class`, etc - [`069c05e44`](https://www.github.com/tauri-apps/tauri/commit/069c05e44fd6f30083fdc00dd6c0001278898592) ([#11315](https://www.github.com/tauri-apps/tauri/pull/11315) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix CLI crashing and failing to find a `.ico` file when `bundle > icon` option is using globs and doesn't have a string that ends with `.ico`. ### Dependencies - Upgraded to `tauri-cli@2.0.3` ## \[2.0.2] ### What's Changed - [`4475fbb50`](https://www.github.com/tauri-apps/tauri/commit/4475fbb502c5ffb3cea4de6bef1c7869be39bed6) ([#11208](https://www.github.com/tauri-apps/tauri/pull/11208) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Update cargo-mobile2 to 0.17.3, fixing lib name validation. - [`a49a19ffa`](https://www.github.com/tauri-apps/tauri/commit/a49a19ffa304f031fb1a04d31a567cc7f42a380a) ([#11218](https://www.github.com/tauri-apps/tauri/pull/11218)) Fix bundling `appimage`, `deb` and `rpm` bundles failing to open when using `mainBinaryName` with spaces. ### Dependencies - Upgraded to `tauri-cli@2.0.2` ## \[2.0.1] ### Dependencies - Upgraded to `tauri-cli@2.0.1` ## \[2.0.0] ### What's Changed - [`637285790`](https://www.github.com/tauri-apps/tauri/commit/6372857905ae9c0aedb7f482ddf6cf9f9836c9f2) Promote to v2 stable! ### Dependencies - Upgraded to `tauri-cli@2.0.0` ## \[2.0.0-rc.18] ### Enhancements - [`a08e6ffa6`](https://www.github.com/tauri-apps/tauri/commit/a08e6ffa6fe499553be3c4c620726d6031cd6dd3) ([#11185](https://www.github.com/tauri-apps/tauri/pull/11185) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Enhance port forwarding on `android dev` to be more resilient and tolerate delays when booting up devices. - [`6cfe7edf6`](https://www.github.com/tauri-apps/tauri/commit/6cfe7edf63636fdf66c429efdeb7bc9a0f404e9f) ([#11186](https://www.github.com/tauri-apps/tauri/pull/11186) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Retain logger verbosity on the `android-studio-script` and `xcode-script` commands. - [`60a5aea53`](https://www.github.com/tauri-apps/tauri/commit/60a5aea53db02ae6af325812ab97555f2c013d70) ([#11181](https://www.github.com/tauri-apps/tauri/pull/11181) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Set the `TRUNK_SERVE_ADDRESS` environment variable when running on iOS physical devices to support Trunk. ### Bug Fixes - [`f5d61822b`](https://www.github.com/tauri-apps/tauri/commit/f5d61822bf5988827776dd58bed75c19364e86bd) ([#11184](https://www.github.com/tauri-apps/tauri/pull/11184) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix iOS application not including the provided capabilities (entitlements). ### Dependencies - Upgraded to `tauri-cli@2.0.0-rc.18` ## \[2.0.0-rc.17] ### New Features - [`a944b9b05`](https://www.github.com/tauri-apps/tauri/commit/a944b9b05bc5ae6125ff451e86c5b207c511f3d7) ([#11118](https://www.github.com/tauri-apps/tauri/pull/11118) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `--github-workflows` flag for `tauri plugin new/init`. - [`f57a729cd`](https://www.github.com/tauri-apps/tauri/commit/f57a729cd8f7e10d8daf0b9d5b85f9c7ad530496) ([#11039](https://www.github.com/tauri-apps/tauri/pull/11039) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `tauri inspect wix-upgrade-code` to print default Upgrade Code for your MSI installer derived from `productName`. ### Bug Fixes - [`62b52f60a`](https://www.github.com/tauri-apps/tauri/commit/62b52f60a22ef84c4a2a2d9e662038b49f58e16c) ([#11064](https://www.github.com/tauri-apps/tauri/pull/11064) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix `tauri add` failing to add NPM depenency with `npm` package manager. - [`56e087471`](https://www.github.com/tauri-apps/tauri/commit/56e087471a347f6bee7422221a956925c60b17e3) ([#11100](https://www.github.com/tauri-apps/tauri/pull/11100) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix iOS xcode-script usage with `bun`. - [`b88e22a5f`](https://www.github.com/tauri-apps/tauri/commit/b88e22a5fe4e2e4376d6cad64d1e74d104ca8927) ([#11063](https://www.github.com/tauri-apps/tauri/pull/11063) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) The cli now only sets the iOS deployment target environment variable when building for iOS. - [`8d22c0c81`](https://www.github.com/tauri-apps/tauri/commit/8d22c0c814e7227d5e56ce9a08929045ccea1a1b) ([#11101](https://www.github.com/tauri-apps/tauri/pull/11101) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Only modify the iOS Xcode project "sign style" if we need to enforce manual signing. - [`df24cb944`](https://www.github.com/tauri-apps/tauri/commit/df24cb944249ee398f6c8ba8c19757b398eec701) ([#11168](https://www.github.com/tauri-apps/tauri/pull/11168) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes Xcode pbxproj file parsing not expecting `_` in build configuration IDs. ### Dependencies - Upgraded to `tauri-cli@2.0.0-rc.17` ### Breaking Changes - [`a944b9b05`](https://www.github.com/tauri-apps/tauri/commit/a944b9b05bc5ae6125ff451e86c5b207c511f3d7) ([#11118](https://www.github.com/tauri-apps/tauri/pull/11118) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) `tauri plugin init/new` will no longer generate a `.github` directory with workflows by default, instead use the new `--github-workflows` flag. ## \[2.0.0-rc.16] ### New Features - [`9bb8fc618`](https://www.github.com/tauri-apps/tauri/commit/9bb8fc6189a93bcb811588b36e710d0f7818a1f9) ([#11030](https://www.github.com/tauri-apps/tauri/pull/11030) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add `--no-example` flag for `tauri plugin new` and `tauri plugin init` to disable creation of an example project. ### Dependencies - Upgraded to `tauri-cli@2.0.0-rc.16` ## \[2.0.0-rc.15] ### Enhancements - [`5a0e922d4`](https://www.github.com/tauri-apps/tauri/commit/5a0e922d40dc3b7d9a8e3a65ccaf76d09f026cb8) ([#11007](https://www.github.com/tauri-apps/tauri/pull/11007) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Automatically discover the `src-tauri/src/main.rs` binary when it is not explicitly defined in the Cargo manifest bin array. ### Bug Fixes - [`94e9d476e`](https://www.github.com/tauri-apps/tauri/commit/94e9d476ef506b1b8c09f55b81620c7839f98086) ([#11011](https://www.github.com/tauri-apps/tauri/pull/11011) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix `main_binary_name` in custom wix and nsis templates including `.exe` ### Dependencies - Upgraded to `tauri-cli@2.0.0-rc.15` ## \[2.0.0-rc.14] ### Enhancements - [`6c5340f8b`](https://www.github.com/tauri-apps/tauri/commit/6c5340f8b2549dfe89f19656304e65cd670afc92) ([#11004](https://www.github.com/tauri-apps/tauri/pull/11004) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Added the `log` plugin to the app template, which is required to visualize logs on Android and iOS. - [`3ad2427dc`](https://www.github.com/tauri-apps/tauri/commit/3ad2427dc08f12c61edc726b587acce32eca1080) ([#10961](https://www.github.com/tauri-apps/tauri/pull/10961) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Only render app logs on iOS unless `-vv` is provided to the `ios dev` command. ### Dependencies - Upgraded to `tauri-cli@2.0.0-rc.13` ## \[2.0.0-rc.13] ### Bug Fixes - [`a5848af65`](https://www.github.com/tauri-apps/tauri/commit/a5848af65b10d89686314cf737b7fd9d91f99dd8) ([#10944](https://www.github.com/tauri-apps/tauri/pull/10944) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Synchronize app version (`tauri.conf.json > version` or `Cargo.toml > package > version`) with the `CFBundleVersion` and `CFBundleShortVersionString` Info.plist values. ### Dependencies - Upgraded to `tauri-cli@2.0.0-rc.12` ## \[2.0.0-rc.12] ### Dependencies - Upgraded to `tauri-cli@2.0.0-rc.11` ## \[2.0.0-rc.11] ### Enhancements - [`9c9644d15`](https://www.github.com/tauri-apps/tauri/commit/9c9644d155818d9efcad65b60aa985a59e767922) ([#10845](https://www.github.com/tauri-apps/tauri/pull/10845) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Enhance iOS library validation, checking libs built with link time optimization. ### Bug Fixes - [`b42683592`](https://www.github.com/tauri-apps/tauri/commit/b42683592d446f25c2005b59e9e3ec551175906d) ([#10847](https://www.github.com/tauri-apps/tauri/pull/10847) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes `ios build --target [aarch64-sim | x86_64]` failing to generate the app bundle for the iOS simulator. ### Dependencies - Upgraded to `tauri-cli@2.0.0-rc.10` ## \[2.0.0-rc.10] ### Bug Fixes - [`6faa03276`](https://www.github.com/tauri-apps/tauri/commit/6faa032766b23cd161503905d4c79365ff6c50d1) ([#10854](https://www.github.com/tauri-apps/tauri/pull/10854) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes iOS code signing failing on CI due to a missing development certificate. ### Dependencies - Upgraded to `tauri-cli@2.0.0-rc.9` ## \[2.0.0-rc.9] ### Bug Fixes - [`5af1f5dec`](https://www.github.com/tauri-apps/tauri/commit/5af1f5dec1bb98f335169df8c5e30c19a24cae07) ([#10851](https://www.github.com/tauri-apps/tauri/pull/10851) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes `ios build` failing to build iOS app in CI when using an API key for automatic signing. ### Dependencies - Upgraded to `tauri-cli@2.0.0-rc.9` ## \[2.0.0-rc.8] ### New Features - [`91e9e784a`](https://www.github.com/tauri-apps/tauri/commit/91e9e784aa59634e3fe6359f8b78d071d76a9e42) ([#10729](https://www.github.com/tauri-apps/tauri/pull/10729) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add plugins information in `tauri info` output - [`09e9dc1aa`](https://www.github.com/tauri-apps/tauri/commit/09e9dc1aab1b66aa6a3a009d5873db586abe76a0) ([#10752](https://www.github.com/tauri-apps/tauri/pull/10752) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Allow Xcode to manage iOS code sign and provisioning profiles by default. On CI, the `APPLE_API_KEY`, `APPLE_API_ISSUER` and `APPLE_API_KEY_PATH` environment variables must be provided for authentication. ### Enhancements - [`3a4972b39`](https://www.github.com/tauri-apps/tauri/commit/3a4972b394c65c32eefebfb2181ba56b0cfc08f7) ([#10793](https://www.github.com/tauri-apps/tauri/pull/10793) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Include architecture in the `tauri info` output. - [`fd68b7fde`](https://www.github.com/tauri-apps/tauri/commit/fd68b7fdea3890d9f0a373a252a3682bd9d04138) ([#10785](https://www.github.com/tauri-apps/tauri/pull/10785) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Remove the `.cargo/config` file creation that used to fix mobile build caches. - [`f67a9eb6d`](https://www.github.com/tauri-apps/tauri/commit/f67a9eb6de4567c2374b8cdbabadcf0ca44d28fb) ([#10802](https://www.github.com/tauri-apps/tauri/pull/10802) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Synchronize identifier, development team and lib name with the iOS Xcode project. ### Bug Fixes - [`83ed090bf`](https://www.github.com/tauri-apps/tauri/commit/83ed090bfa58a1784495f474d93b16a568be513f) ([#10790](https://www.github.com/tauri-apps/tauri/pull/10790) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Do not quit `ios dev` and `android dev` process when we fail to attach the logger. - [`2d31aef75`](https://www.github.com/tauri-apps/tauri/commit/2d31aef759f496f3afe46b7697176e61a8570511) ([#10751](https://www.github.com/tauri-apps/tauri/pull/10751) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Ensure gradlew is executable and does not use CRLF so it can be used on UNIX systems. - [`02b2f964a`](https://www.github.com/tauri-apps/tauri/commit/02b2f964a70c61ff08b5052bd9fcde472d706d9c) ([#10795](https://www.github.com/tauri-apps/tauri/pull/10795) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix the `add` command NPM version specifier for known plugins from `2.0.0-rc` (unknown version requirement) to `^2.0.0-rc`. - [`84070bae9`](https://www.github.com/tauri-apps/tauri/commit/84070bae92d234bc3630e795cfaf79f869f3a751) ([#10792](https://www.github.com/tauri-apps/tauri/pull/10792) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix `tauri plugin ios init` not generating the iOS folder. - [`edb2ca31f`](https://www.github.com/tauri-apps/tauri/commit/edb2ca31f70a39004b6a09ae53425f22e243318e) ([#10794](https://www.github.com/tauri-apps/tauri/pull/10794) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Migrate v1 plugins NPM packages. - [`9718dc9e8`](https://www.github.com/tauri-apps/tauri/commit/9718dc9e8c9bc91d9a5d9e0e06a7afab62492152) ([#10791](https://www.github.com/tauri-apps/tauri/pull/10791) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Reintroduce the `targetSdk` value in the Android application template. ### What's Changed - [`fb6bf3142`](https://www.github.com/tauri-apps/tauri/commit/fb6bf314252c88dd49af74bdbb8499df370836ae) ([#10763](https://www.github.com/tauri-apps/tauri/pull/10763) by [@rdlabo](https://www.github.com/tauri-apps/tauri/../../rdlabo)) Update plugin template Android code to match documentation on Android package ID usage. ### Dependencies - Upgraded to `tauri-cli@2.0.0-rc.8` ### Breaking Changes - [`073bb4f45`](https://www.github.com/tauri-apps/tauri/commit/073bb4f459a923541b94970dfa7e087bccaa2cfd) ([#10772](https://www.github.com/tauri-apps/tauri/pull/10772) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Removed the deprecated `webview_fixed_runtime_path` config option, use the `webview_install_mode` instead. ## \[2.0.0-rc.7] ### Enhancements - [`da8c9a7d3`](https://www.github.com/tauri-apps/tauri/commit/da8c9a7d3069398c26826aeb082caa44b7c92809) ([#10669](https://www.github.com/tauri-apps/tauri/pull/10669) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Modify both ExportOptions.plist and project.pbxproj to reflect changes for the `IOS_CERTIFICATE`, `IOS_CERTIFICATE_PASSWORD` and `IOS_MOBILE_PROVISION` environment variables. ### Bug Fixes - [`793ee0531`](https://www.github.com/tauri-apps/tauri/commit/793ee0531730597e6008c9c0dedabbab7a2bef53) ([#10700](https://www.github.com/tauri-apps/tauri/pull/10700) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Allow hyphens and underscores on app identifiers. - [`da8c9a7d3`](https://www.github.com/tauri-apps/tauri/commit/da8c9a7d3069398c26826aeb082caa44b7c92809) ([#10669](https://www.github.com/tauri-apps/tauri/pull/10669) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Synchronize Xcode project changes with the ExportOptions.plist file so `ios build` calls can work with code signing changes made in Xcode. ### What's Changed - [`f4d5241b3`](https://www.github.com/tauri-apps/tauri/commit/f4d5241b377d0f7a1b58100ee19f7843384634ac) ([#10731](https://www.github.com/tauri-apps/tauri/pull/10731) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Update documentation icon path. ### Dependencies - Upgraded to `tauri-cli@2.0.0-rc.7` ### Breaking Changes - [`da8c9a7d3`](https://www.github.com/tauri-apps/tauri/commit/da8c9a7d3069398c26826aeb082caa44b7c92809) ([#10669](https://www.github.com/tauri-apps/tauri/pull/10669) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) The `IOS_CERTIFICATE`, `IOS_CERTIFICATE_PASSWORD` and `IOS_MOBILE_PROVISION` environment variables are now read by the `ios build` command instead of `ios init`. ## \[2.0.0-rc.6] ### New Features - [`da381e07f`](https://www.github.com/tauri-apps/tauri/commit/da381e07f3770988fe6d0859a02331b87cc6723f) ([#10696](https://www.github.com/tauri-apps/tauri/pull/10696) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Inject configured resources on mobile apps. ### Bug Fixes - [`1a60822a4`](https://www.github.com/tauri-apps/tauri/commit/1a60822a4220b6dbb1ad7295a2e37d6c3004edad) ([#10699](https://www.github.com/tauri-apps/tauri/pull/10699) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Changed the `add` command to use a version requirement that matches the CLI's stable and prerelease numbers. ### Dependencies - Upgraded to `tauri-cli@2.0.0-rc.6` ## \[2.0.0-rc.5] ### New Features - [`8d148a9e2`](https://www.github.com/tauri-apps/tauri/commit/8d148a9e2566edebfea2d75f32df7c9396d765a4) ([#10634](https://www.github.com/tauri-apps/tauri/pull/10634) by [@anatawa12](https://www.github.com/tauri-apps/tauri/../../anatawa12)) Custom sign command with object notation for whitespaces in the command path and arguments. ### Bug Fixes - [`8ae52a615`](https://www.github.com/tauri-apps/tauri/commit/8ae52a615a11d934930001da63ce6ac8442c7efc) ([#10676](https://www.github.com/tauri-apps/tauri/pull/10676) by [@rdlabo](https://www.github.com/tauri-apps/tauri/../../rdlabo)) Change plugin template call to `register_ios_plugin` params to snake case - [`7796a8fc6`](https://www.github.com/tauri-apps/tauri/commit/7796a8fc649cd7397a67048c71f8d1fbf822122a) ([#10687](https://www.github.com/tauri-apps/tauri/pull/10687) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix Swift plugin compilation on older versions. - [`9b99ebab1`](https://www.github.com/tauri-apps/tauri/commit/9b99ebab17d6a043d82a7aeecfb76c56a995c287) ([#10431](https://www.github.com/tauri-apps/tauri/pull/10431) by [@mrguiman](https://www.github.com/tauri-apps/tauri/../../mrguiman)) Do not include the target arch when building and archiving the iOS application, which makes Xcode project modifications more flexible. ### Dependencies - Upgraded to `tauri-cli@2.0.0-rc.5` ## \[2.0.0-rc.4] ### New Features - [`78e22bedc`](https://www.github.com/tauri-apps/tauri/commit/78e22bedcab5096f1a4e667321fc8b2817b79214) ([#10602](https://www.github.com/tauri-apps/tauri/pull/10602) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Add necessary options to `AndroidManifest.xml` in android template to support AndroidTV. - [`3bec7b159`](https://www.github.com/tauri-apps/tauri/commit/3bec7b1595e28630a22b9fb16540beafd5eb7969) ([#10544](https://www.github.com/tauri-apps/tauri/pull/10544) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) v1 migrate script now migrates Svelte and Vue.js code. ### Enhancements - [`bba1a4419`](https://www.github.com/tauri-apps/tauri/commit/bba1a441917defcdf9e88221e9b0e1cdd744e77a) ([#10457](https://www.github.com/tauri-apps/tauri/pull/10457) by [@mmvanheusden](https://www.github.com/tauri-apps/tauri/../../mmvanheusden)) Added `--no-fmt` option to the `add` command to skip formatting the code after applying changes. - [`71d00646a`](https://www.github.com/tauri-apps/tauri/commit/71d00646a9b7c52311ba087820e52fd19861b3d8) ([#10504](https://www.github.com/tauri-apps/tauri/pull/10504) by [@fu050409](https://www.github.com/tauri-apps/tauri/../../fu050409)) Improve the `init` command behavior by detecting the project NPM package manager. - [`8deb1966a`](https://www.github.com/tauri-apps/tauri/commit/8deb1966ace93d1350f271d525a878ba4b0879ce) ([#10652](https://www.github.com/tauri-apps/tauri/pull/10652) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Infer macOS codesign identity from the `APPLE_CERTIFICATE` environment variable when provided, meaning the identity no longer needs to be provided when signing on CI using that option. If the imported certificate name does not match a provided signingIdentity configuration, an error is returned. - [`f35bcda28`](https://www.github.com/tauri-apps/tauri/commit/f35bcda2895a1350df31853da76a051783b9fd3f) ([#10598](https://www.github.com/tauri-apps/tauri/pull/10598) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) `permission add` and `add` commands now check if the plugin is known and if it is either desktop or mobile only we add the permission to a target-specific capability. ### Bug Fixes - [`f712f31d1`](https://www.github.com/tauri-apps/tauri/commit/f712f31d1d21e85fab99194530702c70e45c63fc) ([#10639](https://www.github.com/tauri-apps/tauri/pull/10639) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Include notarization error output in the error message if it fails. - [`9f75d0622`](https://www.github.com/tauri-apps/tauri/commit/9f75d06228fcb7036cf7a4e215abc7bc8d1a0a56) ([#10604](https://www.github.com/tauri-apps/tauri/pull/10604) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes `android dev` port forward failing under some conditions, add better logging and error handling. - [`2d47352a0`](https://www.github.com/tauri-apps/tauri/commit/2d47352a07a7d742e62291a5e6810aed79fc8b50) ([#10418](https://www.github.com/tauri-apps/tauri/pull/10418) by [@samkearney](https://www.github.com/tauri-apps/tauri/../../samkearney)) CLI commands will now consistently search for the `app_dir` (the directory containing `package.json`) from the current working directory of the command invocation. - [`f4cd68f04`](https://www.github.com/tauri-apps/tauri/commit/f4cd68f040635f019ff989667289cfe9061c7dfb) ([#10600](https://www.github.com/tauri-apps/tauri/pull/10600) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes `android dev` not working when using the builtin dev server. - [`41c7a6646`](https://www.github.com/tauri-apps/tauri/commit/41c7a6646ba9afbb2322986fb39054a43a88e604) ([#10572](https://www.github.com/tauri-apps/tauri/pull/10572) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Exit with code 1 if a panic occurs when running the CLI with `bun`. - [`9089d9763`](https://www.github.com/tauri-apps/tauri/commit/9089d97637e49bebbe7dba8adc6351e04b53a44d) ([#10605](https://www.github.com/tauri-apps/tauri/pull/10605) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes `[android|ios] build --config ` failing to resolve. - [`712f1049f`](https://www.github.com/tauri-apps/tauri/commit/712f1049fae74bfda5f360adcee7210cea92fe63) ([#10569](https://www.github.com/tauri-apps/tauri/pull/10569) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes running `ios dev` and `ios build` using `bun`. - [`3998570fd`](https://www.github.com/tauri-apps/tauri/commit/3998570fd3d03c1bb282bd060a4aafb4ab5437f9) ([#10540](https://www.github.com/tauri-apps/tauri/pull/10540) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes v1 migration of Cargo.toml dependencies and features. - [`3beba92b5`](https://www.github.com/tauri-apps/tauri/commit/3beba92b5bdc62ed00c9f6a9b8f8c05cfa78f8dc) ([#10542](https://www.github.com/tauri-apps/tauri/pull/10542) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes v1 frontend code migration when using plugin default imports. - [`10fb027b7`](https://www.github.com/tauri-apps/tauri/commit/10fb027b7590cf2c020b5c220328b9051c05adca) ([#10656](https://www.github.com/tauri-apps/tauri/pull/10656) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Migrate v1 plugins to their v2 releases. - [`10fb027b7`](https://www.github.com/tauri-apps/tauri/commit/10fb027b7590cf2c020b5c220328b9051c05adca) ([#10656](https://www.github.com/tauri-apps/tauri/pull/10656) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Prevent duplicate permissions on v1 migration. - [`b160f9359`](https://www.github.com/tauri-apps/tauri/commit/b160f9359d6f661d280185d2a2a4bdf280b8e72c) ([#10638](https://www.github.com/tauri-apps/tauri/pull/10638) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Only validate the output iOS library on debug builds. - [`4bfe4880f`](https://www.github.com/tauri-apps/tauri/commit/4bfe4880fbef42d1a115f840e712d4a2f59c8ab3) ([#10550](https://www.github.com/tauri-apps/tauri/pull/10550) by [@anatawa12](https://www.github.com/tauri-apps/tauri/../../anatawa12)) fails to build universal fat binary if main bin is renamed to another name in `Cargo.toml` - [`f3837d5b9`](https://www.github.com/tauri-apps/tauri/commit/f3837d5b98f0caebc3337f9a9e8127e7b96c3fc5) ([#10539](https://www.github.com/tauri-apps/tauri/pull/10539) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Improve migration tooling by supporting TOML configs, handle nulls and properly check for updater migration. ### What's Changed - [`794cf8234`](https://www.github.com/tauri-apps/tauri/commit/794cf8234f8b620c74cbd23cc4b81be9b2edc386) ([#10571](https://www.github.com/tauri-apps/tauri/pull/10571) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Change iOS template default export method from deprecated `development` to `debugging`. - [`bfc49cc7a`](https://www.github.com/tauri-apps/tauri/commit/bfc49cc7a1d43e3378e93865b9b37ce4bddfa6e6) ([#10558](https://www.github.com/tauri-apps/tauri/pull/10558) by [@ahqsoftwares](https://www.github.com/tauri-apps/tauri/../../ahqsoftwares)) Remove targetSdk from gradle files ### Dependencies - Upgraded to `tauri-cli@2.0.0-rc.4` ## \[2.0.0-rc.3] ### Enhancements - [`5f56cb0a8`](https://www.github.com/tauri-apps/tauri/commit/5f56cb0a8b9c6f695bc6439a8db997c98b3a3997) ([#10507](https://www.github.com/tauri-apps/tauri/pull/10507) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Update gradle to 8.9 and the gradle android plugin to 8.5.1 in the android templates (requires latest Android Studio). This should add support for Java 21 but Java 17 keeps being the recommended version. ### Bug Fixes - [`f5dfc0280`](https://www.github.com/tauri-apps/tauri/commit/f5dfc02800dbd3bdee671b032454c49ac7102fb4) ([#10533](https://www.github.com/tauri-apps/tauri/pull/10533) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue causing `tauri ios init` to fail if `iOS.minimumSystemVersion` was not configured explicitly. ### Dependencies - Upgraded to `tauri-cli@2.0.0-rc.3` ## \[2.0.0-rc.2] ### New Features - [`8dc81b6cc`](https://www.github.com/tauri-apps/tauri/commit/8dc81b6cc2b8235b11f74a971d6aa3a5df5e9f68) ([#10496](https://www.github.com/tauri-apps/tauri/pull/10496) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Added `bundle > ios > template` configuration option for custom Xcode project YML Handlebars template using XcodeGen. - [`02c00abc6`](https://www.github.com/tauri-apps/tauri/commit/02c00abc63cf86e9bf9179cbb143d5145a9397b6) ([#10495](https://www.github.com/tauri-apps/tauri/pull/10495) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Added `bundle > ios > minimumSystemVersion` configuration option. ### Enhancements - [`8e1e15304`](https://www.github.com/tauri-apps/tauri/commit/8e1e15304e9dc98d7f875fc8dceb7d4ce19adc47) ([#10483](https://www.github.com/tauri-apps/tauri/pull/10483) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Check if the Rust library contains the symbols required at runtime for Android and iOS apps. - [`ca6868956`](https://www.github.com/tauri-apps/tauri/commit/ca68689564cbc8dfa9a5220d3daf81a44ef81fcc) ([#10479](https://www.github.com/tauri-apps/tauri/pull/10479) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Check if identifier or lib name changed when running mobile commands. ### Bug Fixes - [`2e8ab7bac`](https://www.github.com/tauri-apps/tauri/commit/2e8ab7bac12046d734fb07a1b4fe5e03004b305e) ([#10481](https://www.github.com/tauri-apps/tauri/pull/10481) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Migration from v1 to v2 now adds the updater plugin when it is active. ### What's Changed - [`a3cd9779a`](https://www.github.com/tauri-apps/tauri/commit/a3cd9779a47428e306a628d658740669faf69ccd) ([#10480](https://www.github.com/tauri-apps/tauri/pull/10480) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Removed the `[android|ios] open` command. It is recommended to use `[android|ios] dev --open` or `[android|ios] build --open` instead. ### Dependencies - Upgraded to `tauri-cli@2.0.0-rc.2` ## \[2.0.0-rc.1] ### Bug Fixes - [`fb1933f17`](https://www.github.com/tauri-apps/tauri/commit/fb1933f17442674e53374578e57a8cad241ac3c6) ([#10467](https://www.github.com/tauri-apps/tauri/pull/10467) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes running `android dev --open`. - [`206914fe8`](https://www.github.com/tauri-apps/tauri/commit/206914fe8d97eb61a2ff2a80e94e65e7a42bcea5) ([#10466](https://www.github.com/tauri-apps/tauri/pull/10466) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes running `adb reverse` in Node.js context. ### Dependencies - Upgraded to `tauri-cli@2.0.0-rc.1` ## \[2.0.0-rc.0] ### New Features - [`d5511c311`](https://www.github.com/tauri-apps/tauri/commit/d5511c3117b1a117cb0b7359c5fa09aa4795122b) ([#10395](https://www.github.com/tauri-apps/tauri/pull/10395)) Added migration from `2.0.0-beta` to `2.0.0-rc`. - [`a5bfbaa62`](https://www.github.com/tauri-apps/tauri/commit/a5bfbaa62b8cd0aacbb33f730d4e30b43c461fe1)([#9962](https://www.github.com/tauri-apps/tauri/pull/9962)) Added `bundle > iOS > frameworks` configuration to define a list of frameworks that are linked to the Xcode project when it is generated. ### Enhancements - [`a0841d509`](https://www.github.com/tauri-apps/tauri/commit/a0841d509abc43b62bb7c755e8727f3f461862d1) ([#10421](https://www.github.com/tauri-apps/tauri/pull/10421)) Changes the default behavior of the `dev` command to only expose to localhost (`127.0.0.1`) instead of the default system interface. ### Security fixes - [`289ae5555`](https://www.github.com/tauri-apps/tauri/commit/289ae5555da3802741018015bfe4927729a2eb33) ([#10386](https://www.github.com/tauri-apps/tauri/pull/10386)) Re-enable TLS checks that were previously disabled to support an insecure HTTPS custom protocol on Android which is no longer used. ### Dependencies - Upgraded to `tauri-cli@2.0.0-rc.0` ### Breaking Changes - [`758d28c8a`](https://www.github.com/tauri-apps/tauri/commit/758d28c8a2d5c9567158e339326b765f72da983e) ([#10390](https://www.github.com/tauri-apps/tauri/pull/10390)) Core plugin permissions are now prefixed with `core:`, the `core:default` permission set can now be used and the `core` plugin name is reserved. The `tauri migrate` tool will automate the migration process, which involves prefixing all `app`, `event`, `image`, `menu`, `path`, `resources`, `tray`, `webview` and `window` permissions with `core:`. - [`7ba67b4ac`](https://www.github.com/tauri-apps/tauri/commit/7ba67b4aca8d3f3b1aa5ad08819605029d36e6b4)([#10437](https://www.github.com/tauri-apps/tauri/pull/10437)) `ios dev` and `android dev` now uses localhost for the development server unless running on an iOS device, which still requires connecting to the public network address. To conditionally check this on your frontend framework's configuration you can check for the existence of the `TAURI_DEV_HOST` environment variable instead of checking if the target is iOS or Android (previous recommendation). ## \[2.0.0-beta.23] ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.23` ## \[2.0.0-beta.22] ### New Features - [`7c7fa0964`](https://www.github.com/tauri-apps/tauri/commit/7c7fa0964db3403037fdb9a34de2b877ddb8df1c) ([#9963](https://www.github.com/tauri-apps/tauri/pull/9963) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Added `--method` argument for `ios build` to select the export options' method. - [`7c7fa0964`](https://www.github.com/tauri-apps/tauri/commit/7c7fa0964db3403037fdb9a34de2b877ddb8df1c) ([#9963](https://www.github.com/tauri-apps/tauri/pull/9963) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Setup iOS signing by reading `IOS_CERTIFICATE`, `IOS_CERTIFICATE_PASSWORD` and `IOS_MOBILE_PROVISION` environment variables. ### Enhancements - [`c01e87ad4`](https://www.github.com/tauri-apps/tauri/commit/c01e87ad46e2a5b3fb8d018739e724ef932008d7) ([#10198](https://www.github.com/tauri-apps/tauri/pull/10198) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Enhance `tauri migrate` to also migrate variables like `appWindow`: ```ts import { appWindow } from '@tauri-apps/api/window' ``` will become: ```ts import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow' const appWindow = getCurrentWebviewWindow() ``` ### Bug Fixes - [`94136578b`](https://www.github.com/tauri-apps/tauri/commit/94136578bc89e4b973c471050ae9c2d83ffcb7c6) ([#10186](https://www.github.com/tauri-apps/tauri/pull/10186) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix `migrate` command, migrating incorrect permissions for `clipboard`. - [`c01e87ad4`](https://www.github.com/tauri-apps/tauri/commit/c01e87ad46e2a5b3fb8d018739e724ef932008d7) ([#10198](https://www.github.com/tauri-apps/tauri/pull/10198) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix `tauri migrate` incorrectly migrating `@tauri-apps/api/tauri` module to just `core` and `@tauri-apps/api/window` to just `webviewWindow`. - [`15e125996`](https://www.github.com/tauri-apps/tauri/commit/15e12599667b749c3d7cd2259e6cf7c7b5c6e2be) ([#10234](https://www.github.com/tauri-apps/tauri/pull/10234) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Fix cli failing to detect the correct cargo target directory when using cargo `--target-dir` flag with `tauri build` or `tauri dev` ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.22` ## \[2.0.0-beta.21] ### New Features - [`656a64974`](https://www.github.com/tauri-apps/tauri/commit/656a64974468bc207bf39537e02ae179bdee9b83) ([#9318](https://www.github.com/tauri-apps/tauri/pull/9318)) Added a configuration option to disable hardened runtime on macOS codesign. ### Enhancements - [`f44a2ec47`](https://www.github.com/tauri-apps/tauri/commit/f44a2ec47c13243d472fa08a9df8b20d8490d79f) ([#10030](https://www.github.com/tauri-apps/tauri/pull/10030)) Enhance the plugin template to include `permissions/default.toml` and default capabilities file for the example application. ### Bug Fixes - [`019a74e97`](https://www.github.com/tauri-apps/tauri/commit/019a74e970958d29cf69a6f24669d603399dcbb3) ([#9931](https://www.github.com/tauri-apps/tauri/pull/9931)) Fix wrong migration of `clipboard` and `globalShortcut` modules - [`27838365a`](https://www.github.com/tauri-apps/tauri/commit/27838365a6841b0d3fa645ba2528221d23d4aeb2) ([#10135](https://www.github.com/tauri-apps/tauri/pull/10135)) Fix parsing of cargo profile when using `--profile=` syntax. - [`79542f4d4`](https://www.github.com/tauri-apps/tauri/commit/79542f4d4542bd97451da7605de16e8464d6a06c) ([#10039](https://www.github.com/tauri-apps/tauri/pull/10039)) Fixed an issue that prevented `tauri icon` from rendering `` nodes in SVG files. - [`40c0f44e1`](https://www.github.com/tauri-apps/tauri/commit/40c0f44e1c74c18ed0d6c645724d650637725456) ([#9971](https://www.github.com/tauri-apps/tauri/pull/9971)) Changed the deployment target of plugin iOS Xcode project to 13.0 so it works on older iOS releases. - [`f56cdc9e3`](https://www.github.com/tauri-apps/tauri/commit/f56cdc9e391c4d55e4d7e935203d0f891864f22d) ([#10016](https://www.github.com/tauri-apps/tauri/pull/10016)) Add missing dependency `libayatana-appindicator3.so.1` for rpm package. - [`1601da5b5`](https://www.github.com/tauri-apps/tauri/commit/1601da5b525de05cb813002d611f22ea4217a4fb) ([#10114](https://www.github.com/tauri-apps/tauri/pull/10114)) Removed alpha channel from default icons in iOS template to comply with Apple's human interface guideline (https://developer.apple.com/design/human-interface-guidelines/app-icons), because transparent icons with alpha channel are not allowed, and will be rejected upon upload to Apple appstore. ### What's Changed - [`3cca5c2be`](https://www.github.com/tauri-apps/tauri/commit/3cca5c2be88bbd52139e7dda371e88510d28bc8e) ([#9924](https://www.github.com/tauri-apps/tauri/pull/9924)) Migrate to new Android buildFeatures.buildConfig format. ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.21` - [`f955f7b49`](https://www.github.com/tauri-apps/tauri/commit/f955f7b4903bcea376c0a8b430736f66c8cebf56) ([#9929](https://www.github.com/tauri-apps/tauri/pull/9929)) Switch from `dirs_next` to `dirs` as `dirs_next` is now unmaintained while `dirs` is ### Breaking Changes - [`911242f09`](https://www.github.com/tauri-apps/tauri/commit/911242f0928e0a2add3595fa9de27850fb875fa6) ([#9883](https://www.github.com/tauri-apps/tauri/pull/9883)) Move updater target from `bundle > targets` to a separate field `bundle > createUpdaterArtifacts` ## \[2.0.0-beta.20] ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.20` ## \[2.0.0-beta.19] ### New Features - [`8a1ae2dea`](https://www.github.com/tauri-apps/tauri/commit/8a1ae2deaf3086e531ada25b1627f900e2e421fb)([#9843](https://www.github.com/tauri-apps/tauri/pull/9843)) Added an option to use a Xcode project for the iOS plugin instead of a plain SwiftPM project. - [`9e4b2253f`](https://www.github.com/tauri-apps/tauri/commit/9e4b2253f6ddaccd0f5c88734287bd5c84d4936a)([#9734](https://www.github.com/tauri-apps/tauri/pull/9734)) Add `tauri bundle` subcommand which runs the bundle phase only, best paired with `tauri build --no-bundle` ### Enhancements - [`8b032c3cf`](https://www.github.com/tauri-apps/tauri/commit/8b032c3cf638e64e50df9d9cf8bc789c7e285987)([#9896](https://www.github.com/tauri-apps/tauri/pull/9896)) Add a blank LaunchScreen.storyboard to the iOS project init template to pass the App Store validation. - [`9970d88be`](https://www.github.com/tauri-apps/tauri/commit/9970d88becee1560a4b2a7ffc1fe65991a42a8c9)([#9892](https://www.github.com/tauri-apps/tauri/pull/9892)) Update to latest gradle. ### What's Changed - [`80aa50498`](https://www.github.com/tauri-apps/tauri/commit/80aa504987dd9cfa59aa5848c4d7960e1d58d0e6)([#9870](https://www.github.com/tauri-apps/tauri/pull/9870)) Updated Android target SDK to 34. ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.19` ### Breaking Changes - [`265c23886`](https://www.github.com/tauri-apps/tauri/commit/265c23886ee5efbcc6d7188ff5c84cb32fa82aea)([#9375](https://www.github.com/tauri-apps/tauri/pull/9375)) Avoid renaming main binary to product name and perserve the name generated by cargo. - [`1df5cdeb0`](https://www.github.com/tauri-apps/tauri/commit/1df5cdeb06f5464e0eec4055e21b7b7bc8739eed)([#9858](https://www.github.com/tauri-apps/tauri/pull/9858)) Use `tauri.conf.json > identifier` to set the `PackageName` in Android and `BundleId` in iOS. ## \[2.0.0-beta.18] ### Bug Fixes - [`beda18bce`](https://www.github.com/tauri-apps/tauri/commit/beda18bce95fd6e10543b2d8f1eca5fb7ca0655b)([#9855](https://www.github.com/tauri-apps/tauri/pull/9855)) Fixed an issue that caused `tauri add` to fail for multiple rust-only and platform-specific plugins. - [`4a33bc6a6`](https://www.github.com/tauri-apps/tauri/commit/4a33bc6a62d2ed9371191c8a7f78ff3f33930455)([#9553](https://www.github.com/tauri-apps/tauri/pull/9553)) Fixes `pnpm` detection when initializing and running a mobile project. ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.18` ## \[2.0.0-beta.17] ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.17` ## \[2.0.0-beta.16] ### Bug Fixes - [`97ec422f2`](https://www.github.com/tauri-apps/tauri/commit/97ec422f22d069b9570931834241c7e47bc68cc3)([#9638](https://www.github.com/tauri-apps/tauri/pull/9638)) Exit `tauri icon` with non-zero code when it fails. ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.16` ## \[2.0.0-beta.15] ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.15` ## \[2.0.0-beta.14] ### Enhancements - [`8a63ceb4f`](https://www.github.com/tauri-apps/tauri/commit/8a63ceb4f31c422311b0f7dff173a9c8c0e1a604)([#9473](https://www.github.com/tauri-apps/tauri/pull/9473)) Ignore `.DS_Store` by default for `tauri dev` hot reloads. ### Bug Fixes - [`e64b8f1dc`](https://www.github.com/tauri-apps/tauri/commit/e64b8f1dcedad3222f46755bf6f30392a7ec2f90)([#9479](https://www.github.com/tauri-apps/tauri/pull/9479)) Upgrade `heck` to v0.5 to better support Chinese and Japanese product name, because Chinese do not have word separation. - [`aaa332c6e`](https://www.github.com/tauri-apps/tauri/commit/aaa332c6e78c956debd11efda021a0406621a01d)([#9540](https://www.github.com/tauri-apps/tauri/pull/9540)) Fix `tauri migrate` trying to migrate to a non-existing plugin. - [`e64b8f1dc`](https://www.github.com/tauri-apps/tauri/commit/e64b8f1dcedad3222f46755bf6f30392a7ec2f90)([#9479](https://www.github.com/tauri-apps/tauri/pull/9479)) Fixed an issue causing the `build.runner` and `build.features` configs to not take effect. ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.14` ## \[2.0.0-beta.13] ### Bug Fixes - [`73c1c2d33`](https://www.github.com/tauri-apps/tauri/commit/73c1c2d33872651c32c761c838714b684980c668)([#9457](https://www.github.com/tauri-apps/tauri/pull/9457)) Gracefully handle Non-UTF8 files when using `tauri migrate` - [`9331435a5`](https://www.github.com/tauri-apps/tauri/commit/9331435a50cc3769720bd2671da8510699d28671)([#9412](https://www.github.com/tauri-apps/tauri/pull/9412)) Fix `tauri info` crashing when Node.js is not installed. ### What's Changed - [`8f4b1050c`](https://www.github.com/tauri-apps/tauri/commit/8f4b1050c4de0e9194680408ff3a6902b67045f8)([#9459](https://www.github.com/tauri-apps/tauri/pull/9459)) Show full expected path of `frontendDist` when if can't be found. ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.13` ## \[2.0.0-beta.12] ### New Features - [`93e0e1392`](https://www.github.com/tauri-apps/tauri/commit/93e0e1392ec341fcadf696c03e78f0ca1e73c941) Support specifying a version for `tauri add` subcommand, for example: `tauri add window-state@2.0.0-beta.2` ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.12` ## \[2.0.0-beta.11] ### Enhancements - [`ac76a22f3`](https://www.github.com/tauri-apps/tauri/commit/ac76a22f383028d9bacdedebeb41d3fca5ec9dac)([#9183](https://www.github.com/tauri-apps/tauri/pull/9183)) Allow empty responses for `devUrl`, `beforeDevCommand` and `beforeBuildCommands` questions in `tauri init`. - [`b525ddadf`](https://www.github.com/tauri-apps/tauri/commit/b525ddadf7e7588c3e195cf0f821c9862c545d06)([#9237](https://www.github.com/tauri-apps/tauri/pull/9237)) `openssl` is no longer a required dependency on macOS. ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.11` ## \[2.0.0-beta.10] ### New Features - [`7213b9e47`](https://www.github.com/tauri-apps/tauri/commit/7213b9e47242bef814aa7257e0bf84631bf5fe7e)([#9124](https://www.github.com/tauri-apps/tauri/pull/9124)) Add default permission for a plugin to capabilities when using `tauri add `. ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.10` ## \[2.0.0-beta.9] ### Bug Fixes - [`c3ea3a2b7`](https://www.github.com/tauri-apps/tauri/commit/c3ea3a2b7d2fe3085f05b63dd1feb962beb4b7b3)([#9126](https://www.github.com/tauri-apps/tauri/pull/9126)) Fix bundling when `plugins > updater > windows > installerArgs` are set in `tauri.conf.json` ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.9` ## \[2.0.0-beta.8] ### Enhancements - [`3e472d0af`](https://www.github.com/tauri-apps/tauri/commit/3e472d0afcd67545dd6d9f18d304580a3b2759a8)([#9115](https://www.github.com/tauri-apps/tauri/pull/9115)) Changed the permission and capability platforms to be optional. ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.8` ## \[2.0.0-beta.7] ### Enhancements - [`c68218b36`](https://www.github.com/tauri-apps/tauri/commit/c68218b362c417b62e56c7a2b5b32c13fe035a83)([#8990](https://www.github.com/tauri-apps/tauri/pull/8990)) Add `--no-bundle` flag for `tauri build` command to skip bundling. Previously `none` was used to skip bundling, it will now be treated as invalid format and a warning will be emitted instead. ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.7` ## \[2.0.0-beta.6] ### Bug Fixes - [`f5f3ed5f`](https://www.github.com/tauri-apps/tauri/commit/f5f3ed5f6faa0b51e83244acc15e9006299a03ba)([#9009](https://www.github.com/tauri-apps/tauri/pull/9009)) Fixes Android and iOS project initialization when the Tauri CLI is on a different disk partition. - [`d7d03c71`](https://www.github.com/tauri-apps/tauri/commit/d7d03c7197212f3a5bebe08c929417d60927eb89)([#9017](https://www.github.com/tauri-apps/tauri/pull/9017)) Fixes dev watcher on mobile dev. - [`b658ded6`](https://www.github.com/tauri-apps/tauri/commit/b658ded614cfc169228cb22ad5bfc64478dfe161)([#9015](https://www.github.com/tauri-apps/tauri/pull/9015)) Fixes truncation of existing BuildTask.kt when running `tauri android init`. ### What's Changed - [`3657ad82`](https://www.github.com/tauri-apps/tauri/commit/3657ad82f88ce528551d032d521c52eed3f396b4)([#9008](https://www.github.com/tauri-apps/tauri/pull/9008)) Updates to new ACL manifest path. ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.6` ## \[2.0.0-beta.5] ### New Features - [`06d63d67`](https://www.github.com/tauri-apps/tauri/commit/06d63d67a061459dd533ddcae755922427a6dfc5)([#8827](https://www.github.com/tauri-apps/tauri/pull/8827)) Add new subcommands for managing permissions and cababilities: - `tauri permission new` - `tauri permission add` - `tauri permission rm` - `tauri permission ls` - `tauri capability new` ### Breaking Changes - [`b9e6a018`](https://www.github.com/tauri-apps/tauri/commit/b9e6a01879d9233040f3d3fab11c59e70563da7e)([#8937](https://www.github.com/tauri-apps/tauri/pull/8937)) The `custom-protocol` Cargo feature is no longer required on your application and is now ignored. To check if running on production, use `#[cfg(not(dev))]` instead of `#[cfg(feature = "custom-protocol")]`. ### Enhancements - [`9be314f0`](https://www.github.com/tauri-apps/tauri/commit/9be314f07a4ca5d14433d41919492f3e91b5536a)([#8951](https://www.github.com/tauri-apps/tauri/pull/8951)) Add plugins to `Cargo.toml` when using `tauri migrate` ### Bug Fixes - [`cbd9755e`](https://www.github.com/tauri-apps/tauri/commit/cbd9755e0926a7e47e59deb50f4bb93d621791a5)([#8977](https://www.github.com/tauri-apps/tauri/pull/8977)) Fixes process logs not showing on `ios dev`. ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.5` ## \[2.0.0-beta.4] ### Bug Fixes - [`e538ba58`](https://www.github.com/tauri-apps/tauri/commit/e538ba586c5b8b50955586c8ef2704adb5d7cc43)([#8949](https://www.github.com/tauri-apps/tauri/pull/8949)) Fixes android and iOS process spawning not working on Node.js. ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.4` ### Breaking Changes - [`a76fb118`](https://www.github.com/tauri-apps/tauri/commit/a76fb118ce2de22e1bdb4216bf0ac01dfc3e5799)([#8950](https://www.github.com/tauri-apps/tauri/pull/8950)) Changed the capability format to allow configuring both `remote: { urls: Vec }` and `local: bool (default: true)` instead of choosing one on the `context` field. ## \[2.0.0-beta.3] ### Enhancements - [`a029b9f7`](https://www.github.com/tauri-apps/tauri/commit/a029b9f77e432533a403c292940fa3efba68692c)([#8910](https://www.github.com/tauri-apps/tauri/pull/8910)) Setting up code signing is no longer required on iOS when using the simulator. ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.3` ## \[2.0.0-beta.2] ### Enhancements - [`83a68deb`](https://www.github.com/tauri-apps/tauri/commit/83a68deb5676d39cd4728d2e140f6b46d5f787ed)([#8797](https://www.github.com/tauri-apps/tauri/pull/8797)) Update app template following capabilities configuration change. ### Bug Fixes - [`aa06a053`](https://www.github.com/tauri-apps/tauri/commit/aa06a0534cf224038866e0ddd6910ea873b2574d)([#8810](https://www.github.com/tauri-apps/tauri/pull/8810)) Fix `tauri plugin android init` printing invalid code that has a missing closing `"`. - [`3cee26a5`](https://www.github.com/tauri-apps/tauri/commit/3cee26a58ab44639a12c7816f4096655daa327a4)([#8865](https://www.github.com/tauri-apps/tauri/pull/8865)) On Windows, fixed `tauri info` fails to detect the build tool when the system language is CJK. - [`052e8b43`](https://www.github.com/tauri-apps/tauri/commit/052e8b4311d9f0f963a2866163be27bfd8f70c60)([#8838](https://www.github.com/tauri-apps/tauri/pull/8838)) Downgrade minisign dependency fixing updater signing key bug and prevent it from happening in the future. - [`fb0d9971`](https://www.github.com/tauri-apps/tauri/commit/fb0d997117367e3387896bcd0fba004579475c40)([#8783](https://www.github.com/tauri-apps/tauri/pull/8783)) Fixes a regression on the `--config` argument not accepting file paths. - [`baca704d`](https://www.github.com/tauri-apps/tauri/commit/baca704d4b5fae239fc320d10140f35bd705bfbb)([#8768](https://www.github.com/tauri-apps/tauri/pull/8768)) Do not migrate updater configuration if the active flag is set to false. ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.2` ## \[2.0.0-beta.1] ### Enhancements - [`4e101f80`](https://www.github.com/tauri-apps/tauri/commit/4e101f801657e7d01ce8c22f9c6468067d0caab2)([#8756](https://www.github.com/tauri-apps/tauri/pull/8756)) Moved the capability JSON schema to the `src-tauri/gen` folder so it's easier to track changes on the `capabilities` folder. - [`4e101f80`](https://www.github.com/tauri-apps/tauri/commit/4e101f801657e7d01ce8c22f9c6468067d0caab2)([#8756](https://www.github.com/tauri-apps/tauri/pull/8756)) Update app and plugin templates following generated files change from tauri-build and tauri-plugin. ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.1` ## \[2.0.0-beta.0] ### New Features - [`7fcc0bcd`](https://www.github.com/tauri-apps/tauri/commit/7fcc0bcd3482bbc8771e330942ef6cd78cc8ec35)([#8490](https://www.github.com/tauri-apps/tauri/pull/8490)) Add plugin initialization rust code when using `tauri add` - [`1878766f`](https://www.github.com/tauri-apps/tauri/commit/1878766f7f81a03b0f0b87ec33ee113d7aa7a902)([#8667](https://www.github.com/tauri-apps/tauri/pull/8667)) Migrate the allowlist config to the new capability file format. ### Enhancements - [`d6c7568c`](https://www.github.com/tauri-apps/tauri/commit/d6c7568c27445653edf570f3969163bc358ba2ba)([#8720](https://www.github.com/tauri-apps/tauri/pull/8720)) Add `files` option to the AppImage Configuration. - [`b3209bb2`](https://www.github.com/tauri-apps/tauri/commit/b3209bb28bb379d5046d577c7e42319d6e76ced0)([#8688](https://www.github.com/tauri-apps/tauri/pull/8688)) Ignore global `.gitignore` when searching for tauri directory. - [`e691208e`](https://www.github.com/tauri-apps/tauri/commit/e691208e7b39bb8e3ffc9bf66cff731a5025ef16)([#7837](https://www.github.com/tauri-apps/tauri/pull/7837)) Prevent unneeded double Cargo.toml rewrite on `dev` and `build`. - [`f492efd7`](https://www.github.com/tauri-apps/tauri/commit/f492efd7144fdd8d25cac0c4d2389a95ab75fb02)([#8666](https://www.github.com/tauri-apps/tauri/pull/8666)) Update app and plugin template following the new access control permission model. ### Bug Fixes - [`9cb9aa79`](https://www.github.com/tauri-apps/tauri/commit/9cb9aa7978f231f7da238b33d6ab33fdd2d2c842)([#8672](https://www.github.com/tauri-apps/tauri/pull/8672)) Allow license field in Cargo.toml to be `{ workspace = true }` ### Dependencies - Upgraded to `tauri-cli@2.0.0-beta.0` ### Breaking Changes - [`8de308d1`](https://www.github.com/tauri-apps/tauri/commit/8de308d1bf6a855d7a26af58bd0e744938ba47d8)([#8723](https://www.github.com/tauri-apps/tauri/pull/8723)) Restructured Tauri config per [RFC#5](https://github.com/tauri-apps/rfcs/blob/f3e82a6b0c5390401e855850d47dc7b7d9afd684/texts/0005-tauri-config-restructure.md): - Moved `package.productName`, `package.version` and `tauri.bundle.identifier` fields to the top-level. - Removed `package` object. - Renamed `tauri` object to `app`. - Moved `tauri.bundle` object to the top-level. - Renamed `build.distDir` field to `frontendDist`. - Renamed `build.devPath` field to `devUrl` and will no longer accepts paths, it will only accept URLs. - Moved `tauri.pattern` to `app.security.pattern`. - Removed `tauri.bundle.updater` object, and its fields have been moved to the updater plugin under `plugins.updater` object. - Moved `build.withGlobalTauri` to `app.withGlobalTauri`. - Moved `tauri.bundle.dmg` object to `bundle.macOS.dmg`. - Moved `tauri.bundle.deb` object to `bundle.linux.deb`. - Moved `tauri.bundle.appimage` object to `bundle.linux.appimage`. - Removed all license fields from each bundle configuration object and instead added `bundle.license` and `bundle.licenseFile`. - Renamed `AppUrl` to `FrontendDist` and refactored its variants to be more explicit. ## \[2.0.0-alpha.21] ### New Features - [`27bad32d`](https://www.github.com/tauri-apps/tauri/commit/27bad32d4d4acca8155b20225d529d540fb9aaf4)([#7798](https://www.github.com/tauri-apps/tauri/pull/7798)) Add `files` object on the `tauri > bundle > macOS` configuration option. - [`0ec28c39`](https://www.github.com/tauri-apps/tauri/commit/0ec28c39f478de7199a66dd75e8642e1aa1344e6)([#8529](https://www.github.com/tauri-apps/tauri/pull/8529)) Include tauri-build on the migration script. ### Enhancements - [`091100ac`](https://www.github.com/tauri-apps/tauri/commit/091100acbb507b51de39fb1446f685926f888fd2)([#5202](https://www.github.com/tauri-apps/tauri/pull/5202)) Add RPM packaging ### Bug Fixes - [`4f73057e`](https://www.github.com/tauri-apps/tauri/commit/4f73057e6fd4c137bc112367fb91f5fc0c8a39f6)([#8486](https://www.github.com/tauri-apps/tauri/pull/8486)) Prevent `Invalid target triple` warnings and correctly set `TAURI_ENV_` vars when target triple contains 4 components. ### Dependencies - Upgraded to `tauri-cli@2.0.0-alpha.21` ### Breaking Changes - [`4f73057e`](https://www.github.com/tauri-apps/tauri/commit/4f73057e6fd4c137bc112367fb91f5fc0c8a39f6)([#8486](https://www.github.com/tauri-apps/tauri/pull/8486)) Removed `TAURI_ENV_PLATFORM_TYPE` which will not be set for CLI hook commands anymore, use `TAURI_ENV_PLATFORM` instead. Also Changed value of `TAURI_ENV_PLATFORM` and `TAURI_ENV_ARCH` values to match the target triple more accurately: - `darwin` and `androideabi` are no longer replaced with `macos` and `android` in `TAURI_ENV_PLATFORM`. - `i686` and `i586` are no longer replaced with `x86` in `TAURI_ENV_ARCH`. ## \[2.0.0-alpha.20] ### Dependencies - Upgraded to `tauri-cli@2.0.0-alpha.20` ## \[2.0.0-alpha.19] ### Dependencies - Upgraded to `tauri-cli@2.0.0-alpha.19` ## \[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 - [`c6c59cf2`](https://www.github.com/tauri-apps/tauri/commit/c6c59cf2373258b626b00a26f4de4331765dd487) Pull changes from Tauri 1.5 release. ### Dependencies - Upgraded to `tauri-cli@2.0.0-alpha.17` ### Breaking Changes - [`198abe3c`](https://www.github.com/tauri-apps/tauri/commit/198abe3c2cae06dacab860b3a93f715dcf529a95)([#8076](https://www.github.com/tauri-apps/tauri/pull/8076)) Updated the mobile plugin templates following the tauri v2.0.0-alpha.17 changes. ## \[2.0.0-alpha.16] ### New Features - [`8b166e9b`](https://www.github.com/tauri-apps/tauri/commit/8b166e9bf82e69ddb3200a3a825614980bd8d433)([#7949](https://www.github.com/tauri-apps/tauri/pull/7949)) Add `--no-dev-server-wait` option to skip waiting for the dev server to start when using `tauri dev`. ### Dependencies - Upgraded to `tauri-cli@2.0.0-alpha.16` ### Breaking Changes - [`8b166e9b`](https://www.github.com/tauri-apps/tauri/commit/8b166e9bf82e69ddb3200a3a825614980bd8d433)([#7949](https://www.github.com/tauri-apps/tauri/pull/7949)) Changed a number of environment variables used by tauri CLI for consistency and clarity: - `TAURI_PRIVATE_KEY` -> `TAURI_SIGNING_PRIVATE_KEY` - `TAURI_KEY_PASSWORD` -> `TAURI_SIGNING_PRIVATE_KEY_PASSWORD` - `TAURI_SKIP_DEVSERVER_CHECK` -> `TAURI_CLI_NO_DEV_SERVER_WAIT` - `TAURI_DEV_SERVER_PORT` -> `TAURI_CLI_PORT` - `TAURI_PATH_DEPTH` -> `TAURI_CLI_CONFIG_DEPTH` - `TAURI_FIPS_COMPLIANT` -> `TAURI_BUNDLER_WIX_FIPS_COMPLIANT` - `TAURI_DEV_WATCHER_IGNORE_FILE` -> `TAURI_CLI_WATCHER_IGNORE_FILENAME` - `TAURI_TRAY` -> `TAURI_LINUX_AYATANA_APPINDICATOR` - `TAURI_APPLE_DEVELOPMENT_TEAM` -> `APPLE_DEVELOPMENT_TEAM` - [`4caa1cca`](https://www.github.com/tauri-apps/tauri/commit/4caa1cca990806f2c2ef32d5dabaf56e82f349e6)([#7990](https://www.github.com/tauri-apps/tauri/pull/7990)) The `tauri plugin` subcommand is receving a couple of consitency and quality of life improvements: - Renamed `tauri plugin android/ios add` command to `tauri plugin android/ios init` to match the `tauri plugin init` command. - Removed the `-n/--name` argument from the `tauri plugin init`, `tauri plugin android/ios init`, and is now parsed from the first positional argument. - Added `tauri plugin new` to create a plugin in a new directory. - Changed `tauri plugin init` to initalize a plugin in an existing directory (defaults to current directory) instead of creating a new one. - Changed `tauri plugin init` to NOT generate mobile projects by default, you can opt-in to generate them using `--android` and `--ios` flags or `--mobile` flag or initalize them later using `tauri plugin android/ios init`. - [`8b166e9b`](https://www.github.com/tauri-apps/tauri/commit/8b166e9bf82e69ddb3200a3a825614980bd8d433)([#7949](https://www.github.com/tauri-apps/tauri/pull/7949)) Removed checking for a new version of the CLI. - [`ebcc21e4`](https://www.github.com/tauri-apps/tauri/commit/ebcc21e4b95f4e8c27639fb1bca545b432f52d5e)([#8057](https://www.github.com/tauri-apps/tauri/pull/8057)) Renamed the beforeDevCommand, beforeBuildCommand and beforeBundleCommand hooks environment variables from `TAURI_PLATFORM, TAURI_ARCH, TAURI_FAMILY, TAURI_PLATFORM_VERSION, TAURI_PLATFORM_TYPE and TAURI_DEBUG` to `TAURI_ENV_PLATFORM, TAURI_ENV_ARCH, TAURI_ENV_FAMILY, TAURI_ENV_PLATFORM_VERSION, TAURI_ENV_PLATFORM_TYPE and TAURI_ENV_DEBUG` to differentiate the prefix with other CLI environment variables. ## \[2.0.0-alpha.15] ### New Features - [`b2f17723`](https://www.github.com/tauri-apps/tauri/commit/b2f17723a415f04c2620132a6305eb138d7cb47f)([#7971](https://www.github.com/tauri-apps/tauri/pull/7971)) Use `devicectl` to connect to iOS 17+ devices on macOS 14+. ### Bug Fixes - [`100d9ede`](https://www.github.com/tauri-apps/tauri/commit/100d9ede35995d9db21d2087dd5606adfafb89a5)([#7802](https://www.github.com/tauri-apps/tauri/pull/7802)) Properly read platform-specific configuration files for mobile targets. - [`228e5a4c`](https://www.github.com/tauri-apps/tauri/commit/228e5a4c76ad5f97409c912d07699b49ba4bb162)([#7902](https://www.github.com/tauri-apps/tauri/pull/7902)) Fixes `icon` command not writing files to the correct Android project folders. ### Dependencies - Upgraded to `tauri-cli@2.0.0-alpha.15` ## \[2.0.0-alpha.14] ### Dependencies - Upgraded to `tauri-cli@2.0.0-alpha.14` ### Breaking Changes - [`d5074af5`](https://www.github.com/tauri-apps/tauri/commit/d5074af562b2b5cb6c5711442097c4058af32db6)([#7801](https://www.github.com/tauri-apps/tauri/pull/7801)) The custom protocol on Android now uses the `http` scheme instead of `https`. ## \[2.0.0-alpha.13] ### Dependencies - Upgraded to `tauri-cli@2.0.0-alpha.13` ### Breaking Changes - [`4cb51a2d`](https://www.github.com/tauri-apps/tauri/commit/4cb51a2d56cfcae0749062c79ede5236bd8c02c2)([#7779](https://www.github.com/tauri-apps/tauri/pull/7779)) The custom protocol on Windows now uses the `http` scheme instead of `https`. - [`974e38b4`](https://www.github.com/tauri-apps/tauri/commit/974e38b4ddc198530aa977ec77d513b76013b9f3)([#7744](https://www.github.com/tauri-apps/tauri/pull/7744)) Renamed the `plugin add` command to `add`. ## \[2.0.0-alpha.12] ### Bug Fixes - [`b75a1210`](https://www.github.com/tauri-apps/tauri/commit/b75a1210bed589187678861d7314ae6279bf7c87)([#7762](https://www.github.com/tauri-apps/tauri/pull/7762)) Fixes a regression on alpha.11 where iOS logs aren't being displayed when using `ios dev` with a real device. - [`8faa5a4a`](https://www.github.com/tauri-apps/tauri/commit/8faa5a4a1238a44ca7b54d2084aaed553ac2a1ba)([#7765](https://www.github.com/tauri-apps/tauri/pull/7765)) Ensure asset directory exists on the iOS project. ### Dependencies - Upgraded to `tauri-cli@2.0.0-alpha.12` ## \[2.0.0-alpha.11] ### New Features - [`522de0e7`](https://www.github.com/tauri-apps/tauri/commit/522de0e78891d0bdf6387a5118985fc41a11baeb)([#7447](https://www.github.com/tauri-apps/tauri/pull/7447)) Expose an environment variable `TAURI_${PLUGIN_NAME}_PLUGIN_CONFIG` for each defined plugin configuration object. - [`c7dacca4`](https://www.github.com/tauri-apps/tauri/commit/c7dacca4661c6ddf937c1a3dd3ace896d5baf40c)([#7446](https://www.github.com/tauri-apps/tauri/pull/7446)) Expose the `TAURI_IOS_PROJECT_PATH` and `TAURI_IOS_APP_NAME` environment variables when using `ios` commands. - [`aa94f719`](https://www.github.com/tauri-apps/tauri/commit/aa94f7197e4345a7cab1617272b10895859674f9)([#7445](https://www.github.com/tauri-apps/tauri/pull/7445)) Generate empty entitlements file for the iOS project. - [`d010bc07`](https://www.github.com/tauri-apps/tauri/commit/d010bc07b81116bef769b64cdc19b23dff762d48)([#7554](https://www.github.com/tauri-apps/tauri/pull/7554)) Set the iOS project PRODUCT_NAME value to the string under `tauri.conf.json > package > productName` if it is set. - [`8af24974`](https://www.github.com/tauri-apps/tauri/commit/8af2497496f11ee481472dfdc3125757346c1a3e)([#7561](https://www.github.com/tauri-apps/tauri/pull/7561)) The `migrate` command now automatically reads all JavaScript files and updates `@tauri-apps/api` import paths and install the missing plugins. ### Enhancements - [`fbeb5b91`](https://www.github.com/tauri-apps/tauri/commit/fbeb5b9185baeda19e865228179e3e44c165f1d9)([#7170](https://www.github.com/tauri-apps/tauri/pull/7170)) Update migrate command to update the configuration CSP to include `ipc:` on the `connect-src` directive, needed by the new IPC using custom protocols. ### Dependencies - Upgraded to `tauri-cli@2.0.0-alpha.11` ## \[2.0.0-alpha.10] ### New Features - [`7e5905ae`](https://www.github.com/tauri-apps/tauri/commit/7e5905ae1d56b920de0e821be28036cbbe302518)([#7023](https://www.github.com/tauri-apps/tauri/pull/7023)) Added `tauri plugin add` command to add a plugin to the Tauri project. - [`b0f94775`](https://www.github.com/tauri-apps/tauri/commit/b0f947752a315b7b89c5979de50157f997f1dd6e)([#7008](https://www.github.com/tauri-apps/tauri/pull/7008)) Added `migrate` command. ### Enhancements - [`aa6c9164`](https://www.github.com/tauri-apps/tauri/commit/aa6c9164e63b5316d690f25b1c118f1b12310570)([#7007](https://www.github.com/tauri-apps/tauri/pull/7007)) Don't build library files when building desktop targets. - [`a28fdf7e`](https://www.github.com/tauri-apps/tauri/commit/a28fdf7ec71bf6db2498569004de83318b6d25ac)([#7044](https://www.github.com/tauri-apps/tauri/pull/7044)) Skip Rust target installation if they are already installed. - [`735db1ce`](https://www.github.com/tauri-apps/tauri/commit/735db1ce839a16ba998c9e6786c441e3bf6c90b3)([#7044](https://www.github.com/tauri-apps/tauri/pull/7044)) Add `--skip-targets-install` flag for `tauri android init` and `tauri ios init` to skip installing needed rust targets vie rustup. ### Bug Fixes - [`1ed2600d`](https://www.github.com/tauri-apps/tauri/commit/1ed2600da67715908af857255305eaeb293d8791)([#6771](https://www.github.com/tauri-apps/tauri/pull/6771)) Set current directory to tauri directory before reading config file. - [`4847b87b`](https://www.github.com/tauri-apps/tauri/commit/4847b87b1067dd8c6e73986059f51e6eee1f1121)([#7209](https://www.github.com/tauri-apps/tauri/pull/7209)) Fix `tauri (android|ios) (dev|build)` failing when using `npx tauri` - [`655c714e`](https://www.github.com/tauri-apps/tauri/commit/655c714e4100f69d4265c5ea3f08f5bc11709446)([#7240](https://www.github.com/tauri-apps/tauri/pull/7240)) Fixes panic when exiting the `ios dev` command with Ctrl + C. - [`6252380f`](https://www.github.com/tauri-apps/tauri/commit/6252380f4447c66913b0f06611e5949005b1eec2)([#7241](https://www.github.com/tauri-apps/tauri/pull/7241)) Exit `beforeDevCommand` process if the android or iOS `dev` command fails. ## \[2.0.0-alpha.9] - [`19cd0e49`](https://www.github.com/tauri-apps/tauri/commit/19cd0e49603ad3500cd2180bfa16e1649e3a771a)([#6811](https://www.github.com/tauri-apps/tauri/pull/6811)) Add `key.properties` file to android's `.gitignore`. - [`124d5c5a`](https://www.github.com/tauri-apps/tauri/commit/124d5c5adf67f0b68d2e41c7ddb07d9cb63f1996)([#6788](https://www.github.com/tauri-apps/tauri/pull/6788)) On mobile, fix regression introduced in `tauri-cli` version `2.0.0-alpha.3` where library not found error was thrown. - [`31444ac1`](https://www.github.com/tauri-apps/tauri/commit/31444ac196add770f2ad18012d7c18bce7538f22)([#6725](https://www.github.com/tauri-apps/tauri/pull/6725)) Update mobile template to `wry@0.28` - [`41f49aea`](https://www.github.com/tauri-apps/tauri/commit/41f49aeae646f2cb70b42002bb1371c79e592243)([#6659](https://www.github.com/tauri-apps/tauri/pull/6659)) Update tauri-mobile to fix running ADB scripts. - [`6d1fa49f`](https://www.github.com/tauri-apps/tauri/commit/6d1fa49fce3a03965ce7c656390e682ce5b776e3)([#6881](https://www.github.com/tauri-apps/tauri/pull/6881)) Clear Android plugin JSON file before building Rust library to ensure removed plugins are propagated to the Android project. - [`5a9307d1`](https://www.github.com/tauri-apps/tauri/commit/5a9307d11c1643221bc2a280feb00024f8fa6030)([#6890](https://www.github.com/tauri-apps/tauri/pull/6890)) Update android template to gradle 8.0 - [`73c803a5`](https://www.github.com/tauri-apps/tauri/commit/73c803a561181137f20366f5d52511392a619f2b)([#6837](https://www.github.com/tauri-apps/tauri/pull/6837)) Inject Tauri configuration in the Android assets. - [`e1e85dc2`](https://www.github.com/tauri-apps/tauri/commit/e1e85dc2a5f656fc37867e278cae8042037740ac)([#6925](https://www.github.com/tauri-apps/tauri/pull/6925)) Moved the updater configuration to the `BundleConfig`. - [`d48aaa15`](https://www.github.com/tauri-apps/tauri/commit/d48aaa150a1ceeb65ec0ba18f1e3795f70c838e3)([#6894](https://www.github.com/tauri-apps/tauri/pull/6894)) Add Cargo manifest files for the plugin example templates. - [`e1e85dc2`](https://www.github.com/tauri-apps/tauri/commit/e1e85dc2a5f656fc37867e278cae8042037740ac)([#6925](https://www.github.com/tauri-apps/tauri/pull/6925)) Removed the allowlist configuration. ## \[2.0.0-alpha.8] - Do not gitignore the Android project's `buildSrc` folder by default since we removed absolute paths from it. - [ee2d3b97](https://www.github.com/tauri-apps/tauri/commit/ee2d3b971df6d3630b8d935394fb4febcfa3a909) fix(cli): remove buildSrc from Android project gitignored paths ([#6702](https://www.github.com/tauri-apps/tauri/pull/6702)) on 2023-04-13 - Fixes iOS build script using the wrong path for the app library file. - [abc5f91f](https://www.github.com/tauri-apps/tauri/commit/abc5f91fa3569efc9dfdee46d1c501eda8755944) fix(cli): iOS Xcode script using incorrect library path ([#6699](https://www.github.com/tauri-apps/tauri/pull/6699)) on 2023-04-13 ## \[2.0.0-alpha.7] - Add `--release` flag for `tauri android dev` however you will need to sign your Android app, see https://next--tauri.netlify.app/next/guides/distribution/sign-android - [63f088e5](https://www.github.com/tauri-apps/tauri/commit/63f088e5fc9701fd7fb329dad7ffb27a2d8fd5aa) feat(cli): add `--release` for `android dev` ([#6638](https://www.github.com/tauri-apps/tauri/pull/6638)) on 2023-04-05 - Build only specified rust targets for `tauri android build` instead of all. - [d03e47d1](https://www.github.com/tauri-apps/tauri/commit/d03e47d141c3917520975be9081775dbc4e9d4fd) fix: only build specified rust targets for aab/apk build ([#6625](https://www.github.com/tauri-apps/tauri/pull/6625)) on 2023-04-05 - Use local ip address for built-in dev server on mobile. - [7fec0f08](https://www.github.com/tauri-apps/tauri/commit/7fec0f083c932dc63ccb8716080d97e2ab985b25) fix(cli): use local ip addr for built-in server on mobile, closes [#6454](https://www.github.com/tauri-apps/tauri/pull/6454) ([#6631](https://www.github.com/tauri-apps/tauri/pull/6631)) on 2023-04-04 - Readd the Cargo.toml file to the plugin template. - [5288a386](https://www.github.com/tauri-apps/tauri/commit/5288a386f1bf8ac11f991350463c3f5c20983f43) fix(cli): readd Cargo.toml to the plugin template ([#6637](https://www.github.com/tauri-apps/tauri/pull/6637)) on 2023-04-04 ## \[2.0.0-alpha.6] - Use Ubuntu 20.04 to compile the CLI, increasing the minimum libc version required. - Automatically enable the `rustls-tls` tauri feature on mobile and `native-tls` on desktop if `rustls-tls` is not enabled. - [cfdee00f](https://www.github.com/tauri-apps/tauri/commit/cfdee00f2b1455a9719bc44823fdaeabbe4c1cb2) refactor(core): fix tls features, use rustls on mobile ([#6591](https://www.github.com/tauri-apps/tauri/pull/6591)) on 2023-03-30 ## \[2.0.0-alpha.5] - Fixes the iOS project script to build the Rust library. - [6e3e4c22](https://www.github.com/tauri-apps/tauri/commit/6e3e4c22be51500bec7856d90dcb2e40ef7fe1b4) fix(cli): use correct variable on script to build Rust iOS code ([#6581](https://www.github.com/tauri-apps/tauri/pull/6581)) on 2023-03-29 - Fix `tauri android build/dev` crashing when used with standalone `pnpm` executable on Windows. - [39df2c98](https://www.github.com/tauri-apps/tauri/commit/39df2c982e5e2ee8617b40f829a2f2e4abfce412) fix(cli/android): fallback to `${program}.cmd` ([#6576](https://www.github.com/tauri-apps/tauri/pull/6576)) on 2023-03-29 - [6b469c40](https://www.github.com/tauri-apps/tauri/commit/6b469c40c6244ba773d7478adbb41db6fdc72822) chore(changes): adjust change file for Android script execution fix on 2023-03-29 ## \[2.0.0-alpha.4] - Fix android project build crashing when using `pnpm` caused by extra `--`. - [c787f749](https://www.github.com/tauri-apps/tauri/commit/c787f749de01b79d891615aad8c37b23037fff4c) fix(cli): only add `--` to generated android template for npm ([#6508](https://www.github.com/tauri-apps/tauri/pull/6508)) on 2023-03-21 - Fixes the Android build gradle plugin implementation on Windows. - [00241fa9](https://www.github.com/tauri-apps/tauri/commit/00241fa92d104870068a701519340633cc35b716) fix(cli): append .cmd on the gradle plugin binary on Windows, fix [#6502](https://www.github.com/tauri-apps/tauri/pull/6502) ([#6503](https://www.github.com/tauri-apps/tauri/pull/6503)) on 2023-03-21 - Update `napi-rs` dependencies to latest to fix CLI hanging up forever. - [d5ac76b5](https://www.github.com/tauri-apps/tauri/commit/d5ac76b53c7f35253db84ddfbf4ecf975ff6307d) chore(deps): update napi-rs, closes [#6502](https://www.github.com/tauri-apps/tauri/pull/6502) ([#6513](https://www.github.com/tauri-apps/tauri/pull/6513)) on 2023-03-21 ## \[2.0.0-alpha.3] - Added `plugin android add` and `plugin ios add` commands to add mobile plugin functionality to existing projects. - [14d03d42](https://www.github.com/tauri-apps/tauri/commit/14d03d426e86d966950a790926c04560c76203b3) refactor(cli): enhance plugin commands for mobile ([#6289](https://www.github.com/tauri-apps/tauri/pull/6289)) on 2023-02-16 - Add commands to add native Android and iOS functionality to plugins. - [05dad087](https://www.github.com/tauri-apps/tauri/commit/05dad0876842e2a7334431247d49365cee835d3e) feat: initial work for iOS plugins ([#6205](https://www.github.com/tauri-apps/tauri/pull/6205)) on 2023-02-11 - Use temp file instead of environment variable to pass CLI IPC websocket address to the IDE. - [894a8d06](https://www.github.com/tauri-apps/tauri/commit/894a8d060c12a482a0fc5b3714f3848189b809de) refactor(cli): use temp file to communicate IPC websocket address ([#6219](https://www.github.com/tauri-apps/tauri/pull/6219)) on 2023-02-08 - Change the Android template to enable minification on release and pull ProGuard rules from proguard-tauri.pro. - [bef4ef51](https://www.github.com/tauri-apps/tauri/commit/bef4ef51bc2c633b88db121c2087a38dddb7d6bf) feat(android): enable minify on release, add proguard rules ([#6257](https://www.github.com/tauri-apps/tauri/pull/6257)) on 2023-02-13 - Print an error if the Android project was generated with an older bundle identifier or package name. - [79eb0542](https://www.github.com/tauri-apps/tauri/commit/79eb054292b04bb089a0e4df401a5986b33b691e) feat(cli): handle Android package identifier change ([#6314](https://www.github.com/tauri-apps/tauri/pull/6314)) on 2023-02-19 - Fixes the generated mobile build script when using an NPM runner. - [62f15265](https://www.github.com/tauri-apps/tauri/commit/62f152659204ce1218178596f463f0bcfbd4e6dc) fix(cli): generate build script using NPM runner if it was used ([#6233](https://www.github.com/tauri-apps/tauri/pull/6233)) on 2023-02-10 - Resolve Android package name from single word bundle identifiers. - [60a8b07d](https://www.github.com/tauri-apps/tauri/commit/60a8b07dc7c56c9c45331cb57d9afb410e7eadf3) fix: handle single word bundle identifier when resolving Android domain ([#6313](https://www.github.com/tauri-apps/tauri/pull/6313)) on 2023-02-19 - Update Android project template with fix to crash on orientation change. - [947eb391](https://www.github.com/tauri-apps/tauri/commit/947eb391ca41cebdb11abd9ffaec642baffbf44a) fix(android): crash on orientation change due to activity recreation ([#6261](https://www.github.com/tauri-apps/tauri/pull/6261)) on 2023-02-13 - Added `--ios-color` option to the `tauri icon` command. - [67755425](https://www.github.com/tauri-apps/tauri/commit/677554257e40e05b1af0dd61c982d6be8a8a033c) feat(cli): add `--ios-color` option to set iOS icon background color ([#6247](https://www.github.com/tauri-apps/tauri/pull/6247)) on 2023-02-12 - Fixes HMR on mobile when devPath is configured to load a filesystem path. - [4a82da29](https://www.github.com/tauri-apps/tauri/commit/4a82da2919e0564ec993b2005dc65b5b49407b36) fix(cli): use local ip address for reload ([#6285](https://www.github.com/tauri-apps/tauri/pull/6285)) on 2023-02-16 - Ignore the `gen` folder on the dev watcher. - [cab4ff95](https://www.github.com/tauri-apps/tauri/commit/cab4ff95b98aeac88401c1fed2d8b8940e4180cb) fix(cli): ignore the `gen` folder on the dev watcher ([#6232](https://www.github.com/tauri-apps/tauri/pull/6232)) on 2023-02-09 - Correctly pass arguments from `npm run` to `tauri`. - [1b343bd1](https://www.github.com/tauri-apps/tauri/commit/1b343bd11686f47f24a87298d8192097c66250f6) fix(cli): use `npm run tauri -- foo` for correctly passing args to tauri ([#6448](https://www.github.com/tauri-apps/tauri/pull/6448)) on 2023-03-16 - Changed the `--api` flag on `plugin init` to `--no-api`. - [14d03d42](https://www.github.com/tauri-apps/tauri/commit/14d03d426e86d966950a790926c04560c76203b3) refactor(cli): enhance plugin commands for mobile ([#6289](https://www.github.com/tauri-apps/tauri/pull/6289)) on 2023-02-16 ## \[2.0.0-alpha.2] - Fixes `TAURI_*` environment variables for hook scripts on mobile commands. - [1af9be90](https://www.github.com/tauri-apps/tauri/commit/1af9be904a309138b9f79dc741391000b1652c75) feat(cli): properly fill target for TAURI\_ env vars on mobile ([#6116](https://www.github.com/tauri-apps/tauri/pull/6116)) on 2023-01-23 - Force colored logs on mobile commands. - [2c4a0bbd](https://www.github.com/tauri-apps/tauri/commit/2c4a0bbd1fbe15d7500264e6490772397e1917ed) feat(cli): force colored logs on mobile commands ([#5934](https://www.github.com/tauri-apps/tauri/pull/5934)) on 2022-12-28 - Keep the process alive even when the iOS application is closed. - [dee9460f](https://www.github.com/tauri-apps/tauri/commit/dee9460f9c9bc92e9c638e7691e616849ac2085b) feat: keep CLI alive when iOS app exits, show logs, closes [#5855](https://www.github.com/tauri-apps/tauri/pull/5855) ([#5902](https://www.github.com/tauri-apps/tauri/pull/5902)) on 2022-12-27 - Show all application logs on iOS. - [dee9460f](https://www.github.com/tauri-apps/tauri/commit/dee9460f9c9bc92e9c638e7691e616849ac2085b) feat: keep CLI alive when iOS app exits, show logs, closes [#5855](https://www.github.com/tauri-apps/tauri/pull/5855) ([#5902](https://www.github.com/tauri-apps/tauri/pull/5902)) on 2022-12-27 - Print log output for all tags on Android development. - [8cc11149](https://www.github.com/tauri-apps/tauri/commit/8cc111494d74161e489152e52191e1442dd99759) fix(cli): print Android logs for all tags on 2023-01-17 - Add support to custom and kebab case library names for mobile apps. - [50f6dd87](https://www.github.com/tauri-apps/tauri/commit/50f6dd87b1ac2c99f8794b055f1acba4ef7d34d3) feat: improvements to support hyphens in crate name ([#5989](https://www.github.com/tauri-apps/tauri/pull/5989)) on 2023-01-06 - Fix target directory detection when compiling for Android. - [e873bae0](https://www.github.com/tauri-apps/tauri/commit/e873bae09f0f27517f720a753f51c1dcb903f883) fix(cli): Cargo target dir detection on Android, closes [#5865](https://www.github.com/tauri-apps/tauri/pull/5865) ([#5932](https://www.github.com/tauri-apps/tauri/pull/5932)) on 2022-12-28 ## \[2.0.0-alpha.1] - Fixes running on device using Xcode 14. - [1e4a6758](https://www.github.com/tauri-apps/tauri/commit/1e4a675843c486bddc11292d09fb766e98758514) fix(cli): run on iOS device on Xcode 14 ([#5807](https://www.github.com/tauri-apps/tauri/pull/5807)) on 2022-12-12 - Improve local IP address detection with user selection. - [76204b89](https://www.github.com/tauri-apps/tauri/commit/76204b893846a04552f8f8b87ad2c9b55e1b417f) feat(cli): improve local IP detection ([#5817](https://www.github.com/tauri-apps/tauri/pull/5817)) on 2022-12-12 ## \[2.0.0-alpha.0] - Added `android build` command. - [4c9ea450](https://www.github.com/tauri-apps/tauri/commit/4c9ea450c3b47c6b8c825ba32e9837909945ccd7) feat(cli): add `android build` command ([#4999](https://www.github.com/tauri-apps/tauri/pull/4999)) on 2022-08-22 - Added `ios build` command. - [403859d4](https://www.github.com/tauri-apps/tauri/commit/403859d47e1a9bf978b353fa58e4b971e66337a3) feat(cli): add `ios build` command ([#5002](https://www.github.com/tauri-apps/tauri/pull/5002)) on 2022-08-22 - Added `android dev` and `ios dev` commands. - [6f061504](https://www.github.com/tauri-apps/tauri/commit/6f0615044d09ec58393a7ebca5e45bb175e20db3) feat(cli): add `android dev` and `ios dev` commands ([#4982](https://www.github.com/tauri-apps/tauri/pull/4982)) on 2022-08-20 - Added `android init` and `ios init` commands. - [d44f67f7](https://www.github.com/tauri-apps/tauri/commit/d44f67f7afd30a81d53a973ec603b2a253150bde) feat: add `android init` and `ios init` commands ([#4942](https://www.github.com/tauri-apps/tauri/pull/4942)) on 2022-08-15 - Added `android open` and `ios open` commands. - [a9c8e565](https://www.github.com/tauri-apps/tauri/commit/a9c8e565c6495961940877df7090f307be16b554) feat: add `android open` and `ios open` commands ([#4946](https://www.github.com/tauri-apps/tauri/pull/4946)) on 2022-08-15 - First mobile alpha release! - [fa3a1098](https://www.github.com/tauri-apps/tauri/commit/fa3a10988a03aed1b66fb17d893b1a9adb90f7cd) feat(ci): prepare 2.0.0-alpha.0 ([#5786](https://www.github.com/tauri-apps/tauri/pull/5786)) on 2022-12-08 ## \[1.5.11] ### Bug Fixes - [`b15948b11`](https://www.github.com/tauri-apps/tauri/commit/b15948b11c0e362eea7ef57a4606f15f7dbd886b)([#8903](https://www.github.com/tauri-apps/tauri/pull/8903)) Fix `.taurignore` failing to ignore in some cases. ### Dependencies - Upgraded to `tauri-cli@1.5.11` ## \[1.5.10] ### Bug Fixes - [`b0f27814`](https://www.github.com/tauri-apps/tauri/commit/b0f27814b90ded2f1ed44b7852080eedbff0d9e4)([#8776](https://www.github.com/tauri-apps/tauri/pull/8776)) Fix `fail to rename app` when using `--profile dev`. - [`0bff8c32`](https://www.github.com/tauri-apps/tauri/commit/0bff8c325d004fdead2023f58e0f5fd73a9c22ba)([#8697](https://www.github.com/tauri-apps/tauri/pull/8697)) Fix the built-in dev server failing to serve files when URL had queries `?` and other url components. - [`67d7877f`](https://www.github.com/tauri-apps/tauri/commit/67d7877f27f265c133a70d48a46c83ffff31d571)([#8520](https://www.github.com/tauri-apps/tauri/pull/8520)) The cli now also watches cargo workspace members if the tauri folder is the workspace root. ### Dependencies - Upgraded to `tauri-cli@1.5.10` ## \[1.5.9] ### Bug Fixes - [`0a2175ea`](https://www.github.com/tauri-apps/tauri/commit/0a2175eabb736b2a4cd01ab682e08be0b5ebb2b9)([#8439](https://www.github.com/tauri-apps/tauri/pull/8439)) Expand glob patterns in workspace member paths so the CLI would watch all matching pathhs. ### Dependencies - Upgraded to `tauri-cli@1.5.9` ## \[1.5.8] ### Dependencies - Upgraded to `tauri-cli@1.5.8` ## \[1.5.7] ### Bug Fixes - [`1d5aa38a`](https://www.github.com/tauri-apps/tauri/commit/1d5aa38ae418ea31f593590b6d32cf04d3bfd8c1)([#8162](https://www.github.com/tauri-apps/tauri/pull/8162)) Fixes errors on command output, occuring when the output stream contains an invalid UTF-8 character, or ends with a multi-bytes UTF-8 character. - [`f26d9f08`](https://www.github.com/tauri-apps/tauri/commit/f26d9f0884f63f61b9f4d4fac15e6b251163793e)([#8263](https://www.github.com/tauri-apps/tauri/pull/8263)) Fixes an issue in the NSIS installer which caused the uninstallation to leave empty folders on the system if the `resources` feature was used. - [`92bc7d0e`](https://www.github.com/tauri-apps/tauri/commit/92bc7d0e16157434330a1bcf1eefda6f0f1e5f85)([#8233](https://www.github.com/tauri-apps/tauri/pull/8233)) Fixes an issue in the NSIS installer which caused the installation to take much longer than expected when many `resources` were added to the bundle. ### Dependencies - Upgraded to `tauri-cli@1.5.7` ## \[1.5.6] ### Bug Fixes - [`5264e41d`](https://www.github.com/tauri-apps/tauri/commit/5264e41db3763e4c2eb0c3c21bd423fb7bece3e2)([#8082](https://www.github.com/tauri-apps/tauri/pull/8082)) Downgraded `rust-minisign` to `0.7.3` to fix signing updater bundles with empty passwords. ### Dependencies - Upgraded to `tauri-cli@1.5.6` ## \[1.5.5] ### Enhancements - [`9bead42d`](https://www.github.com/tauri-apps/tauri/commit/9bead42dbca0fb6dd7ea0b6bfb2f2308a5c5f992)([#8059](https://www.github.com/tauri-apps/tauri/pull/8059)) Allow rotating the updater private key. ### Bug Fixes - [`be8e5aa3`](https://www.github.com/tauri-apps/tauri/commit/be8e5aa3071d9bc5d0bd24647e8168f312d11c8d)([#8042](https://www.github.com/tauri-apps/tauri/pull/8042)) Fixes duplicated newlines on command outputs. ### Dependencies - Upgraded to `tauri-cli@1.5.5` ## \[1.5.4] ### Dependencies - Upgraded to `tauri-cli@1.5.4` ## \[1.5.3] ### Dependencies - Upgraded to `tauri-cli@1.5.3` ## \[1.5.2] ### Dependencies - Upgraded to `tauri-cli@1.5.2` ## \[1.5.1] ### Bug Fixes - [`d6eb46cf`](https://www.github.com/tauri-apps/tauri/commit/d6eb46cf1116d147121f6b6db9d390b5e2fb238d)([#7934](https://www.github.com/tauri-apps/tauri/pull/7934)) On macOS, fix the `apple-id` option name when using `notarytools submit`. ### Dependencies - Upgraded to `tauri-cli@1.5.1` ## \[1.5.0] ### New Features - [`e1526626`](https://www.github.com/tauri-apps/tauri/commit/e152662687ece7a62d383923a50751cc0dd34331)([#7723](https://www.github.com/tauri-apps/tauri/pull/7723)) Support Bun package manager in CLI ### Enhancements - [`13279917`](https://www.github.com/tauri-apps/tauri/commit/13279917d4cae071d0ce3a686184d48af079f58a)([#7713](https://www.github.com/tauri-apps/tauri/pull/7713)) Add version of Rust Tauri CLI installed with Cargo to `tauri info` command. ### Bug Fixes - [`dad4f54e`](https://www.github.com/tauri-apps/tauri/commit/dad4f54eec9773d2ea6233a7d9fd218741173823)([#7277](https://www.github.com/tauri-apps/tauri/pull/7277)) Removed the automatic version check of the CLI that ran after `tauri` commands which caused various issues. ### Dependencies - Upgraded to `tauri-cli@1.5.0` ## \[1.4.0] ### New Features - [`0ddbb3a1`](https://www.github.com/tauri-apps/tauri/commit/0ddbb3a1dc1961ba5c6c1a60081513c1380c8af1)([#7015](https://www.github.com/tauri-apps/tauri/pull/7015)) Provide prebuilt CLIs for Windows ARM64 targets. - [`35cd751a`](https://www.github.com/tauri-apps/tauri/commit/35cd751adc6fef1f792696fa0cfb471b0bf99374)([#5176](https://www.github.com/tauri-apps/tauri/pull/5176)) Added the `desktop_template` option on `tauri.conf.json > tauri > bundle > deb`. - [`6c5ade08`](https://www.github.com/tauri-apps/tauri/commit/6c5ade08d97844bb685789d30e589400bbe3e04c)([#4537](https://www.github.com/tauri-apps/tauri/pull/4537)) Added `tauri completions` to generate shell completions scripts. - [`e092f799`](https://www.github.com/tauri-apps/tauri/commit/e092f799469ff32c7d1595d0f07d06fd2dab5c29)([#6887](https://www.github.com/tauri-apps/tauri/pull/6887)) Add `nsis > template` option to specify custom NSIS installer template. ### Enhancements - [`d75c1b82`](https://www.github.com/tauri-apps/tauri/commit/d75c1b829bd96d9e3a672bcc79120597d5ada4a0)([#7181](https://www.github.com/tauri-apps/tauri/pull/7181)) Print a useful error when `updater` bundle target is specified without an updater-enabled target. - [`52474e47`](https://www.github.com/tauri-apps/tauri/commit/52474e479d695865299d8c8d868fb98b99731020)([#7141](https://www.github.com/tauri-apps/tauri/pull/7141)) Enhance injection of Cargo features. - [`2659ca1a`](https://www.github.com/tauri-apps/tauri/commit/2659ca1ab4799a5bda65c229c149e98bd01eb1ee)([#6900](https://www.github.com/tauri-apps/tauri/pull/6900)) Add `rustls` as default Cargo feature. ### Bug Fixes - [`3cb7a3e6`](https://www.github.com/tauri-apps/tauri/commit/3cb7a3e642bb10ee90dc1d24daa48b8c8c15c9ce)([#6997](https://www.github.com/tauri-apps/tauri/pull/6997)) Fix built-in devserver adding hot-reload code to non-html files. - [`fb7ef8da`](https://www.github.com/tauri-apps/tauri/commit/fb7ef8dacd9ade96976c84d22507782cdaf38acf)([#6667](https://www.github.com/tauri-apps/tauri/pull/6667)) Fix nodejs binary regex when `0` is in the version name, for example `node-20` - [`1253bbf7`](https://www.github.com/tauri-apps/tauri/commit/1253bbf7ae11a87887e0b3bd98cc26dbb98c8130)([#7013](https://www.github.com/tauri-apps/tauri/pull/7013)) Fixes Cargo.toml feature rewriting. ## \[1.3.1] - Correctly escape XML for resource files in WiX bundler. - Bumped due to a bump in tauri-bundler. - Bumped due to a bump in cli.rs. - [6a6b1388](https://www.github.com/tauri-apps/tauri/commit/6a6b1388ea5787aea4c0e0b0701a4772087bbc0f) fix(bundler): correctly escape resource xml, fixes [#6853](https://www.github.com/tauri-apps/tauri/pull/6853) ([#6855](https://www.github.com/tauri-apps/tauri/pull/6855)) on 2023-05-04 - Added the following languages to the NSIS bundler: - `Spanish` - `SpanishInternational` - Bumped due to a bump in tauri-bundler. - Bumped due to a bump in cli.rs. - [422b4817](https://www.github.com/tauri-apps/tauri/commit/422b48179856504e980a156500afa8e22c44d357) Add Spanish and SpanishInternational languages ([#6871](https://www.github.com/tauri-apps/tauri/pull/6871)) on 2023-05-06 - Correctly escape arguments in NSIS script to fix bundling apps that use non-default WebView2 install modes. - Bumped due to a bump in tauri-bundler. - Bumped due to a bump in cli.rs. - [2915bd06](https://www.github.com/tauri-apps/tauri/commit/2915bd068ed40dc01a363b69212c6b6f2d3ec01e) fix(bundler): Fix webview install modes in NSIS bundler ([#6854](https://www.github.com/tauri-apps/tauri/pull/6854)) on 2023-05-04 ## \[1.3.0] - Add `--ci` flag and respect the `CI` environment variable on the `signer generate` command. In this case the default password will be an empty string and the CLI will not prompt for a value. - [8fb1df8a](https://www.github.com/tauri-apps/tauri/commit/8fb1df8aa65a52cdb4a7e1bb9dda9b912a7a2895) feat(cli): add `--ci` flag to `signer generate`, closes [#6089](https://www.github.com/tauri-apps/tauri/pull/6089) ([#6097](https://www.github.com/tauri-apps/tauri/pull/6097)) on 2023-01-19 - Fix Outdated Github Actions in the Plugin Templates `with-api` and `backend` - [a926b49a](https://www.github.com/tauri-apps/tauri/commit/a926b49a01925ca757d391994bfac3beea29599b) Fix Github Actions of Tauri Plugin with-api template ([#6603](https://www.github.com/tauri-apps/tauri/pull/6603)) on 2023-04-03 - Do not crash on Cargo.toml watcher. - [e8014a7f](https://www.github.com/tauri-apps/tauri/commit/e8014a7f612a1094461ddad63aacc498a2682ff5) fix(cli): do not crash on watcher ([#6303](https://www.github.com/tauri-apps/tauri/pull/6303)) on 2023-02-17 - Fix crash when nodejs binary has the version in its name, for example `node-18` - [1c8229fb](https://www.github.com/tauri-apps/tauri/commit/1c8229fbe273554c0c97cccee45d5967f5df1b9f) fix(cli.js): detect `node-` binary, closes [#6427](https://www.github.com/tauri-apps/tauri/pull/6427) ([#6432](https://www.github.com/tauri-apps/tauri/pull/6432)) on 2023-03-16 - Add `--png` option for the `icon` command to generate custom icon sizes. - [9d214412](https://www.github.com/tauri-apps/tauri/commit/9d2144128fc5fad67d8404bce95f82297ebb0e4a) feat(cli): add option to make custom icon sizes, closes [#5121](https://www.github.com/tauri-apps/tauri/pull/5121) ([#5246](https://www.github.com/tauri-apps/tauri/pull/5246)) on 2022-12-27 - Skip the password prompt on the build command when `TAURI_KEY_PASSWORD` environment variable is empty and the `--ci` argument is provided or the `CI` environment variable is set. - [d4f89af1](https://www.github.com/tauri-apps/tauri/commit/d4f89af18d69fd95a4d8a1ede8442547c6a6d0ee) feat: skip password prompt on the build command if CI is set fixes [#6089](https://www.github.com/tauri-apps/tauri/pull/6089) on 2023-01-18 - Fix `default-run` not deserialized. - [57c6bf07](https://www.github.com/tauri-apps/tauri/commit/57c6bf07bb380847abdf27c3fff9891d99c1c98c) fix(cli): fix default-run not deserialized ([#6584](https://www.github.com/tauri-apps/tauri/pull/6584)) on 2023-03-30 - Fixes HTML serialization removing template tags on the dev server. - [314f0e21](https://www.github.com/tauri-apps/tauri/commit/314f0e212fd2b9e452bfe3424cdce2b0bf37b5d7) fix(cli): web_dev_server html template serialization (fix [#6165](https://www.github.com/tauri-apps/tauri/pull/6165)) ([#6166](https://www.github.com/tauri-apps/tauri/pull/6166)) on 2023-01-29 - Use escaping on Handlebars templates. - [6d6b6e65](https://www.github.com/tauri-apps/tauri/commit/6d6b6e653ea70fc02794f723092cdc860995c259) feat: configure escaping on handlebars templates ([#6678](https://www.github.com/tauri-apps/tauri/pull/6678)) on 2023-05-02 - Add initial support for building `nsis` bundles on non-Windows platforms. - [60e6f6c3](https://www.github.com/tauri-apps/tauri/commit/60e6f6c3f1605f3064b5bb177992530ff788ccf0) feat(bundler): Add support for creating NSIS bundles on unix hosts ([#5788](https://www.github.com/tauri-apps/tauri/pull/5788)) on 2023-01-19 - Add `nsis` bundle target - [c94e1326](https://www.github.com/tauri-apps/tauri/commit/c94e1326a7c0767a13128a8b1d327a00156ece12) feat(bundler): add `nsis`, closes [#4450](https://www.github.com/tauri-apps/tauri/pull/4450), closes [#2319](https://www.github.com/tauri-apps/tauri/pull/2319) ([#4674](https://www.github.com/tauri-apps/tauri/pull/4674)) on 2023-01-03 - Remove default features from Cargo.toml template. - [b08ae637](https://www.github.com/tauri-apps/tauri/commit/b08ae637a0f58b38cbce9b8a1fa0b6c5dc0cfd05) fix(cli): remove default features from template ([#6074](https://www.github.com/tauri-apps/tauri/pull/6074)) on 2023-01-17 - Use Ubuntu 20.04 to compile the CLI, increasing the minimum libc version required. ## \[1.2.3] - Pin `ignore` to `=0.4.18`. - [adcb082b](https://www.github.com/tauri-apps/tauri/commit/adcb082b1651ecb2a6208b093e12f4185aa3fc98) chore(deps): pin `ignore` to =0.4.18 on 2023-01-17 ## \[1.2.2] - Detect SvelteKit and Vite for the init and info commands. - [9d872ab8](https://www.github.com/tauri-apps/tauri/commit/9d872ab8728b1b121909af434adcd5936e5afb7d) feat(cli): detect SvelteKit and Vite ([#5742](https://www.github.com/tauri-apps/tauri/pull/5742)) on 2022-12-02 - Detect SolidJS and SolidStart for the init and info commands. - [9e7ce0a8](https://www.github.com/tauri-apps/tauri/commit/9e7ce0a8eef4bf3536645976e3e09162fbf772ab) feat(cli): detect SolidJS and SolidStart ([#5758](https://www.github.com/tauri-apps/tauri/pull/5758)) on 2022-12-08 - Use older icon types to work around a macOS bug resulting in corrupted 16x16px and 32x32px icons in bundled apps. - [2d545eff](https://www.github.com/tauri-apps/tauri/commit/2d545eff58734ec70f23f11a429d35435cdf090e) fix(cli): corrupted icons in bundled macOS icons ([#5698](https://www.github.com/tauri-apps/tauri/pull/5698)) on 2022-11-28 ## \[1.2.1] - Fixes injection of Cargo features defined in the configuration file. - [1ecaeb29](https://www.github.com/tauri-apps/tauri/commit/1ecaeb29aa798f591f6488dc6c3a7a8d22f6073e) fix(cli): inject config feature flags when features arg is not provided on 2022-11-18 ## \[1.2.0] - Detect JSON5 and TOML configuration files in the dev watcher. - [e7ccbd85](https://www.github.com/tauri-apps/tauri/commit/e7ccbd8573f6b9124e80c0b67fa2365729c3c196) feat(cli): detect JSON5 and TOML configuration files in the dev watcher ([#5439](https://www.github.com/tauri-apps/tauri/pull/5439)) on 2022-10-19 - Log dev watcher file change detection. - [9076d5d2](https://www.github.com/tauri-apps/tauri/commit/9076d5d2e76d432aef475ba403e9ab5bd3b9d2b0) feat(cli): add prompt information when file changing detected, closes [#5417](https://www.github.com/tauri-apps/tauri/pull/5417) ([#5428](https://www.github.com/tauri-apps/tauri/pull/5428)) on 2022-10-19 - Fix crash when nodejs binary has the version in its name, for example `node18` or when running through deno. - [7a231cd1](https://www.github.com/tauri-apps/tauri/commit/7a231cd1c99101f63354b13bb36223568d2f0a11) fix(cli): detect deno ([#5475](https://www.github.com/tauri-apps/tauri/pull/5475)) on 2022-10-28 - Changed the project template to not enable all APIs by default. - [582c25a0](https://www.github.com/tauri-apps/tauri/commit/582c25a0f0fa2725d786ec4edd0defe7811ad6e8) refactor(cli): disable api-all on templates ([#5538](https://www.github.com/tauri-apps/tauri/pull/5538)) on 2022-11-03 ## \[1.1.1] - Fix wrong cli metadata that caused new projects (created through `tauri init`) fail to build - [db26aaf2](https://www.github.com/tauri-apps/tauri/commit/db26aaf2b44ce5335c9223c571ef2b2175e0cd6d) fix: fix wrong cli metadata ([#5214](https://www.github.com/tauri-apps/tauri/pull/5214)) on 2022-09-16 ## \[1.1.0] - Allow adding `build > beforeBundleCommand` in tauri.conf.json to run a shell command before the bundling phase. - [57ab9847](https://www.github.com/tauri-apps/tauri/commit/57ab9847eb2d8c9a5da584b873b7c072e9ee26bf) feat(cli): add `beforeBundleCommand`, closes [#4879](https://www.github.com/tauri-apps/tauri/pull/4879) ([#4893](https://www.github.com/tauri-apps/tauri/pull/4893)) on 2022-08-09 - Change `before_dev_command` and `before_build_command` config value to allow configuring the current working directory. - [d6f7d3cf](https://www.github.com/tauri-apps/tauri/commit/d6f7d3cfe8a7ec8d68c8341016c4e0a3103da587) Add cwd option to `before` commands, add wait option to dev [#4740](https://www.github.com/tauri-apps/tauri/pull/4740) [#3551](https://www.github.com/tauri-apps/tauri/pull/3551) ([#4834](https://www.github.com/tauri-apps/tauri/pull/4834)) on 2022-08-02 - Allow configuring the `before_dev_command` to force the CLI to wait for the command to finish before proceeding. - [d6f7d3cf](https://www.github.com/tauri-apps/tauri/commit/d6f7d3cfe8a7ec8d68c8341016c4e0a3103da587) Add cwd option to `before` commands, add wait option to dev [#4740](https://www.github.com/tauri-apps/tauri/pull/4740) [#3551](https://www.github.com/tauri-apps/tauri/pull/3551) ([#4834](https://www.github.com/tauri-apps/tauri/pull/4834)) on 2022-08-02 - Check if the default build target is set in the Cargo configuration. - [436f3d8d](https://www.github.com/tauri-apps/tauri/commit/436f3d8d66727f5b64165522f0b55f4ab54bd1ae) feat(cli): load Cargo configuration to check default build target ([#4990](https://www.github.com/tauri-apps/tauri/pull/4990)) on 2022-08-21 - Use `cargo metadata` to detect the workspace root and target directory. - [fea70eff](https://www.github.com/tauri-apps/tauri/commit/fea70effad219c0794d919f8834fa1a1ffd204c7) refactor(cli): Use `cargo metadata` to detect the workspace root and target directory, closes [#4632](https://www.github.com/tauri-apps/tauri/pull/4632), [#4928](https://www.github.com/tauri-apps/tauri/pull/4928). ([#4932](https://www.github.com/tauri-apps/tauri/pull/4932)) on 2022-08-21 - Prompt for `beforeDevCommand` and `beforeBuildCommand` in `tauri init`. - [6d4945c9](https://www.github.com/tauri-apps/tauri/commit/6d4945c9f06cd1f7018e1c48686ba682aae817df) feat(cli): prompt for before\*Command, closes [#4691](https://www.github.com/tauri-apps/tauri/pull/4691) ([#4721](https://www.github.com/tauri-apps/tauri/pull/4721)) on 2022-07-25 - Added support to configuration files in TOML format (Tauri.toml file). - [ae83d008](https://www.github.com/tauri-apps/tauri/commit/ae83d008f9e1b89bfc8dddaca42aa5c1fbc36f6d) feat: add support to TOML config file `Tauri.toml`, closes [#4806](https://www.github.com/tauri-apps/tauri/pull/4806) ([#4813](https://www.github.com/tauri-apps/tauri/pull/4813)) on 2022-08-02 - Automatically use any `.taurignore` file as ignore rules for dev watcher and app path finder. - [596fa08d](https://www.github.com/tauri-apps/tauri/commit/596fa08d48e371c7bd29e1ef799119ac8fca0d0b) feat(cli): automatically use `.taurignore`, ref [#4617](https://www.github.com/tauri-apps/tauri/pull/4617) ([#4623](https://www.github.com/tauri-apps/tauri/pull/4623)) on 2022-07-28 - Enable WiX FIPS compliance when the `TAURI_FIPS_COMPLIANT` environment variable is set to `true`. - [d88b9de7](https://www.github.com/tauri-apps/tauri/commit/d88b9de7aaeaaa2e42e4795dbc2b8642b5ae7a50) feat(core): add `fips_compliant` wix config option, closes [#4541](https://www.github.com/tauri-apps/tauri/pull/4541) ([#4843](https://www.github.com/tauri-apps/tauri/pull/4843)) on 2022-08-04 - Fixes dev watcher incorrectly exiting the CLI when sequential file updates are detected. - [47fab680](https://www.github.com/tauri-apps/tauri/commit/47fab6809a1e23b3b9a84695e2d91ff0826ba79a) fix(cli): dev watcher incorrectly killing process on multiple file write ([#4684](https://www.github.com/tauri-apps/tauri/pull/4684)) on 2022-07-25 - Add `libc` field to Node packages. - [f7d2dfc7](https://www.github.com/tauri-apps/tauri/commit/f7d2dfc7a6d086dd1a218d6c1492b3fef8a64f03) chore: add libc field to node packages ([#4856](https://www.github.com/tauri-apps/tauri/pull/4856)) on 2022-08-04 - Set the `MACOSX_DEPLOYMENT_TARGET` environment variable with the configuration `minimum_system_version` value. - [fa23310f](https://www.github.com/tauri-apps/tauri/commit/fa23310f23cb9e6a02ec2524f1ef394a5b42990e) fix(cli): set MACOSX_DEPLOYMENT_TARGET env var, closes [#4704](https://www.github.com/tauri-apps/tauri/pull/4704) ([#4842](https://www.github.com/tauri-apps/tauri/pull/4842)) on 2022-08-02 - Added `--no-watch` argument to the `dev` command to disable the file watcher. - [0983d7ce](https://www.github.com/tauri-apps/tauri/commit/0983d7ce7f24ab43f9ae7b5e1177ff244d8885a8) feat(cli): add `--no-watch` argument to the dev command, closes [#4617](https://www.github.com/tauri-apps/tauri/pull/4617) ([#4793](https://www.github.com/tauri-apps/tauri/pull/4793)) on 2022-07-29 - Validate updater signature matches configured public key. - [b2a8930b](https://www.github.com/tauri-apps/tauri/commit/b2a8930b3c4b72c50ce72e73575f42c9cbe91bad) feat(cli): validate updater private key when signing ([#4754](https://www.github.com/tauri-apps/tauri/pull/4754)) on 2022-07-25 ## \[1.0.5] - Correctly fill the architecture when building Debian packages targeting ARM64 (aarch64). - Bumped due to a bump in cli.rs. - [635f23b8](https://www.github.com/tauri-apps/tauri/commit/635f23b88adbb8726d628f67840709cd870836dc) fix(bundler): correctly set debian architecture for aarch64 ([#4700](https://www.github.com/tauri-apps/tauri/pull/4700)) on 2022-07-17 ## \[1.0.4] - Do not capture and force colors of `cargo build` output. - [c635a0da](https://www.github.com/tauri-apps/tauri/commit/c635a0dad437860d54109adffaf245b7c21bc684) refactor(cli): do not capture and force colors of cargo build output ([#4627](https://www.github.com/tauri-apps/tauri/pull/4627)) on 2022-07-12 - Reduce the amount of allocations when converting cases. - [bc370e32](https://www.github.com/tauri-apps/tauri/commit/bc370e326810446e15b1f50fb962b980114ba16b) feat: reduce the amount of `heck`-related allocations ([#4634](https://www.github.com/tauri-apps/tauri/pull/4634)) on 2022-07-11 ## \[1.0.3] - Changed the app template to not set the default app menu as it is now set automatically on macOS which is the platform that needs a menu to function properly. - [91055883](https://www.github.com/tauri-apps/tauri/commit/9105588373cc8401bd9ad79bdef26f509b2d76b7) feat: add implicit default menu for macOS only, closes [#4551](https://www.github.com/tauri-apps/tauri/pull/4551) ([#4570](https://www.github.com/tauri-apps/tauri/pull/4570)) on 2022-07-04 - Improved bundle identifier validation showing the exact source of the configuration value. - [8e3e7fc6](https://www.github.com/tauri-apps/tauri/commit/8e3e7fc64641afc7a6833bc93205e6f525562545) feat(cli): improve bundle identifier validation, closes [#4589](https://www.github.com/tauri-apps/tauri/pull/4589) ([#4596](https://www.github.com/tauri-apps/tauri/pull/4596)) on 2022-07-05 - Improve configuration deserialization error messages. - [9170c920](https://www.github.com/tauri-apps/tauri/commit/9170c9207044fa561535f624916dfdbaa41ff79d) feat(core): improve config deserialization error messages ([#4607](https://www.github.com/tauri-apps/tauri/pull/4607)) on 2022-07-06 - Revert the `run` command to run in a separate thread. - [f65eb4f8](https://www.github.com/tauri-apps/tauri/commit/f65eb4f84d8e511cd30d01d20a8223a297f7e584) fix(cli.js): revert `run` command to be nonblocking on 2022-07-04 - Skip the static link of the `vcruntime140.dll` if the `STATIC_VCRUNTIME` environment variable is set to `false`. - [2e61abaa](https://www.github.com/tauri-apps/tauri/commit/2e61abaa9ae5d7a41ca1fa6505b5d6c368625ce5) feat(cli): allow dynamic link vcruntime, closes [#4565](https://www.github.com/tauri-apps/tauri/pull/4565) ([#4601](https://www.github.com/tauri-apps/tauri/pull/4601)) on 2022-07-06 - The `TAURI_CONFIG` environment variable now represents the configuration to be merged instead of the entire JSON. - [fa028ebf](https://www.github.com/tauri-apps/tauri/commit/fa028ebf3c8ca7b43a70d283a01dbea86217594f) refactor: do not pass entire config from CLI to core, send patch instead ([#4598](https://www.github.com/tauri-apps/tauri/pull/4598)) on 2022-07-06 - Watch for Cargo workspace members in the `dev` file watcher. - [dbb8c87b](https://www.github.com/tauri-apps/tauri/commit/dbb8c87b96dec9942b1bf877b29bafb8246514d4) feat(cli): watch Cargo workspaces in the dev command, closes [#4222](https://www.github.com/tauri-apps/tauri/pull/4222) ([#4572](https://www.github.com/tauri-apps/tauri/pull/4572)) on 2022-07-03 ## \[1.0.2] - Fixes a crash on the `signer sign` command. - [8e808fec](https://www.github.com/tauri-apps/tauri/commit/8e808fece95f2e506acf2c446d37b9913fd67d50) fix(cli.rs): conflicts_with arg doesn't exist closes ([#4538](https://www.github.com/tauri-apps/tauri/pull/4538)) on 2022-06-30 ## \[1.0.1] - No longer adds the `pkg-config` dependency to `.deb` packages when the `systemTray` is used. This only works with recent versions of `libappindicator-sys` (including https://github.com/tauri-apps/libappindicator-rs/pull/38), so a `cargo update` may be necessary if you create `.deb` bundles and use the tray feature. - [0e6edeb1](https://www.github.com/tauri-apps/tauri/commit/0e6edeb14f379af1e02a7cebb4e3a5c9e87ebf7f) fix(cli): Don't add `pkg-config` to `deb` ([#4508](https://www.github.com/tauri-apps/tauri/pull/4508)) on 2022-06-29 - AppImage bundling will now prefer bundling correctly named appindicator library (including `.1` version suffix). With a symlink for compatibility with the old naming. - [bf45ca1d](https://www.github.com/tauri-apps/tauri/commit/bf45ca1df6691c05bdf72c5716cc01e89a7791d4) fix(cli,bundler): prefer AppImage libraries with ABI version ([#4505](https://www.github.com/tauri-apps/tauri/pull/4505)) on 2022-06-29 - Improve error message when `cargo` is not installed. - [e0e5f772](https://www.github.com/tauri-apps/tauri/commit/e0e5f772430f6349ec99ba891e601331e376e3c7) feat(cli): improve `cargo not found` error message, closes [#4428](https://www.github.com/tauri-apps/tauri/pull/4428) ([#4430](https://www.github.com/tauri-apps/tauri/pull/4430)) on 2022-06-21 - The app template now only sets the default menu on macOS. - [5105b428](https://www.github.com/tauri-apps/tauri/commit/5105b428c4726b2179cd4b3244350d1a1ee73734) feat(cli): change app template to only set default menu on macOS ([#4518](https://www.github.com/tauri-apps/tauri/pull/4518)) on 2022-06-29 - Warn if updater is enabled but not in the bundle target list. - [31c15cd2](https://www.github.com/tauri-apps/tauri/commit/31c15cd2bd94dbe39fb94982a15cbe02ac5d8925) docs(config): enhance documentation for bundle targets, closes [#3251](https://www.github.com/tauri-apps/tauri/pull/3251) ([#4418](https://www.github.com/tauri-apps/tauri/pull/4418)) on 2022-06-21 - Check if target exists and is installed on dev and build commands. - [13b8a240](https://www.github.com/tauri-apps/tauri/commit/13b8a2403d1353a8c3a643fbc6b6e862af68376e) feat(cli): validate target argument ([#4458](https://www.github.com/tauri-apps/tauri/pull/4458)) on 2022-06-24 - Fixes the covector configuration on the plugin templates. - [b8a64d01](https://www.github.com/tauri-apps/tauri/commit/b8a64d01bab11f955b7bbdf323d0afa1a3db4b64) fix(cli): add prepublish scripts to the plugin templates on 2022-06-19 - Set the binary name to the product name in development. - [b025b9f5](https://www.github.com/tauri-apps/tauri/commit/b025b9f581ac1a6ae0a26789c2be1e9928fb0282) refactor(cli): set binary name on dev ([#4447](https://www.github.com/tauri-apps/tauri/pull/4447)) on 2022-06-23 - Allow registering a `.gitignore` file to skip watching some project files and directories via the `TAURI_DEV_WATCHER_IGNORE_FILE` environment variable. - [83186dd8](https://www.github.com/tauri-apps/tauri/commit/83186dd89768407984db35fb67c3cc51f50ea8f5) Read extra ignore file for dev watcher, closes [#4406](https://www.github.com/tauri-apps/tauri/pull/4406) ([#4409](https://www.github.com/tauri-apps/tauri/pull/4409)) on 2022-06-20 - Fix shebang for `kill-children.sh`. - [35dd51db](https://www.github.com/tauri-apps/tauri/commit/35dd51db6826ec1eed7b90082b9eb6b2a699b627) fix(cli): add shebang for kill-children.sh, closes [#4262](https://www.github.com/tauri-apps/tauri/pull/4262) ([#4416](https://www.github.com/tauri-apps/tauri/pull/4416)) on 2022-06-22 - Update plugin templates to use newer `tauri-apps/create-pull-request` GitHub action. - [07f90795](https://www.github.com/tauri-apps/tauri/commit/07f9079532a42f3517d96faeaf46cad6176b31ac) chore(cli): update plugin template tauri-apps/create-pull-request on 2022-06-19 - Use UNIX path separator on the init `$schema` field. - [01053045](https://www.github.com/tauri-apps/tauri/commit/010530459ef62c48eed68ca965f2688accabcf69) chore(cli): use unix path separator on $schema ([#4384](https://www.github.com/tauri-apps/tauri/pull/4384)) on 2022-06-19 - The `info` command now can check the Cargo lockfile on workspaces. - [12f65219](https://www.github.com/tauri-apps/tauri/commit/12f65219ea75a51ebd38659ddce1563e015a036c) fix(cli): read lockfile from workspace on the info command, closes [#4232](https://www.github.com/tauri-apps/tauri/pull/4232) ([#4423](https://www.github.com/tauri-apps/tauri/pull/4423)) on 2022-06-21 - Preserve the `Cargo.toml` formatting when the features array is not changed. - [6650e5d6](https://www.github.com/tauri-apps/tauri/commit/6650e5d6720c215530ca1fdccd19bd2948dd6ca3) fix(cli): preserve Cargo manifest formatting when possible ([#4431](https://www.github.com/tauri-apps/tauri/pull/4431)) on 2022-06-21 - Change the updater signature metadata to include the file name instead of its full path. - [094b3eb3](https://www.github.com/tauri-apps/tauri/commit/094b3eb352bcf5de28414015e7c44290d619ea8c) fix(cli): file name instead of path on updater sig comment, closes [#4467](https://www.github.com/tauri-apps/tauri/pull/4467) ([#4484](https://www.github.com/tauri-apps/tauri/pull/4484)) on 2022-06-27 - Validate bundle identifier as it must only contain alphanumeric characters, hyphens and periods. - [0674a801](https://www.github.com/tauri-apps/tauri/commit/0674a80129d7c31bc93257849afc0a5069129fed) fix: assert config.bundle.identifier to be only alphanumeric, hyphens or dots. closes [#4359](https://www.github.com/tauri-apps/tauri/pull/4359) ([#4363](https://www.github.com/tauri-apps/tauri/pull/4363)) on 2022-06-17 ## \[1.0.0] - Upgrade to `stable`! - [f4bb30cc](https://www.github.com/tauri-apps/tauri/commit/f4bb30cc73d6ba9b9ef19ef004dc5e8e6bb901d3) feat(covector): prepare for v1 ([#4351](https://www.github.com/tauri-apps/tauri/pull/4351)) on 2022-06-15 ## \[1.0.0-rc.16] - Use the default window menu in the app template. - [4c4acc30](https://www.github.com/tauri-apps/tauri/commit/4c4acc3094218dd9cee0f1ad61810c979e0b41fa) feat: implement `Default` for `Menu`, closes [#2398](https://www.github.com/tauri-apps/tauri/pull/2398) ([#4291](https://www.github.com/tauri-apps/tauri/pull/4291)) on 2022-06-15 ## \[1.0.0-rc.15] - Removed the tray icon from the Debian and AppImage bundles since they are embedded in the binary now. - [4ce8e228](https://www.github.com/tauri-apps/tauri/commit/4ce8e228134cd3f22973b74ef26ca0d165fbbbd9) refactor(core): use `Icon` for tray icons ([#4342](https://www.github.com/tauri-apps/tauri/pull/4342)) on 2022-06-14 ## \[1.0.0-rc.14] - Set the `TRAY_LIBRARY_PATH` environment variable to make the bundle copy the appindicator library to the AppImage. - [34552444](https://www.github.com/tauri-apps/tauri/commit/3455244436578003a5fbb447b039e5c8971152ec) feat(cli): bundle appindicator library in the AppImage, closes [#3859](https://www.github.com/tauri-apps/tauri/pull/3859) ([#4267](https://www.github.com/tauri-apps/tauri/pull/4267)) on 2022-06-07 - Set the `APPIMAGE_BUNDLE_GSTREAMER` environment variable to make the bundler copy additional gstreamer files to the AppImage. - [d335fae9](https://www.github.com/tauri-apps/tauri/commit/d335fae92cdcbb0ee18aad4e54558914afa3e778) feat(bundler): bundle additional gstreamer files, closes [#4092](https://www.github.com/tauri-apps/tauri/pull/4092) ([#4271](https://www.github.com/tauri-apps/tauri/pull/4271)) on 2022-06-10 - Configure the AppImage bundler to copy the `/usr/bin/xdg-open` binary if it exists and the shell `open` API is enabled. - [2322ac11](https://www.github.com/tauri-apps/tauri/commit/2322ac11cf6290c6bf65413048a049c8072f863b) fix(bundler): bundle `/usr/bin/xdg-open` in appimage if open API enabled ([#4265](https://www.github.com/tauri-apps/tauri/pull/4265)) on 2022-06-04 - Fixes multiple occurrences handling of the `bundles` and `features` arguments. - [f685df39](https://www.github.com/tauri-apps/tauri/commit/f685df399a5a05480b6e4f5d92da71f3b87895ef) fix(cli): parsing of arguments with multiple values, closes [#4231](https://www.github.com/tauri-apps/tauri/pull/4231) ([#4233](https://www.github.com/tauri-apps/tauri/pull/4233)) on 2022-05-29 - Log command output in real time instead of waiting for it to finish. - [76d1eaae](https://www.github.com/tauri-apps/tauri/commit/76d1eaaebda5c8f6b0d41bf6587945e98cd441f3) feat(cli): debug command output in real time ([#4318](https://www.github.com/tauri-apps/tauri/pull/4318)) on 2022-06-12 - Configure the `STATIC_VCRUNTIME` environment variable so `tauri-build` statically links it on the build command. - [d703d27a](https://www.github.com/tauri-apps/tauri/commit/d703d27a707edc028f13b35603205da1133fcc2b) fix(build): statically link VC runtime only on `tauri build` ([#4292](https://www.github.com/tauri-apps/tauri/pull/4292)) on 2022-06-07 - Use the `TAURI_TRAY` environment variable to determine which package should be added to the Debian `depends` section. Possible values are `ayatana` and `gtk`. - [6216eb49](https://www.github.com/tauri-apps/tauri/commit/6216eb49e72863bfb6d4c9edb8827b21406ac393) refactor(core): drop `ayatana-tray` and `gtk-tray` Cargo features ([#4247](https://www.github.com/tauri-apps/tauri/pull/4247)) on 2022-06-02 ## \[1.0.0-rc.13] - Check if `$CWD/src-tauri/tauri.conf.json` exists before walking through the file tree to find the tauri dir in case the whole project is gitignored. - [bd8f3e29](https://www.github.com/tauri-apps/tauri/commit/bd8f3e298a0cb71809f2e93cc3ebc8e6e5b6a626) fix(cli): manual config lookup to handle gitignored folders, fixes [#3527](https://www.github.com/tauri-apps/tauri/pull/3527) ([#4224](https://www.github.com/tauri-apps/tauri/pull/4224)) on 2022-05-26 - Statically link the Visual C++ runtime instead of using a merge module on the installer. - [bb061509](https://www.github.com/tauri-apps/tauri/commit/bb061509fb674bef86ecbc1de3aa8f3e367a9907) refactor(core): statically link vcruntime, closes [#4122](https://www.github.com/tauri-apps/tauri/pull/4122) ([#4227](https://www.github.com/tauri-apps/tauri/pull/4227)) on 2022-05-27 ## \[1.0.0-rc.12] - Properly fetch the NPM dependency information when using Yarn 2+. - [cdfa6255](https://www.github.com/tauri-apps/tauri/commit/cdfa62551115586725bd3e4c04f12c5256f20790) fix(cli): properly read info when using yarn 2+, closes [#4106](https://www.github.com/tauri-apps/tauri/pull/4106) ([#4193](https://www.github.com/tauri-apps/tauri/pull/4193)) on 2022-05-23 ## \[1.0.0-rc.11] - Allow configuring the display options for the MSI execution allowing quieter updates. - [9f2c3413](https://www.github.com/tauri-apps/tauri/commit/9f2c34131952ea83c3f8e383bc3cec7e1450429f) feat(core): configure msiexec display options, closes [#3951](https://www.github.com/tauri-apps/tauri/pull/3951) ([#4061](https://www.github.com/tauri-apps/tauri/pull/4061)) on 2022-05-15 ## \[1.0.0-rc.10] - Resolve binary file extension from target triple instead of compile-time checks to allow cross compilation. - [4562e671](https://www.github.com/tauri-apps/tauri/commit/4562e671e4795e9386429348bf738f7078706945) fix(build): append .exe binary based on target triple instead of running OS, closes [#3870](https://www.github.com/tauri-apps/tauri/pull/3870) ([#4032](https://www.github.com/tauri-apps/tauri/pull/4032)) on 2022-05-03 - Fixes text overflow on `tauri dev` on Windows. - [094534d1](https://www.github.com/tauri-apps/tauri/commit/094534d138a9286e4746b61adff2da616e3b6a61) fix(cli): dev command stderr text overflow on Windows, closes [#3995](https://www.github.com/tauri-apps/tauri/pull/3995) ([#4000](https://www.github.com/tauri-apps/tauri/pull/4000)) on 2022-04-29 - Improve CLI's logging output, making use of the standard rust `log` system. - [35f21471](https://www.github.com/tauri-apps/tauri/commit/35f2147161e6697cbd2824681eeaf870b5a991c2) feat(cli): Improve CLI logging ([#4060](https://www.github.com/tauri-apps/tauri/pull/4060)) on 2022-05-07 - Don't override the default keychain on macOS while code signing. - [a4fcaf1d](https://www.github.com/tauri-apps/tauri/commit/a4fcaf1d04aafc3b4d42186f0fb386797d959a9d) fix: don't override default keychain, closes [#4008](https://www.github.com/tauri-apps/tauri/pull/4008) ([#4053](https://www.github.com/tauri-apps/tauri/pull/4053)) on 2022-05-05 - - Remove startup delay in `tauri dev` caused by checking for a newer cli version. The check is now done upon process exit. - Add `TAURI_SKIP_UPDATE_CHECK` env variable to skip checking for a newer CLI version. - [bbabc8cd](https://www.github.com/tauri-apps/tauri/commit/bbabc8cd1ea2c1f6806610fd2d533c99305d320c) fix(cli.rs): remove startup delay in `tauri dev` ([#3999](https://www.github.com/tauri-apps/tauri/pull/3999)) on 2022-04-29 - Fix `tauri info` panic when a package isn't installed. - [4f0f3187](https://www.github.com/tauri-apps/tauri/commit/4f0f3187c9e69262ef28350331b368c831ab930a) fix(cli.rs): fix `tauri info` panic when a package isn't installed, closes [#3985](https://www.github.com/tauri-apps/tauri/pull/3985) ([#3996](https://www.github.com/tauri-apps/tauri/pull/3996)) on 2022-04-29 - Added `$schema` support to `tauri.conf.json`. - [715cbde3](https://www.github.com/tauri-apps/tauri/commit/715cbde3842a916c4ebeab2cab348e1774b5c192) feat(config): add `$schema` to `tauri.conf.json`, closes [#3464](https://www.github.com/tauri-apps/tauri/pull/3464) ([#4031](https://www.github.com/tauri-apps/tauri/pull/4031)) on 2022-05-03 - **Breaking change:** The `dev` command now reads the custom config file from CWD instead of the Tauri folder. - [a1929c6d](https://www.github.com/tauri-apps/tauri/commit/a1929c6dacccd00af4cdbcc4d29cfb98d8428f55) fix(cli): always read custom config file from CWD, closes [#4067](https://www.github.com/tauri-apps/tauri/pull/4067) ([#4074](https://www.github.com/tauri-apps/tauri/pull/4074)) on 2022-05-07 - Fixes a Powershell crash when sending SIGINT to the dev command. - [32048486](https://www.github.com/tauri-apps/tauri/commit/320484866b83ecabb01eb58d158e0fedd9dd08be) fix(cli): powershell crashing on SIGINT, closes [#3997](https://www.github.com/tauri-apps/tauri/pull/3997) ([#4007](https://www.github.com/tauri-apps/tauri/pull/4007)) on 2022-04-29 - Prevent building when the bundle identifier is the default `com.tauri.dev`. - [95726ebb](https://www.github.com/tauri-apps/tauri/commit/95726ebb6180d371be44bff9f16ca1eee049006a) feat(cli): prevent default bundle identifier from building, closes [#4041](https://www.github.com/tauri-apps/tauri/pull/4041) ([#4042](https://www.github.com/tauri-apps/tauri/pull/4042)) on 2022-05-04 ## \[1.0.0-rc.9] - Exit CLI when Cargo returns a non-compilation error in `tauri dev`. - [b5622882](https://www.github.com/tauri-apps/tauri/commit/b5622882cf3748e1e5a90915f415c0cd922aaaf8) fix(cli): exit on non-compilation Cargo errors, closes [#3930](https://www.github.com/tauri-apps/tauri/pull/3930) ([#3942](https://www.github.com/tauri-apps/tauri/pull/3942)) on 2022-04-22 - Notify CLI update when running `tauri dev`. - [a649aad7](https://www.github.com/tauri-apps/tauri/commit/a649aad7ad26d4578699370d6e63d80edeca1f97) feat(cli): check and notify about updates on `tauri dev`, closes [#3789](https://www.github.com/tauri-apps/tauri/pull/3789) ([#3960](https://www.github.com/tauri-apps/tauri/pull/3960)) on 2022-04-25 - Kill the `beforeDevCommand` and app processes if the dev command returns an error. - [485c9743](https://www.github.com/tauri-apps/tauri/commit/485c97438ac956d86bcf3794ceaa626bef968a4e) fix(cli): kill beforeDevCommand if dev code returns an error ([#3907](https://www.github.com/tauri-apps/tauri/pull/3907)) on 2022-04-19 - Fix `info` command showing outdated text for latest versions. - [73a4b74a](https://www.github.com/tauri-apps/tauri/commit/73a4b74aea8544e6fda51c1f6697630b0768072c) fix(cli.rs/info): don't show outdated text for latest versions ([#3829](https://www.github.com/tauri-apps/tauri/pull/3829)) on 2022-04-02 - **Breaking change:** Enable default Cargo features except `tauri/custom-protocol` on the dev command. - [f2a30d8b](https://www.github.com/tauri-apps/tauri/commit/f2a30d8bc54fc3ba49e16f69a413eca5f61a9b1f) refactor(core): use ayatana appindicator by default, keep option to use gtk ([#3916](https://www.github.com/tauri-apps/tauri/pull/3916)) on 2022-04-19 - Kill the `beforeDevCommand` process recursively on Unix. - [e251e1b0](https://www.github.com/tauri-apps/tauri/commit/e251e1b0991d26ab10aea33cfb228f3e7f0f85b5) fix(cli): kill before dev command recursively on Unix, closes [#2794](https://www.github.com/tauri-apps/tauri/pull/2794) ([#3848](https://www.github.com/tauri-apps/tauri/pull/3848)) on 2022-04-03 ## \[1.0.0-rc.8] - Allows the `tauri.conf.json` file to be git ignored on the path lookup function. - [cc7c2d77](https://www.github.com/tauri-apps/tauri/commit/cc7c2d77da2e4a39ec2a97b080d41a719e6d0161) feat(cli): allow conf path to be gitignored, closes [#3636](https://www.github.com/tauri-apps/tauri/pull/3636) ([#3683](https://www.github.com/tauri-apps/tauri/pull/3683)) on 2022-03-13 - Remove `minimumSystemVersion: null` from the application template configuration. - [c81534eb](https://www.github.com/tauri-apps/tauri/commit/c81534ebd873c358e0346c7949aeb171803149a5) feat(cli): use default macOS minimum system version when it is empty ([#3658](https://www.github.com/tauri-apps/tauri/pull/3658)) on 2022-03-13 - Improve readability of the `info` subcommand output. - [49d2f13f](https://www.github.com/tauri-apps/tauri/commit/49d2f13fc07d763d5de9bf4b19d00c901776c11d) feat(cli): colorful cli ([#3635](https://www.github.com/tauri-apps/tauri/pull/3635)) on 2022-03-08 - Fixes DMG bundling on macOS 12.3. - [348a1ab5](https://www.github.com/tauri-apps/tauri/commit/348a1ab59d2697478a594016016f1fccbf1ac054) fix(bundler): DMG bundling on macOS 12.3 cannot use bless, closes [#3719](https://www.github.com/tauri-apps/tauri/pull/3719) ([#3721](https://www.github.com/tauri-apps/tauri/pull/3721)) on 2022-03-18 - Fixes resources bundling on Windows when the path is on the root of the Tauri folder. - [4c84559e](https://www.github.com/tauri-apps/tauri/commit/4c84559e1f3019e7aa2666b10a1a0bd97bb09d24) fix(cli): root resource bundling on Windows, closes [#3539](https://www.github.com/tauri-apps/tauri/pull/3539) ([#3685](https://www.github.com/tauri-apps/tauri/pull/3685)) on 2022-03-13 ## \[1.0.0-rc.6] - Added `tsp` config option under `tauri > bundle > windows`, which enables Time-Stamp Protocol (RFC 3161) for the timestamping server under code signing on Windows if set to `true`. - [bdd5f7c2](https://www.github.com/tauri-apps/tauri/commit/bdd5f7c2f03af4af8b60a9527e55bb18525d989b) fix: add support for Time-Stamping Protocol for Windows codesigning (fix [#3563](https://www.github.com/tauri-apps/tauri/pull/3563)) ([#3570](https://www.github.com/tauri-apps/tauri/pull/3570)) on 2022-03-07 - Added `i686-pc-windows-msvc` to the prebuilt targets. - [fb6744da](https://www.github.com/tauri-apps/tauri/commit/fb6744daa45165c7e00e5c01f7df0880d69ca509) feat(cli.js): add 32bit cli for windows ([#3540](https://www.github.com/tauri-apps/tauri/pull/3540)) on 2022-02-24 - Change the `plugin init` templates to use the new `tauri::plugin::Builder` syntax. - [f7acb061](https://www.github.com/tauri-apps/tauri/commit/f7acb061e4d1ecdbfe182793587632d7ba6d8eff) feat(cli): use plugin::Builder syntax on the plugin template ([#3606](https://www.github.com/tauri-apps/tauri/pull/3606)) on 2022-03-03 ## \[1.0.0-rc.5] - Improve "waiting for your dev server to start" message. - [5999379f](https://www.github.com/tauri-apps/tauri/commit/5999379fb06052a115f04f99274ab46d1eefd659) chore(cli): improve "waiting for dev server" message, closes [#3491](https://www.github.com/tauri-apps/tauri/pull/3491) ([#3504](https://www.github.com/tauri-apps/tauri/pull/3504)) on 2022-02-18 - Do not panic if the updater private key password is wrong. - [17f17a80](https://www.github.com/tauri-apps/tauri/commit/17f17a80f818bcc20c387583a6ff00a8e07ec533) fix(cli): do not panic if private key password is wrong, closes [#3449](https://www.github.com/tauri-apps/tauri/pull/3449) ([#3495](https://www.github.com/tauri-apps/tauri/pull/3495)) on 2022-02-17 - Check the current folder before checking the directories on the app and tauri dir path lookup function. - [a06de376](https://www.github.com/tauri-apps/tauri/commit/a06de3760184caa71acfe7a2fe2189a033b565f5) fix(cli): path lookup should not check subfolder before the current one ([#3465](https://www.github.com/tauri-apps/tauri/pull/3465)) on 2022-02-15 - Fixes the signature of the `signer sign` command to not have duplicated short flags. - [a9755514](https://www.github.com/tauri-apps/tauri/commit/a975551461f3698db3f3b6afa5101189aaeeada9) fix(cli): duplicated short flag for `signer sign`, closes [#3483](https://www.github.com/tauri-apps/tauri/pull/3483) ([#3492](https://www.github.com/tauri-apps/tauri/pull/3492)) on 2022-02-17 ## \[1.0.0-rc.4] - Change the `run` function to take a callback and run asynchronously instead of blocking the event loop. - [cd9a20b9](https://www.github.com/tauri-apps/tauri/commit/cd9a20b9ab013759b4bdb742f358988022450795) refactor(cli.js): run on separate thread ([#3436](https://www.github.com/tauri-apps/tauri/pull/3436)) on 2022-02-13 - Improve error message when the dev runner command fails. - [759d1afb](https://www.github.com/tauri-apps/tauri/commit/759d1afb86f3657f6071a2ae39c9be21e20ed22c) feat(cli): improve error message when dev runner command fails ([#3447](https://www.github.com/tauri-apps/tauri/pull/3447)) on 2022-02-13 - Show full error message from `cli.rs` instead of just the outermost underlying error message. - [63826010](https://www.github.com/tauri-apps/tauri/commit/63826010d1f38544f36afd3aac67c45d4608d15b) feat(cli.js): show full error message ([#3442](https://www.github.com/tauri-apps/tauri/pull/3442)) on 2022-02-13 - Increase `tauri.conf.json` directory lookup depth to `3` and allow changing it with the `TAURI_PATH_DEPTH` environment variable. - [c6031c70](https://www.github.com/tauri-apps/tauri/commit/c6031c7070c6bb7539bbfdfe42cb73012829c910) feat(cli): increase lookup depth, add env var option ([#3451](https://www.github.com/tauri-apps/tauri/pull/3451)) on 2022-02-13 - Added `tauri-build`, `tao` and `wry` version to the `info` command output. - [16f1173f](https://www.github.com/tauri-apps/tauri/commit/16f1173f456b1db543d0160df2c9828708bfc68a) feat(cli): add tao and wry version to the `info` output ([#3443](https://www.github.com/tauri-apps/tauri/pull/3443)) on 2022-02-13 ## \[1.0.0-rc.3] - Change default value for the `freezePrototype` configuration to `false`. - Bumped due to a bump in cli.rs. - [3a4c0160](https://www.github.com/tauri-apps/tauri/commit/3a4c01606184be762adee055ddac803de0d28527) fix(core): change default `freezePrototype` to false, closes [#3416](https://www.github.com/tauri-apps/tauri/pull/3416) [#3406](https://www.github.com/tauri-apps/tauri/pull/3406) ([#3423](https://www.github.com/tauri-apps/tauri/pull/3423)) on 2022-02-12 ## \[1.0.0-rc.2] - Fixes Tauri path resolution on projects without Git or a `.gitignore` file. - [d8acbe11](https://www.github.com/tauri-apps/tauri/commit/d8acbe11492bd990e6983c7e63e0f1a8f1ea5c7c) fix(cli.rs): app path resolution on projects without git, closes [#3409](https://www.github.com/tauri-apps/tauri/pull/3409) ([#3410](https://www.github.com/tauri-apps/tauri/pull/3410)) on 2022-02-11 ## \[1.0.0-rc.1] - Fix `init` command prompting for values even if the argument has been provided on the command line. - [def76840](https://www.github.com/tauri-apps/tauri/commit/def76840257a1447723ecda13c807cf0c881f083) fix(cli.rs): do not prompt for `init` values if arg set ([#3400](https://www.github.com/tauri-apps/tauri/pull/3400)) on 2022-02-11 - [41052dee](https://www.github.com/tauri-apps/tauri/commit/41052deeda2a00ee2b8ec2041c9c87c11de82ab2) fix(covector): add cli.js to change files on 2022-02-11 - Fixes CLI freezing when running `light.exe` on Windows without the `--verbose` flag. - [8beab636](https://www.github.com/tauri-apps/tauri/commit/8beab6363491e2a8757cc9fc0fa1eccc98ece916) fix(cli): build freezing on Windows, closes [#3399](https://www.github.com/tauri-apps/tauri/pull/3399) ([#3402](https://www.github.com/tauri-apps/tauri/pull/3402)) on 2022-02-11 - Respect `.gitignore` configuration when looking for the folder with the `tauri.conf.json` file. - [9c6c5a8c](https://www.github.com/tauri-apps/tauri/commit/9c6c5a8c52c6460d0b0a1a55300e1828262994ba) perf(cli.rs): improve performance of tauri dir lookup reading .gitignore ([#3405](https://www.github.com/tauri-apps/tauri/pull/3405)) on 2022-02-11 - [41052dee](https://www.github.com/tauri-apps/tauri/commit/41052deeda2a00ee2b8ec2041c9c87c11de82ab2) fix(covector): add cli.js to change files on 2022-02-11 ## \[1.0.0-rc.0] - Do not force Tauri application code on `src-tauri` folder and use a glob pattern to look for a subfolder with a `tauri.conf.json` file. - [a8cff6b3](https://www.github.com/tauri-apps/tauri/commit/a8cff6b3bc3288a53d7cdc5b3cb95d371309d2d6) feat(cli): do not enforce `src-tauri` folder structure, closes [#2643](https://www.github.com/tauri-apps/tauri/pull/2643) ([#2654](https://www.github.com/tauri-apps/tauri/pull/2654)) on 2021-09-27 - Added CommonJS output to the `dist` folder. - [205b0dc8](https://www.github.com/tauri-apps/tauri/commit/205b0dc8f30bf70902979a2c0a08c8bc8c8e5360) feat(cli.js): add CommonJS dist files ([#2646](https://www.github.com/tauri-apps/tauri/pull/2646)) on 2021-09-23 - Fixes `.ico` icon generation. - [11db96e4](https://www.github.com/tauri-apps/tauri/commit/11db96e440e6cadc1c70992d07bfea3c448208b1) fix(cli.js): `.ico` icon generation, closes [#2692](https://www.github.com/tauri-apps/tauri/pull/2692) ([#2694](https://www.github.com/tauri-apps/tauri/pull/2694)) on 2021-10-02 - Automatically unplug `@tauri-apps/cli` in yarn 2+ installations to fix the download of the rust-cli. - [1e336b68](https://www.github.com/tauri-apps/tauri/commit/1e336b6872c3b78caf7c2c6e71e03016c6abdacf) fix(cli.js): Fix package installation on yarn 2+ ([#3012](https://www.github.com/tauri-apps/tauri/pull/3012)) on 2021-12-09 - Read `package.json` and check for a `tauri` object containing the `appPath` string, which points to the tauri crate path. - [fb2b9a52](https://www.github.com/tauri-apps/tauri/commit/fb2b9a52f594830c0a68ea40ea429a09892f7ba7) feat(cli.js): allow configuring tauri app path on package.json [#2752](https://www.github.com/tauri-apps/tauri/pull/2752) ([#3035](https://www.github.com/tauri-apps/tauri/pull/3035)) on 2021-12-09 - Removed the `icon` command, now exposed as a separate package, see https://github.com/tauri-apps/tauricon. - [58030172](https://www.github.com/tauri-apps/tauri/commit/58030172eddb2403a84b56a21b5bdcebca42c265) feat(tauricon): remove from cli ([#3293](https://www.github.com/tauri-apps/tauri/pull/3293)) on 2022-02-07 ================================================ FILE: packages/cli/Cargo.toml ================================================ [package] edition = "2021" name = "tauri-cli-node" version = "0.0.0" [lib] crate-type = ["cdylib"] [dependencies] napi = "3" napi-derive = "3" tauri-cli = { path = "../../crates/tauri-cli", default-features = false } log = "0.4.21" [build-dependencies] napi-build = "2.2" [features] default = ["tauri-cli/default"] native-tls = ["tauri-cli/native-tls"] native-tls-vendored = ["tauri-cli/native-tls-vendored"] ================================================ FILE: packages/cli/LICENSE_APACHE-2.0 ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS ================================================ FILE: packages/cli/LICENSE_MIT ================================================ MIT License Copyright (c) 2017 - Present Tauri Apps Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: packages/cli/README.md ================================================ # @tauri-apps/cli [![status](https://img.shields.io/badge/status-stable-blue.svg)](https://github.com/tauri-apps/tauri/tree/dev) [![License](https://img.shields.io/badge/License-MIT%20or%20Apache%202-green.svg)](https://opencollective.com/tauri) [![test cli](https://img.shields.io/github/actions/workflow/status/tauri-apps/tauri/test-cli-js.yml?label=test%20cli&logo=github)](https://github.com/tauri-apps/tauri/actions/workflows/test-cli-js.yml) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Ftauri-apps%2Ftauri.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Ftauri-apps%2Ftauri?ref=badge_shield) [![Chat Server](https://img.shields.io/badge/chat-discord-7289da.svg)](https://discord.gg/SpmNs4S) [![website](https://img.shields.io/badge/website-tauri.app-purple.svg)](https://tauri.app) [![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) | Component | Version | | --------------- | ----------------------------------------------------- | | @tauri-apps/cli | ![](https://img.shields.io/npm/v/@tauri-apps/cli.svg) | ## About Tauri Tauri is a polyglot and generic system that is very composable and allows engineers to make a wide variety of applications. It is used for building applications for Desktop Computers using a combination of Rust tools and HTML rendered in a Webview. Apps built with Tauri can ship with any number of pieces of an optional JS API / Rust API so that webviews can control the system via message passing. In fact, developers can extend the default API with their own functionality and bridge the Webview and Rust-based backend easily. Tauri apps can have custom menus and have tray-type interfaces. They can be updated, and are managed by the user's operating system as expected. They are very small, because they use the system's webview. They do not ship a runtime, since the final binary is compiled from rust. This makes the reversing of Tauri apps not a trivial task. ## This module Written in Typescript and packaged such that it can be used with `npm`, `pnpm`, `yarn`, and `bun`, this library provides a node.js runner for common tasks when using Tauri, like `pnpm tauri dev`. For the most part it is a wrapper around [tauri-cli](https://github.com/tauri-apps/tauri/blob/dev/crates/tauri-cli). 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. ## Installation The preferred method is to install this module locally as a development dependency: ``` $ pnpm add -D @tauri-apps/cli $ yarn add -D @tauri-apps/cli $ npm add -D @tauri-apps/cli ``` ## Semver **tauri** is following [Semantic Versioning 2.0](https://semver.org/). ## Licenses Code: (c) 2019 - 2021 - The Tauri Programme within The Commons Conservancy. MIT or MIT/Apache 2.0 where applicable. Logo: CC-BY-NC-ND - Original Tauri Logo Designs by [Daniel Thompson-Yvetot](https://github.com/nothingismagick) and [Guillaume Chau](https://github.com/akryum) ================================================ FILE: packages/cli/__tests__/fixtures/empty/.gitignore ================================================ src-tauri ================================================ FILE: packages/cli/__tests__/fixtures/empty/dist/index.html ================================================
================================================ FILE: packages/cli/__tests__/fixtures/empty/package.json ================================================ { "scripts": { "build": "" } } ================================================ FILE: packages/cli/__tests__/template.spec.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT import { resolve } from 'node:path' import { spawnSync } from 'node:child_process' import { existsSync, readFileSync, writeFileSync, rmSync, renameSync } from 'node:fs' import { beforeAll, describe, it } from 'vitest' // Build CLI before tests, for local usage only. // CI builds the CLI on different platforms and architectures if (!process.env.CI) { beforeAll(() => { const cliDir = resolve(__dirname, '..') exec('pnpm', ['build:debug'], { cwd: cliDir }) }) } describe('[CLI] @tauri-apps/cli template', () => { it('init a project and builds it', { timeout: 15 * 60 * 1000 }, async () => { const cwd = process.cwd() const fixturePath = resolve(__dirname, './fixtures/empty') const tauriFixturePath = resolve(fixturePath, 'src-tauri') const outPath = resolve(tauriFixturePath, 'target') const cacheOutPath = resolve(fixturePath, 'target') process.chdir(fixturePath) const outExists = existsSync(outPath) if (outExists) { if (existsSync(cacheOutPath)) { rmSync(cacheOutPath, { recursive: true, force: true }) } renameSync(outPath, cacheOutPath) } const cli = await import('../main.js') await cli.run([ 'init', '-vvv', '--directory', process.cwd(), '--force', '--tauri-path', resolve(__dirname, '../../..'), '--before-build-command', '', '--before-dev-command', '', '--ci' ]) if (outExists) { renameSync(cacheOutPath, outPath) } process.chdir(tauriFixturePath) const manifestPath = resolve(tauriFixturePath, 'Cargo.toml') const manifestFile = readFileSync(manifestPath).toString() writeFileSync(manifestPath, `workspace = { }\n${manifestFile}`) const configPath = resolve(tauriFixturePath, 'tauri.conf.json') const config = readFileSync(configPath).toString() writeFileSync(configPath, config.replace('com.tauri.dev', 'com.tauri.test')) await cli.run(['build', '-vvv']) process.chdir(cwd) }) }) function exec( bin: string, args?: string[], opts?: { cwd?: string } ) { process.platform === 'win32' ? spawnSync('cmd', ['/c', bin, ...(args ?? [])], { cwd: opts?.cwd }) : spawnSync(bin, args, { cwd: opts?.cwd }) } ================================================ FILE: packages/cli/append-headers.js ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT const HEADERS = `// Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT` const fs = require('fs') for (const file of ['index.js', 'index.d.ts']) { const content = fs.readFileSync(file, 'utf8') const newContent = `${HEADERS}\n\n${content}` fs.writeFileSync(file, newContent, 'utf8') } ================================================ FILE: packages/cli/build.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT fn main() { ::napi_build::setup(); } ================================================ FILE: packages/cli/index.d.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT /* auto-generated by NAPI-RS */ /* eslint-disable */ export declare function logError(error: string): void export declare function run(args: Array, binName: string | undefined | null, callback: ((err: Error | null, arg: boolean) => any)): void ================================================ FILE: packages/cli/index.js ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT // prettier-ignore /* eslint-disable */ // @ts-nocheck /* auto-generated by NAPI-RS */ const { readFileSync } = require('node:fs') let nativeBinding = null const loadErrors = [] const isMusl = () => { let musl = false if (process.platform === 'linux') { musl = isMuslFromFilesystem() if (musl === null) { musl = isMuslFromReport() } if (musl === null) { musl = isMuslFromChildProcess() } } return musl } const isFileMusl = (f) => f.includes('libc.musl-') || f.includes('ld-musl-') const isMuslFromFilesystem = () => { try { return readFileSync('/usr/bin/ldd', 'utf-8').includes('musl') } catch { return null } } const isMuslFromReport = () => { let report = null if (typeof process.report?.getReport === 'function') { process.report.excludeNetwork = true report = process.report.getReport() } if (!report) { return null } if (report.header && report.header.glibcVersionRuntime) { return false } if (Array.isArray(report.sharedObjects)) { if (report.sharedObjects.some(isFileMusl)) { return true } } return false } const isMuslFromChildProcess = () => { try { return require('child_process').execSync('ldd --version', { encoding: 'utf8' }).includes('musl') } catch (e) { // If we reach this case, we don't know if the system is musl or not, so is better to just fallback to false return false } } function requireNative() { if (process.env.NAPI_RS_NATIVE_LIBRARY_PATH) { try { return require(process.env.NAPI_RS_NATIVE_LIBRARY_PATH); } catch (err) { loadErrors.push(err) } } else if (process.platform === 'android') { if (process.arch === 'arm64') { try { return require('./cli.android-arm64.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-android-arm64') const bindingPackageVersion = require('@tauri-apps/cli-android-arm64/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } else if (process.arch === 'arm') { try { return require('./cli.android-arm-eabi.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-android-arm-eabi') const bindingPackageVersion = require('@tauri-apps/cli-android-arm-eabi/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } else { loadErrors.push(new Error(`Unsupported architecture on Android ${process.arch}`)) } } else if (process.platform === 'win32') { if (process.arch === 'x64') { if (process.config?.variables?.shlib_suffix === 'dll.a' || process.config?.variables?.node_target_type === 'shared_library') { try { return require('./cli.win32-x64-gnu.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-win32-x64-gnu') const bindingPackageVersion = require('@tauri-apps/cli-win32-x64-gnu/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } else { try { return require('./cli.win32-x64-msvc.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-win32-x64-msvc') const bindingPackageVersion = require('@tauri-apps/cli-win32-x64-msvc/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } } else if (process.arch === 'ia32') { try { return require('./cli.win32-ia32-msvc.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-win32-ia32-msvc') const bindingPackageVersion = require('@tauri-apps/cli-win32-ia32-msvc/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } else if (process.arch === 'arm64') { try { return require('./cli.win32-arm64-msvc.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-win32-arm64-msvc') const bindingPackageVersion = require('@tauri-apps/cli-win32-arm64-msvc/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } else { loadErrors.push(new Error(`Unsupported architecture on Windows: ${process.arch}`)) } } else if (process.platform === 'darwin') { try { return require('./cli.darwin-universal.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-darwin-universal') const bindingPackageVersion = require('@tauri-apps/cli-darwin-universal/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } if (process.arch === 'x64') { try { return require('./cli.darwin-x64.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-darwin-x64') const bindingPackageVersion = require('@tauri-apps/cli-darwin-x64/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } else if (process.arch === 'arm64') { try { return require('./cli.darwin-arm64.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-darwin-arm64') const bindingPackageVersion = require('@tauri-apps/cli-darwin-arm64/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } else { loadErrors.push(new Error(`Unsupported architecture on macOS: ${process.arch}`)) } } else if (process.platform === 'freebsd') { if (process.arch === 'x64') { try { return require('./cli.freebsd-x64.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-freebsd-x64') const bindingPackageVersion = require('@tauri-apps/cli-freebsd-x64/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } else if (process.arch === 'arm64') { try { return require('./cli.freebsd-arm64.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-freebsd-arm64') const bindingPackageVersion = require('@tauri-apps/cli-freebsd-arm64/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } else { loadErrors.push(new Error(`Unsupported architecture on FreeBSD: ${process.arch}`)) } } else if (process.platform === 'linux') { if (process.arch === 'x64') { if (isMusl()) { try { return require('./cli.linux-x64-musl.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-linux-x64-musl') const bindingPackageVersion = require('@tauri-apps/cli-linux-x64-musl/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } else { try { return require('./cli.linux-x64-gnu.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-linux-x64-gnu') const bindingPackageVersion = require('@tauri-apps/cli-linux-x64-gnu/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } } else if (process.arch === 'arm64') { if (isMusl()) { try { return require('./cli.linux-arm64-musl.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-linux-arm64-musl') const bindingPackageVersion = require('@tauri-apps/cli-linux-arm64-musl/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } else { try { return require('./cli.linux-arm64-gnu.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-linux-arm64-gnu') const bindingPackageVersion = require('@tauri-apps/cli-linux-arm64-gnu/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } } else if (process.arch === 'arm') { if (isMusl()) { try { return require('./cli.linux-arm-musleabihf.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-linux-arm-musleabihf') const bindingPackageVersion = require('@tauri-apps/cli-linux-arm-musleabihf/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } else { try { return require('./cli.linux-arm-gnueabihf.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-linux-arm-gnueabihf') const bindingPackageVersion = require('@tauri-apps/cli-linux-arm-gnueabihf/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } } else if (process.arch === 'loong64') { if (isMusl()) { try { return require('./cli.linux-loong64-musl.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-linux-loong64-musl') const bindingPackageVersion = require('@tauri-apps/cli-linux-loong64-musl/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } else { try { return require('./cli.linux-loong64-gnu.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-linux-loong64-gnu') const bindingPackageVersion = require('@tauri-apps/cli-linux-loong64-gnu/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } } else if (process.arch === 'riscv64') { if (isMusl()) { try { return require('./cli.linux-riscv64-musl.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-linux-riscv64-musl') const bindingPackageVersion = require('@tauri-apps/cli-linux-riscv64-musl/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } else { try { return require('./cli.linux-riscv64-gnu.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-linux-riscv64-gnu') const bindingPackageVersion = require('@tauri-apps/cli-linux-riscv64-gnu/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } } else if (process.arch === 'ppc64') { try { return require('./cli.linux-ppc64-gnu.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-linux-ppc64-gnu') const bindingPackageVersion = require('@tauri-apps/cli-linux-ppc64-gnu/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } else if (process.arch === 's390x') { try { return require('./cli.linux-s390x-gnu.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-linux-s390x-gnu') const bindingPackageVersion = require('@tauri-apps/cli-linux-s390x-gnu/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } else { loadErrors.push(new Error(`Unsupported architecture on Linux: ${process.arch}`)) } } else if (process.platform === 'openharmony') { if (process.arch === 'arm64') { try { return require('./cli.openharmony-arm64.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-openharmony-arm64') const bindingPackageVersion = require('@tauri-apps/cli-openharmony-arm64/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } else if (process.arch === 'x64') { try { return require('./cli.openharmony-x64.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-openharmony-x64') const bindingPackageVersion = require('@tauri-apps/cli-openharmony-x64/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } else if (process.arch === 'arm') { try { return require('./cli.openharmony-arm.node') } catch (e) { loadErrors.push(e) } try { const binding = require('@tauri-apps/cli-openharmony-arm') const bindingPackageVersion = require('@tauri-apps/cli-openharmony-arm/package.json').version if (bindingPackageVersion !== '2.10.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') { throw new Error(`Native binding package version mismatch, expected 2.10.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`) } return binding } catch (e) { loadErrors.push(e) } } else { loadErrors.push(new Error(`Unsupported architecture on OpenHarmony: ${process.arch}`)) } } else { loadErrors.push(new Error(`Unsupported OS: ${process.platform}, architecture: ${process.arch}`)) } } nativeBinding = requireNative() if (!nativeBinding || process.env.NAPI_RS_FORCE_WASI) { let wasiBinding = null let wasiBindingError = null try { wasiBinding = require('./cli.wasi.cjs') nativeBinding = wasiBinding } catch (err) { if (process.env.NAPI_RS_FORCE_WASI) { wasiBindingError = err } } if (!nativeBinding) { try { wasiBinding = require('@tauri-apps/cli-wasm32-wasi') nativeBinding = wasiBinding } catch (err) { if (process.env.NAPI_RS_FORCE_WASI) { wasiBindingError.cause = err loadErrors.push(err) } } } if (process.env.NAPI_RS_FORCE_WASI === 'error' && !wasiBinding) { const error = new Error('WASI binding not found and NAPI_RS_FORCE_WASI is set to error') error.cause = wasiBindingError throw error } } if (!nativeBinding) { if (loadErrors.length > 0) { throw new Error( `Cannot find native binding. ` + `npm has a bug related to optional dependencies (https://github.com/npm/cli/issues/4828). ` + 'Please try `npm i` again after removing both package-lock.json and node_modules directory.', { cause: loadErrors.reduce((err, cur) => { cur.cause = err return cur }), }, ) } throw new Error(`Failed to load native binding`) } module.exports = nativeBinding module.exports.logError = nativeBinding.logError module.exports.run = nativeBinding.run ================================================ FILE: packages/cli/main.d.ts ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT /* tslint:disable */ /* eslint-disable */ export function run( args: Array, binName?: string | undefined | null ): Promise ================================================ FILE: packages/cli/main.js ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT const { run, logError } = require('./index') module.exports.run = (args, binName) => { return new Promise((resolve, reject) => { run(args, binName, (error, res) => { if (error) { reject(error) } else { resolve(res) } }) }) } module.exports.logError = logError ================================================ FILE: packages/cli/npm/darwin-arm64/README.md ================================================ # `@tauri-apps/cli-darwin-arm64` This is the **aarch64-apple-darwin** binary for `@tauri-apps/cli` ================================================ FILE: packages/cli/npm/darwin-arm64/package.json ================================================ { "name": "@tauri-apps/cli-darwin-arm64", "version": "0.0.0", "cpu": [ "arm64" ], "main": "cli.darwin-arm64.node", "files": [ "cli.darwin-arm64.node" ], "description": "Command line interface for building Tauri apps", "homepage": "https://github.com/tauri-apps/tauri#readme", "contributors": [ "Tauri Programme within The Commons Conservancy" ], "license": "Apache-2.0 OR MIT", "engines": { "node": ">= 10" }, "repository": { "type": "git", "url": "git+https://github.com/tauri-apps/tauri.git" }, "bugs": { "url": "https://github.com/tauri-apps/tauri/issues" }, "publishConfig": { "access": "public" }, "os": [ "darwin" ] } ================================================ FILE: packages/cli/npm/darwin-x64/README.md ================================================ # `@tauri-apps/cli-darwin-x64` This is the **x86_64-apple-darwin** binary for `@tauri-apps/cli` ================================================ FILE: packages/cli/npm/darwin-x64/package.json ================================================ { "name": "@tauri-apps/cli-darwin-x64", "version": "0.0.0", "cpu": [ "x64" ], "main": "cli.darwin-x64.node", "files": [ "cli.darwin-x64.node" ], "description": "Command line interface for building Tauri apps", "homepage": "https://github.com/tauri-apps/tauri#readme", "contributors": [ "Tauri Programme within The Commons Conservancy" ], "license": "Apache-2.0 OR MIT", "engines": { "node": ">= 10" }, "repository": { "type": "git", "url": "git+https://github.com/tauri-apps/tauri.git" }, "bugs": { "url": "https://github.com/tauri-apps/tauri/issues" }, "publishConfig": { "access": "public" }, "os": [ "darwin" ] } ================================================ FILE: packages/cli/npm/linux-arm-gnueabihf/README.md ================================================ # `@tauri-apps/cli-linux-arm-gnueabihf` This is the **armv7-unknown-linux-gnueabihf** binary for `@tauri-apps/cli` ================================================ FILE: packages/cli/npm/linux-arm-gnueabihf/package.json ================================================ { "name": "@tauri-apps/cli-linux-arm-gnueabihf", "version": "0.0.0", "cpu": [ "arm" ], "main": "cli.linux-arm-gnueabihf.node", "files": [ "cli.linux-arm-gnueabihf.node" ], "description": "Command line interface for building Tauri apps", "homepage": "https://github.com/tauri-apps/tauri#readme", "contributors": [ "Tauri Programme within The Commons Conservancy" ], "license": "Apache-2.0 OR MIT", "engines": { "node": ">= 10" }, "repository": { "type": "git", "url": "git+https://github.com/tauri-apps/tauri.git" }, "bugs": { "url": "https://github.com/tauri-apps/tauri/issues" }, "publishConfig": { "access": "public" }, "os": [ "linux" ] } ================================================ FILE: packages/cli/npm/linux-arm64-gnu/README.md ================================================ # `@tauri-apps/cli-linux-arm64-gnu` This is the **aarch64-unknown-linux-gnu** binary for `@tauri-apps/cli` ================================================ FILE: packages/cli/npm/linux-arm64-gnu/package.json ================================================ { "name": "@tauri-apps/cli-linux-arm64-gnu", "version": "0.0.0", "cpu": [ "arm64" ], "main": "cli.linux-arm64-gnu.node", "files": [ "cli.linux-arm64-gnu.node" ], "description": "Command line interface for building Tauri apps", "homepage": "https://github.com/tauri-apps/tauri#readme", "contributors": [ "Tauri Programme within The Commons Conservancy" ], "license": "Apache-2.0 OR MIT", "engines": { "node": ">= 10" }, "repository": { "type": "git", "url": "git+https://github.com/tauri-apps/tauri.git" }, "bugs": { "url": "https://github.com/tauri-apps/tauri/issues" }, "publishConfig": { "access": "public" }, "os": [ "linux" ], "libc": [ "glibc" ] } ================================================ FILE: packages/cli/npm/linux-arm64-musl/README.md ================================================ # `@tauri-apps/cli-linux-arm64-musl` This is the **aarch64-unknown-linux-musl** binary for `@tauri-apps/cli` ================================================ FILE: packages/cli/npm/linux-arm64-musl/package.json ================================================ { "name": "@tauri-apps/cli-linux-arm64-musl", "version": "0.0.0", "cpu": [ "arm64" ], "main": "cli.linux-arm64-musl.node", "files": [ "cli.linux-arm64-musl.node" ], "description": "Command line interface for building Tauri apps", "homepage": "https://github.com/tauri-apps/tauri#readme", "contributors": [ "Tauri Programme within The Commons Conservancy" ], "license": "Apache-2.0 OR MIT", "engines": { "node": ">= 10" }, "repository": { "type": "git", "url": "git+https://github.com/tauri-apps/tauri.git" }, "bugs": { "url": "https://github.com/tauri-apps/tauri/issues" }, "publishConfig": { "access": "public" }, "os": [ "linux" ], "libc": [ "musl" ] } ================================================ FILE: packages/cli/npm/linux-riscv64-gnu/README.md ================================================ # `@tauri-apps/cli-linux-riscv64-gnu` This is the **riscv64gc-unknown-linux-gnu** binary for `@tauri-apps/cli` ================================================ FILE: packages/cli/npm/linux-riscv64-gnu/package.json ================================================ { "name": "@tauri-apps/cli-linux-riscv64-gnu", "version": "0.0.0", "cpu": [ "riscv64" ], "main": "cli.linux-riscv64-gnu.node", "files": [ "cli.linux-riscv64-gnu.node" ], "description": "Command line interface for building Tauri apps", "homepage": "https://github.com/tauri-apps/tauri#readme", "contributors": [ "Tauri Programme within The Commons Conservancy" ], "license": "Apache-2.0 OR MIT", "engines": { "node": ">= 10" }, "repository": { "type": "git", "url": "git+https://github.com/tauri-apps/tauri.git" }, "bugs": { "url": "https://github.com/tauri-apps/tauri/issues" }, "publishConfig": { "access": "public" }, "os": [ "linux" ], "libc": [ "glibc" ] } ================================================ FILE: packages/cli/npm/linux-x64-gnu/README.md ================================================ # `@tauri-apps/cli-linux-x64-gnu` This is the **x86_64-unknown-linux-gnu** binary for `@tauri-apps/cli` ================================================ FILE: packages/cli/npm/linux-x64-gnu/package.json ================================================ { "name": "@tauri-apps/cli-linux-x64-gnu", "version": "0.0.0", "cpu": [ "x64" ], "main": "cli.linux-x64-gnu.node", "files": [ "cli.linux-x64-gnu.node" ], "description": "Command line interface for building Tauri apps", "homepage": "https://github.com/tauri-apps/tauri#readme", "contributors": [ "Tauri Programme within The Commons Conservancy" ], "license": "Apache-2.0 OR MIT", "engines": { "node": ">= 10" }, "repository": { "type": "git", "url": "git+https://github.com/tauri-apps/tauri.git" }, "bugs": { "url": "https://github.com/tauri-apps/tauri/issues" }, "publishConfig": { "access": "public" }, "os": [ "linux" ], "libc": [ "glibc" ] } ================================================ FILE: packages/cli/npm/linux-x64-musl/README.md ================================================ # `@tauri-apps/cli-linux-x64-musl` This is the **x86_64-unknown-linux-musl** binary for `@tauri-apps/cli` ================================================ FILE: packages/cli/npm/linux-x64-musl/package.json ================================================ { "name": "@tauri-apps/cli-linux-x64-musl", "version": "0.0.0", "cpu": [ "x64" ], "main": "cli.linux-x64-musl.node", "files": [ "cli.linux-x64-musl.node" ], "description": "Command line interface for building Tauri apps", "homepage": "https://github.com/tauri-apps/tauri#readme", "contributors": [ "Tauri Programme within The Commons Conservancy" ], "license": "Apache-2.0 OR MIT", "engines": { "node": ">= 10" }, "repository": { "type": "git", "url": "git+https://github.com/tauri-apps/tauri.git" }, "bugs": { "url": "https://github.com/tauri-apps/tauri/issues" }, "publishConfig": { "access": "public" }, "os": [ "linux" ], "libc": [ "musl" ] } ================================================ FILE: packages/cli/npm/win32-arm64-msvc/README.md ================================================ # `@tauri-apps/cli-win32-arm64-msvc` This is the **aarch64-pc-windows-msvc** binary for `@tauri-apps/cli` ================================================ FILE: packages/cli/npm/win32-arm64-msvc/package.json ================================================ { "name": "@tauri-apps/cli-win32-arm64-msvc", "version": "0.0.0", "cpu": [ "arm64" ], "main": "cli.win32-arm64-msvc.node", "files": [ "cli.win32-arm64-msvc.node" ], "description": "Command line interface for building Tauri apps", "homepage": "https://github.com/tauri-apps/tauri#readme", "contributors": [ "Tauri Programme within The Commons Conservancy" ], "license": "Apache-2.0 OR MIT", "engines": { "node": ">= 10" }, "repository": { "type": "git", "url": "git+https://github.com/tauri-apps/tauri.git" }, "bugs": { "url": "https://github.com/tauri-apps/tauri/issues" }, "publishConfig": { "access": "public" }, "os": [ "win32" ] } ================================================ FILE: packages/cli/npm/win32-ia32-msvc/README.md ================================================ # `@tauri-apps/cli-win32-ia32-msvc` This is the **i686-pc-windows-msvc** binary for `@tauri-apps/cli` ================================================ FILE: packages/cli/npm/win32-ia32-msvc/package.json ================================================ { "name": "@tauri-apps/cli-win32-ia32-msvc", "version": "0.0.0", "cpu": [ "ia32" ], "main": "cli.win32-ia32-msvc.node", "files": [ "cli.win32-ia32-msvc.node" ], "description": "Command line interface for building Tauri apps", "homepage": "https://github.com/tauri-apps/tauri#readme", "contributors": [ "Tauri Programme within The Commons Conservancy" ], "license": "Apache-2.0 OR MIT", "engines": { "node": ">= 10" }, "repository": { "type": "git", "url": "git+https://github.com/tauri-apps/tauri.git" }, "bugs": { "url": "https://github.com/tauri-apps/tauri/issues" }, "publishConfig": { "access": "public" }, "os": [ "win32" ] } ================================================ FILE: packages/cli/npm/win32-x64-msvc/README.md ================================================ # `@tauri-apps/cli-win32-x64-msvc` This is the **x86_64-pc-windows-msvc** binary for `@tauri-apps/cli` ================================================ FILE: packages/cli/npm/win32-x64-msvc/package.json ================================================ { "name": "@tauri-apps/cli-win32-x64-msvc", "version": "0.0.0", "cpu": [ "x64" ], "main": "cli.win32-x64-msvc.node", "files": [ "cli.win32-x64-msvc.node" ], "description": "Command line interface for building Tauri apps", "homepage": "https://github.com/tauri-apps/tauri#readme", "contributors": [ "Tauri Programme within The Commons Conservancy" ], "license": "Apache-2.0 OR MIT", "engines": { "node": ">= 10" }, "repository": { "type": "git", "url": "git+https://github.com/tauri-apps/tauri.git" }, "bugs": { "url": "https://github.com/tauri-apps/tauri/issues" }, "publishConfig": { "access": "public" }, "os": [ "win32" ] } ================================================ FILE: packages/cli/package.json ================================================ { "name": "@tauri-apps/cli", "version": "2.10.1", "description": "Command line interface for building Tauri apps", "type": "commonjs", "funding": { "type": "opencollective", "url": "https://opencollective.com/tauri" }, "repository": { "type": "git", "url": "git+https://github.com/tauri-apps/tauri.git" }, "contributors": [ "Tauri Programme within The Commons Conservancy" ], "license": "Apache-2.0 OR MIT", "bugs": { "url": "https://github.com/tauri-apps/tauri/issues" }, "homepage": "https://github.com/tauri-apps/tauri#readme", "publishConfig": { "access": "public" }, "main": "main.js", "types": "main.d.ts", "napi": { "binaryName": "cli", "targets": [ "x86_64-unknown-linux-gnu", "x86_64-pc-windows-msvc", "x86_64-apple-darwin", "aarch64-apple-darwin", "aarch64-unknown-linux-gnu", "aarch64-unknown-linux-musl", "armv7-unknown-linux-gnueabihf", "x86_64-unknown-linux-musl", "riscv64gc-unknown-linux-gnu", "i686-pc-windows-msvc", "aarch64-pc-windows-msvc" ] }, "devDependencies": { "@napi-rs/cli": "^3.5.1", "@types/node": "^24.11.0", "cross-env": "10.1.0", "vitest": "^4.0.18" }, "engines": { "node": ">= 10" }, "bin": { "tauri": "./tauri.js" }, "scripts": { "artifacts": "napi artifacts", "build": "cross-env TARGET=node napi build --platform --profile release-size-optimized", "postbuild": "node append-headers.js", "build:debug": "cross-env TARGET=node napi build --platform", "postbuild:debug": "node append-headers.js", "prepublishOnly": "napi prepublish -t npm --gh-release-id $RELEASE_ID", "prepack": "cp ../../crates/tauri-schema-generator/schemas/config.schema.json .", "version": "napi version", "test": "vitest run", "tauri": "node ./tauri.js" } } ================================================ FILE: packages/cli/src/lib.rs ================================================ // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT #![cfg(any(target_os = "macos", target_os = "linux", windows))] use std::sync::Arc; use napi::{ threadsafe_function::{ThreadsafeFunction, ThreadsafeFunctionCallMode}, Error, Result, Status, }; #[napi_derive::napi] pub fn run( args: Vec, bin_name: Option, callback: Arc>, ) -> Result<()> { // we need to run in a separate thread so Node.js consumers // can do work while `tauri dev` is running. std::thread::spawn(move || { let res = match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { tauri_cli::try_run(args, bin_name).inspect_err(|e| eprintln!("{e:#}")) })) { Ok(t) => t, Err(_) => { return callback.call( Err(Error::new( Status::GenericFailure, "Tauri CLI unexpected panic", )), ThreadsafeFunctionCallMode::Blocking, ); } }; match res { Ok(_) => callback.call(Ok(true), ThreadsafeFunctionCallMode::Blocking), Err(e) => callback.call( Err(Error::new(Status::GenericFailure, format!("{e:#}"))), ThreadsafeFunctionCallMode::Blocking, ), } }); Ok(()) } #[napi_derive::napi] pub fn log_error(error: String) { log::error!("{}", error); } ================================================ FILE: packages/cli/tauri.js ================================================ #!/usr/bin/env node // Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT const cli = require('./main') const path = require('path') const [bin, script, ...args] = process.argv const binStem = path.parse(bin).name.toLowerCase() // We want to make a helpful binary name for the underlying CLI helper, if we // can successfully detect what command likely started the execution. let binName // deno run -A npm:@tauri-apps/cli or deno task tauri if (globalThis.navigator?.userAgent?.includes('Deno')) { binName = bin } // Even if started by a package manager, the binary will be NodeJS. // Some distribution still use "nodejs" as the binary name. else if (binStem.match(/(nodejs|node|bun|electron)\-?([0-9]*)*$/g)) { const managerStem = process.env.npm_execpath ? path.parse(process.env.npm_execpath).name.toLowerCase() : null if (managerStem) { let manager switch (managerStem) { // Only supported package manager that has a different filename is npm. case 'npm-cli': manager = 'npm' break // Yarn, pnpm, and bun have the same stem name as their bin. // We assume all unknown package managers do as well. default: manager = managerStem break } binName = `${manager} run ${process.env.npm_lifecycle_event}` } else { // Assume running NodeJS if we didn't detect a manager from the env. // We normalize the path to prevent the script's absolute path being used. const scriptNormal = path.normalize(path.relative(process.cwd(), script)) binName = `${binStem} ${scriptNormal}` } } else { // We don't know what started it, assume it's already stripped. args.unshift(bin) } cli.run(args, binName).catch((err) => { cli.logError(err.message) process.exit(1) }) ================================================ FILE: pnpm-workspace.yaml ================================================ packages: - packages/api - packages/cli - crates/tauri-schema-worker - examples/api - examples/resources - examples/file-associations onlyBuiltDependencies: - esbuild - workerd ================================================ FILE: renovate.json ================================================ { "extends": ["config:recommended"], "baseBranches": ["dev"], "labels": ["type: chore"], "enabledManagers": ["cargo", "npm"], "rangeStrategy": "replace", "packageRules": [ { "matchPackageNames": ["*"], "semanticCommitType": "chore", "minimumReleaseAge": "3 days" }, { "description": "Disable node/pnpm version updates", "matchPackageNames": ["node", "pnpm"], "matchDepTypes": ["engines", "packageManager"], "enabled": false }, { "description": "Disable oxc_* crates because of MSRV and PR spam", "groupName": "oxc crates", "matchPackageNames": ["oxc_*"], "enabled": false }, { "description": "Group windows-rs / webview2-com crates", "groupName": "windows-rs and webview2 crates", "matchSourceUrls": [ "https://github.com/microsoft/windows-rs", "https://github.com/wravery/webview2-rs" ] }, { "description": "Group worker-rs crates", "groupName": "worker-rs crates", "matchSourceUrls": ["https://github.com/cloudflare/workers-rs"] } ], "postUpdateOptions": ["pnpmDedupe"] } ================================================ FILE: rustfmt.toml ================================================ max_width = 100 hard_tabs = false tab_spaces = 2 newline_style = "Unix" use_small_heuristics = "Default" reorder_imports = true reorder_modules = true remove_nested_parens = true edition = "2021" merge_derives = true use_try_shorthand = false use_field_init_shorthand = false force_explicit_abi = true # normalize_comments = true # wrap_comments = true ================================================ FILE: supply-chain/audits.toml ================================================ # cargo-vet audits file [audits] [[trusted.aead]] criteria = "safe-to-deploy" user-id = 267 # Tony Arcieri (tarcieri) start = "2020-06-05" end = "2025-05-08" [[trusted.aes]] criteria = "safe-to-deploy" user-id = 267 # Tony Arcieri (tarcieri) start = "2020-06-05" end = "2025-05-08" [[trusted.aes-gcm]] criteria = "safe-to-deploy" user-id = 267 # Tony Arcieri (tarcieri) start = "2019-08-16" end = "2025-05-08" [[trusted.aho-corasick]] criteria = "safe-to-deploy" user-id = 189 # Andrew Gallant (BurntSushi) start = "2019-03-28" end = "2025-03-06" [[trusted.anyhow]] criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2019-10-05" end = "2025-03-06" [[trusted.autocfg]] criteria = "safe-to-deploy" user-id = 539 # Josh Stone (cuviper) start = "2019-05-22" end = "2025-05-08" [[trusted.backtrace]] criteria = "safe-to-deploy" user-id = 2915 # Amanieu d'Antras (Amanieu) start = "2023-06-29" end = "2025-03-06" [[trusted.byteorder]] criteria = "safe-to-deploy" user-id = 189 # Andrew Gallant (BurntSushi) start = "2019-06-09" end = "2025-03-06" [[trusted.bytes]] criteria = "safe-to-deploy" user-id = 359 # Sean McArthur (seanmonstar) start = "2019-11-27" end = "2025-03-06" [[trusted.bytes]] criteria = "safe-to-deploy" user-id = 6741 # Alice Ryhl (Darksonn) start = "2021-01-11" end = "2025-03-06" [[trusted.cargo-platform]] criteria = "safe-to-deploy" user-id = 1 # Alex Crichton (alexcrichton) start = "2019-09-27" end = "2025-03-06" [[trusted.cc]] criteria = "safe-to-deploy" user-id = 2915 # Amanieu d'Antras (Amanieu) start = "2024-02-20" end = "2025-03-06" [[trusted.cipher]] criteria = "safe-to-deploy" user-id = 267 # Tony Arcieri (tarcieri) start = "2020-10-15" end = "2025-05-08" [[trusted.cpufeatures]] criteria = "safe-to-deploy" user-id = 267 # Tony Arcieri (tarcieri) start = "2021-04-26" end = "2025-05-08" [[trusted.ctr]] criteria = "safe-to-deploy" user-id = 267 # Tony Arcieri (tarcieri) start = "2020-06-06" end = "2025-05-08" [[trusted.digest]] criteria = "safe-to-deploy" user-id = 267 # Tony Arcieri (tarcieri) start = "2020-06-10" end = "2025-05-08" [[trusted.dtoa]] criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2019-05-02" end = "2025-03-06" [[trusted.dyn-clone]] criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2019-12-23" end = "2025-03-06" [[trusted.flate2]] criteria = "safe-to-deploy" user-id = 1 # Alex Crichton (alexcrichton) start = "2019-03-14" end = "2025-03-06" [[trusted.ghash]] criteria = "safe-to-deploy" user-id = 267 # Tony Arcieri (tarcieri) start = "2019-09-19" end = "2025-05-08" [[trusted.h2]] criteria = "safe-to-deploy" user-id = 359 # Sean McArthur (seanmonstar) start = "2019-03-13" end = "2025-03-06" [[trusted.hashbrown]] criteria = "safe-to-deploy" user-id = 2915 # Amanieu d'Antras (Amanieu) start = "2019-04-02" end = "2025-03-06" [[trusted.http]] criteria = "safe-to-deploy" user-id = 359 # Sean McArthur (seanmonstar) start = "2019-04-05" end = "2025-03-06" [[trusted.http-body]] criteria = "safe-to-deploy" user-id = 359 # Sean McArthur (seanmonstar) start = "2019-10-01" end = "2025-03-06" [[trusted.http-body-util]] criteria = "safe-to-deploy" user-id = 359 # Sean McArthur (seanmonstar) start = "2022-10-25" end = "2025-05-08" [[trusted.httparse]] criteria = "safe-to-deploy" user-id = 359 # Sean McArthur (seanmonstar) start = "2019-07-03" end = "2025-03-06" [[trusted.hyper]] criteria = "safe-to-deploy" user-id = 359 # Sean McArthur (seanmonstar) start = "2019-03-01" end = "2025-03-06" [[trusted.hyper-tls]] criteria = "safe-to-deploy" user-id = 359 # Sean McArthur (seanmonstar) start = "2019-03-19" end = "2025-03-06" [[trusted.hyper-util]] criteria = "safe-to-deploy" user-id = 359 # Sean McArthur (seanmonstar) start = "2022-01-15" end = "2025-05-08" [[trusted.indexmap]] criteria = "safe-to-deploy" user-id = 539 # Josh Stone (cuviper) start = "2020-01-15" end = "2025-03-06" [[trusted.itoa]] criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2019-05-02" end = "2025-03-06" [[trusted.javascriptcore-rs]] criteria = "safe-to-deploy" user-id = 95389 # tauri (tauri-bot) start = "2021-10-04" end = "2025-05-08" [[trusted.javascriptcore-rs-sys]] criteria = "safe-to-deploy" user-id = 95389 # tauri (tauri-bot) start = "2021-10-04" end = "2025-05-08" [[trusted.js-sys]] criteria = "safe-to-deploy" user-id = 1 # Alex Crichton (alexcrichton) start = "2019-03-04" end = "2025-03-06" [[trusted.libappindicator]] criteria = "safe-to-deploy" user-id = 95389 # tauri (tauri-bot) start = "2021-10-11" end = "2025-05-08" [[trusted.libappindicator-sys]] criteria = "safe-to-deploy" user-id = 95389 # tauri (tauri-bot) start = "2021-10-11" end = "2025-05-08" [[trusted.libc]] criteria = "safe-to-deploy" user-id = 2915 # Amanieu d'Antras (Amanieu) start = "2021-01-27" end = "2025-03-06" [[trusted.libc]] criteria = "safe-to-deploy" user-id = 51017 # Yuki Okushi (JohnTitor) start = "2020-03-17" end = "2025-05-08" [[trusted.libm]] criteria = "safe-to-deploy" user-id = 2915 # Amanieu d'Antras (Amanieu) start = "2022-02-06" end = "2025-03-06" [[trusted.linux-raw-sys]] criteria = "safe-to-deploy" user-id = 6825 # Dan Gohman (sunfishcode) start = "2021-06-12" end = "2025-03-06" [[trusted.lock_api]] criteria = "safe-to-deploy" user-id = 2915 # Amanieu d'Antras (Amanieu) start = "2019-05-04" end = "2025-03-06" [[trusted.loom]] criteria = "safe-to-deploy" user-id = 6741 # Alice Ryhl (Darksonn) start = "2021-04-12" end = "2025-03-06" [[trusted.memchr]] criteria = "safe-to-deploy" user-id = 189 # Andrew Gallant (BurntSushi) start = "2019-07-07" end = "2025-03-06" [[trusted.mime]] criteria = "safe-to-deploy" user-id = 359 # Sean McArthur (seanmonstar) start = "2019-09-09" end = "2025-03-06" [[trusted.mio]] criteria = "safe-to-deploy" user-id = 10 # Carl Lerche (carllerche) start = "2019-05-15" end = "2025-03-06" [[trusted.muda]] criteria = "safe-to-deploy" user-id = 95389 # tauri (tauri-bot) start = "2022-12-06" end = "2025-05-08" [[trusted.new_debug_unreachable]] criteria = "safe-to-deploy" user-id = 2017 # Matt Brubeck (mbrubeck) start = "2019-02-26" end = "2025-05-08" [[trusted.num_cpus]] criteria = "safe-to-deploy" user-id = 359 # Sean McArthur (seanmonstar) start = "2019-06-10" end = "2025-03-06" [[trusted.openssl-src]] criteria = "safe-to-deploy" user-id = 1 # Alex Crichton (alexcrichton) start = "2019-02-25" end = "2025-03-06" [[trusted.parking_lot]] criteria = "safe-to-deploy" user-id = 2915 # Amanieu d'Antras (Amanieu) start = "2019-05-04" end = "2025-03-06" [[trusted.parking_lot_core]] criteria = "safe-to-deploy" user-id = 2915 # Amanieu d'Antras (Amanieu) start = "2019-05-04" end = "2025-03-06" [[trusted.paste]] criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2019-03-19" end = "2025-05-08" [[trusted.phf]] criteria = "safe-to-deploy" user-id = 51017 # Yuki Okushi (JohnTitor) start = "2021-06-17" end = "2025-05-08" [[trusted.phf_codegen]] criteria = "safe-to-deploy" user-id = 51017 # Yuki Okushi (JohnTitor) start = "2021-06-17" end = "2025-05-08" [[trusted.phf_generator]] criteria = "safe-to-deploy" user-id = 51017 # Yuki Okushi (JohnTitor) start = "2021-06-17" end = "2025-05-08" [[trusted.phf_macros]] criteria = "safe-to-deploy" user-id = 51017 # Yuki Okushi (JohnTitor) start = "2021-06-17" end = "2025-05-08" [[trusted.phf_shared]] criteria = "safe-to-deploy" user-id = 51017 # Yuki Okushi (JohnTitor) start = "2021-06-17" end = "2025-05-08" [[trusted.polyval]] criteria = "safe-to-deploy" user-id = 267 # Tony Arcieri (tarcieri) start = "2019-08-13" end = "2025-05-08" [[trusted.proc-macro-hack]] criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2019-04-16" end = "2025-03-06" [[trusted.proc-macro2]] criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2019-04-23" end = "2025-03-06" [[trusted.quickcheck]] criteria = "safe-to-deploy" user-id = 189 # Andrew Gallant (BurntSushi) start = "2019-05-13" end = "2025-03-06" [[trusted.regex]] criteria = "safe-to-deploy" user-id = 189 # Andrew Gallant (BurntSushi) start = "2019-02-27" end = "2025-03-06" [[trusted.regex-automata]] criteria = "safe-to-deploy" user-id = 189 # Andrew Gallant (BurntSushi) start = "2019-02-25" end = "2025-03-06" [[trusted.regex-syntax]] criteria = "safe-to-deploy" user-id = 189 # Andrew Gallant (BurntSushi) start = "2019-03-30" end = "2025-03-06" [[trusted.reqwest]] criteria = "safe-to-deploy" user-id = 359 # Sean McArthur (seanmonstar) start = "2019-03-04" end = "2025-03-06" [[trusted.rustc-demangle]] criteria = "safe-to-deploy" user-id = 1 # Alex Crichton (alexcrichton) start = "2019-04-12" end = "2025-05-08" [[trusted.rustix]] criteria = "safe-to-deploy" user-id = 6825 # Dan Gohman (sunfishcode) start = "2021-10-29" end = "2025-03-06" [[trusted.rustversion]] criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2019-07-08" end = "2025-05-08" [[trusted.ryu]] criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2019-05-02" end = "2025-03-06" [[trusted.same-file]] criteria = "safe-to-deploy" user-id = 189 # Andrew Gallant (BurntSushi) start = "2019-07-16" end = "2025-03-06" [[trusted.scoped-tls]] criteria = "safe-to-deploy" user-id = 1 # Alex Crichton (alexcrichton) start = "2019-02-26" end = "2025-03-06" [[trusted.scopeguard]] criteria = "safe-to-deploy" user-id = 2915 # Amanieu d'Antras (Amanieu) start = "2020-02-16" end = "2025-03-06" [[trusted.semver]] criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2021-05-25" end = "2025-03-06" [[trusted.serde]] criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2019-03-01" end = "2025-03-06" [[trusted.serde_derive]] criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2019-03-01" end = "2025-05-08" [[trusted.serde_derive_internals]] criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2019-09-08" end = "2025-03-06" [[trusted.serde_json]] criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2019-02-28" end = "2025-03-06" [[trusted.serde_repr]] criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2019-04-26" end = "2025-03-06" [[trusted.serde_spanned]] criteria = "safe-to-deploy" user-id = 6743 # Ed Page (epage) start = "2023-01-20" end = "2025-03-06" [[trusted.serialize-to-javascript]] criteria = "safe-to-deploy" user-id = 28029 # chip (chippers) start = "2022-02-08" end = "2025-05-08" [[trusted.serialize-to-javascript-impl]] criteria = "safe-to-deploy" user-id = 28029 # chip (chippers) start = "2022-02-08" end = "2025-05-08" [[trusted.sha2]] criteria = "safe-to-deploy" user-id = 267 # Tony Arcieri (tarcieri) start = "2020-05-24" end = "2025-05-08" [[trusted.slab]] criteria = "safe-to-deploy" user-id = 6741 # Alice Ryhl (Darksonn) start = "2021-10-13" end = "2025-03-06" [[trusted.smallvec]] criteria = "safe-to-deploy" user-id = 2017 # Matt Brubeck (mbrubeck) start = "2019-10-28" end = "2025-03-06" [[trusted.socket2]] criteria = "safe-to-deploy" user-id = 1 # Alex Crichton (alexcrichton) start = "2019-05-06" end = "2025-03-06" [[trusted.syn]] criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2019-03-01" end = "2025-03-06" [[trusted.tao]] criteria = "safe-to-deploy" user-id = 95389 # tauri (tauri-bot) start = "2021-04-30" end = "2025-05-08" [[trusted.tao-macros]] criteria = "safe-to-deploy" user-id = 95389 # tauri (tauri-bot) start = "2023-01-11" end = "2025-05-08" [[trusted.target-lexicon]] criteria = "safe-to-deploy" user-id = 6825 # Dan Gohman (sunfishcode) start = "2019-03-06" end = "2025-03-06" [[trusted.tauri]] criteria = "safe-to-deploy" user-id = 95389 # tauri (tauri-bot) start = "2020-07-20" end = "2025-05-08" [[trusted.tauri-build]] criteria = "safe-to-deploy" user-id = 95389 # tauri (tauri-bot) start = "2021-04-14" end = "2025-05-08" [[trusted.tauri-codegen]] criteria = "safe-to-deploy" user-id = 95389 # tauri (tauri-bot) start = "2021-04-14" end = "2025-05-08" [[trusted.tauri-macros]] criteria = "safe-to-deploy" user-id = 95389 # tauri (tauri-bot) start = "2021-04-14" end = "2025-05-08" [[trusted.tauri-plugin]] criteria = "safe-to-deploy" user-id = 95389 # tauri (tauri-bot) start = "2024-02-03" end = "2025-05-08" [[trusted.tauri-runtime]] criteria = "safe-to-deploy" user-id = 95389 # tauri (tauri-bot) start = "2021-05-10" end = "2025-05-08" [[trusted.tauri-runtime-wry]] criteria = "safe-to-deploy" user-id = 95389 # tauri (tauri-bot) start = "2021-05-10" end = "2025-05-08" [[trusted.tauri-utils]] criteria = "safe-to-deploy" user-id = 95389 # tauri (tauri-bot) start = "2021-04-14" end = "2025-05-08" [[trusted.tauri-winres]] criteria = "safe-to-deploy" user-id = 95389 # tauri (tauri-bot) start = "2023-01-19" end = "2025-05-08" [[trusted.thiserror]] criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2019-10-09" end = "2025-03-06" [[trusted.thiserror-impl]] criteria = "safe-to-deploy" user-id = 3618 # David Tolnay (dtolnay) start = "2019-10-09" end = "2025-03-06" [[trusted.thread_local]] criteria = "safe-to-deploy" user-id = 2915 # Amanieu d'Antras (Amanieu) start = "2019-09-07" end = "2025-03-06" [[trusted.tokio]] criteria = "safe-to-deploy" user-id = 6741 # Alice Ryhl (Darksonn) start = "2020-12-25" end = "2025-03-06" [[trusted.tokio-macros]] criteria = "safe-to-deploy" user-id = 6741 # Alice Ryhl (Darksonn) start = "2020-10-26" end = "2025-03-06" [[trusted.tokio-macros]] criteria = "safe-to-deploy" user-id = 10 # Carl Lerche (carllerche) start = "2019-04-24" end = "2025-03-06" [[trusted.tokio-util]] criteria = "safe-to-deploy" user-id = 6741 # Alice Ryhl (Darksonn) start = "2021-01-12" end = "2025-03-06" [[trusted.toml]] criteria = "safe-to-deploy" user-id = 1 # Alex Crichton (alexcrichton) start = "2019-05-16" end = "2025-03-06" [[trusted.toml]] criteria = "safe-to-deploy" user-id = 6743 # Ed Page (epage) start = "2022-12-14" end = "2025-03-06" [[trusted.toml_edit]] criteria = "safe-to-deploy" user-id = 6743 # Ed Page (epage) start = "2021-09-13" end = "2025-03-06" [[trusted.tower]] criteria = "safe-to-deploy" user-id = 10 # Carl Lerche (carllerche) start = "2019-04-27" end = "2025-05-08" [[trusted.tower-layer]] criteria = "safe-to-deploy" user-id = 10 # Carl Lerche (carllerche) start = "2019-04-27" end = "2025-05-08" [[trusted.tray-icon]] criteria = "safe-to-deploy" user-id = 95389 # tauri (tauri-bot) start = "2022-12-01" end = "2025-05-08" [[trusted.ucd-trie]] criteria = "safe-to-deploy" user-id = 189 # Andrew Gallant (BurntSushi) start = "2019-07-21" end = "2025-03-06" [[trusted.walkdir]] criteria = "safe-to-deploy" user-id = 189 # Andrew Gallant (BurntSushi) start = "2019-06-09" end = "2025-03-06" [[trusted.wasi]] criteria = "safe-to-deploy" user-id = 6825 # Dan Gohman (sunfishcode) start = "2019-07-22" end = "2025-03-06" [[trusted.wasi]] criteria = "safe-to-deploy" user-id = 1 # Alex Crichton (alexcrichton) start = "2020-06-03" end = "2025-03-06" [[trusted.wasm-bindgen]] criteria = "safe-to-deploy" user-id = 1 # Alex Crichton (alexcrichton) start = "2019-03-04" end = "2025-03-06" [[trusted.wasm-bindgen-backend]] criteria = "safe-to-deploy" user-id = 1 # Alex Crichton (alexcrichton) start = "2019-03-04" end = "2025-03-06" [[trusted.wasm-bindgen-futures]] criteria = "safe-to-deploy" user-id = 1 # Alex Crichton (alexcrichton) start = "2019-03-04" end = "2025-03-06" [[trusted.wasm-bindgen-macro]] criteria = "safe-to-deploy" user-id = 1 # Alex Crichton (alexcrichton) start = "2019-03-04" end = "2025-03-06" [[trusted.wasm-bindgen-macro-support]] criteria = "safe-to-deploy" user-id = 1 # Alex Crichton (alexcrichton) start = "2019-03-04" end = "2025-03-06" [[trusted.wasm-bindgen-shared]] criteria = "safe-to-deploy" user-id = 1 # Alex Crichton (alexcrichton) start = "2019-03-04" end = "2025-03-06" [[trusted.web-sys]] criteria = "safe-to-deploy" user-id = 1 # Alex Crichton (alexcrichton) start = "2019-03-04" end = "2025-03-06" [[trusted.webkit2gtk]] criteria = "safe-to-deploy" user-id = 95389 # tauri (tauri-bot) start = "2021-10-05" end = "2025-05-08" [[trusted.webkit2gtk-sys]] criteria = "safe-to-deploy" user-id = 95389 # tauri (tauri-bot) start = "2021-10-05" end = "2025-05-08" [[trusted.winapi-util]] criteria = "safe-to-deploy" user-id = 189 # Andrew Gallant (BurntSushi) start = "2020-01-11" end = "2025-03-06" [[trusted.window-vibrancy]] criteria = "safe-to-deploy" user-id = 95389 # tauri (tauri-bot) start = "2022-03-05" end = "2025-05-08" [[trusted.windows]] criteria = "safe-to-deploy" user-id = 64539 # Kenny Kerr (kennykerr) start = "2021-01-15" end = "2025-03-06" [[trusted.windows-core]] criteria = "safe-to-deploy" user-id = 64539 # Kenny Kerr (kennykerr) start = "2021-11-15" end = "2025-03-06" [[trusted.windows-implement]] criteria = "safe-to-deploy" user-id = 64539 # Kenny Kerr (kennykerr) start = "2022-01-27" end = "2025-03-06" [[trusted.windows-interface]] criteria = "safe-to-deploy" user-id = 64539 # Kenny Kerr (kennykerr) start = "2022-02-18" end = "2025-03-06" [[trusted.windows-result]] criteria = "safe-to-deploy" user-id = 64539 # Kenny Kerr (kennykerr) start = "2024-02-02" end = "2025-03-06" [[trusted.windows-sys]] criteria = "safe-to-deploy" user-id = 64539 # Kenny Kerr (kennykerr) start = "2021-11-15" end = "2025-03-06" [[trusted.windows-targets]] criteria = "safe-to-deploy" user-id = 64539 # Kenny Kerr (kennykerr) start = "2022-09-09" end = "2025-03-06" [[trusted.windows-version]] criteria = "safe-to-deploy" user-id = 64539 # Kenny Kerr (kennykerr) start = "2023-03-07" end = "2025-03-06" [[trusted.windows_aarch64_gnullvm]] criteria = "safe-to-deploy" user-id = 64539 # Kenny Kerr (kennykerr) start = "2022-09-01" end = "2025-03-06" [[trusted.windows_aarch64_msvc]] criteria = "safe-to-deploy" user-id = 64539 # Kenny Kerr (kennykerr) start = "2021-11-05" end = "2025-03-06" [[trusted.windows_i686_gnu]] criteria = "safe-to-deploy" user-id = 64539 # Kenny Kerr (kennykerr) start = "2021-10-28" end = "2025-03-06" [[trusted.windows_i686_gnullvm]] criteria = "safe-to-deploy" user-id = 64539 # Kenny Kerr (kennykerr) start = "2024-04-02" end = "2025-05-08" [[trusted.windows_i686_msvc]] criteria = "safe-to-deploy" user-id = 64539 # Kenny Kerr (kennykerr) start = "2021-10-27" end = "2025-03-06" [[trusted.windows_x86_64_gnu]] criteria = "safe-to-deploy" user-id = 64539 # Kenny Kerr (kennykerr) start = "2021-10-28" end = "2025-03-06" [[trusted.windows_x86_64_gnullvm]] criteria = "safe-to-deploy" user-id = 64539 # Kenny Kerr (kennykerr) start = "2022-09-01" end = "2025-03-06" [[trusted.windows_x86_64_msvc]] criteria = "safe-to-deploy" user-id = 64539 # Kenny Kerr (kennykerr) start = "2021-10-27" end = "2025-03-06" [[trusted.winnow]] criteria = "safe-to-deploy" user-id = 6743 # Ed Page (epage) start = "2023-02-22" end = "2025-03-06" [[trusted.wry]] criteria = "safe-to-deploy" user-id = 95389 # tauri (tauri-bot) start = "2021-03-11" end = "2025-05-08" [[trusted.zeroize]] criteria = "safe-to-deploy" user-id = 267 # Tony Arcieri (tarcieri) start = "2021-11-05" end = "2025-05-08" ================================================ FILE: supply-chain/config.toml ================================================ # cargo-vet config file [cargo-vet] version = "0.9" [imports.bytecode-alliance] url = "https://raw.githubusercontent.com/bytecodealliance/wasmtime/main/supply-chain/audits.toml" [imports.embark-studios] url = "https://raw.githubusercontent.com/EmbarkStudios/rust-ecosystem/main/audits.toml" [imports.google] url = "https://raw.githubusercontent.com/google/supply-chain/main/audits.toml" [imports.isrg] url = "https://raw.githubusercontent.com/divviup/libprio-rs/main/supply-chain/audits.toml" [imports.mozilla] url = "https://raw.githubusercontent.com/mozilla/supply-chain/main/audits.toml" [imports.zcash] url = "https://raw.githubusercontent.com/zcash/rust-ecosystem/main/supply-chain/audits.toml" [policy.tauri] audit-as-crates-io = true [policy.tauri-build] audit-as-crates-io = true [policy.tauri-codegen] audit-as-crates-io = true [policy.tauri-macros] audit-as-crates-io = true [policy.tauri-plugin] audit-as-crates-io = true [policy.tauri-runtime] audit-as-crates-io = true [policy.tauri-runtime-wry] audit-as-crates-io = true [policy.tauri-utils] audit-as-crates-io = true [[exemptions.addr2line]] version = "0.21.0" criteria = "safe-to-deploy" [[exemptions.alloc-no-stdlib]] version = "2.0.4" criteria = "safe-to-deploy" [[exemptions.alloc-stdlib]] version = "0.2.2" criteria = "safe-to-deploy" [[exemptions.android-tzdata]] version = "0.1.1" criteria = "safe-to-deploy" [[exemptions.as-raw-xcb-connection]] version = "1.0.1" criteria = "safe-to-deploy" [[exemptions.atk]] version = "0.18.0" criteria = "safe-to-deploy" [[exemptions.atk-sys]] version = "0.18.0" criteria = "safe-to-deploy" [[exemptions.base64]] version = "0.21.7" criteria = "safe-to-deploy" [[exemptions.bitflags]] version = "1.3.2" criteria = "safe-to-deploy" [[exemptions.block]] version = "0.1.6" criteria = "safe-to-deploy" [[exemptions.brotli]] version = "3.4.0" criteria = "safe-to-deploy" [[exemptions.brotli-decompressor]] version = "2.5.1" criteria = "safe-to-deploy" [[exemptions.bytemuck]] version = "1.14.3" criteria = "safe-to-deploy" [[exemptions.bytemuck_derive]] version = "1.5.0" criteria = "safe-to-deploy" [[exemptions.cairo-rs]] version = "0.18.5" criteria = "safe-to-deploy" [[exemptions.cairo-sys-rs]] version = "0.18.2" criteria = "safe-to-deploy" [[exemptions.camino]] version = "1.1.6" criteria = "safe-to-deploy" [[exemptions.cargo-platform]] version = "0.1.7" criteria = "safe-to-deploy" [[exemptions.cargo_toml]] version = "0.17.2" criteria = "safe-to-deploy" [[exemptions.cesu8]] version = "1.1.0" criteria = "safe-to-deploy" [[exemptions.cfb]] version = "0.7.3" criteria = "safe-to-deploy" [[exemptions.cfg_aliases]] version = "0.2.0" criteria = "safe-to-deploy" [[exemptions.chrono]] version = "0.4.34" criteria = "safe-to-deploy" [[exemptions.cocoa]] version = "0.25.0" criteria = "safe-to-deploy" [[exemptions.cocoa-foundation]] version = "0.1.2" criteria = "safe-to-deploy" [[exemptions.combine]] version = "4.6.6" criteria = "safe-to-deploy" [[exemptions.console]] version = "0.15.8" criteria = "safe-to-run" [[exemptions.core-foundation]] version = "0.9.4" criteria = "safe-to-deploy" [[exemptions.core-graphics-types]] version = "0.1.3" criteria = "safe-to-deploy" [[exemptions.crc32fast]] version = "1.4.0" criteria = "safe-to-deploy" [[exemptions.crossbeam-channel]] version = "0.5.12" criteria = "safe-to-deploy" [[exemptions.crossbeam-utils]] version = "0.8.19" criteria = "safe-to-deploy" [[exemptions.cssparser]] version = "0.27.2" criteria = "safe-to-deploy" [[exemptions.ctor]] version = "0.2.7" criteria = "safe-to-deploy" [[exemptions.ctr]] version = "0.9.2" criteria = "safe-to-deploy" [[exemptions.darling]] version = "0.20.8" criteria = "safe-to-deploy" [[exemptions.darling_core]] version = "0.20.8" criteria = "safe-to-deploy" [[exemptions.darling_macro]] version = "0.20.8" criteria = "safe-to-deploy" [[exemptions.data-url]] version = "0.3.1" criteria = "safe-to-deploy" [[exemptions.deranged]] version = "0.3.11" criteria = "safe-to-deploy" [[exemptions.dirs-sys-next]] version = "0.1.2" criteria = "safe-to-deploy" [[exemptions.dispatch]] version = "0.2.0" criteria = "safe-to-deploy" [[exemptions.dlib]] version = "0.5.2" criteria = "safe-to-deploy" [[exemptions.dlopen2]] version = "0.7.0" criteria = "safe-to-deploy" [[exemptions.dlopen2_derive]] version = "0.4.0" criteria = "safe-to-deploy" [[exemptions.downcast-rs]] version = "1.2.0" criteria = "safe-to-deploy" [[exemptions.drm]] version = "0.11.1" criteria = "safe-to-deploy" [[exemptions.drm-ffi]] version = "0.7.1" criteria = "safe-to-deploy" [[exemptions.drm-fourcc]] version = "2.2.0" criteria = "safe-to-deploy" [[exemptions.drm-sys]] version = "0.6.1" criteria = "safe-to-deploy" [[exemptions.dtoa-short]] version = "0.3.4" criteria = "safe-to-deploy" [[exemptions.dunce]] version = "1.0.4" criteria = "safe-to-deploy" [[exemptions.embed-resource]] version = "2.4.1" criteria = "safe-to-deploy" [[exemptions.embed_plist]] version = "1.2.2" criteria = "safe-to-deploy" [[exemptions.encode_unicode]] version = "0.3.6" criteria = "safe-to-run" [[exemptions.fdeflate]] version = "0.3.4" criteria = "safe-to-deploy" [[exemptions.field-offset]] version = "0.3.6" criteria = "safe-to-deploy" [[exemptions.flate2]] version = "1.0.28" criteria = "safe-to-deploy" [[exemptions.futf]] version = "0.1.5" criteria = "safe-to-deploy" [[exemptions.futures-executor]] version = "0.3.30" criteria = "safe-to-deploy" [[exemptions.futures-io]] version = "0.3.30" criteria = "safe-to-deploy" [[exemptions.futures-macro]] version = "0.3.30" criteria = "safe-to-deploy" [[exemptions.futures-sink]] version = "0.3.30" criteria = "safe-to-deploy" [[exemptions.futures-task]] version = "0.3.30" criteria = "safe-to-deploy" [[exemptions.futures-util]] version = "0.3.30" criteria = "safe-to-deploy" [[exemptions.gdk]] version = "0.18.0" criteria = "safe-to-deploy" [[exemptions.gdk-pixbuf]] version = "0.18.5" criteria = "safe-to-deploy" [[exemptions.gdk-pixbuf-sys]] version = "0.18.0" criteria = "safe-to-deploy" [[exemptions.gdk-sys]] version = "0.18.0" criteria = "safe-to-deploy" [[exemptions.gdkwayland-sys]] version = "0.18.0" criteria = "safe-to-deploy" [[exemptions.gdkx11]] version = "0.18.0" criteria = "safe-to-deploy" [[exemptions.gdkx11-sys]] version = "0.18.0" criteria = "safe-to-deploy" [[exemptions.generator]] version = "0.7.6" criteria = "safe-to-deploy" [[exemptions.generic-array]] version = "0.14.7" criteria = "safe-to-deploy" [[exemptions.gethostname]] version = "0.4.3" criteria = "safe-to-deploy" [[exemptions.getrandom]] version = "0.1.16" criteria = "safe-to-deploy" [[exemptions.getrandom]] version = "0.2.12" criteria = "safe-to-deploy" [[exemptions.gimli]] version = "0.28.1" criteria = "safe-to-deploy" [[exemptions.gio]] version = "0.18.4" criteria = "safe-to-deploy" [[exemptions.gio-sys]] version = "0.18.1" criteria = "safe-to-deploy" [[exemptions.glib]] version = "0.18.5" criteria = "safe-to-deploy" [[exemptions.glib-macros]] version = "0.18.5" criteria = "safe-to-deploy" [[exemptions.glib-sys]] version = "0.18.1" criteria = "safe-to-deploy" [[exemptions.gobject-sys]] version = "0.18.0" criteria = "safe-to-deploy" [[exemptions.gtk]] version = "0.18.1" criteria = "safe-to-deploy" [[exemptions.gtk-sys]] version = "0.18.0" criteria = "safe-to-deploy" [[exemptions.gtk3-macros]] version = "0.18.0" criteria = "safe-to-deploy" [[exemptions.hermit-abi]] version = "0.3.8" criteria = "safe-to-deploy" [[exemptions.html5ever]] version = "0.26.0" criteria = "safe-to-deploy" [[exemptions.http-range]] version = "0.1.5" criteria = "safe-to-deploy" [[exemptions.hyper-rustls]] version = "0.24.2" criteria = "safe-to-deploy" [[exemptions.iana-time-zone]] version = "0.1.60" criteria = "safe-to-deploy" [[exemptions.ico]] version = "0.3.0" criteria = "safe-to-deploy" [[exemptions.image]] version = "0.24.9" criteria = "safe-to-deploy" [[exemptions.infer]] version = "0.15.0" criteria = "safe-to-deploy" [[exemptions.insta]] version = "1.35.1" criteria = "safe-to-run" [[exemptions.instant]] version = "0.1.12" criteria = "safe-to-deploy" [[exemptions.ipnet]] version = "2.9.0" criteria = "safe-to-deploy" [[exemptions.jni-sys]] version = "0.3.0" criteria = "safe-to-deploy" [[exemptions.json-patch]] version = "1.2.0" criteria = "safe-to-deploy" [[exemptions.json5]] version = "0.4.1" criteria = "safe-to-deploy" [[exemptions.keyboard-types]] version = "0.7.0" criteria = "safe-to-deploy" [[exemptions.kuchikiki]] version = "0.8.2" criteria = "safe-to-deploy" [[exemptions.libloading]] version = "0.7.4" criteria = "safe-to-deploy" [[exemptions.libloading]] version = "0.8.1" criteria = "safe-to-deploy" [[exemptions.libredox]] version = "0.0.1" criteria = "safe-to-deploy" [[exemptions.libxdo]] version = "0.6.0" criteria = "safe-to-deploy" [[exemptions.libxdo-sys]] version = "0.11.0" criteria = "safe-to-deploy" [[exemptions.mac]] version = "0.1.1" criteria = "safe-to-deploy" [[exemptions.markup5ever]] version = "0.11.0" criteria = "safe-to-deploy" [[exemptions.memmap2]] version = "0.9.4" criteria = "safe-to-deploy" [[exemptions.memoffset]] version = "0.9.0" criteria = "safe-to-deploy" [[exemptions.miniz_oxide]] version = "0.7.2" criteria = "safe-to-deploy" [[exemptions.mio]] version = "0.8.11" criteria = "safe-to-deploy" [[exemptions.ndk]] version = "0.7.0" criteria = "safe-to-deploy" [[exemptions.ndk-sys]] version = "0.4.1+23.1.7779620" criteria = "safe-to-deploy" [[exemptions.nodrop]] version = "0.1.14" criteria = "safe-to-deploy" [[exemptions.num-conv]] version = "0.1.0" criteria = "safe-to-deploy" [[exemptions.objc]] version = "0.2.7" criteria = "safe-to-deploy" [[exemptions.objc_exception]] version = "0.1.2" criteria = "safe-to-deploy" [[exemptions.objc_id]] version = "0.1.1" criteria = "safe-to-deploy" [[exemptions.object]] version = "0.32.2" criteria = "safe-to-deploy" [[exemptions.once_cell]] version = "1.19.0" criteria = "safe-to-deploy" [[exemptions.openssl]] version = "0.10.64" criteria = "safe-to-deploy" [[exemptions.openssl-sys]] version = "0.9.101" criteria = "safe-to-deploy" [[exemptions.pango]] version = "0.18.3" criteria = "safe-to-deploy" [[exemptions.pango-sys]] version = "0.18.0" criteria = "safe-to-deploy" [[exemptions.pest]] version = "2.7.7" criteria = "safe-to-deploy" [[exemptions.pest_derive]] version = "2.7.7" criteria = "safe-to-deploy" [[exemptions.pest_generator]] version = "2.7.7" criteria = "safe-to-deploy" [[exemptions.pest_meta]] version = "2.7.7" criteria = "safe-to-deploy" [[exemptions.phf]] version = "0.8.0" criteria = "safe-to-deploy" [[exemptions.phf_codegen]] version = "0.8.0" criteria = "safe-to-deploy" [[exemptions.phf_generator]] version = "0.8.0" criteria = "safe-to-deploy" [[exemptions.phf_macros]] version = "0.8.0" criteria = "safe-to-deploy" [[exemptions.phf_shared]] version = "0.8.0" criteria = "safe-to-deploy" [[exemptions.pkg-config]] version = "0.3.30" criteria = "safe-to-deploy" [[exemptions.plist]] version = "1.6.0" criteria = "safe-to-deploy" [[exemptions.png]] version = "0.17.13" criteria = "safe-to-deploy" [[exemptions.powerfmt]] version = "0.2.0" criteria = "safe-to-deploy" [[exemptions.ppv-lite86]] version = "0.2.17" criteria = "safe-to-deploy" [[exemptions.proc-macro-crate]] version = "1.3.1" criteria = "safe-to-deploy" [[exemptions.proc-macro-crate]] version = "2.0.2" criteria = "safe-to-deploy" [[exemptions.proc-macro-error]] version = "1.0.4" criteria = "safe-to-deploy" [[exemptions.proptest]] version = "1.4.0" criteria = "safe-to-run" [[exemptions.quick-error]] version = "1.2.3" criteria = "safe-to-run" [[exemptions.quick-xml]] version = "0.31.0" criteria = "safe-to-deploy" [[exemptions.rand]] version = "0.7.3" criteria = "safe-to-deploy" [[exemptions.rand]] version = "0.8.5" criteria = "safe-to-deploy" [[exemptions.rand_chacha]] version = "0.2.2" criteria = "safe-to-deploy" [[exemptions.rand_core]] version = "0.5.1" criteria = "safe-to-deploy" [[exemptions.rand_hc]] version = "0.2.0" criteria = "safe-to-deploy" [[exemptions.rand_pcg]] version = "0.2.1" criteria = "safe-to-deploy" [[exemptions.redox_syscall]] version = "0.4.1" criteria = "safe-to-deploy" [[exemptions.redox_users]] version = "0.4.4" criteria = "safe-to-deploy" [[exemptions.ring]] version = "0.17.8" criteria = "safe-to-deploy" [[exemptions.rustls]] version = "0.21.10" criteria = "safe-to-deploy" [[exemptions.rustls-pemfile]] version = "1.0.4" criteria = "safe-to-deploy" [[exemptions.rustls-webpki]] version = "0.101.7" criteria = "safe-to-deploy" [[exemptions.rusty-fork]] version = "0.3.0" criteria = "safe-to-run" [[exemptions.safemem]] version = "0.3.3" criteria = "safe-to-deploy" [[exemptions.schannel]] version = "0.1.23" criteria = "safe-to-deploy" [[exemptions.schemars]] version = "0.8.16" criteria = "safe-to-deploy" [[exemptions.schemars_derive]] version = "0.8.16" criteria = "safe-to-deploy" [[exemptions.sct]] version = "0.7.1" criteria = "safe-to-deploy" [[exemptions.security-framework]] version = "2.9.2" criteria = "safe-to-deploy" [[exemptions.security-framework-sys]] version = "2.9.1" criteria = "safe-to-deploy" [[exemptions.serde_urlencoded]] version = "0.7.1" criteria = "safe-to-deploy" [[exemptions.serde_with]] version = "3.6.1" criteria = "safe-to-deploy" [[exemptions.serde_with_macros]] version = "3.6.1" criteria = "safe-to-deploy" [[exemptions.sha2]] version = "0.10.8" criteria = "safe-to-deploy" [[exemptions.simd-adler32]] version = "0.3.7" criteria = "safe-to-deploy" [[exemptions.similar]] version = "2.4.0" criteria = "safe-to-run" [[exemptions.siphasher]] version = "0.3.11" criteria = "safe-to-deploy" [[exemptions.socket2]] version = "0.5.6" criteria = "safe-to-deploy" [[exemptions.softbuffer]] version = "0.4.1" criteria = "safe-to-deploy" [[exemptions.soup3]] version = "0.5.0" criteria = "safe-to-deploy" [[exemptions.soup3-sys]] version = "0.5.0" criteria = "safe-to-deploy" [[exemptions.spin]] version = "0.9.8" criteria = "safe-to-deploy" [[exemptions.stable_deref_trait]] version = "1.2.0" criteria = "safe-to-deploy" [[exemptions.state]] version = "0.6.0" criteria = "safe-to-deploy" [[exemptions.string_cache]] version = "0.8.7" criteria = "safe-to-deploy" [[exemptions.string_cache_codegen]] version = "0.5.2" criteria = "safe-to-deploy" [[exemptions.swift-rs]] version = "1.0.6" criteria = "safe-to-deploy" [[exemptions.sync_wrapper]] version = "0.1.2" criteria = "safe-to-deploy" [[exemptions.system-configuration]] version = "0.5.1" criteria = "safe-to-deploy" [[exemptions.system-configuration-sys]] version = "0.5.0" criteria = "safe-to-deploy" [[exemptions.system-deps]] version = "6.2.0" criteria = "safe-to-deploy" [[exemptions.tempfile]] version = "3.10.1" criteria = "safe-to-deploy" [[exemptions.tendril]] version = "0.4.3" criteria = "safe-to-deploy" [[exemptions.thin-slice]] version = "0.1.1" criteria = "safe-to-deploy" [[exemptions.time]] version = "0.3.34" criteria = "safe-to-deploy" [[exemptions.time-macros]] version = "0.2.17" criteria = "safe-to-deploy" [[exemptions.tiny-xlib]] version = "0.2.2" criteria = "safe-to-deploy" [[exemptions.tokio-rustls]] version = "0.24.1" criteria = "safe-to-deploy" [[exemptions.tower-service]] version = "0.3.2" criteria = "safe-to-deploy" [[exemptions.tracing]] version = "0.1.40" criteria = "safe-to-deploy" [[exemptions.tracing-attributes]] version = "0.1.27" criteria = "safe-to-deploy" [[exemptions.tracing-core]] version = "0.1.32" criteria = "safe-to-deploy" [[exemptions.tracing-log]] version = "0.2.0" criteria = "safe-to-deploy" [[exemptions.treediff]] version = "4.0.3" criteria = "safe-to-deploy" [[exemptions.typenum]] version = "1.17.0" criteria = "safe-to-deploy" [[exemptions.unarray]] version = "0.1.4" criteria = "safe-to-run" [[exemptions.untrusted]] version = "0.9.0" criteria = "safe-to-deploy" [[exemptions.utf-8]] version = "0.7.6" criteria = "safe-to-deploy" [[exemptions.uuid]] version = "1.7.0" criteria = "safe-to-deploy" [[exemptions.vswhom]] version = "0.1.0" criteria = "safe-to-deploy" [[exemptions.vswhom-sys]] version = "0.1.2" criteria = "safe-to-deploy" [[exemptions.wait-timeout]] version = "0.2.0" criteria = "safe-to-run" [[exemptions.wasm-streams]] version = "0.4.0" criteria = "safe-to-deploy" [[exemptions.wayland-backend]] version = "0.3.3" criteria = "safe-to-deploy" [[exemptions.wayland-client]] version = "0.31.2" criteria = "safe-to-deploy" [[exemptions.wayland-scanner]] version = "0.31.1" criteria = "safe-to-deploy" [[exemptions.wayland-sys]] version = "0.31.1" criteria = "safe-to-deploy" [[exemptions.webpki-roots]] version = "0.25.4" criteria = "safe-to-deploy" [[exemptions.webview2-com]] version = "0.28.0" criteria = "safe-to-deploy" [[exemptions.webview2-com-macros]] version = "0.7.0" criteria = "safe-to-deploy" [[exemptions.webview2-com-sys]] version = "0.28.0" criteria = "safe-to-deploy" [[exemptions.winapi]] version = "0.3.9" criteria = "safe-to-deploy" [[exemptions.winapi-i686-pc-windows-gnu]] version = "0.4.0" criteria = "safe-to-deploy" [[exemptions.winapi-x86_64-pc-windows-gnu]] version = "0.4.0" criteria = "safe-to-deploy" [[exemptions.winreg]] version = "0.50.0" criteria = "safe-to-deploy" [[exemptions.winreg]] version = "0.51.0" criteria = "safe-to-deploy" [[exemptions.x11]] version = "2.21.0" criteria = "safe-to-deploy" [[exemptions.x11-dl]] version = "2.21.0" criteria = "safe-to-deploy" [[exemptions.x11rb]] version = "0.13.0" criteria = "safe-to-deploy" [[exemptions.x11rb-protocol]] version = "0.13.0" criteria = "safe-to-deploy"