diff --git a/pulse-ui/src/lib.rs b/pulse-ui/src/lib.rs index 5725779..b448b45 100644 --- a/pulse-ui/src/lib.rs +++ b/pulse-ui/src/lib.rs @@ -1,6 +1,6 @@ -use std::any::Any; +use std::{any::Any, sync::Arc}; -use tokio::sync::mpsc; +use tokio::sync::{Mutex, MutexGuard, mpsc}; pub mod layout; pub mod render; @@ -44,3 +44,57 @@ impl AppHandler { } } } + +impl Context { + pub fn use_state(&self, v: T) -> State { + State { + value: Arc::new(Mutex::new(v)), + tx: self.tx.clone(), + } + } +} + +pub struct State { + pub value: Arc>, + tx: mpsc::Sender>, +} + +pub struct StateGuard<'a, T> { + is_mutated: bool, + value: MutexGuard<'a, T>, + tx: &'a mpsc::Sender>, +} + +impl State { + pub async fn lock<'a>(&'a self) -> StateGuard<'a, T> { + StateGuard { + value: self.value.lock().await, + is_mutated: false, + tx: &self.tx, + } + } +} + +impl<'a, T> std::ops::Deref for StateGuard<'a, T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.value + } +} + +impl<'a, T> std::ops::DerefMut for StateGuard<'a, T> { + fn deref_mut(&mut self) -> &mut Self::Target { + self.is_mutated = true; + + &mut self.value + } +} + +impl<'a, T> Drop for StateGuard<'a, T> { + fn drop(&mut self) { + if self.is_mutated { + self.tx.blocking_send(Box::new(Refresh)).unwrap() + } + } +}