refactor(splash): convert Skip to explicit guest login flow

- Splash Skip button now dispatches `AuthGuestLoginSubmitted` instead of
  direct routing, keeping guest auth under the state machine
- Update PWA install dialog copy ("Add to Home Screen") and drop favicon
  entry from manifest icons
- Add debug logging and routing sequence docs to splash-button
This commit is contained in:
2026-06-11 15:58:48 +08:00
parent e557f084c4
commit a6bc6941d4
9 changed files with 183 additions and 53 deletions
@@ -1,4 +1,11 @@
"use client";
import { useEffect } from "react";
import { useRouter } from "next/navigation";
import { MobileShell } from "@/app/_components/core/mobile-shell";
import { AuthStorage } from "@/data/storage/auth/auth_storage";
import { ROUTES } from "@/router/routes";
import { SplashBackground } from "./splash-background";
import { SplashLogo } from "./splash-logo";
@@ -7,6 +14,49 @@ import { SplashButton } from "./splash-button";
import styles from "./splash-screen.module.css";
export function SplashScreen() {
const router = useRouter();
// 启动时检查 localStorage 里的 token
// - loginTokenOAuth/email sync 写下的)→ 视为"已登录"跳 /chat
// - guestToken(用户**显式**走"游客模式"留下的)→ 同样视为"已登录"跳 /chat
// - 都没有 → 留在 splash(**不**自动创建游客账号 —— 见 auth-machine.ts 的 checkAuthStatusActor
//
// proxy 读不到 localStorageEdge runtime),所以这条 fallback 必须在 Client 侧。
//
// DEBUGclient 端**不**用 Loggerpino 引入会爆 client bundle),改用 console.log
// 临时调试,bug 修完即删。
useEffect(() => {
let cancelled = false;
void (async () => {
const storage = AuthStorage.getInstance();
// 用 getXxxToken() 拿 string | null(不是 hasXxxToken() 拿 boolean
const [loginR, guestR] = await Promise.all([
storage.getLoginToken(),
storage.getGuestToken(),
]);
const loginTok = loginR.success ? loginR.data : null;
const guestTok = guestR.success ? guestR.data : null;
const hasAny =
(loginTok != null && loginTok.length > 0) ||
(guestTok != null && guestTok.length > 0);
console.log("[splash] useEffect token check", {
loginToken: loginTok ? `${loginTok.slice(0, 8)}...` : null,
guestToken: guestTok ? `${guestTok.slice(0, 8)}...` : null,
hasAny,
willRedirect: hasAny && !cancelled,
});
if (!cancelled && hasAny) {
console.log("[splash] useEffect → router.replace(/chat)");
router.replace(ROUTES.chat);
}
})();
return () => {
cancelled = true;
};
}, [router]);
return (
<MobileShell background="var(--color-sidebar-background)">
<div className={styles.wrapper}>