Skip to content

Commit

Permalink
fix: new arch measurements
Browse files Browse the repository at this point in the history
  • Loading branch information
okwasniewski committed Mar 29, 2024
1 parent 166ec7f commit ed08063
Show file tree
Hide file tree
Showing 20 changed files with 443 additions and 34 deletions.
9 changes: 1 addition & 8 deletions package/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ android {
sourceSets {
main {
if (isNewArchitectureEnabled()) {
java.srcDirs += ['src/newarch']
java.srcDirs += ['src/newarch', "${project.buildDir}/generated/source/codegen/java"]
} else {
java.srcDirs += ['src/oldarch']
}
Expand All @@ -73,10 +73,3 @@ dependencies {
api 'com.facebook.react:react-native:+'
}

if (isNewArchitectureEnabled()) {
react {
jsRootDir = file("../src")
libraryName = "ReactSlider"
codegenJavaPackageName = "com.reactnativecommunity.slider"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,16 @@ public static void setAccessibilityIncrements(ReactSlider view, ReadableArray ac
view.setAccessibilityIncrements(stringList);
}

public static Map getExportedCustomDirectEventTypeConstants() {
return MapBuilder.of(ReactSlidingCompleteEvent.EVENT_NAME, MapBuilder.of("registrationName", "onRNCSliderSlidingComplete"),
ReactSlidingStartEvent.EVENT_NAME, MapBuilder.of("registrationName", "onRNCSliderSlidingStart"));
public static Map<String, Object> getExportedCustomBubblingEventTypeConstants() {
return MapBuilder.of(
ReactSliderEvent.EVENT_NAME, MapBuilder.of("registrationName", ReactSliderEvent.EVENT_NAME)
);
}

public static Map<String, Object> getExportedCustomDirectEventTypeConstants() {
return MapBuilder.of(
ReactSlidingStartEvent.EVENT_NAME, MapBuilder.of("registrationName", ReactSlidingStartEvent.EVENT_NAME),
ReactSlidingCompleteEvent.EVENT_NAME, MapBuilder.of("registrationName", ReactSlidingCompleteEvent.EVENT_NAME)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*/
public class ReactSlidingCompleteEvent extends Event<ReactSlidingCompleteEvent> {

public static final String EVENT_NAME = "topSlidingComplete";
public static final String EVENT_NAME = "onRNCSliderSlidingComplete";

private final double mValue;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*/

public class ReactSlidingStartEvent extends Event<ReactSlidingStartEvent> {
public static final String EVENT_NAME = "topSlidingStart";
public static final String EVENT_NAME = "onRNCSliderSlidingStart";

private final double mValue;

Expand Down Expand Up @@ -58,4 +58,4 @@ private WritableMap serializeEventData() {
return eventData;
}

}
}
79 changes: 79 additions & 0 deletions package/android/src/main/jni/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
cmake_minimum_required(VERSION 3.13)
set(CMAKE_VERBOSE_MAKEFILE ON)

set(LIB_LITERAL RNCSlider)
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}
)

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_render_textlayoutmanager
react_utils
react_nativemodule_core
rrc_image
turbomodulejsijni
rrc_text
rrc_textinput
rrc_view
yoga
)

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}
)
18 changes: 18 additions & 0 deletions package/android/src/main/jni/RNCSlider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

#include <ReactCommon/JavaTurboModule.h>
#include <ReactCommon/TurboModule.h>
#include <jsi/jsi.h>
#include <react/renderer/components/RNCSlider/RNCSliderComponentDescriptor.h>

namespace facebook {
namespace react {

JSI_EXPORT
std::shared_ptr<TurboModule> RNCSlider_ModuleProvider(
const std::string &moduleName,
const JavaTurboModule::InitParams &params);

} // namespace react
} // namespace facebook

Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package com.reactnativecommunity.slider;

import android.content.Context;
import android.view.View;
import android.widget.SeekBar;
import androidx.annotation.Nullable;

import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.UIManagerHelper;
Expand All @@ -17,6 +21,8 @@
import com.facebook.react.viewmanagers.RNCSliderManagerInterface;
import com.facebook.react.viewmanagers.RNCSliderManagerDelegate;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.yoga.YogaMeasureMode;
import com.facebook.yoga.YogaMeasureOutput;

/**
* Manages instances of {@code ReactSlider}.
Expand Down Expand Up @@ -190,11 +196,6 @@ protected void addEventEmitters(final ThemedReactContext reactContext, final Rea
view.setOnSeekBarChangeListener(ON_CHANGE_LISTENER);
}

@Override
public Map getExportedCustomDirectEventTypeConstants() {
return ReactSliderManagerImpl.getExportedCustomDirectEventTypeConstants();
}

// these props are not available on Android, however we must override their setters
@Override
public void setMinimumTrackImage(ReactSlider view, @Nullable ReadableMap readableMap) {}
Expand All @@ -210,4 +211,35 @@ public void setTapToSeek(ReactSlider view, boolean value) {}

@Override
public void setVertical(ReactSlider view, boolean value) {}

@Override
public long measure(
Context context,
ReadableMap localData,
ReadableMap props,
ReadableMap state,
float width,
YogaMeasureMode widthMode,
float height,
YogaMeasureMode heightMode,
@Nullable float[] attachmentsPositions) {
ReactSlider view = new ReactSlider(context, null);
int measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
view.measure(measureSpec, measureSpec);
return YogaMeasureOutput.make(
PixelUtil.toDIPFromPixel(view.getMeasuredWidth()),
PixelUtil.toDIPFromPixel(view.getMeasuredHeight()));
}

@Nullable
@Override
public Map<String, Object> getExportedCustomBubblingEventTypeConstants() {
return ReactSliderManagerImpl.getExportedCustomBubblingEventTypeConstants();
}

@Nullable
@Override
public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
return ReactSliderManagerImpl.getExportedCustomDirectEventTypeConstants();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,15 @@ protected void addEventEmitters(final ThemedReactContext reactContext, final Rea
view.setOnSeekBarChangeListener(ON_CHANGE_LISTENER);
}

@Override
public Map getExportedCustomDirectEventTypeConstants() {
return ReactSliderManagerImpl.getExportedCustomDirectEventTypeConstants();
}
@Nullable
@Override
public Map<String, Object> getExportedCustomBubblingEventTypeConstants() {
return ReactSliderManagerImpl.getExportedCustomBubblingEventTypeConstants();
}

@Nullable
@Override
public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
return ReactSliderManagerImpl.getExportedCustomDirectEventTypeConstants();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#pragma once

#include <react/renderer/components/RNCSlider/RNCSliderShadowNode.h>
#include <react/renderer/core/ConcreteComponentDescriptor.h>
#include "RNCSliderMeasurementsManager.h"

namespace facebook {
namespace react {

class RNCSliderComponentDescriptor final
: public ConcreteComponentDescriptor<RNCSliderShadowNode> {
#ifdef ANDROID
public:
RNCSliderComponentDescriptor(const ComponentDescriptorParameters &parameters)
: ConcreteComponentDescriptor(parameters), measurementsManager_(
std::make_shared<RNCSliderMeasurementsManager>(contextContainer_)) {}

void adopt(ShadowNode &shadowNode) const override {
ConcreteComponentDescriptor::adopt(shadowNode);


auto &rncSliderShadowNode =
static_cast<RNCSliderShadowNode &>(shadowNode);

// `RNCSliderShadowNode` uses `RNCSliderMeasurementsManager` to
// provide measurements to Yoga.
rncSliderShadowNode.setSliderMeasurementsManager(
measurementsManager_);

// All `RNCSliderShadowNode`s must have leaf Yoga nodes with properly
// setup measure function.
rncSliderShadowNode.enableMeasurement();
}
private:
const std::shared_ptr<RNCSliderMeasurementsManager> measurementsManager_;
#else
public:
RNCSliderComponentDescriptor(const ComponentDescriptorParameters &parameters)
: ConcreteComponentDescriptor(parameters) {}
#endif
};

} // namespace react
} // namespace facebook
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#ifdef ANDROID
#include "RNCSliderMeasurementsManager.h"

#include <fbjni/fbjni.h>
#include <react/jni/ReadableNativeMap.h>
#include <react/renderer/core/conversions.h>

using namespace facebook::jni;

namespace facebook::react {

Size RNCSliderMeasurementsManager::measure(
SurfaceId surfaceId,
LayoutConstraints layoutConstraints) const {
{
std::scoped_lock lock(mutex_);
if (hasBeenMeasured_) {
return cachedMeasurement_;
}
}

const jni::global_ref<jobject>& fabricUIManager =
contextContainer_->at<jni::global_ref<jobject>>("FabricUIManager");

static auto measure =
jni::findClassStatic("com/facebook/react/fabric/FabricUIManager")
->getMethod<jlong(
jint,
jstring,
ReadableMap::javaobject,
ReadableMap::javaobject,
ReadableMap::javaobject,
jfloat,
jfloat,
jfloat,
jfloat)>("measure");

auto minimumSize = layoutConstraints.minimumSize;
auto maximumSize = layoutConstraints.maximumSize;

local_ref<JString> componentName = make_jstring("RNCSlider");

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;
}

} // namespace facebook::react
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifdef ANDROID
#pragma once

#include <react/renderer/core/ConcreteComponentDescriptor.h>
#include <react/renderer/core/LayoutConstraints.h>
#include <react/utils/ContextContainer.h>

namespace facebook::react {

class RNCSliderMeasurementsManager {
public:
RNCSliderMeasurementsManager(
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_{};

}; // namespace facebook::react
}
#endif
Loading

0 comments on commit ed08063

Please sign in to comment.