import './page-detail-editor.css'; import { PageNotFoundError } from '@affine/env/constant'; import type { LayoutNode } from '@affine/sdk//entry'; import { rootBlockHubAtom } from '@affine/workspace/atom'; import type { EditorContainer } from '@blocksuite/editor'; import { assertExists } from '@blocksuite/global/utils'; import type { Page, Workspace } from '@blocksuite/store'; import { useBlockSuitePageMeta } from '@toeverything/hooks/use-block-suite-page-meta'; import { useBlockSuiteWorkspacePage } from '@toeverything/hooks/use-block-suite-workspace-page'; import { addCleanup, pluginEditorAtom, pluginWindowAtom, } from '@toeverything/infra/__internal__/plugin'; import { contentLayoutAtom, rootStore } from '@toeverything/infra/atom'; import clsx from 'clsx'; import { useAtomValue, useSetAtom } from 'jotai'; import type { CSSProperties, FC, ReactElement } from 'react'; import { memo, Suspense, useCallback, useMemo } from 'react'; import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels'; import { pageSettingFamily } from '../atoms'; import { fontStyleOptions, useAppSetting } from '../atoms/settings'; import { BlockSuiteEditor as Editor } from './blocksuite/block-suite-editor'; import { TrashButtonGroup } from './blocksuite/workspace-header/header-right-items/trash-button-group'; import * as styles from './page-detail-editor.css'; import { pluginContainer } from './page-detail-editor.css'; export type PageDetailEditorProps = { isPublic?: boolean; workspace: Workspace; pageId: string; onInit: (page: Page, editor: Readonly) => void; onLoad?: (page: Page, editor: EditorContainer) => () => void; }; const EditorWrapper = memo(function EditorWrapper({ workspace, pageId, onInit, onLoad, isPublic, }: PageDetailEditorProps) { const page = useBlockSuiteWorkspacePage(workspace, pageId); if (!page) { throw new PageNotFoundError(workspace, pageId); } const meta = useBlockSuitePageMeta(workspace).find( meta => meta.id === pageId ); const pageSettingAtom = pageSettingFamily(pageId); const pageSetting = useAtomValue(pageSettingAtom); const currentMode = pageSetting?.mode ?? 'page'; const setBlockHub = useSetAtom(rootBlockHubAtom); const [appSettings] = useAppSetting(); assertExists(meta); const value = useMemo(() => { const fontStyle = fontStyleOptions.find( option => option.key === appSettings.fontStyle ); assertExists(fontStyle); return fontStyle.value; }, [appSettings.fontStyle]); return ( <> ) => { onInit(page, editor); }, [onInit] )} setBlockHub={setBlockHub} onLoad={useCallback( (page: Page, editor: EditorContainer) => { page.workspace.setPageMeta(page.id, { updatedDate: Date.now(), }); localStorage.setItem('last_page_id', page.id); let dispose = () => {}; if (onLoad) { dispose = onLoad(page, editor); } const editorItems = rootStore.get(pluginEditorAtom); let disposes: (() => void)[] = []; const renderTimeout = setTimeout(() => { disposes = Object.entries(editorItems).map(([id, editorItem]) => { const div = document.createElement('div'); div.setAttribute('plugin-id', id); const cleanup = editorItem(div, editor); assertExists(parent); document.body.appendChild(div); return () => { cleanup(); document.body.removeChild(div); }; }); }); return () => { dispose(); clearTimeout(renderTimeout); setTimeout(() => { disposes.forEach(dispose => dispose()); }); }; }, [onLoad] )} /> {meta.trash && } ); }); const PluginContentAdapter = memo<{ windowItem: (div: HTMLDivElement) => () => void; pluginName: string; }>(function PluginContentAdapter({ windowItem, pluginName }) { return (
{ if (ref) { const div = document.createElement('div'); const cleanup = windowItem(div); ref.appendChild(div); addCleanup(pluginName, () => { cleanup(); ref.removeChild(div); }); } }, [pluginName, windowItem] )} /> ); }); type LayoutPanelProps = { node: LayoutNode; editorProps: PageDetailEditorProps; }; const LayoutPanel = memo(function LayoutPanel( props: LayoutPanelProps ): ReactElement { const node = props.node; const windowItems = useAtomValue(pluginWindowAtom); if (typeof node === 'string') { if (node === 'editor') { return ; } else { const windowItem = windowItems[node]; return ; } } else { return ( ); } }); export const PageDetailEditor: FC = props => { const { workspace, pageId } = props; const page = useBlockSuiteWorkspacePage(workspace, pageId); if (!page) { throw new PageNotFoundError(workspace, pageId); } const layout = useAtomValue(contentLayoutAtom); return ( <> ); };