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 45b36cf..2364aa0 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 @@ -3490,7 +3490,8 @@ async function switchRigFromSelect(selectEl) { if (typeof setSchedulerRig === "function") setSchedulerRig(lastActiveRigId); if (typeof setBackgroundDecodeRig === "function") setBackgroundDecodeRig(lastActiveRigId); if (typeof bmFetch === "function") bmFetch(document.getElementById("bm-category-filter")?.value || ""); - // Decode SSE and history are rig-independent — no reconnect needed. + // Reconnect decode stream so history + live messages filter to the new rig. + connectDecode(); // Switch this session's rig and reconnect SSE to the new rig's // state channel. try { @@ -4018,11 +4019,11 @@ if (spectrumBwSweetBtn) { } // --- Tab navigation --- -const TAB_ORDER = ["main", "bookmarks", "decoders", "map", "settings", "about"]; +const TAB_ORDER = ["main", "bookmarks", "digital-modes", "map", "settings", "about"]; const TAB_PATHS = { main: "/", bookmarks: "/bookmarks", - decoders: "/decoders", + "digital-modes": "/digital-modes", map: "/map", settings: "/settings", about: "/about", @@ -8196,6 +8197,7 @@ function updateDecodeStatus(text) { if (ft2 && ft2.textContent !== "Receiving") ft2.textContent = text; } function dispatchDecodeMessage(msg) { + if (lastActiveRigId && msg.rig_id && msg.rig_id !== lastActiveRigId) return; if (msg.type === "ais" && window.onServerAis) window.onServerAis(msg); if (msg.type === "vdes" && window.onServerVdes) window.onServerVdes(msg); if (msg.type === "aprs" && window.onServerAprs) window.onServerAprs(msg); @@ -8209,6 +8211,10 @@ function dispatchDecodeMessage(msg) { function dispatchDecodeBatch(batch) { if (!Array.isArray(batch) || batch.length === 0) return; + if (lastActiveRigId) { + batch = batch.filter((m) => !m.rig_id || m.rig_id === lastActiveRigId); + if (batch.length === 0) return; + } const type = String(batch[0]?.type || ""); const uniformType = batch.every((msg) => String(msg?.type || "") === type); if (uniformType) { @@ -8270,6 +8276,7 @@ function scheduleDecodeHistoryDrainStep(callback) { } function decodeHistoryUrl() { + if (lastActiveRigId) return "/decode/history?remote=" + encodeURIComponent(lastActiveRigId); return "/decode/history"; } diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html index 9a3dc37..fbcc1b7 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html +++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html @@ -39,9 +39,9 @@ Bookmarks - 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 9f9ac1d..7a05c5f 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 @@ -2617,7 +2617,7 @@ button:focus-visible, input:focus-visible, select:focus-visible { .tab-icon { display: block; } /* Shorten long tab labels to keep bottom nav compact */ .tab[data-tab="bookmarks"] .tab-label { font-size: 0.6rem; } - .tab[data-tab="decoders"] .tab-label { font-size: 0.6rem; } + .tab[data-tab="digital-modes"] .tab-label { font-size: 0.6rem; } .top-bar-actions { width: 100%; justify-content: flex-start; @@ -2639,7 +2639,7 @@ button:focus-visible, input:focus-visible, select:focus-visible { min-width: 0; } #tab-main, - #tab-decoders, + #tab-digital-modes, #tab-map, #tab-about { scroll-margin-top: 0.75rem; @@ -2917,7 +2917,7 @@ button:focus-visible, input:focus-visible, select:focus-visible { .bm-col-bw::before { content: "Bandwidth"; } .bm-col-loc::before { content: "Locator"; } .bm-col-cat::before { content: "Category"; } - .bm-col-dec::before { content: "Decoders"; } + .bm-col-dec::before { content: "Digital modes"; } .bm-col-cmt { grid-column: 1 / -1; } .bm-col-cmt::before { content: "Comment"; } .bm-col-act { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 0.4rem; padding-top: 0.25rem; } 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 9805a30..265dea8 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 @@ -1945,7 +1945,7 @@ pub async fn set_vchan_mode( pub fn configure(cfg: &mut web::ServiceConfig) { cfg.service(index) .service(map_index) - .service(decoders_index) + .service(digital_modes_index) .service(settings_index) .service(about_index) .service(status_api) @@ -2057,8 +2057,8 @@ async fn map_index() -> impl Responder { no_cache_response("text/html; charset=utf-8", status::index_html()) } -#[get("/decoders")] -async fn decoders_index() -> impl Responder { +#[get("/digital-modes")] +async fn digital_modes_index() -> impl Responder { no_cache_response("text/html; charset=utf-8", status::index_html()) } diff --git a/src/trx-client/trx-frontend/trx-frontend-http/src/auth.rs b/src/trx-client/trx-frontend/trx-frontend-http/src/auth.rs index 7ee2bbb..edafda7 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/src/auth.rs +++ b/src/trx-client/trx-frontend/trx-frontend-http/src/auth.rs @@ -477,7 +477,7 @@ impl RouteAccess { if path == "/" || path == "/index.html" || path == "/map" - || path == "/decoders" + || path == "/digital-modes" || path == "/settings" || path == "/about" || path.starts_with("/auth/") @@ -666,7 +666,10 @@ mod tests { fn test_route_access_public_paths() { assert_eq!(RouteAccess::from_path("/"), RouteAccess::Public); assert_eq!(RouteAccess::from_path("/map"), RouteAccess::Public); - assert_eq!(RouteAccess::from_path("/decoders"), RouteAccess::Public); + assert_eq!( + RouteAccess::from_path("/digital-modes"), + RouteAccess::Public + ); assert_eq!(RouteAccess::from_path("/settings"), RouteAccess::Public); assert_eq!(RouteAccess::from_path("/about"), RouteAccess::Public); assert_eq!(RouteAccess::from_path("/auth/login"), RouteAccess::Public);