mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
fix(studio): resolve lane-header removal against the clicked element
The lane-header keyframe toggle fires on whichever element owns the lane, which need not be the selected one. The remove path looked the animation up in the selected element's animations, so a non-selected element's flat tween missed and silently took the remove-one-keyframe branch, stranding the tween instead of deleting it.
This commit is contained in:
@@ -330,6 +330,41 @@ describe("useTimelineEditCallbacks — flat tween keyframe lanes", () => {
|
||||
view.unmount();
|
||||
});
|
||||
|
||||
// The lane-header toggle fires on whichever element owns the lane, which need
|
||||
// not be the selected one. Looking the flat tween up in the selected element's
|
||||
// animations misses, and the miss silently takes the remove-one-keyframe
|
||||
// branch, which strands the flat tween instead of deleting it.
|
||||
it("removes a non-selected element's flat tween through that element's own animations", async () => {
|
||||
const circle: TimelineElement = {
|
||||
...element,
|
||||
id: "circle",
|
||||
key: "scenes/main.html#circle",
|
||||
domId: "circle",
|
||||
};
|
||||
usePlayerStore.setState({
|
||||
elements: [element, circle],
|
||||
gsapAnimations: new Map([["scenes/main.html#circle", [otherFlatAnimation]]]),
|
||||
});
|
||||
const view = renderCallbacks();
|
||||
|
||||
await act(async () => {
|
||||
await view.callbacks.onTogglePropertyGroupKeyframe?.(circle, {
|
||||
animationId: otherFlatAnimation.id,
|
||||
propertyGroup: "position",
|
||||
tweenPercentage: 0,
|
||||
properties: { x: 0 },
|
||||
remove: true,
|
||||
});
|
||||
});
|
||||
|
||||
expect(mocks.actions.handleGsapDeleteAnimation).toHaveBeenCalledWith(
|
||||
otherFlatAnimation.id,
|
||||
mocks.selection,
|
||||
);
|
||||
expect(mocks.actions.handleGsapRemoveKeyframe).not.toHaveBeenCalled();
|
||||
view.unmount();
|
||||
});
|
||||
|
||||
it("keeps authored interior deletion on the per-keyframe path", () => {
|
||||
mocks.animations = [authoredInteriorAnimation()];
|
||||
usePlayerStore.setState({ gsapAnimations: new Map([["box", mocks.animations]]) });
|
||||
|
||||
@@ -324,10 +324,13 @@ export function useTimelineEditCallbacks({
|
||||
const selection = await buildDomSelectionForTimelineElement(element);
|
||||
if (!selection) return;
|
||||
if (target.remove) {
|
||||
// The clicked element's animations, not the selected element's: this
|
||||
// lookup decides delete-the-flat-tween vs remove-one-keyframe, and a
|
||||
// miss silently takes the keyframe branch, stranding the flat tween.
|
||||
removeKeyframeTarget(
|
||||
target.animationId,
|
||||
target.tweenPercentage,
|
||||
selectedGsapAnimations,
|
||||
resolveElementAnimations(element.key ?? element.id),
|
||||
selection,
|
||||
);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user