diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index f166171..33ac339 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1580,7 +1580,10 @@ export default function App() { // Cached per-call slot status: "new" | "new-band" | "new-slot" | "worked". // Keyed by `${call}|${band}|${mode}` so two spots of the same call on // different slots don't share the same colour. - const [spotStatus, setSpotStatus] = useState>({}); + // worked_slot must be carried explicitly like every other field: this map is + // assembled field by field, so a backend flag that nobody copies here simply + // never reaches the panels — silently, since the extra key is just dropped. + const [spotStatus, setSpotStatus] = useState>({}); // Live mirror of spotStatus so the incoming-spot buffer can tell which slots // still need resolving without re-subscribing the cluster:spot listener. const spotStatusRef = useRef(spotStatus); @@ -1630,7 +1633,7 @@ export default function App() { const k = `${r.call}|${r.band ?? ''}|${(r.mode ?? '').toUpperCase()}`; next[k] = { status: r.status ?? '', country: r.country, continent: (r as any).continent, - worked_call: !!(r as any).worked_call, new_county: !!(r as any).new_county, + worked_call: !!(r as any).worked_call, worked_slot: !!(r as any).worked_slot, new_county: !!(r as any).new_county, new_pota: !!(r as any).new_pota, new_pfx: !!(r as any).new_pfx, pfx: (r as any).pfx, }; } @@ -2729,6 +2732,7 @@ export default function App() { country: r.country, continent: (r as any).continent, worked_call: !!(r as any).worked_call, + worked_slot: !!(r as any).worked_slot, new_county: !!(r as any).new_county, new_pota: !!(r as any).new_pota, new_pfx: !!(r as any).new_pfx, @@ -3196,6 +3200,7 @@ export default function App() { country: r.country, continent: (r as any).continent, worked_call: !!(r as any).worked_call, + worked_slot: !!(r as any).worked_slot, new_county: !!(r as any).new_county, new_pota: !!(r as any).new_pota, new_pfx: !!(r as any).new_pfx, diff --git a/frontend/src/components/BandMap.tsx b/frontend/src/components/BandMap.tsx index af87296..d08ffed 100644 --- a/frontend/src/components/BandMap.tsx +++ b/frontend/src/components/BandMap.tsx @@ -243,13 +243,16 @@ export function BandMap({ band, spots, spotStatus: spotStatusRaw, currentFreqHz, // the map and the cluster list share the single rule set in lib/spotDisplay. // Re-derived whenever the poll delivers a new status map, which is also when a // just-changed option takes effect. + // Read at render time, not inside the memo: the options must be part of the + // dependencies. Keyed only on spotStatusRaw, toggling an option changed + // nothing until the next poll happened to hand over a fresh object. + const dispOpts = readSpotDisplayOptions(); const spotStatus = useMemo(() => { - const o = readSpotDisplayOptions(); - if (!o.muteWorked && !o.slotHighlight) return spotStatusRaw; + if (!dispOpts.muteWorked && !dispOpts.slotHighlight) return spotStatusRaw; const out: Record = {}; - for (const k of Object.keys(spotStatusRaw)) out[k] = applySpotDisplay(spotStatusRaw[k], o) as SpotStatusEntry; + for (const k of Object.keys(spotStatusRaw)) out[k] = applySpotDisplay(spotStatusRaw[k], dispOpts) as SpotStatusEntry; return out; - }, [spotStatusRaw]); + }, [spotStatusRaw, dispOpts.muteWorked, dispOpts.slotHighlight]); const range = BAND_RANGES[band]; const segments = SEGMENT_COLORS[band] ?? []; const [zoomIdx, setZoomIdx] = useState(2); // default 32 px/kHz