Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Fabric support #90

Merged
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 34 additions & 3 deletions android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
buildscript {
repositories {
jcenter()
google()
mavenCentral()
}

dependencies {
classpath 'com.android.tools.build:gradle:1.3.1'
classpath 'com.android.tools.build:gradle:7.2.1'
}
}

def isNewArchitectureEnabled() {
// To opt-in for the New Architecture, you can either:
// - Set `newArchEnabled` to true inside the `gradle.properties` file
// - Invoke gradle with `-newArchEnabled=true`
// - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true`
return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
}

apply plugin: 'com.android.library'

if (isNewArchitectureEnabled()) {
apply plugin: "com.facebook.react"
}

def safeExtGet(prop, fallback) {
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
}
Expand All @@ -26,12 +39,30 @@ android {
lintOptions {
abortOnError false
}
sourceSets.main {
java {
if (!isNewArchitectureEnabled()) {
srcDirs += [
"src/paper/java",
]
}
}
}
}

repositories {
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url "$projectDir/../node_modules/react-native/android"
}
google()
mavenCentral()
}

dependencies {
implementation 'com.facebook.react:react-native:+'
if (isNewArchitectureEnabled()) {
implementation project(":ReactAndroid")
} else {
implementation 'com.facebook.react:react-native:+'
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,26 @@
import javax.annotation.Nullable;

import android.content.Context;
import android.view.View;
import android.widget.ProgressBar;

import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewProps;
import com.facebook.react.uimanager.ViewManagerDelegate;
import com.facebook.react.uimanager.PixelUtil;

import com.facebook.yoga.YogaMeasureFunction;
import com.facebook.yoga.YogaMeasureMode;
import com.facebook.yoga.YogaMeasureOutput;
import com.facebook.yoga.YogaNode;

import com.facebook.react.viewmanagers.RNCProgressBarManagerDelegate;
import com.facebook.react.viewmanagers.RNCProgressBarManagerInterface;

/**
* Manages instances of ProgressBar. ProgressBar is wrapped in a
Expand All @@ -27,9 +39,10 @@
* style given.
*/
@ReactModule(name = ReactProgressBarViewManager.REACT_CLASS)
public class ReactProgressBarViewManager extends BaseViewManager<ProgressBarContainerView, ProgressBarShadowNode> {
public class ReactProgressBarViewManager extends BaseViewManager<ProgressBarContainerView, ProgressBarShadowNode> implements RNCProgressBarManagerInterface<ProgressBarContainerView> {

public static final String REACT_CLASS = "RNCProgressBar";
private final ViewManagerDelegate<ProgressBarContainerView> mDelegate;

/* package */ static final String PROP_STYLE = "styleAttr";
/* package */ static final String PROP_INDETERMINATE = "indeterminate";
Expand All @@ -40,6 +53,36 @@ public class ReactProgressBarViewManager extends BaseViewManager<ProgressBarCont

private static Object sProgressBarCtorLock = new Object();

@Nullable
@Override
protected ViewManagerDelegate<ProgressBarContainerView> getDelegate() {
return mDelegate;
}

public ReactProgressBarViewManager() {
mDelegate = new RNCProgressBarManagerDelegate<>(this);
}

public long measure(
Context context,
ReadableMap localData,
ReadableMap props,
ReadableMap state,
float width,
YogaMeasureMode widthMode,
float height,
YogaMeasureMode heightMode,
@androidx.annotation.Nullable float[] attachmentsPositions) {
final int style = ReactProgressBarViewManager.getStyleFromString(props.getString("styleAttr"));

ProgressBar view = ReactProgressBarViewManager.createProgressBar(context, style);
int measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
view.measure(measureSpec, measureSpec);
return YogaMeasureOutput.make(
PixelUtil.toDIPFromPixel(view.getMeasuredWidth()),
PixelUtil.toDIPFromPixel(view.getMeasuredHeight()));
}

/**
* We create ProgressBars on both the UI and shadow threads. There is a race
* condition in the ProgressBar constructor that may cause crashes when two
Expand All @@ -62,26 +105,31 @@ protected ProgressBarContainerView createViewInstance(ThemedReactContext context
return new ProgressBarContainerView(context);
}

@Override
@ReactProp(name = PROP_STYLE)
public void setStyle(ProgressBarContainerView view, @Nullable String styleName) {
public void setStyleAttr(ProgressBarContainerView view, @Nullable String styleName) {
view.setStyle(styleName);
}

@ReactProp(name = ViewProps.COLOR, customType = "Color")
@Override
@ReactProp(name = ViewProps.COLOR)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is customType = "Color" gone here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of adding processColor in JS the prop stopped working when customType = "Color" was there.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was processColor added in the first place?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 45c5d5e. I don't particularly remember why I've done it this way 😅.

public void setColor(ProgressBarContainerView view, @Nullable Integer color) {
view.setColor(color);
}

@Override
@ReactProp(name = PROP_INDETERMINATE)
public void setIndeterminate(ProgressBarContainerView view, boolean indeterminate) {
view.setIndeterminate(indeterminate);
}

@Override
@ReactProp(name = PROP_PROGRESS)
public void setProgress(ProgressBarContainerView view, double progress) {
view.setProgress(progress);
}

@Override
@ReactProp(name = PROP_ANIMATING)
public void setAnimating(ProgressBarContainerView view, boolean animating) {
view.setAnimating(animating);
Expand Down
71 changes: 71 additions & 0 deletions android/src/main/jni/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
cmake_minimum_required(VERSION 3.13)
set(CMAKE_VERBOSE_MAKEFILE ON)

set(LIB_LITERAL rnandroidprogressbar)
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++17
-Wall
-Wpedantic
-Wno-gnu-zero-variadic-macro-arguments
)

file(GLOB LIB_CUSTOM_SRCS CONFIGURE_DEPENDS *.cpp)
file(GLOB LIB_CODEGEN_SRCS CONFIGURE_DEPENDS ${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_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_nativemodule_core
react_render_core
react_render_debug
react_render_graphics
react_render_mapbuffer
rrc_view
turbomodulejsijni
yoga
)

target_compile_options(
${LIB_TARGET_NAME}
PRIVATE
-DLOG_TAG=\"ReactNative\"
-fexceptions
-frtti
-std=c++17
-Wall
)

target_include_directories(
${CMAKE_PROJECT_NAME}
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
75 changes: 75 additions & 0 deletions android/src/main/jni/RNCProgressBarMeasurementsManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include "RNCProgressBarMeasurementsManager.h"

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

using namespace facebook::jni;

namespace facebook
{
namespace react
{

Size RNCProgressBarMeasurementsManager::measure(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you write a comment from where did you take analogous code with some links and a short explanation of what is done here if needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in 722b62f.

SurfaceId surfaceId,
LayoutConstraints layoutConstraints,
RNCProgressBarProps props) const
{
{
std::lock_guard<std::mutex> lock(mutex_);
if (cachedMeasurements_.find(props.styleAttr) != cachedMeasurements_.end())
{
return cachedMeasurements_[props.styleAttr];
}
}

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("RNCProgressBar");

folly::dynamic serializedProps = folly::dynamic::object();
serializedProps["styleAttr"] = props.styleAttr;

local_ref<ReadableNativeMap::javaobject> propsRNM =
ReadableNativeMap::newObjectCxxArgs(serializedProps);
local_ref<ReadableMap::javaobject> propsRM =
make_local(reinterpret_cast<ReadableMap::javaobject>(propsRNM.get()));

auto measurement = yogaMeassureToSize(measure(
fabricUIManager,
surfaceId,
componentName.get(),
nullptr,
propsRM.get(),
nullptr,
minimumSize.width,
maximumSize.width,
minimumSize.height,
maximumSize.height));

std::lock_guard<std::mutex> lock(mutex_);
cachedMeasurements_[props.styleAttr] = measurement;
return measurement;
}

} // namespace react
} // namespace facebook
29 changes: 29 additions & 0 deletions android/src/main/jni/RNCProgressBarMeasurementsManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once

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

namespace facebook
{
namespace react
{

class RNCProgressBarMeasurementsManager
{
public:
RNCProgressBarMeasurementsManager(
const ContextContainer::Shared &contextContainer)
: contextContainer_(contextContainer) {}

Size measure(SurfaceId surfaceId, LayoutConstraints layoutConstraints, RNCProgressBarProps props) const;

private:
const ContextContainer::Shared contextContainer_;
mutable std::mutex mutex_;
mutable std::unordered_map<std::string, Size> cachedMeasurements_ = {};
};

} // namespace react
} // namespace facebook
28 changes: 28 additions & 0 deletions android/src/main/jni/RNCProgressBarShadowNode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "RNCProgressBarShadowNode.h"
#include "RNCProgressBarMeasurementsManager.h"

namespace facebook
{
namespace react
{

extern const char RNCProgressBarComponentName[] = "RNCProgressBar";

void RNCProgressBarShadowNode::setProgressBarMeasurementsManager(
const std::shared_ptr<RNCProgressBarMeasurementsManager>
&measurementsManager)
{
ensureUnsealed();
measurementsManager_ = measurementsManager;
}

#pragma mark - LayoutableShadowNode

Size RNCProgressBarShadowNode::measureContent(
LayoutContext const &layoutContext,
LayoutConstraints const &layoutConstraints) const
{
return measurementsManager_->measure(getSurfaceId(), layoutConstraints, getConcreteProps());
}
} // namespace react
} // namespace facebook
Loading