From 80aadf54ab7ec8b55ce011afd2e6a93afe4373fd Mon Sep 17 00:00:00 2001 From: Stanislaw Grams Date: Sun, 8 Feb 2026 21:44:55 +0100 Subject: [PATCH] [feat](trx-frontend-http): add interactive Map tab with Leaflet Add a Map sub-tab under Plugins that displays an interactive OpenStreetMap via Leaflet.js showing: - Receiver location (blue marker) from server config lat/lon - APRS station positions (green markers) updated in real-time The map lazy-initializes on first tab switch, handles tile rendering on tab visibility changes, and deduplicates station markers by callsign. Also includes the fallback snapshot lat/lon fields in the API layer. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Stanislaw Grams --- .../trx-frontend-http/assets/web/app.js | 51 +++++++++++++++++++ .../trx-frontend-http/assets/web/index.html | 6 +++ .../assets/web/plugins/aprs.js | 37 +++++++++++--- .../trx-frontend-http/assets/web/style.css | 1 + .../trx-frontend/trx-frontend-http/src/api.rs | 2 + 5 files changed, 90 insertions(+), 7 deletions(-) diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js index e96686d..41a8113 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js +++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js @@ -152,6 +152,8 @@ function setDisabled(disabled) { let serverVersion = null; let serverCallsign = null; +let serverLat = null; +let serverLon = null; function updateTitle() { let title = "trx-rs"; @@ -166,6 +168,8 @@ function render(update) { if (update.info && update.info.model) rigName = update.info.model; if (update.server_version) serverVersion = update.server_version; if (update.server_callsign) serverCallsign = update.server_callsign; + if (update.server_latitude != null) serverLat = update.server_latitude; + if (update.server_longitude != null) serverLon = update.server_longitude; updateTitle(); initialized = !!update.initialized; @@ -637,6 +641,49 @@ document.querySelector(".tab-bar").addEventListener("click", (e) => { connect(); +// --- Leaflet Map (lazy-initialized) --- +let aprsMap = null; +let aprsMapReceiverMarker = null; +const stationMarkers = new Map(); + +function initAprsMap() { + if (aprsMap) return; + const mapEl = document.getElementById("aprs-map"); + if (!mapEl) return; + + const hasLocation = serverLat != null && serverLon != null; + const center = hasLocation ? [serverLat, serverLon] : [20, 0]; + const zoom = hasLocation ? 10 : 2; + + aprsMap = L.map("aprs-map").setView(center, zoom); + L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { + maxZoom: 19, + attribution: '© OpenStreetMap' + }).addTo(aprsMap); + + if (hasLocation) { + const popupText = serverCallsign ? serverCallsign : "Receiver"; + aprsMapReceiverMarker = L.circleMarker([serverLat, serverLon], { + radius: 8, color: "#3388ff", fillColor: "#3388ff", fillOpacity: 0.8 + }).addTo(aprsMap).bindPopup(popupText); + } +} + +window.aprsMapAddStation = function(call, lat, lon, info) { + if (!aprsMap) initAprsMap(); + if (!aprsMap) return; + const existing = stationMarkers.get(call); + if (existing) { + existing.setLatLng([lat, lon]); + existing.setPopupContent(`${call}
${info}`); + } else { + const marker = L.circleMarker([lat, lon], { + radius: 6, color: "#00d17f", fillColor: "#00d17f", fillOpacity: 0.8 + }).addTo(aprsMap).bindPopup(`${call}
${info}`); + stationMarkers.set(call, marker); + } +}; + // --- Sub-tab navigation (Plugins tab) --- document.querySelectorAll(".sub-tab-bar").forEach((bar) => { bar.addEventListener("click", (e) => { @@ -647,6 +694,10 @@ document.querySelectorAll(".sub-tab-bar").forEach((bar) => { const parent = bar.parentElement; parent.querySelectorAll(".sub-tab-panel").forEach((p) => p.style.display = "none"); parent.querySelector(`#subtab-${btn.dataset.subtab}`).style.display = ""; + if (btn.dataset.subtab === "map") { + initAprsMap(); + if (aprsMap) setTimeout(() => aprsMap.invalidateSize(), 50); + } }); }); diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html index abc42c9..5d632b9 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html +++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html @@ -6,6 +6,8 @@ + +
@@ -120,6 +122,7 @@
+