diff --git a/backend/tauri/src/core/commands/mod.rs b/backend/tauri/src/core/commands/mod.rs index 0cd93cd4cd..af5484acf6 100644 --- a/backend/tauri/src/core/commands/mod.rs +++ b/backend/tauri/src/core/commands/mod.rs @@ -1,5 +1,10 @@ +use std::str::FromStr; + use anyhow::Ok; -use clap::{Parser, Subcommand}; +use clap::{Args, Parser, Subcommand}; +use tauri::utils::platform::current_exe; + +use crate::utils; #[derive(Parser, Debug)] #[command(name = "clash-nyanpasu", version, about, long_about = None)] @@ -12,6 +17,12 @@ pub struct Cli { enum Commands { #[command(about = "Migrate home directory to another path.")] MigrateHomeDir { target_path: String }, + #[command(about = "A launch bridge to resolve the delay exit issue.")] + Launch { + // FIXME: why the raw arg is not working? + #[arg(raw = true)] + args: Vec, + }, } struct DelayedExitGuard; @@ -34,6 +45,22 @@ pub fn parse() -> anyhow::Result<()> { Commands::MigrateHomeDir { target_path } => { self::handler::migrate_home_dir_handler(target_path).unwrap(); } + Commands::Launch { args } => { + let _ = utils::init::check_singleton().unwrap(); + let appimage: Option = { + #[cfg(target_os = "linux")] + { + std::env::var_os("APPIMAGE").map(|s| s.to_string_lossy().to_string()) + } + #[cfg(not(target_os = "linux"))] + None + }; + let path = match appimage { + Some(appimage) => std::path::PathBuf::from_str(&appimage).unwrap(), + None => current_exe().unwrap(), + }; + std::process::Command::new(path).args(args).spawn().unwrap(); + } } drop(guard); std::process::exit(0); diff --git a/backend/tauri/src/main.rs b/backend/tauri/src/main.rs index 66a3a94eb0..a38c0ce775 100644 --- a/backend/tauri/src/main.rs +++ b/backend/tauri/src/main.rs @@ -13,9 +13,8 @@ mod utils; use crate::{ config::Config, core::{commands, handle::Handle}, - utils::{dirs, init, resolve}, + utils::{init, resolve}, }; -use anyhow::Context; use tauri::{api, Manager, SystemTray}; rust_i18n::i18n!("../../locales"); @@ -77,7 +76,7 @@ fn main() -> std::io::Result<()> { rust_i18n::set_locale(verge.as_str()); // show a dialog to print the single instance error - single_instance_result.unwrap(); + let _singleton = single_instance_result.unwrap(); // hold the guard until the end of the program #[allow(unused_mut)] let mut builder = tauri::Builder::default() diff --git a/backend/tauri/src/utils/help.rs b/backend/tauri/src/utils/help.rs index fb762c52ec..5d5096c59c 100644 --- a/backend/tauri/src/utils/help.rs +++ b/backend/tauri/src/utils/help.rs @@ -14,7 +14,10 @@ use std::{ str::FromStr, }; use tauri::{ - api::shell::{open, Program}, + api::{ + process::current_binary, + shell::{open, Program}, + }, AppHandle, Manager, }; use tracing::{debug, warn}; @@ -232,7 +235,21 @@ pub fn quit_application(app_handle: &AppHandle) { #[instrument(skip(app_handle))] pub fn restart_application(app_handle: &AppHandle) { cleanup_processes(app_handle); - tauri::api::process::restart(&app_handle.env()); + let env = app_handle.env(); + let path = current_binary(&env).unwrap(); + let arg = std::env::args().collect::>(); + let mut args = vec!["launch".to_string(), "--".to_string()]; + // filter out the first arg + if arg.len() > 1 { + args.extend(arg.iter().skip(1).cloned()); + } + tracing::info!("restart app: {:#?} with args: {:#?}", path, args); + std::process::Command::new(path) + .args(args) + .spawn() + .expect("application failed to start"); + app_handle.exit(0); + std::process::exit(0); } #[macro_export] diff --git a/backend/tauri/src/utils/init/mod.rs b/backend/tauri/src/utils/init/mod.rs index c233997c86..3ccb36a50c 100644 --- a/backend/tauri/src/utils/init/mod.rs +++ b/backend/tauri/src/utils/init/mod.rs @@ -196,13 +196,13 @@ pub fn init_service() -> Result<()> { Ok(()) } -pub fn check_singleton() -> Result<()> { +pub fn check_singleton() -> Result { let placeholder = super::dirs::get_single_instance_placeholder(); for i in 0..5 { let instance = single_instance::SingleInstance::new(&placeholder) .context("failed to create single instance")?; if instance.is_single() { - return Ok(()); + return Ok(instance); } if i != 4 { std::thread::sleep(std::time::Duration::from_secs(1));