mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-28 07:14:40 +08:00
Compare commits
2 Commits
6477dd61c3
...
refactor/t
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc3bb3c14b | ||
|
|
971b8ccadf |
31
Cargo.lock
generated
31
Cargo.lock
generated
@@ -1423,7 +1423,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3653,12 +3653,12 @@ dependencies = [
|
||||
"libc",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"socket2 0.6.1",
|
||||
"socket2 0.5.10",
|
||||
"system-configuration",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
"windows-registry 0.6.1",
|
||||
"windows-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5268,7 +5268,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6077,7 +6077,7 @@ dependencies = [
|
||||
"quinn-udp",
|
||||
"rustc-hash",
|
||||
"rustls",
|
||||
"socket2 0.6.1",
|
||||
"socket2 0.5.10",
|
||||
"thiserror 2.0.17",
|
||||
"tokio",
|
||||
"tracing",
|
||||
@@ -6115,7 +6115,7 @@ dependencies = [
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"socket2 0.6.1",
|
||||
"socket2 0.5.10",
|
||||
"tracing",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
@@ -7967,7 +7967,7 @@ dependencies = [
|
||||
"thiserror 2.0.17",
|
||||
"tracing",
|
||||
"url",
|
||||
"windows-registry 0.5.3",
|
||||
"windows-registry",
|
||||
"windows-result 0.3.4",
|
||||
]
|
||||
|
||||
@@ -8079,8 +8079,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-mihomo"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/clash-verge-rev/tauri-plugin-mihomo#88bf64a17f2c25f306ad22629a8688d094e1cf02"
|
||||
version = "0.1.3"
|
||||
source = "git+https://github.com/clash-verge-rev/tauri-plugin-mihomo#65500f248533c0700a65f0f081e4bcadda4bff35"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"futures-util",
|
||||
@@ -9729,7 +9729,7 @@ version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9909,17 +9909,6 @@ dependencies = [
|
||||
"windows-strings 0.4.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-registry"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
"windows-result 0.4.1",
|
||||
"windows-strings 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.3.4"
|
||||
|
||||
@@ -45,7 +45,7 @@ tauri = { workspace = true, features = [
|
||||
"image-ico",
|
||||
"image-png",
|
||||
] }
|
||||
parking_lot = { workspace = true }
|
||||
parking_lot = { workspace = true, features = ["send_guard"] }
|
||||
anyhow = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
compact_str = { workspace = true }
|
||||
@@ -65,7 +65,12 @@ boa_engine = "0.21.0"
|
||||
once_cell = { version = "1.21.3", features = ["parking_lot"] }
|
||||
delay_timer = "0.11.6"
|
||||
percent-encoding = "2.3.2"
|
||||
reqwest = { version = "0.13.1", features = ["json", "cookies", "rustls", "form"] }
|
||||
reqwest = { version = "0.13.1", features = [
|
||||
"json",
|
||||
"cookies",
|
||||
"rustls",
|
||||
"form",
|
||||
] }
|
||||
regex = "1.12.2"
|
||||
sysproxy = { git = "https://github.com/clash-verge-rev/sysproxy-rs", features = [
|
||||
"guard",
|
||||
|
||||
20
src-tauri/src/core/tray/data.rs
Normal file
20
src-tauri/src/core/tray/data.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
use tauri_plugin_mihomo::models::Proxies;
|
||||
|
||||
use crate::core::handle;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct MihomoProxies {
|
||||
proxies: Proxies,
|
||||
epoch: u64,
|
||||
}
|
||||
|
||||
impl MihomoProxies {
|
||||
async fn refresh(&mut self) -> anyhow::Result<()> {
|
||||
let proxies = handle::Handle::mihomo().await.get_proxies().await?;
|
||||
if proxies != self.proxies {
|
||||
self.proxies = proxies;
|
||||
self.epoch += 1;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
133
src-tauri/src/core/tray/logic.rs
Normal file
133
src-tauri/src/core/tray/logic.rs
Normal file
@@ -0,0 +1,133 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use tokio::fs;
|
||||
|
||||
use crate::{
|
||||
config::IVerge,
|
||||
core::tray::view::{
|
||||
CacheComponent, IconBytes, IconStyle, ProxyStatus, TrayComponent, TrayIcon, TrayIconCache, TrayIconView,
|
||||
},
|
||||
utils::dirs::find_target_icons,
|
||||
};
|
||||
impl TrayIcon {
|
||||
const fn calculate_icon_status(enable_proxy: bool, enable_tun: bool) -> ProxyStatus {
|
||||
match (enable_proxy, enable_tun) {
|
||||
(false, false) => ProxyStatus::Idle,
|
||||
(true, false) => ProxyStatus::Proxy,
|
||||
(false, true) => ProxyStatus::Tun,
|
||||
(true, true) => ProxyStatus::ProxyTUN,
|
||||
}
|
||||
}
|
||||
|
||||
const fn get_builtin_icon(status: ProxyStatus, is_monochrome: bool) -> (IconStyle, IconBytes) {
|
||||
let bytes = match (status, is_monochrome) {
|
||||
(ProxyStatus::Idle, true) => include_bytes!("../../../icons/tray-icon-mono.ico").as_slice(),
|
||||
(ProxyStatus::Idle, false) => include_bytes!("../../../icons/tray-icon.ico").as_slice(),
|
||||
|
||||
(ProxyStatus::Proxy, true) => include_bytes!("../../../icons/tray-icon-sys-mono-new.ico").as_slice(),
|
||||
(ProxyStatus::Proxy, false) => include_bytes!("../../../icons/tray-icon-sys.ico").as_slice(),
|
||||
|
||||
(_, true) => include_bytes!("../../../icons/tray-icon-tun-mono-new.ico").as_slice(),
|
||||
(_, false) => include_bytes!("../../../icons/tray-icon-tun.ico").as_slice(),
|
||||
};
|
||||
|
||||
(
|
||||
if is_monochrome {
|
||||
IconStyle::Monochrome
|
||||
} else {
|
||||
IconStyle::Normal
|
||||
},
|
||||
Cow::Borrowed(bytes),
|
||||
)
|
||||
}
|
||||
|
||||
async fn get_custom_icon_bytes(target: ProxyStatus) -> Option<IconBytes> {
|
||||
let tag = match target {
|
||||
ProxyStatus::Idle => "common",
|
||||
ProxyStatus::Proxy => "sysproxy",
|
||||
_ => "tun",
|
||||
};
|
||||
|
||||
let path = find_target_icons(tag).ok()??;
|
||||
fs::read(path).await.ok().map(Cow::Owned)
|
||||
}
|
||||
|
||||
async fn from_verge(verge: &IVerge, proxy_status: ProxyStatus, is_monochrome: bool) -> (IconStyle, IconBytes) {
|
||||
let is_custom = match proxy_status {
|
||||
ProxyStatus::Idle => verge.common_tray_icon,
|
||||
ProxyStatus::Proxy => verge.sysproxy_tray_icon,
|
||||
_ => verge.tun_tray_icon,
|
||||
}
|
||||
.unwrap_or(false);
|
||||
if is_custom && let Some(bytes) = Self::get_custom_icon_bytes(proxy_status).await {
|
||||
return (IconStyle::Custom, bytes);
|
||||
}
|
||||
|
||||
Self::get_builtin_icon(proxy_status, is_monochrome)
|
||||
}
|
||||
}
|
||||
|
||||
impl CacheComponent for TrayIcon {
|
||||
type Cache = TrayIconCache;
|
||||
type View<'a>
|
||||
= TrayIconView<'a>
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
fn is_some(&self) -> bool {
|
||||
!self.0.last_icon_bytes.is_empty()
|
||||
}
|
||||
|
||||
fn get(&self) -> Self::View<'_> {
|
||||
TrayIconView {
|
||||
last_icon_style: &self.0.last_icon_style,
|
||||
last_icon_bytes: &self.0.last_icon_bytes,
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self, t: Self::Cache) {
|
||||
self.0 = t;
|
||||
}
|
||||
|
||||
/// We assume the cache is equal when both status and style are equal
|
||||
/// and ignore the actual icon bytes comparison
|
||||
fn equals(&self, other: &Self::Cache) -> bool {
|
||||
self.0.last_proxy_status == other.last_proxy_status && self.0.last_icon_style == other.last_icon_style
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl TrayComponent for TrayIcon {
|
||||
type Context = IVerge;
|
||||
|
||||
async fn refresh(&mut self, force: bool, verge: &Self::Context) -> bool {
|
||||
let enable_proxy = verge.enable_system_proxy.unwrap_or(false);
|
||||
let enable_tun = verge.enable_tun_mode.unwrap_or(false);
|
||||
let is_monochrome = cfg!(target_os = "macos") && verge.tray_icon.as_deref() == Some("monochrome");
|
||||
|
||||
let target_status = Self::calculate_icon_status(enable_proxy, enable_tun);
|
||||
let target_style = if is_monochrome {
|
||||
IconStyle::Monochrome
|
||||
} else {
|
||||
IconStyle::Normal
|
||||
};
|
||||
|
||||
let cmpare_cache = TrayIconCache {
|
||||
last_icon_style: target_style,
|
||||
last_proxy_status: target_status,
|
||||
last_icon_bytes: Cow::Borrowed(&[]),
|
||||
};
|
||||
if !force && self.is_some() && self.equals(&cmpare_cache) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let (icon_style, icon_bytes) = Self::from_verge(verge, target_status, is_monochrome).await;
|
||||
self.update(TrayIconCache {
|
||||
last_icon_style: icon_style,
|
||||
last_proxy_status: target_status,
|
||||
last_icon_bytes: icon_bytes,
|
||||
});
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
@@ -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),)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
use governor::{DefaultDirectRateLimiter, Quota, RateLimiter};
|
||||
use parking_lot::Mutex;
|
||||
use tauri::tray::TrayIconBuilder;
|
||||
use tauri_plugin_clash_verge_sysinfo::is_current_app_handle_admin;
|
||||
use tauri_plugin_mihomo::models::Proxies;
|
||||
use tokio::fs;
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod speed_rate;
|
||||
// pub mod data;
|
||||
mod logic;
|
||||
mod view;
|
||||
use crate::config::{IProfilePreview, IVerge};
|
||||
use crate::core::service;
|
||||
#[cfg(target_os = "macos")]
|
||||
use crate::core::tray::view::IconStyle;
|
||||
use crate::core::tray::view::{CacheComponent, TrayComponent, TrayIcon};
|
||||
use crate::module::lightweight;
|
||||
use crate::process::AsyncHandler;
|
||||
use crate::singleton;
|
||||
use crate::utils::window_manager::WindowManager;
|
||||
use crate::{
|
||||
Type, cmd, config::Config, feat, logging, module::lightweight::is_in_lightweight_mode,
|
||||
utils::dirs::find_target_icons,
|
||||
};
|
||||
use crate::{Type, cmd, config::Config, feat, logging, module::lightweight::is_in_lightweight_mode};
|
||||
|
||||
use super::handle;
|
||||
use anyhow::Result;
|
||||
use smartstring::alias::String;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
use std::num::NonZeroU32;
|
||||
use std::sync::Arc;
|
||||
@@ -31,107 +33,13 @@ use tauri::{
|
||||
mod menu_def;
|
||||
use menu_def::{MenuIds, MenuTexts};
|
||||
|
||||
// TODO: 是否需要将可变菜单抽离存储起来,后续直接更新对应菜单实例,无需重新创建菜单(待考虑)
|
||||
|
||||
type ProxyMenuItem = (Option<Submenu<Wry>>, Vec<Box<dyn IsMenuItem<Wry>>>);
|
||||
|
||||
const TRAY_CLICK_DEBOUNCE_MS: u64 = 1_275;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct TrayState {}
|
||||
|
||||
pub struct Tray {
|
||||
limiter: DefaultDirectRateLimiter,
|
||||
}
|
||||
|
||||
impl TrayState {
|
||||
async fn get_tray_icon(verge: &IVerge) -> (bool, Vec<u8>) {
|
||||
let system_mode = verge.enable_system_proxy.as_ref().unwrap_or(&false);
|
||||
let tun_mode = verge.enable_tun_mode.as_ref().unwrap_or(&false);
|
||||
match (*system_mode, *tun_mode) {
|
||||
(true, true) => Self::get_tun_tray_icon(verge).await,
|
||||
(true, false) => Self::get_sysproxy_tray_icon(verge).await,
|
||||
(false, true) => Self::get_tun_tray_icon(verge).await,
|
||||
(false, false) => Self::get_common_tray_icon(verge).await,
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_common_tray_icon(verge: &IVerge) -> (bool, Vec<u8>) {
|
||||
let is_common_tray_icon = verge.common_tray_icon.unwrap_or(false);
|
||||
if is_common_tray_icon
|
||||
&& let Ok(Some(common_icon_path)) = find_target_icons("common")
|
||||
&& let Ok(icon_data) = fs::read(common_icon_path).await
|
||||
{
|
||||
return (true, icon_data);
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let tray_icon_colorful = verge.tray_icon.clone().unwrap_or_else(|| "monochrome".into());
|
||||
if tray_icon_colorful == "monochrome" {
|
||||
(false, include_bytes!("../../../icons/tray-icon-mono.ico").to_vec())
|
||||
} else {
|
||||
(false, include_bytes!("../../../icons/tray-icon.ico").to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
{
|
||||
(false, include_bytes!("../../../icons/tray-icon.ico").to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_sysproxy_tray_icon(verge: &IVerge) -> (bool, Vec<u8>) {
|
||||
let is_sysproxy_tray_icon = verge.sysproxy_tray_icon.unwrap_or(false);
|
||||
if is_sysproxy_tray_icon
|
||||
&& let Ok(Some(sysproxy_icon_path)) = find_target_icons("sysproxy")
|
||||
&& let Ok(icon_data) = fs::read(sysproxy_icon_path).await
|
||||
{
|
||||
return (true, icon_data);
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let tray_icon_colorful = verge.tray_icon.clone().unwrap_or_else(|| "monochrome".into());
|
||||
if tray_icon_colorful == "monochrome" {
|
||||
(
|
||||
false,
|
||||
include_bytes!("../../../icons/tray-icon-sys-mono-new.ico").to_vec(),
|
||||
)
|
||||
} else {
|
||||
(false, include_bytes!("../../../icons/tray-icon-sys.ico").to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
{
|
||||
(false, include_bytes!("../../../icons/tray-icon-sys.ico").to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_tun_tray_icon(verge: &IVerge) -> (bool, Vec<u8>) {
|
||||
let is_tun_tray_icon = verge.tun_tray_icon.unwrap_or(false);
|
||||
if is_tun_tray_icon
|
||||
&& let Ok(Some(tun_icon_path)) = find_target_icons("tun")
|
||||
&& let Ok(icon_data) = fs::read(tun_icon_path).await
|
||||
{
|
||||
return (true, icon_data);
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let tray_icon_colorful = verge.tray_icon.clone().unwrap_or_else(|| "monochrome".into());
|
||||
if tray_icon_colorful == "monochrome" {
|
||||
(
|
||||
false,
|
||||
include_bytes!("../../../icons/tray-icon-tun-mono-new.ico").to_vec(),
|
||||
)
|
||||
} else {
|
||||
(false, include_bytes!("../../../icons/tray-icon-tun.ico").to_vec())
|
||||
}
|
||||
}
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
{
|
||||
(false, include_bytes!("../../../icons/tray-icon-tun.ico").to_vec())
|
||||
}
|
||||
}
|
||||
icon_compoment: Arc<Mutex<TrayIcon>>,
|
||||
}
|
||||
|
||||
impl Default for Tray {
|
||||
@@ -143,6 +51,7 @@ impl Default for Tray {
|
||||
.unwrap()
|
||||
.allow_burst(NonZeroU32::new(1).unwrap()),
|
||||
),
|
||||
icon_compoment: Arc::new(Mutex::new(Default::default())),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,7 +163,6 @@ impl Tray {
|
||||
}
|
||||
|
||||
/// 更新托盘图标
|
||||
#[cfg(target_os = "macos")]
|
||||
pub async fn update_icon(&self, verge: &IVerge) -> Result<()> {
|
||||
if handle::Handle::global().is_exiting() {
|
||||
logging!(debug, Type::Tray, "应用正在退出,跳过托盘图标更新");
|
||||
@@ -271,36 +179,20 @@ impl Tray {
|
||||
}
|
||||
};
|
||||
|
||||
let (_is_custom_icon, icon_bytes) = TrayState::get_tray_icon(verge).await;
|
||||
|
||||
let colorful = verge.tray_icon.clone().unwrap_or_else(|| "monochrome".into());
|
||||
let is_colorful = colorful == "colorful";
|
||||
|
||||
let _ = tray.set_icon(Some(tauri::image::Image::from_bytes(&icon_bytes)?));
|
||||
let _ = tray.set_icon_as_template(!is_colorful);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
pub async fn update_icon(&self, verge: &IVerge) -> Result<()> {
|
||||
if handle::Handle::global().is_exiting() {
|
||||
logging!(debug, Type::Tray, "应用正在退出,跳过托盘图标更新");
|
||||
let mut icon_compoment_guard = self.icon_compoment.lock();
|
||||
let is_refresh = icon_compoment_guard.refresh(false, verge).await;
|
||||
if !is_refresh {
|
||||
logging!(debug, Type::Tray, "托盘图标未更改,跳过更新");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let app_handle = handle::Handle::app_handle();
|
||||
let icon_comp_view = icon_compoment_guard.get();
|
||||
|
||||
let tray = match app_handle.tray_by_id("main") {
|
||||
Some(tray) => tray,
|
||||
None => {
|
||||
logging!(warn, Type::Tray, "Failed to update tray icon: tray not found");
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
let _ = tray.set_icon(Some(tauri::image::Image::from_bytes(icon_comp_view.last_icon_bytes)?));
|
||||
#[cfg(target_os = "macos")]
|
||||
let _ = tray.set_icon_as_template(matches!(icon_comp_view.last_icon_style, IconStyle::Monochrome));
|
||||
|
||||
let (_is_custom_icon, icon_bytes) = TrayState::get_tray_icon(verge).await;
|
||||
|
||||
let _ = tray.set_icon(Some(tauri::image::Image::from_bytes(&icon_bytes)?));
|
||||
drop(icon_compoment_guard);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -391,8 +283,12 @@ impl Tray {
|
||||
|
||||
let verge = Config::verge().await.data_arc();
|
||||
|
||||
let icon_bytes = TrayState::get_tray_icon(&verge).await.1;
|
||||
let icon = tauri::image::Image::from_bytes(&icon_bytes)?;
|
||||
{
|
||||
self.icon_compoment.lock().refresh(false, &verge).await;
|
||||
}
|
||||
let cache_icon_guard = self.icon_compoment.lock();
|
||||
let icon = tauri::image::Image::from_bytes(cache_icon_guard.get().last_icon_bytes)?;
|
||||
drop(cache_icon_guard);
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
let builder = TrayIconBuilder::with_id("main").icon(icon).icon_as_template(false);
|
||||
@@ -609,7 +505,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 {
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
58
src-tauri/src/core/tray/view.rs
Normal file
58
src-tauri/src/core/tray/view.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub type IconBytes = Cow<'static, [u8]>;
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||
pub(crate) enum ProxyStatus {
|
||||
#[default]
|
||||
// Not Proxy, Not TUN
|
||||
Idle,
|
||||
// Proxy Enabled, Not TUN
|
||||
Proxy,
|
||||
// Not Proxy, TUN Enabled
|
||||
Tun,
|
||||
// Proxy Enabled, TUN Enabled
|
||||
ProxyTUN,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||
pub(crate) enum IconStyle {
|
||||
#[default]
|
||||
Normal,
|
||||
Custom,
|
||||
Monochrome,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
pub(crate) trait TrayComponent: CacheComponent {
|
||||
type Context;
|
||||
|
||||
async fn refresh(&mut self, force: bool, ctx: &Self::Context) -> bool;
|
||||
}
|
||||
|
||||
pub(crate) trait CacheComponent {
|
||||
type Cache;
|
||||
type View<'a>
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
fn is_some(&self) -> bool;
|
||||
fn get(&self) -> Self::View<'_>;
|
||||
fn update(&mut self, t: Self::Cache);
|
||||
fn equals(&self, other: &Self::Cache) -> bool;
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct TrayIconCache {
|
||||
pub(crate) last_icon_style: IconStyle,
|
||||
pub(crate) last_proxy_status: ProxyStatus,
|
||||
pub(crate) last_icon_bytes: IconBytes,
|
||||
}
|
||||
|
||||
pub(crate) struct TrayIconView<'a> {
|
||||
pub(crate) last_icon_style: &'a IconStyle,
|
||||
pub(crate) last_icon_bytes: &'a IconBytes,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct TrayIcon(pub TrayIconCache);
|
||||
@@ -90,6 +90,7 @@ pub fn app_icons_dir() -> Result<PathBuf> {
|
||||
Ok(app_home_dir()?.join("icons"))
|
||||
}
|
||||
|
||||
// TODO find target icon when needed
|
||||
pub fn find_target_icons(target: &str) -> Result<Option<String>> {
|
||||
let icons_dir = app_icons_dir()?;
|
||||
let icon_path = fs::read_dir(&icons_dir)?
|
||||
|
||||
Reference in New Issue
Block a user