impulse_thaw/toast/
mod.rs

1mod toast;
2mod toast_body;
3mod toast_footer;
4mod toast_title;
5mod toaster;
6mod toaster_provider;
7
8pub use toast::*;
9pub use toast_body::*;
10pub use toast_footer::*;
11pub use toast_title::*;
12pub use toaster_provider::*;
13
14use leptos::prelude::*;
15use std::sync::mpsc::{channel, Receiver, Sender, TryIter};
16use wasm_bindgen::UnwrapThrowExt;
17
18#[derive(Clone, Copy)]
19pub struct ToasterInjection {
20    sender: StoredValue<Sender<ToasterMessage>>,
21    trigger: StoredValue<ArcTrigger>,
22}
23
24enum ToasterMessage {
25    Dispatch(Children, ToastOptions),
26    Dismiss(uuid::Uuid),
27    DismissAll,
28}
29
30impl ToasterInjection {
31    #[track_caller]
32    pub fn expect_context() -> Self {
33        expect_context()
34    }
35
36    pub fn channel() -> (Self, ToasterReceiver) {
37        let (sender, receiver) = channel::<ToasterMessage>();
38        let trigger = ArcTrigger::new();
39
40        (
41            Self {
42                sender: StoredValue::new(sender),
43                trigger: StoredValue::new(trigger.clone()),
44            },
45            ToasterReceiver::new(receiver, trigger),
46        )
47    }
48
49    pub fn dismiss_toast(&self, toast_id: uuid::Uuid) {
50        self.sender.with_value(|sender| {
51            sender
52                .send(ToasterMessage::Dismiss(toast_id))
53                .unwrap_throw()
54        });
55        self.trigger.with_value(|trigger| trigger.notify());
56    }
57
58    pub fn dismiss_all(&self) {
59        self.sender
60            .with_value(|sender| sender.send(ToasterMessage::DismissAll).unwrap_throw());
61        self.trigger.with_value(|trigger| trigger.notify());
62    }
63
64    pub fn dispatch_toast<C, IV>(&self, children: C, options: ToastOptions)
65    where
66        C: FnOnce() -> IV + Send + 'static,
67        IV: IntoView + 'static,
68    {
69        self.sender.with_value(|sender| {
70            sender
71                .send(ToasterMessage::Dispatch(
72                    Box::new(move || children().into_any()),
73                    options,
74                ))
75                .unwrap_throw()
76        });
77        self.trigger.with_value(|trigger| trigger.notify());
78    }
79}
80
81pub struct ToasterReceiver {
82    receiver: Receiver<ToasterMessage>,
83    trigger: ArcTrigger,
84}
85
86impl ToasterReceiver {
87    fn new(receiver: Receiver<ToasterMessage>, trigger: ArcTrigger) -> Self {
88        Self { receiver, trigger }
89    }
90
91    fn try_recv(&self) -> TryIter<'_, ToasterMessage> {
92        self.trigger.track();
93        self.receiver.try_iter()
94    }
95}