yew_notifications/
manager.rs1use std::fmt::Debug;
2use std::rc::Rc;
3
4use time::Duration;
5use uuid::Uuid;
6use yew::{Reducible, UseReducerDispatcher};
7
8use crate::Notifiable;
9
10#[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 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; 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}