wip: enable more diffing
This commit is contained in:
1 parent
b5e5ef171a
commit
e8f29a8f8a
26 files changed
+1326
-367
No files matched your search
@@ -10,7 +10,7 @@ license = "MIT/Apache-2.0"
|
||||
[dependencies]
|
||||
dioxus-core = { path="../core", version="0.1.2" }
|
||||
js-sys = "0.3"
|
||||
wasm-bindgen = "0.2.71"
|
||||
wasm-bindgen = { version="0.2.71", features=["enable-interning"] }
|
||||
lazy_static = "1.4.0"
|
||||
wasm-bindgen-futures = "0.4.20"
|
||||
wasm-logger = "0.2.0"
|
||||
@@ -31,6 +31,7 @@ slotmap = "1.0.3"
|
||||
version = "0.3.50"
|
||||
features = [
|
||||
"Comment",
|
||||
"Attr",
|
||||
"Document",
|
||||
"Element",
|
||||
"HtmlElement",
|
||||
@@ -47,6 +48,7 @@ features = [
|
||||
"MouseEvent",
|
||||
"InputEvent",
|
||||
"ClipboardEvent",
|
||||
"NamedNodeMap",
|
||||
"KeyboardEvent",
|
||||
"TouchEvent",
|
||||
"WheelEvent",
|
||||
@@ -70,4 +72,5 @@ crate-type = ["cdylib", "rlib"]
|
||||
[dev-dependencies]
|
||||
im-rc = "15.0.0"
|
||||
rand = { version="0.8.4", features=["small_rng"] }
|
||||
separator = "0.4.1"
|
||||
uuid = { version="0.8.2", features=["v4", "wasm-bindgen"] }
|
||||
@@ -3,3 +3,9 @@
|
||||
Build interactive user experiences directly in the web browser!
|
||||
|
||||
Dioxus-web provides a `WebsysRenderer` for the Dioxus Virtual Dom that handles events, progresses components, and updates the actual DOM using web-sys methods.
|
||||
|
||||
|
||||
## Web-specific Optimizations
|
||||
- Uses string interning of all common node types
|
||||
- Optimistically interns short strings
|
||||
- Builds trees completely before mounting them
|
||||
@@ -1,5 +1,6 @@
|
||||
//! Basic example that renders a simple VNode to the browser.
|
||||
|
||||
use dioxus::events::on::MouseEvent;
|
||||
use dioxus_core as dioxus;
|
||||
use dioxus_core::prelude::*;
|
||||
use dioxus_web::*;
|
||||
@@ -14,56 +15,42 @@ fn main() {
|
||||
}
|
||||
|
||||
static App: FC<()> = |cx| {
|
||||
let (state, set_state) = use_state(&cx, || 0);
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
h1 {"hello"}
|
||||
C1 {}
|
||||
C2 {}
|
||||
section { class: "py-12 px-4 text-center"
|
||||
div { class: "w-full max-w-2xl mx-auto"
|
||||
span { class: "text-sm font-semibold"
|
||||
"count: {state}"
|
||||
}
|
||||
div {
|
||||
C1 {
|
||||
onclick: move |_| set_state(state + 1)
|
||||
"incr"
|
||||
}
|
||||
C1 {
|
||||
onclick: move |_| set_state(state - 1)
|
||||
"decr"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
static C1: FC<()> = |cx| {
|
||||
#[derive(Props)]
|
||||
struct IncrementerProps<'a> {
|
||||
onclick: &'a dyn Fn(MouseEvent),
|
||||
}
|
||||
|
||||
fn C1<'a, 'b>(cx: Context<'a, IncrementerProps<'b>>) -> VNode<'a> {
|
||||
cx.render(rsx! {
|
||||
button {
|
||||
"numba 1"
|
||||
class: "inline-block py-4 px-8 mr-6 leading-none text-white bg-indigo-600 hover:bg-indigo-900 font-semibold rounded shadow"
|
||||
onclick: {cx.onclick}
|
||||
"becr"
|
||||
{cx.children()}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
static C2: FC<()> = |cx| {
|
||||
cx.render(rsx! {
|
||||
button {
|
||||
"numba 2"
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
static DocExamples: FC<()> = |cx| {
|
||||
//
|
||||
|
||||
let is_ready = false;
|
||||
|
||||
let items = (0..10).map(|i| rsx! { li {"{i}"} });
|
||||
let _ = rsx! {
|
||||
ul {
|
||||
{items}
|
||||
}
|
||||
};
|
||||
|
||||
// rsx! {
|
||||
// div {}
|
||||
// h1 {}
|
||||
// {""}
|
||||
// "asbasd"
|
||||
// dioxus::Fragment {
|
||||
// //
|
||||
// }
|
||||
// }
|
||||
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
{ is_ready.then(|| rsx!{ h1 {"We are ready!"} }) }
|
||||
}
|
||||
})
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
//! Example: Calculator
|
||||
//! -------------------------
|
||||
|
||||
// use dioxus::events::on::*;
|
||||
// use dioxus::prelude::*;
|
||||
|
||||
use dioxus_core as dioxus;
|
||||
use dioxus_web::WebsysRenderer;
|
||||
|
||||
const STYLE: &str = include_str!("../../../examples/assets/calculator.css");
|
||||
|
||||
fn main() {
|
||||
// Setup logging
|
||||
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
// Run the app
|
||||
wasm_bindgen_futures::spawn_local(WebsysRenderer::start(App));
|
||||
}
|
||||
|
||||
use dioxus::events::on::*;
|
||||
use dioxus::prelude::*;
|
||||
|
||||
enum Operator {
|
||||
Add,
|
||||
Sub,
|
||||
Mul,
|
||||
Div,
|
||||
}
|
||||
|
||||
static App: FC<()> = |cx| {
|
||||
let (cur_val, set_cur_val) = use_state(&cx, || 0.0_f64);
|
||||
let (operator, set_operator) = use_state(&cx, || None as Option<Operator>);
|
||||
let (display_value, set_display_value) = use_state(&cx, || "".to_string());
|
||||
|
||||
let clear_display = display_value.eq("0");
|
||||
let clear_text = if clear_display { "C" } else { "AC" };
|
||||
|
||||
let input_digit =
|
||||
move |num: u8| {
|
||||
log::warn!("Inputting digit {:#?}", num);
|
||||
let mut new = display_value.clone();
|
||||
new.push_str(num.to_string().as_str());
|
||||
set_display_value(new);
|
||||
};
|
||||
|
||||
let input_dot = move || {
|
||||
let mut new = display_value.clone();
|
||||
new.push_str(".");
|
||||
set_display_value(new);
|
||||
};
|
||||
|
||||
let perform_operation = move || {
|
||||
if let Some(op) = operator.as_ref() {
|
||||
let rhs = display_value.parse::<f64>().unwrap();
|
||||
let new_val = match op {
|
||||
Operator::Add => *cur_val + rhs,
|
||||
Operator::Sub => *cur_val - rhs,
|
||||
Operator::Mul => *cur_val * rhs,
|
||||
Operator::Div => *cur_val / rhs,
|
||||
};
|
||||
set_cur_val(new_val);
|
||||
set_display_value(new_val.to_string());
|
||||
set_operator(None);
|
||||
}
|
||||
};
|
||||
|
||||
let toggle_sign = move |_| {
|
||||
if display_value.starts_with("-") {
|
||||
set_display_value(display_value.trim_start_matches("-").to_string())
|
||||
} else {
|
||||
set_display_value(format!("-{}", *display_value))
|
||||
}
|
||||
};
|
||||
let toggle_percent = move |_| todo!();
|
||||
|
||||
let clear_key = move |_| {
|
||||
set_display_value("0".to_string());
|
||||
if !clear_display {
|
||||
set_operator(None);
|
||||
set_cur_val(0.0);
|
||||
}
|
||||
};
|
||||
|
||||
let keydownhandler = move |evt: KeyboardEvent| match evt.key_code() {
|
||||
KeyCode::Backspace => {
|
||||
//
|
||||
let mut new = display_value.clone();
|
||||
if !new.as_str().eq("0") {
|
||||
new.pop();
|
||||
}
|
||||
set_display_value(new);
|
||||
|
||||
},
|
||||
KeyCode::_0 => input_digit(0),
|
||||
KeyCode::_1 => input_digit(1),
|
||||
KeyCode::_2 => input_digit(2),
|
||||
KeyCode::_3 => input_digit(3),
|
||||
KeyCode::_4 => input_digit(4),
|
||||
KeyCode::_5 => input_digit(5),
|
||||
KeyCode::_6 => input_digit(6),
|
||||
KeyCode::_7 => input_digit(7),
|
||||
KeyCode::_8 => input_digit(8),
|
||||
KeyCode::_9 => input_digit(9),
|
||||
KeyCode::Add => set_operator(Some(Operator::Add)),
|
||||
KeyCode::Subtract => set_operator(Some(Operator::Sub)),
|
||||
KeyCode::Divide => set_operator(Some(Operator::Div)),
|
||||
KeyCode::Multiply => set_operator(Some(Operator::Mul)),
|
||||
_ => {}
|
||||
};
|
||||
|
||||
cx.render(rsx! {
|
||||
div { class: "app"
|
||||
onkeydown: {keydownhandler}
|
||||
style {
|
||||
"{STYLE}"
|
||||
}
|
||||
div { class: "calculator",
|
||||
div { class: "input-keys"
|
||||
CalculatorDisplay { val: *cur_val }
|
||||
div { class: "function-keys"
|
||||
CalculatorKey { name: "key-clear", onclick: {clear_key} "{clear_text}" }
|
||||
CalculatorKey { name: "key-sign", onclick: {toggle_sign}, "±"}
|
||||
CalculatorKey { name: "key-percent", onclick: {toggle_percent} "%"}
|
||||
}
|
||||
div { class: "digit-keys"
|
||||
CalculatorKey { name: "key-0", onclick: move |_| input_digit(0), "0" }
|
||||
CalculatorKey { name: "key-dot", onclick: move |_| input_dot(), "●" }
|
||||
|
||||
{(1..9).map(move |k| rsx!{
|
||||
CalculatorKey { key: "{k}", name: "key-{k}", onclick: move |_| input_digit(k), "{k}" }
|
||||
})}
|
||||
}
|
||||
div { class: "operator-keys"
|
||||
CalculatorKey { name: "key-divide", onclick: move |_| set_operator(Some(Operator::Div)) "÷" }
|
||||
CalculatorKey { name: "key-multiply", onclick: move |_| set_operator(Some(Operator::Mul)) "×" }
|
||||
CalculatorKey { name: "key-subtract", onclick: move |_| set_operator(Some(Operator::Sub)) "−" }
|
||||
CalculatorKey { name: "key-add", onclick: move |_| set_operator(Some(Operator::Add)) "+" }
|
||||
CalculatorKey { name: "key-equals", onclick: move |_| perform_operation() "=" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
#[derive(Props)]
|
||||
struct CalculatorKeyProps<'a> {
|
||||
/// Name!
|
||||
name: &'static str,
|
||||
|
||||
/// Click!
|
||||
onclick: &'a dyn Fn(MouseEvent),
|
||||
}
|
||||
|
||||
fn CalculatorKey<'a, 'r>(cx: Context<'a, CalculatorKeyProps<'r>>) -> VNode<'a> {
|
||||
cx.render(rsx! {
|
||||
button {
|
||||
class: "calculator-key {cx.name}"
|
||||
onclick: {cx.onclick}
|
||||
{cx.children()}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Props, PartialEq)]
|
||||
struct CalculatorDisplayProps {
|
||||
val: f64,
|
||||
}
|
||||
|
||||
fn CalculatorDisplay(cx: Context<CalculatorDisplayProps>) -> VNode {
|
||||
use separator::Separatable;
|
||||
// Todo, add float support to the num-format crate
|
||||
let formatted = cx.val.separated_string();
|
||||
// TODO: make it autoscaling with css
|
||||
cx.render(rsx! {
|
||||
div { class: "calculator-display"
|
||||
"{formatted}"
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -3,15 +3,17 @@ use dioxus_core::prelude::*;
|
||||
use dioxus_web::WebsysRenderer;
|
||||
|
||||
fn main() {
|
||||
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
||||
console_error_panic_hook::set_once();
|
||||
// wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
||||
// console_error_panic_hook::set_once();
|
||||
|
||||
// log::info!("hello world");
|
||||
dioxus_web::intern_cache();
|
||||
|
||||
log::info!("hello world");
|
||||
wasm_bindgen_futures::spawn_local(WebsysRenderer::start(Example));
|
||||
}
|
||||
|
||||
static Example: FC<()> = |cx| {
|
||||
let nodes = (0..15).map(|f| rsx! (li { key: "{f}", "{f}"}));
|
||||
let nodes = (0..500).map(|f| rsx! (li {"div"}));
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
span {
|
||||
|
||||
+294
-44
@@ -77,49 +77,6 @@ impl WebsysRenderer {
|
||||
.progress_with_event(&mut websys_dom, trigger)?;
|
||||
}
|
||||
|
||||
// let edits = self.internal_dom.rebuild()?;
|
||||
// log::debug!("Received edits: {:#?}", edits);
|
||||
// edits.iter().for_each(|edit| {
|
||||
// log::debug!("patching with {:?}", edit);
|
||||
// patch_machine.handle_edit(edit);
|
||||
// });
|
||||
|
||||
// patch_machine.reset();
|
||||
// let root_node = body_element.first_child().unwrap();
|
||||
// patch_machine.stack.push(root_node.clone());
|
||||
|
||||
// log::debug!("patch stack size {:?}", patch_machine.stack);
|
||||
|
||||
// Event loop waits for the receiver to finish up
|
||||
// TODO! Connect the sender to the virtual dom's suspense system
|
||||
// Suspense is basically an external event that can force renders to specific nodes
|
||||
// while let Ok(event) = receiver.recv().await {
|
||||
// log::debug!("Stack before entrance {:#?}", patch_machine.stack.top());
|
||||
// log::debug!("patch stack size before {:#?}", patch_machine.stack);
|
||||
// patch_machine.reset();
|
||||
// patch_machine.stack.push(root_node.clone());
|
||||
// self.internal_dom
|
||||
// .progress_with_event(&mut websys_dom, event)?;
|
||||
// let edits = self.internal_dom.progress_with_event(event)?;
|
||||
// log::debug!("Received edits: {:#?}", edits);
|
||||
|
||||
// for edit in &edits {
|
||||
// // log::debug!("edit stream {:?}", edit);
|
||||
// // log::debug!("Stream stack {:#?}", patch_machine.stack.top());
|
||||
// patch_machine.handle_edit(edit);
|
||||
// }
|
||||
|
||||
// log::debug!("patch stack size after {:#?}", patch_machine.stack);
|
||||
// patch_machine.reset();
|
||||
// our root node reference gets invalidated
|
||||
// not sure why
|
||||
// for now, just select the first child again.
|
||||
// eventually, we'll just make our own root element instead of using body
|
||||
// or just use body directly IDEK
|
||||
// let root_node = body_element.first_child().unwrap();
|
||||
// patch_machine.stack.push(root_node.clone());
|
||||
// }
|
||||
|
||||
Ok(()) // should actually never return from this, should be an error, rustc just cant see it
|
||||
}
|
||||
}
|
||||
@@ -135,7 +92,7 @@ fn prepare_websys_dom() -> Element {
|
||||
|
||||
// Build a dummy div
|
||||
let container: &Element = body.as_ref();
|
||||
container.set_inner_html("");
|
||||
// container.set_inner_html("");
|
||||
container
|
||||
.append_child(
|
||||
document
|
||||
@@ -164,6 +121,299 @@ fn prepare_websys_dom() -> Element {
|
||||
// };
|
||||
// }
|
||||
|
||||
/// Wasm-bindgen has a performance option to intern commonly used phrases
|
||||
/// This saves the decoding cost, making the interaction of Rust<->JS more performant.
|
||||
/// We intern all the HTML tags and attributes, making most operations much faster.
|
||||
///
|
||||
/// Interning takes about 1ms at the start of the app, but saves a *ton* of time later on.
|
||||
pub fn intern_cache() {
|
||||
let cached_words = [
|
||||
// All the HTML Tags
|
||||
"a",
|
||||
"abbr",
|
||||
"address",
|
||||
"area",
|
||||
"article",
|
||||
"aside",
|
||||
"audio",
|
||||
"b",
|
||||
"base",
|
||||
"bdi",
|
||||
"bdo",
|
||||
"big",
|
||||
"blockquote",
|
||||
"body",
|
||||
"br",
|
||||
"button",
|
||||
"canvas",
|
||||
"caption",
|
||||
"cite",
|
||||
"code",
|
||||
"col",
|
||||
"colgroup",
|
||||
"command",
|
||||
"data",
|
||||
"datalist",
|
||||
"dd",
|
||||
"del",
|
||||
"details",
|
||||
"dfn",
|
||||
"dialog",
|
||||
"div",
|
||||
"dl",
|
||||
"dt",
|
||||
"em",
|
||||
"embed",
|
||||
"fieldset",
|
||||
"figcaption",
|
||||
"figure",
|
||||
"footer",
|
||||
"form",
|
||||
"h1",
|
||||
"h2",
|
||||
"h3",
|
||||
"h4",
|
||||
"h5",
|
||||
"h6",
|
||||
"head",
|
||||
"header",
|
||||
"hr",
|
||||
"html",
|
||||
"i",
|
||||
"iframe",
|
||||
"img",
|
||||
"input",
|
||||
"ins",
|
||||
"kbd",
|
||||
"keygen",
|
||||
"label",
|
||||
"legend",
|
||||
"li",
|
||||
"link",
|
||||
"main",
|
||||
"map",
|
||||
"mark",
|
||||
"menu",
|
||||
"menuitem",
|
||||
"meta",
|
||||
"meter",
|
||||
"nav",
|
||||
"noscript",
|
||||
"object",
|
||||
"ol",
|
||||
"optgroup",
|
||||
"option",
|
||||
"output",
|
||||
"p",
|
||||
"param",
|
||||
"picture",
|
||||
"pre",
|
||||
"progress",
|
||||
"q",
|
||||
"rp",
|
||||
"rt",
|
||||
"ruby",
|
||||
"s",
|
||||
"samp",
|
||||
"script",
|
||||
"section",
|
||||
"select",
|
||||
"small",
|
||||
"source",
|
||||
"span",
|
||||
"strong",
|
||||
"style",
|
||||
"sub",
|
||||
"summary",
|
||||
"sup",
|
||||
"table",
|
||||
"tbody",
|
||||
"td",
|
||||
"textarea",
|
||||
"tfoot",
|
||||
"th",
|
||||
"thead",
|
||||
"time",
|
||||
"title",
|
||||
"tr",
|
||||
"track",
|
||||
"u",
|
||||
"ul",
|
||||
"var",
|
||||
"video",
|
||||
"wbr",
|
||||
// All the event handlers
|
||||
"Attribute",
|
||||
"accept",
|
||||
"accept-charset",
|
||||
"accesskey",
|
||||
"action",
|
||||
"alt",
|
||||
"async",
|
||||
"autocomplete",
|
||||
"autofocus",
|
||||
"autoplay",
|
||||
"charset",
|
||||
"checked",
|
||||
"cite",
|
||||
"class",
|
||||
"cols",
|
||||
"colspan",
|
||||
"content",
|
||||
"contenteditable",
|
||||
"controls",
|
||||
"coords",
|
||||
"data",
|
||||
"data-*",
|
||||
"datetime",
|
||||
"default",
|
||||
"defer",
|
||||
"dir",
|
||||
"dirname",
|
||||
"disabled",
|
||||
"download",
|
||||
"draggable",
|
||||
"enctype",
|
||||
"for",
|
||||
"form",
|
||||
"formaction",
|
||||
"headers",
|
||||
"height",
|
||||
"hidden",
|
||||
"high",
|
||||
"href",
|
||||
"hreflang",
|
||||
"http-equiv",
|
||||
"id",
|
||||
"ismap",
|
||||
"kind",
|
||||
"label",
|
||||
"lang",
|
||||
"list",
|
||||
"loop",
|
||||
"low",
|
||||
"max",
|
||||
"maxlength",
|
||||
"media",
|
||||
"method",
|
||||
"min",
|
||||
"multiple",
|
||||
"muted",
|
||||
"name",
|
||||
"novalidate",
|
||||
"onabort",
|
||||
"onafterprint",
|
||||
"onbeforeprint",
|
||||
"onbeforeunload",
|
||||
"onblur",
|
||||
"oncanplay",
|
||||
"oncanplaythrough",
|
||||
"onchange",
|
||||
"onclick",
|
||||
"oncontextmenu",
|
||||
"oncopy",
|
||||
"oncuechange",
|
||||
"oncut",
|
||||
"ondblclick",
|
||||
"ondrag",
|
||||
"ondragend",
|
||||
"ondragenter",
|
||||
"ondragleave",
|
||||
"ondragover",
|
||||
"ondragstart",
|
||||
"ondrop",
|
||||
"ondurationchange",
|
||||
"onemptied",
|
||||
"onended",
|
||||
"onerror",
|
||||
"onfocus",
|
||||
"onhashchange",
|
||||
"oninput",
|
||||
"oninvalid",
|
||||
"onkeydown",
|
||||
"onkeypress",
|
||||
"onkeyup",
|
||||
"onload",
|
||||
"onloadeddata",
|
||||
"onloadedmetadata",
|
||||
"onloadstart",
|
||||
"onmousedown",
|
||||
"onmousemove",
|
||||
"onmouseout",
|
||||
"onmouseover",
|
||||
"onmouseup",
|
||||
"onmousewheel",
|
||||
"onoffline",
|
||||
"ononline",
|
||||
"<body>",
|
||||
"onpageshow",
|
||||
"onpaste",
|
||||
"onpause",
|
||||
"onplay",
|
||||
"onplaying",
|
||||
"<body>",
|
||||
"onprogress",
|
||||
"onratechange",
|
||||
"onreset",
|
||||
"onresize",
|
||||
"onscroll",
|
||||
"onsearch",
|
||||
"onseeked",
|
||||
"onseeking",
|
||||
"onselect",
|
||||
"onstalled",
|
||||
"<body>",
|
||||
"onsubmit",
|
||||
"onsuspend",
|
||||
"ontimeupdate",
|
||||
"ontoggle",
|
||||
"onunload",
|
||||
"onvolumechange",
|
||||
"onwaiting",
|
||||
"onwheel",
|
||||
"open",
|
||||
"optimum",
|
||||
"pattern",
|
||||
"placeholder",
|
||||
"poster",
|
||||
"preload",
|
||||
"readonly",
|
||||
"rel",
|
||||
"required",
|
||||
"reversed",
|
||||
"rows",
|
||||
"rowspan",
|
||||
"sandbox",
|
||||
"scope",
|
||||
"selected",
|
||||
"shape",
|
||||
"size",
|
||||
"sizes",
|
||||
"span",
|
||||
"spellcheck",
|
||||
"src",
|
||||
"srcdoc",
|
||||
"srclang",
|
||||
"srcset",
|
||||
"start",
|
||||
"step",
|
||||
"style",
|
||||
"tabindex",
|
||||
"target",
|
||||
"title",
|
||||
"translate",
|
||||
"type",
|
||||
"usemap",
|
||||
"value",
|
||||
"width",
|
||||
"wrap",
|
||||
];
|
||||
|
||||
for s in cached_words {
|
||||
wasm_bindgen::intern(s);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::env;
|
||||
|
||||
+24
-7
@@ -171,6 +171,7 @@ impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom {
|
||||
tag: &str,
|
||||
ns: Option<&'static str>,
|
||||
) -> dioxus_core::virtual_dom::RealDomNode {
|
||||
let tag = wasm_bindgen::intern(tag);
|
||||
let el = match ns {
|
||||
Some(ns) => self
|
||||
.document
|
||||
@@ -200,6 +201,7 @@ impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom {
|
||||
el_id: usize,
|
||||
real_id: RealDomNode,
|
||||
) {
|
||||
let event = wasm_bindgen::intern(event);
|
||||
log::debug!(
|
||||
"Called [`new_event_listener`]: {}, {:?}, {}, {:?}",
|
||||
event,
|
||||
@@ -237,7 +239,7 @@ impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom {
|
||||
// Instead, we just build and immediately execute a closure that returns result
|
||||
match decode_trigger(event) {
|
||||
Ok(synthetic_event) => trigger.as_ref()(synthetic_event),
|
||||
Err(_) => log::error!("Error decoding Dioxus event attribute."),
|
||||
Err(e) => log::error!("Error decoding Dioxus event attribute. {:#?}", e),
|
||||
};
|
||||
}) as Box<dyn FnMut(&Event)>);
|
||||
|
||||
@@ -407,7 +409,7 @@ fn virtual_event_from_websys_event(event: &web_sys::Event) -> VirtualEvent {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CustomMouseEvent(web_sys::MouseEvent);
|
||||
impl dioxus_core::events::on::MouseEvent for CustomMouseEvent {
|
||||
impl dioxus_core::events::on::MouseEventInner for CustomMouseEvent {
|
||||
fn alt_key(&self) -> bool {
|
||||
self.0.alt_key()
|
||||
}
|
||||
@@ -451,7 +453,7 @@ fn virtual_event_from_websys_event(event: &web_sys::Event) -> VirtualEvent {
|
||||
self.0.get_modifier_state(key_code)
|
||||
}
|
||||
}
|
||||
VirtualEvent::MouseEvent(Rc::new(CustomMouseEvent(evt)))
|
||||
VirtualEvent::MouseEvent(MouseEvent(Rc::new(CustomMouseEvent(evt))))
|
||||
// MouseEvent(Box::new(RawMouseEvent {
|
||||
// alt_key: evt.alt_key(),
|
||||
// button: evt.button() as i32,
|
||||
@@ -547,25 +549,36 @@ fn decode_trigger(event: &web_sys::Event) -> anyhow::Result<EventTrigger> {
|
||||
|
||||
use anyhow::Context;
|
||||
|
||||
// for attr in {
|
||||
let attrs = target.attributes();
|
||||
for x in 0..attrs.length() {
|
||||
let attr = attrs.item(x).unwrap();
|
||||
log::debug!("attrs include: {:#?}", attr);
|
||||
}
|
||||
// }
|
||||
// for attr in target.attributes() {
|
||||
// log::debug!("attrs include: {:#?}", attr);
|
||||
// }
|
||||
|
||||
// The error handling here is not very descriptive and needs to be replaced with a zero-cost error system
|
||||
let val: String = target
|
||||
.get_attribute(&format!("dioxus-event-{}", typ))
|
||||
.context("")?;
|
||||
.context(format!("wrong format - received {:#?}", typ))?;
|
||||
|
||||
let mut fields = val.splitn(3, ".");
|
||||
|
||||
let gi_id = fields
|
||||
.next()
|
||||
.and_then(|f| f.parse::<u64>().ok())
|
||||
.context("")?;
|
||||
.context("failed to parse gi id")?;
|
||||
let el_id = fields
|
||||
.next()
|
||||
.and_then(|f| f.parse::<usize>().ok())
|
||||
.context("")?;
|
||||
.context("failed to parse el id")?;
|
||||
let real_id = fields
|
||||
.next()
|
||||
.and_then(|f| f.parse::<u64>().ok().map(RealDomNode::new))
|
||||
.context("")?;
|
||||
.context("failed to parse real id")?;
|
||||
|
||||
// Call the trigger
|
||||
log::debug!("decoded gi_id: {}, li_idx: {}", gi_id, el_id);
|
||||
@@ -575,6 +588,7 @@ fn decode_trigger(event: &web_sys::Event) -> anyhow::Result<EventTrigger> {
|
||||
virtual_event_from_websys_event(event),
|
||||
triggered_scope,
|
||||
real_id,
|
||||
dioxus_core::events::EventPriority::High,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -584,3 +598,6 @@ impl ListenerMap {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
struct JsStringCache {}
|
||||
impl JsStringCache {}
|
||||
Reference in new issue
Block a user