Merge branch 'DioxusLabs:master' into lazy_tui
This commit is contained in:
34 files changed
+212
-92
No files matched your search
@@ -426,6 +426,7 @@ impl<'b> DiffState<'b> {
|
||||
self.mutations.push_root(root);
|
||||
let created = self.create_children(new.children);
|
||||
self.mutations.append_children(created as u32);
|
||||
self.mutations.pop_root();
|
||||
}
|
||||
(_, _) => self.diff_children(old.children, new.children),
|
||||
};
|
||||
|
||||
@@ -185,6 +185,9 @@ pub enum DomEdit<'bump> {
|
||||
/// The namespace of the attribute.
|
||||
ns: Option<&'bump str>,
|
||||
},
|
||||
|
||||
/// Manually pop a root node from the stack.
|
||||
PopRoot {},
|
||||
}
|
||||
|
||||
use fxhash::FxHashSet;
|
||||
@@ -205,6 +208,11 @@ impl<'a> Mutations<'a> {
|
||||
self.edits.push(PushRoot { root: id });
|
||||
}
|
||||
|
||||
// Navigation
|
||||
pub(crate) fn pop_root(&mut self) {
|
||||
self.edits.push(PopRoot {});
|
||||
}
|
||||
|
||||
pub(crate) fn replace_with(&mut self, root: ElementId, m: u32) {
|
||||
let root = root.as_u64();
|
||||
self.edits.push(ReplaceWith { m, root });
|
||||
|
||||
@@ -119,6 +119,11 @@ impl DesktopContext {
|
||||
pub fn devtool(&self) {
|
||||
let _ = self.proxy.send_event(DevTool);
|
||||
}
|
||||
|
||||
/// run (evaluate) a script in the WebView context
|
||||
pub fn eval(&self, script: impl std::string::ToString) {
|
||||
let _ = self.proxy.send_event(Eval(script.to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -144,6 +149,8 @@ pub enum UserWindowEvent {
|
||||
SetDecorations(bool),
|
||||
|
||||
DevTool,
|
||||
|
||||
Eval(String),
|
||||
}
|
||||
|
||||
pub(super) fn handler(
|
||||
@@ -185,5 +192,16 @@ pub(super) fn handler(
|
||||
SetDecorations(state) => window.set_decorations(state),
|
||||
|
||||
DevTool => webview.devtool(),
|
||||
|
||||
Eval(code) => webview
|
||||
.evaluate_script(code.as_str())
|
||||
.expect("eval shouldn't panic"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a closure that executes any JavaScript in the WebView context.
|
||||
pub fn use_eval<S: std::string::ToString>(cx: &ScopeState) -> &dyn Fn(S) {
|
||||
let desktop = use_window(&cx).clone();
|
||||
|
||||
cx.use_hook(|_| move |script| desktop.eval(script))
|
||||
}
|
||||
@@ -11,7 +11,7 @@ mod events;
|
||||
mod protocol;
|
||||
|
||||
use desktop_context::UserWindowEvent;
|
||||
pub use desktop_context::{use_window, DesktopContext};
|
||||
pub use desktop_context::{use_eval, use_window, DesktopContext};
|
||||
pub use wry;
|
||||
pub use wry::application as tao;
|
||||
|
||||
|
||||
@@ -92,9 +92,9 @@ impl<T: 'static> UseState<T> {
|
||||
///
|
||||
/// ```rust, ignore
|
||||
/// fn component(cx: Scope) -> Element {
|
||||
/// let (count, set_count) = use_state(&cx, || 0);
|
||||
/// let count = use_state(&cx, || 0);
|
||||
/// cx.spawn({
|
||||
/// let set_count = set_count.to_owned();
|
||||
/// let set_count = count.to_owned();
|
||||
/// async move {
|
||||
/// let current = set_count.current();
|
||||
/// }
|
||||
@@ -119,11 +119,11 @@ impl<T: 'static> UseState<T> {
|
||||
///
|
||||
/// ```rust, ignore
|
||||
/// fn component(cx: Scope) -> Element {
|
||||
/// let (value, set_value) = use_state(&cx, || 0);
|
||||
/// let value = use_state(&cx, || 0);
|
||||
///
|
||||
/// rsx!{
|
||||
/// Component {
|
||||
/// handler: set_val.setter()
|
||||
/// handler: value.setter()
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
@@ -144,16 +144,16 @@ impl<T: 'static> UseState<T> {
|
||||
/// # use dioxus_core::prelude::*;
|
||||
/// # use dioxus_hooks::*;
|
||||
/// fn component(cx: Scope) -> Element {
|
||||
/// let (value, set_value) = use_state(&cx, || 0);
|
||||
/// let value = use_state(&cx, || 0);
|
||||
///
|
||||
/// // to increment the value
|
||||
/// set_value.modify(|v| v + 1);
|
||||
/// value.modify(|v| v + 1);
|
||||
///
|
||||
/// // usage in async
|
||||
/// cx.spawn({
|
||||
/// let set_value = set_value.to_owned();
|
||||
/// let value = value.to_owned();
|
||||
/// async move {
|
||||
/// set_value.modify(|v| v + 1);
|
||||
/// value.modify(|v| v + 1);
|
||||
/// }
|
||||
/// });
|
||||
///
|
||||
@@ -185,9 +185,9 @@ impl<T: 'static> UseState<T> {
|
||||
/// # use dioxus_core::prelude::*;
|
||||
/// # use dioxus_hooks::*;
|
||||
/// fn component(cx: Scope) -> Element {
|
||||
/// let (value, set_value) = use_state(&cx, || 0);
|
||||
/// let value = use_state(&cx, || 0);
|
||||
///
|
||||
/// let as_rc = set_value.get();
|
||||
/// let as_rc = value.get();
|
||||
/// assert_eq!(as_rc.as_ref(), &0);
|
||||
///
|
||||
/// # todo!()
|
||||
@@ -207,12 +207,12 @@ impl<T: 'static> UseState<T> {
|
||||
///
|
||||
/// ```rust, ignore
|
||||
/// fn component(cx: Scope) -> Element {
|
||||
/// let (count, set_count) = use_state(&cx, || 0);
|
||||
/// let count = use_state(&cx, || 0);
|
||||
/// cx.spawn({
|
||||
/// let set_count = set_count.to_owned();
|
||||
/// let count = count.to_owned();
|
||||
/// async move {
|
||||
/// // for the component to re-render
|
||||
/// set_count.needs_update();
|
||||
/// count.needs_update();
|
||||
/// }
|
||||
/// })
|
||||
/// }
|
||||
@@ -237,9 +237,9 @@ impl<T: Clone> UseState<T> {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let (val, set_val) = use_state(&cx, || 0);
|
||||
/// let val = use_state(&cx, || 0);
|
||||
///
|
||||
/// set_val.with_mut(|v| *v = 1);
|
||||
/// val.with_mut(|v| *v = 1);
|
||||
/// ```
|
||||
pub fn with_mut(&self, apply: impl FnOnce(&mut T)) {
|
||||
let mut slot = self.slot.borrow_mut();
|
||||
@@ -269,9 +269,9 @@ impl<T: Clone> UseState<T> {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let (val, set_val) = use_state(&cx, || 0);
|
||||
/// let val = use_state(&cx, || 0);
|
||||
///
|
||||
/// *set_val.make_mut() += 1;
|
||||
/// *val.make_mut() += 1;
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub fn make_mut(&self) -> RefMut<T> {
|
||||
|
||||
@@ -17,6 +17,9 @@ extern "C" {
|
||||
#[wasm_bindgen(method)]
|
||||
pub fn PushRoot(this: &Interpreter, root: u64);
|
||||
|
||||
#[wasm_bindgen(method)]
|
||||
pub fn PopRoot(this: &Interpreter);
|
||||
|
||||
#[wasm_bindgen(method)]
|
||||
pub fn AppendChildren(this: &Interpreter, many: u32);
|
||||
|
||||
|
||||
@@ -27,6 +27,9 @@ export class Interpreter {
|
||||
const node = this.nodes[root];
|
||||
this.stack.push(node);
|
||||
}
|
||||
PopRoot() {
|
||||
this.stack.pop();
|
||||
}
|
||||
AppendChildren(many) {
|
||||
let root = this.stack[this.stack.length - (1 + many)];
|
||||
let to_add = this.stack.splice(this.stack.length - many);
|
||||
|
||||
@@ -46,7 +46,7 @@ fn BlogList(cx: Scope) -> Element {
|
||||
fn BlogPost(cx: Scope) -> Element {
|
||||
let id = use_route(&cx).segment("id")?;
|
||||
|
||||
log::debug!("rendering blog post {}", id);
|
||||
log::trace!("rendering blog post {}", id);
|
||||
|
||||
cx.render(rsx! { div { "{id:?}" } })
|
||||
}
|
||||
@@ -53,13 +53,13 @@ pub fn Route<'a>(cx: Scope<'a, RouteProps<'a>>) -> Element {
|
||||
router_root.register_total_route(route_context.total_route, cx.scope_id());
|
||||
});
|
||||
|
||||
log::debug!("Checking Route: {:?}", cx.props.to);
|
||||
log::trace!("Checking Route: {:?}", cx.props.to);
|
||||
|
||||
if router_root.should_render(cx.scope_id()) {
|
||||
log::debug!("Route should render: {:?}", cx.scope_id());
|
||||
log::trace!("Route should render: {:?}", cx.scope_id());
|
||||
cx.render(rsx!(&cx.props.children))
|
||||
} else {
|
||||
log::debug!("Route should *not* render: {:?}", cx.scope_id());
|
||||
log::trace!("Route should *not* render: {:?}", cx.scope_id());
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -182,7 +182,7 @@ impl RouterCore {
|
||||
|
||||
if let Some(route) = roots.get(&scope) {
|
||||
let cur = &self.current_location().url;
|
||||
log::debug!("Checking if {} matches {}", cur, route);
|
||||
log::trace!("Checking if {} matches {}", cur, route);
|
||||
|
||||
if route_matches_path(cur, route, self.cfg.base_url.as_ref()) || route.is_empty() {
|
||||
self.route_found.set(Some(scope));
|
||||
@@ -236,7 +236,7 @@ fn route_matches_path(cur: &Url, attempt: &str, base_url: Option<&String>) -> bo
|
||||
|
||||
let attempt_pieces = clean_path(attempt).split('/').collect::<Vec<_>>();
|
||||
|
||||
log::debug!("Comparing {:?} to {:?}", cur_pieces, attempt_pieces);
|
||||
log::trace!("Comparing {:?} to {:?}", cur_pieces, attempt_pieces);
|
||||
|
||||
if attempt_pieces.len() != cur_pieces.len() {
|
||||
return false;
|
||||
|
||||
@@ -21,7 +21,7 @@ fn simple_test() {
|
||||
static APP: Component = |cx| {
|
||||
cx.render(rsx! {
|
||||
Router {
|
||||
onchange: move |route: RouterService| log::info!("route changed to {:?}", route.current_location()),
|
||||
onchange: move |route: RouterService| log::trace!("route changed to {:?}", route.current_location()),
|
||||
active_class: "is-active",
|
||||
Route { to: "/", Home {} }
|
||||
Route { to: "blog"
|
||||
|
||||
@@ -49,7 +49,7 @@ fn main() {
|
||||
let _ = dom.rebuild();
|
||||
|
||||
let pre = dioxus_ssr::pre_render_vdom(&dom);
|
||||
log::debug!("{}", pre);
|
||||
log::trace!("{}", pre);
|
||||
|
||||
// set the inner content of main to the pre-rendered content
|
||||
window()
|
||||
|
||||
@@ -105,6 +105,7 @@ impl WebsysDom {
|
||||
for edit in edits.drain(..) {
|
||||
match edit {
|
||||
DomEdit::PushRoot { root } => self.interpreter.PushRoot(root),
|
||||
DomEdit::PopRoot {} => self.interpreter.PopRoot(),
|
||||
DomEdit::AppendChildren { many } => self.interpreter.AppendChildren(many),
|
||||
DomEdit::ReplaceWith { root, m } => self.interpreter.ReplaceWith(root, m),
|
||||
DomEdit::InsertAfter { root, n } => self.interpreter.InsertAfter(root, n),
|
||||
@@ -244,7 +245,6 @@ fn virtual_event_from_websys_event(
|
||||
let value: Option<String> = (&element)
|
||||
.dyn_ref()
|
||||
.map(|input: &web_sys::HtmlInputElement| {
|
||||
log::info!("Input type: {}", input.type_());
|
||||
match input.type_().as_str() {
|
||||
"checkbox" => {
|
||||
match input.checked() {
|
||||
@@ -261,9 +261,9 @@ fn virtual_event_from_websys_event(
|
||||
_ => Some(input.value())
|
||||
}
|
||||
})
|
||||
.or_else(|| target.dyn_ref().map(|input: &web_sys::HtmlTextAreaElement| Some(input.value())))
|
||||
.or_else(|| target.dyn_ref().map(|input: &web_sys::HtmlSelectElement| Some(input.value())))
|
||||
.or_else(|| Some(target.dyn_ref::<web_sys::HtmlElement>().unwrap().text_content()))
|
||||
.or_else(|| element.dyn_ref().map(|input: &web_sys::HtmlTextAreaElement| Some(input.value())))
|
||||
.or_else(|| element.dyn_ref().map(|input: &web_sys::HtmlSelectElement| Some(input.value())))
|
||||
.or_else(|| Some(element.dyn_ref::<web_sys::HtmlElement>().unwrap().text_content()))
|
||||
.expect("only an InputElement or TextAreaElement or an element with contenteditable=true can have an oninput event listener");
|
||||
if let Some(value) = value {
|
||||
values.insert(name, value);
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
pub use crate::cfg::WebConfig;
|
||||
pub use crate::util::use_eval;
|
||||
use dioxus::SchedulerMsg;
|
||||
use dioxus::VirtualDom;
|
||||
pub use dioxus_core as dioxus;
|
||||
@@ -68,6 +69,7 @@ mod cfg;
|
||||
mod dom;
|
||||
mod rehydrate;
|
||||
mod ric_raf;
|
||||
mod util;
|
||||
|
||||
/// Launch the VirtualDOM given a root component and a configuration.
|
||||
///
|
||||
|
||||
@@ -1 +1,26 @@
|
||||
//! Utilities specific to websys
|
||||
|
||||
use dioxus_core::*;
|
||||
|
||||
/// Get a closure that executes any JavaScript in the webpage.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Please be very careful with this function. A script with too many dynamic
|
||||
/// parts is practically asking for a hacker to find an XSS vulnerability in
|
||||
/// it. **This applies especially to web targets, where the JavaScript context
|
||||
/// has access to most, if not all of your application data.**
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// The closure will panic if the provided script is not valid JavaScript code
|
||||
/// or if it returns an uncaught error.
|
||||
pub fn use_eval<S: std::string::ToString>(cx: &ScopeState) -> &dyn Fn(S) {
|
||||
cx.use_hook(|_| {
|
||||
|script: S| {
|
||||
js_sys::Function::new_no_args(&script.to_string())
|
||||
.call0(&wasm_bindgen::JsValue::NULL)
|
||||
.expect("failed to eval script");
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user