fossdb-client 0.0.1

FossDB client
Documentation
use dioxus::prelude::*;
use futures::StreamExt;
use gloo_net::websocket::{futures::WebSocket, Message};
use std::cell::RefCell;
use std::rc::Rc;

#[derive(Clone, Copy)]
pub struct WebSocketState {
    pub connected: bool,
    pub reconnecting: bool,
}

pub fn use_websocket<T, F>(url: String, on_message: F)
where
    T: for<'de> serde::Deserialize<'de> + 'static,
    F: FnMut(T) + 'static,
{
    let mut state = use_signal(|| WebSocketState {
        connected: false,
        reconnecting: false,
    });

    let on_message = Rc::new(RefCell::new(on_message));

    use_effect(move || {
        let url = url.clone();
        let on_message = on_message.clone();

        spawn(async move {
            loop {
                state.write().reconnecting = true;

                match WebSocket::open(&url) {
                    Ok(mut ws) => {
                        state.write().connected = true;
                        state.write().reconnecting = false;

                        while let Some(msg) = ws.next().await {
                            match msg {
                                Ok(Message::Text(text)) => {
                                    if let Ok(data) = serde_json::from_str::<T>(&text) {
                                        (on_message.borrow_mut())(data);
                                    }
                                }
                                Ok(Message::Bytes(_)) => {}
                                Err(_) => {
                                    state.write().connected = false;
                                    break;
                                }
                            }
                        }

                        state.write().connected = false;
                    }
                    Err(_) => {
                        state.write().connected = false;
                        state.write().reconnecting = false;
                    }
                }

                gloo_timers::future::sleep(std::time::Duration::from_secs(5)).await;
            }
        });
    });
}