100 lines
3.3 KiB
Swift
100 lines
3.3 KiB
Swift
import EventKit
|
|
import Foundation
|
|
|
|
@MainActor
|
|
final class CalendarService {
|
|
static let shared = CalendarService()
|
|
private let eventStore = EKEventStore()
|
|
|
|
private init() {}
|
|
|
|
func requestAccess() async -> Bool {
|
|
do {
|
|
return try await eventStore.requestFullAccessToEvents()
|
|
} catch {
|
|
print("Calendar access error: \(error)")
|
|
return false
|
|
}
|
|
}
|
|
|
|
func availableCalendars() -> [EKCalendar] {
|
|
eventStore.calendars(for: .event)
|
|
}
|
|
|
|
func createEvent(
|
|
slot: MealSlot,
|
|
dishName: String,
|
|
dishDescription: String?,
|
|
weekStartDate: Date,
|
|
settings: AppSettings
|
|
) -> String? {
|
|
guard let calendar = resolvedCalendar(for: settings) else {
|
|
print("Calendar sync skipped: no writable calendar available")
|
|
return nil
|
|
}
|
|
|
|
let event = EKEvent(eventStore: eventStore)
|
|
|
|
let prefix = settings.eventPrefix.isEmpty ? "" : "\(settings.eventPrefix) "
|
|
let mealNameKey = slot.mealType == "lunch" ? "lunch" : "dinner"
|
|
let mealName = localizedString(mealNameKey, language: settings.languageEnum.resolved())
|
|
event.title = "\(prefix)\(mealName): \(dishName)"
|
|
|
|
let slotDate = weekStartDate.addingDays(slot.dayOfWeek)
|
|
let slotTime = slot.mealType == "lunch" ? settings.lunchTime : settings.dinnerTime
|
|
event.startDate = combineDateAndTime(date: slotDate, time: slotTime)
|
|
event.endDate = event.startDate.addingMinutes(settings.eventDuration)
|
|
event.notes = dishDescription
|
|
event.calendar = calendar
|
|
|
|
if let reminder = settings.reminderMinutesBefore {
|
|
event.addAlarm(EKAlarm(relativeOffset: -TimeInterval(reminder * 60)))
|
|
}
|
|
|
|
do {
|
|
try eventStore.save(event, span: .thisEvent)
|
|
return event.eventIdentifier
|
|
} catch {
|
|
print("Error saving event: \(error)")
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func deleteEvent(eventId: String) {
|
|
guard let event = eventStore.event(withIdentifier: eventId) else { return }
|
|
do {
|
|
try eventStore.remove(event, span: .thisEvent)
|
|
} catch {
|
|
print("Error deleting event: \(error)")
|
|
}
|
|
}
|
|
|
|
func updateEventsTime(slots: [MealSlot], weekStartDate: Date, settings: AppSettings) {
|
|
for slot in slots {
|
|
guard let eventId = slot.calendarEventId,
|
|
let event = eventStore.event(withIdentifier: eventId),
|
|
event.startDate >= Date() else { continue }
|
|
|
|
let slotDate = weekStartDate.addingDays(slot.dayOfWeek)
|
|
let newTime = slot.mealType == "lunch" ? settings.lunchTime : settings.dinnerTime
|
|
event.startDate = combineDateAndTime(date: slotDate, time: newTime)
|
|
event.endDate = event.startDate.addingMinutes(settings.eventDuration)
|
|
|
|
try? eventStore.save(event, span: .thisEvent)
|
|
}
|
|
}
|
|
|
|
private func resolvedCalendar(for settings: AppSettings) -> EKCalendar? {
|
|
if let calendarId = settings.calendarId,
|
|
let calendar = eventStore.calendar(withIdentifier: calendarId) {
|
|
return calendar
|
|
}
|
|
|
|
if let defaultCalendar = eventStore.defaultCalendarForNewEvents {
|
|
return defaultCalendar
|
|
}
|
|
|
|
return eventStore.calendars(for: .event).first
|
|
}
|
|
}
|