Merge branch '1.x' into feat/cli/kill-dev-app-api

This commit is contained in:
amrbashir 2024-02-10 02:35:55 +02:00
commit 0fa69531ea
No known key found for this signature in database
GPG Key ID: BBD7A47A2003FF33
191 changed files with 11777 additions and 4577 deletions

View File

@ -1,5 +0,0 @@
---
'tauri': 'minor:feat'
---
Add `tauri::Manager::emit_filter` and only serialize once when emitting to multiple windows.

View File

@ -0,0 +1,5 @@
---
"tauri-bundler": patch:feat
---
Add `priority`, `section` and `changelog` options in Debian config.

View File

@ -1,5 +0,0 @@
---
'@tauri-apps/api': 'patch:bug'
---
Fix `Body.form` static not reading and sending entries of type `Blob` (including subclasses such as `File`)

View File

@ -1,5 +0,0 @@
---
'tauri-bundler': 'patch:bug'
---
Fix bundler skipping updater artifacts if `updater` target shows before other updater-enabled targets in the list, see [#7349](https://github.com/tauri-apps/tauri/issues/7349).

View File

@ -1,5 +0,0 @@
---
'tauri-bundler': 'patch:bug'
---
Fix bundler skipping updater artifacts if only a macOS DMG bundle target is specified.

View File

@ -1,5 +0,0 @@
---
'tauri-bundler': 'minor:enhance'
---
Sign NSIS uninstaller as well.

View File

@ -0,0 +1,5 @@
---
"tauri-bundler": patch:enhance
---
Support using socks proxy from environment when downloading files.

View File

@ -1,7 +0,0 @@
---
'tauri-bundler': 'patch:enhance'
---
On Windows, code sign the application binaries before trying to create the WiX and NSIS bundles to always sign the executables even if no bundle types are enabled.
On Windows, code sign the sidecar binaries if they are not signed already.

View File

@ -0,0 +1,6 @@
---
'tauri-cli': 'patch:bug'
'@tauri-apps/cli': 'patch:bug'
---
Fix `fail to rename app` when using `--profile dev`.

View File

@ -0,0 +1,6 @@
---
"tauri-cli": patch:bug
"@tauri-apps/cli": patch:bug
---
Fix the built-in dev server failing to serve files when URL had queries `?` and other url components.

View File

@ -1,6 +0,0 @@
---
'tauri-cli': 'patch:bug'
'@tauri-apps/cli': 'patch:bug'
---
Removed the automatic version check of the CLI that ran after `tauri` commands which caused various issues.

View File

@ -0,0 +1,6 @@
---
"tauri-cli": patch:bug
"@tauri-apps/cli": patch:bug
---
The cli now also watches cargo workspace members if the tauri folder is the workspace root.

View File

@ -1,6 +1,5 @@
{
"gitSiteUrl": "https://www.github.com/tauri-apps/tauri/",
"timeout": 3600000,
"changeTags": {
"feat": "New Features",
"enhance": "Enhancements",
@ -272,7 +271,8 @@
},
"tauri-driver": {
"path": "./tooling/webdriver",
"manager": "rust"
"manager": "rust",
"postversion": "cargo check"
}
}
}

View File

@ -1,5 +0,0 @@
---
'tauri': 'minor:enhance'
---
Open links externally when `<base target="_blank" />` exists

View File

@ -1,6 +0,0 @@
---
"tauri-cli": minor:enhance
"@tauri-apps/cli": minor:enhance
---
Add version of Rust Tauri CLI installed with Cargo to `tauri info` command.

View File

@ -1,5 +0,0 @@
---
"tauri": patch:enhance
---
Enhance `readDir` API error with path information.

5
.changes/export-url.md Normal file
View File

@ -0,0 +1,5 @@
---
'tauri': 'patch:feat'
---
Re-export `Url` type.

View File

@ -0,0 +1,5 @@
---
"tauri": patch:bug
---
Fixes a deadlock when reading a stdout or stderr line returns an error.

View File

@ -0,0 +1,5 @@
---
'tauri': 'patch:bug'
---
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.

View File

@ -0,0 +1,6 @@
---
'tauri-bundler': 'patch:bug'
---
Fix the `non-standard-file-perm` and `non-standard-dir-perm` issue in Debian packages

View File

@ -1,5 +0,0 @@
---
'tauri-bundler': 'patch:bug'
---
On Windows, fix installation packages not showing correct copyright information.

View File

@ -1,5 +0,0 @@
---
'tauri-bundler': 'patch:bug'
---
On Windows, fix NSIS installer identifying a previous NSIS-installed app as WiX-installed app and then fails to uninstall it.

View File

@ -1,5 +0,0 @@
---
'tauri-bundler': 'patch:bug'
---
On Windows, Fix NSIS uninstaller deleting the wrong application data if the delete the application data checkbox is checked.

View File

@ -1,5 +0,0 @@
---
'tauri-bundler': 'patch:bug'
---
On Windows, fix NSIS installer showing an error dialog even when the previous version was uninstalled sucessfully.

View File

@ -1,5 +0,0 @@
---
'tauri-bundler': 'patch:enhance'
---
On Windows, NSIS installer will write webview2 installer file to the well-known temp dir instead of the install dir, so we don't pollute the install dir.

View File

@ -1,6 +0,0 @@
---
'@tauri-apps/api': 'patch:enhance'
'tauri': 'patch:enhance'
---
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.

View File

@ -1,5 +0,0 @@
---
"tauri-utils": patch:sec
---
Changed HTML implementation from unmaintained `kuchiki` to `kuchikiki`.

View File

@ -0,0 +1,5 @@
---
"tauri-bundler": patch:deps
---
Replace `libflate` with `flate2` , this will help to provide additional functionalities and features.

View File

@ -0,0 +1,6 @@
---
"tauri-cli": patch:feat
"tauri-bundler": patch:feat
---
On macOS, support for signing nested .dylib, .app, .xpc and .framework under predefined directories inside the bundled frameworks ("MacOS", "Frameworks", "Plugins", "Helpers", "XPCServices" and "Libraries").

View File

@ -1,5 +0,0 @@
---
"tauri-bundler": minor:breaking
---
The macOS notarization now uses `notarytool` as `altool` will be discontinued on November 2023. When authenticating with an API key, the key `.p8` file path must be provided in the `APPLE_API_KEY_PATH` environment variable. To prevent a breaking change, we will try to find the key path in the `altool` default search paths.

View File

@ -1,6 +0,0 @@
---
'tauri': 'minor:feat'
'@tauri-apps/api': 'minor:feat'
---
Add option to specify notification sound.

View File

@ -1,5 +0,0 @@
---
'tauri-bundler': 'patch:enhance'
---
Added Bulgarian language support to the NSIS bundler.

View File

@ -1,5 +0,0 @@
---
'tauri-bundler': 'patch:bug'
---
On Windows, fix NSIS installer trying to kill itself if the installer file name and the app `productName` are the same.

View File

@ -1,5 +0,0 @@
---
'tauri-bundler': 'patch:enhance'
---
Add `compression` configuration option under `tauri > bundle > windows > nsis`.

View File

@ -1,5 +0,0 @@
---
'tauri-bundler': 'patch:bug'
---
On Windows, fix NSIS uninstaller failing to remove Start Menu shortcut if `perMachine` mode is used.

View File

@ -1,5 +0,0 @@
---
'tauri': 'minor:feat'
---
Add `tauri::plugin::Builder::register_uri_scheme_protocol`

View File

@ -1,5 +0,0 @@
---
'tauri-bundler': 'patch:deps'
---
Removed the `bitness` dependency to speed up compile time.

View File

@ -1,5 +0,0 @@
---
"tauri-bundler": minor:feat
---
Allow using a resource map instead of a simple array in `BundleSettings::resources_map`.

View File

@ -1,5 +0,0 @@
---
"tauri-utils": minor:feat
---
Allow specifying resources as a map specifying source and target paths.

View File

@ -0,0 +1,5 @@
---
tauri-runtime-wry: patch:bug
---
Add missing `arboard` feature flag to prevent panics in wayland session.

View File

@ -1,6 +0,0 @@
---
'tauri-cli': 'patch:feat'
'@tauri-apps/cli': 'patch:feat'
---
Support Bun package manager in CLI

View File

@ -1,5 +0,0 @@
---
'tauri-build': 'patch:bug'
---
Correctly copy the WebView2 runtime in development when `webviewInstallMode` is used instead of `webviewFixedRuntimePath`.

View File

@ -0,0 +1,5 @@
---
'tauri-bundler': 'minor:feat'
---
On Windows, NSIS installer now supports `/ARGS` flag to pass arguments to be used when launching the app after installation, only works if `/R` is used.

View File

@ -0,0 +1,5 @@
---
'tauri': 'patch:bug'
---
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.

View File

@ -1,5 +0,0 @@
---
'tauri': 'patch:bug'
---
On macOS, fixed tapping on custom title bar doesn't maximize the window.

View File

@ -0,0 +1,5 @@
---
'tauri': 'minor:enhance'
---
On Windows, retain command line args when relaunching the app after an update. Supports NSIS and WiX (without elevated update task).

View File

@ -1,5 +0,0 @@
---
'tauri-utils': 'patch:bug'
---
Fix `io::read_line` not including the new line character `\n`.

View File

@ -1,5 +0,0 @@
---
'tauri': 'patch:bug'
---
On Windows, fix NSIS installers requiring administrator rights failing to be launched by updater.

View File

@ -1,5 +0,0 @@
---
"tauri": minor:feat
---
Added `UpdateBuilder::endpoints` to add request endpoints at runtime.

View File

@ -1,5 +0,0 @@
---
"tauri": minor:feat
---
Added `UpdateResponse::header` and `UpdateResponse::remove_header` to modify the update download request headers.

View File

@ -1,5 +0,0 @@
---
'tauri': 'patch:bug'
---
Fix updater not following endpoint redirects.

View File

@ -1,5 +0,0 @@
---
"tauri-driver": patch
---
Update locked dependencies to fix a Windows build issue when using them with a recent Rust compiler.

View File

@ -1,5 +0,0 @@
---
"tauri-driver": patch
---
Bump minimum Rust version to `1.60` to be in line with the rest of the Tauri project.

View File

