// Orchestrates a full state refresh cycle. // Depends on: core/messaging.js (fetchState), core/state.js (settings, SETTINGS_DEFAULTS, currentState), // pages/ssh.js (sshConnections, renderSshGrid), // pages/rdp.js (rdpConnections, renderRdpGrid), // pages/overview.js (updateDashboard), // pages/virtual-hosts.js (updateConnectionsTable), // pages/servers.js (updateSwarmsTable), // pages/proxy-ca.js (updateTabsTable), // pages/service-tunnels.js (updateServiceTunnelsTable), // pages/settings.js (updateSettingsUI), // pages/backups.js (refreshBackups) const _pingInFlight = new Set(); function _pingLatencyBadges() { const badges = document.querySelectorAll('.latency-badge[data-ping-port]'); badges.forEach(badge => { const port = parseInt(badge.dataset.pingPort, 10); const host = badge.dataset.pingHost || '127.0.0.1'; if (!port) return; const key = host + ':' + port; if (_pingInFlight.has(key)) return; _pingInFlight.add(key); chrome.runtime.sendMessage( { target: 'holesail-native', action: 'send', payload: { type: 'pingTunnel', payload: { host, port } } }, (response) => { _pingInFlight.delete(key); void chrome.runtime.lastError; if (!badge.isConnected) return; if (response && response.ok) { const ms = response.latencyMs; const color = ms < 50 ? 'var(--green)' : ms < 200 ? 'var(--amber)' : 'var(--red)'; badge.style.color = color; badge.textContent = ms + 'ms'; } else { badge.style.color = 'var(--text4)'; badge.textContent = '—'; } } ); }); } async function refresh() { const state = await fetchState(); if (state) { // Sync SSH connections from native host state — decode base64 password if present if (Array.isArray(state.sshConnections)) { sshConnections = state.sshConnections.map(c => { const existing = sshConnections.find(e => e.id === c.id); let password = (existing && existing.password) || ''; if (!password && c.passwordB64) { try { password = decodeURIComponent(escape(atob(c.passwordB64))); } catch (_) {} } return { ...c, password }; }); renderSshGrid(); } // Sync RDP connections from native host state — decode base64 password if present if (Array.isArray(state.rdpConnections)) { rdpConnections = state.rdpConnections.map(c => { const existing = rdpConnections.find(e => e.id === c.id); let password = (existing && existing.password) || ''; if (!password && c.passwordB64) { try { password = decodeURIComponent(escape(atob(c.passwordB64))); } catch (_) {} } return { ...c, password }; }); renderRdpGrid(); } // Sync settings from native host state if (state.settings && typeof state.settings === 'object') { settings = { ...SETTINGS_DEFAULTS, ...state.settings }; } updateDashboard(state); updateConnectionsTable(state); updateSwarmsTable(state); updateTabsTable(state); updateServiceTunnelsTable(state); updateSettingsUI(); } const sshCountEl = $('sshCount'); if (sshCountEl) sshCountEl.textContent = sshConnections.length; refreshBackups(); // Ping latency badges after a short delay so the DOM has been updated setTimeout(_pingLatencyBadges, 200); }