[fix](trx-frontend-http): fix map not loading without manual page refresh

map-core.js is loaded as a dynamic script (effectively async) while
leaflet.js is a static <script defer>. When the user clicks the map tab,
Leaflet may not have executed yet, causing initAprsMap() to silently
bail on the `typeof L === "undefined"` guard with no retry. Introduce
_initMapWhenReady() that polls at 100ms intervals until both Leaflet
and map-core.js are available, showing the loading message in the
meantime. Also update autoInitIfVisible() for direct /map navigation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
2026-04-04 15:16:20 +02:00
parent 806a66b8c6
commit aadfa90a60
2 changed files with 28 additions and 16 deletions
@@ -4469,6 +4469,29 @@ function updateTabHistory(name, replaceHistory = false) {
window.history[method]({}, "", nextUrl); window.history[method]({}, "", nextUrl);
} }
// Initialise the Leaflet map, waiting for both Leaflet (L) and map-core.js
// (window.trx.map) if they haven't loaded yet.
let _mapInitTimer = null;
function _initMapWhenReady() {
const loadingEl = document.getElementById("map-loading");
if (window.trx.map && typeof L !== "undefined") {
if (_mapInitTimer) { clearInterval(_mapInitTimer); _mapInitTimer = null; }
if (loadingEl) loadingEl.style.display = "none";
window.trx.map.initAprsMap();
window.trx.map.sizeAprsMapToViewport();
if (window.trx.map.aprsMap) setTimeout(() => window.trx.map.aprsMap.invalidateSize(), 50);
return;
}
// Not ready yet — show loading and poll until both are available.
if (loadingEl) loadingEl.style.display = "";
if (!_mapInitTimer) {
_mapInitTimer = setInterval(() => {
if (_activeTab !== "map") { clearInterval(_mapInitTimer); _mapInitTimer = null; return; }
_initMapWhenReady();
}, 100);
}
}
function navigateToTab(name, options = {}) { function navigateToTab(name, options = {}) {
const { updateHistory = true, replaceHistory = false } = options; const { updateHistory = true, replaceHistory = false } = options;
if (authEnabled && !authRole && name !== "main") { if (authEnabled && !authRole && name !== "main") {
@@ -4499,15 +4522,7 @@ function navigateToTab(name, options = {}) {
scheduleSpectrumLayout(); scheduleSpectrumLayout();
if (typeof window.loadPluginsForTab === "function") window.loadPluginsForTab(name); if (typeof window.loadPluginsForTab === "function") window.loadPluginsForTab(name);
if (name === "map") { if (name === "map") {
const loadingEl = document.getElementById("map-loading"); _initMapWhenReady();
if (window.trx.map) {
if (loadingEl) loadingEl.style.display = "none";
window.trx.map.initAprsMap();
window.trx.map.sizeAprsMapToViewport();
if (window.trx.map.aprsMap) setTimeout(() => window.trx.map.aprsMap.invalidateSize(), 50);
} else if (loadingEl) {
loadingEl.style.display = "";
}
} }
if (name === "statistics") { if (name === "statistics") {
window.trx.map?.scheduleStatsRender(); window.trx.map?.scheduleStatsRender();
@@ -3427,15 +3427,12 @@
} }
// Auto-init map if the map tab is already visible (e.g. direct /map navigation) // Auto-init map if the map tab is already visible (e.g. direct /map navigation).
// Delegates to _initMapWhenReady() in app.js which handles the Leaflet load race.
function autoInitIfVisible() { function autoInitIfVisible() {
const panel = document.getElementById("tab-map"); const panel = document.getElementById("tab-map");
if (panel && panel.style.display !== "none") { if (panel && panel.style.display !== "none" && typeof _initMapWhenReady === "function") {
const loadingEl = document.getElementById("map-loading"); _initMapWhenReady();
if (loadingEl) loadingEl.style.display = "none";
initAprsMap();
sizeAprsMapToViewport();
if (aprsMap) setTimeout(() => aprsMap.invalidateSize(), 50);
} }
} }