Fix bug when nudging shapes with bindings

This commit is contained in:
Steve Ruiz 2021-09-02 15:46:35 +01:00
parent d09d4087d3
commit 054a9e4acd
2 changed files with 86 additions and 5 deletions

View file

@ -1,5 +1,7 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { TLDrawState } from '~state'
import { mockDocument } from '~test'
import { ArrowShape, TLDrawShapeType } from '~types'
describe('Translate command', () => {
const tlstate = new TLDrawState()
@ -27,6 +29,83 @@ describe('Translate command', () => {
expect(tlstate.getShape('rect2').point).toEqual([110, 120])
})
it.todo('deleted bindings if nudging shape is bound to other shapes')
// When nudging an arrow shape, delete its bindings
describe('when nudging shapes with bindings', () => {
it('deleted bindings if nudging shape is bound to other shapes', () => {
tlstate
.resetDocument()
.createShapes(
{
id: 'target1',
type: TLDrawShapeType.Rectangle,
point: [0, 0],
size: [100, 100],
},
{
type: TLDrawShapeType.Arrow,
id: 'arrow1',
point: [200, 200],
}
)
.select('arrow1')
.startHandleSession([200, 200], 'start')
.updateHandleSession([50, 50])
.completeSession()
const bindingId = tlstate.getShape<ArrowShape>('arrow1').handles.start.bindingId!
tlstate.select('arrow1').nudge([10, 10])
expect(tlstate.getBinding(bindingId)).toBeUndefined()
expect(tlstate.getShape<ArrowShape>('arrow1').handles.start.bindingId).toBeUndefined()
tlstate.undo()
expect(tlstate.getBinding(bindingId)).toBeDefined()
expect(tlstate.getShape<ArrowShape>('arrow1').handles.start.bindingId).toBe(bindingId)
tlstate.redo()
expect(tlstate.getBinding(bindingId)).toBeUndefined()
expect(tlstate.getShape<ArrowShape>('arrow1').handles.start.bindingId).toBeUndefined()
})
it('does not delete bindings if both bound and bound-to shapes are nudged', () => {
tlstate
.resetDocument()
.createShapes(
{
id: 'target1',
type: TLDrawShapeType.Rectangle,
point: [0, 0],
size: [100, 100],
},
{
type: TLDrawShapeType.Arrow,
id: 'arrow1',
point: [200, 200],
}
)
.select('arrow1')
.startHandleSession([200, 200], 'start')
.updateHandleSession([50, 50])
.completeSession()
const bindingId = tlstate.getShape<ArrowShape>('arrow1').handles.start.bindingId!
tlstate.select('arrow1', 'target1').nudge([10, 10])
expect(tlstate.getBinding(bindingId)).toBeDefined()
expect(tlstate.getShape<ArrowShape>('arrow1').handles.start.bindingId).toBe(bindingId)
tlstate.undo()
expect(tlstate.getBinding(bindingId)).toBeDefined()
expect(tlstate.getShape<ArrowShape>('arrow1').handles.start.bindingId).toBe(bindingId)
tlstate.redo()
expect(tlstate.getBinding(bindingId)).toBeDefined()
expect(tlstate.getShape<ArrowShape>('arrow1').handles.start.bindingId).toBe(bindingId)
})
})
})

View file

@ -27,8 +27,9 @@ export function translate(data: Data, ids: string[], delta: number[]): TLDrawCom
before.shapes = change.before
after.shapes = change.after
const bindingsToDelete = TLDR.getBindings(data, currentPageId).filter((binding) =>
ids.includes(binding.fromId)
// Delete bindings from nudged shapes, unless both bound and bound-to shapes are selected
const bindingsToDelete = TLDR.getBindings(data, currentPageId).filter(
(binding) => ids.includes(binding.fromId) && !ids.includes(binding.toId)
)
bindingsToDelete.forEach((binding) => {
@ -39,9 +40,10 @@ export function translate(data: Data, ids: string[], delta: number[]): TLDrawCom
// Let's also look at the bound shape...
const shape = TLDR.getShape(data, id, data.appState.currentPageId)
// If the bound shape has a handle that references the deleted binding, delete that reference
if (!shape.handles) continue
// If the bound shape has a handle that references the deleted binding, delete that reference
Object.values(shape.handles)
.filter((handle) => handle.bindingId === binding.id)
.forEach((handle) => {