Build iOS App / Build .ipa and publish source (push) Successful in 23s
The inbox was slow because it enriched every PR with CI runs + reviews (2 extra API calls per PR, sequential). Drop that from the list — CI/review status now shows only in the PR detail screen. Add a disk cache so the landing screen renders instantly from the last load, then refreshes in the background and keeps the cached list on network failure. Bump to 2.1.
44 lines
1.6 KiB
Swift
44 lines
1.6 KiB
Swift
import Foundation
|
|
|
|
/// Persists the inbox PR list to disk so the landing screen can render
|
|
/// instantly from the last load, then refresh in the background.
|
|
struct InboxCache {
|
|
private let fileURL: URL
|
|
|
|
init() {
|
|
let dir = FileManager.default.urls(for: .cachesDirectory,
|
|
in: .userDomainMask)[0]
|
|
fileURL = dir.appendingPathComponent("inbox.json")
|
|
}
|
|
|
|
func load() -> [PRRow] {
|
|
guard let data = try? Data(contentsOf: fileURL) else { return [] }
|
|
return (try? Self.decoder.decode([PRRow].self, from: data)) ?? []
|
|
}
|
|
|
|
func save(_ rows: [PRRow]) {
|
|
guard let data = try? JSONEncoder().encode(rows) else { return }
|
|
try? data.write(to: fileURL)
|
|
}
|
|
|
|
/// Same ISO8601-with-offset date strategy the API decoder uses, so the
|
|
/// cached `Date?` fields decode correctly.
|
|
private static let decoder: JSONDecoder = {
|
|
let d = JSONDecoder()
|
|
let formatter = ISO8601DateFormatter()
|
|
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
|
|
d.dateDecodingStrategy = .custom { decoder in
|
|
let container = try decoder.singleValueContainer()
|
|
let str = try container.decode(String.self)
|
|
if let date = formatter.date(from: str) { return date }
|
|
let plain = ISO8601DateFormatter()
|
|
plain.formatOptions = [.withInternetDateTime]
|
|
if let date = plain.date(from: str) { return date }
|
|
throw DecodingError.dataCorruptedError(
|
|
in: container,
|
|
debugDescription: "Cannot decode date string \(str)")
|
|
}
|
|
return d
|
|
}()
|
|
}
|