diff --git a/src/app/auth/components/auth-screen.tsx b/src/app/auth/components/auth-screen.tsx index 9828a01b..7ae6cdaf 100644 --- a/src/app/auth/components/auth-screen.tsx +++ b/src/app/auth/components/auth-screen.tsx @@ -24,8 +24,8 @@ export function AuthScreen() { const router = useRouter(); // 邮箱登录成功 → 通知 User + 跳转 - // 用 **pendingRedirect flag**(不是 useRef transition detection)—— - // re-mount 时 flag 在 auth context 里**持久**,区分"刚按了"和"re-visit"准确无误。 + // 用 pendingRedirect flag(不是 useRef transition detection)—— + // re-mount 时 flag 在 auth context 里持久,区分"刚按了"和"re-visit"准确无误。 useEffect(() => { console.log("[auth-screen] useEffect (loginStatus + pendingRedirect)", { pending: state.pendingRedirect, diff --git a/src/app/chat/components/chat-header.tsx b/src/app/chat/components/chat-header.tsx index 6bf693bf..7e0bdcdb 100644 --- a/src/app/chat/components/chat-header.tsx +++ b/src/app/chat/components/chat-header.tsx @@ -8,7 +8,7 @@ * - 游客模式(isGuest=true):渲染 `GuestBanner` 提示注册(点击 → /auth) * - 登录模式(isGuest=false):渲染 `MenuButton`(点击 → push 到 /sidebar) * - * 注意:菜单按钮直接 push 到侧边栏路由,**不**打开下拉菜单 + * 注意:菜单按钮直接 push 到侧边栏路由,不打开下拉菜单 * (Dart 端 `MenuButton(onTap: _goSidebar)` 行为)。 */ import { useRouter } from "next/navigation"; diff --git a/src/app/chat/components/chat-screen.tsx b/src/app/chat/components/chat-screen.tsx index 346e8ee7..66a3899f 100644 --- a/src/app/chat/components/chat-screen.tsx +++ b/src/app/chat/components/chat-screen.tsx @@ -5,9 +5,9 @@ * 原始 Dart: lib/ui/chat/chat_screen.dart(172 行) * * 职责(本文件): - * - **订阅 auth 状态机**(loginStatus)—— 派生 isGuest / **派鉴权生命周期事件**给 chat 机器 + * - 订阅 auth 状态机(loginStatus)—— 派生 isGuest / 派鉴权生命周期事件给 chat 机器 * - 屏幕生命周期事件(init / visible / invisible) - * - **不**直接管理 WebSocket / **不**直接读 AuthStorage(除 token 取值) + * - 不直接管理 WebSocket / 不直接读 AuthStorage(除 token 取值) * * 子组件职责: * - ChatHeader:顶部栏(游客 banner / 菜单按钮) @@ -16,13 +16,13 @@ * - PwaInstallOverlay:PWA 安装提示触发器 * - BrowserHintOverlay:浏览器提示 * - * **鉴权解耦**(**事件驱动**): - * - chat 机器**不**感知鉴权 / **不**管 WebSocket —— 由 chat-screen 派生 loginStatus - * - chat-screen **只**派 3 个事件: - * - `ChatGuestLogin` → 游客会话(**断** WS = 不连) - * - `ChatNonGuestLogin { token }` → 非游客会话(**连** WS) + * 鉴权解耦(事件驱动): + * - chat 机器不感知鉴权 / 不管 WebSocket —— 由 chat-screen 派生 loginStatus + * - chat-screen 只派 3 个事件: + * - `ChatGuestLogin` → 游客会话(断 WS = 不连) + * - `ChatNonGuestLogin { token }` → 非游客会话(连 WS) * - `ChatLogout` → 登出(机器自动 cleanup WS actor) - * - chat 机器**内部**用 fromCallback actor 完整管理 WS 生命周期 + * - chat 机器内部用 fromCallback actor 完整管理 WS 生命周期 */ import { useEffect, useRef } from "react"; import Image from "next/image"; @@ -49,16 +49,16 @@ function deriveIsGuest(loginStatus: LoginStatus): boolean { } /** - * 按 loginStatus 派鉴权生命周期事件(chat 机器**不**感知 loginStatus —— 这层转换在此) + * 按 loginStatus 派鉴权生命周期事件(chat 机器不感知 loginStatus —— 这层转换在此) * - * 设计:**不**直接管理 WS / **不**读 AuthStorage(除取 token) + * 设计:不直接管理 WS / 不读 AuthStorage(除取 token) */ function dispatchAuthLifecycle( loginStatus: LoginStatus, chatDispatch: ReturnType, ): void { if (loginStatus === "guest") { - // 游客:派 ChatGuestLogin(chat 机器**不**连 WS —— 业务事实"断 WS") + // 游客:派 ChatGuestLogin(chat 机器不连 WS —— 业务事实"断 WS") chatDispatch({ type: "ChatGuestLogin" }); return; } @@ -81,7 +81,7 @@ export function ChatScreen() { const authState = useAuthState(); const chatDispatch = useChatDispatch(); - // isGuest 派生(chat-screen 是**唯一**知道这个值的地方 —— chat 机器无 isGuest 字段) + // isGuest 派生(chat-screen 是唯一知道这个值的地方 —— chat 机器无 isGuest 字段) const isGuest = deriveIsGuest(authState.loginStatus); // ───────────────────────────────────────────────────────────── @@ -91,7 +91,7 @@ export function ChatScreen() { dispatchAuthLifecycle(authState.loginStatus, chatDispatch); return () => { }; - // 注:mount useEffect 故意**不**依赖 loginStatus —— 首次 mount 时机是固定的 + // 注:mount useEffect 故意不依赖 loginStatus —— 首次 mount 时机是固定的 // ("用户进 /chat 那一刻"),loginStatus 由 splash/auth-screen 提前 settle。 // loginStatus 后续变化由下方"副作用 ②" 统一处理。 // eslint-disable-next-line react-hooks/exhaustive-deps @@ -110,7 +110,7 @@ export function ChatScreen() { const prev = prevLoginStatusRef.current; prevLoginStatusRef.current = authState.loginStatus; if (prev === null) return; // 首次 mount 由 mount useEffect 处理 - if (prev === authState.loginStatus) return; // 登录态**没**变 + if (prev === authState.loginStatus) return; // 登录态没变 dispatchAuthLifecycle(authState.loginStatus, chatDispatch); }, [authState.loginStatus, chatDispatch]); diff --git a/src/app/chat/components/message-content.tsx b/src/app/chat/components/message-content.tsx index dea5e557..e55671b6 100644 --- a/src/app/chat/components/message-content.tsx +++ b/src/app/chat/components/message-content.tsx @@ -29,7 +29,7 @@ export function MessageContent({ content, imageUrl, isFromAI }: MessageContentPr style={{ display: "flex", flexDirection: "column", - // **关键**:在 row flex 父中撑开(不依赖 content 循环)—— 让 TextBubble 能拿到真实宽度 + // 关键:在 row flex 父中撑开(不依赖 content 循环)—— 让 TextBubble 能拿到真实宽度 flex: "1 1 0", // 防超长 content(图片 / 超长 url)撑爆父 minWidth: 0, diff --git a/src/app/chat/deviceid/[deviceId]/DeepLinkPersist.tsx b/src/app/chat/deviceid/[deviceId]/DeepLinkPersist.tsx index c753a45d..a8157fd1 100644 --- a/src/app/chat/deviceid/[deviceId]/DeepLinkPersist.tsx +++ b/src/app/chat/deviceid/[deviceId]/DeepLinkPersist.tsx @@ -7,7 +7,7 @@ * `redirect` 回调(`app_router.dart:60-78`)。 * * 设计: - * - **不**走 Server `redirect()`:避免把 fbid 暴露在 URL 里。 + * - 不走 Server `redirect()`:避免把 fbid 暴露在 URL 里。 * - deviceId 走 `AuthStorage.getInstance().setDeviceId`(与 `token_interceptor.ts` 同源; * 写入键 `cozsweet.deviceId`)。 * - fbid 走 `window.localStorage.setItem(StorageKeys.facebookId, ...)`, diff --git a/src/app/chat/deviceid/[deviceId]/page.tsx b/src/app/chat/deviceid/[deviceId]/page.tsx index 31de2bb0..687530a1 100644 --- a/src/app/chat/deviceid/[deviceId]/page.tsx +++ b/src/app/chat/deviceid/[deviceId]/page.tsx @@ -9,7 +9,7 @@ * Next.js 16 全局 helper `PageProps<'/literal'>` 由 `next dev` / `next build` / * `next typegen` 生成。 * - * 这里**不**调用 `redirect()`:把 fbid 暴露在 URL 上对用户不友好; + * 这里不调用 `redirect()`:把 fbid 暴露在 URL 上对用户不友好; * 跳转推迟到 Client 完成持久化之后。 */ diff --git a/src/app/page.tsx b/src/app/page.tsx index 8b5815ec..3b935c5e 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -4,7 +4,7 @@ * Server Component:把访客直接送入 `/splash`,由 splash 页(Client)根据 * `authStorage.hasLoginToken()` 决定是否再跳 `/chat`。 * - * 这里**不**做鉴权重定向:Server 端读不到 localStorage,且当前没有 HttpOnly + * 这里不做鉴权重定向:Server 端读不到 localStorage,且当前没有 HttpOnly * cookie(见 `src/data/storage/auth/auth_storage.ts` 的 TODO)。 * `src/proxy.ts` 已为未来 cookie 化预留了基于 `login_token` cookie 的 short-circuit。 */ diff --git a/src/app/splash/components/splash-button.tsx b/src/app/splash/components/splash-button.tsx index ab82cac4..6e4c81c9 100644 --- a/src/app/splash/components/splash-button.tsx +++ b/src/app/splash/components/splash-button.tsx @@ -2,14 +2,14 @@ /** * Splash 底部按钮组 * - * 本组件是 splash 鉴权流程的**纯 UI 入口**: + * 本组件是 splash 鉴权流程的纯 UI 入口: * - 消费 `useAuthState` / `useAuthDispatch`(仅用于 isLoading 显示 + 派事件) - * - **Skip 按钮 = 显式游客登录入口**(派发 `AuthGuestLoginSubmitted`) + * - Skip 按钮 = 显式游客登录入口(派发 `AuthGuestLoginSubmitted`) * - 社交登录按钮仅派发 `AuthFacebookLoginSubmitted` 事件,由状态机负责调 NextAuth * - * **派事件策略**(**单**事件): + * 派事件策略(单事件): * - 派业务事件(`AuthGuestLoginSubmitted` / `AuthFacebookLoginSubmitted`)→ 状态机开始跑 - * - `pendingRedirect: true` 在**登录成功 onDone** 里**自动**置(auth-machine.ts `onLoginSuccess` helper) + * - `pendingRedirect: true` 在登录成功 onDone 里自动置(auth-machine.ts `onLoginSuccess` helper) * - splash-screen 看到 flag=true + loginStatus 非 notLoggedIn → 跳 /chat */ import { useAuthDispatch, useAuthState } from "@/stores/auth/auth-context"; @@ -35,7 +35,7 @@ export function SplashButton() { return (
- {/* Skip 按钮 = 显式游客登录入口(派发 AuthGuestLoginSubmitted,**不**做路由跳转) */} + {/* Skip 按钮 = 显式游客登录入口(派发 AuthGuestLoginSubmitted,不做路由跳转) */}