feat(cluster): dim spots that represent nothing

A spot whose entity/band/mode is already worked, whose callsign isn't in the log,
and that carries no POTA/county/prefix novelty is dimmed (whole row, opacity) so
the eye skips it. "Nothing" follows the status, which already obeys the "same
slot" option and digital grouping. getRowStyle drives it; the spot-status effect
now redrawRows so the dimming re-applies when a status lands.
This commit is contained in:
2026-08-05 14:38:19 +02:00
parent 9af2732314
commit 7e696a72bb
2 changed files with 21 additions and 3 deletions
+17 -1
View File
@@ -140,6 +140,19 @@ function statusColor(s: SpotStatusEntry | undefined): string | null {
}
}
// isDull reports a spot that "represents nothing" under the current worked/slot
// rules: the entity/band/mode is already worked (status resolved, not new in any
// dimension), the callsign itself isn't in the log, and there's no POTA / county
// / prefix novelty. Such rows are dimmed so the eye skips them. Because the
// status obeys the DX-cluster "same slot" option and the digital-mode grouping,
// what counts as dull follows those settings automatically. Unresolved statuses
// (still loading, or entity unknown) are NOT dimmed — that would flicker.
function isDull(s: SpotStatusEntry | undefined): boolean {
if (!s || !s.status) return false;
if (s.status === 'new' || s.status === 'new-band' || s.status === 'new-mode' || s.status === 'new-slot') return false;
return !(s.worked_call || s.new_pota || s.new_county || s.new_pfx);
}
const makeColCatalog = (t: TFn): ColEntry[] => [
{
group: 'Spot', label: t('clg2.c.time'), colId: 'time',
@@ -410,7 +423,9 @@ export function ClusterGrid({ rows, spotStatus, onSpotClick }: Props) {
// won't re-render those cells on its own — force a refresh so e.g. a worked call
// turns blue once its status loads.
useEffect(() => {
gridRef.current?.api?.refreshCells({ force: true });
// redrawRows (not refreshCells) so getRowStyle re-runs too — the whole-row
// dimming of "represents nothing" spots depends on the status that lands here.
gridRef.current?.api?.redrawRows();
}, [spotStatus]);
// Restore AFTER the profile scope is known — this grid has no key= remount to
@@ -496,6 +511,7 @@ export function ClusterGrid({ rows, spotStatus, onSpotClick }: Props) {
onColumnVisible={saveColumnState}
onSortChanged={saveColumnState}
onRowClicked={handleRowClicked}
getRowStyle={(p: any) => (isDull(statusFor(p)) ? { opacity: 0.4 } : undefined)}
animateRows={false}
suppressCellFocus
getRowId={(p) => `${(p.data as any).received_at}-${(p.data as any).dx_call}-${(p.data as any).source_id}`}