refactor(editor): migrate viewport renderer to extension (#10094)

This removes `renderer.setHost(host)`
This commit is contained in:
doodlewind
2025-02-11 11:37:31 +00:00
parent c6932a8ae4
commit 3062bd0771
3 changed files with 42 additions and 27 deletions

View File

@@ -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 { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
import { type Container, type ServiceIdentifier } from '@blocksuite/global/di';
import { getSentenceRects, segmentSentences } from './text-utils.js'; import { getSentenceRects, segmentSentences } from './text-utils.js';
import { type ParagraphLayout, type SectionLayout } from './types.js'; import { type ParagraphLayout, type SectionLayout } from './types.js';
export class ViewportTurboRenderer { export const ViewportTurboRendererIdentifier = LifeCycleWatcherIdentifier(
'ViewportTurboRenderer'
) as ServiceIdentifier<ViewportTurboRendererExtension>;
export class ViewportTurboRendererExtension extends LifeCycleWatcher {
static override setup(di: Container) {
di.addImpl(ViewportTurboRendererIdentifier, this, [StdIdentifier]);
}
public readonly canvas: HTMLCanvasElement = document.createElement('canvas'); public readonly canvas: HTMLCanvasElement = document.createElement('canvas');
private readonly worker: Worker; private readonly worker: Worker;
private readonly targetContainer: HTMLElement;
private host!: EditorHost;
private lastZoom: number | null = null; private lastZoom: number | null = null;
private lastSection: SectionLayout | null = null; private lastSection: SectionLayout | null = null;
private lastBitmap: ImageBitmap | null = null; private lastBitmap: ImageBitmap | null = null;
constructor(targetContainer: HTMLElement) { constructor(std: BlockStdScope) {
this.targetContainer = targetContainer; super(std);
this.worker = new Worker(new URL('./painter.worker.ts', import.meta.url), { this.worker = new Worker(new URL('./painter.worker.ts', import.meta.url), {
type: 'module', type: 'module',
}); });
}
if (!this.targetContainer.querySelector('canvas')) { override mounted() {
this.targetContainer.append(this.canvas); const targetContainer = document.querySelector('#right-column')!;
if (!targetContainer.querySelector('canvas')) {
targetContainer.append(this.canvas);
} }
} }
setHost(host: EditorHost) { override unmounted() {
this.host = host; if (this.lastBitmap) {
this.lastBitmap.close();
}
this.worker.terminate();
this.canvas.remove();
} }
get viewport() { get viewport() {
return this.host.std.get(GfxControllerIdentifier).viewport; return this.std.get(GfxControllerIdentifier).viewport;
} }
getHostRect() { getHostRect() {
return this.host.getBoundingClientRect(); return this.std.host.getBoundingClientRect();
} }
getHostLayout() { getHostLayout() {
const paragraphBlocks = this.host.querySelectorAll( const paragraphBlocks = this.std.host.querySelectorAll(
'.affine-paragraph-rich-text-wrapper [data-v-text="true"]' '.affine-paragraph-rich-text-wrapper [data-v-text="true"]'
); );
@@ -207,6 +225,7 @@ export class ViewportTurboRenderer {
public async render(): Promise<void> { public async render(): Promise<void> {
const hostLayout = this.getHostLayout(); const hostLayout = this.getHostLayout();
if (!hostLayout) return; if (!hostLayout) return;
const { section } = hostLayout; const { section } = hostLayout;
@@ -220,11 +239,4 @@ export class ViewportTurboRenderer {
await this.renderSection(section); await this.renderSection(section);
} }
} }
public destroy() {
if (this.lastBitmap) {
this.lastBitmap.close();
}
this.worker.terminate();
}
} }

View File

@@ -1,5 +1,6 @@
import '../../style.css'; import '../../style.css';
import { ViewportTurboRendererExtension } from '@blocksuite/affine-shared/viewport-renderer';
import { effects as blocksEffects } from '@blocksuite/blocks/effects'; import { effects as blocksEffects } from '@blocksuite/blocks/effects';
import { AffineEditorContainer } from '@blocksuite/presets'; import { AffineEditorContainer } from '@blocksuite/presets';
import { effects as presetsEffects } from '@blocksuite/presets/effects'; import { effects as presetsEffects } from '@blocksuite/presets/effects';
@@ -11,6 +12,10 @@ presetsEffects();
export const doc = createEmptyDoc().init(); export const doc = createEmptyDoc().init();
export const editor = new AffineEditorContainer(); export const editor = new AffineEditorContainer();
editor.pageSpecs = editor.pageSpecs.concat([ViewportTurboRendererExtension]);
editor.edgelessSpecs = editor.edgelessSpecs.concat([
ViewportTurboRendererExtension,
]);
editor.doc = doc; editor.doc = doc;
editor.mode = 'edgeless'; editor.mode = 'edgeless';

View File

@@ -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 { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
import { nextTick } from '@blocksuite/global/utils'; import { nextTick } from '@blocksuite/global/utils';
import { Text } from '@blocksuite/store'; import { Text } from '@blocksuite/store';
@@ -8,11 +8,8 @@ import { doc, editor } from './editor.js';
type DocMode = 'page' | 'edgeless'; type DocMode = 'page' | 'edgeless';
const rightColumn = document.querySelector('#right-column') as HTMLElement;
const renderer = new ViewportTurboRenderer(rightColumn);
async function handleToCanvasClick() { async function handleToCanvasClick() {
renderer.setHost(editor.host!); const renderer = editor.std.get(ViewportTurboRendererIdentifier);
await renderer.render(); await renderer.render();
const viewport = editor.std.get(GfxControllerIdentifier).viewport; const viewport = editor.std.get(GfxControllerIdentifier).viewport;
viewport.viewportUpdated.on(async () => { viewport.viewportUpdated.on(async () => {
@@ -23,7 +20,8 @@ async function handleToCanvasClick() {
async function handleModeChange(mode: DocMode) { async function handleModeChange(mode: DocMode) {
editor.mode = mode; editor.mode = mode;
await nextTick(); await nextTick();
renderer.setHost(editor.host!);
const renderer = editor.std.get(ViewportTurboRendererIdentifier);
await renderer.render(); await renderer.render();
} }