From 7527770c0c7043d8c44c45336f442831e39680bf Mon Sep 17 00:00:00 2001 From: Stanislaw Grams Date: Tue, 17 Mar 2026 22:39:00 +0100 Subject: [PATCH] [fix](trx-frontend): let decoder disable take scheduler control When a scheduler-managed decoder is manually disabled from the frontend, take scheduler control first so the manual change overrides the current scheduler cycle like a direct frequency change does. Track decoder enabled state on the toggle buttons and only take over when the click is actually disabling FT8, FT4, FT2, WSPR, or HF APRS. Co-Authored-By: OpenAI Codex Signed-off-by: Stanislaw Grams --- .../trx-frontend-http/assets/web/app.js | 15 +++++++++++++++ .../trx-frontend-http/assets/web/plugins/ft2.js | 10 ++++++++-- .../trx-frontend-http/assets/web/plugins/ft4.js | 10 ++++++++-- .../trx-frontend-http/assets/web/plugins/ft8.js | 10 ++++++++-- .../assets/web/plugins/hf-aprs.js | 10 ++++++++-- .../trx-frontend-http/assets/web/plugins/vchan.js | 1 + .../trx-frontend-http/assets/web/plugins/wspr.js | 10 ++++++++-- 7 files changed, 56 insertions(+), 10 deletions(-) diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js index 4b1e8ce..f2ee438 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js +++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js @@ -2875,6 +2875,7 @@ function render(update) { const ft8ToggleBtn = document.getElementById("ft8-decode-toggle-btn"); if (ft8ToggleBtn) { const ft8On = !!update.ft8_decode_enabled; + ft8ToggleBtn.dataset.enabled = ft8On ? "true" : "false"; ft8ToggleBtn.textContent = ft8On ? "Disable FT8" : "Enable FT8"; ft8ToggleBtn.style.borderColor = ft8On ? "#00d17f" : ""; ft8ToggleBtn.style.color = ft8On ? "#00d17f" : ""; @@ -2882,6 +2883,7 @@ function render(update) { const ft4ToggleBtn = document.getElementById("ft4-decode-toggle-btn"); if (ft4ToggleBtn) { const ft4On = !!update.ft4_decode_enabled; + ft4ToggleBtn.dataset.enabled = ft4On ? "true" : "false"; ft4ToggleBtn.textContent = ft4On ? "Disable FT4" : "Enable FT4"; ft4ToggleBtn.style.borderColor = ft4On ? "#00d17f" : ""; ft4ToggleBtn.style.color = ft4On ? "#00d17f" : ""; @@ -2889,6 +2891,7 @@ function render(update) { const ft2ToggleBtn = document.getElementById("ft2-decode-toggle-btn"); if (ft2ToggleBtn) { const ft2On = !!update.ft2_decode_enabled; + ft2ToggleBtn.dataset.enabled = ft2On ? "true" : "false"; ft2ToggleBtn.textContent = ft2On ? "Disable FT2" : "Enable FT2"; ft2ToggleBtn.style.borderColor = ft2On ? "#00d17f" : ""; ft2ToggleBtn.style.color = ft2On ? "#00d17f" : ""; @@ -2896,6 +2899,7 @@ function render(update) { const wsprToggleBtn = document.getElementById("wspr-decode-toggle-btn"); if (wsprToggleBtn) { const wsprOn = !!update.wspr_decode_enabled; + wsprToggleBtn.dataset.enabled = wsprOn ? "true" : "false"; wsprToggleBtn.textContent = wsprOn ? "Disable WSPR" : "Enable WSPR"; wsprToggleBtn.style.borderColor = wsprOn ? "#00d17f" : ""; wsprToggleBtn.style.color = wsprOn ? "#00d17f" : ""; @@ -2903,6 +2907,7 @@ function render(update) { const hfAprsToggleBtn = document.getElementById("hf-aprs-decode-toggle-btn"); if (hfAprsToggleBtn) { const hfAprsOn = !!update.hf_aprs_decode_enabled; + hfAprsToggleBtn.dataset.enabled = hfAprsOn ? "true" : "false"; hfAprsToggleBtn.textContent = hfAprsOn ? "Disable HF APRS" : "Enable HF APRS"; hfAprsToggleBtn.style.borderColor = hfAprsOn ? "#00d17f" : ""; hfAprsToggleBtn.style.color = hfAprsOn ? "#00d17f" : ""; @@ -3247,6 +3252,16 @@ async function postPath(path) { return resp; } +async function takeSchedulerControlForDecoderDisable(buttonEl) { + const enabled = buttonEl?.dataset?.enabled === "true" + || /^\s*Disable\b/i.test(buttonEl?.textContent || ""); + if (!enabled) return; + if (typeof window.vchanTakeSchedulerControl === "function") { + await window.vchanTakeSchedulerControl(); + } +} +window.takeSchedulerControlForDecoderDisable = takeSchedulerControlForDecoderDisable; + async function switchRigFromSelect(selectEl) { if (!selectEl || !selectEl.value) { showHint("No rig selected", 1500); 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 d04cf62..ab6d1c9 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 @@ -179,8 +179,14 @@ if (ft2FilterInput) { }); } -document.getElementById("ft2-decode-toggle-btn")?.addEventListener("click", async () => { - try { await postPath("/toggle_ft2_decode"); } catch (e) { console.error("FT2 toggle failed", e); } +const ft2DecodeToggleBtn = document.getElementById("ft2-decode-toggle-btn"); +ft2DecodeToggleBtn?.addEventListener("click", async () => { + try { + await window.takeSchedulerControlForDecoderDisable?.(ft2DecodeToggleBtn); + await postPath("/toggle_ft2_decode"); + } catch (e) { + console.error("FT2 toggle failed", e); + } }); document.getElementById("settings-clear-ft2-history")?.addEventListener("click", async () => { 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 dfcc1cf..ba85dfe 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 @@ -179,8 +179,14 @@ if (ft4FilterInput) { }); } -document.getElementById("ft4-decode-toggle-btn")?.addEventListener("click", async () => { - try { await postPath("/toggle_ft4_decode"); } catch (e) { console.error("FT4 toggle failed", e); } +const ft4DecodeToggleBtn = document.getElementById("ft4-decode-toggle-btn"); +ft4DecodeToggleBtn?.addEventListener("click", async () => { + try { + await window.takeSchedulerControlForDecoderDisable?.(ft4DecodeToggleBtn); + await postPath("/toggle_ft4_decode"); + } catch (e) { + console.error("FT4 toggle failed", e); + } }); document.getElementById("settings-clear-ft4-history")?.addEventListener("click", async () => { 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 44a431c..f5a9de2 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 @@ -447,8 +447,14 @@ if (ft8MessagesEl) { }); } -document.getElementById("ft8-decode-toggle-btn").addEventListener("click", async () => { - try { await postPath("/toggle_ft8_decode"); } catch (e) { console.error("FT8 toggle failed", e); } +const ft8DecodeToggleBtn = document.getElementById("ft8-decode-toggle-btn"); +ft8DecodeToggleBtn?.addEventListener("click", async () => { + try { + await window.takeSchedulerControlForDecoderDisable?.(ft8DecodeToggleBtn); + await postPath("/toggle_ft8_decode"); + } catch (e) { + console.error("FT8 toggle failed", e); + } }); document.getElementById("settings-clear-ft8-history")?.addEventListener("click", async () => { diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/hf-aprs.js b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/hf-aprs.js index 32eee1f..2423a8c 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/hf-aprs.js +++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/hf-aprs.js @@ -372,8 +372,14 @@ window.restoreHfAprsHistory = function(packets) { window.onServerHfAprsBatch(packets); }; -document.getElementById("hf-aprs-decode-toggle-btn")?.addEventListener("click", async () => { - try { await postPath("/toggle_hf_aprs_decode"); } catch (e) { console.error("HF APRS toggle failed", e); } +const hfAprsDecodeToggleBtn = document.getElementById("hf-aprs-decode-toggle-btn"); +hfAprsDecodeToggleBtn?.addEventListener("click", async () => { + try { + await window.takeSchedulerControlForDecoderDisable?.(hfAprsDecodeToggleBtn); + await postPath("/toggle_hf_aprs_decode"); + } catch (e) { + console.error("HF APRS toggle failed", e); + } }); document.getElementById("settings-clear-hf-aprs-history")?.addEventListener("click", async () => { diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/vchan.js b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/vchan.js index 1a1330d..62f6310 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/vchan.js +++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/vchan.js @@ -111,6 +111,7 @@ async function vchanTakeSchedulerControl() { console.error("scheduler control takeover failed", e); } } +window.vchanTakeSchedulerControl = vchanTakeSchedulerControl; // Called by app.js when the SSE `session` event arrives. function vchanHandleSession(data) { diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/wspr.js b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/wspr.js index 84da470..1674be9 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/wspr.js +++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/wspr.js @@ -255,8 +255,14 @@ if (wsprMessagesEl) { }); } -document.getElementById("wspr-decode-toggle-btn").addEventListener("click", async () => { - try { await postPath("/toggle_wspr_decode"); } catch (e) { console.error("WSPR toggle failed", e); } +const wsprDecodeToggleBtn = document.getElementById("wspr-decode-toggle-btn"); +wsprDecodeToggleBtn?.addEventListener("click", async () => { + try { + await window.takeSchedulerControlForDecoderDisable?.(wsprDecodeToggleBtn); + await postPath("/toggle_wspr_decode"); + } catch (e) { + console.error("WSPR toggle failed", e); + } }); document.getElementById("settings-clear-wspr-history")?.addEventListener("click", async () => {