diff --git a/FuelBoard/AlertsView.swift b/FuelBoard/AlertsView.swift index 0910886..6ed0fca 100644 --- a/FuelBoard/AlertsView.swift +++ b/FuelBoard/AlertsView.swift @@ -1,11 +1,13 @@ import SwiftUI -/// Alerts tab — enables the cheapest-station proximity alerts and shows what's -/// being monitored. The fuel being monitored is chosen HERE, independently of -/// the Stations-tab selection: users can browse any fuel without re-targeting -/// their alerts (and vice versa). The Live Activity section also lives here — -/// it mirrors this page's shape (toggle + fuel + distance) so the two -/// "notify me while driving" surfaces sit together. +/// Alerts tab — enables the cheapest-station proximity alerts. The fuel being +/// monitored is chosen HERE, independently of the Stations-tab selection: +/// users can browse any fuel without re-targeting their alerts (and vice +/// versa). The Live Activity section also lives here — it mirrors this page's +/// shape (toggle + fuel + distance) so the two "notify me while driving" +/// surfaces sit together. Geofence plumbing (count, 18-limit) lives in +/// Settings → Debug; the user-facing page keeps a plain-language explainer +/// plus a 0-stations hint. struct AlertsView: View { @Binding var enabled: Bool @Binding var radius: Double // stored in km (monitor + storage) @@ -113,34 +115,21 @@ struct AlertsView: View { Text("\(value) \(distanceUnit.label(for: Double(value)))").tag(AlertRadiusChoice.fixed(value)) } } + if enabled && monitoredCount == 0 { + Text("No stations monitored yet — open the Stations tab to load prices first.") + .font(.caption) + .foregroundStyle(.secondary) + } } header: { Text("Cheapest-station alerts") } footer: { - Text("When you approach a station that is the cheapest within the radius, FuelBoard sends a notification — even with the app closed. Alerts watch for the cheapest \\(fuel.displayName.lowercased()) station within the radius. Follow search mirrors the Stations-tab distance, capped at 8 miles for reliable geofencing.") + Text("When you approach a station that is the cheapest within the radius, FuelBoard sends a notification — even with the app closed. Nearby stations selling \(fuel.displayName.lowercased()) are watched — favourites get priority — and each station alerts at most once per hour. Follow search mirrors the Stations-tab distance, capped at 8 miles for reliable geofencing.") } - if enabled { - Section("Monitoring") { - if monitoredCount == 0 { - Text("No stations monitored yet — open the Stations tab to load prices first.") - .font(.caption) - .foregroundStyle(.secondary) - } else { - LabeledContent("Geofenced stations", value: "\(monitoredCount)") - Text("Your favourites for \(fuel.displayName.lowercased()) get priority, then the closest stations selling that fuel fill the rest (18 max, iOS region limit).") - .font(.caption) - .foregroundStyle(.secondary) - Text("Alerts are checked against the cheapest station within the trigger radius for the fuel chosen above. Each station alerts at most once per hour.") - .font(.caption) - .foregroundStyle(.secondary) - } - } - - if let lastAlert { - Section("Last alert") { - Label(lastAlert, systemImage: "bell.badge.fill") - .font(.footnote) - } + if enabled, let lastAlert { + Section("Last alert") { + Label(lastAlert, systemImage: "bell.badge.fill") + .font(.footnote) } } diff --git a/FuelBoard/ContentView.swift b/FuelBoard/ContentView.swift index af9b442..16b163d 100644 --- a/FuelBoard/ContentView.swift +++ b/FuelBoard/ContentView.swift @@ -376,7 +376,8 @@ struct ContentView: View { onShowOnboarding: { showOnboarding = true }, debugStatus: monitor.debugStatus, appCheapest: appCheapestStatus, - regionError: monitor.lastRegionError + regionError: monitor.lastRegionError, + monitoredCount: monitor.monitoredStationIDs.count ) .tabItem { Label("Settings", systemImage: "gearshape.fill") } } diff --git a/FuelBoard/SettingsView.swift b/FuelBoard/SettingsView.swift index 68613e9..420c043 100644 --- a/FuelBoard/SettingsView.swift +++ b/FuelBoard/SettingsView.swift @@ -37,6 +37,9 @@ struct SettingsView: View { /// Last CoreLocation region-monitoring failure (monitor.lastRegionError). /// Shown in Debug so a silently-failed geofence registration is visible. var regionError: String? + /// Live geofence count (monitor.monitoredStationIDs.count) — Debug-only + /// status; the user-facing Alerts tab no longer exposes fence plumbing. + var monitoredCount: Int = 0 @StateObject private var tipStore = TipStore() @State private var showTipAlert = false @@ -199,6 +202,21 @@ struct SettingsView: View { } footer: { Text("Connection shows whether prices come from the official Fuel Finder API or the CSV mirror. Data updated is the latest price change reported by the GOV.UK server itself.") } + + Section { + if monitoredCount == 0 { + Text("No stations monitored yet — open the Stations tab to load prices first.") + .font(.caption) + .foregroundStyle(.secondary) + } else { + LabeledContent("Geofenced stations", value: "\(monitoredCount)") + } + Text("Favourites for \(alertsFuel.displayName.lowercased()) get priority, then the closest stations selling that fuel fill the rest (18 max, iOS region limit). Each station alerts at most once per hour.") + .font(.caption) + .foregroundStyle(.secondary) + } header: { + Text("Geofence monitoring") + } } Section {