From 2207301ccb9d8d1ece8e63ca941c429134381756 Mon Sep 17 00:00:00 2001 From: chenhang Date: Mon, 29 Jun 2026 10:58:15 +0800 Subject: [PATCH] refactor(sidebar): remove unused store --- src/providers/root-providers.tsx | 17 ++--- .../sidebar/__tests__/sidebar-machine.test.ts | 61 --------------- src/stores/sidebar/index.ts | 8 -- src/stores/sidebar/sidebar-context.tsx | 72 ------------------ src/stores/sidebar/sidebar-events.ts | 13 ---- src/stores/sidebar/sidebar-machine.ts | 76 ------------------- src/stores/sidebar/sidebar-state.ts | 42 ---------- 7 files changed, 7 insertions(+), 282 deletions(-) delete mode 100644 src/stores/sidebar/__tests__/sidebar-machine.test.ts delete mode 100644 src/stores/sidebar/index.ts delete mode 100644 src/stores/sidebar/sidebar-context.tsx delete mode 100644 src/stores/sidebar/sidebar-events.ts delete mode 100644 src/stores/sidebar/sidebar-machine.ts delete mode 100644 src/stores/sidebar/sidebar-state.ts diff --git a/src/providers/root-providers.tsx b/src/providers/root-providers.tsx index f25948d5..e9cf499c 100644 --- a/src/providers/root-providers.tsx +++ b/src/providers/root-providers.tsx @@ -4,7 +4,7 @@ * 根级 Client Providers 包装 * * 把所有功能 Provider 串起来: - * AuthProvider → UserProvider → SidebarProvider → ChatProvider + * AuthProvider → UserProvider → PaymentProvider → ChatProvider * + AuthStatusChecker(启动时一次:派发 AuthInit) * + OAuthSessionSync (持续监听 NextAuth session → auth machine) * + UserAuthSync (auth 登录态恢复后 hydrate user machine) @@ -22,7 +22,6 @@ import { OAuthSessionSync } from "@/stores/auth/oauth-session-sync"; import { ChatAuthSync } from "@/stores/chat/chat-auth-sync"; import { ChatProvider } from "@/stores/chat/chat-context"; import { PaymentProvider, PaymentSuccessSync } from "@/stores/payment"; -import { SidebarProvider } from "@/stores/sidebar/sidebar-context"; import { UserAuthSync } from "@/stores/user/user-auth-sync"; import { UserProvider } from "@/stores/user/user-context"; @@ -41,14 +40,12 @@ export function RootProviders({ children }: RootProvidersProps) { - - - - - {children} -
- - + + + + {children} +
+ diff --git a/src/stores/sidebar/__tests__/sidebar-machine.test.ts b/src/stores/sidebar/__tests__/sidebar-machine.test.ts deleted file mode 100644 index bb1b9f1f..00000000 --- a/src/stores/sidebar/__tests__/sidebar-machine.test.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { createActor } from "xstate"; - -import { sidebarMachine } from "@/stores/sidebar/sidebar-machine"; -import { - BottomNavItem, - SidebarPage, -} from "@/stores/sidebar/sidebar-state"; - -describe("sidebarMachine", () => { - it("shows a page and selects the matching bottom nav item", () => { - const actor = createActor(sidebarMachine).start(); - - actor.send({ - type: "SidebarShowPage", - page: SidebarPage.Topics, - bottomNavItem: BottomNavItem.Topics, - }); - - expect(actor.getSnapshot().matches("idle")).toBe(true); - expect(actor.getSnapshot().context.currentPage).toBe(SidebarPage.Topics); - expect(actor.getSnapshot().context.selectedBottomNavItem).toBe( - BottomNavItem.Topics, - ); - - actor.stop(); - }); - - it("clears bottom nav without changing the current page", () => { - const actor = createActor(sidebarMachine).start(); - - actor.send({ - type: "SidebarShowPage", - page: SidebarPage.Gifts, - bottomNavItem: BottomNavItem.Gifts, - }); - actor.send({ type: "SidebarClearBottomNav" }); - - expect(actor.getSnapshot().context.currentPage).toBe(SidebarPage.Gifts); - expect(actor.getSnapshot().context.selectedBottomNavItem).toBe( - BottomNavItem.None, - ); - - actor.stop(); - }); - - it("updates character progress", () => { - const actor = createActor(sidebarMachine).start(); - - actor.send({ - type: "SidebarUpdateCharacter", - name: "Elio", - progress: 72, - }); - - expect(actor.getSnapshot().context.characterName).toBe("Elio"); - expect(actor.getSnapshot().context.characterProgress).toBe(72); - - actor.stop(); - }); -}); diff --git a/src/stores/sidebar/index.ts b/src/stores/sidebar/index.ts deleted file mode 100644 index 6a1b1ecf..00000000 --- a/src/stores/sidebar/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @file Automatically generated by barrelsby. - */ - -export * from "./sidebar-context"; -export * from "./sidebar-events"; -export * from "./sidebar-machine"; -export * from "./sidebar-state"; diff --git a/src/stores/sidebar/sidebar-context.tsx b/src/stores/sidebar/sidebar-context.tsx deleted file mode 100644 index cb98a7ba..00000000 --- a/src/stores/sidebar/sidebar-context.tsx +++ /dev/null @@ -1,72 +0,0 @@ -"use client"; -/** - * SidebarContext:基于 XState v5 的 React Context Provider - * - * 业务事件通过 `useMachine(sidebarMachine).send()` 派发。 - * XState 自动处理状态转换(无异步副作用)。 - * - * 兼容性:保持原 `useSidebarState()` / `useSidebarDispatch()` API。 - * 内部将 XState 状态机快照映射回原 `SidebarState` 形状。 - */ -import { - type Dispatch, - type ReactNode, - createContext, - useContext, - useMemo, -} from "react"; -import { useMachine } from "@xstate/react"; - -import { sidebarMachine } from "./sidebar-machine"; -import type { - SidebarState as MachineContext, - SidebarEvent, -} from "./sidebar-machine"; - -/** - * 对外暴露的 State 形状(保持与原 SidebarState 兼容) - */ -interface SidebarState { - currentPage: MachineContext["currentPage"]; - selectedBottomNavItem: MachineContext["selectedBottomNavItem"]; - characterName: string; - characterProgress: number; -} - -const SidebarStateCtx = createContext(null); -const SidebarDispatchCtx = createContext | null>(null); - -export function SidebarProvider({ children }: { children: ReactNode }) { - const [state, send] = useMachine(sidebarMachine, {}); - - // 映射 XState 状态机快照 → 原 SidebarState 形状 - const sidebarState = useMemo( - () => ({ - currentPage: state.context.currentPage, - selectedBottomNavItem: state.context.selectedBottomNavItem, - characterName: state.context.characterName, - characterProgress: state.context.characterProgress, - }), - [state], - ); - - return ( - - {children} - - ); -} - -export function useSidebarState(): SidebarState { - const ctx = useContext(SidebarStateCtx); - if (!ctx) - throw new Error("useSidebarState must be used inside "); - return ctx; -} - -export function useSidebarDispatch(): Dispatch { - const ctx = useContext(SidebarDispatchCtx); - if (!ctx) - throw new Error("useSidebarDispatch must be used inside "); - return ctx; -} diff --git a/src/stores/sidebar/sidebar-events.ts b/src/stores/sidebar/sidebar-events.ts deleted file mode 100644 index 30287338..00000000 --- a/src/stores/sidebar/sidebar-events.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Sidebar 状态机:事件联合 - */ -import type { SidebarPage, BottomNavItem } from "./sidebar-state"; - -export type SidebarEvent = - | { - type: "SidebarShowPage"; - page: SidebarPage; - bottomNavItem?: BottomNavItem; - } - | { type: "SidebarClearBottomNav" } - | { type: "SidebarUpdateCharacter"; name: string; progress: number }; diff --git a/src/stores/sidebar/sidebar-machine.ts b/src/stores/sidebar/sidebar-machine.ts deleted file mode 100644 index 6b34fb40..00000000 --- a/src/stores/sidebar/sidebar-machine.ts +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Sidebar 状态机(XState v5) - * - * 原始 Dart: lib/ui/sidebar/bloc/sidebar bloc + sidebar state + sidebar event - * - * 设计要点: - * - XState v5 `setup({...}).createMachine({...})` 声明式 API - * - Sidebar 无异步副作用(纯 UI 状态),仅用 `assign` 处理 - * - 保持事件类型名与原 Dart 一致 - * - actions inline 在 setup() 中(确保类型推断正确) - */ -import { setup, assign } from "xstate"; - -import { BottomNavItem, SidebarState, initialState } from "./sidebar-state"; -import type { SidebarEvent } from "./sidebar-events"; - -// 重新导出 State / Event 类型,保持 machine 文件的公共 API 不变 -export type { SidebarState } from "./sidebar-state"; -export { initialState } from "./sidebar-state"; -export type { SidebarEvent } from "./sidebar-events"; - -// ============================================================ -// Machine -// ============================================================ -export const sidebarMachine = setup({ - types: { - context: {} as SidebarState, - events: {} as SidebarEvent, - }, - actions: { - showPage: assign(({ event }) => { - if (event.type !== "SidebarShowPage") return {}; - return { - currentPage: event.page, - selectedBottomNavItem: event.bottomNavItem ?? BottomNavItem.None, - }; - }), - - clearBottomNav: assign(() => ({ - selectedBottomNavItem: BottomNavItem.None, - })), - - updateCharacter: assign(({ event }) => { - if (event.type !== "SidebarUpdateCharacter") return {}; - return { - characterName: event.name, - characterProgress: event.progress, - }; - }), - }, -}).createMachine({ - id: "sidebar", - initial: "idle", - context: initialState, - states: { - /** - * Sidebar 是纯数据状态(无异步副作用),仅用 idle 状态 - * 所有事件均在 idle 状态内处理 - */ - idle: { - on: { - SidebarShowPage: { - actions: "showPage", - }, - SidebarClearBottomNav: { - actions: "clearBottomNav", - }, - SidebarUpdateCharacter: { - actions: "updateCharacter", - }, - }, - }, - }, -}); - -export type SidebarMachine = typeof sidebarMachine; diff --git a/src/stores/sidebar/sidebar-state.ts b/src/stores/sidebar/sidebar-state.ts deleted file mode 100644 index 4a18efdf..00000000 --- a/src/stores/sidebar/sidebar-state.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Sidebar 状态机:State 形状 + 初始值 - * - * 枚举 `SidebarPage` / `BottomNavItem` 与 state 形状强相关(`currentPage` / - * `selectedBottomNavItem` 字段的取值集合),因此与 state 同源定义在本文件, - * 避免与 `sidebar-machine.ts` 形成循环引用。 - */ - -/** 页面枚举(侧边栏主区域可显示的页面) */ -export const SidebarPage = { - DefaultView: "defaultView", - Profile: "profile", - Topics: "topics", - Gifts: "gifts", - Activities: "activities", -} as const; - -export type SidebarPage = (typeof SidebarPage)[keyof typeof SidebarPage]; - -/** 底部导航枚举(选中态) */ -export const BottomNavItem = { - None: "none", - Topics: "topics", - Gifts: "gifts", - Activities: "activities", -} as const; - -export type BottomNavItem = (typeof BottomNavItem)[keyof typeof BottomNavItem]; - -export interface SidebarState { - currentPage: SidebarPage; - selectedBottomNavItem: BottomNavItem; - characterName: string; - characterProgress: number; -} - -export const initialState: SidebarState = { - currentPage: SidebarPage.DefaultView, - selectedBottomNavItem: BottomNavItem.None, - characterName: "Luna", - characterProgress: 0, -};