diff --git a/blocksuite/affine/shared/src/viewport-renderer/viewport-renderer.ts b/blocksuite/affine/shared/src/viewport-renderer/viewport-renderer.ts index 20fb3ecf0c..b84a9fb68c 100644 --- a/blocksuite/affine/shared/src/viewport-renderer/viewport-renderer.ts +++ b/blocksuite/affine/shared/src/viewport-renderer/viewport-renderer.ts @@ -1,44 +1,62 @@ -import type { EditorHost } from '@blocksuite/block-std'; +import { + type BlockStdScope, + LifeCycleWatcher, + LifeCycleWatcherIdentifier, + StdIdentifier, +} from '@blocksuite/block-std'; import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx'; +import { type Container, type ServiceIdentifier } from '@blocksuite/global/di'; import { getSentenceRects, segmentSentences } from './text-utils.js'; import { type ParagraphLayout, type SectionLayout } from './types.js'; -export class ViewportTurboRenderer { +export const ViewportTurboRendererIdentifier = LifeCycleWatcherIdentifier( + 'ViewportTurboRenderer' +) as ServiceIdentifier; + +export class ViewportTurboRendererExtension extends LifeCycleWatcher { + static override setup(di: Container) { + di.addImpl(ViewportTurboRendererIdentifier, this, [StdIdentifier]); + } + public readonly canvas: HTMLCanvasElement = document.createElement('canvas'); private readonly worker: Worker; - private readonly targetContainer: HTMLElement; - private host!: EditorHost; private lastZoom: number | null = null; private lastSection: SectionLayout | null = null; private lastBitmap: ImageBitmap | null = null; - constructor(targetContainer: HTMLElement) { - this.targetContainer = targetContainer; - + constructor(std: BlockStdScope) { + super(std); this.worker = new Worker(new URL('./painter.worker.ts', import.meta.url), { type: 'module', }); + } - if (!this.targetContainer.querySelector('canvas')) { - this.targetContainer.append(this.canvas); + override mounted() { + const targetContainer = document.querySelector('#right-column')!; + if (!targetContainer.querySelector('canvas')) { + targetContainer.append(this.canvas); } } - setHost(host: EditorHost) { - this.host = host; + override unmounted() { + if (this.lastBitmap) { + this.lastBitmap.close(); + } + this.worker.terminate(); + this.canvas.remove(); } get viewport() { - return this.host.std.get(GfxControllerIdentifier).viewport; + return this.std.get(GfxControllerIdentifier).viewport; } getHostRect() { - return this.host.getBoundingClientRect(); + return this.std.host.getBoundingClientRect(); } getHostLayout() { - const paragraphBlocks = this.host.querySelectorAll( + const paragraphBlocks = this.std.host.querySelectorAll( '.affine-paragraph-rich-text-wrapper [data-v-text="true"]' ); @@ -207,6 +225,7 @@ export class ViewportTurboRenderer { public async render(): Promise { const hostLayout = this.getHostLayout(); + if (!hostLayout) return; const { section } = hostLayout; @@ -220,11 +239,4 @@ export class ViewportTurboRenderer { await this.renderSection(section); } } - - public destroy() { - if (this.lastBitmap) { - this.lastBitmap.close(); - } - this.worker.terminate(); - } } diff --git a/blocksuite/playground/examples/renderer/editor.ts b/blocksuite/playground/examples/renderer/editor.ts index af46eb7aa2..cb6ef5a4f6 100644 --- a/blocksuite/playground/examples/renderer/editor.ts +++ b/blocksuite/playground/examples/renderer/editor.ts @@ -1,5 +1,6 @@ import '../../style.css'; +import { ViewportTurboRendererExtension } from '@blocksuite/affine-shared/viewport-renderer'; import { effects as blocksEffects } from '@blocksuite/blocks/effects'; import { AffineEditorContainer } from '@blocksuite/presets'; import { effects as presetsEffects } from '@blocksuite/presets/effects'; @@ -11,6 +12,10 @@ presetsEffects(); export const doc = createEmptyDoc().init(); export const editor = new AffineEditorContainer(); +editor.pageSpecs = editor.pageSpecs.concat([ViewportTurboRendererExtension]); +editor.edgelessSpecs = editor.edgelessSpecs.concat([ + ViewportTurboRendererExtension, +]); editor.doc = doc; editor.mode = 'edgeless'; diff --git a/blocksuite/playground/examples/renderer/main.ts b/blocksuite/playground/examples/renderer/main.ts index 7fe678fbfa..c77798153e 100644 --- a/blocksuite/playground/examples/renderer/main.ts +++ b/blocksuite/playground/examples/renderer/main.ts @@ -1,4 +1,4 @@ -import { ViewportTurboRenderer } from '@blocksuite/affine-shared/viewport-renderer'; +import { ViewportTurboRendererIdentifier } from '@blocksuite/affine-shared/viewport-renderer'; import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx'; import { nextTick } from '@blocksuite/global/utils'; import { Text } from '@blocksuite/store'; @@ -8,11 +8,8 @@ import { doc, editor } from './editor.js'; type DocMode = 'page' | 'edgeless'; -const rightColumn = document.querySelector('#right-column') as HTMLElement; -const renderer = new ViewportTurboRenderer(rightColumn); - async function handleToCanvasClick() { - renderer.setHost(editor.host!); + const renderer = editor.std.get(ViewportTurboRendererIdentifier); await renderer.render(); const viewport = editor.std.get(GfxControllerIdentifier).viewport; viewport.viewportUpdated.on(async () => { @@ -23,7 +20,8 @@ async function handleToCanvasClick() { async function handleModeChange(mode: DocMode) { editor.mode = mode; await nextTick(); - renderer.setHost(editor.host!); + + const renderer = editor.std.get(ViewportTurboRendererIdentifier); await renderer.render(); }