Calendar Events
Relevant source files
The following files were used as context for generating this wiki page:
The Calendar Events module in Buddi provides a unified interface for managing and displaying macOS system calendar events and reminders within the application's notch utility. It integrates directly with Apple's EventKit framework to fetch, filter, and display upcoming schedule items, allowing users to track their day at a glance.
The system is built on a provider-manager-view architecture. A dedicated CalendarService handles low-level communication with the macOS Event Store, while the CalendarManager maintains the application state, handling authorization and data synchronization. The user interface, primarily located in BuddiCalendar.swift, offers a scrollable date picker and a detailed event list that supports direct interaction, such as marking reminders as complete or opening events in the native macOS Calendar app.
System Architecture
The calendar system follows a reactive data flow pattern. The CalendarManager serves as a central ObservableObject, broadcasting changes to the UI whenever events are updated or authorization statuses change.
This diagram shows the flow of data from the macOS EventKit store through the service and manager layers to the various UI components.
Sources: buddi/managers/CalendarManager.swift:15-20, buddi/Providers/CalendarServiceProviding.swift:14-16, buddi/components/Calendar/BuddiCalendar.swift:140-150
Data Models
The module uses specialized models to abstract EventKit objects into thread-safe, equatable structures suitable for SwiftUI.
Event and Calendar Models
The EventModel represents both calendar events and reminders. The distinction is maintained through an EventType enum.
| Field | Type | Description |
|---|---|---|
id | String | Unique identifier for the event or reminder. |
start | Date | Start time or due date. |
end | Date | End time (defaults to end of day for reminders). |
title | String | The title of the event/reminder. |
type | EventType | Enum: .event(AttendanceStatus), .birthday, or .reminder(completed: Bool). |
isAllDay | Bool | Indicates if the event spans the entire day. |
calendar | CalendarModel | Metadata about the source calendar (title, color, type). |
Sources: buddi/models/EventModel.swift:12-27, buddi/Providers/CalendarServiceProviding.swift:126-155
Attendance and Status
Events track user participation and current status relative to the system time.
- AttendanceStatus:
accepted,maybe,pending,declined,unknown. - EventStatus:
upcoming(start > now),inProgress(now within range),ended(end < now).
Sources: buddi/models/EventModel.swift:29-65
Service and Provider Layer
The CalendarService implements the CalendarServiceProviding protocol, encapsulating EventKit operations. It handles asynchronous requests for full access to events and reminders, which is required on macOS 14.0+.
Sequence of operations for authorizing and fetching event data.
Key Service Functions
requestAccess(to type: EKEntityType): Requests system permissions for.eventor.reminder.calendars(): Retrieves all available calendar and reminder lists accessible to the app.events(from:to:calendars:): Fetches bothEKEventandEKReminderobjects within a date range and converts them toEventModelobjects.setReminderCompleted(reminderID:completed:): Directly updates the completion state of a reminder in theEKEventStore.
Sources: buddi/Providers/CalendarServiceProviding.swift:18-118
Calendar Manager Logic
The CalendarManager is a singleton @MainActor class that manages the active state of the calendar system. It observes Notification.Name.EKEventStoreChanged to trigger automatic refreshes when the system database changes externally.
Authorization Handling
The manager checks status for both events and reminders independently:
func checkCalendarAuthorization() async {
let status = EKEventStore.authorizationStatus(for: .event)
self.calendarAuthorizationStatus = status
if status == .notDetermined {
let granted = try? await calendarService.requestAccess(to: .event)
// Update status and reload...
}
}
Sources: buddi/managers/CalendarManager.swift:65-98, buddi/managers/CalendarManager.swift:45-58
Selection Management
Users can choose to see "All" calendars or a specific subset. This state is persisted via the Defaults library using the CalendarSelectionState enum.
updateSelectedCalendars(): Synchronizes the localselectedCalendarIDsset with the persistedDefaults.setCalendarSelected(_:isSelected:): Updates the selection state and triggers an immediate event fetch.
Sources: buddi/managers/CalendarManager.swift:133-176, buddi/models/Constants.swift:28-31
User Interface Components
WheelPicker
The WheelPicker provides a horizontal, scrollable date selection interface. It uses a Config struct to determine how many past and future days to display (default: 7 past, 14 future). It utilizes ScrollViewReader and scrollPosition to snap the selected date to the center.
Sources: buddi/components/Calendar/BuddiCalendar.swift:11-138
EventListView
The list displays filtered events for the selected day. It implements custom filtering logic:
- Reminders can be hidden if completed (controlled by
Defaults[.hideCompletedReminders]). - All-day events can be toggled via
Defaults[.hideAllDayEvents]. - Events are sorted by start time.
The view also includes an autoScrollToNextEvent feature that uses a ScrollViewProxy to position the list at the most relevant upcoming event upon appearance.
Sources: buddi/components/Calendar/BuddiCalendar.swift:214-300
Reminder Interaction
Reminders are rendered with a ReminderToggle component. When a user clicks the toggle, it triggers an asynchronous update through the CalendarManager to the system store.
ReminderToggle(
isOn: Binding(
get: { isCompleted },
set: { newValue in
Task {
await calendarManager.setReminderCompleted(
reminderID: event.id, completed: newValue
)
}
}
),
color: Color(event.calendar.color)
)
Sources: buddi/components/Calendar/BuddiCalendar.swift:310-340, buddi/managers/CalendarManager.swift:194-202
Configuration and Settings
Users can configure the calendar behavior through the CalendarSettings view within the main Settings panel.
| Setting | Default | Description |
|---|---|---|
showCalendar | false | Enables/Disables the calendar component in the notch. |
hideCompletedReminders | true | Filters out reminders that are already marked done. |
hideAllDayEvents | false | Removes all-day events from the list. |
autoScrollToNextEvent | true | Automatically scrolls the list to the next upcoming event. |
showFullEventTitles | false | Disables line-clamping for event titles. |
Sources: buddi/models/Constants.swift:138-142, buddi/components/Settings/SettingsView.swift:600-680
The Calendar Events module provides a robust, interactive view of the user's schedule, ensuring that critical timing information is always accessible while maintaining performance through incremental updates and efficient system service calls.