feat(cluster): mark the cell that carries the fact, and add the US county
Colour moves from the text to the CELL. A filled Band cell means new band, a filled Pfx cell means new prefix, a filled County cell means new county. This is not the pills coming back: a pill is a box inside the cell with its own height and padding, so it pushed the text off the row baseline. A background has no geometry - the text does not move a pixel - and it reads from across the room, which a tinted glyph does not. Worked-call stays text-only: it is not a novelty, and filling it would wash most of the rows. The colours still come from the semantic tokens and lib/spotMarkers, so a fact keeps one colour across the grid, the band map and the filter chips - and the per-marker colour setting will drive all of it from one table. US County column. The backend already resolved the county from the offline ULS store to decide NewCounty and then threw it away; it now returns it, which costs nothing. The Locator column is renamed Spotter locator. It always held the SPOTTER's grid - cluster.go says so - so a column labelled Locator next to a DX callsign was reading as the DX's grid and was mostly empty besides. The DX grid is not in the feed at any price worth paying under an RBN firehose. Both display options move out of Preferences into the cluster filter panel, beside Hide worked. They are changed while working a run, not set up once, and a preferences dialog reopened every ten minutes is a filter in the wrong place.
This commit is contained in:
+23
-4
@@ -1488,6 +1488,11 @@ export default function App() {
|
||||
// 'new-call' is a DISPLAY status, produced by the slot-highlight option rather
|
||||
// than by the backend, so it is named here and not in SpotStatusKey.
|
||||
type SpotFilterKey = SpotStatusKey | 'new-pota' | 'new-county' | 'new-pfx' | 'new-call';
|
||||
// Display options, shared with the band map through lib/spotDisplay. Kept in
|
||||
// localStorage (mirrored to settings by writeUiPref) so both panels and the
|
||||
// filter predicate read one source without prop-drilling through three levels.
|
||||
const [clusterMuteWorked, setClusterMuteWorked] = useState(() => localStorage.getItem('opslog.clusterMuteWorked') === '1');
|
||||
const [clusterSlotHighlight, setClusterSlotHighlight] = useState(() => localStorage.getItem('opslog.clusterSlotHighlight') === '1');
|
||||
const [clusterStatusFilter, setClusterStatusFilter] = useState<Set<SpotFilterKey>>(() => lsSet<SpotFilterKey>('opslog.clusterStatusFilter'));
|
||||
// Mode filter chips. Empty set = show every mode. Categories map the
|
||||
// inferred per-spot mode onto SSB (phone) / CW / DATA (digital).
|
||||
@@ -1586,7 +1591,7 @@ export default function App() {
|
||||
// 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<Record<string, { status: string; country?: string; continent?: string; worked_call?: boolean; worked_slot?: boolean; new_county?: boolean; new_pota?: boolean; new_pfx?: boolean; pfx?: string }>>({});
|
||||
const [spotStatus, setSpotStatus] = useState<Record<string, { status: string; country?: string; continent?: string; worked_call?: boolean; worked_slot?: boolean; new_county?: boolean; county?: string; state?: string; new_pota?: boolean; new_pfx?: boolean; pfx?: string }>>({});
|
||||
// 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);
|
||||
@@ -1636,7 +1641,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, worked_slot: !!(r as any).worked_slot, 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, county: (r as any).county, state: (r as any).state,
|
||||
new_pota: !!(r as any).new_pota, new_pfx: !!(r as any).new_pfx, pfx: (r as any).pfx,
|
||||
};
|
||||
}
|
||||
@@ -2736,7 +2741,7 @@ export default function App() {
|
||||
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_county: !!(r as any).new_county, county: (r as any).county, state: (r as any).state,
|
||||
new_pota: !!(r as any).new_pota,
|
||||
new_pfx: !!(r as any).new_pfx,
|
||||
pfx: (r as any).pfx,
|
||||
@@ -3204,7 +3209,7 @@ export default function App() {
|
||||
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_county: !!(r as any).new_county, county: (r as any).county, state: (r as any).state,
|
||||
new_pota: !!(r as any).new_pota,
|
||||
new_pfx: !!(r as any).new_pfx,
|
||||
pfx: (r as any).pfx,
|
||||
@@ -4757,6 +4762,20 @@ export default function App() {
|
||||
<Checkbox checked={clusterGroup} onCheckedChange={(c) => setClusterGroup(!!c)} />
|
||||
Group duplicates
|
||||
</label>
|
||||
{/* Two ways to cut through a busy cluster, and they compose: mute what
|
||||
is done, light up what is not. They sit HERE, with the other things
|
||||
an operator changes mid-run, and not in the preferences dialog.
|
||||
Both drive the band map as well, through lib/spotDisplay. */}
|
||||
<label className="flex items-center gap-1.5 cursor-pointer">
|
||||
<Checkbox checked={clusterMuteWorked}
|
||||
onCheckedChange={(c) => { const v = !!c; setClusterMuteWorked(v); writeUiPref('opslog.clusterMuteWorked', v ? '1' : '0'); }} />
|
||||
{t('clu.muteWorkedShort')}
|
||||
</label>
|
||||
<label className="flex items-center gap-1.5 cursor-pointer">
|
||||
<Checkbox checked={clusterSlotHighlight}
|
||||
onCheckedChange={(c) => { const v = !!c; setClusterSlotHighlight(v); writeUiPref('opslog.clusterSlotHighlight', v ? '1' : '0'); }} />
|
||||
{t('clu.slotHighlightShort')}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{/* Band filter — multi-select listbox */}
|
||||
|
||||
Reference in New Issue
Block a user