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:
22
blocksuite/framework/global/src/__tests__/curve.unit.spec.ts
Normal file
22
blocksuite/framework/global/src/__tests__/curve.unit.spec.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
|
||||
import { getBezierParameters } from '../gfx/curve.js';
|
||||
import { PointLocation } from '../gfx/model/index.js';
|
||||
|
||||
describe('getBezierParameters', () => {
|
||||
test('should handle empty path', () => {
|
||||
expect(() => getBezierParameters([])).not.toThrow();
|
||||
expect(getBezierParameters([])).toEqual([
|
||||
new PointLocation(),
|
||||
new PointLocation(),
|
||||
new PointLocation(),
|
||||
new PointLocation(),
|
||||
]);
|
||||
});
|
||||
|
||||
test('should handle single-point path', () => {
|
||||
const point = new PointLocation([10, 20]);
|
||||
|
||||
expect(getBezierParameters([point])).toEqual([point, point, point, point]);
|
||||
});
|
||||
});
|
||||
@@ -142,6 +142,11 @@ export function getBezierNearestPoint(
|
||||
export function getBezierParameters(
|
||||
points: PointLocation[]
|
||||
): BezierCurveParameters {
|
||||
if (points.length === 0) {
|
||||
const point = new PointLocation();
|
||||
return [point, point, point, point];
|
||||
}
|
||||
|
||||
// Fallback for degenerate Bezier curve (all points are at the same position)
|
||||
if (points.length === 1) {
|
||||
const point = points[0];
|
||||
|
||||
@@ -596,7 +596,7 @@ export class LayerManager extends GfxExtension {
|
||||
private _updateLayer(
|
||||
element: GfxModel | GfxLocalElementModel,
|
||||
props?: Record<string, unknown>,
|
||||
oldValues?: Record<string, unknown>
|
||||
_oldValues?: Record<string, unknown>
|
||||
) {
|
||||
const modelType = this._getModelType(element);
|
||||
const isLocalElem = element instanceof GfxLocalElementModel;
|
||||
@@ -613,16 +613,7 @@ export class LayerManager extends GfxExtension {
|
||||
};
|
||||
|
||||
if (shouldUpdateGroupChildren) {
|
||||
const group = element as GfxModel & GfxGroupCompatibleInterface;
|
||||
const oldChildIds = childIdsChanged
|
||||
? Array.isArray(oldValues?.['childIds'])
|
||||
? (oldValues['childIds'] as string[])
|
||||
: this._groupChildSnapshot.get(group.id)
|
||||
: undefined;
|
||||
|
||||
const relatedElements = this._getRelatedGroupElements(group, oldChildIds);
|
||||
this._refreshElementsInLayer(relatedElements);
|
||||
this._syncGroupChildSnapshot(group);
|
||||
this._reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,13 @@ function updateTransform(element: GfxBlockComponent) {
|
||||
element.style.transform = element.getCSSTransform();
|
||||
}
|
||||
|
||||
function updateZIndex(element: GfxBlockComponent) {
|
||||
const zIndex = element.toZIndex();
|
||||
if (element.style.zIndex !== zIndex) {
|
||||
element.style.zIndex = zIndex;
|
||||
}
|
||||
}
|
||||
|
||||
function updateBlockVisibility(view: GfxBlockComponent) {
|
||||
if (view.transformState$.value === 'active') {
|
||||
view.style.visibility = 'visible';
|
||||
@@ -58,14 +65,22 @@ function handleGfxConnection(instance: GfxBlockComponent) {
|
||||
instance.store.slots.blockUpdated.subscribe(({ type, id }) => {
|
||||
if (id === instance.model.id && type === 'update') {
|
||||
updateTransform(instance);
|
||||
updateZIndex(instance);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
instance.disposables.add(
|
||||
instance.gfx.layer.slots.layerUpdated.subscribe(() => {
|
||||
updateZIndex(instance);
|
||||
})
|
||||
);
|
||||
|
||||
instance.disposables.add(
|
||||
effect(() => {
|
||||
updateBlockVisibility(instance);
|
||||
updateTransform(instance);
|
||||
updateZIndex(instance);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user