From 2080dbdc0fe984f98518ec7b35507d0c5c810576 Mon Sep 17 00:00:00 2001 From: wonfen Date: Fri, 29 Aug 2025 20:46:45 +0800 Subject: [PATCH] refactor: proxy control component and system settings UI fix: handle tun toggle state after service uninstall --- UPDATELOG.md | 5 + src/components/home/proxy-tun-card.tsx | 1 + src/components/setting/setting-system.tsx | 173 ++---------------- .../shared/ProxyControlSwitches.tsx | 75 ++++++-- src/hooks/use-verge.ts | 30 +++ src/locales/en.json | 2 + src/locales/zh.json | 2 + 7 files changed, 117 insertions(+), 171 deletions(-) diff --git a/UPDATELOG.md b/UPDATELOG.md index eccbcd4f..9ada17c8 100644 --- a/UPDATELOG.md +++ b/UPDATELOG.md @@ -19,6 +19,11 @@ - 修复通过托盘重启应用无法恢复 - 修复订阅在某些情况下无法导入 - 修复无法新建订阅时使用远程链接 +- 修复卸载服务后的 tun 开关状态问题 + +### 👙 界面样式 + +- 统一代理设置样式 ### 🗑️ 移除内容 diff --git a/src/components/home/proxy-tun-card.tsx b/src/components/home/proxy-tun-card.tsx index fe1dc04e..3a6795b9 100644 --- a/src/components/home/proxy-tun-card.tsx +++ b/src/components/home/proxy-tun-card.tsx @@ -232,6 +232,7 @@ export const ProxyTunCard: FC = () => { diff --git a/src/components/setting/setting-system.tsx b/src/components/setting/setting-system.tsx index 37012d49..c015b4ff 100644 --- a/src/components/setting/setting-system.tsx +++ b/src/components/setting/setting-system.tsx @@ -1,29 +1,19 @@ import { mutate } from "swr"; -import { useRef } from "react"; +import React, { useRef } from "react"; import { useTranslation } from "react-i18next"; -import { - SettingsRounded, - PlayArrowRounded, - PauseRounded, - WarningRounded, - BuildRounded, - DeleteForeverRounded, -} from "@mui/icons-material"; +import { WarningRounded } from "@mui/icons-material"; import { useVerge } from "@/hooks/use-verge"; -import { useSystemProxyState } from "@/hooks/use-system-proxy-state"; import { DialogRef, Switch } from "@/components/base"; import { SettingList, SettingItem } from "./mods/setting-comp"; import { GuardState } from "./mods/guard-state"; import { SysproxyViewer } from "./mods/sysproxy-viewer"; import { TunViewer } from "./mods/tun-viewer"; import { TooltipIcon } from "@/components/base/base-tooltip-icon"; -import { uninstallService, restartCore, stopCore } from "@/services/cmds"; -import { useLockFn } from "ahooks"; -import { Button, Tooltip } from "@mui/material"; +import { Tooltip } from "@mui/material"; import { useSystemState } from "@/hooks/use-system-state"; +import ProxyControlSwitches from "@/components/shared/ProxyControlSwitches"; import { showNotice } from "@/services/noticeService"; -import { useServiceInstaller } from "@/hooks/useServiceInstaller"; interface Props { onError?: (err: Error) => void; @@ -33,167 +23,30 @@ const SettingSystem = ({ onError }: Props) => { const { t } = useTranslation(); const { verge, mutateVerge, patchVerge } = useVerge(); - const { installServiceAndRestartCore } = useServiceInstaller(); - const { actualState: systemProxyActualState, toggleSystemProxy } = - useSystemProxyState(); - const { isAdminMode, isServiceMode, mutateRunningMode } = useSystemState(); + const { isAdminMode } = useSystemState(); - // +++ isTunAvailable 现在使用 SWR 的 isServiceMode - const isTunAvailable = isServiceMode || isAdminMode; + const { enable_auto_launch, enable_silent_start } = verge ?? {}; const sysproxyRef = useRef(null); const tunRef = useRef(null); - const { enable_tun_mode, enable_auto_launch, enable_silent_start } = - verge ?? {}; - - const onSwitchFormat = (_e: any, value: boolean) => value; + const onSwitchFormat = ( + _e: React.ChangeEvent, + value: boolean, + ) => value; const onChangeData = (patch: Partial) => { mutateVerge({ ...verge, ...patch }, false); }; - // 抽象服务操作逻辑 - const handleServiceOperation = useLockFn( - async ({ - beforeMsg, - action, - actionMsg, - successMsg, - }: { - beforeMsg: string; - action: () => Promise; - actionMsg: string; - successMsg: string; - }) => { - try { - showNotice("info", beforeMsg); - await stopCore(); - showNotice("info", actionMsg); - await action(); - showNotice("success", successMsg); - showNotice("info", t("Restarting Core...")); - await restartCore(); - await mutateRunningMode(); - } catch (err: any) { - showNotice("error", err.message || err.toString()); - try { - showNotice("info", t("Try running core as Sidecar...")); - await restartCore(); - await mutateRunningMode(); - } catch (e: any) { - showNotice("error", e?.message || e?.toString()); - } - } - }, - ); - - // 卸载系统服务 - const onUninstallService = () => - handleServiceOperation({ - beforeMsg: t("Stopping Core..."), - action: uninstallService, - actionMsg: t("Uninstalling Service..."), - successMsg: t("Service Uninstalled Successfully"), - }); - return ( - - tunRef.current?.open()} - /> - {!isTunAvailable && ( - - - - )} - {!isServiceMode && !isAdminMode && ( - - - - )} - {isServiceMode && ( - - - - )} - - } - > - { - if (!isTunAvailable) return; - onChangeData({ enable_tun_mode: e }); - }} - onGuard={(e) => { - if (!isTunAvailable) { - showNotice("error", t("TUN requires Service Mode or Admin Mode")); - return Promise.reject( - new Error(t("TUN requires Service Mode or Admin Mode")), - ); - } - return patchVerge({ enable_tun_mode: e }); - }} - > - - - - - sysproxyRef.current?.open()} - /> - {systemProxyActualState ? ( - - ) : ( - - )} - - } - > - toggleSystemProxy(e)} - > - - - + + + void; + noRightPadding?: boolean; } /** * 可复用的代理控制开关组件 * 包含 Tun Mode 和 System Proxy 的开关功能 */ -const ProxyControlSwitches = ({ label, onError }: ProxySwitchProps) => { +const ProxyControlSwitches = ({ + label, + onError, + noRightPadding = false, +}: ProxySwitchProps) => { const { t } = useTranslation(); const { verge, mutateVerge, patchVerge } = useVerge(); const theme = useTheme(); @@ -42,7 +51,7 @@ const ProxyControlSwitches = ({ label, onError }: ProxySwitchProps) => { const { actualState: systemProxyActualState, toggleSystemProxy } = useSystemProxyState(); - const { isAdminMode, isServiceMode } = useSystemState(); + const { isAdminMode, isServiceMode, mutateRunningMode } = useSystemState(); const isTunAvailable = isServiceMode || isAdminMode; @@ -55,7 +64,10 @@ const ProxyControlSwitches = ({ label, onError }: ProxySwitchProps) => { const isSystemProxyMode = label === t("System Proxy") || !label; const isTunMode = label === t("Tun Mode"); - const onSwitchFormat = (_e: any, value: boolean) => value; + const onSwitchFormat = ( + _e: React.ChangeEvent, + value: boolean, + ) => value; const onChangeData = (patch: Partial) => { mutateVerge({ ...verge, ...patch }, false); }; @@ -63,8 +75,31 @@ const ProxyControlSwitches = ({ label, onError }: ProxySwitchProps) => { // 安装系统服务 const onInstallService = installServiceAndRestartCore; + // 卸载系统服务 + const onUninstallService = useLockFn(async () => { + try { + showNotice("info", t("Stopping Core...")); + await stopCore(); + showNotice("info", t("Uninstalling Service...")); + await uninstallService(); + showNotice("success", t("Service Uninstalled Successfully")); + showNotice("info", t("Restarting Core...")); + await restartCore(); + await mutateRunningMode(); + } catch (err: unknown) { + showNotice("error", (err as Error).message || err?.toString()); + try { + showNotice("info", t("Try running core as Sidecar...")); + await restartCore(); + await mutateRunningMode(); + } catch (e: unknown) { + showNotice("error", (e as Error)?.message || e?.toString()); + } + } + }); + return ( - + {label && ( { alignItems: "center", justifyContent: "space-between", p: 1, + pr: noRightPadding ? 1 : 2, borderRadius: 1.5, bgcolor: enable_system_proxy ? alpha(theme.palette.success.main, 0.07) @@ -111,12 +147,6 @@ const ProxyControlSwitches = ({ label, onError }: ProxySwitchProps) => { > {t("System Proxy")} - {/* - {sysproxy?.enable - ? t("Proxy is active") - : t("Enable this for most users") - } - */} @@ -155,6 +185,7 @@ const ProxyControlSwitches = ({ label, onError }: ProxySwitchProps) => { alignItems: "center", justifyContent: "space-between", p: 1, + pr: noRightPadding ? 1 : 2, borderRadius: 1.5, bgcolor: enable_tun_mode ? alpha(theme.palette.success.main, 0.07) @@ -182,6 +213,15 @@ const ProxyControlSwitches = ({ label, onError }: ProxySwitchProps) => { {t("Tun Mode")} + + {!isTunAvailable && ( + + + + )} @@ -199,6 +239,19 @@ const ProxyControlSwitches = ({ label, onError }: ProxySwitchProps) => { )} + {isServiceMode && ( + + + + )} + { + const { t } = useTranslation(); + const { isAdminMode, isServiceMode } = useSystemState(); + const { data: verge, mutate: mutateVerge } = useSWR( "getVergeConfig", async () => { @@ -15,6 +22,29 @@ export const useVerge = () => { mutateVerge(); }; + const isTunAvailable = isServiceMode || isAdminMode; + const { enable_tun_mode } = verge ?? {}; + + // 当服务不可用且TUN模式开启时自动关闭TUN + useEffect(() => { + if (enable_tun_mode && !isTunAvailable) { + console.log("[useVerge] 检测到服务不可用,自动关闭TUN模式"); + + patchVergeConfig({ enable_tun_mode: false }) + .then(() => { + mutateVerge(); + showNotice( + "info", + t("TUN Mode automatically disabled due to service unavailable"), + ); + }) + .catch((err) => { + console.error("[useVerge] 自动关闭TUN模式失败:", err); + showNotice("error", t("Failed to disable TUN Mode automatically")); + }); + } + }, [isTunAvailable, enable_tun_mode, mutateVerge, t]); + return { verge, mutateVerge, diff --git a/src/locales/en.json b/src/locales/en.json index 8650e095..b747d5a7 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -210,6 +210,8 @@ "Reset to Default": "Reset to Default", "Tun Mode Info": "Tun (Virtual NIC) mode: Captures all system traffic, when enabled, there is no need to enable system proxy.", "TUN requires Service Mode or Admin Mode": "TUN requires Service Mode or Admin Mode", + "TUN Mode automatically disabled due to service unavailable": "TUN Mode automatically disabled due to service unavailable", + "Failed to disable TUN Mode automatically": "Failed to disable TUN Mode automatically", "System Proxy Enabled": "System proxy is enabled, your applications will access the network through the proxy", "System Proxy Disabled": "System proxy is disabled, it is recommended for most users to turn on this option", "TUN Mode Enabled": "TUN mode is enabled, applications will access the network through the virtual network card", diff --git a/src/locales/zh.json b/src/locales/zh.json index ac574727..c7a522e4 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -210,6 +210,8 @@ "Reset to Default": "重置为默认值", "Tun Mode Info": "TUN(虚拟网卡)模式接管系统所有流量,启用时无须打开系统代理", "TUN requires Service Mode or Admin Mode": "TUN 模式需要安装服务模式或管理员模式", + "TUN Mode automatically disabled due to service unavailable": "由于服务不可用,TUN 模式已自动关闭", + "Failed to disable TUN Mode automatically": "自动关闭 TUN 模式失败", "System Proxy Enabled": "系统代理已启用,您的应用将通过代理访问网络", "System Proxy Disabled": "系统代理已关闭,建议大多数用户打开此选项", "TUN Mode Enabled": "TUN 模式已启用,应用将通过虚拟网卡访问网络",