refactor: support suspense mode in workspaces (#1304)

This commit is contained in:
Himself65
2023-03-04 20:11:15 -06:00
committed by GitHub
parent dd6bee68cb
commit 9a199eb9a1
27 changed files with 713 additions and 652 deletions

View File

@@ -1,57 +1,100 @@
import { DebugLogger } from '@affine/debug';
import { setUpLanguage, useTranslation } from '@affine/i18n';
import { assertExists, nanoid } from '@blocksuite/store';
import { useAtom, useAtomValue } from 'jotai';
import { NoSsr } from '@mui/material';
import { useAtom, useAtomValue, useSetAtom } from 'jotai';
import { atomWithStorage } from 'jotai/utils';
import { useRouter } from 'next/router';
import React, { useCallback, useEffect } from 'react';
import React, { Suspense, useCallback, useEffect } from 'react';
import { Helmet } from 'react-helmet-async';
import {
currentWorkspaceIdAtom,
jotaiWorkspacesAtom,
openQuickSearchModalAtom,
openWorkspacesModalAtom,
workspaceLockAtom,
} from '../atoms';
import { HelpIsland } from '../components/pure/help-island';
import { PageLoading } from '../components/pure/loading';
import QuickSearchModal from '../components/pure/quick-search-modal';
import WorkSpaceSliderBar from '../components/pure/workspace-slider-bar';
import { useCurrentPageId } from '../hooks/current/use-current-page-id';
import { useCurrentWorkspace } from '../hooks/current/use-current-workspace';
import { useBlockSuiteWorkspaceHelper } from '../hooks/use-blocksuite-workspace-helper';
import { useCreateFirstWorkspace } from '../hooks/use-create-first-workspace';
import { useRouterTitle } from '../hooks/use-router-title';
import {
refreshDataCenter,
useSyncWorkspaces,
useWorkspaces,
} from '../hooks/use-workspaces';
import { useWorkspaces } from '../hooks/use-workspaces';
import { WorkspacePlugins } from '../plugins';
import { ModalProvider } from '../providers/ModalProvider';
import { pathGenerator, publicPathGenerator } from '../shared';
import { StyledPage, StyledToolWrapper, StyledWrapper } from './styles';
const sideBarOpenAtom = atomWithStorage('sideBarOpen', true);
refreshDataCenter();
const logger = new DebugLogger('workspace-layout');
export const WorkspaceLayout: React.FC<React.PropsWithChildren> =
function WorkspacesSuspense({ children }) {
const { i18n } = useTranslation();
useEffect(() => {
document.documentElement.lang = i18n.language;
// todo(himself65): this is a hack, we should use a better way to set the language
setUpLanguage(i18n);
}, [i18n]);
useCreateFirstWorkspace();
const set = useSetAtom(jotaiWorkspacesAtom);
useEffect(() => {
logger.info('mount');
const controller = new AbortController();
const lists = Object.values(WorkspacePlugins)
.sort((a, b) => a.loadPriority - b.loadPriority)
.map(({ CRUD }) => CRUD.list);
async function fetch() {
const items = [];
for (const list of lists) {
try {
const item = await list();
items.push(...item.map(x => ({ id: x.id, flavour: x.flavour })));
} catch (e) {
logger.error('list data error:', e);
}
}
if (controller.signal.aborted) {
return;
}
set([...items]);
logger.info('mount first data:', items);
}
fetch();
return () => {
controller.abort();
logger.info('unmount');
};
}, [set]);
const currentWorkspaceId = useAtomValue(currentWorkspaceIdAtom);
return (
<NoSsr>
{/* fixme(himself65): don't re-render whole modals */}
<ModalProvider key={currentWorkspaceId} />
<Suspense fallback={<PageLoading />}>
<WorkspaceLayoutInner>{children}</WorkspaceLayoutInner>
</Suspense>
</NoSsr>
);
};
export const WorkspaceLayout: React.FC<React.PropsWithChildren> = ({
export const WorkspaceLayoutInner: React.FC<React.PropsWithChildren> = ({
children,
}) => {
const { i18n } = useTranslation();
useEffect(() => {
document.documentElement.lang = i18n.language;
// todo(himself65): this is a hack, we should use a better way to set the language
setUpLanguage(i18n);
}, [i18n]);
useEffect(() => {
const controller = new AbortController();
refreshDataCenter(controller.signal);
return () => {
controller.abort();
};
}, []);
const [show, setShow] = useAtom(sideBarOpenAtom);
useSyncWorkspaces();
const [currentWorkspace] = useCurrentWorkspace();
const [currentPageId] = useCurrentPageId();
const workspaces = useWorkspaces();
useEffect(() => {
console.log(workspaces);
}, [workspaces]);
useEffect(() => {
const providers = workspaces.flatMap(workspace =>
workspace.providers.filter(provider => provider.background)
@@ -91,7 +134,6 @@ export const WorkspaceLayout: React.FC<React.PropsWithChildren> = ({
const isPublicWorkspace =
router.pathname.split('/')[1] === 'public-workspace';
const title = useRouterTitle(router);
const [, setOpenQuickSearchModalAtom] = useAtom(openQuickSearchModalAtom);
const handleOpenPage = useCallback(
(pageId: string) => {
assertExists(currentWorkspace);
@@ -113,6 +155,10 @@ export const WorkspaceLayout: React.FC<React.PropsWithChildren> = ({
const handleOpenWorkspaceListModal = useCallback(() => {
setOpenWorkspacesModal(true);
}, [setOpenWorkspacesModal]);
const [openQuickSearchModal, setOpenQuickSearchModalAtom] = useAtom(
openQuickSearchModalAtom
);
const handleOpenQuickSearchModal = useCallback(() => {
setOpenQuickSearchModalAtom(true);
}, [setOpenQuickSearchModalAtom]);
@@ -153,6 +199,14 @@ export const WorkspaceLayout: React.FC<React.PropsWithChildren> = ({
</StyledToolWrapper>
</StyledWrapper>
</StyledPage>
{currentWorkspace?.blockSuiteWorkspace && (
<QuickSearchModal
blockSuiteWorkspace={currentWorkspace?.blockSuiteWorkspace}
open={openQuickSearchModal}
setOpen={setOpenQuickSearchModalAtom}
router={router}
/>
)}
</>
);
};