mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-08 19:22:44 +08:00
refactor(react): replace avoidable effects with derived state and handlers
Also drops a duplicate WebDAV history request on open and the per-keystroke DNS YAML dump.
This commit is contained in:
@@ -146,7 +146,12 @@ export const BackupHistoryViewer = ({
|
||||
setRows([])
|
||||
return
|
||||
}
|
||||
if (!isLocal && webdavStatus === 'failed' && !options?.force) {
|
||||
// Read the status here: as a dependency, the write below re-runs the fetch.
|
||||
if (
|
||||
!isLocal &&
|
||||
getWebdavStatus(webdavSignature) === 'failed' &&
|
||||
!options?.force
|
||||
) {
|
||||
setRows([])
|
||||
return
|
||||
}
|
||||
@@ -180,7 +185,7 @@ export const BackupHistoryViewer = ({
|
||||
setLoading(false)
|
||||
}
|
||||
},
|
||||
[buildRow, isLocal, open, shouldSkipWebDav, webdavSignature, webdavStatus],
|
||||
[buildRow, isLocal, open, shouldSkipWebDav, webdavSignature],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -190,6 +190,110 @@ const DEFAULT_DNS_CONFIG = {
|
||||
},
|
||||
}
|
||||
|
||||
type DnsFormValues = {
|
||||
enable: boolean
|
||||
listen: string
|
||||
enhancedMode: 'fake-ip' | 'redir-host'
|
||||
fakeIpRange: string
|
||||
fakeIpRange6: string
|
||||
fakeIpFilterMode: 'blacklist' | 'whitelist'
|
||||
preferH3: boolean
|
||||
respectRules: boolean
|
||||
useHosts: boolean
|
||||
useSystemHosts: boolean
|
||||
ipv6: boolean
|
||||
fakeIpFilter: string
|
||||
nameserver: string
|
||||
fallback: string
|
||||
defaultNameserver: string
|
||||
proxyServerNameserver: string
|
||||
directNameserver: string
|
||||
directNameserverFollowPolicy: boolean
|
||||
fallbackGeoip: boolean
|
||||
fallbackGeoipCode: string
|
||||
fallbackIpcidr: string
|
||||
fallbackDomain: string
|
||||
nameserverPolicy: string
|
||||
hosts: string // hosts设置,独立于dns
|
||||
}
|
||||
|
||||
const DEFAULT_FORM_VALUES: DnsFormValues = {
|
||||
enable: DEFAULT_DNS_CONFIG.enable,
|
||||
listen: DEFAULT_DNS_CONFIG.listen,
|
||||
enhancedMode: DEFAULT_DNS_CONFIG['enhanced-mode'],
|
||||
fakeIpRange: DEFAULT_DNS_CONFIG['fake-ip-range'],
|
||||
fakeIpRange6: DEFAULT_DNS_CONFIG['fake-ip-range6'],
|
||||
fakeIpFilterMode: DEFAULT_DNS_CONFIG['fake-ip-filter-mode'],
|
||||
preferH3: DEFAULT_DNS_CONFIG['prefer-h3'],
|
||||
respectRules: DEFAULT_DNS_CONFIG['respect-rules'],
|
||||
useHosts: DEFAULT_DNS_CONFIG['use-hosts'],
|
||||
useSystemHosts: DEFAULT_DNS_CONFIG['use-system-hosts'],
|
||||
ipv6: DEFAULT_DNS_CONFIG.ipv6,
|
||||
fakeIpFilter: DEFAULT_DNS_CONFIG['fake-ip-filter'].join(', '),
|
||||
defaultNameserver: DEFAULT_DNS_CONFIG['default-nameserver'].join(', '),
|
||||
nameserver: DEFAULT_DNS_CONFIG.nameserver.join(', '),
|
||||
fallback: DEFAULT_DNS_CONFIG.fallback.join(', '),
|
||||
proxyServerNameserver:
|
||||
DEFAULT_DNS_CONFIG['proxy-server-nameserver']?.join(', ') || '',
|
||||
directNameserver: DEFAULT_DNS_CONFIG['direct-nameserver']?.join(', ') || '',
|
||||
directNameserverFollowPolicy:
|
||||
DEFAULT_DNS_CONFIG['direct-nameserver-follow-policy'] || false,
|
||||
fallbackGeoip: DEFAULT_DNS_CONFIG['fallback-filter'].geoip,
|
||||
fallbackGeoipCode: DEFAULT_DNS_CONFIG['fallback-filter']['geoip-code'],
|
||||
fallbackIpcidr:
|
||||
DEFAULT_DNS_CONFIG['fallback-filter'].ipcidr?.join(', ') || '',
|
||||
fallbackDomain:
|
||||
DEFAULT_DNS_CONFIG['fallback-filter'].domain?.join(', ') || '',
|
||||
nameserverPolicy: '',
|
||||
hosts: '',
|
||||
}
|
||||
|
||||
function buildDnsConfig(values: DnsFormValues) {
|
||||
const dnsConfig: any = {
|
||||
enable: values.enable,
|
||||
listen: values.listen,
|
||||
'enhanced-mode': values.enhancedMode,
|
||||
'fake-ip-range': values.fakeIpRange,
|
||||
'fake-ip-range6': values.fakeIpRange6,
|
||||
'fake-ip-filter-mode': values.fakeIpFilterMode,
|
||||
'prefer-h3': values.preferH3,
|
||||
'respect-rules': values.respectRules,
|
||||
'use-hosts': values.useHosts,
|
||||
'use-system-hosts': values.useSystemHosts,
|
||||
ipv6: values.ipv6,
|
||||
'fake-ip-filter': parseList(values.fakeIpFilter),
|
||||
'default-nameserver': parseList(values.defaultNameserver),
|
||||
nameserver: parseList(values.nameserver),
|
||||
'nameserver-policy': parseNameserverPolicy(values.nameserverPolicy),
|
||||
'direct-nameserver-follow-policy': values.directNameserverFollowPolicy,
|
||||
'fallback-filter': {
|
||||
geoip: values.fallbackGeoip,
|
||||
'geoip-code': values.fallbackGeoipCode,
|
||||
ipcidr: parseList(values.fallbackIpcidr),
|
||||
domain: parseList(values.fallbackDomain),
|
||||
},
|
||||
|
||||
fallback: parseList(values.fallback),
|
||||
'proxy-server-nameserver': parseList(values.proxyServerNameserver),
|
||||
'direct-nameserver': parseList(values.directNameserver),
|
||||
}
|
||||
|
||||
return dnsConfig
|
||||
}
|
||||
|
||||
function buildDnsYaml(values: DnsFormValues) {
|
||||
const config: Record<string, any> = {}
|
||||
|
||||
const dnsConfig = buildDnsConfig(values)
|
||||
if (Object.keys(dnsConfig).length > 0) {
|
||||
config.dns = dnsConfig
|
||||
}
|
||||
|
||||
config.hosts = parseHosts(values.hosts)
|
||||
|
||||
return yaml.dump(config, { forceQuotes: true })
|
||||
}
|
||||
|
||||
export function DnsViewer({ ref }: { ref?: Ref<DialogRef> }) {
|
||||
const { t } = useTranslation()
|
||||
const { mutateClash } = useClash()
|
||||
@@ -204,63 +308,8 @@ export function DnsViewer({ ref }: { ref?: Ref<DialogRef> }) {
|
||||
|
||||
const [open, setOpen] = useState(false)
|
||||
const [visualization, setVisualization] = useState(true)
|
||||
const skipYamlSyncRef = useRef(false)
|
||||
const editorRef = useRef<MonacoEditorInstance | null>(null)
|
||||
const [values, setValues] = useState<{
|
||||
enable: boolean
|
||||
listen: string
|
||||
enhancedMode: 'fake-ip' | 'redir-host'
|
||||
fakeIpRange: string
|
||||
fakeIpRange6: string
|
||||
fakeIpFilterMode: 'blacklist' | 'whitelist'
|
||||
preferH3: boolean
|
||||
respectRules: boolean
|
||||
useHosts: boolean
|
||||
useSystemHosts: boolean
|
||||
ipv6: boolean
|
||||
fakeIpFilter: string
|
||||
nameserver: string
|
||||
fallback: string
|
||||
defaultNameserver: string
|
||||
proxyServerNameserver: string
|
||||
directNameserver: string
|
||||
directNameserverFollowPolicy: boolean
|
||||
fallbackGeoip: boolean
|
||||
fallbackGeoipCode: string
|
||||
fallbackIpcidr: string
|
||||
fallbackDomain: string
|
||||
nameserverPolicy: string
|
||||
hosts: string // hosts设置,独立于dns
|
||||
}>({
|
||||
enable: DEFAULT_DNS_CONFIG.enable,
|
||||
listen: DEFAULT_DNS_CONFIG.listen,
|
||||
enhancedMode: DEFAULT_DNS_CONFIG['enhanced-mode'],
|
||||
fakeIpRange: DEFAULT_DNS_CONFIG['fake-ip-range'],
|
||||
fakeIpRange6: DEFAULT_DNS_CONFIG['fake-ip-range6'],
|
||||
fakeIpFilterMode: DEFAULT_DNS_CONFIG['fake-ip-filter-mode'],
|
||||
preferH3: DEFAULT_DNS_CONFIG['prefer-h3'],
|
||||
respectRules: DEFAULT_DNS_CONFIG['respect-rules'],
|
||||
useHosts: DEFAULT_DNS_CONFIG['use-hosts'],
|
||||
useSystemHosts: DEFAULT_DNS_CONFIG['use-system-hosts'],
|
||||
ipv6: DEFAULT_DNS_CONFIG.ipv6,
|
||||
fakeIpFilter: DEFAULT_DNS_CONFIG['fake-ip-filter'].join(', '),
|
||||
defaultNameserver: DEFAULT_DNS_CONFIG['default-nameserver'].join(', '),
|
||||
nameserver: DEFAULT_DNS_CONFIG.nameserver.join(', '),
|
||||
fallback: DEFAULT_DNS_CONFIG.fallback.join(', '),
|
||||
proxyServerNameserver:
|
||||
DEFAULT_DNS_CONFIG['proxy-server-nameserver']?.join(', ') || '',
|
||||
directNameserver: DEFAULT_DNS_CONFIG['direct-nameserver']?.join(', ') || '',
|
||||
directNameserverFollowPolicy:
|
||||
DEFAULT_DNS_CONFIG['direct-nameserver-follow-policy'] || false,
|
||||
fallbackGeoip: DEFAULT_DNS_CONFIG['fallback-filter'].geoip,
|
||||
fallbackGeoipCode: DEFAULT_DNS_CONFIG['fallback-filter']['geoip-code'],
|
||||
fallbackIpcidr:
|
||||
DEFAULT_DNS_CONFIG['fallback-filter'].ipcidr?.join(', ') || '',
|
||||
fallbackDomain:
|
||||
DEFAULT_DNS_CONFIG['fallback-filter'].domain?.join(', ') || '',
|
||||
nameserverPolicy: '',
|
||||
hosts: '',
|
||||
})
|
||||
const [values, setValues] = useState<DnsFormValues>(DEFAULT_FORM_VALUES)
|
||||
|
||||
// Prevent YAML-to-form sync before configuration loads.
|
||||
const [yamlContent, setYamlContent] = useReducer(
|
||||
@@ -269,7 +318,7 @@ export function DnsViewer({ ref }: { ref?: Ref<DialogRef> }) {
|
||||
)
|
||||
|
||||
const updateValuesFromConfig = useCallback((config: any) => {
|
||||
if (!config) return
|
||||
if (!config) return undefined
|
||||
|
||||
const dnsConfig = config.dns || {}
|
||||
const hostsConfig = config.hosts || {}
|
||||
@@ -289,7 +338,7 @@ export function DnsViewer({ ref }: { ref?: Ref<DialogRef> }) {
|
||||
? fakeIpFilterMode
|
||||
: DEFAULT_DNS_CONFIG['fake-ip-filter-mode']
|
||||
|
||||
setValues({
|
||||
const next: DnsFormValues = {
|
||||
enable: dnsConfig.enable ?? DEFAULT_DNS_CONFIG.enable,
|
||||
listen: dnsConfig.listen ?? DEFAULT_DNS_CONFIG.listen,
|
||||
enhancedMode: validEnhancedMode,
|
||||
@@ -341,127 +390,27 @@ export function DnsViewer({ ref }: { ref?: Ref<DialogRef> }) {
|
||||
nameserverPolicy:
|
||||
formatNameserverPolicy(dnsConfig['nameserver-policy']) || '',
|
||||
hosts: formatHosts(hostsConfig) || '',
|
||||
})
|
||||
}
|
||||
setValues(next)
|
||||
return next
|
||||
}, [])
|
||||
|
||||
const generateDnsConfig = useCallback(() => {
|
||||
const dnsConfig: any = {
|
||||
enable: values.enable,
|
||||
listen: values.listen,
|
||||
'enhanced-mode': values.enhancedMode,
|
||||
'fake-ip-range': values.fakeIpRange,
|
||||
'fake-ip-range6': values.fakeIpRange6,
|
||||
'fake-ip-filter-mode': values.fakeIpFilterMode,
|
||||
'prefer-h3': values.preferH3,
|
||||
'respect-rules': values.respectRules,
|
||||
'use-hosts': values.useHosts,
|
||||
'use-system-hosts': values.useSystemHosts,
|
||||
ipv6: values.ipv6,
|
||||
'fake-ip-filter': parseList(values.fakeIpFilter),
|
||||
'default-nameserver': parseList(values.defaultNameserver),
|
||||
nameserver: parseList(values.nameserver),
|
||||
'nameserver-policy': parseNameserverPolicy(values.nameserverPolicy),
|
||||
'direct-nameserver-follow-policy': values.directNameserverFollowPolicy,
|
||||
'fallback-filter': {
|
||||
geoip: values.fallbackGeoip,
|
||||
'geoip-code': values.fallbackGeoipCode,
|
||||
ipcidr: parseList(values.fallbackIpcidr),
|
||||
domain: parseList(values.fallbackDomain),
|
||||
},
|
||||
|
||||
fallback: parseList(values.fallback),
|
||||
'proxy-server-nameserver': parseList(values.proxyServerNameserver),
|
||||
'direct-nameserver': parseList(values.directNameserver),
|
||||
}
|
||||
|
||||
return dnsConfig
|
||||
}, [values])
|
||||
|
||||
const updateYamlFromValues = useCallback(() => {
|
||||
const config: Record<string, any> = {}
|
||||
|
||||
const dnsConfig = generateDnsConfig()
|
||||
if (Object.keys(dnsConfig).length > 0) {
|
||||
config.dns = dnsConfig
|
||||
}
|
||||
|
||||
config.hosts = parseHosts(values.hosts)
|
||||
|
||||
setYamlContent(yaml.dump(config, { forceQuotes: true }))
|
||||
}, [generateDnsConfig, values.hosts])
|
||||
|
||||
const resetToDefaults = useCallback(() => {
|
||||
setValues({
|
||||
enable: DEFAULT_DNS_CONFIG.enable,
|
||||
listen: DEFAULT_DNS_CONFIG.listen,
|
||||
enhancedMode: DEFAULT_DNS_CONFIG['enhanced-mode'],
|
||||
fakeIpRange: DEFAULT_DNS_CONFIG['fake-ip-range'],
|
||||
fakeIpRange6: DEFAULT_DNS_CONFIG['fake-ip-range6'],
|
||||
fakeIpFilterMode: DEFAULT_DNS_CONFIG['fake-ip-filter-mode'],
|
||||
preferH3: DEFAULT_DNS_CONFIG['prefer-h3'],
|
||||
respectRules: DEFAULT_DNS_CONFIG['respect-rules'],
|
||||
useHosts: DEFAULT_DNS_CONFIG['use-hosts'],
|
||||
useSystemHosts: DEFAULT_DNS_CONFIG['use-system-hosts'],
|
||||
ipv6: DEFAULT_DNS_CONFIG.ipv6,
|
||||
fakeIpFilter: DEFAULT_DNS_CONFIG['fake-ip-filter'].join(', '),
|
||||
defaultNameserver: DEFAULT_DNS_CONFIG['default-nameserver'].join(', '),
|
||||
nameserver: DEFAULT_DNS_CONFIG.nameserver.join(', '),
|
||||
fallback: DEFAULT_DNS_CONFIG.fallback.join(', '),
|
||||
proxyServerNameserver:
|
||||
DEFAULT_DNS_CONFIG['proxy-server-nameserver']?.join(', ') || '',
|
||||
directNameserver:
|
||||
DEFAULT_DNS_CONFIG['direct-nameserver']?.join(', ') || '',
|
||||
directNameserverFollowPolicy:
|
||||
DEFAULT_DNS_CONFIG['direct-nameserver-follow-policy'] || false,
|
||||
fallbackGeoip: DEFAULT_DNS_CONFIG['fallback-filter'].geoip,
|
||||
fallbackGeoipCode: DEFAULT_DNS_CONFIG['fallback-filter']['geoip-code'],
|
||||
fallbackIpcidr:
|
||||
DEFAULT_DNS_CONFIG['fallback-filter'].ipcidr?.join(', ') || '',
|
||||
fallbackDomain:
|
||||
DEFAULT_DNS_CONFIG['fallback-filter'].domain?.join(', ') || '',
|
||||
nameserverPolicy: '',
|
||||
hosts: '',
|
||||
})
|
||||
|
||||
updateYamlFromValues()
|
||||
}, [updateYamlFromValues])
|
||||
setValues(DEFAULT_FORM_VALUES)
|
||||
setYamlContent(buildDnsYaml(DEFAULT_FORM_VALUES))
|
||||
}, [])
|
||||
|
||||
const updateValuesFromYaml = useCallback(() => {
|
||||
try {
|
||||
const parsedYaml = yaml.load(yamlContent) as any
|
||||
if (!parsedYaml || parsedYaml.isInitValue) return
|
||||
|
||||
skipYamlSyncRef.current = true
|
||||
updateValuesFromConfig(parsedYaml)
|
||||
} catch {
|
||||
showNotice.error('settings.modals.dns.errors.invalidYaml')
|
||||
}
|
||||
}, [yamlContent, updateValuesFromConfig])
|
||||
|
||||
useEffect(() => {
|
||||
if (skipYamlSyncRef.current) {
|
||||
skipYamlSyncRef.current = false
|
||||
return
|
||||
}
|
||||
updateYamlFromValues()
|
||||
}, [updateYamlFromValues])
|
||||
|
||||
const latestUpdateValuesFromYamlRef = useRef(updateValuesFromYaml)
|
||||
const latestUpdateYamlFromValuesRef = useRef(updateYamlFromValues)
|
||||
|
||||
useEffect(() => {
|
||||
latestUpdateValuesFromYamlRef.current = updateValuesFromYaml
|
||||
latestUpdateYamlFromValuesRef.current = updateYamlFromValues
|
||||
}, [updateValuesFromYaml, updateYamlFromValues])
|
||||
|
||||
useEffect(() => {
|
||||
if (visualization) {
|
||||
latestUpdateValuesFromYamlRef.current()
|
||||
} else {
|
||||
latestUpdateYamlFromValuesRef.current()
|
||||
}
|
||||
}, [visualization])
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
editorRef.current?.dispose()
|
||||
@@ -476,8 +425,8 @@ export function DnsViewer({ ref }: { ref?: Ref<DialogRef> }) {
|
||||
if (dnsConfig !== null) {
|
||||
const config = yaml.load(dnsConfig) as any
|
||||
|
||||
updateValuesFromConfig(config)
|
||||
setYamlContent(dnsConfig)
|
||||
const loaded = updateValuesFromConfig(config)
|
||||
setYamlContent(loaded ? buildDnsYaml(loaded) : dnsConfig)
|
||||
} else {
|
||||
resetToDefaults()
|
||||
}
|
||||
@@ -506,7 +455,7 @@ export function DnsViewer({ ref }: { ref?: Ref<DialogRef> }) {
|
||||
if (visualization) {
|
||||
config = {}
|
||||
|
||||
const dnsConfig = generateDnsConfig()
|
||||
const dnsConfig = buildDnsConfig(values)
|
||||
if (Object.keys(dnsConfig).length > 0) {
|
||||
config.dns = dnsConfig
|
||||
}
|
||||
@@ -619,7 +568,12 @@ export function DnsViewer({ ref }: { ref?: Ref<DialogRef> }) {
|
||||
variant="contained"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
setVisualization((prev) => !prev)
|
||||
if (visualization) {
|
||||
setYamlContent(buildDnsYaml(values))
|
||||
} else {
|
||||
updateValuesFromYaml()
|
||||
}
|
||||
setVisualization(!visualization)
|
||||
}}
|
||||
>
|
||||
{visualization
|
||||
|
||||
@@ -13,13 +13,7 @@ import {
|
||||
Typography,
|
||||
} from '@mui/material'
|
||||
import { useLockFn } from 'ahooks'
|
||||
import {
|
||||
forwardRef,
|
||||
useEffect,
|
||||
useImperativeHandle,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { forwardRef, useImperativeHandle, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import {
|
||||
@@ -41,6 +35,7 @@ import {
|
||||
getSystemHostname,
|
||||
} from '@/services/cmds'
|
||||
import { showNotice } from '@/services/notice-service'
|
||||
import { useQuery } from '@/services/query-client'
|
||||
import { debugLog } from '@/utils/debug'
|
||||
import getSystem from '@/utils/get-system'
|
||||
|
||||
@@ -128,13 +123,10 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
} = verge ?? {}
|
||||
|
||||
const [value, setValue] = useState(() => buildInitialValues(null))
|
||||
const [embeddedServerPort, setEmbeddedServerPort] = useState<number | null>(
|
||||
null,
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
getEmbeddedServerPort().then(setEmbeddedServerPort).catch(console.error)
|
||||
}, [])
|
||||
const { data: embeddedServerPort } = useQuery({
|
||||
queryKey: ['getEmbeddedServerPort'],
|
||||
queryFn: getEmbeddedServerPort,
|
||||
})
|
||||
|
||||
const separator = useMemo(() => (isWindows ? ';' : ','), [isWindows])
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable @eslint-react/set-state-in-effect */
|
||||
import { Delete, ExpandLess, ExpandMore } from '@mui/icons-material'
|
||||
import {
|
||||
Button,
|
||||
@@ -14,7 +13,6 @@ import {
|
||||
} from '@mui/material'
|
||||
import {
|
||||
forwardRef,
|
||||
useEffect,
|
||||
useImperativeHandle,
|
||||
useMemo,
|
||||
useRef,
|
||||
@@ -157,29 +155,20 @@ export const TunnelsViewer = forwardRef<TunnelsViewerRef>((_, ref) => {
|
||||
const selectedProxyToken = selectedProxyOption
|
||||
? proxyOptionToken(selectedProxyOption)
|
||||
: ''
|
||||
const selectedGroupExists =
|
||||
!values.group || proxyGroups.some(({ name }) => name === values.group)
|
||||
// A group or member missing from the proxy view reads as the default.
|
||||
const effectiveGroup = proxyGroups.some(({ name }) => name === values.group)
|
||||
? values.group
|
||||
: ''
|
||||
const effectiveProxy = selectedProxyOption ? values.proxy : null
|
||||
const latestProxyStateRef = useRef({
|
||||
binding: values.proxy,
|
||||
binding: effectiveProxy,
|
||||
options: proxyOptions,
|
||||
})
|
||||
latestProxyStateRef.current = {
|
||||
binding: values.proxy,
|
||||
binding: effectiveProxy,
|
||||
options: proxyOptions,
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedGroupExists && (!values.proxy || selectedProxyOption)) return
|
||||
setValues((current) => {
|
||||
if (current.group !== values.group || current.proxy !== values.proxy) {
|
||||
return current
|
||||
}
|
||||
return selectedGroupExists
|
||||
? { ...current, proxy: null }
|
||||
: { ...current, group: '', proxy: null }
|
||||
})
|
||||
}, [selectedGroupExists, selectedProxyOption, values.group, values.proxy])
|
||||
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
await patchClash({ tunnels: draftTunnels })
|
||||
@@ -490,7 +479,7 @@ export const TunnelsViewer = forwardRef<TunnelsViewerRef>((_, ref) => {
|
||||
<Select
|
||||
size="small"
|
||||
sx={{ width: 200, '> div': { py: '7.5px' } }}
|
||||
value={values.group}
|
||||
value={effectiveGroup}
|
||||
displayEmpty
|
||||
onChange={(e) => {
|
||||
const nextGroup = e.target.value as string
|
||||
@@ -569,7 +558,7 @@ export const TunnelsViewer = forwardRef<TunnelsViewerRef>((_, ref) => {
|
||||
: null,
|
||||
}))
|
||||
}}
|
||||
disabled={!values.group} // 没选组就禁用
|
||||
disabled={!effectiveGroup} // 没选组就禁用
|
||||
>
|
||||
<MenuItem value="">
|
||||
{t('settings.sections.clash.form.fields.tunnels.default')}
|
||||
|
||||
Reference in New Issue
Block a user