From 84778d7cfd58c991da4bb50cdbe4937f4780eb4a Mon Sep 17 00:00:00 2001 From: Joshua Gross Date: Wed, 17 Feb 2021 10:30:20 -0800 Subject: [PATCH] LayoutAnimation: ensure onCompleteCallback is called in Fabric and non-Fabric Summary: Previously this branch of code only ran on Fabric+iOS. It is also needed for non-Fabric+Android in case `setLayoutAnimationEnabledExperimental` is not called on Android and an animation is queued up. Changelog: [Internal] Reviewed By: ShikaSD Differential Revision: D26466482 fbshipit-source-id: 11c50bf94daa287a619f2b623785b60675eb6cf0 --- Libraries/LayoutAnimation/LayoutAnimation.js | 45 +++++++++----------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/Libraries/LayoutAnimation/LayoutAnimation.js b/Libraries/LayoutAnimation/LayoutAnimation.js index 731a3e76fea..9ff9f7fb1e6 100644 --- a/Libraries/LayoutAnimation/LayoutAnimation.js +++ b/Libraries/LayoutAnimation/LayoutAnimation.js @@ -43,10 +43,29 @@ function configureNext( return; } + // Since LayoutAnimations may possibly be disabled for now on iOS (Fabric), + // or Android (non-Fabric) we race a setTimeout with animation completion, + // in case onComplete is never called + // from native. Once LayoutAnimations+Fabric unconditionally ship everywhere, we can + // delete this mechanism at least in the Fabric branch. + let animationCompletionHasRun = false; + const onAnimationComplete = () => { + if (animationCompletionHasRun) { + return; + } + animationCompletionHasRun = true; + clearTimeout(raceWithAnimationId); + onAnimationDidEnd?.(); + }; + const raceWithAnimationId = setTimeout( + onAnimationComplete, + (config.duration ?? 0) + 17 /* one frame + 1ms */, + ); + if (UIManager?.configureNextLayoutAnimation) { UIManager.configureNextLayoutAnimation( config, - onAnimationDidEnd ?? function() {}, + onAnimationComplete ?? function() {}, onAnimationDidFail ?? function() {} /* this should never be called in Non-Fabric */, ); @@ -56,30 +75,6 @@ function configureNext( // conditionally enabled on iOS (pending fully shipping; this is a temporary state). const FabricUIManager: FabricUIManagerSpec = global?.nativeFabricUIManager; if (FabricUIManager?.configureNextLayoutAnimation) { - // Since LayoutAnimations may possibly be disabled for now on iOS, we race - // a setTimeout with animation completion, in case onComplete is never called - // from native. Once LayoutAnimations unconditionally ship everywhere, we can - // delete this mechanism. - // TODO: (T65643440) remove timeout once LayoutAnimation ships on iOS. - let animationCompletionHasRun = false; - const onAnimationComplete = () => { - if (Platform.OS === 'ios') { - if (animationCompletionHasRun) { - return; - } - animationCompletionHasRun = true; - clearTimeout(raceWithAnimationId); - } - onAnimationDidEnd?.(); - }; - const raceWithAnimationId = - Platform.OS === 'ios' - ? setTimeout( - onAnimationComplete, - (config.duration ?? 0) + 17 /* one frame + 1ms */, - ) - : null; - global?.nativeFabricUIManager?.configureNextLayoutAnimation( config, onAnimationComplete,