#![warn(clippy::pedantic)]
use dioxus::{
hooks::UnboundedReceiver,
prelude::{use_coroutine, use_signal, Coroutine, Readable, ReadableRef, Signal, Writable},
};
use futures_util::StreamExt;
pub trait TeaModel: 'static + Default + Clone + PartialEq {
type Action;
fn update(&mut self, action: Self::Action);
}
#[derive(Clone, PartialEq)]
pub struct TeaModelSignal<T: TeaModel> {
inner: Signal<T>,
co: Coroutine<<T as TeaModel>::Action>,
}
impl<T: TeaModel> Copy for TeaModelSignal<T> {}
impl<T: TeaModel> TeaModelSignal<T> {
#[must_use]
pub fn read(&self) -> ReadableRef<Signal<T>> {
self.inner.read()
}
pub fn send(&self, action: T::Action) {
self.co.send(action);
}
}
#[must_use]
pub fn use_tea_model<T: TeaModel>() -> TeaModelSignal<T> {
let mut inner = use_signal(|| T::default());
let co = use_coroutine(move |mut rx: UnboundedReceiver<T::Action>| async move {
loop {
if let Some(action) = rx.next().await {
inner.with_mut(|me| {
me.update(action);
});
}
}
});
TeaModelSignal { inner, co }
}