Files
jrshikoku/targets/widget/SharedData.swift

72 lines
2.1 KiB
Swift

import Foundation
import WidgetKit
import SwiftUI
let operationInfoSnapshotURL = "https://jr-shikoku-api-data-storage.haruk.in/operation-info/jr-shikoku/latest.json"
let delayInfoLegacyURL = "https://jr-shikoku-api-data-storage.haruk.in/legacy/trainfo-ex.txt"
/// App Group ID shared between the main app and widget extension.
let appGroupID = "group.jrshikokuinfo.xprocess.hrkn"
// MARK: - Shared data helpers
struct FelicaSnapshot: Codable {
let balance: Int
let idm: String
let systemCode: String?
let scannedAt: String
}
struct OperationInfoCompatibility: Decodable {
let operationInfoText: String
let hasOperationInfo: Bool
}
struct OperationInfoSnapshot: Decodable {
let compatibility: OperationInfoCompatibility
}
enum OperationInfoFetchError: Error {
case invalidURL
case invalidResponse
}
func fetchOperationInfoSnapshot(completion: @escaping (Result<OperationInfoSnapshot, Error>) -> Void) {
guard let url = URL(string: operationInfoSnapshotURL) else {
completion(.failure(OperationInfoFetchError.invalidURL))
return
}
var request = URLRequest(
url: url,
cachePolicy: .reloadIgnoringLocalCacheData,
timeoutInterval: 15
)
request.setValue("no-cache", forHTTPHeaderField: "Cache-Control")
URLSession.shared.dataTask(with: request) { data, response, error in
guard error == nil,
let response = response as? HTTPURLResponse,
(200..<300).contains(response.statusCode),
let data = data else {
completion(.failure(error ?? OperationInfoFetchError.invalidResponse))
return
}
do {
completion(.success(try JSONDecoder().decode(OperationInfoSnapshot.self, from: data)))
} catch {
completion(.failure(error))
}
}.resume()
}
func sharedDefaults() -> UserDefaults {
UserDefaults(suiteName: appGroupID) ?? .standard
}
func loadFelicaSnapshot() -> FelicaSnapshot? {
guard let data = sharedDefaults().data(forKey: "felicaLastSnapshot") else { return nil }
return try? JSONDecoder().decode(FelicaSnapshot.self, from: data)
}