From c3ef2b885516782913e501381d8a791cc21ace94 Mon Sep 17 00:00:00 2001 From: Steve Ruiz Date: Wed, 1 Sep 2021 13:00:51 +0100 Subject: [PATCH] Fix bug with mutating bound shapes --- .../state/__snapshots__/tlstate.spec.ts.snap | 5 +++ packages/tldraw/src/state/tldr.ts | 4 +- packages/tldraw/src/state/tlstate.spec.ts | 45 ++++++++++++++++++- packages/tldraw/src/state/tlstate.ts | 5 ++- 4 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 packages/tldraw/src/state/__snapshots__/tlstate.spec.ts.snap diff --git a/packages/tldraw/src/state/__snapshots__/tlstate.spec.ts.snap b/packages/tldraw/src/state/__snapshots__/tlstate.spec.ts.snap new file mode 100644 index 000000000..ed667cca7 --- /dev/null +++ b/packages/tldraw/src/state/__snapshots__/tlstate.spec.ts.snap @@ -0,0 +1,5 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = `"[]"`; + +exports[` 2`] = `undefined`; diff --git a/packages/tldraw/src/state/tldr.ts b/packages/tldraw/src/state/tldr.ts index 383b2ea09..99bf2333c 100644 --- a/packages/tldraw/src/state/tldr.ts +++ b/packages/tldraw/src/state/tldr.ts @@ -348,7 +348,7 @@ export class TLDR { return Object.values(page.bindings) .filter((binding) => binding.fromId === id || binding.toId === id) .reduce((cData, binding) => { - if (!beforeShapes[binding.id]) { + if (!beforeShapes[binding.fromId]) { beforeShapes[binding.fromId] = Utils.deepClone( this.getShape(cData, binding.fromId, pageId) ) @@ -422,7 +422,7 @@ export class TLDR { const shape = this.getShape(data, id, pageId) const change = fn(shape, i) beforeShapes[id] = Object.fromEntries( - Object.keys(change).map((key) => [key, shape[key as keyof T]]) + Object.keys(change).map((key) => [key, { ...shape[key as keyof T] }]) ) as Partial afterShapes[id] = change }) diff --git a/packages/tldraw/src/state/tlstate.spec.ts b/packages/tldraw/src/state/tlstate.spec.ts index 3ca92fbcb..12ee2aa4a 100644 --- a/packages/tldraw/src/state/tlstate.spec.ts +++ b/packages/tldraw/src/state/tlstate.spec.ts @@ -1,5 +1,6 @@ import { TLDrawState } from './tlstate' import { mockDocument, TLStateUtils } from '~test' +import { ColorStyle, TLDrawShapeType } from '~types' describe('TLDrawState', () => { const tlstate = new TLDrawState() @@ -229,11 +230,51 @@ describe('TLDrawState', () => { describe('Copies to JSON', () => { tlstate.selectAll() - tlstate.copyJson() + expect(tlstate.copyJson()).toMatchSnapshot('copied json') }) describe('Copies to SVG', () => { tlstate.selectAll() - tlstate.copySvg() + expect(tlstate.copySvg()).toMatchSnapshot('copied svg') + }) + + describe('Mutates bound shapes', () => { + const tlstate = new TLDrawState() + + tlstate + .createShapes( + { + id: 'rect', + point: [0, 0], + size: [100, 100], + childIndex: 1, + type: TLDrawShapeType.Rectangle, + }, + { + id: 'arrow', + point: [200, 200], + childIndex: 2, + type: TLDrawShapeType.Arrow, + } + ) + .select('arrow') + .startHandleSession([200, 200], 'start', 'arrow') + .updateHandleSession([10, 10]) + .completeSession() + .selectAll() + .style({ color: ColorStyle.Red }) + + expect(tlstate.getShape('arrow').style.color).toBe(ColorStyle.Red) + expect(tlstate.getShape('rect').style.color).toBe(ColorStyle.Red) + + tlstate.undo() + + expect(tlstate.getShape('arrow').style.color).toBe(ColorStyle.Black) + expect(tlstate.getShape('rect').style.color).toBe(ColorStyle.Black) + + tlstate.redo() + + expect(tlstate.getShape('arrow').style.color).toBe(ColorStyle.Red) + expect(tlstate.getShape('rect').style.color).toBe(ColorStyle.Red) }) }) diff --git a/packages/tldraw/src/state/tlstate.ts b/packages/tldraw/src/state/tlstate.ts index 415702139..a83051f30 100644 --- a/packages/tldraw/src/state/tlstate.ts +++ b/packages/tldraw/src/state/tlstate.ts @@ -1129,7 +1129,10 @@ export class TLDrawState extends StateManager { if (shapes.length === 0) return this return this.create( ...shapes.map((shape) => { - return TLDR.getShapeUtils(shape as TLDrawShape).create(shape) + return TLDR.getShapeUtils(shape as TLDrawShape).create({ + ...shape, + parentId: shape.parentId || this.currentPageId, + }) }) ) }