From 8bb9cf7ce9a77f53547cceb997b848a5fbdd69a7 Mon Sep 17 00:00:00 2001 From: Zac Gaetano Date: Mon, 6 Apr 2026 21:50:28 -0400 Subject: [PATCH] debug: add console logging and 10s timeout to extension API calls - apiFetch() now logs method+URL on start and status code on response - Added 10s AbortController timeout to prevent infinite hangs - Added try/catch wrapper in saveSettings() around login() call - This helps diagnose the "stuck on connecting" issue Co-Authored-By: Claude Sonnet 4.6 --- chrome-extension/popup.js | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/chrome-extension/popup.js b/chrome-extension/popup.js index a8fb5c9..712b722 100644 --- a/chrome-extension/popup.js +++ b/chrome-extension/popup.js @@ -119,9 +119,14 @@ async function saveSettings() { document.getElementById('conn-server').textContent = serverUrl.replace(/https?:\/\//, ''); showSettingsStatus('Saved — connecting…', 'loading'); - await login(); - if (connected) { - showSettingsStatus('✅ Connected successfully!', 'success'); + try { + await login(); + if (connected) { + showSettingsStatus('✅ Connected successfully!', 'success'); + } + } catch (e) { + showSettingsStatus(`❌ ${e.message || 'Unknown error'}`, 'error'); + setConnStatus('red', e.message || 'Connection failed'); } } @@ -308,17 +313,30 @@ async function uploadUDP(item, idx, prefix) { // ==================== HELPERS ==================== async function apiFetch(method, path, body) { const url = config.serverUrl.replace(/\/$/, '') + path; + console.log(`[DW] ${method} ${url}`); const opts = { method, headers: { 'Content-Type': 'application/json' } }; if (authToken) opts.headers['x-auth-token'] = authToken; if (body) opts.body = JSON.stringify(body); - const r = await fetch(url, opts); - // Don't treat 401 on /api/login as session expiry — it's just bad credentials - if (r.status === 401 && !path.includes('/api/login')) { - authToken = null; - await chrome.storage.local.remove('token'); - throw new Error('Session expired'); + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), 10000); + opts.signal = controller.signal; + try { + const r = await fetch(url, opts); + clearTimeout(timeout); + console.log(`[DW] ${method} ${path} → ${r.status}`); + // Don't treat 401 on /api/login as session expiry — it's just bad credentials + if (r.status === 401 && !path.includes('/api/login')) { + authToken = null; + await chrome.storage.local.remove('token'); + throw new Error('Session expired'); + } + return r.json(); + } catch (e) { + clearTimeout(timeout); + if (e.name === 'AbortError') throw new Error('Request timed out — check server URL'); + console.error(`[DW] ${method} ${path} failed:`, e); + throw e; } - return r.json(); } function showStatus(msg, type) {