diff --git a/src/providers/root-providers.tsx b/src/providers/root-providers.tsx index 4f05aefc..a90817e6 100644 --- a/src/providers/root-providers.tsx +++ b/src/providers/root-providers.tsx @@ -7,6 +7,7 @@ * AuthProvider → UserProvider → SidebarProvider → ChatProvider * + AuthStatusChecker(启动时一次:派发 AuthInit) * + OAuthSessionSync (持续监听 NextAuth session → auth machine) + * + UserAuthSync (auth 登录态恢复后 hydrate user machine) * * 它们始终挂载,保证各页面直接 `use*State()` / `use*Dispatch()` 即可, * 无需在每个页面单独包裹。 @@ -19,6 +20,7 @@ import { AuthStatusChecker } from "@/stores/auth/auth-status-checker"; import { OAuthSessionSync } from "@/stores/auth/oauth-session-sync"; import { ChatProvider } from "@/stores/chat/chat-context"; import { SidebarProvider } from "@/stores/sidebar/sidebar-context"; +import { UserAuthSync } from "@/stores/user/user-auth-sync"; import { UserProvider } from "@/stores/user/user-context"; export interface RootProvidersProps { @@ -34,6 +36,7 @@ export function RootProviders({ children }: RootProvidersProps) { {/* OAuthSessionSync 同样依赖 AuthProvider 上下文 */} + {children} diff --git a/src/stores/user/user-auth-sync.tsx b/src/stores/user/user-auth-sync.tsx new file mode 100644 index 00000000..26911c9d --- /dev/null +++ b/src/stores/user/user-auth-sync.tsx @@ -0,0 +1,34 @@ +"use client"; + +/** + * Auth → User 启动同步器 + * + * AuthStatusChecker 只负责恢复 loginStatus;头像等登录用户资料由 + * UserStorage 持久化在 user machine 这一侧。冷启动直达 /chat 时, + * 没有经过 splash/auth 的跳转副作用,因此需要在登录态恢复后主动 + * hydrate user store。 + */ +import { useEffect, useRef } from "react"; + +import { useAuthState } from "@/stores/auth/auth-context"; + +import { useUserDispatch } from "./user-context"; + +export function UserAuthSync() { + const { loginStatus } = useAuthState(); + const userDispatch = useUserDispatch(); + const lastInitializedStatusRef = useRef(null); + + useEffect(() => { + if (loginStatus === "notLoggedIn" || loginStatus === "guest") { + lastInitializedStatusRef.current = null; + return; + } + + if (lastInitializedStatusRef.current === loginStatus) return; + lastInitializedStatusRef.current = loginStatus; + userDispatch({ type: "UserInit" }); + }, [loginStatus, userDispatch]); + + return null; +}