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:
+28
-17
@@ -17,6 +17,16 @@ struct Coordinate: Equatable, Codable {
|
||||
let lng: Double
|
||||
}
|
||||
|
||||
/// A favourite = a station pinned for ONE fuel type. Starring a row while
|
||||
/// viewing Unleaded only creates an Unleaded favourite, so the same station
|
||||
/// can be favourite for Diesel independently (or not at all).
|
||||
struct FavouriteEntry: Identifiable, Codable, Equatable {
|
||||
var station: FuelStation
|
||||
let fuel: FuelType
|
||||
|
||||
var id: String { "\(fuel.rawValue)|\(station.id)" }
|
||||
}
|
||||
|
||||
enum SortMode: String, Codable, CaseIterable, Identifiable {
|
||||
case cheapest
|
||||
case closest
|
||||
@@ -234,7 +244,7 @@ struct FuelStore {
|
||||
static let sortModeKey = "fuelboard.sortMode" // SortMode raw value
|
||||
static let stationLimitKey = "fuelboard.stationLimitMiles" // Int miles (5/10/15)
|
||||
static let distanceUnitKey = "fuelboard.distanceUnit" // DistanceUnit raw value
|
||||
static let favouritesKey = "fuelboard.favourites" // [FuelStation] JSON
|
||||
static let favouritesKey = "fuelboard.favourites" // [FavouriteEntry] JSON
|
||||
static let alertsEnabledKey = "fuelboard.alertsEnabled" // Bool
|
||||
static let alertsRadiusKey = "fuelboard.alertsRadius" // Double km
|
||||
static let onboardingCompletedKey = "fuelboard.onboardingCompleted" // Bool
|
||||
@@ -348,24 +358,27 @@ struct FuelStore {
|
||||
|
||||
// MARK: Favourites
|
||||
|
||||
static func loadFavourites() -> [FuelStation] {
|
||||
/// A favourite pins a station FOR ONE fuel type. Starring a row while
|
||||
/// viewing Unleaded only creates an Unleaded favourite — the station is
|
||||
/// not automatically favourited for Premium or Diesel.
|
||||
static func loadFavourites() -> [FavouriteEntry] {
|
||||
if let data = keychainData(service: favouritesKey),
|
||||
let favs = try? JSONDecoder().decode([FuelStation].self, from: data) {
|
||||
return favs.map { fav in
|
||||
var f = fav
|
||||
f.name = fav.name.sanitizedStationTitle
|
||||
return f
|
||||
let entries = try? JSONDecoder().decode([FavouriteEntry].self, from: data) {
|
||||
return entries.map { entry in
|
||||
var e = entry
|
||||
e.station.name = entry.station.name.sanitizedStationTitle
|
||||
return e
|
||||
}
|
||||
}
|
||||
if let defaults = UserDefaults(suiteName: appGroupSuite),
|
||||
let data = defaults.data(forKey: favouritesKey),
|
||||
let favs = try? JSONDecoder().decode([FuelStation].self, from: data) {
|
||||
return favs
|
||||
let entries = try? JSONDecoder().decode([FavouriteEntry].self, from: data) {
|
||||
return entries
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
static func saveFavourites(_ favourites: [FuelStation]) {
|
||||
static func saveFavourites(_ favourites: [FavouriteEntry]) {
|
||||
if let data = try? JSONEncoder().encode(favourites) {
|
||||
UserDefaults(suiteName: appGroupSuite)?.set(data, forKey: favouritesKey)
|
||||
writeKeychain(data: data, service: favouritesKey)
|
||||
@@ -374,14 +387,12 @@ struct FuelStore {
|
||||
|
||||
/// Returns favourites with fresh prices applied from the given station list
|
||||
/// (favourites keep their cached snapshot when not in the current results).
|
||||
static func refreshedFavourites(_ favourites: [FuelStation], from stations: [FuelStation]) -> [FuelStation] {
|
||||
var updated = favourites
|
||||
for (i, fav) in favourites.enumerated() {
|
||||
if let fresh = stations.first(where: { $0.id == fav.id }) {
|
||||
updated[i] = fresh
|
||||
}
|
||||
/// The fuel scoping is preserved per entry.
|
||||
static func refreshedFavourites(_ favourites: [FavouriteEntry], from stations: [FuelStation]) -> [FavouriteEntry] {
|
||||
favourites.map { entry in
|
||||
guard let fresh = stations.first(where: { $0.id == entry.station.id }) else { return entry }
|
||||
return FavouriteEntry(station: fresh, fuel: entry.fuel)
|
||||
}
|
||||
return updated
|
||||
}
|
||||
|
||||
// MARK: Alerts
|
||||
|
||||
Reference in New Issue
Block a user