1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
use async_channel::{Receiver, Sender};
use chrono::NaiveDate;
use std::collections::HashSet;
use crate::{
gui::{calendar, form, utils, App},
model::{event, event::Event},
};
pub fn send(tx: Sender<Msg>, msg: Msg) {
utils::spawn(async move {
let _ = tx.send(msg).await;
})
}
pub enum Msg {
ShowAddForm { date: NaiveDate },
ShowUpdateForm { event: Event },
AddEvent { new: Event },
UpdateEvent { old: Event, new: Event },
DeleteEvent { event: Event },
}
pub async fn event_handler(rx: Receiver<Msg>, mut app: App) {
while let Ok(msg) = rx.recv().await {
match msg {
Msg::ShowAddForm { date } => {
form::show(&app, event::init(date), true).await;
}
Msg::ShowUpdateForm { event } => {
form::show(&app, event, false).await;
}
Msg::AddEvent { new } => {
let refresh_dates = add(&mut app, &new);
refresh(&app, &refresh_dates)
}
Msg::UpdateEvent { old, new } => {
let refresh_dates_1 = remove(&mut app, &old);
let refresh_dates_2 = add(&mut app, &new);
refresh(
&app,
&refresh_dates_1
.union(&refresh_dates_2)
.copied()
.collect::<HashSet<NaiveDate>>(),
)
}
Msg::DeleteEvent { event } => {
let refresh_dates = remove(&mut app, &event);
refresh(&app, &refresh_dates)
}
}
}
}
/// Remove event and return dates that should be refreshed.
fn remove(app: &mut App, event: &Event) -> HashSet<NaiveDate> {
if event.repetition.is_some() {
match app.repeated_events.iter().position(|e| e.id == event.id) {
Some(index) => {
app.repeated_events.remove(index);
let mut dates = repetition_dates(app, event);
dates.insert(event.date);
dates
}
None => {
eprintln!("Event not found when trying to delete {:?}", event);
HashSet::new()
}
}
} else {
match app.events.iter().position(|e| e.id == event.id) {
Some(index) => {
app.events.remove(index);
HashSet::from([event.date])
}
None => {
eprintln!("Event not found when trying to delete {:?}", event);
HashSet::new()
}
}
}
}
/// Add event and return dates that should be refreshed.
fn add(app: &mut App, event: &Event) -> HashSet<NaiveDate> {
if event.repetition.is_some() {
app.repeated_events.push(event.clone());
let mut dates = repetition_dates(app, event);
dates.insert(event.date);
dates
} else {
app.events.push(event.clone());
HashSet::from([event.date])
}
}
/// Repetition dates of a repetead event.
fn repetition_dates(app: &App, event: &Event) -> HashSet<NaiveDate> {
let event_reps = event::repetitions_between(&[event.clone()], app.start_date, app.end_date);
HashSet::from_iter(event_reps.keys().copied())
}
/// Refresh app for the given dates.
fn refresh(app: &App, dates: &HashSet<NaiveDate>) {
let repetitions =
event::repetitions_between(&app.repeated_events, app.start_date, app.end_date);
for date in dates {
calendar::refresh_date(app, *date, &repetitions)
}
}
|