Extract auth into hooks/useAuth; move form state into its pages
Build and Push Docker Image / build-and-push (push) Successful in 6m28s
Build and Push Docker Image / build-and-push (push) Successful in 6m28s
- useAuth owns authUser/authServerDown, the startup session check, and signIn/logout, so every sign-in path runs the same follow-up (switch local storage to the account, load reader ink). Previously reader ink only loaded on a page refresh, not right after logging in. - Login/2FA form state now lives in AuthPage, and 2FA setup, password change, and podcast name state in SettingsPage (23 fewer context values; typing in these forms no longer re-renders all of App). - Add tests for form sign-in, 2FA, session restore + logout, and the Settings podcast-name prefill. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
009fa1e78f
commit
49ffefed54
5 files changed
+162
-113
No files matched your search
@@ -0,0 +1,44 @@
|
||||
// Who is signed in. Checks the session on startup and exposes signIn/logout so
|
||||
// every sign-in path (startup, login form, 2FA) runs the same follow-up work.
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { getCurrentUser, logoutUser } from '../syncService.js';
|
||||
|
||||
// onSignIn(user) runs right after a user becomes signed in (switch local
|
||||
// storage to their account, load their data). onSignOut() runs after logout.
|
||||
export function useAuth({ onSignIn, onSignOut }) {
|
||||
// authUser: undefined = still checking · null = signed out · object = signed in
|
||||
const [authUser, setAuthUser] = useState(undefined);
|
||||
const [authServerDown, setAuthServerDown] = useState(false);
|
||||
|
||||
// Callbacks come from App and close over its latest state; read them through
|
||||
// a ref so signIn/logout never call a stale copy.
|
||||
const callbacksRef = useRef({ onSignIn, onSignOut });
|
||||
callbacksRef.current = { onSignIn, onSignOut };
|
||||
|
||||
const signIn = (user) => {
|
||||
setAuthUser(user);
|
||||
callbacksRef.current.onSignIn(user);
|
||||
};
|
||||
|
||||
const logout = async () => {
|
||||
await logoutUser();
|
||||
setAuthUser(null);
|
||||
callbacksRef.current.onSignOut();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getCurrentUser().then((result) => {
|
||||
if (result.ok) {
|
||||
if (result.user) signIn(result.user);
|
||||
else setAuthUser(null);
|
||||
} else {
|
||||
// Genuine network failure (server unreachable) — fall back to local-only mode.
|
||||
setAuthServerDown(true);
|
||||
setAuthUser(null);
|
||||
}
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
return { authUser, setAuthUser, authServerDown, signIn, logout };
|
||||
}
|
||||
Reference in new issue
Block a user