refactor(store): extract workspace out of AppState (#1037)

This commit is contained in:
Himself65
2023-02-15 21:41:43 -06:00
committed by GitHub
parent a4d0813354
commit cdc2b449a9
30 changed files with 323 additions and 245 deletions
@@ -1,16 +1,8 @@
import { createContext, useContext, useEffect, useState, useRef } from 'react';
import { createContext, useContext, useEffect, useState } from 'react';
import type { PropsWithChildren } from 'react';
import {
AppStateContext,
AppStateFunction,
AppStateValue,
PageMeta,
} from './interface';
import { useGlobalState, useGlobalStateApi } from '@/store/app';
export interface Disposable {
dispose(): void;
}
import { AppStateContext } from './interface';
import type { Disposable } from '@blocksuite/global/utils';
import { useGlobalState } from '@/store/app';
type AppStateContextProps = PropsWithChildren<Record<string, unknown>>;
@@ -20,113 +12,14 @@ export const useAppState = () => useContext(AppState);
export const AppStateProvider = ({
children,
}: PropsWithChildren<AppStateContextProps>) => {
const globalStateApi = useGlobalStateApi();
const [appState, setAppState] = useState<AppStateValue>({} as AppStateValue);
const currentDataCenterWorkspace = useGlobalState(
store => store.currentDataCenterWorkspace
);
const [blobState, setBlobState] = useState(false);
useEffect(() => {
if (!appState?.currentWorkspace?.blocksuiteWorkspace) {
return;
}
const currentWorkspace = appState.currentWorkspace;
const dispose = currentWorkspace?.blocksuiteWorkspace?.meta.pagesUpdated.on(
() => {
setAppState({
...appState,
pageList: currentWorkspace.blocksuiteWorkspace?.meta
.pageMetas as PageMeta[],
});
}
).dispose;
return () => {
dispose && dispose();
};
}, [appState]);
const onceRef = useRef(true);
const dataCenter = useGlobalState(store => store.dataCenter);
if (onceRef.current && dataCenter) {
setAppState({
workspaceList: dataCenter.workspaces,
currentWorkspace: null,
pageList: [],
});
onceRef.current = false;
}
useEffect(() => {
// FIXME: onWorkspacesChange should have dispose function
return dataCenter?.onWorkspacesChange(
() => {
setAppState(_appState => ({
..._appState,
workspaceList: dataCenter.workspaces,
}));
},
{ immediate: false }
);
}, [dataCenter]);
const loadWorkspace: AppStateFunction['loadWorkspace'] =
useRef() as AppStateFunction['loadWorkspace'];
loadWorkspace.current = async (workspaceId, abort) => {
const { dataCenter } = globalStateApi.getState();
const { workspaceList, currentWorkspace } = appState;
if (!workspaceList.find(v => v.id.toString() === workspaceId)) {
return null;
}
if (workspaceId === currentWorkspace?.id) {
return currentWorkspace;
}
let aborted = false;
const onAbort = () => {
aborted = true;
};
abort?.addEventListener('abort', onAbort);
const workspace = (await dataCenter.loadWorkspace(workspaceId)) ?? null;
if (aborted) {
// do not update state if aborted
return null;
}
let isOwner;
if (workspace?.provider === 'local') {
// isOwner is useful only in the cloud
isOwner = true;
} else {
const userInfo = globalStateApi.getState().user;
// We must ensure workspace.owner exists, then ensure id same.
isOwner = workspace?.owner && userInfo?.id === workspace.owner.id;
}
const pageList =
(workspace?.blocksuiteWorkspace?.meta.pageMetas as PageMeta[]) ?? [];
if (workspace?.blocksuiteWorkspace) {
globalStateApi.getState().setWorkspace(workspace.blocksuiteWorkspace);
}
globalStateApi.setState({
isOwner,
});
setAppState({
...appState,
currentWorkspace: workspace,
pageList: pageList,
});
abort?.removeEventListener('abort', onAbort);
return workspace;
};
useEffect(() => {
let syncChangeDisposable: Disposable | undefined;
const currentWorkspace = appState.currentWorkspace;
const currentWorkspace = currentDataCenterWorkspace;
if (!currentWorkspace) {
return;
}
@@ -142,13 +35,11 @@ export const AppStateProvider = ({
return () => {
syncChangeDisposable?.dispose();
};
}, [appState.currentWorkspace]);
}, [currentDataCenterWorkspace]);
return (
<AppState.Provider
value={{
...appState,
loadWorkspace: loadWorkspace,
blobDataSynced: blobState,
}}
>
@@ -1,11 +1,10 @@
import { WorkspaceUnit } from '@affine/datacenter';
import type { EditorContainer } from '@blocksuite/editor';
import type {
Page as StorePage,
PageMeta as StorePageMeta,
} from '@blocksuite/store';
import { MutableRefObject } from 'react';
export interface PageMeta extends StorePageMeta {
favorite: boolean;
trash: boolean;
@@ -15,16 +14,14 @@ export interface PageMeta extends StorePageMeta {
}
export type AppStateValue = {
workspaceList: WorkspaceUnit[];
currentWorkspace: WorkspaceUnit | null;
pageList: PageMeta[];
blobDataSynced?: boolean;
blobDataSynced: boolean;
};
/**
* @deprecated
*/
export type AppStateFunction = {
loadWorkspace: MutableRefObject<
(workspaceId: string, abort?: AbortSignal) => Promise<WorkspaceUnit | null>
>;
// todo: remove this in the future
};
export type AppStateContext = AppStateValue & AppStateFunction;