diff --git a/src/reanimated2/core.ts b/src/reanimated2/core.ts index 761bb4e772a..c6ce18a162f 100644 --- a/src/reanimated2/core.ts +++ b/src/reanimated2/core.ts @@ -135,8 +135,18 @@ export function subscribeForKeyboardEvents( eventHandler: (state: number, height: number) => void, options: AnimatedKeyboardOptions ): number { + // TODO: this should really go with the same code path as other events, that is + // via registerEventHandler. For now we are copying the code from there. + function handleAndFlushImmediates(state: number, height: number) { + 'worklet'; + const now = performance.now(); + global.__frameTimestamp = now; + eventHandler(state, height); + global.__flushAnimationFrame(now); + global.__frameTimestamp = undefined; + } return NativeReanimatedModule.subscribeForKeyboardEvents( - makeShareableCloneRecursive(eventHandler), + makeShareableCloneRecursive(handleAndFlushImmediates), options.isStatusBarTranslucentAndroid ?? false ); } diff --git a/src/reanimated2/initializers.ts b/src/reanimated2/initializers.ts index 0f6a641a48a..78a1e1f6247 100644 --- a/src/reanimated2/initializers.ts +++ b/src/reanimated2/initializers.ts @@ -100,13 +100,25 @@ function setupRequestAnimationFrame() { const nativeRequestAnimationFrame = global.requestAnimationFrame; let animationFrameCallbacks: Array<(timestamp: number) => void> = []; + let lastFlushWasNative = true; - global.__flushAnimationFrame = (frameTimestamp: number) => { + function flushAnimationFrame(frameTimestamp: number, nativeFlush = false) { + if (!lastFlushWasNative && nativeFlush) { + // we ignore the first naitve flush that happens after flush coming from + // different source. In particular if rAF queue is flushed from events + // we already performed the work for the given frame and hence we don't + // need to run another set of animation in the same frame. + lastFlushWasNative = nativeFlush; + return; + } + lastFlushWasNative = nativeFlush; const currentCallbacks = animationFrameCallbacks; animationFrameCallbacks = []; currentCallbacks.forEach((f) => f(frameTimestamp)); flushImmediates(); - }; + } + + global.__flushAnimationFrame = flushAnimationFrame; global.requestAnimationFrame = ( callback: (timestamp: number) => void @@ -118,7 +130,7 @@ function setupRequestAnimationFrame() { // the callbacks are run, we clear the array. nativeRequestAnimationFrame((timestamp) => { global.__frameTimestamp = timestamp; - global.__flushAnimationFrame(timestamp); + flushAnimationFrame(timestamp, true); global.__frameTimestamp = undefined; }); }