refactor: restructure DNS setting logic

This commit is contained in:
wonfen
2025-03-08 11:25:00 +08:00
parent eddcf209c1
commit e27a32395a
10 changed files with 404 additions and 69 deletions

View File

@@ -22,6 +22,7 @@ import yaml from "js-yaml";
import MonacoEditor from "react-monaco-editor";
import { useThemeMode } from "@/services/states";
import getSystem from "@/utils/get-system";
import { invoke } from "@tauri-apps/api/core";
const Item = styled(ListItem)(({ theme }) => ({
padding: "8px 0",
@@ -145,11 +146,109 @@ export const DnsViewer = forwardRef<DialogRef>((props, ref) => {
useImperativeHandle(ref, () => ({
open: () => {
setOpen(true);
resetToDefaults();
// 获取DNS配置文件并初始化表单
initDnsConfig();
},
close: () => setOpen(false),
}));
// 初始化DNS配置
const initDnsConfig = async () => {
try {
// 尝试从dns_config.yaml文件读取配置
const dnsConfigExists = await invoke<boolean>(
"check_dns_config_exists",
{},
);
if (dnsConfigExists) {
// 如果存在配置文件,加载其内容
const dnsConfig = await invoke<string>("get_dns_config_content", {});
const config = yaml.load(dnsConfig) as any;
// 更新表单数据
updateValuesFromConfig(config);
// 更新YAML编辑器内容
setYamlContent(dnsConfig);
} else {
// 如果不存在配置文件,使用默认值
resetToDefaults();
}
} catch (err) {
console.error("Failed to initialize DNS config", err);
resetToDefaults();
}
};
// 从配置对象更新表单值
const updateValuesFromConfig = (config: any) => {
if (!config) return;
const enhancedMode =
config["enhanced-mode"] || DEFAULT_DNS_CONFIG["enhanced-mode"];
const validEnhancedMode =
enhancedMode === "fake-ip" || enhancedMode === "redir-host"
? enhancedMode
: DEFAULT_DNS_CONFIG["enhanced-mode"];
const fakeIpFilterMode =
config["fake-ip-filter-mode"] ||
DEFAULT_DNS_CONFIG["fake-ip-filter-mode"];
const validFakeIpFilterMode =
fakeIpFilterMode === "blacklist" || fakeIpFilterMode === "whitelist"
? fakeIpFilterMode
: DEFAULT_DNS_CONFIG["fake-ip-filter-mode"];
setValues({
enable: config.enable ?? DEFAULT_DNS_CONFIG.enable,
listen: config.listen ?? DEFAULT_DNS_CONFIG.listen,
enhancedMode: validEnhancedMode,
fakeIpRange:
config["fake-ip-range"] ?? DEFAULT_DNS_CONFIG["fake-ip-range"],
fakeIpFilterMode: validFakeIpFilterMode,
preferH3: config["prefer-h3"] ?? DEFAULT_DNS_CONFIG["prefer-h3"],
respectRules:
config["respect-rules"] ?? DEFAULT_DNS_CONFIG["respect-rules"],
fakeIpFilter:
config["fake-ip-filter"]?.join(", ") ??
DEFAULT_DNS_CONFIG["fake-ip-filter"].join(", "),
nameserver:
config.nameserver?.join(", ") ??
DEFAULT_DNS_CONFIG.nameserver.join(", "),
fallback:
config.fallback?.join(", ") ?? DEFAULT_DNS_CONFIG.fallback.join(", "),
defaultNameserver:
config["default-nameserver"]?.join(", ") ??
DEFAULT_DNS_CONFIG["default-nameserver"].join(", "),
useHosts: config["use-hosts"] ?? DEFAULT_DNS_CONFIG["use-hosts"],
useSystemHosts:
config["use-system-hosts"] ?? DEFAULT_DNS_CONFIG["use-system-hosts"],
proxyServerNameserver:
config["proxy-server-nameserver"]?.join(", ") ??
(DEFAULT_DNS_CONFIG["proxy-server-nameserver"]?.join(", ") || ""),
directNameserver:
config["direct-nameserver"]?.join(", ") ??
(DEFAULT_DNS_CONFIG["direct-nameserver"]?.join(", ") || ""),
directNameserverFollowPolicy:
config["direct-nameserver-follow-policy"] ??
DEFAULT_DNS_CONFIG["direct-nameserver-follow-policy"],
fallbackGeoip:
config["fallback-filter"]?.geoip ??
DEFAULT_DNS_CONFIG["fallback-filter"].geoip,
fallbackGeoipCode:
config["fallback-filter"]?.["geoip-code"] ??
DEFAULT_DNS_CONFIG["fallback-filter"]["geoip-code"],
fallbackIpcidr:
config["fallback-filter"]?.ipcidr?.join(", ") ??
DEFAULT_DNS_CONFIG["fallback-filter"].ipcidr.join(", "),
fallbackDomain:
config["fallback-filter"]?.domain?.join(", ") ??
DEFAULT_DNS_CONFIG["fallback-filter"].domain.join(", "),
nameserverPolicy:
formatNameserverPolicy(config["nameserver-policy"]) || "",
});
};
// 重置为默认值
const resetToDefaults = () => {
setValues({
@@ -396,6 +495,7 @@ export const DnsViewer = forwardRef<DialogRef>((props, ref) => {
return dnsConfig;
};
// 处理保存操作
const onSave = useLockFn(async () => {
try {
let dnsConfig;
@@ -412,8 +512,15 @@ export const DnsViewer = forwardRef<DialogRef>((props, ref) => {
dnsConfig = parsedConfig;
}
await patchClash({ dns: dnsConfig });
mutateClash();
// 不直接应用到clash配置而是保存到单独文件
await invoke("save_dns_config", { dnsConfig });
// 如果DNS开关当前是打开的则需要应用新的DNS配置
if (clash?.dns?.enable) {
await invoke("apply_dns_config", { apply: true });
mutateClash(); // 刷新UI
}
setOpen(false);
Notice.success(t("DNS settings saved"));
} catch (err: any) {

View File

@@ -1,4 +1,4 @@
import { useRef } from "react";
import { useRef, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { TextField, Select, MenuItem, Typography } from "@mui/material";
import {
@@ -22,6 +22,9 @@ 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";
@@ -45,6 +48,10 @@ const SettingClash = ({ onError }: Props) => {
const { enable_random_port = false, verge_mixed_port } = verge ?? {};
// 独立跟踪DNS设置开关状态
const [dnsSettingsEnabled, setDnsSettingsEnabled] = useState(false);
const { addListener } = useListen();
const webRef = useRef<DialogRef>(null);
const portRef = useRef<DialogRef>(null);
const ctrlRef = useRef<DialogRef>(null);
@@ -52,6 +59,12 @@ const SettingClash = ({ onError }: Props) => {
const networkRef = useRef<DialogRef>(null);
const dnsRef = useRef<DialogRef>(null);
// 初始化时从verge配置中加载DNS设置开关状态
useEffect(() => {
const dnsSettingsState = verge?.enable_dns_settings ?? false;
setDnsSettingsEnabled(dnsSettingsState);
}, [verge]);
const onSwitchFormat = (_e: any, value: boolean) => value;
const onChangeData = (patch: Partial<IConfigData>) => {
mutateClash((old) => ({ ...(old! || {}), ...patch }), false);
@@ -68,6 +81,25 @@ const SettingClash = ({ onError }: Props) => {
}
};
// 实现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); // 延迟500ms确保后端完成处理
} catch (err: any) {
Notice.error(err.message || err.toString());
setDnsSettingsEnabled(!enable);
await patchVerge({ enable_dns_settings: !enable }).catch(() => {
// 忽略恢复状态时的错误
});
throw err;
}
});
return (
<SettingList title={t("Clash Setting")}>
<WebUIViewer ref={webRef} />
@@ -111,16 +143,12 @@ const SettingClash = ({ onError }: Props) => {
/>
}
>
<GuardState
value={dns?.enable ?? false}
valueProps="checked"
onCatch={onError}
onFormat={onSwitchFormat}
onChange={(e) => onChangeData({ dns: { ...dns, enable: e } })}
onGuard={(e) => patchClash({ dns: { enable: e } })}
>
<Switch edge="end" />
</GuardState>
{/* 使用独立状态不再依赖dns?.enable */}
<Switch
edge="end"
checked={dnsSettingsEnabled}
onChange={(_, checked) => handleDnsToggle(checked)}
/>
</SettingItem>
<SettingItem label={t("IPv6")}>

View File

@@ -194,7 +194,7 @@
"Test URL": "测试地址",
"Settings": "设置",
"System Setting": "系统设置",
"Tun Mode": "TUN虚拟网卡模式",
"Tun Mode": "TUN(虚拟网卡)模式",
"TUN requires Service Mode": "TUN 模式需要服务",
"Install Service": "安装服务",
"Reset to Default": "重置为默认值",
@@ -502,6 +502,5 @@
"Fallback IP CIDR": "回退 IP CIDR",
"IP CIDRs not using fallback servers": "不使用回退服务器的 IP CIDR用逗号分隔",
"Fallback Domain": "回退域名",
"Domains using fallback servers": "使用回退服务器的域名,用逗号分隔",
"Fallback Geosite": "回退 Geosite"
"Domains using fallback servers": "使用回退服务器的域名,用逗号分隔"
}

View File

@@ -739,6 +739,7 @@ interface IVergeConfig {
enable_silent_start?: boolean;
enable_system_proxy?: boolean;
enable_global_hotkey?: boolean;
enable_dns_settings?: boolean;
proxy_auto_config?: boolean;
pac_file_content?: string;
enable_random_port?: boolean;