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:
@@ -41,6 +41,21 @@ enum FuelPriceProvider {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Decodes the relay envelope metadata (source, dataset update time) — the
|
||||
/// About section shows these so the user can see which data source is
|
||||
/// live and how fresh the GOV.UK data itself is. The fields are additive
|
||||
/// on the relay, so older relays simply return nil values.
|
||||
static func decodeRelayMeta(from data: Data) -> RelayMeta? {
|
||||
guard let payload = try? JSONDecoder().decode(RelayResponse.self, from: data) else {
|
||||
return nil
|
||||
}
|
||||
return RelayMeta(
|
||||
source: payload.source,
|
||||
stationCount: payload.stationsCount,
|
||||
dataUpdated: payload.dataUpdated
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Relay provider (default)
|
||||
@@ -51,6 +66,11 @@ enum FuelPriceProvider {
|
||||
struct RelayFuelProvider: FuelPriceProviding {
|
||||
var baseURL = URL(string: "http://192.168.1.131:8789")!
|
||||
|
||||
/// Envelope metadata from the most recent successful relay fetch —
|
||||
/// consumed by Settings → About (source api/csv, station count, GOV.UK
|
||||
/// dataset update time). Written by fetchStations, read by the view.
|
||||
static var latestMeta: RelayMeta?
|
||||
|
||||
func fetchStations(near lat: Double?, lng: Double?, fuel: FuelType, radiusKM: Double?) async throws -> [FuelStation] {
|
||||
var components = URLComponents(url: baseURL.appendingPathComponent("api/v1/stations"), resolvingAgainstBaseURL: false)!
|
||||
var query: [URLQueryItem] = [URLQueryItem(name: "fuel", value: fuel.rawValue)]
|
||||
@@ -73,11 +93,25 @@ struct RelayFuelProvider: FuelPriceProviding {
|
||||
guard let http = response as? HTTPURLResponse, http.statusCode == 200 else {
|
||||
throw FuelProviderError.relayUnavailable
|
||||
}
|
||||
return try FuelPriceProvider.decodeStations(from: data)
|
||||
let stations = try FuelPriceProvider.decodeStations(from: data)
|
||||
Self.latestMeta = FuelPriceProvider.decodeRelayMeta(from: data)
|
||||
return stations
|
||||
}
|
||||
}
|
||||
|
||||
private struct RelayResponse: Codable {
|
||||
/// Envelope metadata surfaced in Settings → About so the user can see
|
||||
/// which relay source is live and how fresh the GOV.UK data is.
|
||||
let source: String?
|
||||
let stationsCount: Int?
|
||||
let dataUpdated: String?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case source, stations
|
||||
case stationsCount = "stations_count"
|
||||
case dataUpdated = "data_updated"
|
||||
}
|
||||
|
||||
struct RelayStation: Codable {
|
||||
let id: String?
|
||||
let name: String?
|
||||
@@ -117,6 +151,15 @@ private struct RelayResponse: Codable {
|
||||
let stations: [RelayStation]
|
||||
}
|
||||
|
||||
/// Envelope metadata from the relay response — which data source is live
|
||||
/// (api/csv) and the freshest price-update timestamp the GOV.UK server
|
||||
/// itself reports for the dataset. Displayed in Settings → About.
|
||||
struct RelayMeta: Codable, Equatable {
|
||||
let source: String?
|
||||
let stationCount: Int?
|
||||
let dataUpdated: String?
|
||||
}
|
||||
|
||||
// MARK: - Sample provider (offline fallback only)
|
||||
|
||||
/// Representative stations spread across ENGLAND (one cluster per region) so
|
||||
|
||||
Reference in New Issue
Block a user