Live Activity: cheapest-in-radius Lock Screen/Dynamic Island pill

- Shared FuelBoardLiveActivityAttributes/ContentState (app + widget targets)
- FuelBoardLiveActivity Widget: ActivityConfiguration rendered by the widget
  extension - Lock Screen banner + Dynamic Island (leading/trailing/bottom,
  compact, minimal), tap anywhere -> maps:// directions to the best station
- LiveActivityManager (app side): request/update/end; mirrors the app list's
  TOP badge (selected fuel + chosen distance radius, price-then-distance
  ties); local start-date tracking for the 8h cap (this SDK's Activity has no
  startDate) - auto-restarts at 7h59m; silent no-op when disabled/denied
- Wiring: 250m/60s location hook (incl. background significant-change
  wake-ups), refresh completion, fuel/radius/unit changes, toggle flip
- Settings toggle + FuelStore persistence (keychain-backed, app-group)
- App-Info.plist: NSSupportsLiveActivities
This commit is contained in:
Ade Thompson
2026-08-12 20:11:27 +01:00
parent 1dcd47c6cd
commit c362d562d7
8 changed files with 362 additions and 0 deletions
+11
View File
@@ -262,6 +262,7 @@ struct FuelStore {
static let alertsRadiusKey = "fuelboard.alertsRadius" // Double km
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 onboardingCompletedKey = "fuelboard.onboardingCompleted" // Bool
static let lastRefreshKey = "fuelboard.lastRefresh" // TimeInterval (seconds since 1970)
static let relaySourceKey = "fuelboard.relaySource" // String "api" | "csv"
@@ -490,6 +491,16 @@ struct FuelStore {
saveString(String(radius), service: alertsRadiusKey)
}
// MARK: Live Activity
static func loadLiveActivityEnabled() -> Bool {
loadString(service: liveActivityKey) == "1"
}
static func saveLiveActivityEnabled(_ enabled: Bool) {
saveString(enabled ? "1" : "0", service: liveActivityKey)
}
// MARK: Refresh policy data is cached; the app only auto-refreshes
// twice a day (pull-to-refresh is the manual override).