Skip to main content

tauri_plugin_single_instance/
lib.rs

1// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
2// SPDX-License-Identifier: Apache-2.0
3// SPDX-License-Identifier: MIT
4
5//! Ensure a single instance of your tauri app is running.
6
7#![doc(
8    html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png",
9    html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png"
10)]
11#![cfg(not(any(target_os = "android", target_os = "ios")))]
12
13use tauri::{plugin::TauriPlugin, AppHandle, Manager, Runtime};
14
15#[cfg(target_os = "windows")]
16#[path = "platform_impl/windows.rs"]
17mod platform_impl;
18#[cfg(target_os = "linux")]
19#[path = "platform_impl/linux.rs"]
20mod platform_impl;
21#[cfg(target_os = "macos")]
22#[path = "platform_impl/macos.rs"]
23mod platform_impl;
24
25#[cfg(feature = "semver")]
26mod semver_compat;
27
28pub(crate) type SingleInstanceCallback<R> =
29    dyn FnMut(&AppHandle<R>, Vec<String>, String) + Send + Sync + 'static;
30
31pub fn init<R: Runtime, F: FnMut(&AppHandle<R>, Vec<String>, String) + Send + Sync + 'static>(
32    f: F,
33) -> TauriPlugin<R> {
34    Builder::new().callback(f).build()
35}
36
37pub fn destroy<R: Runtime, M: Manager<R>>(manager: &M) {
38    platform_impl::destroy(manager)
39}
40
41pub struct Builder<R: Runtime> {
42    callback: Box<SingleInstanceCallback<R>>,
43    dbus_id: Option<String>,
44}
45
46impl<R: Runtime> Default for Builder<R> {
47    fn default() -> Self {
48        Self {
49            callback: Box::new(move |_app, _args, _| {
50                #[cfg(feature = "deep-link")]
51                if let Some(deep_link) = _app.try_state::<tauri_plugin_deep_link::DeepLink<R>>() {
52                    deep_link.handle_cli_arguments(_args.iter());
53                }
54            }),
55            dbus_id: None,
56        }
57    }
58}
59
60impl<R: Runtime> Builder<R> {
61    pub fn new() -> Self {
62        Default::default()
63    }
64
65    /// Function to call when a secondary instance was opened by the user and killed by the plugin.
66    /// If the `deep-link` feature is enabled, the plugin triggers the deep-link plugin before executing the callback.
67    pub fn callback<F: FnMut(&AppHandle<R>, Vec<String>, String) + Send + Sync + 'static>(
68        mut self,
69        mut f: F,
70    ) -> Self {
71        self.callback = Box::new(move |app, args, cwd| {
72            #[cfg(feature = "deep-link")]
73            if let Some(deep_link) = app.try_state::<tauri_plugin_deep_link::DeepLink<R>>() {
74                deep_link.handle_cli_arguments(args.iter());
75            }
76            f(app, args, cwd)
77        });
78        self
79    }
80
81    /// Set a custom D-Bus ID, used on Linux. The plugin will append a `.SingleInstance` subname.
82    /// For example `com.mycompany.myapp` will result in the plugin registering its D-Bus service on `com.mycompany.myapp.SingleInstance`.
83    /// Usually you want the same base ID across all components in your app.
84    ///
85    /// Defaults to the app's bundle identifier set in tauri.conf.json.
86    pub fn dbus_id(mut self, dbus_id: impl Into<String>) -> Self {
87        self.dbus_id = Some(dbus_id.into());
88        self
89    }
90
91    pub fn build(self) -> TauriPlugin<R> {
92        platform_impl::init(
93            self.callback,
94            #[cfg(target_os = "linux")]
95            self.dbus_id,
96        )
97    }
98}