diff --git a/Cargo.toml b/Cargo.toml index 6aec650..277c50a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ path = "src/main.rs" cc = "1.0" [dependencies] +access-cell = "0.1.3" crossterm = "0.28.1" figlet-rs = "0.1.5" osui-macros = { path = "macros" } diff --git a/src/component/context.rs b/src/component/context.rs index 0a1a75d..17c7a17 100644 --- a/src/component/context.rs +++ b/src/component/context.rs @@ -4,6 +4,8 @@ use std::{ sync::{Arc, Mutex}, }; +use access_cell::AccessCell; + use crate::{ component::EventHandler, engine::{Command, CommandExecutor}, @@ -15,9 +17,9 @@ use crate::{ use super::{scope::Scope, Component, ComponentImpl}; pub struct Context { - component: Mutex, + component: AccessCell, + view: AccessCell, event_handlers: Mutex>>, - view: Mutex, pub(crate) scopes: Mutex>>, executor: Arc, } @@ -28,45 +30,55 @@ impl Context { executor: Arc, ) -> Arc { Arc::new(Self { - component: Mutex::new(Arc::new(component)), + component: AccessCell::new(Arc::new(component)), + view: AccessCell::new(Arc::new(|_| {})), event_handlers: Mutex::new(HashMap::new()), - view: Mutex::new(Arc::new(|_| {})), scopes: Mutex::new(Vec::new()), executor, }) } pub fn refresh(self: &Arc) { - let s = self.clone(); - - std::thread::spawn({ - move || { - s.event_handlers.lock().unwrap().clear(); - let c = s.component.lock().unwrap().clone(); - *s.view.lock().unwrap() = c.call(&s); + self.event_handlers.lock().unwrap().clear(); + self.component.access({ + let s = self.clone(); + move |component| { + let component = component.clone(); + s.view.access({ + let s = s.clone(); + move |view| *view = component.call(&s) + }) } }); } - pub fn refresh_atomic(self: &Arc) -> Arc> { - let s = self.clone(); - let done = Arc::new(Mutex::new(false)); + pub fn refresh_sync(self: &Arc) { + self.event_handlers.lock().unwrap().clear(); - std::thread::spawn({ - let done = done.clone(); - move || { - s.event_handlers.lock().unwrap().clear(); - let c = s.component.lock().unwrap().clone(); - *s.view.lock().unwrap() = c.call(&s); - *done.lock().unwrap() = true; + let (tx, rx) = std::sync::mpsc::channel::<()>(); + + self.component.access({ + let s = self.clone(); + move |component| { + let component = component.clone(); + + s.view.access({ + let s = s.clone(); + let tx = tx.clone(); + move |view| { + *view = component.call(&s); + let _ = tx.send(()); // signal completion + } + }); } }); - done + // BLOCK until view closure finishes + let _ = rx.recv(); } pub fn get_view(self: &Arc) -> View { - self.view.lock().unwrap().clone() + self.view.access_ref().clone() } pub fn on_event, &T) + Send + Sync + 'static>(