feat: allow 'static futures to be spawned from handlers

This commit is contained in:
Jonathan Kelley committed 2023-02-06 00:54:08 -08:00
1 parent d0fb05385a
commit 9ebafc46bb
5 files changed
+38 -9

No files matched your search

+8 -1
View File
@@ -6,6 +6,13 @@ fn main() {
fn app(cx: Scope) -> Element { fn app(cx: Scope) -> Element {
cx.render(rsx! { cx.render(rsx! {
button { "hello, desktop!" } button {
onclick: |e| async move {
println!("hello, desktop!");
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
println!("goodbye, desktop!");
},
"hello, desktop!"
}
}) })
} }
+21
View File
@@ -3,6 +3,10 @@ use std::{
rc::Rc, rc::Rc,
}; };
use futures_util::Future;
use crate::ScopeState;
/// A wrapper around some generic data that handles the event's state /// A wrapper around some generic data that handles the event's state
/// ///
/// ///
@@ -106,6 +110,23 @@ impl<T: std::fmt::Debug> std::fmt::Debug for Event<T> {
} }
} }
#[doc(hidden)]
pub trait EventReturn<P>: Sized {
fn spawn(self, _cx: &ScopeState) {}
}
impl EventReturn<()> for () {}
pub struct AsyncMarker;
impl<T> EventReturn<AsyncMarker> for T
where
T: Future<Output = ()> + '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. /// 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. /// This makes it possible to pass `move |evt| {}` style closures into components as property fields.
+4 -4
View File
@@ -71,10 +71,10 @@ pub(crate) mod innerlude {
pub use crate::innerlude::{ pub use crate::innerlude::{
fc_to_builder, AnyValue, Attribute, AttributeValue, BorrowedAttributeValue, CapturedError, fc_to_builder, AnyValue, Attribute, AttributeValue, BorrowedAttributeValue, CapturedError,
Component, DynamicNode, Element, ElementId, Event, Fragment, IntoDynNode, LazyNodes, Mutation, Component, DynamicNode, Element, ElementId, Event, EventReturn, Fragment, IntoDynNode,
Mutations, Properties, RenderReturn, Scope, ScopeId, ScopeState, Scoped, SuspenseContext, LazyNodes, Mutation, Mutations, Properties, RenderReturn, Scope, ScopeId, ScopeState, Scoped,
TaskId, Template, TemplateAttribute, TemplateNode, VComponent, VNode, VPlaceholder, VText, SuspenseContext, TaskId, Template, TemplateAttribute, TemplateNode, VComponent, VNode,
VirtualDom, VPlaceholder, VText, VirtualDom,
}; };
/// The purpose of this module is to alleviate imports of many common types /// The purpose of this module is to alleviate imports of many common types
+4 -3
View File
@@ -7,7 +7,7 @@ use crate::{
innerlude::{ErrorBoundary, Scheduler, SchedulerMsg}, innerlude::{ErrorBoundary, Scheduler, SchedulerMsg},
lazynodes::LazyNodes, lazynodes::LazyNodes,
nodes::{ComponentReturn, IntoAttributeValue, IntoDynNode, RenderReturn}, 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 bumpalo::{boxed::Box as BumpBox, Bump};
use bumpslab::{BumpSlab, Slot}; use bumpslab::{BumpSlab, Slot};
@@ -581,9 +581,9 @@ impl<'src> ScopeState {
/// Create a new [`AttributeValue`] with the listener variant from a callback /// Create a new [`AttributeValue`] with the listener variant from a callback
/// ///
/// The callback must be confined to the lifetime of the ScopeState /// The callback must be confined to the lifetime of the ScopeState
pub fn listener<T: 'static>( pub fn listener<T: 'static, P, E: EventReturn<P>>(
&'src self, &'src self,
mut callback: impl FnMut(Event<T>) + 'src, mut callback: impl FnMut(Event<T>) -> E + 'src,
) -> AttributeValue<'src> { ) -> AttributeValue<'src> {
// safety: there's no other way to create a dynamicly-dispatched bump box other than alloc + from-raw // 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 // This is the suggested way to build a bumpbox
@@ -596,6 +596,7 @@ impl<'src> ScopeState {
propagates: event.propagates, propagates: event.propagates,
data, data,
}) })
.spawn(self);
} }
})) }))
}; };
+1 -1
View File
@@ -8,7 +8,7 @@ macro_rules! impl_event {
) => { ) => {
$( $(
$( #[$attr] )* $( #[$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>, T>(_cx: &'a ::dioxus_core::ScopeState, _f: impl FnMut(::dioxus_core::Event<$data>) -> E + 'a) -> ::dioxus_core::Attribute<'a> {
::dioxus_core::Attribute { ::dioxus_core::Attribute {
name: stringify!($name), name: stringify!($name),
value: _cx.listener(_f), value: _cx.listener(_f),