diff --git a/LeCountdown.xcodeproj/project.pbxproj b/LeCountdown.xcodeproj/project.pbxproj index f8a5b09..6675c34 100644 --- a/LeCountdown.xcodeproj/project.pbxproj +++ b/LeCountdown.xcodeproj/project.pbxproj @@ -1461,7 +1461,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 0.1.1; + MARKETING_VERSION = 0.1.2; PRODUCT_BUNDLE_IDENTIFIER = com.staxriver.LeCountdown; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -1495,7 +1495,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 0.1.1; + MARKETING_VERSION = 0.1.2; PRODUCT_BUNDLE_IDENTIFIER = com.staxriver.LeCountdown; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -1598,7 +1598,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 0.1.1; + MARKETING_VERSION = 0.1.2; PRODUCT_BUNDLE_IDENTIFIER = com.staxriver.LeCountdown.LaunchWidget; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -1626,7 +1626,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 0.1.1; + MARKETING_VERSION = 0.1.2; PRODUCT_BUNDLE_IDENTIFIER = com.staxriver.LeCountdown.LaunchWidget; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -1653,7 +1653,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 0.1.1; + MARKETING_VERSION = 0.1.2; PRODUCT_BUNDLE_IDENTIFIER = com.staxriver.LeCountdown.LaunchIntents; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -1680,7 +1680,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 0.1.1; + MARKETING_VERSION = 0.1.2; PRODUCT_BUNDLE_IDENTIFIER = com.staxriver.LeCountdown.LaunchIntents; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; diff --git a/LeCountdown.xcodeproj/xcshareddata/xcschemes/LeCountdown.xcscheme b/LeCountdown.xcodeproj/xcshareddata/xcschemes/LeCountdown.xcscheme index c47ab63..22e466d 100644 --- a/LeCountdown.xcodeproj/xcshareddata/xcschemes/LeCountdown.xcscheme +++ b/LeCountdown.xcodeproj/xcshareddata/xcschemes/LeCountdown.xcscheme @@ -50,6 +50,20 @@ ReferencedContainer = "container:LeCountdown.xcodeproj"> + + + + + + + + Bool { UNUserNotificationCenter.current().delegate = self + + self._initSchemaIfNeeded() + self._activateAudioSession() + + Sound.computeSoundDurationsIfNecessary() + Conductor.maestro.cleanup() + return true } + fileprivate func _initSchemaIfNeeded() { + if !Preferences.cloudKitSchemaInitialized { + do { + try PersistenceController.shared.container.initializeCloudKitSchema() + Preferences.cloudKitSchemaInitialized = true + } catch { + print("initializeCloudKitSchema error: \(error)") + } + } + } + + fileprivate func _activateAudioSession() { + do { + let audioSession: AVAudioSession = AVAudioSession.sharedInstance() + try audioSession.setCategory(.playback) + try audioSession.setActive(true) + } catch { + Logger.error(error) + } + } + func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { if userActivity.interaction == nil { diff --git a/LeCountdown/Intent/TimerIdentifierAppEntity.swift b/LeCountdown/Intent/TimerIdentifierAppEntity.swift index c4ddcb4..25c1169 100644 --- a/LeCountdown/Intent/TimerIdentifierAppEntity.swift +++ b/LeCountdown/Intent/TimerIdentifierAppEntity.swift @@ -21,10 +21,14 @@ struct TimerIdentifierAppEntity: AppEntity { } func suggestedEntities() async throws -> [TimerIdentifierAppEntity] { + + try await PersistenceController.shared.container.performBackgroundTask { context in + let timers = try IntentDataProvider.main.timers(context: context) + return timers.map { TimerIdentifierAppEntity(id: $0.stringId, displayString: $0.displayName) } + } + // TODO: return likely TimerIdentifierAppEntity entities here. // This method is optional; the default implementation returns an empty array. - let timers = try IntentDataProvider.main.timers() - return timers.map { TimerIdentifierAppEntity(id: $0.stringId, displayString: $0.displayName) } } } diff --git a/LeCountdown/LeCountdownApp.swift b/LeCountdown/LeCountdownApp.swift index b283982..7500570 100644 --- a/LeCountdown/LeCountdownApp.swift +++ b/LeCountdown/LeCountdownApp.swift @@ -24,31 +24,15 @@ struct LeCountdownApp: App { UIPageControl.appearance().currentPageIndicatorTintColor = .systemPink UIPageControl.appearance().pageIndicatorTintColor = UIColor(white: 0.7, alpha: 1.0) + Logger.log("path = \(Bundle.main.bundlePath)") + self._registerBackgroundRefreshes() - self._initSchemaIfNeeded() - self._activateAudioSession() - } - - fileprivate func _initSchemaIfNeeded() { - if !Preferences.cloudKitSchemaInitialized { - do { - try persistenceController.container.initializeCloudKitSchema() - Preferences.cloudKitSchemaInitialized = true - } catch { - print("ERROR \(error)") - } - } - } - - fileprivate func _activateAudioSession() { - do { - let audioSession: AVAudioSession = AVAudioSession.sharedInstance() - try audioSession.setCategory(.playback) - try audioSession.setActive(true) - } catch { - Logger.error(error) - } +// if !ProcessInfo.processInfo.isiOSAppOnMac { +// self._initSchemaIfNeeded() +// self._activateAudioSession() +// } + } @Environment(\.scenePhase) var scenePhase @@ -98,7 +82,6 @@ struct LeCountdownApp: App { Logger.log("preferredLanguages = \(String(describing: Locale.preferredLanguages))") - Sound.computeSoundDurationsIfNecessary() self._patch() diff --git a/LeCountdown/Model/Persistence.swift b/LeCountdown/Model/Persistence.swift index 5b8c7ac..ed1934b 100644 --- a/LeCountdown/Model/Persistence.swift +++ b/LeCountdown/Model/Persistence.swift @@ -38,7 +38,6 @@ struct PersistenceController { record.activity = activities.randomElement() } - do { try viewContext.save() } catch { diff --git a/LeCountdown/TimerRouter.swift b/LeCountdown/TimerRouter.swift index 17110cf..8e74554 100644 --- a/LeCountdown/TimerRouter.swift +++ b/LeCountdown/TimerRouter.swift @@ -59,16 +59,18 @@ class TimerRouter { fileprivate static func _launchCountdown(_ countdown: Countdown, handler: @escaping (Result) -> Void) { UNUserNotificationCenter.current().getNotificationSettings { settings in - switch settings.authorizationStatus { - case .notDetermined, .denied: - handler(.failure(TimerRouterError.notificationAuthorizationMissing)) - default: - CountdownScheduler.master.scheduleIfPossible(countdown: countdown) { result in - switch result { - case .success: - handler(.success(Void())) - case .failure(let failure): - handler(.failure(failure)) + DispatchQueue.main.async { + switch settings.authorizationStatus { + case .notDetermined, .denied: + handler(.failure(TimerRouterError.notificationAuthorizationMissing)) + default: + CountdownScheduler.master.scheduleIfPossible(countdown: countdown) { result in + switch result { + case .success: + handler(.success(Void())) + case .failure(let failure): + handler(.failure(failure)) + } } } } diff --git a/LeCountdown/Views/TimersView.swift b/LeCountdown/Views/TimersView.swift index 7893c94..f4dee58 100644 --- a/LeCountdown/Views/TimersView.swift +++ b/LeCountdown/Views/TimersView.swift @@ -53,7 +53,8 @@ struct TimersView: View { } } - }.padding(.horizontal, itemSpacing) + } + .padding(.horizontal, itemSpacing) } else { Text("You'll find your timers here. Start by creating them on the left screen").multilineTextAlignment(.center) } @@ -75,6 +76,7 @@ struct TimersView: View { } fileprivate func _handleSiriTips(timer: AbstractTimer) { + let timerId = timer.stringId if !Preferences.timerSiriTips.contains(timerId) { self.boringContext.siriTimer = timer diff --git a/LeCountdown/Widget/IntentDataProvider.swift b/LeCountdown/Widget/IntentDataProvider.swift index 7b7e7fb..f13e2cd 100644 --- a/LeCountdown/Widget/IntentDataProvider.swift +++ b/LeCountdown/Widget/IntentDataProvider.swift @@ -13,7 +13,10 @@ class IntentDataProvider { static let main: IntentDataProvider = IntentDataProvider() func timers() throws -> [AbstractTimer] { - let context = PersistenceController.shared.container.viewContext + return try timers(context: PersistenceController.shared.container.viewContext) + } + + func timers(context: NSManagedObjectContext) throws -> [AbstractTimer] { let request: NSFetchRequest = AbstractTimer.fetchRequest() request.sortDescriptors = [NSSortDescriptor(keyPath: (\AbstractTimer.order), ascending: true)] return try context.fetch(request)