Distances (the "Approx. 1.5 mi" report):
- Refuse junk CoreLocation fixes (invalid accuracy, or a coarse >300 m fix
within 3 km of the position already held; a coarse fix in another city is
real travel and is still accepted).
- Resolve ONE display basis per render through FuelStore.distanceDisplayOrigin,
used by rows, radius filter, sorting, savings figures and the Live Activity,
so a stray fix can no longer re-base the list outside the route cache's 600 m
ring while the routed values sit unused in the cache.
- Treat an incomplete route set as a state: retry it after 30 s rather than the
full 10-minute throttle, and repair a stale incomplete flag once every
in-radius station has a route (nothing left to route, flag stuck down).
- Widget extension resolves the same origin for fetch, radius, ordering and
labels, and keeps its own fix in fuelboard.widgetLocation instead of
overwriting the app's GPS fix.
Alerts:
- Best Value as a distinct alert mode on the existing geofence/notification
pipeline, with a persisted threshold; reverts to cheapest when the feature is
unconfigured and is not selectable while disabled.
Diagnostics (DEBUG, gated): FB_DIST_FOCUS now prints FB-DIST-ORIGIN (candidate,
accuracy, anchor, offset, resolved branch, served origin), FB_FAKE_FIX feeds a
synthetic fix through the real guard, FB_STALE_INCOMPLETE forces the stale-flag
state, and the route-fill status is surfaced in Settings behind debug mode.
- AppIcon / AppIcon-dark / AppIcon-tinted swapped for the drip design
(1024px, dark + tinted variants), onboarding artwork matched
- Alerts tab: live explainer under the Radius picker — situational
guidance per option (Follow search = set-and-forget mirror of the
Stations distance; 1 = town driving; 2 = city/suburb commute;
3 = mixed; 5 = A-roads/motorway exits; 8 = long-distance) — plus the
trade-off line in the section footer
- 83 tests, Release build green
- Alerts section restyled to mirror the Live Activity section: one section
with toggle + Fuel picker + Radius picker (was segmented fuel + slider)
- Alert radius options expanded to 1/2/3/5/8/10/15/20 (display unit, snapped
to nearest option; stored km unchanged; validation widened to 33 km)
- Live Activity section moved from Settings into the Alerts tab so both
'notify while driving' surfaces sit together
- SettingsView loses the Live Activity bindings/section
The proximity monitor was tied to the Stations-tab fuel selection, so
switching the list to another fuel silently re-targeted geofences. Now the
Alerts tab has its own 'Fuel to monitor' picker (persisted as
fuelboard.alertsFuel):
- Monitor reads loadAlertsFuel() on init/background relaunch
- Changing the alerts fuel re-registers geofences around stations selling
that fuel only
- Favourites priority slots stay scoped to the monitored fuel
- Tests: alerts fuel round-trip + default (33/33 passing)
- FuelType labels: 'Unleaded (E10)'/'Premium (E5)' -> 'Unleaded'/'Premium'
- New DistanceUnit (miles/km) preference; all app + widget distances,
radii and alert text convert/display in the chosen unit
- Settings tab (4th tab): segmented miles/km picker, 'Show introduction'
replay button (onboarding moved out of Alerts tab), StoreKit tip £4.99
- ProximityMonitor + widget notifications use the chosen unit
- Tests: label expectations updated, DistanceUnit conversion + format tests