flams_web_utils/components/
await.rs

1use std::future::Future;
2
3use crate::components::{display_error, Spinner};
4use flams_utils::parking_lot;
5use leptos::{
6    either::{Either, EitherOf3},
7    prelude::*,
8};
9
10pub fn wait_local<
11    V: IntoView + 'static,
12    Out: 'static + Send + Sync + Clone,
13    Fut: Future<Output = Option<Out>> + 'static + Send,
14    F: Fn() -> Fut + 'static,
15>(
16    future: F,
17    children: impl Fn(Out) -> V + 'static + Send,
18    err: String,
19) -> impl IntoView {
20    let res = LocalResource::new(future);
21    view! {
22      <Suspense fallback = || view!(<Spinner/>)>{move || {
23        res.get().and_then(|mut r| r.take()).map_or_else(
24          || Either::Left(view!(<div>{err.clone()}</div>)),
25          |res| Either::Right(children(res))
26        )
27      }}</Suspense>
28    }
29}
30
31pub fn wait_and_then<E, Fut, F, T, V: IntoView + 'static>(
32    f: F,
33    r: impl FnOnce(T) -> V + Send + 'static,
34) -> impl IntoView
35where
36    Fut: Future<Output = Result<T, ServerFnError<E>>> + Send + 'static,
37    F: Fn() -> Fut + Send + Sync + 'static,
38    T: Send + Sync + Clone + 'static + serde::Serialize + for<'de> serde::Deserialize<'de>,
39    E: std::fmt::Display
40        + Clone
41        + serde::Serialize
42        + for<'de> serde::Deserialize<'de>
43        + Send
44        + Sync
45        + 'static,
46{
47    let r = std::sync::Arc::new(parking_lot::Mutex::new(Some(r)));
48    let res = Resource::new(|| (), move |()| f());
49    view! {
50        <Suspense fallback = || view!(<Spinner/>)>{move ||
51            match res.get() {
52              Some(Ok(t)) =>
53                EitherOf3::A(r.lock().take().map(|r| r(t))),
54              Some(Err(e)) => EitherOf3::B(display_error(e.to_string().into())),
55              None => EitherOf3::C(view!(<Spinner/>)),
56            }
57        }</Suspense>
58    }
59}
60
61pub fn wait_and_then_fn<E, Fut, F, T, V: IntoView + 'static>(
62    f: F,
63    r: impl Fn(T) -> V + 'static + Send,
64) -> impl IntoView
65where
66    Fut: Future<Output = Result<T, ServerFnError<E>>> + Send + 'static,
67    F: Fn() -> Fut + 'static + Send + Sync,
68    T: Send + Sync + Clone + 'static + serde::Serialize + for<'de> serde::Deserialize<'de>,
69    E: std::fmt::Display
70        + Clone
71        + serde::Serialize
72        + for<'de> serde::Deserialize<'de>
73        + Send
74        + Sync
75        + 'static,
76{
77    let res = Resource::new(|| (), move |()| f());
78    view! {
79        <Suspense fallback = || view!(<Spinner/>)>{move ||
80            match res.get() {
81              Some(Ok(t)) =>
82                EitherOf3::A(r(t)),
83              Some(Err(e)) => EitherOf3::B(display_error(e.to_string().into())),
84              None => EitherOf3::C(view!(<Spinner/>)),
85            }
86        }</Suspense>
87    }
88}