From 23e551e384fabd14e29adaecd2786f7af7387ba8 Mon Sep 17 00:00:00 2001 From: Slinetrac Date: Sun, 21 Dec 2025 10:33:19 +0800 Subject: [PATCH] feat(tray): add optional inline outbound modes in tray menu #5881 Closes #5881 --- src-tauri/src/config/verge.rs | 4 ++ src-tauri/src/core/tray/mod.rs | 54 ++++++++++++------- src-tauri/src/feat/config.rs | 4 ++ src/components/setting/mods/layout-viewer.tsx | 17 ++++++ src/locales/ar/settings.json | 1 + src/locales/de/settings.json | 1 + src/locales/en/settings.json | 1 + src/locales/es/settings.json | 1 + src/locales/fa/settings.json | 1 + src/locales/id/settings.json | 1 + src/locales/jp/settings.json | 1 + src/locales/ko/settings.json | 1 + src/locales/ru/settings.json | 1 + src/locales/tr/settings.json | 1 + src/locales/tt/settings.json | 1 + src/locales/zh/settings.json | 1 + src/locales/zhtw/settings.json | 1 + src/types/generated/i18n-keys.ts | 1 + src/types/generated/i18n-resources.ts | 1 + src/types/global.d.ts | 1 + 20 files changed, 76 insertions(+), 19 deletions(-) diff --git a/src-tauri/src/config/verge.rs b/src-tauri/src/config/verge.rs index 8e2553d5d..6efdcf764 100644 --- a/src-tauri/src/config/verge.rs +++ b/src-tauri/src/config/verge.rs @@ -230,6 +230,8 @@ pub struct IVerge { // pub enable_tray_icon: Option, /// show proxy groups directly on tray root menu pub tray_inline_proxy_groups: Option, + /// show outbound modes directly on tray root menu + pub tray_inline_outbound_modes: Option, /// 自动进入轻量模式 pub enable_auto_light_weight_mode: Option, @@ -440,6 +442,7 @@ impl IVerge { enable_tray_speed: Some(false), // enable_tray_icon: Some(true), tray_inline_proxy_groups: Some(true), + tray_inline_outbound_modes: Some(false), enable_global_hotkey: Some(true), enable_auto_light_weight_mode: Some(false), auto_light_weight_minutes: Some(10), @@ -541,6 +544,7 @@ impl IVerge { patch!(enable_tray_speed); // patch!(enable_tray_icon); patch!(tray_inline_proxy_groups); + patch!(tray_inline_outbound_modes); patch!(enable_auto_light_weight_mode); patch!(auto_light_weight_minutes); patch!(enable_dns_settings); diff --git a/src-tauri/src/core/tray/mod.rs b/src-tauri/src/core/tray/mod.rs index ea2891177..e21d62234 100644 --- a/src-tauri/src/core/tray/mod.rs +++ b/src-tauri/src/core/tray/mod.rs @@ -771,6 +771,7 @@ async fn create_tray_menu( let verge_settings = Config::verge().await.latest_arc(); let show_proxy_groups_inline = verge_settings.tray_inline_proxy_groups.unwrap_or(true); + let show_outbound_modes_inline = verge_settings.tray_inline_outbound_modes.unwrap_or(false); let version = env!("CARGO_PKG_VERSION"); @@ -794,13 +795,6 @@ async fn create_tray_menu( hotkeys.get("open_or_close_dashboard").map(|s| s.as_str()), )?; - let current_mode_text = match current_proxy_mode { - "global" => rust_i18n::t!("tray.global"), - "direct" => rust_i18n::t!("tray.direct"), - _ => rust_i18n::t!("tray.rule"), - }; - let outbound_modes_label = format!("{} ({})", texts.outbound_modes, current_mode_text); - let rule_mode = &CheckMenuItem::with_id( app_handle, MenuIds::RULE_MODE, @@ -828,17 +822,27 @@ async fn create_tray_menu( hotkeys.get("clash_mode_direct").map(|s| s.as_str()), )?; - let outbound_modes = &Submenu::with_id_and_items( - app_handle, - MenuIds::OUTBOUND_MODES, - outbound_modes_label.as_str(), - true, - &[ - rule_mode as &dyn IsMenuItem, - global_mode as &dyn IsMenuItem, - direct_mode as &dyn IsMenuItem, - ], - )?; + let outbound_modes = if show_outbound_modes_inline { + None + } else { + let current_mode_text = match current_proxy_mode { + "global" => rust_i18n::t!("tray.global"), + "direct" => rust_i18n::t!("tray.direct"), + _ => rust_i18n::t!("tray.rule"), + }; + let outbound_modes_label = format!("{} ({})", texts.outbound_modes, current_mode_text); + Some(Submenu::with_id_and_items( + app_handle, + MenuIds::OUTBOUND_MODES, + outbound_modes_label.as_str(), + true, + &[ + rule_mode as &dyn IsMenuItem, + global_mode as &dyn IsMenuItem, + direct_mode as &dyn IsMenuItem, + ], + )?) + }; let profiles = &Submenu::with_id_and_items( app_handle, @@ -946,7 +950,19 @@ async fn create_tray_menu( let separator = &PredefinedMenuItem::separator(app_handle)?; // 动态构建菜单项 - let mut menu_items: Vec<&dyn IsMenuItem> = vec![open_window, outbound_modes, separator, profiles]; + let mut menu_items: Vec<&dyn IsMenuItem> = vec![open_window, separator]; + + if show_outbound_modes_inline { + menu_items.extend_from_slice(&[ + rule_mode as &dyn IsMenuItem, + global_mode as &dyn IsMenuItem, + direct_mode as &dyn IsMenuItem, + ]); + } else if let Some(ref outbound_modes) = outbound_modes { + menu_items.push(outbound_modes); + } + + menu_items.extend_from_slice(&[separator, profiles]); // 如果有代理节点,添加代理节点菜单 if show_proxy_groups_inline { diff --git a/src-tauri/src/feat/config.rs b/src-tauri/src/feat/config.rs index 3bca539b8..eac968e9f 100644 --- a/src-tauri/src/feat/config.rs +++ b/src-tauri/src/feat/config.rs @@ -103,6 +103,7 @@ fn determine_update_flags(patch: &IVerge) -> i32 { let enable_auto_light_weight = patch.enable_auto_light_weight_mode; let enable_external_controller = patch.enable_external_controller; let tray_inline_proxy_groups = patch.tray_inline_proxy_groups; + let tray_inline_outbound_modes = patch.tray_inline_outbound_modes; let enable_proxy_guard = patch.enable_proxy_guard; let proxy_guard_duration = patch.proxy_guard_duration; @@ -184,6 +185,9 @@ fn determine_update_flags(patch: &IVerge) -> i32 { if tray_inline_proxy_groups.is_some() { update_flags |= UpdateFlags::SystrayMenu as i32; } + if tray_inline_outbound_modes.is_some() { + update_flags |= UpdateFlags::SystrayMenu as i32; + } update_flags } diff --git a/src/components/setting/mods/layout-viewer.tsx b/src/components/setting/mods/layout-viewer.tsx index 8d698ece7..664ed9afe 100644 --- a/src/components/setting/mods/layout-viewer.tsx +++ b/src/components/setting/mods/layout-viewer.tsx @@ -436,6 +436,23 @@ export const LayoutViewer = forwardRef((_, ref) => { + + + onChangeData({ tray_inline_outbound_modes: e })} + onGuard={(e) => patchVerge({ tray_inline_outbound_modes: e })} + > + + +