From b1f52bbfa54188470060f6116fafadc15989c07c Mon Sep 17 00:00:00 2001 From: Stan Grams Date: Sun, 15 Mar 2026 08:46:10 +0100 Subject: [PATCH] [fix](trx-frontend-http): fix FT4/FT2/WSPR message container styling and cap DOM rows Apply #ft8-messages container style (border, rounded corners, monospace font, max-height with scroll) to #ft4-messages, #ft2-messages, and #wspr-messages which were missing it. Add #ft4-decode-toggle-btn and #ft2-decode-toggle-btn to the narrow- screen white-space:nowrap media query rule alongside FT8/WSPR. Cap DOM rows rendered per history view to 200 (FT8_MAX_DOM_ROWS, FT4_MAX_DOM_ROWS, FT2_MAX_DOM_ROWS). Full history is retained in memory; only the DOM representation is bounded. This prevents tab switching from becoming sluggish after a long decode session where thousands of rows accumulate in the DOM. Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Stan Grams --- .../trx-frontend-http/assets/web/plugins/ft2.js | 5 ++++- .../trx-frontend-http/assets/web/plugins/ft4.js | 5 ++++- .../trx-frontend-http/assets/web/plugins/ft8.js | 4 +++- .../trx-frontend/trx-frontend-http/assets/web/style.css | 7 +++++-- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/ft2.js b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/ft2.js index 0293fc7..d04cf62 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/ft2.js +++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/ft2.js @@ -13,6 +13,7 @@ const ft2PeriodEl = document.getElementById("ft2-period"); const ft2MessagesEl = document.getElementById("ft2-messages"); const ft2FilterInput = document.getElementById("ft2-filter"); const FT2_PERIOD_MS = 3750; +const FT2_MAX_DOM_ROWS = 200; let ft2FilterText = ""; let ft2MessageHistory = []; @@ -80,10 +81,12 @@ function renderFt2History() { if (!ft2MessagesEl) return; const filter = ft2FilterText; const fragment = document.createDocumentFragment(); - for (let i = 0; i < ft2MessageHistory.length; i++) { + let rendered = 0; + for (let i = 0; i < ft2MessageHistory.length && rendered < FT2_MAX_DOM_ROWS; i++) { const msg = ft2MessageHistory[i]; if (filter && !(msg.message || "").toString().toUpperCase().includes(filter)) continue; fragment.appendChild(renderFt2Row(msg)); + rendered++; } ft2MessagesEl.replaceChildren(fragment); } diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/ft4.js b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/ft4.js index 87eeede..dfcc1cf 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/ft4.js +++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/ft4.js @@ -13,6 +13,7 @@ const ft4PeriodEl = document.getElementById("ft4-period"); const ft4MessagesEl = document.getElementById("ft4-messages"); const ft4FilterInput = document.getElementById("ft4-filter"); const FT4_PERIOD_MS = 7500; +const FT4_MAX_DOM_ROWS = 200; let ft4FilterText = ""; let ft4MessageHistory = []; @@ -80,10 +81,12 @@ function renderFt4History() { if (!ft4MessagesEl) return; const filter = ft4FilterText; const fragment = document.createDocumentFragment(); - for (let i = 0; i < ft4MessageHistory.length; i++) { + let rendered = 0; + for (let i = 0; i < ft4MessageHistory.length && rendered < FT4_MAX_DOM_ROWS; i++) { const msg = ft4MessageHistory[i]; if (filter && !(msg.message || "").toString().toUpperCase().includes(filter)) continue; fragment.appendChild(renderFt4Row(msg)); + rendered++; } ft4MessagesEl.replaceChildren(fragment); } diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/ft8.js b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/ft8.js index 69e26aa..44a431c 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/ft8.js +++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/ft8.js @@ -6,6 +6,7 @@ const ft8FilterInput = document.getElementById("ft8-filter"); const ft8BarOverlay = document.getElementById("ft8-bar-overlay"); const FT8_BAR_WINDOW_MS = 15 * 60 * 1000; const FT8_PERIOD_SECONDS = 15; +const FT8_MAX_DOM_ROWS = 200; const FT8_BAR_DECODER_LABELS = { ft8: "FT8", ft4: "FT4", @@ -105,7 +106,8 @@ function renderFt8History() { pruneFt8MessageHistory(); if (!ft8MessagesEl) return; const fragment = document.createDocumentFragment(); - for (let i = 0; i < ft8MessageHistory.length; i += 1) { + const limit = Math.min(ft8MessageHistory.length, FT8_MAX_DOM_ROWS); + for (let i = 0; i < limit; i += 1) { fragment.appendChild(renderFt8Row(ft8MessageHistory[i])); } ft8MessagesEl.replaceChildren(fragment); diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css index 8d6b144..69bcce1 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css +++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css @@ -2104,7 +2104,10 @@ body.map-fake-fullscreen-active { } .ft8-filter::placeholder { color: color-mix(in srgb, var(--filter-fg) 55%, transparent); } .ft8-header { display: flex; gap: 0.6rem; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); border-bottom: 1px solid var(--border); padding: 0 0 0.35rem 0; margin-bottom: 0.35rem; } -#ft8-messages { max-height: 360px; overflow-y: auto; border: 1px solid var(--border-light); border-radius: 6px; background: var(--input-bg); font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-size: 0.85rem; padding: 0.35rem 0.5rem; } +#ft8-messages, +#ft4-messages, +#ft2-messages, +#wspr-messages { max-height: 360px; overflow-y: auto; border: 1px solid var(--border-light); border-radius: 6px; background: var(--input-bg); font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-size: 0.85rem; padding: 0.35rem 0.5rem; } .ft8-row { display: flex; gap: 0.6rem; line-height: 1.4; border-bottom: 1px solid var(--border); padding: 0.25rem 0; } .ft8-row:last-child { border-bottom: none; } .ft8-time { color: var(--text-muted); min-width: 4.6rem; } @@ -2365,7 +2368,7 @@ button:focus-visible, input:focus-visible, select:focus-visible { .controls-col.label-below-col .btn-grid { margin-top: 0; } .wfm-controls-inline { flex-wrap: wrap; } .ft8-controls { flex-wrap: wrap; } - #ft8-decode-toggle-btn, #wspr-decode-toggle-btn { white-space: nowrap; } + #ft8-decode-toggle-btn, #ft4-decode-toggle-btn, #ft2-decode-toggle-btn, #wspr-decode-toggle-btn { white-space: nowrap; } .jog-container { flex-wrap: wrap; } .vfo-picker { flex-direction: column; } .vfo-picker button { border-right: none; border-bottom: 1px solid var(--border-light); }