impulse_thaw/toast/
mod.rs1mod 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}