@wavemaker-ai/wm-reactnative-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +236 -0
- package/assets/CLI-EnvironmentVariable.png +0 -0
- package/assets/EnvironmentVariable.png +0 -0
- package/assets/EnvironmentVariable1.png +0 -0
- package/files/ui-build.js +331 -0
- package/index.js +381 -0
- package/package.json +39 -0
- package/src/android.js +479 -0
- package/src/command.js +552 -0
- package/src/config.js +11 -0
- package/src/custom-logger/progress-bar.js +97 -0
- package/src/custom-logger/steps.js +117 -0
- package/src/custom-logger/task-logger.js +147 -0
- package/src/exec.js +73 -0
- package/src/expo-launcher.js +596 -0
- package/src/ios.js +517 -0
- package/src/logger.js +104 -0
- package/src/mobileprovision-parse/index.js +72 -0
- package/src/project-sync.service.js +390 -0
- package/src/requirements.js +250 -0
- package/src/utils.js +100 -0
- package/src/web-preview-launcher.js +548 -0
- package/src/zip.js +19 -0
- package/templates/embed/android/ReactNativeAppFragment.java +78 -0
- package/templates/embed/android/SplashScreenReactActivityLifecycleListener.kt +41 -0
- package/templates/embed/android/fragment_react_native_app.xml +14 -0
- package/templates/embed/ios/ReactNativeView.h +12 -0
- package/templates/embed/ios/ReactNativeView.m +59 -0
- package/templates/embed/ios/ReactNativeView.swift +53 -0
- package/templates/expo-camera-patch/useWebQRScanner.js +100 -0
- package/templates/ios-build-patch/podFIlePostInstall.js +72 -0
- package/templates/package/packageLock.json +14334 -0
- package/templates/wm-rn-runtime/App.js +479 -0
- package/templates/wm-rn-runtime/App.navigator.js +109 -0
- package/test.js +0 -0
- package/tools-site/index.html.template +17 -0
- package/tools-site/page_background.svg +99 -0
- package/tools-site/qrcode.js +614 -0
- package/tools-site/styles.css +39 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
package com.wavemaker.reactnative;
|
|
2
|
+
|
|
3
|
+
import android.os.Bundle;
|
|
4
|
+
|
|
5
|
+
import androidx.fragment.app.Fragment;
|
|
6
|
+
|
|
7
|
+
import android.view.LayoutInflater;
|
|
8
|
+
import android.view.View;
|
|
9
|
+
import android.view.ViewGroup;
|
|
10
|
+
|
|
11
|
+
import com.facebook.react.ReactFragment;
|
|
12
|
+
import ${packageName}.R;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A simple {@link Fragment} subclass.
|
|
16
|
+
* Use the {@link ReactNativeAppFragment#newInstance} factory method to
|
|
17
|
+
* create an instance of this fragment.
|
|
18
|
+
*/
|
|
19
|
+
public class ReactNativeAppFragment extends Fragment {
|
|
20
|
+
|
|
21
|
+
// TODO: Rename parameter arguments, choose names that match
|
|
22
|
+
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
|
|
23
|
+
private static final String PAGE_NAME = "pageName";
|
|
24
|
+
|
|
25
|
+
// TODO: Rename and change types of parameters
|
|
26
|
+
private String pageName;
|
|
27
|
+
|
|
28
|
+
public ReactNativeAppFragment() {
|
|
29
|
+
// Required empty public constructor
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Use this factory method to create a new instance of
|
|
34
|
+
* this fragment using the provided parameters.
|
|
35
|
+
*
|
|
36
|
+
* @param pageName Parameter 2.
|
|
37
|
+
* @return A new instance of fragment ReactNativeAppFragment.
|
|
38
|
+
*/
|
|
39
|
+
// TODO: Rename and change types and number of parameters
|
|
40
|
+
public static ReactNativeAppFragment newInstance(String pageName) {
|
|
41
|
+
ReactNativeAppFragment fragment = new ReactNativeAppFragment();
|
|
42
|
+
Bundle args = new Bundle();
|
|
43
|
+
args.putString(PAGE_NAME, pageName);
|
|
44
|
+
fragment.setArguments(args);
|
|
45
|
+
return fragment;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@Override
|
|
49
|
+
public void onCreate(Bundle savedInstanceState) {
|
|
50
|
+
super.onCreate(null);
|
|
51
|
+
if (getArguments() != null) {
|
|
52
|
+
pageName = getArguments().getString(PAGE_NAME);
|
|
53
|
+
}
|
|
54
|
+
Fragment reactNativeFragment = new ReactFragment.Builder()
|
|
55
|
+
.setComponentName("main")
|
|
56
|
+
.setLaunchOptions(getLaunchOptions(pageName))
|
|
57
|
+
.setFabricEnabled(false)
|
|
58
|
+
.build();
|
|
59
|
+
|
|
60
|
+
this.getChildFragmentManager().beginTransaction()
|
|
61
|
+
.add(R.id.reactNativeFragment, reactNativeFragment)
|
|
62
|
+
.commit();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@Override
|
|
66
|
+
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
67
|
+
Bundle savedInstanceState) {
|
|
68
|
+
setHasOptionsMenu(true);
|
|
69
|
+
// Inflate the layout for this fragment
|
|
70
|
+
return inflater.inflate(R.layout.fragment_react_native_app, container, false);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private Bundle getLaunchOptions(String pageName) {
|
|
74
|
+
Bundle initialProperties = new Bundle();
|
|
75
|
+
initialProperties.putString("pageName", pageName);
|
|
76
|
+
return initialProperties;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
package expo.modules.splashscreen
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.os.Bundle
|
|
6
|
+
import android.os.Handler
|
|
7
|
+
import com.facebook.react.ReactRootView
|
|
8
|
+
import expo.modules.core.interfaces.ReactActivityLifecycleListener
|
|
9
|
+
import expo.modules.splashscreen.singletons.SplashScreen
|
|
10
|
+
|
|
11
|
+
// this needs to stay for versioning to work
|
|
12
|
+
/* ktlint-disable no-unused-imports */
|
|
13
|
+
import expo.modules.splashscreen.SplashScreenImageResizeMode
|
|
14
|
+
// EXPO_VERSIONING_NEEDS_EXPOVIEW_R
|
|
15
|
+
/* ktlint-enable no-unused-imports */
|
|
16
|
+
|
|
17
|
+
class SplashScreenReactActivityLifecycleListener(activityContext: Context) : ReactActivityLifecycleListener {
|
|
18
|
+
override fun onCreate(activity: Activity, savedInstanceState: Bundle?) {
|
|
19
|
+
// To support backward compatible or SplashScreenImageResizeMode customization
|
|
20
|
+
// that calling `SplashScreen.show()` in MainActivity,
|
|
21
|
+
// we postpone the in-module call to the end of main loop.
|
|
22
|
+
// If MainActivity.onCreate has `SplashScreen.show()`, it will override the call here.
|
|
23
|
+
Handler(activity.mainLooper).post {
|
|
24
|
+
/*SplashScreen.show(
|
|
25
|
+
activity,
|
|
26
|
+
getResizeMode(activity),
|
|
27
|
+
ReactRootView::class.java,
|
|
28
|
+
getStatusBarTranslucent(activity)
|
|
29
|
+
)*/
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private fun getResizeMode(context: Context): SplashScreenImageResizeMode =
|
|
34
|
+
SplashScreenImageResizeMode.fromString(
|
|
35
|
+
context.getString(R.string.expo_splash_screen_resize_mode).toLowerCase()
|
|
36
|
+
)
|
|
37
|
+
?: SplashScreenImageResizeMode.CONTAIN
|
|
38
|
+
|
|
39
|
+
private fun getStatusBarTranslucent(context: Context): Boolean =
|
|
40
|
+
context.getString(R.string.expo_splash_screen_status_bar_translucent).toBoolean()
|
|
41
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
+
xmlns:tools="http://schemas.android.com/tools"
|
|
4
|
+
android:layout_width="match_parent"
|
|
5
|
+
android:layout_height="match_parent"
|
|
6
|
+
tools:context=".ui.ReactNativeAppFragment">
|
|
7
|
+
|
|
8
|
+
<!-- TODO: Update blank fragment layout -->
|
|
9
|
+
<FrameLayout
|
|
10
|
+
android:id="@+id/reactNativeFragment"
|
|
11
|
+
android:layout_width="match_parent"
|
|
12
|
+
android:layout_height="match_parent" />
|
|
13
|
+
|
|
14
|
+
</FrameLayout>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
#import <React/RCTBridgeDelegate.h>
|
|
3
|
+
#import <UIKit/UIKit.h>
|
|
4
|
+
|
|
5
|
+
#import <Expo/Expo.h>
|
|
6
|
+
|
|
7
|
+
@interface ReactNativeView : EXAppDelegateWrapper <RCTBridgeDelegate>
|
|
8
|
+
@property (nonatomic, strong) UIView *view;
|
|
9
|
+
|
|
10
|
+
- (ReactNativeView*) initWithPageName:(NSString *)aPageName;
|
|
11
|
+
|
|
12
|
+
@end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#import "ReactNativeView.h"
|
|
2
|
+
|
|
3
|
+
#import <React/RCTBridge.h>
|
|
4
|
+
#import <React/RCTBundleURLProvider.h>
|
|
5
|
+
#import <React/RCTRootView.h>
|
|
6
|
+
#import <React/RCTLinkingManager.h>
|
|
7
|
+
#import <React/RCTConvert.h>
|
|
8
|
+
|
|
9
|
+
#import <RCTAppSetupUtils.h>
|
|
10
|
+
|
|
11
|
+
#if RCT_NEW_ARCH_ENABLED
|
|
12
|
+
#import <React/CoreModulesPlugins.h>
|
|
13
|
+
#import <React/RCTCxxBridgeDelegate.h>
|
|
14
|
+
#import <React/RCTFabricSurfaceHostingProxyRootView.h>
|
|
15
|
+
#import <React/RCTSurfacePresenter.h>
|
|
16
|
+
#import <React/RCTSurfacePresenterBridgeAdapter.h>
|
|
17
|
+
#import <ReactCommon/RCTTurboModuleManager.h>
|
|
18
|
+
|
|
19
|
+
#import <react/config/ReactNativeConfig.h>
|
|
20
|
+
|
|
21
|
+
#endif
|
|
22
|
+
|
|
23
|
+
@implementation ReactNativeView
|
|
24
|
+
|
|
25
|
+
static RCTBridge *bridge;
|
|
26
|
+
|
|
27
|
+
UIView *_view;
|
|
28
|
+
|
|
29
|
+
NSString* pageName = nil;
|
|
30
|
+
|
|
31
|
+
- (ReactNativeView*) initWithPageName:(NSString *)aPageName {
|
|
32
|
+
if (self = [super init]) {
|
|
33
|
+
pageName = aPageName;
|
|
34
|
+
}
|
|
35
|
+
if (!bridge) {
|
|
36
|
+
bridge = [self.reactDelegate createBridgeWithDelegate:self launchOptions: nil];
|
|
37
|
+
}
|
|
38
|
+
_view = [self.reactDelegate createRootViewWithBridge:bridge moduleName:@"main" initialProperties:@{@"pageName": pageName}];
|
|
39
|
+
return self;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
- (UIView *)view {
|
|
43
|
+
return _view;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge
|
|
47
|
+
{
|
|
48
|
+
// If you'd like to export some custom RCTBridgeModules, add them here!
|
|
49
|
+
return @[];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
|
|
53
|
+
{
|
|
54
|
+
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import SwiftUI
|
|
2
|
+
import UIKit
|
|
3
|
+
import EmbedCommModule
|
|
4
|
+
|
|
5
|
+
struct ReactNativeSwiftView: UIViewRepresentable {
|
|
6
|
+
var pageName = ""
|
|
7
|
+
|
|
8
|
+
init(pageName: String) {
|
|
9
|
+
self.pageName = pageName;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
typealias UIViewType = UIView
|
|
13
|
+
|
|
14
|
+
typealias UIViewControllerType = UIViewController
|
|
15
|
+
|
|
16
|
+
func makeUIView(context: Context) -> UIView {
|
|
17
|
+
return ReactNativeView(pageName: self.pageName).view;
|
|
18
|
+
}
|
|
19
|
+
func updateUIView(_ uiView: UIView, context: Context) {
|
|
20
|
+
//
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@available(iOS 13.0, *)
|
|
25
|
+
struct ReactNativePageView: View {
|
|
26
|
+
var pageName = ""
|
|
27
|
+
|
|
28
|
+
@available(iOS 13.0, *)
|
|
29
|
+
var body: some View {
|
|
30
|
+
ReactNativeSwiftView(pageName: self.pageName)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@available(iOS 13.0, *)
|
|
35
|
+
class ReactNativeHostingController: UIHostingController<ReactNativePageView> {
|
|
36
|
+
required init?(coder aDecoder: NSCoder) {
|
|
37
|
+
super.init(coder: aDecoder, rootView: ReactNativePageView(pageName: ""))
|
|
38
|
+
CommunicationService.INSTANCE.process(
|
|
39
|
+
messageType: "close",
|
|
40
|
+
processor: {(message: NSDictionary?, promise: Promise?) in
|
|
41
|
+
DispatchQueue.main.async(execute: {
|
|
42
|
+
self.navigationController?.popViewController(animated: true);
|
|
43
|
+
self.dismiss(animated: true);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
override func viewWillDisappear(_ animated: Bool) {
|
|
49
|
+
super.viewDidDisappear(animated);
|
|
50
|
+
CommunicationService.INSTANCE.removeProcessor(messageType: "close");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// import { useWorker } from '@koale/useworker';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { captureImageData } from './WebCameraUtils';
|
|
4
|
+
const qrWorkerMethod = ({ data, width, height }) => {
|
|
5
|
+
// eslint-disable-next-line no-undef
|
|
6
|
+
const decoded = self.jsQR(data, width, height, {
|
|
7
|
+
inversionAttempts: 'attemptBoth',
|
|
8
|
+
});
|
|
9
|
+
let parsed;
|
|
10
|
+
try {
|
|
11
|
+
parsed = JSON.parse(decoded);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
parsed = decoded;
|
|
15
|
+
}
|
|
16
|
+
if (parsed?.data) {
|
|
17
|
+
const nativeEvent = {
|
|
18
|
+
type: 'qr',
|
|
19
|
+
data: parsed.data,
|
|
20
|
+
cornerPoints: [],
|
|
21
|
+
bounds: { origin: { x: 0, y: 0 }, size: { width: 0, height: 0 } },
|
|
22
|
+
};
|
|
23
|
+
if (parsed.location) {
|
|
24
|
+
nativeEvent.cornerPoints = [
|
|
25
|
+
parsed.location.topLeftCorner,
|
|
26
|
+
parsed.location.bottomLeftCorner,
|
|
27
|
+
parsed.location.topRightCorner,
|
|
28
|
+
parsed.location.bottomRightCorner,
|
|
29
|
+
];
|
|
30
|
+
}
|
|
31
|
+
return nativeEvent;
|
|
32
|
+
}
|
|
33
|
+
return parsed;
|
|
34
|
+
};
|
|
35
|
+
function useRemoteJsQR() {
|
|
36
|
+
/*return useWorker(qrWorkerMethod, {
|
|
37
|
+
remoteDependencies: ['https://cdn.jsdelivr.net/npm/jsqr@1.2.0/dist/jsQR.min.js'],
|
|
38
|
+
autoTerminate: false,
|
|
39
|
+
});*/
|
|
40
|
+
}
|
|
41
|
+
export function useWebQRScanner(video, { isEnabled, captureOptions, interval, onScanned, onError, }) {
|
|
42
|
+
const isRunning = React.useRef(false);
|
|
43
|
+
const timeout = React.useRef(undefined);
|
|
44
|
+
const [decode, clearWorker] = useRemoteJsQR();
|
|
45
|
+
async function scanAsync() {
|
|
46
|
+
// If interval is 0 then only scan once.
|
|
47
|
+
if (!isRunning.current || !onScanned) {
|
|
48
|
+
stop();
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const data = captureImageData(video.current, captureOptions);
|
|
53
|
+
if (data) {
|
|
54
|
+
const nativeEvent = await decode(data);
|
|
55
|
+
if (nativeEvent?.data) {
|
|
56
|
+
onScanned({
|
|
57
|
+
nativeEvent,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
if (onError) {
|
|
64
|
+
onError({ nativeEvent: error });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
// If interval is 0 then only scan once.
|
|
69
|
+
if (interval === 0) {
|
|
70
|
+
stop();
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const intervalToUse = !interval || interval < 0 ? 16 : interval;
|
|
74
|
+
// @ts-ignore: Type 'Timeout' is not assignable to type 'number'
|
|
75
|
+
timeout.current = setTimeout(() => {
|
|
76
|
+
scanAsync();
|
|
77
|
+
}, intervalToUse);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function stop() {
|
|
81
|
+
isRunning.current = false;
|
|
82
|
+
clearTimeout(timeout.current);
|
|
83
|
+
}
|
|
84
|
+
React.useEffect(() => {
|
|
85
|
+
if (isEnabled) {
|
|
86
|
+
isRunning.current = true;
|
|
87
|
+
scanAsync();
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
stop();
|
|
91
|
+
}
|
|
92
|
+
}, [isEnabled]);
|
|
93
|
+
React.useEffect(() => {
|
|
94
|
+
return () => {
|
|
95
|
+
stop();
|
|
96
|
+
clearWorker.kill();
|
|
97
|
+
};
|
|
98
|
+
}, []);
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=useWebQRScanner.js.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const newPostInstallBlock =
|
|
2
|
+
`post_install do |installer|
|
|
3
|
+
react_native_post_install(
|
|
4
|
+
installer,
|
|
5
|
+
config[:reactNativePath],
|
|
6
|
+
:mac_catalyst_enabled => false
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
# Set provisioning profile to "None" for all pod targets
|
|
10
|
+
installer.pods_project.targets.each do |target|
|
|
11
|
+
target.build_configurations.each do |config|
|
|
12
|
+
config.build_settings['PROVISIONING_PROFILE'] = 'None'
|
|
13
|
+
config.build_settings['CODE_SIGN_IDENTITY'] = ''
|
|
14
|
+
config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Disable code signing for resource bundle targets
|
|
19
|
+
installer.target_installation_results.pod_target_installation_results
|
|
20
|
+
.each do |pod_name, target_installation_result|
|
|
21
|
+
target_installation_result.resource_bundle_targets.each do |resource_bundle_target|
|
|
22
|
+
resource_bundle_target.build_configurations.each do |config|
|
|
23
|
+
config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
|
|
24
|
+
config.build_settings['PROVISIONING_PROFILE'] = 'None'
|
|
25
|
+
config.build_settings['CODE_SIGN_IDENTITY'] = ''
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Fix for React Native Firebase when using static frameworks
|
|
31
|
+
# ROOT CAUSE: Static frameworks with modules enabled create strict module boundaries.
|
|
32
|
+
# When RNFBMessaging imports <RNFBApp/...>, the module system expects ALL types to be
|
|
33
|
+
# visible through RNFBApp's module exports. But RCTPromiseRejectBlock is in React-Core,
|
|
34
|
+
# and RNFBApp doesn't re-export it. The module system blocks access even if headers exist.
|
|
35
|
+
#
|
|
36
|
+
# SOLUTION: Disable modules for RNFB targets entirely. This makes the compiler use
|
|
37
|
+
# traditional #import header inclusion instead of strict module boundaries.
|
|
38
|
+
installer.pods_project.targets.each do |target|
|
|
39
|
+
if target.name.start_with?('RNFB')
|
|
40
|
+
target.build_configurations.each do |config|
|
|
41
|
+
# DISABLE modules - this is the key fix
|
|
42
|
+
# Without modules, the compiler uses traditional header inclusion and can find
|
|
43
|
+
# React-Core types through the header search paths
|
|
44
|
+
config.build_settings['CLANG_ENABLE_MODULES'] = 'NO'
|
|
45
|
+
|
|
46
|
+
# Ensure header maps are enabled so headers can be found
|
|
47
|
+
config.build_settings['USE_HEADERMAP'] = 'YES'
|
|
48
|
+
|
|
49
|
+
# Add React-Core headers to search paths so they can be found via #import
|
|
50
|
+
header_search_paths = config.build_settings['HEADER_SEARCH_PATHS'] || '$(inherited)'
|
|
51
|
+
react_core_path = File.join(installer.sandbox.root, 'Headers', 'Public', 'React-Core')
|
|
52
|
+
react_core_path_quoted = '"' + react_core_path + '"'
|
|
53
|
+
if header_search_paths.is_a?(Array)
|
|
54
|
+
unless header_search_paths.any? { |path| path.include?('React-Core') }
|
|
55
|
+
header_search_paths << react_core_path_quoted
|
|
56
|
+
end
|
|
57
|
+
elsif header_search_paths.is_a?(String)
|
|
58
|
+
unless header_search_paths.include?('React-Core')
|
|
59
|
+
config.build_settings['HEADER_SEARCH_PATHS'] = [header_search_paths, react_core_path_quoted]
|
|
60
|
+
end
|
|
61
|
+
else
|
|
62
|
+
config.build_settings['HEADER_SEARCH_PATHS'] = ['$(inherited)', react_core_path_quoted]
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
end`;
|
|
69
|
+
|
|
70
|
+
module.exports = {
|
|
71
|
+
newPostInstallBlock
|
|
72
|
+
}
|