refactor: public workspace (#996)

Co-authored-by: himself65 <himself65@outlook.com>
This commit is contained in:
Qi
2023-02-15 01:39:53 +08:00
committed by GitHub
parent 0370ec67df
commit 5a3e6aa041
5 changed files with 127 additions and 89 deletions

View File

@@ -0,0 +1,35 @@
import { getDataCenter, WorkspaceUnit } from '@affine/datacenter';
import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';
export function useLoadPublicWorkspace(workspaceId: string) {
const router = useRouter();
const [workspace, setWorkspace] = useState<WorkspaceUnit | null>();
const [status, setStatus] = useState<'loading' | 'error' | 'success'>(
'loading'
);
useEffect(() => {
setStatus('loading');
const init = async () => {
const dataCenter = await getDataCenter();
dataCenter
.loadPublicWorkspace(workspaceId)
.then(data => {
setWorkspace(data);
setStatus('success');
})
.catch(() => {
// if (!cancel) {
// router.push('/404');
// }
setStatus('error');
});
};
init();
}, [router, workspaceId]);
return { status, workspace };
}

View File

@@ -1,31 +0,0 @@
import { useAppState } from '@/providers/app-state-provider';
import { WorkspaceUnit } from '@affine/datacenter';
import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';
export function usePublicWorkspace(workspaceId: string) {
const { dataCenter } = useAppState();
const router = useRouter();
const [workspace, setWorkspace] = useState<WorkspaceUnit>();
useEffect(() => {
let cancel = false;
dataCenter
.loadPublicWorkspace(workspaceId)
.then(data => {
if (!cancel) {
setWorkspace(data);
}
})
.catch(() => {
if (!cancel) {
router.push('/404');
}
});
return () => {
cancel = true;
};
}, [router, workspaceId, dataCenter]);
return workspace;
}

View File

@@ -39,9 +39,16 @@ type AppPropsWithLayout = AppProps & {
Component: NextPageWithLayout; Component: NextPageWithLayout;
}; };
// Page list which do not rely on app state
const NoNeedAppStatePageList = [
'/404',
'/public-workspace/[workspaceId]',
'/public-workspace/[workspaceId]/[pageId]',
];
const App = ({ Component, pageProps }: AppPropsWithLayout) => { const App = ({ Component, pageProps }: AppPropsWithLayout) => {
const getLayout = Component.getLayout || (page => page); const getLayout = Component.getLayout || (page => page);
const { i18n } = useTranslation(); const { i18n } = useTranslation();
const router = useRouter();
React.useEffect(() => { React.useEffect(() => {
document.documentElement.lang = i18n.language; document.documentElement.lang = i18n.language;
@@ -68,7 +75,11 @@ const App = ({ Component, pageProps }: AppPropsWithLayout) => {
<ConfirmProvider key="ConfirmProvider" />, <ConfirmProvider key="ConfirmProvider" />,
]} ]}
> >
<AppDefender>{getLayout(<Component {...pageProps} />)}</AppDefender> {NoNeedAppStatePageList.includes(router.route) ? (
getLayout(<Component {...pageProps} />)
) : (
<AppDefender>{getLayout(<Component {...pageProps} />)}</AppDefender>
)}
</ProviderComposer> </ProviderComposer>
</> </>
); );
@@ -84,11 +95,6 @@ const AppDefender = ({ children }: PropsWithChildren) => {
} }
}, [router]); }, [router]);
// if you visit /404, you will see the children directly
if (router.route === '/404') {
return <div>{children}</div>;
}
return <div>{synced ? children : <PageLoading />}</div>; return <div>{synced ? children : <PageLoading />}</div>;
}; };

View File

