Access cell in event handlers

This commit is contained in:
2026-01-31 14:19:37 +01:00
parent 17f78b86f4
commit ec320e47fd
2 changed files with 48 additions and 34 deletions
+37 -24
View File
@@ -19,7 +19,7 @@ use super::{scope::Scope, Component, ComponentImpl};
pub struct Context { pub struct Context {
component: AccessCell<Component>, component: AccessCell<Component>,
view: AccessCell<View>, view: AccessCell<View>,
event_handlers: Mutex<HashMap<TypeId, Vec<EventHandler>>>, event_handlers: AccessCell<HashMap<TypeId, Vec<EventHandler>>>,
pub(crate) scopes: Mutex<Vec<Arc<Scope>>>, pub(crate) scopes: Mutex<Vec<Arc<Scope>>>,
executor: Arc<dyn CommandExecutor>, executor: Arc<dyn CommandExecutor>,
} }
@@ -32,14 +32,15 @@ impl Context {
Arc::new(Self { Arc::new(Self {
component: AccessCell::new(Arc::new(component)), component: AccessCell::new(Arc::new(component)),
view: AccessCell::new(Arc::new(|_| {})), view: AccessCell::new(Arc::new(|_| {})),
event_handlers: Mutex::new(HashMap::new()), event_handlers: AccessCell::new(HashMap::new()),
scopes: Mutex::new(Vec::new()), scopes: Mutex::new(Vec::new()),
executor, executor,
}) })
} }
pub fn refresh(self: &Arc<Self>) { pub fn refresh(self: &Arc<Self>) {
self.event_handlers.lock().unwrap().clear(); self.event_handlers
.access(|event_handlers| event_handlers.clear());
self.component.access({ self.component.access({
let s = self.clone(); let s = self.clone();
move |component| { move |component| {
@@ -53,10 +54,11 @@ impl Context {
} }
pub fn refresh_sync(self: &Arc<Self>) { pub fn refresh_sync(self: &Arc<Self>) {
self.event_handlers.lock().unwrap().clear();
let (tx, rx) = std::sync::mpsc::channel::<()>(); let (tx, rx) = std::sync::mpsc::channel::<()>();
self.event_handlers
.access(|event_handlers| event_handlers.clear());
self.component.access({ self.component.access({
let s = self.clone(); let s = self.clone();
move |component| { move |component| {
@@ -85,30 +87,37 @@ impl Context {
self: &Arc<Self>, self: &Arc<Self>,
handler: F, handler: F,
) { ) {
self.event_handlers let new_handler: EventHandler = Arc::new(Mutex::new(
.lock() move |ctx: &Arc<Context>, event: &dyn Any| {
.unwrap()
.entry(TypeId::of::<T>())
.or_insert_with(|| Vec::new())
.push(Arc::new(Mutex::new(
move |ctx: &Arc<Self>, event: &dyn Any| {
if let Some(e) = event.downcast_ref::<T>() { if let Some(e) = event.downcast_ref::<T>() {
(handler)(ctx, e); (handler)(ctx, e);
} }
}, },
))); ));
self.event_handlers.access(|event_handlers| {
event_handlers
.entry(TypeId::of::<T>())
.or_insert_with(Vec::new)
.push(new_handler);
});
} }
pub fn emit_event<E: Any + 'static>(self: &Arc<Self>, event: &E) { pub fn emit_event<E: Send + Sync + Any + 'static>(self: &Arc<Self>, event: E) {
if let Some(v) = self.event_handlers.lock().unwrap().get(&TypeId::of::<E>()) { let event = Arc::new(event);
for i in v { let handlers_to_call: Vec<EventHandler> = {
(i.lock().unwrap())(self, event); let guard = self.event_handlers.access_ref();
} guard
.get(&TypeId::of::<E>())
.cloned()
.unwrap_or_default()
};
for h in &handlers_to_call {
(h.lock().unwrap())(self, event.as_ref());
} }
for scope in self.scopes.lock().unwrap().iter() { for scope in self.scopes.lock().unwrap().iter() {
for (child, _) in scope.children.lock().unwrap().iter() { for (child, _) in scope.children.lock().unwrap().iter() {
child.emit_event(event); child.emit_event(event.clone());
} }
} }
} }
@@ -117,16 +126,20 @@ impl Context {
self: &Arc<Self>, self: &Arc<Self>,
event: &E, event: &E,
) { ) {
if let Some(v) = self.event_handlers.lock().unwrap().get(&TypeId::of::<E>()) { let handlers_to_call: Vec<EventHandler> = {
for i in v { let guard = self.event_handlers.access_ref();
let i = i.clone(); guard
.get(&TypeId::of::<E>())
.cloned()
.unwrap_or_default()
};
for h in handlers_to_call {
let event = event.clone(); let event = event.clone();
let s = self.clone(); let s = self.clone();
std::thread::spawn(move || { std::thread::spawn(move || {
(i.lock().unwrap())(&s, &event); (h.lock().unwrap())(&s, &event);
}); });
} }
}
for scope in self.scopes.lock().unwrap().iter() { for scope in self.scopes.lock().unwrap().iter() {
for (child, _) in scope.children.lock().unwrap().iter() { for (child, _) in scope.children.lock().unwrap().iter() {
+3 -2
View File
@@ -192,7 +192,7 @@ pub fn use_sync_state<
pub fn use_sync_effect< pub fn use_sync_effect<
T: Send + Sync + 'static, T: Send + Sync + 'static,
Ev: 'static, Ev: Send + Sync + 'static,
E: Fn(&State<T>) -> Ev + Send + Sync + 'static, E: Fn(&State<T>) -> Ev + Send + Sync + 'static,
>( >(
cx: &Arc<Context>, cx: &Arc<Context>,
@@ -205,7 +205,8 @@ pub fn use_sync_effect<
let state = state.clone(); let state = state.clone();
let cx = cx.clone(); let cx = cx.clone();
move || { move || {
cx.emit_event(&encoder(&state)); let ev = encoder(&state);
cx.emit_event(ev);
} }
}, },
deps, deps,