[fix](trx-frontend-http): reset decoder state and virtual channels on rig switch

Broadcast virtual channel list for newly selected rig from select_rig so SSE
clients receive correct channels immediately. Detect rig changes in render()
and reset stale decoder state (RDS, spectrum, decoder status indicators) from
the previous rig.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
2026-03-21 15:58:20 +01:00
parent 49d9756fd1
commit 72465d14b3
2 changed files with 38 additions and 0 deletions
@@ -1608,6 +1608,32 @@ function resetRdsDisplay() {
updateRdsPsOverlay(primaryRds); updateRdsPsOverlay(primaryRds);
} }
function resetDecoderStateOnRigSwitch() {
// RDS
primaryRds = null;
vchanRdsById = new Map();
resetRdsDisplay();
resetWfmStereoIndicator();
// Spectrum — clear stale data from previous rig's SDR
lastSpectrumData = null;
window.lastSpectrumData = null;
lastSpectrumRenderData = null;
// Decoder status indicators
const decoderIds = ["ais-status", "vdes-status", "aprs-status", "cw-status", "ft8-status", "wspr-status"];
decoderIds.forEach((id) => {
const el = document.getElementById(id);
if (el) el.textContent = "--";
});
// FT8/FT4/WSPR history tables
if (typeof window.ft8ClearHistory === "function") window.ft8ClearHistory();
if (typeof window.ft4ClearHistory === "function") window.ft4ClearHistory();
if (typeof window.ft2ClearHistory === "function") window.ft2ClearHistory();
if (typeof window.wsprClearHistory === "function") window.wsprClearHistory();
}
function resetWfmStereoIndicator() { function resetWfmStereoIndicator() {
if (!wfmStFlagEl) return; if (!wfmStFlagEl) return;
wfmStFlagEl.textContent = "MO"; wfmStFlagEl.textContent = "MO";
@@ -2701,6 +2727,10 @@ function render(update) {
`trx-server hosted by <a href="https://qrzcq.com/call/${encodedCallsign}" target="_blank" rel="noopener">${safeCallsign}</a>`; `trx-server hosted by <a href="https://qrzcq.com/call/${encodedCallsign}" target="_blank" rel="noopener">${safeCallsign}</a>`;
} }
} }
// Detect rig switch and reset stale decoder state from the previous rig.
if (typeof update.active_rig_id === "string" && update.active_rig_id.length > 0 && update.active_rig_id !== lastActiveRigId) {
resetDecoderStateOnRigSwitch();
}
updateRigSubtitle(update.active_rig_id); updateRigSubtitle(update.active_rig_id);
if (ownerSubtitle) { if (ownerSubtitle) {
if (ownerCallsign) { if (ownerCallsign) {
@@ -1379,6 +1379,7 @@ pub struct SelectRigQuery {
pub async fn select_rig( pub async fn select_rig(
query: web::Query<SelectRigQuery>, query: web::Query<SelectRigQuery>,
context: web::Data<Arc<FrontendRuntimeContext>>, context: web::Data<Arc<FrontendRuntimeContext>>,
vchan_mgr: web::Data<Arc<ClientChannelManager>>,
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let rig_id = query.rig_id.trim(); let rig_id = query.rig_id.trim();
if rig_id.is_empty() { if rig_id.is_empty() {
@@ -1403,6 +1404,13 @@ pub async fn select_rig(
*active = Some(rig_id.to_string()); *active = Some(rig_id.to_string());
} }
// Broadcast the channel list for the newly selected rig so all SSE
// clients receive the correct virtual channels immediately.
let chans = vchan_mgr.channels(rig_id);
if let Ok(json) = serde_json::to_string(&chans) {
let _ = vchan_mgr.change_tx.send(format!("{rig_id}:{json}"));
}
Ok(HttpResponse::Ok().json(build_rig_list_payload(context.get_ref().as_ref()))) Ok(HttpResponse::Ok().json(build_rig_list_payload(context.get_ref().as_ref())))
} }