From cc0e930d34db00bdc50264507f94e7afac6b2df1 Mon Sep 17 00:00:00 2001 From: GyDi Date: Sat, 15 Jan 2022 21:55:05 +0800 Subject: [PATCH] feat: supports auto launch on macos and windows --- src-tauri/src/core/verge.rs | 99 ++++++++++++++++++++-------------- src-tauri/src/utils/mod.rs | 1 - src-tauri/src/utils/resolve.rs | 5 +- src-tauri/src/utils/startup.rs | 74 ------------------------- 4 files changed, 62 insertions(+), 117 deletions(-) delete mode 100644 src-tauri/src/utils/startup.rs diff --git a/src-tauri/src/core/verge.rs b/src-tauri/src/core/verge.rs index 3a1077a..eab6350 100644 --- a/src-tauri/src/core/verge.rs +++ b/src-tauri/src/core/verge.rs @@ -1,6 +1,6 @@ -use crate::utils::{config, dirs, startup, sysopt::SysProxyConfig}; +use crate::utils::{config, dirs, sysopt::SysProxyConfig}; +use auto_launch::{AutoLaunch, AutoLaunchBuilder}; use serde::{Deserialize, Serialize}; -use std::path::PathBuf; use tauri::api::path::resource_dir; /// ### `verge.yaml` schema @@ -14,7 +14,7 @@ pub struct VergeConfig { pub theme_blur: Option, /// can the app auto startup - pub enable_self_startup: Option, + pub enable_auto_launch: Option, /// set system proxy pub enable_system_proxy: Option, @@ -49,7 +49,7 @@ pub struct Verge { pub cur_sysproxy: Option, - pub exe_path: Option, + pub auto_launch: Option, } impl Default for Verge { @@ -64,7 +64,7 @@ impl Verge { config: VergeConfig::new(), old_sysproxy: None, cur_sysproxy: None, - exe_path: None, + auto_launch: None, } } @@ -101,53 +101,61 @@ impl Verge { } } - /// set the exe_path - pub fn set_exe_path(&mut self, package_info: &tauri::PackageInfo) { - let exe = if cfg!(target_os = "windows") { - "clash-verge.exe" - } else { - "clash-verge" - }; - let path = resource_dir(package_info).unwrap().join(exe); - self.exe_path = Some(path); + /// init the auto launch + pub fn init_launch(&mut self, package_info: &tauri::PackageInfo) { + let app_name = "clash-verge"; + let app_path = get_app_path(app_name); + let app_path = resource_dir(package_info).unwrap().join(app_path); + let app_path = app_path.as_os_str().to_str().unwrap(); + + let auto = AutoLaunchBuilder::new() + .set_app_name(app_name) + .set_app_path(app_path) + .build(); + + self.auto_launch = Some(auto); } /// sync the startup when run the app - pub fn sync_startup(&self) -> Result<(), String> { - let enable = self.config.enable_self_startup.clone().unwrap_or(false); - + pub fn sync_launch(&self) -> Result<(), String> { + let enable = self.config.enable_auto_launch.clone().unwrap_or(false); if !enable { return Ok(()); } - if self.exe_path.is_none() { - return Err("should init the exe_path first".into()); + + if self.auto_launch.is_none() { + return Err("should init the auto launch first".into()); } - let exe_path = self.exe_path.clone().unwrap(); - match startup::get_startup(&exe_path) { - Ok(sys_enable) => { - if sys_enable || (!sys_enable && startup::set_startup(true, &exe_path).is_ok()) { - Ok(()) - } else { - Err("failed to sync startup".into()) - } + let auto_launch = self.auto_launch.clone().unwrap(); + + let is_enabled = auto_launch.is_enabled().unwrap_or(false); + if !is_enabled { + if let Err(_) = auto_launch.enable() { + return Err("failed to enable auto-launch".into()); } - Err(_) => Err("failed to get system startup info".into()), } + + Ok(()) } /// update the startup - fn update_startup(&mut self, enable: bool) -> Result<(), String> { - let conf_enable = self.config.enable_self_startup.clone().unwrap_or(false); + fn update_launch(&mut self, enable: bool) -> Result<(), String> { + let conf_enable = self.config.enable_auto_launch.clone().unwrap_or(false); if enable == conf_enable { return Ok(()); } - if self.exe_path.is_none() { - return Err("should init the exe_path first".into()); - } - let exe_path = self.exe_path.clone().unwrap(); - match startup::set_startup(enable, &exe_path) { + + let auto_launch = self.auto_launch.clone().unwrap(); + + let result = if enable { + auto_launch.enable() + } else { + auto_launch.disable() + }; + + match result { Ok(_) => Ok(()), Err(_) => Err("failed to set system startup info".into()), } @@ -166,10 +174,10 @@ impl Verge { } // should update system startup - if patch.enable_self_startup.is_some() { - let enable = patch.enable_self_startup.unwrap(); - self.update_startup(enable)?; - self.config.enable_self_startup = Some(enable); + if patch.enable_auto_launch.is_some() { + let enable = patch.enable_auto_launch.unwrap(); + self.update_launch(enable)?; + self.config.enable_auto_launch = Some(enable); } // should update system proxy @@ -187,7 +195,7 @@ impl Verge { } // todo - // should update system proxt too + // should update system proxy too if patch.system_proxy_bypass.is_some() { self.config.system_proxy_bypass = patch.system_proxy_bypass; } @@ -195,3 +203,14 @@ impl Verge { self.config.save_file() } } + +// Get the target app_path +fn get_app_path(app_name: &str) -> String { + #[cfg(target_os = "linux")] + let ext = ""; + #[cfg(target_os = "macos")] + let ext = ".app"; + #[cfg(target_os = "windows")] + let ext = ".exe"; + String::from(app_name) + ext +} diff --git a/src-tauri/src/utils/mod.rs b/src-tauri/src/utils/mod.rs index 2ba9a57..a5fe22b 100644 --- a/src-tauri/src/utils/mod.rs +++ b/src-tauri/src/utils/mod.rs @@ -4,5 +4,4 @@ pub mod fetch; pub mod init; pub mod resolve; pub mod server; -pub mod startup; pub mod sysopt; diff --git a/src-tauri/src/utils/resolve.rs b/src-tauri/src/utils/resolve.rs index 281fecb..96cb9c4 100644 --- a/src-tauri/src/utils/resolve.rs +++ b/src-tauri/src/utils/resolve.rs @@ -9,6 +9,7 @@ pub fn resolve_setup(app: &App) { let window = app.get_window("main").unwrap(); window.set_shadow(true); + // enable system blur use tauri_plugin_vibrancy::Vibrancy; #[cfg(target_os = "windows")] window.apply_blur(); @@ -42,9 +43,9 @@ pub fn resolve_setup(app: &App) { log::error!("{}", err); } - verge.set_exe_path(app.package_info()); verge.init_sysproxy(clash.info.port.clone()); - if let Err(err) = verge.sync_startup() { + verge.init_launch(app.package_info()); + if let Err(err) = verge.sync_launch() { log::error!("{}", err); } } diff --git a/src-tauri/src/utils/startup.rs b/src-tauri/src/utils/startup.rs deleted file mode 100644 index 224e795..0000000 --- a/src-tauri/src/utils/startup.rs +++ /dev/null @@ -1,74 +0,0 @@ -use std::io; -use std::path::PathBuf; - -static APP_KEY: &str = "ClashVerge"; - -/// get the startup value -/// whether as same as the exe_path -#[cfg(target_os = "windows")] -pub fn get_startup(exe_path: &PathBuf) -> io::Result { - use winreg::enums::*; - use winreg::RegKey; - - let hkcu = RegKey::predef(HKEY_CURRENT_USER); - let cur_var = hkcu.open_subkey_with_flags( - "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", - KEY_READ, - )?; - - match cur_var.get_value::(APP_KEY) { - Ok(path) => { - let exe_path = exe_path.clone(); - let exe_path = exe_path.as_os_str().to_str().unwrap(); - Ok(path == exe_path) - } - Err(_) => Ok(false), - } -} - -/// set the startup on windows -/// delete the reg key if disabled -#[cfg(target_os = "windows")] -pub fn set_startup(enable: bool, exe_path: &PathBuf) -> io::Result<()> { - use winreg::enums::*; - use winreg::RegKey; - - let hkcu = RegKey::predef(HKEY_CURRENT_USER); - let cur_var = hkcu.open_subkey_with_flags( - "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", - KEY_SET_VALUE, - )?; - - match enable { - true => { - let exe_path = exe_path.clone(); - let exe_path = exe_path.as_os_str().to_str().unwrap(); - cur_var.set_value::<&str, _>(APP_KEY, &exe_path) - } - false => cur_var.delete_value(APP_KEY), - } -} - -/// todo -#[cfg(target_os = "macos")] -pub fn get_startup(exe_path: &PathBuf) -> io::Result { - Ok(true) -} - -/// todo -#[cfg(target_os = "macos")] -pub fn set_startup(enable: bool, exe_path: &PathBuf) -> io::Result<()> { - Ok(()) -} - -#[cfg(target_os = "windows")] -#[test] -fn test() { - let path = PathBuf::from(r"D:\Software\Clash Verge\clash-verge.exe"); - - assert!(set_startup(true, &path).is_ok()); - assert_eq!(get_startup(&path).unwrap(), true); - - assert!(set_startup(false, &path).is_ok()); - assert_eq!(get_startup(&path).unwrap(), false); -}