fix: render embed linked/synced doc as affine-reference for shared pages (#7179)

fix TOV-779
This commit is contained in:
pengx17
2024-06-07 11:42:48 +00:00
parent 8dc3fd2a99
commit ab26e0f360
5 changed files with 84 additions and 12 deletions

View File

@@ -46,6 +46,7 @@ function forwardSlot<T extends Record<string, Slot<any>>>(
interface BlocksuiteEditorContainerProps { interface BlocksuiteEditorContainerProps {
page: Doc; page: Doc;
mode: DocMode; mode: DocMode;
shared?: boolean;
className?: string; className?: string;
style?: React.CSSProperties; style?: React.CSSProperties;
defaultSelectedBlockId?: string; defaultSelectedBlockId?: string;
@@ -102,7 +103,7 @@ export const BlocksuiteEditorContainer = forwardRef<
AffineEditorContainer, AffineEditorContainer,
BlocksuiteEditorContainerProps BlocksuiteEditorContainerProps
>(function AffineEditorContainer( >(function AffineEditorContainer(
{ page, mode, className, style, defaultSelectedBlockId }, { page, mode, className, style, defaultSelectedBlockId, shared },
ref ref
) { ) {
const scrolledRef = useRef(false); const scrolledRef = useRef(false);
@@ -327,9 +328,13 @@ export const BlocksuiteEditorContainer = forwardRef<
ref={rootRef} ref={rootRef}
> >
{mode === 'page' ? ( {mode === 'page' ? (
<BlocksuiteDocEditor page={page} ref={docRef} /> <BlocksuiteDocEditor shared={shared} page={page} ref={docRef} />
) : ( ) : (
<BlocksuiteEdgelessEditor page={page} ref={edgelessRef} /> <BlocksuiteEdgelessEditor
shared={shared}
page={page}
ref={edgelessRef}
/>
)} )}
</div> </div>
); );

View File

@@ -23,6 +23,7 @@ export type ErrorBoundaryProps = {
export type EditorProps = { export type EditorProps = {
page: Doc; page: Doc;
mode: 'page' | 'edgeless'; mode: 'page' | 'edgeless';
shared?: boolean;
defaultSelectedBlockId?: string; defaultSelectedBlockId?: string;
// on Editor instance instantiated // on Editor instance instantiated
onLoadEditor?: (editor: AffineEditorContainer) => () => void; onLoadEditor?: (editor: AffineEditorContainer) => () => void;
@@ -54,7 +55,15 @@ function usePageRoot(page: Doc) {
const BlockSuiteEditorImpl = forwardRef<AffineEditorContainer, EditorProps>( const BlockSuiteEditorImpl = forwardRef<AffineEditorContainer, EditorProps>(
function BlockSuiteEditorImpl( function BlockSuiteEditorImpl(
{ mode, page, className, defaultSelectedBlockId, onLoadEditor, style }, {
mode,
page,
className,
defaultSelectedBlockId,
onLoadEditor,
shared,
style,
},
ref ref
) { ) {
usePageRoot(page); usePageRoot(page);
@@ -89,6 +98,7 @@ const BlockSuiteEditorImpl = forwardRef<AffineEditorContainer, EditorProps>(
<BlocksuiteEditorContainer <BlocksuiteEditorContainer
mode={mode} mode={mode}
page={page} page={page}
shared={shared}
ref={onRefChange} ref={onRefChange}
className={className} className={className}
style={style} style={style}

View File

@@ -7,7 +7,6 @@ import { useJournalInfoHelper } from '@affine/core/hooks/use-journal';
import { QuickSearchService } from '@affine/core/modules/cmdk'; import { QuickSearchService } from '@affine/core/modules/cmdk';
import { PeekViewService } from '@affine/core/modules/peek-view'; import { PeekViewService } from '@affine/core/modules/peek-view';
import { WorkbenchService } from '@affine/core/modules/workbench'; import { WorkbenchService } from '@affine/core/modules/workbench';
import type { BlockSpec } from '@blocksuite/block-std';
import { import {
BiDirectionalLinkPanel, BiDirectionalLinkPanel,
DocMetaTags, DocMetaTags,
@@ -16,7 +15,7 @@ import {
PageEditor, PageEditor,
} from '@blocksuite/presets'; } from '@blocksuite/presets';
import type { Doc } from '@blocksuite/store'; import type { Doc } from '@blocksuite/store';
import { useLiveData, useService } from '@toeverything/infra'; import { type DocMode, useLiveData, useService } from '@toeverything/infra';
import React, { import React, {
forwardRef, forwardRef,
Fragment, Fragment,
@@ -31,6 +30,7 @@ import { PagePropertiesTable } from '../../affine/page-properties';
import { AffinePageReference } from '../../affine/reference-link'; import { AffinePageReference } from '../../affine/reference-link';
import { BlocksuiteEditorJournalDocTitle } from './journal-doc-title'; import { BlocksuiteEditorJournalDocTitle } from './journal-doc-title';
import { import {
patchForSharedPage,
patchNotificationService, patchNotificationService,
patchPeekViewService, patchPeekViewService,
patchQuickSearchService, patchQuickSearchService,
@@ -66,9 +66,10 @@ const adapted = {
interface BlocksuiteEditorProps { interface BlocksuiteEditorProps {
page: Doc; page: Doc;
shared?: boolean;
} }
const usePatchSpecs = (page: Doc, specs: BlockSpec[]) => { const usePatchSpecs = (page: Doc, shared: boolean, mode: DocMode) => {
const [reactToLit, portals] = useLitPortalFactory(); const [reactToLit, portals] = useLitPortalFactory();
const peekViewService = useService(PeekViewService); const peekViewService = useService(PeekViewService);
const quickSearchService = useService(QuickSearchService); const quickSearchService = useService(QuickSearchService);
@@ -82,6 +83,8 @@ const usePatchSpecs = (page: Doc, specs: BlockSpec[]) => {
}; };
}, [page.collection]); }, [page.collection]);
const specs = mode === 'page' ? PageModeSpecs : EdgelessModeSpecs;
const confirmModal = useConfirmModal(); const confirmModal = useConfirmModal();
const patchedSpecs = useMemo(() => { const patchedSpecs = useMemo(() => {
let patched = patchReferenceRenderer(specs, reactToLit, referenceRenderer); let patched = patchReferenceRenderer(specs, reactToLit, referenceRenderer);
@@ -95,6 +98,9 @@ const usePatchSpecs = (page: Doc, specs: BlockSpec[]) => {
if (!page.readonly) { if (!page.readonly) {
patched = patchQuickSearchService(patched, quickSearchService); patched = patchQuickSearchService(patched, quickSearchService);
} }
if (shared) {
patched = patchForSharedPage(patched);
}
return patched; return patched;
}, [ }, [
confirmModal, confirmModal,
@@ -103,6 +109,7 @@ const usePatchSpecs = (page: Doc, specs: BlockSpec[]) => {
quickSearchService, quickSearchService,
reactToLit, reactToLit,
referenceRenderer, referenceRenderer,
shared,
specs, specs,
]); ]);
@@ -124,7 +131,7 @@ const usePatchSpecs = (page: Doc, specs: BlockSpec[]) => {
export const BlocksuiteDocEditor = forwardRef< export const BlocksuiteDocEditor = forwardRef<
PageEditor, PageEditor,
BlocksuiteEditorProps BlocksuiteEditorProps
>(function BlocksuiteDocEditor({ page }, ref) { >(function BlocksuiteDocEditor({ page, shared }, ref) {
const titleRef = useRef<DocTitle>(null); const titleRef = useRef<DocTitle>(null);
const docRef = useRef<PageEditor | null>(null); const docRef = useRef<PageEditor | null>(null);
const [docPage, setDocPage] = const [docPage, setDocPage] =
@@ -166,7 +173,7 @@ export const BlocksuiteDocEditor = forwardRef<
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
const [specs, portals] = usePatchSpecs(page, PageModeSpecs); const [specs, portals] = usePatchSpecs(page, !!shared, 'page');
return ( return (
<> <>
@@ -203,8 +210,8 @@ export const BlocksuiteDocEditor = forwardRef<
export const BlocksuiteEdgelessEditor = forwardRef< export const BlocksuiteEdgelessEditor = forwardRef<
EdgelessEditor, EdgelessEditor,
BlocksuiteEditorProps BlocksuiteEditorProps
>(function BlocksuiteEdgelessEditor({ page }, ref) { >(function BlocksuiteEdgelessEditor({ page, shared }, ref) {
const [specs, portals] = usePatchSpecs(page, EdgelessModeSpecs); const [specs, portals] = usePatchSpecs(page, !!shared, 'edgeless');
const editorRef = useRef<EdgelessEditor | null>(null); const editorRef = useRef<EdgelessEditor | null>(null);
const onDocRef = useCallback( const onDocRef = useCallback(

View File

@@ -18,10 +18,16 @@ import type { BlockSpec, WidgetElement } from '@blocksuite/block-std';
import { import {
type AffineReference, type AffineReference,
AffineSlashMenuWidget, AffineSlashMenuWidget,
EmbedBlockElement,
type EmbedLinkedDocBlockService,
type EmbedLinkedDocModel,
type ParagraphBlockService, type ParagraphBlockService,
ReferenceNodeConfig,
type RootService, type RootService,
} from '@blocksuite/blocks'; } from '@blocksuite/blocks';
import { LitElement, type TemplateResult } from 'lit'; import { html, LitElement, type TemplateResult } from 'lit';
import { customElement } from 'lit/decorators.js';
import { literal } from 'lit/static-html.js';
import React, { createElement, type ReactNode } from 'react'; import React, { createElement, type ReactNode } from 'react';
const logger = new DebugLogger('affine::spec-patchers'); const logger = new DebugLogger('affine::spec-patchers');
@@ -377,3 +383,46 @@ export function patchQuickSearchService(
return specs; return specs;
} }
@customElement('affine-linked-doc-ref-block')
export class LinkedDocBlockComponent extends EmbedBlockElement<
EmbedLinkedDocModel,
EmbedLinkedDocBlockService
> {
referenceNodeConfig = new ReferenceNodeConfig();
override render() {
this.referenceNodeConfig.setDoc(this.model.doc);
return html`<affine-reference
.delta=${{
insert: '',
attributes: {
reference: {
type: 'LinkedPage',
pageId: this.model.pageId,
},
},
} as const}
.config=${this.referenceNodeConfig}
></affine-reference>`;
}
}
export function patchForSharedPage(specs: BlockSpec[]) {
return specs.map(spec => {
const linkedDocNames = [
'affine:embed-linked-doc',
'affine:embed-synced-doc',
];
if (linkedDocNames.includes(spec.schema.model.flavour)) {
spec = {
...spec,
view: {
component: literal`affine-linked-doc-ref-block`,
widgets: {},
},
};
}
return spec;
});
}

View File

@@ -114,6 +114,7 @@ const PageDetailEditorMain = memo(function PageDetailEditorMain({
} }
mode={mode} mode={mode}
page={page} page={page}
shared={isPublic}
defaultSelectedBlockId={blockId} defaultSelectedBlockId={blockId}
onLoadEditor={onLoadEditor} onLoadEditor={onLoadEditor}
/> />