diff --git a/docs/guide/Cargo.toml b/docs/guide/Cargo.toml index eb8060552..87d5b9006 100644 --- a/docs/guide/Cargo.toml +++ b/docs/guide/Cargo.toml @@ -4,6 +4,7 @@ version = "0.0.1" edition = "2021" description = "Dioxus guide, including testable examples" license = "MIT/Apache-2.0" +publish = false [dev-dependencies] dioxus = { path = "../../packages/dioxus" } @@ -20,4 +21,4 @@ fermi = { path = "../../packages/fermi" } serde = { version = "1.0.138", features=["derive"] } reqwest = { version = "0.11.11", features = ["json"] } tokio = { version = "1.19.2" , features=[]} -axum = { version = "0.6.1", features = ["ws"] } \ No newline at end of file +axum = { version = "0.6.1", features = ["ws"] } diff --git a/docs/guide/src/en/getting_started/tui.md b/docs/guide/src/en/getting_started/tui.md index c776e24d9..e49cb84a8 100644 --- a/docs/guide/src/en/getting_started/tui.md +++ b/docs/guide/src/en/getting_started/tui.md @@ -12,7 +12,7 @@ TUI support is currently quite experimental. But, if you're willing to venture i - It uses flexbox for the layout - It only supports a subset of the attributes and elements -- Regular widgets will not work in the tui render, but the tui renderer has its own widget components that start with a capital letter. See the [widgets example](https://github.com/DioxusLabs/dioxus/blob/master/packages/tui/examples/tui_widgets.rs) +- Regular widgets will not work in the tui render, but the tui renderer has its own widget components that start with a capital letter. See the [widgets example](https://github.com/DioxusLabs/dioxus/blob/master/packages/tui/examples/widgets.rs) - 1px is one character line height. Your regular CSS px does not translate - If your app panics, your terminal is wrecked. This will be fixed eventually diff --git a/examples/button.rs b/examples/button.rs index 9d32819e8..f001ed531 100644 --- a/examples/button.rs +++ b/examples/button.rs @@ -6,6 +6,13 @@ fn main() { fn app(cx: Scope) -> Element { cx.render(rsx! { - button { "hello, desktop!" } + button { + onclick: |_| async move { + println!("hello, desktop!"); + tokio::time::sleep(std::time::Duration::from_secs(1)).await; + println!("goodbye, desktop!"); + }, + "hello, desktop!" + } }) } diff --git a/packages/core/src/create.rs b/packages/core/src/create.rs index 3014a7bfe..12c11d1e9 100644 --- a/packages/core/src/create.rs +++ b/packages/core/src/create.rs @@ -11,6 +11,7 @@ use std::iter::Peekable; use std::rc::Rc; use TemplateNode::*; +#[cfg(debug_assertions)] fn sort_bfs(paths: &[&'static [u8]]) -> Vec<(usize, &'static [u8])> { let mut with_indecies = paths.iter().copied().enumerate().collect::>(); with_indecies.sort_unstable_by(|(_, a), (_, b)| { @@ -386,6 +387,8 @@ impl<'b> VirtualDom { } /// Insert a new template into the VirtualDom's template registry + // used in conditional compilation + #[allow(unused_mut)] pub(crate) fn register_template(&mut self, mut template: Template<'static>) { let (path, byte_index) = template.name.rsplit_once(':').unwrap(); let byte_index = byte_index.parse::().unwrap(); diff --git a/packages/core/src/events.rs b/packages/core/src/events.rs index 849dd4d24..b7057fbcc 100644 --- a/packages/core/src/events.rs +++ b/packages/core/src/events.rs @@ -3,6 +3,10 @@ use std::{ rc::Rc, }; +use futures_util::Future; + +use crate::ScopeState; + /// A wrapper around some generic data that handles the event's state /// /// @@ -106,6 +110,23 @@ impl std::fmt::Debug for Event { } } +#[doc(hidden)] +pub trait EventReturn

: Sized { + fn spawn(self, _cx: &ScopeState) {} +} + +impl EventReturn<()> for () {} + +pub struct AsyncMarker; +impl EventReturn for T +where + T: Future + 'static, +{ + fn spawn(self, cx: &ScopeState) { + cx.spawn(self); + } +} + /// The callback type generated by the `rsx!` macro when an `on` field is specified for components. /// /// This makes it possible to pass `move |evt| {}` style closures into components as property fields. diff --git a/packages/core/src/lib.rs b/packages/core/src/lib.rs index 304197dab..4fd8e4a8a 100644 --- a/packages/core/src/lib.rs +++ b/packages/core/src/lib.rs @@ -71,10 +71,10 @@ pub(crate) mod innerlude { pub use crate::innerlude::{ fc_to_builder, AnyValue, Attribute, AttributeValue, BorrowedAttributeValue, CapturedError, - Component, DynamicNode, Element, ElementId, Event, Fragment, IntoDynNode, LazyNodes, Mutation, - Mutations, Properties, RenderReturn, Scope, ScopeId, ScopeState, Scoped, SuspenseContext, - TaskId, Template, TemplateAttribute, TemplateNode, VComponent, VNode, VPlaceholder, VText, - VirtualDom, + Component, DynamicNode, Element, ElementId, Event, EventReturn, Fragment, IntoDynNode, + LazyNodes, Mutation, Mutations, Properties, RenderReturn, Scope, ScopeId, ScopeState, Scoped, + SuspenseContext, TaskId, Template, TemplateAttribute, TemplateNode, VComponent, VNode, + VPlaceholder, VText, VirtualDom, }; /// The purpose of this module is to alleviate imports of many common types diff --git a/packages/core/src/scopes.rs b/packages/core/src/scopes.rs index bee7ea1db..201e1d424 100644 --- a/packages/core/src/scopes.rs +++ b/packages/core/src/scopes.rs @@ -7,7 +7,7 @@ use crate::{ innerlude::{ErrorBoundary, Scheduler, SchedulerMsg}, lazynodes::LazyNodes, nodes::{ComponentReturn, IntoAttributeValue, IntoDynNode, RenderReturn}, - AnyValue, Attribute, AttributeValue, Element, Event, Properties, TaskId, + AnyValue, Attribute, AttributeValue, Element, Event, EventReturn, Properties, TaskId, }; use bumpalo::{boxed::Box as BumpBox, Bump}; use bumpslab::{BumpSlab, Slot}; @@ -581,9 +581,9 @@ impl<'src> ScopeState { /// Create a new [`AttributeValue`] with the listener variant from a callback /// /// The callback must be confined to the lifetime of the ScopeState - pub fn listener( + pub fn listener>( &'src self, - mut callback: impl FnMut(Event) + 'src, + mut callback: impl FnMut(Event) -> E + 'src, ) -> AttributeValue<'src> { // safety: there's no other way to create a dynamicly-dispatched bump box other than alloc + from-raw // This is the suggested way to build a bumpbox @@ -596,6 +596,7 @@ impl<'src> ScopeState { propagates: event.propagates, data, }) + .spawn(self); } })) }; diff --git a/packages/desktop/src/desktop_context.rs b/packages/desktop/src/desktop_context.rs index e5f928222..edddd7887 100644 --- a/packages/desktop/src/desktop_context.rs +++ b/packages/desktop/src/desktop_context.rs @@ -9,6 +9,7 @@ use crate::Config; use crate::WebviewHandler; use dioxus_core::ScopeState; use dioxus_core::VirtualDom; +#[cfg(all(feature = "hot-reload", debug_assertions))] use dioxus_hot_reload::HotReloadMsg; use serde_json::Value; use slab::Slab; @@ -285,6 +286,7 @@ pub enum EventData { Ipc(IpcMessage), + #[cfg(all(feature = "hot-reload", debug_assertions))] HotReloadEvent(HotReloadMsg), NewWindow, diff --git a/packages/desktop/src/lib.rs b/packages/desktop/src/lib.rs index dea69e532..16f562464 100644 --- a/packages/desktop/src/lib.rs +++ b/packages/desktop/src/lib.rs @@ -185,6 +185,7 @@ pub fn launch_with_props(root: Component

, props: P, cfg: Config) } Event::UserEvent(event) => match event.0 { + #[cfg(all(feature = "hot-reload", debug_assertions))] EventData::HotReloadEvent(msg) => match msg { dioxus_hot_reload::HotReloadMsg::UpdateTemplate(template) => { for webview in webviews.values_mut() { diff --git a/packages/html/src/events.rs b/packages/html/src/events.rs index d2aec70c1..604c3a955 100644 --- a/packages/html/src/events.rs +++ b/packages/html/src/events.rs @@ -8,7 +8,7 @@ macro_rules! impl_event { ) => { $( $( #[$attr] )* - pub fn $name<'a>(_cx: &'a ::dioxus_core::ScopeState, _f: impl FnMut(::dioxus_core::Event<$data>) + 'a) -> ::dioxus_core::Attribute<'a> { + pub fn $name<'a, E: ::dioxus_core::EventReturn, T>(_cx: &'a ::dioxus_core::ScopeState, _f: impl FnMut(::dioxus_core::Event<$data>) -> E + 'a) -> ::dioxus_core::Attribute<'a> { ::dioxus_core::Attribute { name: stringify!($name), value: _cx.listener(_f), diff --git a/packages/interpreter/src/sledgehammer_bindings.rs b/packages/interpreter/src/sledgehammer_bindings.rs index 61e37c2cb..33f6b4420 100644 --- a/packages/interpreter/src/sledgehammer_bindings.rs +++ b/packages/interpreter/src/sledgehammer_bindings.rs @@ -217,7 +217,7 @@ mod js { } fn remove_attribute(id: u32, field: &str, ns: &str) { r#"{name = $field$; - node = this.nodes[$id$]; + node = nodes[$id$]; if (ns == "style") { node.style.removeProperty(name); } else if (ns !== null && ns !== undefined && ns !== "") { diff --git a/packages/liveview/src/pool.rs b/packages/liveview/src/pool.rs index b3ed6bef5..022641d5c 100644 --- a/packages/liveview/src/pool.rs +++ b/packages/liveview/src/pool.rs @@ -134,7 +134,7 @@ where #[cfg(all(feature = "hot-reload", debug_assertions))] let hot_reload_wait = hot_reload_rx.recv(); #[cfg(not(all(feature = "hot-reload", debug_assertions)))] - let hot_reload_wait = std::future::pending(); + let hot_reload_wait: std::future::Pending> = std::future::pending(); tokio::select! { // poll any futures or suspense @@ -157,17 +157,18 @@ where } } - msg = hot_reload_wait => { - if let Some(msg) = msg { - match msg{ - dioxus_hot_reload::HotReloadMsg::UpdateTemplate(new_template) => { - vdom.replace_template(new_template); - } - dioxus_hot_reload::HotReloadMsg::Shutdown => { - std::process::exit(0); - }, + Some(msg) = hot_reload_wait => { + #[cfg(all(feature = "hot-reload", debug_assertions))] + match msg{ + dioxus_hot_reload::HotReloadMsg::UpdateTemplate(new_template) => { + vdom.replace_template(new_template); } + dioxus_hot_reload::HotReloadMsg::Shutdown => { + std::process::exit(0); + }, } + #[cfg(not(all(feature = "hot-reload", debug_assertions)))] + let () = msg; } } diff --git a/packages/tui/src/lib.rs b/packages/tui/src/lib.rs index 30a207c23..efcd4ed64 100644 --- a/packages/tui/src/lib.rs +++ b/packages/tui/src/lib.rs @@ -20,7 +20,7 @@ use std::{rc::Rc, sync::RwLock}; use style_attributes::StyleModifier; use taffy::Taffy; pub use taffy::{geometry::Point, prelude::*}; -use tokio::{select, sync::mpsc::unbounded_channel}; +use tokio::select; use tui::{backend::CrosstermBackend, layout::Rect, Terminal}; mod config; @@ -118,7 +118,7 @@ pub fn render>>( #[cfg(all(feature = "hot-reload", debug_assertions))] let mut hot_reload_rx = { let (hot_reload_tx, hot_reload_rx) = - unbounded_channel::(); + tokio::sync::mpsc::unbounded_channel::(); dioxus_hot_reload::connect(move |msg| { let _ = hot_reload_tx.send(msg); }); @@ -215,7 +215,7 @@ pub fn render>>( // #[cfg(all(feature = "hot-reload", debug_assertions))] // let hot_reload_wait = hot_reload_rx.recv(); // #[cfg(not(all(feature = "hot-reload", debug_assertions)))] - // let hot_reload_wait = std::future::pending(); + // let hot_reload_wait: std::future::Pending> = std::future::pending(); pin_mut!(wait); @@ -245,12 +245,18 @@ pub fn render>>( } }, // Some(msg) = hot_reload_wait => { - // hot_reload_msg = Some(msg); + // #[cfg(all(feature = "hot-reload", debug_assertions))] + // { + // hot_reload_msg = Some(msg); + // } + // #[cfg(not(all(feature = "hot-reload", debug_assertions)))] + // let () = msg; // } } } // // if we have a new template, replace the old one + // #[cfg(all(feature = "hot-reload", debug_assertions))] // if let Some(msg) = hot_reload_msg { // match msg { // dioxus_hot_reload::HotReloadMsg::UpdateTemplate(template) => {