Skip to content

Commit

Permalink
feat: add new arch (zoontek#748)
Browse files Browse the repository at this point in the history
* feat: add FabricExample app

* feat: add code from example

* feat: add codegen spec and entry point for RN

* feat: add spec and change methods files

* feat: add Android impl

* feat: add iOS impl

* feat: enable new arch without permissions type working

* fix: make both platforms work on both archs

* chore: rename back to rnpermissions

* chore: remove FabricExample from PR

* fix: ts

* fix: lazily get constants

* fix package.json

---------

Co-authored-by: Mathieu Acthernoene <zoontek@gmail.com>
  • Loading branch information
WoLewicki and zoontek authored Mar 14, 2023
1 parent 863d50d commit 3701d9d
Show file tree
Hide file tree
Showing 36 changed files with 567 additions and 150 deletions.
29 changes: 27 additions & 2 deletions RNPermissions.podspec
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
require 'json'
package = JSON.parse(File.read('./package.json'))

fabric_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == '1'

Pod::Spec.new do |s|
s.name = "RNPermissions"
s.dependency "React-Core"

s.version = package["version"]
s.license = package["license"]
Expand All @@ -16,5 +17,29 @@ Pod::Spec.new do |s|
s.requires_arc = true

s.source = { :git => package["repository"]["url"], :tag => s.version }
s.source_files = "ios/*.{h,m,mm}"
s.source_files = "ios/*.{h,m,mm}"

if fabric_enabled
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'

s.pod_target_xcconfig = {
'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/boost" "$(PODS_ROOT)/boost-for-react-native" "$(PODS_ROOT)/RCT-Folly"',
'CLANG_CXX_LANGUAGE_STANDARD' => 'c++17',
}
s.platforms = { ios: '11.0', tvos: '11.0' }
s.compiler_flags = folly_compiler_flags + ' -DRCT_NEW_ARCH_ENABLED'

s.dependency "React"
s.dependency "React-RCTFabric" # This is for fabric component
s.dependency "React-Codegen"
s.dependency "RCT-Folly"
s.dependency "RCTRequired"
s.dependency "RCTTypeSafety"
s.dependency "ReactCommon/turbomodule/core"
else
s.platforms = { :ios => "9.0", :tvos => "9.0" }

s.dependency "React-Core"
end

end
67 changes: 65 additions & 2 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,57 @@ buildscript {

apply plugin: "com.android.library"

def resolveReactNativeDirectory() {
// monorepo workaround
// react-native can be hoisted or in project's own node_modules
def reactNativeFromProjectNodeModules = file("${rootProject.projectDir}/../node_modules/react-native")
if (reactNativeFromProjectNodeModules.exists()) {
return reactNativeFromProjectNodeModules
}

def reactNativeFromNodeModulesWithLibrary = file("${projectDir}/../../react-native")
if (reactNativeFromNodeModulesWithLibrary.exists()) {
return reactNativeFromNodeModulesWithLibrary
}

throw new Exception(
"[react-native-clipboard] Unable to resolve react-native location in " +
"node_modules. You should add project extension property (in app/build.gradle) " +
"`REACT_NATIVE_NODE_MODULES_DIR` with path to react-native."
)
}

def REACT_NATIVE_DIR = resolveReactNativeDirectory()

def reactProperties = new Properties()
file("$REACT_NATIVE_DIR/ReactAndroid/gradle.properties").withInputStream { reactProperties.load(it) }

def REACT_NATIVE_VERSION = reactProperties.getProperty("VERSION_NAME")
def REACT_NATIVE_MINOR_VERSION = REACT_NATIVE_VERSION.startsWith("0.0.0-") ? 1000 : REACT_NATIVE_VERSION.split("\\.")[1].toInteger()

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

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

android {

// Used to override the NDK path/version on internal CI or by allowing
// users to customize the NDK path/version from their root project (e.g. for M1 support)
if (rootProject.hasProperty("ndkPath")) {
ndkPath rootProject.ext.ndkPath
}
if (rootProject.hasProperty("ndkVersion")) {
ndkVersion rootProject.ext.ndkVersion
}

compileSdkVersion safeExtGet("compileSdkVersion", 33)
buildToolsVersion safeExtGet("buildToolsVersion", "33.0.0")
defaultConfig {
Expand All @@ -29,6 +79,15 @@ android {
lintOptions {
abortOnError false
}


sourceSets.main {
java {
if (!isNewArchitectureEnabled()) {
srcDirs += 'src/paper/java'
}
}
}
}

repositories {
Expand All @@ -46,6 +105,10 @@ repositories {
}

dependencies {
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+" // From node_modules
if (isNewArchitectureEnabled() && REACT_NATIVE_MINOR_VERSION < 71) {
implementation project(":ReactAndroid")
} else {
//noinspection GradleDynamicVersion
implementation 'com.facebook.react:react-native:+'
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.WritableMap;
Expand All @@ -28,12 +27,14 @@
import com.facebook.react.modules.core.PermissionListener;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

@ReactModule(name = RNPermissionsModule.MODULE_NAME)
public class RNPermissionsModule extends ReactContextBaseJavaModule implements PermissionListener {
@ReactModule(name = RNPermissionsModule.NAME)
public class RNPermissionsModule extends NativePermissionsModuleSpec implements PermissionListener {

private static final String ERROR_INVALID_ACTIVITY = "E_INVALID_ACTIVITY";
public static final String MODULE_NAME = "RNPermissions";
public static final String NAME = "RNPermissionsModule";

private final SparseArray<Callback> mCallbacks;
private int mRequestCode = 0;
Expand All @@ -49,7 +50,7 @@ public RNPermissionsModule(ReactApplicationContext reactContext) {

@Override
public String getName() {
return MODULE_NAME;
return NAME;
}

private @Nullable String getFieldName(final String permission) {
Expand Down Expand Up @@ -373,6 +374,41 @@ public void invoke(Object... args) {
}
}

@Override
protected Map<String, Object> getTypedExportedConstants() {
return new HashMap<>();
}

@Override
public void check(String permission, Promise promise) {
promise.reject("Permissions:check", "check is not supported on Android");
}

@Override
public void checkLocationAccuracy(Promise promise) {
promise.reject("Permissions:checkLocationAccuracy", "checkLocationAccuracy is not supported on Android");
}

@Override
public void request(String permission, Promise promise) {
promise.reject("Permissions:request", "request is not supported on Android");
}

@Override
public void requestLocationAccuracy(String purposeKey, Promise promise) {
promise.reject("Permissions:requestLocationAccuracy", "requestLocationAccuracy is not supported on Android");
}

@Override
public void requestNotifications(ReadableArray options, Promise promise) {
promise.reject("Permissions:requestNotifications", "requestNotifications is not supported on Android");
}

@Override
public void openLimitedPhotoLibraryPicker(Promise promise) {
promise.reject("Permissions:openLimitedPhotoLibraryPicker", "openLimitedPhotoLibraryPicker is not supported on Android");
}

@Override
public boolean onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
mCallbacks.get(requestCode).invoke(grantResults, getPermissionAwareActivity());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,102 @@
package com.zoontek.rnpermissions;

import com.facebook.react.ReactPackage;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.facebook.react.TurboReactPackage;
import com.facebook.react.ViewManagerOnDemandReactPackage;
import com.facebook.react.bridge.ModuleSpec;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.module.annotations.ReactModuleList;
import com.facebook.react.module.model.ReactModuleInfo;
import com.facebook.react.module.model.ReactModuleInfoProvider;
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
import com.facebook.react.uimanager.ViewManager;

import java.util.Collections;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

@ReactModuleList(
nativeModules = {
RNPermissionsModule.class,
})
public class RNPermissionsPackage extends TurboReactPackage implements ViewManagerOnDemandReactPackage {

/** {@inheritDoc} */
@Override
public List<String> getViewManagerNames(ReactApplicationContext reactContext) {
return null;
}

@Override
protected List<ModuleSpec> getViewManagers(ReactApplicationContext reactContext) {
return null;
}

public class RNPermissionsPackage implements ReactPackage {
/** {@inheritDoc} */
@Override
public @Nullable
ViewManager createViewManager(
ReactApplicationContext reactContext, String viewManagerName) {
return null;
}

@Override
public NativeModule getModule(String name, @Nonnull ReactApplicationContext reactContext) {
switch (name) {
case RNPermissionsModule.NAME:
return new RNPermissionsModule(reactContext);
default:
return null;
}
}

@Override
public ReactModuleInfoProvider getReactModuleInfoProvider() {
try {
Class<?> reactModuleInfoProviderClass =
Class.forName("com.zoontek.rnpermissions.RNPermissionsPackage$$ReactModuleInfoProvider");
return (ReactModuleInfoProvider) reactModuleInfoProviderClass.newInstance();
} catch (ClassNotFoundException e) {
// ReactModuleSpecProcessor does not run at build-time. Create this ReactModuleInfoProvider by
// hand.
return new ReactModuleInfoProvider() {
@Override
public Map<String, ReactModuleInfo> getReactModuleInfos() {
final Map<String, ReactModuleInfo> reactModuleInfoMap = new HashMap<>();

Class<? extends NativeModule>[] moduleList =
new Class[] {
RNPermissionsModule.class,
};

for (Class<? extends NativeModule> moduleClass : moduleList) {
ReactModule reactModule = moduleClass.getAnnotation(ReactModule.class);

reactModuleInfoMap.put(
reactModule.name(),
new ReactModuleInfo(
reactModule.name(),
moduleClass.getName(),
reactModule.canOverrideExistingModule(),
reactModule.needsEagerInit(),
reactModule.hasConstants(),
reactModule.isCxxModule(),
TurboModule.class.isAssignableFrom(moduleClass)));
}

return reactModuleInfoMap;
}
};
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(
"No ReactModuleInfoProvider for com.zoontek.rnpermissions.RNPermissionsPackage$$ReactModuleInfoProvider", e);
}
}

@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
Expand Down
Loading

0 comments on commit 3701d9d

Please sign in to comment.