@@ -10,7 +10,7 @@ import NextLink from 'next/link';
import { PaperIcon, SearchIcon } from '@blocksuite/icons'; import { PaperIcon, SearchIcon } from '@blocksuite/icons';
import { WorkspaceUnitAvatar } from '@/components/workspace-avatar'; import { WorkspaceUnitAvatar } from '@/components/workspace-avatar';
import { useModal } from '@/store/globalModal'; import { useModal } from '@/store/globalModal';
import { usePublicWorkspace } from '@/hooks/use-public-workspace'; import { useLoadPublicWorkspace } from '@/hooks/use-load-public-workspace';
import { useTranslation } from '@affine/i18n'; import { useTranslation } from '@affine/i18n';
const DynamicBlocksuite = dynamic(() => import('@/components/editor'), { const DynamicBlocksuite = dynamic(() => import('@/components/editor'), {
@@ -20,8 +20,9 @@ const DynamicBlocksuite = dynamic(() => import('@/components/editor'), {
const Page: NextPageWithLayout = () => { const Page: NextPageWithLayout = () => {
const router = useRouter(); const router = useRouter();
const { workspaceId, pageId } = router.query as Record<string, string>; const { workspaceId, pageId } = router.query as Record<string, string>;
const workspaceUnit = usePublicWorkspace(workspaceId); const { status, workspace: workspaceUnit } =
const [loaded, setLoaded] = useState(false); useLoadPublicWorkspace(workspaceId);
const [editorLoaded, setEditorLoaded] = useState(false);
const { triggerQuickSearchModal } = useModal(); const { triggerQuickSearchModal } = useModal();
const { t } = useTranslation(); const { t } = useTranslation();
@@ -43,48 +44,58 @@ const Page: NextPageWithLayout = () => {
} }
}, [workspace, router, pageId]); }, [workspace, router, pageId]);
return ( useEffect(() => {
<> if (status === 'error') {
{!loaded && <PageLoading />} router.push('/404');
<PageContainer> }
<NavContainer> }, [router, status]);
<Breadcrumbs>
<StyledBreadcrumbs href={`/public-workspace/${workspaceId}`}>
<WorkspaceUnitAvatar
size={24}
name={workspaceName}
workspaceUnit={workspaceUnit}
/>
<span>{workspaceName}</span>
</StyledBreadcrumbs>
<StyledBreadcrumbs
href={`/public-workspace/${workspaceId}/${pageId}`}
>
<PaperIcon fontSize={24} />
<span>{pageTitle ? pageTitle : t('Untitled')}</span>
</StyledBreadcrumbs>
</Breadcrumbs>
<SearchButton
onClick={() => {
triggerQuickSearchModal();
}}
>
<SearchIcon />
</SearchButton>
</NavContainer>
{workspace && page && ( if (status === 'loading' || !editorLoaded) {
<DynamicBlocksuite return <PageLoading />;
page={page} }
workspace={workspace}
setEditor={editor => { if (status === 'error') {
editor.readonly = true; return null;
setLoaded(true); }
}} return (
/> <PageContainer>
)} <NavContainer>
</PageContainer> <Breadcrumbs>
</> <StyledBreadcrumbs href={`/public-workspace/${workspaceId}`}>
<WorkspaceUnitAvatar
size={24}
name={workspaceName}
workspaceUnit={workspaceUnit}
/>
<span>{workspaceName}</span>
</StyledBreadcrumbs>
<StyledBreadcrumbs
href={`/public-workspace/${workspaceId}/${pageId}`}
>
<PaperIcon fontSize={24} />
<span>{pageTitle ? pageTitle : t('Untitled')}</span>
</StyledBreadcrumbs>
</Breadcrumbs>
<SearchButton
onClick={() => {
triggerQuickSearchModal();
}}
>
<SearchIcon />
</SearchButton>
</NavContainer>
{workspace && page && (
<DynamicBlocksuite
page={page}
workspace={workspace}
setEditor={editor => {
editor.readonly = true;
setEditorLoaded(true);
}}
/>
)}
</PageContainer>
); );
}; };

View File

@@ -1,30 +1,47 @@
import { PageList } from '@/components/page-list'; import { PageList } from '@/components/page-list';
import { WorkspaceUnitAvatar } from '@/components/workspace-avatar'; import { WorkspaceUnitAvatar } from '@/components/workspace-avatar';
import { usePublicWorkspace } from '@/hooks/use-public-workspace'; import { useLoadPublicWorkspace } from '@/hooks/use-load-public-workspace';
import { PageMeta } from '@/providers/app-state-provider'; import { PageMeta } from '@/providers/app-state-provider';
import { useModal } from '@/store/globalModal'; import { useModal } from '@/store/globalModal';
import { Breadcrumbs } from '@affine/component'; import { Breadcrumbs } from '@affine/component';
import { SearchIcon } from '@blocksuite/icons'; import { SearchIcon } from '@blocksuite/icons';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { ReactElement, useMemo } from 'react'; import { ReactElement, useMemo, useEffect } from 'react';
import { import {
NavContainer, NavContainer,
PageContainer, PageContainer,
SearchButton, SearchButton,
StyledBreadcrumbs, StyledBreadcrumbs,
} from './[pageId]'; } from './[pageId]';
import { PageLoading } from '@/components/loading';
const All = () => { const All = () => {
const router = useRouter(); const router = useRouter();
const { triggerQuickSearchModal } = useModal(); const { triggerQuickSearchModal } = useModal();
const workspaceUnit = usePublicWorkspace(router.query.workspaceId as string); const { status, workspace } = useLoadPublicWorkspace(
router.query.workspaceId as string
);
const pageList = useMemo(() => { const pageList = useMemo(() => {
return (workspaceUnit?.blocksuiteWorkspace?.meta.pageMetas ?? return (workspace?.blocksuiteWorkspace?.meta.pageMetas ?? []) as PageMeta[];
[]) as PageMeta[]; }, [workspace]);
}, [workspaceUnit]);
const workspaceName = workspace?.blocksuiteWorkspace?.meta.name;
useEffect(() => {
if (status === 'error') {
router.push('/404');
}
}, [router, status]);
if (status === 'loading') {
return <PageLoading />;
}
if (status === 'error') {
return null;
}
const workspaceName = workspaceUnit?.blocksuiteWorkspace?.meta.name;
return ( return (
<PageContainer> <PageContainer>
<NavContainer> <NavContainer>
@@ -35,7 +52,7 @@ const All = () => {
<WorkspaceUnitAvatar <WorkspaceUnitAvatar
size={24} size={24}
name={workspaceName} name={workspaceName}
workspaceUnit={workspaceUnit} workspaceUnit={workspace}
/> />
<span>{workspaceName}</span> <span>{workspaceName}</span>
</StyledBreadcrumbs> </StyledBreadcrumbs>