aboutsummaryrefslogtreecommitdiff
path: root/src/gui/update.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/update.rs')
-rw-r--r--src/gui/update.rs112
1 files changed, 112 insertions, 0 deletions
diff --git a/src/gui/update.rs b/src/gui/update.rs
new file mode 100644
index 0000000..91102bf
--- /dev/null
+++ b/src/gui/update.rs
@@ -0,0 +1,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)
+ }
+}