50 lines
1.9 KiB
Swift
50 lines
1.9 KiB
Swift
// The last good feed, and the last detail of each thread opened, saved as JSON in the app's caches
|
|
// folder. Launch shows them at once while the first refresh runs. Signing out clears them, and demo
|
|
// mode never reads or writes them.
|
|
|
|
import Foundation
|
|
|
|
struct FeedCache: Sendable {
|
|
let directory: URL
|
|
|
|
static let standard = FeedCache(directory: .cachesDirectory.appending(path: "WristCode", directoryHint: .isDirectory))
|
|
|
|
func feed() -> Feed? {
|
|
read(Feed.self, "feed.json")
|
|
}
|
|
|
|
func save(_ feed: Feed) {
|
|
write(feed, "feed.json")
|
|
}
|
|
|
|
func thread(hostId: String, threadId: String) -> ThreadDetail? {
|
|
read(ThreadDetail.self, Self.threadFile(hostId, threadId))
|
|
}
|
|
|
|
func save(_ detail: ThreadDetail) {
|
|
write(detail, Self.threadFile(detail.item.hostId, detail.item.threadId))
|
|
}
|
|
|
|
/// Deletes everything saved, as when the watch unpairs.
|
|
func clear() {
|
|
try? FileManager.default.removeItem(at: directory)
|
|
}
|
|
|
|
/// `thread-<hostId>-<threadId>.json`, with the ids percent-encoded so any id is a safe file name.
|
|
private static func threadFile(_ hostId: String, _ threadId: String) -> String {
|
|
let safe = { (id: String) in id.addingPercentEncoding(withAllowedCharacters: .alphanumerics) ?? id }
|
|
return "thread-\(safe(hostId))-\(safe(threadId)).json"
|
|
}
|
|
|
|
private func read<Value: Decodable>(_ type: Value.Type, _ name: String) -> Value? {
|
|
guard let data = try? Data(contentsOf: directory.appending(path: name)) else { return nil }
|
|
return try? JSON.decoder().decode(type, from: data)
|
|
}
|
|
|
|
private func write(_ value: some Encodable, _ name: String) {
|
|
guard let data = try? JSON.encoder().encode(value) else { return }
|
|
try? FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)
|
|
try? data.write(to: directory.appending(path: name), options: .atomic)
|
|
}
|
|
}
|