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 1ef0f52..261ffe1 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
@@ -1608,6 +1608,32 @@ function resetRdsDisplay() {
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() {
if (!wfmStFlagEl) return;
wfmStFlagEl.textContent = "MO";
@@ -2701,6 +2727,10 @@ function render(update) {
`trx-server hosted by ${safeCallsign}`;
}
}
+ // 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);
if (ownerSubtitle) {
if (ownerCallsign) {
diff --git a/src/trx-client/trx-frontend/trx-frontend-http/src/api.rs b/src/trx-client/trx-frontend/trx-frontend-http/src/api.rs
index 63b6e6a..3eb7651 100644
--- a/src/trx-client/trx-frontend/trx-frontend-http/src/api.rs
+++ b/src/trx-client/trx-frontend/trx-frontend-http/src/api.rs
@@ -1379,6 +1379,7 @@ pub struct SelectRigQuery {
pub async fn select_rig(
query: web::Query,
context: web::Data>,
+ vchan_mgr: web::Data>,
) -> Result {
let rig_id = query.rig_id.trim();
if rig_id.is_empty() {
@@ -1403,6 +1404,13 @@ pub async fn select_rig(
*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())))
}