diff --git a/static/index.html b/static/index.html index 574a532..2e3b2fb 100644 --- a/static/index.html +++ b/static/index.html @@ -2028,8 +2028,13 @@ opts.headers['Authorization'] = 'Bearer ' + AppState.authToken; } } + // 15s timeout to prevent hanging lookups on slow/mobile networks + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 15000); + opts.signal = controller.signal; try { const res = await fetch(url, opts); + clearTimeout(timeoutId); if (res.status === 204) return null; const text = await res.text(); let data = null; @@ -2041,9 +2046,13 @@ if (returnMeta) return { data, headers: res.headers }; return data; } catch (e) { + clearTimeout(timeoutId); if (e.name === 'TypeError' && e.message === 'Failed to fetch') { throw new Error('Network error — check your connection'); } + if (e.name === 'AbortError') { + throw new Error('Request timed out — check your connection'); + } throw e; } } @@ -3060,6 +3069,10 @@ barcodeDebounce = machineId; currentScannedMachineId = machineId; + // Stop the camera scanner before the API call — on mobile browsers + // an active camera stream can throttle concurrent fetch requests. + stopScanning(); + setScanStatus(`Scanned: ${machineId} — looking up...`, 'working'); document.getElementById('scanResult').style.display = 'none'; document.getElementById('checkinCard').style.display = 'none';