From bf0e907284b39034a38c36a349f9e3476e84b12f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwas=CC=81niewski?= Date: Tue, 14 Jan 2025 10:33:48 +0100 Subject: [PATCH] fix: remove custom shadow nodes measurements --- apps/example/android/gradle.properties | 2 +- .../main/java/com/rcttabview/RCTTabView.kt | 2 +- .../android/src/main/jni/CMakeLists.txt | 87 ------------------- .../android/src/main/jni/RNCTabView.h | 13 --- .../android/src/newarch/RCTTabViewManager.kt | 75 ++++++++-------- .../RNCTabViewComponentDescriptor.h | 47 ---------- .../RNCTabViewMeasurementsManager.cpp | 65 -------------- .../RNCTabViewMeasurementsManager.h | 31 ------- .../RNCTabView/RNCTabViewShadowNode.cpp | 28 ------ .../RNCTabView/RNCTabViewShadowNode.h | 48 ---------- .../components/RNCTabView/RNCTabViewState.h | 35 -------- .../react-native.config.js | 11 --- .../src/TabViewNativeComponent.ts | 4 +- 13 files changed, 43 insertions(+), 405 deletions(-) delete mode 100644 packages/react-native-bottom-tabs/android/src/main/jni/CMakeLists.txt delete mode 100644 packages/react-native-bottom-tabs/android/src/main/jni/RNCTabView.h delete mode 100644 packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewComponentDescriptor.h delete mode 100644 packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewMeasurementsManager.cpp delete mode 100644 packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewMeasurementsManager.h delete mode 100644 packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewShadowNode.cpp delete mode 100644 packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewShadowNode.h delete mode 100644 packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewState.h delete mode 100644 packages/react-native-bottom-tabs/react-native.config.js diff --git a/apps/example/android/gradle.properties b/apps/example/android/gradle.properties index 66ddb865..490e2deb 100644 --- a/apps/example/android/gradle.properties +++ b/apps/example/android/gradle.properties @@ -40,7 +40,7 @@ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 # to write custom TurboModules/Fabric components OR use libraries that # are providing them. # Note that this is incompatible with web debugging. -newArchEnabled=false +newArchEnabled=true #bridgelessEnabled=true # Uncomment the line below to build React Native from source. diff --git a/packages/react-native-bottom-tabs/android/src/main/java/com/rcttabview/RCTTabView.kt b/packages/react-native-bottom-tabs/android/src/main/java/com/rcttabview/RCTTabView.kt index 6d5a3239..c00d979f 100644 --- a/packages/react-native-bottom-tabs/android/src/main/java/com/rcttabview/RCTTabView.kt +++ b/packages/react-native-bottom-tabs/android/src/main/java/com/rcttabview/RCTTabView.kt @@ -43,7 +43,7 @@ class ReactBottomNavigationView(context: ReactContext) : FrameLayout(context) { var onTabSelectedListener: ((key: String) -> Unit)? = null var onTabLongPressedListener: ((key: String) -> Unit)? = null var onNativeLayoutListener: ((width: Double, height: Double) -> Unit)? = null - var disablePageTransitions = false + private var disablePageTransitions = false var items: MutableList? = null private var selectedItem: String? = null diff --git a/packages/react-native-bottom-tabs/android/src/main/jni/CMakeLists.txt b/packages/react-native-bottom-tabs/android/src/main/jni/CMakeLists.txt deleted file mode 100644 index 71147d64..00000000 --- a/packages/react-native-bottom-tabs/android/src/main/jni/CMakeLists.txt +++ /dev/null @@ -1,87 +0,0 @@ -cmake_minimum_required(VERSION 3.13) -set(CMAKE_VERBOSE_MAKEFILE ON) - -set(LIB_LITERAL RNCTabView) -set(LIB_TARGET_NAME react_codegen_${LIB_LITERAL}) - -set(LIB_ANDROID_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) -set(LIB_COMMON_DIR ${LIB_ANDROID_DIR}/../common/cpp) -set(LIB_ANDROID_GENERATED_JNI_DIR ${LIB_ANDROID_DIR}/build/generated/source/codegen/jni) -set(LIB_ANDROID_GENERATED_COMPONENTS_DIR ${LIB_ANDROID_GENERATED_JNI_DIR}/react/renderer/components/${LIB_LITERAL}) - -add_compile_options( - -fexceptions - -frtti - -std=c++20 - -Wall - -Wpedantic - -Wno-gnu-zero-variadic-macro-arguments -) - -file(GLOB LIB_CUSTOM_SRCS CONFIGURE_DEPENDS *.cpp ${LIB_COMMON_DIR}/react/renderer/components/${LIB_LITERAL}/*.cpp) -file(GLOB LIB_CODEGEN_SRCS CONFIGURE_DEPENDS ${LIB_ANDROID_GENERATED_JNI_DIR}/*.cpp ${LIB_ANDROID_GENERATED_COMPONENTS_DIR}/*.cpp) - -add_library( - ${LIB_TARGET_NAME} - SHARED - ${LIB_CUSTOM_SRCS} - ${LIB_CODEGEN_SRCS} -) - -target_include_directories( - ${LIB_TARGET_NAME} - PUBLIC - . - ${LIB_COMMON_DIR} - ${LIB_ANDROID_GENERATED_JNI_DIR} - ${LIB_ANDROID_GENERATED_COMPONENTS_DIR} -) - -# https://github.com/react-native-community/discussions-and-proposals/discussions/816 -# This if-then-else can be removed once this library does not support version below 0.76 -if (REACTNATIVE_MERGED_SO) - target_link_libraries( - ${LIB_TARGET_NAME} - fbjni - jsi - reactnative - ) -else() - target_link_libraries( - ${LIB_TARGET_NAME} - fbjni - folly_runtime - glog - jsi - react_codegen_rncore - react_debug - react_render_componentregistry - react_render_core - react_render_debug - react_render_graphics - react_render_imagemanager - react_render_mapbuffer - react_utils - react_nativemodule_core - rrc_image - turbomodulejsijni - rrc_view - yoga - ) -endif() - -target_compile_options( - ${LIB_TARGET_NAME} - PRIVATE - -DLOG_TAG=\"ReactNative\" - -fexceptions - -frtti - -std=c++20 - -Wall -) - -target_include_directories( - ${CMAKE_PROJECT_NAME} - PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR} -) diff --git a/packages/react-native-bottom-tabs/android/src/main/jni/RNCTabView.h b/packages/react-native-bottom-tabs/android/src/main/jni/RNCTabView.h deleted file mode 100644 index f7a1fb25..00000000 --- a/packages/react-native-bottom-tabs/android/src/main/jni/RNCTabView.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace facebook::react { -JSI_EXPORT -std::shared_ptr RNCTabView_ModuleProvider( - const std::string &moduleName, - const JavaTurboModule::InitParams ¶ms); -} diff --git a/packages/react-native-bottom-tabs/android/src/newarch/RCTTabViewManager.kt b/packages/react-native-bottom-tabs/android/src/newarch/RCTTabViewManager.kt index 0d3935d6..70d8381b 100644 --- a/packages/react-native-bottom-tabs/android/src/newarch/RCTTabViewManager.kt +++ b/packages/react-native-bottom-tabs/android/src/newarch/RCTTabViewManager.kt @@ -1,28 +1,26 @@ package com.rcttabview -import android.content.Context import android.view.View +import android.view.ViewGroup import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReadableArray -import com.facebook.react.bridge.ReadableMap import com.facebook.react.module.annotations.ReactModule -import com.facebook.react.uimanager.PixelUtil.toDIPFromPixel -import com.facebook.react.uimanager.SimpleViewManager import com.facebook.react.uimanager.ThemedReactContext import com.facebook.react.uimanager.UIManagerHelper +import com.facebook.react.uimanager.ViewGroupManager import com.facebook.react.uimanager.ViewManagerDelegate import com.facebook.react.viewmanagers.RNCTabViewManagerDelegate import com.facebook.react.viewmanagers.RNCTabViewManagerInterface -import com.facebook.yoga.YogaMeasureMode -import com.facebook.yoga.YogaMeasureOutput +import com.rcttabview.events.OnNativeLayoutEvent +import com.rcttabview.events.PageSelectedEvent +import com.rcttabview.events.TabLongPressEvent @ReactModule(name = RCTTabViewImpl.NAME) class RCTTabViewManager(context: ReactApplicationContext) : - SimpleViewManager(), + ViewGroupManager(), RNCTabViewManagerInterface { - private val contextInner: ReactApplicationContext = context private val delegate: RNCTabViewManagerDelegate = RNCTabViewManagerDelegate(this) private val tabViewImpl: RCTTabViewImpl = RCTTabViewImpl() @@ -37,6 +35,10 @@ class RCTTabViewManager(context: ReactApplicationContext) : view.onTabLongPressedListener = { key -> eventDispatcher?.dispatchEvent(TabLongPressEvent(viewTag = view.id, key)) } + + view.onNativeLayoutListener = { width, height -> + eventDispatcher?.dispatchEvent(OnNativeLayoutEvent(viewTag = view.id, width, height)) + } return view } @@ -45,6 +47,36 @@ class RCTTabViewManager(context: ReactApplicationContext) : return tabViewImpl.getName() } + override fun getChildCount(parent: ReactBottomNavigationView): Int { + return parent.viewPagerAdapter.itemCount ?: 0 + } + + override fun getChildAt(parent: ReactBottomNavigationView, index: Int): View? { + return parent.viewPagerAdapter.getChildAt(index) + } + + override fun removeView(parent: ReactBottomNavigationView, view: View) { + parent.viewPagerAdapter.removeChild(view) + } + + override fun removeAllViews(parent: ReactBottomNavigationView) { + parent.viewPagerAdapter.removeAll() + } + + override fun removeViewAt(parent: ReactBottomNavigationView, index: Int) { + val child = parent.viewPagerAdapter.getChildAt(index) + + if (child.parent != null) { + (child.parent as? ViewGroup)?.removeView(child) + } + + parent.viewPagerAdapter.removeChildAt(index) + } + + override fun needsCustomLayoutForChildren(): Boolean { + return true + } + override fun setItems(view: ReactBottomNavigationView?, value: ReadableArray?) { if (view != null && value != null) tabViewImpl.setItems(view, value) @@ -99,30 +131,6 @@ class RCTTabViewManager(context: ReactApplicationContext) : tabViewImpl.setHapticFeedbackEnabled(view, value) } - public override fun measure( - context: Context?, - localData: ReadableMap?, - props: ReadableMap?, - state: ReadableMap?, - width: Float, - widthMode: YogaMeasureMode?, - height: Float, - heightMode: YogaMeasureMode?, - attachmentsPositions: FloatArray? - ): Long { - val view = ReactBottomNavigationView(context ?: contextInner) - val measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED) - view.measure(measureSpec, measureSpec) - - val bottomInset = RCTTabViewImpl.getNavigationBarInset(contextInner) - - return YogaMeasureOutput.make( - // TabBar should always stretch to the width of the screen. - toDIPFromPixel(width), - toDIPFromPixel(view.measuredHeight.toFloat() + bottomInset) - ) - } - override fun setFontFamily(view: ReactBottomNavigationView?, value: String?) { view?.setFontFamily(value) } @@ -136,7 +144,6 @@ class RCTTabViewManager(context: ReactApplicationContext) : } // iOS Methods - override fun setTranslucent(view: ReactBottomNavigationView?, value: Boolean) { } @@ -151,6 +158,4 @@ class RCTTabViewManager(context: ReactApplicationContext) : override fun setScrollEdgeAppearance(view: ReactBottomNavigationView?, value: String?) { } - - } diff --git a/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewComponentDescriptor.h b/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewComponentDescriptor.h deleted file mode 100644 index 9e80b06b..00000000 --- a/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewComponentDescriptor.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifdef __cplusplus - -#pragma once - -#include -#include - -namespace facebook::react { - -class RNCTabViewComponentDescriptor final : public ConcreteComponentDescriptor -{ -#ifdef ANDROID -public: - RNCTabViewComponentDescriptor(const ComponentDescriptorParameters ¶meters) - : ConcreteComponentDescriptor(parameters), measurementsManager_( - std::make_shared(contextContainer_)) {} - - void adopt(ShadowNode &shadowNode) const override - { - ConcreteComponentDescriptor::adopt(shadowNode); - - auto &rncTabViewShadowNode = - static_cast(shadowNode); - - // `RNCTabViewShadowNode` uses `RNCTabViewMeasurementsManager` to - // provide measurements to Yoga. - rncTabViewShadowNode.setSliderMeasurementsManager( - measurementsManager_); - - // All `RNCTabViewShadowNode`s must have leaf Yoga nodes with properly - // setup measure function. - rncTabViewShadowNode.enableMeasurement(); - } - -private: - const std::shared_ptr measurementsManager_; -#else -public: - RNCTabViewComponentDescriptor(const ComponentDescriptorParameters ¶meters) - : ConcreteComponentDescriptor(parameters) {} -#endif - -}; - -} - -#endif diff --git a/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewMeasurementsManager.cpp b/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewMeasurementsManager.cpp deleted file mode 100644 index 996da9f4..00000000 --- a/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewMeasurementsManager.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#ifdef ANDROID -#include "RNCTabViewMeasurementsManager.h" - -#include -#include -#include - - -using namespace facebook::jni; - -namespace facebook::react -{ -Size RNCTabViewMeasurementsManager::measure( - SurfaceId surfaceId, - LayoutConstraints layoutConstraints) const -{ - { - std::scoped_lock lock(mutex_); - if (hasBeenMeasured_) - { - return cachedMeasurement_; - } - } - - const jni::global_ref& fabricUIManager = - contextContainer_->at>("FabricUIManager"); - - static auto measure = facebook::jni::findClassStatic( - "com/facebook/react/fabric/FabricUIManager") - ->getMethod("measure"); - - auto minimumSize = layoutConstraints.minimumSize; - auto maximumSize = layoutConstraints.maximumSize; - - local_ref componentName = make_jstring("RNCTabView"); - - auto measurement = yogaMeassureToSize(measure( - fabricUIManager, - surfaceId, - componentName.get(), - nullptr, - nullptr, - nullptr, - minimumSize.width, - maximumSize.width, - minimumSize.height, - maximumSize.height)); - - std::scoped_lock lock(mutex_); - cachedMeasurement_ = measurement; - hasBeenMeasured_ = true; - return measurement; -} -} - -#endif diff --git a/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewMeasurementsManager.h b/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewMeasurementsManager.h deleted file mode 100644 index 1882ac43..00000000 --- a/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewMeasurementsManager.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifdef __cplusplus - -#ifdef ANDROID -#pragma once -#include -#include -#include - -namespace facebook::react -{ - - class RNCTabViewMeasurementsManager - { - public: - RNCTabViewMeasurementsManager( - const ContextContainer::Shared &contextContainer) - : contextContainer_(contextContainer) {} - - Size measure(SurfaceId surfaceId, LayoutConstraints layoutConstraints) const; - - private: - const ContextContainer::Shared contextContainer_; - mutable std::mutex mutex_; - mutable bool hasBeenMeasured_ = false; - mutable Size cachedMeasurement_{}; - }; -} - -#endif - -#endif diff --git a/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewShadowNode.cpp b/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewShadowNode.cpp deleted file mode 100644 index 47867419..00000000 --- a/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewShadowNode.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "RNCTabViewShadowNode.h" -#include "RNCTabViewMeasurementsManager.h" - -namespace facebook::react { - -extern const char RNCTabViewComponentName[] = "RNCTabView"; - -#ifdef ANDROID -void RNCTabViewShadowNode::setSliderMeasurementsManager( - const std::shared_ptr & - measurementsManager) -{ - ensureUnsealed(); - measurementsManager_ = measurementsManager; -} - -#pragma mark - LayoutableShadowNode - -Size RNCTabViewShadowNode::measureContent( - const LayoutContext & /*layoutContext*/, - const LayoutConstraints &layoutConstraints) const -{ - return measurementsManager_->measure(getSurfaceId(), layoutConstraints); -} - -#endif - -} diff --git a/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewShadowNode.h b/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewShadowNode.h deleted file mode 100644 index f725d903..00000000 --- a/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewShadowNode.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifdef __cplusplus - -#pragma once - -#include -#include -#include -#include -#include - -#include "RNCTabViewMeasurementsManager.h" - -namespace facebook::react { - -JSI_EXPORT extern const char RNCTabViewComponentName[]; - -/* -* `ShadowNode` for component. -*/ -class JSI_EXPORT RNCTabViewShadowNode final -: public ConcreteViewShadowNode< -RNCTabViewComponentName, -RNCTabViewProps, -RNCTabViewEventEmitter, -RNCTabViewState> -{ -public: - using ConcreteViewShadowNode::ConcreteViewShadowNode; - -#ifdef ANDROID - void setSliderMeasurementsManager( - const std::shared_ptr &measurementsManager); - - #pragma mark - LayoutableShadowNode - - Size measureContent( - const LayoutContext &layoutContext, - const LayoutConstraints &layoutConstraints) const override; - -private: - std::shared_ptr measurementsManager_; -#endif - -}; - -} - -#endif diff --git a/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewState.h b/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewState.h deleted file mode 100644 index cabea07e..00000000 --- a/packages/react-native-bottom-tabs/common/cpp/react/renderer/components/RNCTabView/RNCTabViewState.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifdef __cplusplus - -#pragma once - -#ifdef ANDROID -#include -#include -#include -#endif - -namespace facebook::react { - -class RNCTabViewState -{ -public: - RNCTabViewState() = default; - -#ifdef ANDROID - RNCTabViewState(RNCTabViewState const &previousState, folly::dynamic data) {}; - - folly::dynamic getDynamic() const - { - return {}; - }; - - MapBuffer getMapBuffer() const - { - return MapBufferBuilder::EMPTY(); - }; -#endif -}; - -} - -#endif diff --git a/packages/react-native-bottom-tabs/react-native.config.js b/packages/react-native-bottom-tabs/react-native.config.js deleted file mode 100644 index b3ebd7d7..00000000 --- a/packages/react-native-bottom-tabs/react-native.config.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = { - dependency: { - platforms: { - android: { - libraryName: 'RNCTabView', - componentDescriptors: ['RNCTabViewComponentDescriptor'], - cmakeListsPath: 'src/main/jni/CMakeLists.txt', - }, - }, - }, -}; diff --git a/packages/react-native-bottom-tabs/src/TabViewNativeComponent.ts b/packages/react-native-bottom-tabs/src/TabViewNativeComponent.ts index 113f990f..0a818b5b 100644 --- a/packages/react-native-bottom-tabs/src/TabViewNativeComponent.ts +++ b/packages/react-native-bottom-tabs/src/TabViewNativeComponent.ts @@ -57,6 +57,4 @@ export interface TabViewProps extends ViewProps { fontSize?: Int32; } -export default codegenNativeComponent('RNCTabView', { - interfaceOnly: true, -}); +export default codegenNativeComponent('RNCTabView');