diff --git a/packages/frontend/core/src/components/page-detail-editor.tsx b/packages/frontend/core/src/components/page-detail-editor.tsx index e7a13d5a39..1217e36bf6 100644 --- a/packages/frontend/core/src/components/page-detail-editor.tsx +++ b/packages/frontend/core/src/components/page-detail-editor.tsx @@ -86,8 +86,14 @@ const PageDetailEditorMain = memo(function PageDetailEditorMain({ }) ); localStorage.setItem('last_page_id', page.id); + if (onLoad) { - disposableGroup.add(onLoad(page, editor)); + // Invoke onLoad once the editor has been mounted to the DOM. + editor.updateComplete + .then(() => { + disposableGroup.add(onLoad(page, editor)); + }) + .catch(console.error); } return () => { diff --git a/packages/frontend/core/src/pages/workspace/detail-page/detail-page.tsx b/packages/frontend/core/src/pages/workspace/detail-page/detail-page.tsx index 3cab121373..5c943750f1 100644 --- a/packages/frontend/core/src/pages/workspace/detail-page/detail-page.tsx +++ b/packages/frontend/core/src/pages/workspace/detail-page/detail-page.tsx @@ -1,19 +1,24 @@ import { PageDetailSkeleton } from '@affine/component/page-detail-skeleton'; import { ResizePanel } from '@affine/component/resize-panel'; +import { pageSettingFamily, setPageModeAtom } from '@affine/core/atoms'; +import { collectionsCRUDAtom } from '@affine/core/atoms/collections'; import { useBlockSuitePageMeta } from '@affine/core/hooks/use-block-suite-page-meta'; import { useWorkspaceStatus } from '@affine/core/hooks/use-workspace-status'; import { waitForCurrentWorkspaceAtom } from '@affine/core/modules/workspace'; -import { WorkspaceSubPath } from '@affine/core/shared'; import { globalBlockSuiteSchema, SyncEngineStep } from '@affine/workspace'; import { BookmarkService, customImageProxyMiddleware, + EmbedGithubService, + EmbedLoomService, + EmbedYoutubeService, ImageService, + type PageService, } from '@blocksuite/blocks'; import type { AffineEditorContainer } from '@blocksuite/presets'; import type { Page, Workspace } from '@blocksuite/store'; -import { appSettingAtom } from '@toeverything/infra/atom'; -import { useAtom, useAtomValue, useSetAtom } from 'jotai'; +import { appSettingAtom } from '@toeverything/infra'; +import { useAtom, useAtomValue, useSetAtom, useStore } from 'jotai'; import { memo, type ReactElement, @@ -25,8 +30,6 @@ import { import { useParams } from 'react-router-dom'; import type { Map as YMap } from 'yjs'; -import { setPageModeAtom } from '../../../atoms'; -import { collectionsCRUDAtom } from '../../../atoms/collections'; import { currentModeAtom, currentPageIdAtom } from '../../../atoms/mode'; import { AffineErrorBoundary } from '../../../components/affine/affine-error-boundary'; import { HubIsland } from '../../../components/affine/hub-island'; @@ -42,7 +45,7 @@ import { TopTip } from '../../../components/top-tip'; import { useRegisterBlocksuiteEditorCommands } from '../../../hooks/affine/use-register-blocksuite-editor-commands'; import { usePageDocumentTitle } from '../../../hooks/use-global-state'; import { useNavigateHelper } from '../../../hooks/use-navigate-helper'; -import { performanceRenderLogger } from '../../../shared'; +import { performanceRenderLogger, WorkspaceSubPath } from '../../../shared'; import { PageNotFound } from '../../404'; import * as styles from './detail-page.css'; import { DetailPageHeader, RightSidebarHeader } from './detail-page-header'; @@ -121,6 +124,7 @@ const DetailPageImpl = memo(function DetailPageImpl({ page }: { page: Page }) { const setPageMode = useSetAtom(setPageModeAtom); useRegisterBlocksuiteEditorCommands(currentPageId, mode); usePageDocumentTitle(pageMeta); + const rootStore = useStore(); const onLoad = useCallback( (page: Page, editor: AffineEditorContainer) => { @@ -144,11 +148,35 @@ const DetailPageImpl = memo(function DetailPageImpl({ page }: { page: Page }) { } } catch {} - ImageService.setImageProxyURL(runtimeConfig.imageProxyUrl); - BookmarkService.setLinkPreviewEndpoint(runtimeConfig.linkPreviewUrl); - editor.host?.std.clipboard.use( + // blocksuite editor host + const editorHost = editor.host; + + // provide image proxy endpoint to blocksuite + editorHost.std.clipboard.use( customImageProxyMiddleware(runtimeConfig.imageProxyUrl) ); + ImageService.setImageProxyURL(runtimeConfig.imageProxyUrl); + + // provide link preview endpoint to blocksuite + BookmarkService.setLinkPreviewEndpoint(runtimeConfig.linkPreviewUrl); + EmbedGithubService.setLinkPreviewEndpoint(runtimeConfig.linkPreviewUrl); + EmbedYoutubeService.setLinkPreviewEndpoint(runtimeConfig.linkPreviewUrl); + EmbedLoomService.setLinkPreviewEndpoint(runtimeConfig.linkPreviewUrl); + + // provide page mode and updated date to blocksuite + const pageService = editorHost.std.spec.getService( + 'affine:page' + ) as PageService; + pageService.getPageMode = (pageId: string) => + rootStore.get(pageSettingFamily(pageId)).mode; + pageService.getPageUpdatedAt = (pageId: string) => { + const linkedPage = page.workspace.getPage(pageId); + if (!linkedPage) return new Date(); + + const updatedDate = linkedPage.meta.updatedDate; + const createDate = linkedPage.meta.createDate; + return updatedDate ? new Date(updatedDate) : new Date(createDate); + }; setPageMode(currentPageId, mode); // fixme: it seems pageLinkClicked is not triggered sometimes? @@ -173,6 +201,7 @@ const DetailPageImpl = memo(function DetailPageImpl({ page }: { page: Page }) { openPage, setPageMode, setTemporaryFilter, + rootStore, ] ); diff --git a/packages/frontend/templates/templates.gen.ts b/packages/frontend/templates/templates.gen.ts index aaf6e85bcb..df6762e110 100644 --- a/packages/frontend/templates/templates.gen.ts +++ b/packages/frontend/templates/templates.gen.ts @@ -1,28 +1,28 @@ /* eslint-disable simple-import-sort/imports */ // Auto generated, do not edit manually import json_0 from './onboarding/wbXL4bZcblxLKC6ETqcQ1.snapshot.json'; -import json_1 from './onboarding/Scod6coKmJJ-waH1-jkiW.snapshot.json'; -import json_2 from './onboarding/rzyBHDgN5KIlEYzB9oBaD.snapshot.json'; -import json_3 from './onboarding/RCpxnWMtBWmUZy5awgJBh.snapshot.json'; -import json_4 from './onboarding/nPPyOV0JBNKu5hvW9hE00.snapshot.json'; -import json_5 from './onboarding/info.json'; -import json_6 from './onboarding/GWsRbUtMF4Ee6foVg-H9R.snapshot.json'; -import json_7 from './onboarding/e5cYLNpIRUb-nwpSZGdix.snapshot.json'; -import json_8 from './onboarding/b1F2xKjgZ4ISHhXNe1kck.snapshot.json'; +import json_1 from './onboarding/rzyBHDgN5KIlEYzB9oBaD.snapshot.json'; +import json_2 from './onboarding/nPPyOV0JBNKu5hvW9hE00.snapshot.json'; +import json_3 from './onboarding/info.json'; +import json_4 from './onboarding/e5cYLNpIRUb-nwpSZGdix.snapshot.json'; +import json_5 from './onboarding/b1F2xKjgZ4ISHhXNe1kck.snapshot.json'; +import json_6 from './onboarding/Scod6coKmJJ-waH1-jkiW.snapshot.json'; +import json_7 from './onboarding/RCpxnWMtBWmUZy5awgJBh.snapshot.json'; +import json_8 from './onboarding/GWsRbUtMF4Ee6foVg-H9R.snapshot.json'; import json_9 from './onboarding/9iIScyvuIB_kUKbs1AYOQ.snapshot.json'; import json_10 from './onboarding/0nee_XzkrN23Xy7HMoXL-.snapshot.json'; import json_11 from './onboarding/-P-O4GSfVGTkI16zJRVa4.snapshot.json'; export const onboarding = { 'wbXL4bZcblxLKC6ETqcQ1.snapshot.json': json_0, - 'Scod6coKmJJ-waH1-jkiW.snapshot.json': json_1, - 'rzyBHDgN5KIlEYzB9oBaD.snapshot.json': json_2, - 'RCpxnWMtBWmUZy5awgJBh.snapshot.json': json_3, - 'nPPyOV0JBNKu5hvW9hE00.snapshot.json': json_4, - 'info.json': json_5, - 'GWsRbUtMF4Ee6foVg-H9R.snapshot.json': json_6, - 'e5cYLNpIRUb-nwpSZGdix.snapshot.json': json_7, - 'b1F2xKjgZ4ISHhXNe1kck.snapshot.json': json_8, + 'rzyBHDgN5KIlEYzB9oBaD.snapshot.json': json_1, + 'nPPyOV0JBNKu5hvW9hE00.snapshot.json': json_2, + 'info.json': json_3, + 'e5cYLNpIRUb-nwpSZGdix.snapshot.json': json_4, + 'b1F2xKjgZ4ISHhXNe1kck.snapshot.json': json_5, + 'Scod6coKmJJ-waH1-jkiW.snapshot.json': json_6, + 'RCpxnWMtBWmUZy5awgJBh.snapshot.json': json_7, + 'GWsRbUtMF4Ee6foVg-H9R.snapshot.json': json_8, '9iIScyvuIB_kUKbs1AYOQ.snapshot.json': json_9, '0nee_XzkrN23Xy7HMoXL-.snapshot.json': json_10, '-P-O4GSfVGTkI16zJRVa4.snapshot.json': json_11