[feat](trx-frontend-http): refactor map source filter to toggle behavior

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
This commit is contained in:
2026-03-18 21:29:26 +01:00
parent 353be875be
commit 71b9a3128b
@@ -4884,16 +4884,11 @@ function renderMapLocatorChipRow(container, items, selectedSet, kind) {
return; return;
} }
let helperText = ""; let helperText = "";
const isDefaultSourceState = kind === "source" const sourceKeys = kind === "source" ? Object.keys(DEFAULT_MAP_SOURCE_FILTER) : [];
&& items.every((item) => { const noneSelected = kind === "source" && sourceKeys.every((k) => !mapFilter[k]);
const def = Object.prototype.hasOwnProperty.call(DEFAULT_MAP_SOURCE_FILTER, item.key)
? !!DEFAULT_MAP_SOURCE_FILTER[item.key]
: true;
return !!mapFilter[item.key] === def;
});
if (kind === "source") { if (kind === "source") {
if (isDefaultSourceState) { if (noneSelected) {
helperText = "Click a source to isolate it"; helperText = "All sources visible \u2014 click to filter";
} }
} else if (!(selectedSet instanceof Set) || selectedSet.size === 0) { } else if (!(selectedSet instanceof Set) || selectedSet.size === 0) {
helperText = `All ${kind === "band" ? "bands" : "sources"} visible by default`; helperText = `All ${kind === "band" ? "bands" : "sources"} visible by default`;
@@ -4903,15 +4898,8 @@ function renderMapLocatorChipRow(container, items, selectedSet, kind) {
btn.type = "button"; btn.type = "button";
btn.className = "map-locator-chip"; btn.className = "map-locator-chip";
const isActive = kind === "source" ? !!mapFilter[item.key] : selectedSet.has(item.key); const isActive = kind === "source" ? !!mapFilter[item.key] : selectedSet.has(item.key);
if (kind === "source" && isDefaultSourceState) { if (kind === "source" && noneSelected) {
const def = Object.prototype.hasOwnProperty.call(DEFAULT_MAP_SOURCE_FILTER, item.key)
? !!DEFAULT_MAP_SOURCE_FILTER[item.key]
: true;
if (def) {
btn.classList.add("is-default"); btn.classList.add("is-default");
} else {
btn.classList.add("is-inactive");
}
} else if (!isActive) { } else if (!isActive) {
btn.classList.add("is-inactive"); btn.classList.add("is-inactive");
} }
@@ -5519,23 +5507,18 @@ function initAprsMap() {
const key = String(chip.dataset.filterKey || ""); const key = String(chip.dataset.filterKey || "");
if (!key) return; if (!key) return;
if (kind === "source" && Object.prototype.hasOwnProperty.call(mapFilter, key)) { if (kind === "source" && Object.prototype.hasOwnProperty.call(mapFilter, key)) {
const sourceKeys = Object.keys(DEFAULT_MAP_SOURCE_FILTER); // toggle the clicked source; when none are selected everything is shown
const onlyThisSelected = mapFilter[key] && sourceKeys.every((k) => mapFilter[k] === (k === key)); mapFilter[key] = !mapFilter[key];
if (onlyThisSelected) { const srcKeys = Object.keys(DEFAULT_MAP_SOURCE_FILTER);
// clicking the sole active source restores defaults const anySelected = srcKeys.some((k) => mapFilter[k]);
for (const k of sourceKeys) mapFilter[k] = DEFAULT_MAP_SOURCE_FILTER[k]; if (anySelected && !mapFilter.aprs && selectedAprsTrackCall) {
} else {
// select only the clicked source
for (const k of sourceKeys) mapFilter[k] = (k === key);
}
if (!mapFilter.aprs && selectedAprsTrackCall) {
const entry = stationMarkers.get(String(selectedAprsTrackCall)); const entry = stationMarkers.get(String(selectedAprsTrackCall));
if (entry && entry.track && aprsMap && aprsMap.hasLayer(entry.track)) { if (entry && entry.track && aprsMap && aprsMap.hasLayer(entry.track)) {
entry.track.removeFrom(aprsMap); entry.track.removeFrom(aprsMap);
} }
selectedAprsTrackCall = null; selectedAprsTrackCall = null;
} }
if (!mapFilter.ais && selectedAisTrackMmsi) { if (anySelected && !mapFilter.ais && selectedAisTrackMmsi) {
const entry = aisMarkers.get(String(selectedAisTrackMmsi)); const entry = aisMarkers.get(String(selectedAisTrackMmsi));
if (entry && entry.track && aprsMap && aprsMap.hasLayer(entry.track)) { if (entry && entry.track && aprsMap && aprsMap.hasLayer(entry.track)) {
entry.track.removeFrom(aprsMap); entry.track.removeFrom(aprsMap);
@@ -6240,21 +6223,17 @@ function maidenheadToBounds(grid) {
function applyMapFilter() { function applyMapFilter() {
if (!aprsMap) return; if (!aprsMap) return;
const sourceKeys = Object.keys(DEFAULT_MAP_SOURCE_FILTER);
const noneSelected = sourceKeys.every((k) => !mapFilter[k]);
mapMarkers.forEach((marker) => { mapMarkers.forEach((marker) => {
const type = marker.__trxType; const type = marker.__trxType;
const sourceVisible = noneSelected
? DEFAULT_MAP_SOURCE_FILTER[type] !== undefined ? DEFAULT_MAP_SOURCE_FILTER[type] : true
: !!mapFilter[type];
const visible = marker.__trxHistoryVisible !== false const visible = marker.__trxHistoryVisible !== false
&& markerPassesSearchFilter(marker) && markerPassesSearchFilter(marker)
&& markerPassesLocatorFilters(marker) && markerPassesLocatorFilters(marker)
&& ( && sourceVisible;
(type === "bookmark" && mapFilter.bookmark) ||
(type === "ais" && mapFilter.ais) ||
(type === "vdes" && mapFilter.vdes) ||
(type === "aprs" && mapFilter.aprs) ||
(type === "ft8" && mapFilter.ft8) ||
(type === "ft4" && mapFilter.ft4) ||
(type === "ft2" && mapFilter.ft2) ||
(type === "wspr" && mapFilter.wspr)
);
const onMap = aprsMap.hasLayer(marker); const onMap = aprsMap.hasLayer(marker);
if (visible && !onMap) { if (visible && !onMap) {
marker.addTo(aprsMap); marker.addTo(aprsMap);