Merge branch 'dev' into test

This commit is contained in:
2026-06-17 17:11:45 +08:00
6 changed files with 6 additions and 36 deletions
@@ -112,9 +112,6 @@ export function AuthEmailPanel({
setShowOptions(false); setShowOptions(false);
onGoogle?.(); onGoogle?.();
}} }}
onEmail={() => {
// 在 email 模式下不再显示 Email 入口
}}
googleSlot={googleSlot} googleSlot={googleSlot}
/> />
</div> </div>
@@ -11,7 +11,6 @@
* `AuthGoogleLoginSubmitted` 事件,状态机内部调 next-auth/react 的 signIn(provider) * `AuthGoogleLoginSubmitted` 事件,状态机内部调 next-auth/react 的 signIn(provider)
* - busy / error 状态来自 `useAuthState()`(与邮箱登录同源) * - busy / error 状态来自 `useAuthState()`(与邮箱登录同源)
* - "Other Sign-in Options" 链接打开底部弹层 * - "Other Sign-in Options" 链接打开底部弹层
* - 弹层 Email 按钮 → 触发 `onSwitchToEmail`(父级派发 `AuthPanelModeChanged`
*/ */
import Image from "next/image"; import Image from "next/image";
import { useState } from "react"; import { useState } from "react";
@@ -24,11 +23,7 @@ import { AuthOtherOptionsDialog } from "./auth-other-options-dialog";
import { AuthProviderIcon } from "./auth-provider-icon"; import { AuthProviderIcon } from "./auth-provider-icon";
import styles from "./auth-facebook-panel.module.css"; import styles from "./auth-facebook-panel.module.css";
export interface AuthFacebookPanelProps { export function AuthFacebookPanel() {
onSwitchToEmail: () => void;
}
export function AuthFacebookPanel({ onSwitchToEmail }: AuthFacebookPanelProps) {
const [showOptions, setShowOptions] = useState(false); const [showOptions, setShowOptions] = useState(false);
const { isLoading, errorMessage } = useAuthState(); const { isLoading, errorMessage } = useAuthState();
const authDispatch = useAuthDispatch(); const authDispatch = useAuthDispatch();
@@ -98,7 +93,6 @@ export function AuthFacebookPanel({ onSwitchToEmail }: AuthFacebookPanelProps) {
mode="facebook" mode="facebook"
onFacebook={() => handleFacebook()} onFacebook={() => handleFacebook()}
onGoogle={() => handleGoogle()} onGoogle={() => handleGoogle()}
onEmail={onSwitchToEmail}
/> />
</div> </div>
); );
@@ -9,12 +9,11 @@
* - 固定底部、宽 100%(≤500px)、顶部圆角 28px * - 固定底部、宽 100%(≤500px)、顶部圆角 28px
* - drag handle 40×4 灰胶囊 * - drag handle 40×4 灰胶囊
* - 标题 "Other Sign-in Options" 24px bold 深色 * - 标题 "Other Sign-in Options" 24px bold 深色
* - 条件渲染 Email / Facebook 按钮(40px 白胶囊 + 边框 + 图标) * - email 模式下渲染 Facebook 按钮(40px 白胶囊 + 边框 + 图标)
* - 始终渲染 Google 按钮 * - 始终渲染 Google 按钮
* - Cancel 文本按钮 * - Cancel 文本按钮
*/ */
import type { ReactNode } from "react"; import type { ReactNode } from "react";
import { Mail } from "lucide-react";
import { BottomSheet } from "@/app/_components/core/bottom-sheet"; import { BottomSheet } from "@/app/_components/core/bottom-sheet";
@@ -27,7 +26,6 @@ export interface AuthOtherOptionsDialogProps {
onClose: () => void; onClose: () => void;
onFacebook: () => void; onFacebook: () => void;
onGoogle: () => void; onGoogle: () => void;
onEmail: () => void;
/** 当前面板模式:facebook 模式下显示 Email + Googleemail 模式下显示 Facebook + Google。 */ /** 当前面板模式:facebook 模式下显示 Email + Googleemail 模式下显示 Facebook + Google。 */
mode: "facebook" | "email"; mode: "facebook" | "email";
/** 自定义子节点(如嵌入 GIS 按钮) */ /** 自定义子节点(如嵌入 GIS 按钮) */
@@ -39,7 +37,6 @@ export function AuthOtherOptionsDialog({
onClose, onClose,
onFacebook, onFacebook,
onGoogle, onGoogle,
onEmail,
mode, mode,
googleSlot, googleSlot,
}: AuthOtherOptionsDialogProps) { }: AuthOtherOptionsDialogProps) {
@@ -53,17 +50,7 @@ export function AuthOtherOptionsDialog({
<div className={styles.handle} aria-hidden="true" /> <div className={styles.handle} aria-hidden="true" />
<h2 className={styles.title}>Other Sign-in Options</h2> <h2 className={styles.title}>Other Sign-in Options</h2>
{mode === "facebook" ? ( {mode === "email" ? (
<AuthSocialButton
icon={<Mail size={20} aria-hidden="true" />}
onClick={() => {
onClose();
onEmail();
}}
>
Email Sign In / Register
</AuthSocialButton>
) : (
<AuthSocialButton <AuthSocialButton
icon={<AuthProviderIcon provider="facebook" />} icon={<AuthProviderIcon provider="facebook" />}
onClick={() => { onClick={() => {
@@ -73,7 +60,7 @@ export function AuthOtherOptionsDialog({
> >
Facebook Sign In Facebook Sign In
</AuthSocialButton> </AuthSocialButton>
)} ) : null}
{googleSlot ? ( {googleSlot ? (
<div className={styles.googleSlot}>{googleSlot}</div> <div className={styles.googleSlot}>{googleSlot}</div>
+1 -3
View File
@@ -16,8 +16,6 @@ export function AuthPanel() {
const dispatch = useAuthDispatch(); const dispatch = useAuthDispatch();
const router = useRouter(); const router = useRouter();
const switchToEmail = () =>
dispatch({ type: "AuthPanelModeChanged", mode: "email" });
const switchToFacebook = () => const switchToFacebook = () =>
dispatch({ type: "AuthPanelModeChanged", mode: "facebook" }); dispatch({ type: "AuthPanelModeChanged", mode: "facebook" });
@@ -41,7 +39,7 @@ export function AuthPanel() {
</button> </button>
{state.authPanelMode === "facebook" ? ( {state.authPanelMode === "facebook" ? (
<AuthFacebookPanel onSwitchToEmail={switchToEmail} /> <AuthFacebookPanel />
) : ( ) : (
<AuthEmailPanel <AuthEmailPanel
onSwitchToFacebook={() => { onSwitchToFacebook={() => {
@@ -45,7 +45,7 @@ export function ChatQuotaExhaustedBanner({
onUnlock(); onUnlock();
return; return;
} }
router.push(ROUTES.subscription); router.push(ROUTES.auth);
}; };
return ( return (
-6
View File
@@ -4,12 +4,6 @@
* *
* 派发时机:仅 mount 时一次(`useEffect` deps = `[dispatch]`,永远不重跑)。 * 派发时机:仅 mount 时一次(`useEffect` deps = `[dispatch]`,永远不重跑)。
* *
* 与原 `AuthStatusCheckSubmitted` 的区别:
* - 原版本有两个 useEffect:① mount + ② loginStatus 变化 re-check
* - re-check 是 dead code —— 状态机 onDone 已经把 loginStatus 写对,
* 再读 storage 只会拿到相同值(no-op),徒增死循环防护复杂度
* - 新版本只保留 ①,命名 `AuthInit` 与 `UserInit` 对齐(user-machine 的同模式)
*
* 与 <OAuthSessionSync /> 平级: * 与 <OAuthSessionSync /> 平级:
* - AuthStatusChecker: 启动时一次性 init"自己启动时同步" * - AuthStatusChecker: 启动时一次性 init"自己启动时同步"
* - OAuthSessionSync: 持续监听 NextAuth session"别人在写" * - OAuthSessionSync: 持续监听 NextAuth session"别人在写"