Properly handle moved appointments instead of just defining an exclusion date and a new date (this fixes edge cases where an appointment has been moved to the same date)
This commit is contained in:
@@ -8,6 +8,51 @@ use log::warn;
|
||||
use reqwest::IntoUrl;
|
||||
use rrule::{RRule, RRuleSet, RRuleSetIter, Tz, Unvalidated};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct RRuleWithReplacements {
|
||||
rrule_set: RRuleSet,
|
||||
replacements: HashMap<DateTime<Tz>, DateTime<Tz>>,
|
||||
}
|
||||
|
||||
struct RRuleWithReplacementsIter<'a> {
|
||||
inner: RRuleSetIter<'a>,
|
||||
rrule_set: &'a RRuleWithReplacements,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for RRuleWithReplacementsIter<'a> {
|
||||
type Item = <RRuleSetIter<'a> as IntoIterator>::Item;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next().map(|mut next_appointment| {
|
||||
if let Some(replacement) = self.rrule_set.replacements.get(&next_appointment) {
|
||||
next_appointment = *replacement;
|
||||
}
|
||||
next_appointment
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a RRuleWithReplacements {
|
||||
type Item = <RRuleSetIter<'a> as IntoIterator>::Item;
|
||||
type IntoIter = RRuleWithReplacementsIter<'a>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
Self::IntoIter {
|
||||
inner: self.rrule_set.into_iter(),
|
||||
rrule_set: self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RRuleWithReplacements {
|
||||
fn new(rrule_set: RRuleSet) -> Self {
|
||||
Self {
|
||||
rrule_set,
|
||||
replacements: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn fetch_next_appointment<U: IntoUrl>(url: U) -> Result<Option<Appointment<Tz>>> {
|
||||
let response = reqwest::get(url).await?.bytes().await?;
|
||||
|
||||
@@ -25,6 +70,7 @@ pub async fn fetch_next_appointment<U: IntoUrl>(url: U) -> Result<Option<Appoint
|
||||
let mut series = HashMap::new();
|
||||
let mut ends = HashMap::new();
|
||||
for event in events {
|
||||
println!("{}", event.start);
|
||||
ends.insert(event.uid.clone(), event.end);
|
||||
if let Some(rrule) = event.rrule {
|
||||
// TODO This is a workaround for https://github.com/fmeringdal/rust-rrule/issues/87
|
||||
@@ -35,14 +81,19 @@ pub async fn fetch_next_appointment<U: IntoUrl>(url: U) -> Result<Option<Appoint
|
||||
for exdate in event.exdates {
|
||||
rrule_set = rrule_set.exdate(exdate);
|
||||
}
|
||||
series.insert(event.uid, rrule_set);
|
||||
series.insert(event.uid, RRuleWithReplacements::new(rrule_set));
|
||||
} else if let Some(recurrence_id) = event.recurrence_id {
|
||||
let uid = event.uid;
|
||||
let (uid, rrule_set) = series.remove_entry(&uid).unwrap();
|
||||
let rrule_set = rrule_set.exdate(recurrence_id).rdate(event.start);
|
||||
series.insert(uid, rrule_set);
|
||||
series
|
||||
.get_mut(&uid)
|
||||
.unwrap()
|
||||
.replacements
|
||||
.insert(recurrence_id, event.start);
|
||||
} else {
|
||||
series.insert(event.uid, RRuleSet::new(now).rdate(event.start));
|
||||
series.insert(
|
||||
event.uid,
|
||||
RRuleWithReplacements::new(RRuleSet::new(now).rdate(event.start)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +117,7 @@ pub async fn fetch_next_appointment<U: IntoUrl>(url: U) -> Result<Option<Appoint
|
||||
}
|
||||
|
||||
struct AppointmentsIterator<'a> {
|
||||
inner: Vec<(&'a String, DateTime<Tz>, RRuleSetIter<'a>)>,
|
||||
inner: Vec<(&'a String, DateTime<Tz>, RRuleWithReplacementsIter<'a>)>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for AppointmentsIterator<'a> {
|
||||
@@ -92,7 +143,7 @@ trait IterAppointments {
|
||||
fn iter_appointments(&self) -> AppointmentsIterator<'_>;
|
||||
}
|
||||
|
||||
impl IterAppointments for HashMap<String, RRuleSet> {
|
||||
impl IterAppointments for HashMap<String, RRuleWithReplacements> {
|
||||
fn iter_appointments(&self) -> AppointmentsIterator {
|
||||
let mut inner = vec![];
|
||||
for (uid, rrule_set) in self {
|
||||
|
||||
Reference in New Issue
Block a user