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>
45 lines
1.6 KiB
JavaScript
45 lines
1.6 KiB
JavaScript
// 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 };
|
|
}
|