Merge branch 'v2' into feat/fs/get-filename-android

pull/2421/head
VulnX 5 months ago committed by GitHub
commit fba537e0e8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,6 +0,0 @@
---
"log": patch
"log-js": patch
---
Fix timezone_strategy overwriting previously set LogLevels.

@ -0,0 +1,5 @@
---
'log': 'minor:feat'
'log-js': 'minor:feat'
---
Add a `is_skip_logger` flag to the Log Plugin `Builder` struct, a `skip_logger()` method to the Builder, and logic to avoid acquiring (creating) a logger and attaching it to the global logger. Since acquire_logger is pub, a `LoggerNotInitialized` is added and returned if it's called when the `is_skip_looger` flag is set. Overall, this feature permits a user to avoid calling `attach_logger` which can only be called once in a program's lifetime and allows the user to control the logger returned from `logger()`. Additionally, it also will allow users to generate multiple Tauri Mock apps in test suites that run and parallel and have the `log` plugin attached (assuming they use `skip_logger()`).

@ -46,7 +46,7 @@ jobs:
node-version: 'lts/*' node-version: 'lts/*'
- uses: pnpm/action-setup@v4 - uses: pnpm/action-setup@v4
with: with:
version: 9.x.x version: 10.x.x
run_install: true run_install: true
- name: audit - name: audit
run: pnpm audit run: pnpm audit

@ -167,7 +167,7 @@ jobs:
node-version: 'lts/*' node-version: 'lts/*'
- uses: pnpm/action-setup@v4 - uses: pnpm/action-setup@v4
with: with:
version: 9.x.x version: 10.x.x
run_install: true run_install: true
- name: build api - name: build api

@ -39,7 +39,7 @@ jobs:
- uses: pnpm/action-setup@v4 - uses: pnpm/action-setup@v4
with: with:
version: 9.x.x version: 10.x.x
run_install: true run_install: true
- name: cargo login - name: cargo login
@ -75,7 +75,7 @@ jobs:
- name: Create Pull Request With Versions Bumped - name: Create Pull Request With Versions Bumped
id: cpr id: cpr
uses: tauri-apps/create-pull-request@v3 uses: peter-evans/create-pull-request@dd2324fc52d5d43c699a5636bcf19fceaa70c284 # 7.0.7
if: steps.covector.outputs.commandRan == 'version' if: steps.covector.outputs.commandRan == 'version'
with: with:
title: 'Publish New Versions (${{ github.ref_name }})' title: 'Publish New Versions (${{ github.ref_name }})'

@ -38,7 +38,7 @@ jobs:
node-version: 'lts/*' node-version: 'lts/*'
- uses: pnpm/action-setup@v4 - uses: pnpm/action-setup@v4
with: with:
version: 9.x.x version: 10.x.x
run_install: true run_install: true
- run: pnpm format:check - run: pnpm format:check

@ -49,7 +49,7 @@ jobs:
node-version: 'lts/*' node-version: 'lts/*'
- uses: pnpm/action-setup@v4 - uses: pnpm/action-setup@v4
with: with:
version: 9.x.x version: 10.x.x
run_install: true run_install: true
- name: eslint - name: eslint
run: pnpm lint run: pnpm lint

@ -38,7 +38,7 @@ jobs:
- uses: pnpm/action-setup@v4 - uses: pnpm/action-setup@v4
with: with:
version: 9.x.x version: 10.x.x
run_install: true run_install: true
- name: Build packages - name: Build packages

2
.gitignore vendored

@ -14,6 +14,8 @@ target/
# .vscode workspace settings file # .vscode workspace settings file
.vscode/settings.json .vscode/settings.json
.vscode/launch.json
.vscode/tasks.json
# npm, yarn and bun lock files # npm, yarn and bun lock files
package-lock.json package-lock.json

750
Cargo.lock generated

File diff suppressed because it is too large Load Diff

@ -1,5 +1,19 @@
# Changelog # Changelog
## \[2.0.15]
### Dependencies
- Upgraded to `log-js@2.2.3`
- Upgraded to `opener-js@2.2.6`
## \[2.0.14]
### Dependencies
- Upgraded to `log-js@2.2.2`
- Upgraded to `updater-js@2.5.1`
## \[2.0.13] ## \[2.0.13]
### Dependencies ### Dependencies

