refactor(auth): funnel OAuth signIn into auth state machine
Move new AuthPlatform(provider).signIn() out of UI components and into the auth state machine. UI now dispatches AuthGoogle/FacebookLoginSubmitted events; a new oauthSignIn actor inside the machine calls next-auth/react's signIn(provider). Errors and the OAuth redirect window are exposed via the existing state.isLoading / state.errorMessage surface, removing the local busy / error state in auth-facebook-panel. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -55,9 +55,11 @@ export function AuthProvider({ children }: AuthProviderProps) {
|
||||
password: state.context.password,
|
||||
username: state.context.username,
|
||||
confirmPassword: state.context.confirmPassword,
|
||||
// isLoading 仅来自邮箱登录 actor(社交登录改由 NextAuth 处理,UI 自行管 busy 状态)
|
||||
isLoading: state.matches("loadingEmailLogin") ||
|
||||
state.matches("loadingEmailRegister"),
|
||||
// isLoading 覆盖邮箱登录 / 邮箱注册 / OAuth 跳转(NextAuth 重定向期间)
|
||||
isLoading:
|
||||
state.matches("loadingEmailLogin") ||
|
||||
state.matches("loadingEmailRegister") ||
|
||||
state.matches("loadingOAuth"),
|
||||
errorMessage: state.context.errorMessage,
|
||||
isSuccess: state.matches("success"),
|
||||
loginType: state.context.loginType,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*
|
||||
* 事件名与原 Dart AuthEvent 对齐。
|
||||
*/
|
||||
import type { AuthProvider } from "@/lib/auth/auth_platform";
|
||||
import type { AuthMode } from "@/models/auth/auth-mode";
|
||||
import type { AuthPanelMode } from "@/models/auth/auth-panel-mode";
|
||||
|
||||
@@ -21,7 +22,7 @@ export type AuthEvent =
|
||||
username: string;
|
||||
confirmPassword: string;
|
||||
}
|
||||
// 社交登录(已迁移到 NextAuth)— 业务层直接 await nextauth.googleLogin() 即可
|
||||
| { type: "AuthGoogleLoginSubmitted" }
|
||||
| { type: "AuthFacebookLoginSubmitted" }
|
||||
// 社交登录 —— 状态机内部调 next-auth/react 的 signIn(provider)
|
||||
| { type: "AuthGoogleLoginSubmitted"; provider: AuthProvider }
|
||||
| { type: "AuthFacebookLoginSubmitted"; provider: AuthProvider }
|
||||
| { type: "AuthAppleLoginSubmitted" };
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
*
|
||||
* 原始 Dart: lib/ui/auth/bloc/auth_bloc.dart + auth_state.dart + auth_event.dart
|
||||
*
|
||||
* 本轮迁移:社交登录改由 NextAuth 处理(`@/lib/auth/nextauth`),状态机仅保留
|
||||
* 邮箱注册/登录 + 通用 reset 事件。社交登录走 `new AuthPlatform("google").signIn()` /
|
||||
* `new AuthPlatform("facebook").signIn()`。
|
||||
* 本轮迁移:所有认证登录调用(含 OAuth 社交登录)统一收口到状态机内。
|
||||
* 业务层只派发事件(`AuthEmailLoginSubmitted` / `AuthGoogleLoginSubmitted` / 等),
|
||||
* 状态机通过 actors 调 `authRepository`(邮箱)或 `next-auth/react.signIn`(OAuth)。
|
||||
*/
|
||||
import { setup, fromPromise, assign } from "xstate";
|
||||
import { signIn } from "next-auth/react";
|
||||
|
||||
import type { AuthProvider } from "@/lib/auth/auth_platform";
|
||||
import type { LoginType } from "@/models/auth/login-type";
|
||||
import { authRepository } from "@/data/repositories/auth_repository";
|
||||
import { AuthStorage } from "@/data/storage/auth/auth_storage";
|
||||
@@ -68,6 +70,13 @@ const emailRegisterThenLoginActor = fromPromise<
|
||||
return "email" as LoginType;
|
||||
});
|
||||
|
||||
// OAuth 登录 actor:调 next-auth/react 的 signIn(provider) 触发 OAuth 跳转。
|
||||
// 成功路径下 NextAuth 会重定向离开本应用,actor 通常不会 resolve;
|
||||
// onDone 仍保留以处理 SDK 同步返回(极少见)。
|
||||
const oauthSignInActor = fromPromise<void, AuthProvider>(async ({ input }) => {
|
||||
await signIn(input);
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
// Machine
|
||||
// ============================================================
|
||||
@@ -79,6 +88,7 @@ export const authMachine = setup({
|
||||
actors: {
|
||||
emailLogin: emailLoginActor,
|
||||
emailRegisterThenLogin: emailRegisterThenLoginActor,
|
||||
oauthSignIn: oauthSignInActor,
|
||||
},
|
||||
}).createMachine({
|
||||
id: "auth",
|
||||
@@ -113,10 +123,8 @@ export const authMachine = setup({
|
||||
},
|
||||
AuthEmailLoginSubmitted: "loadingEmailLogin",
|
||||
AuthEmailRegisterSubmitted: "loadingEmailRegister",
|
||||
// 社交登录已迁移到 NextAuth + AuthPlatform 类
|
||||
// 状态机保留事件以兼容旧调用方(实际不再触发)
|
||||
AuthGoogleLoginSubmitted: {},
|
||||
AuthFacebookLoginSubmitted: {},
|
||||
AuthGoogleLoginSubmitted: "loadingOAuth",
|
||||
AuthFacebookLoginSubmitted: "loadingOAuth",
|
||||
AuthAppleLoginSubmitted: {
|
||||
actions: assign({
|
||||
errorMessage: "Apple login not implemented",
|
||||
@@ -180,6 +188,31 @@ export const authMachine = setup({
|
||||
},
|
||||
},
|
||||
|
||||
loadingOAuth: {
|
||||
entry: assign({ errorMessage: null }),
|
||||
invoke: {
|
||||
src: "oauthSignIn",
|
||||
input: ({ event }) => {
|
||||
// event 来自 idle 跳转(AuthGoogle/FacebookLoginSubmitted)
|
||||
if (event.type === "AuthGoogleLoginSubmitted") return event.provider;
|
||||
if (event.type === "AuthFacebookLoginSubmitted") return event.provider;
|
||||
return "google" as AuthProvider;
|
||||
},
|
||||
onDone: {
|
||||
// 罕见分支:NextAuth 同步 resolve(实际几乎不会发生,
|
||||
// OAuth 流程会通过重定向离开本应用)。
|
||||
target: "idle",
|
||||
},
|
||||
onError: {
|
||||
target: "idle",
|
||||
actions: assign({
|
||||
errorMessage: ({ event }) =>
|
||||
event.error instanceof Error ? event.error.message : String(event.error),
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
success: {
|
||||
// 终态:业务层通过 state.matches("success") 判断
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user