Feat: move webview logic into library
This commit is contained in:
1 parent
18a7a1f9c4
commit
32b45e5ba1
10 files changed
+249
-514
No files matched your search
@@ -79,7 +79,6 @@ impl<'a> Context<'a> {
|
||||
let safe_nodes = lazy_nodes(self.bump);
|
||||
let unsafe_nodes = unsafe { std::mem::transmute::<VNode<'a>, VNode<'static>>(safe_nodes) };
|
||||
self.final_nodes.deref().borrow_mut().replace(unsafe_nodes);
|
||||
info!("lazy nodes have been generated");
|
||||
DomTree {}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ pub struct Scope {
|
||||
pub frames: ActiveFrame,
|
||||
|
||||
// IE Which listeners need to be woken up?
|
||||
pub listeners: Vec<Box<dyn Fn()>>,
|
||||
pub listeners: Vec<Box<dyn Fn(crate::events::VirtualEvent)>>,
|
||||
|
||||
// lying, cheating reference >:(
|
||||
pub props: Box<dyn std::any::Any>,
|
||||
@@ -55,7 +55,7 @@ impl Scope {
|
||||
// Capture the caller
|
||||
let caller = f as *const ();
|
||||
|
||||
let listeners: Vec<Box<dyn Fn()>> = vec![Box::new(|| {
|
||||
let listeners: Vec<Box<dyn Fn(crate::events::VirtualEvent)>> = vec![Box::new(|_| {
|
||||
log::info!("Base listener called");
|
||||
})];
|
||||
|
||||
|
||||
@@ -98,12 +98,7 @@ impl VirtualDom {
|
||||
|
||||
component.run::<()>();
|
||||
|
||||
let old = component.old_frame();
|
||||
let new = component.new_frame();
|
||||
dbg!(old);
|
||||
dbg!(new);
|
||||
|
||||
diff_machine.diff_node(old, new);
|
||||
diff_machine.diff_node(component.old_frame(), component.new_frame());
|
||||
|
||||
Ok(diff_machine.consume())
|
||||
}
|
||||
@@ -136,7 +131,7 @@ impl VirtualDom {
|
||||
let EventTrigger {
|
||||
component_id,
|
||||
listener_id,
|
||||
event: _,
|
||||
event: source,
|
||||
} = event;
|
||||
|
||||
let component = self
|
||||
@@ -151,7 +146,7 @@ impl VirtualDom {
|
||||
.as_ref();
|
||||
|
||||
// Run the callback with the user event
|
||||
listener();
|
||||
listener(source);
|
||||
|
||||
// Mark dirty components. Descend from the highest node until all dirty nodes are updated.
|
||||
let mut affected_components = Vec::new();
|
||||
|
||||
+20
-270
@@ -1,6 +1,6 @@
|
||||
use dioxus_core::changelist::Edit;
|
||||
use fxhash::FxHashMap;
|
||||
use log::{debug};
|
||||
use log::debug;
|
||||
use wasm_bindgen::{closure::Closure, JsCast};
|
||||
use web_sys::{window, Document, Element, Event, Node};
|
||||
|
||||
@@ -8,13 +8,13 @@ use web_sys::{window, Document, Element, Event, Node};
|
||||
pub struct CacheId(u32);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PatchMachine {
|
||||
pub(crate) struct PatchMachine {
|
||||
container: Element,
|
||||
pub stack: Stack,
|
||||
pub(crate) stack: Stack,
|
||||
temporaries: FxHashMap<u32, Node>,
|
||||
templates: FxHashMap<CacheId, Node>,
|
||||
callback: Option<Closure<dyn FnMut(&Event)>>,
|
||||
document: Document,
|
||||
// templates: FxHashMap<CacheId, Node>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
@@ -65,10 +65,10 @@ impl PatchMachine {
|
||||
.expect("must have access to the Document");
|
||||
|
||||
Self {
|
||||
// templates: Default::default(),
|
||||
container,
|
||||
stack: Stack::with_capacity(20),
|
||||
temporaries: Default::default(),
|
||||
templates: Default::default(),
|
||||
callback: None,
|
||||
document,
|
||||
}
|
||||
@@ -77,7 +77,7 @@ impl PatchMachine {
|
||||
pub fn unmount(&mut self) {
|
||||
self.stack.clear();
|
||||
self.temporaries.clear();
|
||||
self.templates.clear();
|
||||
// self.templates.clear();
|
||||
}
|
||||
|
||||
pub fn start(&mut self) {
|
||||
@@ -92,7 +92,8 @@ impl PatchMachine {
|
||||
}
|
||||
|
||||
pub fn get_template(&self, id: CacheId) -> Option<&Node> {
|
||||
self.templates.get(&id)
|
||||
todo!()
|
||||
// self.templates.get(&id)
|
||||
}
|
||||
|
||||
pub fn init_events_trampoline(&mut self, _trampoline: ()) {
|
||||
@@ -379,273 +380,22 @@ impl PatchMachine {
|
||||
}
|
||||
}
|
||||
|
||||
// // 0
|
||||
// pub fn set_text(&mut self, text: &str) {
|
||||
// self.stack.top().set_text_content(Some(text));
|
||||
// // 24
|
||||
// pub fn save_template(&mut self, id: CacheId) {
|
||||
// let template = self.stack.top();
|
||||
// let t = template.clone_node_with_deep(true).unwrap();
|
||||
// // self.templates.insert(id, t);
|
||||
// }
|
||||
|
||||
// // 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();
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 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);
|
||||
// }
|
||||
|
||||
// self.stack.push(new_node);
|
||||
// }
|
||||
|
||||
// // 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();
|
||||
|
||||
// // 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();
|
||||
|
||||
// // 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);
|
||||
// }
|
||||
|
||||
// // 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();
|
||||
// }
|
||||
|
||||
// // 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(),
|
||||
// );
|
||||
// }
|
||||
|
||||
// // 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();
|
||||
|
||||
// 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();
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 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);
|
||||
// }
|
||||
|
||||
// // 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);
|
||||
// }
|
||||
|
||||
// // 19
|
||||
// pub fn push_temporary(&mut self, temp: u32) {
|
||||
// let t = self.temporaries.get(&temp).unwrap().clone();
|
||||
// // 25
|
||||
// pub fn push_template(&mut self, id: CacheId) {
|
||||
// let template = self.get_template(id).unwrap();
|
||||
// let t = template.clone_node_with_deep(true).unwrap();
|
||||
// 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);
|
||||
// pub fn has_template(&self, id: CacheId) -> bool {
|
||||
// todo!()
|
||||
// // self.templates.contains_key(&id)
|
||||
// }
|
||||
|
||||
// // 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();
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 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) {
|
||||
let template = self.stack.top();
|
||||
let t = template.clone_node_with_deep(true).unwrap();
|
||||
self.templates.insert(id, t);
|
||||
}
|
||||
|
||||
// 25
|
||||
pub fn push_template(&mut self, id: CacheId) {
|
||||
let template = self.get_template(id).unwrap();
|
||||
let t = template.clone_node_with_deep(true).unwrap();
|
||||
self.stack.push(t);
|
||||
}
|
||||
|
||||
pub fn has_template(&self, id: CacheId) -> bool {
|
||||
self.templates.contains_key(&id)
|
||||
}
|
||||
}
|
||||
@@ -19,9 +19,6 @@ pub mod interpreter;
|
||||
///
|
||||
pub struct WebsysRenderer {
|
||||
internal_dom: VirtualDom,
|
||||
|
||||
// this should be a component index
|
||||
_event_map: FxHashMap<(u32, u32), u32>,
|
||||
}
|
||||
|
||||
impl WebsysRenderer {
|
||||
@@ -58,10 +55,7 @@ impl WebsysRenderer {
|
||||
/// Create a new text renderer from an existing Virtual DOM.
|
||||
pub fn from_vdom(dom: VirtualDom) -> Self {
|
||||
// todo: initialize the event registry properly
|
||||
Self {
|
||||
internal_dom: dom,
|
||||
_event_map: FxHashMap::default(),
|
||||
}
|
||||
Self { internal_dom: dom }
|
||||
}
|
||||
|
||||
pub async fn run(&mut self) -> dioxus_core::error::Result<()> {
|
||||
@@ -72,7 +66,7 @@ impl WebsysRenderer {
|
||||
let root_node = body_element.first_child().unwrap();
|
||||
patch_machine.stack.push(root_node);
|
||||
|
||||
// todo: initialize the event registry properly on the root element
|
||||
// todo: initialize the event registry properly on the root
|
||||
|
||||
self.internal_dom
|
||||
.rebuild()?
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
// 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,152 +1,52 @@
|
||||
//! An example where the dioxus vdom is running in a native thread, interacting with webview
|
||||
//! Content is passed from the native thread into the webview
|
||||
|
||||
use std::{
|
||||
borrow::BorrowMut,
|
||||
rc::Rc,
|
||||
sync::{mpsc::channel, Arc},
|
||||
};
|
||||
use dioxus_core::prelude::*;
|
||||
|
||||
// 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))
|
||||
.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(())
|
||||
})
|
||||
.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"
|
||||
fn main(){
|
||||
dioxus_webview::launch(
|
||||
// Customize the webview
|
||||
|builder| {
|
||||
builder
|
||||
.title("Test Dioxus App")
|
||||
.size(320, 480)
|
||||
.resizable(true)
|
||||
.debug(true)
|
||||
},
|
||||
// Props
|
||||
(),
|
||||
// Draw the root component
|
||||
|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="http://localhost:8080/fib/{}" class="underline">
|
||||
"Legit made my own React"
|
||||
</a>
|
||||
</div>
|
||||
</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")?;
|
||||
}
|
||||
})
|
||||
},
|
||||
).expect("Webview finished");
|
||||
}
|
||||
|
||||
// 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>
|
||||
// })
|
||||
// };
|
||||
@@ -12,34 +12,6 @@
|
||||
<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];
|
||||
@@ -302,20 +274,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
let op = new OPTABLE();
|
||||
const c = window.document.body.firstChild;
|
||||
console.log("First child");
|
||||
console.log(c);
|
||||
const op_table = new OPTABLE();
|
||||
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);
|
||||
op_table[edit.type](edit, interpreter);
|
||||
});
|
||||
}
|
||||
|
||||
+167
-41
@@ -1,8 +1,18 @@
|
||||
use dioxus_core::prelude::*;
|
||||
use web_view::WebViewBuilder;
|
||||
use std::sync::mpsc::channel;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub fn new<T>(root: FC<T>) -> WebviewRenderer<T> {
|
||||
WebviewRenderer::new(root)
|
||||
use dioxus_core::prelude::*;
|
||||
use web_view::Handle;
|
||||
use web_view::{WVResult, WebView, WebViewBuilder};
|
||||
|
||||
static HTML_CONTENT: &'static str = include_str!("./index.html");
|
||||
|
||||
pub fn launch<T: 'static>(
|
||||
builder: impl FnOnce(DioxusWebviewBuilder) -> DioxusWebviewBuilder,
|
||||
props: T,
|
||||
root: FC<T>,
|
||||
) -> anyhow::Result<()> {
|
||||
WebviewRenderer::run(root, props, builder)
|
||||
}
|
||||
|
||||
/// The `WebviewRenderer` provides a way of rendering a Dioxus Virtual DOM through a bridge to a Webview instance.
|
||||
@@ -11,13 +21,78 @@ pub struct WebviewRenderer<T> {
|
||||
/// The root component used to render the Webview
|
||||
root: FC<T>,
|
||||
}
|
||||
enum InnerEvent {
|
||||
Initiate(Handle<()>),
|
||||
}
|
||||
|
||||
impl<T: 'static> WebviewRenderer<T> {
|
||||
pub fn run(
|
||||
root: FC<T>,
|
||||
props: T,
|
||||
user_builder: impl FnOnce(DioxusWebviewBuilder) -> DioxusWebviewBuilder,
|
||||
) -> anyhow::Result<()> {
|
||||
let (sender, receiver) = channel::<InnerEvent>();
|
||||
|
||||
let DioxusWebviewBuilder {
|
||||
title,
|
||||
width,
|
||||
height,
|
||||
resizable,
|
||||
debug,
|
||||
frameless,
|
||||
visible,
|
||||
min_width,
|
||||
min_height,
|
||||
} = user_builder(DioxusWebviewBuilder::new());
|
||||
|
||||
let mut view = web_view::builder()
|
||||
.invoke_handler(|view, arg| {
|
||||
let handle = view.handle();
|
||||
sender
|
||||
.send(InnerEvent::Initiate(handle))
|
||||
.expect("should not fail");
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.content(web_view::Content::Html(HTML_CONTENT))
|
||||
.user_data(())
|
||||
.title(title)
|
||||
.size(width, height)
|
||||
.resizable(resizable)
|
||||
.debug(debug)
|
||||
.frameless(frameless)
|
||||
.visible(visible)
|
||||
.min_size(min_width, min_height)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let mut vdom = VirtualDom::new_with_props(root, props);
|
||||
let edits = vdom.rebuild()?;
|
||||
let ref_edits = Arc::new(serde_json::to_string(&edits)?);
|
||||
|
||||
loop {
|
||||
view.step()
|
||||
.expect("should not fail")
|
||||
.expect("should not fail");
|
||||
|
||||
if let Ok(event) = receiver.try_recv() {
|
||||
if let InnerEvent::Initiate(handle) = event {
|
||||
let editlist = ref_edits.clone();
|
||||
handle
|
||||
.dispatch(move |view| {
|
||||
view.eval(format!("EditListReceived(`{}`);", editlist).as_str())
|
||||
})
|
||||
.expect("Dispatch failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> WebviewRenderer<T> {
|
||||
/// Create a new text-renderer instance from a functional component root.
|
||||
/// Automatically progresses the creation of the VNode tree to completion.
|
||||
///
|
||||
/// A VDom is automatically created. If you want more granular control of the VDom, use `from_vdom`
|
||||
pub fn new(root: FC<T>) -> Self {
|
||||
pub fn new(root: FC<T>, builder: impl FnOnce() -> WVResult<WebView<'static, ()>>) -> Self {
|
||||
Self { root }
|
||||
}
|
||||
|
||||
@@ -36,41 +111,92 @@ impl<T> WebviewRenderer<T> {
|
||||
pub fn update_mut(&mut self, modifier: impl Fn(&mut T)) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn launch(self, props: T) {
|
||||
todo!()
|
||||
// let mut ctx = Context { props: &props };
|
||||
// let WebviewRenderer { root } = self;
|
||||
// let content = root(&mut ctx);
|
||||
// let html_content = content.to_string();
|
||||
// /*
|
||||
// TODO: @Jon
|
||||
// Launch the webview with a premade VDom app
|
||||
// */
|
||||
|
||||
// web_view::builder()
|
||||
// .title("My Project")
|
||||
// .content(web_view::Content::Html(html_content))
|
||||
// .size(320, 480)
|
||||
// .resizable(true)
|
||||
// .debug(true)
|
||||
// .user_data(())
|
||||
// .invoke_handler(|_webview, _arg| Ok(()))
|
||||
// .run()
|
||||
// .unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
// mod receiver {
|
||||
// use dioxus_core::prelude::*;
|
||||
pub struct DioxusWebviewBuilder<'a> {
|
||||
pub(crate) title: &'a str,
|
||||
pub(crate) width: i32,
|
||||
pub(crate) height: i32,
|
||||
pub(crate) resizable: bool,
|
||||
pub(crate) debug: bool,
|
||||
pub(crate) frameless: bool,
|
||||
pub(crate) visible: bool,
|
||||
pub(crate) min_width: i32,
|
||||
pub(crate) min_height: i32,
|
||||
}
|
||||
impl<'a> DioxusWebviewBuilder<'a> {
|
||||
fn new() -> Self {
|
||||
#[cfg(debug_assertions)]
|
||||
let debug = true;
|
||||
#[cfg(not(debug_assertions))]
|
||||
let debug = false;
|
||||
|
||||
// /// The receiver app is a container that builds a connection to the host process that shuttles events and patches.
|
||||
// pub(crate) static ReceiverApp: FC<()> = |ctx| {
|
||||
// //
|
||||
// html! {
|
||||
// <div>
|
||||
// {}
|
||||
// </div>
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
DioxusWebviewBuilder {
|
||||
title: "Application",
|
||||
width: 800,
|
||||
height: 600,
|
||||
resizable: true,
|
||||
debug,
|
||||
frameless: false,
|
||||
visible: true,
|
||||
min_width: 300,
|
||||
min_height: 300,
|
||||
}
|
||||
}
|
||||
/// Sets the title of the WebView window.
|
||||
///
|
||||
/// Defaults to `"Application"`.
|
||||
pub fn title(mut self, title: &'a str) -> Self {
|
||||
self.title = title;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the size of the WebView window.
|
||||
///
|
||||
/// Defaults to 800 x 600.
|
||||
pub fn size(mut self, width: i32, height: i32) -> Self {
|
||||
self.width = width;
|
||||
self.height = height;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the resizability of the WebView window. If set to false, the window cannot be resized.
|
||||
///
|
||||
/// Defaults to `true`.
|
||||
pub fn resizable(mut self, resizable: bool) -> Self {
|
||||
self.resizable = resizable;
|
||||
self
|
||||
}
|
||||
|
||||
/// Enables or disables debug mode.
|
||||
///
|
||||
/// Defaults to `true` for debug builds, `false` for release builds.
|
||||
pub fn debug(mut self, debug: bool) -> Self {
|
||||
self.debug = debug;
|
||||
self
|
||||
}
|
||||
/// The window crated will be frameless
|
||||
///
|
||||
/// defaults to `false`
|
||||
pub fn frameless(mut self, frameless: bool) -> Self {
|
||||
self.frameless = frameless;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the visibility of the WebView window.
|
||||
///
|
||||
/// defaults to `true`
|
||||
pub fn visible(mut self, visible: bool) -> Self {
|
||||
self.visible = visible;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the minimum size of the WebView window.
|
||||
///
|
||||
/// Defaults to 300 x 300.
|
||||
pub fn min_size(mut self, width: i32, height: i32) -> Self {
|
||||
self.min_width = width;
|
||||
self.min_height = height;
|
||||
self
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user