mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-27 02:42:25 +08:00
feat(editor): replace flat layout cache with tree in turbo renderer (#11319)
### TL;DR Refactored the BlockSuite turbo renderer to use a hierarchical tree structure for layouts instead of a flat list, improving rendering accuracy and performance. ### What changed? - Redesigned the layout system to use a tree structure (`ViewportLayoutTree`) that better represents the document hierarchy - Added `blockId` to all layout objects for better tracking and debugging - Updated the layout query mechanism to work with models directly instead of components - Enhanced error handling with more descriptive warnings and error messages - Improved the painting process to traverse the layout tree recursively - Fixed viewport coordinate calculations for more accurate rendering - Updated the worker communication to support the new tree-based layout structure ### Why make this change? The previous flat layout structure didn't properly represent the hierarchical nature of documents, leading to rendering issues with nested blocks. This tree-based approach: 1. Better represents the actual document structure 2. Improves rendering accuracy for nested elements 3. Makes debugging easier with more consistent block identification 4. Provides a more robust foundation for future rendering optimizations 5. Reduces the likelihood of rendering artifacts when scrolling or zooming
This commit is contained in:
@@ -6,8 +6,9 @@ import {
|
||||
segmentSentences,
|
||||
} from '@blocksuite/affine-gfx-turbo-renderer';
|
||||
import type { Container } from '@blocksuite/global/di';
|
||||
import type { GfxBlockComponent } from '@blocksuite/std';
|
||||
import { clientToModelCoord } from '@blocksuite/std/gfx';
|
||||
import type { EditorHost, GfxBlockComponent } from '@blocksuite/std';
|
||||
import { clientToModelCoord, type ViewportRecord } from '@blocksuite/std/gfx';
|
||||
import type { BlockModel } from '@blocksuite/store';
|
||||
|
||||
import type { ListLayout } from './list-painter.worker';
|
||||
|
||||
@@ -21,24 +22,27 @@ export class ListLayoutHandlerExtension extends BlockLayoutHandlerExtension<List
|
||||
);
|
||||
}
|
||||
|
||||
queryLayout(component: GfxBlockComponent): ListLayout | null {
|
||||
// Select all list items within this list block
|
||||
override queryLayout(
|
||||
model: BlockModel,
|
||||
host: EditorHost,
|
||||
viewportRecord: ViewportRecord
|
||||
): ListLayout | null {
|
||||
const component = host.std.view.getBlock(model.id) as GfxBlockComponent;
|
||||
if (!component) return null;
|
||||
|
||||
// Find the list items within this specific list component
|
||||
const listItemSelector =
|
||||
'.affine-list-block-container .affine-list-rich-text-wrapper [data-v-text="true"]';
|
||||
const listItemNodes = component.querySelectorAll(listItemSelector);
|
||||
|
||||
if (listItemNodes.length === 0) return null;
|
||||
|
||||
const viewportRecord = component.gfx.viewport.deserializeRecord(
|
||||
component.dataset.viewportState
|
||||
);
|
||||
|
||||
if (!viewportRecord) return null;
|
||||
|
||||
const { zoom, viewScale } = viewportRecord;
|
||||
const list: ListLayout = {
|
||||
type: 'affine:list',
|
||||
items: [],
|
||||
blockId: model.id,
|
||||
rect: { x: 0, y: 0, w: 0, h: 0 },
|
||||
};
|
||||
|
||||
listItemNodes.forEach(listItemNode => {
|
||||
|
||||
@@ -77,10 +77,15 @@ class ListLayoutPainter implements BlockLayoutPainter {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isListLayout(layout)) return;
|
||||
if (!isListLayout(layout)) {
|
||||
console.warn(
|
||||
'Expected list layout but received different format:',
|
||||
layout
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const renderedPositions = new Set<string>();
|
||||
|
||||
layout.items.forEach(item => {
|
||||
const fontSize = item.fontSize;
|
||||
const baselineY = getBaseline(fontSize);
|
||||
|
||||
Reference in New Issue
Block a user