mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-27 06:30:20 +00:00
wip: more overhaul on virtualevents
This commit is contained in:
parent
cef116aa3a
commit
41cc42919d
10 changed files with 165 additions and 181 deletions
|
@ -251,7 +251,7 @@ impl<'bump> DiffMachine<'bump> {
|
|||
fn create_suspended_node(&mut self, suspended: &'bump VSuspended) {
|
||||
let real_id = self.vdom.reserve_node();
|
||||
self.mutations.create_placeholder(real_id);
|
||||
suspended.node.set(Some(real_id));
|
||||
suspended.dom_id.set(Some(real_id));
|
||||
self.stack.add_child_count(1);
|
||||
}
|
||||
|
||||
|
@ -372,7 +372,7 @@ impl<'bump> DiffMachine<'bump> {
|
|||
(Component(old), Component(new)) => self.diff_component_nodes(old, new),
|
||||
(Fragment(old), Fragment(new)) => self.diff_fragment_nodes(old, new),
|
||||
(Anchor(old), Anchor(new)) => new.dom_id.set(old.dom_id.get()),
|
||||
(Suspended(old), Suspended(new)) => new.node.set(old.node.get()),
|
||||
(Suspended(old), Suspended(new)) => new.dom_id.set(old.dom_id.get()),
|
||||
(Element(old), Element(new)) => self.diff_element_nodes(old, new),
|
||||
|
||||
// Anything else is just a basic replace and create
|
||||
|
@ -952,7 +952,7 @@ impl<'bump> DiffMachine<'bump> {
|
|||
match &search_node.take().unwrap() {
|
||||
VNode::Text(t) => break t.dom_id.get(),
|
||||
VNode::Element(t) => break t.dom_id.get(),
|
||||
VNode::Suspended(t) => break t.node.get(),
|
||||
VNode::Suspended(t) => break t.dom_id.get(),
|
||||
VNode::Anchor(t) => break t.dom_id.get(),
|
||||
|
||||
VNode::Fragment(frag) => {
|
||||
|
@ -983,7 +983,7 @@ impl<'bump> DiffMachine<'bump> {
|
|||
}
|
||||
VNode::Text(t) => break t.dom_id.get(),
|
||||
VNode::Element(t) => break t.dom_id.get(),
|
||||
VNode::Suspended(t) => break t.node.get(),
|
||||
VNode::Suspended(t) => break t.dom_id.get(),
|
||||
VNode::Anchor(t) => break t.dom_id.get(),
|
||||
}
|
||||
}
|
||||
|
@ -1016,7 +1016,7 @@ impl<'bump> DiffMachine<'bump> {
|
|||
});
|
||||
}
|
||||
VNode::Suspended(s) => {
|
||||
s.node.get().map(|id| {
|
||||
s.dom_id.get().map(|id| {
|
||||
self.mutations.remove(id.as_u64());
|
||||
self.vdom.collect_garbage(id);
|
||||
});
|
||||
|
|
|
@ -3,16 +3,7 @@
|
|||
//!
|
||||
//! 3rd party renderers are responsible for converting their native events into these virtual event types. Events might
|
||||
//! be heavy or need to interact through FFI, so the events themselves are designed to be lazy.
|
||||
|
||||
use std::{
|
||||
cell::{Cell, RefCell},
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
innerlude::{ElementId, ScopeId},
|
||||
VNode,
|
||||
};
|
||||
use crate::innerlude::{ElementId, ScopeId};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct EventTrigger {
|
||||
|
@ -23,12 +14,15 @@ pub struct EventTrigger {
|
|||
pub mounted_dom_id: Option<ElementId>,
|
||||
|
||||
/// The type of event
|
||||
pub event: VirtualEvent,
|
||||
pub event: SyntheticEvent,
|
||||
|
||||
/// Is consistency important for this event?
|
||||
/// UI events are the only events where consistency is important.
|
||||
/// All else may be batched.
|
||||
pub discrete: bool,
|
||||
}
|
||||
|
||||
pub enum VirtualEvent {
|
||||
pub enum SyntheticEvent {
|
||||
KeyboardEvent(on::KeyboardEvent),
|
||||
TouchEvent(on::TouchEvent),
|
||||
MouseEvent(on::MouseEvent),
|
||||
|
@ -47,24 +41,24 @@ pub enum VirtualEvent {
|
|||
// ImageEvent(event_data::ImageEvent),
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for VirtualEvent {
|
||||
impl std::fmt::Debug for SyntheticEvent {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let name = match self {
|
||||
VirtualEvent::ClipboardEvent(_) => "ClipboardEvent",
|
||||
VirtualEvent::CompositionEvent(_) => "CompositionEvent",
|
||||
VirtualEvent::KeyboardEvent(_) => "KeyboardEvent",
|
||||
VirtualEvent::FocusEvent(_) => "FocusEvent",
|
||||
VirtualEvent::FormEvent(_) => "FormEvent",
|
||||
VirtualEvent::SelectionEvent(_) => "SelectionEvent",
|
||||
VirtualEvent::TouchEvent(_) => "TouchEvent",
|
||||
VirtualEvent::UIEvent(_) => "UIEvent",
|
||||
VirtualEvent::WheelEvent(_) => "WheelEvent",
|
||||
VirtualEvent::MediaEvent(_) => "MediaEvent",
|
||||
VirtualEvent::AnimationEvent(_) => "AnimationEvent",
|
||||
VirtualEvent::TransitionEvent(_) => "TransitionEvent",
|
||||
VirtualEvent::ToggleEvent(_) => "ToggleEvent",
|
||||
VirtualEvent::MouseEvent(_) => "MouseEvent",
|
||||
VirtualEvent::PointerEvent(_) => "PointerEvent",
|
||||
SyntheticEvent::ClipboardEvent(_) => "ClipboardEvent",
|
||||
SyntheticEvent::CompositionEvent(_) => "CompositionEvent",
|
||||
SyntheticEvent::KeyboardEvent(_) => "KeyboardEvent",
|
||||
SyntheticEvent::FocusEvent(_) => "FocusEvent",
|
||||
SyntheticEvent::FormEvent(_) => "FormEvent",
|
||||
SyntheticEvent::SelectionEvent(_) => "SelectionEvent",
|
||||
SyntheticEvent::TouchEvent(_) => "TouchEvent",
|
||||
SyntheticEvent::UIEvent(_) => "UIEvent",
|
||||
SyntheticEvent::WheelEvent(_) => "WheelEvent",
|
||||
SyntheticEvent::MediaEvent(_) => "MediaEvent",
|
||||
SyntheticEvent::AnimationEvent(_) => "AnimationEvent",
|
||||
SyntheticEvent::TransitionEvent(_) => "TransitionEvent",
|
||||
SyntheticEvent::ToggleEvent(_) => "ToggleEvent",
|
||||
SyntheticEvent::MouseEvent(_) => "MouseEvent",
|
||||
SyntheticEvent::PointerEvent(_) => "PointerEvent",
|
||||
};
|
||||
|
||||
f.debug_struct("VirtualEvent").field("type", &name).finish()
|
||||
|
@ -90,7 +84,7 @@ pub mod on {
|
|||
};
|
||||
use std::cell::Cell;
|
||||
|
||||
use super::VirtualEvent;
|
||||
use super::SyntheticEvent;
|
||||
|
||||
macro_rules! event_directory {
|
||||
( $(
|
||||
|
@ -126,12 +120,12 @@ pub mod on {
|
|||
{
|
||||
let bump = &c.bump();
|
||||
|
||||
let cb: &mut dyn FnMut(VirtualEvent) = bump.alloc(move |evt: VirtualEvent| match evt {
|
||||
VirtualEvent::$wrapper(event) => callback(event),
|
||||
_ => unreachable!("Downcasted VirtualEvent to wrong event type - this is an internal bug!")
|
||||
let cb: &mut dyn FnMut(SyntheticEvent) = bump.alloc(move |evt: SyntheticEvent| match evt {
|
||||
SyntheticEvent::$wrapper(event) => callback(event),
|
||||
_ => unreachable!("Downcasted SyntheticEvent to wrong event type - this is an internal bug!")
|
||||
});
|
||||
|
||||
let callback: BumpBox<dyn FnMut(VirtualEvent) + 'a> = unsafe { BumpBox::from_raw(cb) };
|
||||
let callback: BumpBox<dyn FnMut(SyntheticEvent) + 'a> = unsafe { BumpBox::from_raw(cb) };
|
||||
|
||||
let event_name = stringify!($name);
|
||||
let shortname: &'static str = &event_name[2..];
|
||||
|
|
|
@ -126,14 +126,7 @@ where
|
|||
let handle = cx.submit_task(Box::pin(task_fut.then(move |output| async move {
|
||||
*slot.as_ref().borrow_mut() = Some(output);
|
||||
updater(update_id);
|
||||
EventTrigger {
|
||||
event: VirtualEvent::AsyncEvent {
|
||||
should_rerender: false,
|
||||
},
|
||||
scope: originator,
|
||||
priority: EventPriority::Low,
|
||||
mounted_dom_id: None,
|
||||
}
|
||||
originator
|
||||
})));
|
||||
|
||||
TaskHook {
|
||||
|
@ -172,71 +165,75 @@ where
|
|||
Out: 'static,
|
||||
Cb: for<'a> Fn(SuspendedContext<'a>, &Out) -> DomTree<'a> + 'static,
|
||||
{
|
||||
/*
|
||||
General strategy:
|
||||
- Create a slot for the future to dump its output into
|
||||
- Create a new future feeding off the user's future that feeds the output into that slot
|
||||
- Submit that future as a task
|
||||
- Take the task handle id and attach that to our suspended node
|
||||
- when the hook runs, check if the value exists
|
||||
- if it does, then we can render the node directly
|
||||
- if it doesn't, then we render a suspended node along with with the callback and task id
|
||||
*/
|
||||
cx.use_hook(
|
||||
move |hook_idx| {
|
||||
let value = Rc::new(RefCell::new(None));
|
||||
|
||||
let dom_node_id = Rc::new(empty_cell());
|
||||
let domnode = dom_node_id.clone();
|
||||
|
||||
let slot = value.clone();
|
||||
|
||||
let callback: SuspendedCallback = Box::new(move |ctx: SuspendedContext| {
|
||||
let v: std::cell::Ref<Option<Box<dyn Any>>> = slot.as_ref().borrow();
|
||||
match v.as_ref() {
|
||||
Some(a) => {
|
||||
let v: &dyn Any = a.as_ref();
|
||||
let real_val = v.downcast_ref::<Out>().unwrap();
|
||||
user_callback(ctx, real_val)
|
||||
}
|
||||
None => {
|
||||
//
|
||||
Some(VNode::Suspended(VSuspended {
|
||||
node: domnode.clone(),
|
||||
}))
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let originator = cx.scope.our_arena_idx.clone();
|
||||
let task_fut = task_initializer();
|
||||
let domnode = dom_node_id.clone();
|
||||
|
||||
let slot = value.clone();
|
||||
cx.submit_task(Box::pin(task_fut.then(move |output| async move {
|
||||
// When the new value arrives, set the hooks internal slot
|
||||
// Dioxus will call the user's callback to generate new nodes outside of the diffing system
|
||||
*slot.borrow_mut() = Some(Box::new(output) as Box<dyn Any>);
|
||||
EventTrigger {
|
||||
event: VirtualEvent::SuspenseEvent { hook_idx, domnode },
|
||||
scope: originator,
|
||||
priority: EventPriority::Low,
|
||||
mounted_dom_id: None,
|
||||
}
|
||||
})));
|
||||
let handle = cx.submit_task(Box::pin(task_initializer().then(
|
||||
move |output| async move {
|
||||
*slot.borrow_mut() = Some(Box::new(output) as Box<dyn Any>);
|
||||
originator
|
||||
},
|
||||
)));
|
||||
|
||||
SuspenseHook {
|
||||
value,
|
||||
callback,
|
||||
dom_node_id,
|
||||
}
|
||||
SuspenseHook { handle, value }
|
||||
},
|
||||
move |hook| {
|
||||
let cx = Context {
|
||||
scope: &cx.scope,
|
||||
props: &(),
|
||||
};
|
||||
let csx = SuspendedContext { inner: cx };
|
||||
(&hook.callback)(csx)
|
||||
move |hook| match hook.value.borrow().as_ref() {
|
||||
Some(value) => {
|
||||
let out = value.downcast_ref::<Out>().unwrap();
|
||||
let sus = SuspendedContext {
|
||||
inner: Context {
|
||||
props: &(),
|
||||
scope: cx.scope,
|
||||
},
|
||||
};
|
||||
user_callback(sus, out)
|
||||
}
|
||||
None => {
|
||||
let value = hook.value.clone();
|
||||
|
||||
cx.render(LazyNodes::new(|f| {
|
||||
let bump = f.bump();
|
||||
let g: &dyn FnOnce(SuspendedContext<'src>) -> DomTree<'src> =
|
||||
bump.alloc(|sus| {
|
||||
let out = value
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
.downcast_ref::<Out>()
|
||||
.unwrap();
|
||||
user_callback(sus, out)
|
||||
});
|
||||
|
||||
VNode::Suspended(bump.alloc(VSuspended {
|
||||
dom_id: empty_cell(),
|
||||
task_id: hook.handle.our_id,
|
||||
callback: RefCell::new(Some(g)),
|
||||
}))
|
||||
}))
|
||||
}
|
||||
},
|
||||
|_| {},
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) struct SuspenseHook {
|
||||
pub handle: TaskHandle,
|
||||
pub value: Rc<RefCell<Option<Box<dyn Any>>>>,
|
||||
pub callback: SuspendedCallback,
|
||||
pub dom_node_id: Rc<Cell<Option<ElementId>>>,
|
||||
}
|
||||
type SuspendedCallback = Box<dyn for<'a> Fn(SuspendedContext<'a>) -> DomTree<'a>>;
|
||||
pub struct SuspendedContext<'a> {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
pub use crate::innerlude::{
|
||||
format_args_f, html, rsx, Context, DiffInstruction, DioxusElement, DomEdit, DomTree, ElementId,
|
||||
EventPriority, EventTrigger, LazyNodes, MountType, Mutations, NodeFactory, Properties, ScopeId,
|
||||
SuspendedContext, VNode, VirtualDom, VirtualEvent, FC,
|
||||
SuspendedContext, SyntheticEvent, VNode, VirtualDom, FC,
|
||||
};
|
||||
|
||||
pub mod prelude {
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
//!
|
||||
//! These VNodes should be *very* cheap and *very* fast to construct - building a full tree should be insanely quick.
|
||||
use crate::{
|
||||
events::VirtualEvent,
|
||||
events::SyntheticEvent,
|
||||
innerlude::{empty_cell, Context, DomTree, ElementId, Properties, Scope, ScopeId, FC},
|
||||
SuspendedContext,
|
||||
};
|
||||
use bumpalo::{boxed::Box as BumpBox, Bump};
|
||||
use std::{
|
||||
|
@ -30,7 +31,7 @@ pub enum VNode<'src> {
|
|||
|
||||
Component(&'src VComponent<'src>),
|
||||
|
||||
Suspended(VSuspended),
|
||||
Suspended(&'src VSuspended<'src>),
|
||||
|
||||
Anchor(VAnchor),
|
||||
}
|
||||
|
@ -127,7 +128,7 @@ pub struct Listener<'bump> {
|
|||
|
||||
pub mounted_node: Cell<Option<ElementId>>,
|
||||
|
||||
pub(crate) callback: RefCell<Option<BumpBox<'bump, dyn FnMut(VirtualEvent) + 'bump>>>,
|
||||
pub(crate) callback: RefCell<Option<BumpBox<'bump, dyn FnMut(SyntheticEvent) + 'bump>>>,
|
||||
}
|
||||
|
||||
impl Listener<'_> {
|
||||
|
@ -168,8 +169,10 @@ pub struct VComponent<'src> {
|
|||
pub(crate) user_fc: *const (),
|
||||
}
|
||||
|
||||
pub struct VSuspended {
|
||||
pub node: Rc<Cell<Option<ElementId>>>,
|
||||
pub struct VSuspended<'a> {
|
||||
pub dom_id: Cell<Option<ElementId>>,
|
||||
pub task_id: u64,
|
||||
pub callback: RefCell<Option<&'a dyn FnOnce(SuspendedContext<'a>) -> DomTree<'a>>>,
|
||||
}
|
||||
|
||||
/// This struct provides an ergonomic API to quickly build VNodes.
|
||||
|
@ -301,12 +304,6 @@ impl<'a> NodeFactory<'a> {
|
|||
}))
|
||||
}
|
||||
|
||||
pub fn suspended() -> VNode<'static> {
|
||||
VNode::Suspended(VSuspended {
|
||||
node: Rc::new(empty_cell()),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn attr(
|
||||
&self,
|
||||
name: &'static str,
|
||||
|
|
|
@ -34,7 +34,7 @@ pub struct EventChannel {
|
|||
|
||||
pub enum SchedulerMsg {
|
||||
Immediate(ScopeId),
|
||||
UiEvent(),
|
||||
UiEvent(EventTrigger),
|
||||
SubmitTask(u64),
|
||||
ToggleTask(u64),
|
||||
PauseTask(u64),
|
||||
|
@ -232,16 +232,6 @@ impl Scheduler {
|
|||
id
|
||||
}
|
||||
|
||||
pub fn make_trigger_key(&self, trigger: &EventTrigger) -> EventKey {
|
||||
let height = self.get_scope(trigger.scope).map(|f| f.height).unwrap();
|
||||
|
||||
EventKey {
|
||||
height,
|
||||
originator: trigger.scope,
|
||||
priority: trigger.priority,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clean_up_garbage(&mut self) {
|
||||
let mut scopes_to_kill = Vec::new();
|
||||
let mut garbage_list = Vec::new();
|
||||
|
@ -330,11 +320,11 @@ impl Scheduler {
|
|||
pub fn consume_pending_events(&mut self) -> Result<()> {
|
||||
while let Some(trigger) = self.pending_events.pop_back() {
|
||||
match &trigger.event {
|
||||
VirtualEvent::AsyncEvent { .. } => {}
|
||||
SyntheticEvent::AsyncEvent { .. } => {}
|
||||
|
||||
// This suspense system works, but it's not the most elegant solution.
|
||||
// TODO: Replace this system
|
||||
VirtualEvent::SuspenseEvent { hook_idx, domnode } => {
|
||||
SyntheticEvent::SuspenseEvent { hook_idx, domnode } => {
|
||||
todo!("suspense needs to be converted into its own channel");
|
||||
|
||||
// // Safety: this handler is the only thing that can mutate shared items at this moment in tim
|
||||
|
@ -369,21 +359,21 @@ impl Scheduler {
|
|||
// }
|
||||
}
|
||||
|
||||
VirtualEvent::ClipboardEvent(_)
|
||||
| VirtualEvent::CompositionEvent(_)
|
||||
| VirtualEvent::KeyboardEvent(_)
|
||||
| VirtualEvent::FocusEvent(_)
|
||||
| VirtualEvent::FormEvent(_)
|
||||
| VirtualEvent::SelectionEvent(_)
|
||||
| VirtualEvent::TouchEvent(_)
|
||||
| VirtualEvent::UIEvent(_)
|
||||
| VirtualEvent::WheelEvent(_)
|
||||
| VirtualEvent::MediaEvent(_)
|
||||
| VirtualEvent::AnimationEvent(_)
|
||||
| VirtualEvent::TransitionEvent(_)
|
||||
| VirtualEvent::ToggleEvent(_)
|
||||
| VirtualEvent::MouseEvent(_)
|
||||
| VirtualEvent::PointerEvent(_) => {
|
||||
SyntheticEvent::ClipboardEvent(_)
|
||||
| SyntheticEvent::CompositionEvent(_)
|
||||
| SyntheticEvent::KeyboardEvent(_)
|
||||
| SyntheticEvent::FocusEvent(_)
|
||||
| SyntheticEvent::FormEvent(_)
|
||||
| SyntheticEvent::SelectionEvent(_)
|
||||
| SyntheticEvent::TouchEvent(_)
|
||||
| SyntheticEvent::UIEvent(_)
|
||||
| SyntheticEvent::WheelEvent(_)
|
||||
| SyntheticEvent::MediaEvent(_)
|
||||
| SyntheticEvent::AnimationEvent(_)
|
||||
| SyntheticEvent::TransitionEvent(_)
|
||||
| SyntheticEvent::ToggleEvent(_)
|
||||
| SyntheticEvent::MouseEvent(_)
|
||||
| SyntheticEvent::PointerEvent(_) => {
|
||||
if let Some(scope) = self.get_scope_mut(trigger.scope) {
|
||||
if let Some(element) = trigger.mounted_dom_id {
|
||||
scope.call_listener(trigger.event, element)?;
|
||||
|
@ -528,8 +518,8 @@ impl Scheduler {
|
|||
}
|
||||
|
||||
pub struct TaskHandle {
|
||||
channel: EventChannel,
|
||||
our_id: u64,
|
||||
pub channel: EventChannel,
|
||||
pub our_id: u64,
|
||||
}
|
||||
|
||||
impl TaskHandle {
|
||||
|
|
|
@ -40,6 +40,8 @@ pub struct Scope {
|
|||
pub(crate) listeners: RefCell<Vec<*const Listener<'static>>>,
|
||||
pub(crate) borrowed_props: RefCell<Vec<*const VComponent<'static>>>,
|
||||
|
||||
pub(crate) suspended_nodes: RefCell<HashMap<u64, *const VNode<'static>>>,
|
||||
|
||||
// State
|
||||
pub(crate) hooks: HookList,
|
||||
pub(crate) shared_contexts: RefCell<HashMap<TypeId, Rc<dyn Any>>>,
|
||||
|
@ -52,8 +54,9 @@ pub struct Scope {
|
|||
// The type of closure that wraps calling components
|
||||
pub type WrappedCaller = dyn for<'b> Fn(&'b Scope) -> DomTree<'b>;
|
||||
|
||||
// The type of task that gets sent to the task scheduler
|
||||
pub type FiberTask = Pin<Box<dyn Future<Output = EventTrigger>>>;
|
||||
/// The type of task that gets sent to the task scheduler
|
||||
/// Submitting a fiber task returns a handle to that task, which can be used to wake up suspended nodes
|
||||
pub type FiberTask = Pin<Box<dyn Future<Output = ScopeId>>>;
|
||||
|
||||
impl Scope {
|
||||
// we are being created in the scope of an existing component (where the creator_node lifetime comes into play)
|
||||
|
@ -91,6 +94,7 @@ impl Scope {
|
|||
height,
|
||||
frames: ActiveFrame::new(),
|
||||
hooks: Default::default(),
|
||||
suspended_nodes: Default::default(),
|
||||
shared_contexts: Default::default(),
|
||||
listeners: Default::default(),
|
||||
borrowed_props: Default::default(),
|
||||
|
@ -194,7 +198,11 @@ impl Scope {
|
|||
// A safe wrapper around calling listeners
|
||||
//
|
||||
//
|
||||
pub(crate) fn call_listener(&mut self, event: VirtualEvent, element: ElementId) -> Result<()> {
|
||||
pub(crate) fn call_listener(
|
||||
&mut self,
|
||||
event: SyntheticEvent,
|
||||
element: ElementId,
|
||||
) -> Result<()> {
|
||||
let listners = self.listeners.borrow_mut();
|
||||
|
||||
let raw_listener = listners.iter().find(|lis| {
|
||||
|
|
|
@ -100,24 +100,31 @@ impl VirtualDom {
|
|||
///
|
||||
/// Note: the VirtualDOM is not progressed, you must either "run_with_deadline" or use "rebuild" to progress it.
|
||||
pub fn new_with_props<P: Properties + 'static>(root: FC<P>, root_props: P) -> Self {
|
||||
let components = Scheduler::new();
|
||||
let scheduler = Scheduler::new();
|
||||
|
||||
let root_props: Pin<Box<dyn Any>> = Box::pin(root_props);
|
||||
let props_ptr = root_props.as_ref().downcast_ref::<P>().unwrap() as *const P;
|
||||
let _root_props: Pin<Box<dyn Any>> = Box::pin(root_props);
|
||||
let _root_prop_type = TypeId::of::<P>();
|
||||
|
||||
let update_sender = components.immediate_sender.clone();
|
||||
let props_ptr = _root_props.as_ref().downcast_ref::<P>().unwrap() as *const P;
|
||||
|
||||
let base_scope = components.insert_scope_with_key(move |myidx| {
|
||||
let base_scope = scheduler.insert_scope_with_key(|myidx| {
|
||||
let caller = NodeFactory::create_component_caller(root, props_ptr as *const _);
|
||||
let name = type_name_of(root);
|
||||
Scope::new(caller, myidx, None, 0, ScopeChildren(&[]), update_sender)
|
||||
Scope::new(
|
||||
caller,
|
||||
myidx,
|
||||
None,
|
||||
0,
|
||||
ScopeChildren(&[]),
|
||||
scheduler.channel.clone(),
|
||||
)
|
||||
});
|
||||
|
||||
Self {
|
||||
base_scope,
|
||||
_root_props: root_props,
|
||||
scheduler: components,
|
||||
_root_prop_type: TypeId::of::<P>(),
|
||||
_root_props,
|
||||
scheduler,
|
||||
_root_prop_type,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,15 +225,6 @@ impl VirtualDom {
|
|||
// .expect("this future will always resolve immediately")
|
||||
}
|
||||
|
||||
/// Runs the virtualdom with no time limit.
|
||||
///
|
||||
/// If there are pending tasks, they will be progressed before returning. This is useful when rendering an application
|
||||
/// that has suspended nodes or suspended tasks. Be warned - any async tasks running forever will prevent this method
|
||||
/// from completing. Consider using `run` and specifing a deadline.
|
||||
pub async fn run_unbounded<'s>(&'s mut self) -> Mutations<'s> {
|
||||
self.run_with_deadline(async {}).await.unwrap()
|
||||
}
|
||||
|
||||
/// Run the virtualdom with a deadline.
|
||||
///
|
||||
/// This method will progress async tasks until the deadline is reached. If tasks are completed before the deadline,
|
||||
|
@ -327,8 +325,8 @@ impl VirtualDom {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_event_sender(&self) -> futures_channel::mpsc::UnboundedSender<EventTrigger> {
|
||||
self.scheduler.ui_event_sender.clone()
|
||||
pub fn get_event_sender(&self) -> futures_channel::mpsc::UnboundedSender<SchedulerMsg> {
|
||||
self.scheduler.channel.sender.clone()
|
||||
}
|
||||
|
||||
pub fn has_work(&self) -> bool {
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::rc::Rc;
|
|||
use dioxus_core::{
|
||||
events::{
|
||||
on::{MouseEvent, MouseEventInner},
|
||||
VirtualEvent,
|
||||
SyntheticEvent,
|
||||
},
|
||||
ElementId, EventPriority, EventTrigger, ScopeId,
|
||||
};
|
||||
|
@ -21,7 +21,7 @@ pub fn trigger_from_serialized(val: serde_json::Value) -> EventTrigger {
|
|||
let mut data: Vec<ImEvent> = serde_json::from_value(val).unwrap();
|
||||
let data = data.drain(..).next().unwrap();
|
||||
|
||||
let event = VirtualEvent::MouseEvent(MouseEvent(Rc::new(WebviewMouseEvent)));
|
||||
let event = SyntheticEvent::MouseEvent(MouseEvent(Rc::new(WebviewMouseEvent)));
|
||||
let scope = ScopeId(data.scope as usize);
|
||||
let mounted_dom_id = Some(ElementId(data.mounted_dom_id as usize));
|
||||
let priority = EventPriority::High;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::{collections::HashMap, fmt::Debug, rc::Rc, sync::Arc};
|
||||
|
||||
use dioxus_core::{
|
||||
events::{on::GenericEventInner, EventTrigger, VirtualEvent},
|
||||
events::{on::GenericEventInner, EventTrigger, SyntheticEvent},
|
||||
mutations::NodeRefMutation,
|
||||
DomEdit, ElementId, ScopeId,
|
||||
};
|
||||
|
@ -436,82 +436,82 @@ impl Stack {
|
|||
}
|
||||
}
|
||||
|
||||
fn virtual_event_from_websys_event(event: web_sys::Event) -> VirtualEvent {
|
||||
fn virtual_event_from_websys_event(event: web_sys::Event) -> SyntheticEvent {
|
||||
use crate::events::*;
|
||||
use dioxus_core::events::on::*;
|
||||
match event.type_().as_str() {
|
||||
"copy" | "cut" | "paste" => {
|
||||
VirtualEvent::ClipboardEvent(ClipboardEvent(Rc::new(WebsysClipboardEvent(event))))
|
||||
SyntheticEvent::ClipboardEvent(ClipboardEvent(Rc::new(WebsysClipboardEvent(event))))
|
||||
}
|
||||
"compositionend" | "compositionstart" | "compositionupdate" => {
|
||||
let evt: web_sys::CompositionEvent = event.clone().dyn_into().unwrap();
|
||||
VirtualEvent::CompositionEvent(CompositionEvent(Rc::new(WebsysCompositionEvent(evt))))
|
||||
SyntheticEvent::CompositionEvent(CompositionEvent(Rc::new(WebsysCompositionEvent(evt))))
|
||||
}
|
||||
"keydown" | "keypress" | "keyup" => {
|
||||
let evt: web_sys::KeyboardEvent = event.dyn_into().unwrap();
|
||||
VirtualEvent::KeyboardEvent(KeyboardEvent(Rc::new(WebsysKeyboardEvent(evt))))
|
||||
SyntheticEvent::KeyboardEvent(KeyboardEvent(Rc::new(WebsysKeyboardEvent(evt))))
|
||||
}
|
||||
"focus" | "blur" => {
|
||||
let evt: web_sys::FocusEvent = event.dyn_into().unwrap();
|
||||
VirtualEvent::FocusEvent(FocusEvent(Rc::new(WebsysFocusEvent(evt))))
|
||||
SyntheticEvent::FocusEvent(FocusEvent(Rc::new(WebsysFocusEvent(evt))))
|
||||
}
|
||||
"change" => {
|
||||
let evt = event.dyn_into().unwrap();
|
||||
VirtualEvent::UIEvent(UIEvent(Rc::new(WebsysGenericUiEvent(evt))))
|
||||
SyntheticEvent::UIEvent(UIEvent(Rc::new(WebsysGenericUiEvent(evt))))
|
||||
}
|
||||
"input" | "invalid" | "reset" | "submit" => {
|
||||
let evt: web_sys::InputEvent = event.clone().dyn_into().unwrap();
|
||||
VirtualEvent::FormEvent(FormEvent(Rc::new(WebsysFormEvent(evt))))
|
||||
SyntheticEvent::FormEvent(FormEvent(Rc::new(WebsysFormEvent(evt))))
|
||||
}
|
||||
"click" | "contextmenu" | "doubleclick" | "drag" | "dragend" | "dragenter" | "dragexit"
|
||||
| "dragleave" | "dragover" | "dragstart" | "drop" | "mousedown" | "mouseenter"
|
||||
| "mouseleave" | "mousemove" | "mouseout" | "mouseover" | "mouseup" => {
|
||||
let evt: web_sys::MouseEvent = event.clone().dyn_into().unwrap();
|
||||
VirtualEvent::MouseEvent(MouseEvent(Rc::new(WebsysMouseEvent(evt))))
|
||||
SyntheticEvent::MouseEvent(MouseEvent(Rc::new(WebsysMouseEvent(evt))))
|
||||
}
|
||||
"pointerdown" | "pointermove" | "pointerup" | "pointercancel" | "gotpointercapture"
|
||||
| "lostpointercapture" | "pointerenter" | "pointerleave" | "pointerover" | "pointerout" => {
|
||||
let evt: web_sys::PointerEvent = event.clone().dyn_into().unwrap();
|
||||
VirtualEvent::PointerEvent(PointerEvent(Rc::new(WebsysPointerEvent(evt))))
|
||||
SyntheticEvent::PointerEvent(PointerEvent(Rc::new(WebsysPointerEvent(evt))))
|
||||
}
|
||||
"select" => {
|
||||
let evt: web_sys::UiEvent = event.clone().dyn_into().unwrap();
|
||||
VirtualEvent::SelectionEvent(SelectionEvent(Rc::new(WebsysGenericUiEvent(evt))))
|
||||
SyntheticEvent::SelectionEvent(SelectionEvent(Rc::new(WebsysGenericUiEvent(evt))))
|
||||
}
|
||||
"touchcancel" | "touchend" | "touchmove" | "touchstart" => {
|
||||
let evt: web_sys::TouchEvent = event.clone().dyn_into().unwrap();
|
||||
VirtualEvent::TouchEvent(TouchEvent(Rc::new(WebsysTouchEvent(evt))))
|
||||
SyntheticEvent::TouchEvent(TouchEvent(Rc::new(WebsysTouchEvent(evt))))
|
||||
}
|
||||
"scroll" => {
|
||||
let evt: web_sys::UiEvent = event.clone().dyn_into().unwrap();
|
||||
VirtualEvent::UIEvent(UIEvent(Rc::new(WebsysGenericUiEvent(evt))))
|
||||
SyntheticEvent::UIEvent(UIEvent(Rc::new(WebsysGenericUiEvent(evt))))
|
||||
}
|
||||
"wheel" => {
|
||||
let evt: web_sys::WheelEvent = event.clone().dyn_into().unwrap();
|
||||
VirtualEvent::WheelEvent(WheelEvent(Rc::new(WebsysWheelEvent(evt))))
|
||||
SyntheticEvent::WheelEvent(WheelEvent(Rc::new(WebsysWheelEvent(evt))))
|
||||
}
|
||||
"animationstart" | "animationend" | "animationiteration" => {
|
||||
let evt: web_sys::AnimationEvent = event.clone().dyn_into().unwrap();
|
||||
VirtualEvent::AnimationEvent(AnimationEvent(Rc::new(WebsysAnimationEvent(evt))))
|
||||
SyntheticEvent::AnimationEvent(AnimationEvent(Rc::new(WebsysAnimationEvent(evt))))
|
||||
}
|
||||
"transitionend" => {
|
||||
let evt: web_sys::TransitionEvent = event.clone().dyn_into().unwrap();
|
||||
VirtualEvent::TransitionEvent(TransitionEvent(Rc::new(WebsysTransitionEvent(evt))))
|
||||
SyntheticEvent::TransitionEvent(TransitionEvent(Rc::new(WebsysTransitionEvent(evt))))
|
||||
}
|
||||
"abort" | "canplay" | "canplaythrough" | "durationchange" | "emptied" | "encrypted"
|
||||
| "ended" | "error" | "loadeddata" | "loadedmetadata" | "loadstart" | "pause" | "play"
|
||||
| "playing" | "progress" | "ratechange" | "seeked" | "seeking" | "stalled" | "suspend"
|
||||
| "timeupdate" | "volumechange" | "waiting" => {
|
||||
let evt: web_sys::UiEvent = event.clone().dyn_into().unwrap();
|
||||
VirtualEvent::MediaEvent(MediaEvent(Rc::new(WebsysMediaEvent(evt))))
|
||||
SyntheticEvent::MediaEvent(MediaEvent(Rc::new(WebsysMediaEvent(evt))))
|
||||
}
|
||||
"toggle" => {
|
||||
let evt: web_sys::UiEvent = event.clone().dyn_into().unwrap();
|
||||
VirtualEvent::ToggleEvent(ToggleEvent(Rc::new(WebsysToggleEvent(evt))))
|
||||
SyntheticEvent::ToggleEvent(ToggleEvent(Rc::new(WebsysToggleEvent(evt))))
|
||||
}
|
||||
_ => {
|
||||
let evt: web_sys::UiEvent = event.clone().dyn_into().unwrap();
|
||||
VirtualEvent::UIEvent(UIEvent(Rc::new(WebsysGenericUiEvent(evt))))
|
||||
SyntheticEvent::UIEvent(UIEvent(Rc::new(WebsysGenericUiEvent(evt))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue