diff --git a/Cargo.lock b/Cargo.lock index 643a7437..917c054a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4555,6 +4555,7 @@ name = "tauri-plugin-single-instance" version = "0.0.0" dependencies = [ "log", + "semver 1.0.16", "serde", "serde_json", "tauri", diff --git a/Cargo.toml b/Cargo.toml index 94a7e79d..702e4ffc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ serde = { version = "1", features = ["derive"] } log = "0.4" tauri = "1" tauri-build = "1" +semver = "1" serde_json = "1" thiserror = "1" diff --git a/plugins/single-instance/Cargo.toml b/plugins/single-instance/Cargo.toml index be46f3aa..b7ef93a1 100644 --- a/plugins/single-instance/Cargo.toml +++ b/plugins/single-instance/Cargo.toml @@ -11,6 +11,7 @@ exclude = ["/examples"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +semver.workspace = true serde.workspace = true serde_json.workspace = true tauri.workspace = true diff --git a/plugins/single-instance/src/lib.rs b/plugins/single-instance/src/lib.rs index a2ff71af..72360ed2 100644 --- a/plugins/single-instance/src/lib.rs +++ b/plugins/single-instance/src/lib.rs @@ -10,6 +10,9 @@ mod platform_impl; #[path = "platform_impl/macos.rs"] mod platform_impl; + +mod semver_compat; + pub(crate) type SingleInstanceCallback = dyn FnMut(&AppHandle, Vec, String) + Send + Sync + 'static; diff --git a/plugins/single-instance/src/platform_impl/linux.rs b/plugins/single-instance/src/platform_impl/linux.rs index 513526d4..601485a6 100644 --- a/plugins/single-instance/src/platform_impl/linux.rs +++ b/plugins/single-instance/src/platform_impl/linux.rs @@ -2,7 +2,7 @@ use std::sync::Arc; -use crate::SingleInstanceCallback; +use crate::{SingleInstanceCallback, semver_compat::semver_compat_string}; use tauri::{ plugin::{self, TauriPlugin}, AppHandle, Config, Manager, RunEvent, Runtime, @@ -26,14 +26,17 @@ impl SingleInstanceDBus { } } -fn dbus_id(config: Arc) -> String { - config.tauri.bundle.identifier.replace(['.', '-'], "_") +fn dbus_id(config: Arc, version: semver::Version) -> String { + let mut id = config.tauri.bundle.identifier.replace(['.', '-'], "_"); + id.push('_'); + id.push_str(semver_compat_string(version).as_str()); + id } pub fn init(f: Box>) -> TauriPlugin { plugin::Builder::new("single-instance") .setup(|app| { - let id = dbus_id(app.config()); + let id = dbus_id(app.config(), app.package_info().version.clone()); let single_instance_dbus = SingleInstanceDBus { callback: f, app_handle: app.clone(), @@ -85,7 +88,7 @@ pub fn init(f: Box>) -> TauriPlugin { pub fn destroy>(manager: &M) { if let Some(connection) = manager.try_state::() { - let dbus_name = format!("org.{}.SingleInstance", dbus_id(manager.config())); + let dbus_name = format!("org.{}.SingleInstance", dbus_id(manager.config(), manager.app_handle().package_info().version.clone())); let _ = connection.0.release_name(dbus_name); } } diff --git a/plugins/single-instance/src/platform_impl/windows.rs b/plugins/single-instance/src/platform_impl/windows.rs index 5919d3e1..3d977c97 100644 --- a/plugins/single-instance/src/platform_impl/windows.rs +++ b/plugins/single-instance/src/platform_impl/windows.rs @@ -1,6 +1,6 @@ #![cfg(target_os = "windows")] -use crate::SingleInstanceCallback; +use crate::{SingleInstanceCallback, semver_compat::semver_compat_string}; use std::ffi::CStr; use tauri::{ plugin::{self, TauriPlugin}, @@ -29,7 +29,9 @@ const WMCOPYDATA_SINGLE_INSTANCE_DATA: usize = 1542; pub fn init(f: Box>) -> TauriPlugin { plugin::Builder::new("single-instance") .setup(|app| { - let id = &app.config().tauri.bundle.identifier; + let mut id = (&app.config().tauri.bundle.identifier).to_owned(); + id.push('_'); + id.push_str(semver_compat_string(app.package_info().version.clone()).as_str()); let class_name = encode_wide(format!("{id}-sic")); let window_name = encode_wide(format!("{id}-siw")); diff --git a/plugins/single-instance/src/semver_compat.rs b/plugins/single-instance/src/semver_compat.rs new file mode 100644 index 00000000..497db738 --- /dev/null +++ b/plugins/single-instance/src/semver_compat.rs @@ -0,0 +1,16 @@ +/// Takes a version and spits out a String with trailing .x, thus only considering the digits +/// relevant regarding semver compatibility +pub fn semver_compat_string(version: semver::Version) -> String { + if version.pre.is_empty() == false { // for pre-release always treat each version separately + return version.to_string().replace(['.', '-'], "_") + } + match version.major { + 0 => { + match version.minor { + 0 => format!("0_0_{}", version.patch), + _ => format!("0_{}_x", version.minor), + } + }, + _ => format!("{}_x_x", version.major) + } +} \ No newline at end of file