From 3162889920c1834e464e46db68b5b87372ddab2d Mon Sep 17 00:00:00 2001 From: Gerardo Pacheco Date: Tue, 11 Oct 2022 13:32:15 +0200 Subject: [PATCH] [Mobile] - React Native 0.69.4 Upgrade - Android (#43486) * Mobile - React Native 0.69.4 upgrade, base Android changes * Mobile - Remove RNGestureHandlerEnabledRootView since its now deprecated * Mobile - Update bundle android script --- packages/edit-post/src/editor.native.js | 25 ++-- .../react-native-aztec/android/build.gradle | 13 +- .../android/react-native-bridge/build.gradle | 17 ++- .../WPAndroidGlue/WPAndroidGlueCode.java | 3 +- .../android/app/build.gradle | 109 ++++++++++++++-- .../android/app/src/debug/AndroidManifest.xml | 2 +- .../android/app/src/main/AndroidManifest.xml | 5 +- .../main/java/com/gutenberg/MainActivity.java | 7 -- .../MainApplicationReactNativeHost.java | 116 ++++++++++++++++++ .../components/MainComponentsRegistry.java | 36 ++++++ ...ApplicationTurboModuleManagerDelegate.java | 48 ++++++++ .../android/app/src/main/jni/Android.mk | 48 ++++++++ .../jni/MainApplicationModuleProvider.cpp | 24 ++++ .../main/jni/MainApplicationModuleProvider.h | 16 +++ ...nApplicationTurboModuleManagerDelegate.cpp | 45 +++++++ ...ainApplicationTurboModuleManagerDelegate.h | 38 ++++++ .../src/main/jni/MainComponentsRegistry.cpp | 61 +++++++++ .../app/src/main/jni/MainComponentsRegistry.h | 32 +++++ .../android/app/src/main/jni/OnLoad.cpp | 11 ++ .../res/drawable/rn_edit_text_material.xml | 36 ++++++ .../app/src/main/res/values/styles.xml | 1 + .../react-native-editor/android/build.gradle | 29 ++++- .../android/gradle.properties | 13 +- .../android/settings.gradle | 7 ++ packages/react-native-editor/package.json | 2 +- 25 files changed, 697 insertions(+), 47 deletions(-) create mode 100644 packages/react-native-editor/android/app/src/main/java/com/gutenberg/newarchitecture/MainApplicationReactNativeHost.java create mode 100644 packages/react-native-editor/android/app/src/main/java/com/gutenberg/newarchitecture/components/MainComponentsRegistry.java create mode 100644 packages/react-native-editor/android/app/src/main/java/com/gutenberg/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java create mode 100644 packages/react-native-editor/android/app/src/main/jni/Android.mk create mode 100644 packages/react-native-editor/android/app/src/main/jni/MainApplicationModuleProvider.cpp create mode 100644 packages/react-native-editor/android/app/src/main/jni/MainApplicationModuleProvider.h create mode 100644 packages/react-native-editor/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp create mode 100644 packages/react-native-editor/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h create mode 100644 packages/react-native-editor/android/app/src/main/jni/MainComponentsRegistry.cpp create mode 100644 packages/react-native-editor/android/app/src/main/jni/MainComponentsRegistry.h create mode 100644 packages/react-native-editor/android/app/src/main/jni/OnLoad.cpp create mode 100644 packages/react-native-editor/android/app/src/main/res/drawable/rn_edit_text_material.xml diff --git a/packages/edit-post/src/editor.native.js b/packages/edit-post/src/editor.native.js index d600a8ea8dec5..6638c3bd05e0e 100644 --- a/packages/edit-post/src/editor.native.js +++ b/packages/edit-post/src/editor.native.js @@ -4,6 +4,7 @@ import memize from 'memize'; import { map, without } from 'lodash'; import { I18nManager } from 'react-native'; +import { GestureHandlerRootView } from 'react-native-gesture-handler'; /** * WordPress dependencies @@ -174,17 +175,19 @@ class Editor extends Component { }; return ( - - - - - + + + + + + + ); } } diff --git a/packages/react-native-aztec/android/build.gradle b/packages/react-native-aztec/android/build.gradle index 39383624f2bf7..338e7622453ce 100644 --- a/packages/react-native-aztec/android/build.gradle +++ b/packages/react-native-aztec/android/build.gradle @@ -34,11 +34,11 @@ List dirs = [ 'template'] // boilerplate code that is generated by the sample template process android { - compileSdkVersion 30 + compileSdkVersion 31 defaultConfig { minSdkVersion 21 - targetSdkVersion 30 + targetSdkVersion 31 } compileOptions { @@ -73,10 +73,15 @@ repositories { includeGroup "org.wordpress.aztec" } } - maven { url "https://a8c-libs.s3.amazonaws.com/android/hermes-mirror" } maven { url "https://a8c-libs.s3.amazonaws.com/android/react-native-mirror" } google() - mavenCentral() + mavenCentral { + // We don't want to fetch react-native from Maven Central as there are + // older versions over there. + content { + excludeGroup "com.facebook.react" + } + } } dependencies { diff --git a/packages/react-native-bridge/android/react-native-bridge/build.gradle b/packages/react-native-bridge/android/react-native-bridge/build.gradle index 6998e5cbdca53..6ee028d1ed967 100644 --- a/packages/react-native-bridge/android/react-native-bridge/build.gradle +++ b/packages/react-native-bridge/android/react-native-bridge/build.gradle @@ -14,11 +14,11 @@ group='org.wordpress-mobile.gutenberg-mobile' def buildAssetsFolder = 'build/assets' android { - compileSdkVersion 30 + compileSdkVersion 31 defaultConfig { minSdkVersion 21 - targetSdkVersion 30 + targetSdkVersion 31 buildConfigField "boolean", "SHOULD_ATTACH_JS_BUNDLE", willPublishReactNativeBridgeBinary.toString() } @@ -45,10 +45,15 @@ android { repositories { maven { url "https://a8c-libs.s3.amazonaws.com/android" } - maven { url "https://a8c-libs.s3.amazonaws.com/android/hermes-mirror" } maven { url "https://jitpack.io" } google() - mavenCentral() + mavenCentral { + // We don't want to fetch react-native from Maven Central as there are + // older versions over there. + content { + excludeGroup "com.facebook.react" + } + } } dependencies { @@ -83,7 +88,9 @@ dependencies { exclude group: 'com.github.wordpress-mobile', module: 'react-native-reanimated' }) - runtimeOnly "org.wordpress-mobile:hermes-release-mirror:$rnVersion" + runtimeOnly("com.facebook.react:hermes-engine:$rnVersion", { + exclude group:'com.facebook.fbjni' + }) if (willPublishReactNativeBridgeBinary) { implementation "org.wordpress-mobile.gutenberg-mobile:react-native-aztec:$reactNativeAztecVersion" diff --git a/packages/react-native-bridge/android/react-native-bridge/src/main/java/org/wordpress/mobile/WPAndroidGlue/WPAndroidGlueCode.java b/packages/react-native-bridge/android/react-native-bridge/src/main/java/org/wordpress/mobile/WPAndroidGlue/WPAndroidGlueCode.java index 74236bb49bcd8..bd3111e846325 100644 --- a/packages/react-native-bridge/android/react-native-bridge/src/main/java/org/wordpress/mobile/WPAndroidGlue/WPAndroidGlueCode.java +++ b/packages/react-native-bridge/android/react-native-bridge/src/main/java/org/wordpress/mobile/WPAndroidGlue/WPAndroidGlueCode.java @@ -45,7 +45,6 @@ import com.reactnativecommunity.slider.ReactSliderPackage; import org.linusu.RNGetRandomValuesPackage; import com.reactnativecommunity.webview.RNCWebViewPackage; -import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView; import com.swmansion.gesturehandler.RNGestureHandlerPackage; import com.swmansion.reanimated.ReanimatedJSIModulePackage; import com.swmansion.reanimated.ReanimatedPackage; @@ -615,7 +614,7 @@ public void onCreateView(Context initContext, mIsDarkMode = gutenbergProps.isDarkMode(); mExceptionLogger = exceptionLogger; mBreadcrumbLogger = breadcrumbLogger; - mReactRootView = new RNGestureHandlerEnabledRootView(new MutableContextWrapper(initContext)); + mReactRootView = new ReactRootView(new MutableContextWrapper(initContext)); mReactRootView.setBackgroundColor(colorBackground); ReactInstanceManagerBuilder builder = diff --git a/packages/react-native-editor/android/app/build.gradle b/packages/react-native-editor/android/app/build.gradle index e4b5d092724e2..ad95c1be10ea0 100644 --- a/packages/react-native-editor/android/app/build.gradle +++ b/packages/react-native-editor/android/app/build.gradle @@ -103,16 +103,19 @@ def enableProguardInReleaseBuilds = false /** * Whether to enable the Hermes VM. * - * This should be set on project.ext.react and mirrored here. If it is not set + * This should be set on project.ext.react and that value will be read here. If it is not set * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode * and the benefits of using Hermes will therefore be sharply reduced. */ def enableHermes = project.ext.react.get("enableHermes", false); /** - * Architectures to build native code for in debug. + * Architectures to build native code for. */ -def nativeArchitectures = project.getProperties().get("reactNativeDebugArchitectures") +def reactNativeArchitectures() { + def value = project.getProperties().get("reactNativeArchitectures") + return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] +} android { ndkVersion rootProject.ext.ndkVersion @@ -130,9 +133,73 @@ android { targetSdkVersion rootProject.ext.targetSdkVersion versionCode 1 versionName "1.0" - ndk { - abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86", "mips" + buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() + if (isNewArchitectureEnabled()) { + // We configure the NDK build only if you decide to opt-in for the New Architecture. + externalNativeBuild { + ndkBuild { + arguments "APP_PLATFORM=android-21", + "APP_STL=c++_shared", + "NDK_TOOLCHAIN_VERSION=clang", + "GENERATED_SRC_DIR=$buildDir/generated/source", + "PROJECT_BUILD_DIR=$buildDir", + "REACT_ANDROID_DIR=../../../../node_modules/react-native/ReactAndroid", + "REACT_ANDROID_BUILD_DIR=../../../../node_modules/react-native/ReactAndroid/build", + "NODE_MODULES_DIR=../../../../node_modules" + cFlags "-Wall", "-Werror", "-fexceptions", "-frtti", "-DWITH_INSPECTOR=1" + cppFlags "-std=c++17" + // Make sure this target name is the same you specify inside the + // src/main/jni/Android.mk file for the `LOCAL_MODULE` variable. + targets "gutenberg_appmodules" + } + } + if (!enableSeparateBuildPerCPUArchitecture) { + ndk { + abiFilters (*reactNativeArchitectures()) + } + } + } + } + + if (isNewArchitectureEnabled()) { + // We configure the NDK build only if you decide to opt-in for the New Architecture. + externalNativeBuild { + ndkBuild { + path "$projectDir/src/main/jni/Android.mk" + } + } + def reactAndroidProjectDir = project(':ReactAndroid').projectDir + def packageReactNdkDebugLibs = tasks.register("packageReactNdkDebugLibs", Copy) { + dependsOn(":ReactAndroid:packageReactNdkDebugLibsForBuck") + from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib") + into("$buildDir/react-ndk/exported") + } + def packageReactNdkReleaseLibs = tasks.register("packageReactNdkReleaseLibs", Copy) { + dependsOn(":ReactAndroid:packageReactNdkReleaseLibsForBuck") + from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib") + into("$buildDir/react-ndk/exported") + } + afterEvaluate { + // If you wish to add a custom TurboModule or component locally, + // you should uncomment this line. + // preBuild.dependsOn("generateCodegenArtifactsFromSchema") + preDebugBuild.dependsOn(packageReactNdkDebugLibs) + preReleaseBuild.dependsOn(packageReactNdkReleaseLibs) + + // Due to a bug inside AGP, we have to explicitly set a dependency + // between configureNdkBuild* tasks and the preBuild tasks. + // This can be removed once this is solved: https://issuetracker.google.com/issues/207403732 + configureNdkBuildRelease.dependsOn(preReleaseBuild) + configureNdkBuildDebug.dependsOn(preDebugBuild) + reactNativeArchitectures().each { architecture -> + tasks.findByName("configureNdkBuildDebug[${architecture}]")?.configure { + dependsOn("preDebugBuild") + } + tasks.findByName("configureNdkBuildRelease[${architecture}]")?.configure { + dependsOn("preReleaseBuild") + } + } } } splits { @@ -140,7 +207,7 @@ android { reset() enable enableSeparateBuildPerCPUArchitecture universalApk false // If true, also generate a universal APK - include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" + include (*reactNativeArchitectures()) } } buildTypes { @@ -177,7 +244,7 @@ dependencies { }) implementation 'androidx.appcompat:appcompat:1.2.0' //noinspection GradleDynamicVersion - implementation "com.facebook.react:react-native:${extractPackageVersion(packageJson, 'react-native', 'dependencies')}" // From node_modules + implementation "com.facebook.react:react-native:${extractPackageVersion(packageJson, 'react-native', 'dependencies')}" implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" @@ -199,6 +266,26 @@ dependencies { // Remove Reanimated transitive dependency as it's already defined here exclude group: 'com.github.wordpress-mobile', module: 'react-native-reanimated' }) + + implementation("com.facebook.react:hermes-engine:${extractPackageVersion(packageJson, 'react-native', 'dependencies')}") { + exclude group:'com.facebook.fbjni' + } +} + +if (isNewArchitectureEnabled()) { + // If new architecture is enabled, we let you build RN from source + // Otherwise we fallback to a prebuilt .aar bundled in the NPM package. + // This will be applied to all the imported transtitive dependency. + configurations.all { + resolutionStrategy.dependencySubstitution { + substitute(module("com.facebook.react:react-native")) + .using(project(":ReactAndroid")) + .because("On New Architecture we're building React Native from source") + substitute(module("com.facebook.react:hermes-engine")) + .using(project(":ReactAndroid:hermes-engine")) + .because("On New Architecture we're building Hermes from source") + } + } } // Run this once to be able to run the application with BUCK @@ -207,3 +294,11 @@ task copyDownloadableDepsToLibs(type: Copy) { from configurations.implementation into 'libs' } + +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" +} \ No newline at end of file diff --git a/packages/react-native-editor/android/app/src/debug/AndroidManifest.xml b/packages/react-native-editor/android/app/src/debug/AndroidManifest.xml index 179354e4c747a..1970c1dc4856e 100644 --- a/packages/react-native-editor/android/app/src/debug/AndroidManifest.xml +++ b/packages/react-native-editor/android/app/src/debug/AndroidManifest.xml @@ -5,6 +5,6 @@ android:networkSecurityConfig="@xml/react_native_config" tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning"> - + \ No newline at end of file diff --git a/packages/react-native-editor/android/app/src/main/AndroidManifest.xml b/packages/react-native-editor/android/app/src/main/AndroidManifest.xml index 59178922a493f..3f139808aa706 100644 --- a/packages/react-native-editor/android/app/src/main/AndroidManifest.xml +++ b/packages/react-native-editor/android/app/src/main/AndroidManifest.xml @@ -15,9 +15,10 @@ + android:windowSoftInputMode="adjustResize" + android:exported="true"> diff --git a/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainActivity.java b/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainActivity.java index 447f2d35ee4de..ae81e808011ea 100644 --- a/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainActivity.java +++ b/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainActivity.java @@ -6,8 +6,6 @@ import com.facebook.react.ReactActivity; import com.facebook.react.ReactActivityDelegate; -import com.facebook.react.ReactRootView; -import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView; import org.wordpress.mobile.WPAndroidGlue.GutenbergProps; @@ -27,11 +25,6 @@ protected String getMainComponentName() { @Override protected ReactActivityDelegate createReactActivityDelegate() { return new ReactActivityDelegate(this, getMainComponentName()) { - @Override - protected ReactRootView createRootView() { - return new RNGestureHandlerEnabledRootView(MainActivity.this); - } - @Nullable @Override protected Bundle getLaunchOptions() { diff --git a/packages/react-native-editor/android/app/src/main/java/com/gutenberg/newarchitecture/MainApplicationReactNativeHost.java b/packages/react-native-editor/android/app/src/main/java/com/gutenberg/newarchitecture/MainApplicationReactNativeHost.java new file mode 100644 index 0000000000000..5a3deee24f507 --- /dev/null +++ b/packages/react-native-editor/android/app/src/main/java/com/gutenberg/newarchitecture/MainApplicationReactNativeHost.java @@ -0,0 +1,116 @@ +package com.gutenberg.newarchitecture; + +import android.app.Application; +import androidx.annotation.NonNull; +import com.facebook.react.ReactInstanceManager; +import com.facebook.react.ReactNativeHost; +import com.facebook.react.ReactPackage; +import com.facebook.react.ReactPackageTurboModuleManagerDelegate; +import com.facebook.react.bridge.JSIModulePackage; +import com.facebook.react.bridge.JSIModuleProvider; +import com.facebook.react.bridge.JSIModuleSpec; +import com.facebook.react.bridge.JSIModuleType; +import com.facebook.react.bridge.JavaScriptContextHolder; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.UIManager; +import com.facebook.react.fabric.ComponentFactory; +import com.facebook.react.fabric.CoreComponentsRegistry; +import com.facebook.react.fabric.FabricJSIModuleProvider; +import com.facebook.react.fabric.ReactNativeConfig; +import com.facebook.react.uimanager.ViewManagerRegistry; +import com.gutenberg.BuildConfig; +import com.gutenberg.newarchitecture.components.MainComponentsRegistry; +import com.gutenberg.newarchitecture.modules.MainApplicationTurboModuleManagerDelegate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * A {@link ReactNativeHost} that helps you load everything needed for the New Architecture, both + * TurboModule delegates and the Fabric Renderer. + * + *

Please note that this class is used ONLY if you opt-in for the New Architecture (see the + * `newArchEnabled` property). Is ignored otherwise. + */ +public class MainApplicationReactNativeHost extends ReactNativeHost { + public MainApplicationReactNativeHost(Application application) { + super(application); + } + + @Override + public boolean getUseDeveloperSupport() { + return BuildConfig.DEBUG; + } + + @Override + protected List getPackages() { + List packages = Arrays.asList(); + // Packages that cannot be autolinked yet can be added manually here, for example: + // packages.add(new MyReactNativePackage()); + // TurboModules must also be loaded here providing a valid TurboReactPackage implementation: + // packages.add(new TurboReactPackage() { ... }); + // If you have custom Fabric Components, their ViewManagers should also be loaded here + // inside a ReactPackage. + return packages; + } + + @Override + protected String getJSMainModuleName() { + return "index"; + } + + @NonNull + @Override + protected ReactPackageTurboModuleManagerDelegate.Builder + getReactPackageTurboModuleManagerDelegateBuilder() { + // Here we provide the ReactPackageTurboModuleManagerDelegate Builder. This is necessary + // for the new architecture and to use TurboModules correctly. + return new MainApplicationTurboModuleManagerDelegate.Builder(); + } + + @Override + protected JSIModulePackage getJSIModulePackage() { + return new JSIModulePackage() { + @Override + public List getJSIModules( + final ReactApplicationContext reactApplicationContext, + final JavaScriptContextHolder jsContext) { + final List specs = new ArrayList<>(); + + // Here we provide a new JSIModuleSpec that will be responsible of providing the + // custom Fabric Components. + specs.add( + new JSIModuleSpec() { + @Override + public JSIModuleType getJSIModuleType() { + return JSIModuleType.UIManager; + } + + @Override + public JSIModuleProvider getJSIModuleProvider() { + final ComponentFactory componentFactory = new ComponentFactory(); + CoreComponentsRegistry.register(componentFactory); + + // Here we register a Components Registry. + // The one that is generated with the template contains no components + // and just provides you the one from React Native core. + MainComponentsRegistry.register(componentFactory); + + final ReactInstanceManager reactInstanceManager = getReactInstanceManager(); + + ViewManagerRegistry viewManagerRegistry = + new ViewManagerRegistry( + reactInstanceManager.getOrCreateViewManagers(reactApplicationContext)); + + return new FabricJSIModuleProvider( + reactApplicationContext, + componentFactory, + ReactNativeConfig.DEFAULT_CONFIG, + viewManagerRegistry); + } + }); + return specs; + } + }; + } +} diff --git a/packages/react-native-editor/android/app/src/main/java/com/gutenberg/newarchitecture/components/MainComponentsRegistry.java b/packages/react-native-editor/android/app/src/main/java/com/gutenberg/newarchitecture/components/MainComponentsRegistry.java new file mode 100644 index 0000000000000..4a613ac3a2bc3 --- /dev/null +++ b/packages/react-native-editor/android/app/src/main/java/com/gutenberg/newarchitecture/components/MainComponentsRegistry.java @@ -0,0 +1,36 @@ +package com.gutenberg.newarchitecture.components; + +import com.facebook.jni.HybridData; +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.react.fabric.ComponentFactory; +import com.facebook.soloader.SoLoader; + +/** + * Class responsible to load the custom Fabric Components. This class has native methods and needs a + * corresponding C++ implementation/header file to work correctly (already placed inside the jni/ + * folder for you). + * + *

Please note that this class is used ONLY if you opt-in for the New Architecture (see the + * `newArchEnabled` property). Is ignored otherwise. + */ +@DoNotStrip +public class MainComponentsRegistry { + static { + SoLoader.loadLibrary("fabricjni"); + } + + @DoNotStrip private final HybridData mHybridData; + + @DoNotStrip + private native HybridData initHybrid(ComponentFactory componentFactory); + + @DoNotStrip + private MainComponentsRegistry(ComponentFactory componentFactory) { + mHybridData = initHybrid(componentFactory); + } + + @DoNotStrip + public static MainComponentsRegistry register(ComponentFactory componentFactory) { + return new MainComponentsRegistry(componentFactory); + } +} \ No newline at end of file diff --git a/packages/react-native-editor/android/app/src/main/java/com/gutenberg/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java b/packages/react-native-editor/android/app/src/main/java/com/gutenberg/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java new file mode 100644 index 0000000000000..b80720e9bdd88 --- /dev/null +++ b/packages/react-native-editor/android/app/src/main/java/com/gutenberg/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java @@ -0,0 +1,48 @@ +package com.gutenberg.newarchitecture.modules; + +import com.facebook.jni.HybridData; +import com.facebook.react.ReactPackage; +import com.facebook.react.ReactPackageTurboModuleManagerDelegate; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.soloader.SoLoader; +import java.util.List; + +/** + * Class responsible to load the TurboModules. This class has native methods and needs a + * corresponding C++ implementation/header file to work correctly (already placed inside the jni/ + * folder for you). + * + *

Please note that this class is used ONLY if you opt-in for the New Architecture (see the + * `newArchEnabled` property). Is ignored otherwise. + */ +public class MainApplicationTurboModuleManagerDelegate + extends ReactPackageTurboModuleManagerDelegate { + + private static volatile boolean sIsSoLibraryLoaded; + + protected MainApplicationTurboModuleManagerDelegate( + ReactApplicationContext reactApplicationContext, List packages) { + super(reactApplicationContext, packages); + } + + protected native HybridData initHybrid(); + + native boolean canCreateTurboModule(String moduleName); + + public static class Builder extends ReactPackageTurboModuleManagerDelegate.Builder { + protected MainApplicationTurboModuleManagerDelegate build( + ReactApplicationContext context, List packages) { + return new MainApplicationTurboModuleManagerDelegate(context, packages); + } + } + + @Override + protected synchronized void maybeLoadOtherSoLibraries() { + if (!sIsSoLibraryLoaded) { + // If you change the name of your application .so file in the Android.mk file, + // make sure you update the name here as well. + SoLoader.loadLibrary("gutenberg_appmodules"); + sIsSoLibraryLoaded = true; + } + } +} \ No newline at end of file diff --git a/packages/react-native-editor/android/app/src/main/jni/Android.mk b/packages/react-native-editor/android/app/src/main/jni/Android.mk new file mode 100644 index 0000000000000..633707fd91605 --- /dev/null +++ b/packages/react-native-editor/android/app/src/main/jni/Android.mk @@ -0,0 +1,48 @@ +THIS_DIR := $(call my-dir) + +include $(REACT_ANDROID_DIR)/Android-prebuilt.mk + +# If you wish to add a custom TurboModule or Fabric component in your app you +# will have to include the following autogenerated makefile. +# include $(GENERATED_SRC_DIR)/codegen/jni/Android.mk +include $(CLEAR_VARS) + +LOCAL_PATH := $(THIS_DIR) + +# You can customize the name of your application .so file here. +LOCAL_MODULE := gutenberg_appmodules + +LOCAL_C_INCLUDES := $(LOCAL_PATH) +LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) + +# If you wish to add a custom TurboModule or Fabric component in your app you +# will have to uncomment those lines to include the generated source +# files from the codegen (placed in $(GENERATED_SRC_DIR)/codegen/jni) +# +# LOCAL_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni +# LOCAL_SRC_FILES += $(wildcard $(GENERATED_SRC_DIR)/codegen/jni/*.cpp) +# LOCAL_EXPORT_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni + +# Here you should add any native library you wish to depend on. +LOCAL_SHARED_LIBRARIES := \ + libfabricjni \ + libfbjni \ + libfolly_runtime \ + libglog \ + libjsi \ + libreact_codegen_rncore \ + libreact_debug \ + libreact_nativemodule_core \ + libreact_render_componentregistry \ + libreact_render_core \ + libreact_render_debug \ + libreact_render_graphics \ + librrc_view \ + libruntimeexecutor \ + libturbomodulejsijni \ + libyoga + +LOCAL_CFLAGS := -DLOG_TAG=\"ReactNative\" -fexceptions -frtti -std=c++17 -Wall + +include $(BUILD_SHARED_LIBRARY) \ No newline at end of file diff --git a/packages/react-native-editor/android/app/src/main/jni/MainApplicationModuleProvider.cpp b/packages/react-native-editor/android/app/src/main/jni/MainApplicationModuleProvider.cpp new file mode 100644 index 0000000000000..39de093d1136d --- /dev/null +++ b/packages/react-native-editor/android/app/src/main/jni/MainApplicationModuleProvider.cpp @@ -0,0 +1,24 @@ +#include "MainApplicationModuleProvider.h" + +#include + +namespace facebook { +namespace react { + +std::shared_ptr MainApplicationModuleProvider( + const std::string moduleName, + const JavaTurboModule::InitParams ¶ms) { + // Here you can provide your own module provider for TurboModules coming from + // either your application or from external libraries. The approach to follow + // is similar to the following (for a library called `samplelibrary`: + // + // auto module = samplelibrary_ModuleProvider(moduleName, params); + // if (module != nullptr) { + // return module; + // } + // return rncore_ModuleProvider(moduleName, params); + return rncore_ModuleProvider(moduleName, params); +} + +} // namespace react +} // namespace facebook \ No newline at end of file diff --git a/packages/react-native-editor/android/app/src/main/jni/MainApplicationModuleProvider.h b/packages/react-native-editor/android/app/src/main/jni/MainApplicationModuleProvider.h new file mode 100644 index 0000000000000..2f2fb24a3a76c --- /dev/null +++ b/packages/react-native-editor/android/app/src/main/jni/MainApplicationModuleProvider.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include + +#include + +namespace facebook { +namespace react { + +std::shared_ptr MainApplicationModuleProvider( + const std::string moduleName, + const JavaTurboModule::InitParams ¶ms); + +} // namespace react +} // namespace facebook \ No newline at end of file diff --git a/packages/react-native-editor/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp b/packages/react-native-editor/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp new file mode 100644 index 0000000000000..f2e4714dc93b6 --- /dev/null +++ b/packages/react-native-editor/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp @@ -0,0 +1,45 @@ +#include "MainApplicationTurboModuleManagerDelegate.h" +#include "MainApplicationModuleProvider.h" + +namespace facebook { +namespace react { + +jni::local_ref +MainApplicationTurboModuleManagerDelegate::initHybrid( + jni::alias_ref) { + return makeCxxInstance(); +} + +void MainApplicationTurboModuleManagerDelegate::registerNatives() { + registerHybrid({ + makeNativeMethod( + "initHybrid", MainApplicationTurboModuleManagerDelegate::initHybrid), + makeNativeMethod( + "canCreateTurboModule", + MainApplicationTurboModuleManagerDelegate::canCreateTurboModule), + }); +} + +std::shared_ptr +MainApplicationTurboModuleManagerDelegate::getTurboModule( + const std::string name, + const std::shared_ptr jsInvoker) { + // Not implemented yet: provide pure-C++ NativeModules here. + return nullptr; +} + +std::shared_ptr +MainApplicationTurboModuleManagerDelegate::getTurboModule( + const std::string name, + const JavaTurboModule::InitParams ¶ms) { + return MainApplicationModuleProvider(name, params); +} + +bool MainApplicationTurboModuleManagerDelegate::canCreateTurboModule( + std::string name) { + return getTurboModule(name, nullptr) != nullptr || + getTurboModule(name, {.moduleName = name}) != nullptr; +} + +} // namespace react +} // namespace facebook \ No newline at end of file diff --git a/packages/react-native-editor/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h b/packages/react-native-editor/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h new file mode 100644 index 0000000000000..2cd17d7a944c0 --- /dev/null +++ b/packages/react-native-editor/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h @@ -0,0 +1,38 @@ +#include +#include + +#include +#include + +namespace facebook { +namespace react { + +class MainApplicationTurboModuleManagerDelegate + : public jni::HybridClass< + MainApplicationTurboModuleManagerDelegate, + TurboModuleManagerDelegate> { + public: + // Adapt it to the package you used for your Java class. + static constexpr auto kJavaDescriptor = + "Lcom/gutenberg/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate;"; + + static jni::local_ref initHybrid(jni::alias_ref); + + static void registerNatives(); + + std::shared_ptr getTurboModule( + const std::string name, + const std::shared_ptr jsInvoker) override; + std::shared_ptr getTurboModule( + const std::string name, + const JavaTurboModule::InitParams ¶ms) override; + + /** + * Test-only method. Allows user to verify whether a TurboModule can be + * created by instances of this class. + */ + bool canCreateTurboModule(std::string name); +}; + +} // namespace react +} // namespace facebook \ No newline at end of file diff --git a/packages/react-native-editor/android/app/src/main/jni/MainComponentsRegistry.cpp b/packages/react-native-editor/android/app/src/main/jni/MainComponentsRegistry.cpp new file mode 100644 index 0000000000000..c5188f4dc7b12 --- /dev/null +++ b/packages/react-native-editor/android/app/src/main/jni/MainComponentsRegistry.cpp @@ -0,0 +1,61 @@ +#include "MainComponentsRegistry.h" + +#include +#include +#include +#include + +namespace facebook { +namespace react { + +MainComponentsRegistry::MainComponentsRegistry(ComponentFactory *delegate) {} + +std::shared_ptr +MainComponentsRegistry::sharedProviderRegistry() { + auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry(); + + // Custom Fabric Components go here. You can register custom + // components coming from your App or from 3rd party libraries here. + // + // providerRegistry->add(concreteComponentDescriptorProvider< + // AocViewerComponentDescriptor>()); + return providerRegistry; +} + +jni::local_ref +MainComponentsRegistry::initHybrid( + jni::alias_ref, + ComponentFactory *delegate) { + auto instance = makeCxxInstance(delegate); + + auto buildRegistryFunction = + [](EventDispatcher::Weak const &eventDispatcher, + ContextContainer::Shared const &contextContainer) + -> ComponentDescriptorRegistry::Shared { + auto registry = MainComponentsRegistry::sharedProviderRegistry() + ->createComponentDescriptorRegistry( + {eventDispatcher, contextContainer}); + + auto mutableRegistry = + std::const_pointer_cast(registry); + + mutableRegistry->setFallbackComponentDescriptor( + std::make_shared( + ComponentDescriptorParameters{ + eventDispatcher, contextContainer, nullptr})); + + return registry; + }; + + delegate->buildRegistryFunction = buildRegistryFunction; + return instance; +} + +void MainComponentsRegistry::registerNatives() { + registerHybrid({ + makeNativeMethod("initHybrid", MainComponentsRegistry::initHybrid), + }); +} + +} // namespace react +} // namespace facebook \ No newline at end of file diff --git a/packages/react-native-editor/android/app/src/main/jni/MainComponentsRegistry.h b/packages/react-native-editor/android/app/src/main/jni/MainComponentsRegistry.h new file mode 100644 index 0000000000000..1046cfa3f2f73 --- /dev/null +++ b/packages/react-native-editor/android/app/src/main/jni/MainComponentsRegistry.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include +#include + +namespace facebook { +namespace react { + +class MainComponentsRegistry + : public facebook::jni::HybridClass { + public: + // Adapt it to the package you used for your Java class. + constexpr static auto kJavaDescriptor = + "Lcom/gutenberg/newarchitecture/components/MainComponentsRegistry;"; + + static void registerNatives(); + + MainComponentsRegistry(ComponentFactory *delegate); + + private: + static std::shared_ptr + sharedProviderRegistry(); + + static jni::local_ref initHybrid( + jni::alias_ref, + ComponentFactory *delegate); +}; + +} // namespace react +} // namespace facebook \ No newline at end of file diff --git a/packages/react-native-editor/android/app/src/main/jni/OnLoad.cpp b/packages/react-native-editor/android/app/src/main/jni/OnLoad.cpp new file mode 100644 index 0000000000000..ae1ef007d1524 --- /dev/null +++ b/packages/react-native-editor/android/app/src/main/jni/OnLoad.cpp @@ -0,0 +1,11 @@ +#include +#include "MainApplicationTurboModuleManagerDelegate.h" +#include "MainComponentsRegistry.h" + +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { + return facebook::jni::initialize(vm, [] { + facebook::react::MainApplicationTurboModuleManagerDelegate:: + registerNatives(); + facebook::react::MainComponentsRegistry::registerNatives(); + }); +} \ No newline at end of file diff --git a/packages/react-native-editor/android/app/src/main/res/drawable/rn_edit_text_material.xml b/packages/react-native-editor/android/app/src/main/res/drawable/rn_edit_text_material.xml new file mode 100644 index 0000000000000..986188ce0e448 --- /dev/null +++ b/packages/react-native-editor/android/app/src/main/res/drawable/rn_edit_text_material.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/packages/react-native-editor/android/app/src/main/res/values/styles.xml b/packages/react-native-editor/android/app/src/main/res/values/styles.xml index 24bc061368750..7ba83a2ad5a2c 100644 --- a/packages/react-native-editor/android/app/src/main/res/values/styles.xml +++ b/packages/react-native-editor/android/app/src/main/res/values/styles.xml @@ -3,6 +3,7 @@ diff --git a/packages/react-native-editor/android/build.gradle b/packages/react-native-editor/android/build.gradle index 848c57073453a..191d4cbcbfd2a 100644 --- a/packages/react-native-editor/android/build.gradle +++ b/packages/react-native-editor/android/build.gradle @@ -1,13 +1,23 @@ +import org.apache.tools.ant.taskdefs.condition.Os + buildscript { ext { gradlePluginVersion = '7.2.1' kotlinVersion = '1.5.32' - buildToolsVersion = "30.0.2" + buildToolsVersion = "31.0.0" minSdkVersion = 21 - compileSdkVersion = 30 - targetSdkVersion = 30 + compileSdkVersion = 31 + targetSdkVersion = 31 supportLibVersion = '28.0.0' - ndkVersion = "21.4.7075529" + gradleDownloadTask = '5.0.1' + + if (System.properties['os.arch'] == "aarch64") { + // For M1 Users we need to use the NDK 24 which added support for aarch64 + ndkVersion = "24.0.8215888" + } else { + // Otherwise we default to the side-by-side NDK version from AGP. + ndkVersion = "21.4.7075529" + } } repositories { google() @@ -15,13 +25,21 @@ buildscript { } dependencies { classpath "com.android.tools.build:gradle:$gradlePluginVersion" + classpath("com.facebook.react:react-native-gradle-plugin") + classpath("de.undercouch:gradle-download-task:$gradleDownloadTask") classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" } } allprojects { repositories { - mavenCentral() + mavenCentral { + // We don't want to fetch react-native from Maven Central as there are + // older versions over there. + content { + excludeGroup "com.facebook.react" + } + } mavenLocal() maven { url "https://a8c-libs.s3.amazonaws.com/android" @@ -32,7 +50,6 @@ allprojects { } } maven { url "https://a8c-libs.s3.amazonaws.com/android/react-native-mirror" } - maven { url "https://a8c-libs.s3.amazonaws.com/android/hermes-mirror" } maven { url 'https://www.jitpack.io' } google() } diff --git a/packages/react-native-editor/android/gradle.properties b/packages/react-native-editor/android/gradle.properties index 094d0de62d995..8f91fa8476d6a 100644 --- a/packages/react-native-editor/android/gradle.properties +++ b/packages/react-native-editor/android/gradle.properties @@ -25,4 +25,15 @@ android.useAndroidX=true # Automatically convert third-party libraries to use AndroidX android.enableJetifier=false android.useDeprecatedNdk=true -FLIPPER_VERSION=0.99.0 \ No newline at end of file +FLIPPER_VERSION=0.125.0 + +# Use this property to specify which architecture you want to build. +# You can also override it from the CLI using +# ./gradlew -PreactNativeArchitectures=x86_64 +reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 +# Use this property to enable support to the new architecture. +# This will allow you to use TurboModules and the Fabric render in +# your application. You should enable this flag either if you want +# to write custom TurboModules/Fabric components OR use libraries that +# are providing them. +newArchEnabled=false \ No newline at end of file diff --git a/packages/react-native-editor/android/settings.gradle b/packages/react-native-editor/android/settings.gradle index 00081747119a5..fea32ba7734e7 100644 --- a/packages/react-native-editor/android/settings.gradle +++ b/packages/react-native-editor/android/settings.gradle @@ -3,3 +3,10 @@ rootProject.name = 'gutenberg' includeBuild("../../react-native-bridge/android") include ':app' +includeBuild('../../../node_modules/react-native-gradle-plugin') +if (settings.hasProperty("newArchEnabled") && settings.newArchEnabled == "true") { + include(":ReactAndroid") + project(":ReactAndroid").projectDir = file('../../../node_modules/react-native/ReactAndroid') + include(":ReactAndroid:hermes-engine") + project(":ReactAndroid:hermes-engine").projectDir = file('../../../node_modules/react-native/ReactAndroid/hermes-engine') +} \ No newline at end of file diff --git a/packages/react-native-editor/package.json b/packages/react-native-editor/package.json index 1da27953bd55c..ceb94ea21d7ce 100644 --- a/packages/react-native-editor/package.json +++ b/packages/react-native-editor/package.json @@ -89,7 +89,7 @@ "postrn-bundle": "cd ../.. && patch-package --reverse --patch-dir packages/react-native-editor/metro-patch", "prebundle": "npm run i18n-cache:force", "bundle": "npm run bundle:android && npm run bundle:ios", - "bundle:android": "mkdir -p bundle/android && npm run rn-bundle -- --platform android --dev false --entry-file index.js --assets-dest bundle/android --bundle-output bundle/android/App.text.js --sourcemap-output bundle/android/App.text.js.map && ./../../node_modules/hermes-engine/`node -e \"const platform=require('os').platform();console.log(platform === 'darwin' ? 'osx-bin' : (platform === 'linux' ? 'linux64-bin' : (platform === 'win32' ? 'win64-bin' : 'unsupported-os')));\"`/hermesc -emit-binary -O -out bundle/android/App.js bundle/android/App.text.js -output-source-map", + "bundle:android": "mkdir -p bundle/android && npm run rn-bundle -- --platform android --dev false --entry-file index.js --assets-dest bundle/android --bundle-output bundle/android/App.text.js --sourcemap-output bundle/android/App.text.js.map && ./../../node_modules/react-native/sdks/hermesc/`node -e \"const platform=require('os').platform();console.log(platform === 'darwin' ? 'osx-bin' : (platform === 'linux' ? 'linux64-bin' : (platform === 'win32' ? 'win64-bin' : 'unsupported-os')));\"`/hermesc -emit-binary -O -out bundle/android/App.js bundle/android/App.text.js -output-source-map", "bundle:ios": "mkdir -p bundle/ios && npm run rn-bundle -- --platform ios --dev false --entry-file index.js --assets-dest bundle/ios --bundle-output bundle/ios/App.js --sourcemap-output bundle/ios/App.js.map", "i18n-cache": "node i18n-cache/index.js", "i18n-cache:force": "cross-env REFRESH_I18N_CACHE=1 node i18n-cache/index.js",