"use client"; /** * Auth → Chat 同步器 * * Chat machine 不直接感知 Auth machine;这里作为根级桥接器,持续监听 * loginStatus 变化并派发 chat 鉴权生命周期事件。这样页面组件只负责 UI, * 不再承担全局状态同步职责。 */ import { useEffect, useRef } from "react"; import { usePathname, useRouter } from "next/navigation"; import { AuthStorage } from "@/data/storage/auth"; import { useAuthState } from "@/stores/auth/auth-context"; import { useChatDispatch } from "@/stores/chat/chat-context"; import { PROTECTED_ROUTES, ROUTES, type StaticRoute } from "@/router/routes"; function isProtectedPath(pathname: string): boolean { return PROTECTED_ROUTES.some((route: StaticRoute) => pathname === route); } export function ChatAuthSync() { const authState = useAuthState(); const chatDispatch = useChatDispatch(); const pathname = usePathname(); const router = useRouter(); const prevSessionKeyRef = useRef(null); useEffect(() => { if (!authState.hasInitialized || authState.isLoading) return; const sessionKey = authState.loginStatus; if (prevSessionKeyRef.current === sessionKey) return; prevSessionKeyRef.current = sessionKey; if (authState.loginStatus === "notLoggedIn") { chatDispatch({ type: "ChatLogout" }); if (isProtectedPath(pathname)) { router.replace(ROUTES.splash); } return; } if (authState.loginStatus === "guest") { chatDispatch({ type: "ChatGuestLogin" }); return; } let cancelled = false; void (async () => { const tokenR = await AuthStorage.getInstance().getLoginToken(); if (!cancelled && tokenR.success && tokenR.data) { chatDispatch({ type: "ChatUserLogin", token: tokenR.data, }); } })(); return () => { cancelled = true; }; }, [ authState.hasInitialized, authState.isLoading, authState.loginStatus, chatDispatch, pathname, router, ]); return null; }