From d2a63c784a1772877060807fd1c474ac3e89d46f Mon Sep 17 00:00:00 2001 From: pe1hvh Date: Thu, 12 Mar 2026 06:12:16 +0100 Subject: [PATCH] HotFix2 --- CHANGELOG.md | 8 ++++++-- meshcore_gui/gui/panels/map_panel.py | 6 +++--- meshcore_gui/static/leaflet_map_panel.js | 26 ++++++------------------ 3 files changed, 15 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b253b4..bc1c472 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,8 +31,7 @@ Format follows [Keep a Changelog](https://keepachangelog.com/) and [Semantic Ver ### Changed - 🔄 `meshcore_gui/static/leaflet_map_panel.js` — Added size guard in `ensureMap`: returns `null` when host has `clientWidth === 0 && clientHeight === 0` and no map - state exists yet. `processPending` now explicitly reschedules itself until the panel - becomes visible, instead of silently returning and leaving the map pending forever. + state exists yet. `processPending` retries on the next tick once the panel is visible. - 🔄 `meshcore_gui/gui/dashboard.py` — Consolidated two conditional map-update blocks into a single unconditional update while the MAP panel is active. Added `h-96` to the DOMCA CSS height overrides for consistency with the route page map container. @@ -838,3 +837,8 @@ overwriting all historical data with only the new buffered messages. ### Changed - Map lifecycle is browser-owned: NiceGUI hosts the container, Leaflet owns map state. - Contact markers are updated incrementally in the existing cluster layer. + +## 2026-03-12 map host bootstrap fix +- Fixed dashboard MAP bootstrap for hidden/inactive panels by rendering the Leaflet host as a real NiceGUI `div` element instead of injecting raw HTML inside a hidden container. +- Fixed browser bootstrap retries so a zero-size hidden host is retried instead of being dropped permanently. +- Simplified host waiting logic to polling-based retries, which avoids missing late NiceGUI DOM inserts while the MAP panel is still being mounted. diff --git a/meshcore_gui/gui/panels/map_panel.py b/meshcore_gui/gui/panels/map_panel.py index 33a89f5..2934350 100644 --- a/meshcore_gui/gui/panels/map_panel.py +++ b/meshcore_gui/gui/panels/map_panel.py @@ -45,9 +45,9 @@ class MapPanel: on_change=lambda e: self._set_map_theme_mode(e.value), ).props('dense') ui.button('Center on Device', on_click=self._center_on_device) - ui.html( - f'
' - ).classes('w-full h-72') + ui.element('div').props(f'id={self._container_id}').classes( + 'meshcore-leaflet-host w-full h-72' + ) self._dispatch_to_browser(snapshot={'__command__': 'ensure_map'}) self._apply_theme_only() diff --git a/meshcore_gui/static/leaflet_map_panel.js b/meshcore_gui/static/leaflet_map_panel.js index ebecd27..3a21db1 100644 --- a/meshcore_gui/static/leaflet_map_panel.js +++ b/meshcore_gui/static/leaflet_map_panel.js @@ -504,35 +504,21 @@ return; } - const observer = new MutationObserver(() => { + const timer = window.setTimeout(() => { + watchers.delete(containerId); const host = document.getElementById(containerId); - if (!host) { + if (host) { + scheduleProcess(containerId, retries + 1); return; } - observer.disconnect(); - watchers.delete(containerId); - scheduleProcess(containerId, retries + 1); - }); - - observer.observe(document.body, { - childList: true, - subtree: true, - }); - - watchers.set(containerId, observer); - - window.setTimeout(() => { - if (watchers.get(containerId) !== observer) { - return; - } - observer.disconnect(); - watchers.delete(containerId); if (retries >= MAX_RETRIES) { console.error('MeshCoreLeafletBoot timeout waiting for host element', { containerId }); return; } scheduleProcess(containerId, retries + 1); }, RETRY_DELAY_MS); + + watchers.set(containerId, timer); } function isDomReady() {