[fix] reparenting locked shapes (#2070)
This PR allows locked shapes to be reparented. This fixes a bug where grouped and locked shapes would disappear when their parent group would be ungrouped. ### Change Type - [x] `patch` — Bug fix ### Test Plan 1. Create two shapes. 2. Group the shapes. 3. Lock one shape. 4. Ungroup the group - [x] Unit Tests ### Release Notes - Fix a bug where grouped locked shapes would be deleted when ungrouped.
This commit is contained in:
parent
01d46bbe22
commit
bfb61b12ad
2 changed files with 54 additions and 9 deletions
|
@ -4787,16 +4787,25 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
|
||||
const invertedParentTransform = parentTransform.clone().invert()
|
||||
|
||||
let id: TLShapeId
|
||||
for (let i = 0; i < ids.length; i++) {
|
||||
id = ids[i]
|
||||
const shape = this.getShape(id)
|
||||
if (!shape) continue
|
||||
const shapesToReparent = compact(ids.map((id) => this.getShape(id)))
|
||||
|
||||
// The user is allowed to re-parent locked shapes. Unintutive? Yeah! But there are plenty of
|
||||
// times when a locked shape's parent is deleted... and we need to put that shape somewhere!
|
||||
const lockedShapes = shapesToReparent.filter((shape) => shape.isLocked)
|
||||
|
||||
if (lockedShapes.length) {
|
||||
// If we have locked shapes, unlock them before we update them
|
||||
this.updateShapes(lockedShapes.map(({ id, type }) => ({ id, type, isLocked: false })))
|
||||
}
|
||||
|
||||
for (let i = 0; i < shapesToReparent.length; i++) {
|
||||
const shape = shapesToReparent[i]
|
||||
|
||||
const pageTransform = this.getShapePageTransform(shape)!
|
||||
if (!pageTransform) continue
|
||||
const pagePoint = pageTransform.point()
|
||||
|
||||
if (!shape || !pagePoint) continue
|
||||
const pagePoint = pageTransform.point()
|
||||
if (!pagePoint) continue
|
||||
|
||||
const newPoint = invertedParentTransform.applyToPoint(pagePoint)
|
||||
const newRotation = pageTransform.rotation() - parentPageRotation
|
||||
|
@ -4809,10 +4818,12 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
y: newPoint.y,
|
||||
rotation: newRotation,
|
||||
index: indices[i],
|
||||
isLocked: shape.isLocked, // this will re-lock locked shapes
|
||||
})
|
||||
}
|
||||
|
||||
this.updateShapes(changes)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
|
|
|
@ -28,10 +28,9 @@ const ids = {
|
|||
boxD: createShapeId('boxD'),
|
||||
boxE: createShapeId('boxE'),
|
||||
boxF: createShapeId('boxF'),
|
||||
|
||||
boxX: createShapeId('boxX'),
|
||||
|
||||
lineA: createShapeId('lineA'),
|
||||
groupA: createShapeId('groupA'),
|
||||
}
|
||||
|
||||
const box = (
|
||||
|
@ -1965,3 +1964,38 @@ describe('Group opacity', () => {
|
|||
expect(group.opacity).toBe(1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Grouping / ungrouping locked shapes', () => {
|
||||
it('keeps locked shapes locked when grouped', () => {
|
||||
editor.createShapes([box(ids.boxA, 0, 0), box(ids.boxB, 200, 0)])
|
||||
editor.groupShapes([ids.boxA, ids.boxB], ids.groupA)
|
||||
editor.select(ids.boxA)
|
||||
|
||||
// Lock boxA
|
||||
editor.updateShape({ id: ids.boxA, type: 'geo', isLocked: true })
|
||||
|
||||
// Select the group; when we ungroup, the children should be selected
|
||||
editor.select(ids.groupA)
|
||||
|
||||
// Move the group shape; this should also move locked children
|
||||
editor.nudgeShapes([ids.groupA], { x: 100, y: 0 })
|
||||
|
||||
// When we ungroup, the locked children should...
|
||||
editor.ungroupShapes([ids.groupA])
|
||||
|
||||
// Still exist
|
||||
expect(editor.getShape(ids.boxA)).toBeTruthy()
|
||||
expect(editor.getShape(ids.boxB)).toBeTruthy()
|
||||
|
||||
// Both be selected
|
||||
expect(editor.selectedShapeIds).toMatchObject([ids.boxA, ids.boxB])
|
||||
|
||||
// And be in the correct position
|
||||
expect(editor.getShape(ids.boxA)!.x).toBe(100)
|
||||
expect(editor.getShape(ids.boxB)!.x).toBe(300)
|
||||
|
||||
// And have the correct locked state
|
||||
expect(editor.getShape(ids.boxA)!.isLocked).toBe(true)
|
||||
expect(editor.getShape(ids.boxB)!.isLocked).toBe(false)
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue