diff --git a/templates/adsb_dashboard.html b/templates/adsb_dashboard.html
index b035aac..ae9019e 100644
--- a/templates/adsb_dashboard.html
+++ b/templates/adsb_dashboard.html
@@ -440,6 +440,11 @@
let panelSelectionStageTimer = null;
let mapCrosshairRequestId = 0;
let detectedDevicesPromise = null;
+ let clockInterval = null;
+ let cleanupInterval = null;
+ let delayedGpsInitTimer = null;
+ let delayedDriverCheckTimer = null;
+ let delayedAircraftDbTimer = null;
// Watchlist - persisted to localStorage
let watchlist = JSON.parse(localStorage.getItem('adsb_watchlist') || '[]');
@@ -1586,7 +1591,7 @@ ACARS: ${r.statistics.acarsMessages} messages`;
// ============================================
async function autoConnectGps() {
try {
- const response = await fetch('/gps/auto-connect', { method: 'POST' });
+ const response = await fetchJsonWithTimeout('/gps/auto-connect', { method: 'POST' }, 2000);
const data = await response.json();
if (data.status === 'connected') {
@@ -1717,6 +1722,17 @@ ACARS: ${r.statistics.acarsMessages} messages`;
window.addEventListener('pagehide', function() {
if (eventSource) { eventSource.close(); eventSource = null; }
if (gpsEventSource) { gpsEventSource.close(); gpsEventSource = null; }
+ if (acarsEventSource) { acarsEventSource.close(); acarsEventSource = null; }
+ if (vdl2EventSource) { vdl2EventSource.close(); vdl2EventSource = null; }
+ if (allAgentsEventSource) { allAgentsEventSource.close(); allAgentsEventSource = null; }
+ if (agentPollTimer) { clearInterval(agentPollTimer); agentPollTimer = null; }
+ if (acarsPollTimer) { clearInterval(acarsPollTimer); acarsPollTimer = null; }
+ if (vdl2PollTimer) { clearInterval(vdl2PollTimer); vdl2PollTimer = null; }
+ if (clockInterval) { clearInterval(clockInterval); clockInterval = null; }
+ if (cleanupInterval) { clearInterval(cleanupInterval); cleanupInterval = null; }
+ if (delayedGpsInitTimer) { clearTimeout(delayedGpsInitTimer); delayedGpsInitTimer = null; }
+ if (delayedDriverCheckTimer) { clearTimeout(delayedDriverCheckTimer); delayedDriverCheckTimer = null; }
+ if (delayedAircraftDbTimer) { clearTimeout(delayedAircraftDbTimer); delayedAircraftDbTimer = null; }
});
document.addEventListener('DOMContentLoaded', () => {
@@ -1738,13 +1754,25 @@ ACARS: ${r.statistics.acarsMessages} messages`;
.then((devices) => checkAdsbTools(devices))
.catch(() => checkAdsbTools([]));
updateClock();
- setInterval(updateClock, 1000);
- setInterval(cleanupOldAircraft, 10000);
- checkAircraftDatabase();
- checkDvbDriverConflict();
+ clockInterval = setInterval(updateClock, 1000);
+ cleanupInterval = setInterval(cleanupOldAircraft, 10000);
- // Auto-connect to gpsd if available
- autoConnectGps();
+ // Defer nonessential startup probes so the page can paint and
+ // return navigation remains snappy if the user leaves quickly.
+ delayedAircraftDbTimer = setTimeout(() => {
+ delayedAircraftDbTimer = null;
+ checkAircraftDatabase();
+ }, 1200);
+
+ delayedDriverCheckTimer = setTimeout(() => {
+ delayedDriverCheckTimer = null;
+ checkDvbDriverConflict();
+ }, 1800);
+
+ delayedGpsInitTimer = setTimeout(() => {
+ delayedGpsInitTimer = null;
+ autoConnectGps();
+ }, 2500);
// Sync tracking state if ADS-B already running
syncTrackingStatus();
@@ -1960,7 +1988,7 @@ ACARS: ${r.statistics.acarsMessages} messages`;
let aircraftDbStatus = { installed: false };
function checkAircraftDatabase() {
- fetch('/adsb/aircraft-db/status')
+ fetchJsonWithTimeout('/adsb/aircraft-db/status', {}, 2000)
.then(r => r.json())
.then(status => {
aircraftDbStatus = status;
@@ -1968,7 +1996,7 @@ ACARS: ${r.statistics.acarsMessages} messages`;
showAircraftDbBanner('not_installed');
} else {
// Check for updates in background
- fetch('/adsb/aircraft-db/check-updates')
+ fetchJsonWithTimeout('/adsb/aircraft-db/check-updates', {}, 2000)
.then(r => r.json())
.then(data => {
if (data.update_available) {