import { LanRounded, SettingsRounded } from '@mui/icons-material' import { MenuItem, Select, TextField, Typography } from '@mui/material' import { invoke } from '@tauri-apps/api/core' import { useLockFn } from 'ahooks' import { useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { updateGeo, type LogLevel } from 'tauri-plugin-mihomo-api' import { DialogRef, Switch, TooltipIcon } from '@/components/base' import { useClash } from '@/hooks/use-clash' import { useClashLog } from '@/hooks/use-clash-log' import { useVerge } from '@/hooks/use-verge' import { invoke_uwp_tool } from '@/services/cmds' import { showNotice } from '@/services/notice-service' import getSystem from '@/utils/get-system' import { ClashCoreViewer } from './mods/clash-core-viewer' import { ClashPortViewer } from './mods/clash-port-viewer' import { ControllerViewer } from './mods/controller-viewer' import { DnsViewer } from './mods/dns-viewer' import { HeaderConfiguration } from './mods/external-controller-cors' import { GuardState } from './mods/guard-state' import { NetworkInterfaceViewer } from './mods/network-interface-viewer' import { SettingItem, SettingList } from './mods/setting-comp' import { TunnelsViewer } from './mods/tunnels-viewer' import { WebUIViewer } from './mods/web-ui-viewer' 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, patchVerge } = useVerge() const [, setClashLog] = useClashLog() const { ipv6, 'allow-lan': allowLan, 'log-level': logLevel, 'unified-delay': unifiedDelay, } = clash ?? {} const { verge_mixed_port } = verge ?? {} // 独立跟踪DNS设置开关状态 const [dnsSettingsEnabled, setDnsSettingsEnabled] = useState(() => { return verge?.enable_dns_settings ?? false }) 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 corsRef = useRef(null) const tunnelRef = useRef(null) const onSwitchFormat = (_e: any, value: boolean) => value const onChangeData = (patch: Partial) => { mutateClash((old) => ({ ...old!, ...patch }), false) } const onUpdateGeo = async () => { try { await updateGeo() showNotice.success('settings.feedback.notifications.clash.geoDataUpdated') } catch (err: any) { showNotice.error(err) } } // 实现DNS设置开关处理函数 const handleDnsToggle = useLockFn(async (enable: boolean) => { try { setDnsSettingsEnabled(enable) await patchVerge({ enable_dns_settings: enable }) await invoke('apply_dns_config', { apply: enable }) setTimeout(() => { mutateClash() }, 500) } catch (err: any) { setDnsSettingsEnabled(!enable) showNotice.error(err) 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) => { setClashLog((pre) => ({ ...pre!, logLevel: e.toUpperCase() as LogLevel, })) return patchClash({ 'log-level': e }) }} > { portRef.current?.open() ;(e.target as HTMLElement).blur() }} /> { e.stopPropagation() corsRef.current?.open() }} /> } onClick={() => { ctrlRef.current?.open() }} /> webRef.current?.open()} label={t('settings.sections.clash.form.fields.webUI')} /> coreRef.current?.open()} /> } > {version} {isWIN && ( } /> )} tunnelRef.current?.open()} /> ) } export default SettingClash