refactor(stores): split state and event unions into separate files
Extract `<Name>Context` interface + `initialContext` const into `<name>-context.ts` and the event union into `<name>-events.ts` for all four state machines (auth, chat, sidebar, user) under src/stores/. - `*-machine.ts` keeps helpers, actors, actions, and the `setup().createMachine()` body; re-exports the types/initial value to preserve its public API. - `*-types.ts` re-exports from the new files for backward compatibility (sidebar keeps enum re-exports, chat keeps GuestChatQuota). - `index.ts` barrels updated to re-export the new files. - Removed unused model imports (AuthMode, AuthPanelMode) from auth-machine.ts; kept LoginType, UiMessage, UserView where still used by actors/helpers. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* Auth 状态机:Context 形状 + 初始值
|
||||||
|
*/
|
||||||
|
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 {
|
||||||
|
/** 当前面板模式(Facebook / Email) */
|
||||||
|
authPanelMode: AuthPanelMode;
|
||||||
|
/** 内部登录模式(login / register) */
|
||||||
|
authMode: AuthMode;
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
username: string;
|
||||||
|
confirmPassword: string;
|
||||||
|
errorMessage: string | null;
|
||||||
|
loginType: LoginType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const initialContext: AuthContext = {
|
||||||
|
authPanelMode: "facebook",
|
||||||
|
authMode: "login",
|
||||||
|
email: "",
|
||||||
|
password: "",
|
||||||
|
username: "",
|
||||||
|
confirmPassword: "",
|
||||||
|
errorMessage: null,
|
||||||
|
loginType: "none",
|
||||||
|
};
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* Auth 状态机:事件联合
|
||||||
|
*
|
||||||
|
* 事件名与原 Dart AuthEvent 对齐。
|
||||||
|
*/
|
||||||
|
import type { AuthMode } from "@/models/auth/auth-mode";
|
||||||
|
import type { AuthPanelMode } from "@/models/auth/auth-panel-mode";
|
||||||
|
|
||||||
|
export type AuthEvent =
|
||||||
|
// 内部 UI 事件
|
||||||
|
| { type: "AuthPanelModeChanged"; mode: AuthPanelMode }
|
||||||
|
| { type: "AuthModeChanged"; mode: AuthMode }
|
||||||
|
| { type: "AuthFormCleared" }
|
||||||
|
| { type: "AuthReset" }
|
||||||
|
// 业务事件(提交)
|
||||||
|
| { type: "AuthEmailLoginSubmitted"; email: string; password: string }
|
||||||
|
| {
|
||||||
|
type: "AuthEmailRegisterSubmitted";
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
username: string;
|
||||||
|
confirmPassword: string;
|
||||||
|
}
|
||||||
|
// 社交登录(已迁移到 NextAuth)— 业务层直接 await nextauth.googleLogin() 即可
|
||||||
|
| { type: "AuthGoogleLoginSubmitted" }
|
||||||
|
| { type: "AuthFacebookLoginSubmitted" }
|
||||||
|
| { type: "AuthAppleLoginSubmitted" };
|
||||||
@@ -9,62 +9,18 @@
|
|||||||
*/
|
*/
|
||||||
import { setup, fromPromise, assign } from "xstate";
|
import { setup, fromPromise, assign } from "xstate";
|
||||||
|
|
||||||
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";
|
import type { LoginType } from "@/models/auth/login-type";
|
||||||
import { authRepository } from "@/data/repositories/auth_repository";
|
import { authRepository } from "@/data/repositories/auth_repository";
|
||||||
import { AuthStorage } from "@/data/storage/auth/auth_storage";
|
import { AuthStorage } from "@/data/storage/auth/auth_storage";
|
||||||
import { Result } from "@/utils/result";
|
import { Result } from "@/utils/result";
|
||||||
|
|
||||||
// ============================================================
|
import { AuthContext, initialContext } from "./auth-context";
|
||||||
// Context
|
import type { AuthEvent } from "./auth-events";
|
||||||
// ============================================================
|
|
||||||
export interface AuthContext {
|
|
||||||
/** 当前面板模式(Facebook / Email) */
|
|
||||||
authPanelMode: AuthPanelMode;
|
|
||||||
/** 内部登录模式(login / register) */
|
|
||||||
authMode: AuthMode;
|
|
||||||
email: string;
|
|
||||||
password: string;
|
|
||||||
username: string;
|
|
||||||
confirmPassword: string;
|
|
||||||
errorMessage: string | null;
|
|
||||||
loginType: LoginType;
|
|
||||||
}
|
|
||||||
|
|
||||||
const initialContext: AuthContext = {
|
// 重新导出 Context / Event 类型,保持 machine 文件的公共 API 不变
|
||||||
authPanelMode: "facebook",
|
export type { AuthContext } from "./auth-context";
|
||||||
authMode: "login",
|
export { initialContext } from "./auth-context";
|
||||||
email: "",
|
export type { AuthEvent } from "./auth-events";
|
||||||
password: "",
|
|
||||||
username: "",
|
|
||||||
confirmPassword: "",
|
|
||||||
errorMessage: null,
|
|
||||||
loginType: "none",
|
|
||||||
};
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// Events(事件类型名与原 Dart AuthEvent 对齐)
|
|
||||||
// ============================================================
|
|
||||||
export type AuthEvent =
|
|
||||||
// 内部 UI 事件
|
|
||||||
| { type: "AuthPanelModeChanged"; mode: AuthPanelMode }
|
|
||||||
| { type: "AuthModeChanged"; mode: AuthMode }
|
|
||||||
| { type: "AuthFormCleared" }
|
|
||||||
| { type: "AuthReset" }
|
|
||||||
// 业务事件(提交)
|
|
||||||
| { type: "AuthEmailLoginSubmitted"; email: string; password: string }
|
|
||||||
| {
|
|
||||||
type: "AuthEmailRegisterSubmitted";
|
|
||||||
email: string;
|
|
||||||
password: string;
|
|
||||||
username: string;
|
|
||||||
confirmPassword: string;
|
|
||||||
}
|
|
||||||
// 社交登录(已迁移到 NextAuth)— 业务层走 GoogleLogin / FacebookLogin 类
|
|
||||||
| { type: "AuthGoogleLoginSubmitted" }
|
|
||||||
| { type: "AuthFacebookLoginSubmitted" }
|
|
||||||
| { type: "AuthAppleLoginSubmitted" };
|
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Helpers
|
// Helpers
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
*
|
*
|
||||||
* 原始文件定义了 AuthState 接口、AuthEvent 联合、initialAuthState。
|
* 原始文件定义了 AuthState 接口、AuthEvent 联合、initialAuthState。
|
||||||
* 状态机重构后:
|
* 状态机重构后:
|
||||||
* - `AuthEvent` 联合由 `auth-machine.ts` 重新导出(保留类型)
|
* - `AuthEvent` 联合由 `auth-events.ts` 导出
|
||||||
|
* - Context 形状与初始值由 `auth-context.ts` 导出
|
||||||
* - `AuthState` 由 `auth-context.tsx` 导出(保持原 API 兼容)
|
* - `AuthState` 由 `auth-context.tsx` 导出(保持原 API 兼容)
|
||||||
*/
|
*/
|
||||||
export type { AuthEvent } from "./auth-machine";
|
export type { AuthEvent } from "./auth-events";
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
/**
|
/**
|
||||||
* @file Automatically generated by barrelsby.
|
* @file Auth 公共导出
|
||||||
|
*
|
||||||
|
* 状态机重构后:
|
||||||
|
* - Context 形状与初始值位于 auth-context.ts
|
||||||
|
* - 事件联合位于 auth-events.ts
|
||||||
|
* - machine / 类型 / React 入口分别由对应文件导出
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export * from "./auth-context";
|
export * from "./auth-context";
|
||||||
|
export * from "./auth-events";
|
||||||
export * from "./auth-machine";
|
export * from "./auth-machine";
|
||||||
export * from "./auth-types";
|
export * from "./auth-types";
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* Chat 状态机:Context 形状 + 初始值
|
||||||
|
*
|
||||||
|
* 注:GuestChatQuota 仍位于 chat-machine.ts(属于业务常量,与上下文配对紧密)。
|
||||||
|
*/
|
||||||
|
import type { UiMessage } from "@/models/chat/ui-message";
|
||||||
|
|
||||||
|
export interface ChatContext {
|
||||||
|
messages: UiMessage[];
|
||||||
|
isReplyingAI: boolean;
|
||||||
|
isGuest: boolean;
|
||||||
|
guestRemainingQuota: number;
|
||||||
|
guestTotalQuota: number;
|
||||||
|
quotaExceededTrigger: number;
|
||||||
|
isLoadingMore: boolean;
|
||||||
|
hasMore: boolean;
|
||||||
|
historyOffset: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const initialContext: ChatContext = {
|
||||||
|
messages: [],
|
||||||
|
isReplyingAI: false,
|
||||||
|
isGuest: true,
|
||||||
|
guestRemainingQuota: 40,
|
||||||
|
guestTotalQuota: 50,
|
||||||
|
quotaExceededTrigger: 0,
|
||||||
|
isLoadingMore: false,
|
||||||
|
hasMore: true,
|
||||||
|
historyOffset: 0,
|
||||||
|
};
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* Chat 状态机:事件联合
|
||||||
|
*
|
||||||
|
* 事件名与原 Dart ChatEvent 对齐。
|
||||||
|
*/
|
||||||
|
export type ChatEvent =
|
||||||
|
| { type: "ChatInit" }
|
||||||
|
| { type: "ChatScreenVisible" }
|
||||||
|
| { type: "ChatScreenInvisible" }
|
||||||
|
| { type: "ChatSendMessage"; content: string }
|
||||||
|
| { type: "ChatSendImage"; imageBase64: string }
|
||||||
|
| { type: "ChatLoadMoreHistory" }
|
||||||
|
| {
|
||||||
|
type: "ChatAISentenceReceived";
|
||||||
|
index: number;
|
||||||
|
text: string;
|
||||||
|
total: number;
|
||||||
|
done: boolean;
|
||||||
|
}
|
||||||
|
| { type: "ChatWebSocketError"; errorMessage: string }
|
||||||
|
| { type: "ChatWebSocketConnected"; userId: string }
|
||||||
|
| { type: "ChatQuotaExceeded" }
|
||||||
|
| { type: "ChatAuthStatusChanged" };
|
||||||
@@ -23,32 +23,8 @@ import { AuthStorage } from "@/data/storage/auth/auth_storage";
|
|||||||
import { formatDate } from "@/utils/date";
|
import { formatDate } from "@/utils/date";
|
||||||
import { Result } from "@/utils/result";
|
import { Result } from "@/utils/result";
|
||||||
|
|
||||||
// ============================================================
|
import { ChatContext, initialContext } from "./chat-context";
|
||||||
// Context
|
import type { ChatEvent } from "./chat-events";
|
||||||
// ============================================================
|
|
||||||
export interface ChatContext {
|
|
||||||
messages: UiMessage[];
|
|
||||||
isReplyingAI: boolean;
|
|
||||||
isGuest: boolean;
|
|
||||||
guestRemainingQuota: number;
|
|
||||||
guestTotalQuota: number;
|
|
||||||
quotaExceededTrigger: number;
|
|
||||||
isLoadingMore: boolean;
|
|
||||||
hasMore: boolean;
|
|
||||||
historyOffset: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const initialContext: ChatContext = {
|
|
||||||
messages: [],
|
|
||||||
isReplyingAI: false,
|
|
||||||
isGuest: true,
|
|
||||||
guestRemainingQuota: 40,
|
|
||||||
guestTotalQuota: 50,
|
|
||||||
quotaExceededTrigger: 0,
|
|
||||||
isLoadingMore: false,
|
|
||||||
hasMore: true,
|
|
||||||
historyOffset: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 游客配额阈值(与 Dart `GuestChatQuota` 保持一致) */
|
/** 游客配额阈值(与 Dart `GuestChatQuota` 保持一致) */
|
||||||
export const GuestChatQuota = {
|
export const GuestChatQuota = {
|
||||||
@@ -56,27 +32,10 @@ export const GuestChatQuota = {
|
|||||||
quotaExhausted: 0,
|
quotaExhausted: 0,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
// ============================================================
|
// 重新导出 Context / Event 类型,保持 machine 文件的公共 API 不变
|
||||||
// Events
|
export type { ChatContext } from "./chat-context";
|
||||||
// ============================================================
|
export { initialContext } from "./chat-context";
|
||||||
export type ChatEvent =
|
export type { ChatEvent } from "./chat-events";
|
||||||
| { type: "ChatInit" }
|
|
||||||
| { type: "ChatScreenVisible" }
|
|
||||||
| { type: "ChatScreenInvisible" }
|
|
||||||
| { type: "ChatSendMessage"; content: string }
|
|
||||||
| { type: "ChatSendImage"; imageBase64: string }
|
|
||||||
| { type: "ChatLoadMoreHistory" }
|
|
||||||
| {
|
|
||||||
type: "ChatAISentenceReceived";
|
|
||||||
index: number;
|
|
||||||
text: string;
|
|
||||||
total: number;
|
|
||||||
done: boolean;
|
|
||||||
}
|
|
||||||
| { type: "ChatWebSocketError"; errorMessage: string }
|
|
||||||
| { type: "ChatWebSocketConnected"; userId: string }
|
|
||||||
| { type: "ChatQuotaExceeded" }
|
|
||||||
| { type: "ChatAuthStatusChanged" };
|
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Helpers
|
// Helpers
|
||||||
|
|||||||
@@ -3,9 +3,10 @@
|
|||||||
*
|
*
|
||||||
* 原始文件定义了 ChatState 接口、ChatEvent 联合、initialChatState、GuestChatQuota。
|
* 原始文件定义了 ChatState 接口、ChatEvent 联合、initialChatState、GuestChatQuota。
|
||||||
* 状态机重构后:
|
* 状态机重构后:
|
||||||
* - `ChatEvent` 联合由 `chat-machine.ts` 重新导出(保留类型)
|
* - `ChatEvent` 联合由 `chat-events.ts` 导出
|
||||||
|
* - Context 形状与初始值由 `chat-context.ts` 导出
|
||||||
* - `ChatState` 由 `chat-context.tsx` 导出(保持原 API 兼容)
|
* - `ChatState` 由 `chat-context.tsx` 导出(保持原 API 兼容)
|
||||||
* - `GuestChatQuota` 重新导出
|
* - `GuestChatQuota` 仍由 `chat-machine.ts` 导出(业务常量,与上下文配对紧密)
|
||||||
*/
|
*/
|
||||||
export type { ChatEvent } from "./chat-machine";
|
export type { ChatEvent } from "./chat-events";
|
||||||
export { GuestChatQuota } from "./chat-machine";
|
export { GuestChatQuota } from "./chat-machine";
|
||||||
|
|||||||
@@ -5,10 +5,13 @@
|
|||||||
* - 业务类(Dart 风格 context/reducer/side-effects)已合并到 chat-machine.ts
|
* - 业务类(Dart 风格 context/reducer/side-effects)已合并到 chat-machine.ts
|
||||||
* - 类型由 chat-types.ts 重新导出
|
* - 类型由 chat-types.ts 重新导出
|
||||||
* - React 入口为 chat-context.tsx(useMachine 包装)
|
* - React 入口为 chat-context.tsx(useMachine 包装)
|
||||||
|
* - Context 形状与初始值位于 chat-context.ts
|
||||||
|
* - 事件联合位于 chat-events.ts
|
||||||
*
|
*
|
||||||
* 注:chat-side-effects.ts 暂未删除(其中 WebSocket 长生命周期逻辑
|
* 注:chat-side-effects.ts 暂未删除(其中 WebSocket 长生命周期逻辑
|
||||||
* 待下一轮迁移到 fromCallback actor)。
|
* 待下一轮迁移到 fromCallback actor)。
|
||||||
*/
|
*/
|
||||||
export * from "./chat-context";
|
export * from "./chat-context";
|
||||||
|
export * from "./chat-events";
|
||||||
export * from "./chat-types";
|
export * from "./chat-types";
|
||||||
export { chatMachine } from "./chat-machine";
|
export { chatMachine } from "./chat-machine";
|
||||||
|
|||||||
@@ -5,7 +5,10 @@
|
|||||||
* - reducer 逻辑已合并到 sidebar-machine.ts
|
* - reducer 逻辑已合并到 sidebar-machine.ts
|
||||||
* - 类型由 sidebar-types.ts 重新导出
|
* - 类型由 sidebar-types.ts 重新导出
|
||||||
* - React 入口为 sidebar-context.tsx(useMachine 包装)
|
* - React 入口为 sidebar-context.tsx(useMachine 包装)
|
||||||
|
* - Context 形状与初始值位于 sidebar-context.ts
|
||||||
|
* - 事件联合位于 sidebar-events.ts
|
||||||
*/
|
*/
|
||||||
export * from "./sidebar-context";
|
export * from "./sidebar-context";
|
||||||
|
export * from "./sidebar-events";
|
||||||
export * from "./sidebar-types";
|
export * from "./sidebar-types";
|
||||||
export { sidebarMachine } from "./sidebar-machine";
|
export { sidebarMachine } from "./sidebar-machine";
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* Sidebar 状态机:Context 形状 + 初始值
|
||||||
|
*
|
||||||
|
* SidebarPage / BottomNavItem 仍由 sidebar-machine.ts 导出(事件/上下文均需引用)。
|
||||||
|
*/
|
||||||
|
import { SidebarPage, BottomNavItem } from "./sidebar-machine";
|
||||||
|
|
||||||
|
export interface SidebarContext {
|
||||||
|
currentPage: SidebarPage;
|
||||||
|
selectedBottomNavItem: BottomNavItem;
|
||||||
|
characterName: string;
|
||||||
|
characterProgress: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const initialContext: SidebarContext = {
|
||||||
|
currentPage: SidebarPage.DefaultView,
|
||||||
|
selectedBottomNavItem: BottomNavItem.None,
|
||||||
|
characterName: "Luna",
|
||||||
|
characterProgress: 0,
|
||||||
|
};
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* Sidebar 状态机:事件联合
|
||||||
|
*/
|
||||||
|
import type { SidebarPage, BottomNavItem } from "./sidebar-machine";
|
||||||
|
|
||||||
|
export type SidebarEvent =
|
||||||
|
| {
|
||||||
|
type: "SidebarShowPage";
|
||||||
|
page: SidebarPage;
|
||||||
|
bottomNavItem?: BottomNavItem;
|
||||||
|
}
|
||||||
|
| { type: "SidebarClearBottomNav" }
|
||||||
|
| { type: "SidebarUpdateCharacter"; name: string; progress: number };
|
||||||
@@ -11,6 +11,9 @@
|
|||||||
*/
|
*/
|
||||||
import { setup, assign } from "xstate";
|
import { setup, assign } from "xstate";
|
||||||
|
|
||||||
|
import { SidebarContext, initialContext } from "./sidebar-context";
|
||||||
|
import type { SidebarEvent } from "./sidebar-events";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sidebar 页面/底部导航枚举(与原 sidebar-types.ts 保持一致)
|
* Sidebar 页面/底部导航枚举(与原 sidebar-types.ts 保持一致)
|
||||||
*/
|
*/
|
||||||
@@ -33,34 +36,10 @@ export const BottomNavItem = {
|
|||||||
|
|
||||||
export type BottomNavItem = (typeof BottomNavItem)[keyof typeof BottomNavItem];
|
export type BottomNavItem = (typeof BottomNavItem)[keyof typeof BottomNavItem];
|
||||||
|
|
||||||
// ============================================================
|
// 重新导出 Context / Event 类型,保持 machine 文件的公共 API 不变
|
||||||
// Context
|
export type { SidebarContext } from "./sidebar-context";
|
||||||
// ============================================================
|
export { initialContext } from "./sidebar-context";
|
||||||
export interface SidebarContext {
|
export type { SidebarEvent } from "./sidebar-events";
|
||||||
currentPage: SidebarPage;
|
|
||||||
selectedBottomNavItem: BottomNavItem;
|
|
||||||
characterName: string;
|
|
||||||
characterProgress: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const initialContext: SidebarContext = {
|
|
||||||
currentPage: SidebarPage.DefaultView,
|
|
||||||
selectedBottomNavItem: BottomNavItem.None,
|
|
||||||
characterName: "Luna",
|
|
||||||
characterProgress: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// Events
|
|
||||||
// ============================================================
|
|
||||||
export type SidebarEvent =
|
|
||||||
| {
|
|
||||||
type: "SidebarShowPage";
|
|
||||||
page: SidebarPage;
|
|
||||||
bottomNavItem?: BottomNavItem;
|
|
||||||
}
|
|
||||||
| { type: "SidebarClearBottomNav" }
|
|
||||||
| { type: "SidebarUpdateCharacter"; name: string; progress: number };
|
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Machine
|
// Machine
|
||||||
|
|||||||
@@ -3,12 +3,10 @@
|
|||||||
*
|
*
|
||||||
* 原始文件定义了 SidebarPage、BottomNavItem、SidebarState、SidebarEvent。
|
* 原始文件定义了 SidebarPage、BottomNavItem、SidebarState、SidebarEvent。
|
||||||
* 状态机重构后:
|
* 状态机重构后:
|
||||||
* - 枚举(SidebarPage、BottomNavItem)由 `sidebar-machine.ts` 重新导出
|
* - 枚举(SidebarPage、BottomNavItem)由 `sidebar-machine.ts` 导出
|
||||||
* - 事件联合(SidebarEvent)由 `sidebar-machine.ts` 重新导出
|
* - 事件联合(SidebarEvent)由 `sidebar-events.ts` 导出
|
||||||
|
* - Context 形状由 `sidebar-context.ts` 导出
|
||||||
* - SidebarState 由 `sidebar-context.tsx` 导出(保持原 API 兼容)
|
* - SidebarState 由 `sidebar-context.tsx` 导出(保持原 API 兼容)
|
||||||
*/
|
*/
|
||||||
export {
|
export { SidebarPage, BottomNavItem } from "./sidebar-machine";
|
||||||
SidebarPage,
|
export type { SidebarEvent } from "./sidebar-events";
|
||||||
BottomNavItem,
|
|
||||||
type SidebarEvent,
|
|
||||||
} from "./sidebar-machine";
|
|
||||||
|
|||||||
@@ -5,7 +5,10 @@
|
|||||||
* - 业务类(Dart 风格 context/reducer/side-effects)已合并到 user-machine.ts
|
* - 业务类(Dart 风格 context/reducer/side-effects)已合并到 user-machine.ts
|
||||||
* - 类型由 user-types.ts 重新导出
|
* - 类型由 user-types.ts 重新导出
|
||||||
* - React 入口为 user-context.tsx(useMachine 包装)
|
* - React 入口为 user-context.tsx(useMachine 包装)
|
||||||
|
* - Context 形状与初始值位于 user-context.ts
|
||||||
|
* - 事件联合位于 user-events.ts
|
||||||
*/
|
*/
|
||||||
export * from "./user-context";
|
export * from "./user-context";
|
||||||
|
export * from "./user-events";
|
||||||
export * from "./user-types";
|
export * from "./user-types";
|
||||||
export { userMachine } from "./user-machine";
|
export { userMachine } from "./user-machine";
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* User 状态机:Context 形状 + 初始值
|
||||||
|
*/
|
||||||
|
import type { UserView } from "@/models/user/user";
|
||||||
|
|
||||||
|
export interface UserContext {
|
||||||
|
currentUser: UserView | null;
|
||||||
|
pronouns: string;
|
||||||
|
coinBalance: number;
|
||||||
|
isLoading: boolean;
|
||||||
|
avatarUrl: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const initialContext: UserContext = {
|
||||||
|
currentUser: null,
|
||||||
|
pronouns: "He",
|
||||||
|
coinBalance: 45,
|
||||||
|
isLoading: false,
|
||||||
|
avatarUrl: null,
|
||||||
|
};
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* User 状态机:事件联合
|
||||||
|
*/
|
||||||
|
import type { UserView } from "@/models/user/user";
|
||||||
|
|
||||||
|
export type UserEvent =
|
||||||
|
| { type: "UserInit" }
|
||||||
|
| { type: "UserFetch" }
|
||||||
|
| { type: "UserUpdate"; user: UserView }
|
||||||
|
| { type: "UserUpdateUsername"; username: string }
|
||||||
|
| { type: "UserUpdatePronouns"; pronouns: string }
|
||||||
|
| { type: "UserLogout" }
|
||||||
|
| { type: "UserDeleteChatHistory" }
|
||||||
|
| { type: "UserDeleteAccount" };
|
||||||
@@ -17,37 +17,13 @@ import { authRepository } from "@/data/repositories/auth_repository";
|
|||||||
import { UserStorage } from "@/data/storage/user/user_storage";
|
import { UserStorage } from "@/data/storage/user/user_storage";
|
||||||
import { Result } from "@/utils/result";
|
import { Result } from "@/utils/result";
|
||||||
|
|
||||||
// ============================================================
|
import { UserContext, initialContext } from "./user-context";
|
||||||
// Context
|
import type { UserEvent } from "./user-events";
|
||||||
// ============================================================
|
|
||||||
export interface UserContext {
|
|
||||||
currentUser: UserView | null;
|
|
||||||
pronouns: string;
|
|
||||||
coinBalance: number;
|
|
||||||
isLoading: boolean;
|
|
||||||
avatarUrl: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const initialContext: UserContext = {
|
// 重新导出 Context / Event 类型,保持 machine 文件的公共 API 不变
|
||||||
currentUser: null,
|
export type { UserContext } from "./user-context";
|
||||||
pronouns: "He",
|
export { initialContext } from "./user-context";
|
||||||
coinBalance: 45,
|
export type { UserEvent } from "./user-events";
|
||||||
isLoading: false,
|
|
||||||
avatarUrl: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// Events
|
|
||||||
// ============================================================
|
|
||||||
export type UserEvent =
|
|
||||||
| { type: "UserInit" }
|
|
||||||
| { type: "UserFetch" }
|
|
||||||
| { type: "UserUpdate"; user: UserView }
|
|
||||||
| { type: "UserUpdateUsername"; username: string }
|
|
||||||
| { type: "UserUpdatePronouns"; pronouns: string }
|
|
||||||
| { type: "UserLogout" }
|
|
||||||
| { type: "UserDeleteChatHistory" }
|
|
||||||
| { type: "UserDeleteAccount" };
|
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Helpers
|
// Helpers
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
*
|
*
|
||||||
* 原始文件定义了 UserState 接口、UserEvent 联合、initialUserState。
|
* 原始文件定义了 UserState 接口、UserEvent 联合、initialUserState。
|
||||||
* 状态机重构后:
|
* 状态机重构后:
|
||||||
* - `UserEvent` 联合由 `user-machine.ts` 重新导出(保留类型)
|
* - `UserEvent` 联合由 `user-events.ts` 导出
|
||||||
|
* - Context 形状与初始值由 `user-context.ts` 导出
|
||||||
* - `UserState` 由 `user-context.tsx` 导出(保持原 API 兼容)
|
* - `UserState` 由 `user-context.tsx` 导出(保持原 API 兼容)
|
||||||
*/
|
*/
|
||||||
export type { UserEvent } from "./user-machine";
|
export type { UserEvent } from "./user-events";
|
||||||
|
|||||||
Reference in New Issue
Block a user