Merge branch 'dev' of https://github.com/Be-Forever223/clash-verge-rev into dev
This commit is contained in:
@@ -657,89 +657,81 @@ async fn create_tray_menu(
|
||||
if let Some(proxies) = proxy_nodes_data.get("proxies").and_then(|v| v.as_object()) {
|
||||
|
||||
for (group_name, group_data) in proxies.iter() {
|
||||
let group_type_wrap = group_data.get("type").and_then(|v| v.as_str());
|
||||
let all_proxies_wrap = group_data.get("all").and_then(|v| v.as_array());
|
||||
|
||||
if group_type_wrap.is_none() || all_proxies_wrap.is_none() {
|
||||
continue;
|
||||
}
|
||||
if let (Some(group_type),Some(all_proxies)) = (group_data.get("type").and_then(|v| v.as_str()),group_data.get("all").and_then(|v| v.as_array())) {
|
||||
// 在全局模式下只显示GLOBAL组,在规则模式下显示所有Selector类型的代理组
|
||||
let should_show_group = if mode == "global" {
|
||||
group_name == "GLOBAL"
|
||||
} else {
|
||||
group_type == "Selector" && group_name != "GLOBAL"
|
||||
};
|
||||
|
||||
if !should_show_group {
|
||||
continue;
|
||||
}
|
||||
|
||||
let group_type = group_type_wrap.unwrap();
|
||||
let all_proxies = all_proxies_wrap.unwrap();
|
||||
|
||||
// 在全局模式下只显示GLOBAL组,在规则模式下显示所有Selector类型的代理组
|
||||
let should_show_group = if mode == "global" {
|
||||
group_name == "GLOBAL"
|
||||
} else {
|
||||
group_type == "Selector" && group_name != "GLOBAL"
|
||||
};
|
||||
|
||||
if !should_show_group {
|
||||
continue;
|
||||
}
|
||||
|
||||
let now_proxy = group_data.get("now").and_then(|v| v.as_str()).unwrap_or("");
|
||||
|
||||
// 为每个代理组创建子菜单项
|
||||
let mut group_items = Vec::new();
|
||||
for proxy_name in all_proxies.iter() {
|
||||
if let Some(proxy_str) = proxy_name.as_str() {
|
||||
let is_selected = proxy_str == now_proxy;
|
||||
let item_id = format!("proxy_{}_{}", group_name, proxy_str);
|
||||
|
||||
match CheckMenuItem::with_id(
|
||||
app_handle,
|
||||
item_id,
|
||||
proxy_str, // 只显示节点名,不显示组名前缀
|
||||
true,
|
||||
is_selected,
|
||||
None::<&str>,
|
||||
) {
|
||||
Ok(item) => group_items.push(item),
|
||||
Err(e) => log::warn!(target: "app", "创建代理菜单项失败: {}", e),
|
||||
let now_proxy = group_data.get("now").and_then(|v| v.as_str()).unwrap_or("");
|
||||
|
||||
// 为每个代理组创建子菜单项
|
||||
let mut group_items = Vec::new();
|
||||
for proxy_name in all_proxies.iter() {
|
||||
if let Some(proxy_str) = proxy_name.as_str() {
|
||||
let is_selected = proxy_str == now_proxy;
|
||||
let item_id = format!("proxy_{}_{}", group_name, proxy_str);
|
||||
|
||||
match CheckMenuItem::with_id(
|
||||
app_handle,
|
||||
item_id,
|
||||
proxy_str, // 只显示节点名,不显示组名前缀
|
||||
true,
|
||||
is_selected,
|
||||
None::<&str>,
|
||||
) {
|
||||
Ok(item) => group_items.push(item),
|
||||
Err(e) => log::warn!(target: "app", "创建代理菜单项失败: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 创建代理组子菜单
|
||||
if !group_items.is_empty() {
|
||||
let group_items_refs: Vec<&dyn IsMenuItem<Wry>> = group_items
|
||||
.iter()
|
||||
.map(|item| item as &dyn IsMenuItem<Wry>)
|
||||
.collect();
|
||||
|
||||
// 判断当前代理组是否为真正在使用中的组
|
||||
let is_group_active = if mode == "global" {
|
||||
// 全局模式下,只有GLOBAL组才能显示勾选
|
||||
group_name == "GLOBAL" && !now_proxy.is_empty()
|
||||
} else if mode == "direct" {
|
||||
// 直连模式下,不显示任何勾选
|
||||
false
|
||||
} else {
|
||||
// 规则模式下:只对用户在当前配置中手动选择过的代理组显示勾选
|
||||
// 这些组表示用户真正关心和使用的代理组
|
||||
let is_user_selected = current_profile_selected.iter().any(|selected| {
|
||||
selected.name.as_deref() == Some(group_name)
|
||||
});
|
||||
is_user_selected && !now_proxy.is_empty()
|
||||
};
|
||||
|
||||
// 如果组处于活动状态,在组名前添加勾选标记
|
||||
let group_display_name = if is_group_active {
|
||||
format!("✓ {}", group_name)
|
||||
} else {
|
||||
group_name.to_string()
|
||||
};
|
||||
|
||||
match Submenu::with_id_and_items(
|
||||
app_handle,
|
||||
format!("proxy_group_{}", group_name),
|
||||
group_display_name, // 使用带勾选标记的组名
|
||||
true,
|
||||
&group_items_refs,
|
||||
) {
|
||||
Ok(submenu) => submenus.push(submenu),
|
||||
Err(e) => log::warn!(target: "app", "创建代理组子菜单失败: {}", e),
|
||||
// 创建代理组子菜单
|
||||
if !group_items.is_empty() {
|
||||
let group_items_refs: Vec<&dyn IsMenuItem<Wry>> = group_items
|
||||
.iter()
|
||||
.map(|item| item as &dyn IsMenuItem<Wry>)
|
||||
.collect();
|
||||
|
||||
// 判断当前代理组是否为真正在使用中的组
|
||||
let is_group_active = if mode == "global" {
|
||||
// 全局模式下,只有GLOBAL组才能显示勾选
|
||||
group_name == "GLOBAL" && !now_proxy.is_empty()
|
||||
} else if mode == "direct" {
|
||||
// 直连模式下,不显示任何勾选
|
||||
false
|
||||
} else {
|
||||
// 规则模式下:只对用户在当前配置中手动选择过的代理组显示勾选
|
||||
// 这些组表示用户真正关心和使用的代理组
|
||||
let is_user_selected = current_profile_selected.iter().any(|selected| {
|
||||
selected.name.as_deref() == Some(group_name)
|
||||
});
|
||||
is_user_selected && !now_proxy.is_empty()
|
||||
};
|
||||
|
||||
// 如果组处于活动状态,在组名前添加勾选标记
|
||||
let group_display_name = if is_group_active {
|
||||
format!("✓ {}", group_name)
|
||||
} else {
|
||||
group_name.to_string()
|
||||
};
|
||||
|
||||
match Submenu::with_id_and_items(
|
||||
app_handle,
|
||||
format!("proxy_group_{}", group_name),
|
||||
group_display_name, // 使用带勾选标记的组名
|
||||
true,
|
||||
&group_items_refs,
|
||||
) {
|
||||
Ok(submenu) => submenus.push(submenu),
|
||||
Err(e) => log::warn!(target: "app", "创建代理组子菜单失败: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,11 @@ import {
|
||||
} from "@mui/icons-material";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { EnhancedCard } from "@/components/home/enhanced-card";
|
||||
import { updateProxy, deleteConnection, syncTrayProxySelection } from "@/services/cmds";
|
||||
import {
|
||||
updateProxy,
|
||||
deleteConnection,
|
||||
syncTrayProxySelection,
|
||||
} from "@/services/cmds";
|
||||
import delayManager from "@/services/delay";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { useAppData } from "@/providers/app-data-provider";
|
||||
|
||||
@@ -344,7 +344,7 @@ export const ProxyGroups = (props: Props) => {
|
||||
|
||||
const { name, now } = group;
|
||||
console.log(`[ProxyGroups] GUI代理切换: ${name} -> ${proxy.name}`);
|
||||
|
||||
|
||||
try {
|
||||
// 1. 保存到selected中 (先保存本地状态)
|
||||
if (current) {
|
||||
@@ -364,7 +364,9 @@ export const ProxyGroups = (props: Props) => {
|
||||
|
||||
// 2. 使用统一的同步命令更新代理并同步状态
|
||||
await updateProxyAndSync(name, proxy.name);
|
||||
console.log(`[ProxyGroups] 代理和状态同步完成: ${name} -> ${proxy.name}`);
|
||||
console.log(
|
||||
`[ProxyGroups] 代理和状态同步完成: ${name} -> ${proxy.name}`,
|
||||
);
|
||||
|
||||
// 3. 刷新前端显示
|
||||
onProxies();
|
||||
@@ -379,18 +381,25 @@ export const ProxyGroups = (props: Props) => {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error(`[ProxyGroups] 代理切换失败: ${name} -> ${proxy.name}`, 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}`);
|
||||
console.log(
|
||||
`[ProxyGroups] 代理切换回退成功: ${name} -> ${proxy.name}`,
|
||||
);
|
||||
} catch (fallbackError) {
|
||||
console.error(`[ProxyGroups] 代理切换回退也失败: ${name} -> ${proxy.name}`, fallbackError);
|
||||
console.error(
|
||||
`[ProxyGroups] 代理切换回退也失败: ${name} -> ${proxy.name}`,
|
||||
fallbackError,
|
||||
);
|
||||
onProxies(); // 至少刷新显示
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ export const AppDataProvider = ({
|
||||
// 监听强制代理刷新事件(托盘代理切换立即刷新)
|
||||
const handleForceRefreshProxies = () => {
|
||||
console.log("[AppDataProvider] 强制代理刷新事件");
|
||||
|
||||
|
||||
// 立即刷新,无延迟,无防抖
|
||||
forceRefreshProxies()
|
||||
.then(() => {
|
||||
@@ -263,9 +263,18 @@ export const AppDataProvider = ({
|
||||
// 使用 Tauri 事件监听器替代 window 事件监听器
|
||||
const setupTauriListeners = async () => {
|
||||
try {
|
||||
const unlistenClash = await listen("verge://refresh-clash-config", handleRefreshClash);
|
||||
const unlistenProxy = await listen("verge://refresh-proxy-config", handleRefreshProxy);
|
||||
const unlistenForceRefresh = await listen("verge://force-refresh-proxies", handleForceRefreshProxies);
|
||||
const unlistenClash = await listen(
|
||||
"verge://refresh-clash-config",
|
||||
handleRefreshClash,
|
||||
);
|
||||
const unlistenProxy = await listen(
|
||||
"verge://refresh-proxy-config",
|
||||
handleRefreshProxy,
|
||||
);
|
||||
const unlistenForceRefresh = await listen(
|
||||
"verge://force-refresh-proxies",
|
||||
handleForceRefreshProxies,
|
||||
);
|
||||
|
||||
return () => {
|
||||
unlistenClash();
|
||||
@@ -274,16 +283,34 @@ export const AppDataProvider = ({
|
||||
};
|
||||
} catch (error) {
|
||||
console.warn("[AppDataProvider] 设置 Tauri 事件监听器失败:", error);
|
||||
|
||||
|
||||
// 降级到 window 事件监听器
|
||||
window.addEventListener("verge://refresh-clash-config", handleRefreshClash);
|
||||
window.addEventListener("verge://refresh-proxy-config", handleRefreshProxy);
|
||||
window.addEventListener("verge://force-refresh-proxies", handleForceRefreshProxies);
|
||||
window.addEventListener(
|
||||
"verge://refresh-clash-config",
|
||||
handleRefreshClash,
|
||||
);
|
||||
window.addEventListener(
|
||||
"verge://refresh-proxy-config",
|
||||
handleRefreshProxy,
|
||||
);
|
||||
window.addEventListener(
|
||||
"verge://force-refresh-proxies",
|
||||
handleForceRefreshProxies,
|
||||
);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("verge://refresh-clash-config", handleRefreshClash);
|
||||
window.removeEventListener("verge://refresh-proxy-config", handleRefreshProxy);
|
||||
window.removeEventListener("verge://force-refresh-proxies", handleForceRefreshProxies);
|
||||
window.removeEventListener(
|
||||
"verge://refresh-clash-config",
|
||||
handleRefreshClash,
|
||||
);
|
||||
window.removeEventListener(
|
||||
"verge://refresh-proxy-config",
|
||||
handleRefreshProxy,
|
||||
);
|
||||
window.removeEventListener(
|
||||
"verge://force-refresh-proxies",
|
||||
handleForceRefreshProxies,
|
||||
);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user