fix(chat): redirect unauthenticated users from chat

This commit is contained in:
2026-06-17 19:44:22 +08:00
parent bb40f3c042
commit e4b1690b45
4 changed files with 47 additions and 22 deletions
+23 -21
View File
@@ -19,12 +19,14 @@
*/
import { useEffect, useRef } from "react";
import Image from "next/image";
import { useRouter } from "next/navigation";
import { useAuthState } from "@/stores/auth/auth-context";
import type { LoginStatus } from "@/data/dto/auth";
import { AuthStorage } from "@/data/storage/auth/auth_storage";
import { useChatDispatch, useChatState } from "@/stores/chat/chat-context";
import { AppEnvUtil } from "@/utils/app-env";
import { ROUTES } from "@/router/routes";
import { MobileShell } from "@/app/_components/core";
@@ -75,6 +77,7 @@ function dispatchAuthLifecycle(
}
export function ChatScreen() {
const router = useRouter();
const state = useChatState();
const authState = useAuthState();
const chatDispatch = useChatDispatch();
@@ -91,37 +94,36 @@ export function ChatScreen() {
const showExhaustedBanner =
isGuest && state.quotaLoaded && state.quotaExceededTrigger > 0;
// ─────────────────────────────────────────────────────────────
// 屏幕生命周期 + 派初次鉴权生命周期事件
// ─────────────────────────────────────────────────────────────
useEffect(() => {
dispatchAuthLifecycle(authState.loginStatus, chatDispatch);
return () => {
};
// 注:mount useEffect 故意不依赖 loginStatus —— 首次 mount 时机是固定的
// "用户进 /chat 那一刻"),loginStatus 由 splash/auth-screen 提前 settle。
// loginStatus 后续变化由下方"副作用 ②" 统一处理。
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [chatDispatch]);
// ─────────────────────────────────────────────────────────────
// 副作用 ②:loginStatus 变化 → 派对应鉴权生命周期事件
// loginStatus 变化 → 派对应鉴权生命周期事件
//
// 规则:
// - 首次 mountprev === null)→ 由 mount useEffect 统一处理
// - "notLoggedIn" → 派 ChatLogout
// - AuthInit 未完成 → 等,避免初始 notLoggedIn 把 /chat 变成死状态
// - AuthInit 完成后仍 "notLoggedIn" → 清 chat 并回 splash
// - 登录态变化(guest→email 等)→ 派 ChatGuestLogin 或 ChatNonGuestLogin
// ─────────────────────────────────────────────────────────────
const prevLoginStatusRef = useRef<LoginStatus | null>(null);
useEffect(() => {
if (!authState.hasInitialized || authState.isLoading) return;
const prev = prevLoginStatusRef.current;
prevLoginStatusRef.current = authState.loginStatus;
if (prev === null) return; // 首次 mount 由 mount useEffect 处理
if (prev === authState.loginStatus) return; // 登录态没变
prevLoginStatusRef.current = authState.loginStatus;
if (authState.loginStatus === "notLoggedIn") {
chatDispatch({ type: "ChatLogout" });
router.replace(ROUTES.splash);
return;
}
dispatchAuthLifecycle(authState.loginStatus, chatDispatch);
}, [authState.loginStatus, chatDispatch]);
}, [
authState.hasInitialized,
authState.isLoading,
authState.loginStatus,
chatDispatch,
router,
]);
return (
<MobileShell>