[fix](trx-frontend-http): decouple signal view from spectrum and fix canvas scaling

This commit is contained in:
2026-03-05 21:14:35 +01:00
parent a041dd4505
commit 633ad92dd6
2 changed files with 20 additions and 91 deletions
@@ -245,6 +245,7 @@ function applyAuthRestrictions() {
function applyCapabilities(caps) { function applyCapabilities(caps) {
if (!caps) return; if (!caps) return;
lastHasTx = !!caps.tx; lastHasTx = !!caps.tx;
if (signalVisualBlockEl) signalVisualBlockEl.style.display = "";
// PTT / TX controls // PTT / TX controls
const pttBtn = document.getElementById("ptt-btn"); const pttBtn = document.getElementById("ptt-btn");
@@ -292,6 +293,8 @@ function applyCapabilities(caps) {
setSignalSplitControlVisible(false); setSignalSplitControlVisible(false);
if (centerFreqField) centerFreqField.style.display = "none"; if (centerFreqField) centerFreqField.style.display = "none";
stopSpectrumStreaming(); stopSpectrumStreaming();
resizeHeaderSignalCanvas();
scheduleOverviewDraw();
} }
scheduleSpectrumLayout(); scheduleSpectrumLayout();
} }
@@ -767,10 +770,16 @@ function _wfPalKey(pal) {
} }
function resizeHeaderSignalCanvas() { function resizeHeaderSignalCanvas() {
if (!overviewCanvas) return; if (!ensureOverviewCanvasBackingStore()) return;
positionRdsPsOverlay();
drawHeaderSignalGraph();
}
function ensureOverviewCanvasBackingStore() {
if (!overviewCanvas) return false;
const cssW = Math.floor(overviewCanvas.clientWidth); const cssW = Math.floor(overviewCanvas.clientWidth);
const cssH = Math.floor(overviewCanvas.clientHeight); const cssH = Math.floor(overviewCanvas.clientHeight);
if (cssW <= 0 || cssH <= 0) return; if (cssW <= 0 || cssH <= 0) return false;
const dpr = window.devicePixelRatio || 1; const dpr = window.devicePixelRatio || 1;
const nextW = Math.floor(cssW * dpr); const nextW = Math.floor(cssW * dpr);
const nextH = Math.floor(cssH * dpr); const nextH = Math.floor(cssH * dpr);
@@ -780,8 +789,7 @@ function resizeHeaderSignalCanvas() {
_wfResetOffscreen(); _wfResetOffscreen();
trimOverviewWaterfallRows(); trimOverviewWaterfallRows();
} }
positionRdsPsOverlay(); return true;
drawHeaderSignalGraph();
} }
function signalOverlayHeight() { function signalOverlayHeight() {
@@ -835,26 +843,6 @@ function drawSignalOverlay() {
const range = spectrumVisibleRange(lastSpectrumData); const range = spectrumVisibleRange(lastSpectrumData);
const hzToX = (hz) => ((hz - range.visLoHz) / range.visSpanHz) * cssW; const hzToX = (hz) => ((hz - range.visLoHz) / range.visSpanHz) * cssW;
// ── Bookmark frequency markers (span full overlay height = waterfall + waveform) ──
const _bmOvRef = typeof bmList !== "undefined" ? bmList : null;
if (Array.isArray(_bmOvRef) && _bmOvRef.length > 0) {
const colorMap = bmCategoryColorMap();
ctx.save();
ctx.lineWidth = 1;
ctx.setLineDash([4, 3]);
for (const bm of _bmOvRef) {
const x = hzToX(bm.freq_hz);
if (x < 0 || x > cssW) continue;
ctx.strokeStyle = bmHexToRgba(colorMap[bm.category || ""], 0.60);
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, cssH);
ctx.stroke();
}
ctx.setLineDash([]);
ctx.restore();
}
if (lastFreqHz != null && currentBandwidthHz > 0) { if (lastFreqHz != null && currentBandwidthHz > 0) {
for (const spec of visibleBandwidthSpecs(lastFreqHz)) { for (const spec of visibleBandwidthSpecs(lastFreqHz)) {
const span = displaySpanForBandwidthSpec(spec); const span = displaySpanForBandwidthSpec(spec);
@@ -988,7 +976,7 @@ function startHeaderSignalSampling() {
} }
function drawHeaderSignalGraph() { function drawHeaderSignalGraph() {
if (!overviewCanvas) return; if (!ensureOverviewCanvasBackingStore()) return;
const ctx = overviewCanvas.getContext("2d"); const ctx = overviewCanvas.getContext("2d");
if (!ctx) return; if (!ctx) return;
const pal = canvasPalette(); const pal = canvasPalette();
@@ -2033,15 +2021,15 @@ function updateSpectrumAutoHeight() {
if (!mainVisible || !contentVisible || !spectrumVisible) { if (!mainVisible || !contentVisible || !spectrumVisible) {
setSignalSplitControlVisible(false); setSignalSplitControlVisible(false);
const dimensionsChanged =
currentOverviewHeight !== DEFAULT_OVERVIEW_PLOT_HEIGHT_PX
|| currentSpectrumHeight !== DEFAULT_SPECTRUM_PLOT_HEIGHT_PX;
root.style.setProperty("--overview-plot-height", `${DEFAULT_OVERVIEW_PLOT_HEIGHT_PX}px`); root.style.setProperty("--overview-plot-height", `${DEFAULT_OVERVIEW_PLOT_HEIGHT_PX}px`);
root.style.setProperty("--spectrum-plot-height", `${DEFAULT_SPECTRUM_PLOT_HEIGHT_PX}px`); root.style.setProperty("--spectrum-plot-height", `${DEFAULT_SPECTRUM_PLOT_HEIGHT_PX}px`);
if ( if (dimensionsChanged) {
(currentOverviewHeight !== DEFAULT_OVERVIEW_PLOT_HEIGHT_PX resizeHeaderSignalCanvas();
|| currentSpectrumHeight !== DEFAULT_SPECTRUM_PLOT_HEIGHT_PX)
&& lastSpectrumData
) {
scheduleSpectrumDraw();
scheduleOverviewDraw(); scheduleOverviewDraw();
if (lastSpectrumData) scheduleSpectrumDraw();
} }
return; return;
} }
@@ -7003,23 +6991,6 @@ if (spectrumCanvas) {
}, { passive: false }); }, { passive: false });
} }
if (overviewCanvas) {
overviewCanvas.addEventListener("wheel", (e) => {
e.preventDefault();
if (!lastSpectrumData) return;
if (e.ctrlKey) {
const direction = e.deltaY < 0 ? 1 : -1;
jogFreq(direction);
return;
}
const rect = overviewCanvas.getBoundingClientRect();
const cssX = e.clientX - rect.left;
const factor = e.deltaY < 0 ? 1.25 : 1 / 1.25;
spectrumZoomAt(cssX, rect.width, lastSpectrumData, factor);
scheduleSpectrumDraw();
scheduleOverviewDraw();
}, { passive: false });
}
// ── BW strip edge hit-test (CSS pixels) ────────────────────────────────────── // ── BW strip edge hit-test (CSS pixels) ──────────────────────────────────────
function getBwEdgeHit(cssX, cssW, range) { function getBwEdgeHit(cssX, cssW, range) {
@@ -7247,48 +7218,6 @@ if (spectrumCanvas) {
}); });
} }
if (overviewCanvas) {
overviewCanvas.addEventListener("mousemove", (e) => {
if (!lastSpectrumData) return;
const rect = overviewCanvas.getBoundingClientRect();
const cssX = e.clientX - rect.left;
const range = spectrumVisibleRange(lastSpectrumData);
const edge = getBwEdgeHit(cssX, rect.width, range);
overviewCanvas.style.cursor = edge ? "ew-resize" : "crosshair";
});
overviewCanvas.addEventListener("mouseleave", () => {
overviewCanvas.style.cursor = "crosshair";
});
overviewCanvas.addEventListener("mousedown", (e) => {
if (e.button !== 0 || !lastSpectrumData) return;
const rect = overviewCanvas.getBoundingClientRect();
const cssX = e.clientX - rect.left;
const range = spectrumVisibleRange(lastSpectrumData);
const edge = getBwEdgeHit(cssX, rect.width, range);
if (!edge) return;
_bwDragEdge = edge;
_bwDragStartX = cssX;
_bwDragStartBwHz = currentBandwidthHz;
_bwDragCanvas = overviewCanvas;
_sDragStart = null;
_sDragMoved = true;
e.preventDefault();
});
overviewCanvas.addEventListener("click", (e) => {
if (_sDragMoved) { _sDragMoved = false; return; }
if (!lastSpectrumData) return;
const rect = overviewCanvas.getBoundingClientRect();
const cssX = e.clientX - rect.left;
const targetHz = spectrumTargetHzAt(cssX, rect.width, lastSpectrumData);
if (!Number.isFinite(targetHz)) return;
setRigFrequency(targetHz)
.catch(() => {});
});
}
if (spectrumCenterLeftBtn) { if (spectrumCenterLeftBtn) {
spectrumCenterLeftBtn.addEventListener("click", () => { spectrumCenterLeftBtn.addEventListener("click", () => {
shiftSpectrumCenter(-1).catch(() => {}); shiftSpectrumCenter(-1).catch(() => {});
@@ -86,9 +86,9 @@
<div id="ft8-bar-overlay" aria-live="polite" aria-label="Recent FT8 decodes"></div> <div id="ft8-bar-overlay" aria-live="polite" aria-label="Recent FT8 decodes"></div>
<div id="aprs-bar-overlay" aria-live="polite" aria-label="Recent APRS frames"></div> <div id="aprs-bar-overlay" aria-live="polite" aria-label="Recent APRS frames"></div>
</div> </div>
<div id="spectrum-bookmark-axis"></div>
<div id="spectrum-panel" style="display:none;"> <div id="spectrum-panel" style="display:none;">
<div class="spectrum-wrap"> <div class="spectrum-wrap">
<div id="spectrum-bookmark-axis"></div>
<div id="spectrum-bookmark-side-left" class="spectrum-bookmark-side spectrum-bookmark-side-left" aria-hidden="true"></div> <div id="spectrum-bookmark-side-left" class="spectrum-bookmark-side spectrum-bookmark-side-left" aria-hidden="true"></div>
<button id="spectrum-center-left-btn" class="spectrum-edge-shift spectrum-edge-shift-left" type="button" aria-label="Shift spectrum center left">&lsaquo;</button> <button id="spectrum-center-left-btn" class="spectrum-edge-shift spectrum-edge-shift-left" type="button" aria-label="Shift spectrum center left">&lsaquo;</button>
<canvas id="spectrum-canvas"></canvas> <canvas id="spectrum-canvas"></canvas>