diff --git a/.claude/plans/reflective-meandering-castle.md b/.claude/plans/reflective-meandering-castle.md index ab3792e3..3f6676aa 100644 --- a/.claude/plans/reflective-meandering-castle.md +++ b/.claude/plans/reflective-meandering-castle.md @@ -50,7 +50,7 @@ After getting Claude Max OAuth working on the live server, hardening the deploy - **Change**: Add drag-and-drop overlay with `@dragover.prevent` and `@drop.prevent`. Show visual drop zone when dragging. Extract files from `dataTransfer` and call existing `handleUpload()`. - **Verify**: Drag a file over CloudFolder — drop zone overlay appears, dropping uploads file -### Task 9: Route persistence on refresh +### Task 9: Route persistence on refresh [DONE] - **Files**: `neode-ui/src/router/index.ts` - **Change**: In `router.beforeEach`, when `checkSessionWithTimeout` times out, check `store.isAuthenticated` from localStorage. If true, allow navigation and revalidate in background. Only redirect to `/login` if genuinely no stored token. - **Verify**: Navigate to `/dashboard/cloud`, hit browser refresh — stays on cloud page diff --git a/neode-ui/src/router/index.ts b/neode-ui/src/router/index.ts index 153917a9..55149114 100644 --- a/neode-ui/src/router/index.ts +++ b/neode-ui/src/router/index.ts @@ -179,14 +179,16 @@ router.beforeEach(async (to, _from, next) => { return } - // Protected routes: validate session if stale auth from localStorage (with timeout) + // Protected routes: validate session if stale auth from localStorage if (store.needsSessionValidation()) { - const valid = await checkSessionWithTimeout(store) - if (!valid) { - next('/login') - return - } + // localStorage says we're authed — proceed immediately, revalidate in background. + // No timeout wrapper here: a slow server shouldn't bounce the user to login. next() + store.checkSession().then((valid) => { + if (!valid) { + router.replace('/login').catch(() => {}) + } + }) return }