[fix](trx-frontend): fix CW picker visibility and widen tone range

Fix CW picker redraw when the decoder sub-tab becomes visible to avoid
white/blank canvas rendering.
Widen CW tone picker/input range to 100-10000 Hz and raise CW/CWR
bandwidth max to 9 kHz.

Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
2026-03-04 23:04:56 +01:00
parent 878b50cad7
commit d8f7ebafa0
3 changed files with 26 additions and 15 deletions
@@ -2937,8 +2937,8 @@ lockBtn.addEventListener("click", async () => {
// Per-mode defaults: [default bandwidth Hz, min Hz, max Hz, step Hz] // Per-mode defaults: [default bandwidth Hz, min Hz, max Hz, step Hz]
const MODE_BW_DEFAULTS = { const MODE_BW_DEFAULTS = {
CW: [500, 50, 2_000, 50], CW: [500, 100, 9_000, 50],
CWR: [500, 50, 2_000, 50], CWR: [500, 100, 9_000, 50],
LSB: [2_700, 300, 6_000, 100], LSB: [2_700, 300, 6_000, 100],
USB: [2_700, 300, 6_000, 100], USB: [2_700, 300, 6_000, 100],
AM: [9_000, 500, 20_000, 500], AM: [9_000, 500, 20_000, 500],
@@ -4987,7 +4987,13 @@ document.querySelectorAll(".sub-tab-bar").forEach((bar) => {
btn.classList.add("active"); btn.classList.add("active");
const parent = bar.parentElement; const parent = bar.parentElement;
parent.querySelectorAll(".sub-tab-panel").forEach((p) => p.style.display = "none"); parent.querySelectorAll(".sub-tab-panel").forEach((p) => p.style.display = "none");
parent.querySelector(`#subtab-${btn.dataset.subtab}`).style.display = ""; const nextPanel = parent.querySelector(`#subtab-${btn.dataset.subtab}`);
if (nextPanel) nextPanel.style.display = "";
if (btn.dataset.subtab === "cw" && window.refreshCwTonePicker) {
requestAnimationFrame(() => {
if (window.refreshCwTonePicker) window.refreshCwTonePicker();
});
}
}); });
}); });
@@ -561,7 +561,7 @@
<div class="cw-config"> <div class="cw-config">
<label class="cw-auto-label">Auto WPM + Tone <input type="checkbox" id="cw-auto" checked /></label> <label class="cw-auto-label">Auto WPM + Tone <input type="checkbox" id="cw-auto" checked /></label>
<label>WPM <input type="number" id="cw-wpm" min="5" max="40" value="15" /></label> <label>WPM <input type="number" id="cw-wpm" min="5" max="40" value="15" /></label>
<label>Tone (Hz) <input type="number" id="cw-tone" min="300" max="1200" value="700" /></label> <label>Tone (Hz) <input type="number" id="cw-tone" min="100" max="10000" value="700" /></label>
</div> </div>
<div class="cw-tone-picker"> <div class="cw-tone-picker">
<div class="cw-tone-picker-head"> <div class="cw-tone-picker-head">
@@ -10,8 +10,8 @@ const cwToneCanvas = document.getElementById("cw-tone-waterfall");
const cwTonePickerEl = document.querySelector(".cw-tone-picker"); const cwTonePickerEl = document.querySelector(".cw-tone-picker");
const cwToneRangeEl = document.getElementById("cw-tone-range"); const cwToneRangeEl = document.getElementById("cw-tone-range");
const CW_MAX_LINES = 200; const CW_MAX_LINES = 200;
const CW_TONE_MIN_HZ = 300; const CW_TONE_MIN_HZ = 100;
const CW_TONE_MAX_HZ = 1200; const CW_TONE_MAX_HZ = 10_000;
const CW_WPM_MIN = 5; const CW_WPM_MIN = 5;
const CW_WPM_MAX = 40; const CW_WPM_MAX = 40;
let cwLastAppendTime = 0; let cwLastAppendTime = 0;
@@ -59,10 +59,7 @@ function currentCwToneRange() {
if (!lowerSideband && !upperSideband) return null; if (!lowerSideband && !upperSideband) return null;
const toneMinHz = CW_TONE_MIN_HZ; const toneMinHz = CW_TONE_MIN_HZ;
const toneMaxHz = Math.min( const toneMaxHz = CW_TONE_MAX_HZ;
CW_TONE_MAX_HZ,
Math.round(bandwidthHz),
);
if (toneMaxHz < toneMinHz) { if (toneMaxHz < toneMinHz) {
return null; return null;
} }
@@ -93,11 +90,14 @@ function toneClampForRange(tone, range) {
function ensureCwToneCanvasResolution() { function ensureCwToneCanvasResolution() {
if (!cwToneCanvas) return false; if (!cwToneCanvas) return false;
const rect = cwToneCanvas.getBoundingClientRect(); const rect = cwToneCanvas.getBoundingClientRect();
const cssWidth = Math.max(1, Math.round(rect.width)); const cssWidth = Math.round(rect.width);
const cssHeight = Math.max(1, Math.round(rect.height)); const cssHeight = Math.round(rect.height);
if (cssWidth < 8 || cssHeight < 8) {
return false;
}
const dpr = window.devicePixelRatio || 1; const dpr = window.devicePixelRatio || 1;
const nextWidth = Math.max(1, Math.round(cssWidth * dpr)); const nextWidth = Math.round(cssWidth * dpr);
const nextHeight = Math.max(1, Math.round(cssHeight * dpr)); const nextHeight = Math.round(cssHeight * dpr);
if (cwToneCanvas.width !== nextWidth || cwToneCanvas.height !== nextHeight) { if (cwToneCanvas.width !== nextWidth || cwToneCanvas.height !== nextHeight) {
cwToneCanvas.width = nextWidth; cwToneCanvas.width = nextWidth;
cwToneCanvas.height = nextHeight; cwToneCanvas.height = nextHeight;
@@ -108,6 +108,8 @@ function ensureCwToneCanvasResolution() {
function drawCwTonePicker() { function drawCwTonePicker() {
if (!cwToneCanvas) return; if (!cwToneCanvas) return;
ensureCwToneCanvasResolution();
if (cwToneCanvas.width < 8 || cwToneCanvas.height < 8) return;
const ctx = cwToneCanvas.getContext("2d"); const ctx = cwToneCanvas.getContext("2d");
if (!ctx) return; if (!ctx) return;
@@ -382,7 +384,10 @@ if (cwPauseBtn) {
}); });
} }
window.refreshCwTonePicker = drawCwTonePicker; window.refreshCwTonePicker = function refreshCwTonePicker() {
ensureCwToneCanvasResolution();
drawCwTonePicker();
};
window.addEventListener("resize", () => { window.addEventListener("resize", () => {
if (ensureCwToneCanvasResolution()) drawCwTonePicker(); if (ensureCwToneCanvasResolution()) drawCwTonePicker();
}); });