mirror of
https://github.com/toeverything/AFFiNE.git
synced 2024-12-23 18:21:50 +03:00
refactor: use suspense in AppDefender (#1020)
This commit is contained in:
parent
eb1d4fe1f6
commit
34a3a99d62
@ -16,14 +16,13 @@ import { ModalProvider } from '@/store/globalModal';
|
||||
// import AppStateProvider2 from '@/providers/app-state-provider2/provider';
|
||||
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect } from 'react';
|
||||
import { useAppState } from '@/providers/app-state-provider';
|
||||
import { Suspense, useEffect } from 'react';
|
||||
import { PageLoading } from '@/components/loading';
|
||||
import Head from 'next/head';
|
||||
import '@affine/i18n';
|
||||
import { useTranslation } from '@affine/i18n';
|
||||
import React from 'react';
|
||||
import { GlobalAppProvider } from '@/store/app';
|
||||
import { DataCenterLoader, GlobalAppProvider } from '@/store/app';
|
||||
|
||||
const ThemeProvider = dynamic(() => import('@/providers/ThemeProvider'), {
|
||||
ssr: false,
|
||||
@ -80,7 +79,13 @@ const App = ({ Component, pageProps }: AppPropsWithLayout) => {
|
||||
{NoNeedAppStatePageList.includes(router.route) ? (
|
||||
getLayout(<Component {...pageProps} />)
|
||||
) : (
|
||||
<AppDefender>{getLayout(<Component {...pageProps} />)}</AppDefender>
|
||||
<Suspense fallback={<PageLoading />}>
|
||||
{/* we should put this before every component in case of they read a null value */}
|
||||
<DataCenterLoader />
|
||||
<AppDefender>
|
||||
{getLayout(<Component {...pageProps} />)}
|
||||
</AppDefender>
|
||||
</Suspense>
|
||||
)}
|
||||
</ProviderComposer>
|
||||
</GlobalAppProvider>
|
||||
@ -90,15 +95,13 @@ const App = ({ Component, pageProps }: AppPropsWithLayout) => {
|
||||
|
||||
const AppDefender = ({ children }: PropsWithChildren) => {
|
||||
const router = useRouter();
|
||||
const { synced } = useAppState();
|
||||
|
||||
useEffect(() => {
|
||||
if (['/index.html', '/'].includes(router.asPath)) {
|
||||
router.replace('/workspace');
|
||||
}
|
||||
}, [router]);
|
||||
|
||||
return <div>{synced ? children : <PageLoading />}</div>;
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
export default App;
|
||||
|
@ -45,21 +45,14 @@ export const AppStateProvider = ({
|
||||
|
||||
const onceRef = useRef(true);
|
||||
const dataCenter = useGlobalState(store => store.dataCenter);
|
||||
useEffect(() => {
|
||||
if (dataCenter !== null) {
|
||||
if (onceRef.current) {
|
||||
setAppState({
|
||||
workspaceList: dataCenter.workspaces,
|
||||
currentWorkspace: null,
|
||||
pageList: [],
|
||||
synced: true,
|
||||
});
|
||||
onceRef.current = false;
|
||||
} else {
|
||||
console.warn('dataCenter Effect called twice. Please fix this ASAP');
|
||||
}
|
||||
}
|
||||
}, [dataCenter]);
|
||||
if (onceRef.current && dataCenter) {
|
||||
setAppState({
|
||||
workspaceList: dataCenter.workspaces,
|
||||
currentWorkspace: null,
|
||||
pageList: [],
|
||||
});
|
||||
onceRef.current = false;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
// FIXME: onWorkspacesChange should have dispose function
|
||||
|
@ -18,7 +18,6 @@ export type AppStateValue = {
|
||||
workspaceList: WorkspaceUnit[];
|
||||
currentWorkspace: WorkspaceUnit | null;
|
||||
pageList: PageMeta[];
|
||||
synced: boolean;
|
||||
blobDataSynced?: boolean;
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import type React from 'react';
|
||||
import { createContext, useContext, useEffect, useMemo, useRef } from 'react';
|
||||
import { createContext, useContext, useMemo } from 'react';
|
||||
import { createStore, StateCreator, useStore } from 'zustand';
|
||||
import { combine, subscribeWithSelector } from 'zustand/middleware';
|
||||
import type { UseBoundStore } from 'zustand/react';
|
||||
@ -27,6 +27,7 @@ export type GlobalActionsCreator<Actions, Store = GlobalState> = StateCreator<
|
||||
|
||||
export interface GlobalState extends BlockSuiteState, UserState {
|
||||
readonly dataCenter: DataCenter;
|
||||
readonly dataCenterPromise: Promise<DataCenter>;
|
||||
}
|
||||
|
||||
export interface GlobalActions extends BlockSuiteActions, UserActions {}
|
||||
@ -40,6 +41,8 @@ const create = () =>
|
||||
...createUserState(),
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
dataCenter: null!,
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
dataCenterPromise: null!,
|
||||
},
|
||||
/* deepscan-disable TOO_MANY_ARGS */
|
||||
(set, get, api) => ({
|
||||
@ -71,27 +74,25 @@ export const useGlobalState: UseBoundStore<Store> = ((
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
}) as any;
|
||||
|
||||
function DataCenterSideEffect() {
|
||||
const onceRef = useRef(true);
|
||||
export function DataCenterLoader() {
|
||||
const dataCenter = useGlobalState(store => store.dataCenter);
|
||||
const dataCenterPromise = useGlobalState(store => store.dataCenterPromise);
|
||||
const api = useGlobalStateApi();
|
||||
useEffect(() => {
|
||||
async function init() {
|
||||
const dataCenterPromise = getDataCenter();
|
||||
dataCenterPromise.then(async dataCenter => {
|
||||
// Ensure datacenter has at least one workspace
|
||||
if (dataCenter.workspaces.length === 0) {
|
||||
await createDefaultWorkspace(dataCenter);
|
||||
}
|
||||
api.setState({ dataCenter });
|
||||
});
|
||||
}
|
||||
if (onceRef.current) {
|
||||
onceRef.current = false;
|
||||
init().then(() => {
|
||||
console.log('datacenter init success');
|
||||
});
|
||||
}
|
||||
}, [api]);
|
||||
if (!dataCenter && !dataCenterPromise) {
|
||||
const promise = getDataCenter();
|
||||
api.setState({ dataCenterPromise: promise });
|
||||
promise.then(async dataCenter => {
|
||||
// Ensure datacenter has at least one workspace
|
||||
if (dataCenter.workspaces.length === 0) {
|
||||
await createDefaultWorkspace(dataCenter);
|
||||
}
|
||||
api.setState({ dataCenter });
|
||||
});
|
||||
throw promise;
|
||||
}
|
||||
if (!dataCenter) {
|
||||
throw dataCenterPromise;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -99,7 +100,6 @@ export const GlobalAppProvider: React.FC<React.PropsWithChildren> =
|
||||
function ModelProvider({ children }) {
|
||||
return (
|
||||
<GlobalStateContext.Provider value={useMemo(() => create(), [])}>
|
||||
<DataCenterSideEffect />
|
||||
{children}
|
||||
</GlobalStateContext.Provider>
|
||||
);
|
||||
|
@ -29,8 +29,9 @@ export const createWorkspaceUnit = async (params: WorkspaceUnitCtorParams) => {
|
||||
await setDefaultAvatar(blocksuiteWorkspace);
|
||||
workspaceUnit.update({ avatar: blocksuiteWorkspace.meta.avatar });
|
||||
}
|
||||
|
||||
await writeUpdatesToLocal(blocksuiteWorkspace);
|
||||
if (typeof window !== 'undefined') {
|
||||
await writeUpdatesToLocal(blocksuiteWorkspace);
|
||||
}
|
||||
|
||||
workspaceUnit.setBlocksuiteWorkspace(blocksuiteWorkspace);
|
||||
|
||||
|
@ -11,6 +11,7 @@ export const createBlocksuiteWorkspace = (
|
||||
return new BlocksuiteWorkspace({
|
||||
room: workspaceId,
|
||||
defaultFlags: { enable_slash_menu: true },
|
||||
isSSR: typeof window === 'undefined',
|
||||
...workspaceOption,
|
||||
})
|
||||
.register(builtInSchemas)
|
||||
|
Loading…
Reference in New Issue
Block a user