106 lines
2.6 KiB
V
106 lines
2.6 KiB
V
module calbox
|
|
|
|
// Represents an event
|
|
@[heap]
|
|
pub struct Event {
|
|
CalendarComponent
|
|
pub mut:
|
|
start_time i64
|
|
end_time ?i64 // Either end_time or duration must be set
|
|
duration ?string // ISO 8601 duration format
|
|
rrule ?RecurrenceRule
|
|
rdate []i64 // Additional recurrence dates
|
|
exdate []i64 // Dates to exclude
|
|
transp EventTransp
|
|
attendees []Attendee
|
|
organizer ?Attendee
|
|
}
|
|
|
|
// Event transparency (busy time)
|
|
pub enum EventTransp {
|
|
opaque // Blocks time (shows as busy)
|
|
transparent // Does not block time (shows as free)
|
|
}
|
|
|
|
// String representation of event transparency
|
|
pub fn (t EventTransp) str() string {
|
|
return match t {
|
|
.opaque { 'OPAQUE' }
|
|
.transparent { 'TRANSPARENT' }
|
|
}
|
|
}
|
|
|
|
// Parse event transparency from string
|
|
pub fn parse_event_transp(s string) !EventTransp {
|
|
return match s {
|
|
'OPAQUE' { EventTransp.opaque }
|
|
'TRANSPARENT' { EventTransp.transparent }
|
|
else { error('Invalid event transparency: ${s}') }
|
|
}
|
|
}
|
|
|
|
// Checks if an event overlaps with a time range
|
|
fn (event Event) overlaps(tr TimeRange) bool {
|
|
// Get end time from either end_time or duration
|
|
mut end_ts := event.end_time or {
|
|
// TODO: Add duration parsing to get actual end time
|
|
event.start_time + 3600 // Default 1 hour if no end/duration
|
|
}
|
|
|
|
// Check basic overlap
|
|
if is_in_range(event.start_time, tr) || is_in_range(end_ts, tr) {
|
|
return true
|
|
}
|
|
|
|
// Check recurrences if any
|
|
if rule := event.rrule {
|
|
// TODO: Implement recurrence expansion
|
|
// For now just check if the rule's until date (if any) is after range start
|
|
if until := rule.until {
|
|
return until >= tr.start
|
|
}
|
|
return true // Infinite recurrence overlaps everything
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// Gets the effective end time of an event
|
|
pub fn (event Event) get_effective_end_time() !i64 {
|
|
if end := event.end_time {
|
|
return end
|
|
}
|
|
if dur_str := event.duration {
|
|
duration := parse_duration(dur_str)!
|
|
return duration.add_to(event.start_time)
|
|
}
|
|
// Default 1 hour duration
|
|
return event.start_time + 3600
|
|
}
|
|
|
|
// Gets all instances of an event that overlap with a time range
|
|
pub fn (event Event) get_instances(tr TimeRange) ![]EventInstance {
|
|
// For non-recurring events, just check if it overlaps
|
|
if event.rrule == none && event.rdate.len == 0 {
|
|
end_time := event.get_effective_end_time()!
|
|
if event.start_time < tr.end && end_time > tr.start {
|
|
return [
|
|
EventInstance{
|
|
original_event: event
|
|
start_time: event.start_time
|
|
end_time: end_time
|
|
recurrence_id: event.start_time
|
|
is_override: false
|
|
},
|
|
]
|
|
}
|
|
return []
|
|
}
|
|
|
|
// Expand recurring event
|
|
if instances := expand_recurring_event(event, tr) {
|
|
return instances
|
|
}
|
|
return []
|
|
}
|