Preload cached stations at launch (all tabs populate instantly); alert handler falls back to cache on background wake, restores enabled/fuel/radius in monitor init, re-registers geofences on setEnabled

This commit is contained in:
FuelBoard Contributor
2026-08-11 16:50:45 +01:00
parent c5050df445
commit e8a82ce515
2 changed files with 19 additions and 5 deletions
+1 -1
View File
@@ -5,7 +5,7 @@ import WidgetKit
struct ContentView: View {
@Environment(\.scenePhase) private var scenePhase
@State private var stations: [FuelStation] = []
@State private var stations: [FuelStation] = FuelStore.loadStations()
@State private var selectedFuel: FuelType = FuelStore.loadSelectedFuel()
@State private var sortMode: SortMode = FuelStore.loadSortMode()
@State private var stationLimit: Int = FuelStore.loadStationLimit()
+18 -4
View File
@@ -25,12 +25,21 @@ final class ProximityMonitor: NSObject, ObservableObject, @preconcurrency CLLoca
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyHundredMeters
manager.pausesLocationUpdatesAutomatically = true
// Restore persisted state on background relaunch so region events work
// even before the view fully appears.
enabled = FuelStore.loadAlertsEnabled()
fuel = FuelStore.loadSelectedFuel()
radiusKM = FuelStore.loadAlertsRadius()
stations = FuelStore.loadStations()
favourites = FuelStore.loadFavourites()
}
/// Re-registers geofences. Call whenever stations/favourites/settings change.
func update(stations: [FuelStation], favourites: [FuelStation], fuel: FuelType, radiusKM: Double) {
self.stations = stations
self.favourites = favourites
// Fall back to the shared cache when called before the first fetch
// completes (launch, background region-event wake).
self.stations = stations.isEmpty ? FuelStore.loadStations() : stations
self.favourites = favourites.isEmpty ? FuelStore.loadFavourites() : favourites
self.fuel = fuel
self.radiusKM = radiusKM
@@ -78,6 +87,8 @@ final class ProximityMonitor: NSObject, ObservableObject, @preconcurrency CLLoca
monitoredStationIDs = []
} else {
requestPermissions()
// Re-register geofences from restored cache immediately.
update(stations: stations, favourites: favourites, fuel: fuel, radiusKM: radiusKM)
}
}
@@ -111,6 +122,9 @@ final class ProximityMonitor: NSObject, ObservableObject, @preconcurrency CLLoca
private func handleEntry(_ region: CLRegion) {
let stationID = region.identifier
// Fall back to cached data on background wake (stations may not be
// fetched yet when the app is relaunched by a region event).
if stations.isEmpty { stations = FuelStore.loadStations() }
guard let station = stations.first(where: { $0.id == stationID }) else { return }
// Dedup: one alert per station per hour.
@@ -128,9 +142,9 @@ final class ProximityMonitor: NSObject, ObservableObject, @preconcurrency CLLoca
}
guard let cheapest = withinRadius.min(by: { $0.prices[fuel]! < $1.prices[fuel]! }),
cheapest.id == station.id,
let price = station.prices[fuel] else { return }
let price = cheapest.prices[fuel] else { return }
fireAlert(for: station, price: price)
fireAlert(for: cheapest, price: price)
lastNotified[stationID] = Date()
} catch {
// Silent geofence state stays valid for next entry.