mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 06:34:20 +00:00
Feat: desktop app wired up
This commit is contained in:
parent
bcbb93b697
commit
b3e6886351
10 changed files with 744 additions and 269 deletions
|
@ -19,6 +19,8 @@
|
|||
//!
|
||||
//!
|
||||
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use bumpalo::Bump;
|
||||
|
||||
use crate::innerlude::{Listener, VirtualDom};
|
||||
|
@ -32,8 +34,9 @@ use crate::innerlude::{Listener, VirtualDom};
|
|||
///
|
||||
///
|
||||
///
|
||||
///
|
||||
#[derive(Debug)]
|
||||
/// todo@ jon: allow serde to be optional
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum Edit<'d> {
|
||||
SetText { text: &'d str },
|
||||
RemoveSelfAndNextSiblings {},
|
||||
|
@ -59,20 +62,23 @@ pub enum Edit<'d> {
|
|||
SetClass { class_name: &'d str },
|
||||
}
|
||||
|
||||
pub struct EditList<'src> {
|
||||
pub type EditList<'src> = Vec<Edit<'src>>;
|
||||
|
||||
pub struct EditMachine<'src> {
|
||||
pub traversal: Traversal,
|
||||
next_temporary: u32,
|
||||
forcing_new_listeners: bool,
|
||||
pub emitter: Vec<Edit<'src>>,
|
||||
|
||||
pub emitter: EditList<'src>,
|
||||
}
|
||||
|
||||
impl<'b> EditList<'b> {
|
||||
impl<'b> EditMachine<'b> {
|
||||
pub fn new(bump: &'b Bump) -> Self {
|
||||
Self {
|
||||
traversal: Traversal::new(),
|
||||
next_temporary: 0,
|
||||
forcing_new_listeners: false,
|
||||
emitter: Vec::new(),
|
||||
emitter: EditList::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,7 +159,7 @@ impl<'b> EditList<'b> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> EditList<'a> {
|
||||
impl<'a> EditMachine<'a> {
|
||||
pub fn next_temporary(&self) -> u32 {
|
||||
self.next_temporary
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ use fxhash::{FxHashMap, FxHashSet};
|
|||
use generational_arena::Index;
|
||||
|
||||
use crate::{
|
||||
changelist::{Edit, EditList},
|
||||
changelist::{Edit, EditList, EditMachine},
|
||||
innerlude::{Attribute, Listener, Scope, VElement, VNode, VText},
|
||||
virtual_dom::LifecycleEvent,
|
||||
};
|
||||
|
@ -57,7 +57,7 @@ use std::cmp::Ordering;
|
|||
/// that were modified by the eventtrigger. This prevents doubly evaluating components if they wereboth updated via
|
||||
/// subscriptions and props changes.
|
||||
pub struct DiffMachine<'a> {
|
||||
pub change_list: EditList<'a>,
|
||||
pub change_list: EditMachine<'a>,
|
||||
immediate_queue: Vec<Index>,
|
||||
diffed: FxHashSet<Index>,
|
||||
need_to_diff: FxHashSet<Index>,
|
||||
|
@ -71,14 +71,14 @@ enum NeedToDiff {
|
|||
impl<'a> DiffMachine<'a> {
|
||||
pub fn new(bump: &'a Bump) -> Self {
|
||||
Self {
|
||||
change_list: EditList::new(bump),
|
||||
change_list: EditMachine::new(bump),
|
||||
immediate_queue: Vec::new(),
|
||||
diffed: FxHashSet::default(),
|
||||
need_to_diff: FxHashSet::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn consume(self) -> Vec<Edit<'a>> {
|
||||
pub fn consume(self) -> EditList<'a> {
|
||||
self.change_list.emitter
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,11 @@ impl EventTrigger {
|
|||
}
|
||||
|
||||
pub enum VirtualEvent {
|
||||
// the event to drain the current lifecycle queue
|
||||
// Used to initate the dom
|
||||
InitiateEvent,
|
||||
|
||||
// Real events
|
||||
ClipboardEvent,
|
||||
CompositionEvent,
|
||||
KeyboardEvent,
|
||||
|
|
|
@ -21,7 +21,8 @@ use std::{
|
|||
///
|
||||
/// Scopes are allocated in a generational arena. As components are mounted/unmounted, they will replace slots of dead components.
|
||||
/// The actual contents of the hooks, though, will be allocated with the standard allocator. These should not allocate as frequently.
|
||||
pub(crate) struct Scope {
|
||||
pub struct Scope {
|
||||
// pub(crate) struct Scope {
|
||||
// TODO @Jon
|
||||
// These hooks are actually references into the hook arena
|
||||
// These two could be combined with "OwningRef" to remove unsafe usage
|
||||
|
@ -50,23 +51,10 @@ pub(crate) struct Scope {
|
|||
pub caller: *const i32,
|
||||
}
|
||||
|
||||
// pub enum ActiveFrame {
|
||||
// First,
|
||||
// Second,
|
||||
// }
|
||||
|
||||
// impl ActiveFrame {
|
||||
// fn next(&mut self) {
|
||||
// match self {
|
||||
// ActiveFrame::First => *self = ActiveFrame::Second,
|
||||
// ActiveFrame::Second => *self = ActiveFrame::First,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl Scope {
|
||||
// create a new scope from a function
|
||||
pub(crate) fn new<T: 'static>(
|
||||
pub fn new<T: 'static>(
|
||||
// pub(crate) fn new<T: 'static>(
|
||||
f: FC<T>,
|
||||
props: impl Properties + 'static,
|
||||
parent: Option<Index>,
|
||||
|
@ -120,7 +108,7 @@ impl Scope {
|
|||
/// This function downcasts the function pointer based on the stored props_type
|
||||
///
|
||||
/// Props is ?Sized because we borrow the props and don't need to know the size. P (sized) is used as a marker (unsized)
|
||||
pub(crate) fn run<'bump, P: Properties + Sized + 'static>(&'bump mut self) {
|
||||
pub fn run<'bump, P: Properties + Sized + 'static>(&'bump mut self) {
|
||||
let frame = {
|
||||
let frame = self.frames.next();
|
||||
frame.bump.reset();
|
||||
|
@ -164,14 +152,12 @@ impl Scope {
|
|||
|
||||
let unsafe_node = unsafe { std::mem::transmute::<VNode<'bump>, VNode<'static>>(nodes) };
|
||||
frame.head_node = unsafe_node;
|
||||
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Accessor to get the root node and its children (safely)\
|
||||
/// Scope is self-referntial, so we are forced to use the 'static lifetime to cheat
|
||||
pub fn current_root_node<'bump>(&'bump self) -> &'bump VNode<'bump> {
|
||||
todo!()
|
||||
self.frames.current_head_node()
|
||||
}
|
||||
pub fn prev_root_node<'bump>(&'bump self) -> &'bump VNode<'bump> {
|
||||
todo!()
|
||||
|
@ -196,6 +182,16 @@ impl ActiveFrame {
|
|||
}
|
||||
}
|
||||
|
||||
fn current_head_node<'b>(&'b self) -> &'b VNode<'b> {
|
||||
let cur_idx = self.idx.borrow().load(std::sync::atomic::Ordering::Relaxed);
|
||||
let raw_node = &self.frames[cur_idx];
|
||||
unsafe {
|
||||
let unsafe_head = &raw_node.head_node;
|
||||
let safe_node = std::mem::transmute::<&VNode<'static>, &VNode<'b>>(unsafe_head);
|
||||
safe_node
|
||||
}
|
||||
}
|
||||
|
||||
fn next(&mut self) -> &mut BumpFrame {
|
||||
self.idx.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||
let cur = self.idx.borrow().load(std::sync::atomic::Ordering::Relaxed);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
// use crate::{changelist::EditList, nodes::VNode};
|
||||
use crate::{dodriodiff::DiffMachine, nodes::VNode};
|
||||
use crate::{changelist::{self, EditList}, dodriodiff::DiffMachine, nodes::VNode};
|
||||
use crate::{events::EventTrigger, innerlude::*};
|
||||
use any::Any;
|
||||
use bumpalo::Bump;
|
||||
use changelist::EditMachine;
|
||||
use generational_arena::{Arena, Index};
|
||||
use std::{
|
||||
any::{self, TypeId},
|
||||
|
@ -105,6 +106,10 @@ impl VirtualDom {
|
|||
/// This lets services external to the virtual dom interact directly with the component and event system.
|
||||
pub fn queue_update() {}
|
||||
|
||||
pub fn start(&mut self) -> Result<EditList> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Pop an event off the event queue and process it
|
||||
/// Update the root props, and progress
|
||||
/// Takes a bump arena to allocate into, making the diff phase as fast as possible
|
||||
|
@ -115,7 +120,7 @@ impl VirtualDom {
|
|||
.borrow_mut()
|
||||
.pop_front()
|
||||
.ok_or(Error::NoEvent)?;
|
||||
self.process_event(event)
|
||||
self.process_lifecycle(event)
|
||||
}
|
||||
|
||||
/// This method is the most sophisticated way of updating the virtual dom after an external event has been triggered.
|
||||
|
@ -171,7 +176,7 @@ impl VirtualDom {
|
|||
new_evt
|
||||
} {
|
||||
affected_components.push(event.component_index);
|
||||
self.process_event(event)?;
|
||||
self.process_lifecycle(event)?;
|
||||
}
|
||||
|
||||
let diff_bump = Bump::new();
|
||||
|
@ -180,9 +185,6 @@ impl VirtualDom {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn progress_completely(&mut self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
/// Using mutable access to the Virtual Dom, progress a given lifecycle event
|
||||
///
|
||||
///
|
||||
|
@ -190,7 +192,7 @@ impl VirtualDom {
|
|||
///
|
||||
///
|
||||
///
|
||||
fn process_event(
|
||||
fn process_lifecycle(
|
||||
&mut self,
|
||||
LifecycleEvent {
|
||||
component_index: index,
|
||||
|
|
|
@ -380,257 +380,257 @@ impl PatchMachine {
|
|||
}
|
||||
}
|
||||
|
||||
// 0
|
||||
pub fn set_text(&mut self, text: &str) {
|
||||
self.stack.top().set_text_content(Some(text));
|
||||
}
|
||||
// // 0
|
||||
// pub fn set_text(&mut self, text: &str) {
|
||||
// self.stack.top().set_text_content(Some(text));
|
||||
// }
|
||||
|
||||
// 1
|
||||
pub fn remove_self_and_next_siblings(&mut self) {
|
||||
let node = self.stack.pop();
|
||||
let mut sibling = node.next_sibling();
|
||||
// // 1
|
||||
// pub fn remove_self_and_next_siblings(&mut self) {
|
||||
// let node = self.stack.pop();
|
||||
// let mut sibling = node.next_sibling();
|
||||
|
||||
while let Some(inner) = sibling {
|
||||
let temp = inner.next_sibling();
|
||||
if let Some(sibling) = inner.dyn_ref::<Element>() {
|
||||
sibling.remove();
|
||||
}
|
||||
sibling = temp;
|
||||
}
|
||||
if let Some(node) = node.dyn_ref::<Element>() {
|
||||
node.remove();
|
||||
}
|
||||
}
|
||||
// while let Some(inner) = sibling {
|
||||
// let temp = inner.next_sibling();
|
||||
// if let Some(sibling) = inner.dyn_ref::<Element>() {
|
||||
// sibling.remove();
|
||||
// }
|
||||
// sibling = temp;
|
||||
// }
|
||||
// if let Some(node) = node.dyn_ref::<Element>() {
|
||||
// node.remove();
|
||||
// }
|
||||
// }
|
||||
|
||||
// 2
|
||||
pub fn replace_with(&mut self) {
|
||||
let new_node = self.stack.pop();
|
||||
let old_node = self.stack.pop();
|
||||
// // 2
|
||||
// pub fn replace_with(&mut self) {
|
||||
// let new_node = self.stack.pop();
|
||||
// let old_node = self.stack.pop();
|
||||
|
||||
if old_node.has_type::<Element>() {
|
||||
old_node
|
||||
.dyn_ref::<Element>()
|
||||
.unwrap()
|
||||
.replace_with_with_node_1(&new_node)
|
||||
.unwrap();
|
||||
} else if old_node.has_type::<web_sys::CharacterData>() {
|
||||
old_node
|
||||
.dyn_ref::<web_sys::CharacterData>()
|
||||
.unwrap()
|
||||
.replace_with_with_node_1(&new_node)
|
||||
.unwrap();
|
||||
} else if old_node.has_type::<web_sys::DocumentType>() {
|
||||
old_node
|
||||
.dyn_ref::<web_sys::DocumentType>()
|
||||
.unwrap()
|
||||
.replace_with_with_node_1(&new_node)
|
||||
.unwrap();
|
||||
} else {
|
||||
panic!("Cannot replace node: {:?}", old_node);
|
||||
}
|
||||
// if old_node.has_type::<Element>() {
|
||||
// old_node
|
||||
// .dyn_ref::<Element>()
|
||||
// .unwrap()
|
||||
// .replace_with_with_node_1(&new_node)
|
||||
// .unwrap();
|
||||
// } else if old_node.has_type::<web_sys::CharacterData>() {
|
||||
// old_node
|
||||
// .dyn_ref::<web_sys::CharacterData>()
|
||||
// .unwrap()
|
||||
// .replace_with_with_node_1(&new_node)
|
||||
// .unwrap();
|
||||
// } else if old_node.has_type::<web_sys::DocumentType>() {
|
||||
// old_node
|
||||
// .dyn_ref::<web_sys::DocumentType>()
|
||||
// .unwrap()
|
||||
// .replace_with_with_node_1(&new_node)
|
||||
// .unwrap();
|
||||
// } else {
|
||||
// panic!("Cannot replace node: {:?}", old_node);
|
||||
// }
|
||||
|
||||
self.stack.push(new_node);
|
||||
}
|
||||
// self.stack.push(new_node);
|
||||
// }
|
||||
|
||||
// 3
|
||||
pub fn set_attribute(&mut self, name: &str, value: &str) {
|
||||
let node = self.stack.top();
|
||||
// // 3
|
||||
// pub fn set_attribute(&mut self, name: &str, value: &str) {
|
||||
// let node = self.stack.top();
|
||||
|
||||
if let Some(node) = node.dyn_ref::<Element>() {
|
||||
node.set_attribute(name, value).unwrap();
|
||||
// if let Some(node) = node.dyn_ref::<Element>() {
|
||||
// node.set_attribute(name, value).unwrap();
|
||||
|
||||
// Some attributes are "volatile" and don't work through `setAttribute`.
|
||||
// TODO:
|
||||
// if name == "value" {
|
||||
// node.set_value(value);
|
||||
// }
|
||||
// if name == "checked" {
|
||||
// node.set_checked(true);
|
||||
// }
|
||||
// if name == "selected" {
|
||||
// node.set_selected(true);
|
||||
// }
|
||||
}
|
||||
}
|
||||
// // Some attributes are "volatile" and don't work through `setAttribute`.
|
||||
// // TODO:
|
||||
// // if name == "value" {
|
||||
// // node.set_value(value);
|
||||
// // }
|
||||
// // if name == "checked" {
|
||||
// // node.set_checked(true);
|
||||
// // }
|
||||
// // if name == "selected" {
|
||||
// // node.set_selected(true);
|
||||
// // }
|
||||
// }
|
||||
// }
|
||||
|
||||
// 4
|
||||
pub fn remove_attribute(&mut self, name: &str) {
|
||||
let node = self.stack.top();
|
||||
if let Some(node) = node.dyn_ref::<Element>() {
|
||||
node.remove_attribute(name).unwrap();
|
||||
// // 4
|
||||
// pub fn remove_attribute(&mut self, name: &str) {
|
||||
// let node = self.stack.top();
|
||||
// if let Some(node) = node.dyn_ref::<Element>() {
|
||||
// node.remove_attribute(name).unwrap();
|
||||
|
||||
// Some attributes are "volatile" and don't work through `removeAttribute`.
|
||||
// TODO:
|
||||
// if name == "value" {
|
||||
// node.set_value("");
|
||||
// }
|
||||
// if name == "checked" {
|
||||
// node.set_checked(false);
|
||||
// }
|
||||
// if name == "selected" {
|
||||
// node.set_selected(false);
|
||||
// }
|
||||
}
|
||||
}
|
||||
// // Some attributes are "volatile" and don't work through `removeAttribute`.
|
||||
// // TODO:
|
||||
// // if name == "value" {
|
||||
// // node.set_value("");
|
||||
// // }
|
||||
// // if name == "checked" {
|
||||
// // node.set_checked(false);
|
||||
// // }
|
||||
// // if name == "selected" {
|
||||
// // node.set_selected(false);
|
||||
// // }
|
||||
// }
|
||||
// }
|
||||
|
||||
// 5
|
||||
pub fn push_reverse_child(&mut self, n: u32) {
|
||||
let parent = self.stack.top();
|
||||
let children = parent.child_nodes();
|
||||
let child = children.get(children.length() - n - 1).unwrap();
|
||||
self.stack.push(child);
|
||||
}
|
||||
// // 5
|
||||
// pub fn push_reverse_child(&mut self, n: u32) {
|
||||
// let parent = self.stack.top();
|
||||
// let children = parent.child_nodes();
|
||||
// let child = children.get(children.length() - n - 1).unwrap();
|
||||
// self.stack.push(child);
|
||||
// }
|
||||
|
||||
// 6
|
||||
pub fn pop_push_child(&mut self, n: u32) {
|
||||
self.stack.pop();
|
||||
let parent = self.stack.top();
|
||||
let children = parent.child_nodes();
|
||||
let child = children.get(n).unwrap();
|
||||
self.stack.push(child);
|
||||
}
|
||||
// // 6
|
||||
// pub fn pop_push_child(&mut self, n: u32) {
|
||||
// self.stack.pop();
|
||||
// let parent = self.stack.top();
|
||||
// let children = parent.child_nodes();
|
||||
// let child = children.get(n).unwrap();
|
||||
// self.stack.push(child);
|
||||
// }
|
||||
|
||||
// 7
|
||||
pub fn pop(&mut self) {
|
||||
self.stack.pop();
|
||||
}
|
||||
// // 7
|
||||
// pub fn pop(&mut self) {
|
||||
// self.stack.pop();
|
||||
// }
|
||||
|
||||
// 8
|
||||
pub fn append_child(&mut self) {
|
||||
let child = self.stack.pop();
|
||||
self.stack.top().append_child(&child).unwrap();
|
||||
}
|
||||
// // 8
|
||||
// pub fn append_child(&mut self) {
|
||||
// let child = self.stack.pop();
|
||||
// self.stack.top().append_child(&child).unwrap();
|
||||
// }
|
||||
|
||||
// 9
|
||||
pub fn create_text_node(&mut self, text: &str) {
|
||||
self.stack.push(
|
||||
self.document
|
||||
.create_text_node(text)
|
||||
.dyn_into::<Node>()
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
// // 9
|
||||
// pub fn create_text_node(&mut self, text: &str) {
|
||||
// self.stack.push(
|
||||
// self.document
|
||||
// .create_text_node(text)
|
||||
// .dyn_into::<Node>()
|
||||
// .unwrap(),
|
||||
// );
|
||||
// }
|
||||
|
||||
// 10
|
||||
pub fn create_element(&mut self, tag_name: &str) {
|
||||
let el = self
|
||||
.document
|
||||
.create_element(tag_name)
|
||||
.unwrap()
|
||||
.dyn_into::<Node>()
|
||||
.unwrap();
|
||||
self.stack.push(el);
|
||||
}
|
||||
// // 10
|
||||
// pub fn create_element(&mut self, tag_name: &str) {
|
||||
// let el = self
|
||||
// .document
|
||||
// .create_element(tag_name)
|
||||
// .unwrap()
|
||||
// .dyn_into::<Node>()
|
||||
// .unwrap();
|
||||
// self.stack.push(el);
|
||||
// }
|
||||
|
||||
// 11
|
||||
pub fn new_event_listener(&mut self, event_type: &str, a: u32, b: u32) {
|
||||
let el = self.stack.top();
|
||||
// // 11
|
||||
// pub fn new_event_listener(&mut self, event_type: &str, a: u32, b: u32) {
|
||||
// let el = self.stack.top();
|
||||
|
||||
let el = el
|
||||
.dyn_ref::<Element>()
|
||||
.expect(&format!("not an element: {:?}", el));
|
||||
el.add_event_listener_with_callback(
|
||||
event_type,
|
||||
self.callback.as_ref().unwrap().as_ref().unchecked_ref(),
|
||||
)
|
||||
.unwrap();
|
||||
debug!("adding attributes: {}, {}", a, b);
|
||||
el.set_attribute(&format!("dodrio-a-{}", event_type), &a.to_string())
|
||||
.unwrap();
|
||||
el.set_attribute(&format!("dodrio-b-{}", event_type), &b.to_string())
|
||||
.unwrap();
|
||||
}
|
||||
// let el = el
|
||||
// .dyn_ref::<Element>()
|
||||
// .expect(&format!("not an element: {:?}", el));
|
||||
// el.add_event_listener_with_callback(
|
||||
// event_type,
|
||||
// self.callback.as_ref().unwrap().as_ref().unchecked_ref(),
|
||||
// )
|
||||
// .unwrap();
|
||||
// debug!("adding attributes: {}, {}", a, b);
|
||||
// el.set_attribute(&format!("dodrio-a-{}", event_type), &a.to_string())
|
||||
// .unwrap();
|
||||
// el.set_attribute(&format!("dodrio-b-{}", event_type), &b.to_string())
|
||||
// .unwrap();
|
||||
// }
|
||||
|
||||
// 12
|
||||
pub fn update_event_listener(&mut self, event_type: &str, a: u32, b: u32) {
|
||||
if let Some(el) = self.stack.top().dyn_ref::<Element>() {
|
||||
el.set_attribute(&format!("dodrio-a-{}", event_type), &a.to_string())
|
||||
.unwrap();
|
||||
el.set_attribute(&format!("dodrio-b-{}", event_type), &b.to_string())
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
// // 12
|
||||
// pub fn update_event_listener(&mut self, event_type: &str, a: u32, b: u32) {
|
||||
// if let Some(el) = self.stack.top().dyn_ref::<Element>() {
|
||||
// el.set_attribute(&format!("dodrio-a-{}", event_type), &a.to_string())
|
||||
// .unwrap();
|
||||
// el.set_attribute(&format!("dodrio-b-{}", event_type), &b.to_string())
|
||||
// .unwrap();
|
||||
// }
|
||||
// }
|
||||
|
||||
// 13
|
||||
pub fn remove_event_listener(&mut self, event_type: &str) {
|
||||
if let Some(el) = self.stack.top().dyn_ref::<Element>() {
|
||||
el.remove_event_listener_with_callback(
|
||||
event_type,
|
||||
self.callback.as_ref().unwrap().as_ref().unchecked_ref(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
// // 13
|
||||
// pub fn remove_event_listener(&mut self, event_type: &str) {
|
||||
// if let Some(el) = self.stack.top().dyn_ref::<Element>() {
|
||||
// el.remove_event_listener_with_callback(
|
||||
// event_type,
|
||||
// self.callback.as_ref().unwrap().as_ref().unchecked_ref(),
|
||||
// )
|
||||
// .unwrap();
|
||||
// }
|
||||
// }
|
||||
|
||||
// 16
|
||||
pub fn create_element_ns(&mut self, tag_name: &str, ns: &str) {
|
||||
let el = self
|
||||
.document
|
||||
.create_element_ns(Some(ns), tag_name)
|
||||
.unwrap()
|
||||
.dyn_into::<Node>()
|
||||
.unwrap();
|
||||
self.stack.push(el);
|
||||
}
|
||||
// // 16
|
||||
// pub fn create_element_ns(&mut self, tag_name: &str, ns: &str) {
|
||||
// let el = self
|
||||
// .document
|
||||
// .create_element_ns(Some(ns), tag_name)
|
||||
// .unwrap()
|
||||
// .dyn_into::<Node>()
|
||||
// .unwrap();
|
||||
// self.stack.push(el);
|
||||
// }
|
||||
|
||||
// 17
|
||||
pub fn save_children_to_temporaries(&mut self, mut temp: u32, start: u32, end: u32) {
|
||||
let parent = self.stack.top();
|
||||
let children = parent.child_nodes();
|
||||
for i in start..end {
|
||||
self.temporaries.insert(temp, children.get(i).unwrap());
|
||||
temp += 1;
|
||||
}
|
||||
}
|
||||
// // 17
|
||||
// pub fn save_children_to_temporaries(&mut self, mut temp: u32, start: u32, end: u32) {
|
||||
// let parent = self.stack.top();
|
||||
// let children = parent.child_nodes();
|
||||
// for i in start..end {
|
||||
// self.temporaries.insert(temp, children.get(i).unwrap());
|
||||
// temp += 1;
|
||||
// }
|
||||
// }
|
||||
|
||||
// 18
|
||||
pub fn push_child(&mut self, n: u32) {
|
||||
let parent = self.stack.top();
|
||||
let child = parent.child_nodes().get(n).unwrap();
|
||||
self.stack.push(child);
|
||||
}
|
||||
// // 18
|
||||
// pub fn push_child(&mut self, n: u32) {
|
||||
// let parent = self.stack.top();
|
||||
// let child = parent.child_nodes().get(n).unwrap();
|
||||
// self.stack.push(child);
|
||||
// }
|
||||
|
||||
// 19
|
||||
pub fn push_temporary(&mut self, temp: u32) {
|
||||
let t = self.temporaries.get(&temp).unwrap().clone();
|
||||
self.stack.push(t);
|
||||
}
|
||||
// // 19
|
||||
// pub fn push_temporary(&mut self, temp: u32) {
|
||||
// let t = self.temporaries.get(&temp).unwrap().clone();
|
||||
// self.stack.push(t);
|
||||
// }
|
||||
|
||||
// 20
|
||||
pub fn insert_before(&mut self) {
|
||||
let before = self.stack.pop();
|
||||
let after = self.stack.pop();
|
||||
after
|
||||
.parent_node()
|
||||
.unwrap()
|
||||
.insert_before(&before, Some(&after))
|
||||
.unwrap();
|
||||
self.stack.push(before);
|
||||
}
|
||||
// // 20
|
||||
// pub fn insert_before(&mut self) {
|
||||
// let before = self.stack.pop();
|
||||
// let after = self.stack.pop();
|
||||
// after
|
||||
// .parent_node()
|
||||
// .unwrap()
|
||||
// .insert_before(&before, Some(&after))
|
||||
// .unwrap();
|
||||
// self.stack.push(before);
|
||||
// }
|
||||
|
||||
// 21
|
||||
pub fn pop_push_reverse_child(&mut self, n: u32) {
|
||||
self.stack.pop();
|
||||
let parent = self.stack.top();
|
||||
let children = parent.child_nodes();
|
||||
let child = children.get(children.length() - n - 1).unwrap();
|
||||
self.stack.push(child);
|
||||
}
|
||||
// // 21
|
||||
// pub fn pop_push_reverse_child(&mut self, n: u32) {
|
||||
// self.stack.pop();
|
||||
// let parent = self.stack.top();
|
||||
// let children = parent.child_nodes();
|
||||
// let child = children.get(children.length() - n - 1).unwrap();
|
||||
// self.stack.push(child);
|
||||
// }
|
||||
|
||||
// 22
|
||||
pub fn remove_child(&mut self, n: u32) {
|
||||
let parent = self.stack.top();
|
||||
if let Some(child) = parent.child_nodes().get(n).unwrap().dyn_ref::<Element>() {
|
||||
child.remove();
|
||||
}
|
||||
}
|
||||
// // 22
|
||||
// pub fn remove_child(&mut self, n: u32) {
|
||||
// let parent = self.stack.top();
|
||||
// if let Some(child) = parent.child_nodes().get(n).unwrap().dyn_ref::<Element>() {
|
||||
// child.remove();
|
||||
// }
|
||||
// }
|
||||
|
||||
// 23
|
||||
pub fn set_class(&mut self, class_name: &str) {
|
||||
if let Some(el) = self.stack.top().dyn_ref::<Element>() {
|
||||
el.set_class_name(class_name);
|
||||
}
|
||||
}
|
||||
// // 23
|
||||
// pub fn set_class(&mut self, class_name: &str) {
|
||||
// if let Some(el) = self.stack.top().dyn_ref::<Element>() {
|
||||
// el.set_class_name(class_name);
|
||||
// }
|
||||
// }
|
||||
|
||||
// 24
|
||||
pub fn save_template(&mut self, id: CacheId) {
|
||||
|
|
|
@ -9,6 +9,13 @@ edition = "2018"
|
|||
[dependencies]
|
||||
web-view = "0.7.2"
|
||||
dioxus-core = { path = "../core" }
|
||||
|
||||
anyhow = "1.0.38"
|
||||
argh = "0.1.4"
|
||||
serde = "1.0.120"
|
||||
serde_json = "1.0.61"
|
||||
async-std = { version = "1.9.0", features = ["attributes"] }
|
||||
thiserror = "1.0.23"
|
||||
log = "0.4.13"
|
||||
fern = { version = "0.6.0", features = ["colored"] }
|
||||
|
||||
[build-dependencies]
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
// This file interperets incoming edit messages into the page and renders them.
|
||||
// This is written in javascript to be slightly easier to work with (instead of having to pre-compile the wasm)
|
||||
// One day, we'll probably using wasmbindgen for the inner, but a javascripty one is fine too.
|
|
@ -1,20 +1,152 @@
|
|||
//! An example where the dioxus vdom is running in a native thread, interacting with webview
|
||||
|
||||
fn main() {
|
||||
let html_content = "<div>Hello world!</div>";
|
||||
use std::{
|
||||
borrow::BorrowMut,
|
||||
rc::Rc,
|
||||
sync::{mpsc::channel, Arc},
|
||||
};
|
||||
|
||||
web_view::builder()
|
||||
// use async_std::{channel, task::block_on};
|
||||
|
||||
use dioxus_core::{dodriodiff::DiffMachine, prelude::bumpalo::Bump, prelude::*, scope};
|
||||
use scope::Scope;
|
||||
use web_view::Handle;
|
||||
static HTML_CONTENT: &'static str = include_str!("./index.html");
|
||||
|
||||
enum InnerEvent {
|
||||
Initiate(Handle<()>),
|
||||
}
|
||||
|
||||
// async_std::task::spawn(async {
|
||||
// #[async_std::main]
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let (sender, receiver) = channel::<InnerEvent>();
|
||||
// let (sender, receiver) = channel::unbounded::<InnerEvent>();
|
||||
|
||||
// let task = async_std::task::spawn(async move {
|
||||
let mut view = web_view::builder()
|
||||
.title("My Project")
|
||||
.content(web_view::Content::Html(html_content))
|
||||
.content(web_view::Content::Html(HTML_CONTENT))
|
||||
.size(320, 480)
|
||||
.resizable(true)
|
||||
.debug(true)
|
||||
.user_data(())
|
||||
.invoke_handler(|view, arg| {
|
||||
//
|
||||
|
||||
// todo: handle events here
|
||||
println!("handling invoker");
|
||||
let handle = view.handle();
|
||||
sender.send(InnerEvent::Initiate(handle));
|
||||
Ok(())
|
||||
})
|
||||
.run()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
println!("building the diff");
|
||||
let bump = Bump::new();
|
||||
let mut diff_machine = DiffMachine::new(&bump);
|
||||
let old = html! {<div> </div>}(&bump);
|
||||
|
||||
// let mut scope = Scope::new(TEST, (), None);
|
||||
// scope.run::<()>();
|
||||
let new = html! {
|
||||
<div>
|
||||
<div class="flex items-center justify-center flex-col">
|
||||
<div class="flex items-center justify-center">
|
||||
<div class="flex flex-col bg-white rounded p-4 w-full max-w-xs">
|
||||
// Title
|
||||
<div class="font-bold text-xl">
|
||||
"Jon's awesome site!!11"
|
||||
</div>
|
||||
|
||||
// Subtext / description
|
||||
<div class="text-sm text-gray-500">
|
||||
"He worked so hard on it :)"
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row items-center justify-center mt-6">
|
||||
// Main number
|
||||
<div class="font-medium text-6xl">
|
||||
"1337"
|
||||
</div>
|
||||
</div>
|
||||
|
||||
// Try another
|
||||
<div class="flex flex-row justify-between mt-6">
|
||||
// <a href=format!("http://localhost:8080/fib/{}", other_fib_to_try) class="underline">
|
||||
"Legit made my own React"
|
||||
// </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}(&bump);
|
||||
|
||||
diff_machine.diff_node(&old, &new);
|
||||
|
||||
let edits = diff_machine.consume();
|
||||
let ready_edits = serde_json::to_string(&edits)?;
|
||||
let ref_edits = Arc::new(ready_edits);
|
||||
|
||||
loop {
|
||||
view.step().expect("should not fail");
|
||||
// if let Some(evt) = receiver.try_recv() {}
|
||||
if let Ok(event) = receiver.try_recv() {
|
||||
match event {
|
||||
InnerEvent::Initiate(handle) => {
|
||||
// println!("awesome, things worked");
|
||||
let ediits = ref_edits.clone();
|
||||
// println!("{}", ediits);
|
||||
handle
|
||||
.dispatch(move |view| {
|
||||
view.eval(format!("EditListReceived(`{}`);", ediits).as_str())?;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.expect("Dispatch failed");
|
||||
// let g = handle.();
|
||||
}
|
||||
}
|
||||
}
|
||||
// let event = receiver.try_recv();
|
||||
|
||||
// view.eval("alert('omg');")?;
|
||||
// view.step().expect("webview should not fail")?;
|
||||
}
|
||||
}
|
||||
|
||||
// static TEST: FC<()> = |ctx, props| {
|
||||
// ctx.view(html! {
|
||||
// <div>
|
||||
// <div class="flex items-center justify-center flex-col">
|
||||
// <div class="flex items-center justify-center">
|
||||
// <div class="flex flex-col bg-white rounded p-4 w-full max-w-xs">
|
||||
// // Title
|
||||
// <div class="font-bold text-xl">
|
||||
// "Jon's awesome site!!11"
|
||||
// </div>
|
||||
|
||||
// // Subtext / description
|
||||
// <div class="text-sm text-gray-500">
|
||||
// "He worked so hard on it :)"
|
||||
// </div>
|
||||
|
||||
// <div class="flex flex-row items-center justify-center mt-6">
|
||||
// // Main number
|
||||
// <div class="font-medium text-6xl">
|
||||
// "1337"
|
||||
// </div>
|
||||
// </div>
|
||||
|
||||
// // Try another
|
||||
// <div class="flex flex-row justify-between mt-6">
|
||||
// // <a href=format!("http://localhost:8080/fib/{}", other_fib_to_try) class="underline">
|
||||
// "Legit made my own React"
|
||||
// // </a>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// })
|
||||
// };
|
||||
|
|
324
packages/webview/examples/index.html
Normal file
324
packages/webview/examples/index.html
Normal file
|
@ -0,0 +1,324 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
|
||||
<meta charset="UTF-8" />
|
||||
<link
|
||||
href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<div></div>
|
||||
</body>
|
||||
<script>
|
||||
// #[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
// pub enum Edit<'d> {
|
||||
// SetText { text: &'d str },
|
||||
// RemoveSelfAndNextSiblings {},
|
||||
// ReplaceWith,
|
||||
// SetAttribute { name: &'d str, value: &'d str },
|
||||
// RemoveAttribute { name: &'d str },
|
||||
// PushReverseChild { n: u32 },
|
||||
// PopPushChild { n: u32 },
|
||||
// Pop,
|
||||
// AppendChild,
|
||||
// CreateTextNode { text: &'d str },
|
||||
// CreateElement { tag_name: &'d str },
|
||||
// NewEventListener { event_type: &'d str, a: u32, b: u32 },
|
||||
// UpdateEventListener { event_type: &'d str, a: u32, b: u32 },
|
||||
// RemoveEventListener { event_type: &'d str },
|
||||
// CreateElementNs { tag_name: &'d str, ns: &'d str },
|
||||
// SaveChildrenToTemporaries { temp: u32, start: u32, end: u32 },
|
||||
// PushChild { n: u32 },
|
||||
// PushTemporary { temp: u32 },
|
||||
// InsertBefore,
|
||||
// PopPushReverseChild { n: u32 },
|
||||
// RemoveChild { n: u32 },
|
||||
// SetClass { class_name: &'d str },
|
||||
// }
|
||||
|
||||
// const interpreter = new Interpreter();
|
||||
|
||||
class Interpreter {
|
||||
constructor(root) {
|
||||
this.stack = [root];
|
||||
}
|
||||
|
||||
top() {
|
||||
return this.stack[this.stack.length - 1];
|
||||
}
|
||||
|
||||
pop() {
|
||||
return this.stack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
class OPTABLE {
|
||||
// 0
|
||||
SetText(edit, interp) {
|
||||
interp.top(interp.stack).textContent = edit.text;
|
||||
}
|
||||
// 1
|
||||
RemoveSelfAndNextSiblings(edit) {
|
||||
const node = interp.pop();
|
||||
let sibling = node.nextSibling;
|
||||
while (sibling) {
|
||||
const temp = sibling.nextSibling;
|
||||
sibling.remove();
|
||||
sibling = temp;
|
||||
}
|
||||
node.remove();
|
||||
}
|
||||
|
||||
// 2
|
||||
ReplaceWith(edit, interp) {
|
||||
const newNode = interp.pop();
|
||||
const oldNode = interp.pop();
|
||||
oldNode.replaceWith(newNode);
|
||||
interp.stack.push(newNode);
|
||||
}
|
||||
|
||||
// 3
|
||||
SetAttribute(edit, interp) {
|
||||
const name = edit.name;
|
||||
const value = edit.value;
|
||||
const node = interp.top(interp.stack);
|
||||
node.setAttribute(name, value);
|
||||
|
||||
// Some attributes are "volatile" and don't work through `setAttribute`.
|
||||
if ((name === "value", interp)) {
|
||||
node.value = value;
|
||||
}
|
||||
if ((name === "checked", interp)) {
|
||||
node.checked = true;
|
||||
}
|
||||
if ((name === "selected", interp)) {
|
||||
node.selected = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 4
|
||||
RemoveAttribute(edit, interp) {
|
||||
const name = edit.name;
|
||||
const node = interp.top(interp.stack);
|
||||
node.removeAttribute(name);
|
||||
|
||||
// Some attributes are "volatile" and don't work through `removeAttribute`.
|
||||
if ((name === "value", interp)) {
|
||||
node.value = null;
|
||||
}
|
||||
if ((name === "checked", interp)) {
|
||||
node.checked = false;
|
||||
}
|
||||
if ((name === "selected", interp)) {
|
||||
node.selected = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 5
|
||||
PushReverseChild(edit, interp) {
|
||||
const n = edit.n;
|
||||
const parent = interp.top(interp.stack);
|
||||
const children = parent.childNodes;
|
||||
const child = children[children.length - n - 1];
|
||||
interp.stack.push(child);
|
||||
}
|
||||
|
||||
// 6
|
||||
PopPushChild(edit, interp) {
|
||||
const n = edit.n;
|
||||
interp.pop();
|
||||
const parent = interp.top(interp.stack);
|
||||
const children = parent.childNodes;
|
||||
const child = children[n];
|
||||
interp.stack.push(child);
|
||||
}
|
||||
|
||||
// 7
|
||||
Pop(edit, interp) {
|
||||
interp.pop();
|
||||
}
|
||||
|
||||
// 8
|
||||
AppendChild(edit, interp) {
|
||||
console.log(interp.stack);
|
||||
const child = interp.pop();
|
||||
console.log(interp.stack);
|
||||
interp.top().appendChild(child);
|
||||
}
|
||||
|
||||
// 9
|
||||
CreateTextNode(edit, interp) {
|
||||
// interp.stack.push(document.createTextNode("asd"));
|
||||
console.log(interp.stack);
|
||||
|
||||
interp.stack.push(document.createTextNode(edit.text));
|
||||
console.log(interp.stack);
|
||||
}
|
||||
|
||||
// 10
|
||||
CreateElement(edit, interp) {
|
||||
const tagName = edit.tag_name;
|
||||
interp.stack.push(document.createElement(tagName));
|
||||
}
|
||||
|
||||
// 11
|
||||
NewEventListener(edit, interp) {
|
||||
// todo!
|
||||
const eventId = mem32[i++];
|
||||
const eventType = interp.getCachedString(eventId);
|
||||
const a = mem32[i++];
|
||||
const b = mem32[i++];
|
||||
const el = interp.top(interp.stack);
|
||||
el.addEventListener(eventType, interp.eventHandler);
|
||||
el[`dodrio-a-${eventType}`] = a;
|
||||
el[`dodrio-b-${eventType}`] = b;
|
||||
}
|
||||
|
||||
// 12
|
||||
UpdateEventListener(edit, interp) {
|
||||
// todo!
|
||||
const eventId = mem32[i++];
|
||||
const eventType = interp.getCachedString(eventId);
|
||||
const el = interp.top(interp.stack);
|
||||
el[`dodrio-a-${eventType}`] = mem32[i++];
|
||||
el[`dodrio-b-${eventType}`] = mem32[i++];
|
||||
}
|
||||
|
||||
// 13
|
||||
RemoveEventListener(edit, interp) {
|
||||
// todo!
|
||||
const eventId = mem32[i++];
|
||||
const eventType = interp.getCachedString(eventId);
|
||||
const el = interp.top(interp.stack);
|
||||
el.removeEventListener(eventType, interp.eventHandler);
|
||||
}
|
||||
|
||||
// 14
|
||||
AddCachedString(edit, interp) {
|
||||
// todo!
|
||||
const pointer = mem32[i++];
|
||||
const length = mem32[i++];
|
||||
const id = mem32[i++];
|
||||
const str = string(mem8, pointer, length);
|
||||
interp.addCachedString(str, id);
|
||||
}
|
||||
|
||||
// 15
|
||||
DropCachedString(edit, interp) {
|
||||
// todo!
|
||||
const id = mem32[i++];
|
||||
interp.dropCachedString(id);
|
||||
}
|
||||
|
||||
// 16
|
||||
CreateElementNS(edit, interp) {
|
||||
// const tagNameId = mem32[i++];
|
||||
// const tagName = interp.getCachedString(tagNameId);
|
||||
// const nsId = mem32[i++];
|
||||
// const ns = interp.getCachedString(nsId);
|
||||
interp.stack.push(document.createElementNS(edit.ns, edit.tag_name));
|
||||
}
|
||||
|
||||
// 17
|
||||
SaveChildrenToTemporaries(edit, interp) {
|
||||
// let temp = mem32[i++];
|
||||
// const start = mem32[i++];
|
||||
// const end = mem32[i++];
|
||||
let temp = edit.temp;
|
||||
const start = edit.start;
|
||||
const end = edit.end;
|
||||
const parent = interp.top(interp.stack);
|
||||
const children = parent.childNodes;
|
||||
for (let i = start; i < end; i++, interp) {
|
||||
interp.temporaries[temp++] = children[i];
|
||||
}
|
||||
}
|
||||
|
||||
// 18
|
||||
PushChild(edit, interp) {
|
||||
const parent = interp.top(interp.stack);
|
||||
// const n = mem32[i++];
|
||||
const n = edit.n;
|
||||
const child = parent.childNodes[n];
|
||||
interp.stack.push(child);
|
||||
}
|
||||
|
||||
// 19
|
||||
PushTemporary(edit, interp) {
|
||||
// const temp = mem32[i++];
|
||||
const temp = edit.temp;
|
||||
interp.stack.push(interp.temporaries[temp]);
|
||||
}
|
||||
|
||||
// 20
|
||||
InsertBefore(edit, interp) {
|
||||
const before = interp.pop();
|
||||
const after = interp.pop();
|
||||
after.parentNode.insertBefore(before, after);
|
||||
interp.stack.push(before);
|
||||
}
|
||||
|
||||
// 21
|
||||
PopPushReverseChild(edit, interp) {
|
||||
// const n = mem32[i++];
|
||||
const n = edit.n;
|
||||
interp.pop();
|
||||
const parent = interp.top(interp.stack);
|
||||
const children = parent.childNodes;
|
||||
const child = children[children.length - n - 1];
|
||||
interp.stack.push(child);
|
||||
}
|
||||
|
||||
// 22
|
||||
RemoveChild(edit, interp) {
|
||||
// const n = mem32[i++];
|
||||
const n = edit.n;
|
||||
const parent = interp.top(interp.stack);
|
||||
const child = parent.childNodes[n];
|
||||
child.remove();
|
||||
}
|
||||
|
||||
// 23
|
||||
SetClass(edit, interp) {
|
||||
// const classId = mem32[i++];
|
||||
const className = edit.class_name;
|
||||
interp.top(interp.stack).className = className;
|
||||
}
|
||||
|
||||
// 24
|
||||
SaveTemplate(edit, interp) {
|
||||
const id = mem32[i++];
|
||||
const template = interp.top(interp.stack);
|
||||
interp.saveTemplate(id, template.cloneNode(true));
|
||||
}
|
||||
|
||||
// 25
|
||||
PushTemplate(edit, interp) {
|
||||
const id = mem32[i++];
|
||||
const template = interp.getTemplate(id);
|
||||
interp.stack.push(template.cloneNode(true));
|
||||
}
|
||||
}
|
||||
|
||||
let op = new OPTABLE();
|
||||
const c = window.document.body.firstChild;
|
||||
console.log("First child");
|
||||
console.log(c);
|
||||
const interpreter = new Interpreter(window.document.body);
|
||||
function EditListReceived(rawEditList) {
|
||||
let editList = JSON.parse(rawEditList);
|
||||
console.log(editList);
|
||||
editList.forEach(function (edit, index) {
|
||||
// console.log("processing edit");
|
||||
const name = edit.type;
|
||||
console.log(name);
|
||||
const f = op[name];
|
||||
f(edit, interpreter);
|
||||
});
|
||||
}
|
||||
|
||||
external.invoke("initiate");
|
||||
</script>
|
||||
</html>
|
Loading…
Reference in a new issue