From ac4039393d70118fe1029ad30a1d5dd479326ad0 Mon Sep 17 00:00:00 2001 From: rouggy Date: Sat, 18 Jul 2026 04:06:43 +0200 Subject: [PATCH] feat: RIT back to 0 once a qso is logged --- app.go | 2 ++ frontend/src/components/FlexPanel.tsx | 33 ++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/app.go b/app.go index e314c61..c560a2c 100644 --- a/app.go +++ b/app.go @@ -1851,6 +1851,8 @@ func (a *App) AddQSO(q qso.QSO) (id int64, err error) { } if err == nil { q.ID = id + // Announce the log so UI widgets can react (e.g. the Flex panel zeroing RIT). + wruntime.EventsEmit(a.ctx, "qso:logged", id) a.saveQSORecording(&q) if a.extsvc != nil { a.extsvc.OnQSOLogged(id) diff --git a/frontend/src/components/FlexPanel.tsx b/frontend/src/components/FlexPanel.tsx index aee0b2d..57cc16e 100644 --- a/frontend/src/components/FlexPanel.tsx +++ b/frontend/src/components/FlexPanel.tsx @@ -12,6 +12,7 @@ import { FlexSetAPF, FlexSetAPFLevel, FlexSetCWSpeed, FlexSetCWPitch, FlexSetCWBreakInDelay, FlexSetCWSidetone, FlexSetSidetoneLevel, FlexSetCWFilter, FlexSetFilter, } from '../../wailsjs/go/main/App'; +import { EventsOn } from '../../wailsjs/runtime/runtime'; import { cn } from '@/lib/utils'; import { useI18n } from '@/lib/i18n'; import { sMeterRST } from '@/lib/rst'; @@ -189,7 +190,7 @@ function OffsetRow({ label, on, onToggle, hz, onHz, disabled, title }: { return (
-
@@ -317,6 +318,36 @@ export function FlexPanel({ onCWSpeed, onReportRST }: { onCWSpeed?: (wpm: number const off = !st.available; const rxOff = off || !st.rx_avail; + + // Radio-style global RIT tuning: Ctrl+←/→ nudges the RIT offset (Ctrl+Shift = + // ±100 Hz) from anywhere, without having to click the RIT field first. A + // focused offset row (data-offsetrow) or a text field handles its own keys, so + // this never double-fires. Only active while RIT is on and the RX is available. + useEffect(() => { + const onKey = (e: KeyboardEvent) => { + if (!(e.ctrlKey || e.metaKey)) return; + if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return; + const ae = document.activeElement as HTMLElement | null; + if (ae && (ae.hasAttribute('data-offsetrow') || /^(input|textarea|select)$/i.test(ae.tagName) || ae.isContentEditable)) return; + if (!st.rit || rxOff) return; + e.preventDefault(); + const mag = e.shiftKey ? 100 : 10; + const next = (st.rit_freq || 0) + (e.key === 'ArrowRight' ? mag : -mag); + change('rit_freq', next, () => FlexSetRITFreq(next)); + }; + window.addEventListener('keydown', onKey); + return () => window.removeEventListener('keydown', onKey); + }, [st.rit, st.rit_freq, rxOff]); + + // Clear the RIT offset back to 0 whenever a QSO is logged (any path: Log + // button, keyer macro, WSJT-X), so the next station starts centred. Only acts + // when there's actually a non-zero offset to clear. + useEffect(() => { + const off = EventsOn('qso:logged', () => { + if (st.rit && (st.rit_freq || 0) !== 0) change('rit_freq', 0, () => FlexSetRITFreq(0)); + }); + return () => off(); + }, [st.rit, st.rit_freq]); const isCW = (st.mode || '').toUpperCase().includes('CW'); const PROC = [{ v: '0', l: 'NOR' }, { v: '1', l: 'DX' }, { v: '2', l: 'DX+' }]; const AGC = [{ v: 'off', l: 'OFF' }, { v: 'slow', l: 'SLOW' }, { v: 'med', l: 'MED' }, { v: 'fast', l: 'FAST' }];