fix: automatically reconnect after losing a WebSocket connection (#112)

This commit was merged in pull request #112.
This commit is contained in:
2026-01-23 19:32:12 +00:00
committed by Gitea

View File

@@ -1,6 +1,6 @@
use dioxus::{
CapturedError,
fullstack::{Loader, Loading, WebSocketOptions, use_websocket},
fullstack::{Loader, Loading, WebSocketOptions},
prelude::*,
};
use serde::{Serialize, de::DeserializeOwned};
@@ -13,6 +13,29 @@ use crate::{
},
};
fn use_on_document_become_visible(mut callback: impl FnMut() + 'static) {
let callback = use_callback(move |_| callback());
use_effect(move || {
spawn(async move {
let mut eval = document::eval(
r#"
document.addEventListener("visibilitychange", () => {
if (!document.hidden) {
dioxus.send(0);
}
});
"#,
);
loop {
eval.recv::<u8>()
.await
.expect("The JS code returned a value not parsable to `u8`.");
callback.call(());
}
});
});
}
#[allow(clippy::result_large_err)]
fn sort_loader_result<T: Ord + Clone>(
result: Result<Loader<Vec<T>>, Loading>,
@@ -34,17 +57,37 @@ where
E: Into<CapturedError> + 'static,
{
let mut refresh_tick = use_signal(|| 0u64);
let mut websocket_reset_tick = use_signal(|| 0u64);
let loader = use_loader(move || {
let _ = refresh_tick(); // Read => dependency.
future()
});
let mut socket = use_websocket(|| subscribe_to_updates(WebSocketOptions::default()));
use_future(move || async move {
while socket.recv().await.is_ok() {
refresh_tick += 1;
}
use_effect(move || {
let initial_websocket_reset_tick = websocket_reset_tick();
spawn(async move {
let Ok(socket) =
subscribe_to_updates(WebSocketOptions::new().with_automatic_reconnect()).await
else {
return;
};
while socket.recv().await.is_ok() {
if websocket_reset_tick() != initial_websocket_reset_tick {
// A new WebSocket has been created (a new task spawned), cleaning this one up.
break;
}
refresh_tick += 1;
}
});
});
/* So that when the device goes to sleep or suspends the app, the WebSocket gets recreated on
waking up. It is important to do this only on becoming visible (document.hidden == false),
because becoming hidden is the part when network may not work and thus cause errors. */
use_on_document_become_visible(move || {
websocket_reset_tick += 1;
refresh_tick += 1;
});
loader