feat(chase): the switches follow the operator, not the panel
Chase POTA, US counties, prefixes and grids were written for the cluster and stayed there, so an operator who does not chase parks still met NEW POTA in the FT decode list and in Chase new: the same badge withdrawn on one screen and shouting on the next. The setting is about what is hunted. One helper answers the question for every panel, keyed by both the status field names and the shorter category names so a single call serves badges and filter chips alike. Chase new also stops CATEGORISING a row by a marker that is switched off, which had left rows listed with no visible reason for being there. A new US state has no switch of its own, so it is always allowed.
This commit is contained in:
@@ -12,6 +12,7 @@ import { useEffect, useMemo, useState } from 'react';
|
||||
import { Radar, Loader2, X } from 'lucide-react';
|
||||
import { formatDistance } from '@/lib/units';
|
||||
import { useI18n } from '@/lib/i18n';
|
||||
import { chaseAllows } from '@/lib/spotDisplay';
|
||||
import { markerColour } from '@/lib/spotMarkers';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { GetChaseNewSpots } from '../../wailsjs/go/main/App';
|
||||
@@ -60,6 +61,10 @@ const CATEGORIES: Array<{ key: Category; labelKey: string; colour: string }> = [
|
||||
];
|
||||
|
||||
// categoryOf is the single thing a row says about a station.
|
||||
//
|
||||
// A category the operator does not chase is not a category here either: with
|
||||
// prefixes and squares switched off this panel showed rows whose only reason
|
||||
// for being listed had been withdrawn everywhere else.
|
||||
function categoryOf(s: ChaseNewSpot): Category | null {
|
||||
switch (s.status) {
|
||||
case 'new': return 'dxcc';
|
||||
@@ -68,8 +73,8 @@ function categoryOf(s: ChaseNewSpot): Category | null {
|
||||
case 'new-mode': return 'mode';
|
||||
case 'new-slot': return 'slot';
|
||||
}
|
||||
if (s.new_pfx) return 'pfx';
|
||||
if (s.new_grid) return 'grid';
|
||||
if (s.new_pfx && chaseAllows('pfx')) return 'pfx';
|
||||
if (s.new_grid && chaseAllows('grid')) return 'grid';
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -83,7 +88,7 @@ function loadFilters(): Set<Category> {
|
||||
if (Array.isArray(list)) return new Set(list);
|
||||
}
|
||||
} catch { /* a corrupt preference is not worth a broken panel */ }
|
||||
return new Set(CATEGORIES.map((c) => c.key));
|
||||
return new Set(CATEGORIES.filter((c) => chaseAllows(c.key)).map((c) => c.key));
|
||||
}
|
||||
|
||||
export function ChaseNewPanel({ onPick, onClose }: Props) {
|
||||
@@ -132,7 +137,7 @@ export function ChaseNewPanel({ onPick, onClose }: Props) {
|
||||
|
||||
{/* Filters, in the same order and colours as the badges they hide. */}
|
||||
<div className="flex flex-1 flex-wrap items-center gap-1">
|
||||
{CATEGORIES.map((c) => (
|
||||
{CATEGORIES.filter((c) => chaseAllows(c.key)).map((c) => (
|
||||
<button
|
||||
key={c.key}
|
||||
type="button"
|
||||
|
||||
@@ -16,6 +16,7 @@ import { useEffect, useMemo, useState } from 'react';
|
||||
import { Radio, Search, X, Signal, ArrowUpRight, Timer, Trash2, Ban, Columns2, Bot } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useI18n } from '@/lib/i18n';
|
||||
import { chaseAllows } from '@/lib/spotDisplay';
|
||||
import { markerColour, type SpotMarkerKey } from '@/lib/spotMarkers';
|
||||
import { writeUiPref } from '@/lib/uiPref';
|
||||
|
||||
@@ -743,7 +744,7 @@ export function DecodesPanel({ decodes, txMsgs, txState, txStates, spotStatus, o
|
||||
{/* Per-category badges, in the colours of the flags they select — the
|
||||
same vocabulary as the Chase New panel. */}
|
||||
<span className="flex items-center gap-1 pl-1 border-l border-border/60 ml-1" title={t('dec.catsHint')}>
|
||||
{NEW_CATS.map((c) => {
|
||||
{NEW_CATS.filter((c) => chaseAllows(c.key)).map((c) => {
|
||||
const on = cats.has(c.key);
|
||||
return (
|
||||
<button
|
||||
@@ -1051,7 +1052,7 @@ export function DecodesPanel({ decodes, txMsgs, txState, txStates, spotStatus, o
|
||||
const e = statusOf(d);
|
||||
const st = e?.status && e.status !== 'worked' ? e.status : '';
|
||||
const entities = st ? entityBadgesFor(st) : [];
|
||||
const extras = EXTRA_BADGES.filter((b) => !!e?.[b.key]);
|
||||
const extras = EXTRA_BADGES.filter((b) => !!e?.[b.key] && chaseAllows(b.key as string));
|
||||
const mine = !!me && d.call === me;
|
||||
const hot = entities.length > 0 || extras.length > 0;
|
||||
// Someone answering us outranks everything else on the screen.
|
||||
|
||||
@@ -44,6 +44,27 @@ export function chaseGrid(): boolean {
|
||||
try { return localStorage.getItem('opslog.chaseGrids') !== '0'; } catch { return true; }
|
||||
}
|
||||
|
||||
// chaseAllows answers "does this operator chase this kind of thing at all?"
|
||||
// for the ORTHOGONAL markers — park, square, prefix, county.
|
||||
//
|
||||
// The switches were written for the cluster and stayed there, so an operator
|
||||
// who does not chase parks still met NEW POTA in the decode list and in Chase
|
||||
// new: the same badge, withdrawn on one screen and shouting on the next. The
|
||||
// setting is about what the operator hunts, not about which panel is open.
|
||||
//
|
||||
// The keys are both the status-entry field names (new_pota…) and the shorter
|
||||
// category names the panels filter with (pota…), so one call serves both.
|
||||
// Anything without a switch of its own — a new US state — is always allowed.
|
||||
export function chaseAllows(key: string): boolean {
|
||||
switch (key) {
|
||||
case 'new_pota': case 'pota': return chasePota();
|
||||
case 'new_grid': case 'grid': return chaseGrid();
|
||||
case 'new_pfx': case 'pfx': return chasePfx();
|
||||
case 'new_county': case 'cty': return chaseCounty();
|
||||
default: return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Both options are withdrawn from the filter panel for now. The machinery below
|
||||
// is deliberately kept whole — it is correct and hard-won — so putting the two
|
||||
// switches back is this one flag and the block they came from in App.tsx.
|
||||
|
||||
Reference in New Issue
Block a user