Settings About: data source section (connection, station count, GOV.UK update time)

- Relay envelope now carries source (api|csv), stations_count, and
  data_updated (freshest price_last_updated the GOV.UK server reports,
  independent of relay sync time).
- App decodes the new envelope metadata (RelayMeta), persists it after
  each full fetch, and shows it in Settings → About → Data source:
  Connection (API/CSV), Stations count, Data updated (local-formatted).
- Older relays without the fields decode cleanly (nil meta → em-dash).
- 2 new tests for meta decode + absent-meta tolerance; 37/37 pass.
This commit is contained in:
FuelBoard Contributor
2026-08-12 16:23:41 +01:00
parent a5a95cbb03
commit fccd0c07ef
5 changed files with 162 additions and 1 deletions
+31
View File
@@ -264,6 +264,9 @@ struct FuelStore {
static let debugModeKey = "fuelboard.debugMode" // Bool hidden dev flag
static let onboardingCompletedKey = "fuelboard.onboardingCompleted" // Bool
static let lastRefreshKey = "fuelboard.lastRefresh" // TimeInterval (seconds since 1970)
static let relaySourceKey = "fuelboard.relaySource" // String "api" | "csv"
static let stationCountKey = "fuelboard.stationCount" // String station count
static let dataUpdatedKey = "fuelboard.dataUpdated" // String govUK dataset update time
// MARK: Stations
// The full-UK dataset (~2.9 MB) lives in app-group UserDefaults only
@@ -503,6 +506,34 @@ struct FuelStore {
saveString(String(date.timeIntervalSince1970), service: lastRefreshKey)
}
// MARK: Relay metadata shown in Settings About. Written after each
// successful full fetch so the About section reflects the live source.
static func saveRelayMeta(_ meta: RelayMeta) {
if let source = meta.source {
saveString(source, service: relaySourceKey)
}
if let count = meta.stationCount {
saveString(String(count), service: stationCountKey)
}
if let updated = meta.dataUpdated {
saveString(updated, service: dataUpdatedKey)
}
}
static func loadRelaySource() -> String? {
loadString(service: relaySourceKey)
}
static func loadStationCount() -> Int? {
guard let raw = loadString(service: stationCountKey) else { return nil }
return Int(raw)
}
static func loadDataUpdated() -> String? {
loadString(service: dataUpdatedKey)
}
/// True when the cached data is fresh enough that a scheduled auto-refresh
/// should be skipped (twice-a-day policy).
static var isCacheFresh: Bool {