diff --git a/UPDATELOG.md b/UPDATELOG.md index 3f0f8df62..9f6039050 100644 --- a/UPDATELOG.md +++ b/UPDATELOG.md @@ -2,11 +2,11 @@ #### 已知问题 - 仅在Ubuntu 22.04/24.04,Fedora 41 **Gnome桌面环境** 做过简单测试,不保证其他其他Linux发行版可用,将在未来做进一步适配和调优 - - Win/Mac/Linux 托盘图标缓存机制问题,无法正确切换自定义图标。 ### 2.2.3-alpha 相对于 2.2.2 #### 修复了: - 首页“当前代理”因为重复刷新导致的CPU占用过高的问题 + - 托盘图标无法自定义 #### 新增了: - ClashVergeRev 从现在开始不再强依赖系统服务和管理权限 diff --git a/src-tauri/src/cmd/app.rs b/src-tauri/src/cmd/app.rs index cd54de3ac..99fb12b8c 100644 --- a/src-tauri/src/cmd/app.rs +++ b/src-tauri/src/cmd/app.rs @@ -1,5 +1,9 @@ use super::CmdResult; -use crate::{feat, utils::dirs, wrap_err}; +use crate::{ + feat, logging, + utils::{dirs, logging::Type}, + wrap_err, +}; use tauri::Manager; /// 打开应用程序所在目录 @@ -194,7 +198,14 @@ pub fn copy_icon_file(path: String, icon_info: IconInfo) -> CmdResult { ) .unwrap_or_default(); } - + logging!( + info, + Type::CMD, + true, + "Copying icon file path: {:?} -> file dist: {:?}", + path, + dest_path + ); match fs::copy(file_path, &dest_path) { Ok(_) => Ok(dest_path.to_string_lossy().to_string()), Err(err) => Err(err.to_string()), diff --git a/src-tauri/src/core/core.rs b/src-tauri/src/core/core.rs index 5625e4fc6..038da7e46 100644 --- a/src-tauri/src/core/core.rs +++ b/src-tauri/src/core/core.rs @@ -4,7 +4,7 @@ use crate::{ config::*, core::{ handle, - service::{self, is_service_available}, + service::{self}, }, log_err, logging, logging_error, module::mihomo::MihomoManager, diff --git a/src-tauri/src/core/tray/mod.rs b/src-tauri/src/core/tray/mod.rs index a5fff8fd5..7286876c4 100644 --- a/src-tauri/src/core/tray/mod.rs +++ b/src-tauri/src/core/tray/mod.rs @@ -8,7 +8,7 @@ use crate::{ feat, module::{lightweight::entry_lightweight_mode, mihomo::Rate}, resolve, - utils::{dirs, i18n::t, resolve::VERSION}, + utils::{dirs::find_target_icons, i18n::t, resolve::VERSION}, }; use anyhow::Result; @@ -22,6 +22,7 @@ use parking_lot::RwLock; pub use speed_rate::{SpeedRate, Traffic}; #[cfg(target_os = "macos")] use std::collections::hash_map::DefaultHasher; +use std::fs; #[cfg(target_os = "macos")] use std::hash::{Hash, Hasher}; #[cfg(target_os = "macos")] @@ -35,6 +36,10 @@ use tauri::{ use tokio::sync::broadcast; use super::handle; + +#[derive(Clone)] +struct TrayState {} + #[cfg(target_os = "macos")] pub struct Tray { pub speed_rate: Arc>>, @@ -43,10 +48,89 @@ pub struct Tray { pub icon_hash: Arc>>, pub icon_cache: Arc>>>, pub rate_cache: Arc>>, + // pub tray_state: Arc>, } #[cfg(not(target_os = "macos"))] -pub struct Tray {} +pub struct Tray { + pub tray_state: Arc>, +} + +impl TrayState { + pub fn get_common_tray_icon() -> Vec { + let verge = Config::verge().latest().clone(); + let is_common_tray_icon = verge.common_tray_icon.clone().unwrap_or(false); + if is_common_tray_icon { + if let Some(common_icon_path) = find_target_icons("common").unwrap() { + let icon_data = fs::read(common_icon_path).unwrap(); + return icon_data; + } + } + #[cfg(target_os = "macos")] + { + let tray_icon_colorful = verge.tray_icon.clone().unwrap_or("monochrome".to_string()); + if tray_icon_colorful == "monochrome" { + include_bytes!("../../../icons/tray-icon.ico").to_vec() + } else { + include_bytes!("../../../icons/tray-icon-mono.ico").to_vec() + } + } + + #[cfg(not(target_os = "macos"))] + { + include_bytes!("../../../icons/tray-icon.ico").to_vec() + } + } + + pub fn get_sysproxy_tray_icon() -> Vec { + let verge = Config::verge().latest().clone(); + let is_sysproxy_tray_icon = verge.sysproxy_tray_icon.clone().unwrap_or(false); + if is_sysproxy_tray_icon { + if let Some(sysproxy_icon_path) = find_target_icons("sysproxy").unwrap() { + let icon_data = fs::read(sysproxy_icon_path).unwrap(); + return icon_data; + } + } + #[cfg(target_os = "macos")] + { + let tray_icon_colorful = verge.tray_icon.clone().unwrap_or("monochrome".to_string()); + if tray_icon_colorful == "monochrome" { + include_bytes!("../../../icons/tray-icon-sys.ico").to_vec() + } else { + include_bytes!("../../../icons/tray-icon-sys-mono.ico").to_vec() + } + } + + #[cfg(not(target_os = "macos"))] + { + include_bytes!("../../../icons/tray-icon-sys.ico").to_vec() + } + } + + pub fn get_tun_tray_icon() -> Vec { + let verge = Config::verge().latest().clone(); + let is_tun_tray_icon = verge.tun_tray_icon.clone().unwrap_or(false); + if is_tun_tray_icon { + if let Some(tun_icon_path) = find_target_icons("tun").unwrap() { + let icon_data = fs::read(tun_icon_path).unwrap(); + return icon_data; + } + } + #[cfg(target_os = "macos")] + { + let tray_icon_colorful = verge.tray_icon.clone().unwrap_or("monochrome".to_string()); + if tray_icon_colorful == "monochrome" { + include_bytes!("../../../icons/tray-icon-tun.ico").to_vec() + } else { + include_bytes!("../../../icons/tray-icon-tun-mono.ico").to_vec() + } + } + #[cfg(not(target_os = "macos"))] + { + include_bytes!("../../../icons/tray-icon-tun.ico").to_vec() + } + } +} impl Tray { pub fn global() -> &'static Tray { @@ -159,89 +243,27 @@ impl Tray { } /// 更新托盘图标 - #[allow(unused_variables)] pub fn update_icon(&self, rate: Option) -> Result<()> { - let app_handle = handle::Handle::global().app_handle().unwrap(); let verge = Config::verge().latest().clone(); - let system_proxy = verge.enable_system_proxy.as_ref().unwrap_or(&false); + let system_mode = verge.enable_system_proxy.as_ref().unwrap_or(&false); let tun_mode = verge.enable_tun_mode.as_ref().unwrap_or(&false); - let common_tray_icon = verge.common_tray_icon.as_ref().unwrap_or(&false); - let sysproxy_tray_icon = verge.sysproxy_tray_icon.as_ref().unwrap_or(&false); - let tun_tray_icon = verge.tun_tray_icon.as_ref().unwrap_or(&false); - + let app_handle = handle::Handle::global().app_handle().unwrap(); let tray = app_handle.tray_by_id("main").unwrap(); - #[cfg(target_os = "macos")] - let tray_icon = verge.tray_icon.clone().unwrap_or("monochrome".to_string()); - - let icon_bytes = if *system_proxy && !*tun_mode { - #[cfg(target_os = "macos")] - let mut icon = match tray_icon.as_str() { - "colorful" => include_bytes!("../../../icons/tray-icon-sys.ico").to_vec(), - _ => include_bytes!("../../../icons/tray-icon-sys-mono.ico").to_vec(), - }; - - #[cfg(not(target_os = "macos"))] - let mut icon = include_bytes!("../../../icons/tray-icon-sys.ico").to_vec(); - if *sysproxy_tray_icon { - let icon_dir_path = dirs::app_home_dir()?.join("icons"); - let png_path = icon_dir_path.join("sysproxy.png"); - let ico_path = icon_dir_path.join("sysproxy.ico"); - if ico_path.exists() { - icon = std::fs::read(ico_path).unwrap(); - } else if png_path.exists() { - icon = std::fs::read(png_path).unwrap(); - } - } - icon - } else if *tun_mode { - #[cfg(target_os = "macos")] - let mut icon = match tray_icon.as_str() { - "colorful" => include_bytes!("../../../icons/tray-icon-tun.ico").to_vec(), - _ => include_bytes!("../../../icons/tray-icon-tun-mono.ico").to_vec(), - }; - - #[cfg(not(target_os = "macos"))] - let mut icon = include_bytes!("../../../icons/tray-icon-tun.ico").to_vec(); - if *tun_tray_icon { - let icon_dir_path = dirs::app_home_dir()?.join("icons"); - let png_path = icon_dir_path.join("tun.png"); - let ico_path = icon_dir_path.join("tun.ico"); - if ico_path.exists() { - icon = std::fs::read(ico_path).unwrap(); - } else if png_path.exists() { - icon = std::fs::read(png_path).unwrap(); - } - } - icon - } else { - #[cfg(target_os = "macos")] - let mut icon = match tray_icon.as_str() { - "colorful" => include_bytes!("../../../icons/tray-icon.ico").to_vec(), - _ => include_bytes!("../../../icons/tray-icon-mono.ico").to_vec(), - }; - - #[cfg(not(target_os = "macos"))] - let mut icon = include_bytes!("../../../icons/tray-icon.ico").to_vec(); - if *common_tray_icon { - let icon_dir_path = dirs::app_home_dir()?.join("icons"); - let png_path = icon_dir_path.join("common.png"); - let ico_path = icon_dir_path.join("common.ico"); - if ico_path.exists() { - icon = std::fs::read(ico_path).unwrap(); - } else if png_path.exists() { - icon = std::fs::read(png_path).unwrap(); - } - } - icon + let icon_bytes = match (*system_mode, *tun_mode) { + (true, true) => TrayState::get_tun_tray_icon(), + (true, false) => TrayState::get_sysproxy_tray_icon(), + (false, true) => TrayState::get_tun_tray_icon(), + (false, false) => TrayState::get_common_tray_icon(), }; #[cfg(target_os = "macos")] { let enable_tray_speed = verge.enable_tray_speed.unwrap_or(true); let enable_tray_icon = verge.enable_tray_icon.unwrap_or(true); - let is_colorful = tray_icon == "colorful"; + let colorful = verge.tray_icon.clone().unwrap_or("monochrome".to_string()); + let is_colorful = colorful == "colorful"; let icon_hash = { let mut hasher = DefaultHasher::new(); diff --git a/src-tauri/src/utils/dirs.rs b/src-tauri/src/utils/dirs.rs index 72b70a2c9..fc4f179ec 100644 --- a/src-tauri/src/utils/dirs.rs +++ b/src-tauri/src/utils/dirs.rs @@ -77,9 +77,39 @@ pub fn app_profiles_dir() -> Result { Ok(app_home_dir()?.join("profiles")) } +/// icons dir +pub fn app_icons_dir() -> Result { + Ok(app_home_dir()?.join("icons")) +} + +pub fn find_target_icons(target: &str) -> Result> { + let icons_dir = app_icons_dir()?; + let mut matching_files = Vec::new(); + + for entry in fs::read_dir(icons_dir)? { + let entry = entry?; + let path = entry.path(); + + if let Some(file_name) = path.file_name().and_then(|n| n.to_str()) { + if file_name.starts_with(target) + && (file_name.ends_with(".ico") || file_name.ends_with(".png")) + { + matching_files.push(path); + } + } + } + + if matching_files.is_empty() { + Ok(None) + } else { + let first = path_to_str(matching_files.first().unwrap())?; + Ok(Some(first.to_string())) + } +} + /// logs dir pub fn app_logs_dir() -> Result { - Ok(app_home_dir()?.join("logs")) + Ok(app_home_dir()?.join("icons")) } pub fn clash_path() -> Result { diff --git a/src-tauri/src/utils/logging.rs b/src-tauri/src/utils/logging.rs index a2e00b4f8..4a46fb95c 100644 --- a/src-tauri/src/utils/logging.rs +++ b/src-tauri/src/utils/logging.rs @@ -7,6 +7,7 @@ pub enum Type { Hotkey, Window, Config, + CMD, } impl fmt::Display for Type { @@ -17,6 +18,7 @@ impl fmt::Display for Type { Type::Hotkey => write!(f, "[Hotkey]"), Type::Window => write!(f, "[Window]"), Type::Config => write!(f, "[Config]"), + Type::CMD => write!(f, "[CMD]"), } } }