diff --git a/src-tauri/src/core/handle.rs b/src-tauri/src/core/handle.rs index 1ca9b6e..f734536 100644 --- a/src-tauri/src/core/handle.rs +++ b/src-tauri/src/core/handle.rs @@ -1,7 +1,6 @@ -use crate::data::*; +use super::tray::Tray; use crate::log_if_err; use anyhow::{bail, Result}; -use serde_yaml::Value; use tauri::{AppHandle, Manager, Window}; #[derive(Debug, Default, Clone)] @@ -46,62 +45,22 @@ impl Handle { } } - // update system tray state (clash config) - pub fn update_systray_clash(&self) -> Result<()> { - if self.app_handle.is_none() { - bail!("update_systray_clash unhandle error"); - } - - let app_handle = self.app_handle.as_ref().unwrap(); - - let global = Data::global(); - let clash = global.clash.lock(); - let mode = clash - .config - .get(&Value::from("mode")) - .map(|val| val.as_str().unwrap_or("rule")) - .unwrap_or("rule"); - - let tray = app_handle.tray_handle(); - - tray.get_item("rule_mode").set_selected(mode == "rule")?; - tray - .get_item("global_mode") - .set_selected(mode == "global")?; - tray - .get_item("direct_mode") - .set_selected(mode == "direct")?; - tray - .get_item("script_mode") - .set_selected(mode == "script")?; - - Ok(()) - } - - /// update the system tray state (verge config) pub fn update_systray(&self) -> Result<()> { if self.app_handle.is_none() { bail!("update_systray unhandle error"); } - let app_handle = self.app_handle.as_ref().unwrap(); - let tray = app_handle.tray_handle(); - - let global = Data::global(); - let verge = global.verge.lock(); - let system_proxy = verge.enable_system_proxy.as_ref(); - let tun_mode = verge.enable_tun_mode.as_ref(); - - tray - .get_item("system_proxy") - .set_selected(*system_proxy.unwrap_or(&false))?; - tray - .get_item("tun_mode") - .set_selected(*tun_mode.unwrap_or(&false))?; - - // update verge config - self.refresh_verge(); + Tray::update_systray(app_handle)?; + Ok(()) + } + /// update the system tray state + pub fn update_systray_part(&self) -> Result<()> { + if self.app_handle.is_none() { + bail!("update_systray unhandle error"); + } + let app_handle = self.app_handle.as_ref().unwrap(); + Tray::update_part(app_handle)?; Ok(()) } } diff --git a/src-tauri/src/core/mod.rs b/src-tauri/src/core/mod.rs index 1313049..631070d 100644 --- a/src-tauri/src/core/mod.rs +++ b/src-tauri/src/core/mod.rs @@ -16,6 +16,7 @@ mod hotkey; mod service; mod sysopt; mod timer; +pub mod tray; pub use self::service::*; @@ -64,8 +65,7 @@ impl Core { drop(sysopt); let handle = self.handle.lock(); - log_if_err!(handle.update_systray()); - log_if_err!(handle.update_systray_clash()); + log_if_err!(handle.update_systray_part()); drop(handle); let mut hotkey = self.hotkey.lock(); @@ -136,7 +136,7 @@ impl Core { if has_mode { let handle = self.handle.lock(); - handle.update_systray_clash()?; + handle.update_systray_part()?; } Ok(()) @@ -155,6 +155,7 @@ impl Core { let system_proxy = patch.enable_system_proxy; let proxy_bypass = patch.system_proxy_bypass; let proxy_guard = patch.enable_proxy_guard; + let language = patch.language; #[cfg(target_os = "windows")] { @@ -197,9 +198,13 @@ impl Core { sysopt.guard_proxy(); } - if system_proxy.is_some() || tun_mode.is_some() { + // 更新tray + if language.is_some() { let handle = self.handle.lock(); handle.update_systray()?; + } else if system_proxy.is_some() || tun_mode.is_some() { + let handle = self.handle.lock(); + handle.update_systray_part()?; } if patch.hotkeys.is_some() { @@ -232,7 +237,7 @@ impl Core { // update tray let handle = handle.lock(); handle.refresh_clash(); - log_if_err!(handle.update_systray_clash()); + log_if_err!(handle.update_systray_part()); }); Ok(()) diff --git a/src-tauri/src/core/tray.rs b/src-tauri/src/core/tray.rs new file mode 100644 index 0000000..7bef9ae --- /dev/null +++ b/src-tauri/src/core/tray.rs @@ -0,0 +1,109 @@ +use crate::{data::Data, feat, utils::resolve}; +use anyhow::{Ok, Result}; +use tauri::{ + api, AppHandle, CustomMenuItem, Manager, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem, +}; + +pub struct Tray {} + +impl Tray { + pub fn tray_menu() -> SystemTrayMenu { + let data = Data::global(); + let zh = { + let verge = data.verge.lock(); + verge.language == Some("zh".into()) + }; + + if zh { + SystemTrayMenu::new() + .add_item(CustomMenuItem::new("open_window", "打开面板")) + .add_native_item(SystemTrayMenuItem::Separator) + .add_item(CustomMenuItem::new("rule_mode", "规则模式")) + .add_item(CustomMenuItem::new("global_mode", "全局模式")) + .add_item(CustomMenuItem::new("direct_mode", "直连模式")) + .add_item(CustomMenuItem::new("script_mode", "脚本模式")) + .add_native_item(SystemTrayMenuItem::Separator) + .add_item(CustomMenuItem::new("system_proxy", "系统代理")) + .add_item(CustomMenuItem::new("tun_mode", "TUN 模式")) + .add_item(CustomMenuItem::new("restart_clash", "重启 Clash")) + .add_item(CustomMenuItem::new("restart_app", "重启应用")) + .add_native_item(SystemTrayMenuItem::Separator) + .add_item(CustomMenuItem::new("quit", "退出").accelerator("CmdOrControl+Q")) + } else { + SystemTrayMenu::new() + .add_item(CustomMenuItem::new("open_window", "Dashboard")) + .add_native_item(SystemTrayMenuItem::Separator) + .add_item(CustomMenuItem::new("rule_mode", "Rule Mode")) + .add_item(CustomMenuItem::new("global_mode", "Global Mode")) + .add_item(CustomMenuItem::new("direct_mode", "Direct Mode")) + .add_item(CustomMenuItem::new("script_mode", "Script Mode")) + .add_native_item(SystemTrayMenuItem::Separator) + .add_item(CustomMenuItem::new("system_proxy", "System Proxy")) + .add_item(CustomMenuItem::new("tun_mode", "Tun Mode")) + .add_item(CustomMenuItem::new("restart_clash", "Restart Clash")) + .add_item(CustomMenuItem::new("restart_app", "Restart App")) + .add_native_item(SystemTrayMenuItem::Separator) + .add_item(CustomMenuItem::new("quit", "Quit").accelerator("CmdOrControl+Q")) + } + } + + pub fn update_systray(app_handle: &AppHandle) -> Result<()> { + app_handle.tray_handle().set_menu(Tray::tray_menu())?; + Tray::update_part(app_handle)?; + Ok(()) + } + + pub fn update_part(app_handle: &AppHandle) -> Result<()> { + let global = Data::global(); + let clash = global.clash.lock(); + let mode = clash + .config + .get(&serde_yaml::Value::from("mode")) + .map(|val| val.as_str().unwrap_or("rule")) + .unwrap_or("rule"); + + let tray = app_handle.tray_handle(); + + let _ = tray.get_item("rule_mode").set_selected(mode == "rule"); + let _ = tray.get_item("global_mode").set_selected(mode == "global"); + let _ = tray.get_item("direct_mode").set_selected(mode == "direct"); + let _ = tray.get_item("script_mode").set_selected(mode == "script"); + + let verge = global.verge.lock(); + let system_proxy = verge.enable_system_proxy.as_ref().unwrap_or(&false); + let tun_mode = verge.enable_tun_mode.as_ref().unwrap_or(&false); + + let _ = tray.get_item("system_proxy").set_selected(*system_proxy); + let _ = tray.get_item("tun_mode").set_selected(*tun_mode); + + Ok(()) + } + + pub fn on_system_tray_event(app_handle: &AppHandle, event: SystemTrayEvent) { + match event { + SystemTrayEvent::MenuItemClick { id, .. } => match id.as_str() { + mode @ ("rule_mode" | "global_mode" | "direct_mode" | "script_mode") => { + let mode = &mode[0..mode.len() - 5]; + feat::change_clash_mode(mode); + } + + "open_window" => resolve::create_window(app_handle), + "system_proxy" => feat::toggle_system_proxy(), + "tun_mode" => feat::toggle_tun_mode(), + "restart_clash" => feat::restart_clash_core(), + "restart_app" => api::process::restart(&app_handle.env()), + "quit" => { + resolve::resolve_reset(); + api::process::kill_children(); + app_handle.exit(0); + } + _ => {} + }, + #[cfg(target_os = "windows")] + SystemTrayEvent::LeftClick { .. } => { + resolve::create_window(app_handle); + } + _ => {} + } + } +} diff --git a/src-tauri/src/feat.rs b/src-tauri/src/feat.rs index 47dabbf..5bf1d49 100644 --- a/src-tauri/src/feat.rs +++ b/src-tauri/src/feat.rs @@ -2,6 +2,15 @@ use crate::core::*; use crate::data::*; use crate::log_if_err; +// 重启clash +pub fn restart_clash_core() { + let core = Core::global(); + let mut service = core.service.lock(); + log_if_err!(service.restart()); + drop(service); + log_if_err!(core.activate()); +} + // 切换模式 pub fn change_clash_mode(mode: &str) { let core = Core::global(); diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index db065ab..334fb9c 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -14,9 +14,7 @@ use crate::{ data::Verge, utils::{resolve, server}, }; -use tauri::{ - api, CustomMenuItem, Manager, SystemTray, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem, -}; +use tauri::{api, Manager, SystemTray}; fn main() -> std::io::Result<()> { { @@ -34,51 +32,11 @@ fn main() -> std::io::Result<()> { dirs::init_portable_flag(); } - let tray_menu = SystemTrayMenu::new() - .add_item(CustomMenuItem::new("open_window", "Show")) - .add_native_item(SystemTrayMenuItem::Separator) - .add_item(CustomMenuItem::new("rule_mode", "Rule Mode")) - .add_item(CustomMenuItem::new("global_mode", "Global Mode")) - .add_item(CustomMenuItem::new("direct_mode", "Direct Mode")) - .add_item(CustomMenuItem::new("script_mode", "Script Mode")) - .add_native_item(SystemTrayMenuItem::Separator) - .add_item(CustomMenuItem::new("system_proxy", "System Proxy")) - .add_item(CustomMenuItem::new("tun_mode", "Tun Mode")) - .add_item(CustomMenuItem::new("restart_clash", "Restart Clash")) - .add_item(CustomMenuItem::new("restart_app", "Restart App")) - .add_native_item(SystemTrayMenuItem::Separator) - .add_item(CustomMenuItem::new("quit", "Quit").accelerator("CmdOrControl+Q")); - #[allow(unused_mut)] let mut builder = tauri::Builder::default() .setup(|app| Ok(resolve::resolve_setup(app))) - .system_tray(SystemTray::new().with_menu(tray_menu)) - .on_system_tray_event(move |app_handle, event| match event { - SystemTrayEvent::MenuItemClick { id, .. } => match id.as_str() { - "open_window" => { - resolve::create_window(app_handle); - } - mode @ ("rule_mode" | "global_mode" | "direct_mode" | "script_mode") => { - let mode = &mode[0..mode.len() - 5]; - feat::change_clash_mode(mode); - } - "system_proxy" => feat::toggle_system_proxy(), - "tun_mode" => feat::toggle_tun_mode(), - "restart_app" => { - api::process::restart(&app_handle.env()); - } - "quit" => { - resolve::resolve_reset(); - app_handle.exit(0); - } - _ => {} - }, - #[cfg(target_os = "windows")] - SystemTrayEvent::LeftClick { .. } => { - resolve::create_window(app_handle); - } - _ => {} - }) + .system_tray(SystemTray::new().with_menu(core::tray::Tray::tray_menu())) + .on_system_tray_event(core::tray::Tray::on_system_tray_event) .invoke_handler(tauri::generate_handler![ // common cmds::get_sys_proxy, @@ -126,17 +84,18 @@ fn main() -> std::io::Result<()> { { use tauri::{Menu, MenuItem, Submenu}; - let submenu_file = Submenu::new( - "File", - Menu::new() - .add_native_item(MenuItem::Undo) - .add_native_item(MenuItem::Redo) - .add_native_item(MenuItem::Copy) - .add_native_item(MenuItem::Paste) - .add_native_item(MenuItem::Cut) - .add_native_item(MenuItem::SelectAll), + builder = builder.menu( + Menu::new().add_submenu(Submenu::new( + "File", + Menu::new() + .add_native_item(MenuItem::Undo) + .add_native_item(MenuItem::Redo) + .add_native_item(MenuItem::Copy) + .add_native_item(MenuItem::Paste) + .add_native_item(MenuItem::Cut) + .add_native_item(MenuItem::SelectAll), + )), ); - builder = builder.menu(Menu::new().add_submenu(submenu_file)); } #[allow(unused_mut)] @@ -162,6 +121,7 @@ fn main() -> std::io::Result<()> { tauri::RunEvent::Exit => { resolve::resolve_reset(); api::process::kill_children(); + app_handle.exit(0); } #[cfg(target_os = "macos")] tauri::RunEvent::WindowEvent { label, event, .. } => {