diff --git a/src-tauri/src/core/core.rs b/src-tauri/src/core/core.rs index 4ae10993..b6f932ba 100644 --- a/src-tauri/src/core/core.rs +++ b/src-tauri/src/core/core.rs @@ -900,6 +900,7 @@ impl CoreManager { logging_error!(Type::Core, true, self.start_core_by_sidecar().await); } }; + handle::Handle::refresh_websocket(); Ok(()) } diff --git a/src-tauri/src/core/handle.rs b/src-tauri/src/core/handle.rs index 0a014d06..ec590ba2 100644 --- a/src-tauri/src/core/handle.rs +++ b/src-tauri/src/core/handle.rs @@ -307,6 +307,14 @@ impl Handle { window } + pub fn refresh_websocket() { + if let Some(window) = Self::get_window() { + if let Err(e) = window.emit("verge://refresh-websocket", "yes") { + log::error!("{e}"); + } + } + } + pub fn refresh_clash() { let handle = Self::global(); if handle.is_exiting() { diff --git a/src-tauri/src/core/tray/mod.rs b/src-tauri/src/core/tray/mod.rs index 7b5ec2c7..7f72d09d 100644 --- a/src-tauri/src/core/tray/mod.rs +++ b/src-tauri/src/core/tray/mod.rs @@ -546,7 +546,7 @@ async fn create_tray_menu( .unwrap_or_default() }; - let proxy_nodes_data = handle::Handle::mihomo().await.get_proxies().await?; + let proxy_nodes_data = handle::Handle::mihomo().await.get_proxies().await; let version = env!("CARGO_PKG_VERSION"); @@ -599,96 +599,98 @@ async fn create_tray_menu( let mut submenus = Vec::new(); let mut group_name_submenus_hash = HashMap::new(); - for (group_name, group_data) in proxy_nodes_data.proxies.iter() { - // Filter groups based on mode - let should_show = match mode { + if let Ok(proxy_nodes_data) = proxy_nodes_data { + for (group_name, group_data) in proxy_nodes_data.proxies.iter() { + // Filter groups based on mode + let should_show = match mode { "global" => group_name == "GLOBAL", _ => group_name != "GLOBAL", } && // Check if the group is hidden !group_data.hidden.unwrap_or_default(); - if !should_show { - continue; - } - - let Some(all_proxies) = group_data.all.as_ref() else { - continue; - }; - - let now_proxy = group_data.now.as_deref().unwrap_or_default(); - - // Create proxy items - let group_items: Vec> = all_proxies - .iter() - .filter_map(|proxy_str| { - let is_selected = *proxy_str == now_proxy; - let item_id = format!("proxy_{}_{}", group_name, proxy_str); - - // Get delay for display - let delay_text = proxy_nodes_data - .proxies - .get(proxy_str) - .and_then(|h| h.history.last()) - .map(|h| match h.delay { - 0 => "-ms".to_string(), - delay if delay >= 10000 => "-ms".to_string(), - _ => format!("{}ms", h.delay), - }) - .unwrap_or_else(|| "-ms".to_string()); - - let display_text = format!("{} | {}", proxy_str, delay_text); - - CheckMenuItem::with_id( - app_handle, - item_id, - display_text, - true, - is_selected, - None::<&str>, - ) - .map_err(|e| log::warn!(target: "app", "创建代理菜单项失败: {}", e)) - .ok() - }) - .collect(); - - if group_items.is_empty() { - continue; - } - - // Determine if group is active - let is_group_active = match mode { - "global" => group_name == "GLOBAL" && !now_proxy.is_empty(), - "direct" => false, - _ => { - current_profile_selected - .iter() - .any(|s| s.name.as_deref() == Some(group_name)) - && !now_proxy.is_empty() + if !should_show { + continue; } - }; - let group_display_name = if is_group_active { - format!("✓ {}", group_name) - } else { - group_name.to_string() - }; + let Some(all_proxies) = group_data.all.as_ref() else { + continue; + }; - let group_items_refs: Vec<&dyn IsMenuItem> = group_items - .iter() - .map(|item| item as &dyn IsMenuItem) - .collect(); + let now_proxy = group_data.now.as_deref().unwrap_or_default(); - if let Ok(submenu) = Submenu::with_id_and_items( - app_handle, - format!("proxy_group_{}", group_name), - group_display_name, - true, - &group_items_refs, - ) { - group_name_submenus_hash.insert(group_name.to_string(), submenu); - } else { - log::warn!(target: "app", "创建代理组子菜单失败: {}", group_name); + // Create proxy items + let group_items: Vec> = all_proxies + .iter() + .filter_map(|proxy_str| { + let is_selected = *proxy_str == now_proxy; + let item_id = format!("proxy_{}_{}", group_name, proxy_str); + + // Get delay for display + let delay_text = proxy_nodes_data + .proxies + .get(proxy_str) + .and_then(|h| h.history.last()) + .map(|h| match h.delay { + 0 => "-ms".to_string(), + delay if delay >= 10000 => "-ms".to_string(), + _ => format!("{}ms", h.delay), + }) + .unwrap_or_else(|| "-ms".to_string()); + + let display_text = format!("{} | {}", proxy_str, delay_text); + + CheckMenuItem::with_id( + app_handle, + item_id, + display_text, + true, + is_selected, + None::<&str>, + ) + .map_err(|e| log::warn!(target: "app", "创建代理菜单项失败: {}", e)) + .ok() + }) + .collect(); + + if group_items.is_empty() { + continue; + } + + // Determine if group is active + let is_group_active = match mode { + "global" => group_name == "GLOBAL" && !now_proxy.is_empty(), + "direct" => false, + _ => { + current_profile_selected + .iter() + .any(|s| s.name.as_deref() == Some(group_name)) + && !now_proxy.is_empty() + } + }; + + let group_display_name = if is_group_active { + format!("✓ {}", group_name) + } else { + group_name.to_string() + }; + + let group_items_refs: Vec<&dyn IsMenuItem> = group_items + .iter() + .map(|item| item as &dyn IsMenuItem) + .collect(); + + if let Ok(submenu) = Submenu::with_id_and_items( + app_handle, + format!("proxy_group_{}", group_name), + group_display_name, + true, + &group_items_refs, + ) { + group_name_submenus_hash.insert(group_name.to_string(), submenu); + } else { + log::warn!(target: "app", "创建代理组子菜单失败: {}", group_name); + } } } diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 6fc1502a..da836d8e 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -14,7 +14,7 @@ mod utils; #[cfg(target_os = "macos")] use crate::utils::window_manager::WindowManager; use crate::{ - core::hotkey, + core::{handle, hotkey}, process::AsyncHandler, utils::{resolve, server}, }; @@ -559,6 +559,12 @@ pub fn run() { }); } tauri::RunEvent::ExitRequested { api, code, .. } => { + tauri::async_runtime::block_on(async { + let _ = handle::Handle::mihomo() + .await + .clear_all_ws_connections() + .await; + }); if code.is_none() { api.prevent_exit(); } diff --git a/src/components/home/enhanced-traffic-stats.tsx b/src/components/home/enhanced-traffic-stats.tsx index 8d19033d..d0e3da2f 100644 --- a/src/components/home/enhanced-traffic-stats.tsx +++ b/src/components/home/enhanced-traffic-stats.tsx @@ -280,7 +280,7 @@ export const EnhancedTrafficStats = () => { {/* 统计卡片区域 */} {statCards.map((card, _index) => ( - + ))} diff --git a/src/services/cmds.ts b/src/services/cmds.ts index 7f9bd14c..6c86f178 100644 --- a/src/services/cmds.ts +++ b/src/services/cmds.ts @@ -197,12 +197,18 @@ export async function calcuProxies(): Promise<{ ), ); - const _global: IProxyGroupItem = { + const _global = { ...global, all: global?.all?.map((item) => generateItem(item)) || [], }; - return { global: _global, direct, groups, records: proxyRecord, proxies }; + return { + global: _global as IProxyGroupItem, + direct: direct as IProxyItem, + groups, + records: proxyRecord as Record, + proxies: (proxies as IProxyItem[]) ?? [], + }; } export async function calcuProxyProviders() {