diff --git a/Cargo.toml b/Cargo.toml index 523d0b521..93b1de804 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,6 +47,7 @@ fxhash = "0.2.1" anyhow = "1.0.42" reqwest = "0.11.4" serde_json = "1.0.68" +simple_logger = "1.13.0" [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] argh = "0.1.5" diff --git a/examples/calculator.rs b/examples/calculator.rs index 7108b368b..42b475468 100644 --- a/examples/calculator.rs +++ b/examples/calculator.rs @@ -3,7 +3,7 @@ This example is a simple iOS-style calculator. This particular example can run a This calculator version uses React-style state management. All state is held as individual use_states. */ -use dioxus::events::on::*; +use dioxus::events::*; use dioxus::prelude::*; fn main() { @@ -56,7 +56,7 @@ const APP: FC<()> = |cx, _| { } }; - let keydownhandler = move |evt: KeyboardEvent| match evt.key_code() { + let keydownhandler = move |evt: KeyboardEvent| match evt.key_code { KeyCode::Add => operator.set(Some("+")), KeyCode::Subtract => operator.set(Some("-")), KeyCode::Divide => operator.set(Some("/")), diff --git a/examples/crm.rs b/examples/crm.rs index 8d8662647..c44423bd0 100644 --- a/examples/crm.rs +++ b/examples/crm.rs @@ -59,13 +59,13 @@ static App: FC<()> = |cx, _| { h2 {"Add new client" margin_bottom: "10px" } form { class: "pure-form" input { class: "new-client firstname" placeholder: "First name" value: "{firstname}" - oninput: move |e| firstname.set(e.value()) + oninput: move |e| firstname.set(e.value.clone()) } input { class: "new-client lastname" placeholder: "Last name" value: "{lastname}" - oninput: move |e| lastname.set(e.value()) + oninput: move |e| lastname.set(e.value.clone()) } textarea { class: "new-client description" placeholder: "Description" value: "{description}" - oninput: move |e| description.set(e.value()) + oninput: move |e| description.set(e.value.clone()) } } button { class: "pure-button pure-button-primary", onclick: {add_new}, "Add New" } diff --git a/examples/file_explorer.rs b/examples/file_explorer.rs index e6fadc989..e050ce0d4 100644 --- a/examples/file_explorer.rs +++ b/examples/file_explorer.rs @@ -8,11 +8,11 @@ use dioxus::prelude::*; fn main() { - env_logger::init(); + simple_logger::init_with_level(log::Level::Debug); dioxus::desktop::launch(App, |c| { c.with_window(|w| { - w.with_resizable(false).with_inner_size( - dioxus::desktop::wry::application::dpi::LogicalSize::new(800.0, 400.0), + w.with_resizable(true).with_inner_size( + dioxus::desktop::wry::application::dpi::LogicalSize::new(400.0, 800.0), ) }) }) @@ -70,6 +70,7 @@ impl Files { fn reload_path_list(&mut self) { let cur_path = self.path_stack.last().unwrap(); + log::info!("Reloading path list for {:?}", cur_path); let paths = match std::fs::read_dir(cur_path) { Ok(e) => e, Err(err) => { @@ -79,15 +80,18 @@ impl Files { return; } }; + let collected = paths.collect::>(); + log::info!("Path list reloaded {:#?}", collected); // clear the current state self.clear_err(); self.path_names.clear(); - for path in paths { + for path in collected { self.path_names .push(path.unwrap().path().display().to_string()); } + log::info!("path namees are {:#?}", self.path_names); } fn go_up(&mut self) { diff --git a/examples/manual_edits.rs b/examples/manual_edits.rs index 57150c9a2..30e133d2c 100644 --- a/examples/manual_edits.rs +++ b/examples/manual_edits.rs @@ -30,7 +30,7 @@ fn main() { AppendChildren { many: 1 }, ]; - dioxus_desktop::WebviewRenderer::run_with_edits(APP, (), |c| c, Some(edits)).expect("failed"); + dioxus_desktop::run(APP, (), |c| c.with_edits(edits)).unwrap(); } const APP: FC<()> = |cx, _props| { diff --git a/examples/pattern_model.rs b/examples/pattern_model.rs index f7012fa32..5bdbcca66 100644 --- a/examples/pattern_model.rs +++ b/examples/pattern_model.rs @@ -16,7 +16,7 @@ //! RefMuts at the same time. use dioxus::desktop::wry::application::dpi::LogicalSize; -use dioxus::events::on::*; +use dioxus::events::{on::*, KeyCode}; use dioxus::prelude::*; const STYLE: &str = include_str!("./assets/calculator.css"); @@ -169,7 +169,7 @@ impl Calculator { self.waiting_for_operand = true; } fn handle_keydown(&mut self, evt: KeyboardEvent) { - match evt.key_code() { + match evt.key_code { KeyCode::Backspace => self.backspace(), KeyCode::Num0 => self.input_digit(0), KeyCode::Num1 => self.input_digit(1), diff --git a/examples/todomvc.rs b/examples/todomvc.rs index c094d889a..a28059c3e 100644 --- a/examples/todomvc.rs +++ b/examples/todomvc.rs @@ -57,7 +57,7 @@ const App: FC<()> = |cx, props| { class: "new-todo" placeholder: "What needs to be done?" value: "{draft}" - oninput: move |evt| draft.set(evt.value()) + oninput: move |evt| draft.set(evt.value.clone()) } } {todolist} @@ -100,7 +100,7 @@ pub fn TodoEntry<'a>(cx: Context<'a>, props: &TodoEntryProps) -> DomTree<'a> { {is_editing.then(|| rsx!{ input { value: "{contents}" - oninput: move |evt| contents.set(evt.value()) + oninput: move |evt| contents.set(evt.value.clone()) } })} }) diff --git a/packages/core/src/events.rs b/packages/core/src/events.rs index 042884c68..2b40802a0 100644 --- a/packages/core/src/events.rs +++ b/packages/core/src/events.rs @@ -17,6 +17,8 @@ use std::{ sync::Arc, }; +pub use on::*; + #[derive(Debug)] pub struct UserEvent { /// The originator of the event trigger diff --git a/packages/desktop/src/cfg.rs b/packages/desktop/src/cfg.rs index 8ba0ddc73..0bfdbab36 100644 --- a/packages/desktop/src/cfg.rs +++ b/packages/desktop/src/cfg.rs @@ -30,8 +30,9 @@ impl<'a> DesktopConfig<'a> { } } - pub fn with_edits(&mut self, edits: Vec>) { + pub fn with_edits(&mut self, edits: Vec>) -> &mut Self { self.manual_edits = Some(edits); + self } pub fn with_prerendered(&mut self, content: String) -> &mut Self { diff --git a/packages/desktop/src/index.html b/packages/desktop/src/index.html index 1e7372c48..f58b973e0 100644 --- a/packages/desktop/src/index.html +++ b/packages/desktop/src/index.html @@ -9,7 +9,7 @@
- diff --git a/packages/desktop/src/index.js b/packages/desktop/src/index.js index 04a315fde..b48878073 100644 --- a/packages/desktop/src/index.js +++ b/packages/desktop/src/index.js @@ -153,6 +153,10 @@ class Interpreter { this.root.addEventListener(event_name, (event) => { const target = event.target; const val = target.getAttribute(`dioxus-event-${event_name}`); + if (val == null) { + return; + } + const fields = val.split("."); const scope_id = parseInt(fields[0]); const real_id = parseInt(fields[1]); diff --git a/packages/desktop/src/lib.rs b/packages/desktop/src/lib.rs index 9deda3bc9..cba3e518e 100644 --- a/packages/desktop/src/lib.rs +++ b/packages/desktop/src/lib.rs @@ -93,7 +93,7 @@ pub fn run( let locked_receiver = Rc::new(RefCell::new(event_rx)); let webview = WebViewBuilder::new(window)? - .with_url("wry://src/index.html")? + .with_url("wry://index.html")? .with_rpc_handler(move |_window: &Window, mut req: RpcRequest| { // match req.method.as_str() { @@ -130,20 +130,11 @@ pub fn run( use wry::http::ResponseBuilder; // Remove url scheme let path = request.uri().replace("wry://", ""); - // Read the file content from file path - let content = read(canonicalize(&path)?)?; - // Return asset contents and mime types based on file extentions - // If you don't want to do this manually, there are some crates for you. - // Such as `infer` and `mime_guess`. - let (data, meta) = if path.ends_with(".html") { - (content, "text/html") - } else if path.ends_with(".js") { - (content, "text/javascript") - } else if path.ends_with(".png") { - (content, "image/png") - } else { - unimplemented!(); + let (data, meta) = match path.as_str() { + "index.html" => (include_bytes!("./index.html").to_vec(), "text/html"), + "index.html/index.js" => (include_bytes!("./index.js").to_vec(), "text/javascript"), + _ => unimplemented!("path {}", path), }; ResponseBuilder::new().mimetype(meta).body(data) diff --git a/packages/hooks/src/useref.rs b/packages/hooks/src/useref.rs index 1639628e0..0f780b6e4 100644 --- a/packages/hooks/src/useref.rs +++ b/packages/hooks/src/useref.rs @@ -1,14 +1,37 @@ -use std::cell::{Ref, RefCell, RefMut}; +use std::{ + cell::{Cell, Ref, RefCell, RefMut}, + rc::Rc, +}; use dioxus_core::Context; +pub fn use_ref(cx: Context, f: impl FnOnce() -> T) -> UseRef { + cx.use_hook( + |_| UseRefInner { + update_scheuled: Cell::new(false), + update_callback: cx.schedule_update(), + value: RefCell::new(f()), + }, + |inner| { + inner.update_scheuled.set(false); + UseRef { inner } + }, + |_| {}, + ) +} + pub struct UseRef<'a, T> { - inner: &'a RefCell, + inner: &'a UseRefInner, +} +struct UseRefInner { + update_scheuled: Cell, + update_callback: Rc, + value: RefCell, } impl<'a, T> UseRef<'a, T> { pub fn read(&self) -> Ref<'_, T> { - self.inner.borrow() + self.inner.value.borrow() } pub fn read_write(&self) -> (Ref<'_, T>, &Self) { @@ -17,12 +40,20 @@ impl<'a, T> UseRef<'a, T> { /// Calling "write" will force the component to re-render pub fn write(&self) -> RefMut<'_, T> { - self.inner.borrow_mut() + self.needs_update(); + self.inner.value.borrow_mut() } /// Allows the ability to write the value without forcing a re-render pub fn write_silent(&self) -> RefMut<'_, T> { - self.inner.borrow_mut() + self.inner.value.borrow_mut() + } + + pub fn needs_update(&self) { + if !self.inner.update_scheuled.get() { + self.inner.update_scheuled.set(true); + (self.inner.update_callback)(); + } } } @@ -32,7 +63,3 @@ impl Clone for UseRef<'_, T> { } } impl Copy for UseRef<'_, T> {} - -pub fn use_ref(cx: Context, f: impl FnOnce() -> T) -> UseRef { - cx.use_hook(|_| RefCell::new(f()), |f| UseRef { inner: f }, |_| {}) -} diff --git a/packages/mobile/src/lib.rs b/packages/mobile/src/lib.rs index fccdd4317..ff9614fab 100644 --- a/packages/mobile/src/lib.rs +++ b/packages/mobile/src/lib.rs @@ -29,7 +29,7 @@ static HTML_CONTENT: &'static str = include_str!("../../desktop/src/index.html") pub fn launch(root: FC<()>, builder: fn(WindowBuilder) -> WindowBuilder) -> anyhow::Result<()> { launch_with_props(root, (), builder) } -pub fn launch_with_props( +pub fn launch_with_props( root: FC

, props: P, builder: fn(WindowBuilder) -> WindowBuilder, @@ -50,7 +50,7 @@ enum RpcEvent<'a> { }, } -impl WebviewRenderer { +impl WebviewRenderer { pub fn run( root: FC, props: T, diff --git a/packages/web/examples/basic.rs b/packages/web/examples/basic.rs index bee94bcdf..99615dc69 100644 --- a/packages/web/examples/basic.rs +++ b/packages/web/examples/basic.rs @@ -26,7 +26,7 @@ static APP: FC<()> = |cx, _| { input { r#type: "text", value: "{text_content}" - oninput: move |e| text_content.set(e.value()) + oninput: move |e| text_content.set(e.value.clone()) } {(0..10).map(|_| { @@ -45,8 +45,8 @@ static APP: FC<()> = |cx, _| { id: "cars" value: "{content}" oninput: move |ev| { - content.set(ev.value()); - match ev.value().as_str() { + content.set(ev.value.clone()); + match ev.value.as_str() { "h1" => count.set(0), "h2" => count.set(5), "h3" => count.set(10), diff --git a/packages/web/examples/crm2.rs b/packages/web/examples/crm2.rs index a539d262d..4dfe9db34 100644 --- a/packages/web/examples/crm2.rs +++ b/packages/web/examples/crm2.rs @@ -68,13 +68,13 @@ static App: FC<()> = |cx, _| { h2 {"Add new client" margin_bottom: "10px" } form { class: "pure-form" input { class: "new-client firstname" placeholder: "First name" value: "{firstname}" - oninput: move |evt| firstname.set(evt.value()) + oninput: move |evt| firstname.set(evt.value.clone()) } input { class: "new-client lastname" placeholder: "Last name" value: "{lastname}" - oninput: move |evt| lastname.set(evt.value()) + oninput: move |evt| lastname.set(evt.value.clone()) } textarea { class: "new-client description" placeholder: "Description" value: "{description}" - oninput: move |evt| description.set(evt.value()) + oninput: move |evt| description.set(evt.value.clone()) } } button { class: "pure-button pure-button-primary", onclick: {add_new}, "Add New" }