fix native core, plasmo and dioxus-tui

This commit is contained in:
Evan Almloff committed 2024-01-19 09:48:45 -06:00
1 parent 87572d694f
commit 439e39bab4
37 files changed
+588 -266

No files matched your search

+174 -152
View File
@@ -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<V>,
) -> DioxusNativeCoreMutationWriter<'a, V> {
DioxusNativeCoreMutationWriter { rdom, state: self }
}
fn set_element_id<V: FromAnyValue + Send + Sync>(
&mut self,
mut node: NodeMut<V>,
@@ -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<V: FromAnyValue + Send + Sync>(
/// A writer for mutations that can be used with the RealDom.
pub struct DioxusNativeCoreMutationWriter<'a, V: FromAnyValue + Send + Sync = ()> {
pub rdom: &'a mut RealDom<V>,
pub state: &'a mut DioxusState,
}
impl<V: FromAnyValue + Send + Sync> 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<V>,
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<V: FromAnyValue + Send + Sync>(
+9 -8
View File
@@ -201,15 +201,16 @@ impl<V: FromAnyValue> Display for OwnedAttributeValue<V> {
}
#[cfg(feature = "dioxus")]
impl<V: FromAnyValue> From<dioxus_core::BorrowedAttributeValue<'_>> for OwnedAttributeValue<V> {
fn from(value: dioxus_core::BorrowedAttributeValue<'_>) -> Self {
impl<V: FromAnyValue> From<&dioxus_core::AttributeValue> for OwnedAttributeValue<V> {
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"),
}
}
}