fix(chase-new): one badge, filters, a way in and a way out — and the frequency
Four things from an operator's first look at the panel, and one of them was mine. The frequency column showed "—" on every row. pskr.Spot.FreqHz was declared and documented in one edit and never assigned in the next, so the payload's "f" was parsed and dropped. A click therefore filled the callsign and left the rig where it was, which is half the point of the panel. Assigned, with a test that runs a real payload through and checks the value survives into the Spot — the field being declared is what made it look done. A row now carries ONE indication instead of stacking them. A station can be a new band and a new prefix at once; the row says the first that matters, in the order that would make an operator leave what they are doing: entity, band, mode, slot, then prefix, then square. Two badges on one line made the list unreadable at a glance, which is the only thing it is for. Each category has a filter chip in the header, in its own colour, remembered across sessions. A toolbar button shows the panel and a cross closes it — the same split the Super Check Partial panel uses, where the setting decides whether the feature exists and the button whether it is on screen. The panel is wider and the country column gets what is left, which is more than it was now that a row carries one badge.
This commit is contained in:
+22
-5
@@ -1,7 +1,7 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import {
|
||||
Activity, AlertCircle, Antenna, Bell, Check, CheckCircle2, ChevronDown, Clock, CloudOff, Compass, Database, Ear, Eraser, Flame, Gauge, Hash, Loader2, Lock,
|
||||
Maximize2, Minimize2, Mic, MessageSquare, Pencil, Radio, RadioTower, RefreshCw, Satellite, Send, Settings, SlidersHorizontal, SpellCheck, Square, Terminal, Trash2, Unlock, X, Zap,
|
||||
Maximize2, Minimize2, Mic, MessageSquare, Pencil, Radar, Radio, RadioTower, RefreshCw, Satellite, Send, Settings, SlidersHorizontal, SpellCheck, Square, Terminal, Trash2, Unlock, X, Zap,
|
||||
} from 'lucide-react';
|
||||
|
||||
import {
|
||||
@@ -2091,6 +2091,9 @@ export default function App() {
|
||||
// panel is only meaningful while the PSK Reporter feed is up, and that is what
|
||||
// the setting decides.
|
||||
const [chaseNewOn, setChaseNewOn] = useState(false);
|
||||
// The setting decides whether the feature exists; this decides whether the
|
||||
// panel is on screen — the same split the Super Check Partial panel uses.
|
||||
const [showChaseNew, setShowChaseNew] = useState(() => localStorage.getItem('opslog.showChaseNew') !== '0');
|
||||
const refreshChaseNew = useCallback(() => { GetChaseNew().then(setChaseNewOn).catch(() => {}); }, []);
|
||||
useEffect(() => { refreshChaseNew(); }, [refreshChaseNew]);
|
||||
const [showBeamOnMap, setShowBeamOnMap] = useState(() => localStorage.getItem('opslog.showBeamOnMap') !== '0');
|
||||
@@ -5579,6 +5582,20 @@ export default function App() {
|
||||
<SpellCheck className="size-4" />
|
||||
</button>
|
||||
)}
|
||||
{chaseNewOn && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => { const v = !showChaseNew; setShowChaseNew(v); writeUiPref('opslog.showChaseNew', v ? '1' : '0'); }}
|
||||
title={showChaseNew ? `${t('chn.toggle')} — ${t('chn.close')}` : t('chn.toggle')}
|
||||
className={cn(
|
||||
'relative inline-flex items-center justify-center size-7 rounded-md border transition-colors',
|
||||
showChaseNew ? 'border-success-border bg-success-muted text-success-muted-foreground hover:bg-success-muted'
|
||||
: 'border-border text-muted-foreground hover:bg-muted',
|
||||
)}
|
||||
>
|
||||
<Radar className="size-4" />
|
||||
</button>
|
||||
)}
|
||||
{chatAvailable && (
|
||||
<button
|
||||
type="button"
|
||||
@@ -6098,7 +6115,7 @@ export default function App() {
|
||||
{/* Reserved free space to the right. The WinKeyer CW keyer and/or the
|
||||
Digital Voice Keyer take this slot when enabled (Log4OM-style);
|
||||
otherwise it shows the QRZ profile photo. */}
|
||||
{!compact && (chatShown || wkEnabled || dvkEnabled || lookupResult?.image_url || (showRotor && (rotatorHeading.enabled || dxPath)) || (showAntGenius && agEnabled) || (showTuner && tgEnabled) || (showAmpWidget && ampSts.length > 0) || (showScp && scpEnabled) || (showLiveStations && dbConn?.backend === 'mysql')) && (
|
||||
{!compact && (chatShown || wkEnabled || dvkEnabled || lookupResult?.image_url || (showRotor && (rotatorHeading.enabled || dxPath)) || (showAntGenius && agEnabled) || (showTuner && tgEnabled) || (showAmpWidget && ampSts.length > 0) || (showScp && scpEnabled) || (chaseNewOn && showChaseNew) || (showLiveStations && dbConn?.backend === 'mysql')) && (
|
||||
// relative + absolute inner (like the F1-F5 panel): a taller widget (e.g.
|
||||
// the DVK with Auto CQ) can't grow the row — the row height stays set by
|
||||
// the entry strip and each widget fills that height, scrolling inside.
|
||||
@@ -6224,14 +6241,14 @@ export default function App() {
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{chaseNewOn && (
|
||||
<div className="w-[360px] shrink-0 min-h-0">
|
||||
{chaseNewOn && showChaseNew && (
|
||||
<div className="w-[420px] shrink-0 min-h-0">
|
||||
{/* Same reflex as clicking a cluster spot: the callsign into the
|
||||
entry, and the rig onto the frequency it was decoded on. */}
|
||||
<ChaseNewPanel onPick={(sp) => {
|
||||
onCallsignInput(sp.call, { force: true });
|
||||
if (sp.freq_hz) void tuneRigCAT(sp.freq_hz, sp.mode);
|
||||
}} />
|
||||
}} onClose={() => { setShowChaseNew(false); writeUiPref('opslog.showChaseNew', '0'); }} />
|
||||
</div>
|
||||
)}
|
||||
{dvkEnabled && (
|
||||
|
||||
Reference in New Issue
Block a user