Skip to main content

flams_web_utils/components/
await.rs

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