feat: allow 'static futures to be spawned from handlers
This commit is contained in:
parent
d0fb05385a
commit
9ebafc46bb
|
@ -6,6 +6,13 @@ fn main() {
|
|||
|
||||
fn app(cx: Scope) -> Element {
|
||||
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!"
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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<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.
|
||||
///
|
||||
/// This makes it possible to pass `move |evt| {}` style closures into components as property fields.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<T: 'static>(
|
||||
pub fn listener<T: 'static, P, E: EventReturn<P>>(
|
||||
&'src self,
|
||||
mut callback: impl FnMut(Event<T>) + 'src,
|
||||
mut callback: impl FnMut(Event<T>) -> 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);
|
||||
}
|
||||
}))
|
||||
};
|
||||
|
|
|
@ -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>, 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),
|
||||
|
|
Loading…
Reference in New Issue