mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-03-24 16:18:39 +08:00
feat(editor): improve edgeless perf & memory usage (#14591)
#### PR Dependency Tree * **PR #14591** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * New canvas renderer debug metrics and controls for runtime inspection. * Mindmap/group reordering now normalizes group targets, improving reorder consistency. * **Bug Fixes** * Fixed connector behavior for empty/degenerate paths. * More aggressive viewport invalidation so structural changes display correctly. * Improved z-index synchronization during transforms and layer updates. * **Performance** * Retained DOM caching for brushes, shapes, and connectors to reduce DOM churn. * Targeted canvas refreshes, pooling, and reuse to lower redraw and memory overhead. * **Tests** * Added canvas renderer performance benchmarks and curve edge-case unit tests. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -6,6 +6,7 @@ import type {
|
||||
import { ungroupCommand } from '@blocksuite/affine/gfx/group';
|
||||
import type {
|
||||
GroupElementModel,
|
||||
MindmapElementModel,
|
||||
NoteBlockModel,
|
||||
} from '@blocksuite/affine/model';
|
||||
import { generateKeyBetween } from '@blocksuite/affine/std/gfx';
|
||||
@@ -253,6 +254,40 @@ test('blocks should rerender when their z-index changed', async () => {
|
||||
assertBlocksContent();
|
||||
});
|
||||
|
||||
test('block host z-index should update after reordering', async () => {
|
||||
const backId = addNote(doc);
|
||||
const frontId = addNote(doc);
|
||||
|
||||
await wait();
|
||||
|
||||
const getBlockHost = (id: string) =>
|
||||
document.querySelector<HTMLElement>(
|
||||
`affine-edgeless-root gfx-viewport > [data-block-id="${id}"]`
|
||||
);
|
||||
|
||||
const backHost = getBlockHost(backId);
|
||||
const frontHost = getBlockHost(frontId);
|
||||
|
||||
expect(backHost).not.toBeNull();
|
||||
expect(frontHost).not.toBeNull();
|
||||
expect(Number(backHost!.style.zIndex)).toBeLessThan(
|
||||
Number(frontHost!.style.zIndex)
|
||||
);
|
||||
|
||||
service.crud.updateElement(backId, {
|
||||
index: service.layer.getReorderedIndex(
|
||||
service.crud.getElementById(backId)!,
|
||||
'front'
|
||||
),
|
||||
});
|
||||
|
||||
await wait();
|
||||
|
||||
expect(Number(backHost!.style.zIndex)).toBeGreaterThan(
|
||||
Number(frontHost!.style.zIndex)
|
||||
);
|
||||
});
|
||||
|
||||
describe('layer reorder functionality', () => {
|
||||
let ids: string[] = [];
|
||||
|
||||
@@ -428,14 +463,17 @@ describe('group related functionality', () => {
|
||||
const elements = [
|
||||
service.crud.addElement('shape', {
|
||||
shapeType: 'rect',
|
||||
xywh: '[0,0,100,100]',
|
||||
})!,
|
||||
addNote(doc),
|
||||
service.crud.addElement('shape', {
|
||||
shapeType: 'rect',
|
||||
xywh: '[120,0,100,100]',
|
||||
})!,
|
||||
addNote(doc),
|
||||
service.crud.addElement('shape', {
|
||||
shapeType: 'rect',
|
||||
xywh: '[240,0,100,100]',
|
||||
})!,
|
||||
];
|
||||
|
||||
@@ -528,6 +566,35 @@ describe('group related functionality', () => {
|
||||
expect(service.layer.layers[1].elements[0]).toBe(group);
|
||||
});
|
||||
|
||||
test("change mindmap index should update its nodes' layer", async () => {
|
||||
const noteId = addNote(doc);
|
||||
const mindmapId = service.crud.addElement('mindmap', {
|
||||
children: {
|
||||
text: 'root',
|
||||
children: [{ text: 'child' }],
|
||||
},
|
||||
})!;
|
||||
|
||||
await wait();
|
||||
|
||||
const note = service.crud.getElementById(noteId)!;
|
||||
const mindmap = service.crud.getElementById(
|
||||
mindmapId
|
||||
)! as MindmapElementModel;
|
||||
const root = mindmap.tree.element;
|
||||
|
||||
expect(service.layer.getZIndex(root)).toBeGreaterThan(
|
||||
service.layer.getZIndex(note)
|
||||
);
|
||||
|
||||
mindmap.index = service.layer.getReorderedIndex(mindmap, 'back');
|
||||
await wait();
|
||||
|
||||
expect(service.layer.getZIndex(root)).toBeLessThan(
|
||||
service.layer.getZIndex(note)
|
||||
);
|
||||
});
|
||||
|
||||
test('should keep relative index order of elements after group, ungroup, undo, redo', () => {
|
||||
const edgeless = getDocRootBlock(doc, editor, 'edgeless');
|
||||
const elementIds = [
|
||||
@@ -769,6 +836,7 @@ test('indexed canvas should be inserted into edgeless portal when switch to edge
|
||||
|
||||
service.crud.addElement('shape', {
|
||||
shapeType: 'rect',
|
||||
xywh: '[0,0,100,100]',
|
||||
})!;
|
||||
|
||||
addNote(doc);
|
||||
@@ -777,6 +845,7 @@ test('indexed canvas should be inserted into edgeless portal when switch to edge
|
||||
|
||||
service.crud.addElement('shape', {
|
||||
shapeType: 'rect',
|
||||
xywh: '[120,0,100,100]',
|
||||
})!;
|
||||
|
||||
editor.mode = 'page';
|
||||
@@ -792,10 +861,10 @@ test('indexed canvas should be inserted into edgeless portal when switch to edge
|
||||
'.indexable-canvas'
|
||||
)[0] as HTMLCanvasElement;
|
||||
|
||||
expect(indexedCanvas.width).toBe(
|
||||
expect(indexedCanvas.width).toBeLessThanOrEqual(
|
||||
(surface.renderer as CanvasRenderer).canvas.width
|
||||
);
|
||||
expect(indexedCanvas.height).toBe(
|
||||
expect(indexedCanvas.height).toBeLessThanOrEqual(
|
||||
(surface.renderer as CanvasRenderer).canvas.height
|
||||
);
|
||||
expect(indexedCanvas.width).not.toBe(0);
|
||||
|
||||
Reference in New Issue
Block a user