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 b7e6d17..fe2de8f 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 @@ -3755,7 +3755,7 @@ const decodeContactPaths = new Map(); const mapMarkers = new Set(); const DEFAULT_MAP_SOURCE_FILTER = { ais: true, vdes: true, aprs: true, bookmark: false, ft8: true, wspr: true }; const mapFilter = { ...DEFAULT_MAP_SOURCE_FILTER }; -const mapLocatorFilter = { phase: "type", bands: new Set() }; +const mapLocatorFilter = { phase: "band", bands: new Set() }; let mapSearchFilter = ""; const APRS_TRACK_MAX_POINTS = 64; const AIS_TRACK_MAX_POINTS = 64; @@ -4303,11 +4303,30 @@ function renderMapLocatorPhaseRow(container, phase) { } } +function renderMapBandLegend(items) { + const legendEl = document.getElementById("map-band-legend"); + if (!legendEl) return; + const bandItems = Array.isArray(items) ? items : []; + if (bandItems.length === 0) { + legendEl.classList.add("is-empty"); + legendEl.innerHTML = ""; + return; + } + legendEl.classList.remove("is-empty"); + const rows = bandItems + .map((item) => { + const label = escapeMapHtml(item.label); + const color = escapeMapHtml(item.color); + return `${label}`; + }) + .join(""); + legendEl.innerHTML = `
Band Colors
${rows}
`; +} + function rebuildMapLocatorFilters() { const phaseEl = document.getElementById("map-locator-phase"); const choiceEl = document.getElementById("map-locator-choice-filter"); const choiceLabelEl = document.getElementById("map-locator-choice-label"); - if (!phaseEl || !choiceEl || !choiceLabelEl) return; const availableSources = new Set(); if (aisMarkers.size > 0) availableSources.add("ais"); @@ -4360,6 +4379,9 @@ function rebuildMapLocatorFilters() { const bandItems = Array.from(bandMap.values()) .sort((a, b) => (b.sortHz - a.sortHz) || a.label.localeCompare(b.label)); + renderMapBandLegend(bandItems); + if (!phaseEl || !choiceEl || !choiceLabelEl) return; + renderMapLocatorPhaseRow(phaseEl, mapLocatorFilter.phase); if (mapLocatorFilter.phase === "band") { choiceLabelEl.textContent = "Visible Bands"; 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 5752f0f..f733d17 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 @@ -698,6 +698,7 @@ +
diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css index 2778a55..b862205 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css +++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css @@ -1314,6 +1314,61 @@ small { color: var(--text-muted); } border-color: color-mix(in srgb, var(--accent-green) 34%, var(--border-light)); color: var(--text-heading); } +.map-band-legend { + position: absolute; + left: 0.7rem; + bottom: 0.7rem; + z-index: 410; + display: flex; + flex-direction: column; + gap: 0.45rem; + width: min(14rem, calc(100% - 5.8rem)); + max-height: min(40%, 18rem); + padding: 0.65rem 0.7rem; + border-radius: 0.8rem; + border: 1px solid color-mix(in srgb, var(--border-light) 74%, transparent); + background: color-mix(in srgb, var(--card-bg) 78%, transparent); + box-shadow: 0 16px 30px rgba(0, 0, 0, 0.2); + backdrop-filter: blur(14px); + -webkit-backdrop-filter: blur(14px); + overflow: auto; +} +.map-band-legend.is-empty { + display: none; +} +.map-band-legend-title { + font-size: 0.72rem; + font-weight: 800; + letter-spacing: 0.1em; + text-transform: uppercase; + color: var(--text-muted); +} +.map-band-legend-list { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(5.4rem, 1fr)); + gap: 0.35rem 0.55rem; +} +.map-band-legend-item { + display: inline-flex; + align-items: center; + gap: 0.4rem; + min-width: 0; +} +.map-band-legend-swatch { + flex: 0 0 auto; + width: 0.78rem; + height: 0.78rem; + border-radius: 999px; + background: var(--legend-color, var(--accent-green)); + box-shadow: 0 0 0 1px color-mix(in srgb, var(--legend-color, var(--accent-green)) 44%, rgba(255, 255, 255, 0.18)); +} +.map-band-legend-text { + min-width: 0; + font-size: 0.76rem; + font-weight: 700; + color: var(--text); + white-space: nowrap; +} #map-stage:fullscreen, #map-stage:-webkit-full-screen, #map-stage.map-fake-fullscreen { @@ -2321,6 +2376,17 @@ button:focus-visible, input:focus-visible, select:focus-visible { top: 0.55rem; right: 0.55rem; } + .map-band-legend { + left: 0.55rem; + bottom: 0.55rem; + width: min(12rem, calc(100% - 1.1rem)); + max-height: min(36%, 13rem); + padding: 0.55rem 0.6rem; + border-radius: 0.7rem; + } + .map-band-legend-list { + grid-template-columns: repeat(auto-fit, minmax(4.8rem, 1fr)); + } .map-locator-filter-group { align-items: stretch; }