Live-test fixes: CarPlay disfavor, widget location refresh, debug cheapest parity
1. CarPlay widget taps could never launch Maps — FuelBoard is not a CarPlay app, and Apple only lets a widget launch its own app in CarPlay when that app is CarPlay-enabled. Marked the widget as a disfavored CarPlay location (iOS 26+; no-op below): read-only in the car, no dead tap. Header comment updated to match reality. 2. Widgets now track the user's location: timeline refresh 15m -> 5m, and the app's location manager reloads all widget timelines after every significant move (250m filter, throttled to 60s), so the widget re-orders around the new position while driving instead of waiting for the next tick. 3. Debug 'Cheapest in range' no longer shows the ALERT prediction (alertsFuel + alert radius — a different pool by design). It now mirrors the app list exactly: the TOP-badge station for the selected fuel within the stationLimit radius (new DebugAppCheapest computed in ContentView, passed to Settings). Alert-prediction cheapest kept as fallback when the app view hasn't resolved.
This commit is contained in:
@@ -67,6 +67,24 @@ struct ContentView: View {
|
||||
return displayedStations.first { $0.prices[selectedFuel] == baselinePrice }?.id
|
||||
}
|
||||
|
||||
/// The app's own "cheapest in range" — the TOP-badge station — mirrored
|
||||
/// into the Settings → Debug section so its "Cheapest in range" row
|
||||
/// matches the app list (and the widget when the widget's fuel + distance
|
||||
/// match the app's). The debug section previously showed the ALERT
|
||||
/// prediction (alertsFuel + alert radius), which is a different pool by
|
||||
/// design — that mismatch is what this fixes.
|
||||
private var appCheapestStatus: DebugAppCheapest? {
|
||||
guard let topID = topStationID,
|
||||
let station = stations.first(where: { $0.id == topID }),
|
||||
let location else { return nil }
|
||||
return DebugAppCheapest(
|
||||
station: station,
|
||||
fuel: selectedFuel,
|
||||
radiusKM: distanceUnit.toKM(Double(stationLimit)),
|
||||
distanceKM: station.distanceKM(to: location.lat, lng2: location.lng)
|
||||
)
|
||||
}
|
||||
|
||||
private var displayedStations: [FuelStation] {
|
||||
sortedStations
|
||||
}
|
||||
@@ -258,7 +276,8 @@ struct ContentView: View {
|
||||
onPlainTestAlert: { monitor.sendPlainTestNotification() },
|
||||
onRefreshDebugStatus: { monitor.refreshDebugStatus() },
|
||||
onShowOnboarding: { showOnboarding = true },
|
||||
debugStatus: monitor.debugStatus
|
||||
debugStatus: monitor.debugStatus,
|
||||
appCheapest: appCheapestStatus
|
||||
)
|
||||
.tabItem { Label("Settings", systemImage: "gearshape.fill") }
|
||||
}
|
||||
@@ -494,8 +513,19 @@ final class LocationManager: NSObject, ObservableObject, @preconcurrency CLLocat
|
||||
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
|
||||
guard let loc = locations.last else { return }
|
||||
current = Coordinate(lat: loc.coordinate.latitude, lng: loc.coordinate.longitude)
|
||||
// Drive the widget: every significant move re-orders the widget list
|
||||
// around the new position immediately, instead of waiting for the
|
||||
// widget's own 5-minute timeline tick. Throttled — WidgetKit ignores
|
||||
// reload spam and the relay has a rate limit, so 60 s is plenty.
|
||||
let now = Date()
|
||||
if now.timeIntervalSince(lastWidgetReload) >= 60 {
|
||||
lastWidgetReload = now
|
||||
WidgetCenter.shared.reloadAllTimelines()
|
||||
}
|
||||
}
|
||||
|
||||
private var lastWidgetReload = Date.distantPast
|
||||
|
||||
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
|
||||
// Ignore — the app still works price-sorted without location.
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user