添加win下系统托盘 节点

代理->代理组->nodes
同时添加了对应gui同步
This commit is contained in:
Kasserrr
2025-08-28 02:58:45 +08:00
Unverified
parent f566a564af
commit 2934a2b7f2
5 changed files with 109 additions and 61 deletions

View File

@@ -1,5 +1,7 @@
use tauri::Emitter;
use super::CmdResult;
use crate::{ipc::IpcManager, logging, state::proxy::ProxyRequestCache, utils::logging::Type};
use crate::{core::{handle::Handle, tray::Tray}, ipc::IpcManager, logging, state::proxy::ProxyRequestCache, utils::logging::Type};
use std::time::Duration;
const PROXIES_REFRESH_INTERVAL: Duration = Duration::from_secs(60);
@@ -62,3 +64,35 @@ pub async fn sync_tray_proxy_selection() -> CmdResult<()> {
}
}
}
/// 更新代理选择并同步托盘和GUI状态
#[tauri::command]
pub async fn update_proxy_and_sync(group: String, proxy: String) -> CmdResult<()> {
match IpcManager::global().update_proxy(&group, &proxy).await {
Ok(_) => {
logging!(info, Type::Cmd, "Proxy updated successfully: {} -> {}", group, proxy);
let cache = crate::state::proxy::ProxyRequestCache::global();
let key = crate::state::proxy::ProxyRequestCache::make_key("proxies", "default");
cache.map.remove(&key);
if let Err(e) = Tray::global().update_menu().await {
logging!(error, Type::Cmd, "Failed to sync tray menu: {}", e);
}
if let Some(app_handle) = Handle::global().app_handle() {
let _ = app_handle.emit("verge://force-refresh-proxies", ());
let _ = app_handle.emit("verge://refresh-proxy-config", ());
}
logging!(info, Type::Cmd, "Proxy and sync completed successfully: {} -> {}", group, proxy);
Ok(())
}
Err(e) => {
logging!(error, Type::Cmd, "Failed to update proxy: {} -> {}, error: {}", group, proxy, e);
Err(e.to_string())
}
}
}

View File

