refactor(tray): replace Arc<str> with Cow<'static, str> for menu texts and update tray event handling

This commit is contained in:
Tunglies
2026-01-03 19:25:36 +08:00
parent c18821288e
commit eb8ba8b369
2 changed files with 54 additions and 40 deletions

View File

@@ -1,21 +1,11 @@
use clash_verge_i18n::t;
use std::{borrow::Cow, sync::Arc};
fn to_arc_str<S>(value: S) -> Arc<str>
where
S: Into<Cow<'static, str>>,
{
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<str>,)+
$(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,
}
}
}

View File

@@ -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<Submenu<Wry>>,
proxies_text: &Arc<str>,
proxies_text: &str,
) -> Result<ProxyMenuItem> {
// 创建代理主菜单
let (proxies_submenu, inline_proxy_items) = if show_proxy_groups_inline {