fix(auth): auth pages reload when a session appears in another tab
Fixes #69 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
import { useEffect } from 'react';
|
||||
import { getFallbackSession, subscribeSessionChanges } from '../state/sessions';
|
||||
|
||||
/**
|
||||
* #69 — `useSessionSync` (the full cross-tab session sync, with in-place token
|
||||
* rotation handling) is mounted only inside the authenticated `ClientRoot`
|
||||
* shell, so a tab parked on the login/register/OIDC-callback pages never
|
||||
* learns that another tab just signed in. Left alone, that tab keeps showing
|
||||
* the login form and, if submitted, starts a second device/session for the
|
||||
* same account.
|
||||
*
|
||||
* This is a deliberately lighter watcher for the unauthenticated routes: it
|
||||
* only cares about a session APPEARING where there was none before (a fresh
|
||||
* login completed in another tab) and reloads so this tab picks up the
|
||||
* authenticated shell instead. It does not need `useSessionSync`'s
|
||||
* rotation/relogin handling since there is no running client here to keep in
|
||||
* sync — do not import/duplicate that logic, just reload.
|
||||
*/
|
||||
export function useSessionAppeared(): void {
|
||||
useEffect(() => {
|
||||
// If we already have a session, there's nothing to watch for here — the
|
||||
// authenticated shell's own useSessionSync takes over once mounted.
|
||||
if (getFallbackSession()) return undefined;
|
||||
|
||||
const unsubscribe = subscribeSessionChanges((session) => {
|
||||
if (session) {
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
|
||||
return unsubscribe;
|
||||
}, []);
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import { settingsAtom } from '../state/settings';
|
||||
import { isWithinTimeWindow } from '../utils/timeWindow';
|
||||
import { LotusToastContainer } from '../features/toast/LotusToastContainer';
|
||||
import { useTauriNotificationBadge } from '../hooks/useTauriNotificationBadge';
|
||||
import { useSessionAppeared } from '../hooks/useSessionAppeared';
|
||||
import { useTauriWindowChrome } from '../hooks/useTauriWindowChrome';
|
||||
import { isTauri } from '../hooks/useTauri';
|
||||
import { TitleBar } from '../features/desktop/TitleBar';
|
||||
@@ -165,6 +166,12 @@ const queryClient = new QueryClient();
|
||||
function App() {
|
||||
const screenSize = useScreenSize();
|
||||
useCompositionEndTracking();
|
||||
// #69 — cross-tab session sync (useSessionSync) only mounts inside the
|
||||
// authenticated ClientRoot shell, so a tab still on the unauthenticated
|
||||
// routes (login/register/OIDC callback) never learns that another tab just
|
||||
// signed in. This lighter watcher covers that gap by reloading once a
|
||||
// session appears where there was none.
|
||||
useSessionAppeared();
|
||||
|
||||
const portalContainer = document.getElementById('portalContainer') ?? undefined;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user