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:
@@ -121,6 +121,33 @@ struct SettingsView: View {
|
||||
Text("A small tip helps keep the data relay and app development going. Thank you!")
|
||||
}
|
||||
|
||||
Section {
|
||||
HStack {
|
||||
Text("Connection")
|
||||
Spacer()
|
||||
Text(connectionText)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
HStack {
|
||||
Text("Stations")
|
||||
Spacer()
|
||||
Text(stationCountText)
|
||||
.foregroundStyle(.secondary)
|
||||
.monospacedDigit()
|
||||
}
|
||||
HStack {
|
||||
Text("Data updated")
|
||||
Spacer()
|
||||
Text(dataUpdatedText)
|
||||
.foregroundStyle(.secondary)
|
||||
.monospacedDigit()
|
||||
}
|
||||
} header: {
|
||||
Text("Data source")
|
||||
} footer: {
|
||||
Text("Connection shows whether prices come from the official Fuel Finder API or the CSV mirror. Data updated is the latest price change reported by the GOV.UK server itself.")
|
||||
}
|
||||
|
||||
Section {
|
||||
HStack {
|
||||
Text("Version")
|
||||
@@ -252,6 +279,40 @@ struct SettingsView: View {
|
||||
return "\(version) (\(build))"
|
||||
}
|
||||
|
||||
/// "API" when the relay is serving the official Fuel Finder API, "CSV"
|
||||
/// when it fell back to the public mirror, "—" when unknown/never fetched.
|
||||
private var connectionText: String {
|
||||
switch FuelStore.loadRelaySource()?.lowercased() {
|
||||
case "api": return "API"
|
||||
case "csv": return "CSV"
|
||||
default: return "—"
|
||||
}
|
||||
}
|
||||
|
||||
private var stationCountText: String {
|
||||
guard let count = FuelStore.loadStationCount() else { return "—" }
|
||||
return count.formatted()
|
||||
}
|
||||
|
||||
/// GOV.UK server's own dataset update timestamp (ISO 8601 from the API,
|
||||
/// e.g. 2026-08-12T10:23:00.000Z). Shown as a local date/time — it is the
|
||||
/// data's own freshness, not the relay's sync time.
|
||||
private var dataUpdatedText: String {
|
||||
guard let raw = FuelStore.loadDataUpdated(), !raw.isEmpty else { return "—" }
|
||||
let iso = ISO8601DateFormatter()
|
||||
iso.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
|
||||
if let date = iso.date(from: raw) {
|
||||
return date.formatted(date: .abbreviated, time: .shortened)
|
||||
}
|
||||
// Some sources send "YYYY-MM-DDTHH:MM:SS" without fractional seconds
|
||||
// or timezone — try the plain form before showing the raw string.
|
||||
iso.formatOptions = [.withInternetDateTime]
|
||||
if let date = iso.date(from: raw) {
|
||||
return date.formatted(date: .abbreviated, time: .shortened)
|
||||
}
|
||||
return raw
|
||||
}
|
||||
|
||||
/// Hidden debug-mode toggle: five taps on the Version row flips the flag.
|
||||
/// Nothing in the UI advertises this — the Debug section simply appears or
|
||||
/// disappears. Deliberately NOT a visible switch so end users never see it.
|
||||
|
||||
Reference in New Issue
Block a user