diff --git a/changelog.json b/changelog.json index df6ad61..8384332 100644 --- a/changelog.json +++ b/changelog.json @@ -5,12 +5,12 @@ "en": [ "TCI (SunSDR): the meter subscription is renewed when the radio announces it is ready — sent only at connect, it could fall inside the initial state dump and be ignored, which left the transmit power and SWR empty. The log now also records the subscription and the first sensor frames, so a report can tell “the radio never sends them” from “they arrived and were dropped”.", "Sending a spot while in split now pre-fills the RX frequency — where the station actually is — instead of the TX frequency, which spotted the pile-up five up from the DX.", - "Cluster: NEW SLOT gets its own colour (aqua, matching the panadapter palette) — it shared the amber of the NEW family while NEW PFX sat in a near-identical yellow beside it." + "Cluster: NEW SLOT gets its own colour — the sky cyan the panadapter palette already uses for it, clearly apart from POTA green and the yellows. The NEW SLOT and NEW COUNTY filter chips now wear the same colours as the badges they select, and the NEW CALL filter works even when the slot-highlight display option is off." ], "fr": [ "TCI (SunSDR) : l'abonnement aux mesures est renouvelé quand la radio annonce qu'elle est prête — envoyé seulement à la connexion, il pouvait tomber pendant l'envoi initial de l'état et être ignoré, laissant la puissance et le ROS vides en émission. Le journal enregistre aussi l'abonnement et les premières trames de mesure, pour distinguer « la radio ne les envoie jamais » de « elles arrivaient et étaient perdues ».", "Envoyer un spot en split préremplit désormais la fréquence RX — là où la station se trouve réellement — au lieu de la fréquence TX, qui spottait le pile-up cinq au-dessus du DX.", - "Cluster : NOUVEAU SLOT reçoit sa propre couleur (aqua, celle de la palette du panadapter) — il partageait l'ambre de la famille NOUVEAU alors que NOUVEAU PFX portait un jaune quasi identique juste à côté." + "Cluster : NOUVEAU SLOT reçoit sa propre couleur — le cyan ciel que la palette du panadapter lui donne déjà, bien distinct du vert POTA et des jaunes. Les puces de filtre NOUVEAU SLOT et NOUVEAU COMTÉ portent désormais les couleurs des badges qu'elles sélectionnent, et le filtre NOUVEAU CALL fonctionne même quand l'option de surlignage par slot est désactivée." ] }, { diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 2e19e84..70d7773 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -5870,6 +5870,13 @@ export default function App() { // worked call still matches its own entity status too (new-band/new-slot), // so it stays visible under those chips. const matches = (st !== 'worked' && clusterStatusFilter.has(st)) + // NEW CALL is a FACT about the callsign (never worked on this band and + // mode), surfaced as a status only by the slot-highlight option. The + // chip filters on the fact itself, so it works whether or not that + // display option is on — worked_slot is computed whenever either + // slot option is enabled. + || (clusterStatusFilter.has('new-call') && e?.worked_slot === false + && (!e?.status || e?.status === 'worked' || e?.status === 'new-call')) || (!!e?.worked_call && clusterStatusFilter.has('worked')) || (!!e?.new_pota && clusterStatusFilter.has('new-pota')) || (!!e?.new_county && clusterStatusFilter.has('new-county')) @@ -5976,12 +5983,20 @@ export default function App() { ); const F_CHIP = 'px-1.5 py-[3px] rounded-md border text-[10px] font-bold tracking-wider transition-opacity'; - const fChip = (key: string, label: string, cls: string, on: boolean, toggle: () => void) => ( - ); + // chipStyle builds a filter chip in an arbitrary colour — for the statuses + // whose grid badge is not one of the semantic tokens the chip classes cover. + // A filter that does not look like what it selects has to be learned twice. + const chipStyle = (c: string): React.CSSProperties => ({ + color: c, + borderColor: `color-mix(in srgb, ${c} 45%, transparent)`, + background: `color-mix(in srgb, ${c} 14%, transparent)`, + }); const renderClusterFilters = () => (
@@ -6097,14 +6112,14 @@ export default function App() { { k: 'new-band-mode' as SpotFilterKey, label: 'NEW B+M', cls: 'bg-danger-muted text-danger-muted-foreground border-danger-border' }, { k: 'new-band' as SpotFilterKey, label: 'NEW BAND', cls: 'bg-warning-muted text-warning-muted-foreground border-warning-border' }, { k: 'new-mode' as SpotFilterKey, label: 'NEW MODE', cls: 'bg-caution-muted text-caution-muted-foreground border-caution-border' }, - { k: 'new-slot' as SpotFilterKey, label: 'NEW SLOT', cls: 'bg-caution-muted text-caution-muted-foreground border-caution-border' }, + { k: 'new-slot' as SpotFilterKey, label: 'NEW SLOT', cls: 'border', style: chipStyle('#5AC8FA') }, // NEW CALL is about the CALLSIGN, not the entity: never worked on this // band and mode. Only appears when the slot-highlight option is on. { k: 'new-call' as SpotFilterKey, label: 'NEW CALL', cls: 'bg-caution-muted text-caution-muted-foreground border-caution-border' }, // Same colours as the badges in the grid — a filter that does not // look like what it selects has to be learned twice. { k: 'new-pota' as SpotFilterKey, label: 'NEW POTA', cls: 'bg-success-muted text-success-muted-foreground border-success-border' }, - { k: 'new-county' as SpotFilterKey, label: 'NEW COUNTY', cls: 'bg-success-muted text-success-muted-foreground border-success-border' }, + { k: 'new-county' as SpotFilterKey, label: 'NEW COUNTY', cls: 'border', style: chipStyle('var(--chart-5)') }, { k: 'new-pfx' as SpotFilterKey, label: 'NEW PFX', cls: 'bg-caution-muted text-caution-muted-foreground border-caution-border' }, // Only ever set for a station this receiver decoded over the UDP link. { k: 'new-grid' as SpotFilterKey, label: 'NEW GRID', cls: 'bg-muted text-foreground border-border' }, @@ -6112,8 +6127,8 @@ export default function App() { // worked spots; the separate "Hide worked" checkbox drops them — they // are opposite controls, so don't use both at once. { k: 'worked' as SpotFilterKey, label: 'WORKED', cls: 'bg-info-muted text-info-muted-foreground border-info-border' }, - ]).map((s) => fChip(s.k, s.label, s.cls, clusterStatusFilter.has(s.k), - () => setClusterStatusFilter((cur) => { const n = new Set(cur); if (n.has(s.k)) n.delete(s.k); else n.add(s.k); return n; })))} + ]).map((s: any) => fChip(s.k, s.label, s.cls, clusterStatusFilter.has(s.k), + () => setClusterStatusFilter((cur) => { const n = new Set(cur); if (n.has(s.k)) n.delete(s.k); else n.add(s.k); return n; }), s.style))}
, clusterStatusFilter.size > 0 ? (