From 58e9f8fed17a3ce71aa3569cdb58bc1246e675e6 Mon Sep 17 00:00:00 2001 From: Steve Ruiz Date: Fri, 24 Sep 2021 14:23:52 +0100 Subject: [PATCH] Fix undo/redo on deleted handles --- .../command/delete/delete.command.spec.ts | 14 +++++++ .../command/utils/removeShapesFromPage.ts | 12 ++++-- packages/tldraw/src/state/tlstate.ts | 38 ++++++++++++------- 3 files changed, 48 insertions(+), 16 deletions(-) diff --git a/packages/tldraw/src/state/command/delete/delete.command.spec.ts b/packages/tldraw/src/state/command/delete/delete.command.spec.ts index dee3728e8..501059962 100644 --- a/packages/tldraw/src/state/command/delete/delete.command.spec.ts +++ b/packages/tldraw/src/state/command/delete/delete.command.spec.ts @@ -56,6 +56,20 @@ describe('Delete command', () => { expect(tlstate.getShape('rect2')).toBe(undefined) }) + it('deletes bound shapes, undoes and redoes', () => { + const tlstate = new TLDrawState() + .createShapes( + { type: TLDrawShapeType.Rectangle, id: 'target1', point: [0, 0], size: [100, 100] }, + { type: TLDrawShapeType.Arrow, id: 'arrow1', point: [200, 200] } + ) + .select('arrow1') + .startHandleSession([200, 200], 'start') + .updateHandleSession([50, 50]) + .completeSession() + .delete() + .undo() + }) + it('deletes bound shapes', () => { expect(Object.values(tlstate.page.bindings)[0]).toBe(undefined) diff --git a/packages/tldraw/src/state/command/utils/removeShapesFromPage.ts b/packages/tldraw/src/state/command/utils/removeShapesFromPage.ts index 9cd049eea..af437ed8e 100644 --- a/packages/tldraw/src/state/command/utils/removeShapesFromPage.ts +++ b/packages/tldraw/src/state/command/utils/removeShapesFromPage.ts @@ -1,5 +1,5 @@ import { TLDR } from '~state/tldr' -import type { Data, GroupShape, PagePartial } from '~types' +import type { ArrowShape, Data, GroupShape, PagePartial } from '~types' export function removeShapesFromPage(data: Data, ids: string[], pageId: string) { const before: PagePartial = { @@ -75,7 +75,10 @@ export function removeShapesFromPage(data: Data, ids: string[], pageId: string) ...before.shapes[id], handles: { ...before.shapes[id]?.handles, - [handle.id]: { bindingId: binding.id }, + [handle.id]: { + ...before.shapes[id]?.handles?.[handle.id as keyof ArrowShape['handles']], + bindingId: binding.id, + }, }, } @@ -86,7 +89,10 @@ export function removeShapesFromPage(data: Data, ids: string[], pageId: string) ...after.shapes[id], handles: { ...after.shapes[id]?.handles, - [handle.id]: { bindingId: undefined }, + [handle.id]: { + ...after.shapes[id]?.handles?.[handle.id as keyof ArrowShape['handles']], + bindingId: undefined, + }, }, } } diff --git a/packages/tldraw/src/state/tlstate.ts b/packages/tldraw/src/state/tlstate.ts index 6cf8b9b8e..6f0c06542 100644 --- a/packages/tldraw/src/state/tlstate.ts +++ b/packages/tldraw/src/state/tlstate.ts @@ -244,26 +244,38 @@ export class TLDrawState extends StateManager { bindingsToUpdate.forEach((binding) => { const toShape = page.shapes[binding.toId] const fromShape = page.shapes[binding.fromId] + const toUtils = TLDR.getShapeUtils(toShape) // We only need to update the binding's "from" shape const util = TLDR.getShapeUtils(fromShape) - const fromDelta = util.onBindingChange( - fromShape, - binding, - toShape, - toUtils.getBounds(toShape), - toUtils.getCenter(toShape) - ) + try { + const fromDelta = util.onBindingChange( + fromShape, + binding, + toShape, + toUtils.getBounds(toShape), + toUtils.getCenter(toShape) + ) - if (fromDelta) { - const nextShape = { - ...fromShape, - ...fromDelta, - } as TLDrawShape + if (fromDelta) { + const nextShape = { + ...fromShape, + ...fromDelta, + } as TLDrawShape - page.shapes[fromShape.id] = nextShape + page.shapes[fromShape.id] = nextShape + } + } catch (e) { + console.log( + fromShape, + binding, + toShape, + toUtils.getBounds(toShape), + toUtils.getCenter(toShape) + ) + throw Error('something went wrong') } })