You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
LeCountdown/LeCountdown/LeCountdownApp.swift

170 lines
5.3 KiB

//
// LeCountdownApp.swift
// LeCountdown
//
// Created by Laurent Morvillier on 20/01/2023.
//
import SwiftUI
import CoreData
import BackgroundTasks
import AVFoundation
import Combine
import CloudKit
@main
struct LeCountdownApp: App {
let persistenceController = PersistenceController.shared
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
@Environment(\.scenePhase) var scenePhase
@State var showStartView: Bool = false
init() {
UIPageControl.appearance().currentPageIndicatorTintColor = .systemPink
UIPageControl.appearance().pageIndicatorTintColor = UIColor(white: 0.7, alpha: 1.0)
Logger.log("path = \(Bundle.main.bundlePath)")
self._registerBackgroundRefreshes()
}
var body: some Scene {
WindowGroup {
CompactHomeView()
.environment(\.managedObjectContext, persistenceController.container.viewContext)
.fullScreenCover(isPresented: $showStartView) {
StartView(isPresented: $showStartView)
.environment(\.managedObjectContext, persistenceController.container.viewContext)
}
.onAppear {
self._onAppear()
}
.onChange(of: scenePhase) { newPhase in
switch newPhase {
case .inactive:
Conductor.maestro.stopMainPlayersIfPossible()
Conductor.maestro.memoryWarningReceived = false
case .active:
// Logger.log("onChange(of: scenePhase) active")
// Logger.log(Conductor.maestro.currentCountdowns.count)
Conductor.maestro.restoreSoundPlayers()
Conductor.maestro.cleanup()
default:
break
}
}
}
}
fileprivate func _shouldShowStartView() -> Bool {
let count = persistenceController.container.viewContext.count(entityName: "AbstractTimer")
return count == 0 && Preferences.hasShownStartView == false
}
fileprivate func _onAppear() {
Logger.log("preferredLanguages = \(String(describing: Locale.preferredLanguages))")
self.showStartView = self._shouldShowStartView()
self._patch()
let containerAvailable = self.isICloudContainerAvailable()
Logger.log("isICloudContainerAvailable = \(containerAvailable)")
// let voices = AVSpeechSynthesisVoice.speechVoices()
// let grouped = Dictionary(grouping: voices, by: { $0.language })
// for language in grouped.keys {
// if let lvoices = grouped[language] {
// print("language = \(language)")
// for voice in lvoices {
// print("name = \(voice.name), gender = \(voice.gender)")
// }
// print("========")
// }
// }
}
fileprivate func _registerBackgroundRefreshes() {
BGTaskScheduler.shared.register(forTaskWithIdentifier: BGTaskIdentifier.refresh.rawValue, using: nil) { task in
self._handleAppRefresh(task: task as! BGAppRefreshTask)
}
}
fileprivate func _handleAppRefresh(task: BGAppRefreshTask) {
print("_handleAppRefresh = \(task.description)")
// task.expirationHandler = {
// print("expired")
// }
//
// DispatchQueue.main.async {
// Conductor.maestro.updateLiveActivities()
// task.setTaskCompleted(success: true)
// }
}
fileprivate func _patch() {
let context = PersistenceController.shared.container.viewContext
do {
let records = try context.fetch(Record.fetchRequest())
for record in records {
record.preCompute()
}
try context.save()
} catch {
Logger.error(error)
}
}
func isICloudContainerAvailable() -> Bool {
print(#function)
CKContainer.default().accountStatus { (accountStatus, error) in
if accountStatus == .available {
return
}
///
// Checking account availability
// Silently return if everything goes well, or do a second check 200ms after the first failure
//
DispatchQueue.global().asyncAfter(deadline: .now() + 0.2) {
guard error != nil, accountStatus != CKAccountStatus.available else {return}
print("iCloud account is not available! Be sure you have signed in iCloud on this device!")
}
}
if FileManager.default.ubiquityIdentityToken != nil {
//print("User logged in")
return true
}
else {
//print("User is not logged in")
return false
}
}
static func askPermissions() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { success, error in
print("requestAuthorization > success = \(success), error = \(String(describing: error))")
}
}
}