From eb8ba8b3698c4c28451702b3474302185f06c4ac Mon Sep 17 00:00:00 2001 From: Tunglies <77394545+Tunglies@users.noreply.github.com> Date: Sat, 3 Jan 2026 19:25:36 +0800 Subject: [PATCH] refactor(tray): replace Arc with Cow<'static, str> for menu texts and update tray event handling --- src-tauri/src/core/tray/menu_def.rs | 37 ++++++++++++------- src-tauri/src/core/tray/mod.rs | 57 +++++++++++++++-------------- 2 files changed, 54 insertions(+), 40 deletions(-) diff --git a/src-tauri/src/core/tray/menu_def.rs b/src-tauri/src/core/tray/menu_def.rs index df47400fa..720bd0a8d 100644 --- a/src-tauri/src/core/tray/menu_def.rs +++ b/src-tauri/src/core/tray/menu_def.rs @@ -1,21 +1,11 @@ use clash_verge_i18n::t; -use std::{borrow::Cow, sync::Arc}; - -fn to_arc_str(value: S) -> Arc -where - S: Into>, -{ - match value.into() { - Cow::Borrowed(s) => Arc::from(s), - Cow::Owned(s) => Arc::from(s.into_boxed_str()), - } -} +use std::borrow::Cow; macro_rules! define_menu { ($($field:ident => $const_name:ident, $id:expr, $text:expr),+ $(,)?) => { #[derive(Debug)] pub struct MenuTexts { - $(pub $field: Arc,)+ + $(pub $field: Cow<'static, str>,)+ } pub struct MenuIds; @@ -23,7 +13,7 @@ macro_rules! define_menu { impl MenuTexts { pub fn new() -> Self { Self { - $($field: to_arc_str(t!($text)),)+ + $($field: t!($text),)+ } } } @@ -59,3 +49,24 @@ define_menu! { more => MORE, "tray_more", "tray.more", exit => EXIT, "tray_exit", "tray.exit", } + +#[derive(Debug, Clone, Copy)] +pub(crate) enum TrayAction { + SystemProxy, + TunMode, + MainWindow, + TrayMenue, + Unknown, +} + +impl From<&str> for TrayAction { + fn from(s: &str) -> Self { + match s { + "system_proxy" => Self::SystemProxy, + "tun_mode" => Self::TunMode, + "main_window" => Self::MainWindow, + "tray_menue" => Self::TrayMenue, + _ => Self::Unknown, + } + } +} diff --git a/src-tauri/src/core/tray/mod.rs b/src-tauri/src/core/tray/mod.rs index c69a0eee5..21b3d3010 100644 --- a/src-tauri/src/core/tray/mod.rs +++ b/src-tauri/src/core/tray/mod.rs @@ -7,6 +7,7 @@ use tokio::fs; pub mod speed_rate; use crate::config::{IProfilePreview, IVerge}; use crate::core::service; +use crate::core::tray::menu_def::TrayAction; use crate::module::lightweight; use crate::process::AsyncHandler; use crate::singleton; @@ -21,7 +22,6 @@ use anyhow::Result; use smartstring::alias::String; use std::collections::HashMap; use std::num::NonZeroU32; -use std::sync::Arc; use std::time::Duration; use tauri::{ AppHandle, Wry, @@ -187,12 +187,12 @@ impl Tray { let app_handle = handle::Handle::app_handle(); let tray_event = { Config::verge().await.latest_arc().tray_event.clone() }; - let tray_event = tray_event.unwrap_or_else(|| "main_window".into()); + let tray_event = TrayAction::from(tray_event.as_deref().unwrap_or("main_window")); let tray = app_handle .tray_by_id("main") .ok_or_else(|| anyhow::anyhow!("Failed to get main tray"))?; - match tray_event.as_str() { - "tray_menu" => tray.set_show_menu_on_left_click(true)?, + match tray_event { + TrayAction::TrayMenue => tray.set_show_menu_on_left_click(true)?, _ => tray.set_show_menu_on_left_click(false)?, } Ok(()) @@ -398,17 +398,13 @@ impl Tray { let builder = TrayIconBuilder::with_id("main").icon(icon).icon_as_template(false); #[cfg(any(target_os = "macos", target_os = "windows"))] - let show_menu_on_left_click = { - // TODO 优化这里 复用 verge - let tray_event = { Config::verge().await.latest_arc().tray_event.clone() }; - tray_event.is_some_and(|v| v == "tray_menu") - }; + let show_menu_on_left_click = verge.tray_event.as_ref().is_some_and(|v| v == "tray_menu"); #[cfg(not(target_os = "linux"))] let mut builder = TrayIconBuilder::with_id("main").icon(icon).icon_as_template(false); #[cfg(target_os = "macos")] { - let is_monochrome = verge.tray_icon.clone().is_none_or(|v| v == "monochrome"); + let is_monochrome = verge.tray_icon.as_ref().is_none_or(|v| v == "monochrome"); builder = builder.icon_as_template(is_monochrome); } @@ -420,8 +416,10 @@ impl Tray { } let tray = builder.build(app_handle)?; + let tray_event = verge.tray_event.clone().unwrap_or_else(|| "main_window".into()); + let tray_action = TrayAction::from(tray_event.as_str()); - tray.on_tray_icon_event(|_app_handle, event| { + tray.on_tray_icon_event(move |_app_handle, event| { if let TrayIconEvent::Click { button: MouseButton::Left, button_state: MouseButtonState::Down, @@ -433,24 +431,29 @@ impl Tray { if !Tray::global().should_handle_tray_click() { return; } - AsyncHandler::spawn(|| async move { - let tray_event = { Config::verge().await.latest_arc().tray_event.clone() }; - let tray_event: String = tray_event.unwrap_or_else(|| "main_window".into()); - logging!(debug, Type::Tray, "tray event: {tray_event:?}"); - - match tray_event.as_str() { - "system_proxy" => feat::toggle_system_proxy().await, - "tun_mode" => feat::toggle_tun_mode(None).await, - "main_window" => { + logging!(debug, Type::Tray, "tray event: {tray_action:?}"); + match tray_action { + TrayAction::SystemProxy => { + AsyncHandler::spawn(|| async move { + let _ = feat::toggle_system_proxy().await; + }); + } + TrayAction::TunMode => { + AsyncHandler::spawn(|| async move { + let _ = feat::toggle_tun_mode(None).await; + }); + } + TrayAction::MainWindow => { + AsyncHandler::spawn(|| async move { if !lightweight::exit_lightweight_mode().await { WindowManager::show_main_window().await; }; - } - _ => { - logging!(warn, Type::Tray, "invalid tray event: {}", tray_event); - } - }; - }); + }); + } + _ => { + logging!(warn, Type::Tray, "invalid tray event: {}", tray_event); + } + }; } }); tray.on_menu_event(on_menu_event); @@ -609,7 +612,7 @@ fn create_proxy_menu_item( app_handle: &AppHandle, show_proxy_groups_inline: bool, proxy_submenus: Vec>, - proxies_text: &Arc, + proxies_text: &str, ) -> Result { // 创建代理主菜单 let (proxies_submenu, inline_proxy_items) = if show_proxy_groups_inline {