diff --git a/ios/AWSary/resources/Info.plist b/ios/AWSary/resources/Info.plist index f5674e0..866804b 100644 --- a/ios/AWSary/resources/Info.plist +++ b/ios/AWSary/resources/Info.plist @@ -4,7 +4,7 @@ ITSAppUsesNonExemptEncryption - NSCalendarsWriteOnlyAccessUsageDescription - + NSCalendarsWriteOnlyAccessUsageDescription + Calendar access is only used to add the classroom schedules you request. diff --git a/ios/Shared/DataModels/AwsServices.swift b/ios/Shared/DataModels/AwsServices.swift index 40f276c..9c7d062 100644 --- a/ios/Shared/DataModels/AwsServices.swift +++ b/ios/Shared/DataModels/AwsServices.swift @@ -8,7 +8,6 @@ import Foundation var fm = FileManager.default -var subUrl: URL? var mainUrl: URL? = Bundle.main.url(forResource: "aws_services", withExtension: "json") var lastRandom: awsService = awsService(id: 10, name: "DeepRacer", longName: "AWS DeepRacer", shortDesctiption: "DeepRacer", imageURL: "https://static.tig.pt/awsary/logos/Arch_AWS-DeepRacer_64.svg", youtube_id: "") @@ -23,47 +22,78 @@ class AwsServices: ObservableObject { return lastRandom } - func getRandomElement() -> awsService{ - lastRandom = services.randomElement()! - return lastRandom + func getRandomElement() -> awsService { + if services.isEmpty { + refresh() + } + + guard let randomService = services.randomElement() else { + return lastRandom + } + + lastRandom = randomService + return randomService + } + + init() { + refresh() + } + + private func servicesFromDocuments() -> [awsService] { + do { + let documentDirectory = try fm.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) + let documentURL = documentDirectory.appendingPathComponent("aws_services.json") + + guard fm.fileExists(atPath: documentURL.path) else { + return [] + } + + return decodeData(pathName: documentURL) + } catch { + print("Failed to resolve documents directory for aws_services.json: \(error)") + return [] + } + } + + private func servicesFromBundle() -> [awsService] { + guard let bundleURL = mainUrl else { + print("Missing bundled aws_services.json") + return [] + } + + return decodeData(pathName: bundleURL) + } + + private func decodeData(pathName: URL) -> [awsService] { + do { + let jsonData = try Data(contentsOf: pathName) + let decoder = JSONDecoder() + let decoded = try decoder.decode([awsService].self, from: jsonData) + + if decoded.isEmpty { + print("Decoded zero services from \(pathName.lastPathComponent)") + } + + return decoded + } catch { + print("Failed to decode aws_services.json from \(pathName): \(error)") + return [] + } + } + + func refresh() { + var loadedServices = servicesFromDocuments() + + if loadedServices.isEmpty { + loadedServices = servicesFromBundle() + } + + if loadedServices.isEmpty { + print("Falling back to last known service to prevent empty catalogue") + services = [lastRandom] + } else { + loadedServices.sort { $0.name < $1.name } + services = loadedServices + } } - init() { - refresh() - } - - func getData() { - do { - let documentDirectory = try fm.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) - subUrl = documentDirectory.appendingPathComponent("aws_services.json") - loadFile(mainPath: mainUrl!, subPath: subUrl!) - } catch { - print(error) - } - } - - func loadFile(mainPath: URL, subPath: URL){ - if fm.fileExists(atPath: subPath.path){ - decodeData(pathName: subPath) - - if services.isEmpty{ - decodeData(pathName: mainPath) - } - - }else{ - decodeData(pathName: mainPath) - } - } - - func decodeData(pathName: URL){ - do{ - let jsonData = try Data(contentsOf: pathName) - let decoder = JSONDecoder() - services = try decoder.decode([awsService].self, from: jsonData) - } catch {} - } - - func refresh(){ - getData() - services.sort {$0.name < $1.name} - } }