Settings Debug: device coordinates + in-range station indicator
- Debug section now shows the last device fix (lat/lng to 5dp) and its age. - In-range indicator uses the SAME criteria as live alerts: stations selling the monitored fuel within the alert radius of the fix. Green dot + count when in range, red when none, grey while waiting for a fix. - Shows the cheapest in-range station (name, distance, price). - ProximityMonitor recomputes the snapshot on every location/stations change and on Debug-section appear; ContentView passes the live status. - SettingsView extracted to its own property to keep TabView body within the compiler type-check budget. 35 tests pass.
This commit is contained in:
@@ -4,6 +4,20 @@ import SwiftUI
|
||||
import MapKit
|
||||
import UIKit
|
||||
|
||||
/// Debug-only location snapshot shown in Settings → Debug. Lets the
|
||||
/// developer verify location services while testing: the last fix (with age)
|
||||
/// plus how many stations selling the monitored fuel are within the alert
|
||||
/// radius of that fix — the exact criteria live alerts use.
|
||||
struct DebugLocationStatus: Equatable {
|
||||
var coordinate: Coordinate?
|
||||
var fixAge: TimeInterval?
|
||||
var fuel: FuelType
|
||||
var radiusKM: Double
|
||||
var inRangeCount: Int
|
||||
var cheapestInRange: FuelStation?
|
||||
var cheapestDistanceKM: Double?
|
||||
}
|
||||
|
||||
/// A station the user wants to see on a map — set when a notification tap
|
||||
/// can't hand off to Apple Maps (e.g. inside LiveContainer), so the app shows
|
||||
/// an in-app map with directions instead.
|
||||
@@ -33,6 +47,9 @@ final class ProximityMonitor: NSObject, ObservableObject, @preconcurrency CLLoca
|
||||
@Published var lastAlert: String?
|
||||
@Published private(set) var lastTestResult: String?
|
||||
@Published var pendingStationMap: StationMapRequest?
|
||||
/// Debug-only snapshot for the Settings → Debug section. Recomputed on
|
||||
/// every location/stations change via `refreshDebugStatus()`.
|
||||
@Published private(set) var debugStatus: DebugLocationStatus?
|
||||
|
||||
private let manager = CLLocationManager()
|
||||
private var stations: [FuelStation] = []
|
||||
@@ -76,6 +93,8 @@ final class ProximityMonitor: NSObject, ObservableObject, @preconcurrency CLLoca
|
||||
self.fuel = fuel
|
||||
self.radiusKM = radiusKM
|
||||
|
||||
refreshDebugStatus()
|
||||
|
||||
for region in manager.monitoredRegions {
|
||||
manager.stopMonitoring(for: region)
|
||||
}
|
||||
@@ -128,6 +147,33 @@ final class ProximityMonitor: NSObject, ObservableObject, @preconcurrency CLLoca
|
||||
|
||||
var isEnabled: Bool { enabled }
|
||||
|
||||
/// Recomputes the Settings → Debug location snapshot from current state.
|
||||
/// "In range" uses the SAME criteria as live alerts: stations selling the
|
||||
/// monitored fuel within the alert radius of the last known location.
|
||||
func refreshDebugStatus() {
|
||||
guard let fix = FuelStore.loadLocationWithDate() else {
|
||||
debugStatus = DebugLocationStatus(
|
||||
coordinate: nil, fixAge: nil,
|
||||
fuel: fuel, radiusKM: radiusKM,
|
||||
inRangeCount: 0, cheapestInRange: nil, cheapestDistanceKM: nil)
|
||||
return
|
||||
}
|
||||
let sellers = stations.filter { $0.prices[fuel] != nil }
|
||||
let inRange = sellers.filter {
|
||||
$0.distanceKM(to: fix.coordinate.lat, lng2: fix.coordinate.lng) <= radiusKM
|
||||
}
|
||||
let cheapest = inRange.min { ($0.prices[fuel] ?? .infinity) < ($1.prices[fuel] ?? .infinity) }
|
||||
let cheapestDistance = cheapest.map {
|
||||
$0.distanceKM(to: fix.coordinate.lat, lng2: fix.coordinate.lng)
|
||||
}
|
||||
debugStatus = DebugLocationStatus(
|
||||
coordinate: fix.coordinate,
|
||||
fixAge: Date().timeIntervalSince(fix.date),
|
||||
fuel: fuel, radiusKM: radiusKM,
|
||||
inRangeCount: inRange.count,
|
||||
cheapestInRange: cheapest, cheapestDistanceKM: cheapestDistance)
|
||||
}
|
||||
|
||||
private func requestPermissions() {
|
||||
// Region monitoring needs Always location for background delivery.
|
||||
switch manager.authorizationStatus {
|
||||
|
||||
Reference in New Issue
Block a user