Onboarding: prompt permissions in context + data page

Location and network fetches no longer fire at launch before onboarding
reaches the relevant step: foreground tracking and the first refresh are
gated behind onboarding completion (scenePhase no longer starts tracking
while the cover is up, and onAppear defers its fetch until after
finish). A new Data page sits just before 'You're all set': it probes
the FuelBoard Relay, which surfaces the iOS Local Network permission
prompt in context (NSLocalNetworkUsageDescription added), verifies
connectivity, and offers Open Settings/Check again on denial. Onboarding
is now 5 pages: Welcome, Location, Notifications, Data, Done. 35 tests
pass.
This commit is contained in:
FuelBoard Contributor
2026-08-12 11:59:07 +01:00
parent 002d7f63e2
commit 20589f41fe
3 changed files with 143 additions and 15 deletions
+20 -8
View File
@@ -165,28 +165,40 @@ struct ContentView: View {
}
.onAppear {
// Onboarding runs first on a fresh install it owns the initial
// permission prompts. Location tracking starts once it's done.
// permission prompts (location, notifications, and the data/local
// network probe on the Data page). Location tracking and the first
// network fetch start once it's done.
if FuelStore.loadHasCompletedOnboarding() {
locationManager.startForegroundTracking()
monitor.update(stations: stations, favourites: refreshedFavourites,
fuel: alertsFuel, radiusKM: alertsRadius)
monitor.setEnabled(alertsEnabled)
// Refresh only when the cache is stale (twice-a-day policy).
Task { await refresh() }
} else {
showOnboarding = true
}
monitor.update(stations: stations, favourites: refreshedFavourites,
fuel: alertsFuel, radiusKM: alertsRadius)
monitor.setEnabled(alertsEnabled)
// Refresh only when the cache is stale (twice-a-day policy).
Task { await refresh() }
}
.onChange(of: showOnboarding) { _, showing in
// After onboarding finishes (or the test re-run is dismissed),
// begin foreground location tracking if permission allows.
// begin foreground location tracking if permission allows, and
// run the first data fetch (the relay probe during onboarding
// already surfaced the Local Network prompt).
if !showing, FuelStore.loadHasCompletedOnboarding() {
locationManager.startForegroundTracking()
monitor.update(stations: stations, favourites: refreshedFavourites,
fuel: alertsFuel, radiusKM: alertsRadius)
Task { await refresh() }
}
}
.onChange(of: scenePhase) { _, newPhase in
if newPhase == .active {
locationManager.startForegroundTracking()
// Never start location tracking while onboarding is on screen
// onboarding owns the initial permission prompts. Once it's
// completed, normal foreground tracking resumes.
if !showOnboarding, FuelStore.loadHasCompletedOnboarding() {
locationManager.startForegroundTracking()
}
monitor.update(stations: stations, favourites: refreshedFavourites,
fuel: alertsFuel, radiusKM: alertsRadius)
// No network fetch on foreground pull-to-refresh is the override.