Activate the account with parallel requests, run the full vault sync in the background, skip the duplicate space list request, and send the rejoin together with the first screen of data. [CI]
57 lines
2.1 KiB
TypeScript
57 lines
2.1 KiB
TypeScript
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<ChannelInfo>;
|
|
join: (link: ParsedChannelLink, password?: string) => Promise<ChannelInfo>;
|
|
hydrate: () => Promise<void>;
|
|
refresh: () => Promise<void>;
|
|
forget: (id: string) => Promise<void>;
|
|
setPendingLink: (link: ParsedChannelLink | null) => void;
|
|
clearJustCreated: () => void;
|
|
}
|
|
|
|
const upsert = (list: ChannelInfo[], c: ChannelInfo) => [c, ...list.filter((x) => x.id !== c.id)];
|
|
let hydration: Promise<void> | undefined;
|
|
|
|
export const useChannels = create<ChannelsState>()((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 }),
|
|
}));
|