1+ import CoreLocation
12import EventKit
23import Foundation
34
@@ -116,6 +117,9 @@ public actor RemindersStore {
116117 if let recurrenceRule = draft. recurrenceRule {
117118 replaceRecurrence ( on: reminder, with: recurrenceRule)
118119 }
120+ if let locationTrigger = draft. locationTrigger {
121+ reminder. addAlarm ( try await locationAlarm ( from: locationTrigger) )
122+ }
119123 try eventStore. save ( reminder, commit: true )
120124 return item ( from: reminder)
121125 }
@@ -211,6 +215,7 @@ extension RemindersStore {
211215 let dueDateIsAllDay : Bool
212216 let alarmDate : Date ?
213217 let recurrenceRule : RecurrenceRule ?
218+ let locationTrigger : LocationTrigger ?
214219 let listID : String
215220 let listName : String
216221 }
@@ -234,6 +239,7 @@ extension RemindersStore {
234239 dueDateIsAllDay: isAllDay ( components) ,
235240 alarmDate: Self . alarmDate ( from: reminder) ,
236241 recurrenceRule: Self . recurrenceRule ( from: reminder) ,
242+ locationTrigger: Self . locationTrigger ( from: reminder) ,
237243 listID: reminder. calendar. calendarIdentifier,
238244 listName: reminder. calendar. title
239245 )
@@ -257,6 +263,7 @@ extension RemindersStore {
257263 dueDateIsAllDay: data. dueDateIsAllDay,
258264 alarmDate: data. alarmDate,
259265 recurrenceRule: data. recurrenceRule,
266+ locationTrigger: data. locationTrigger,
260267 listID: data. listID,
261268 listName: data. listName
262269 )
@@ -310,6 +317,7 @@ extension RemindersStore {
310317 dueDateIsAllDay: isAllDay ( components) ,
311318 alarmDate: Self . alarmDate ( from: reminder) ,
312319 recurrenceRule: Self . recurrenceRule ( from: reminder) ,
320+ locationTrigger: Self . locationTrigger ( from: reminder) ,
313321 listID: reminder. calendar. calendarIdentifier,
314322 listName: reminder. calendar. title
315323 )
@@ -344,6 +352,44 @@ extension RemindersStore {
344352 guard let frequency = RecurrenceFrequency ( eventKitFrequency: rule. frequency) else { return nil }
345353 return RecurrenceRule ( frequency: frequency, interval: rule. interval)
346354 }
355+
356+ private func locationAlarm( from trigger: LocationTrigger ) async throws -> EKAlarm {
357+ let structuredLocation = EKStructuredLocation ( title: trigger. address)
358+ let location : CLLocation
359+ if let latitude = trigger. latitude, let longitude = trigger. longitude {
360+ location = CLLocation ( latitude: latitude, longitude: longitude)
361+ } else {
362+ let placemarks = try await CLGeocoder ( ) . geocodeAddressString ( trigger. address)
363+ guard let geocodedLocation = placemarks. first? . location else {
364+ throw RemindCoreError . operationFailed ( " Could not geocode location: \( trigger. address) " )
365+ }
366+ location = geocodedLocation
367+ }
368+
369+ structuredLocation. geoLocation = location
370+ structuredLocation. radius = trigger. radius
371+
372+ let alarm = EKAlarm ( )
373+ alarm. structuredLocation = structuredLocation
374+ alarm. proximity = trigger. proximity == . arriving ? . enter : . leave
375+ return alarm
376+ }
377+
378+ private static func locationTrigger( from reminder: EKReminder ) -> LocationTrigger ? {
379+ guard let alarm = reminder. alarms? . first ( where: { $0. structuredLocation != nil } ) ,
380+ let structuredLocation = alarm. structuredLocation,
381+ let proximity = LocationProximity ( eventKitProximity: alarm. proximity)
382+ else { return nil }
383+
384+ let coordinate = structuredLocation. geoLocation? . coordinate
385+ return LocationTrigger (
386+ address: structuredLocation. title ?? " " ,
387+ latitude: coordinate? . latitude,
388+ longitude: coordinate? . longitude,
389+ radius: structuredLocation. radius,
390+ proximity: proximity
391+ )
392+ }
347393}
348394
349395extension RecurrenceFrequency {
@@ -381,3 +427,16 @@ extension RecurrenceRule {
381427 frequency. eventKitFrequency
382428 }
383429}
430+
431+ extension LocationProximity {
432+ fileprivate init ? ( eventKitProximity: EKAlarmProximity ) {
433+ switch eventKitProximity {
434+ case . enter:
435+ self = . arriving
436+ case . leave:
437+ self = . leaving
438+ default :
439+ return nil
440+ }
441+ }
442+ }
0 commit comments