@ -1,7 +1,7 @@
{ {
"name": "api", "name": "api",
"private": true, "private": true,
"version": "2.0.13", "version": "2.0.15",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite --clearScreen false", "dev": "vite --clearScreen false",
@ -10,7 +10,7 @@
"tauri": "tauri" "tauri": "tauri"
}, },
"dependencies": { "dependencies": {
"@tauri-apps/api": "2.2.0", "@tauri-apps/api": "2.3.0",
"@tauri-apps/plugin-barcode-scanner": "^2.2.0", "@tauri-apps/plugin-barcode-scanner": "^2.2.0",
"@tauri-apps/plugin-biometric": "^2.2.0", "@tauri-apps/plugin-biometric": "^2.2.0",
"@tauri-apps/plugin-cli": "^2.2.0", "@tauri-apps/plugin-cli": "^2.2.0",
@ -19,26 +19,26 @@
"@tauri-apps/plugin-fs": "^2.2.0", "@tauri-apps/plugin-fs": "^2.2.0",
"@tauri-apps/plugin-geolocation": "^2.2.0", "@tauri-apps/plugin-geolocation": "^2.2.0",
"@tauri-apps/plugin-global-shortcut": "^2.2.0", "@tauri-apps/plugin-global-shortcut": "^2.2.0",
"@tauri-apps/plugin-opener": "^2.2.5",
"@tauri-apps/plugin-haptics": "^2.2.0", "@tauri-apps/plugin-haptics": "^2.2.0",
"@tauri-apps/plugin-http": "^2.3.0", "@tauri-apps/plugin-http": "^2.3.0",
"@tauri-apps/plugin-nfc": "^2.2.0", "@tauri-apps/plugin-nfc": "^2.2.0",
"@tauri-apps/plugin-notification": "^2.2.1", "@tauri-apps/plugin-notification": "^2.2.1",
"@tauri-apps/plugin-opener": "^2.2.6",
"@tauri-apps/plugin-os": "^2.2.0", "@tauri-apps/plugin-os": "^2.2.0",
"@tauri-apps/plugin-process": "^2.2.0", "@tauri-apps/plugin-process": "^2.2.0",
"@tauri-apps/plugin-shell": "^2.2.0", "@tauri-apps/plugin-shell": "^2.2.0",
"@tauri-apps/plugin-store": "^2.2.0", "@tauri-apps/plugin-store": "^2.2.0",
"@tauri-apps/plugin-updater": "^2.5.0", "@tauri-apps/plugin-updater": "^2.5.1",
"@zerodevx/svelte-json-view": "1.0.11" "@zerodevx/svelte-json-view": "1.0.11"
}, },
"devDependencies": { "devDependencies": {
"@iconify-json/codicon": "^1.2.6", "@iconify-json/codicon": "^1.2.12",
"@iconify-json/ph": "^1.2.1", "@iconify-json/ph": "^1.2.2",
"@sveltejs/vite-plugin-svelte": "^5.0.1", "@sveltejs/vite-plugin-svelte": "^5.0.3",
"@tauri-apps/cli": "2.2.7", "@tauri-apps/cli": "2.3.1",
"@unocss/extractor-svelte": "^65.0.0", "@unocss/extractor-svelte": "^66.0.0",
"svelte": "^5.10.0", "svelte": "^5.20.4",
"unocss": "^65.0.0", "unocss": "^66.0.0",
"vite": "^6.0.3" "vite": "^6.2.0"
} }
} }

@ -1,5 +1,19 @@
# Changelog # Changelog
## \[2.0.19]
### Dependencies
- Upgraded to `log@2.2.3`
- Upgraded to `opener@2.2.6`
## \[2.0.18]
### Dependencies
- Upgraded to `log@2.2.2`
- Upgraded to `updater@2.5.1`
## \[2.0.17] ## \[2.0.17]
### Dependencies ### Dependencies

@ -1,7 +1,7 @@
[package] [package]
name = "api" name = "api"
publish = false publish = false
version = "2.0.17" version = "2.0.19"
description = "An example Tauri Application showcasing the api" description = "An example Tauri Application showcasing the api"
edition = "2021" edition = "2021"
rust-version = { workspace = true } rust-version = { workspace = true }
@ -19,7 +19,7 @@ serde_json = { workspace = true }
serde = { workspace = true } serde = { workspace = true }
tiny_http = "0.12" tiny_http = "0.12"
log = { workspace = true } log = { workspace = true }
tauri-plugin-log = { path = "../../../plugins/log", version = "2.2.1" } tauri-plugin-log = { path = "../../../plugins/log", version = "2.2.3" }
tauri-plugin-fs = { path = "../../../plugins/fs", version = "2.2.0", features = [ tauri-plugin-fs = { path = "../../../plugins/fs", version = "2.2.0", features = [
"watch", "watch",
] } ] }
@ -33,7 +33,7 @@ tauri-plugin-notification = { path = "../../../plugins/notification", version =
] } ] }
tauri-plugin-os = { path = "../../../plugins/os", version = "2.2.0" } tauri-plugin-os = { path = "../../../plugins/os", version = "2.2.0" }
tauri-plugin-process = { path = "../../../plugins/process", version = "2.2.0" } tauri-plugin-process = { path = "../../../plugins/process", version = "2.2.0" }
tauri-plugin-opener = { path = "../../../plugins/opener", version = "2.2.5" } tauri-plugin-opener = { path = "../../../plugins/opener", version = "2.2.6" }
tauri-plugin-shell = { path = "../../../plugins/shell", version = "2.2.0" } tauri-plugin-shell = { path = "../../../plugins/shell", version = "2.2.0" }
tauri-plugin-store = { path = "../../../plugins/store", version = "2.2.0" } tauri-plugin-store = { path = "../../../plugins/store", version = "2.2.0" }
@ -53,7 +53,7 @@ features = [
[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies] [target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
tauri-plugin-cli = { path = "../../../plugins/cli", version = "2.2.0" } tauri-plugin-cli = { path = "../../../plugins/cli", version = "2.2.0" }
tauri-plugin-global-shortcut = { path = "../../../plugins/global-shortcut", version = "2.2.0" } tauri-plugin-global-shortcut = { path = "../../../plugins/global-shortcut", version = "2.2.0" }
tauri-plugin-updater = { path = "../../../plugins/updater", version = "2.5.0" } tauri-plugin-updater = { path = "../../../plugins/updater", version = "2.5.1" }
tauri-plugin-window-state = { path = "../../../plugins/window-state", version = "2.2.0" } tauri-plugin-window-state = { path = "../../../plugins/window-state", version = "2.2.0" }
[target."cfg(any(target_os = \"android\", target_os = \"ios\"))".dependencies] [target."cfg(any(target_os = \"android\", target_os = \"ios\"))".dependencies]

@ -11,26 +11,29 @@
"example:api:dev": "pnpm run --filter \"api\" tauri dev" "example:api:dev": "pnpm run --filter \"api\" tauri dev"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "9.19.0", "@eslint/js": "9.21.0",
"@rollup/plugin-node-resolve": "16.0.0", "@rollup/plugin-node-resolve": "16.0.0",
"@rollup/plugin-terser": "0.4.4", "@rollup/plugin-terser": "0.4.4",
"@rollup/plugin-typescript": "11.1.6", "@rollup/plugin-typescript": "12.1.2",
"@types/eslint__js": "8.42.3", "covector": "^0.12.4",
"covector": "^0.12.3", "eslint": "9.21.0",
"eslint": "9.19.0", "eslint-config-prettier": "10.0.2",
"eslint-config-prettier": "10.0.1",
"eslint-plugin-security": "3.0.1", "eslint-plugin-security": "3.0.1",
"prettier": "3.5.1", "prettier": "3.5.3",
"rollup": "4.34.7", "rollup": "4.34.9",
"tslib": "2.8.1", "tslib": "2.8.1",
"typescript": "5.7.3", "typescript": "5.8.2",
"typescript-eslint": "8.24.0" "typescript-eslint": "8.25.0"
}, },
"resolutions": { "pnpm": {
"semver": ">=7.5.2", "overrides": {
"optionator": ">=0.9.3" "esbuild@<0.25.0": ">=0.25.0"
},
"onlyBuiltDependencies": [
"esbuild"
]
}, },
"engines": { "engines": {
"pnpm": "^9.0.0" "pnpm": "^10.0.0"
} }
} }

