diff --git a/changelog.json b/changelog.json index 7761dd8..3056240 100644 --- a/changelog.json +++ b/changelog.json @@ -6,13 +6,15 @@ "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 — 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.", - "Elecraft console: a mode row — CW, USB, LSB, DATA and DATA RTTY. The two DATA buttons set the K3’s submode as well (DATA A for FT8/FT4, FSK D for RTTY): switching to DATA by mode alone kept whatever submode the last session left, which is how a K3 “in DATA” keys FT8 with no audio." + "Elecraft console: a mode row — CW, USB, LSB, DATA and DATA RTTY. The two DATA buttons set the K3’s submode as well (DATA A for FT8/FT4, FSK D for RTTY): switching to DATA by mode alone kept whatever submode the last session left, which is how a K3 “in DATA” keys FT8 with no audio.", + "DX Cluster settings: “I chase POTA” and “I chase SOTA”, on by default. Unticked, the NEW POTA badge, colour and filter disappear — a new-band + new-POTA spot reads NEW BAND alone — and the reference columns stay empty." ], "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 — 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.", - "Console Elecraft : une rangée de modes — CW, USB, LSB, DATA et DATA RTTY. Les deux boutons DATA règlent aussi le sous-mode du K3 (DATA A pour FT8/FT4, FSK D pour le RTTY) : passer en DATA par le seul mode gardait le sous-mode de la session précédente, et un K3 « en DATA » manipulait le FT8 sans audio." + "Console Elecraft : une rangée de modes — CW, USB, LSB, DATA et DATA RTTY. Les deux boutons DATA règlent aussi le sous-mode du K3 (DATA A pour FT8/FT4, FSK D pour le RTTY) : passer en DATA par le seul mode gardait le sous-mode de la session précédente, et un K3 « en DATA » manipulait le FT8 sans audio.", + "Réglages DX Cluster : « Je chasse le POTA » et « Je chasse le SOTA », cochés par défaut. Décochés, le badge, la couleur et le filtre NOUVEAU POTA disparaissent — un spot nouvelle bande + nouveau POTA affiche seulement NOUVELLE BANDE — et les colonnes de références restent vides." ] }, { diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 70d7773..493ac8f 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -98,7 +98,7 @@ import { ExportFieldsDialog } from '@/components/ExportFieldsDialog'; import { ShutdownProgress } from '@/components/ShutdownProgress'; import { ClusterGrid } from '@/components/ClusterGrid'; import { cleanSpotter, inferSpotMode, spotModeCategory, spotStatusKey } from '@/lib/spot'; -import { applySpotDisplay, readSpotDisplayOptions, spotIsWorked, SPOT_DISPLAY_OPTIONS_EXPOSED } from '@/lib/spotDisplay'; +import { applySpotDisplay, chasePota, readSpotDisplayOptions, spotIsWorked, SPOT_DISPLAY_OPTIONS_EXPOSED } from '@/lib/spotDisplay'; import { AnswerDecode, HaltDecodeTx, LogUIError, FlexTXOnBand, GetMatrixColors, GetRotorPresets, GetRowColors, GetSpotTTLMinutes, GetSpotMax, IsNewUSCounty } from '../wailsjs/go/main/App'; import { applyMatrixColors } from '@/lib/matrixColors'; import { WorkedBeforeGrid } from '@/components/WorkedBeforeGrid'; @@ -6127,7 +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: any) => fChip(s.k, s.label, s.cls, clusterStatusFilter.has(s.k), + ]).filter((s: any) => s.k !== 'new-pota' || chasePota()) + .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 ? ( diff --git a/frontend/src/components/BandMap.tsx b/frontend/src/components/BandMap.tsx index a33c596..35ebc45 100644 --- a/frontend/src/components/BandMap.tsx +++ b/frontend/src/components/BandMap.tsx @@ -272,11 +272,11 @@ export function BandMap({ band, spots, spotStatus: spotStatusRaw, currentFreqHz, // nothing until the next poll happened to hand over a fresh object. const dispOpts = readSpotDisplayOptions(); const spotStatus = useMemo(() => { - if (!dispOpts.muteWorked && !dispOpts.slotHighlight) return spotStatusRaw; + if (!dispOpts.muteWorked && !dispOpts.slotHighlight && dispOpts.chasePota) return spotStatusRaw; const out: Record = {}; for (const k of Object.keys(spotStatusRaw)) out[k] = applySpotDisplay(spotStatusRaw[k], dispOpts) as SpotStatusEntry; return out; - }, [spotStatusRaw, dispOpts.muteWorked, dispOpts.slotHighlight]); + }, [spotStatusRaw, dispOpts.muteWorked, dispOpts.slotHighlight, dispOpts.chasePota]); // Re-render when the operator changes their IARU region in Settings. const [, setRegionTick] = useState(0); useEffect(() => subscribeIaruRegion(() => setRegionTick((n) => n + 1)), []); diff --git a/frontend/src/components/ClusterGrid.tsx b/frontend/src/components/ClusterGrid.tsx index c35b1cc..56d9490 100644 --- a/frontend/src/components/ClusterGrid.tsx +++ b/frontend/src/components/ClusterGrid.tsx @@ -13,7 +13,7 @@ import { Button } from '@/components/ui/button'; import { Checkbox } from '@/components/ui/checkbox'; import { cleanSpotter, inferSpotMode, spotStatusKey } from '@/lib/spot'; import { markerColour } from '@/lib/spotMarkers'; -import { applySpotDisplay, readSpotDisplayOptions } from '@/lib/spotDisplay'; +import { applySpotDisplay, chasePota, chaseSota, readSpotDisplayOptions } from '@/lib/spotDisplay'; import { loadLocal, loadRemote, saveState, seedLocal, whenGridPrefsReady } from '@/lib/gridPrefs'; import { distanceUnit, distanceValue, subscribeDistanceUnit } from '@/lib/units'; import { useI18n } from '@/lib/i18n'; @@ -343,7 +343,9 @@ const makeColCatalog = (t: TFn): ColEntry[] => [ }, { group: 'Spot', label: t('clg2.c.pota'), colId: 'pota', - headerName: t('clg2.c.pota'), field: 'pota_ref' as any, width: 92, cellClass: 'font-mono', + headerName: t('clg2.c.pota'), width: 92, cellClass: 'font-mono', + // Through a valueGetter so the chase switch empties the column live. + valueGetter: (p: any) => (chasePota() ? p.data?.pota_ref ?? '' : ''), defaultVisible: true, cellStyle: (p: any) => (statusFor(p)?.new_pota ? fillStyle(markerColour('new_pota')) @@ -356,7 +358,8 @@ const makeColCatalog = (t: TFn): ColEntry[] => [ // which is why the column is off by default rather than an empty column for // everyone who does not watch summits. group: 'Spot', label: t('clg2.c.sota'), colId: 'sota', - headerName: t('clg2.c.sota'), field: 'sota_ref' as any, width: 100, cellClass: 'font-mono', + headerName: t('clg2.c.sota'), width: 100, cellClass: 'font-mono', + valueGetter: (p: any) => (chaseSota() ? p.data?.sota_ref ?? '' : ''), defaultVisible: false, cellStyle: () => ({ color: 'var(--success)' }) as any, }, diff --git a/frontend/src/components/SettingsModal.tsx b/frontend/src/components/SettingsModal.tsx index 6a44873..77748d0 100644 --- a/frontend/src/components/SettingsModal.tsx +++ b/frontend/src/components/SettingsModal.tsx @@ -2068,6 +2068,8 @@ function SettingsModalImpl({ onClose, onSaved, initialSection, onMainPaneChanged try { await SaveGridScopeSettings(next); } catch { /* the panel keeps the choice either way */ } }; const [chaseGrids, setChaseGrids] = useState(false); + const [chasePotaOn, setChasePotaOn] = useState(() => localStorage.getItem('opslog.chasePota') !== '0'); + const [chaseSotaOn, setChaseSotaOn] = useState(() => localStorage.getItem('opslog.chaseSota') !== '0'); const [chaseNew, setChaseNew] = useState(false); const [spotTTL, setSpotTTL] = useState(0); const [spotTTLText, setSpotTTLText] = useState('0'); @@ -5380,6 +5382,19 @@ function SettingsModalImpl({ onClose, onSaved, initialSection, onMainPaneChanged
+ {/* Chase switches: off, the marker stops being TOLD, everywhere at + once — badge, colour, filter chip, reference column. A "new band + + new POTA" spot then reads NEW BAND alone. */} + +