@ -10,8 +10,101 @@ on:
- 1.x
jobs:
msrv-list:
runs-on: ${{ matrix.platform.os }}
strategy:
fail-fast: false
matrix:
platform:
- {
target: x86_64-pc-windows-msvc,
os: windows-latest,
toolchain: '1.61.0'
}
- {
target: x86_64-unknown-linux-gnu,
os: ubuntu-latest,
toolchain: '1.60.0'
}
- {
target: x86_64-apple-darwin,
os: macos-latest,
toolchain: '1.60.0'
}
steps:
- uses: actions/checkout@v4
- name: install rust ${{ matrix.platform.toolchain }}
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.platform.toolchain }}
target: ${{ matrix.platform.target }}
override: true
default: true
- name: install Linux dependencies
if: contains(matrix.platform.target, 'unknown-linux')
run: |
sudo apt-get update
sudo apt-get install -y webkit2gtk-4.0 libayatana-appindicator3-dev
- uses: Swatinem/rust-cache@v2
- name: delete lockfile
run: rm Cargo.lock
- name: Downgrade crates with MSRV conflict
# The --precise flag can only be used once per invocation.
run: |
cargo update -p system-deps:6.2.0 --precise 6.1.1
cargo update -p toml:0.7.8 --precise 0.7.3
cargo update -p toml_edit:0.19.15 --precise 0.19.8
cargo update -p embed-resource --precise 2.3.0
cargo update -p toml_datetime --precise 0.6.1
cargo update -p serde_spanned --precise 0.6.1
cargo update -p winnow --precise 0.4.1
cargo update -p plist --precise 1.5.1
cargo update -p time --precise 0.3.15
cargo update -p ignore --precise 0.4.18
cargo update -p raw-window-handle --precise 0.5.0
cargo update -p cargo_toml:0.15.3 --precise 0.15.2
cargo update -p zbus --precise 3.13.0
cargo update -p zbus_names --precise 2.5.0
cargo update -p colored --precise 2.0.2
cargo update -p tempfile --precise 3.6.0
cargo update -p serde_with:3.4.0 --precise 3.0.0
cargo update -p tokio --precise 1.29.0
cargo update -p flate2 --precise 1.0.26
cargo update -p h2 --precise 0.3.20
cargo update -p reqwest --precise 0.11.18
cargo update -p bstr --precise 1.6.2
cargo update -p cfg-expr:0.15.6 --precise 0.15.4
cargo update -p memchr --precise 2.6.2
cargo update -p async-executor --precise 1.5.1
cargo update -p proptest --precise 1.2.0
cargo update -p regex --precise 1.9.6
cargo update -p bstr --precise 1.6.2
cargo update -p backtrace --precise 0.3.68
cargo update -p blocking --precise 1.4.1
cargo update -p ignore --precise 0.4.18
cargo update -p regex --precise 1.9.6
cargo update -p globset --precise 0.4.13
cargo update -p crossbeam-channel --precise 0.5.8
cargo update -p crossbeam-utils --precise 0.8.16
cargo update -p image --precise 0.24.4
cargo update -p async-process --precise 1.7.0
cargo update -p is-terminal --precise 0.4.7
cargo update -p tar --precise 0.4.39
cargo update -p serde_json --precise 1.0.97
cargo update -p arboard --precise 3.2.1
cargo update -p petgraph --precise 0.6.3
- name: test build
run: cargo check --target ${{ matrix.platform.target }} --features tracing,compression,wry,linux-protocol-headers,isolation,custom-protocol,api-all,cli,updater,system-tray,windows7-compat,http-multipart,test,
run-integration-tests:
runs-on: ${{ matrix.platform }}
needs: msrv-list
strategy:
fail-fast: false
@ -19,7 +112,7 @@ jobs:
platform: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: install stable
@ -66,7 +159,7 @@ jobs:
- run-integration-tests
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v2
@ -115,27 +208,15 @@ jobs:
repository: tauri-apps/tauri-docs
event-type: update-docs
- name: Get `@tauri-apps/cli` release id
id: cliReleaseId
if: |
steps.covector.outputs.successfulPublish == 'true' &&
contains(steps.covector.outputs.packagesPublished, '@tauri-apps/cli')
run: |
echo '${{ steps.covector.outputs }}' > output.json
id=$(jq '.["-tauri-apps-cli-releaseId"]' < output.json)
rm output.json
echo "cliReleaseId=$id" >> "$GITHUB_OUTPUT"
- name: Trigger `@tauri-apps/cli` publishing workflow
if: |
steps.covector.outputs.successfulPublish == 'true' &&
contains(steps.covector.outputs.packagesPublished, '@tauri-apps/cli')
uses: peter-evans/repository-dispatch@v1
with:
token: ${{ secrets.ORG_TAURI_BOT_PAT }}
repository: tauri-apps/tauri
event-type: publish-js-cli
client-payload: '{"releaseId": "${{ steps.cliReleaseId.outputs.cliReleaseId }}" }'
client-payload: >-
{"releaseId": "${{ steps.covector.outputs['-tauri-apps-cli-releaseId'] }}" }
- name: Trigger `tauri-cli` publishing workflow
if: |
@ -143,6 +224,4 @@ jobs:
contains(steps.covector.outputs.packagesPublished, 'tauri-cli')
uses: peter-evans/repository-dispatch@v1
with:
token: ${{ secrets.ORG_TAURI_BOT_PAT }}
repository: tauri-apps/tauri
event-type: publish-clirs

View File

@ -115,27 +115,15 @@ jobs:
repository: tauri-apps/tauri-docs
event-type: update-docs
- name: Get `@tauri-apps/cli` release id
id: cliReleaseId
if: |
steps.covector.outputs.successfulPublish == 'true' &&
contains(steps.covector.outputs.packagesPublished, '@tauri-apps/cli')
run: |
echo '${{ toJSON(steps.covector.outputs) }}' > output.json
id=$(jq '.["-tauri-apps-cli-releaseId"]' < output.json)
rm output.json
echo "cliReleaseId=$id" >> "$GITHUB_OUTPUT"
- name: Trigger `@tauri-apps/cli` publishing workflow
if: |
steps.covector.outputs.successfulPublish == 'true' &&
contains(steps.covector.outputs.packagesPublished, '@tauri-apps/cli')
uses: peter-evans/repository-dispatch@v1
with:
token: ${{ secrets.ORG_TAURI_BOT_PAT }}
repository: tauri-apps/tauri
event-type: publish-js-cli
client-payload: '{"releaseId": "${{ steps.cliReleaseId.outputs.cliReleaseId }}" }'
client-payload: >-
{"releaseId": "${{ steps.covector.outputs['-tauri-apps-cli-releaseId'] }}" }
- name: Trigger `tauri-cli` publishing workflow
if: |
@ -143,6 +131,4 @@ jobs:
contains(steps.covector.outputs.packagesPublished, 'tauri-cli')
uses: peter-evans/repository-dispatch@v1
with:
token: ${{ secrets.ORG_TAURI_BOT_PAT }}
repository: tauri-apps/tauri
event-type: publish-clirs

View File

@ -49,6 +49,9 @@ jobs:
- name: install deps via yarn
working-directory: ./tooling/api/
run: yarn
- name: run ts:check
working-directory: ./tooling/api/
run: yarn ts:check
- name: run lint
working-directory: ./tooling/api/
run: yarn lint

View File

@ -297,14 +297,10 @@ jobs:
- name: List packages
run: ls -R .
shell: bash
- name: Install system dependencies
run: |
apk add openssl-dev musl-dev glib-dev cairo-dev pkgconfig gdk-pixbuf-dev webkit2gtk-dev curl gtk+3.0-dev
- name: Setup and run tests
run: |
yarn tauri --help
ls -la
# TODO: fix this test: https://github.com/tauri-apps/tauri/runs/5145729140?check_suite_focus=true#step:9:704
#- name: Setup and run tests
# run: |
# rustup install stable

View File

@ -50,8 +50,8 @@ jobs:
with:
workspaces: tooling/cli
- name: build CLI
- name: test CLI
uses: actions-rs/cargo@v1
with:
command: build
command: test
args: --manifest-path ./tooling/cli/Cargo.toml

View File

@ -56,7 +56,7 @@ jobs:
key: api-all
}
- {
args: --features compression,wry,linux-protocol-headers,isolation,custom-protocol,api-all,cli,updater,system-tray,windows7-compat,http-multipart,test,
args: --features tracing,compression,wry,linux-protocol-headers,isolation,custom-protocol,api-all,cli,updater,system-tray,windows7-compat,http-multipart,test,
key: all
}
@ -82,28 +82,5 @@ jobs:
workspaces: core -> ../target
save-if: ${{ matrix.features.key == 'all' }}
- name: Downgrade crates with MSRV conflict
# The --precise flag can only be used once per invocation.
run: |
cargo update -p toml:0.7.6 --precise 0.7.3
cargo update -p toml_edit --precise 0.19.8
cargo update -p toml_datetime --precise 0.6.1
cargo update -p serde_spanned --precise 0.6.1
cargo update -p winnow --precise 0.4.1
cargo update -p time --precise 0.3.15
cargo update -p ignore --precise 0.4.18
cargo update -p raw-window-handle --precise 0.5.0
cargo update -p cargo_toml:0.15.3 --precise 0.15.2
cargo update -p zbus --precise 3.13.0
cargo update -p zbus_names --precise 2.5.0
cargo update -p is-terminal --precise 0.4.7
cargo update -p colored --precise 2.0.2
cargo update -p tempfile --precise 3.6.0
cargo update -p serde_with:3.3.0 --precise 3.0.0
cargo update -p tokio --precise 1.29.0
cargo update -p flate2 --precise 1.0.26
cargo update -p h2 --precise 0.3.20
cargo update -p reqwest --precise 0.11.18
- name: test
run: cargo test --target ${{ matrix.platform.target }} ${{ matrix.features.args }}

2
.gitignore vendored
View File

@ -73,7 +73,7 @@ TODO.md
target
# lock for libs
/Cargo.lock
#/Cargo.lock Committed to prevent msrv checks from failing
/tooling/bench/tests/Cargo.lock
/yarn.lock

View File

@ -11,7 +11,7 @@ if [ -z "$(git diff --name-only tooling/api)" ]; then
else
cd tooling/api
yarn format
yarn lint-fix
yarn lint:fix
cd ../..
fi

5
.prettierrc Normal file
View File

@ -0,0 +1,5 @@
{
"singleQuote": true,
"semi": false,
"trailingComma": "none"
}

View File

@ -1,9 +0,0 @@
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
module.exports = {
singleQuote: true,
semi: false,
trailingComma: 'none'
}

5727
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,30 @@
# Changelog
## \[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

View File

@ -1,6 +1,6 @@
[package]
name = "tauri-build"
version = "1.4.0"
version = "1.5.1"
authors = [ "Tauri Programme within The Commons Conservancy" ]
categories = [ "gui", "web-programming" ]
license = "Apache-2.0 OR MIT"
@ -19,15 +19,17 @@ rustdoc-args = [ "--cfg", "doc_cfg" ]
[dependencies]
anyhow = "1"
quote = { version = "1", optional = true }
tauri-codegen = { version = "1.4.0", path = "../tauri-codegen", optional = true }
tauri-utils = { version = "1.4.0", path = "../tauri-utils", features = [ "build", "resources" ] }
tauri-codegen = { version = "1.4.2", path = "../tauri-codegen", optional = true }
tauri-utils = { version = "1.5.2", path = "../tauri-utils", features = [ "build", "resources" ] }
cargo_toml = "0.15"
serde = "1"
serde_json = "1"
heck = "0.4"
json-patch = "1.0"
json-patch = "1.2"
tauri-winres = "0.1"
semver = "1"
walkdir = "2"
dirs-next = "2"
[features]
codegen = [ "tauri-codegen", "quote" ]

