refactor!: next generation AFFiNE code structure (#1176)
This commit is contained in:
1 parent
2dcccc772c
commit
e0481d29ad
270 files changed
+8308
-6829
No files matched your search
@@ -1,152 +1,73 @@
|
||||
import { useTranslation } from '@affine/i18n';
|
||||
import { assertEquals } from '@blocksuite/store';
|
||||
import dynamic from 'next/dynamic';
|
||||
import Head from 'next/head';
|
||||
import { useRouter } from 'next/router';
|
||||
import {
|
||||
PropsWithChildren,
|
||||
ReactElement,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import { EditorHeader } from '@/components/header';
|
||||
import MobileModal from '@/components/mobile-modal';
|
||||
import WorkspaceLayout from '@/components/workspace-layout';
|
||||
import { usePageHelper } from '@/hooks/use-page-helper';
|
||||
import { useGlobalState, useGlobalStateApi } from '@/store/app';
|
||||
import exampleMarkdown from '@/templates/Welcome-to-AFFiNE-Alpha-Downhills.md';
|
||||
import { Unreachable } from '../../../components/affine/affine-error-eoundary';
|
||||
import { PageLoading } from '../../../components/pure/loading';
|
||||
import { useCurrentPageId } from '../../../hooks/current/use-current-page-id';
|
||||
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
|
||||
import { useLoadWorkspace } from '../../../hooks/use-load-workspace';
|
||||
import { useSyncRouterWithCurrentWorkspaceAndPage } from '../../../hooks/use-sync-router-with-current-workspace-and-page';
|
||||
import { WorkspaceLayout } from '../../../layouts';
|
||||
import { WorkspacePlugins } from '../../../plugins';
|
||||
import { NextPageWithLayout, RemWorkspaceFlavour } from '../../../shared';
|
||||
|
||||
import type { NextPageWithLayout } from '../..//_app';
|
||||
|
||||
const DynamicBlocksuite = dynamic(() => import('@/components/editor'), {
|
||||
ssr: false,
|
||||
});
|
||||
|
||||
const BlockHubAppender = () => {
|
||||
const setBlockHub = useGlobalState(store => store.setBlockHub);
|
||||
const editor = useGlobalState(store => store.editor);
|
||||
const WorkspaceDetail: React.FC = () => {
|
||||
const [pageId] = useCurrentPageId();
|
||||
const [currentWorkspace] = useCurrentWorkspace();
|
||||
const [, rerender] = useState(false);
|
||||
// fixme(himself65): this is a hack
|
||||
useEffect(() => {
|
||||
// todo(himself65): refactor with `useRef`
|
||||
const abortController = new AbortController();
|
||||
let blockHubElement: HTMLElement | null = null;
|
||||
abortController.signal.addEventListener('abort', () => {
|
||||
blockHubElement?.remove();
|
||||
const toolWrapper = document.querySelector('#toolWrapper');
|
||||
if (toolWrapper) {
|
||||
assertEquals(toolWrapper.childNodes.length, 0);
|
||||
}
|
||||
});
|
||||
|
||||
editor?.createBlockHub().then(blockHub => {
|
||||
const toolWrapper = document.querySelector('#toolWrapper');
|
||||
if (!toolWrapper) {
|
||||
// In an invitation page there is no toolWrapper, which contains helper icon and blockHub icon
|
||||
return;
|
||||
}
|
||||
if (abortController.signal.aborted) {
|
||||
return;
|
||||
}
|
||||
blockHubElement = blockHub;
|
||||
setBlockHub(blockHub);
|
||||
toolWrapper.appendChild(blockHub);
|
||||
});
|
||||
return () => {
|
||||
abortController.abort();
|
||||
};
|
||||
}, [editor, setBlockHub]);
|
||||
return null;
|
||||
};
|
||||
|
||||
const Page: NextPageWithLayout = () => {
|
||||
const currentPage = useGlobalState(store => store.currentPage);
|
||||
const setEditor = useGlobalState(store => store.setEditor);
|
||||
const currentWorkspace = useGlobalState(
|
||||
useCallback(store => store.currentDataCenterWorkspace, [])
|
||||
);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
// Only first workspace and first page will have template markdown
|
||||
const shouldInitTemplateContent =
|
||||
currentPage?.isEmpty &&
|
||||
currentWorkspace?.blocksuiteWorkspace?.meta.pageMetas.length === 1;
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{currentPage?.meta?.title || t('Untitled')} - AFFiNE</title>
|
||||
</Head>
|
||||
<EditorHeader />
|
||||
<MobileModal />
|
||||
|
||||
{currentPage && currentWorkspace?.blocksuiteWorkspace && (
|
||||
<>
|
||||
<DynamicBlocksuite
|
||||
page={currentPage}
|
||||
workspace={currentWorkspace.blocksuiteWorkspace}
|
||||
setEditor={setEditor}
|
||||
templateMarkdown={
|
||||
shouldInitTemplateContent ? exampleMarkdown : undefined
|
||||
}
|
||||
templateTitle={
|
||||
shouldInitTemplateContent
|
||||
? 'Welcome to AFFiNE Alpha "Downhills"'
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
<BlockHubAppender key={currentWorkspace.id + currentPage.id} />
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const PageDefender = ({ children }: PropsWithChildren) => {
|
||||
const router = useRouter();
|
||||
const [pageLoaded, setPageLoaded] = useState(false);
|
||||
const loadPage = useGlobalState(store => store.loadPage);
|
||||
const currentWorkspace = useGlobalState(
|
||||
useCallback(store => store.currentDataCenterWorkspace, [])
|
||||
);
|
||||
const dataCenter = useGlobalState(store => store.dataCenter);
|
||||
const { createPage } = usePageHelper();
|
||||
|
||||
useEffect(() => {
|
||||
const initPage = async () => {
|
||||
const pageId = router.query.pageId as string;
|
||||
const isPageExist =
|
||||
currentWorkspace?.blocksuiteWorkspace?.meta?.pageMetas.find(
|
||||
p => p.id === pageId
|
||||
);
|
||||
if (!isPageExist) {
|
||||
await createPage({ pageId });
|
||||
}
|
||||
await loadPage(pageId);
|
||||
setPageLoaded(true);
|
||||
};
|
||||
initPage();
|
||||
}, [createPage, currentWorkspace, loadPage, router.query.pageId]);
|
||||
const api = useGlobalStateApi();
|
||||
useEffect(
|
||||
() =>
|
||||
dataCenter.onWorkspacesChange(({ deleted }) => {
|
||||
if (deleted?.some(workspace => workspace.id === currentWorkspace?.id)) {
|
||||
router.replace('/404?code=kicked');
|
||||
const dispose = currentWorkspace?.blockSuiteWorkspace.signals.pageAdded.on(
|
||||
id => {
|
||||
if (pageId === id) {
|
||||
rerender(prev => !prev);
|
||||
}
|
||||
}),
|
||||
[api, currentWorkspace?.id, dataCenter, router]
|
||||
);
|
||||
|
||||
return <>{pageLoaded ? children : null}</>;
|
||||
}
|
||||
);
|
||||
return () => {
|
||||
dispose?.dispose();
|
||||
};
|
||||
}, [currentWorkspace?.blockSuiteWorkspace.signals.pageAdded, pageId]);
|
||||
if (currentWorkspace === null) {
|
||||
return <PageLoading />;
|
||||
}
|
||||
if (!pageId) {
|
||||
return <PageLoading />;
|
||||
}
|
||||
if (!currentWorkspace.blockSuiteWorkspace.getPage(pageId)) {
|
||||
return <PageLoading />;
|
||||
}
|
||||
if (currentWorkspace.flavour === RemWorkspaceFlavour.AFFINE) {
|
||||
const PageDetail = WorkspacePlugins[currentWorkspace.flavour].PageDetail;
|
||||
return (
|
||||
<PageDetail currentWorkspace={currentWorkspace} currentPageId={pageId} />
|
||||
);
|
||||
} else if (currentWorkspace.flavour === RemWorkspaceFlavour.LOCAL) {
|
||||
const PageDetail = WorkspacePlugins[currentWorkspace.flavour].PageDetail;
|
||||
return (
|
||||
<PageDetail currentWorkspace={currentWorkspace} currentPageId={pageId} />
|
||||
);
|
||||
}
|
||||
throw new Unreachable();
|
||||
};
|
||||
|
||||
Page.getLayout = function getLayout(page: ReactElement) {
|
||||
return (
|
||||
<WorkspaceLayout>
|
||||
<PageDefender>{page}</PageDefender>
|
||||
</WorkspaceLayout>
|
||||
);
|
||||
const WorkspaceDetailPage: NextPageWithLayout = () => {
|
||||
const router = useRouter();
|
||||
useLoadWorkspace(useCurrentWorkspace()[0]);
|
||||
useSyncRouterWithCurrentWorkspaceAndPage(router);
|
||||
if (!router.isReady) {
|
||||
return <PageLoading />;
|
||||
} else if (
|
||||
typeof router.query.pageId !== 'string' ||
|
||||
typeof router.query.workspaceId !== 'string'
|
||||
) {
|
||||
throw new Error('Invalid router query');
|
||||
}
|
||||
return <WorkspaceDetail />;
|
||||
};
|
||||
|
||||
export default Page;
|
||||
export default WorkspaceDetailPage;
|
||||
|
||||
WorkspaceDetailPage.getLayout = page => {
|
||||
return <WorkspaceLayout>{page}</WorkspaceLayout>;
|
||||
};
|
||||
Reference in new issue
Block a user