@@ -16,10 +16,7 @@ public final class Scheduler: NSObject, CLLocationManagerDelegate {
1616 public static let shared = Scheduler ( )
1717 private override init ( ) { super. init ( ) }
1818
19- private var isScheduling = false
20- public func schedule( ) {
21- if isScheduling { return }
22- isScheduling = true
19+ private func requestLocationUpdate( ) -> Bool {
2320 switch CLLocationManager . authorizationStatus ( ) {
2421 case . authorizedAlways, . notDetermined:
2522 manager. stopUpdatingLocation ( )
@@ -28,79 +25,109 @@ public final class Scheduler: NSObject, CLLocationManagerDelegate {
2825 } else {
2926 manager. startUpdatingLocation ( )
3027 }
28+ return true
3129 default :
30+ return false
31+ }
32+ }
33+
34+ private var isScheduling = false
35+ public func schedule( ) {
36+ if isScheduling { return }
37+ isScheduling = true
38+ if !requestLocationUpdate( ) {
3239 scheduleAtCachedLocation ( )
3340 }
3441 }
3542
43+ public typealias StyleProcessor = ( AppleInterfaceStyle ? ) -> Void
44+ private var _callback : StyleProcessor ?
45+ private var callback : StyleProcessor ? {
46+ get {
47+ defer { _callback = nil }
48+ return _callback
49+ }
50+ set {
51+ _callback = newValue
52+ }
53+ }
54+ public func getCurrentMode( then process: @escaping StyleProcessor ) {
55+ callback = process
56+ if requestLocationUpdate ( ) { return }
57+ callback ? ( nil )
58+ }
59+
3660 private var task : Task ?
3761
38- private func schedule( atLocation coordinate: CLLocationCoordinate2D ? ) {
39- defer { isScheduling = false }
40- guard preferences. scheduled else { return cancel ( ) }
62+ public func mode( atLocation coordinate: CLLocationCoordinate2D ? ) -> ( style: AppleInterfaceStyle , date: Date ? ) {
4163 let now = Date ( )
4264 let tomorrow = Calendar . current. date ( byAdding: . day, value: 1 , to: now) !
4365 if let coordinate = coordinate
4466 , CLLocationCoordinate2DIsValid ( coordinate)
4567 , preferences. scheduleZenithType != . custom {
46- defer { removeAllNotifications ( ) }
4768 let scheduledDate : Date
4869 let solar = Solar ( for: now, coordinate: coordinate) !
4970 let dates = solar. sunriseSunsetTime
50- #warning("FIXME: Having trouble figuring out time zone")
5171 if now < dates. sunrise {
52- AppleInterfaceStyle . darkAqua. enable ( )
5372 scheduledDate = dates. sunrise
5473 let yesterday = Calendar . current. date ( byAdding: . day, value: - 1 , to: now) !
5574 let pastSolar = Solar ( for: yesterday, coordinate: coordinate) !
5675 preferences. scheduleStart = pastSolar. sunriseSunsetTime. sunset
5776 preferences. scheduleEnd = scheduledDate
77+ return ( . darkAqua, scheduledDate)
5878 } else {
5979 let futureSolar = Solar ( for: tomorrow, coordinate: coordinate) !
6080 let futureDates = futureSolar. sunriseSunsetTime
6181 if now < dates. sunset {
62- AppleInterfaceStyle . aqua. enable ( )
6382 scheduledDate = dates. sunset
6483 preferences. scheduleStart = scheduledDate
6584 preferences. scheduleEnd = futureDates. sunrise
85+ return ( . aqua, scheduledDate)
6686 } else { // after sunset
67- AppleInterfaceStyle . darkAqua. enable ( )
6887 preferences. scheduleStart = dates. sunset
6988 scheduledDate = futureDates. sunrise
7089 preferences. scheduleEnd = scheduledDate
90+ return ( . darkAqua, scheduledDate)
7191 }
7292 }
73- return task = Plan . at ( scheduledDate) . do ( onElapse: schedule)
7493 }
7594 if preferences. scheduleZenithType != . custom {
7695 preferences. scheduleZenithType = . custom
7796 }
78- #warning("FIXME: This is gonna be a catastrophe when a user moves across timezone")
7997 let current = Calendar . current. dateComponents ( [ . hour, . minute] , from: now)
8098 let start = Calendar . current. dateComponents (
8199 [ . hour, . minute] , from: preferences. scheduleStart
82100 )
83101 let end = Calendar . current. dateComponents (
84102 [ . hour, . minute] , from: preferences. scheduleEnd
85103 )
86- let scheduledDate : Date !
104+ if start == end { return ( . current , nil ) }
87105 if current < end {
88- AppleInterfaceStyle . darkAqua. enable ( )
89- scheduledDate = Calendar . current. date (
106+ return ( . darkAqua, Calendar . current. date (
90107 bySettingHour: end. hour!, minute: end. minute!, second: 0 , of: now
91- )
108+ ) )
92109 } else if current < start {
93- AppleInterfaceStyle . aqua. enable ( )
94- scheduledDate = Calendar . current. date (
110+ return ( . aqua, Calendar . current. date (
95111 bySettingHour: start. hour!, minute: start. minute!, second: 0 , of: now
96- )
97- } else {
98- AppleInterfaceStyle . darkAqua. enable ( )
99- scheduledDate = Calendar . current. date (
112+ ) )
113+ } else if start > end {
114+ return ( . darkAqua, Calendar . current. date (
100115 bySettingHour: end. hour!, minute: end. minute!, second: 0 , of: tomorrow
101- )
116+ ) )
117+ } else {
118+ return ( . aqua, Calendar . current. date (
119+ bySettingHour: start. hour!, minute: start. minute!, second: 0 , of: tomorrow
120+ ) )
102121 }
103- task = Plan . at ( scheduledDate) . do ( onElapse: schedule)
122+ }
123+
124+ private func schedule( atLocation coordinate: CLLocationCoordinate2D ? ) {
125+ defer { isScheduling = false }
126+ removeAllNotifications ( )
127+ let decision = mode ( atLocation: coordinate)
128+ AppleScript . checkPermission ( onSuccess: decision. style. enable)
129+ guard let date = decision. date else { return }
130+ task = Plan . at ( date) . do ( onElapse: schedule)
104131 }
105132
106133 public func cancel( ) {
@@ -128,7 +155,12 @@ public final class Scheduler: NSObject, CLLocationManagerDelegate {
128155 guard let location = locations. last else { return }
129156 manager. stopUpdatingLocation ( )
130157 preferences. location = location
131- schedule ( atLocation: location. coordinate)
158+ let coordinate = location. coordinate
159+ if isScheduling {
160+ schedule ( atLocation: coordinate)
161+ } else {
162+ callback ? ( mode ( atLocation: coordinate) . style)
163+ }
132164 }
133165
134166 public func locationManager( _ manager: CLLocationManager ,
0 commit comments