Files
openclaw/apps/ios/Sources/Permissions/EventKitPermissionRequester.swift

52 lines
1.9 KiB
Swift

import EventKit
protocol EventKitPermissionStore: AnyObject {
func requestWriteOnlyAccessToEvents(
completion: @escaping @Sendable (Bool, (any Error)?) -> Void)
func requestFullAccessToEvents(
completion: @escaping @Sendable (Bool, (any Error)?) -> Void)
func requestFullAccessToReminders(
completion: @escaping @Sendable (Bool, (any Error)?) -> Void)
}
extension EKEventStore: EventKitPermissionStore {}
/// Keeps one event store alive while Calendar or Reminders permission sheets are active.
///
/// EventKit recommends retaining a long-lived store. A temporary store can disappear
/// before its asynchronous authorization callback completes, leaving the UI waiting
/// even though iOS persisted the user's choice.
/// `PermissionRequestBridge` starts every store request on the main actor; the unchecked
/// conformance only allows that private store owner to cross the bridge's sendable closure.
final class EventKitPermissionRequester: @unchecked Sendable {
private let store: any EventKitPermissionStore
init(store: any EventKitPermissionStore = EKEventStore()) {
self.store = store
}
func requestWriteOnlyAccessToEvents() async -> Bool {
await PermissionRequestBridge.awaitRequest { [self] completion in
self.store.requestWriteOnlyAccessToEvents { granted, _ in
completion(granted)
}
}
}
func requestFullAccessToEvents() async -> Bool {
await PermissionRequestBridge.awaitRequest { [self] completion in
self.store.requestFullAccessToEvents { granted, _ in
completion(granted)
}
}
}
func requestFullAccessToReminders() async -> Bool {
await PermissionRequestBridge.awaitRequest { [self] completion in
self.store.requestFullAccessToReminders { granted, _ in
completion(granted)
}
}
}
}