mirror of
https://github.com/smittix/intercept.git
synced 2026-04-24 06:40:00 -07:00
Harden APRS mode teardown and map fallback
This commit is contained in:
@@ -4218,7 +4218,14 @@
|
||||
acars: () => { if (acarsMainEventSource) { acarsMainEventSource.close(); acarsMainEventSource = null; } },
|
||||
vdl2: () => { if (vdl2MainEventSource) { vdl2MainEventSource.close(); vdl2MainEventSource = null; } },
|
||||
radiosonde: () => { if (radiosondeEventSource) { radiosondeEventSource.close(); radiosondeEventSource = null; } },
|
||||
aprs: () => { if (aprsEventSource) { aprsEventSource.close(); aprsEventSource = null; } },
|
||||
aprs: () => {
|
||||
if (typeof destroyAprsMode === 'function') {
|
||||
destroyAprsMode();
|
||||
} else if (aprsEventSource) {
|
||||
aprsEventSource.close();
|
||||
aprsEventSource = null;
|
||||
}
|
||||
},
|
||||
tscm: () => { if (tscmEventSource) { tscmEventSource.close(); tscmEventSource = null; } },
|
||||
meteor: () => typeof MeteorScatter !== 'undefined' && MeteorScatter.destroy?.(),
|
||||
ook: () => typeof OokMode !== 'undefined' && OokMode.destroy?.(),
|
||||
@@ -9880,6 +9887,7 @@
|
||||
let aprsStationCount = 0;
|
||||
let aprsMeterLastUpdate = 0;
|
||||
let aprsMeterCheckInterval = null;
|
||||
let aprsClockInterval = null;
|
||||
const APRS_METER_TIMEOUT = 5000; // 5 seconds for "no signal" state
|
||||
|
||||
// APRS user location (from GPS or shared observer location)
|
||||
@@ -10023,6 +10031,47 @@
|
||||
});
|
||||
}
|
||||
|
||||
function createAprsFallbackGridLayer() {
|
||||
const layer = L.gridLayer({
|
||||
tileSize: 256,
|
||||
updateWhenIdle: true,
|
||||
attribution: 'Local fallback grid'
|
||||
});
|
||||
layer.createTile = function(coords) {
|
||||
const tile = document.createElement('canvas');
|
||||
tile.width = 256;
|
||||
tile.height = 256;
|
||||
const ctx = tile.getContext('2d');
|
||||
|
||||
ctx.fillStyle = '#08121c';
|
||||
ctx.fillRect(0, 0, 256, 256);
|
||||
|
||||
ctx.strokeStyle = 'rgba(0, 212, 255, 0.12)';
|
||||
ctx.lineWidth = 1;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0, 0);
|
||||
ctx.lineTo(256, 0);
|
||||
ctx.moveTo(0, 0);
|
||||
ctx.lineTo(0, 256);
|
||||
ctx.stroke();
|
||||
|
||||
ctx.strokeStyle = 'rgba(255, 255, 255, 0.06)';
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(128, 0);
|
||||
ctx.lineTo(128, 256);
|
||||
ctx.moveTo(0, 128);
|
||||
ctx.lineTo(256, 128);
|
||||
ctx.stroke();
|
||||
|
||||
ctx.fillStyle = 'rgba(160, 220, 255, 0.28)';
|
||||
ctx.font = '11px "JetBrains Mono", monospace';
|
||||
ctx.fillText(`Z${coords.z} X${coords.x} Y${coords.y}`, 12, 22);
|
||||
|
||||
return tile;
|
||||
};
|
||||
return layer;
|
||||
}
|
||||
|
||||
async function initAprsMap() {
|
||||
if (aprsMap) return;
|
||||
|
||||
@@ -10054,13 +10103,8 @@
|
||||
aprsMap = L.map('aprsMap').setView([initialLat, initialLon], initialZoom);
|
||||
window.aprsMap = aprsMap;
|
||||
|
||||
// Add fallback tiles immediately so the map is visible instantly
|
||||
const fallbackTiles = L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png', {
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OSM</a> © <a href="https://carto.com/">CARTO</a>',
|
||||
maxZoom: 19,
|
||||
subdomains: 'abcd',
|
||||
className: 'tile-layer-cyan'
|
||||
}).addTo(aprsMap);
|
||||
// Zero-network fallback so mode switches never block on external tiles.
|
||||
const fallbackTiles = createAprsFallbackGridLayer().addTo(aprsMap);
|
||||
|
||||
// Upgrade tiles in background via Settings (with timeout fallback)
|
||||
if (typeof Settings !== 'undefined') {
|
||||
@@ -10084,7 +10128,8 @@
|
||||
}
|
||||
|
||||
// Update time display (both map header and function bar)
|
||||
setInterval(() => {
|
||||
if (aprsClockInterval) clearInterval(aprsClockInterval);
|
||||
aprsClockInterval = setInterval(() => {
|
||||
const now = new Date();
|
||||
const timeStr = now.toLocaleTimeString('en-US', { hour12: false });
|
||||
const utcStr = now.toUTCString().slice(17, 25) + ' UTC';
|
||||
@@ -10097,6 +10142,31 @@
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function destroyAprsMode() {
|
||||
stopAprsMeterCheck();
|
||||
if (aprsEventSource) {
|
||||
aprsEventSource.close();
|
||||
aprsEventSource = null;
|
||||
}
|
||||
if (aprsPollTimer) {
|
||||
clearInterval(aprsPollTimer);
|
||||
aprsPollTimer = null;
|
||||
}
|
||||
if (aprsClockInterval) {
|
||||
clearInterval(aprsClockInterval);
|
||||
aprsClockInterval = null;
|
||||
}
|
||||
if (aprsMap) {
|
||||
try {
|
||||
aprsMap.remove();
|
||||
} catch (_) {}
|
||||
aprsMap = null;
|
||||
window.aprsMap = null;
|
||||
}
|
||||
aprsMarkers = {};
|
||||
aprsUserMarker = null;
|
||||
}
|
||||
|
||||
function updateAprsStatus(state, freq) {
|
||||
// Update function bar status
|
||||
const stripDot = document.getElementById('aprsStripDot');
|
||||
|
||||
Reference in New Issue
Block a user