import { useRef, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { TextField, Select, MenuItem, Typography } from "@mui/material"; import { SettingsRounded, ShuffleRounded, LanRounded, } from "@mui/icons-material"; import { DialogRef, Notice, Switch } from "@/components/base"; import { useClash } from "@/hooks/use-clash"; import { GuardState } from "./mods/guard-state"; import { WebUIViewer } from "./mods/web-ui-viewer"; import { ClashPortViewer } from "./mods/clash-port-viewer"; import { ControllerViewer } from "./mods/controller-viewer"; import { SettingList, SettingItem } from "./mods/setting-comp"; import { ClashCoreViewer } from "./mods/clash-core-viewer"; import { invoke_uwp_tool } from "@/services/cmds"; import getSystem from "@/utils/get-system"; import { useVerge } from "@/hooks/use-verge"; import { updateGeoData } from "@/services/api"; import { TooltipIcon } from "@/components/base/base-tooltip-icon"; import { NetworkInterfaceViewer } from "./mods/network-interface-viewer"; import { DnsViewer } from "./mods/dns-viewer"; import { invoke } from "@tauri-apps/api/core"; import { useLockFn } from "ahooks"; import { useListen } from "@/hooks/use-listen"; const isWIN = getSystem() === "windows"; interface Props { onError: (err: Error) => void; } const SettingClash = ({ onError }: Props) => { const { t } = useTranslation(); const { clash, version, mutateClash, patchClash } = useClash(); const { verge, mutateVerge, patchVerge } = useVerge(); const { ipv6, "allow-lan": allowLan, "log-level": logLevel, "unified-delay": unifiedDelay, dns, } = clash ?? {}; const { enable_random_port = false, verge_mixed_port } = verge ?? {}; // 独立跟踪DNS设置开关状态 const [dnsSettingsEnabled, setDnsSettingsEnabled] = useState(() => { // 尝试从localStorage获取之前保存的状态 const savedState = localStorage.getItem("dns_settings_enabled"); if (savedState !== null) { return savedState === "true"; } // 如果没有保存的状态,则从verge配置中获取 return verge?.enable_dns_settings ?? false; }); const { addListener } = useListen(); const webRef = useRef(null); const portRef = useRef(null); const ctrlRef = useRef(null); const coreRef = useRef(null); const networkRef = useRef(null); const dnsRef = useRef(null); const onSwitchFormat = (_e: any, value: boolean) => value; const onChangeData = (patch: Partial) => { mutateClash((old) => ({ ...(old! || {}), ...patch }), false); }; const onChangeVerge = (patch: Partial) => { mutateVerge({ ...verge, ...patch }, false); }; const onUpdateGeo = async () => { try { await updateGeoData(); Notice.success(t("GeoData Updated")); } catch (err: any) { Notice.error(err?.response.data.message || err.toString()); } }; // 实现DNS设置开关处理函数 const handleDnsToggle = useLockFn(async (enable: boolean) => { try { // 立即更新UI状态 setDnsSettingsEnabled(enable); // 保存到localStorage,用于记住用户的选择 localStorage.setItem("dns_settings_enabled", String(enable)); // 更新verge配置 await patchVerge({ enable_dns_settings: enable }); await invoke("apply_dns_config", { apply: enable }); setTimeout(() => { mutateClash(); }, 500); // 延迟500ms确保后端完成处理 } catch (err: any) { // 如果出错,恢复原始状态 setDnsSettingsEnabled(!enable); localStorage.setItem("dns_settings_enabled", String(!enable)); Notice.error(err.message || err.toString()); await patchVerge({ enable_dns_settings: !enable }).catch(() => { // 忽略恢复状态时的错误 }); throw err; } }); return ( { networkRef.current?.open(); }} /> } > onChangeData({ "allow-lan": e })} onGuard={(e) => patchClash({ "allow-lan": e })} > dnsRef.current?.open()} /> } > handleDnsToggle(checked)} /> onChangeData({ ipv6: e })} onGuard={(e) => patchClash({ ipv6: e })} > } > onChangeData({ "unified-delay": e })} onGuard={(e) => patchClash({ "unified-delay": e })} > } > e.target.value} onChange={(e) => onChangeData({ "log-level": e })} onGuard={(e) => patchClash({ "log-level": e })} > { Notice.success( t("Restart Application to Apply Modifications"), 1000, ); onChangeVerge({ enable_random_port: !enable_random_port }); patchVerge({ enable_random_port: !enable_random_port }); }} /> } > { portRef.current?.open(); (e.target as any).blur(); }} /> ctrlRef.current?.open()} label={t("External")} /> webRef.current?.open()} label={t("Web UI")} /> coreRef.current?.open()} /> } > {version} {isWIN && ( } /> )} ); }; export default SettingClash;