From d5a174c71b0030337230d3ddd63c8999aa7374b0 Mon Sep 17 00:00:00 2001 From: wonfen Date: Mon, 23 Jun 2025 12:59:24 +0800 Subject: [PATCH] perf: improve proxy status indicator and toggle responsiveness --- src/components/home/proxy-tun-card.tsx | 10 ++- src/components/setting/setting-system.tsx | 82 ++++--------------- .../shared/ProxyControlSwitches.tsx | 45 ++++------ src/hooks/use-system-proxy-state.ts | 72 ++++++++++++++++ src/providers/app-data-provider.tsx | 5 +- 5 files changed, 110 insertions(+), 104 deletions(-) create mode 100644 src/hooks/use-system-proxy-state.ts diff --git a/src/components/home/proxy-tun-card.tsx b/src/components/home/proxy-tun-card.tsx index 5803c326..6dcba565 100644 --- a/src/components/home/proxy-tun-card.tsx +++ b/src/components/home/proxy-tun-card.tsx @@ -19,6 +19,7 @@ import { } from "@mui/icons-material"; import { useVerge } from "@/hooks/use-verge"; import { useSystemState } from "@/hooks/use-system-state"; +import { useSystemProxyState } from "@/hooks/use-system-proxy-state"; import { showNotice } from "@/services/noticeService"; import { getRunningMode } from "@/services/cmds"; import { mutate } from "swr"; @@ -145,8 +146,9 @@ export const ProxyTunCard: FC = () => { const { verge } = useVerge(); const { isAdminMode } = useSystemState(); + const { indicator: systemProxyIndicator } = useSystemProxyState(); - const { enable_system_proxy, enable_tun_mode } = verge ?? {}; + const { enable_tun_mode } = verge ?? {}; const updateLocalStatus = async () => { try { @@ -180,7 +182,7 @@ export const ProxyTunCard: FC = () => { const tabDescription = useMemo(() => { if (activeTab === "system") { return { - text: enable_system_proxy + text: systemProxyIndicator ? t("System Proxy Enabled") : t("System Proxy Disabled"), tooltip: t("System Proxy Info"), @@ -195,7 +197,7 @@ export const ProxyTunCard: FC = () => { tooltip: t("TUN Mode Intercept Info"), }; } - }, [activeTab, enable_system_proxy, enable_tun_mode, isTunAvailable, t]); + }, [activeTab, systemProxyIndicator, enable_tun_mode, isTunAvailable, t]); return ( @@ -214,7 +216,7 @@ export const ProxyTunCard: FC = () => { onClick={() => handleTabChange("system")} icon={ComputerRounded} label={t("System Proxy")} - hasIndicator={enable_system_proxy} + hasIndicator={systemProxyIndicator} /> { const { verge, mutateVerge, patchVerge } = useVerge(); const { installServiceAndRestartCore } = useServiceInstaller(); - - const { data: sysproxy } = useSWR("getSystemProxy", getSystemProxy); - const { data: autoproxy } = useSWR("getAutotemProxy", getAutotemProxy); + const { + actualState: systemProxyActualState, + indicator: systemProxyIndicator, + toggleSystemProxy, + } = useSystemProxyState(); const { isAdminMode, isServiceMode, mutateRunningMode } = useSystemState(); @@ -51,26 +48,14 @@ const SettingSystem = ({ onError }: Props) => { const sysproxyRef = useRef(null); const tunRef = useRef(null); - const { - enable_tun_mode, - enable_auto_launch, - enable_silent_start, - enable_system_proxy, - proxy_auto_config, - enable_hover_jump_navigator, - } = verge ?? {}; + const { enable_tun_mode, enable_auto_launch, enable_silent_start } = + verge ?? {}; const onSwitchFormat = (_e: any, value: boolean) => value; const onChangeData = (patch: Partial) => { mutateVerge({ ...verge, ...patch }, false); }; - const updateProxyStatus = async () => { - await new Promise((resolve) => setTimeout(resolve, 100)); - await mutate("getSystemProxy"); - await mutate("getAutotemProxy"); - }; - // 抽象服务操作逻辑 const handleServiceOperation = useLockFn( async ({ @@ -194,13 +179,7 @@ const SettingSystem = ({ onError }: Props) => { icon={SettingsRounded} onClick={() => sysproxyRef.current?.open()} /> - {proxy_auto_config ? ( - autoproxy?.enable ? ( - - ) : ( - - ) - ) : sysproxy?.enable ? ( + {systemProxyIndicator ? ( ) : ( @@ -209,44 +188,13 @@ const SettingSystem = ({ onError }: Props) => { } > { - if (autoproxy?.enable === false && sysproxy?.enable === false) { - onChangeData({ enable_system_proxy: !enable_system_proxy }); - } else { - onChangeData({ enable_system_proxy: e }); - } - }} - onGuard={async (e) => { - if (autoproxy?.enable === false && sysproxy?.enable === false) { - await patchVerge({ enable_system_proxy: !enable_system_proxy }); - await updateProxyStatus(); - return; - } - if (!e && verge?.auto_close_connection) { - closeAllConnections(); - } - await patchVerge({ enable_system_proxy: e }); - await updateProxyStatus(); - }} + onGuard={(e) => toggleSystemProxy(e)} > - + diff --git a/src/components/shared/ProxyControlSwitches.tsx b/src/components/shared/ProxyControlSwitches.tsx index dcf4a651..f96d5cbe 100644 --- a/src/components/shared/ProxyControlSwitches.tsx +++ b/src/components/shared/ProxyControlSwitches.tsx @@ -1,6 +1,6 @@ import { useRef } from "react"; import { useTranslation } from "react-i18next"; -import useSWR, { mutate } from "swr"; +import useSWR from "swr"; import { SettingsRounded, PlayCircleOutlineRounded, @@ -20,12 +20,8 @@ import { GuardState } from "@/components/setting/mods/guard-state"; import { SysproxyViewer } from "@/components/setting/mods/sysproxy-viewer"; import { TunViewer } from "@/components/setting/mods/tun-viewer"; import { useVerge } from "@/hooks/use-verge"; -import { - getSystemProxy, - getAutotemProxy, - getRunningMode, -} from "@/services/cmds"; -import { closeAllConnections } from "@/services/api"; +import { useSystemProxyState } from "@/hooks/use-system-proxy-state"; +import { getRunningMode } from "@/services/cmds"; import { showNotice } from "@/services/noticeService"; import { useServiceInstaller } from "@/hooks/useServiceInstaller"; @@ -44,12 +40,13 @@ const ProxyControlSwitches = ({ label, onError }: ProxySwitchProps) => { const theme = useTheme(); const { installServiceAndRestartCore } = useServiceInstaller(); - const { data: sysproxy } = useSWR("getSystemProxy", getSystemProxy); - const { data: autoproxy } = useSWR("getAutotemProxy", getAutotemProxy); - const { data: runningMode, mutate: mutateRunningMode } = useSWR( - "getRunningMode", - getRunningMode, - ); + const { + actualState: systemProxyActualState, + indicator: systemProxyIndicator, + toggleSystemProxy, + } = useSystemProxyState(); + + const { data: runningMode } = useSWR("getRunningMode", getRunningMode); // 是否以sidecar模式运行 const isSidecarMode = runningMode === "Sidecar"; @@ -57,8 +54,7 @@ const ProxyControlSwitches = ({ label, onError }: ProxySwitchProps) => { const sysproxyRef = useRef(null); const tunRef = useRef(null); - const { enable_tun_mode, enable_system_proxy, proxy_auto_config } = - verge ?? {}; + const { enable_tun_mode, enable_system_proxy } = verge ?? {}; // 确定当前显示哪个开关 const isSystemProxyMode = label === t("System Proxy") || !label; @@ -69,12 +65,6 @@ const ProxyControlSwitches = ({ label, onError }: ProxySwitchProps) => { mutateVerge({ ...verge, ...patch }, false); }; - const updateProxyStatus = async () => { - await new Promise((resolve) => setTimeout(resolve, 100)); - await mutate("getSystemProxy"); - await mutate("getAutotemProxy"); - }; - // 安装系统服务 const onInstallService = installServiceAndRestartCore; @@ -109,7 +99,7 @@ const ProxyControlSwitches = ({ label, onError }: ProxySwitchProps) => { }} > - {enable_system_proxy ? ( + {systemProxyIndicator ? ( @@ -151,18 +141,11 @@ const ProxyControlSwitches = ({ label, onError }: ProxySwitchProps) => { onChangeData({ enable_system_proxy: e })} - onGuard={async (e) => { - if (!e && verge?.auto_close_connection) { - closeAllConnections(); - } - await patchVerge({ enable_system_proxy: e }); - await updateProxyStatus(); - }} + onGuard={(e) => toggleSystemProxy(e)} > diff --git a/src/hooks/use-system-proxy-state.ts b/src/hooks/use-system-proxy-state.ts new file mode 100644 index 00000000..2e4621ba --- /dev/null +++ b/src/hooks/use-system-proxy-state.ts @@ -0,0 +1,72 @@ +import useSWR, { mutate } from "swr"; +import { useVerge } from "@/hooks/use-verge"; +import { getAutotemProxy } from "@/services/cmds"; +import { useAppData } from "@/providers/app-data-provider"; +import { closeAllConnections } from "@/services/api"; + +// 系统代理状态检测统一逻辑 +export const useSystemProxyState = () => { + const { verge, mutateVerge, patchVerge } = useVerge(); + const { sysproxy } = useAppData(); + const { data: autoproxy } = useSWR("getAutotemProxy", getAutotemProxy, { + revalidateOnFocus: true, + revalidateOnReconnect: true, + }); + + const { enable_system_proxy, proxy_auto_config } = verge ?? {}; + + const getSystemProxyActualState = () => { + const userEnabled = enable_system_proxy ?? false; + + if (userEnabled) { + return true; + } + + return autoproxy?.enable === false && sysproxy?.enable === false + ? false + : userEnabled; + }; + + const getSystemProxyIndicator = () => { + if (proxy_auto_config) { + return autoproxy?.enable ?? false; + } else { + return sysproxy?.enable ?? false; + } + }; + + const updateProxyStatus = async () => { + await new Promise((resolve) => setTimeout(resolve, 100)); + await mutate("getSystemProxy"); + await mutate("getAutotemProxy"); + }; + + const toggleSystemProxy = (enabled: boolean) => { + mutateVerge({ ...verge, enable_system_proxy: enabled }, false); + + setTimeout(async () => { + try { + if (!enabled && verge?.auto_close_connection) { + closeAllConnections(); + } + await patchVerge({ enable_system_proxy: enabled }); + + updateProxyStatus(); + } catch (error) { + mutateVerge({ ...verge, enable_system_proxy: !enabled }, false); + } + }, 0); + + return Promise.resolve(); + }; + + return { + actualState: getSystemProxyActualState(), + indicator: getSystemProxyIndicator(), + configState: enable_system_proxy ?? false, + sysproxy, + autoproxy, + proxy_auto_config, + toggleSystemProxy, + }; +}; diff --git a/src/providers/app-data-provider.tsx b/src/providers/app-data-provider.tsx index 337c74de..9e7ab3af 100644 --- a/src/providers/app-data-provider.tsx +++ b/src/providers/app-data-provider.tsx @@ -68,7 +68,7 @@ export const AppDataProvider = ({ getProxies, { refreshInterval: 5000, - revalidateOnFocus: false, + revalidateOnFocus: true, suspense: false, errorRetryCount: 3, }, @@ -243,7 +243,8 @@ export const AppDataProvider = ({ "getSystemProxy", getSystemProxy, { - revalidateOnFocus: false, + revalidateOnFocus: true, + revalidateOnReconnect: true, suspense: false, errorRetryCount: 3, },