123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- use crate::unified_bindings::Interpreter as Channel;
- use dioxus_core::{Template, TemplateAttribute, TemplateNode, WriteMutations};
- use dioxus_html::event_bubbles;
- use rustc_hash::FxHashMap;
- /// The state needed to apply mutations to a channel. This state should be kept across all mutations for the app
- #[derive(Default)]
- pub struct MutationState {
- /// The currently registered templates with the template ids
- templates: FxHashMap<Template, u16>,
- /// The channel that we are applying mutations to
- channel: Channel,
- }
- impl MutationState {
- pub fn new() -> Self {
- Self::default()
- }
- pub fn export_memory(&mut self) -> Vec<u8> {
- let bytes: Vec<_> = self.channel.export_memory().collect();
- self.channel.reset();
- bytes
- }
- pub fn write_memory_into(&mut self, buffer: &mut Vec<u8>) {
- buffer.extend(self.channel.export_memory());
- self.channel.reset();
- }
- pub fn channel(&mut self) -> &mut Channel {
- &mut self.channel
- }
- pub fn channel_mut(&mut self) -> &mut Channel {
- &mut self.channel
- }
- fn create_template_node(&mut self, node: &'static TemplateNode) {
- use TemplateNode::*;
- match node {
- Element {
- tag,
- namespace,
- attrs,
- children,
- ..
- } => {
- // Push the current node onto the stack
- match namespace {
- Some(ns) => self.channel.create_element_ns(tag, ns),
- None => self.channel.create_element(tag),
- }
- // Set attributes on the current node
- for attr in *attrs {
- if let TemplateAttribute::Static {
- name,
- value,
- namespace,
- } = attr
- {
- self.channel
- .set_top_attribute(name, value, namespace.unwrap_or_default())
- }
- }
- // Add each child to the stack
- for child in *children {
- self.create_template_node(child);
- }
- // Add all children to the parent
- self.channel.append_children_to_top(children.len() as u16);
- }
- Text { text } => self.channel.create_raw_text(text),
- Dynamic { .. } => self.channel.add_placeholder(),
- }
- }
- }
- impl WriteMutations for MutationState {
- fn append_children(&mut self, id: dioxus_core::ElementId, m: usize) {
- self.channel.append_children(id.0 as u32, m as u16);
- }
- fn assign_node_id(&mut self, path: &'static [u8], id: dioxus_core::ElementId) {
- self.channel.assign_id_ref(path, id.0 as u32);
- }
- fn create_placeholder(&mut self, id: dioxus_core::ElementId) {
- self.channel.create_placeholder(id.0 as u32);
- }
- fn create_text_node(&mut self, value: &str, id: dioxus_core::ElementId) {
- self.channel.create_text_node(value, id.0 as u32);
- }
- fn load_template(&mut self, template: Template, index: usize, id: dioxus_core::ElementId) {
- // Get the template or create it if we haven't seen it before
- let tmpl_id = self.templates.get(&template).cloned().unwrap_or_else(|| {
- let tmpl_id = self.templates.len() as u16;
- self.templates.insert(template, tmpl_id);
- for root in template.roots.iter() {
- self.create_template_node(root);
- }
- let len = template.roots.len() as u16;
- self.channel.add_templates(tmpl_id, len);
- tmpl_id
- });
- self.channel
- .load_template(tmpl_id, index as u16, id.0 as u32);
- }
- fn replace_node_with(&mut self, id: dioxus_core::ElementId, m: usize) {
- self.channel.replace_with(id.0 as u32, m as u16);
- }
- fn replace_placeholder_with_nodes(&mut self, path: &'static [u8], m: usize) {
- self.channel.replace_placeholder_ref(path, m as u16);
- }
- fn insert_nodes_after(&mut self, id: dioxus_core::ElementId, m: usize) {
- self.channel.insert_after(id.0 as u32, m as u16);
- }
- fn insert_nodes_before(&mut self, id: dioxus_core::ElementId, m: usize) {
- self.channel.insert_before(id.0 as u32, m as u16);
- }
- fn set_attribute(
- &mut self,
- name: &'static str,
- ns: Option<&'static str>,
- value: &dioxus_core::AttributeValue,
- id: dioxus_core::ElementId,
- ) {
- match value {
- dioxus_core::AttributeValue::Text(txt) => {
- self.channel
- .set_attribute(id.0 as u32, name, txt, ns.unwrap_or_default())
- }
- dioxus_core::AttributeValue::Float(f) => self.channel.set_attribute(
- id.0 as u32,
- name,
- &f.to_string(),
- ns.unwrap_or_default(),
- ),
- dioxus_core::AttributeValue::Int(n) => self.channel.set_attribute(
- id.0 as u32,
- name,
- &n.to_string(),
- ns.unwrap_or_default(),
- ),
- dioxus_core::AttributeValue::Bool(b) => self.channel.set_attribute(
- id.0 as u32,
- name,
- if *b { "true" } else { "false" },
- ns.unwrap_or_default(),
- ),
- dioxus_core::AttributeValue::None => {
- self.channel
- .remove_attribute(id.0 as u32, name, ns.unwrap_or_default())
- }
- _ => unreachable!("Any attributes are not supported by the current renderer"),
- }
- }
- fn set_node_text(&mut self, value: &str, id: dioxus_core::ElementId) {
- self.channel.set_text(id.0 as u32, value);
- }
- fn create_event_listener(&mut self, name: &'static str, id: dioxus_core::ElementId) {
- // note that we use the foreign event listener here instead of the native one
- // the native method assumes we have direct access to the dom, which we don't.
- self.channel
- .foreign_event_listener(name, id.0 as u32, event_bubbles(name) as u8);
- }
- fn remove_event_listener(&mut self, name: &'static str, id: dioxus_core::ElementId) {
- self.channel
- .remove_event_listener(name, id.0 as u32, event_bubbles(name) as u8);
- }
- fn remove_node(&mut self, id: dioxus_core::ElementId) {
- self.channel.remove(id.0 as u32);
- }
- fn push_root(&mut self, id: dioxus_core::ElementId) {
- self.channel.push_root(id.0 as _);
- }
- }
- /// A synchronous response to a browser event which may prevent the default browser's action
- #[cfg_attr(feature = "serialize", derive(serde::Serialize))]
- #[derive(Default)]
- pub struct SynchronousEventResponse {
- #[cfg(feature = "serialize")]
- #[serde(rename = "preventDefault")]
- prevent_default: bool,
- }
- impl SynchronousEventResponse {
- /// Create a new SynchronousEventResponse
- #[allow(unused)]
- pub fn new(prevent_default: bool) -> Self {
- Self {
- #[cfg(feature = "serialize")]
- prevent_default,
- }
- }
- }
|