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