[fix](trx-rs): frost main view on trx-server disconnect

Nudge state watch when server_connected goes false so SSE delivers the change. Frontend applies a desaturated frost + banner instead of a blocking overlay, keeping the last-known state visible.

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-26 20:28:56 +01:00
parent c8de54d85e
commit caa7603489
4 changed files with 41 additions and 2 deletions
+2
View File
@@ -109,6 +109,8 @@ pub async fn run_remote_client(
warn!("Remote connection dropped: {}", e);
}
config.server_connected.store(false, Ordering::Relaxed);
// Nudge the state watch so SSE clients see server_connected=false.
state_tx.send_modify(|_| {});
}
Ok(Err(e)) => {
warn!("Remote connect failed: {}", e);
@@ -3381,6 +3381,8 @@ function connect() {
lastEventAt = Date.now();
es.onopen = () => {
setConnLostOverlay(false);
const tm = document.getElementById("tab-main");
if (tm) tm.classList.remove("server-disconnected");
if (!aboutUptimeStart) aboutUptimeStart = Date.now();
pollFreshSnapshot();
refreshRigList();
@@ -3392,11 +3394,12 @@ function connect() {
lastRendered = evt.data;
render(data);
lastEventAt = Date.now();
const tabMain = document.getElementById("tab-main");
if (data.server_connected === false) {
powerHint.textContent = "trx-server connection lost";
setConnLostOverlay(true, "trx-server connection lost", "trx-client is running but cannot reach the radio server");
if (tabMain) tabMain.classList.add("server-disconnected");
} else {
setConnLostOverlay(false);
if (tabMain) tabMain.classList.remove("server-disconnected");
if (data.initialized) powerHint.textContent = readyText();
}
} catch (e) {
@@ -96,6 +96,7 @@
<div id="auth-role" style="margin-top: 1rem; color: var(--text-muted); font-size: 0.85rem; display: none;"></div>
</div>
<div id="tab-main" class="tab-panel">
<div id="server-lost-banner" aria-live="assertive"><span class="banner-dot"></span>trx-server connection lost — waiting for reconnect</div>
<div id="loading" style="text-align:center; padding:2rem 0;">
<div id="loading-title" style="margin-bottom:0.4rem; font-size:1.1rem; font-weight:600;">Initializing (rig)…</div>
<div id="loading-sub" style="color:#9aa4b5;"></div>
@@ -1431,6 +1431,39 @@ small { color: var(--text-muted); }
position: fixed;
border-radius: 0;
}
#server-lost-banner {
display: none;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 0.45rem 0.75rem;
background: color-mix(in srgb, var(--accent-red) 18%, var(--card-bg));
border: 1px solid color-mix(in srgb, var(--accent-red) 40%, var(--border));
border-radius: 0.4rem;
color: var(--accent-red);
font-size: 0.82rem;
font-weight: 600;
margin-bottom: 0.5rem;
}
#server-lost-banner .banner-dot {
width: 7px; height: 7px; border-radius: 50%;
background: var(--accent-red);
animation: banner-pulse 1.5s ease-in-out infinite;
}
@keyframes banner-pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.3; }
}
#tab-main.server-disconnected #content {
pointer-events: none;
filter: saturate(0.3) brightness(0.7);
opacity: 0.55;
transition: filter 0.4s ease, opacity 0.4s ease;
}
#tab-main.server-disconnected #server-lost-banner { display: flex; }
#tab-main:not(.server-disconnected) #content {
transition: filter 0.3s ease, opacity 0.3s ease;
}
.decode-history-overlay-card {
min-width: min(26rem, calc(100vw - 2.4rem));
max-width: min(30rem, calc(100vw - 2.4rem));