fix(chat): redirect guests to auth before image paywall

This commit is contained in:
2026-06-24 18:41:59 +08:00
parent c288148c12
commit 5aa32a4256
4 changed files with 47 additions and 12 deletions
+23 -6
View File
@@ -17,10 +17,15 @@ import { Logger } from "@/utils";
const log = new Logger("AppAuthAuthScreen");
export function AuthScreen() {
export interface AuthScreenProps {
redirectTo?: string | null;
}
export function AuthScreen({ redirectTo = null }: AuthScreenProps) {
const state = useAuthState();
const authDispatch = useAuthDispatch();
const router = useRouter();
const safeRedirectTo = getSafeRedirectPath(redirectTo) ?? ROUTES.chat;
// 邮箱登录成功 → 跳转;User hydrate 由根级 <UserAuthSync /> 监听 loginStatus 变化处理。
// 用 pendingRedirect flag(不是 useRef transition detection)——
@@ -34,13 +39,19 @@ export function AuthScreen() {
});
if (state.pendingRedirect && state.loginStatus !== "notLoggedIn") {
log.debug(
"[auth-screen] useEffect → router.replace(/chat) [via pendingRedirect flag]",
);
log.debug("[auth-screen] useEffect → router.replace [via pendingRedirect flag]", {
redirectTo: safeRedirectTo,
});
authDispatch({ type: "AuthClearPendingRedirect" });
router.replace(ROUTES.chat);
router.replace(safeRedirectTo);
}
}, [state.loginStatus, state.pendingRedirect, authDispatch, router]);
}, [
state.loginStatus,
state.pendingRedirect,
authDispatch,
router,
safeRedirectTo,
]);
return (
<MobileShell>
@@ -53,3 +64,9 @@ export function AuthScreen() {
</MobileShell>
);
}
function getSafeRedirectPath(redirectTo: string | null | undefined): string | null {
if (!redirectTo) return null;
if (!redirectTo.startsWith("/") || redirectTo.startsWith("//")) return null;
return redirectTo;
}
+13 -4
View File
@@ -1,7 +1,16 @@
"use client";
import { AuthScreen } from "@/app/auth/auth-screen";
export default function AuthPage() {
return <AuthScreen />;
interface AuthPageProps {
searchParams: Promise<{
redirect?: string | string[];
}>;
}
export default async function AuthPage({ searchParams }: AuthPageProps) {
const params = await searchParams;
const redirectTo = Array.isArray(params.redirect)
? params.redirect[0]
: params.redirect;
return <AuthScreen redirectTo={redirectTo ?? null} />;
}
+7 -2
View File
@@ -133,7 +133,12 @@ export function ChatScreen() {
}
function handleUnlockImagePaywall(): void {
router.push(`${ROUTES.subscription}?type=vip`);
const subscriptionUrl = ROUTE_BUILDERS.subscription("vip");
if (isGuest) {
router.push(ROUTE_BUILDERS.authWithRedirect(subscriptionUrl));
return;
}
router.push(subscriptionUrl);
}
function handleMessageLimitUnlock(): void {
@@ -141,7 +146,7 @@ export function ChatScreen() {
router.push(ROUTES.auth);
return;
}
router.push(`${ROUTES.subscription}?type=vip`);
router.push(ROUTE_BUILDERS.subscription("vip"));
}
return (
+4
View File
@@ -30,6 +30,10 @@ export type StaticRoute = (typeof ROUTES)[keyof typeof ROUTES];
export const ROUTE_BUILDERS = {
chatDeviceId: (deviceId: string): `/chat/deviceid/${string}` =>
`/chat/deviceid/${encodeURIComponent(deviceId)}` as const,
subscription: (type: "vip" | "voice"): `/subscription?type=${string}` =>
`${ROUTES.subscription}?type=${encodeURIComponent(type)}` as const,
authWithRedirect: (redirectTo: string): `/auth?redirect=${string}` =>
`${ROUTES.auth}?redirect=${encodeURIComponent(redirectTo)}` as const,
} as const;
/** 仅未登录态可见的路由(命中后已登录用户应跳走) */