Merge branch 'DioxusLabs:master' into lazy_tui

This commit is contained in:
Demonthos authored and GitHub committed 2022-04-04 12:10:18 -05:00
commit 479c12725f
34 files changed
+212 -92

No files matched your search

+1
View File
@@ -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),
};
+8
View File
@@ -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 });
+18
View File
@@ -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))
}
+1 -1
View File
@@ -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;
+17 -17
View File
@@ -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> {
+3
View File
@@ -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);
+3
View File
@@ -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);
+1 -1
View File
@@ -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:?}" } })
}
+3 -3
View File
@@ -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
}
}
+2 -2
View File
@@ -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;
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -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()
+4 -4
View File
@@ -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);
+2
View File
@@ -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.
///
+25
View File
@@ -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");
}
})
}