diff --git a/src/app/auth/components/auth-facebook-panel.tsx b/src/app/auth/components/auth-facebook-panel.tsx
index c3633af2..9d63528a 100644
--- a/src/app/auth/components/auth-facebook-panel.tsx
+++ b/src/app/auth/components/auth-facebook-panel.tsx
@@ -7,13 +7,13 @@
* 视觉规格(与 Dart 对齐):
* - Spacer → logo(120h)→ Spacer → Facebook 主按钮 → 链接 → Spacer → 法律
* - Facebook 主按钮:46px 白胶囊 + Facebook "f" 图标(#1877f2)+ "Login with Facebook"
- * - 社交登录走 NextAuth:`new FacebookLogin().signIn()` / `new GoogleLogin().signIn()`
+ * - 社交登录走 NextAuth:`new AuthPlatform("facebook").signIn()` / `new AuthPlatform("google").signIn()`
* - "Other Sign-in Options" 链接打开底部弹层
* - 弹层 Email 按钮 → 触发 `onSwitchToEmail`(父级派发 `AuthPanelModeChanged`)
*/
import { useState } from "react";
-import { FacebookLogin, GoogleLogin } from "@/lib/auth/nextauth";
+import { AuthPlatform } from "@/lib/auth/nextauth";
import { AuthErrorMessage } from "./auth-error-message";
import { AuthLegalText } from "./auth-legal-text";
@@ -33,7 +33,7 @@ export function AuthFacebookPanel({ onSwitchToEmail }: AuthFacebookPanelProps) {
setBusy("facebook");
setError(null);
try {
- await new FacebookLogin().signIn();
+ await new AuthPlatform("facebook").signIn();
} catch (e) {
setError(e instanceof Error ? e.message : "Facebook login failed");
} finally {
@@ -45,7 +45,7 @@ export function AuthFacebookPanel({ onSwitchToEmail }: AuthFacebookPanelProps) {
setBusy("google");
setError(null);
try {
- await new GoogleLogin().signIn();
+ await new AuthPlatform("google").signIn();
} catch (e) {
setError(e instanceof Error ? e.message : "Google login failed");
} finally {
diff --git a/src/app/splash/components/splash-button.tsx b/src/app/splash/components/splash-button.tsx
index 59b86837..5c5965ed 100644
--- a/src/app/splash/components/splash-button.tsx
+++ b/src/app/splash/components/splash-button.tsx
@@ -11,7 +11,7 @@
* - 消费 `useChatDispatch` / `useUserDispatch`(登录成功后初始化)
* - 自管路由跳转(已登录 / 登录成功 → /chat)
* - Skip 用 `` 保留 SPA 体验
- * - 社交登录按钮走 `new FacebookLogin().signIn()`(NextAuth 流程)
+ * - 社交登录按钮走 `new AuthPlatform("facebook").signIn()`(NextAuth 流程)
*/
import Link from "next/link";
import { useRouter } from "next/navigation";
@@ -20,7 +20,7 @@ import { useEffect, useRef } from "react";
import { useAuthState } from "@/stores/auth/auth-context";
import { useChatDispatch } from "@/stores/chat/chat-context";
import { useUserDispatch } from "@/stores/user/user-context";
-import { FacebookLogin } from "@/lib/auth/nextauth";
+import { AuthPlatform } from "@/lib/auth/nextauth";
import { ROUTES } from "@/router/routes";
import { LoadingIndicator } from "@/app/_components/core/loading-indicator";
import styles from "./splash-button.module.css";
@@ -53,7 +53,7 @@ export function SplashButton() {
const handleFacebookLogin = async () => {
try {
- await new FacebookLogin().signIn();
+ await new AuthPlatform("facebook").signIn();
} catch (e) {
console.error("[splash-button] Facebook login failed", e);
}
diff --git a/src/lib/auth/auth_platform.ts b/src/lib/auth/auth_platform.ts
new file mode 100644
index 00000000..2c4180ec
--- /dev/null
+++ b/src/lib/auth/auth_platform.ts
@@ -0,0 +1,31 @@
+"use client";
+/**
+ * AuthPlatform 统一 OAuth 登录入口
+ *
+ * 合并自原 FacebookLogin / GoogleLogin 两个类。
+ * 构造时传入 provider 名,调用 signIn() 触发 NextAuth OAuth 流程。
+ *
+ * 用法:
+ * await new AuthPlatform("facebook").signIn()
+ * await new AuthPlatform("google").signIn()
+ *
+ * NextAuth 流程:
+ * 1. NextAuth 重定向到 provider OAuth 授权页
+ * 2. 用户授权 → 回调 /api/auth/callback/{provider}
+ * 3. NextAuth 写 next-auth.session-token (httpOnly) cookie
+ * 4. 重定向到 callbackUrl (默认 /chat)
+ *
+ * **不**做任何持久化(不写 unstorage / 不调后端 / 不设自定义 cookie)。
+ * 原始 Dart: nextauth-helpers.{facebookLogin, googleLogin}()
+ */
+import { signIn } from "next-auth/react";
+
+export type AuthProvider = "facebook" | "google";
+
+export class AuthPlatform {
+ constructor(private readonly provider: AuthProvider) {}
+
+ async signIn(): Promise {
+ await signIn(this.provider);
+ }
+}
diff --git a/src/lib/auth/facebook_login.ts b/src/lib/auth/facebook_login.ts
deleted file mode 100644
index fdc469cd..00000000
--- a/src/lib/auth/facebook_login.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-"use client";
-/**
- * Facebook 登录(NextAuth OAuth 流程触发器)
- *
- * 调用 `signIn("facebook")` 触发 NextAuth 的 OAuth 流程:
- * 1. NextAuth 重定向到 Facebook OAuth 授权页
- * 2. 用户授权 → Facebook 回调 /api/auth/callback/facebook
- * 3. NextAuth 写 `next-auth.session-token` (httpOnly) cookie
- * 4. 重定向到 callbackUrl (默认 /chat)
- *
- * **不**做任何持久化(不写 unstorage / 不调后端 / 不设自定义 cookie)。
- * 原始 Dart: nextauth-helpers.facebookLogin()
- */
-import { signIn } from "next-auth/react";
-
-export class FacebookLogin {
- async signIn(): Promise {
- await signIn("facebook");
- }
-}
diff --git a/src/lib/auth/google_login.ts b/src/lib/auth/google_login.ts
deleted file mode 100644
index 3eb42a78..00000000
--- a/src/lib/auth/google_login.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-"use client";
-/**
- * Google 登录(NextAuth OAuth 流程触发器)
- *
- * 调用 `signIn("google")` 触发 NextAuth 的 OAuth 流程:
- * 1. NextAuth 重定向到 Google OAuth 授权页
- * 2. 用户授权 → Google 回调 /api/auth/callback/google
- * 3. NextAuth 写 `next-auth.session-token` (httpOnly) cookie
- * 4. 重定向到 callbackUrl (默认 /chat)
- *
- * **不**做任何持久化(不写 unstorage / 不调后端 / 不设自定义 cookie)。
- * 原始 Dart: nextauth-helpers.googleLogin()
- */
-import { signIn } from "next-auth/react";
-
-export class GoogleLogin {
- async signIn(): Promise {
- await signIn("google");
- }
-}
diff --git a/src/lib/auth/nextauth.ts b/src/lib/auth/nextauth.ts
index ba69020c..42d56640 100644
--- a/src/lib/auth/nextauth.ts
+++ b/src/lib/auth/nextauth.ts
@@ -2,14 +2,14 @@
* NextAuth v4 配置(单一来源)
*
* 极简模式:参考 `auth.js` 官方示例的**精神**(不做任何持久化),但保留 v4 语法:
- * - 客户端点击登录按钮 → `new GoogleLogin().signIn()` / `new FacebookLogin().signIn()`
+ * - 客户端点击登录按钮 → `new AuthPlatform("google").signIn()` / `new AuthPlatform("facebook").signIn()`
* - NextAuth 重定向到 Google / Facebook OAuth
* - OAuth 回调 → NextAuth 写 `next-auth.session-token` (httpOnly) cookie
* - 重定向到 callbackUrl (默认 /chat)
* - 业务 token 持久化(unstorage / 后端 / 自定义 cookie)**全部不在本轮 scope**
*
* 导出 `GET` / `POST` 给 `src/app/api/auth/[...nextauth]/route.ts` 引用。
- * 客户端通过 `src/lib/auth/{google_login,facebook_login,logout,auth_gate}.ts` 触发。
+ * 客户端通过 `src/lib/auth/{auth_platform,logout}.ts` 触发。
*/
import NextAuth from "next-auth";
import Google from "next-auth/providers/google";
@@ -43,8 +43,7 @@ export { handler as GET, handler as POST };
// 每个 class 一个独立文件,详见同目录的子模块。
// 这里 re-export 仅为消费者提供 `@/lib/auth/nextauth` 单点导入。
// 注:上方 `next-auth` 是 server-only,本文件编译时会被 Next.js 切分到 server bundle;
-// 客户端 import `GoogleLogin` / `FacebookLogin` / `Logout` 时不会拉入。
+// 客户端 import `AuthPlatform` / `Logout` 时不会拉入。
// ============================================================
-export { GoogleLogin } from "./google_login";
-export { FacebookLogin } from "./facebook_login";
+export { AuthPlatform, type AuthProvider } from "./auth_platform";
export { Logout } from "./logout";
diff --git a/src/stores/auth/auth-context.ts b/src/stores/auth/auth-state.ts
similarity index 84%
rename from src/stores/auth/auth-context.ts
rename to src/stores/auth/auth-state.ts
index 4f25bbef..4213206b 100644
--- a/src/stores/auth/auth-context.ts
+++ b/src/stores/auth/auth-state.ts
@@ -1,11 +1,11 @@
/**
- * Auth 状态机:Context 形状 + 初始值
+ * Auth 状态机:State 形状 + 初始值
*/
import type { AuthMode } from "@/models/auth/auth-mode";
import type { AuthPanelMode } from "@/models/auth/auth-panel-mode";
import type { LoginType } from "@/models/auth/login-type";
-export interface AuthContext {
+export interface AuthState {
/** 当前面板模式(Facebook / Email) */
authPanelMode: AuthPanelMode;
/** 内部登录模式(login / register) */
@@ -18,7 +18,7 @@ export interface AuthContext {
loginType: LoginType;
}
-export const initialContext: AuthContext = {
+export const initialState: AuthState = {
authPanelMode: "facebook",
authMode: "login",
email: "",
diff --git a/src/stores/auth/auth-types.ts b/src/stores/auth/auth-types.ts
index 998f3b13..9a42c424 100644
--- a/src/stores/auth/auth-types.ts
+++ b/src/stores/auth/auth-types.ts
@@ -7,4 +7,4 @@
* - Context 形状与初始值由 `auth-context.ts` 导出
* - `AuthState` 由 `auth-context.tsx` 导出(保持原 API 兼容)
*/
-export type { AuthEvent } from "./auth-events";
+export type { AuthEvent } from "./machine/auth-events";
diff --git a/src/stores/auth/index.ts b/src/stores/auth/index.ts
index 5dbd5147..baa0c844 100644
--- a/src/stores/auth/index.ts
+++ b/src/stores/auth/index.ts
@@ -6,7 +6,8 @@
* - 事件联合位于 auth-events.ts
* - machine / 类型 / React 入口分别由对应文件导出
*/
+export * from "./auth-state";
export * from "./auth-context";
-export * from "./auth-events";
-export * from "./auth-machine";
+export * from "./machine/auth-events";
+export * from "./machine/auth-machine";
export * from "./auth-types";
diff --git a/src/stores/auth/auth-context.tsx b/src/stores/auth/machine/auth-context.tsx
similarity index 95%
rename from src/stores/auth/auth-context.tsx
rename to src/stores/auth/machine/auth-context.tsx
index 8fa7c09c..020356fe 100644
--- a/src/stores/auth/auth-context.tsx
+++ b/src/stores/auth/machine/auth-context.tsx
@@ -18,12 +18,12 @@ import {
import { useMachine } from "@xstate/react";
import { authMachine } from "./auth-machine";
-import type { AuthEvent, AuthContext as MachineContext } from "./auth-machine";
+import type { AuthEvent, AuthState as MachineContext } from "./auth-machine";
/**
* 对外暴露的 State 形状(保持与原 AuthState 兼容)
*/
-export interface AuthState {
+interface AuthState {
authPanelMode: MachineContext["authPanelMode"];
authMode: MachineContext["authMode"];
email: string;
diff --git a/src/stores/auth/auth-events.ts b/src/stores/auth/machine/auth-events.ts
similarity index 100%
rename from src/stores/auth/auth-events.ts
rename to src/stores/auth/machine/auth-events.ts
diff --git a/src/stores/auth/auth-machine.ts b/src/stores/auth/machine/auth-machine.ts
similarity index 91%
rename from src/stores/auth/auth-machine.ts
rename to src/stores/auth/machine/auth-machine.ts
index f692a0b6..1e494795 100644
--- a/src/stores/auth/auth-machine.ts
+++ b/src/stores/auth/machine/auth-machine.ts
@@ -4,8 +4,8 @@
* 原始 Dart: lib/ui/auth/bloc/auth_bloc.dart + auth_state.dart + auth_event.dart
*
* 本轮迁移:社交登录改由 NextAuth 处理(`@/lib/auth/nextauth`),状态机仅保留
- * 邮箱注册/登录 + 通用 reset 事件。社交登录走 `new GoogleLogin().signIn()` /
- * `new FacebookLogin().signIn()`。
+ * 邮箱注册/登录 + 通用 reset 事件。社交登录走 `new AuthPlatform("google").signIn()` /
+ * `new AuthPlatform("facebook").signIn()`。
*/
import { setup, fromPromise, assign } from "xstate";
@@ -14,12 +14,12 @@ import { authRepository } from "@/data/repositories/auth_repository";
import { AuthStorage } from "@/data/storage/auth/auth_storage";
import { Result } from "@/utils/result";
-import { AuthContext, initialContext } from "./auth-context";
+import { AuthState, initialState } from "../auth-state";
import type { AuthEvent } from "./auth-events";
-// 重新导出 Context / Event 类型,保持 machine 文件的公共 API 不变
-export type { AuthContext } from "./auth-context";
-export { initialContext } from "./auth-context";
+// 重新导出 State / Event 类型,保持 machine 文件的公共 API 不变
+export type { AuthState } from "../auth-state";
+export { initialState } from "../auth-state";
export type { AuthEvent } from "./auth-events";
// ============================================================
@@ -73,7 +73,7 @@ const emailRegisterThenLoginActor = fromPromise<
// ============================================================
export const authMachine = setup({
types: {
- context: {} as AuthContext,
+ context: {} as AuthState,
events: {} as AuthEvent,
},
actors: {
@@ -83,7 +83,7 @@ export const authMachine = setup({
}).createMachine({
id: "auth",
initial: "idle",
- context: initialContext,
+ context: initialState,
states: {
idle: {
on: {
@@ -109,11 +109,11 @@ export const authMachine = setup({
}),
},
AuthReset: {
- actions: assign(() => initialContext),
+ actions: assign(() => initialState),
},
AuthEmailLoginSubmitted: "loadingEmailLogin",
AuthEmailRegisterSubmitted: "loadingEmailRegister",
- // 社交登录已迁移到 NextAuth + GoogleLogin / FacebookLogin 类
+ // 社交登录已迁移到 NextAuth + AuthPlatform 类
// 状态机保留事件以兼容旧调用方(实际不再触发)
AuthGoogleLoginSubmitted: {},
AuthFacebookLoginSubmitted: {},
diff --git a/src/stores/chat/chat-context.tsx b/src/stores/chat/chat-context.tsx
index df03d662..2efe40ed 100644
--- a/src/stores/chat/chat-context.tsx
+++ b/src/stores/chat/chat-context.tsx
@@ -20,13 +20,13 @@ import {
} from "react";
import { useMachine } from "@xstate/react";
-import { chatMachine } from "./chat-machine";
-import type { ChatEvent, ChatContext as MachineContext } from "./chat-machine";
+import { chatMachine } from "./machine/chat-machine";
+import type { ChatEvent, ChatState as MachineContext } from "./machine/chat-machine";
/**
* 对外暴露的 State 形状(保持与原 ChatState 兼容)
*/
-export interface ChatState {
+interface ChatState {
messages: MachineContext["messages"];
isReplyingAI: boolean;
isGuest: boolean;
diff --git a/src/stores/chat/chat-types.ts b/src/stores/chat/chat-types.ts
index 7d67d910..b4319e57 100644
--- a/src/stores/chat/chat-types.ts
+++ b/src/stores/chat/chat-types.ts
@@ -8,5 +8,5 @@
* - `ChatState` 由 `chat-context.tsx` 导出(保持原 API 兼容)
* - `GuestChatQuota` 仍由 `chat-machine.ts` 导出(业务常量,与上下文配对紧密)
*/
-export type { ChatEvent } from "./chat-events";
+export type { ChatEvent } from "./machine/chat-events";
export { GuestChatQuota } from "./chat-machine";
diff --git a/src/stores/chat/index.ts b/src/stores/chat/index.ts
index a1b064a2..d9b4c66f 100644
--- a/src/stores/chat/index.ts
+++ b/src/stores/chat/index.ts
@@ -11,7 +11,8 @@
* 注:chat-side-effects.ts 暂未删除(其中 WebSocket 长生命周期逻辑
* 待下一轮迁移到 fromCallback actor)。
*/
+export * from "./machine/chat-state";
export * from "./chat-context";
-export * from "./chat-events";
+export * from "./machine/chat-events";
export * from "./chat-types";
export { chatMachine } from "./chat-machine";
diff --git a/src/stores/chat/chat-events.ts b/src/stores/chat/machine/chat-events.ts
similarity index 100%
rename from src/stores/chat/chat-events.ts
rename to src/stores/chat/machine/chat-events.ts
diff --git a/src/stores/chat/chat-machine.ts b/src/stores/chat/machine/chat-machine.ts
similarity index 95%
rename from src/stores/chat/chat-machine.ts
rename to src/stores/chat/machine/chat-machine.ts
index 4aef4435..5efae4c3 100644
--- a/src/stores/chat/chat-machine.ts
+++ b/src/stores/chat/machine/chat-machine.ts
@@ -23,8 +23,8 @@ import { AuthStorage } from "@/data/storage/auth/auth_storage";
import { formatDate } from "@/utils/date";
import { Result } from "@/utils/result";
-import { ChatContext, initialContext } from "./chat-context";
-import type { ChatEvent } from "./chat-events";
+import { ChatState, initialState } from "./chat-state";
+import type { ChatEvent } from "./machine/chat-events";
/** 游客配额阈值(与 Dart `GuestChatQuota` 保持一致) */
export const GuestChatQuota = {
@@ -32,10 +32,10 @@ export const GuestChatQuota = {
quotaExhausted: 0,
} as const;
-// 重新导出 Context / Event 类型,保持 machine 文件的公共 API 不变
-export type { ChatContext } from "./chat-context";
-export { initialContext } from "./chat-context";
-export type { ChatEvent } from "./chat-events";
+// 重新导出 State / Event 类型,保持 machine 文件的公共 API 不变
+export type { ChatState } from "./chat-state";
+export { initialState } from "./chat-state";
+export type { ChatEvent } from "./machine/chat-events";
// ============================================================
// Helpers
@@ -146,7 +146,7 @@ const loadMoreHistoryActor = fromPromise<
// ============================================================
export const chatMachine = setup({
types: {
- context: {} as ChatContext,
+ context: {} as ChatState,
events: {} as ChatEvent,
},
actors: {
@@ -230,7 +230,7 @@ export const chatMachine = setup({
}).createMachine({
id: "chat",
initial: "idle",
- context: initialContext,
+ context: initialState,
states: {
idle: {
on: {
diff --git a/src/stores/chat/chat-context.ts b/src/stores/chat/machine/chat-state.ts
similarity index 83%
rename from src/stores/chat/chat-context.ts
rename to src/stores/chat/machine/chat-state.ts
index ba882afd..ed204a32 100644
--- a/src/stores/chat/chat-context.ts
+++ b/src/stores/chat/machine/chat-state.ts
@@ -1,11 +1,11 @@
/**
- * Chat 状态机:Context 形状 + 初始值
+ * Chat 状态机:State 形状 + 初始值
*
* 注:GuestChatQuota 仍位于 chat-machine.ts(属于业务常量,与上下文配对紧密)。
*/
import type { UiMessage } from "@/models/chat/ui-message";
-export interface ChatContext {
+export interface ChatState {
messages: UiMessage[];
isReplyingAI: boolean;
isGuest: boolean;
@@ -17,7 +17,7 @@ export interface ChatContext {
historyOffset: number;
}
-export const initialContext: ChatContext = {
+export const initialState: ChatState = {
messages: [],
isReplyingAI: false,
isGuest: true,
diff --git a/src/stores/sidebar/index.ts b/src/stores/sidebar/index.ts
index 6ef25855..9d43e4b3 100644
--- a/src/stores/sidebar/index.ts
+++ b/src/stores/sidebar/index.ts
@@ -8,7 +8,8 @@
* - Context 形状与初始值位于 sidebar-context.ts
* - 事件联合位于 sidebar-events.ts
*/
+export * from "./sidebar-state";
export * from "./sidebar-context";
export * from "./sidebar-events";
export * from "./sidebar-types";
-export { sidebarMachine } from "./sidebar-machine";
+export { sidebarMachine } from "./machine/sidebar-machine";
diff --git a/src/stores/sidebar/sidebar-events.ts b/src/stores/sidebar/machine/sidebar-events.ts
similarity index 100%
rename from src/stores/sidebar/sidebar-events.ts
rename to src/stores/sidebar/machine/sidebar-events.ts
diff --git a/src/stores/sidebar/sidebar-machine.ts b/src/stores/sidebar/machine/sidebar-machine.ts
similarity index 88%
rename from src/stores/sidebar/sidebar-machine.ts
rename to src/stores/sidebar/machine/sidebar-machine.ts
index 21fffd43..f6e747b1 100644
--- a/src/stores/sidebar/sidebar-machine.ts
+++ b/src/stores/sidebar/machine/sidebar-machine.ts
@@ -11,7 +11,7 @@
*/
import { setup, assign } from "xstate";
-import { SidebarContext, initialContext } from "./sidebar-context";
+import { SidebarState, initialState } from "../sidebar-state";
import type { SidebarEvent } from "./sidebar-events";
/**
@@ -36,9 +36,9 @@ export const BottomNavItem = {
export type BottomNavItem = (typeof BottomNavItem)[keyof typeof BottomNavItem];
-// 重新导出 Context / Event 类型,保持 machine 文件的公共 API 不变
-export type { SidebarContext } from "./sidebar-context";
-export { initialContext } from "./sidebar-context";
+// 重新导出 State / Event 类型,保持 machine 文件的公共 API 不变
+export type { SidebarState } from "../sidebar-state";
+export { initialState } from "../sidebar-state";
export type { SidebarEvent } from "./sidebar-events";
// ============================================================
@@ -46,7 +46,7 @@ export type { SidebarEvent } from "./sidebar-events";
// ============================================================
export const sidebarMachine = setup({
types: {
- context: {} as SidebarContext,
+ context: {} as SidebarState,
events: {} as SidebarEvent,
},
actions: {
@@ -73,7 +73,7 @@ export const sidebarMachine = setup({
}).createMachine({
id: "sidebar",
initial: "idle",
- context: initialContext,
+ context: initialState,
states: {
/**
* Sidebar 是纯数据状态(无异步副作用),仅用 idle 状态
diff --git a/src/stores/sidebar/sidebar-context.ts b/src/stores/sidebar/machine/sidebar-state.ts
similarity index 65%
rename from src/stores/sidebar/sidebar-context.ts
rename to src/stores/sidebar/machine/sidebar-state.ts
index e70da168..dd53b815 100644
--- a/src/stores/sidebar/sidebar-context.ts
+++ b/src/stores/sidebar/machine/sidebar-state.ts
@@ -1,18 +1,18 @@
/**
- * Sidebar 状态机:Context 形状 + 初始值
+ * Sidebar 状态机:State 形状 + 初始值
*
* SidebarPage / BottomNavItem 仍由 sidebar-machine.ts 导出(事件/上下文均需引用)。
*/
-import { SidebarPage, BottomNavItem } from "./sidebar-machine";
+import { SidebarPage, BottomNavItem } from "./machine/sidebar-machine";
-export interface SidebarContext {
+export interface SidebarState {
currentPage: SidebarPage;
selectedBottomNavItem: BottomNavItem;
characterName: string;
characterProgress: number;
}
-export const initialContext: SidebarContext = {
+export const initialState: SidebarState = {
currentPage: SidebarPage.DefaultView,
selectedBottomNavItem: BottomNavItem.None,
characterName: "Luna",
diff --git a/src/stores/sidebar/sidebar-context.tsx b/src/stores/sidebar/sidebar-context.tsx
index f5c04560..1b02bc31 100644
--- a/src/stores/sidebar/sidebar-context.tsx
+++ b/src/stores/sidebar/sidebar-context.tsx
@@ -17,16 +17,16 @@ import {
} from "react";
import { useMachine } from "@xstate/react";
-import { sidebarMachine } from "./sidebar-machine";
+import { sidebarMachine } from "./machine/sidebar-machine";
import type {
- SidebarContext as MachineContext,
+ SidebarState as MachineContext,
SidebarEvent,
-} from "./sidebar-machine";
+} from "./machine/sidebar-machine";
/**
* 对外暴露的 State 形状(保持与原 SidebarState 兼容)
*/
-export interface SidebarState {
+interface SidebarState {
currentPage: MachineContext["currentPage"];
selectedBottomNavItem: MachineContext["selectedBottomNavItem"];
characterName: string;
diff --git a/src/stores/sidebar/sidebar-types.ts b/src/stores/sidebar/sidebar-types.ts
index a81b4c77..b9e00e7a 100644
--- a/src/stores/sidebar/sidebar-types.ts
+++ b/src/stores/sidebar/sidebar-types.ts
@@ -8,5 +8,5 @@
* - Context 形状由 `sidebar-context.ts` 导出
* - SidebarState 由 `sidebar-context.tsx` 导出(保持原 API 兼容)
*/
-export { SidebarPage, BottomNavItem } from "./sidebar-machine";
+export { SidebarPage, BottomNavItem } from "./machine/sidebar-machine";
export type { SidebarEvent } from "./sidebar-events";
diff --git a/src/stores/user/index.ts b/src/stores/user/index.ts
index 47edfcf8..07faba26 100644
--- a/src/stores/user/index.ts
+++ b/src/stores/user/index.ts
@@ -8,7 +8,8 @@
* - Context 形状与初始值位于 user-context.ts
* - 事件联合位于 user-events.ts
*/
+export * from "./machine/user-state";
export * from "./user-context";
-export * from "./user-events";
+export * from "./machine/user-events";
export * from "./user-types";
export { userMachine } from "./user-machine";
diff --git a/src/stores/user/user-events.ts b/src/stores/user/machine/user-events.ts
similarity index 100%
rename from src/stores/user/user-events.ts
rename to src/stores/user/machine/user-events.ts
diff --git a/src/stores/user/user-machine.ts b/src/stores/user/machine/user-machine.ts
similarity index 92%
rename from src/stores/user/user-machine.ts
rename to src/stores/user/machine/user-machine.ts
index c5006026..7b5afade 100644
--- a/src/stores/user/user-machine.ts
+++ b/src/stores/user/machine/user-machine.ts
@@ -17,13 +17,13 @@ import { authRepository } from "@/data/repositories/auth_repository";
import { UserStorage } from "@/data/storage/user/user_storage";
import { Result } from "@/utils/result";
-import { UserContext, initialContext } from "./user-context";
-import type { UserEvent } from "./user-events";
+import { UserState, initialState } from "./machine/user-state";
+import type { UserEvent } from "./machine/user-events";
-// 重新导出 Context / Event 类型,保持 machine 文件的公共 API 不变
-export type { UserContext } from "./user-context";
-export { initialContext } from "./user-context";
-export type { UserEvent } from "./user-events";
+// 重新导出 State / Event 类型,保持 machine 文件的公共 API 不变
+export type { UserState } from "./machine/user-state";
+export { initialState } from "./machine/user-state";
+export type { UserEvent } from "./machine/user-events";
// ============================================================
// Helpers
@@ -102,7 +102,7 @@ const userLogoutActor = fromPromise(async () => {
// ============================================================
export const userMachine = setup({
types: {
- context: {} as UserContext,
+ context: {} as UserState,
events: {} as UserEvent,
},
actors: {
@@ -136,7 +136,7 @@ export const userMachine = setup({
}).createMachine({
id: "user",
initial: "idle",
- context: initialContext,
+ context: initialState,
states: {
idle: {
on: {
diff --git a/src/stores/user/user-context.ts b/src/stores/user/machine/user-state.ts
similarity index 70%
rename from src/stores/user/user-context.ts
rename to src/stores/user/machine/user-state.ts
index aeecf8d9..b7a6e3a0 100644
--- a/src/stores/user/user-context.ts
+++ b/src/stores/user/machine/user-state.ts
@@ -1,9 +1,9 @@
/**
- * User 状态机:Context 形状 + 初始值
+ * User 状态机:State 形状 + 初始值
*/
import type { UserView } from "@/models/user/user";
-export interface UserContext {
+export interface UserState {
currentUser: UserView | null;
pronouns: string;
coinBalance: number;
@@ -11,7 +11,7 @@ export interface UserContext {
avatarUrl: string | null;
}
-export const initialContext: UserContext = {
+export const initialState: UserState = {
currentUser: null,
pronouns: "He",
coinBalance: 45,
diff --git a/src/stores/user/user-context.tsx b/src/stores/user/user-context.tsx
index db86c1cd..399b1d71 100644
--- a/src/stores/user/user-context.tsx
+++ b/src/stores/user/user-context.tsx
@@ -18,12 +18,12 @@ import {
import { useMachine } from "@xstate/react";
import { userMachine } from "./user-machine";
-import type { UserContext as MachineContext, UserEvent } from "./user-machine";
+import type { UserState as MachineContext, UserEvent } from "./user-machine";
/**
* 对外暴露的 State 形状(保持与原 UserState 兼容)
*/
-export interface UserState {
+interface UserState {
currentUser: MachineContext["currentUser"];
pronouns: string;
coinBalance: number;
diff --git a/src/stores/user/user-types.ts b/src/stores/user/user-types.ts
index 738d2605..3d4c47b5 100644
--- a/src/stores/user/user-types.ts
+++ b/src/stores/user/user-types.ts
@@ -7,4 +7,4 @@
* - Context 形状与初始值由 `user-context.ts` 导出
* - `UserState` 由 `user-context.tsx` 导出(保持原 API 兼容)
*/
-export type { UserEvent } from "./user-events";
+export type { UserEvent } from "./machine/user-events";