b2970e4c-45a2-423e-b84d-257.../Sources/storage/GoldPositionStore.swift

58 lines
2.0 KiB
Swift
Raw Normal View History

//
// GoldPositionStore.swift
// plugin v0.2
//
// Persists the single GoldPosition to its own JSON file (separate
// from watchlist.json different shape, different lifecycle).
//
// Path: ~/Library/Application Support/Mio Island/Fund/gold-position.json
//
import Foundation
@MainActor
final class GoldPositionStore: ObservableObject {
@Published private(set) var position: GoldPosition = GoldPosition(grams: nil, costPerGram: nil)
private let storeURL: URL
private let queue = DispatchQueue(label: "com.mioisland.plugin.fund.gold-position", qos: .userInitiated)
init() {
let appSupport = FileManager.default
.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0]
let dir = appSupport.appendingPathComponent("Mio Island/Fund", isDirectory: true)
try? FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true)
self.storeURL = dir.appendingPathComponent("gold-position.json")
load()
}
func update(grams: Double?, costPerGram: Double?) {
position = GoldPosition(grams: grams, costPerGram: costPerGram)
save()
}
private func load() {
guard let data = try? Data(contentsOf: storeURL),
let decoded = try? JSONDecoder().decode(GoldPosition.self, from: data) else {
return
}
position = decoded
}
private func save() {
let snapshot = position
queue.async { [storeURL] in
do {
let encoder = JSONEncoder()
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
let data = try encoder.encode(snapshot)
let tmp = storeURL.appendingPathExtension("tmp")
try data.write(to: tmp, options: .atomic)
_ = try? FileManager.default.replaceItemAt(storeURL, withItemAt: tmp)
} catch {
NSLog("[fund-plugin] gold position save failed: \(error)")
}
}
}
}