yew_notifications/
manager.rs

1use std::fmt::Debug;
2use std::rc::Rc;
3
4use time::Duration;
5use uuid::Uuid;
6use yew::{Reducible, UseReducerDispatcher};
7
8use crate::Notifiable;
9
10/// Returned object from the `use_notification` hook. Can spawn new notifications.
11#[derive(Clone, PartialEq)]
12pub struct NotificationsManager<N: Notifiable + PartialEq + Clone> {
13    pub(crate) sender: Option<UseReducerDispatcher<NotificationsList<N>>>,
14}
15
16impl<N: Notifiable + PartialEq + Clone> NotificationsManager<N> {
17    /// Spawns new notification of the type N.
18    pub fn spawn(&self, notification: N) {
19        if let Some(sender) = &self.sender {
20            sender.dispatch(Action::New(notification));
21        }
22    }
23}
24
25impl<N: Notifiable + PartialEq + Clone> Default for NotificationsManager<N> {
26    fn default() -> Self {
27        Self {
28            sender: Default::default(),
29        }
30    }
31}
32
33#[derive(Debug)]
34pub enum Action<N: Notifiable + PartialEq + Clone> {
35    New(N),
36    Close(Uuid),
37    Tick,
38    Pause(Uuid),
39    Continue(Uuid),
40}
41
42#[derive(Debug, Clone, PartialEq)]
43pub struct NotificationsList<N> {
44    pub notifications: Vec<N>,
45}
46
47impl<N> Default for NotificationsList<N> {
48    fn default() -> Self {
49        Self {
50            notifications: Default::default(),
51        }
52    }
53}
54
55impl<N> NotificationsList<N> {
56    pub const TIME_TICK_MILLIS: usize = 1000; // every second
57    pub const TIME_TICK_DURATION: Duration = Duration::seconds(1);
58
59    pub fn is_empty(&self) -> bool {
60        self.notifications.is_empty()
61    }
62}
63
64impl<N: Notifiable + PartialEq + Clone> Reducible for NotificationsList<N> {
65    type Action = Action<N>;
66
67    fn reduce(self: Rc<Self>, action: Self::Action) -> Rc<Self> {
68        match action {
69            Action::New(notification) => {
70                let mut notifications = self.notifications.clone();
71                notifications.push(notification);
72
73                Rc::new(Self { notifications })
74            }
75            Action::Close(id) => {
76                let notifications = self
77                    .notifications
78                    .clone()
79                    .into_iter()
80                    .filter(|n| n.id() != id)
81                    .collect();
82
83                Rc::new(Self { notifications })
84            }
85            Action::Tick => {
86                let notifications = self
87                    .notifications
88                    .clone()
89                    .into_iter()
90                    .filter_map(|mut n| {
91                        if n.is_paused() {
92                            Some(n)
93                        } else if n.is_alive() {
94                            n.apply_tick(Self::TIME_TICK_DURATION);
95
96                            Some(n)
97                        } else {
98                            None
99                        }
100                    })
101                    .collect();
102
103                Rc::new(Self { notifications })
104            }
105            Action::Pause(id) => {
106                let notifications = self
107                    .notifications
108                    .clone()
109                    .into_iter()
110                    .map(|mut n| {
111                        if n.id() == id {
112                            n.mouse_in();
113                        }
114                        n
115                    })
116                    .collect();
117
118                Rc::new(Self { notifications })
119            }
120            Action::Continue(id) => {
121                let notifications = self
122                    .notifications
123                    .clone()
124                    .into_iter()
125                    .map(|mut n| {
126                        if n.id() == id {
127                            n.mouse_out();
128                        }
129                        n
130                    })
131                    .collect();
132
133                Rc::new(Self { notifications })
134            }
135        }
136    }
137}