Push subscription improvements + CalendarAlert implementation (closes #1248)

This commit is contained in:
mdecimus
2025-10-19 18:43:47 +02:00
parent 496d866052
commit a4720e1efe
55 changed files with 2196 additions and 1226 deletions

View File

@@ -17,15 +17,25 @@ use std::str::FromStr;
use store::write::bitpack::BitpackIterator;
use utils::codec::leb128::Leb128Reader;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct CalendarAlarm {
pub alarm_id: u16,
pub event_id: u16,
pub alarm_time: i64,
pub event_start: i64,
pub event_start_tz: u16,
pub event_end: i64,
pub event_end_tz: u16,
pub typ: CalendarAlarmType,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum CalendarAlarmType {
Email {
event_start: i64,
event_start_tz: u16,
event_end: i64,
event_end_tz: u16,
},
Display {
recurrence_id: Option<i64>,
},
}
impl ArchivedCalendarEventData {
@@ -39,11 +49,7 @@ impl ArchivedCalendarEventData {
'outer: for range in self.time_ranges.iter() {
let comp_id = range.id.to_native();
let Some(alarm) = self
.alarms
.iter()
.find(|a| a.is_email_alert && a.parent_id == comp_id)
else {
let Some(alarm) = self.alarms.iter().find(|a| a.parent_id == comp_id) else {
continue;
};
@@ -83,30 +89,34 @@ impl ArchivedCalendarEventData {
if let Some(alarm_time) = alarm.delta.to_timestamp(start, end, default_tz)
&& alarm_time > start_time
&& next_alarm
.as_ref()
.is_none_or(|next| alarm_time < next.alarm_time)
{
if let Some(next) = next_alarm {
if alarm_time < next.alarm_time {
next_alarm = Some(CalendarAlarm {
alarm_id: alarm.id.to_native(),
event_id: alarm.parent_id.to_native(),
alarm_time,
next_alarm = Some(CalendarAlarm {
alarm_id: alarm.id.to_native(),
event_id: alarm.parent_id.to_native(),
alarm_time,
typ: if alarm.is_email_alert {
CalendarAlarmType::Email {
event_start: start_date_naive,
event_start_tz: start_tz.as_id(),
event_end: end_date_naive,
event_end_tz: end_tz.as_id(),
});
}
} else {
next_alarm = Some(CalendarAlarm {
alarm_id: alarm.id.to_native(),
event_id: alarm.parent_id.to_native(),
alarm_time,
event_start: start_date_naive,
event_start_tz: start_tz.as_id(),
event_end: end_date_naive,
event_end_tz: end_tz.as_id(),
});
}
}
} else {
let comp =
&self.event.components[alarm.parent_id.to_native() as usize];
CalendarAlarmType::Display {
recurrence_id: if comp.is_recurrent_or_override() {
start_date_naive.into()
} else {
None
},
}
},
});
continue 'outer;
}
}
@@ -129,30 +139,33 @@ impl ArchivedCalendarEventData {
if let Some(alarm_time) = alarm.delta.to_timestamp(start, end, default_tz)
&& alarm_time > start_time
&& next_alarm
.as_ref()
.is_none_or(|next| alarm_time < next.alarm_time)
{
if let Some(next) = next_alarm {
if alarm_time < next.alarm_time {
next_alarm = Some(CalendarAlarm {
alarm_id: alarm.id.to_native(),
event_id: alarm.parent_id.to_native(),
alarm_time,
next_alarm = Some(CalendarAlarm {
alarm_id: alarm.id.to_native(),
event_id: alarm.parent_id.to_native(),
alarm_time,
typ: if alarm.is_email_alert {
CalendarAlarmType::Email {
event_start: start_date_naive,
event_start_tz: start_tz.as_id(),
event_end: end_date_naive,
event_end_tz: end_tz.as_id(),
});
}
} else {
next_alarm = Some(CalendarAlarm {
alarm_id: alarm.id.to_native(),
event_id: alarm.parent_id.to_native(),
alarm_time,
event_start: start_date_naive,
event_start_tz: start_tz.as_id(),
event_end: end_date_naive,
event_end_tz: end_tz.as_id(),
});
}
}
} else {
let comp = &self.event.components[alarm.parent_id.to_native() as usize];
CalendarAlarmType::Display {
recurrence_id: if comp.is_recurrent_or_override() {
start_date_naive.into()
} else {
None
},
}
},
});
}
}
}

View File

@@ -8,7 +8,7 @@ use super::{
ArchivedCalendarEventData, ArchivedTimezone, CalendarEventData, Timezone,
alarm::{CalendarAlarm, ExpandAlarm},
};
use crate::calendar::ComponentTimeRange;
use crate::calendar::{ComponentTimeRange, alarm::CalendarAlarmType};
use calcard::{
common::timezone::Tz,
icalendar::{ICalendar, ICalendarComponentType, dates::TimeOrDelta},
@@ -88,30 +88,34 @@ impl CalendarEventData {
if alarm_time > max {
max = alarm_time;
}
if alarm.is_email_alert && alarm_time > now {
if let Some(next) = next_email_alarm {
if alarm_time < next.alarm_time {
*next = CalendarAlarm {
alarm_id: alarm.id,
event_id: alarm.parent_id,
alarm_time,
if alarm_time > now
&& next_email_alarm
.as_ref()
.is_none_or(|next| alarm_time < next.alarm_time)
{
*next_email_alarm = Some(CalendarAlarm {
alarm_id: alarm.id,
event_id: alarm.parent_id,
alarm_time,
typ: if alarm.is_email_alert {
CalendarAlarmType::Email {
event_start: start_timestamp_naive,
event_end: end_timestamp_naive,
event_start_tz: start_tz,
event_end_tz: end_tz,
};
}
} else {
*next_email_alarm = Some(CalendarAlarm {
alarm_id: alarm.id,
event_id: alarm.parent_id,
alarm_time,
event_start: start_timestamp_naive,
event_end: end_timestamp_naive,
event_start_tz: start_tz,
event_end_tz: end_tz,
});
}
}
} else {
CalendarAlarmType::Display {
recurrence_id: if ical.components[alarm.parent_id as usize]
.is_recurrent_or_override()
{
start_timestamp_naive.into()
} else {
None
},
}
},
});
}
}
}

View File

@@ -10,7 +10,9 @@ use super::{
};
use crate::{
DavResourceName, DestroyArchive, RFC_3986,
calendar::{ArchivedCalendarEventNotification, CalendarEventNotification},
calendar::{
ArchivedCalendarEventNotification, CalendarEventNotification, alarm::CalendarAlarmType,
},
scheduling::{ItipMessages, event_cancel::itip_cancel},
};
use calcard::common::timezone::Tz;
@@ -470,19 +472,42 @@ impl DestroyArchive<Archive<&ArchivedCalendarEventNotification>> {
impl CalendarAlarm {
pub fn write_task(&self, batch: &mut BatchBuilder) {
batch.set(
ValueClass::TaskQueue(TaskQueueClass::SendAlarm {
due: self.alarm_time as u64,
event_id: self.event_id,
alarm_id: self.alarm_id,
}),
KeySerializer::new((U64_LEN * 2) + (U16_LEN * 2))
.write(self.event_start as u64)
.write(self.event_end as u64)
.write(self.event_start_tz)
.write(self.event_end_tz)
.finalize(),
);
match &self.typ {
CalendarAlarmType::Email {
event_start,
event_start_tz,
event_end,
event_end_tz,
} => {
batch.set(
ValueClass::TaskQueue(TaskQueueClass::SendAlarm {
due: self.alarm_time as u64,
event_id: self.event_id,
alarm_id: self.alarm_id,
is_email_alert: true,
}),
KeySerializer::new((U64_LEN * 2) + (U16_LEN * 2))
.write(*event_start as u64)
.write(*event_end as u64)
.write(*event_start_tz)
.write(*event_end_tz)
.finalize(),
);
}
CalendarAlarmType::Display { recurrence_id } => {
batch.set(
ValueClass::TaskQueue(TaskQueueClass::SendAlarm {
due: self.alarm_time as u64,
event_id: self.event_id,
alarm_id: self.alarm_id,
is_email_alert: false,
}),
KeySerializer::new(U64_LEN)
.write(recurrence_id.unwrap_or_default() as u64)
.finalize(),
);
}
}
}
pub fn delete_task(&self, batch: &mut BatchBuilder) {
@@ -490,6 +515,7 @@ impl CalendarAlarm {
due: self.alarm_time as u64,
event_id: self.event_id,
alarm_id: self.alarm_id,
is_email_alert: matches!(self.typ, CalendarAlarmType::Email { .. }),
}));
}
}