fix subscriptions in events
This commit is contained in:
1 parent
07ed3e67dd
commit
a6f611eccf
12 files changed
+445
-103
No files matched your search
@@ -163,7 +163,7 @@ impl VirtualDom {
|
||||
let listener = unsafe { &*listener };
|
||||
match &listener.value {
|
||||
AttributeValue::Listener(l) => {
|
||||
_ = l.take();
|
||||
_ = l.callback.take();
|
||||
}
|
||||
AttributeValue::Any(a) => {
|
||||
_ = a.take();
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use std::{
|
||||
cell::{Cell, RefCell},
|
||||
rc::Rc,
|
||||
|
||||
};
|
||||
use crate::ScopeId;
|
||||
|
||||
/// A wrapper around some generic data that handles the event's state
|
||||
///
|
||||
@@ -134,13 +136,15 @@ impl<T: std::fmt::Debug> std::fmt::Debug for Event<T> {
|
||||
/// }
|
||||
///
|
||||
/// ```
|
||||
pub struct EventHandler<'bump, T = ()> {
|
||||
pub struct EventHandler<'bump, T:?Sized = ()> {
|
||||
pub(crate) origin: ScopeId,
|
||||
pub(super) callback: RefCell<Option<ExternalListenerCallback<'bump, T>>>,
|
||||
}
|
||||
|
||||
impl<T> Default for EventHandler<'_, T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
origin: ScopeId(0),
|
||||
callback: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{
|
||||
use crate::prelude::EventHandler;use crate::{
|
||||
any_props::AnyProps, arena::ElementId, Element, Event, LazyNodes, ScopeId, ScopeState,
|
||||
};
|
||||
use bumpalo::boxed::Box as BumpBox;
|
||||
@@ -476,7 +476,7 @@ pub enum AttributeValue<'a> {
|
||||
Bool(bool),
|
||||
|
||||
/// A listener, like "onclick"
|
||||
Listener(RefCell<Option<ListenerCb<'a>>>),
|
||||
Listener(EventHandler<'a, Event<dyn Any>>),
|
||||
|
||||
/// An arbitrary value that implements PartialEq and is static
|
||||
Any(RefCell<Option<BumpBox<'a, dyn AnyValue>>>),
|
||||
@@ -485,8 +485,6 @@ pub enum AttributeValue<'a> {
|
||||
None,
|
||||
}
|
||||
|
||||
pub type ListenerCb<'a> = BumpBox<'a, dyn FnMut(Event<dyn Any>) + 'a>;
|
||||
|
||||
/// Any of the built-in values that the Dioxus VirtualDom supports as dynamic attributes on elements that are borrowed
|
||||
///
|
||||
/// These varients are used to communicate what the value of an attribute is that needs to be updated
|
||||
|
||||
+10
-16
@@ -446,7 +446,7 @@ impl<'src> ScopeState {
|
||||
let handler: &mut dyn FnMut(T) = self.bump().alloc(f);
|
||||
let caller = unsafe { BumpBox::from_raw(handler as *mut dyn FnMut(T)) };
|
||||
let callback = RefCell::new(Some(caller));
|
||||
EventHandler { callback }
|
||||
EventHandler { callback, origin: self.context().id }
|
||||
}
|
||||
|
||||
/// Create a new [`AttributeValue`] with the listener variant from a callback
|
||||
@@ -456,22 +456,16 @@ impl<'src> ScopeState {
|
||||
&'src self,
|
||||
mut callback: impl FnMut(Event<T>) + 'src,
|
||||
) -> AttributeValue<'src> {
|
||||
// safety: there's no other way to create a dynamicly-dispatched bump box other than alloc + from-raw
|
||||
// This is the suggested way to build a bumpbox
|
||||
//
|
||||
// In theory, we could just use regular boxes
|
||||
let boxed: BumpBox<'src, dyn FnMut(_) + 'src> = unsafe {
|
||||
BumpBox::from_raw(self.bump().alloc(move |event: Event<dyn Any>| {
|
||||
if let Ok(data) = event.data.downcast::<T>() {
|
||||
callback(Event {
|
||||
propagates: event.propagates,
|
||||
data,
|
||||
});
|
||||
}
|
||||
}))
|
||||
};
|
||||
|
||||
|
||||
AttributeValue::Listener(RefCell::new(Some(boxed)))
|
||||
AttributeValue::Listener(self.event_handler(move |event: Event<dyn Any>| {
|
||||
if let Ok(data) = event.data.downcast::<T>() {
|
||||
callback(Event {
|
||||
propagates: event.propagates,
|
||||
data,
|
||||
});
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
/// Create a new [`AttributeValue`] with a value that implements [`AnyValue`]
|
||||
|
||||
@@ -391,9 +391,12 @@ impl VirtualDom {
|
||||
// We check the bubble state between each call to see if the event has been stopped from bubbling
|
||||
for listener in listeners.drain(..).rev() {
|
||||
if let AttributeValue::Listener(listener) = listener {
|
||||
if let Some(cb) = listener.borrow_mut().as_deref_mut() {
|
||||
let origin = listener.origin;
|
||||
self.runtime.scope_stack.borrow_mut().push(origin);
|
||||
if let Some(cb) = listener.callback.borrow_mut().as_deref_mut() {
|
||||
cb(uievent.clone());
|
||||
}
|
||||
self.runtime.scope_stack.borrow_mut().pop();
|
||||
|
||||
if !uievent.propagates.get() {
|
||||
return;
|
||||
@@ -422,9 +425,12 @@ impl VirtualDom {
|
||||
// Only call the listener if this is the exact target element.
|
||||
if attr.name.trim_start_matches("on") == name && target_path == this_path {
|
||||
if let AttributeValue::Listener(listener) = &attr.value {
|
||||
if let Some(cb) = listener.borrow_mut().as_deref_mut() {
|
||||
let origin = listener.origin;
|
||||
self.runtime.scope_stack.borrow_mut().push(origin);
|
||||
if let Some(cb) = listener.callback.borrow_mut().as_deref_mut() {
|
||||
cb(uievent.clone());
|
||||
}
|
||||
self.runtime.scope_stack.borrow_mut().pop();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user