dioxus.rs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. use dioxus_core::{BorrowedAttributeValue, ElementId, Mutations, TemplateNode};
  2. use rustc_hash::{FxHashMap, FxHashSet};
  3. use crate::{
  4. node::{ElementNode, FromAnyValue, NodeType, OwnedAttributeDiscription, OwnedAttributeValue},
  5. prelude::{NodeImmutable, NodeMutable},
  6. real_dom::NodeTypeMut,
  7. NodeId, NodeMut, RealDom,
  8. };
  9. pub struct DioxusState {
  10. templates: FxHashMap<String, Vec<NodeId>>,
  11. stack: Vec<NodeId>,
  12. node_id_mapping: Vec<Option<NodeId>>,
  13. }
  14. impl DioxusState {
  15. pub fn create(rdom: &mut RealDom) -> Self {
  16. rdom.insert_slab::<ElementId>();
  17. let root_id = rdom.root_id();
  18. let mut root = rdom.get_mut(root_id).unwrap();
  19. root.insert(ElementId(0));
  20. Self {
  21. templates: FxHashMap::default(),
  22. stack: vec![root_id],
  23. node_id_mapping: vec![Some(root_id)],
  24. }
  25. }
  26. pub fn element_to_node_id(&self, element_id: ElementId) -> NodeId {
  27. self.node_id_mapping.get(element_id.0).unwrap().unwrap()
  28. }
  29. fn set_element_id(&mut self, mut node: NodeMut, element_id: ElementId) {
  30. let node_id = node.id();
  31. node.insert(element_id);
  32. if self.node_id_mapping.len() <= element_id.0 {
  33. self.node_id_mapping.resize(element_id.0 + 1, None);
  34. }
  35. self.node_id_mapping[element_id.0] = Some(node_id);
  36. }
  37. pub fn load_child(&self, rdom: &RealDom, path: &[u8]) -> NodeId {
  38. let mut current = rdom.get(*self.stack.last().unwrap()).unwrap();
  39. for i in path {
  40. let new_id = current.child_ids().unwrap()[*i as usize];
  41. current = rdom.get(new_id).unwrap();
  42. }
  43. current.id()
  44. }
  45. /// Updates the dom with some mutations and return a set of nodes that were updated. Pass the dirty nodes to update_state.
  46. pub fn apply_mutations(&mut self, rdom: &mut RealDom, mutations: Mutations) {
  47. for template in mutations.templates {
  48. let mut template_root_ids = Vec::new();
  49. for root in template.roots {
  50. let id = create_template_node(rdom, root);
  51. template_root_ids.push(id);
  52. }
  53. self.templates
  54. .insert(template.name.to_string(), template_root_ids);
  55. }
  56. for e in mutations.edits {
  57. use dioxus_core::Mutation::*;
  58. match e {
  59. AppendChildren { id, m } => {
  60. let children = self.stack.split_off(self.stack.len() - m);
  61. let parent = self.element_to_node_id(id);
  62. for child in children {
  63. rdom.add_child(parent, child);
  64. }
  65. }
  66. AssignId { path, id } => {
  67. let node_id = self.load_child(rdom, path);
  68. self.set_element_id(rdom.get_mut(node_id).unwrap(), id);
  69. }
  70. CreatePlaceholder { id } => {
  71. let node = NodeType::Placeholder;
  72. let node = rdom.create_node(node);
  73. let node_id = node.id();
  74. self.set_element_id(node, id);
  75. self.stack.push(node_id);
  76. }
  77. CreateTextNode { value, id } => {
  78. let node_data = NodeType::Text(value.to_string());
  79. let node = rdom.create_node(node_data);
  80. let node_id = node.id();
  81. self.set_element_id(node, id);
  82. self.stack.push(node_id);
  83. }
  84. HydrateText { path, value, id } => {
  85. let node_id = self.load_child(rdom, path);
  86. let node = rdom.get_mut(node_id).unwrap();
  87. self.set_element_id(node, id);
  88. let mut node = rdom.get_mut(node_id).unwrap();
  89. if let NodeTypeMut::Text(text) = node.node_type_mut() {
  90. *text = value.to_string();
  91. } else {
  92. node.set_type(NodeType::Text(value.to_string()));
  93. }
  94. }
  95. LoadTemplate { name, index, id } => {
  96. let template_id = self.templates[name][index];
  97. let clone_id = rdom.clone_node(template_id);
  98. let clone = rdom.get_mut(clone_id).unwrap();
  99. self.set_element_id(clone, id);
  100. self.stack.push(clone_id);
  101. }
  102. ReplaceWith { id, m } => {
  103. let new_nodes = self.stack.split_off(self.stack.len() - m);
  104. let old_node_id = self.element_to_node_id(id);
  105. for new in new_nodes {
  106. let mut node = rdom.get_mut(new).unwrap();
  107. node.insert_before(old_node_id);
  108. }
  109. rdom.remove(old_node_id);
  110. }
  111. ReplacePlaceholder { path, m } => {
  112. let new_nodes = self.stack.split_off(self.stack.len() - m);
  113. let old_node_id = self.load_child(rdom, path);
  114. for new in new_nodes {
  115. let mut node = rdom.get_mut(new).unwrap();
  116. node.insert_before(old_node_id);
  117. }
  118. rdom.remove(old_node_id);
  119. }
  120. InsertAfter { id, m } => {
  121. let new_nodes = self.stack.split_off(self.stack.len() - m);
  122. let old_node_id = self.element_to_node_id(id);
  123. for new in new_nodes.into_iter().rev() {
  124. let mut node = rdom.get_mut(new).unwrap();
  125. node.insert_after(old_node_id);
  126. }
  127. }
  128. InsertBefore { id, m } => {
  129. let new_nodes = self.stack.split_off(self.stack.len() - m);
  130. let old_node_id = self.element_to_node_id(id);
  131. for new in new_nodes {
  132. rdom.tree.insert_before(old_node_id, new);
  133. }
  134. }
  135. SetAttribute {
  136. name,
  137. value,
  138. id,
  139. ns,
  140. } => {
  141. let node_id = self.element_to_node_id(id);
  142. let mut node = rdom.get_mut(node_id).unwrap();
  143. if let NodeTypeMut::Element(element) = &mut node.node_type_mut() {
  144. if let BorrowedAttributeValue::None = &value {
  145. element.remove_attributes(&OwnedAttributeDiscription {
  146. name: name.to_string(),
  147. namespace: ns.map(|s| s.to_string()),
  148. volatile: false,
  149. });
  150. } else {
  151. element.set_attribute(
  152. OwnedAttributeDiscription {
  153. name: name.to_string(),
  154. namespace: ns.map(|s| s.to_string()),
  155. volatile: false,
  156. },
  157. OwnedAttributeValue::from(value),
  158. );
  159. }
  160. }
  161. }
  162. SetText { value, id } => {
  163. let node_id = self.element_to_node_id(id);
  164. let mut node = rdom.get_mut(node_id).unwrap();
  165. if let NodeTypeMut::Text(text) = node.node_type_mut() {
  166. *text = value.to_string();
  167. }
  168. }
  169. NewEventListener { name, id } => {
  170. let node_id = self.element_to_node_id(id);
  171. let mut node = rdom.get_mut(node_id).unwrap();
  172. node.add_event_listener(name);
  173. }
  174. RemoveEventListener { id, name } => {
  175. let node_id = self.element_to_node_id(id);
  176. let mut node = rdom.get_mut(node_id).unwrap();
  177. node.remove_event_listener(name);
  178. }
  179. Remove { id } => {
  180. let node_id = self.element_to_node_id(id);
  181. rdom.remove(node_id);
  182. }
  183. PushRoot { id } => {
  184. let node_id = self.element_to_node_id(id);
  185. self.stack.push(node_id);
  186. }
  187. }
  188. }
  189. }
  190. }
  191. fn create_template_node(rdom: &mut RealDom, node: &TemplateNode) -> NodeId {
  192. match node {
  193. TemplateNode::Element {
  194. tag,
  195. namespace,
  196. attrs,
  197. children,
  198. } => {
  199. let node = NodeType::Element(ElementNode {
  200. tag: tag.to_string(),
  201. namespace: namespace.map(|s| s.to_string()),
  202. attributes: attrs
  203. .iter()
  204. .filter_map(|attr| match attr {
  205. dioxus_core::TemplateAttribute::Static {
  206. name,
  207. value,
  208. namespace,
  209. } => Some((
  210. OwnedAttributeDiscription {
  211. namespace: namespace.map(|s| s.to_string()),
  212. name: name.to_string(),
  213. volatile: false,
  214. },
  215. OwnedAttributeValue::Text(value.to_string()),
  216. )),
  217. dioxus_core::TemplateAttribute::Dynamic { .. } => None,
  218. })
  219. .collect(),
  220. listeners: FxHashSet::default(),
  221. });
  222. let node_id = rdom.create_node(node).id();
  223. for child in *children {
  224. let child_id = create_template_node(rdom, child);
  225. rdom.add_child(node_id, child_id);
  226. }
  227. node_id
  228. }
  229. TemplateNode::Text { text } => rdom.create_node(NodeType::Text(text.to_string())).id(),
  230. TemplateNode::Dynamic { .. } => rdom.create_node(NodeType::Placeholder).id(),
  231. TemplateNode::DynamicText { .. } => rdom.create_node(NodeType::Text(String::new())).id(),
  232. }
  233. }
  234. trait NodeImmutableDioxusExt<V: FromAnyValue + Send + Sync>: NodeImmutable<V> {
  235. fn mounted_id(&self) -> Option<ElementId> {
  236. self.get().copied()
  237. }
  238. }
  239. impl<T: NodeImmutable<V>, V: FromAnyValue + Send + Sync> NodeImmutableDioxusExt<V> for T {}