From 88e2da6c11c84bd413304c9eb49f648a2302192a Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Sat, 6 Jan 2024 16:44:07 -0600 Subject: [PATCH] update the web renderer to the new dioxus core --- examples/compose.rs | 2 +- packages/core/src/mutations.rs | 2 +- packages/core/tests/event_propagation.rs | 21 ++- packages/desktop/src/lib.rs | 2 +- packages/html/src/events.rs | 2 +- packages/web/src/dom.rs | 171 +----------------- packages/web/src/eval.rs | 11 +- packages/web/src/hot_reload.rs | 4 +- packages/web/src/lib.rs | 48 ++--- packages/web/src/mutations.rs | 215 +++++++++++++++++++++++ 10 files changed, 274 insertions(+), 204 deletions(-) create mode 100644 packages/web/src/mutations.rs diff --git a/examples/compose.rs b/examples/compose.rs index 823e47a57..133192281 100644 --- a/examples/compose.rs +++ b/examples/compose.rs @@ -61,7 +61,7 @@ fn compose(cx: Scope) -> Element { }, "Click to send" } - + input { oninput: move |e| user_input.set(e.value()), value: "{user_input}" } } }) diff --git a/packages/core/src/mutations.rs b/packages/core/src/mutations.rs index 3d2ba049c..60118db5d 100644 --- a/packages/core/src/mutations.rs +++ b/packages/core/src/mutations.rs @@ -128,7 +128,7 @@ pub trait WriteMutations { /// Push the given root node onto our stack. /// /// Id: The ID of the root node to push. - fn push_root(&mut self, _id: ElementId); + fn push_root(&mut self, id: ElementId); /// Swap to a new subtree fn swap_subtree(&mut self, _subtree_index: usize) {} diff --git a/packages/core/tests/event_propagation.rs b/packages/core/tests/event_propagation.rs index d9d96ac32..fb87bb16a 100644 --- a/packages/core/tests/event_propagation.rs +++ b/packages/core/tests/event_propagation.rs @@ -12,7 +12,12 @@ fn events_propagate() { _ = dom.rebuild(); // Top-level click is registered - dom.handle_event("click", Rc::new(PlatformEventData::new(Box::::default())), ElementId(1), true); + dom.handle_event( + "click", + Rc::new(PlatformEventData::new(Box::::default())), + ElementId(1), + true, + ); assert_eq!(*CLICKS.lock().unwrap(), 1); // break reference.... @@ -22,7 +27,12 @@ fn events_propagate() { } // Lower click is registered - dom.handle_event("click", Rc::new(PlatformEventData::new(Box::::default())), ElementId(2), true); + dom.handle_event( + "click", + Rc::new(PlatformEventData::new(Box::::default())), + ElementId(2), + true, + ); assert_eq!(*CLICKS.lock().unwrap(), 3); // break reference.... @@ -32,7 +42,12 @@ fn events_propagate() { } // Stop propagation occurs - dom.handle_event("click", Rc::new(PlatformEventData::new(Box::::default())), ElementId(2), true); + dom.handle_event( + "click", + Rc::new(PlatformEventData::new(Box::::default())), + ElementId(2), + true, + ); assert_eq!(*CLICKS.lock().unwrap(), 3); } diff --git a/packages/desktop/src/lib.rs b/packages/desktop/src/lib.rs index 34007587c..b39cb0149 100644 --- a/packages/desktop/src/lib.rs +++ b/packages/desktop/src/lib.rs @@ -149,7 +149,7 @@ pub fn launch_with_props(root: Component

, props: P, cfg: // Copy over any assets we find crate::collect_assets::copy_assets(); - + // Set the event converter dioxus_html::set_event_converter(Box::new(SerializedHtmlEventConverter)); diff --git a/packages/html/src/events.rs b/packages/html/src/events.rs index ad83049e8..a282d6483 100644 --- a/packages/html/src/events.rs +++ b/packages/html/src/events.rs @@ -16,7 +16,7 @@ macro_rules! impl_event { ::dioxus_core::Attribute::new( stringify!($name), ::dioxus_core::AttributeValue::listener(move |e: ::dioxus_core::Event| { - _f(e.map(|e|e.into())).spawn(_cx); + _f(e.map(|e|e.into())).spawn(); }), None, false, diff --git a/packages/web/src/dom.rs b/packages/web/src/dom.rs index da46e5012..62ca32424 100644 --- a/packages/web/src/dom.rs +++ b/packages/web/src/dom.rs @@ -6,9 +6,7 @@ //! - tests to ensure dyn_into works for various event types. //! - Partial delegation? -use dioxus_core::{ - BorrowedAttributeValue, ElementId, Mutation, Template, TemplateAttribute, TemplateNode, -}; +use dioxus_core::{ElementId, Mutation, Template, TemplateAttribute, TemplateNode}; use dioxus_html::{event_bubbles, MountedData, PlatformEventData}; use dioxus_interpreter_js::get_node; use dioxus_interpreter_js::{minimal_bindings, save_template, Channel}; @@ -20,14 +18,14 @@ use web_sys::{Document, Element, Event}; use crate::{load_document, virtual_event_from_websys_event, Config, WebEventConverter}; pub struct WebsysDom { - document: Document, + pub(crate) document: Document, #[allow(dead_code)] pub(crate) root: Element, - templates: FxHashMap, - max_template_id: u16, + pub(crate) templates: FxHashMap, + pub(crate) max_template_id: u16, pub(crate) interpreter: Channel, #[cfg(feature = "mounted")] - event_channel: mpsc::UnboundedSender, + pub(crate) event_channel: mpsc::UnboundedSender, } pub struct UiEvent { @@ -118,165 +116,6 @@ impl WebsysDom { pub fn mount(&mut self) { self.interpreter.mount_to_root(); } - - pub fn load_templates(&mut self, templates: &[Template]) { - for template in templates { - let mut roots = vec![]; - - for root in template.roots { - roots.push(self.create_template_node(root)) - } - - self.templates - .insert(template.name.to_owned(), self.max_template_id); - save_template(roots, self.max_template_id); - self.max_template_id += 1 - } - } - - fn create_template_node(&self, v: &TemplateNode) -> web_sys::Node { - use TemplateNode::*; - match v { - Element { - tag, - namespace, - attrs, - children, - .. - } => { - let el = match namespace { - Some(ns) => self.document.create_element_ns(Some(ns), tag).unwrap(), - None => self.document.create_element(tag).unwrap(), - }; - for attr in *attrs { - if let TemplateAttribute::Static { - name, - value, - namespace, - } = attr - { - minimal_bindings::setAttributeInner( - el.clone().into(), - name, - JsValue::from_str(value), - *namespace, - ); - } - } - for child in *children { - let _ = el.append_child(&self.create_template_node(child)); - } - el.dyn_into().unwrap() - } - Text { text } => self.document.create_text_node(text).dyn_into().unwrap(), - DynamicText { .. } => self.document.create_text_node("p").dyn_into().unwrap(), - Dynamic { .. } => { - let el = self.document.create_element("pre").unwrap(); - let _ = el.toggle_attribute("hidden"); - el.dyn_into().unwrap() - } - } - } - - pub fn apply_edits(&mut self, mut edits: Vec) { - use Mutation::*; - let i = &mut self.interpreter; - #[cfg(feature = "mounted")] - // we need to apply the mount events last, so we collect them here - let mut to_mount = Vec::new(); - for edit in &edits { - match edit { - AppendChildren { id, m } => i.append_children(id.0 as u32, *m as u16), - AssignId { path, id } => { - i.assign_id(path.as_ptr() as u32, path.len() as u8, id.0 as u32) - } - CreatePlaceholder { id } => i.create_placeholder(id.0 as u32), - CreateTextNode { value, id } => i.create_text_node(value, id.0 as u32), - HydrateText { path, value, id } => { - i.hydrate_text(path.as_ptr() as u32, path.len() as u8, value, id.0 as u32) - } - LoadTemplate { name, index, id } => { - if let Some(tmpl_id) = self.templates.get(*name) { - i.load_template(*tmpl_id, *index as u16, id.0 as u32) - } - } - ReplaceWith { id, m } => i.replace_with(id.0 as u32, *m as u16), - ReplacePlaceholder { path, m } => { - i.replace_placeholder(path.as_ptr() as u32, path.len() as u8, *m as u16) - } - InsertAfter { id, m } => i.insert_after(id.0 as u32, *m as u16), - InsertBefore { id, m } => i.insert_before(id.0 as u32, *m as u16), - SetAttribute { - name, - value, - id, - ns, - } => match value { - BorrowedAttributeValue::Text(txt) => { - i.set_attribute(id.0 as u32, name, txt, ns.unwrap_or_default()) - } - BorrowedAttributeValue::Float(f) => { - i.set_attribute(id.0 as u32, name, &f.to_string(), ns.unwrap_or_default()) - } - BorrowedAttributeValue::Int(n) => { - i.set_attribute(id.0 as u32, name, &n.to_string(), ns.unwrap_or_default()) - } - BorrowedAttributeValue::Bool(b) => i.set_attribute( - id.0 as u32, - name, - if *b { "true" } else { "false" }, - ns.unwrap_or_default(), - ), - BorrowedAttributeValue::None => { - i.remove_attribute(id.0 as u32, name, ns.unwrap_or_default()) - } - _ => unreachable!(), - }, - SetText { value, id } => i.set_text(id.0 as u32, value), - NewEventListener { name, id, .. } => { - match *name { - // mounted events are fired immediately after the element is mounted. - "mounted" => { - #[cfg(feature = "mounted")] - to_mount.push(*id); - } - _ => { - i.new_event_listener(name, id.0 as u32, event_bubbles(name) as u8); - } - } - } - RemoveEventListener { name, id } => match *name { - "mounted" => {} - _ => { - i.remove_event_listener(name, id.0 as u32, event_bubbles(name) as u8); - } - }, - Remove { id } => i.remove(id.0 as u32), - PushRoot { id } => i.push_root(id.0 as u32), - } - } - edits.clear(); - i.flush(); - - #[cfg(feature = "mounted")] - for id in to_mount { - self.send_mount_event(id); - } - } - - pub(crate) fn send_mount_event(&self, id: ElementId) { - let node = get_node(id.0 as u32); - if let Some(element) = node.dyn_ref::() { - let data: MountedData = element.into(); - let data = Box::new(data); - let _ = self.event_channel.unbounded_send(UiEvent { - name: "mounted".to_string(), - bubbles: false, - element: id, - data: PlatformEventData::new(data), - }); - } - } } fn walk_event_for_id(event: &web_sys::Event) -> Option<(ElementId, web_sys::Element)> { diff --git a/packages/web/src/eval.rs b/packages/web/src/eval.rs index eefece50e..5dde2c896 100644 --- a/packages/web/src/eval.rs +++ b/packages/web/src/eval.rs @@ -1,5 +1,6 @@ use async_trait::async_trait; -use dioxus_core::ScopeState; +use dioxus_core::prelude::provide_context; +use dioxus_core::ScopeId; use dioxus_html::prelude::{EvalError, EvalProvider, Evaluator}; use js_sys::Function; use serde_json::Value; @@ -7,12 +8,12 @@ use std::{cell::RefCell, rc::Rc, str::FromStr}; use wasm_bindgen::prelude::*; /// Provides the WebEvalProvider through [`cx.provide_context`]. -pub fn init_eval(cx: &ScopeState) { +pub fn init_eval() { let provider: Rc = Rc::new(WebEvalProvider {}); - cx.provide_context(provider); + ScopeId::ROOT.provide_context(provider); } -/// Reprents the web-target's provider of evaluators. +/// Represents the web-target's provider of evaluators. pub struct WebEvalProvider; impl EvalProvider for WebEvalProvider { fn new_evaluator(&self, js: String) -> Result, EvalError> { @@ -28,7 +29,7 @@ const PROMISE_WRAPPER: &str = r#" }); "#; -/// Reprents a web-target's JavaScript evaluator. +/// Represents a web-target's JavaScript evaluator. pub struct WebEvaluator { dioxus: Dioxus, channel_receiver: async_channel::Receiver, diff --git a/packages/web/src/hot_reload.rs b/packages/web/src/hot_reload.rs index e8b4e42e4..d5ba2a69c 100644 --- a/packages/web/src/hot_reload.rs +++ b/packages/web/src/hot_reload.rs @@ -4,7 +4,7 @@ use futures_channel::mpsc::UnboundedReceiver; use dioxus_core::Template; -pub(crate) fn init() -> UnboundedReceiver> { +pub(crate) fn init() -> UnboundedReceiver