fix: improve cw decoding with qrm

This commit is contained in:
2026-06-20 02:25:53 +02:00
parent 32878c17be
commit 2228816057
3 changed files with 87 additions and 74 deletions
+9 -6
View File
@@ -597,6 +597,9 @@ export default function App() {
const [cwText, setCwText] = useState('');
const [cwStatus, setCwStatus] = useState<{ wpm: number; pitch: number; level: number; active: boolean }>({ wpm: 0, pitch: 0, level: 0, active: false });
const cwOn = cwEnabled && mode === 'CW';
// Keep the decoded line scrolled to the newest text (left-aligned, no scrollbar).
const cwScrollRef = useRef<HTMLDivElement>(null);
useEffect(() => { const el = cwScrollRef.current; if (el) el.scrollLeft = el.scrollWidth; }, [cwText]);
useEffect(() => {
const offT = EventsOn('cw:text', (t: string) => setCwText((s) => (s + t).slice(-200)));
const offS = EventsOn('cw:status', (st: any) => setCwStatus(st));
@@ -3202,7 +3205,7 @@ export default function App() {
{/* ===== CW decoder strip (only when enabled AND mode is CW) ===== */}
{cwOn && (
<div className="mx-2.5 mb-1 flex items-center gap-2 rounded-md border border-emerald-300/70 bg-emerald-50/60 px-2 py-1 text-xs">
<div className="ml-2.5 mb-1 w-[45%] flex items-center gap-2 rounded-md border border-emerald-300/70 bg-emerald-50/60 px-2 py-1 text-xs">
<Ear className={cn('size-4 shrink-0', cwStatus.active ? 'text-emerald-600' : 'text-muted-foreground')} />
{/* Input-level meter — if this stays flat with a strong signal, the RX
audio device is wrong/silent rather than a decode problem. */}
@@ -3212,18 +3215,18 @@ export default function App() {
<span className="shrink-0 font-mono text-[10px] text-muted-foreground tabular-nums">
{cwStatus.wpm > 0 ? `${cwStatus.wpm} WPM` : '— WPM'} · {cwStatus.pitch > 0 ? `${cwStatus.pitch} Hz` : '— Hz'}
</span>
{/* Single-line rolling ticker — no scrollbar; newest text stays
pinned to the right, older text scrolls off the left. */}
<div className="flex-1 min-w-0 overflow-hidden font-mono leading-5">
{/* Left-aligned single line, no scrollbar; auto-scrolled to the newest
text (see cwScrollRef effect) so the latest stays in view. */}
<div ref={cwScrollRef} className="flex-1 min-w-0 overflow-hidden font-mono leading-5">
{cwText.trim() === '' ? (
<span className="text-muted-foreground italic">listening</span>
) : (
<div className="flex justify-end whitespace-nowrap">
<div className="inline-flex whitespace-nowrap">
{cwText.trim().split(/\s+/).map((tok, i) => (
<button
key={i}
type="button"
className="ml-1 shrink-0 rounded px-1 hover:bg-emerald-200/70"
className="mr-1 shrink-0 rounded px-1 hover:bg-emerald-200/70"
title="Use as callsign"
onClick={() => onCallsignInput(tok, { force: true })}
>