import { create } from 'zustand'; import { api } from '@/core-bridge/instance'; import type { ChannelInfo, CreateOptions } from '@/core-bridge/types'; import type { ParsedChannelLink } from '@/lib/channelLink'; interface ChannelsState { /** 服务端空间列表的界面投影,IndexedDB 提供离线缓存。 */ list: ChannelInfo[]; hydrated: boolean; /** 从链接进来、还没确认加入的空间;含密钥,只放内存 */ pendingLink: ParsedChannelLink | null; /** 刚创建的空间:进入时直接展示分享面板与二维码 */ justCreatedId: string | null; create: (opts: CreateOptions, captchaToken?: string) => Promise; join: (link: ParsedChannelLink, password?: string) => Promise; hydrate: () => Promise; refresh: () => Promise; forget: (id: string) => Promise; setPendingLink: (link: ParsedChannelLink | null) => void; clearJustCreated: () => void; } const upsert = (list: ChannelInfo[], c: ChannelInfo) => [c, ...list.filter((x) => x.id !== c.id)]; let hydration: Promise | undefined; export const useChannels = create()((set, get) => ({ list: [], hydrated: false, pendingLink: null, justCreatedId: null, create: async (opts, captchaToken) => { const c = await api.createChannel(opts, captchaToken); set((s) => ({ list: upsert(s.list, c), justCreatedId: c.id })); return c; }, join: async (link, password) => { const c = await api.joinChannel(link, password); set((s) => ({ list: upsert(s.list, c), pendingLink: null })); return c; }, hydrate: () => { // 账号刷新已经列过一次,别再请求一遍 if (get().hydrated) return Promise.resolve(); hydration ??= api.listSaved().then((list) => set({ list, hydrated: true }), () => set({ hydrated: true })); return hydration; }, refresh: async () => set({ list: await api.listSaved(), hydrated: true }), forget: async (id) => { await api.forget(id); set((s) => ({ list: s.list.filter((c) => c.id !== id) })); }, setPendingLink: (link) => set({ pendingLink: link }), clearJustCreated: () => set({ justCreatedId: null }), }));