feat(cluster): chase switches for POTA and SOTA

An operator who does not chase parks does not want NEW POTA shouting from every
activator spot. Two switches (Settings → DX Cluster, on by default): off, the
marker is withdrawn at the display layer — applySpotDisplay, the same chokepoint
the grid, the band map and the filter read through — so the badge, the colour,
the filter chip and the reference column all go quiet together, and a new-band +
new-POTA spot reads NEW BAND alone. The facts keep being computed; only the
telling stops, so ticking the box back on needs no rescan.
This commit is contained in:
2026-08-28 23:48:22 +02:00
parent 5e38319379
commit bd8719ce99
8 changed files with 63 additions and 14 deletions
+29 -3
View File
@@ -11,7 +11,25 @@
//
// They compose deliberately: mute what is done, light up what is not.
export type SpotDisplayOptions = { muteWorked: boolean; slotHighlight: boolean };
export type SpotDisplayOptions = {
muteWorked: boolean; slotHighlight: boolean;
// Chase switches (Settings → DX Cluster), ON by default. An operator who does
// not chase parks does not want NEW POTA shouting from every activator spot:
// off, the marker is withdrawn at the display layer — a "new band + new POTA"
// spot simply reads NEW BAND — and the reference column goes quiet. The facts
// keep being computed; only the telling stops, so ticking the box back on
// needs no rescan.
chasePota: boolean; chaseSota: boolean;
};
// chasePota/chaseSota read the switches directly — for the places that show a
// REFERENCE rather than a status (the POTA and SOTA columns).
export function chasePota(): boolean {
try { return localStorage.getItem('opslog.chasePota') !== '0'; } catch { return true; }
}
export function chaseSota(): boolean {
try { return localStorage.getItem('opslog.chaseSota') !== '0'; } catch { return true; }
}
// Both options are withdrawn from the filter panel for now. The machinery below
// is deliberately kept whole — it is correct and hard-won — so putting the two
@@ -23,14 +41,19 @@ export type SpotDisplayOptions = { muteWorked: boolean; slotHighlight: boolean }
export const SPOT_DISPLAY_OPTIONS_EXPOSED = false;
export function readSpotDisplayOptions(): SpotDisplayOptions {
if (!SPOT_DISPLAY_OPTIONS_EXPOSED) return { muteWorked: false, slotHighlight: false };
// The EXPOSED flag only withdraws the two original switches; the chase
// switches are live regardless.
if (!SPOT_DISPLAY_OPTIONS_EXPOSED) {
return { muteWorked: false, slotHighlight: false, chasePota: chasePota(), chaseSota: chaseSota() };
}
try {
return {
muteWorked: localStorage.getItem('opslog.clusterMuteWorked') === '1',
slotHighlight: localStorage.getItem('opslog.clusterSlotHighlight') === '1',
chasePota: chasePota(), chaseSota: chaseSota(),
};
} catch {
return { muteWorked: false, slotHighlight: false };
return { muteWorked: false, slotHighlight: false, chasePota: true, chaseSota: true };
}
}
@@ -72,6 +95,9 @@ export function applySpotDisplay<T extends Entry>(s: T, o: SpotDisplayOptions):
if (o.muteWorked) {
e = { ...e, worked_call: false } as NonNullable<T>;
}
if (!o.chasePota && e.new_pota) {
e = { ...e, new_pota: false } as NonNullable<T>;
}
return e;
}