Favourites are fuel-scoped: starring pins the station for one fuel only

Fixing the bug where favouriting an Unleaded entry also created a Diesel
favourite. Favourites are now [FavouriteEntry] = (station, fuel) pairs:
- Starring a row pins it only for the fuel being viewed
- Favourites tabs show only fuels that actually have favourites
- Geofence monitor gives priority slots only to favourites matching the
  monitored fuel
- Tests updated + new fuel-scoping test (31/31 passing)
This commit is contained in:
FuelBoard Contributor
2026-08-12 08:31:08 +01:00
parent 0dbf88ee7d
commit 35e0adaf0b
6 changed files with 88 additions and 54 deletions
+12 -6
View File
@@ -31,15 +31,20 @@ final class ProximityMonitor: NSObject, ObservableObject, @preconcurrency CLLoca
fuel = FuelStore.loadSelectedFuel()
radiusKM = FuelStore.loadAlertsRadius()
stations = FuelStore.loadStations()
favourites = FuelStore.loadFavourites()
favourites = FuelStore.loadFavourites().filter { $0.fuel == fuel }.map(\.station)
}
/// Re-registers geofences. Call whenever stations/favourites/settings change.
func update(stations: [FuelStation], favourites: [FuelStation], fuel: FuelType, radiusKM: Double) {
/// Favourites are fuel-scoped entries; only entries for the monitored fuel
/// get priority slots (a Diesel favourite must not grab a slot while
/// monitoring Unleaded).
func update(stations: [FuelStation], favourites: [FavouriteEntry], fuel: FuelType, radiusKM: Double) {
// 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.favourites = favourites.isEmpty
? FuelStore.loadFavourites().filter { $0.fuel == fuel }.map(\.station)
: favourites.filter { $0.fuel == fuel }.map(\.station)
self.fuel = fuel
self.radiusKM = radiusKM
@@ -51,8 +56,9 @@ final class ProximityMonitor: NSObject, ObservableObject, @preconcurrency CLLoca
guard enabled else { return }
// Favourites first (guaranteed slots), then closest stations, max 18.
var candidates: [FuelStation] = favourites
let favIDs = Set(favourites.map(\.id))
// `self.favourites` is already filtered to the monitored fuel.
var candidates: [FuelStation] = self.favourites
let favIDs = Set(self.favourites.map(\.id))
let location = FuelStore.loadLocation()
let others = stations
.filter { !favIDs.contains($0.id) }
@@ -88,7 +94,7 @@ final class ProximityMonitor: NSObject, ObservableObject, @preconcurrency CLLoca
} else {
requestPermissions()
// Re-register geofences from restored cache immediately.
update(stations: stations, favourites: favourites, fuel: fuel, radiusKM: radiusKM)
update(stations: stations, favourites: FuelStore.loadFavourites(), fuel: fuel, radiusKM: radiusKM)
}
}