flams_web_utils/components/
await.rs1use 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}