From 439e39bab4958665257c644dda0dcd4bd2a9a1c1 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 19 Jan 2024 09:48:45 -0600 Subject: [PATCH] fix native core, plasmo and dioxus-tui --- Cargo.lock | 258 +++++++++++++- Cargo.toml | 16 +- packages/dioxus-tui/src/element.rs | 119 +++++-- packages/dioxus-tui/src/lib.rs | 86 ++--- packages/html/src/events/keyboard.rs | 2 - packages/native-core/src/dioxus.rs | 326 ++++++++++-------- packages/native-core/src/node.rs | 17 +- packages/{rink => plasmo}/.gitignore | 0 .../{rink => plasmo}/.vscode/spellright.dict | 0 packages/{rink => plasmo}/Cargo.toml | 0 packages/{rink => plasmo}/README.md | 26 +- .../examples/counter_button.rs | 0 .../{rink => plasmo}/examples/example.png | Bin packages/{rink => plasmo}/examples/grid.rs | 0 packages/{rink => plasmo}/examples/widgets.rs | 0 packages/{rink => plasmo}/src/config.rs | 0 packages/{rink => plasmo}/src/focus.rs | 0 packages/{rink => plasmo}/src/hooks.rs | 0 packages/{rink => plasmo}/src/layout.rs | 0 packages/{rink => plasmo}/src/lib.rs | 0 .../{rink => plasmo}/src/prevent_default.rs | 0 packages/{rink => plasmo}/src/query.rs | 0 packages/{rink => plasmo}/src/render.rs | 0 packages/{rink => plasmo}/src/style.rs | 2 +- .../{rink => plasmo}/src/style_attributes.rs | 0 packages/{rink => plasmo}/src/widget.rs | 0 .../{rink => plasmo}/src/widgets/button.rs | 0 .../{rink => plasmo}/src/widgets/checkbox.rs | 0 .../{rink => plasmo}/src/widgets/input.rs | 0 packages/{rink => plasmo}/src/widgets/mod.rs | 0 .../{rink => plasmo}/src/widgets/number.rs | 0 .../{rink => plasmo}/src/widgets/password.rs | 0 .../{rink => plasmo}/src/widgets/slider.rs | 0 .../{rink => plasmo}/src/widgets/text_like.rs | 0 .../{rink => plasmo}/src/widgets/textbox.rs | 0 packages/{rink => plasmo}/test.html | 0 translations/pt-br/README.md | 2 +- 37 files changed, 588 insertions(+), 266 deletions(-) rename packages/{rink => plasmo}/.gitignore (100%) rename packages/{rink => plasmo}/.vscode/spellright.dict (100%) rename packages/{rink => plasmo}/Cargo.toml (100%) rename packages/{rink => plasmo}/README.md (63%) rename packages/{rink => plasmo}/examples/counter_button.rs (100%) rename packages/{rink => plasmo}/examples/example.png (100%) rename packages/{rink => plasmo}/examples/grid.rs (100%) rename packages/{rink => plasmo}/examples/widgets.rs (100%) rename packages/{rink => plasmo}/src/config.rs (100%) rename packages/{rink => plasmo}/src/focus.rs (100%) rename packages/{rink => plasmo}/src/hooks.rs (100%) rename packages/{rink => plasmo}/src/layout.rs (100%) rename packages/{rink => plasmo}/src/lib.rs (100%) rename packages/{rink => plasmo}/src/prevent_default.rs (100%) rename packages/{rink => plasmo}/src/query.rs (100%) rename packages/{rink => plasmo}/src/render.rs (100%) rename packages/{rink => plasmo}/src/style.rs (99%) rename packages/{rink => plasmo}/src/style_attributes.rs (100%) rename packages/{rink => plasmo}/src/widget.rs (100%) rename packages/{rink => plasmo}/src/widgets/button.rs (100%) rename packages/{rink => plasmo}/src/widgets/checkbox.rs (100%) rename packages/{rink => plasmo}/src/widgets/input.rs (100%) rename packages/{rink => plasmo}/src/widgets/mod.rs (100%) rename packages/{rink => plasmo}/src/widgets/number.rs (100%) rename packages/{rink => plasmo}/src/widgets/password.rs (100%) rename packages/{rink => plasmo}/src/widgets/slider.rs (100%) rename packages/{rink => plasmo}/src/widgets/text_like.rs (100%) rename packages/{rink => plasmo}/src/widgets/textbox.rs (100%) rename packages/{rink => plasmo}/test.html (100%) diff --git a/Cargo.lock b/Cargo.lock index 133b5dc19..ece51b8bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -203,6 +203,12 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344" +[[package]] +name = "anymap" +version = "1.0.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1f8f5a6f3d50d89e3797d7593a50f96bb2aaa20ca0cc7be1fb673232c91d72" + [[package]] name = "anymap2" version = "0.13.0" @@ -1354,6 +1360,12 @@ dependencies = [ "toml 0.8.2", ] +[[package]] +name = "cassowary" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" + [[package]] name = "cast" version = "0.3.0" @@ -1947,6 +1959,47 @@ version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +[[package]] +name = "crossterm" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13" +dependencies = [ + "bitflags 1.3.2", + "crossterm_winapi", + "libc", + "mio", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" +dependencies = [ + "bitflags 2.4.2", + "crossterm_winapi", + "libc", + "mio", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + [[package]] name = "cruet" version = "0.14.0" @@ -2503,7 +2556,7 @@ dependencies = [ name = "dioxus-fullstack" version = "0.4.3" dependencies = [ - "anymap", + "anymap 0.12.1", "async-trait", "axum 0.6.20", "base64 0.21.7", @@ -2668,6 +2721,40 @@ dependencies = [ "dioxus-desktop", ] +[[package]] +name = "dioxus-native-core" +version = "0.4.3" +dependencies = [ + "anymap 1.0.0-beta.2", + "dashmap", + "dioxus", + "dioxus-core", + "dioxus-native-core", + "dioxus-native-core-macro", + "keyboard-types", + "lightningcss", + "parking_lot", + "rand 0.8.5", + "rustc-hash", + "shipyard", + "smallvec", + "taffy", + "tokio", +] + +[[package]] +name = "dioxus-native-core-macro" +version = "0.4.3" +dependencies = [ + "anymap 0.12.1", + "dioxus", + "dioxus-native-core", + "quote", + "rustc-hash", + "smallvec", + "syn 2.0.48", +] + [[package]] name = "dioxus-playwright-fullstack-test" version = "0.1.0" @@ -2817,6 +2904,24 @@ dependencies = [ "manganis", ] +[[package]] +name = "dioxus-tui" +version = "0.4.3" +dependencies = [ + "criterion 0.3.6", + "crossterm 0.26.1", + "dioxus", + "dioxus-core", + "dioxus-hot-reload", + "dioxus-html", + "dioxus-native-core", + "dioxus-native-core-macro", + "futures", + "plasmo", + "taffy", + "tokio", +] + [[package]] name = "dioxus-web" version = "0.4.3" @@ -4316,6 +4421,12 @@ dependencies = [ "system-deps", ] +[[package]] +name = "grid" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eec1c01eb1de97451ee0d60de7d81cf1e72aabefb021616027f3d1c3ec1c723c" + [[package]] name = "gtk" version = "0.18.1" @@ -5175,6 +5286,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.12.0" @@ -5692,6 +5812,15 @@ dependencies = [ "hashbrown 0.13.2", ] +[[package]] +name = "lru" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2994eeba8ed550fd9b47a0b38f0242bc3344e496483c6180b69139cc2fa5d1d7" +dependencies = [ + "hashbrown 0.14.3", +] + [[package]] name = "lru-cache" version = "0.1.2" @@ -7033,6 +7162,28 @@ version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" +[[package]] +name = "plasmo" +version = "0.4.3" +dependencies = [ + "anyhow", + "anymap 1.0.0-beta.2", + "criterion 0.3.6", + "crossterm 0.26.1", + "dioxus-html", + "dioxus-native-core", + "dioxus-native-core-macro", + "futures", + "futures-channel", + "once_cell", + "ratatui", + "rustc-hash", + "shipyard", + "smallvec", + "taffy", + "tokio", +] + [[package]] name = "plist" version = "1.6.0" @@ -7463,6 +7614,24 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "ratatui" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ebc917cfb527a566c37ecb94c7e3fd098353516fb4eb6bea17015ade0182425" +dependencies = [ + "bitflags 2.4.2", + "cassowary", + "crossterm 0.27.0", + "indoc", + "itertools 0.11.0", + "lru 0.12.1", + "paste", + "strum", + "unicode-segmentation", + "unicode-width", +] + [[package]] name = "rav1e" version = "0.6.6" @@ -8744,6 +8913,50 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" +[[package]] +name = "shipyard" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3511ae730f2e1c3d62a9025e2f9b2acbf130968057f1b3caab6d74a54a5e0e56" +dependencies = [ + "hashbrown 0.12.3", + "lock_api", + "rayon", + "shipyard_proc", +] + +[[package]] +name = "shipyard_proc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb847f4b9582e468198b5cfb5731b65cc67fe5e535acc9cbf3c11703d15f08c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -8841,6 +9054,15 @@ dependencies = [ "rustc-hash", ] +[[package]] +name = "slotmap" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +dependencies = [ + "version_check", +] + [[package]] name = "smallvec" version = "1.13.0" @@ -9265,6 +9487,28 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.48", +] + [[package]] name = "subprocess" version = "0.2.9" @@ -9365,6 +9609,18 @@ dependencies = [ "version-compare", ] +[[package]] +name = "taffy" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c2287b6d7f721ada4cddf61ade5e760b2c6207df041cac9bfaa192897362fd3" +dependencies = [ + "arrayvec", + "grid", + "num-traits", + "slotmap", +] + [[package]] name = "tao" version = "0.24.1" diff --git a/Cargo.toml b/Cargo.toml index 3169bfb7f..24eed2fbb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,10 +24,10 @@ members = [ "packages/autofmt", "packages/check", "packages/rsx", - # "packages/dioxus-tui", - # "packages/rink", - # "packages/native-core", - # "packages/native-core-macro", + "packages/dioxus-tui", + "packages/plasmo", + "packages/native-core", + "packages/native-core-macro", "packages/rsx-rosetta", "packages/generational-box", "packages/signals", @@ -78,10 +78,10 @@ dioxus-liveview = { path = "packages/liveview", version = "0.4.0" } dioxus-autofmt = { path = "packages/autofmt", version = "0.4.0" } dioxus-check = { path = "packages/check", version = "0.4.0" } dioxus-rsx = { path = "packages/rsx", version = "0.4.0" } -# dioxus-tui = { path = "packages/dioxus-tui", version = "0.4.0" } -# plasmo = { path = "packages/rink", version = "0.4.0" } -# dioxus-native-core = { path = "packages/native-core", version = "0.4.0" } -# dioxus-native-core-macro = { path = "packages/native-core-macro", version = "0.4.0" } +dioxus-tui = { path = "packages/dioxus-tui", version = "0.4.0" } +plasmo = { path = "packages/plasmo", version = "0.4.0" } +dioxus-native-core = { path = "packages/native-core", version = "0.4.0" } +dioxus-native-core-macro = { path = "packages/native-core-macro", version = "0.4.0" } rsx-rosetta = { path = "packages/rsx-rosetta", version = "0.4.0" } dioxus-signals = { path = "packages/signals" } dioxus-cli-config = { path = "packages/cli-config", version = "0.4.1" } diff --git a/packages/dioxus-tui/src/element.rs b/packages/dioxus-tui/src/element.rs index 8fdb60b9f..bb6e36722 100644 --- a/packages/dioxus-tui/src/element.rs +++ b/packages/dioxus-tui/src/element.rs @@ -3,45 +3,104 @@ use std::{ fmt::{Display, Formatter}, }; -use dioxus_core::{ElementId, Mutations, VirtualDom}; +use dioxus_core::{ElementId, WriteMutations}; use dioxus_html::{ geometry::euclid::{Point2D, Rect, Size2D}, MountedData, MountedError, RenderedElementBacking, }; -use dioxus_native_core::NodeId; +use dioxus_native_core::{dioxus::DioxusNativeCoreMutationWriter, NodeId}; use plasmo::query::{ElementRef, Query}; -pub(crate) fn find_mount_events(mutations: &Mutations) -> Vec { - let mut mount_events = Vec::new(); - for mutation in &mutations.edits { - if let dioxus_core::Mutation::NewEventListener { - name: "mounted", - id, - } = mutation - { - mount_events.push(*id); - } - } - mount_events +pub(crate) struct DioxusTUIMutationWriter<'a> { + pub(crate) query: Query, + pub(crate) events: &'a mut Vec<(ElementId, &'static str, Box, bool)>, + pub(crate) native_core_writer: DioxusNativeCoreMutationWriter<'a>, } -// We need to queue the mounted events to give rink time to rendere and resolve the layout of elements after they are created -pub(crate) fn create_mounted_events( - vdom: &VirtualDom, - events: &mut Vec<(ElementId, &'static str, Box, bool)>, - mount_events: impl Iterator, -) { - let query: Query = vdom - .base_scope() - .consume_context() - .expect("Query should be in context"); - for (id, node_id) in mount_events { - let element = TuiElement { - query: query.clone(), - id: node_id, - }; - events.push((id, "mounted", Box::new(MountedData::new(element)), false)); +impl WriteMutations for DioxusTUIMutationWriter<'_> { + fn register_template(&mut self, template: dioxus_core::prelude::Template) { + self.native_core_writer.register_template(template) + } + + fn append_children(&mut self, id: ElementId, m: usize) { + self.native_core_writer.append_children(id, m) + } + + fn assign_node_id(&mut self, path: &'static [u8], id: ElementId) { + self.native_core_writer.assign_node_id(path, id) + } + + fn create_placeholder(&mut self, id: ElementId) { + self.native_core_writer.create_placeholder(id) + } + + fn create_text_node(&mut self, value: &str, id: ElementId) { + self.native_core_writer.create_text_node(value, id) + } + + fn hydrate_text_node(&mut self, path: &'static [u8], value: &str, id: ElementId) { + self.native_core_writer.hydrate_text_node(path, value, id) + } + + fn load_template(&mut self, name: &'static str, index: usize, id: ElementId) { + self.native_core_writer.load_template(name, index, id) + } + + fn replace_node_with(&mut self, id: ElementId, m: usize) { + self.native_core_writer.replace_node_with(id, m) + } + + fn replace_placeholder_with_nodes(&mut self, path: &'static [u8], m: usize) { + self.native_core_writer + .replace_placeholder_with_nodes(path, m) + } + + fn insert_nodes_after(&mut self, id: ElementId, m: usize) { + self.native_core_writer.insert_nodes_after(id, m) + } + + fn insert_nodes_before(&mut self, id: ElementId, m: usize) { + self.native_core_writer.insert_nodes_before(id, m) + } + + fn set_attribute( + &mut self, + name: &'static str, + ns: Option<&'static str>, + value: &dioxus_core::AttributeValue, + id: ElementId, + ) { + self.native_core_writer.set_attribute(name, ns, value, id) + } + + fn set_node_text(&mut self, value: &str, id: ElementId) { + self.native_core_writer.set_node_text(value, id) + } + + fn create_event_listener(&mut self, name: &'static str, id: ElementId) { + if name == "mounted" { + let element = TuiElement { + query: self.query.clone(), + id: self.native_core_writer.state.element_to_node_id(id), + }; + self.events + .push((id, "mounted", Box::new(MountedData::new(element)), false)); + } else { + self.native_core_writer.create_event_listener(name, id) + } + } + + fn remove_event_listener(&mut self, name: &'static str, id: ElementId) { + self.native_core_writer.remove_event_listener(name, id) + } + + fn remove_node(&mut self, id: ElementId) { + self.native_core_writer.remove_node(id) + } + + fn push_root(&mut self, id: ElementId) { + self.native_core_writer.push_root(id) } } diff --git a/packages/dioxus-tui/src/lib.rs b/packages/dioxus-tui/src/lib.rs index fff318c47..5614df3ad 100644 --- a/packages/dioxus-tui/src/lib.rs +++ b/packages/dioxus-tui/src/lib.rs @@ -12,24 +12,20 @@ use std::{ sync::{Arc, RwLock}, }; -use dioxus_core::{Component, ElementId, VirtualDom}; +use dioxus_core::{Element, ElementId, ScopeId, VirtualDom}; use dioxus_html::PlatformEventData; use dioxus_native_core::dioxus::{DioxusState, NodeImmutableDioxusExt}; use dioxus_native_core::prelude::*; -use element::{create_mounted_events, find_mount_events}; +use element::DioxusTUIMutationWriter; pub use plasmo::{query::Query, Config, RenderingMode, Size, TuiContext}; use plasmo::{render, Driver}; -pub fn launch(app: Component<()>) { +pub fn launch(app: fn() -> Element) { launch_cfg(app, Config::default()) } -pub fn launch_cfg(app: Component<()>, cfg: Config) { - launch_cfg_with_props(app, (), cfg); -} - -pub fn launch_cfg_with_props(app: Component, props: Props, cfg: Config) { +pub fn launch_cfg(app: fn() -> Element, cfg: Config) { dioxus_html::set_event_converter(Box::new(events::SerializedHtmlEventConverter)); render(cfg, |rdom, taffy, event_tx| { @@ -38,36 +34,16 @@ pub fn launch_cfg_with_props(app: Component, props: Props DioxusState::create(&mut rdom) }; let dioxus_state = Rc::new(RwLock::new(dioxus_state)); - let mut vdom = VirtualDom::new_with_props(app, props) + let mut vdom = VirtualDom::new(app) .with_root_context(TuiContext::new(event_tx)) .with_root_context(Query::new(rdom.clone(), taffy.clone())) .with_root_context(DioxusElementToNodeId { mapping: dioxus_state.clone(), }); - let muts = vdom.rebuild(); - let mut queued_events = Vec::new(); + let queued_events = Vec::new(); - { - let mut rdom = rdom.write().unwrap(); - let mut dioxus_state = dioxus_state.write().unwrap(); - - // Find any mount events - let mounted = find_mount_events(&muts); - - dioxus_state.apply_mutations(&mut rdom, muts); - - // Send the mount events - create_mounted_events( - &vdom, - &mut queued_events, - mounted - .iter() - .map(|id| (*dbg!(id), dioxus_state.element_to_node_id(*id))), - ); - } - - DioxusRenderer { + let mut myself = DioxusRenderer { vdom, dioxus_state, queued_events, @@ -80,7 +56,25 @@ pub fn launch_cfg_with_props(app: Component, props: Props }); hot_reload_rx }, + }; + + { + let mut rdom = rdom.write().unwrap(); + let mut dioxus_state = myself.dioxus_state.write().unwrap(); + + let mut writer = DioxusTUIMutationWriter { + query: myself + .vdom + .in_runtime(|| ScopeId::ROOT.consume_context().unwrap()), + events: &mut myself.queued_events, + native_core_writer: dioxus_state.create_mutation_writer(&mut rdom), + }; + + // Find any mount events + myself.vdom.rebuild(&mut writer); } + + myself }) .unwrap(); } @@ -96,27 +90,19 @@ struct DioxusRenderer { impl Driver for DioxusRenderer { fn update(&mut self, rdom: &Arc>) { - let muts = self.vdom.render_immediate(); - { - let mut rdom = rdom.write().unwrap(); + let mut rdom = rdom.write().unwrap(); + let mut dioxus_state = self.dioxus_state.write().unwrap(); - { - // Find any mount events - let mounted = find_mount_events(&muts); + let mut writer = DioxusTUIMutationWriter { + query: self + .vdom + .in_runtime(|| ScopeId::ROOT.consume_context().unwrap()), + events: &mut self.queued_events, + native_core_writer: dioxus_state.create_mutation_writer(&mut rdom), + }; - let mut dioxus_state = self.dioxus_state.write().unwrap(); - dioxus_state.apply_mutations(&mut rdom, muts); - - // Send the mount events - create_mounted_events( - &self.vdom, - &mut self.queued_events, - mounted - .iter() - .map(|id| (*id, dioxus_state.element_to_node_id(*id))), - ); - } - } + // Find any mount events + self.vdom.render_immediate(&mut writer); } fn handle_event( diff --git a/packages/html/src/events/keyboard.rs b/packages/html/src/events/keyboard.rs index feb0ab313..88055478f 100644 --- a/packages/html/src/events/keyboard.rs +++ b/packages/html/src/events/keyboard.rs @@ -246,8 +246,6 @@ impl<'de> serde::Deserialize<'de> for KeyCode { where D: serde::Deserializer<'de>, { - use std::convert::TryInto; - // We could be deserializing a unicode character, so we need to use u64 even if the output only takes u8 let value = u64::deserialize(deserializer)?; diff --git a/packages/native-core/src/dioxus.rs b/packages/native-core/src/dioxus.rs index c245de4fc..e05c47b63 100644 --- a/packages/native-core/src/dioxus.rs +++ b/packages/native-core/src/dioxus.rs @@ -1,7 +1,7 @@ //! Integration between Dioxus and the RealDom use crate::tree::TreeMut; -use dioxus_core::{BorrowedAttributeValue, ElementId, Mutations, TemplateNode}; +use dioxus_core::{AttributeValue, ElementId, TemplateNode, WriteMutations}; use rustc_hash::{FxHashMap, FxHashSet}; use shipyard::Component; @@ -48,6 +48,14 @@ impl DioxusState { self.node_id_mapping.get(element_id.0).copied().flatten() } + /// Create a mutation writer for the RealDom + pub fn create_mutation_writer<'a, V: FromAnyValue + Send + Sync>( + &'a mut self, + rdom: &'a mut RealDom, + ) -> DioxusNativeCoreMutationWriter<'a, V> { + DioxusNativeCoreMutationWriter { rdom, state: self } + } + fn set_element_id( &mut self, mut node: NodeMut, @@ -74,165 +82,179 @@ impl DioxusState { } current.id() } +} - /// Updates the dom with some mutations and return a set of nodes that were updated. Pass the dirty nodes to update_state. - pub fn apply_mutations( +/// A writer for mutations that can be used with the RealDom. +pub struct DioxusNativeCoreMutationWriter<'a, V: FromAnyValue + Send + Sync = ()> { + pub rdom: &'a mut RealDom, + pub state: &'a mut DioxusState, +} + +impl WriteMutations for DioxusNativeCoreMutationWriter<'_, V> { + fn register_template(&mut self, template: dioxus_core::prelude::Template) { + let mut template_root_ids = Vec::new(); + for root in template.roots { + let id = create_template_node(self.rdom, root); + template_root_ids.push(id); + } + self.state + .templates + .insert(template.name.to_string(), template_root_ids); + } + + fn append_children(&mut self, id: ElementId, m: usize) { + let children = self.state.stack.split_off(self.state.stack.len() - m); + let parent = self.state.element_to_node_id(id); + for child in children { + self.rdom.get_mut(parent).unwrap().add_child(child); + } + } + + fn assign_node_id(&mut self, path: &'static [u8], id: ElementId) { + let node_id = self.state.load_child(self.rdom, path); + self.state + .set_element_id(self.rdom.get_mut(node_id).unwrap(), id); + } + + fn create_placeholder(&mut self, id: ElementId) { + let node = NodeType::Placeholder; + let node = self.rdom.create_node(node); + let node_id = node.id(); + self.state.set_element_id(node, id); + self.state.stack.push(node_id); + } + + fn create_text_node(&mut self, value: &str, id: ElementId) { + let node_data = NodeType::Text(TextNode { + listeners: FxHashSet::default(), + text: value.to_string(), + }); + let node = self.rdom.create_node(node_data); + let node_id = node.id(); + self.state.set_element_id(node, id); + self.state.stack.push(node_id); + } + + fn hydrate_text_node(&mut self, path: &'static [u8], value: &str, id: ElementId) { + let node_id = self.state.load_child(self.rdom, path); + let node = self.rdom.get_mut(node_id).unwrap(); + self.state.set_element_id(node, id); + let mut node = self.rdom.get_mut(node_id).unwrap(); + let node_type_mut = node.node_type_mut(); + if let NodeTypeMut::Text(mut text) = node_type_mut { + *text.text_mut() = value.to_string(); + } else { + drop(node_type_mut); + node.set_type(NodeType::Text(TextNode { + text: value.to_string(), + listeners: FxHashSet::default(), + })); + } + } + + fn load_template(&mut self, name: &'static str, index: usize, id: ElementId) { + let template_id = self.state.templates[name][index]; + let clone_id = self.rdom.get_mut(template_id).unwrap().clone_node(); + let clone = self.rdom.get_mut(clone_id).unwrap(); + self.state.set_element_id(clone, id); + self.state.stack.push(clone_id); + } + + fn replace_node_with(&mut self, id: ElementId, m: usize) { + let new_nodes = self.state.stack.split_off(self.state.stack.len() - m); + let old_node_id = self.state.element_to_node_id(id); + for new in new_nodes { + let mut node = self.rdom.get_mut(new).unwrap(); + node.insert_before(old_node_id); + } + self.rdom.get_mut(old_node_id).unwrap().remove(); + } + + fn replace_placeholder_with_nodes(&mut self, path: &'static [u8], m: usize) { + let new_nodes = self.state.stack.split_off(self.state.stack.len() - m); + let old_node_id = self.state.load_child(self.rdom, path); + for new in new_nodes { + let mut node = self.rdom.get_mut(new).unwrap(); + node.insert_before(old_node_id); + } + self.rdom.get_mut(old_node_id).unwrap().remove(); + } + + fn insert_nodes_after(&mut self, id: ElementId, m: usize) { + let new_nodes = self.state.stack.split_off(self.state.stack.len() - m); + let old_node_id = self.state.element_to_node_id(id); + for new in new_nodes.into_iter().rev() { + let mut node = self.rdom.get_mut(new).unwrap(); + node.insert_after(old_node_id); + } + } + + fn insert_nodes_before(&mut self, id: ElementId, m: usize) { + let new_nodes = self.state.stack.split_off(self.state.stack.len() - m); + let old_node_id = self.state.element_to_node_id(id); + for new in new_nodes { + self.rdom.tree_mut().insert_before(old_node_id, new); + } + } + + fn set_attribute( &mut self, - rdom: &mut RealDom, - mutations: Mutations, + name: &'static str, + ns: Option<&'static str>, + value: &AttributeValue, + id: ElementId, ) { - for template in mutations.templates { - let mut template_root_ids = Vec::new(); - for root in template.roots { - let id = create_template_node(rdom, root); - template_root_ids.push(id); + let node_id = self.state.element_to_node_id(id); + let mut node = self.rdom.get_mut(node_id).unwrap(); + let mut node_type_mut = node.node_type_mut(); + if let NodeTypeMut::Element(element) = &mut node_type_mut { + if let AttributeValue::None = &value { + element.remove_attribute(&OwnedAttributeDiscription { + name: name.to_string(), + namespace: ns.map(|s| s.to_string()), + }); + } else { + element.set_attribute( + OwnedAttributeDiscription { + name: name.to_string(), + namespace: ns.map(|s| s.to_string()), + }, + OwnedAttributeValue::from(value), + ); } - self.templates - .insert(template.name.to_string(), template_root_ids); } + } - for e in mutations.edits { - use dioxus_core::Mutation::*; - match e { - AppendChildren { id, m } => { - let children = self.stack.split_off(self.stack.len() - m); - let parent = self.element_to_node_id(id); - for child in children { - rdom.get_mut(parent).unwrap().add_child(child); - } - } - AssignId { path, id } => { - let node_id = self.load_child(rdom, path); - self.set_element_id(rdom.get_mut(node_id).unwrap(), id); - } - CreatePlaceholder { id } => { - let node = NodeType::Placeholder; - let node = rdom.create_node(node); - let node_id = node.id(); - self.set_element_id(node, id); - self.stack.push(node_id); - } - CreateTextNode { value, id } => { - let node_data = NodeType::Text(TextNode { - listeners: FxHashSet::default(), - text: value.to_string(), - }); - let node = rdom.create_node(node_data); - let node_id = node.id(); - self.set_element_id(node, id); - self.stack.push(node_id); - } - HydrateText { path, value, id } => { - let node_id = self.load_child(rdom, path); - let node = rdom.get_mut(node_id).unwrap(); - self.set_element_id(node, id); - let mut node = rdom.get_mut(node_id).unwrap(); - let node_type_mut = node.node_type_mut(); - if let NodeTypeMut::Text(mut text) = node_type_mut { - *text.text_mut() = value.to_string(); - } else { - drop(node_type_mut); - node.set_type(NodeType::Text(TextNode { - text: value.to_string(), - listeners: FxHashSet::default(), - })); - } - } - LoadTemplate { name, index, id } => { - let template_id = self.templates[name][index]; - let clone_id = rdom.get_mut(template_id).unwrap().clone_node(); - let clone = rdom.get_mut(clone_id).unwrap(); - self.set_element_id(clone, id); - self.stack.push(clone_id); - } - ReplaceWith { id, m } => { - let new_nodes = self.stack.split_off(self.stack.len() - m); - let old_node_id = self.element_to_node_id(id); - for new in new_nodes { - let mut node = rdom.get_mut(new).unwrap(); - node.insert_before(old_node_id); - } - rdom.get_mut(old_node_id).unwrap().remove(); - } - ReplacePlaceholder { path, m } => { - let new_nodes = self.stack.split_off(self.stack.len() - m); - let old_node_id = self.load_child(rdom, path); - for new in new_nodes { - let mut node = rdom.get_mut(new).unwrap(); - node.insert_before(old_node_id); - } - rdom.get_mut(old_node_id).unwrap().remove(); - } - InsertAfter { id, m } => { - let new_nodes = self.stack.split_off(self.stack.len() - m); - let old_node_id = self.element_to_node_id(id); - for new in new_nodes.into_iter().rev() { - let mut node = rdom.get_mut(new).unwrap(); - node.insert_after(old_node_id); - } - } - InsertBefore { id, m } => { - let new_nodes = self.stack.split_off(self.stack.len() - m); - let old_node_id = self.element_to_node_id(id); - for new in new_nodes { - rdom.tree_mut().insert_before(old_node_id, new); - } - } - SetAttribute { - name, - value, - id, - ns, - } => { - let node_id = self.element_to_node_id(id); - let mut node = rdom.get_mut(node_id).unwrap(); - let mut node_type_mut = node.node_type_mut(); - if let NodeTypeMut::Element(element) = &mut node_type_mut { - if let BorrowedAttributeValue::None = &value { - element.remove_attribute(&OwnedAttributeDiscription { - name: name.to_string(), - namespace: ns.map(|s| s.to_string()), - }); - } else { - element.set_attribute( - OwnedAttributeDiscription { - name: name.to_string(), - namespace: ns.map(|s| s.to_string()), - }, - OwnedAttributeValue::from(value), - ); - } - } - } - SetText { value, id } => { - let node_id = self.element_to_node_id(id); - let mut node = rdom.get_mut(node_id).unwrap(); - let node_type_mut = node.node_type_mut(); - if let NodeTypeMut::Text(mut text) = node_type_mut { - *text.text_mut() = value.to_string(); - } - } - NewEventListener { name, id } => { - let node_id = self.element_to_node_id(id); - let mut node = rdom.get_mut(node_id).unwrap(); - node.add_event_listener(name); - } - RemoveEventListener { id, name } => { - let node_id = self.element_to_node_id(id); - let mut node = rdom.get_mut(node_id).unwrap(); - node.remove_event_listener(name); - } - Remove { id } => { - let node_id = self.element_to_node_id(id); - rdom.get_mut(node_id).unwrap().remove(); - } - PushRoot { id } => { - let node_id = self.element_to_node_id(id); - self.stack.push(node_id); - } - } + fn set_node_text(&mut self, value: &str, id: ElementId) { + let node_id = self.state.element_to_node_id(id); + let mut node = self.rdom.get_mut(node_id).unwrap(); + let node_type_mut = node.node_type_mut(); + if let NodeTypeMut::Text(mut text) = node_type_mut { + *text.text_mut() = value.to_string(); } } + + fn create_event_listener(&mut self, name: &'static str, id: ElementId) { + let node_id = self.state.element_to_node_id(id); + let mut node = self.rdom.get_mut(node_id).unwrap(); + node.add_event_listener(name); + } + + fn remove_event_listener(&mut self, name: &'static str, id: ElementId) { + let node_id = self.state.element_to_node_id(id); + let mut node = self.rdom.get_mut(node_id).unwrap(); + node.remove_event_listener(name); + } + + fn remove_node(&mut self, id: ElementId) { + let node_id = self.state.element_to_node_id(id); + self.rdom.get_mut(node_id).unwrap().remove(); + } + + fn push_root(&mut self, id: ElementId) { + let node_id = self.state.element_to_node_id(id); + self.state.stack.push(node_id); + } } fn create_template_node( diff --git a/packages/native-core/src/node.rs b/packages/native-core/src/node.rs index 42ff8229f..9644bda7f 100644 --- a/packages/native-core/src/node.rs +++ b/packages/native-core/src/node.rs @@ -201,15 +201,16 @@ impl Display for OwnedAttributeValue { } #[cfg(feature = "dioxus")] -impl From> for OwnedAttributeValue { - fn from(value: dioxus_core::BorrowedAttributeValue<'_>) -> Self { +impl From<&dioxus_core::AttributeValue> for OwnedAttributeValue { + fn from(value: &dioxus_core::AttributeValue) -> Self { match value { - dioxus_core::BorrowedAttributeValue::Text(text) => Self::Text(text.to_string()), - dioxus_core::BorrowedAttributeValue::Float(float) => Self::Float(float), - dioxus_core::BorrowedAttributeValue::Int(int) => Self::Int(int), - dioxus_core::BorrowedAttributeValue::Bool(bool) => Self::Bool(bool), - dioxus_core::BorrowedAttributeValue::Any(any) => Self::Custom(V::from_any_value(any.as_any())), - dioxus_core::BorrowedAttributeValue::None => panic!("None attribute values result in removing the attribute, not converting it to a None value.") + dioxus_core::AttributeValue::Text(text) => Self::Text(text.clone()), + dioxus_core::AttributeValue::Float(float) => Self::Float(*float), + dioxus_core::AttributeValue::Int(int) => Self::Int(*int), + dioxus_core::AttributeValue::Bool(bool) => Self::Bool(*bool), + dioxus_core::AttributeValue::Any(any) => Self::Custom(V::from_any_value(any.as_any())), + dioxus_core::AttributeValue::None => panic!("None attribute values result in removing the attribute, not converting it to a None value."), + _ => panic!("Unsupported attribute value type"), } } } diff --git a/packages/rink/.gitignore b/packages/plasmo/.gitignore similarity index 100% rename from packages/rink/.gitignore rename to packages/plasmo/.gitignore diff --git a/packages/rink/.vscode/spellright.dict b/packages/plasmo/.vscode/spellright.dict similarity index 100% rename from packages/rink/.vscode/spellright.dict rename to packages/plasmo/.vscode/spellright.dict diff --git a/packages/rink/Cargo.toml b/packages/plasmo/Cargo.toml similarity index 100% rename from packages/rink/Cargo.toml rename to packages/plasmo/Cargo.toml diff --git a/packages/rink/README.md b/packages/plasmo/README.md similarity index 63% rename from packages/rink/README.md rename to packages/plasmo/README.md index 0c327db13..42fef4900 100644 --- a/packages/rink/README.md +++ b/packages/plasmo/README.md @@ -1,5 +1,5 @@
-

Rink

+

Plasmo

A beautiful terminal user interfaces library in Rust.

@@ -7,23 +7,23 @@
- - + Crates.io version - - + Download - + docs.rs docs - - + CI status @@ -34,7 +34,7 @@
-Leverage CSS, HTML, and Rust to build beautiful, portable, terminal user interfaces. Rink is the cross-framework library that powers [`Dioxus-TUI`](https://github.com/DioxusLabs/dioxus/tree/master/packages/dioxus-tui) +Leverage CSS, HTML, and Rust to build beautiful, portable, terminal user interfaces. Plasmo is the cross-framework library that powers [`Dioxus-TUI`](https://github.com/DioxusLabs/dioxus/tree/master/packages/dioxus-tui) ![demo app](examples/example.png) @@ -42,7 +42,7 @@ Leverage CSS, HTML, and Rust to build beautiful, portable, terminal user interfa You can use Html-like semantics with inline styles, tree hierarchy, components, and more in your [`text-based user interface (TUI)`](https://en.wikipedia.org/wiki/Text-based_user_interface) application. -Rink is essentially a port of [Ink](https://github.com/vadimdemedes/ink) but for [`Rust`](https://www.rust-lang.org/). Rink doesn't depend on Node.js or any other JavaScript runtime, so your binaries are portable and beautiful. +Plasmo is essentially a port of [Ink](https://github.com/vadimdemedes/ink) but for [`Rust`](https://www.rust-lang.org/). Plasmo doesn't depend on Node.js or any other JavaScript runtime, so your binaries are portable and beautiful. ## Limitations @@ -53,13 +53,13 @@ Rink is essentially a port of [Ink](https://github.com/vadimdemedes/ink) but for ## Status -**WARNING: Rink is currently under construction!** +**WARNING: Plasmo is currently under construction!** Rendering a Dom works fine, but the ecosystem of widgets is not ready yet. Additionally, some bugs in the flexbox implementation might be quirky at times. ## Features -Rink features: +Plasmo features: - [x] Flexbox-based layout system - [ ] CSS selectors @@ -71,4 +71,4 @@ Rink features: * [ ] Html tags2 1 Basic keyboard, mouse, and focus events are implemented. -2 Currently, most HTML tags don't translate into any meaning inside of Rink. So an `input` _element_ won't mean anything nor does it have any additional functionality. +2 Currently, most HTML tags don't translate into any meaning inside of Plasmo. So an `input` _element_ won't mean anything nor does it have any additional functionality. diff --git a/packages/rink/examples/counter_button.rs b/packages/plasmo/examples/counter_button.rs similarity index 100% rename from packages/rink/examples/counter_button.rs rename to packages/plasmo/examples/counter_button.rs diff --git a/packages/rink/examples/example.png b/packages/plasmo/examples/example.png similarity index 100% rename from packages/rink/examples/example.png rename to packages/plasmo/examples/example.png diff --git a/packages/rink/examples/grid.rs b/packages/plasmo/examples/grid.rs similarity index 100% rename from packages/rink/examples/grid.rs rename to packages/plasmo/examples/grid.rs diff --git a/packages/rink/examples/widgets.rs b/packages/plasmo/examples/widgets.rs similarity index 100% rename from packages/rink/examples/widgets.rs rename to packages/plasmo/examples/widgets.rs diff --git a/packages/rink/src/config.rs b/packages/plasmo/src/config.rs similarity index 100% rename from packages/rink/src/config.rs rename to packages/plasmo/src/config.rs diff --git a/packages/rink/src/focus.rs b/packages/plasmo/src/focus.rs similarity index 100% rename from packages/rink/src/focus.rs rename to packages/plasmo/src/focus.rs diff --git a/packages/rink/src/hooks.rs b/packages/plasmo/src/hooks.rs similarity index 100% rename from packages/rink/src/hooks.rs rename to packages/plasmo/src/hooks.rs diff --git a/packages/rink/src/layout.rs b/packages/plasmo/src/layout.rs similarity index 100% rename from packages/rink/src/layout.rs rename to packages/plasmo/src/layout.rs diff --git a/packages/rink/src/lib.rs b/packages/plasmo/src/lib.rs similarity index 100% rename from packages/rink/src/lib.rs rename to packages/plasmo/src/lib.rs diff --git a/packages/rink/src/prevent_default.rs b/packages/plasmo/src/prevent_default.rs similarity index 100% rename from packages/rink/src/prevent_default.rs rename to packages/plasmo/src/prevent_default.rs diff --git a/packages/rink/src/query.rs b/packages/plasmo/src/query.rs similarity index 100% rename from packages/rink/src/query.rs rename to packages/plasmo/src/query.rs diff --git a/packages/rink/src/render.rs b/packages/plasmo/src/render.rs similarity index 100% rename from packages/rink/src/render.rs rename to packages/plasmo/src/render.rs diff --git a/packages/rink/src/style.rs b/packages/plasmo/src/style.rs similarity index 99% rename from packages/rink/src/style.rs rename to packages/plasmo/src/style.rs index 905cc4b34..affcd4324 100644 --- a/packages/rink/src/style.rs +++ b/packages/plasmo/src/style.rs @@ -329,7 +329,7 @@ fn to_rgb(c: Color) -> [u8; 3] { let l = (idx - 232) / 24; [l; 3] } - // rink will never generate these colors, but they might be on the screen from another program + // plasmo will never generate these colors, but they might be on the screen from another program _ => [0, 0, 0], }, Color::Reset => [0, 0, 0], diff --git a/packages/rink/src/style_attributes.rs b/packages/plasmo/src/style_attributes.rs similarity index 100% rename from packages/rink/src/style_attributes.rs rename to packages/plasmo/src/style_attributes.rs diff --git a/packages/rink/src/widget.rs b/packages/plasmo/src/widget.rs similarity index 100% rename from packages/rink/src/widget.rs rename to packages/plasmo/src/widget.rs diff --git a/packages/rink/src/widgets/button.rs b/packages/plasmo/src/widgets/button.rs similarity index 100% rename from packages/rink/src/widgets/button.rs rename to packages/plasmo/src/widgets/button.rs diff --git a/packages/rink/src/widgets/checkbox.rs b/packages/plasmo/src/widgets/checkbox.rs similarity index 100% rename from packages/rink/src/widgets/checkbox.rs rename to packages/plasmo/src/widgets/checkbox.rs diff --git a/packages/rink/src/widgets/input.rs b/packages/plasmo/src/widgets/input.rs similarity index 100% rename from packages/rink/src/widgets/input.rs rename to packages/plasmo/src/widgets/input.rs diff --git a/packages/rink/src/widgets/mod.rs b/packages/plasmo/src/widgets/mod.rs similarity index 100% rename from packages/rink/src/widgets/mod.rs rename to packages/plasmo/src/widgets/mod.rs diff --git a/packages/rink/src/widgets/number.rs b/packages/plasmo/src/widgets/number.rs similarity index 100% rename from packages/rink/src/widgets/number.rs rename to packages/plasmo/src/widgets/number.rs diff --git a/packages/rink/src/widgets/password.rs b/packages/plasmo/src/widgets/password.rs similarity index 100% rename from packages/rink/src/widgets/password.rs rename to packages/plasmo/src/widgets/password.rs diff --git a/packages/rink/src/widgets/slider.rs b/packages/plasmo/src/widgets/slider.rs similarity index 100% rename from packages/rink/src/widgets/slider.rs rename to packages/plasmo/src/widgets/slider.rs diff --git a/packages/rink/src/widgets/text_like.rs b/packages/plasmo/src/widgets/text_like.rs similarity index 100% rename from packages/rink/src/widgets/text_like.rs rename to packages/plasmo/src/widgets/text_like.rs diff --git a/packages/rink/src/widgets/textbox.rs b/packages/plasmo/src/widgets/textbox.rs similarity index 100% rename from packages/rink/src/widgets/textbox.rs rename to packages/plasmo/src/widgets/textbox.rs diff --git a/packages/rink/test.html b/packages/plasmo/test.html similarity index 100% rename from packages/rink/test.html rename to packages/plasmo/test.html diff --git a/translations/pt-br/README.md b/translations/pt-br/README.md index 1d2967e23..9b10fb87d 100644 --- a/translations/pt-br/README.md +++ b/translations/pt-br/README.md @@ -167,7 +167,7 @@ Para mais informações sobre quais funções estão atualmente disponíveis e p Quer adentrar e ajudar a construir o futuro do frontend em Rust? Há um vasto número de lugares em que você pode contribuir e fazer uma grande diferença: -- [TUI renderer](https://github.com/dioxusLabs/rink) +- [TUI renderer](https://github.com/dioxusLabs/plasmo) - [Ferramentas CLI](https://github.com/dioxusLabs/cli) - [Documentação e Exemplos de Projeto](https://github.com/dioxusLabs/docsite) - LiveView e Servidor Web