diff --git a/webui/src/pages/Settings.jsx b/webui/src/pages/Settings.jsx index 115e62f..654cc97 100644 --- a/webui/src/pages/Settings.jsx +++ b/webui/src/pages/Settings.jsx @@ -432,6 +432,7 @@ function Settings() { // identity const [identity, setIdentity] = useState({ cell_name: '', domain: '', ip_range: '' }); const [identityDirty, setIdentityDirty] = useState(false); + const [loadedCellName, setLoadedCellName] = useState(''); // DDNS const [domainMode, setDomainMode] = useState('lan'); @@ -475,6 +476,7 @@ function Settings() { domain: cfg.domain || '', ip_range: cfg.ip_range || '', }); + setLoadedCellName(cfg.cell_name || ''); setIdentityDirty(false); setDomainMode(cfg.domain_mode || 'lan'); setDomainName(cfg.domain_name || ''); @@ -545,6 +547,7 @@ function Settings() { try { const res = await cellAPI.updateConfig(identity); setIdentityDirty(false); + setLoadedCellName(identity.cell_name); draftConfig?.setDirty('identity', false); if (res.data.warnings?.length) res.data.warnings.forEach((w) => toast(w, 'warning')); // Refresh to get updated domain_name after DDNS registration @@ -687,10 +690,15 @@ function Settings() { useEffect(() => { if (!identityDirty) return; if (ipRangeError || cellNameError || domainError) return; - if (domainMode === 'pic_ngo' && (picAvail === 'taken' || picAvail === 'checking')) return; + // In pic_ngo mode, if the cell name differs from what was last saved/loaded, + // wait for the availability check to reach a terminal state before saving. + // 'available' and 'unreachable' are terminal; null/'checking'/'taken' are not. + if (domainMode === 'pic_ngo' && identity.cell_name !== loadedCellName) { + if (picAvail !== 'available' && picAvail !== 'unreachable') return; + } const timer = setTimeout(() => saveIdentityRef.current(), 800); return () => clearTimeout(timer); - }, [identity, identityDirty, ipRangeError, cellNameError, domainError, domainMode, picAvail]); // eslint-disable-line react-hooks/exhaustive-deps + }, [identity, identityDirty, ipRangeError, cellNameError, domainError, domainMode, picAvail, loadedCellName]); // eslint-disable-line react-hooks/exhaustive-deps useEffect(() => { const timers = SERVICE_DEFS