@ -38,7 +38,7 @@ url = { workspace = true }
[target."cfg(windows)".dependencies] [target."cfg(windows)".dependencies]
dunce = "1" dunce = "1"
windows-registry = "0.4" windows-registry = "0.5"
windows-result = "0.3" windows-result = "0.3"
[target."cfg(target_os = \"linux\")".dependencies] [target."cfg(target_os = \"linux\")".dependencies]

@ -10,12 +10,12 @@
"tauri": "tauri" "tauri": "tauri"
}, },
"dependencies": { "dependencies": {
"@tauri-apps/api": "2.2.0", "@tauri-apps/api": "2.3.0",
"@tauri-apps/plugin-deep-link": "2.2.0" "@tauri-apps/plugin-deep-link": "2.2.0"
}, },
"devDependencies": { "devDependencies": {
"@tauri-apps/cli": "2.2.7", "@tauri-apps/cli": "2.3.1",
"typescript": "^5.2.2", "typescript": "^5.7.3",
"vite": "^6.0.0" "vite": "^6.2.0"
} }
} }

@ -265,18 +265,15 @@ mod imp {
.to_string(); .to_string();
let key_reg = CURRENT_USER.create(&key_base)?; let key_reg = CURRENT_USER.create(&key_base)?;
key_reg.set_string( key_reg.set_string("", format!("URL:{} protocol", self.app.config().identifier))?;
"",
&format!("URL:{} protocol", self.app.config().identifier),
)?;
key_reg.set_string("URL Protocol", "")?; key_reg.set_string("URL Protocol", "")?;
let icon_reg = CURRENT_USER.create(format!("{key_base}\\DefaultIcon"))?; let icon_reg = CURRENT_USER.create(format!("{key_base}\\DefaultIcon"))?;
icon_reg.set_string("", &format!("{exe},0"))?; icon_reg.set_string("", format!("{exe},0"))?;
let cmd_reg = CURRENT_USER.create(format!("{key_base}\\shell\\open\\command"))?; let cmd_reg = CURRENT_USER.create(format!("{key_base}\\shell\\open\\command"))?;
cmd_reg.set_string("", &format!("\"{exe}\" \"%1\""))?; cmd_reg.set_string("", format!("\"{exe}\" \"%1\""))?;
Ok(()) Ok(())
} }

