Remove Location status section; add 10/25/50/75/100 station limit picker; refresh location every foreground
This commit is contained in:
+29
-23
@@ -8,6 +8,7 @@ struct ContentView: View {
|
||||
@State private var stations: [FuelStation] = []
|
||||
@State private var selectedFuel: FuelType = FuelStore.loadSelectedFuel()
|
||||
@State private var sortMode: SortMode = FuelStore.loadSortMode()
|
||||
@State private var stationLimit: Int = FuelStore.loadStationLimit()
|
||||
@State private var location: Coordinate? = {
|
||||
if let loc = FuelStore.loadLocation() { return Coordinate(lat: loc.lat, lng: loc.lng) }
|
||||
return nil
|
||||
@@ -20,6 +21,10 @@ struct ContentView: View {
|
||||
stations.compactMap { $0.prices[selectedFuel] }.min()
|
||||
}
|
||||
|
||||
private var displayedStations: [FuelStation] {
|
||||
Array(sortedStations.prefix(stationLimit))
|
||||
}
|
||||
|
||||
private var sortedStations: [FuelStation] {
|
||||
let available = stations.filter { $0.prices[selectedFuel] != nil }
|
||||
switch sortMode {
|
||||
@@ -84,11 +89,11 @@ struct ContentView: View {
|
||||
ProgressView()
|
||||
Text("Fetching prices…")
|
||||
}
|
||||
} else if sortedStations.isEmpty {
|
||||
} else if displayedStations.isEmpty {
|
||||
Text("No \(selectedFuel.displayName) stations found.")
|
||||
.foregroundStyle(.secondary)
|
||||
} else {
|
||||
ForEach(Array(sortedStations.enumerated()), id: \.element.id) { index, station in
|
||||
ForEach(Array(displayedStations.enumerated()), id: \.element.id) { index, station in
|
||||
StationRow(
|
||||
station: station,
|
||||
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") {
|
||||
@@ -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 {
|
||||
Section("Status") {
|
||||
Text(statusMessage)
|
||||
@@ -165,15 +171,15 @@ struct ContentView: View {
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
// Auto-request location on first launch so the widget gets a
|
||||
// fresh fix without the user hunting for the button.
|
||||
if FuelStore.loadLocation() == nil {
|
||||
locationManager.requestUpdate()
|
||||
}
|
||||
// Request a fresh fix on every launch so "Closest" stays
|
||||
// accurate and the widget gets fresh coords.
|
||||
locationManager.requestUpdate()
|
||||
Task { await refresh() }
|
||||
}
|
||||
.onChange(of: scenePhase) { _, newPhase in
|
||||
if newPhase == .active {
|
||||
// Re-request location on foreground too.
|
||||
locationManager.requestUpdate()
|
||||
Task { await refresh() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,6 +103,7 @@ struct FuelStore {
|
||||
static let locationKey = "fuelboard.lastLocation" // "lat,lng,timestamp"
|
||||
static let fuelKey = "fuelboard.selectedFuel" // FuelType raw value
|
||||
static let sortModeKey = "fuelboard.sortMode" // SortMode raw value
|
||||
static let stationLimitKey = "fuelboard.stationLimit" // Int (10/25/50/75/100)
|
||||
|
||||
// MARK: Stations
|
||||
|
||||
@@ -167,6 +168,19 @@ struct FuelStore {
|
||||
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
|
||||
|
||||
private static func keychainData(service: String) -> Data? {
|
||||
|
||||
Reference in New Issue
Block a user