|
@@ -1,4 +1,4 @@
|
|
|
-import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
|
|
|
|
|
+import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
|
import { useTranslation } from 'react-i18next';
|
|
import { useTranslation } from 'react-i18next';
|
|
|
import { Alert, Button, Empty, Input, InputNumber, Modal, Select, Space, Switch, Table, Tabs } from 'antd';
|
|
import { Alert, Button, Empty, Input, InputNumber, Modal, Select, Space, Switch, Table, Tabs } from 'antd';
|
|
|
import {
|
|
import {
|
|
@@ -42,6 +42,23 @@ export default function DnsTab({ templateSettings, setTemplateSettings }: DnsTab
|
|
|
|
|
|
|
|
const dns = (templateSettings?.dns as DnsConfig | undefined) ?? null;
|
|
const dns = (templateSettings?.dns as DnsConfig | undefined) ?? null;
|
|
|
const dnsEnabled = !!dns;
|
|
const dnsEnabled = !!dns;
|
|
|
|
|
+ const sourceHosts = dns?.hosts;
|
|
|
|
|
+ const incomingHosts = JSON.stringify(sourceHosts ?? {});
|
|
|
|
|
+ const lastWrittenHostsRef = useRef<string | null>(null);
|
|
|
|
|
+
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ if (!dns) {
|
|
|
|
|
+ lastWrittenHostsRef.current = '{}';
|
|
|
|
|
+ setHostsList([]);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (incomingHosts === lastWrittenHostsRef.current) return;
|
|
|
|
|
+ lastWrittenHostsRef.current = incomingHosts;
|
|
|
|
|
+ setHostsList(Object.entries(sourceHosts ?? {}).map(([domain, values]) => ({
|
|
|
|
|
+ domain,
|
|
|
|
|
+ values: Array.isArray(values) ? [...values] : [String(values)],
|
|
|
|
|
+ })));
|
|
|
|
|
+ }, [dnsEnabled, incomingHosts, sourceHosts]);
|
|
|
|
|
|
|
|
const mutate = useCallback(
|
|
const mutate = useCallback(
|
|
|
(mutator: (next: XraySettingsValue) => void) => {
|
|
(mutator: (next: XraySettingsValue) => void) => {
|
|
@@ -79,32 +96,18 @@ export default function DnsTab({ templateSettings, setTemplateSettings }: DnsTab
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- useEffect(() => {
|
|
|
|
|
- if (!dns) {
|
|
|
|
|
- setHostsList([]);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- const src = dns.hosts || {};
|
|
|
|
|
- setHostsList(
|
|
|
|
|
- Object.entries(src).map(([domain, val]) => ({
|
|
|
|
|
- domain,
|
|
|
|
|
- values: Array.isArray(val) ? [...val] : [String(val)],
|
|
|
|
|
- })),
|
|
|
|
|
- );
|
|
|
|
|
- // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
|
- }, [dnsEnabled]);
|
|
|
|
|
-
|
|
|
|
|
function syncHosts(next: HostRow[]) {
|
|
function syncHosts(next: HostRow[]) {
|
|
|
|
|
+ const obj: Record<string, string | string[]> = {};
|
|
|
|
|
+ for (const row of next) {
|
|
|
|
|
+ if (!row.domain) continue;
|
|
|
|
|
+ const vals = (row.values || []).filter(Boolean);
|
|
|
|
|
+ if (vals.length === 0) continue;
|
|
|
|
|
+ obj[row.domain] = vals.length === 1 ? vals[0] : vals;
|
|
|
|
|
+ }
|
|
|
|
|
+ lastWrittenHostsRef.current = JSON.stringify(obj);
|
|
|
setHostsList(next);
|
|
setHostsList(next);
|
|
|
mutate((tt) => {
|
|
mutate((tt) => {
|
|
|
if (!tt.dns) return;
|
|
if (!tt.dns) return;
|
|
|
- const obj: Record<string, string | string[]> = {};
|
|
|
|
|
- for (const row of next) {
|
|
|
|
|
- if (!row.domain) continue;
|
|
|
|
|
- const vals = (row.values || []).filter(Boolean);
|
|
|
|
|
- if (vals.length === 0) continue;
|
|
|
|
|
- obj[row.domain] = vals.length === 1 ? vals[0] : vals;
|
|
|
|
|
- }
|
|
|
|
|
if (Object.keys(obj).length > 0) {
|
|
if (Object.keys(obj).length > 0) {
|
|
|
(tt.dns as DnsConfig).hosts = obj;
|
|
(tt.dns as DnsConfig).hosts = obj;
|
|
|
} else if ('hosts' in (tt.dns as DnsConfig)) {
|
|
} else if ('hosts' in (tt.dns as DnsConfig)) {
|