From 2f78fb69076bdaf892a4b9fe8319d7bf04f74a5a Mon Sep 17 00:00:00 2001 From: archipelago Date: Wed, 15 Jul 2026 03:49:23 -0400 Subject: [PATCH] fix(ui): DNS apply no longer blanks the page + WiFi/DNS modals cover the whole app Applying DNS assigned the RPC response's fields into networkData without guarding the shape; the demo mock answered {success:true} with no servers array, dnsServers became undefined, and the dnsDisplayLabel computed crashed the whole page render on .length. Guard the assignment, teach the mock to round-trip DNS state per session, and Teleport the WiFi + DNS modals to body so they overlay the full app instead of just the right panel (position:fixed is containing-block-relative inside the dashboard). Co-Authored-By: Claude Fable 5 --- neode-ui/mock-backend.js | 26 +++++++++++++++++----- neode-ui/src/views/Server.vue | 6 ++++- neode-ui/src/views/server/ServerModals.vue | 4 ++++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/neode-ui/mock-backend.js b/neode-ui/mock-backend.js index 63f13aed..01db85a3 100755 --- a/neode-ui/mock-backend.js +++ b/neode-ui/mock-backend.js @@ -2418,20 +2418,34 @@ app.post('/rpc/v1', (req, res) => { } case 'network.dns-status': { + const dns = mockState.dns || { provider: 'system', servers: ['1.1.1.1', '9.9.9.9'], doh_enabled: false } return res.json({ result: { - provider: 'system', - servers: ['1.1.1.1', '9.9.9.9'], - doh_enabled: false, + provider: dns.provider, + servers: dns.servers, + doh_enabled: dns.doh_enabled, doh_url: null, - resolv_conf_servers: ['1.1.1.1', '9.9.9.9'], + resolv_conf_servers: dns.servers, }, }) } case 'network.configure-dns': { - console.log(`[Network] DNS configured: ${params?.provider}`) - return res.json({ result: { success: true } }) + const dnsProviders = { + system: ['192.168.4.1'], + cloudflare: ['1.1.1.1', '1.0.0.1'], + google: ['8.8.8.8', '8.8.4.4'], + quad9: ['9.9.9.9', '149.112.112.112'], + mullvad: ['194.242.2.2'], + } + const provider = params?.provider || 'system' + const servers = provider === 'custom' + ? (Array.isArray(params?.servers) ? params.servers : []) + : (dnsProviders[provider] || dnsProviders.system) + const doh_enabled = ['cloudflare', 'google', 'quad9', 'mullvad'].includes(provider) + mockState.dns = { provider, servers, doh_enabled } + console.log(`[Network] DNS configured: ${provider} → ${servers.join(', ')}`) + return res.json({ result: { provider, servers, doh_enabled } }) } case 'network.accept-request': { diff --git a/neode-ui/src/views/Server.vue b/neode-ui/src/views/Server.vue index 32adf94b..a73c48dd 100644 --- a/neode-ui/src/views/Server.vue +++ b/neode-ui/src/views/Server.vue @@ -630,7 +630,11 @@ async function applyDnsConfig(customServers: string) { const params: { provider: DnsProviderValue; servers?: string[] } = { provider } if (provider === 'custom') { params.servers = customServers.split(',').map(s => s.trim()).filter(s => s.length > 0) } const res = await rpcClient.configureDns(params) - networkData.value.dnsProvider = res.provider; networkData.value.dnsServers = res.servers; networkData.value.dnsDoH = res.doh_enabled + // Never trust the response shape: an undefined `servers` used to reach the + // dnsDisplayLabel computed and crash the whole page render on `.length`. + networkData.value.dnsProvider = res?.provider ?? provider + networkData.value.dnsServers = Array.isArray(res?.servers) ? res.servers : (params.servers ?? []) + networkData.value.dnsDoH = !!res?.doh_enabled showDnsModal.value = false } catch (e) { dnsError.value = e instanceof Error ? e.message : 'DNS configuration failed.' } finally { dnsApplying.value = false } } diff --git a/neode-ui/src/views/server/ServerModals.vue b/neode-ui/src/views/server/ServerModals.vue index a8fbc116..5ee5c34f 100644 --- a/neode-ui/src/views/server/ServerModals.vue +++ b/neode-ui/src/views/server/ServerModals.vue @@ -94,6 +94,7 @@ +
@@ -161,8 +162,10 @@
+
+
@@ -223,6 +226,7 @@
+