refactor(auth): simplify splash guest entry
This commit is contained in:
@@ -3,10 +3,9 @@
|
||||
import { useEffect } from "react";
|
||||
|
||||
import { MobileShell } from "@/app/_components/core";
|
||||
import { hasBusinessLoginToken } from "@/lib/auth/auth_session";
|
||||
import { useAppNavigator } from "@/router/use-app-navigator";
|
||||
import { useAuthDispatch, useAuthState } from "@/stores/auth/auth-context";
|
||||
import { pwaUtil, Logger } from "@/utils";
|
||||
import { useAuthState } from "@/stores/auth/auth-context";
|
||||
import { pwaUtil } from "@/utils";
|
||||
|
||||
import {
|
||||
SplashBackground,
|
||||
@@ -16,7 +15,7 @@ import {
|
||||
} from "./components";
|
||||
import styles from "./components/splash-screen.module.css";
|
||||
|
||||
const log = new Logger("AppSplashSplashScreen");
|
||||
const AUTO_OPEN_CHAT_DELAY_MS = 1800;
|
||||
|
||||
// 尽量早地缓存 beforeinstallprompt,避免用户停留 splash 时浏览器事件已触发并丢失。
|
||||
if (typeof window !== "undefined") {
|
||||
@@ -26,10 +25,8 @@ if (typeof window !== "undefined") {
|
||||
export function SplashScreen() {
|
||||
const navigator = useAppNavigator();
|
||||
const state = useAuthState();
|
||||
const authDispatch = useAuthDispatch();
|
||||
|
||||
const handleSkip = () => {
|
||||
authDispatch({ type: "AuthGuestLoginSubmitted" });
|
||||
const handleStartChat = () => {
|
||||
navigator.openChat({ replace: true });
|
||||
};
|
||||
|
||||
@@ -37,50 +34,13 @@ export function SplashScreen() {
|
||||
pwaUtil.prepareInstallPrompt();
|
||||
}, []);
|
||||
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// useEffect ① 启动时检查 localStorage 里的 loginToken:
|
||||
// - loginToken(OAuth/email sync 写下的)→ 视为"已登录"跳 /chat
|
||||
// - 不查 guestToken —— 游客用户停留 splash(按你要求)
|
||||
// - 都没有 → 留 splash
|
||||
// proxy 读不到 localStorage(Edge runtime),所以这条 fallback 必须在 Client 侧。
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
void (async () => {
|
||||
if (!cancelled && (await hasBusinessLoginToken())) {
|
||||
navigator.openChat({ replace: true });
|
||||
}
|
||||
})();
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [navigator]);
|
||||
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// useEffect ② 按钮刚派了事件(pendingRedirect=true) +
|
||||
// loginStatus 是非 notLoggedIn → 跳 /chat
|
||||
//
|
||||
// 关键:`pendingRedirect` 是 auth context 里的持久状态(不是 ref)——
|
||||
// re-mount 时不重置,区分"刚按了"和"历史登录"准确无误。
|
||||
// 跳完调 `AuthClearPendingRedirect` 置 false(一次性信号)。
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
useEffect(() => {
|
||||
// 调试日志(保留,不删 —— 用于排查"re-mount 误跳 /chat"问题)
|
||||
log.debug("[splash] useEffect ② (loginStatus + pendingRedirect)", {
|
||||
pending: state.pendingRedirect,
|
||||
loginStatus: state.loginStatus,
|
||||
willRedirect:
|
||||
state.pendingRedirect && state.loginStatus !== "notLoggedIn",
|
||||
});
|
||||
|
||||
if (state.pendingRedirect && state.loginStatus !== "notLoggedIn") {
|
||||
log.debug(
|
||||
"[splash] useEffect ② → navigator.openChat [via pendingRedirect flag]",
|
||||
);
|
||||
authDispatch({ type: "AuthClearPendingRedirect" });
|
||||
const timer = window.setTimeout(() => {
|
||||
navigator.openChat({ replace: true });
|
||||
}
|
||||
}, [state.loginStatus, state.pendingRedirect, authDispatch, navigator]);
|
||||
}, AUTO_OPEN_CHAT_DELAY_MS);
|
||||
|
||||
return () => window.clearTimeout(timer);
|
||||
}, [navigator]);
|
||||
|
||||
return (
|
||||
<MobileShell background="var(--color-sidebar-background)">
|
||||
@@ -93,28 +53,8 @@ export function SplashScreen() {
|
||||
<div className={styles.spacer} />
|
||||
<SplashContent />
|
||||
<div className={styles.buttonArea}>
|
||||
<SplashButton onSkip={handleSkip} />
|
||||
<SplashButton onStartChat={handleStartChat} />
|
||||
</div>
|
||||
{/*
|
||||
* 登录错误提示 —— auth state machine 的 onError 会设 errorMessage
|
||||
* (如 Facebook 同步后端失败 / 后端返回数据 schema 不匹配等)。
|
||||
* 之前没显示,导致用户卡在 splash 看不到原因。
|
||||
*/}
|
||||
{state.errorMessage ? (
|
||||
<p
|
||||
role="alert"
|
||||
style={{
|
||||
color: "#c0392b",
|
||||
fontSize: "0.875rem",
|
||||
marginTop: "1rem",
|
||||
textAlign: "center",
|
||||
maxWidth: "320px",
|
||||
lineHeight: 1.4,
|
||||
}}
|
||||
>
|
||||
{state.errorMessage}
|
||||
</p>
|
||||
) : null}
|
||||
<p className={styles.bottom}>
|
||||
Elio Silvestri, Your exclusive AI boyfriend
|
||||
<br />
|
||||
|
||||
Reference in New Issue
Block a user