mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-02 01:49:51 +08:00
fix: public workspace loading (#1144)
This commit is contained in:
@@ -1,36 +0,0 @@
|
|||||||
import { WorkspaceUnit } from '@affine/datacenter';
|
|
||||||
import { dataCenterPromise } from '@affine/store';
|
|
||||||
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 dataCenterPromise;
|
|
||||||
|
|
||||||
dataCenter
|
|
||||||
.loadPublicWorkspace(workspaceId)
|
|
||||||
.then(data => {
|
|
||||||
setWorkspace(data);
|
|
||||||
setStatus('success');
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
// if (!cancel) {
|
|
||||||
// router.push('/404');
|
|
||||||
// }
|
|
||||||
setStatus('error');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
init();
|
|
||||||
}, [router, workspaceId]);
|
|
||||||
|
|
||||||
return { status, workspace };
|
|
||||||
}
|
|
||||||
@@ -7,15 +7,13 @@ import '@affine/i18n';
|
|||||||
|
|
||||||
import { useTranslation } from '@affine/i18n';
|
import { useTranslation } from '@affine/i18n';
|
||||||
import { DataCenterPreloader } from '@affine/store';
|
import { DataCenterPreloader } from '@affine/store';
|
||||||
import { NoSsr } from '@mui/material';
|
|
||||||
import { Logger } from '@toeverything/pathfinder-logger';
|
import { Logger } from '@toeverything/pathfinder-logger';
|
||||||
import type { NextPage } from 'next';
|
import type { NextPage } from 'next';
|
||||||
import type { AppProps } from 'next/app';
|
import type { AppProps } from 'next/app';
|
||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
// import AppStateProvider2 from '@/providers/app-state-provider2/provider';
|
// import AppStateProvider2 from '@/providers/app-state-provider2/provider';
|
||||||
import { useRouter } from 'next/router';
|
import type { ReactElement, ReactNode } from 'react';
|
||||||
import type { PropsWithChildren, ReactElement, ReactNode } from 'react';
|
import { Suspense } from 'react';
|
||||||
import { Suspense, useEffect } from 'react';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { PageLoading } from '@/components/loading';
|
import { PageLoading } from '@/components/loading';
|
||||||
@@ -37,16 +35,9 @@ 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;
|
||||||
@@ -73,35 +64,16 @@ const App = ({ Component, pageProps }: AppPropsWithLayout) => {
|
|||||||
<ConfirmProvider key="ConfirmProvider" />,
|
<ConfirmProvider key="ConfirmProvider" />,
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<NoSsr>
|
<Suspense fallback={<PageLoading />}>
|
||||||
{NoNeedAppStatePageList.includes(router.route) ? (
|
<DataCenterPreloader>
|
||||||
getLayout(<Component {...pageProps} />)
|
<MessageCenterHandler>
|
||||||
) : (
|
{getLayout(<Component {...pageProps} />)}
|
||||||
<Suspense fallback={<PageLoading />}>
|
</MessageCenterHandler>
|
||||||
<DataCenterPreloader>
|
</DataCenterPreloader>
|
||||||
<MessageCenterHandler>
|
</Suspense>
|
||||||
<AppDefender>
|
|
||||||
{getLayout(<Component {...pageProps} />)}
|
|
||||||
</AppDefender>
|
|
||||||
</MessageCenterHandler>
|
|
||||||
</DataCenterPreloader>
|
|
||||||
</Suspense>
|
|
||||||
)}
|
|
||||||
</NoSsr>
|
|
||||||
</ProviderComposer>
|
</ProviderComposer>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const AppDefender = ({ children }: PropsWithChildren) => {
|
|
||||||
const router = useRouter();
|
|
||||||
useEffect(() => {
|
|
||||||
if (['/index.html', '/'].includes(router.asPath)) {
|
|
||||||
router.replace('/workspace');
|
|
||||||
}
|
|
||||||
}, [router]);
|
|
||||||
|
|
||||||
return <>{children}</>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|||||||
@@ -1,7 +1,15 @@
|
|||||||
import type { NextPage } from 'next';
|
import type { NextPage } from 'next';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
|
import { PageLoading } from '@/components/loading';
|
||||||
|
|
||||||
const Home: NextPage = () => {
|
const Home: NextPage = () => {
|
||||||
return <div title="Home Page"></div>;
|
const router = useRouter();
|
||||||
|
useEffect(() => {
|
||||||
|
router.replace('/workspace');
|
||||||
|
}, [router]);
|
||||||
|
return <PageLoading />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Home;
|
export default Home;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { displayFlex, styled } from '@affine/component';
|
|||||||
import { Breadcrumbs } from '@affine/component';
|
import { Breadcrumbs } from '@affine/component';
|
||||||
import { IconButton } from '@affine/component';
|
import { IconButton } from '@affine/component';
|
||||||
import { useTranslation } from '@affine/i18n';
|
import { useTranslation } from '@affine/i18n';
|
||||||
|
import { useDataCenterPublicWorkspace } from '@affine/store';
|
||||||
import { PaperIcon, SearchIcon } from '@blocksuite/icons';
|
import { PaperIcon, SearchIcon } from '@blocksuite/icons';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import NextLink from 'next/link';
|
import NextLink from 'next/link';
|
||||||
@@ -10,7 +11,6 @@ import { ReactElement, useEffect, useMemo } from 'react';
|
|||||||
|
|
||||||
import { PageLoading } from '@/components/loading';
|
import { PageLoading } from '@/components/loading';
|
||||||
import { WorkspaceUnitAvatar } from '@/components/workspace-avatar';
|
import { WorkspaceUnitAvatar } from '@/components/workspace-avatar';
|
||||||
import { useLoadPublicWorkspace } from '@/hooks/use-load-public-workspace';
|
|
||||||
import { useModal } from '@/store/globalModal';
|
import { useModal } from '@/store/globalModal';
|
||||||
|
|
||||||
import type { NextPageWithLayout } from '../..//_app';
|
import type { NextPageWithLayout } from '../..//_app';
|
||||||
@@ -21,13 +21,17 @@ 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;
|
||||||
const { status, workspace: workspaceUnit } =
|
const { error, workspace: workspaceUnit } = useDataCenterPublicWorkspace(
|
||||||
useLoadPublicWorkspace(workspaceId);
|
typeof workspaceId === 'string' ? workspaceId : null
|
||||||
|
);
|
||||||
const { triggerQuickSearchModal } = useModal();
|
const { triggerQuickSearchModal } = useModal();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const page = useMemo(() => {
|
const page = useMemo(() => {
|
||||||
|
if (typeof pageId !== 'string') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (workspaceUnit?.blocksuiteWorkspace) {
|
if (workspaceUnit?.blocksuiteWorkspace) {
|
||||||
return workspaceUnit.blocksuiteWorkspace.getPage(pageId);
|
return workspaceUnit.blocksuiteWorkspace.getPage(pageId);
|
||||||
}
|
}
|
||||||
@@ -46,18 +50,15 @@ const Page: NextPageWithLayout = () => {
|
|||||||
}, [workspace, router, pageId]);
|
}, [workspace, router, pageId]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (status === 'error') {
|
if (error) {
|
||||||
router.push('/404');
|
router.push('/404');
|
||||||
}
|
}
|
||||||
}, [router, status]);
|
}, [router, error]);
|
||||||
|
|
||||||
if (status === 'loading') {
|
if (!workspace) {
|
||||||
return <PageLoading />;
|
return <PageLoading />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status === 'error') {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<PageContainer>
|
<PageContainer>
|
||||||
<NavContainer>
|
<NavContainer>
|
||||||
@@ -86,7 +87,7 @@ const Page: NextPageWithLayout = () => {
|
|||||||
</SearchButton>
|
</SearchButton>
|
||||||
</NavContainer>
|
</NavContainer>
|
||||||
|
|
||||||
{workspace && page && (
|
{page && (
|
||||||
<DynamicBlocksuite
|
<DynamicBlocksuite
|
||||||
page={page}
|
page={page}
|
||||||
workspace={workspace}
|
workspace={workspace}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Breadcrumbs } from '@affine/component';
|
import { Breadcrumbs } from '@affine/component';
|
||||||
import { PageMeta } from '@affine/store';
|
import { PageMeta, useDataCenterPublicWorkspace } from '@affine/store';
|
||||||
import { SearchIcon } from '@blocksuite/icons';
|
import { SearchIcon } from '@blocksuite/icons';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { ReactElement, useEffect, useMemo } from 'react';
|
import { ReactElement, useEffect, useMemo } from 'react';
|
||||||
@@ -7,7 +7,6 @@ import { ReactElement, useEffect, useMemo } from 'react';
|
|||||||
import { PageLoading } from '@/components/loading';
|
import { PageLoading } from '@/components/loading';
|
||||||
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 { useLoadPublicWorkspace } from '@/hooks/use-load-public-workspace';
|
|
||||||
import { useModal } from '@/store/globalModal';
|
import { useModal } from '@/store/globalModal';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -20,8 +19,10 @@ import {
|
|||||||
const All = () => {
|
const All = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { triggerQuickSearchModal } = useModal();
|
const { triggerQuickSearchModal } = useModal();
|
||||||
const { status, workspace } = useLoadPublicWorkspace(
|
const { workspace, error } = useDataCenterPublicWorkspace(
|
||||||
router.query.workspaceId as string
|
typeof router.query.workspaceId === 'string'
|
||||||
|
? router.query.workspaceId
|
||||||
|
: null
|
||||||
);
|
);
|
||||||
|
|
||||||
const pageList = useMemo(() => {
|
const pageList = useMemo(() => {
|
||||||
@@ -31,19 +32,15 @@ const All = () => {
|
|||||||
const workspaceName = workspace?.blocksuiteWorkspace?.meta.name;
|
const workspaceName = workspace?.blocksuiteWorkspace?.meta.name;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (status === 'error') {
|
if (error) {
|
||||||
router.push('/404');
|
router.push('/404');
|
||||||
}
|
}
|
||||||
}, [router, status]);
|
}, [router, error]);
|
||||||
|
|
||||||
if (status === 'loading') {
|
if (!workspace) {
|
||||||
return <PageLoading />;
|
return <PageLoading />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status === 'error') {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContainer>
|
<PageContainer>
|
||||||
<NavContainer>
|
<NavContainer>
|
||||||
|
|||||||
@@ -129,6 +129,19 @@ export function useDataCenterWorkspace(
|
|||||||
return data ?? null;
|
return data ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useDataCenterPublicWorkspace(workspaceId: string | null) {
|
||||||
|
const { data, error } = useSWR<WorkspaceUnit | null>(
|
||||||
|
['datacenter', workspaceId, 'public'],
|
||||||
|
{
|
||||||
|
fallbackData: null,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
workspace: data ?? null,
|
||||||
|
error,
|
||||||
|
} as const;
|
||||||
|
}
|
||||||
|
|
||||||
export function DataCenterPreloader({ children }: React.PropsWithChildren) {
|
export function DataCenterPreloader({ children }: React.PropsWithChildren) {
|
||||||
const api = useGlobalStateApi();
|
const api = useGlobalStateApi();
|
||||||
//# region effect for updating workspace page list
|
//# region effect for updating workspace page list
|
||||||
|
|||||||
@@ -84,7 +84,9 @@ export const useGlobalState: UseBoundStore<Store> = ((
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
}) as any;
|
}) as any;
|
||||||
|
|
||||||
export type DataKey = ['datacenter', string | null] | ['datacenter'];
|
export type DataKey =
|
||||||
|
| ['datacenter', string | null, 'public' | undefined]
|
||||||
|
| ['datacenter'];
|
||||||
|
|
||||||
const swrFetcher = async (keys: DataKey) => {
|
const swrFetcher = async (keys: DataKey) => {
|
||||||
assertEquals(keys[0], 'datacenter');
|
assertEquals(keys[0], 'datacenter');
|
||||||
@@ -100,6 +102,9 @@ const swrFetcher = async (keys: DataKey) => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const dataCenter = await dataCenterPromise;
|
const dataCenter = await dataCenterPromise;
|
||||||
|
if (keys[2] === 'public') {
|
||||||
|
return dataCenter.loadPublicWorkspace(keys[1]);
|
||||||
|
}
|
||||||
return dataCenter.loadWorkspace(keys[1]);
|
return dataCenter.loadWorkspace(keys[1]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,5 +4,6 @@ export { createDefaultWorkspace, DataCenterPreloader } from './app/datacenter';
|
|||||||
export {
|
export {
|
||||||
dataCenterPromise,
|
dataCenterPromise,
|
||||||
useDataCenter,
|
useDataCenter,
|
||||||
|
useDataCenterPublicWorkspace,
|
||||||
useDataCenterWorkspace,
|
useDataCenterWorkspace,
|
||||||
} from './app/datacenter';
|
} from './app/datacenter';
|
||||||
|
|||||||
Reference in New Issue
Block a user