Transfer view, change data flow, actors
This commit is contained in:
@ -3,7 +3,7 @@ import Combine
|
||||
import BinaryCodable
|
||||
import SwiftUI
|
||||
|
||||
final class TemperatureStorage: ObservableObject {
|
||||
final class PersistentStorage: ObservableObject {
|
||||
|
||||
static var documentDirectory: URL {
|
||||
try! FileManager.default.url(
|
||||
@ -15,6 +15,9 @@ final class TemperatureStorage: ObservableObject {
|
||||
@AppStorage("newestDate")
|
||||
private var newestMeasurementTime: Int = 0
|
||||
|
||||
@AppStorage("deviceTime")
|
||||
private var lastDeviceTimeData: Data?
|
||||
|
||||
/**
|
||||
The date of the latest measurement.
|
||||
|
||||
@ -34,22 +37,26 @@ final class TemperatureStorage: ObservableObject {
|
||||
|
||||
@Published
|
||||
var dailyMeasurementCounts: [MeasurementDailyCount] = []
|
||||
|
||||
|
||||
/// The formatter for the temperature measurement file names
|
||||
private let fileNameFormatter: DateFormatter
|
||||
|
||||
private let storageFolder: URL
|
||||
|
||||
private let overviewFileUrl: URL
|
||||
|
||||
/// The storage of daily temperature measurements
|
||||
private let temperatureStorageFolderUrl: URL
|
||||
|
||||
/// The storage of the measurement counts per day
|
||||
private let dailyCountsFileUrl: URL
|
||||
|
||||
private let fm: FileManager
|
||||
|
||||
|
||||
/// The interval in which the measurements should be kept in `recentMeasurements`
|
||||
private let lastValueInterval: TimeInterval
|
||||
|
||||
init(lastMeasurements: [TemperatureMeasurement] = [], lastValueInterval: TimeInterval = 3600) {
|
||||
self.recentMeasurements = lastMeasurements
|
||||
let documentDirectory = TemperatureStorage.documentDirectory
|
||||
self.storageFolder = documentDirectory.appendingPathComponent("measurements")
|
||||
self.overviewFileUrl = documentDirectory.appendingPathComponent("overview.bin")
|
||||
let documentDirectory = PersistentStorage.documentDirectory
|
||||
self.temperatureStorageFolderUrl = documentDirectory.appendingPathComponent("measurements")
|
||||
self.dailyCountsFileUrl = documentDirectory.appendingPathComponent("overview.bin")
|
||||
self.fm = .default
|
||||
self.fileNameFormatter = DateFormatter()
|
||||
self.fileNameFormatter.dateFormat = "yyyyMMdd.bin"
|
||||
@ -63,15 +70,15 @@ final class TemperatureStorage: ObservableObject {
|
||||
}
|
||||
|
||||
ensureExistenceOfFolder()
|
||||
recalculateDailyCounts()
|
||||
//recalculateDailyCounts()
|
||||
}
|
||||
|
||||
private func ensureExistenceOfFolder() {
|
||||
guard !fm.fileExists(atPath: storageFolder.path) else {
|
||||
guard !fm.fileExists(atPath: temperatureStorageFolderUrl.path) else {
|
||||
return
|
||||
}
|
||||
do {
|
||||
try fm.createDirectory(at: storageFolder, withIntermediateDirectories: true)
|
||||
try fm.createDirectory(at: temperatureStorageFolderUrl, withIntermediateDirectories: true)
|
||||
} catch {
|
||||
log.error("Failed to create folder: \(error)")
|
||||
}
|
||||
@ -86,16 +93,17 @@ final class TemperatureStorage: ObservableObject {
|
||||
}
|
||||
|
||||
private func fileUrl(for dateIndex: Int) -> URL {
|
||||
storageFolder.appendingPathComponent(fileName(for: dateIndex))
|
||||
temperatureStorageFolderUrl.appendingPathComponent(fileName(for: dateIndex))
|
||||
}
|
||||
|
||||
private func fileUrl(for fileName: String) -> URL {
|
||||
storageFolder.appendingPathComponent(fileName)
|
||||
temperatureStorageFolderUrl.appendingPathComponent(fileName)
|
||||
}
|
||||
|
||||
private func loadLastMeasurements() {
|
||||
let startDate = Date().addingTimeInterval(-lastValueInterval)
|
||||
let todayIndex = Date().dateIndex
|
||||
let now = Date.now
|
||||
let startDate = now.addingTimeInterval(-lastValueInterval)
|
||||
let todayIndex = now.dateIndex
|
||||
let todayValues = loadMeasurements(for: todayIndex)
|
||||
.filter { $0.date >= startDate }
|
||||
let dateIndexOfStart = startDate.dateIndex
|
||||
@ -220,7 +228,7 @@ final class TemperatureStorage: ObservableObject {
|
||||
|
||||
private func loadDailyCounts() {
|
||||
do {
|
||||
let data = try Data(contentsOf: overviewFileUrl)
|
||||
let data = try Data(contentsOf: dailyCountsFileUrl)
|
||||
dailyMeasurementCounts = try BinaryDecoder.decode(from: data)
|
||||
} catch {
|
||||
log.error("Failed to load overview: \(error)")
|
||||
@ -230,7 +238,7 @@ final class TemperatureStorage: ObservableObject {
|
||||
private func saveDailyCounts() {
|
||||
do {
|
||||
let data = try BinaryEncoder.encode(dailyMeasurementCounts)
|
||||
try data.write(to: overviewFileUrl)
|
||||
try data.write(to: dailyCountsFileUrl)
|
||||
} catch {
|
||||
log.error("Failed to write overview: \(error)")
|
||||
}
|
||||
@ -248,7 +256,7 @@ final class TemperatureStorage: ObservableObject {
|
||||
|
||||
func recalculateDailyCounts() {
|
||||
do {
|
||||
let files = try fm.contentsOfDirectory(atPath: storageFolder.path)
|
||||
let files = try fm.contentsOfDirectory(atPath: temperatureStorageFolderUrl.path)
|
||||
let newValues: [Int: Int] = files
|
||||
.reduce(into: [:]) { counts, fileName in
|
||||
let dateString = fileName.replacingOccurrences(of: ".bin", with: "")
|
||||
@ -269,6 +277,37 @@ final class TemperatureStorage: ObservableObject {
|
||||
log.error("Failed to load daily counts: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Device time
|
||||
|
||||
var lastDeviceTime: DeviceTime? {
|
||||
get {
|
||||
guard let data = lastDeviceTimeData else {
|
||||
return nil
|
||||
}
|
||||
do {
|
||||
let result: DeviceTime = try BinaryDecoder.decode(from: data)
|
||||
return result
|
||||
} catch {
|
||||
log.error("Failed to decode device time: \(error)")
|
||||
lastDeviceTimeData = nil
|
||||
return nil
|
||||
}
|
||||
}
|
||||
set {
|
||||
guard let newValue else {
|
||||
lastDeviceTimeData = nil
|
||||
return
|
||||
}
|
||||
do {
|
||||
let data = try BinaryEncoder.encode(newValue)
|
||||
lastDeviceTimeData = data
|
||||
} catch {
|
||||
log.error("Failed to encode device time: \(error)")
|
||||
lastDeviceTimeData = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension Array where Element == TemperatureMeasurement {
|
||||
@ -294,9 +333,9 @@ private extension Array where Element == TemperatureMeasurement {
|
||||
}
|
||||
}
|
||||
|
||||
extension TemperatureStorage {
|
||||
extension PersistentStorage {
|
||||
|
||||
static var mock: TemperatureStorage {
|
||||
static var mock: PersistentStorage {
|
||||
.init(lastMeasurements: TemperatureMeasurement.mockData)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user