Remove Location status section; add 10/25/50/75/100 station limit picker; refresh location every foreground

This commit is contained in:
FuelBoard Contributor
2026-08-11 14:41:39 +01:00
parent 7304d99fd8
commit acb5c33578
2 changed files with 43 additions and 23 deletions
+29 -23
View File
@@ -8,6 +8,7 @@ struct ContentView: View {
@State private var stations: [FuelStation] = [] @State private var stations: [FuelStation] = []
@State private var selectedFuel: FuelType = FuelStore.loadSelectedFuel() @State private var selectedFuel: FuelType = FuelStore.loadSelectedFuel()
@State private var sortMode: SortMode = FuelStore.loadSortMode() @State private var sortMode: SortMode = FuelStore.loadSortMode()
@State private var stationLimit: Int = FuelStore.loadStationLimit()
@State private var location: Coordinate? = { @State private var location: Coordinate? = {
if let loc = FuelStore.loadLocation() { return Coordinate(lat: loc.lat, lng: loc.lng) } if let loc = FuelStore.loadLocation() { return Coordinate(lat: loc.lat, lng: loc.lng) }
return nil return nil
@@ -20,6 +21,10 @@ struct ContentView: View {
stations.compactMap { $0.prices[selectedFuel] }.min() stations.compactMap { $0.prices[selectedFuel] }.min()
} }
private var displayedStations: [FuelStation] {
Array(sortedStations.prefix(stationLimit))
}
private var sortedStations: [FuelStation] { private var sortedStations: [FuelStation] {
let available = stations.filter { $0.prices[selectedFuel] != nil } let available = stations.filter { $0.prices[selectedFuel] != nil }
switch sortMode { switch sortMode {
@@ -84,11 +89,11 @@ struct ContentView: View {
ProgressView() ProgressView()
Text("Fetching prices…") Text("Fetching prices…")
} }
} else if sortedStations.isEmpty { } else if displayedStations.isEmpty {
Text("No \(selectedFuel.displayName) stations found.") Text("No \(selectedFuel.displayName) stations found.")
.foregroundStyle(.secondary) .foregroundStyle(.secondary)
} else { } else {
ForEach(Array(sortedStations.enumerated()), id: \.element.id) { index, station in ForEach(Array(displayedStations.enumerated()), id: \.element.id) { index, station in
StationRow( StationRow(
station: station, station: station,
fuel: selectedFuel, fuel: selectedFuel,
@@ -98,6 +103,23 @@ struct ContentView: View {
) )
} }
} }
if !displayedStations.isEmpty {
Divider()
Picker("Show", selection: $stationLimit) {
ForEach([10, 25, 50, 75, 100], id: \.self) { count in
Text("\(count)").tag(count)
}
}
.pickerStyle(.segmented)
.onChange(of: stationLimit) { _, newValue in
FuelStore.saveStationLimit(newValue)
}
.padding(.vertical, 2)
Text("Showing \(displayedStations.count) of \(sortedStations.count) stations")
.font(.caption2)
.foregroundStyle(.secondary)
}
} }
Section("Key") { Section("Key") {
@@ -128,22 +150,6 @@ struct ContentView: View {
} }
} }
Section("Location") {
if let location {
Text("Using location \(String(format: "%.4f, %.4f", location.lat, location.lng))")
.font(.caption)
.foregroundStyle(.secondary)
} else {
Text("No location yet — allow location access to sort by distance.")
.font(.caption)
.foregroundStyle(.secondary)
}
Button("Update my location") {
locationManager.requestUpdate()
}
.font(.footnote)
}
if !statusMessage.isEmpty { if !statusMessage.isEmpty {
Section("Status") { Section("Status") {
Text(statusMessage) Text(statusMessage)
@@ -165,15 +171,15 @@ struct ContentView: View {
} }
} }
.onAppear { .onAppear {
// Auto-request location on first launch so the widget gets a // Request a fresh fix on every launch so "Closest" stays
// fresh fix without the user hunting for the button. // accurate and the widget gets fresh coords.
if FuelStore.loadLocation() == nil { locationManager.requestUpdate()
locationManager.requestUpdate()
}
Task { await refresh() } Task { await refresh() }
} }
.onChange(of: scenePhase) { _, newPhase in .onChange(of: scenePhase) { _, newPhase in
if newPhase == .active { if newPhase == .active {
// Re-request location on foreground too.
locationManager.requestUpdate()
Task { await refresh() } Task { await refresh() }
} }
} }
+14
View File
@@ -103,6 +103,7 @@ struct FuelStore {
static let locationKey = "fuelboard.lastLocation" // "lat,lng,timestamp" static let locationKey = "fuelboard.lastLocation" // "lat,lng,timestamp"
static let fuelKey = "fuelboard.selectedFuel" // FuelType raw value static let fuelKey = "fuelboard.selectedFuel" // FuelType raw value
static let sortModeKey = "fuelboard.sortMode" // SortMode raw value static let sortModeKey = "fuelboard.sortMode" // SortMode raw value
static let stationLimitKey = "fuelboard.stationLimit" // Int (10/25/50/75/100)
// MARK: Stations // MARK: Stations
@@ -167,6 +168,19 @@ struct FuelStore {
saveString(mode.rawValue, service: sortModeKey) saveString(mode.rawValue, service: sortModeKey)
} }
// MARK: Station count limit
static func loadStationLimit() -> Int {
if let raw = loadString(service: stationLimitKey), let value = Int(raw), [10, 25, 50, 75, 100].contains(value) {
return value
}
return 25
}
static func saveStationLimit(_ limit: Int) {
saveString(String(limit), service: stationLimitKey)
}
// MARK: Low-level keychain helpers // MARK: Low-level keychain helpers
private static func keychainData(service: String) -> Data? { private static func keychainData(service: String) -> Data? {