View File

@ -4,6 +4,7 @@
#![cfg_attr(doc_cfg, feature(doc_cfg))]
use anyhow::Context;
pub use anyhow::Result;
use cargo_toml::Manifest;
use heck::AsShoutySnakeCase;
@ -80,6 +81,113 @@ fn copy_resources(resources: ResourcePaths<'_>, path: &Path) -> Result<()> {
Ok(())
}
#[cfg(unix)]
fn symlink_dir(src: &Path, dst: &Path) -> std::io::Result<()> {
std::os::unix::fs::symlink(src, dst)
}
/// Makes a symbolic link to a directory.
#[cfg(windows)]
fn symlink_dir(src: &Path, dst: &Path) -> std::io::Result<()> {
std::os::windows::fs::symlink_dir(src, dst)
}
/// Makes a symbolic link to a file.
#[cfg(unix)]
fn symlink_file(src: &Path, dst: &Path) -> std::io::Result<()> {
std::os::unix::fs::symlink(src, dst)
}
/// Makes a symbolic link to a file.
#[cfg(windows)]
fn symlink_file(src: &Path, dst: &Path) -> std::io::Result<()> {
std::os::windows::fs::symlink_file(src, dst)
}
fn copy_dir(from: &Path, to: &Path) -> Result<()> {
for entry in walkdir::WalkDir::new(from) {
let entry = entry?;
debug_assert!(entry.path().starts_with(from));
let rel_path = entry.path().strip_prefix(from)?;
let dest_path = to.join(rel_path);
if entry.file_type().is_symlink() {
let target = std::fs::read_link(entry.path())?;
if entry.path().is_dir() {
symlink_dir(&target, &dest_path)?;
} else {
symlink_file(&target, &dest_path)?;
}
} else if entry.file_type().is_dir() {
std::fs::create_dir(dest_path)?;
} else {
std::fs::copy(entry.path(), dest_path)?;
}
}
Ok(())
}
// Copies the framework under `{src_dir}/{framework}.framework` to `{dest_dir}/{framework}.framework`.
fn copy_framework_from(src_dir: &Path, framework: &str, dest_dir: &Path) -> Result<bool> {
let src_name = format!("{}.framework", framework);
let src_path = src_dir.join(&src_name);
if src_path.exists() {
copy_dir(&src_path, &dest_dir.join(&src_name))?;
Ok(true)
} else {
Ok(false)
}
}
// Copies the macOS application bundle frameworks to the target folder
fn copy_frameworks(dest_dir: &Path, frameworks: &[String]) -> Result<()> {
std::fs::create_dir_all(dest_dir).with_context(|| {
format!(
"Failed to create frameworks output directory at {:?}",
dest_dir
)
})?;
for framework in frameworks.iter() {
if framework.ends_with(".framework") {
let src_path = PathBuf::from(framework);
let src_name = src_path
.file_name()
.expect("Couldn't get framework filename");
let dest_path = dest_dir.join(src_name);
copy_dir(&src_path, &dest_path)?;
continue;
} else if framework.ends_with(".dylib") {
let src_path = PathBuf::from(framework);
if !src_path.exists() {
return Err(anyhow::anyhow!("Library not found: {}", framework));
}
let src_name = src_path.file_name().expect("Couldn't get library filename");
let dest_path = dest_dir.join(src_name);
copy_file(&src_path, &dest_path)?;
continue;
} else if framework.contains('/') {
return Err(anyhow::anyhow!(
"Framework path should have .framework extension: {}",
framework
));
}
if let Some(home_dir) = dirs_next::home_dir() {
if copy_framework_from(&home_dir.join("Library/Frameworks/"), framework, dest_dir)? {
continue;
}
}
if copy_framework_from(&PathBuf::from("/Library/Frameworks/"), framework, dest_dir)?
|| copy_framework_from(
&PathBuf::from("/Network/Library/Frameworks/"),
framework,
dest_dir,
)?
{
continue;
}
}
Ok(())
}
// checks if the given Cargo feature is enabled.
fn has_feature(feature: &str) -> bool {
// when a feature is enabled, Cargo sets the `CARGO_FEATURE_<name` env var to 1
@ -370,13 +478,26 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
}
if target_triple.contains("darwin") {
if let Some(frameworks) = &config.tauri.bundle.macos.frameworks {
if !frameworks.is_empty() {
let frameworks_dir = target_dir.parent().unwrap().join("Frameworks");
let _ = std::fs::remove_dir_all(&frameworks_dir);
// copy frameworks to the root `target` folder (instead of `target/debug` for instance)
// because the rpath is set to `@executable_path/../Frameworks`.
copy_frameworks(&frameworks_dir, frameworks)?;
// If we have frameworks, we need to set the @rpath
// https://github.com/tauri-apps/tauri/issues/7710
println!("cargo:rustc-link-arg=-Wl,-rpath,@executable_path/../Frameworks");
}
}
if let Some(version) = &config.tauri.bundle.macos.minimum_system_version {
println!("cargo:rustc-env=MACOSX_DEPLOYMENT_TARGET={version}");
}
}
if target_triple.contains("windows") {
use anyhow::Context;
use semver::Version;
use tauri_winres::{VersionInfo, WindowsResource};

View File

@ -1,5 +1,17 @@
# Changelog
## \[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

View File

@ -1,6 +1,6 @@
[package]
name = "tauri-codegen"
version = "1.4.0"
version = "1.4.2"
authors = [ "Tauri Programme within The Commons Conservancy" ]
categories = [ "gui", "web-programming" ]
license = "Apache-2.0 OR MIT"
@ -19,16 +19,16 @@ proc-macro2 = "1"
quote = "1"
serde = { version = "1", features = [ "derive" ] }
serde_json = "1"
tauri-utils = { version = "1.4.0", path = "../tauri-utils", features = [ "build" ] }
tauri-utils = { version = "1.5.2", path = "../tauri-utils", features = [ "build" ] }
thiserror = "1"
walkdir = "2"
brotli = { version = "3", optional = true, default-features = false, features = [ "std" ] }
regex = { version = "1.7.1", optional = true }
regex = { version = "1", optional = true }
uuid = { version = "1", features = [ "v4" ] }
semver = "1"
ico = "0.3"
png = "0.17"
json-patch = "1.0"
json-patch = "1.2"
[target."cfg(target_os = \"macos\")".dependencies]
plist = "1"

View File

@ -350,14 +350,11 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
}
}
let out_path = out_dir.join("Info.plist");
info_plist
.to_file_xml(&out_path)
.to_file_xml(out_dir.join("Info.plist"))
.expect("failed to write Info.plist");
let info_plist_path = out_path.display().to_string();
quote!({
tauri::embed_plist::embed_info_plist!(#info_plist_path);
tauri::embed_plist::embed_info_plist!(concat!(std::env!("OUT_DIR"), "/Info.plist"));
})
} else {
quote!(())
@ -473,15 +470,20 @@ fn ico_icon<P: AsRef<Path>>(
let width = entry.width();
let height = entry.height();
let out_path = out_dir.join(path.file_name().unwrap());
let icon_file_name = path.file_name().unwrap();
let out_path = out_dir.join(icon_file_name);
write_if_changed(&out_path, &rgba).map_err(|error| EmbeddedAssetsError::AssetWrite {
path: path.to_owned(),
error,
})?;
let out_path = out_path.display().to_string();
let icon = quote!(Some(#root::Icon::Rgba { rgba: include_bytes!(#out_path).to_vec(), width: #width, height: #height }));
let icon_file_name = icon_file_name.to_str().unwrap();
let icon = quote!(Some(
#root::Icon::Rgba {
rgba: include_bytes!(concat!(std::env!("OUT_DIR"), "/", #icon_file_name)).to_vec(),
width: #width,
height: #height
}));
Ok(icon)
}
@ -497,9 +499,10 @@ fn raw_icon<P: AsRef<Path>>(out_dir: &Path, path: P) -> Result<TokenStream, Embe
error,
})?;
let out_path = out_path.display().to_string();
let icon = quote!(Some(include_bytes!(#out_path).to_vec()));
let icon_path = path.file_name().unwrap().to_str().unwrap().to_string();
let icon = quote!(::std::option::Option::Some(
include_bytes!(concat!(std::env!("OUT_DIR"), "/", #icon_path)).to_vec()
));
Ok(icon)
}
@ -530,15 +533,21 @@ fn png_icon<P: AsRef<Path>>(
let width = reader.info().width;
let height = reader.info().height;
let out_path = out_dir.join(path.file_name().unwrap());
let icon_file_name = path.file_name().unwrap();
let out_path = out_dir.join(icon_file_name);
write_if_changed(&out_path, &buffer).map_err(|error| EmbeddedAssetsError::AssetWrite {
path: path.to_owned(),
error,
})?;
let out_path = out_path.display().to_string();
let icon = quote!(Some(#root::Icon::Rgba { rgba: include_bytes!(#out_path).to_vec(), width: #width, height: #height }));
let icon_file_name = icon_file_name.to_str().unwrap();
let icon = quote!(Some(
#root::Icon::Rgba {
rgba: include_bytes!(concat!(std::env!("OUT_DIR"), "/", #icon_file_name)).to_vec(),
width: #width,
height: #height,
}
));
Ok(icon)
}

View File

@ -11,5 +11,4 @@ tauri-utils = { version = "1.0.0", features = [
schemars = { version = "0.8", features = ["url", "preserve_order"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_with = "1.12"
url = { version = "2.3", features = ["serde"] }

View File

@ -167,6 +167,7 @@
"security": {
"dangerousDisableAssetCspModification": false,
"dangerousRemoteDomainIpcAccess": [],
"dangerousUseHttpScheme": false,
"freezePrototype": false
},
"updater": {
@ -423,6 +424,7 @@
"default": {
"dangerousDisableAssetCspModification": false,
"dangerousRemoteDomainIpcAccess": [],
"dangerousUseHttpScheme": false,
"freezePrototype": false
},
"allOf": [
@ -1318,6 +1320,27 @@
"string",
"null"
]
},
"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`. 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 https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes",
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
@ -2740,6 +2763,11 @@
"items": {
"$ref": "#/definitions/RemoteDomainAccessScope"
}
},
"dangerousUseHttpScheme": {
"description": "Sets whether the custom protocols should use `http://<scheme>.localhost` instead of the default `https://<scheme>.localhost` on Windows.\n\n**WARNING:** Using a `http` scheme will allow mixed content when trying to fetch `http` endpoints and is therefore less secure but will match the behavior of the `<scheme>://localhost` protocols used on macOS and Linux.",
"default": false,
"type": "boolean"
}
},
"additionalProperties": false

View File

@ -1,5 +1,25 @@
# Changelog
## \[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

View File

@ -1,6 +1,6 @@
[package]
name = "tauri-macros"
version = "1.4.0"
version = "1.4.3"
authors = [ "Tauri Programme within The Commons Conservancy" ]
categories = [ "gui", "os", "filesystem", "web-programming" ]
license = "Apache-2.0 OR MIT"
@ -16,12 +16,12 @@ readme = "README.md"
proc-macro = true
[dependencies]
proc-macro2 = "1"
proc-macro2 = { version = "1", features = [ "span-locations" ] }
quote = "1"
syn = { version = "1", features = [ "full" ] }
heck = "0.4"
tauri-codegen = { version = "1.4.0", default-features = false, path = "../tauri-codegen" }
tauri-utils = { version = "1.4.0", path = "../tauri-utils" }
tauri-codegen = { version = "1.4.2", default-features = false, path = "../tauri-codegen" }
tauri-utils = { version = "1.5.2", path = "../tauri-utils" }
[features]
custom-protocol = [ ]
@ -30,3 +30,4 @@ isolation = [ "tauri-codegen/isolation" ]
shell-scope = [ "tauri-codegen/shell-scope" ]
config-json5 = [ "tauri-codegen/config-json5", "tauri-utils/config-json5" ]
config-toml = [ "tauri-codegen/config-toml", "tauri-utils/config-toml" ]
tracing = [ ]

View File

@ -161,21 +161,51 @@ pub fn wrapper(attributes: TokenStream, item: TokenStream) -> TokenStream {
}
// body to the command wrapper or a `compile_error!` of an error occurred while parsing it.
let body = syn::parse::<WrapperAttributes>(attributes)
let (body, attributes) = syn::parse::<WrapperAttributes>(attributes)
.map(|mut attrs| {
if function.sig.asyncness.is_some() {
attrs.execution_context = ExecutionContext::Async;
}
attrs
})
.and_then(|attrs| match attrs.execution_context {
ExecutionContext::Async => body_async(&function, &invoke, attrs.argument_case),
ExecutionContext::Blocking => body_blocking(&function, &invoke, attrs.argument_case),
.and_then(|attrs| {
let body = match attrs.execution_context {
ExecutionContext::Async => body_async(&function, &invoke, attrs.argument_case),
ExecutionContext::Blocking => body_blocking(&function, &invoke, attrs.argument_case),
};
body.map(|b| (b, Some(attrs)))
})
.unwrap_or_else(syn::Error::into_compile_error);
.unwrap_or_else(|e| (syn::Error::into_compile_error(e), None));
let Invoke { message, resolver } = invoke;
let kind = match attributes.as_ref().map(|a| &a.execution_context) {
Some(ExecutionContext::Async) if function.sig.asyncness.is_none() => "sync_threadpool",
Some(ExecutionContext::Async) => "async",
Some(ExecutionContext::Blocking) => "sync",
_ => "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!()
};
// Rely on rust 2018 edition to allow importing a macro from a path.
quote!(
#async_command_check
@ -193,6 +223,8 @@ pub fn wrapper(attributes: TokenStream, item: TokenStream) -> TokenStream {
#[allow(unused_variables)]
let ::tauri::Invoke { message: #message, resolver: #resolver } = $invoke;
#maybe_span
#body
}};
}
@ -212,6 +244,20 @@ pub fn wrapper(attributes: TokenStream, item: TokenStream) -> TokenStream {
fn body_async(function: &ItemFn, invoke: &Invoke, case: ArgumentCase) -> syn::Result<TokenStream2> {
let Invoke { message, resolver } = invoke;
parse_args(function, message, case).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));
}
#[cfg(not(feature = "tracing"))]
quote! {
#resolver.respond_async_serialized(async move {
let result = $path(#(#args?),*);
@ -241,7 +287,14 @@ fn body_blocking(
Err(err) => return #resolver.invoke_error(err),
});
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);

View File

@ -1,5 +1,38 @@
# Changelog
## \[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://<scheme>.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

View File

@ -1,6 +1,6 @@
[package]
name = "tauri-runtime-wry"
version = "0.14.0"
version = "0.14.3"
authors = [ "Tauri Programme within The Commons Conservancy" ]
categories = [ "gui", "web-programming" ]
license = "Apache-2.0 OR MIT"
@ -13,12 +13,14 @@ exclude = [ "CHANGELOG.md", "/target" ]
readme = "README.md"
[dependencies]
wry = { version = "0.24.1", default-features = false, features = [ "file-drop", "protocol" ] }
tauri-runtime = { version = "0.14.0", path = "../tauri-runtime" }
tauri-utils = { version = "1.4.0", path = "../tauri-utils" }
wry = { version = "0.24.6", default-features = false, features = [ "file-drop", "protocol" ] }
tauri-runtime = { version = "0.14.2", path = "../tauri-runtime" }
tauri-utils = { version = "1.5.2", path = "../tauri-utils" }
uuid = { version = "1", features = [ "v4" ] }
rand = "0.8"
raw-window-handle = "0.5"
tracing = { version = "0.1", optional = true }
arboard = { version = "3", optional = true }
[target."cfg(windows)".dependencies]
webview2-com = "0.19.1"
@ -46,5 +48,6 @@ macos-private-api = [
]
objc-exception = [ "wry/objc-exception" ]
global-shortcut = [ "tauri-runtime/global-shortcut" ]
clipboard = [ "tauri-runtime/clipboard" ]
clipboard = [ "tauri-runtime/clipboard", "arboard/wayland-data-control" ]
linux-headers = [ "wry/linux-headers", "webkit2gtk/v2_36" ]
tracing = [ "dep:tracing", "wry/tracing" ]

View File

@ -4,59 +4,36 @@
//! Clipboard implementation.
use crate::{getter, Context, Message};
use std::sync::{
mpsc::{channel, Sender},
Arc, Mutex,
use std::{
fmt,
sync::{Arc, Mutex},
};
use tauri_runtime::{ClipboardManager, Result, UserEvent};
pub use wry::application::clipboard::Clipboard;
pub use arboard::Clipboard;
use tauri_runtime::{ClipboardManager, Result};
#[derive(Debug, Clone)]
pub enum ClipboardMessage {
WriteText(String, Sender<()>),
ReadText(Sender<Option<String>>),
#[derive(Clone)]
pub struct ClipboardManagerWrapper {
pub clipboard: Arc<Mutex<Clipboard>>,
}
#[derive(Debug, Clone)]
pub struct ClipboardManagerWrapper<T: UserEvent> {
pub context: Context<T>,
impl fmt::Debug for ClipboardManagerWrapper {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ClipboardManagerWrapper").finish()
}
}
// SAFETY: this is safe since the `Context` usage is guarded on `send_user_message`.
#[allow(clippy::non_send_fields_in_send_ty)]
unsafe impl<T: UserEvent> Sync for ClipboardManagerWrapper<T> {}
impl<T: UserEvent> ClipboardManager for ClipboardManagerWrapper<T> {
impl ClipboardManager for ClipboardManagerWrapper {
fn read_text(&self) -> Result<Option<String>> {
let (tx, rx) = channel();
getter!(self, rx, Message::Clipboard(ClipboardMessage::ReadText(tx)))
Ok(self.clipboard.lock().unwrap().get_text().ok())
}
fn write_text<V: Into<String>>(&mut self, text: V) -> Result<()> {
let (tx, rx) = channel();
getter!(
self,
rx,
Message::Clipboard(ClipboardMessage::WriteText(text.into(), tx))
)?;
Ok(())
}
}
pub fn handle_clipboard_message(
message: ClipboardMessage,
clipboard_manager: &Arc<Mutex<Clipboard>>,
) {
match message {
ClipboardMessage::WriteText(text, tx) => {
clipboard_manager.lock().unwrap().write_text(text);
tx.send(()).unwrap();
}
ClipboardMessage::ReadText(tx) => tx
.send(clipboard_manager.lock().unwrap().read_text())
.unwrap(),
self
.clipboard
.lock()
.unwrap()
.set_text(text.into())
.map_err(|e| crate::Error::Clipboard(Box::new(e)))
}
}

View File

@ -8,6 +8,7 @@ use std::{
collections::HashMap,
error::Error as StdError,
fmt,
rc::Rc,
sync::{
mpsc::{channel, Sender},
Arc, Mutex,
@ -138,7 +139,7 @@ impl<T: UserEvent> GlobalShortcutManager for GlobalShortcutManagerHandle<T> {
pub fn handle_global_shortcut_message(
message: GlobalShortcutMessage,
global_shortcut_manager: &Arc<Mutex<WryShortcutManager>>,
global_shortcut_manager: &Rc<Mutex<WryShortcutManager>>,
) {
match message {
GlobalShortcutMessage::IsRegistered(accelerator, tx) => tx

View File

@ -175,8 +175,6 @@ pub(crate) fn send_user_message<T: UserEvent>(
webview_id_map: context.webview_id_map.clone(),
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager: context.main_thread.global_shortcut_manager.clone(),
#[cfg(feature = "clipboard")]
clipboard_manager: context.main_thread.clipboard_manager.clone(),
windows: context.main_thread.windows.clone(),
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager: context.main_thread.system_tray_manager.clone(),
@ -244,17 +242,55 @@ impl<T: UserEvent> Context<T> {
}
}
#[cfg(feature = "tracing")]
#[derive(Debug, Clone, Default)]
pub struct ActiveTraceSpanStore(Rc<RefCell<Vec<ActiveTracingSpan>>>);
#[cfg(feature = "tracing")]
impl ActiveTraceSpanStore {
pub fn remove_window_draw(&self, window_id: WindowId) {
let mut store = self.0.borrow_mut();
if let Some(index) = store
.iter()
.position(|t| matches!(t, ActiveTracingSpan::WindowDraw { id, span: _ } if id == &window_id))
{
store.remove(index);
}
}
}
#[cfg(feature = "tracing")]
#[derive(Debug)]
pub enum ActiveTracingSpan {
WindowDraw {
id: WindowId,
span: tracing::span::EnteredSpan,
},
}
#[derive(Debug)]
pub struct WindowsStore(RefCell<HashMap<WebviewId, WindowWrapper>>);
// 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<T: UserEvent> {
pub window_target: EventLoopWindowTarget<Message<T>>,
pub web_context: WebContextStore,
#[cfg(all(desktop, feature = "global-shortcut"))]
pub global_shortcut_manager: Arc<Mutex<WryShortcutManager>>,
#[cfg(feature = "clipboard")]
pub clipboard_manager: Arc<Mutex<Clipboard>>,
pub windows: Rc<RefCell<HashMap<WebviewId, WindowWrapper>>>,
pub global_shortcut_manager: Rc<Mutex<WryShortcutManager>>,
// changing this to an Rc will cause frequent app crashes.
pub windows: Arc<WindowsStore>,
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager: SystemTrayManager,
#[cfg(feature = "tracing")]
pub active_tracing_spans: ActiveTraceSpanStore,
}
// SAFETY: we ensure this type is only used on the main thread.
@ -1135,7 +1171,10 @@ pub enum WindowMessage {
#[derive(Debug, Clone)]
pub enum WebviewMessage {
#[cfg(not(feature = "tracing"))]
EvaluateScript(String),
#[cfg(feature = "tracing")]
EvaluateScript(String, Sender<()>, tracing::Span),
#[allow(dead_code)]
WebviewEvent(WebviewEvent),
Print,
@ -1182,8 +1221,6 @@ pub enum Message<T: 'static> {
),
#[cfg(all(desktop, feature = "global-shortcut"))]
GlobalShortcut(GlobalShortcutMessage),
#[cfg(feature = "clipboard")]
Clipboard(ClipboardMessage),
UserEvent(T),
}
@ -1195,8 +1232,6 @@ impl<T: UserEvent> Clone for Message<T> {
Self::Tray(i, m) => Self::Tray(*i, m.clone()),
#[cfg(all(desktop, feature = "global-shortcut"))]
Self::GlobalShortcut(m) => Self::GlobalShortcut(m.clone()),
#[cfg(feature = "clipboard")]
Self::Clipboard(m) => Self::Clipboard(m.clone()),
Self::UserEvent(t) => Self::UserEvent(t.clone()),
_ => unimplemented!(),
}
@ -1651,6 +1686,21 @@ impl<T: UserEvent> Dispatch<T> for WryDispatcher<T> {
)
}
#[cfg(feature = "tracing")]
fn eval_script<S: Into<String>>(&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,
WebviewMessage::EvaluateScript(script.into(), tx, tracing::Span::current()),
)
)
}
#[cfg(not(feature = "tracing"))]
fn eval_script<S: Into<String>>(&self, script: S) -> Result<()> {
send_user_message(
&self.context,
@ -1783,7 +1833,7 @@ pub struct Wry<T: UserEvent> {
global_shortcut_manager_handle: GlobalShortcutManagerHandle<T>,
#[cfg(feature = "clipboard")]
clipboard_manager_handle: ClipboardManagerWrapper<T>,
clipboard_manager_handle: ClipboardManagerWrapper,
event_loop: EventLoop<Message<T>>,
}
@ -1814,11 +1864,7 @@ impl<T: UserEvent> fmt::Debug for Wry<T> {
);
#[cfg(feature = "clipboard")]
d.field(
"clipboard_manager",
&self.context.main_thread.clipboard_manager,
)
.field("clipboard_manager_handle", &self.clipboard_manager_handle);
d.field("clipboard_manager_handle", &self.clipboard_manager_handle);
d.finish()
}
@ -1937,12 +1983,9 @@ impl<T: UserEvent> Wry<T> {
let web_context = WebContextStore::default();
#[cfg(all(desktop, feature = "global-shortcut"))]
let global_shortcut_manager = Arc::new(Mutex::new(WryShortcutManager::new(&event_loop)));
let global_shortcut_manager = Rc::new(Mutex::new(WryShortcutManager::new(&event_loop)));
#[cfg(feature = "clipboard")]
let clipboard_manager = Arc::new(Mutex::new(Clipboard::new()));
let windows = Rc::new(RefCell::new(HashMap::default()));
let windows = Arc::new(WindowsStore(RefCell::new(HashMap::default())));
let webview_id_map = WebviewIdStore::default();
#[cfg(all(desktop, feature = "system-tray"))]
@ -1957,11 +2000,11 @@ impl<T: UserEvent> Wry<T> {
web_context,
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager,
#[cfg(feature = "clipboard")]
clipboard_manager,
windows,
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager,
#[cfg(feature = "tracing")]
active_tracing_spans: Default::default(),
},
};
@ -1975,7 +2018,7 @@ impl<T: UserEvent> Wry<T> {
#[cfg(feature = "clipboard")]
#[allow(clippy::redundant_clone)]
let clipboard_manager_handle = ClipboardManagerWrapper {
context: context.clone(),
clipboard: Arc::new(Mutex::new(Clipboard::new().unwrap())),
};
Ok(Self {
@ -2008,7 +2051,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
type GlobalShortcutManager = GlobalShortcutManagerHandle<T>;
#[cfg(feature = "clipboard")]
type ClipboardManager = ClipboardManagerWrapper<T>;
type ClipboardManager = ClipboardManagerWrapper;
#[cfg(all(desktop, feature = "system-tray"))]
type TrayHandler = SystemTrayHandle<T>;
@ -2073,6 +2116,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
.context
.main_thread
.windows
.0
.borrow_mut()
.insert(window_id, webview);
@ -2165,13 +2209,14 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
#[cfg(all(desktop, feature = "system-tray"))]
let system_tray_manager = self.context.main_thread.system_tray_manager.clone();
#[cfg(feature = "tracing")]
let active_tracing_spans = self.context.main_thread.active_tracing_spans.clone();
#[cfg(all(desktop, feature = "global-shortcut"))]
let global_shortcut_manager = self.context.main_thread.global_shortcut_manager.clone();
#[cfg(all(desktop, feature = "global-shortcut"))]
let global_shortcut_manager_handle = self.global_shortcut_manager_handle.clone();
#[cfg(feature = "clipboard")]
let clipboard_manager = self.context.main_thread.clipboard_manager.clone();
let mut iteration = RunIteration::default();
let proxy = self.event_loop.create_proxy();
@ -2198,10 +2243,10 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
global_shortcut_manager: global_shortcut_manager.clone(),
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager_handle: &global_shortcut_manager_handle,
#[cfg(feature = "clipboard")]
clipboard_manager: clipboard_manager.clone(),
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager: system_tray_manager.clone(),
#[cfg(feature = "tracing")]
active_tracing_spans: active_tracing_spans.clone(),
},
web_context,
);
@ -2222,10 +2267,10 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
global_shortcut_manager: global_shortcut_manager.clone(),
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager_handle: &global_shortcut_manager_handle,
#[cfg(feature = "clipboard")]
clipboard_manager: clipboard_manager.clone(),
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager: system_tray_manager.clone(),
#[cfg(feature = "tracing")]
active_tracing_spans: active_tracing_spans.clone(),
},
web_context,
);
@ -2240,6 +2285,9 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
let web_context = self.context.main_thread.web_context;
let mut plugins = self.plugins;
#[cfg(feature = "tracing")]
let active_tracing_spans = self.context.main_thread.active_tracing_spans.clone();
#[cfg(all(desktop, feature = "system-tray"))]
let system_tray_manager = self.context.main_thread.system_tray_manager;
@ -2248,9 +2296,6 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
#[cfg(all(desktop, feature = "global-shortcut"))]
let global_shortcut_manager_handle = self.global_shortcut_manager_handle.clone();
#[cfg(feature = "clipboard")]
let clipboard_manager = self.context.main_thread.clipboard_manager.clone();
let proxy = self.event_loop.create_proxy();
self.event_loop.run(move |event, event_loop, control_flow| {
@ -2268,10 +2313,10 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
global_shortcut_manager: global_shortcut_manager.clone(),
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager_handle: &global_shortcut_manager_handle,
#[cfg(feature = "clipboard")]
clipboard_manager: clipboard_manager.clone(),
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager: system_tray_manager.clone(),
#[cfg(feature = "tracing")]
active_tracing_spans: active_tracing_spans.clone(),
},
&web_context,
);
@ -2291,10 +2336,10 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
global_shortcut_manager: global_shortcut_manager.clone(),
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager_handle: &global_shortcut_manager_handle,
#[cfg(feature = "clipboard")]
clipboard_manager: clipboard_manager.clone(),
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager: system_tray_manager.clone(),
#[cfg(feature = "tracing")]
active_tracing_spans: active_tracing_spans.clone(),
},
&web_context,
);
@ -2305,24 +2350,22 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
pub struct EventLoopIterationContext<'a, T: UserEvent> {
pub callback: &'a mut (dyn FnMut(RunEvent<T>) + 'static),
pub webview_id_map: WebviewIdStore,
pub windows: Rc<RefCell<HashMap<WebviewId, WindowWrapper>>>,
pub windows: Arc<WindowsStore>,
#[cfg(all(desktop, feature = "global-shortcut"))]
pub global_shortcut_manager: Arc<Mutex<WryShortcutManager>>,
pub global_shortcut_manager: Rc<Mutex<WryShortcutManager>>,
#[cfg(all(desktop, feature = "global-shortcut"))]
pub global_shortcut_manager_handle: &'a GlobalShortcutManagerHandle<T>,
#[cfg(feature = "clipboard")]
pub clipboard_manager: Arc<Mutex<Clipboard>>,
#[cfg(all(desktop, feature = "system-tray"))]
pub system_tray_manager: SystemTrayManager,
#[cfg(feature = "tracing")]
pub active_tracing_spans: ActiveTraceSpanStore,
}
struct UserMessageContext {
windows: Rc<RefCell<HashMap<WebviewId, WindowWrapper>>>,
windows: Arc<WindowsStore>,
webview_id_map: WebviewIdStore,
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager: Arc<Mutex<WryShortcutManager>>,
#[cfg(feature = "clipboard")]
clipboard_manager: Arc<Mutex<Clipboard>>,
global_shortcut_manager: Rc<Mutex<WryShortcutManager>>,
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager: SystemTrayManager,
}
@ -2337,8 +2380,6 @@ fn handle_user_message<T: UserEvent>(
webview_id_map,
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager,
#[cfg(feature = "clipboard")]
clipboard_manager,
windows,
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager,
@ -2356,7 +2397,12 @@ fn handle_user_message<T: UserEvent>(
},
Message::Window(id, window_message) => {
if let WindowMessage::UpdateMenuItem(item_id, update) = window_message {
if let Some(menu_items) = windows.borrow_mut().get_mut(&id).map(|w| &mut w.menu_items) {
if let Some(menu_items) = windows
.0
.borrow_mut()
.get_mut(&id)
.map(|w| &mut w.menu_items)
{
if let Some(menu_items) = menu_items.as_mut() {
let item = menu_items.get_mut(&item_id).expect("menu item not found");
match update {
@ -2371,7 +2417,7 @@ fn handle_user_message<T: UserEvent>(
}
}
} else {
let w = windows.borrow().get(&id).map(|w| {
let w = windows.0.borrow().get(&id).map(|w| {
(
w.inner.clone(),
w.window_event_listeners.clone(),
@ -2590,9 +2636,22 @@ fn handle_user_message<T: UserEvent>(
}
}
Message::Webview(id, webview_message) => match webview_message {
#[cfg(feature = "tracing")]
WebviewMessage::EvaluateScript(script, tx, span) => {
let _span = span.entered();
if let Some(WindowHandle::Webview { inner: webview, .. }) =
windows.0.borrow().get(&id).and_then(|w| w.inner.as_ref())
{
if let Err(e) = webview.evaluate_script(&script) {
debug_eprintln!("{}", e);
}
}
tx.send(()).unwrap();
}
#[cfg(not(feature = "tracing"))]
WebviewMessage::EvaluateScript(script) => {
if let Some(WindowHandle::Webview { inner: webview, .. }) =
windows.borrow().get(&id).and_then(|w| w.inner.as_ref())
windows.0.borrow().get(&id).and_then(|w| w.inner.as_ref())
{
if let Err(e) = webview.evaluate_script(&script) {
debug_eprintln!("{}", e);
@ -2601,7 +2660,7 @@ fn handle_user_message<T: UserEvent>(
}
WebviewMessage::Print => {
if let Some(WindowHandle::Webview { inner: webview, .. }) =
windows.borrow().get(&id).and_then(|w| w.inner.as_ref())
windows.0.borrow().get(&id).and_then(|w| w.inner.as_ref())
{
let _ = webview.print();
}
@ -2610,7 +2669,7 @@ fn handle_user_message<T: UserEvent>(
},
Message::CreateWebview(window_id, handler) => match handler(event_loop, web_context) {
Ok(webview) => {
windows.borrow_mut().insert(window_id, webview);
windows.0.borrow_mut().insert(window_id, webview);
}
Err(e) => {
debug_eprintln!("{}", e);
@ -2623,7 +2682,7 @@ fn handle_user_message<T: UserEvent>(
let w = Arc::new(window);
windows.borrow_mut().insert(
windows.0.borrow_mut().insert(
window_id,
WindowWrapper {
label,
@ -2728,13 +2787,11 @@ fn handle_user_message<T: UserEvent>(
Message::GlobalShortcut(message) => {
handle_global_shortcut_message(message, &global_shortcut_manager)
}
#[cfg(feature = "clipboard")]
Message::Clipboard(message) => handle_clipboard_message(message, &clipboard_manager),
Message::UserEvent(_) => (),
}
let it = RunIteration {
window_count: windows.borrow().len(),
window_count: windows.0.borrow().len(),
};
it
}
@ -2754,10 +2811,10 @@ fn handle_event_loop<T: UserEvent>(
global_shortcut_manager,
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager_handle,
#[cfg(feature = "clipboard")]
clipboard_manager,
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager,
#[cfg(feature = "tracing")]
active_tracing_spans,
} = context;
if *control_flow != ControlFlow::Exit {
*control_flow = ControlFlow::Wait;
@ -2780,6 +2837,11 @@ fn handle_event_loop<T: UserEvent>(
callback(RunEvent::Exit);
}
#[cfg(feature = "tracing")]
Event::RedrawRequested(id) => {
active_tracing_spans.remove_window_draw(id);
}
#[cfg(all(desktop, feature = "global-shortcut"))]
Event::GlobalShortcutEvent(accelerator_id) => {
for (id, handler) in &*global_shortcut_manager_handle.listeners.lock().unwrap() {
@ -2817,6 +2879,7 @@ fn handle_event_loop<T: UserEvent>(
*webview_id_map.0.lock().unwrap().values().next().unwrap()
};
windows
.0
.borrow()
.get(&window_id)
.unwrap()
@ -2902,7 +2965,7 @@ fn handle_event_loop<T: UserEvent>(
}
Event::UserEvent(Message::Webview(id, WebviewMessage::WebviewEvent(event))) => {
if let Some(event) = WindowEventWrapper::from(&event).0 {
let windows = windows.borrow();
let windows = windows.0.borrow();
let window = windows.get(&id);
if let Some(window) = window {
callback(RunEvent::WindowEvent {
@ -2923,7 +2986,7 @@ fn handle_event_loop<T: UserEvent>(
} => {
if let Some(window_id) = webview_id_map.get(&window_id) {
{
let windows_ref = windows.borrow();
let windows_ref = windows.0.borrow();
if let Some(window) = windows_ref.get(&window_id) {
if let Some(event) = WindowEventWrapper::parse(&window.inner, &event).0 {
let label = window.label.clone();
@ -2947,7 +3010,7 @@ fn handle_event_loop<T: UserEvent>(
match event {
#[cfg(windows)]
WryWindowEvent::ThemeChanged(theme) => {
if let Some(window) = windows.borrow().get(&window_id) {
if let Some(window) = windows.0.borrow().get(&window_id) {
if let Some(WindowHandle::Webview { inner, .. }) = &window.inner {
let theme = match theme {
WryTheme::Dark => wry::webview::Theme::Dark,
@ -2962,9 +3025,9 @@ fn handle_event_loop<T: UserEvent>(
on_close_requested(callback, window_id, windows.clone());
}
WryWindowEvent::Destroyed => {
let removed = windows.borrow_mut().remove(&window_id).is_some();
let removed = windows.0.borrow_mut().remove(&window_id).is_some();
if removed {
let is_empty = windows.borrow().is_empty();
let is_empty = windows.0.borrow().is_empty();
if is_empty {
let (tx, rx) = channel();
callback(RunEvent::ExitRequested { tx });
@ -2995,8 +3058,6 @@ fn handle_event_loop<T: UserEvent>(
webview_id_map,
#[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager,
#[cfg(feature = "clipboard")]
clipboard_manager,
windows,
#[cfg(all(desktop, feature = "system-tray"))]
system_tray_manager,
@ -3009,7 +3070,7 @@ fn handle_event_loop<T: UserEvent>(
}
let it = RunIteration {
window_count: windows.borrow().len(),
window_count: windows.0.borrow().len(),
};
it
}
@ -3017,10 +3078,10 @@ fn handle_event_loop<T: UserEvent>(
fn on_close_requested<'a, T: UserEvent>(
callback: &'a mut (dyn FnMut(RunEvent<T>) + 'static),
window_id: WebviewId,
windows: Rc<RefCell<HashMap<WebviewId, WindowWrapper>>>,
windows: Arc<WindowsStore>,
) {
let (tx, rx) = channel();
let windows_ref = windows.borrow();
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();
@ -3045,8 +3106,8 @@ fn on_close_requested<'a, T: UserEvent>(
}
}
fn on_window_close(window_id: WebviewId, windows: Rc<RefCell<HashMap<WebviewId, WindowWrapper>>>) {
if let Some(window_wrapper) = windows.borrow_mut().get_mut(&window_id) {
fn on_window_close(window_id: WebviewId, windows: Arc<WindowsStore>) {
if let Some(window_wrapper) = windows.0.borrow_mut().get_mut(&window_id) {
window_wrapper.inner = None;
}
}
@ -3123,6 +3184,14 @@ fn create_webview<T: UserEvent>(
#[cfg(windows)]
let proxy = context.proxy.clone();
#[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)]
@ -3154,8 +3223,24 @@ fn create_webview<T: UserEvent>(
} else {
None
};
let focused = window_builder.inner.window.focused;
let window = window_builder.inner.build(event_loop).unwrap();
#[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,
});
}
webview_id_map.insert(window.id(), window_id);
if window_builder.center {
@ -3163,6 +3248,7 @@ fn create_webview<T: UserEvent>(
}
let mut webview_builder = WebViewBuilder::new(window)
.map_err(|e| Error::CreateWebview(Box::new(e)))?
.with_focused(focused)
.with_url(&url)
.unwrap() // safe to unwrap because we validate the URL beforehand
.with_transparent(is_window_transparent)
@ -3194,6 +3280,11 @@ fn create_webview<T: UserEvent>(
});
}
#[cfg(windows)]
{
webview_builder = webview_builder.with_https_scheme(!pending.http_scheme);
}
if let Some(handler) = ipc_handler {
webview_builder = webview_builder.with_ipc_handler(create_ipc_handler(
context,

View File

@ -3,10 +3,7 @@
// SPDX-License-Identifier: MIT
pub use tauri_runtime::{
menu::{
Menu, MenuEntry, MenuItem, MenuUpdate, Submenu, SystemTrayMenu, SystemTrayMenuEntry,
SystemTrayMenuItem, TrayHandle,
},
menu::{MenuUpdate, SystemTrayMenu, SystemTrayMenuEntry, SystemTrayMenuItem, TrayHandle},
Icon, SystemTrayEvent,
};
use wry::application::event_loop::EventLoopWindowTarget;

View File

@ -1,5 +1,21 @@
# Changelog
## \[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://<scheme>.localhost/` for custom protocols on Windows.
### Dependencies
- Upgraded to `tauri-utils@1.5.0`
## \[0.14.0]
### New Features

View File

@ -1,6 +1,6 @@
[package]
name = "tauri-runtime"
version = "0.14.0"
version = "0.14.2"
authors = [ "Tauri Programme within The Commons Conservancy" ]
categories = [ "gui", "web-programming" ]
license = "Apache-2.0 OR MIT"
@ -26,7 +26,7 @@ targets = [
serde = { version = "1.0", features = [ "derive" ] }
serde_json = "1.0"
thiserror = "1.0"
tauri-utils = { version = "1.4.0", path = "../tauri-utils" }
tauri-utils = { version = "1.5.2", path = "../tauri-utils" }
uuid = { version = "1", features = [ "v4" ] }
http = "0.2.4"
http-range = "0.1.4"

View File

@ -252,6 +252,9 @@ pub enum Error {
#[cfg(all(desktop, feature = "global-shortcut"))]
#[error(transparent)]
GlobalShortcut(Box<dyn std::error::Error + Send + Sync>),
#[cfg(all(desktop, feature = "clipboard"))]
#[error(transparent)]
Clipboard(Box<dyn std::error::Error + Send + Sync>),
#[error("Invalid header name: {0}")]
InvalidHeaderName(#[from] InvalidHeaderName),
#[error("Invalid header value: {0}")]

View File

@ -335,6 +335,12 @@ impl Menu {
}
/// Adds the custom menu item to the menu.
///
/// ## Platform-spcific:
///
/// - **macOS:** Only [`Submenu`] can be added to the menu
///
/// [`Submenu`]: crate::Submenu
#[must_use]
pub fn add_item(mut self, item: CustomMenuItem) -> Self {
self.items.push(MenuEntry::CustomItem(item));

View File

@ -224,6 +224,9 @@ pub struct PendingWindow<T: UserEvent, R: Runtime<T>> {
pub uri_scheme_protocols: HashMap<String, Box<UriSchemeProtocol>>,
// Whether custom protocols on windows should use http://<scheme>.localhost/ instead of https://<scheme>.localhost/
pub http_scheme: bool,
/// How to handle IPC calls on the webview window.
pub ipc_handler: Option<WebviewIpcHandler<T, R>>,
@ -281,6 +284,7 @@ impl<T: UserEvent, R: Runtime<T>> PendingWindow<T, R> {
navigation_handler: Default::default(),
web_resource_request_handler: Default::default(),
url: "tauri://localhost".to_string(),
http_scheme: false,
})
}
}
@ -312,6 +316,7 @@ impl<T: UserEvent, R: Runtime<T>> PendingWindow<T, R> {
navigation_handler: Default::default(),
web_resource_request_handler: Default::default(),
url: "tauri://localhost".to_string(),
http_scheme: false,
})
}
}

View File

@ -1,5 +1,35 @@
# Changelog
## \[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://<scheme>.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

View File

@ -1,6 +1,6 @@
[package]
name = "tauri-utils"
version = "1.4.0"
version = "1.5.2"
authors = [ "Tauri Programme within The Commons Conservancy" ]
license = "Apache-2.0 OR MIT"
homepage = "https://tauri.app"
@ -15,7 +15,7 @@ readme = "README.md"
serde = { version = "1", features = [ "derive" ] }
serde_json = "1"
thiserror = "1"
phf = { version = "0.10", features = [ "macros" ] }
phf = { version = "0.11", features = [ "macros" ] }
brotli = { version = "3", optional = true, default-features = false, features = [ "std" ] }
url = { version = "2", features = [ "serde" ] }
html5ever = "0.26"
@ -27,29 +27,23 @@ serde_with = "3"
aes-gcm = { version = "0.10", optional = true }
getrandom = { version = "0.2", optional = true, features = [ "std" ] }
serialize-to-javascript = { version = "=0.1.1", optional = true }
ctor = "0.1"
ctor = "0.2"
json5 = { version = "0.4", optional = true }
toml = { version = "0.5", optional = true }
json-patch = "1.0"
toml = { version = "0.7", optional = true }
json-patch = "1.2"
glob = { version = "0.3", optional = true }
walkdir = { version = "2", optional = true }
memchr = "2"
semver = "1"
infer = "0.12"
infer = "0.13"
dunce = "1"
log = "0.4.20"
[target."cfg(target_os = \"linux\")".dependencies]
heck = "0.4"
[target."cfg(windows)".dependencies.windows]
version = "0.39.0"
features = [
"implement",
"Win32_Foundation",
"Win32_System_Com",
"Win32_System_LibraryLoader",
"Win32_System_SystemInformation"
]
[target."cfg(windows)".dependencies]
windows-version = "0.1"
[features]
build = [ "proc-macro2", "quote" ]

View File

@ -109,6 +109,9 @@ pub trait Assets: Send + Sync + 'static {
/// Get the content of the passed [`AssetKey`].
fn get(&self, key: &AssetKey) -> Option<Cow<'_, [u8]>>;
/// Iterator for the assets.
fn iter(&self) -> Box<dyn Iterator<Item = (&&str, &&[u8])> + '_>;
/// Gets the hashes for the CSP tag of the HTML on the given path.
fn csp_hashes(&self, html_path: &AssetKey) -> Box<dyn Iterator<Item = CspHash<'_>> + '_>;
}
@ -163,6 +166,10 @@ impl Assets for EmbeddedAssets {
.map(|a| Cow::Owned(a.to_vec()))
}
fn iter(&self) -> Box<dyn Iterator<Item = (&&str, &&[u8])> + '_> {
Box::new(self.assets.into_iter())
}
fn csp_hashes(&self, html_path: &AssetKey) -> Box<dyn Iterator<Item = CspHash<'_>> + '_> {
Box::new(
self

View File

@ -280,6 +280,14 @@ pub struct DebConfig {
///
/// Available variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.
pub desktop_template: Option<PathBuf>,
/// Define the section in Debian Control file. See : https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections
pub section: Option<String>,
/// Change the priority of the Debian Package. By default, it is set to `optional`.
/// Recognized Priorities as of now are : `required`, `important`, `standard`, `optional`, `extra`
pub priority: Option<String>,
/// Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See
/// https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes
pub changelog: Option<PathBuf>,
}
fn de_minimum_system_version<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
@ -1326,6 +1334,11 @@ pub struct SecurityConfig {
/// vulnerable to dangerous Tauri command related attacks otherwise.
#[serde(default, alias = "dangerous-remote-domain-ipc-access")]
pub dangerous_remote_domain_ipc_access: Vec<RemoteDomainAccessScope>,
/// Sets whether the custom protocols should use `http://<scheme>.localhost` instead of the default `https://<scheme>.localhost` on Windows.
///
/// **WARNING:** Using a `http` scheme will allow mixed content when trying to fetch `http` endpoints and is therefore less secure but will match the behavior of the `<scheme>://localhost` protocols used on macOS and Linux.
#[serde(default, alias = "dangerous-use-http-scheme")]
pub dangerous_use_http_scheme: bool,
}
/// Defines an allowlist type.
@ -2573,6 +2586,9 @@ impl WindowsUpdateInstallMode {
}
/// Returns the associated nsis arguments.
///
/// [WindowsUpdateInstallMode::Passive] will return `["/P", "/R"]`
/// [WindowsUpdateInstallMode::Quiet] will return `["/S", "/R"]`
pub fn nsis_args(&self) -> &'static [&'static str] {
match self {
Self::Passive => &["/P", "/R"],
@ -3209,7 +3225,7 @@ mod build {
} else if num.is_f64() {
// guaranteed f64
let num = num.as_f64().unwrap();
quote! { #prefix::Number(#num.into()) }
quote! { #prefix::Number(::serde_json::Number::from_f64(#num).unwrap(/* safe to unwrap, guaranteed f64 */)) }
} else {
// invalid number
quote! { #prefix::Null }
@ -3736,6 +3752,7 @@ mod build {
let dev_csp = opt_lit(self.dev_csp.as_ref());
let freeze_prototype = self.freeze_prototype;
let dangerous_disable_asset_csp_modification = &self.dangerous_disable_asset_csp_modification;
let dangerous_use_http_scheme = &self.dangerous_use_http_scheme;
let dangerous_remote_domain_ipc_access =
vec_lit(&self.dangerous_remote_domain_ipc_access, identity);
@ -3746,7 +3763,8 @@ mod build {
dev_csp,
freeze_prototype,
dangerous_disable_asset_csp_modification,
dangerous_remote_domain_ipc_access
dangerous_remote_domain_ipc_access,
dangerous_use_http_scheme
);
}
}
@ -4013,6 +4031,7 @@ mod test {
freeze_prototype: false,
dangerous_disable_asset_csp_modification: DisabledCspModificationKind::Flag(false),
dangerous_remote_domain_ipc_access: Vec::new(),
dangerous_use_http_scheme: false,
},
allowlist: AllowlistConfig::default(),
system_tray: None,

View File

@ -13,6 +13,8 @@ use std::{
use semver::Version;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use log::warn;
pub mod assets;
pub mod config;
pub mod html;
@ -202,7 +204,7 @@ impl Default for Env {
.unwrap_or(true);
if !is_temp {
panic!("`APPDIR` or `APPIMAGE` environment variable found but this application was not detected as an AppImage; this might be a security issue.");
warn!("`APPDIR` or `APPIMAGE` environment variable found but this application was not detected as an AppImage; this might be a security issue.");
}
}
env

View File

@ -208,81 +208,16 @@ pub use windows_platform::{is_windows_7, windows_version};
#[cfg(windows)]
mod windows_platform {
use std::{iter::once, os::windows::prelude::OsStrExt};
use windows::{
core::{PCSTR, PCWSTR},
Win32::{
Foundation::FARPROC,
System::{
LibraryLoader::{GetProcAddress, LoadLibraryW},
SystemInformation::OSVERSIONINFOW,
},
},
};
/// Checks if we're running on Windows 7.
pub fn is_windows_7() -> bool {
if let Some(v) = windows_version() {
// windows 7 is 6.1
if v.0 == 6 && v.1 == 1 {
return true;
}
}
false
}
fn encode_wide(string: impl AsRef<std::ffi::OsStr>) -> Vec<u16> {
string.as_ref().encode_wide().chain(once(0)).collect()
}
// Helper function to dynamically load function pointer.
// `library` and `function` must be zero-terminated.
fn get_function_impl(library: &str, function: &str) -> Option<FARPROC> {
let library = encode_wide(library);
assert_eq!(function.chars().last(), Some('\0'));
let function = PCSTR::from_raw(function.as_ptr());
// Library names we will use are ASCII so we can use the A version to avoid string conversion.
let module = unsafe { LoadLibraryW(PCWSTR::from_raw(library.as_ptr())) }.unwrap_or_default();
if module.is_invalid() {
None
} else {
Some(unsafe { GetProcAddress(module, function) })
}
}
macro_rules! get_function {
($lib:expr, $func:ident) => {
get_function_impl(concat!($lib, '\0'), concat!(stringify!($func), '\0'))
.map(|f| unsafe { std::mem::transmute::<windows::Win32::Foundation::FARPROC, $func>(f) })
};
windows_version()
.map(|v| v.0 == 6 && v.1 == 1)
.unwrap_or_default()
}
/// Returns a tuple of (major, minor, buildnumber) for the Windows version.
pub fn windows_version() -> Option<(u32, u32, u32)> {
type RtlGetVersion = unsafe extern "system" fn(*mut OSVERSIONINFOW) -> i32;
let handle = get_function!("ntdll.dll", RtlGetVersion);
if let Some(rtl_get_version) = handle {
unsafe {
let mut vi = OSVERSIONINFOW {
dwOSVersionInfoSize: 0,
dwMajorVersion: 0,
dwMinorVersion: 0,
dwBuildNumber: 0,
dwPlatformId: 0,
szCSDVersion: [0; 128],
};
let status = (rtl_get_version)(&mut vi as _);
if status >= 0 {
Some((vi.dwMajorVersion, vi.dwMinorVersion, vi.dwBuildNumber))
} else {
None
}
}
} else {
None
}
let v = windows_version::OsVersion::current();
Some((v.major, v.minor, v.build))
}
}

View File

@ -1,5 +1,84 @@
# Changelog
## \[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 `<base target="_blank" />` 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://<scheme>.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

View File

@ -10,14 +10,13 @@ license = "Apache-2.0 OR MIT"
name = "tauri"
readme = "README.md"
repository = "https://github.com/tauri-apps/tauri"
version = "1.4.1"
version = "1.5.4"
[package.metadata.docs.rs]
no-default-features = true
features = [
"wry",
"custom-protocol",
"api-all",
"windows7-compat",
"cli",
"updater",
@ -27,7 +26,16 @@ features = [
"http-multipart",
"icon-png",
"test",
"dox"
"dox",
"dialog",
"global-shortcut",
"http-request",
"os-api",
"process-relaunch",
"process-exit",
"protocol-asset",
"process-command-api",
"shell-open"
]
rustdoc-args = [ "--cfg", "doc_cfg" ]
default-target = "x86_64-unknown-linux-gnu"
@ -41,7 +49,7 @@ targets = [
normal = [ "reqwest" ]
[dependencies]
serde_json = { version = "1.0", features = [ "raw_value" ] }
serde_json = { version = "1.0", features = [ "raw_value", "preserve_order" ] }
serde = { version = "1.0", features = [ "derive" ] }
tokio = { version = "1", features = [ "rt", "rt-multi-thread", "sync", "fs", "io-util" ] }
futures-util = "0.3"
@ -50,10 +58,10 @@ url = { version = "2.3" }
anyhow = "1.0"
thiserror = "1.0"
once_cell = "1"
tauri-runtime = { version = "0.14.0", path = "../tauri-runtime" }
tauri-macros = { version = "1.4.0", path = "../tauri-macros" }
tauri-utils = { version = "1.4.0", features = [ "resources" ], path = "../tauri-utils" }
tauri-runtime-wry = { version = "0.14.0", path = "../tauri-runtime-wry", optional = true }
tauri-runtime = { version = "0.14.2", path = "../tauri-runtime" }
tauri-macros = { version = "1.4.3", path = "../tauri-macros" }
tauri-utils = { version = "1.5.2", features = [ "resources" ], path = "../tauri-utils" }
tauri-runtime-wry = { version = "0.14.3", path = "../tauri-runtime-wry", optional = true }
rand = "0.8"
semver = { version = "1.0", features = [ "serde" ] }
serde_repr = "0.1"
@ -77,7 +85,7 @@ raw-window-handle = "0.5"
minisign-verify = { version = "0.2", optional = true }
time = { version = "0.3", features = [ "parsing", "formatting" ], optional = true }
os_info = { version = "3", optional = true }
regex = { version = "1.6.0", optional = true }
regex = { version = "1", optional = true }
glob = "0.3"
data-url = { version = "0.2", optional = true }
serialize-to-javascript = "=0.1.1"
@ -86,6 +94,8 @@ png = { version = "0.17", optional = true }
ico = { version = "0.2.0", optional = true }
encoding_rs = "0.8.31"
sys-locale = { version = "0.2.3", optional = true }
tracing = { version = "0.1", optional = true }
indexmap = { version = "1", features = [ "std", "serde" ], optional = true }
[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
rfd = { version = "0.10", optional = true, features = [ "gtk3", "common-controls-v6" ] }
@ -102,6 +112,7 @@ cocoa = "0.24"
objc = "0.2"
[target."cfg(windows)".dependencies]
dunce = "1"
webview2-com = "0.19.1"
win7-notifications = { version = "0.4", optional = true }
@ -127,6 +138,11 @@ cargo_toml = "0.11"
[features]
default = [ "wry", "compression", "objc-exception" ]
tracing = [
"dep:tracing",
"tauri-macros/tracing",
"tauri-runtime-wry/tracing"
]
test = [ ]
compression = [ "tauri-macros/compression", "tauri-utils/compression" ]
wry = [ "tauri-runtime-wry" ]
@ -142,7 +158,7 @@ updater = [
"dialog-ask",
"fs-extract-api"
]
http-api = [ "reqwest", "bytes" ]
http-api = [ "reqwest", "bytes", "indexmap" ]
http-multipart = [ "reqwest/multipart" ]
os-api = [ "sys-locale" ]
shell-open-api = [ "open", "regex", "tauri-macros/shell-scope" ]

File diff suppressed because one or more lines are too long

View File

@ -13,6 +13,16 @@
})
}
const osName = __TEMPLATE_os_name__
const protocolScheme = __TEMPLATE_protocol_scheme__
window.__TAURI__.convertFileSrc = function convertFileSrc(filePath, protocol = 'asset') {
const path = encodeURIComponent(filePath)
return osName === 'windows'
? `${protocolScheme}://${protocol}.localhost/${path}`
: `${protocol}://localhost/${path}`
}
window.__TAURI__.transformCallback = function transformCallback(
callback,
once
@ -132,16 +142,40 @@
)
}
// drag region
//-----------------------//
// data-tauri-drag-region
//
// drag on mousedown and maximize on double click on Windows and Linux
// while macOS macos maximization should be on mouseup and if the mouse
// moves after the double click, it should be cancelled (see https://github.com/tauri-apps/tauri/issues/8306)
//-----------------------//
const TAURI_DRAG_REGION_ATTR = 'data-tauri-drag-region';
let x = 0, y = 0;
document.addEventListener('mousedown', (e) => {
if (e.target.hasAttribute('data-tauri-drag-region') && e.button === 0) {
if (
// element has the magic data attribute
e.target.hasAttribute(TAURI_DRAG_REGION_ATTR) &&
// and was left mouse button
e.button === 0 &&
// and was normal click to drag or double click to maximize
(e.detail === 1 || e.detail === 2)
) {
// macOS maximization happens on `mouseup`,
// so we save needed state and early return
if (osName === 'macos' && e.detail == 2) {
x = e.clientX
y = e.clientY
return
}
// prevents text cursor
e.preventDefault()
// fix #2549: double click on drag region edge causes content to maximize without window sizing change
// https://github.com/tauri-apps/tauri/issues/2549#issuecomment-1250036908
e.stopImmediatePropagation()
// start dragging if the element has a `tauri-drag-region` data attribute and maximize on double-clicking it
window.__TAURI_INVOKE__('tauri', {
__tauriModule: 'Window',
message: {
@ -155,6 +189,34 @@
})
}
})
// on macOS we maximze on mouseup instead, to match the system behavior where maximization can be canceled
// if the mouse moves outside the data-tauri-drag-region
if (osName === "macos") {
document.addEventListener('mouseup', (e) => {
if (
// element has the magic data attribute
e.target.hasAttribute(TAURI_DRAG_REGION_ATTR) &&
// and was left mouse button
e.button === 0 &&
// and was double click
e.detail === 2 &&
// and the cursor hasn't moved from initial mousedown
e.clientX === x && e.clientY === y
) {
window.__TAURI_INVOKE__('tauri', {
__tauriModule: 'Window',
message: {
cmd: 'manage',
data: {
cmd: {
type: '__toggleMaximize'
}
}
}
})
}
})
}
let permissionSettable = false
let permissionValue = 'default'

View File

@ -3,10 +3,12 @@
// SPDX-License-Identifier: MIT
(function () {
const osName = __TEMPLATE_os_name__
function toggleDevtoolsHotkey() {
const isHotkey = navigator.appVersion.includes("Mac")
? (event) => event.metaKey && event.altKey && event.key === "I"
: (event) => event.ctrlKey && event.shiftKey && event.key === "I";
const isHotkey = osName === 'macos' ?
(event) => event.metaKey && event.altKey && event.code === "KeyI" :
(event) => event.ctrlKey && event.shiftKey && event.code === "KeyI";
document.addEventListener("keydown", (event) => {
if (isHotkey(event)) {

View File

@ -250,11 +250,16 @@ pub enum FormPart {
/// Form body definition.
#[derive(Debug, Deserialize)]
pub struct FormBody(pub(crate) HashMap<String, FormPart>);
pub struct FormBody(pub(crate) indexmap::IndexMap<String, FormPart>);
impl FormBody {
/// Creates a new form body.
pub fn new(data: HashMap<String, FormPart>) -> Self {
Self(indexmap::IndexMap::from_iter(data))
}
/// Creates a new form body with pre-ordered keys. Useful if the api requires a specific order.
pub fn new_ordered(data: indexmap::IndexMap<String, FormPart>) -> Self {
Self(data)
}
}

View File

@ -31,7 +31,7 @@ pub mod cli;
#[cfg_attr(doc_cfg, doc(cfg(feature = "cli")))]
pub use clap;
#[cfg(all(desktop, feature = "notification"))]
#[cfg(all(desktop, any(feature = "notification", feature = "dox")))]
#[cfg_attr(doc_cfg, doc(cfg(all(desktop, feature = "notification"))))]
pub mod notification;

View File

@ -110,6 +110,10 @@ impl Notification {
}
/// Sets the notification icon.
///
/// ## Platform-specific
///
/// - **Windows**: The app must be installed for this to have any effect.
#[must_use]
pub fn icon(mut self, icon: impl Into<String>) -> Self {
self.icon = Some(icon.into());
@ -149,55 +153,60 @@ impl Notification {
deprecated = "This function does not work on Windows 7. Use `Self::notify` instead."
)]
pub fn show(self) -> crate::api::Result<()> {
let mut notification = notify_rust::Notification::new();
if let Some(body) = self.body {
notification.body(&body);
}
if let Some(title) = self.title {
notification.summary(&title);
}
if let Some(icon) = self.icon {
notification.icon(&icon);
} else {
notification.auto_icon();
}
if let Some(sound) = self.sound {
notification.sound_name(&match sound {
#[cfg(target_os = "macos")]
Sound::Default => "NSUserNotificationDefaultSoundName".to_string(),
#[cfg(windows)]
Sound::Default => "Default".to_string(),
#[cfg(all(unix, not(target_os = "macos")))]
Sound::Default => "message-new-instant".to_string(),
Sound::Custom(c) => c,
});
}
#[cfg(windows)]
#[cfg(feature = "dox")]
return Ok(());
#[cfg(not(feature = "dox"))]
{
let exe = tauri_utils::platform::current_exe()?;
let exe_dir = exe.parent().expect("failed to get exe directory");
let curr_dir = exe_dir.display().to_string();
// set the notification's System.AppUserModel.ID only when running the installed app
if !(curr_dir.ends_with(format!("{SEP}target{SEP}debug").as_str())
|| curr_dir.ends_with(format!("{SEP}target{SEP}release").as_str()))
{
notification.app_id(&self.identifier);
let mut notification = notify_rust::Notification::new();
if let Some(body) = self.body {
notification.body(&body);
}
}
#[cfg(target_os = "macos")]
{
let _ = notify_rust::set_application(if cfg!(feature = "custom-protocol") {
&self.identifier
if let Some(title) = self.title {
notification.summary(&title);
}
if let Some(icon) = self.icon {
notification.icon(&icon);
} else {
"com.apple.Terminal"
notification.auto_icon();
}
if let Some(sound) = self.sound {
notification.sound_name(&match sound {
#[cfg(target_os = "macos")]
Sound::Default => "NSUserNotificationDefaultSoundName".to_string(),
#[cfg(windows)]
Sound::Default => "Default".to_string(),
#[cfg(all(unix, not(target_os = "macos")))]
Sound::Default => "message-new-instant".to_string(),
Sound::Custom(c) => c,
});
}
#[cfg(windows)]
{
let exe = tauri_utils::platform::current_exe()?;
let exe_dir = exe.parent().expect("failed to get exe directory");
let curr_dir = exe_dir.display().to_string();
// set the notification's System.AppUserModel.ID only when running the installed app
if !(curr_dir.ends_with(format!("{SEP}target{SEP}debug").as_str())
|| curr_dir.ends_with(format!("{SEP}target{SEP}release").as_str()))
{
notification.app_id(&self.identifier);
}
}
#[cfg(target_os = "macos")]
{
let _ = notify_rust::set_application(if cfg!(feature = "custom-protocol") {
&self.identifier
} else {
"com.apple.Terminal"
});
}
crate::async_runtime::spawn(async move {
let _ = notification.show();
});
Ok(())
}
crate::async_runtime::spawn(async move {
let _ = notification.show();
});
Ok(())
}
/// Shows the notification. This API is similar to [`Self::show`], but it also works on Windows 7.

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