Live Activity: own fuel + distance config, independent of Stations tab

- Settings → Live Activity now has Fuel and Distance pickers (5/10/15,
  unit-aware) stored under fuelboard.liveActivityFuel / liveActivityRadiusMiles
- LiveActivityManager uses these instead of the Stations-tab selectedFuel /
  stationLimit; Stations changes no longer re-target the pill
- Fuel moved from Activity attributes into ContentState so changing fuel in
  Settings updates the RUNNING activity in place (no end+restart needed)
- Stations tab stays a pure data-interrogation + favourites surface
This commit is contained in:
FuelBoard Contributor
2026-08-12 20:58:05 +01:00
parent 04b233bf9a
commit fcb83f1eed
6 changed files with 82 additions and 20 deletions
+9 -8
View File
@@ -5,20 +5,21 @@
// is deliberately NOT symlinked into FuelBoardTests/Sources the SPM test
// target runs on macOS where ActivityKit does not exist.
//
// The activity mirrors the app's TOP badge: the cheapest station selling the
// app's selected fuel within the app's chosen distance radius. Tapping the
// activity opens Apple Maps driving directions to that station (maps://).
// The activity tracks the cheapest station for the fuel + radius configured
// in Settings Live Activity (INDEPENDENT of the Stations-tab selection).
// Everything dynamic lives in ContentState so updates including a fuel
// change apply to the running activity without needing to restart it.
// Tapping the activity opens Apple Maps driving directions (maps://).
import ActivityKit
import Foundation
/// Attributes are fixed at request time. Here they pin the FUEL being
/// tracked; everything that can change while driving (station, price,
/// distance) lives in ContentState so updates don't need a new activity.
/// Attributes are fixed at request time. Kept empty: the fuel itself lives in
/// ContentState so a fuel change in Settings updates the running activity
/// in place instead of requiring an end + restart.
struct FuelBoardLiveActivityAttributes: ActivityAttributes {
var fuel: FuelType
public struct ContentState: Codable, Hashable {
var fuel: FuelType
var stationID: String
var stationName: String
var brand: String
+28
View File
@@ -263,6 +263,8 @@ struct FuelStore {
static let alertsFuelKey = "fuelboard.alertsFuel" // FuelType raw value
static let debugModeKey = "fuelboard.debugMode" // Bool hidden dev flag
static let liveActivityKey = "fuelboard.liveActivity" // Bool Live Activity toggle
static let liveActivityFuelKey = "fuelboard.liveActivityFuel" // FuelType raw value
static let liveActivityRadiusKey = "fuelboard.liveActivityRadiusMiles" // Int miles (5/10/15)
static let onboardingCompletedKey = "fuelboard.onboardingCompleted" // Bool
static let lastRefreshKey = "fuelboard.lastRefresh" // TimeInterval (seconds since 1970)
static let relaySourceKey = "fuelboard.relaySource" // String "api" | "csv"
@@ -501,6 +503,32 @@ struct FuelStore {
saveString(enabled ? "1" : "0", service: liveActivityKey)
}
/// The fuel the Live Activity tracks independent of the Stations-tab
/// selection so the Lock Screen pill keeps its own target.
static func loadLiveActivityFuel() -> FuelType {
if let raw = loadString(service: liveActivityFuelKey), let fuel = FuelType(rawValue: raw) {
return fuel
}
return .e10
}
static func saveLiveActivityFuel(_ fuel: FuelType) {
saveString(fuel.rawValue, service: liveActivityFuelKey)
}
/// The Live Activity's search radius in miles (5/10/15), converted to the
/// chosen unit at use same options as the Stations list.
static func loadLiveActivityRadiusMiles() -> Int {
if let raw = loadString(service: liveActivityRadiusKey), let value = Int(raw), stationRadiusOptions.contains(value) {
return value
}
return 5
}
static func saveLiveActivityRadiusMiles(_ miles: Int) {
saveString(String(miles), service: liveActivityRadiusKey)
}
// MARK: Refresh policy data is cached; the app only auto-refreshes
// twice a day (pull-to-refresh is the manual override).