/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #include "NativeAnimatedNodesManagerProvider.h" #include #include #include #include #ifdef RN_USE_ANIMATION_BACKEND #include #endif #include namespace facebook::react { UIManagerNativeAnimatedDelegateImpl::UIManagerNativeAnimatedDelegateImpl( std::weak_ptr manager) : nativeAnimatedNodesManager_(manager) {} void UIManagerNativeAnimatedDelegateImpl::runAnimationFrame() { if (auto nativeAnimatedNodesManagerStrong = nativeAnimatedNodesManager_.lock()) { nativeAnimatedNodesManagerStrong->onRender(); } } NativeAnimatedNodesManagerProvider::NativeAnimatedNodesManagerProvider( NativeAnimatedNodesManager::StartOnRenderCallback startOnRenderCallback, NativeAnimatedNodesManager::StopOnRenderCallback stopOnRenderCallback, NativeAnimatedNodesManager::FrameRateListenerCallback frameRateListenerCallback) : eventEmitterListenerContainer_( std::make_shared()), startOnRenderCallback_(std::move(startOnRenderCallback)), stopOnRenderCallback_(std::move(stopOnRenderCallback)), frameRateListenerCallback_(std::move(frameRateListenerCallback)) {} std::shared_ptr NativeAnimatedNodesManagerProvider::getOrCreate( jsi::Runtime& runtime, std::shared_ptr jsInvoker) { if (nativeAnimatedNodesManager_ == nullptr) { auto* uiManager = &UIManagerBinding::getBinding(runtime)->getUIManager(); NativeAnimatedNodesManager::FabricCommitCallback fabricCommitCallback = nullptr; if (!ReactNativeFeatureFlags::disableFabricCommitInCXXAnimated()) { mergedValueDispatcher_ = std::make_unique( [jsInvoker](std::function&& func) { jsInvoker->invokeAsync(std::move(func)); }, [uiManager](std::unordered_map&& tagToProps) { uiManager->updateShadowTree(std::move(tagToProps)); }); fabricCommitCallback = [this](std::unordered_map& tagToProps) { mergedValueDispatcher_->dispatch(tagToProps); }; } auto directManipulationCallback = [uiManager](Tag viewTag, const folly::dynamic& props) { uiManager->synchronouslyUpdateViewOnUIThread(viewTag, props); }; if (ReactNativeFeatureFlags::useSharedAnimatedBackend()) { #ifdef RN_USE_ANIMATION_BACKEND // TODO: this should be initialized outside of animated, but for now it // was convenient to do it here animationBackend_ = std::make_shared( std::move(startOnRenderCallback_), std::move(stopOnRenderCallback_), std::move(directManipulationCallback), std::move(fabricCommitCallback), uiManager); #endif nativeAnimatedNodesManager_ = std::make_shared(animationBackend_); uiManager->unstable_setAnimationBackend(animationBackend_); } else { nativeAnimatedNodesManager_ = std::make_shared( std::move(directManipulationCallback), std::move(fabricCommitCallback), std::move(startOnRenderCallback_), std::move(stopOnRenderCallback_)); } 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; })); nativeAnimatedDelegate_ = std::make_shared( nativeAnimatedNodesManager_); uiManager->setNativeAnimatedDelegate(nativeAnimatedDelegate_); // TODO: remove force casting. auto* scheduler = (Scheduler*)uiManager->getDelegate(); 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); }); } return nativeAnimatedNodesManager_; } void NativeAnimatedNodesManagerProvider::addEventEmitterListener( const std::shared_ptr& listener) { eventEmitterListenerContainer_->addListener(listener); } std::shared_ptr NativeAnimatedNodesManagerProvider::getEventEmitterListener() { if (!eventEmitterListener_) { eventEmitterListener_ = std::make_shared( [eventEmitterListenerContainerWeak = std::weak_ptr( eventEmitterListenerContainer_)]( Tag tag, const std::string& eventName, const EventPayload& payload) -> bool { if (auto eventEmitterListenerContainer = eventEmitterListenerContainerWeak.lock(); eventEmitterListenerContainer != nullptr) { return eventEmitterListenerContainer->willDispatchEvent( tag, eventName, payload); } return false; }); } return eventEmitterListener_; } } // namespace facebook::react