feat(flex): edit the split chaser's marker on the panel

The marker text is chosen in the skimmer, and the two have to agree or
nothing fires -- so it belongs next to the switch, not in a settings page
the operator would have to remember exists. Kept as raw text until blur:
it is a comma-separated list and normalising each keystroke would eat the
comma as it is typed.
This commit is contained in:
2026-08-23 18:57:52 +02:00
parent 4fb013701b
commit 775daa233e
3 changed files with 30 additions and 5 deletions
+24 -1
View File
@@ -310,10 +310,14 @@ export function FlexPanel({ onCWSpeed, onReportRST }: { onCWSpeed?: (wpm: number
const [rstChase, setRstChase] = useState<{ enabled: boolean; markers: string; offset_hz: number; split_only: boolean }>(
{ enabled: false, markers: '599', offset_hz: 0, split_only: true });
const [rstChaseOffsetText, setRstChaseOffsetText] = useState('0');
// The marker text is edited as raw text and only parsed on blur: it is a
// comma-separated list, and normalising it on every keystroke would eat the
// comma the moment it is typed.
const [rstChaseMarkersText, setRstChaseMarkersText] = useState('599');
useEffect(() => {
GetFlexRSTChase().then((c: any) => {
if (!c) return;
setRstChase(c); setRstChaseOffsetText(String(c.offset_hz ?? 0));
setRstChase(c); setRstChaseOffsetText(String(c.offset_hz ?? 0)); setRstChaseMarkersText(String(c.markers ?? '599'));
}).catch(() => {});
}, []);
const [st, setSt] = useState<FlexState>(ZERO);
@@ -676,6 +680,25 @@ export function FlexPanel({ onCWSpeed, onReportRST }: { onCWSpeed?: (wpm: number
rstChase.enabled ? 'bg-success text-success-foreground border-success shadow-[0_0_12px] shadow-success/50' : 'bg-card text-success border-success hover:bg-success-muted')}>
{rstChase.markers.split(',')[0].trim() || '599'}
</button>
{rstChase.enabled && (
<label className="flex items-center gap-1 text-[11px] text-muted-foreground whitespace-nowrap">
{/* The marker is whatever SDC was told to write — "599", "5NN",
or several. Editable here rather than in a settings page
because it is chosen in the skimmer, and the two have to
agree or nothing ever fires. */}
{t('flxp.rstChaseMarker')}
<input type="text" value={rstChaseMarkersText}
onChange={(e) => setRstChaseMarkersText(e.target.value)}
onBlur={() => {
const v = rstChaseMarkersText.trim() || '599';
setRstChaseMarkersText(v);
const next = { ...rstChase, markers: v };
setRstChase(next); SaveFlexRSTChase(next as any).catch(() => {});
}}
title={t('flxp.rstChaseMarkerHint')}
className="w-20 h-6 rounded border border-input bg-background px-1 text-[11px] font-mono uppercase" />
</label>
)}
{rstChase.enabled && (
<label className="flex items-center gap-1 text-[11px] text-muted-foreground whitespace-nowrap">
{t('flxp.rstChaseOffset')}