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:
@@ -5,7 +5,7 @@ import WidgetKit
|
|||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
@Environment(\.scenePhase) private var scenePhase
|
@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 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 stationLimit: Int = FuelStore.loadStationLimit()
|
||||||
|
|||||||
@@ -25,12 +25,21 @@ final class ProximityMonitor: NSObject, ObservableObject, @preconcurrency CLLoca
|
|||||||
manager.delegate = self
|
manager.delegate = self
|
||||||
manager.desiredAccuracy = kCLLocationAccuracyHundredMeters
|
manager.desiredAccuracy = kCLLocationAccuracyHundredMeters
|
||||||
manager.pausesLocationUpdatesAutomatically = true
|
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.
|
/// Re-registers geofences. Call whenever stations/favourites/settings change.
|
||||||
func update(stations: [FuelStation], favourites: [FuelStation], fuel: FuelType, radiusKM: Double) {
|
func update(stations: [FuelStation], favourites: [FuelStation], fuel: FuelType, radiusKM: Double) {
|
||||||
self.stations = stations
|
// Fall back to the shared cache when called before the first fetch
|
||||||
self.favourites = favourites
|
// completes (launch, background region-event wake).
|
||||||
|
self.stations = stations.isEmpty ? FuelStore.loadStations() : stations
|
||||||
|
self.favourites = favourites.isEmpty ? FuelStore.loadFavourites() : favourites
|
||||||
self.fuel = fuel
|
self.fuel = fuel
|
||||||
self.radiusKM = radiusKM
|
self.radiusKM = radiusKM
|
||||||
|
|
||||||
@@ -78,6 +87,8 @@ final class ProximityMonitor: NSObject, ObservableObject, @preconcurrency CLLoca
|
|||||||
monitoredStationIDs = []
|
monitoredStationIDs = []
|
||||||
} else {
|
} else {
|
||||||
requestPermissions()
|
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) {
|
private func handleEntry(_ region: CLRegion) {
|
||||||
let stationID = region.identifier
|
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 }
|
guard let station = stations.first(where: { $0.id == stationID }) else { return }
|
||||||
|
|
||||||
// Dedup: one alert per station per hour.
|
// 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]! }),
|
guard let cheapest = withinRadius.min(by: { $0.prices[fuel]! < $1.prices[fuel]! }),
|
||||||
cheapest.id == station.id,
|
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()
|
lastNotified[stationID] = Date()
|
||||||
} catch {
|
} catch {
|
||||||
// Silent — geofence state stays valid for next entry.
|
// Silent — geofence state stays valid for next entry.
|
||||||
|
|||||||
Reference in New Issue
Block a user