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) { 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, 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::>(), ) } 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 { 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 { 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 { 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) { let repetitions = event::repetitions_between(&app.repeated_events, app.start_date, app.end_date); for date in dates { calendar::refresh_date(app, *date, &repetitions) } }