From 386a2396d13edae2a95f45e5f1cca99b8dad2fa0 Mon Sep 17 00:00:00 2001 From: David Sheldrick Date: Tue, 19 Sep 2023 16:29:13 +0100 Subject: [PATCH] Fix shape drag perf (#1932) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This prevents geometry from being recalculated when dragging shapes around. It uses an equality check on the shape props to opt out of recalculations. This still allows bounds to be calculated based on other reactive values, so if folks really want to use x,y values or opacity or whatever, they can call editor.getShape(id) when making their calculation. ### Change Type - [x] `patch` — Bug fix - [ ] `minor` — New feature - [ ] `major` — Breaking change - [ ] `dependencies` — Changes to package dependencies[^1] - [ ] `documentation` — Changes to the documentation only[^2] - [ ] `tests` — Changes to any test code only[^2] - [ ] `internal` — Any other changes that don't affect the published package[^2] - [ ] I don't know [^1]: publishes a `patch` release, for devDependencies use `internal` [^2]: will not publish a new version ### Release Notes - Fixes a perf regression for dragging shapes around --- packages/editor/src/lib/editor/Editor.ts | 8 +++++--- packages/store/api-report.md | 2 +- packages/store/src/lib/Store.ts | 14 ++++++++++---- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/packages/editor/src/lib/editor/Editor.ts b/packages/editor/src/lib/editor/Editor.ts index c2ed81c9e..38038abb2 100644 --- a/packages/editor/src/lib/editor/Editor.ts +++ b/packages/editor/src/lib/editor/Editor.ts @@ -3724,9 +3724,11 @@ export class Editor extends EventEmitter { @computed private get _shapeGeometryCache(): ComputedCache { - return this.store.createComputedCache('bounds', (shape) => { - return this.getShapeUtil(shape).getGeometry(shape) - }) + return this.store.createComputedCache( + 'bounds', + (shape) => this.getShapeUtil(shape).getGeometry(shape), + (a, b) => a.props === b.props + ) } /** diff --git a/packages/store/api-report.md b/packages/store/api-report.md index 3be5d05b2..ad8d23601 100644 --- a/packages/store/api-report.md +++ b/packages/store/api-report.md @@ -230,7 +230,7 @@ export class Store { // (undocumented) applyDiff(diff: RecordsDiff, runCallbacks?: boolean): void; clear: () => void; - createComputedCache: (name: string, derive: (record: V) => T | undefined) => ComputedCache; + createComputedCache: (name: string, derive: (record: V) => T | undefined, isEqual?: ((a: V, b: V) => boolean) | undefined) => ComputedCache; createSelectedComputedCache: (name: string, selector: (record: V) => T | undefined, derive: (input: T) => J | undefined) => ComputedCache; // @internal (undocumented) ensureStoreIsUsable(): void; diff --git a/packages/store/src/lib/Store.ts b/packages/store/src/lib/Store.ts index 5418836ad..7aca636e1 100644 --- a/packages/store/src/lib/Store.ts +++ b/packages/store/src/lib/Store.ts @@ -766,7 +766,8 @@ export class Store { */ createComputedCache = ( name: string, - derive: (record: V) => T | undefined + derive: (record: V) => T | undefined, + isEqual?: (a: V, b: V) => boolean ): ComputedCache => { const cache = new Cache, Computed>() return { @@ -775,9 +776,14 @@ export class Store { if (!atom) { return undefined } - return cache.get(atom, () => - computed(name + ':' + id, () => derive(atom.value as V)) - ).value + return cache.get(atom, () => { + const recordSignal = isEqual + ? computed(atom.name + ':equals', () => atom.value, { isEqual }) + : atom + return computed(name + ':' + id, () => { + return derive(recordSignal.value as V) + }) + }).value }, } }