Skip to content

Commit a49952b

Browse files
authored
Properly clean up gesture Animations (facebook#35559)
Follow up to facebook#35337. During a gesture, we always cancel the original animation and create a new one that we control. That's the one we need to add to the set that needs to be cancelled. Otherwise future gestures hang. An unfortunate consequence is that any custom ones that you start e.g. with facebook#35556 or through other means aren't automatically cleaned up (in fact there's not even a clean up callback yet). This can lead these to freeze the whole UI afterwards. It would be really good to get this fixed in browsers instead so we can revert facebook#35337.
1 parent 4bcf67e commit a49952b

1 file changed

Lines changed: 10 additions & 3 deletions

File tree

packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2372,6 +2372,7 @@ function animateGesture(
23722372
targetElement: Element,
23732373
pseudoElement: string,
23742374
timeline: GestureTimeline,
2375+
viewTransitionAnimations: Array<Animation>,
23752376
customTimelineCleanup: Array<() => void>,
23762377
rangeStart: number,
23772378
rangeEnd: number,
@@ -2464,7 +2465,7 @@ function animateGesture(
24642465
if (timeline instanceof AnimationTimeline) {
24652466
// Native Timeline
24662467
// $FlowFixMe[incompatible-call]
2467-
targetElement.animate(keyframes, {
2468+
const animation = targetElement.animate(keyframes, {
24682469
pseudoElement: pseudoElement,
24692470
// Set the timeline to the current gesture timeline to drive the updates.
24702471
timeline: timeline,
@@ -2482,6 +2483,7 @@ function animateGesture(
24822483
rangeStart: (reverse ? rangeEnd : rangeStart) + '%',
24832484
rangeEnd: (reverse ? rangeStart : rangeEnd) + '%',
24842485
});
2486+
viewTransitionAnimations.push(animation);
24852487
} else {
24862488
// Custom Timeline
24872489
// $FlowFixMe[incompatible-call]
@@ -2554,8 +2556,10 @@ export function startGestureTransition(
25542556
// $FlowFixMe
25552557
const pseudoElement: ?string = effect.pseudoElement;
25562558
if (pseudoElement == null) {
2557-
} else if (pseudoElement.startsWith('::view-transition')) {
2558-
viewTransitionAnimations.push(animations[i]);
2559+
} else if (
2560+
pseudoElement.startsWith('::view-transition') &&
2561+
effect.target === documentElement
2562+
) {
25592563
const timing = effect.getTiming();
25602564
const duration =
25612565
// $FlowFixMe[prop-missing]
@@ -2648,6 +2652,7 @@ export function startGestureTransition(
26482652
effect.target,
26492653
pseudoElement,
26502654
timeline,
2655+
viewTransitionAnimations,
26512656
customTimelineCleanup,
26522657
adjustedRangeStart,
26532658
adjustedRangeEnd,
@@ -2675,6 +2680,7 @@ export function startGestureTransition(
26752680
effect.target,
26762681
pseudoElementName,
26772682
timeline,
2683+
viewTransitionAnimations,
26782684
customTimelineCleanup,
26792685
rangeStart,
26802686
rangeEnd,
@@ -2696,6 +2702,7 @@ export function startGestureTransition(
26962702
duration: 1,
26972703
});
26982704
blockingAnim.pause();
2705+
viewTransitionAnimations.push(blockingAnim);
26992706
animateCallback();
27002707
};
27012708
// In Chrome, "new" animations are not ready in the ready callback. We have to wait

0 commit comments

Comments
 (0)