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/*'
- uses: pnpm/action-setup@v4
with:
version: 9.x.x
version: 10.x.x
run_install: true
- name: audit
run: pnpm audit

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

@ -39,7 +39,7 @@ jobs:
- uses: pnpm/action-setup@v4
with:
version: 9.x.x
version: 10.x.x
run_install: true
- name: cargo login
@ -75,7 +75,7 @@ jobs:
- name: Create Pull Request With Versions Bumped
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'
with:
title: 'Publish New Versions (${{ github.ref_name }})'

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

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

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

2
.gitignore vendored

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

750
Cargo.lock generated

File diff suppressed because it is too large Load Diff

@ -1,5 +1,19 @@
# 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]
### Dependencies

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

@ -1,5 +1,19 @@
# 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]
### Dependencies

@ -1,7 +1,7 @@
[package]
name = "api"
publish = false
version = "2.0.17"
version = "2.0.19"
description = "An example Tauri Application showcasing the api"
edition = "2021"
rust-version = { workspace = true }
@ -19,7 +19,7 @@ serde_json = { workspace = true }
serde = { workspace = true }
tiny_http = "0.12"
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 = [
"watch",
] }
@ -33,7 +33,7 @@ tauri-plugin-notification = { path = "../../../plugins/notification", version =
] }
tauri-plugin-os = { path = "../../../plugins/os", 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-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]
tauri-plugin-cli = { path = "../../../plugins/cli", 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" }
[target."cfg(any(target_os = \"android\", target_os = \"ios\"))".dependencies]

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

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

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

@ -265,18 +265,15 @@ mod imp {
.to_string();
let key_reg = CURRENT_USER.create(&key_base)?;
key_reg.set_string(
"",
&format!("URL:{} protocol", self.app.config().identifier),
)?;
key_reg.set_string("", format!("URL:{} protocol", self.app.config().identifier))?;
key_reg.set_string("URL Protocol", "")?;
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"))?;
cmd_reg.set_string("", &format!("\"{exe}\" \"%1\""))?;
cmd_reg.set_string("", format!("\"{exe}\" \"%1\""))?;
Ok(())
}

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

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

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

@ -58,6 +58,8 @@ pub enum Error {
TimeFormat(#[from] time::error::Format),
#[error(transparent)]
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.
@ -230,6 +232,7 @@ pub struct Builder {
timezone_strategy: TimezoneStrategy,
max_file_size: u128,
targets: Vec<Target>,
is_skip_logger: bool,
}
impl Default for Builder {
@ -258,6 +261,7 @@ impl Default for Builder {
timezone_strategy: DEFAULT_TIMEZONE_STRATEGY,
max_file_size: DEFAULT_MAX_FILE_SIZE,
targets: DEFAULT_LOG_TARGETS.into(),
is_skip_logger: false,
}
}
}
@ -339,6 +343,22 @@ impl Builder {
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.
///
/// ```rust
@ -481,6 +501,9 @@ impl Builder {
self,
app_handle: &AppHandle<R>,
) -> 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 (max_level, log) = Self::acquire_logger(
app_handle,
@ -497,6 +520,7 @@ impl Builder {
pub fn build<R: Runtime>(self) -> TauriPlugin<R> {
Self::plugin_builder()
.setup(move |app_handle, _api| {
if !self.is_skip_logger {
let (max_level, log) = Self::acquire_logger(
app_handle,
self.dispatch,
@ -505,9 +529,8 @@ impl Builder {
self.max_file_size,
self.targets,
)?;
attach_logger(max_level, log)?;
}
Ok(())
})
.build()

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

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

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

@ -56,7 +56,7 @@ impl<R: Runtime> Opener<R> {
/// - **Android / iOS**: Always opens using default program.
#[cfg(desktop)]
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.
@ -108,7 +108,7 @@ impl<R: Runtime> Opener<R> {
path: impl Into<String>,
with: Option<impl Into<String>>,
) -> 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.

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

@ -75,7 +75,7 @@ impl<R: Runtime> Shell<R> {
#[deprecated(since = "2.1.0", note = "Use tauri-plugin-opener instead.")]
#[allow(deprecated)]
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.

@ -1,5 +1,9 @@
# 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]
- [`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]
name = "tauri-plugin-single-instance"
version = "2.2.1"
version = "2.2.2"
description = "Ensure a single instance of your tauri app is running."
authors = { workspace = true }
license = { workspace = true }

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

@ -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"

@ -9,7 +9,6 @@
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_cli::init())
.plugin(tauri_plugin_single_instance::init(|app, argv, cwd| {
println!("{}, {argv:?}, {cwd}", app.package_info().name);
}))

@ -20,18 +20,38 @@ use windows_sys::Win32::{
},
UI::WindowsAndMessaging::{
self as w32wm, CreateWindowExW, DefWindowProcW, DestroyWindow, FindWindowW,
RegisterClassExW, SendMessageW, GWL_STYLE, GWL_USERDATA, WINDOW_LONG_PTR_INDEX,
WM_COPYDATA, WM_DESTROY, WNDCLASSEXW, WS_EX_LAYERED, WS_EX_NOACTIVATE, WS_EX_TOOLWINDOW,
WS_EX_TRANSPARENT, WS_OVERLAPPED, WS_POPUP, WS_VISIBLE,
RegisterClassExW, SendMessageW, CREATESTRUCTW, GWLP_USERDATA, GWL_STYLE,
WINDOW_LONG_PTR_INDEX, WM_COPYDATA, WM_CREATE, WM_DESTROY, WNDCLASSEXW, WS_EX_LAYERED,
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 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")
.setup(|app, _api| {
#[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());
if !hwnd.is_null() {
let data = format!(
"{}|{}\0",
std::env::current_dir()
.unwrap_or_default()
.to_str()
.unwrap_or_default(),
std::env::args().collect::<Vec<String>>().join("|")
);
let cwd = std::env::current_dir().unwrap_or_default();
let cwd = cwd.to_str().unwrap_or_default();
let args = std::env::args().collect::<Vec<String>>().join("|");
let data = format!("{cwd}|{args}\0",);
let bytes = data.as_bytes();
let cds = COPYDATASTRUCT {
dwData: WMCOPYDATA_SINGLE_INSTANCE_DATA,
cbData: bytes.len() as _,
lpData: bytes.as_ptr() as _,
};
SendMessageW(hwnd, WM_COPYDATA, 0, &cds as *const _ as _);
app.cleanup_before_exit();
std::process::exit(0);
}
@ -76,15 +97,12 @@ pub fn init<R: Runtime>(f: Box<SingleInstanceCallback<R>>) -> TauriPlugin<R> {
} else {
app.manage(MutexHandle(hmutex as _));
let hwnd = create_event_target_window::<R>(&class_name, &window_name);
unsafe {
SetWindowLongPtrW(
hwnd,
GWL_USERDATA,
Box::into_raw(Box::new((app.clone(), f))) as _,
)
let userdata = UserData {
app: app.clone(),
callback,
};
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 _));
}
@ -116,32 +134,43 @@ unsafe extern "system" fn single_instance_window_proc<R: Runtime>(
wparam: WPARAM,
lparam: LPARAM,
) -> LRESULT {
let data_ptr = GetWindowLongPtrW(hwnd, GWL_USERDATA)
as *mut (AppHandle<R>, Box<SingleInstanceCallback<R>>);
let (app_handle, callback) = &mut *data_ptr;
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 => {
let cds_ptr = lparam as *const COPYDATASTRUCT;
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 mut s = data.split('|');
let cwd = s.next().unwrap();
let args = s.map(|s| s.to_string()).collect();
callback(app_handle, args, cwd.to_string());
userdata.run_callback(args, cwd.to_string());
}
1
}
WM_DESTROY => {
let _ = Box::from_raw(data_ptr);
let userdata = UserData::<R>::from_hwnd_raw(hwnd);
drop(Box::from_raw(userdata));
0
}
_ => 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 {
let class = WNDCLASSEXW {
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(),
GetModuleHandleW(std::ptr::null()),
std::ptr::null(),
userdata as _,
);
SetWindowLongPtrW(
hwnd,

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

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

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

@ -4,7 +4,7 @@
use std::{
collections::HashMap,
ffi::{OsStr, OsString},
ffi::OsString,
io::Cursor,
path::{Path, PathBuf},
str::FromStr,
@ -12,6 +12,9 @@ use std::{
time::Duration,
};
#[cfg(not(target_os = "macos"))]
use std::ffi::OsStr;
use base64::Engine;
use futures_util::StreamExt;
use http::HeaderName;
@ -383,7 +386,8 @@ impl Updater {
.send()
.await;
if let Ok(res) = response {
match response {
Ok(res) => {
if res.status().is_success() {
// no updates found!
if StatusCode::NO_CONTENT == res.status() {
@ -404,6 +408,8 @@ impl Updater {
}
}
}
Err(err) => last_error = Some(err.into()),
}
}
// Last error is cleaned on success.

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

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

@ -9,9 +9,9 @@
"preview": "vite preview"
},
"devDependencies": {
"@tauri-apps/cli": "2.2.7",
"typescript": "^5.3.3",
"vite": "^6.0.0"
"@tauri-apps/cli": "2.3.1",
"typescript": "^5.7.3",
"vite": "^6.2.0"
},
"dependencies": {
"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: MIT
import { readFileSync } from 'fs'
import { join } from 'path'
import { cwd } from 'process'
import { readFileSync } from 'node:fs'
import { dirname, join } from 'node:path'
import { cwd } from 'node:process'
import { nodeResolve } from '@rollup/plugin-node-resolve'
import typescript from '@rollup/plugin-typescript'
import terser from '@rollup/plugin-terser'
@ -53,7 +53,7 @@ export function createConfig(options = {}) {
plugins: [
typescript({
declaration: true,
declarationDir: `./${pkg.exports.import.split('/')[0]}`
declarationDir: dirname(pkg.exports.import)
})
],
external: [

Loading…
Cancel
Save