@ -53,10 +53,7 @@ impl FilePath {
#[inline] #[inline]
pub fn into_path(self) -> Result<PathBuf> { pub fn into_path(self) -> Result<PathBuf> {
match self { match self {
Self::Url(url) => url Self::Url(url) => url.to_file_path().map_err(|_| Error::InvalidPathUrl),
.to_file_path()
.map(PathBuf::from)
.map_err(|_| Error::InvalidPathUrl),
Self::Path(p) => Ok(p), Self::Path(p) => Ok(p),
} }
} }
@ -91,10 +88,7 @@ impl SafeFilePath {
#[inline] #[inline]
pub fn into_path(self) -> Result<PathBuf> { pub fn into_path(self) -> Result<PathBuf> {
match self { match self {
Self::Url(url) => url Self::Url(url) => url.to_file_path().map_err(|_| Error::InvalidPathUrl),
.to_file_path()
.map(PathBuf::from)
.map_err(|_| Error::InvalidPathUrl),
Self::Path(p) => Ok(p.as_ref().to_owned()), Self::Path(p) => Ok(p.as_ref().to_owned()),
} }
} }

@ -1,5 +1,13 @@
# Changelog # Changelog
## \[2.2.3]
- [`1a984659`](https://github.com/tauri-apps/plugins-workspace/commit/1a9846599b6a71faf330845847a30f6bf9735898) ([#2469](https://github.com/tauri-apps/plugins-workspace/pull/2469) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Update `objc2` crate to 0.6. No user facing changes.
## \[2.2.2]
- [`6b4c3917`](https://github.com/tauri-apps/plugins-workspace/commit/6b4c3917389f4bc489d03b48a837557ac0584175) ([#2401](https://github.com/tauri-apps/plugins-workspace/pull/2401) by [@Seishiin](https://github.com/tauri-apps/plugins-workspace/../../Seishiin)) Fix timezone_strategy overwriting previously set LogLevels.
## \[2.2.1] ## \[2.2.1]
- [`784a54a3`](https://github.com/tauri-apps/plugins-workspace/commit/784a54a39094dfbaaa8dd123eb083c04dc6c3bb2) ([#2344](https://github.com/tauri-apps/plugins-workspace/pull/2344) by [@madsmtm](https://github.com/tauri-apps/plugins-workspace/../../madsmtm)) Use `objc2` instead of `objc`. - [`784a54a3`](https://github.com/tauri-apps/plugins-workspace/commit/784a54a39094dfbaaa8dd123eb083c04dc6c3bb2) ([#2344](https://github.com/tauri-apps/plugins-workspace/pull/2344) by [@madsmtm](https://github.com/tauri-apps/plugins-workspace/../../madsmtm)) Use `objc2` instead of `objc`.

@ -1,6 +1,6 @@
[package] [package]
name = "tauri-plugin-log" name = "tauri-plugin-log"
version = "2.2.1" version = "2.2.3"
description = "Configurable logging for your Tauri app." description = "Configurable logging for your Tauri app."
authors = { workspace = true } authors = { workspace = true }
license = { workspace = true } license = { workspace = true }
@ -39,8 +39,8 @@ android_logger = "0.14"
[target."cfg(target_os = \"ios\")".dependencies] [target."cfg(target_os = \"ios\")".dependencies]
swift-rs = "1" swift-rs = "1"
objc2 = "0.5" objc2 = "0.6"
objc2-foundation = { version = "0.2", default-features = false, features = [ objc2-foundation = { version = "0.3", default-features = false, features = [
"std", "std",
"NSString", "NSString",
] } ] }

@ -1,6 +1,6 @@
{ {
"name": "@tauri-apps/plugin-log", "name": "@tauri-apps/plugin-log",
"version": "2.2.1", "version": "2.2.3",
"description": "Configurable logging for your Tauri app.", "description": "Configurable logging for your Tauri app.",
"license": "MIT OR Apache-2.0", "license": "MIT OR Apache-2.0",
"authors": [ "authors": [

@ -58,6 +58,8 @@ pub enum Error {
TimeFormat(#[from] time::error::Format), TimeFormat(#[from] time::error::Format),
#[error(transparent)] #[error(transparent)]
InvalidFormatDescription(#[from] time::error::InvalidFormatDescription), InvalidFormatDescription(#[from] time::error::InvalidFormatDescription),
#[error("Internal logger disabled and cannot be acquired or attached")]
LoggerNotInitialized,
} }
/// An enum representing the available verbosity levels of the logger. /// An enum representing the available verbosity levels of the logger.
@ -230,6 +232,7 @@ pub struct Builder {
timezone_strategy: TimezoneStrategy, timezone_strategy: TimezoneStrategy,
max_file_size: u128, max_file_size: u128,
targets: Vec<Target>, targets: Vec<Target>,
is_skip_logger: bool,
} }
impl Default for Builder { impl Default for Builder {
@ -258,6 +261,7 @@ impl Default for Builder {
timezone_strategy: DEFAULT_TIMEZONE_STRATEGY, timezone_strategy: DEFAULT_TIMEZONE_STRATEGY,
max_file_size: DEFAULT_MAX_FILE_SIZE, max_file_size: DEFAULT_MAX_FILE_SIZE,
targets: DEFAULT_LOG_TARGETS.into(), targets: DEFAULT_LOG_TARGETS.into(),
is_skip_logger: false,
} }
} }
} }
@ -339,6 +343,22 @@ impl Builder {
self self
} }
/// Skip the creation and global registration of a logger
///
/// If you wish to use your own global logger, you must call `skip_logger` so that the plugin does not attempt to set a second global logger. In this configuration, no logger will be created and the plugin's `log` command will rely on the result of `log::logger()`. You will be responsible for configuring the logger yourself and any included targets will be ignored. This can also be used with `tracing-log` or if running tests in parallel that require the plugin to be registered.
/// ```rust
/// static LOGGER: SimpleLogger = SimpleLogger;
///
/// log::set_logger(&SimpleLogger)?;
/// log::set_max_level(LevelFilter::Info);
/// tauri_plugin_log::Builder::new()
/// .skip_logger();
/// ```
pub fn skip_logger(mut self) -> Self {
self.is_skip_logger = true;
self
}
/// Adds a collection of targets to the logger. /// Adds a collection of targets to the logger.
/// ///
/// ```rust /// ```rust
@ -481,6 +501,9 @@ impl Builder {
self, self,
app_handle: &AppHandle<R>, app_handle: &AppHandle<R>,
) -> Result<(TauriPlugin<R>, log::LevelFilter, Box<dyn log::Log>), Error> { ) -> Result<(TauriPlugin<R>, log::LevelFilter, Box<dyn log::Log>), Error> {
if self.is_skip_logger {
return Err(Error::LoggerNotInitialized);
}
let plugin = Self::plugin_builder(); let plugin = Self::plugin_builder();
let (max_level, log) = Self::acquire_logger( let (max_level, log) = Self::acquire_logger(
app_handle, app_handle,
@ -497,17 +520,17 @@ impl Builder {
pub fn build<R: Runtime>(self) -> TauriPlugin<R> { pub fn build<R: Runtime>(self) -> TauriPlugin<R> {
Self::plugin_builder() Self::plugin_builder()
.setup(move |app_handle, _api| { .setup(move |app_handle, _api| {
let (max_level, log) = Self::acquire_logger( if !self.is_skip_logger {
app_handle, let (max_level, log) = Self::acquire_logger(
self.dispatch, app_handle,
self.rotation_strategy, self.dispatch,
self.timezone_strategy, self.rotation_strategy,
self.max_file_size, self.timezone_strategy,
self.targets, self.max_file_size,
)?; self.targets,
)?;
attach_logger(max_level, log)?; attach_logger(max_level, log)?;
}
Ok(()) Ok(())
}) })
.build() .build()

@ -46,7 +46,7 @@ windows-version = { version = "0.1", optional = true }
notify-rust = "4.11" notify-rust = "4.11"
[dev-dependencies] [dev-dependencies]
color-backtrace = "0.6" color-backtrace = "0.7"
ctor = "0.2" ctor = "0.2"
maplit = "1" maplit = "1"

@ -1,5 +1,10 @@
# Changelog # Changelog
## \[2.2.6]
- [`1a984659`](https://github.com/tauri-apps/plugins-workspace/commit/1a9846599b6a71faf330845847a30f6bf9735898) ([#2469](https://github.com/tauri-apps/plugins-workspace/pull/2469) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Update `objc2` crate to 0.6. No user facing changes.
- [`71f95c9f`](https://github.com/tauri-apps/plugins-workspace/commit/71f95c9f05b29cf1be586849614c0b007757c15d) ([#2445](https://github.com/tauri-apps/plugins-workspace/pull/2445) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated `windows` crate to 0.60 to match Tauri 2.3.0. No user facing changes.
## \[2.2.5] ## \[2.2.5]
- [`5b821181`](https://github.com/tauri-apps/plugins-workspace/commit/5b8211815825ddae2dcc0c00520e0cfdff002763) ([#2332](https://github.com/tauri-apps/plugins-workspace/pull/2332) by [@betamos](https://github.com/tauri-apps/plugins-workspace/../../betamos)) Fix broken JS commands `opener.openPath` and `opener.openUrl` on mobile. - [`5b821181`](https://github.com/tauri-apps/plugins-workspace/commit/5b8211815825ddae2dcc0c00520e0cfdff002763) ([#2332](https://github.com/tauri-apps/plugins-workspace/pull/2332) by [@betamos](https://github.com/tauri-apps/plugins-workspace/../../betamos)) Fix broken JS commands `opener.openPath` and `opener.openUrl` on mobile.

@ -1,6 +1,6 @@
[package] [package]
name = "tauri-plugin-opener" name = "tauri-plugin-opener"
version = "2.2.5" version = "2.2.6"
description = "Open files and URLs using their default application." description = "Open files and URLs using their default application."
edition = { workspace = true } edition = { workspace = true }
authors = { workspace = true } authors = { workspace = true }
@ -40,7 +40,7 @@ glob = { workspace = true }
dunce = { workspace = true } dunce = { workspace = true }
[target."cfg(windows)".dependencies.windows] [target."cfg(windows)".dependencies.windows]
version = "0.58" version = "0.60"
features = [ features = [
"Win32_Foundation", "Win32_Foundation",
"Win32_UI_Shell_Common", "Win32_UI_Shell_Common",
@ -54,12 +54,12 @@ zbus = { workspace = true }
url = { workspace = true } url = { workspace = true }
[target."cfg(target_os = \"macos\")".dependencies.objc2-app-kit] [target."cfg(target_os = \"macos\")".dependencies.objc2-app-kit]
version = "0.2" version = "0.3"
default-features = false default-features = false
features = ["std", "NSWorkspace"] features = ["std", "NSWorkspace"]
[target."cfg(target_os = \"macos\")".dependencies.objc2-foundation] [target."cfg(target_os = \"macos\")".dependencies.objc2-foundation]
version = "0.2" version = "0.3"
default-features = false default-features = false
features = ["std", "NSURL", "NSArray", "NSString"] features = ["std", "NSURL", "NSArray", "NSString"]

@ -1,6 +1,6 @@
{ {
"name": "@tauri-apps/plugin-opener", "name": "@tauri-apps/plugin-opener",
"version": "2.2.5", "version": "2.2.6",
"description": "Open files and URLs using their default application.", "description": "Open files and URLs using their default application.",
"license": "MIT OR Apache-2.0", "license": "MIT OR Apache-2.0",
"authors": [ "authors": [

@ -56,7 +56,7 @@ impl<R: Runtime> Opener<R> {
/// - **Android / iOS**: Always opens using default program. /// - **Android / iOS**: Always opens using default program.
#[cfg(desktop)] #[cfg(desktop)]
pub fn open_url(&self, url: impl Into<String>, with: Option<impl Into<String>>) -> Result<()> { pub fn open_url(&self, url: impl Into<String>, with: Option<impl Into<String>>) -> Result<()> {
crate::open::open(url.into(), with.map(Into::into)).map_err(Into::into) crate::open::open(url.into(), with.map(Into::into))
} }
/// Open a url with a default or specific program. /// Open a url with a default or specific program.
@ -108,7 +108,7 @@ impl<R: Runtime> Opener<R> {
path: impl Into<String>, path: impl Into<String>,
with: Option<impl Into<String>>, with: Option<impl Into<String>>,
) -> Result<()> { ) -> Result<()> {
crate::open::open(path.into(), with.map(Into::into)).map_err(Into::into) crate::open::open(path.into(), with.map(Into::into))
} }
/// Open a path with a default or specific program. /// Open a path with a default or specific program.

@ -185,7 +185,7 @@ mod imp {
let path = path.to_string_lossy(); let path = path.to_string_lossy();
let path = NSString::from_str(&path); let path = NSString::from_str(&path);
let urls = vec![NSURL::fileURLWithPath(&path)]; let urls = vec![NSURL::fileURLWithPath(&path)];
let urls = NSArray::from_vec(urls); let urls = NSArray::from_retained_slice(&urls);
let workspace = NSWorkspace::new(); let workspace = NSWorkspace::new();
workspace.activateFileViewerSelectingURLs(&urls); workspace.activateFileViewerSelectingURLs(&urls);

@ -75,7 +75,7 @@ impl<R: Runtime> Shell<R> {
#[deprecated(since = "2.1.0", note = "Use tauri-plugin-opener instead.")] #[deprecated(since = "2.1.0", note = "Use tauri-plugin-opener instead.")]
#[allow(deprecated)] #[allow(deprecated)]
pub fn open(&self, path: impl Into<String>, with: Option<open::Program>) -> Result<()> { pub fn open(&self, path: impl Into<String>, with: Option<open::Program>) -> Result<()> {
open::open(&self.open_scope, path.into(), with).map_err(Into::into) open::open(&self.open_scope, path.into(), with)
} }
/// Open a (url) path with a default or specific browser opening program. /// Open a (url) path with a default or specific browser opening program.

@ -1,5 +1,9 @@
# Changelog # Changelog
## \[2.2.2]
- [`1ab5f157`](https://github.com/tauri-apps/plugins-workspace/commit/1ab5f1576333174095bc7dad4bef7a8576bb29ab) ([#2452](https://github.com/tauri-apps/plugins-workspace/pull/2452) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Fixed `null pointer dereference` panic on rust nightly on Windows.
## \[2.2.1] ## \[2.2.1]
- [`da5c59e2`](https://github.com/tauri-apps/plugins-workspace/commit/da5c59e2fe879d177e3cfd52fcacce85440423cb) ([#2271](https://github.com/tauri-apps/plugins-workspace/pull/2271) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated `zbus` dependency to version 5. No API changes. - [`da5c59e2`](https://github.com/tauri-apps/plugins-workspace/commit/da5c59e2fe879d177e3cfd52fcacce85440423cb) ([#2271](https://github.com/tauri-apps/plugins-workspace/pull/2271) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated `zbus` dependency to version 5. No API changes.

@ -1,6 +1,6 @@
[package] [package]
name = "tauri-plugin-single-instance" name = "tauri-plugin-single-instance"
version = "2.2.1" version = "2.2.2"
description = "Ensure a single instance of your tauri app is running." description = "Ensure a single instance of your tauri app is running."
authors = { workspace = true } authors = { workspace = true }
license = { workspace = true } license = { workspace = true }

@ -9,6 +9,6 @@
"author": "", "author": "",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@tauri-apps/cli": "2.2.7" "@tauri-apps/cli": "2.3.1"
} }
} }

@ -3,5 +3,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
fn main() { fn main() {
tauri_build::build() tauri_build::build()
} }

@ -1,14 +0,0 @@
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"

@ -3,16 +3,15 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#![cfg_attr( #![cfg_attr(
all(not(debug_assertions), target_os = "windows"), all(not(debug_assertions), target_os = "windows"),
windows_subsystem = "windows" windows_subsystem = "windows"
)] )]
fn main() { fn main() {
tauri::Builder::default() tauri::Builder::default()
.plugin(tauri_plugin_cli::init()) .plugin(tauri_plugin_single_instance::init(|app, argv, cwd| {
.plugin(tauri_plugin_single_instance::init(|app, argv, cwd| { println!("{}, {argv:?}, {cwd}", app.package_info().name);
println!("{}, {argv:?}, {cwd}", app.package_info().name); }))
})) .run(tauri::generate_context!())
.run(tauri::generate_context!()) .expect("error while running tauri application");
.expect("error while running tauri application");
} }

@ -20,18 +20,38 @@ use windows_sys::Win32::{
}, },
UI::WindowsAndMessaging::{ UI::WindowsAndMessaging::{
self as w32wm, CreateWindowExW, DefWindowProcW, DestroyWindow, FindWindowW, self as w32wm, CreateWindowExW, DefWindowProcW, DestroyWindow, FindWindowW,
RegisterClassExW, SendMessageW, GWL_STYLE, GWL_USERDATA, WINDOW_LONG_PTR_INDEX, RegisterClassExW, SendMessageW, CREATESTRUCTW, GWLP_USERDATA, GWL_STYLE,
WM_COPYDATA, WM_DESTROY, WNDCLASSEXW, WS_EX_LAYERED, WS_EX_NOACTIVATE, WS_EX_TOOLWINDOW, WINDOW_LONG_PTR_INDEX, WM_COPYDATA, WM_CREATE, WM_DESTROY, WNDCLASSEXW, WS_EX_LAYERED,
WS_EX_TRANSPARENT, WS_OVERLAPPED, WS_POPUP, WS_VISIBLE, WS_EX_NOACTIVATE, WS_EX_TOOLWINDOW, WS_EX_TRANSPARENT, WS_OVERLAPPED, WS_POPUP, WS_VISIBLE,
}, },
}; };
const WMCOPYDATA_SINGLE_INSTANCE_DATA: usize = 1542;
struct MutexHandle(isize); struct MutexHandle(isize);
struct TargetWindowHandle(isize); struct TargetWindowHandle(isize);
const WMCOPYDATA_SINGLE_INSTANCE_DATA: usize = 1542; struct UserData<R: Runtime> {
app: AppHandle<R>,
callback: Box<SingleInstanceCallback<R>>,
}
impl<R: Runtime> UserData<R> {
unsafe fn from_hwnd_raw(hwnd: HWND) -> *mut Self {
GetWindowLongPtrW(hwnd, GWLP_USERDATA) as *mut Self
}
pub fn init<R: Runtime>(f: Box<SingleInstanceCallback<R>>) -> TauriPlugin<R> { unsafe fn from_hwnd<'a>(hwnd: HWND) -> &'a mut Self {
&mut *Self::from_hwnd_raw(hwnd)
}
fn run_callback(&mut self, args: Vec<String>, cwd: String) {
(self.callback)(&self.app, args, cwd)
}
}
pub fn init<R: Runtime>(callback: Box<SingleInstanceCallback<R>>) -> TauriPlugin<R> {
plugin::Builder::new("single-instance") plugin::Builder::new("single-instance")
.setup(|app, _api| { .setup(|app, _api| {
#[allow(unused_mut)] #[allow(unused_mut)]
@ -54,21 +74,22 @@ pub fn init<R: Runtime>(f: Box<SingleInstanceCallback<R>>) -> TauriPlugin<R> {
let hwnd = FindWindowW(class_name.as_ptr(), window_name.as_ptr()); let hwnd = FindWindowW(class_name.as_ptr(), window_name.as_ptr());
if !hwnd.is_null() { if !hwnd.is_null() {
let data = format!( let cwd = std::env::current_dir().unwrap_or_default();
"{}|{}\0", let cwd = cwd.to_str().unwrap_or_default();
std::env::current_dir()
.unwrap_or_default() let args = std::env::args().collect::<Vec<String>>().join("|");
.to_str()
.unwrap_or_default(), let data = format!("{cwd}|{args}\0",);
std::env::args().collect::<Vec<String>>().join("|")
);
let bytes = data.as_bytes(); let bytes = data.as_bytes();
let cds = COPYDATASTRUCT { let cds = COPYDATASTRUCT {
dwData: WMCOPYDATA_SINGLE_INSTANCE_DATA, dwData: WMCOPYDATA_SINGLE_INSTANCE_DATA,
cbData: bytes.len() as _, cbData: bytes.len() as _,
lpData: bytes.as_ptr() as _, lpData: bytes.as_ptr() as _,
}; };
SendMessageW(hwnd, WM_COPYDATA, 0, &cds as *const _ as _); SendMessageW(hwnd, WM_COPYDATA, 0, &cds as *const _ as _);
app.cleanup_before_exit(); app.cleanup_before_exit();
std::process::exit(0); std::process::exit(0);
} }
@ -76,15 +97,12 @@ pub fn init<R: Runtime>(f: Box<SingleInstanceCallback<R>>) -> TauriPlugin<R> {
} else { } else {
app.manage(MutexHandle(hmutex as _)); app.manage(MutexHandle(hmutex as _));
let hwnd = create_event_target_window::<R>(&class_name, &window_name); let userdata = UserData {
unsafe { app: app.clone(),
SetWindowLongPtrW( callback,
hwnd,
GWL_USERDATA,
Box::into_raw(Box::new((app.clone(), f))) as _,
)
}; };
let userdata = Box::into_raw(Box::new(userdata));
let hwnd = create_event_target_window::<R>(&class_name, &window_name, userdata);
app.manage(TargetWindowHandle(hwnd as _)); app.manage(TargetWindowHandle(hwnd as _));
} }
@ -116,32 +134,43 @@ unsafe extern "system" fn single_instance_window_proc<R: Runtime>(
wparam: WPARAM, wparam: WPARAM,
lparam: LPARAM, lparam: LPARAM,
) -> LRESULT { ) -> LRESULT {
let data_ptr = GetWindowLongPtrW(hwnd, GWL_USERDATA)
as *mut (AppHandle<R>, Box<SingleInstanceCallback<R>>);
let (app_handle, callback) = &mut *data_ptr;
match msg { match msg {
WM_CREATE => {
let create_struct = &*(lparam as *const CREATESTRUCTW);
let userdata = create_struct.lpCreateParams as *const UserData<R>;
SetWindowLongPtrW(hwnd, GWLP_USERDATA, userdata as _);
0
}
WM_COPYDATA => { WM_COPYDATA => {
let cds_ptr = lparam as *const COPYDATASTRUCT; let cds_ptr = lparam as *const COPYDATASTRUCT;
if (*cds_ptr).dwData == WMCOPYDATA_SINGLE_INSTANCE_DATA { if (*cds_ptr).dwData == WMCOPYDATA_SINGLE_INSTANCE_DATA {
let userdata = UserData::<R>::from_hwnd(hwnd);
let data = CStr::from_ptr((*cds_ptr).lpData as _).to_string_lossy(); let data = CStr::from_ptr((*cds_ptr).lpData as _).to_string_lossy();
let mut s = data.split('|'); let mut s = data.split('|');
let cwd = s.next().unwrap(); let cwd = s.next().unwrap();
let args = s.map(|s| s.to_string()).collect(); let args = s.map(|s| s.to_string()).collect();
callback(app_handle, args, cwd.to_string());
userdata.run_callback(args, cwd.to_string());
} }
1 1
} }
WM_DESTROY => { WM_DESTROY => {
let _ = Box::from_raw(data_ptr); let userdata = UserData::<R>::from_hwnd_raw(hwnd);
drop(Box::from_raw(userdata));
0 0
} }
_ => DefWindowProcW(hwnd, msg, wparam, lparam), _ => DefWindowProcW(hwnd, msg, wparam, lparam),
} }
} }
fn create_event_target_window<R: Runtime>(class_name: &[u16], window_name: &[u16]) -> HWND { fn create_event_target_window<R: Runtime>(
class_name: &[u16],
window_name: &[u16],
userdata: *const UserData<R>,
) -> HWND {
unsafe { unsafe {
let class = WNDCLASSEXW { let class = WNDCLASSEXW {
cbSize: std::mem::size_of::<WNDCLASSEXW>() as u32, cbSize: std::mem::size_of::<WNDCLASSEXW>() as u32,
@ -182,7 +211,7 @@ fn create_event_target_window<R: Runtime>(class_name: &[u16], window_name: &[u16
std::ptr::null_mut(), std::ptr::null_mut(),
std::ptr::null_mut(), std::ptr::null_mut(),
GetModuleHandleW(std::ptr::null()), GetModuleHandleW(std::ptr::null()),
std::ptr::null(), userdata as _,
); );
SetWindowLongPtrW( SetWindowLongPtrW(
hwnd, hwnd,

@ -8,8 +8,8 @@
"tauri": "tauri" "tauri": "tauri"
}, },
"devDependencies": { "devDependencies": {
"@tauri-apps/cli": "2.2.7", "@tauri-apps/cli": "2.3.1",
"vite": "^6.0.0", "typescript": "^5.7.3",
"typescript": "^5.4.7" "vite": "^6.2.0"
} }
} }

@ -1,5 +1,9 @@
# Changelog # Changelog
## \[2.5.1]
- [`6f881293`](https://github.com/tauri-apps/plugins-workspace/commit/6f881293fcd67838f6f3f8063f536292431dd1f7) ([#2439](https://github.com/tauri-apps/plugins-workspace/pull/2439) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Fixed an issue that caused the plugin to emit a `ReleaseNotFound` error instead of a `Reqwest` error when the http request in `check()` failed.
## \[2.5.0] ## \[2.5.0]
- [`5369898d`](https://github.com/tauri-apps/plugins-workspace/commit/5369898db7a6098e3e2f43436100ea556d405628) ([#2067](https://github.com/tauri-apps/plugins-workspace/pull/2067) by [@jLynx](https://github.com/tauri-apps/plugins-workspace/../../jLynx)) Fix update installation on macOS when using an user without admin privileges. - [`5369898d`](https://github.com/tauri-apps/plugins-workspace/commit/5369898db7a6098e3e2f43436100ea556d405628) ([#2067](https://github.com/tauri-apps/plugins-workspace/pull/2067) by [@jLynx](https://github.com/tauri-apps/plugins-workspace/../../jLynx)) Fix update installation on macOS when using an user without admin privileges.

@ -1,6 +1,6 @@
[package] [package]
name = "tauri-plugin-updater" name = "tauri-plugin-updater"
version = "2.5.0" version = "2.5.1"
description = "In-app updates for Tauri applications." description = "In-app updates for Tauri applications."
edition = { workspace = true } edition = { workspace = true }
authors = { workspace = true } authors = { workspace = true }
@ -43,7 +43,7 @@ base64 = "0.22"
semver = { version = "1", features = ["serde"] } semver = { version = "1", features = ["serde"] }
futures-util = "0.3" futures-util = "0.3"
tempfile = "3" tempfile = "3"
infer = "0.16" infer = "0.19"
percent-encoding = "2.3" percent-encoding = "2.3"
[target."cfg(target_os = \"windows\")".dependencies] [target."cfg(target_os = \"windows\")".dependencies]

@ -1,6 +1,6 @@
{ {
"name": "@tauri-apps/plugin-updater", "name": "@tauri-apps/plugin-updater",
"version": "2.5.0", "version": "2.5.1",
"license": "MIT OR Apache-2.0", "license": "MIT OR Apache-2.0",
"authors": [ "authors": [
"Tauri Programme within The Commons Conservancy" "Tauri Programme within The Commons Conservancy"

@ -4,7 +4,7 @@
use std::{ use std::{
collections::HashMap, collections::HashMap,
ffi::{OsStr, OsString}, ffi::OsString,
io::Cursor, io::Cursor,
path::{Path, PathBuf}, path::{Path, PathBuf},
str::FromStr, str::FromStr,
@ -12,6 +12,9 @@ use std::{
time::Duration, time::Duration,
}; };
#[cfg(not(target_os = "macos"))]
use std::ffi::OsStr;
use base64::Engine; use base64::Engine;
use futures_util::StreamExt; use futures_util::StreamExt;
use http::HeaderName; use http::HeaderName;
@ -383,26 +386,29 @@ impl Updater {
.send() .send()
.await; .await;
if let Ok(res) = response { match response {
if res.status().is_success() { Ok(res) => {
// no updates found! if res.status().is_success() {
if StatusCode::NO_CONTENT == res.status() { // no updates found!
return Ok(None); if StatusCode::NO_CONTENT == res.status() {
}; return Ok(None);
};
raw_json = Some(res.json().await?);
match serde_json::from_value::<RemoteRelease>(raw_json.clone().unwrap()) raw_json = Some(res.json().await?);
.map_err(Into::into) match serde_json::from_value::<RemoteRelease>(raw_json.clone().unwrap())
{ .map_err(Into::into)
Ok(release) => { {
last_error = None; Ok(release) => {
remote_release = Some(release); last_error = None;
// we found a relase, break the loop remote_release = Some(release);
break; // we found a relase, break the loop
break;
}
Err(err) => last_error = Some(err),
} }
Err(err) => last_error = Some(err),
} }
} }
Err(err) => last_error = Some(err.into()),
} }
} }

@ -63,8 +63,6 @@ fn build_app(cwd: &Path, config: &Config, bundle_updater: bool, target: BundleTa
if bundle_updater { if bundle_updater {
#[cfg(windows)] #[cfg(windows)]
command.args(["--bundles", "msi", "nsis"]); command.args(["--bundles", "msi", "nsis"]);
command.args(["--bundles", "updater"]);
} else { } else {
#[cfg(windows)] #[cfg(windows)]
command.args(["--bundles", target.name()]); command.args(["--bundles", target.name()]);

@ -67,8 +67,6 @@ mod v1 {
if bundle_updater { if bundle_updater {
#[cfg(windows)] #[cfg(windows)]
command.args(["--bundles", "msi", "nsis"]); command.args(["--bundles", "msi", "nsis"]);
command.args(["--bundles", "updater"]);
} else { } else {
#[cfg(windows)] #[cfg(windows)]
command.args(["--bundles", target.name()]); command.args(["--bundles", target.name()]);
@ -173,8 +171,6 @@ mod v2 {
if bundle_updater { if bundle_updater {
#[cfg(windows)] #[cfg(windows)]
command.args(["--bundles", "msi", "nsis"]); command.args(["--bundles", "msi", "nsis"]);
command.args(["--bundles", "updater"]);
} else { } else {
#[cfg(windows)] #[cfg(windows)]
command.args(["--bundles", target.name()]); command.args(["--bundles", target.name()]);

@ -9,9 +9,9 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"devDependencies": { "devDependencies": {
"@tauri-apps/cli": "2.2.7", "@tauri-apps/cli": "2.3.1",
"typescript": "^5.3.3", "typescript": "^5.7.3",
"vite": "^6.0.0" "vite": "^6.2.0"
}, },
"dependencies": { "dependencies": {
"tauri-plugin-websocket-api": "link:..\\.." "tauri-plugin-websocket-api": "link:..\\.."

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

@ -2,9 +2,9 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import { readFileSync } from 'fs' import { readFileSync } from 'node:fs'
import { join } from 'path' import { dirname, join } from 'node:path'
import { cwd } from 'process' import { cwd } from 'node:process'
import { nodeResolve } from '@rollup/plugin-node-resolve' import { nodeResolve } from '@rollup/plugin-node-resolve'
import typescript from '@rollup/plugin-typescript' import typescript from '@rollup/plugin-typescript'
import terser from '@rollup/plugin-terser' import terser from '@rollup/plugin-terser'
@ -53,7 +53,7 @@ export function createConfig(options = {}) {
plugins: [ plugins: [
typescript({ typescript({
declaration: true, declaration: true,
declarationDir: `./${pkg.exports.import.split('/')[0]}` declarationDir: dirname(pkg.exports.import)
}) })
], ],
external: [ external: [

Loading…
Cancel
Save