diff --git a/app/app.json b/app/app.json index 3b6ab44..75800ba 100644 --- a/app/app.json +++ b/app/app.json @@ -3,14 +3,14 @@ "name": "BigBrainParking", "slug": "bigbrainparking", "scheme": "bigbrainparking", - "version": "0.1.5", + "version": "0.1.6", "orientation": "portrait", "userInterfaceStyle": "automatic", "newArchEnabled": true, "icon": "./assets/icon.png", "android": { "package": "top.mowden.bigbrainparking", - "versionCode": 5, + "versionCode": 6, "edgeToEdgeEnabled": true, "adaptiveIcon": { "foregroundImage": "./assets/adaptive-icon.png", diff --git a/app/src/auth/AuthContext.tsx b/app/src/auth/AuthContext.tsx index 3b5e098..7f31272 100644 --- a/app/src/auth/AuthContext.tsx +++ b/app/src/auth/AuthContext.tsx @@ -37,18 +37,28 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { }; }, []); - // On launch: bootstrap (seeds SessionId + feature flags) and probe for an - // existing token by attempting an authenticated read. + // On launch: bootstrap (seeds SessionId + feature flags), then verify any + // stored token BEFORE showing the app. A stale/expired token doesn't 401 — + // /api/User just returns an empty body, so getUserDetail() resolves to + // undefined without throwing. Require real user data to count as signed in, + // and clear the dead token otherwise, so an expired session lands on the + // login screen at open instead of failing later on the map. useEffect(() => { (async () => { try { const v = await ps.getApplicationValidity(); setValidity(v); const existing = await ps.tokens.getAuthToken(); - if (existing) { - await ps.getUserDetail(); // 401 throws -> treated as signed out + if (!existing) { + setStatus('signedOut'); + return; + } + const user = await ps.getUserDetail().catch(() => null); + const valid = !!(user && (user.PersonalPhone || user.PersonalEmailAddress)); + if (valid) { setStatus('signedIn'); } else { + await ps.logoutLocal(); // drop the dead token so the login screen is clean setStatus('signedOut'); } } catch {