mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 14:54:16 +00:00
stash
This commit is contained in:
parent
42b99dd912
commit
883fd57fe1
5 changed files with 276 additions and 56 deletions
|
@ -106,7 +106,9 @@ pub fn TodoApp() -> impl IntoView {
|
|||
|
||||
#[component]
|
||||
pub fn Todos() -> impl IntoView {
|
||||
//let add_todo = create_server_multi_action::<AddTodo>();
|
||||
let add_todo = create_server_multi_action::<AddTodo>();
|
||||
let delete_todo = ServerAction::<DeleteTodo>::new();
|
||||
let submissions = add_todo.submissions();
|
||||
let delete_todo = ServerAction::<DeleteTodo>::new();
|
||||
//let submissions = add_todo.submissions();
|
||||
|
||||
|
|
|
@ -1,63 +1,13 @@
|
|||
use crate::{
|
||||
computed::AsyncState,
|
||||
diagnostics::is_suppressing_resource_load,
|
||||
owner::{Owner, StoredValue},
|
||||
signal::{ArcReadSignal, ArcRwSignal, ReadSignal, RwSignal},
|
||||
traits::{DefinedAt, GetUntracked, Set, Update, WithUntracked},
|
||||
signal::{ArcRwSignal, RwSignal},
|
||||
traits::{DefinedAt, GetUntracked, Update},
|
||||
unwrap_signal,
|
||||
};
|
||||
use any_spawner::Executor;
|
||||
use futures::{
|
||||
channel::oneshot,
|
||||
select,
|
||||
stream::{AbortRegistration, Abortable},
|
||||
FutureExt,
|
||||
};
|
||||
use std::{
|
||||
future::Future,
|
||||
mem::swap,
|
||||
panic::Location,
|
||||
pin::Pin,
|
||||
sync::{atomic::AtomicUsize, Arc},
|
||||
};
|
||||
|
||||
/*enum ActionState<I, O> {
|
||||
Idle,
|
||||
Loading(I),
|
||||
LoadingMultiple(I, usize),
|
||||
Complete(O),
|
||||
Reloading(I, O),
|
||||
ReloadingMultiple(I, O, usize),
|
||||
}
|
||||
|
||||
impl<I, O> ActionState<I, O> {
|
||||
fn currently_loading(&self) -> usize {
|
||||
match self {
|
||||
ActionState::Idle => 0,
|
||||
ActionState::Loading(_) => 1,
|
||||
ActionState::LoadingMultiple(_, curr) => *curr,
|
||||
ActionState::Complete(_) => 0,
|
||||
ActionState::Reloading(_, _) => 1,
|
||||
ActionState::ReloadingMultiple(_, _, curr) => *curr,
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
struct ActionInner<I, O> {
|
||||
input: Option<I>,
|
||||
value: Option<O>,
|
||||
version: usize,
|
||||
}
|
||||
|
||||
impl<I, O> Default for ActionInner<I, O> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
input: Default::default(),
|
||||
value: Default::default(),
|
||||
version: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
use futures::{channel::oneshot, select, FutureExt};
|
||||
use std::{future::Future, panic::Location, pin::Pin, sync::Arc};
|
||||
|
||||
pub struct ArcAction<I, O>
|
||||
where
|
4
reactive_graph/src/actions/mod.rs
Normal file
4
reactive_graph/src/actions/mod.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
mod action;
|
||||
mod multi_action;
|
||||
pub use action::*;
|
||||
pub use multi_action::*;
|
264
reactive_graph/src/actions/multi_action.rs
Normal file
264
reactive_graph/src/actions/multi_action.rs
Normal file
|
@ -0,0 +1,264 @@
|
|||
use crate::{
|
||||
diagnostics::is_suppressing_resource_load,
|
||||
owner::StoredValue,
|
||||
signal::{ArcReadSignal, ArcRwSignal, ReadSignal, RwSignal},
|
||||
traits::{GetUntracked, Set, Update},
|
||||
};
|
||||
use any_spawner::Executor;
|
||||
use std::{future::Future, pin::Pin, sync::Arc};
|
||||
|
||||
pub struct MultiAction<I, O>
|
||||
where
|
||||
I: 'static,
|
||||
O: 'static,
|
||||
{
|
||||
inner: StoredValue<ArcMultiAction<I, O>>,
|
||||
}
|
||||
|
||||
impl<I, O> Copy for MultiAction<I, O>
|
||||
where
|
||||
I: 'static,
|
||||
O: 'static,
|
||||
{
|
||||
}
|
||||
|
||||
impl<I, O> Clone for MultiAction<I, O>
|
||||
where
|
||||
I: 'static,
|
||||
O: 'static,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, O> MultiAction<I, O>
|
||||
where
|
||||
I: Send + Sync + 'static,
|
||||
O: Send + Sync + 'static,
|
||||
{
|
||||
#[track_caller]
|
||||
pub fn new<Fut>(action_fn: impl Fn(&I) -> Fut + 'static) -> Self
|
||||
where
|
||||
Fut: Future<Output = O> + Send + 'static,
|
||||
ArcMultiAction<I, O>: Send + Sync,
|
||||
{
|
||||
Self {
|
||||
inner: StoredValue::new(ArcMultiAction::new(action_fn)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Calls the `async` function with a reference to the input type as its argument.
|
||||
pub fn dispatch(&self, input: I) {
|
||||
if !is_suppressing_resource_load() {
|
||||
self.inner.with_value(|inner| inner.dispatch(input));
|
||||
}
|
||||
}
|
||||
|
||||
/// The set of all submissions to this multi-action.
|
||||
pub fn submissions(&self) -> ReadSignal<Vec<ArcSubmission<I, O>>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// How many times an action has successfully resolved.
|
||||
pub fn version(&self) -> RwSignal<usize> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ArcMultiAction<I, O>
|
||||
where
|
||||
I: 'static,
|
||||
O: 'static,
|
||||
{
|
||||
version: ArcRwSignal<usize>,
|
||||
submissions: ArcRwSignal<Vec<ArcSubmission<I, O>>>,
|
||||
#[allow(clippy::complexity)]
|
||||
action_fn: Arc<dyn Fn(&I) -> Pin<Box<dyn Future<Output = O> + Send>>>,
|
||||
}
|
||||
|
||||
impl<I, O> ArcMultiAction<I, O>
|
||||
where
|
||||
I: 'static,
|
||||
O: 'static,
|
||||
{
|
||||
pub fn new<Fut>(action_fn: impl Fn(&I) -> Fut + 'static) -> Self
|
||||
where
|
||||
Fut: Future<Output = O> + Send + 'static,
|
||||
{
|
||||
let action_fn = Arc::new(move |input: &I| {
|
||||
let fut = action_fn(input);
|
||||
Box::pin(fut) as Pin<Box<dyn Future<Output = O> + Send>>
|
||||
});
|
||||
Self {
|
||||
version: ArcRwSignal::new(0),
|
||||
submissions: ArcRwSignal::new(Vec::new()),
|
||||
action_fn,
|
||||
}
|
||||
}
|
||||
|
||||
/// Calls the `async` function with a reference to the input type as its argument.
|
||||
pub fn dispatch(&self, input: I) {
|
||||
if !is_suppressing_resource_load() {
|
||||
let fut = (self.action_fn)(&input);
|
||||
|
||||
let submission = ArcSubmission {
|
||||
input: ArcRwSignal::new(Some(input)),
|
||||
value: ArcRwSignal::new(None),
|
||||
pending: ArcRwSignal::new(true),
|
||||
canceled: ArcRwSignal::new(false),
|
||||
};
|
||||
|
||||
self.submissions
|
||||
.try_update(|subs| subs.push(submission.clone()));
|
||||
|
||||
let version = self.version.clone();
|
||||
|
||||
Executor::spawn_local(async move {
|
||||
let new_value = fut.await;
|
||||
let canceled = submission.canceled.get_untracked();
|
||||
if !canceled {
|
||||
submission.value.try_set(Some(new_value));
|
||||
}
|
||||
submission.input.try_set(None);
|
||||
submission.pending.try_set(false);
|
||||
version.try_update(|n| *n += 1);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// The set of all submissions to this multi-action.
|
||||
pub fn submissions(&self) -> ArcReadSignal<Vec<ArcSubmission<I, O>>> {
|
||||
self.submissions.read_only()
|
||||
}
|
||||
|
||||
/// How many times an action has successfully resolved.
|
||||
pub fn version(&self) -> ArcRwSignal<usize> {
|
||||
self.version.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// An action that has been submitted by dispatching it to a [MultiAction](crate::MultiAction).
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ArcSubmission<I, O>
|
||||
where
|
||||
I: 'static,
|
||||
O: 'static,
|
||||
{
|
||||
/// The current argument that was dispatched to the `async` function.
|
||||
/// `Some` while we are waiting for it to resolve, `None` if it has resolved.
|
||||
input: ArcRwSignal<Option<I>>,
|
||||
/// The most recent return value of the `async` function.
|
||||
value: ArcRwSignal<Option<O>>,
|
||||
pending: ArcRwSignal<bool>,
|
||||
/// Controls this submission has been canceled.
|
||||
canceled: ArcRwSignal<bool>,
|
||||
}
|
||||
|
||||
impl<I, O> ArcSubmission<I, O>
|
||||
where
|
||||
I: 'static,
|
||||
O: 'static,
|
||||
{
|
||||
pub fn input(&self) -> ArcReadSignal<Option<I>> {
|
||||
self.input.read_only()
|
||||
}
|
||||
|
||||
pub fn value(&self) -> ArcReadSignal<Option<O>> {
|
||||
self.value.read_only()
|
||||
}
|
||||
|
||||
pub fn pending(&self) -> ArcReadSignal<bool> {
|
||||
self.pending.read_only()
|
||||
}
|
||||
|
||||
pub fn canceled(&self) -> ArcReadSignal<bool> {
|
||||
self.canceled.read_only()
|
||||
}
|
||||
|
||||
pub fn cancel(&self) {
|
||||
self.canceled.try_set(true);
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, O> Clone for ArcSubmission<I, O> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
input: self.input.clone(),
|
||||
value: self.value.clone(),
|
||||
pending: self.pending.clone(),
|
||||
canceled: self.canceled.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Submission<I, O>
|
||||
where
|
||||
I: 'static,
|
||||
O: 'static,
|
||||
{
|
||||
/// The current argument that was dispatched to the `async` function.
|
||||
/// `Some` while we are waiting for it to resolve, `None` if it has resolved.
|
||||
input: RwSignal<Option<I>>,
|
||||
/// The most recent return value of the `async` function.
|
||||
value: RwSignal<Option<O>>,
|
||||
pending: RwSignal<bool>,
|
||||
/// Controls this submission has been canceled.
|
||||
canceled: RwSignal<bool>,
|
||||
}
|
||||
|
||||
impl<I, O> From<ArcSubmission<I, O>> for Submission<I, O>
|
||||
where
|
||||
I: Send + Sync + 'static,
|
||||
O: Send + Sync + 'static,
|
||||
{
|
||||
fn from(value: ArcSubmission<I, O>) -> Self {
|
||||
let ArcSubmission {
|
||||
input,
|
||||
value,
|
||||
pending,
|
||||
canceled,
|
||||
} = value;
|
||||
Self {
|
||||
input: input.into(),
|
||||
value: value.into(),
|
||||
pending: pending.into(),
|
||||
canceled: canceled.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, O> Submission<I, O>
|
||||
where
|
||||
I: Send + Sync + 'static,
|
||||
O: Send + Sync + 'static,
|
||||
{
|
||||
pub fn input(&self) -> ReadSignal<Option<I>> {
|
||||
self.input.read_only()
|
||||
}
|
||||
|
||||
pub fn value(&self) -> ReadSignal<Option<O>> {
|
||||
self.value.read_only()
|
||||
}
|
||||
|
||||
pub fn pending(&self) -> ReadSignal<bool> {
|
||||
self.pending.read_only()
|
||||
}
|
||||
|
||||
pub fn canceled(&self) -> ReadSignal<bool> {
|
||||
self.canceled.read_only()
|
||||
}
|
||||
|
||||
pub fn cancel(&self) {
|
||||
self.canceled.try_set(true);
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, O> Clone for Submission<I, O> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, O> Copy for Submission<I, O> {}
|
|
@ -72,7 +72,7 @@
|
|||
use futures::Stream;
|
||||
use std::{future::Future, pin::Pin};
|
||||
|
||||
pub mod action;
|
||||
pub mod actions;
|
||||
pub(crate) mod channel;
|
||||
pub mod computed;
|
||||
pub mod diagnostics;
|
||||
|
|
Loading…
Reference in a new issue