@@ -1039,14 +1039,13 @@ fn on_menu_event(_: &AppHandle, event: MenuEvent) {
feat::toggle_proxy_profile(profile_index.into()).await; // Await async function
}
id if id.starts_with("proxy_") => {
// 处理代理节点切换: proxy_{group_name}_{proxy_name}
// proxy_{group_name}_{proxy_name}
let parts: Vec<&str> = id.splitn(3, '_').collect();
if parts.len() == 3 && parts[0] == "proxy" {
let group_name = parts[1];
let proxy_name = parts[2];
// 获取当前clash配置模式
let current_mode = {
Config::clash()
.await
@@ -1058,31 +1057,30 @@ fn on_menu_event(_: &AppHandle, event: MenuEvent) {
.to_owned()
};
// 使用 IPC 管理器切换代理节点
match IpcManager::global().update_proxy(group_name, proxy_name).await {
match cmd::proxy::update_proxy_and_sync(group_name.to_string(), proxy_name.to_string()).await {
Ok(_) => {
log::info!(target: "app", "代理节点切换成功: {} -> {} (模式: {}, 目标组: {})", group_name, proxy_name, current_mode, group_name);
println!("代理节点切换成功: {} -> {} (模式: {}, 目标组: {})", group_name, proxy_name, current_mode, group_name);
// 立即刷新托盘菜单
if let Err(e) = Tray::global().update_menu().await {
log::warn!(target: "app", "立即更新托盘菜单失败: {e}");
}
// 发出前端刷新事件确保GUI及时更新
if let Some(app_handle) = handle::Handle::global().app_handle() {
// 先强制刷新代理缓存然后发送GUI刷新事件
let _ = app_handle.emit("verge://force-refresh-proxies", ());
// 发送GUI刷新事件
let _ = app_handle.emit("verge://refresh-proxy-config", ());
let _ = app_handle.emit("verge://refresh-clash-config", ());
log::debug!(target: "app", "托盘代理切换事件已发送到前端");
}
log::info!(target: "app", " {} -> {} (模式: {})", group_name, proxy_name, current_mode);
}
Err(e) => {
log::error!(target: "app", "代理节点切换失败: {} -> {}, 错误: {}", group_name, proxy_name, e);
log::error!(target: "app", " {} -> {}, 错误: {:?}", group_name, proxy_name, e);
match IpcManager::global().update_proxy(group_name, proxy_name).await {
Ok(_) => {
log::info!(target: "app", " {} -> {}", group_name, proxy_name);
if let Err(e) = Tray::global().update_menu().await {
log::warn!(target: "app", "托盘菜单更新失败: {e}");
}
if let Some(app_handle) = handle::Handle::global().app_handle() {
let _ = app_handle.emit("verge://force-refresh-proxies", ());
let _ = app_handle.emit("verge://refresh-proxy-config", ());
}
}
Err(e2) => {
log::error!(target: "app", "托盘代理切换回退也失败: {} -> {}, 错误: {}", group_name, proxy_name, e2);
}
}
}
}
}

View File

@@ -338,6 +338,7 @@ mod app_init {
cmd::force_refresh_proxies,
cmd::get_providers_proxies,
cmd::sync_tray_proxy_selection,
cmd::update_proxy_and_sync,
cmd::save_dns_config,
cmd::apply_dns_config,
cmd::check_dns_config_exists,

View File

@@ -8,6 +8,7 @@ import {
deleteConnection,
getGroupProxyDelays,
syncTrayProxySelection,
updateProxyAndSync,
} from "@/services/cmds";
import { forceRefreshProxies } from "@/services/cmds";
import { useProfiles } from "@/hooks/use-profiles";
@@ -344,44 +345,54 @@ export const ProxyGroups = (props: Props) => {
const { name, now } = group;
console.log(`[ProxyGroups] GUI代理切换: ${name} -> ${proxy.name}`);
await updateProxy(name, proxy.name);
await forceRefreshProxies();
onProxies();
// 断开连接
if (verge?.auto_close_connection) {
getConnections().then(({ connections }) => {
connections.forEach((conn) => {
if (conn.chains.includes(now!)) {
deleteConnection(conn.id);
}
});
});
}
// 保存到selected中
if (!current) return;
if (!current.selected) current.selected = [];
const index = current.selected.findIndex(
(item) => item.name === group.name,
);
if (index < 0) {
current.selected.push({ name, now: proxy.name });
} else {
current.selected[index] = { name, now: proxy.name };
}
await patchCurrent({ selected: current.selected });
// 同步托盘菜单状态
try {
await syncTrayProxySelection();
console.log(`[ProxyGroups] 托盘状态同步成功: ${name} -> ${proxy.name}`);
// 1. 保存到selected中 (先保存本地状态)
if (current) {
if (!current.selected) current.selected = [];
const index = current.selected.findIndex(
(item) => item.name === group.name,
);
if (index < 0) {
current.selected.push({ name, now: proxy.name });
} else {
current.selected[index] = { name, now: proxy.name };
}
await patchCurrent({ selected: current.selected });
}
// 2. 使用统一的同步命令更新代理并同步状态
await updateProxyAndSync(name, proxy.name);
console.log(`[ProxyGroups] 代理和状态同步完成: ${name} -> ${proxy.name}`);
// 3. 刷新前端显示
onProxies();
// 4. 断开连接 (异步处理不影响UI更新)
if (verge?.auto_close_connection) {
getConnections().then(({ connections }) => {
connections.forEach((conn) => {
if (conn.chains.includes(now!)) {
deleteConnection(conn.id);
}
});
});
}
} catch (error) {
console.warn("Failed to sync tray proxy selection:", error);
console.error(`[ProxyGroups] 代理切换失败: ${name} -> ${proxy.name}`, error);
// 如果统一命令失败,回退到原来的方式
try {
await updateProxy(name, proxy.name);
await forceRefreshProxies();
await syncTrayProxySelection();
onProxies();
console.log(`[ProxyGroups] 代理切换回退成功: ${name} -> ${proxy.name}`);
} catch (fallbackError) {
console.error(`[ProxyGroups] 代理切换回退也失败: ${name} -> ${proxy.name}`, fallbackError);
onProxies(); // 至少刷新显示
}
}
},
);

View File

@@ -147,6 +147,10 @@ export async function syncTrayProxySelection() {
return invoke<void>("sync_tray_proxy_selection");
}
export async function updateProxyAndSync(group: string, proxy: string) {
return invoke<void>("update_proxy_and_sync", { group, proxy });
}
export async function getProxies(): Promise<{
global: IProxyGroupItem;
direct: IProxyItem;