diff --git a/packages/react-native/Libraries/Animated/animations/TimingAnimation.js b/packages/react-native/Libraries/Animated/animations/TimingAnimation.js index 0589855753f5..1d50b48de703 100644 --- a/packages/react-native/Libraries/Animated/animations/TimingAnimation.js +++ b/packages/react-native/Libraries/Animated/animations/TimingAnimation.js @@ -15,9 +15,22 @@ import type AnimatedValue from '../nodes/AnimatedValue'; import type AnimatedValueXY from '../nodes/AnimatedValueXY'; import type {AnimationConfig, EndCallback} from './Animation'; +import NativeAnimatedModule from '../NativeAnimatedModule'; +import NativeAnimatedTurboModule from '../NativeAnimatedTurboModule'; import AnimatedColor from '../nodes/AnimatedColor'; import Animation from './Animation'; +const Platform = require('../Utilities/Platform').default; + +const singleFrameInterval = + Platform.OS === 'ios' + ? NativeAnimatedTurboModule?.getConstants().singleFrameInterval + : NativeAnimatedModule?.getConstants().singleFrameInterval; + +const frameDuration = singleFrameInterval + ? singleFrameInterval * 1000 + : 1000.0 / 60.0; + export type TimingAnimationConfig = $ReadOnly<{ ...AnimationConfig, toValue: @@ -88,7 +101,6 @@ export default class TimingAnimation extends Animation { platformConfig: ?PlatformConfig, ... }> { - const frameDuration = 1000.0 / 60.0; const frames = []; const numFrames = Math.round(this._duration / frameDuration); for (let frame = 0; frame < numFrames; frame++) { diff --git a/packages/react-native/Libraries/NativeAnimation/Drivers/RCTAnimationDriver.h b/packages/react-native/Libraries/NativeAnimation/Drivers/RCTAnimationDriver.h index 2782c2abb70a..94d7d0bcf821 100644 --- a/packages/react-native/Libraries/NativeAnimation/Drivers/RCTAnimationDriver.h +++ b/packages/react-native/Libraries/NativeAnimation/Drivers/RCTAnimationDriver.h @@ -9,8 +9,30 @@ #import #import - -static CGFloat RCTSingleFrameInterval = (CGFloat)(1.0 / 60.0); +#import + +#ifdef __cplusplus +#include + +static CGFloat RCTSingleFrameInterval(void) +{ + if (facebook::react::ReactNativeFeatureFlags::disableHighRefreshRateAnimations()) { + // Fallback to 60 fps if disabled. + return 1.0 / 60; + } + + static CGFloat maximumFramesPerSecond; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + RCTUnsafeExecuteOnMainQueueSync(^{ + maximumFramesPerSecond = [UIScreen mainScreen].maximumFramesPerSecond; + }); + }); + + return 1.0 / maximumFramesPerSecond; +}; + +#endif @class RCTValueAnimatedNode; diff --git a/packages/react-native/Libraries/NativeAnimation/Drivers/RCTDecayAnimation.mm b/packages/react-native/Libraries/NativeAnimation/Drivers/RCTDecayAnimation.mm index b4aec0c33288..964e07a4becc 100644 --- a/packages/react-native/Libraries/NativeAnimation/Drivers/RCTDecayAnimation.mm +++ b/packages/react-native/Libraries/NativeAnimation/Drivers/RCTDecayAnimation.mm @@ -85,7 +85,7 @@ - (void)stepAnimationWithTime:(NSTimeInterval)currentTime if (_frameStartTime == -1) { // Since this is the first animation step, consider the start to be on the previous frame. - _frameStartTime = currentTime - RCTSingleFrameInterval; + _frameStartTime = currentTime - RCTSingleFrameInterval(); if (_fromValue == _lastValue) { // First iteration, assign _fromValue based on _valueNode. _fromValue = _valueNode.value; diff --git a/packages/react-native/Libraries/NativeAnimation/Drivers/RCTFrameAnimation.mm b/packages/react-native/Libraries/NativeAnimation/Drivers/RCTFrameAnimation.mm index 1de5cb13eb8f..d44c815d3fa1 100644 --- a/packages/react-native/Libraries/NativeAnimation/Drivers/RCTFrameAnimation.mm +++ b/packages/react-native/Libraries/NativeAnimation/Drivers/RCTFrameAnimation.mm @@ -95,10 +95,12 @@ - (void)stepAnimationWithTime:(NSTimeInterval)currentTime _animationCurrentTime = currentTime; NSTimeInterval currentDuration = (_animationCurrentTime - _animationStartTime) / RCTAnimationDragCoefficient(); + + CGFloat singleFrameInterval = RCTSingleFrameInterval(); // Determine how many frames have passed since last update. // Get index of frames that surround the current interval - NSUInteger startIndex = floor(currentDuration / RCTSingleFrameInterval); + NSUInteger startIndex = floor(currentDuration / singleFrameInterval); NSUInteger nextIndex = startIndex + 1; if (nextIndex >= _frames.count) { @@ -121,8 +123,8 @@ - (void)stepAnimationWithTime:(NSTimeInterval)currentTime // Do a linear remap of the two frames to safeguard against variable framerates NSNumber *fromFrameValue = _frames[startIndex]; NSNumber *toFrameValue = _frames[nextIndex]; - NSTimeInterval fromInterval = (double)startIndex * RCTSingleFrameInterval; - NSTimeInterval toInterval = (double)nextIndex * RCTSingleFrameInterval; + NSTimeInterval fromInterval = (double)startIndex * singleFrameInterval; + NSTimeInterval toInterval = (double)nextIndex * singleFrameInterval; // Interpolate between the individual frames to ensure the animations are // smooth and of the proper duration regardless of the framerate. diff --git a/packages/react-native/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.mm b/packages/react-native/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.mm index 206fdd26f851..fe032b1a7f6e 100644 --- a/packages/react-native/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.mm +++ b/packages/react-native/Libraries/NativeAnimation/RCTNativeAnimatedNodesManager.mm @@ -441,6 +441,7 @@ - (void)startAnimationLoopIfNeeded { if (!_displayLink && _activeAnimations.count > 0) { _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(stepAnimations:)]; + _displayLink.preferredFramesPerSecond = [UIScreen mainScreen].maximumFramesPerSecond; [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; } } diff --git a/packages/react-native/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm b/packages/react-native/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm index 000aa7018653..1c33dcd1ab76 100644 --- a/packages/react-native/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm +++ b/packages/react-native/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm @@ -11,9 +11,12 @@ #import #import #import +#import #import "RCTAnimationPlugins.h" +using namespace facebook::react; + typedef void (^AnimatedOperation)(RCTNativeAnimatedNodesManager *nodesManager); @interface RCTNativeAnimatedTurboModule () @@ -28,13 +31,14 @@ @implementation RCTNativeAnimatedTurboModule { NSMutableArray *_preOperations; NSSet *_userDrivenAnimationEndedEvents; + ModuleConstants _constants; } RCT_EXPORT_MODULE(); + (BOOL)requiresMainQueueSetup { - return NO; + return YES; } - (instancetype)init @@ -43,6 +47,10 @@ - (instancetype)init _operations = [NSMutableArray new]; _preOperations = [NSMutableArray new]; _userDrivenAnimationEndedEvents = [NSSet setWithArray:@[ @"onScrollEnded" ]]; + + _constants = typedConstants({ + .singleFrameInterval = RCTSingleFrameInterval() + }); } return self; } @@ -371,6 +379,18 @@ - (void)eventDispatcherWillDispatchEvent:(id)event }); } +#pragma mark -- Constants + +- (ModuleConstants)constantsToExport +{ + return _constants; +} + +- (ModuleConstants)getConstants +{ + return _constants; +} + - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params { diff --git a/packages/react-native/React/CoreModules/RCTFPSGraph.mm b/packages/react-native/React/CoreModules/RCTFPSGraph.mm index 1fc4bd24b9c3..c19efc9839a2 100644 --- a/packages/react-native/React/CoreModules/RCTFPSGraph.mm +++ b/packages/react-native/React/CoreModules/RCTFPSGraph.mm @@ -100,7 +100,8 @@ - (void)onTick:(NSTimeInterval)timestamp }); CGFloat previousScale = _scale; - CGFloat targetFps = MAX(_maxFPS, 60.0); + CGFloat screenRefreshRate = [UIScreen mainScreen].maximumFramesPerSecond; + CGFloat targetFps = MAX(_maxFPS, screenRefreshRate); _scale = targetFps / (CGFloat)_height; for (NSUInteger i = 0; i < _length - 1; i++) { // Move each Frame back one position and adjust to new scale (if there is a new scale) diff --git a/packages/react-native/React/CoreModules/RCTPerfMonitor.mm b/packages/react-native/React/CoreModules/RCTPerfMonitor.mm index 86eabc6fb20a..784e150d22bd 100644 --- a/packages/react-native/React/CoreModules/RCTPerfMonitor.mm +++ b/packages/react-native/React/CoreModules/RCTPerfMonitor.mm @@ -300,6 +300,7 @@ - (void)show [RCTKeyWindow() addSubview:self.container]; _uiDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(threadUpdate:)]; + _uiDisplayLink.preferredFramesPerSecond = [UIScreen mainScreen].maximumFramesPerSecond; [_uiDisplayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; self.container.frame = diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/AnimationDriver.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/AnimationDriver.kt index 66b7fe4c3985..e858e8fdb93e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/AnimationDriver.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/AnimationDriver.kt @@ -10,6 +10,20 @@ package com.facebook.react.animated import com.facebook.react.bridge.Callback import com.facebook.react.bridge.JSApplicationCausedNativeException import com.facebook.react.bridge.ReadableMap +import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags +import android.content.Context +import android.view.WindowManager + +public fun getSingleFrameInterval(context: Context): Double { + if (ReactNativeFeatureFlags.disableHighRefreshRateAnimations()) { + return 60.0 + } + + val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager + + val refreshRate = windowManager.defaultDisplay.supportedRefreshRates.maxOrNull() + return refreshRate?.toDouble() ?: 60.0 +} /** * Base class for different types of animation drivers. Can be used to implement simple time-based diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/FrameBasedAnimationDriver.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/FrameBasedAnimationDriver.kt index ab772fb69d2b..89a2cf4b8d9e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/FrameBasedAnimationDriver.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/FrameBasedAnimationDriver.kt @@ -7,18 +7,23 @@ package com.facebook.react.animated +import android.content.Context import com.facebook.common.logging.FLog +import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReadableMap import com.facebook.react.bridge.ReadableType import com.facebook.react.common.ReactConstants import com.facebook.react.common.build.ReactBuildConfig +import kotlin.math.roundToInt /** * Implementation of [AnimationDriver] which provides a support for simple time-based animations * that are pre-calculate on the JS side. For each animation frame JS provides a value from 0 to 1 * that indicates a progress of the animation at that frame. */ -internal class FrameBasedAnimationDriver(config: ReadableMap) : AnimationDriver() { +internal class FrameBasedAnimationDriver(config: ReadableMap, + private var context: ReactApplicationContext? +) : AnimationDriver() { private var startFrameTimeNanos: Long = -1 private var frames: DoubleArray = DoubleArray(0) private var toValue = 0.0 @@ -62,7 +67,8 @@ internal class FrameBasedAnimationDriver(config: ReadableMap) : AnimationDriver( } } val timeFromStartMillis = (frameTimeNanos - startFrameTimeNanos) / 1000000 - val frameIndex = Math.round(timeFromStartMillis / FRAME_TIME_MILLIS).toInt() + val frameTime = getFrameTimeMillis(context) + val frameIndex = (timeFromStartMillis / frameTime).roundToInt() if (frameIndex < 0) { val message = ("Calculated frame index should never be lower than 0. Called with frameTimeNanos " + @@ -98,7 +104,11 @@ internal class FrameBasedAnimationDriver(config: ReadableMap) : AnimationDriver( } companion object { - // 60FPS - private const val FRAME_TIME_MILLIS = 1000.0 / 60.0 + fun getFrameTimeMillis(context: Context?): Double { + if (context == null) { + return 1000.0 / 60.0 + } + return 1000.0 / getSingleFrameInterval(context) + } } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.kt index 6c5a505c9218..ade2670e9ca6 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.kt @@ -7,6 +7,8 @@ package com.facebook.react.animated +import android.content.Context +import android.view.WindowManager import androidx.annotation.AnyThread import androidx.annotation.UiThread import com.facebook.common.logging.FLog @@ -23,6 +25,7 @@ import com.facebook.react.bridge.buildReadableMap import com.facebook.react.common.annotations.UnstableReactNativeAPI import com.facebook.react.common.annotations.VisibleForTesting import com.facebook.react.common.build.ReactBuildConfig +import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags import com.facebook.react.module.annotations.ReactModule import com.facebook.react.modules.core.ReactChoreographer import com.facebook.react.uimanager.GuardedFrameCallback @@ -1112,6 +1115,12 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext) : finishOperationBatch() } + override fun getTypedExportedConstants(): Map? { + return mapOf( + "singleFrameInterval" to getSingleFrameInterval(context = reactApplicationContext), + ) + } + public companion object { public const val NAME: String = NativeAnimatedModuleSpec.NAME diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.kt index f7237025ab3b..01617d7e341c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.kt @@ -247,7 +247,7 @@ public class NativeAnimatedNodesManager( val animation = when (val type = animationConfig.getString("type")) { - "frames" -> FrameBasedAnimationDriver(animationConfig) + "frames" -> FrameBasedAnimationDriver(animationConfig, reactApplicationContext) "spring" -> SpringAnimation(animationConfig) "decay" -> DecayAnimation(animationConfig) else -> { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt index 7995a1db8c20..3472ca62b3d3 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<1e8a84a53072fa0c8665aead80d0199f>> + * @generated SignedSource<<1049251770171308f0dd79974aa9627c>> */ /** @@ -60,6 +60,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun disableFabricCommitInCXXAnimated(): Boolean = accessor.disableFabricCommitInCXXAnimated() + /** + * Disables high refresh rate animations on devices that support it (e.g. 120Hz). + */ + @JvmStatic + public fun disableHighRefreshRateAnimations(): Boolean = accessor.disableHighRefreshRateAnimations() + /** * Prevent FabricMountingManager from reordering mountItems, which may lead to invalid state on the UI thread */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt index b1c01a45d71a..0b0e4f6caab7 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<7347872aafe465d387af7706930203fb>> */ /** @@ -25,6 +25,7 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces private var cxxNativeAnimatedEnabledCache: Boolean? = null private var cxxNativeAnimatedRemoveJsSyncCache: Boolean? = null private var disableFabricCommitInCXXAnimatedCache: Boolean? = null + private var disableHighRefreshRateAnimationsCache: Boolean? = null private var disableMountItemReorderingAndroidCache: Boolean? = null private var disableOldAndroidAttachmentMetricsWorkaroundsCache: Boolean? = null private var disableTextLayoutManagerCacheAndroidCache: Boolean? = null @@ -134,6 +135,15 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun disableHighRefreshRateAnimations(): Boolean { + var cached = disableHighRefreshRateAnimationsCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.disableHighRefreshRateAnimations() + disableHighRefreshRateAnimationsCache = cached + } + return cached + } + override fun disableMountItemReorderingAndroid(): Boolean { var cached = disableMountItemReorderingAndroidCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt index 6ce331fd73f3..a8f0d1006b6c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<6e384a07f0e7bc237f72b49a1268e16b>> + * @generated SignedSource<> */ /** @@ -38,6 +38,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun disableFabricCommitInCXXAnimated(): Boolean + @DoNotStrip @JvmStatic public external fun disableHighRefreshRateAnimations(): Boolean + @DoNotStrip @JvmStatic public external fun disableMountItemReorderingAndroid(): Boolean @DoNotStrip @JvmStatic public external fun disableOldAndroidAttachmentMetricsWorkarounds(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt index 23a471f1f025..a4eca32267a6 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<3c47ba9c7fdbb37f0e06fdca56de3223>> + * @generated SignedSource<<7a6d60bf914bbeee4a50389ead452ec2>> */ /** @@ -33,6 +33,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun disableFabricCommitInCXXAnimated(): Boolean = false + override fun disableHighRefreshRateAnimations(): Boolean = false + override fun disableMountItemReorderingAndroid(): Boolean = false override fun disableOldAndroidAttachmentMetricsWorkarounds(): Boolean = true diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt index b0b54e83625f..8449a5e5952f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<1a19e0569371a038ba8d3849fb26eb5c>> + * @generated SignedSource<<464e4b731aceac397f2233b9e358c639>> */ /** @@ -29,6 +29,7 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc private var cxxNativeAnimatedEnabledCache: Boolean? = null private var cxxNativeAnimatedRemoveJsSyncCache: Boolean? = null private var disableFabricCommitInCXXAnimatedCache: Boolean? = null + private var disableHighRefreshRateAnimationsCache: Boolean? = null private var disableMountItemReorderingAndroidCache: Boolean? = null private var disableOldAndroidAttachmentMetricsWorkaroundsCache: Boolean? = null private var disableTextLayoutManagerCacheAndroidCache: Boolean? = null @@ -143,6 +144,16 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc return cached } + override fun disableHighRefreshRateAnimations(): Boolean { + var cached = disableHighRefreshRateAnimationsCache + if (cached == null) { + cached = currentProvider.disableHighRefreshRateAnimations() + accessedFeatureFlags.add("disableHighRefreshRateAnimations") + disableHighRefreshRateAnimationsCache = cached + } + return cached + } + override fun disableMountItemReorderingAndroid(): Boolean { var cached = disableMountItemReorderingAndroidCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt index 5c50635fb9e0..b44d5dc3da5d 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<5f84a9a17209b9ecb95e13e6567e7c3c>> + * @generated SignedSource<> */ /** @@ -33,6 +33,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun disableFabricCommitInCXXAnimated(): Boolean + @DoNotStrip public fun disableHighRefreshRateAnimations(): Boolean + @DoNotStrip public fun disableMountItemReorderingAndroid(): Boolean @DoNotStrip public fun disableOldAndroidAttachmentMetricsWorkarounds(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp index f2d24b7de7e2..23e78011daf8 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<1eff5bade524e3ad8e827ad4adb37f1a>> + * @generated SignedSource<> */ /** @@ -69,6 +69,12 @@ class ReactNativeFeatureFlagsJavaProvider return method(javaProvider_); } + bool disableHighRefreshRateAnimations() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("disableHighRefreshRateAnimations"); + return method(javaProvider_); + } + bool disableMountItemReorderingAndroid() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("disableMountItemReorderingAndroid"); @@ -476,6 +482,11 @@ bool JReactNativeFeatureFlagsCxxInterop::disableFabricCommitInCXXAnimated( return ReactNativeFeatureFlags::disableFabricCommitInCXXAnimated(); } +bool JReactNativeFeatureFlagsCxxInterop::disableHighRefreshRateAnimations( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::disableHighRefreshRateAnimations(); +} + bool JReactNativeFeatureFlagsCxxInterop::disableMountItemReorderingAndroid( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::disableMountItemReorderingAndroid(); @@ -837,6 +848,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "disableFabricCommitInCXXAnimated", JReactNativeFeatureFlagsCxxInterop::disableFabricCommitInCXXAnimated), + makeNativeMethod( + "disableHighRefreshRateAnimations", + JReactNativeFeatureFlagsCxxInterop::disableHighRefreshRateAnimations), makeNativeMethod( "disableMountItemReorderingAndroid", JReactNativeFeatureFlagsCxxInterop::disableMountItemReorderingAndroid), diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h index 3941c2e6f521..40d739c12203 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<05dba4cd49bd4f490e1ea943dd02cae0>> + * @generated SignedSource<> */ /** @@ -45,6 +45,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool disableFabricCommitInCXXAnimated( facebook::jni::alias_ref); + static bool disableHighRefreshRateAnimations( + facebook::jni::alias_ref); + static bool disableMountItemReorderingAndroid( facebook::jni::alias_ref); diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp index 87020a8702cc..dc1181ed2616 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<6abfb79e92705c2736b0084368c04eff>> */ /** @@ -46,6 +46,10 @@ bool ReactNativeFeatureFlags::disableFabricCommitInCXXAnimated() { return getAccessor().disableFabricCommitInCXXAnimated(); } +bool ReactNativeFeatureFlags::disableHighRefreshRateAnimations() { + return getAccessor().disableHighRefreshRateAnimations(); +} + bool ReactNativeFeatureFlags::disableMountItemReorderingAndroid() { return getAccessor().disableMountItemReorderingAndroid(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index b14e3be19c22..1fb1db6476ea 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<4831f7b871223d8347db93f9a0b3a1f9>> + * @generated SignedSource<> */ /** @@ -64,6 +64,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool disableFabricCommitInCXXAnimated(); + /** + * Disables high refresh rate animations on devices that support it (e.g. 120Hz). + */ + RN_EXPORT static bool disableHighRefreshRateAnimations(); + /** * Prevent FabricMountingManager from reordering mountItems, which may lead to invalid state on the UI thread */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 6f0a805e0932..8cae10688206 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -119,6 +119,24 @@ bool ReactNativeFeatureFlagsAccessor::disableFabricCommitInCXXAnimated() { return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::disableHighRefreshRateAnimations() { + auto flagValue = disableHighRefreshRateAnimations_.load(); + + if (!flagValue.has_value()) { + // This block is not exclusive but it is not necessary. + // If multiple threads try to initialize the feature flag, we would only + // be accessing the provider multiple times but the end state of this + // instance and the returned flag value would be the same. + + markFlagAsAccessed(5, "disableHighRefreshRateAnimations"); + + flagValue = currentProvider_->disableHighRefreshRateAnimations(); + disableHighRefreshRateAnimations_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::disableMountItemReorderingAndroid() { auto flagValue = disableMountItemReorderingAndroid_.load(); @@ -128,7 +146,7 @@ bool ReactNativeFeatureFlagsAccessor::disableMountItemReorderingAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(5, "disableMountItemReorderingAndroid"); + markFlagAsAccessed(6, "disableMountItemReorderingAndroid"); flagValue = currentProvider_->disableMountItemReorderingAndroid(); disableMountItemReorderingAndroid_ = flagValue; @@ -146,7 +164,7 @@ bool ReactNativeFeatureFlagsAccessor::disableOldAndroidAttachmentMetricsWorkarou // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(6, "disableOldAndroidAttachmentMetricsWorkarounds"); + markFlagAsAccessed(7, "disableOldAndroidAttachmentMetricsWorkarounds"); flagValue = currentProvider_->disableOldAndroidAttachmentMetricsWorkarounds(); disableOldAndroidAttachmentMetricsWorkarounds_ = flagValue; @@ -164,7 +182,7 @@ bool ReactNativeFeatureFlagsAccessor::disableTextLayoutManagerCacheAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(7, "disableTextLayoutManagerCacheAndroid"); + markFlagAsAccessed(8, "disableTextLayoutManagerCacheAndroid"); flagValue = currentProvider_->disableTextLayoutManagerCacheAndroid(); disableTextLayoutManagerCacheAndroid_ = flagValue; @@ -182,7 +200,7 @@ bool ReactNativeFeatureFlagsAccessor::enableAccessibilityOrder() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(8, "enableAccessibilityOrder"); + markFlagAsAccessed(9, "enableAccessibilityOrder"); flagValue = currentProvider_->enableAccessibilityOrder(); enableAccessibilityOrder_ = flagValue; @@ -200,7 +218,7 @@ bool ReactNativeFeatureFlagsAccessor::enableAccumulatedUpdatesInRawPropsAndroid( // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(9, "enableAccumulatedUpdatesInRawPropsAndroid"); + markFlagAsAccessed(10, "enableAccumulatedUpdatesInRawPropsAndroid"); flagValue = currentProvider_->enableAccumulatedUpdatesInRawPropsAndroid(); enableAccumulatedUpdatesInRawPropsAndroid_ = flagValue; @@ -218,7 +236,7 @@ bool ReactNativeFeatureFlagsAccessor::enableAndroidTextMeasurementOptimizations( // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(10, "enableAndroidTextMeasurementOptimizations"); + markFlagAsAccessed(11, "enableAndroidTextMeasurementOptimizations"); flagValue = currentProvider_->enableAndroidTextMeasurementOptimizations(); enableAndroidTextMeasurementOptimizations_ = flagValue; @@ -236,7 +254,7 @@ bool ReactNativeFeatureFlagsAccessor::enableBridgelessArchitecture() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(11, "enableBridgelessArchitecture"); + markFlagAsAccessed(12, "enableBridgelessArchitecture"); flagValue = currentProvider_->enableBridgelessArchitecture(); enableBridgelessArchitecture_ = flagValue; @@ -254,7 +272,7 @@ bool ReactNativeFeatureFlagsAccessor::enableCppPropsIteratorSetter() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(12, "enableCppPropsIteratorSetter"); + markFlagAsAccessed(13, "enableCppPropsIteratorSetter"); flagValue = currentProvider_->enableCppPropsIteratorSetter(); enableCppPropsIteratorSetter_ = flagValue; @@ -272,7 +290,7 @@ bool ReactNativeFeatureFlagsAccessor::enableCustomFocusSearchOnClippedElementsAn // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(13, "enableCustomFocusSearchOnClippedElementsAndroid"); + markFlagAsAccessed(14, "enableCustomFocusSearchOnClippedElementsAndroid"); flagValue = currentProvider_->enableCustomFocusSearchOnClippedElementsAndroid(); enableCustomFocusSearchOnClippedElementsAndroid_ = flagValue; @@ -290,7 +308,7 @@ bool ReactNativeFeatureFlagsAccessor::enableDestroyShadowTreeRevisionAsync() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(14, "enableDestroyShadowTreeRevisionAsync"); + markFlagAsAccessed(15, "enableDestroyShadowTreeRevisionAsync"); flagValue = currentProvider_->enableDestroyShadowTreeRevisionAsync(); enableDestroyShadowTreeRevisionAsync_ = flagValue; @@ -308,7 +326,7 @@ bool ReactNativeFeatureFlagsAccessor::enableDoubleMeasurementFixAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(15, "enableDoubleMeasurementFixAndroid"); + markFlagAsAccessed(16, "enableDoubleMeasurementFixAndroid"); flagValue = currentProvider_->enableDoubleMeasurementFixAndroid(); enableDoubleMeasurementFixAndroid_ = flagValue; @@ -326,7 +344,7 @@ bool ReactNativeFeatureFlagsAccessor::enableEagerMainQueueModulesOnIOS() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(16, "enableEagerMainQueueModulesOnIOS"); + markFlagAsAccessed(17, "enableEagerMainQueueModulesOnIOS"); flagValue = currentProvider_->enableEagerMainQueueModulesOnIOS(); enableEagerMainQueueModulesOnIOS_ = flagValue; @@ -344,7 +362,7 @@ bool ReactNativeFeatureFlagsAccessor::enableEagerRootViewAttachment() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(17, "enableEagerRootViewAttachment"); + markFlagAsAccessed(18, "enableEagerRootViewAttachment"); flagValue = currentProvider_->enableEagerRootViewAttachment(); enableEagerRootViewAttachment_ = flagValue; @@ -362,7 +380,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFabricLogs() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(18, "enableFabricLogs"); + markFlagAsAccessed(19, "enableFabricLogs"); flagValue = currentProvider_->enableFabricLogs(); enableFabricLogs_ = flagValue; @@ -380,7 +398,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFabricRenderer() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(19, "enableFabricRenderer"); + markFlagAsAccessed(20, "enableFabricRenderer"); flagValue = currentProvider_->enableFabricRenderer(); enableFabricRenderer_ = flagValue; @@ -398,7 +416,7 @@ bool ReactNativeFeatureFlagsAccessor::enableFontScaleChangesUpdatingLayout() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(20, "enableFontScaleChangesUpdatingLayout"); + markFlagAsAccessed(21, "enableFontScaleChangesUpdatingLayout"); flagValue = currentProvider_->enableFontScaleChangesUpdatingLayout(); enableFontScaleChangesUpdatingLayout_ = flagValue; @@ -416,7 +434,7 @@ bool ReactNativeFeatureFlagsAccessor::enableIOSTextBaselineOffsetPerLine() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(21, "enableIOSTextBaselineOffsetPerLine"); + markFlagAsAccessed(22, "enableIOSTextBaselineOffsetPerLine"); flagValue = currentProvider_->enableIOSTextBaselineOffsetPerLine(); enableIOSTextBaselineOffsetPerLine_ = flagValue; @@ -434,7 +452,7 @@ bool ReactNativeFeatureFlagsAccessor::enableIOSViewClipToPaddingBox() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(22, "enableIOSViewClipToPaddingBox"); + markFlagAsAccessed(23, "enableIOSViewClipToPaddingBox"); flagValue = currentProvider_->enableIOSViewClipToPaddingBox(); enableIOSViewClipToPaddingBox_ = flagValue; @@ -452,7 +470,7 @@ bool ReactNativeFeatureFlagsAccessor::enableImagePrefetchingAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(23, "enableImagePrefetchingAndroid"); + markFlagAsAccessed(24, "enableImagePrefetchingAndroid"); flagValue = currentProvider_->enableImagePrefetchingAndroid(); enableImagePrefetchingAndroid_ = flagValue; @@ -470,7 +488,7 @@ bool ReactNativeFeatureFlagsAccessor::enableImmediateUpdateModeForContentOffsetC // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(24, "enableImmediateUpdateModeForContentOffsetChanges"); + markFlagAsAccessed(25, "enableImmediateUpdateModeForContentOffsetChanges"); flagValue = currentProvider_->enableImmediateUpdateModeForContentOffsetChanges(); enableImmediateUpdateModeForContentOffsetChanges_ = flagValue; @@ -488,7 +506,7 @@ bool ReactNativeFeatureFlagsAccessor::enableInteropViewManagerClassLookUpOptimiz // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(25, "enableInteropViewManagerClassLookUpOptimizationIOS"); + markFlagAsAccessed(26, "enableInteropViewManagerClassLookUpOptimizationIOS"); flagValue = currentProvider_->enableInteropViewManagerClassLookUpOptimizationIOS(); enableInteropViewManagerClassLookUpOptimizationIOS_ = flagValue; @@ -506,7 +524,7 @@ bool ReactNativeFeatureFlagsAccessor::enableLayoutAnimationsOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(26, "enableLayoutAnimationsOnAndroid"); + markFlagAsAccessed(27, "enableLayoutAnimationsOnAndroid"); flagValue = currentProvider_->enableLayoutAnimationsOnAndroid(); enableLayoutAnimationsOnAndroid_ = flagValue; @@ -524,7 +542,7 @@ bool ReactNativeFeatureFlagsAccessor::enableLayoutAnimationsOnIOS() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(27, "enableLayoutAnimationsOnIOS"); + markFlagAsAccessed(28, "enableLayoutAnimationsOnIOS"); flagValue = currentProvider_->enableLayoutAnimationsOnIOS(); enableLayoutAnimationsOnIOS_ = flagValue; @@ -542,7 +560,7 @@ bool ReactNativeFeatureFlagsAccessor::enableMainQueueCoordinatorOnIOS() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(28, "enableMainQueueCoordinatorOnIOS"); + markFlagAsAccessed(29, "enableMainQueueCoordinatorOnIOS"); flagValue = currentProvider_->enableMainQueueCoordinatorOnIOS(); enableMainQueueCoordinatorOnIOS_ = flagValue; @@ -560,7 +578,7 @@ bool ReactNativeFeatureFlagsAccessor::enableModuleArgumentNSNullConversionIOS() // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(29, "enableModuleArgumentNSNullConversionIOS"); + markFlagAsAccessed(30, "enableModuleArgumentNSNullConversionIOS"); flagValue = currentProvider_->enableModuleArgumentNSNullConversionIOS(); enableModuleArgumentNSNullConversionIOS_ = flagValue; @@ -578,7 +596,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNativeCSSParsing() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(30, "enableNativeCSSParsing"); + markFlagAsAccessed(31, "enableNativeCSSParsing"); flagValue = currentProvider_->enableNativeCSSParsing(); enableNativeCSSParsing_ = flagValue; @@ -596,7 +614,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNetworkEventReporting() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(31, "enableNetworkEventReporting"); + markFlagAsAccessed(32, "enableNetworkEventReporting"); flagValue = currentProvider_->enableNetworkEventReporting(); enableNetworkEventReporting_ = flagValue; @@ -614,7 +632,7 @@ bool ReactNativeFeatureFlagsAccessor::enableNewBackgroundAndBorderDrawables() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(32, "enableNewBackgroundAndBorderDrawables"); + markFlagAsAccessed(33, "enableNewBackgroundAndBorderDrawables"); flagValue = currentProvider_->enableNewBackgroundAndBorderDrawables(); enableNewBackgroundAndBorderDrawables_ = flagValue; @@ -632,7 +650,7 @@ bool ReactNativeFeatureFlagsAccessor::enablePreparedTextLayout() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(33, "enablePreparedTextLayout"); + markFlagAsAccessed(34, "enablePreparedTextLayout"); flagValue = currentProvider_->enablePreparedTextLayout(); enablePreparedTextLayout_ = flagValue; @@ -650,7 +668,7 @@ bool ReactNativeFeatureFlagsAccessor::enablePropsUpdateReconciliationAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(34, "enablePropsUpdateReconciliationAndroid"); + markFlagAsAccessed(35, "enablePropsUpdateReconciliationAndroid"); flagValue = currentProvider_->enablePropsUpdateReconciliationAndroid(); enablePropsUpdateReconciliationAndroid_ = flagValue; @@ -668,7 +686,7 @@ bool ReactNativeFeatureFlagsAccessor::enableResourceTimingAPI() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(35, "enableResourceTimingAPI"); + markFlagAsAccessed(36, "enableResourceTimingAPI"); flagValue = currentProvider_->enableResourceTimingAPI(); enableResourceTimingAPI_ = flagValue; @@ -686,7 +704,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewCulling() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(36, "enableViewCulling"); + markFlagAsAccessed(37, "enableViewCulling"); flagValue = currentProvider_->enableViewCulling(); enableViewCulling_ = flagValue; @@ -704,7 +722,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecycling() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(37, "enableViewRecycling"); + markFlagAsAccessed(38, "enableViewRecycling"); flagValue = currentProvider_->enableViewRecycling(); enableViewRecycling_ = flagValue; @@ -722,7 +740,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForScrollView() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(38, "enableViewRecyclingForScrollView"); + markFlagAsAccessed(39, "enableViewRecyclingForScrollView"); flagValue = currentProvider_->enableViewRecyclingForScrollView(); enableViewRecyclingForScrollView_ = flagValue; @@ -740,7 +758,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForText() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(39, "enableViewRecyclingForText"); + markFlagAsAccessed(40, "enableViewRecyclingForText"); flagValue = currentProvider_->enableViewRecyclingForText(); enableViewRecyclingForText_ = flagValue; @@ -758,7 +776,7 @@ bool ReactNativeFeatureFlagsAccessor::enableViewRecyclingForView() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(40, "enableViewRecyclingForView"); + markFlagAsAccessed(41, "enableViewRecyclingForView"); flagValue = currentProvider_->enableViewRecyclingForView(); enableViewRecyclingForView_ = flagValue; @@ -776,7 +794,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewDebugFeatures() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(41, "enableVirtualViewDebugFeatures"); + markFlagAsAccessed(42, "enableVirtualViewDebugFeatures"); flagValue = currentProvider_->enableVirtualViewDebugFeatures(); enableVirtualViewDebugFeatures_ = flagValue; @@ -794,7 +812,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewRenderState() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(42, "enableVirtualViewRenderState"); + markFlagAsAccessed(43, "enableVirtualViewRenderState"); flagValue = currentProvider_->enableVirtualViewRenderState(); enableVirtualViewRenderState_ = flagValue; @@ -812,7 +830,7 @@ bool ReactNativeFeatureFlagsAccessor::enableVirtualViewWindowFocusDetection() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(43, "enableVirtualViewWindowFocusDetection"); + markFlagAsAccessed(44, "enableVirtualViewWindowFocusDetection"); flagValue = currentProvider_->enableVirtualViewWindowFocusDetection(); enableVirtualViewWindowFocusDetection_ = flagValue; @@ -830,7 +848,7 @@ bool ReactNativeFeatureFlagsAccessor::fixMappingOfEventPrioritiesBetweenFabricAn // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(44, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); + markFlagAsAccessed(45, "fixMappingOfEventPrioritiesBetweenFabricAndReact"); flagValue = currentProvider_->fixMappingOfEventPrioritiesBetweenFabricAndReact(); fixMappingOfEventPrioritiesBetweenFabricAndReact_ = flagValue; @@ -848,7 +866,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxEnabledRelease() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(45, "fuseboxEnabledRelease"); + markFlagAsAccessed(46, "fuseboxEnabledRelease"); flagValue = currentProvider_->fuseboxEnabledRelease(); fuseboxEnabledRelease_ = flagValue; @@ -866,7 +884,7 @@ bool ReactNativeFeatureFlagsAccessor::fuseboxNetworkInspectionEnabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(46, "fuseboxNetworkInspectionEnabled"); + markFlagAsAccessed(47, "fuseboxNetworkInspectionEnabled"); flagValue = currentProvider_->fuseboxNetworkInspectionEnabled(); fuseboxNetworkInspectionEnabled_ = flagValue; @@ -884,7 +902,7 @@ bool ReactNativeFeatureFlagsAccessor::hideOffscreenVirtualViewsOnIOS() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(47, "hideOffscreenVirtualViewsOnIOS"); + markFlagAsAccessed(48, "hideOffscreenVirtualViewsOnIOS"); flagValue = currentProvider_->hideOffscreenVirtualViewsOnIOS(); hideOffscreenVirtualViewsOnIOS_ = flagValue; @@ -902,7 +920,7 @@ bool ReactNativeFeatureFlagsAccessor::perfMonitorV2Enabled() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(48, "perfMonitorV2Enabled"); + markFlagAsAccessed(49, "perfMonitorV2Enabled"); flagValue = currentProvider_->perfMonitorV2Enabled(); perfMonitorV2Enabled_ = flagValue; @@ -920,7 +938,7 @@ double ReactNativeFeatureFlagsAccessor::preparedTextCacheSize() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(49, "preparedTextCacheSize"); + markFlagAsAccessed(50, "preparedTextCacheSize"); flagValue = currentProvider_->preparedTextCacheSize(); preparedTextCacheSize_ = flagValue; @@ -938,7 +956,7 @@ bool ReactNativeFeatureFlagsAccessor::preventShadowTreeCommitExhaustion() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(50, "preventShadowTreeCommitExhaustion"); + markFlagAsAccessed(51, "preventShadowTreeCommitExhaustion"); flagValue = currentProvider_->preventShadowTreeCommitExhaustion(); preventShadowTreeCommitExhaustion_ = flagValue; @@ -956,7 +974,7 @@ bool ReactNativeFeatureFlagsAccessor::releaseImageDataWhenConsumed() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(51, "releaseImageDataWhenConsumed"); + markFlagAsAccessed(52, "releaseImageDataWhenConsumed"); flagValue = currentProvider_->releaseImageDataWhenConsumed(); releaseImageDataWhenConsumed_ = flagValue; @@ -974,7 +992,7 @@ bool ReactNativeFeatureFlagsAccessor::shouldPressibilityUseW3CPointerEventsForHo // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(52, "shouldPressibilityUseW3CPointerEventsForHover"); + markFlagAsAccessed(53, "shouldPressibilityUseW3CPointerEventsForHover"); flagValue = currentProvider_->shouldPressibilityUseW3CPointerEventsForHover(); shouldPressibilityUseW3CPointerEventsForHover_ = flagValue; @@ -992,7 +1010,7 @@ bool ReactNativeFeatureFlagsAccessor::skipActivityIdentityAssertionOnHostPause() // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(53, "skipActivityIdentityAssertionOnHostPause"); + markFlagAsAccessed(54, "skipActivityIdentityAssertionOnHostPause"); flagValue = currentProvider_->skipActivityIdentityAssertionOnHostPause(); skipActivityIdentityAssertionOnHostPause_ = flagValue; @@ -1010,7 +1028,7 @@ bool ReactNativeFeatureFlagsAccessor::sweepActiveTouchOnChildNativeGesturesAndro // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(54, "sweepActiveTouchOnChildNativeGesturesAndroid"); + markFlagAsAccessed(55, "sweepActiveTouchOnChildNativeGesturesAndroid"); flagValue = currentProvider_->sweepActiveTouchOnChildNativeGesturesAndroid(); sweepActiveTouchOnChildNativeGesturesAndroid_ = flagValue; @@ -1028,7 +1046,7 @@ bool ReactNativeFeatureFlagsAccessor::traceTurboModulePromiseRejectionsOnAndroid // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(55, "traceTurboModulePromiseRejectionsOnAndroid"); + markFlagAsAccessed(56, "traceTurboModulePromiseRejectionsOnAndroid"); flagValue = currentProvider_->traceTurboModulePromiseRejectionsOnAndroid(); traceTurboModulePromiseRejectionsOnAndroid_ = flagValue; @@ -1046,7 +1064,7 @@ bool ReactNativeFeatureFlagsAccessor::updateRuntimeShadowNodeReferencesOnCommit( // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(56, "updateRuntimeShadowNodeReferencesOnCommit"); + markFlagAsAccessed(57, "updateRuntimeShadowNodeReferencesOnCommit"); flagValue = currentProvider_->updateRuntimeShadowNodeReferencesOnCommit(); updateRuntimeShadowNodeReferencesOnCommit_ = flagValue; @@ -1064,7 +1082,7 @@ bool ReactNativeFeatureFlagsAccessor::useAlwaysAvailableJSErrorHandling() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(57, "useAlwaysAvailableJSErrorHandling"); + markFlagAsAccessed(58, "useAlwaysAvailableJSErrorHandling"); flagValue = currentProvider_->useAlwaysAvailableJSErrorHandling(); useAlwaysAvailableJSErrorHandling_ = flagValue; @@ -1082,7 +1100,7 @@ bool ReactNativeFeatureFlagsAccessor::useFabricInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(58, "useFabricInterop"); + markFlagAsAccessed(59, "useFabricInterop"); flagValue = currentProvider_->useFabricInterop(); useFabricInterop_ = flagValue; @@ -1100,7 +1118,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeEqualsInNativeReadableArrayAndroi // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(59, "useNativeEqualsInNativeReadableArrayAndroid"); + markFlagAsAccessed(60, "useNativeEqualsInNativeReadableArrayAndroid"); flagValue = currentProvider_->useNativeEqualsInNativeReadableArrayAndroid(); useNativeEqualsInNativeReadableArrayAndroid_ = flagValue; @@ -1118,7 +1136,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeTransformHelperAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(60, "useNativeTransformHelperAndroid"); + markFlagAsAccessed(61, "useNativeTransformHelperAndroid"); flagValue = currentProvider_->useNativeTransformHelperAndroid(); useNativeTransformHelperAndroid_ = flagValue; @@ -1136,7 +1154,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(61, "useNativeViewConfigsInBridgelessMode"); + markFlagAsAccessed(62, "useNativeViewConfigsInBridgelessMode"); flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode(); useNativeViewConfigsInBridgelessMode_ = flagValue; @@ -1154,7 +1172,7 @@ bool ReactNativeFeatureFlagsAccessor::useOptimizedEventBatchingOnAndroid() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(62, "useOptimizedEventBatchingOnAndroid"); + markFlagAsAccessed(63, "useOptimizedEventBatchingOnAndroid"); flagValue = currentProvider_->useOptimizedEventBatchingOnAndroid(); useOptimizedEventBatchingOnAndroid_ = flagValue; @@ -1172,7 +1190,7 @@ bool ReactNativeFeatureFlagsAccessor::useRawPropsJsiValue() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(63, "useRawPropsJsiValue"); + markFlagAsAccessed(64, "useRawPropsJsiValue"); flagValue = currentProvider_->useRawPropsJsiValue(); useRawPropsJsiValue_ = flagValue; @@ -1190,7 +1208,7 @@ bool ReactNativeFeatureFlagsAccessor::useShadowNodeStateOnClone() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(64, "useShadowNodeStateOnClone"); + markFlagAsAccessed(65, "useShadowNodeStateOnClone"); flagValue = currentProvider_->useShadowNodeStateOnClone(); useShadowNodeStateOnClone_ = flagValue; @@ -1208,7 +1226,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModuleInterop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(65, "useTurboModuleInterop"); + markFlagAsAccessed(66, "useTurboModuleInterop"); flagValue = currentProvider_->useTurboModuleInterop(); useTurboModuleInterop_ = flagValue; @@ -1226,7 +1244,7 @@ bool ReactNativeFeatureFlagsAccessor::useTurboModules() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(66, "useTurboModules"); + markFlagAsAccessed(67, "useTurboModules"); flagValue = currentProvider_->useTurboModules(); useTurboModules_ = flagValue; @@ -1244,7 +1262,7 @@ double ReactNativeFeatureFlagsAccessor::virtualViewPrerenderRatio() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(67, "virtualViewPrerenderRatio"); + markFlagAsAccessed(68, "virtualViewPrerenderRatio"); flagValue = currentProvider_->virtualViewPrerenderRatio(); virtualViewPrerenderRatio_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index 8e1c7b5c4396..31849375cf8c 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<009c00b2f643505839123289abb0f40e>> */ /** @@ -37,6 +37,7 @@ class ReactNativeFeatureFlagsAccessor { bool cxxNativeAnimatedEnabled(); bool cxxNativeAnimatedRemoveJsSync(); bool disableFabricCommitInCXXAnimated(); + bool disableHighRefreshRateAnimations(); bool disableMountItemReorderingAndroid(); bool disableOldAndroidAttachmentMetricsWorkarounds(); bool disableTextLayoutManagerCacheAndroid(); @@ -111,13 +112,14 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 68> accessedFeatureFlags_; + std::array, 69> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> cdpInteractionMetricsEnabled_; std::atomic> cxxNativeAnimatedEnabled_; std::atomic> cxxNativeAnimatedRemoveJsSync_; std::atomic> disableFabricCommitInCXXAnimated_; + std::atomic> disableHighRefreshRateAnimations_; std::atomic> disableMountItemReorderingAndroid_; std::atomic> disableOldAndroidAttachmentMetricsWorkarounds_; std::atomic> disableTextLayoutManagerCacheAndroid_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index 8b34c3d46dc5..ca81debd5792 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<30170e483b919c7bd235bfcfe4174c39>> + * @generated SignedSource<<46fdd190f4c6461e7bb29305685d4c52>> */ /** @@ -47,6 +47,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool disableHighRefreshRateAnimations() override { + return false; + } + bool disableMountItemReorderingAndroid() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h index f55df4907aee..d4d9beddd06c 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<6030ed59832efdf42e23c13b689da64f>> + * @generated SignedSource<> */ /** @@ -90,6 +90,15 @@ class ReactNativeFeatureFlagsDynamicProvider : public ReactNativeFeatureFlagsDef return ReactNativeFeatureFlagsDefaults::disableFabricCommitInCXXAnimated(); } + bool disableHighRefreshRateAnimations() override { + auto value = values_["disableHighRefreshRateAnimations"]; + if (!value.isNull()) { + return value.getBool(); + } + + return ReactNativeFeatureFlagsDefaults::disableHighRefreshRateAnimations(); + } + bool disableMountItemReorderingAndroid() override { auto value = values_["disableMountItemReorderingAndroid"]; if (!value.isNull()) { diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index edfeaf7643ad..942fbba803cd 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<95940b74b0055760be69c501a97a6f45>> + * @generated SignedSource<<0a640ed828004949468a276ddb74a1ff>> */ /** @@ -30,6 +30,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool cxxNativeAnimatedEnabled() = 0; virtual bool cxxNativeAnimatedRemoveJsSync() = 0; virtual bool disableFabricCommitInCXXAnimated() = 0; + virtual bool disableHighRefreshRateAnimations() = 0; virtual bool disableMountItemReorderingAndroid() = 0; virtual bool disableOldAndroidAttachmentMetricsWorkarounds() = 0; virtual bool disableTextLayoutManagerCacheAndroid() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index a4fa0e554d9e..395a277de594 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<998bdf037d58ca747c22ada099d236f0>> + * @generated SignedSource<<4ce764e9a9e13bc3033265ffb24e9ebc>> */ /** @@ -69,6 +69,11 @@ bool NativeReactNativeFeatureFlags::disableFabricCommitInCXXAnimated( return ReactNativeFeatureFlags::disableFabricCommitInCXXAnimated(); } +bool NativeReactNativeFeatureFlags::disableHighRefreshRateAnimations( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::disableHighRefreshRateAnimations(); +} + bool NativeReactNativeFeatureFlags::disableMountItemReorderingAndroid( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::disableMountItemReorderingAndroid(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 3fdaeda4acdb..a48d2e8de464 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<89c5d22cd228da57d82843f7e660f262>> + * @generated SignedSource<<9af36c207ac0ecc3e5c2c9ea83df234e>> */ /** @@ -46,6 +46,8 @@ class NativeReactNativeFeatureFlags bool disableFabricCommitInCXXAnimated(jsi::Runtime& runtime); + bool disableHighRefreshRateAnimations(jsi::Runtime& runtime); + bool disableMountItemReorderingAndroid(jsi::Runtime& runtime); bool disableOldAndroidAttachmentMetricsWorkarounds(jsi::Runtime& runtime); diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 4c2ef150206d..73b1f1f91ae0 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -103,6 +103,17 @@ const definitions: FeatureFlagDefinitions = { }, ossReleaseStage: 'none', }, + disableHighRefreshRateAnimations: { + defaultValue: false, + metadata: { + dateAdded: '2025-08-24', + description: + 'Disables high refresh rate animations on devices that support it (e.g. 120Hz).', + expectedReleaseValue: false, + purpose: 'experimentation', + }, + ossReleaseStage: 'none', + }, disableMountItemReorderingAndroid: { defaultValue: false, metadata: { diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index f54f1ff1f768..36dca3bde4d9 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<6ec32c21e134bd51702d7fcab094c725>> + * @generated SignedSource<<2b69f3f912d561ec4127215b61073443>> * @flow strict * @noformat */ @@ -52,6 +52,7 @@ export type ReactNativeFeatureFlags = $ReadOnly<{ cxxNativeAnimatedEnabled: Getter, cxxNativeAnimatedRemoveJsSync: Getter, disableFabricCommitInCXXAnimated: Getter, + disableHighRefreshRateAnimations: Getter, disableMountItemReorderingAndroid: Getter, disableOldAndroidAttachmentMetricsWorkarounds: Getter, disableTextLayoutManagerCacheAndroid: Getter, @@ -201,6 +202,10 @@ export const cxxNativeAnimatedRemoveJsSync: Getter = createNativeFlagGe * Prevents use of Fabric commit in C++ Animated implementation */ export const disableFabricCommitInCXXAnimated: Getter = createNativeFlagGetter('disableFabricCommitInCXXAnimated', false); +/** + * Disables high refresh rate animations on devices that support it (e.g. 120Hz). + */ +export const disableHighRefreshRateAnimations: Getter = createNativeFlagGetter('disableHighRefreshRateAnimations', false); /** * Prevent FabricMountingManager from reordering mountItems, which may lead to invalid state on the UI thread */ diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js index 30a467f2224b..cf7c04cc6963 100644 --- a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<2b0679c42d8e1cb021612807d94d9f4c>> + * @generated SignedSource<<8358e7bc65eaf189f6a83f4f858f2bb5>> * @flow strict * @noformat */ @@ -30,6 +30,7 @@ export interface Spec extends TurboModule { +cxxNativeAnimatedEnabled?: () => boolean; +cxxNativeAnimatedRemoveJsSync?: () => boolean; +disableFabricCommitInCXXAnimated?: () => boolean; + +disableHighRefreshRateAnimations?: () => boolean; +disableMountItemReorderingAndroid?: () => boolean; +disableOldAndroidAttachmentMetricsWorkarounds?: () => boolean; +disableTextLayoutManagerCacheAndroid?: () => boolean; diff --git a/packages/react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedModule.js b/packages/react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedModule.js index 91f64cdcdc39..b412a23232a1 100644 --- a/packages/react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedModule.js +++ b/packages/react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedModule.js @@ -22,6 +22,10 @@ export type EventMapping = { animatedValueTag: ?number, }; +export type AnimatedConstants = { + +singleFrameInterval?: number, +}; + // The config has different keys depending on the type of the Node // TODO(T54896888): Make these types strict export type AnimatedNodeConfig = Object; @@ -69,9 +73,12 @@ export interface Spec extends TurboModule { // All of the above in a batched mode +queueAndExecuteBatchedOperations?: (operationsAndArgs: Array) => void; + + +getConstants?: () => AnimatedConstants; } const NativeModule: ?Spec = !shouldUseTurboAnimatedModule() ? TurboModuleRegistry.get('NativeAnimatedModule') : null; + export default NativeModule; diff --git a/packages/react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedTurboModule.js b/packages/react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedTurboModule.js index 5a20ac1539de..52c9bd860ecd 100644 --- a/packages/react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedTurboModule.js +++ b/packages/react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedTurboModule.js @@ -22,6 +22,10 @@ export type EventMapping = { animatedValueTag: ?number, }; +export type AnimatedConstants = { + +singleFrameInterval?: number, +}; + // The config has different keys depending on the type of the Node // TODO(T54896888): Make these types strict export type AnimatedNodeConfig = Object; @@ -69,6 +73,8 @@ export interface Spec extends TurboModule { // All of the above in a batched mode +queueAndExecuteBatchedOperations?: (operationsAndArgs: Array) => void; + + +getConstants?: () => AnimatedConstants; } const NativeModule: ?Spec = shouldUseTurboAnimatedModule() diff --git a/packages/rn-tester/RNTester/Info.plist b/packages/rn-tester/RNTester/Info.plist index 373b8322fdc7..61c772a37e3e 100644 --- a/packages/rn-tester/RNTester/Info.plist +++ b/packages/rn-tester/RNTester/Info.plist @@ -2,6 +2,8 @@ + CADisableMinimumFrameDurationOnPhone + CFBundleDevelopmentRegion en CFBundleExecutable