fix(ui): fall back to polling when websocket is unavailable

Poll the state endpoint while the WebSocket is not open so browsers that fail to establish the socket still receive initial state and continue updating the UI. Retain WebSocket streaming as the primary transport.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Steve Biedermann 2026-10-11 18:28:47 +02:00
parent 52277ae779
commit 2220a6eb3c
1 changed files with 20 additions and 1 deletions

View File

@ -17,13 +17,32 @@ pub fn connect(on_state: impl Fn(String) + 'static) {
let Some(loc) = web_sys::window().map(|w| w.location()) else { let Some(loc) = web_sys::window().map(|w| w.location()) else {
return; return;
}; };
let on_state = Rc::new(on_state);
let proto = if loc.protocol().is_ok_and(|p| p == "https:") { let proto = if loc.protocol().is_ok_and(|p| p == "https:") {
"wss" "wss"
} else { } else {
"ws" "ws"
}; };
let Ok(host) = loc.host() else { return }; let Ok(host) = loc.host() else { return };
open(format!("{proto}://{host}/ws"), Rc::new(on_state)); open(format!("{proto}://{host}/ws"), on_state.clone());
spawn_local(async move {
loop {
TimeoutFuture::new(1000).await;
let connected = SOCKET.with(|socket| {
socket
.borrow()
.as_ref()
.is_some_and(|socket| socket.ready_state() == WebSocket::OPEN)
});
if connected {
continue;
}
if let Some(state) = get_text("/api/state").await {
on_state(state);
}
}
});
} }
fn open(url: String, on_state: Rc<dyn Fn(String)>) { fn open(url: String, on_state: Rc<dyn Fn(String)>) {