From 8aabcd77a54bfafe7e7c60d53aa14bdabd439a32 Mon Sep 17 00:00:00 2001 From: Tunglies Date: Sat, 22 Mar 2025 23:00:45 +0800 Subject: [PATCH] feat: enhance tray icon handling with caching and speed rate rendering --- src-tauri/src/core/tray/mod.rs | 77 +++++++++++++++++++-------- src-tauri/src/core/tray/speed_rate.rs | 17 +++--- 2 files changed, 66 insertions(+), 28 deletions(-) diff --git a/src-tauri/src/core/tray/mod.rs b/src-tauri/src/core/tray/mod.rs index ba87d8b9..ae2b1002 100644 --- a/src-tauri/src/core/tray/mod.rs +++ b/src-tauri/src/core/tray/mod.rs @@ -21,6 +21,10 @@ use parking_lot::RwLock; #[cfg(target_os = "macos")] pub use speed_rate::{SpeedRate, Traffic}; #[cfg(target_os = "macos")] +use std::collections::hash_map::DefaultHasher; +#[cfg(target_os = "macos")] +use std::hash::{Hash, Hasher}; +#[cfg(target_os = "macos")] use std::sync::Arc; use tauri::{ menu::{CheckMenuItem, IsMenuItem, MenuEvent, MenuItem, PredefinedMenuItem, Submenu}, @@ -36,6 +40,9 @@ pub struct Tray { pub speed_rate: Arc>>, shutdown_tx: Arc>>>, is_subscribed: Arc>, + pub icon_hash: Arc>>, + pub icon_cache: Arc>>>, + pub rate_cache: Arc>>, } #[cfg(not(target_os = "macos"))] @@ -50,6 +57,9 @@ impl Tray { speed_rate: Arc::new(Mutex::new(None)), shutdown_tx: Arc::new(RwLock::new(None)), is_subscribed: Arc::new(RwLock::new(false)), + icon_hash: Arc::new(Mutex::new(None)), + icon_cache: Arc::new(Mutex::new(None)), + rate_cache: Arc::new(Mutex::new(None)), }); #[cfg(not(target_os = "macos"))] @@ -228,34 +238,59 @@ impl Tray { #[cfg(target_os = "macos")] { - let enable_tray_speed = Config::verge().latest().enable_tray_speed.unwrap_or(true); + let enable_tray_speed = verge.enable_tray_speed.unwrap_or(true); let is_colorful = tray_icon == "colorful"; - // 处理图标和速率 - let final_icon_bytes = if enable_tray_speed { - let rate = rate.or_else(|| { - self.speed_rate - .lock() - .as_ref() - .and_then(|speed_rate| speed_rate.get_curent_rate()) - }); - - // 使用新的方法渲染图标和速率 - SpeedRate::add_speed_text(icon_bytes, rate)? - } else { - icon_bytes + let icon_hash = { + let mut hasher = DefaultHasher::new(); + icon_bytes.clone().hash(&mut hasher); + hasher.finish() }; - // 设置系统托盘图标 - let _ = tray.set_icon(Some(tauri::image::Image::from_bytes(&final_icon_bytes)?)); - // 只对单色图标使用 template 模式 - let _ = tray.set_icon_as_template(!is_colorful); + let mut icon_hash_guard = self.icon_hash.lock(); + let mut icon_bytes_guard = self.icon_cache.lock(); + if *icon_hash_guard != Some(icon_hash) { + *icon_hash_guard = Some(icon_hash); + *icon_bytes_guard = Some(icon_bytes.clone()); + } + + if !enable_tray_speed { + let _ = tray.set_icon(Some(tauri::image::Image::from_bytes( + &(*icon_bytes_guard).clone().unwrap(), + )?)); + let _ = tray.set_icon_as_template(!is_colorful); + return Ok(()); + } + + let rate = if let Some(rate) = rate { + Some(rate) + } else { + let guard = self.speed_rate.lock(); + if let Some(rate) = guard.as_ref().unwrap().get_curent_rate() { + Some(rate) + } else { + Some(Rate::default()) + } + }; + + let mut rate_guard = self.rate_cache.lock(); + if *rate_guard != rate { + *rate_guard = rate; + + let bytes = icon_bytes_guard.as_ref().unwrap(); + let rate = rate_guard.as_ref(); + let rate_bytes = SpeedRate::add_speed_text(bytes, rate).unwrap(); + let _ = tray.set_icon(Some(tauri::image::Image::from_bytes(&rate_bytes)?)); + let _ = tray.set_icon_as_template(!is_colorful); + } + Ok(()) } #[cfg(not(target_os = "macos"))] - let _ = tray.set_icon(Some(tauri::image::Image::from_bytes(&icon_bytes)?)); - - Ok(()) + { + let _ = tray.set_icon(Some(tauri::image::Image::from_bytes(&icon_bytes)?)); + Ok(()) + } } /// 更新托盘提示 diff --git a/src-tauri/src/core/tray/speed_rate.rs b/src-tauri/src/core/tray/speed_rate.rs index c061fb93..c37bd7c5 100644 --- a/src-tauri/src/core/tray/speed_rate.rs +++ b/src-tauri/src/core/tray/speed_rate.rs @@ -15,7 +15,6 @@ use tungstenite::client::IntoClientRequest; pub struct SpeedRate { rate: Arc>, last_update: Arc>, - // 移除 base_image,不再缓存原始图像 } impl SpeedRate { @@ -77,20 +76,24 @@ impl SpeedRate { } // 分离图标加载和速率渲染 - pub fn add_speed_text(icon_bytes: Vec, rate: Option) -> Result> { - let rate = rate.unwrap_or(Rate { up: 0, down: 0 }); + pub fn add_speed_text<'a>(icon_bytes: &'a Vec, rate: Option<&'a Rate>) -> Result> { + let rate = rate.unwrap_or(&Rate { up: 0, down: 0 }); // 加载原始图标 - let icon_image = image::load_from_memory(&icon_bytes)?; + let icon_image = image::load_from_memory(icon_bytes)?; let (icon_width, icon_height) = (icon_image.width(), icon_image.height()); // 判断是否为彩色图标 let is_colorful = - !crate::utils::help::is_monochrome_image_from_bytes(&icon_bytes).unwrap_or(false); + !crate::utils::help::is_monochrome_image_from_bytes(icon_bytes).unwrap_or(false); // 增加文本宽度和间距 - let text_width = 580; // 文本区域宽度 - let total_width = icon_width + text_width; + let total_width = if icon_width < 580 { + let text_width = 580; // 文本区域宽度 + icon_width + text_width + } else { + icon_width + }; // 创建新的透明画布 let mut combined_image = RgbaImage::new(total_width, icon_height);