diff --git a/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt b/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt index 979ec533075f..f3b278578f1b 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt +++ b/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt @@ -82,6 +82,7 @@ add_react_common_subdir(react/debug) add_react_common_subdir(react/featureflags) add_react_common_subdir(react/performance/cdpmetrics) add_react_common_subdir(react/performance/timeline) +add_react_common_subdir(react/renderer/animated) add_react_common_subdir(react/renderer/animationbackend) add_react_common_subdir(react/renderer/animations) add_react_common_subdir(react/renderer/attributedstring) @@ -201,6 +202,7 @@ add_library(reactnative $ $ $ + $ $ $ $ @@ -295,6 +297,7 @@ target_include_directories(reactnative $ $ $ + $ $ $ $ diff --git a/packages/react-native/ReactApple/RCTAnimatedModuleProvider/RCTAnimatedModuleProvider.mm b/packages/react-native/ReactApple/RCTAnimatedModuleProvider/RCTAnimatedModuleProvider.mm index 17914749a512..5cc907bacc23 100644 --- a/packages/react-native/ReactApple/RCTAnimatedModuleProvider/RCTAnimatedModuleProvider.mm +++ b/packages/react-native/ReactApple/RCTAnimatedModuleProvider/RCTAnimatedModuleProvider.mm @@ -70,7 +70,10 @@ - (void)_onDisplayLinkTick - (std::shared_ptr)getTurboModule:(const std::string &)name jsInvoker:(std::shared_ptr)jsInvoker { - if (facebook::react::ReactNativeFeatureFlags::cxxNativeAnimatedEnabled()) { + if (facebook::react::ReactNativeFeatureFlags::cxxNativeAnimatedEnabled() && + // initialization is moved to DefaultTurboModules when using shared animated backend + // TODO: T257053961 deprecate RCTAnimatedModuleProvider. + !facebook::react::ReactNativeFeatureFlags::useSharedAnimatedBackend()) { if (name == facebook::react::AnimatedModule::kModuleName) { __weak RCTAnimatedModuleProvider *weakSelf = self; auto provider = std::make_shared( diff --git a/packages/react-native/ReactCommon/react/nativemodule/defaults/CMakeLists.txt b/packages/react-native/ReactCommon/react/nativemodule/defaults/CMakeLists.txt index 42bcbe2724ff..9f4ce619d652 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/defaults/CMakeLists.txt +++ b/packages/react-native/ReactCommon/react/nativemodule/defaults/CMakeLists.txt @@ -23,6 +23,7 @@ target_link_libraries(react_nativemodule_defaults react_nativemodule_idlecallbacks react_nativemodule_intersectionobserver react_nativemodule_webperformance + react_renderer_animated ) target_compile_reactnative_options(react_nativemodule_defaults PRIVATE) target_compile_options(react_nativemodule_defaults PRIVATE -Wpedantic) diff --git a/packages/react-native/ReactCommon/react/nativemodule/defaults/DefaultTurboModules.cpp b/packages/react-native/ReactCommon/react/nativemodule/defaults/DefaultTurboModules.cpp index 3c50a17e2ff7..b433364f8a11 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/defaults/DefaultTurboModules.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/defaults/DefaultTurboModules.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #ifdef REACT_NATIVE_DEBUGGER_ENABLED_DEVONLY #include @@ -49,6 +50,13 @@ namespace facebook::react { } } + if (ReactNativeFeatureFlags::cxxNativeAnimatedEnabled() && + ReactNativeFeatureFlags::useSharedAnimatedBackend() && + name == AnimatedModule::kModuleName) { + return std::make_shared( + jsInvoker, std::make_shared()); + } + #ifdef REACT_NATIVE_DEBUGGER_ENABLED_DEVONLY if (name == DevToolsRuntimeSettingsModule::kModuleName) { return std::make_shared(jsInvoker); diff --git a/packages/react-native/ReactCommon/react/renderer/animated/NativeAnimatedNodesManagerProvider.cpp b/packages/react-native/ReactCommon/react/renderer/animated/NativeAnimatedNodesManagerProvider.cpp index 7d95dcee3b51..95d3a508521e 100644 --- a/packages/react-native/ReactCommon/react/renderer/animated/NativeAnimatedNodesManagerProvider.cpp +++ b/packages/react-native/ReactCommon/react/renderer/animated/NativeAnimatedNodesManagerProvider.cpp @@ -45,8 +45,16 @@ std::shared_ptr NativeAnimatedNodesManagerProvider::getOrCreate( jsi::Runtime& runtime, std::shared_ptr jsInvoker) { - if (nativeAnimatedNodesManager_ == nullptr) { - auto* uiManager = &UIManagerBinding::getBinding(runtime)->getUIManager(); + if (nativeAnimatedNodesManager_ != nullptr) { + return nativeAnimatedNodesManager_; + } + + auto* uiManager = &UIManagerBinding::getBinding(runtime)->getUIManager(); + + if (!ReactNativeFeatureFlags::useSharedAnimatedBackend()) { + // === PATH 1: Legacy Backend (useSharedAnimatedBackend = false) === + // Uses the architecture with MergedValueDispatcher and + // AnimatedMountingOverrideDelegate mergedValueDispatcher_ = std::make_unique( [jsInvoker](std::function&& func) { @@ -84,78 +92,78 @@ NativeAnimatedNodesManagerProvider::getOrCreate( } }; - if (ReactNativeFeatureFlags::useSharedAnimatedBackend()) { - auto animationBackend = uiManager->unstable_getAnimationBackend().lock(); - react_native_assert( - animationBackend != nullptr && "animationBackend is nullptr"); - animationBackend->registerJSInvoker(jsInvoker); - - nativeAnimatedNodesManager_ = - std::make_shared(animationBackend); - } else { - nativeAnimatedNodesManager_ = - std::make_shared( - std::move(directManipulationCallback), - std::move(fabricCommitCallback), - std::move(resolvePlatformColor), - std::move(startOnRenderCallback_), - std::move(stopOnRenderCallback_), - std::move(frameRateListenerCallback_)); - - nativeAnimatedDelegate_ = - std::make_shared( - nativeAnimatedNodesManager_); - } - - addEventEmitterListener( - nativeAnimatedNodesManager_->getEventEmitterListener()); - - uiManager->addEventListener( - std::make_shared( - [eventEmitterListenerContainerWeak = - std::weak_ptr( - eventEmitterListenerContainer_)]( - const RawEvent& rawEvent) { - const auto& eventTarget = rawEvent.eventTarget; - const auto& eventPayload = rawEvent.eventPayload; - if (eventTarget && eventPayload) { - if (auto eventEmitterListenerContainer = - eventEmitterListenerContainerWeak.lock(); - eventEmitterListenerContainer != nullptr) { - return eventEmitterListenerContainer->willDispatchEvent( - eventTarget->getTag(), rawEvent.type, *eventPayload); - } - } - return false; - })); + nativeAnimatedNodesManager_ = std::make_shared( + std::move(directManipulationCallback), + std::move(fabricCommitCallback), + std::move(resolvePlatformColor), + std::move(startOnRenderCallback_), + std::move(stopOnRenderCallback_), + std::move(frameRateListenerCallback_)); + + nativeAnimatedDelegate_ = + std::make_shared( + nativeAnimatedNodesManager_); + + animatedMountingOverrideDelegate_ = + std::make_shared( + *nativeAnimatedNodesManager_, *scheduler); + + // Register on existing surfaces + uiManager->getShadowTreeRegistry().enumerate( + [animatedMountingOverrideDelegate = + std::weak_ptr( + animatedMountingOverrideDelegate_)]( + const ShadowTree& shadowTree, bool& /*stop*/) { + shadowTree.getMountingCoordinator()->setMountingOverrideDelegate( + animatedMountingOverrideDelegate); + }); - uiManager->setNativeAnimatedDelegate(nativeAnimatedDelegate_); + // Register on surfaces started in the future + uiManager->setOnSurfaceStartCallback( + [animatedMountingOverrideDelegate = + std::weak_ptr( + animatedMountingOverrideDelegate_)]( + const ShadowTree& shadowTree) { + shadowTree.getMountingCoordinator()->setMountingOverrideDelegate( + animatedMountingOverrideDelegate); + }); - if (!ReactNativeFeatureFlags::useSharedAnimatedBackend()) { - animatedMountingOverrideDelegate_ = - std::make_shared( - *nativeAnimatedNodesManager_, *scheduler); - - // Register on existing surfaces - uiManager->getShadowTreeRegistry().enumerate( - [animatedMountingOverrideDelegate = - std::weak_ptr( - animatedMountingOverrideDelegate_)]( - const ShadowTree& shadowTree, bool& /*stop*/) { - shadowTree.getMountingCoordinator()->setMountingOverrideDelegate( - animatedMountingOverrideDelegate); - }); - // Register on surfaces started in the future - uiManager->setOnSurfaceStartCallback( - [animatedMountingOverrideDelegate = - std::weak_ptr( - animatedMountingOverrideDelegate_)]( - const ShadowTree& shadowTree) { - shadowTree.getMountingCoordinator()->setMountingOverrideDelegate( - animatedMountingOverrideDelegate); - }); - } + uiManager->setNativeAnimatedDelegate(nativeAnimatedDelegate_); + } else { + // === PATH 2: Shared AnimationBackend (useSharedAnimatedBackend = true) === + // Uses the shared AnimationBackend from UIManager. The backend handles all + // animation commits and platform integration internally. + + auto animationBackend = uiManager->unstable_getAnimationBackend().lock(); + react_native_assert( + animationBackend != nullptr && "animationBackend is nullptr"); + animationBackend->registerJSInvoker(jsInvoker); + + nativeAnimatedNodesManager_ = + std::make_shared(animationBackend); } + + addEventEmitterListener( + nativeAnimatedNodesManager_->getEventEmitterListener()); + + uiManager->addEventListener( + std::make_shared( + [eventEmitterListenerContainerWeak = + std::weak_ptr( + eventEmitterListenerContainer_)](const RawEvent& rawEvent) { + const auto& eventTarget = rawEvent.eventTarget; + const auto& eventPayload = rawEvent.eventPayload; + if (eventTarget && eventPayload) { + if (auto eventEmitterListenerContainer = + eventEmitterListenerContainerWeak.lock(); + eventEmitterListenerContainer != nullptr) { + return eventEmitterListenerContainer->willDispatchEvent( + eventTarget->getTag(), rawEvent.type, *eventPayload); + } + } + return false; + })); + return nativeAnimatedNodesManager_; }