v0.6.1: stop Anonymous Mode bouncing to sign-in on every foreground
All checks were successful
build-apk / build (push) Successful in 9m55s

Parking without an account showed "Your session expired — please sign in
again." repeatedly and kicked the user back to the login screen.

The 401 hook on the API client is global: it fires on every unauthorized
response whether or not the caller caught the error. Anonymous Mode has no
token, so any ParkSmarter call 401s, and two of them run automatically —
discoverPaidSession() on open and every foreground, and the map's
lastSessionLot() on every mount. Each one flipped the status to signedOut;
re-entering anonymous mode ran them again, hence "over and over".

Both call sites already caught their errors, which is why this hid: the
bounce came from the client hook, not from the catch.

- A 401 in Anonymous Mode is no longer treated as a session expiry. There is
  no session to expire, and bouncing to sign-in makes the mode pointless.
  This also covers the Sessions/Favorites/Scan tabs, which 401 the same way.
- authBus carries the mode to the non-React modules that need it.
- discoverPaidSession() and lastSessionLot() are skipped entirely when
  anonymous rather than fired and discarded.
- "Last lot" now says it needs an account instead of silently doing nothing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-13 04:19:12 +00:00
parent 148e1635d3
commit 7fc92d24e4
5 changed files with 35 additions and 6 deletions

View file

@ -113,6 +113,9 @@ export function MapScreen() {
// Look up the LAST session's parking-lot coordinate (the meter's own location
// from history — never the user's GPS). Used to open the map and by "Last lot".
const lastSessionLot = useCallback(async (): Promise<Coords | null> => {
// No account, no session history — and asking anyway 401s, which the global
// handler would turn into a bogus "session expired" bounce.
if (isAnonymous) return null;
try {
const past = await ps.getPastParkingSessions({ currentPage: 1, pageSize: 1 });
const s = past.Session?.[0] as Record<string, any> | undefined;
@ -125,7 +128,7 @@ export function MapScreen() {
/* ignore */
}
return null;
}, []);
}, [isAnonymous]);
// Open on your last parking lot — NOT your GPS. Your location is only ever sent
// to the API when you explicitly tap "My location", so we never auto-center on it.
@ -257,6 +260,10 @@ export function MapScreen() {
// Center on the LAST SESSION's parking lot (the meter's own coordinate from
// history — never your GPS) and search around it with a ~couple-mile view.
const searchLastSessionLot = async () => {
if (isAnonymous) {
setStatus('Sign in to use your last parking lot — it comes from your account history.');
return;
}
setLoading(true);
setStatus('Finding your last parking lot…');
const lot = await lastSessionLot();