@callstack/react-native-brownfield 3.0.0-rc.1 → 3.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/CHANGELOG.md +11 -0
- package/ReactBrownfield.podspec +4 -0
- package/ios/BrownfieldBundlePathResolver.swift +21 -0
- package/ios/ExpoHostRuntime.swift +140 -0
- package/ios/JSBundleLoadObserver.swift +38 -0
- package/ios/Notification+Brownfield.swift +12 -0
- package/ios/ReactNativeBrownfield.swift +78 -112
- package/ios/ReactNativeHostRuntime.swift +138 -0
- package/lib/commonjs/expo-config-plugin/android/constants.js +1 -1
- package/lib/commonjs/expo-config-plugin/ios/podfileHelpers.js +3 -26
- package/lib/commonjs/expo-config-plugin/ios/podfileHelpers.js.map +1 -1
- package/lib/commonjs/expo-config-plugin/ios/withBrownfieldIos.js +1 -1
- package/lib/commonjs/expo-config-plugin/ios/withBrownfieldIos.js.map +1 -1
- package/lib/commonjs/expo-config-plugin/ios/withIosFrameworkFiles.js +1 -1
- package/lib/commonjs/expo-config-plugin/ios/withIosFrameworkFiles.js.map +1 -1
- package/lib/commonjs/expo-config-plugin/ios/xcodeHelpers.js +1 -1
- package/lib/commonjs/expo-config-plugin/ios/xcodeHelpers.js.map +1 -1
- package/lib/commonjs/expo-config-plugin/template/ios/FrameworkInterface.swift +8 -3
- package/lib/commonjs/expo-config-plugin/template/ios/PodfileTargetBlock.rb +1 -0
- package/lib/commonjs/expo-config-plugin/template/ios/patchExpoPre55.sh +1 -1
- package/lib/module/expo-config-plugin/android/constants.js +1 -1
- package/lib/module/expo-config-plugin/ios/podfileHelpers.js +3 -26
- package/lib/module/expo-config-plugin/ios/podfileHelpers.js.map +1 -1
- package/lib/module/expo-config-plugin/ios/withBrownfieldIos.js +1 -1
- package/lib/module/expo-config-plugin/ios/withBrownfieldIos.js.map +1 -1
- package/lib/module/expo-config-plugin/ios/withIosFrameworkFiles.js +1 -1
- package/lib/module/expo-config-plugin/ios/withIosFrameworkFiles.js.map +1 -1
- package/lib/module/expo-config-plugin/ios/xcodeHelpers.js +1 -1
- package/lib/module/expo-config-plugin/ios/xcodeHelpers.js.map +1 -1
- package/lib/module/expo-config-plugin/template/ios/FrameworkInterface.swift +8 -3
- package/lib/module/expo-config-plugin/template/ios/PodfileTargetBlock.rb +1 -0
- package/lib/module/expo-config-plugin/template/ios/patchExpoPre55.sh +1 -1
- package/lib/typescript/commonjs/src/expo-config-plugin/android/constants.d.ts +2 -2
- package/lib/typescript/commonjs/src/expo-config-plugin/ios/podfileHelpers.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/expo-config-plugin/ios/withBrownfieldIos.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/expo-config-plugin/ios/withIosFrameworkFiles.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/expo-config-plugin/ios/xcodeHelpers.d.ts +2 -2
- package/lib/typescript/commonjs/src/expo-config-plugin/ios/xcodeHelpers.d.ts.map +1 -1
- package/lib/typescript/module/src/expo-config-plugin/android/constants.d.ts +2 -2
- package/lib/typescript/module/src/expo-config-plugin/ios/podfileHelpers.d.ts.map +1 -1
- package/lib/typescript/module/src/expo-config-plugin/ios/withBrownfieldIos.d.ts.map +1 -1
- package/lib/typescript/module/src/expo-config-plugin/ios/withIosFrameworkFiles.d.ts.map +1 -1
- package/lib/typescript/module/src/expo-config-plugin/ios/xcodeHelpers.d.ts +2 -2
- package/lib/typescript/module/src/expo-config-plugin/ios/xcodeHelpers.d.ts.map +1 -1
- package/package.json +6 -5
- package/scripts/react_native_brownfield_post_integrate.rb +22 -0
- package/src/expo-config-plugin/android/constants.ts +1 -1
- package/src/expo-config-plugin/ios/podfileHelpers.ts +30 -27
- package/src/expo-config-plugin/ios/withBrownfieldIos.ts +1 -2
- package/src/expo-config-plugin/ios/withIosFrameworkFiles.ts +0 -4
- package/src/expo-config-plugin/ios/xcodeHelpers.ts +75 -1
- package/src/expo-config-plugin/template/ios/FrameworkInterface.swift +8 -3
- package/src/expo-config-plugin/template/ios/PodfileTargetBlock.rb +1 -0
- package/src/expo-config-plugin/template/ios/patchExpoPre55.sh +1 -1
- package/lib/commonjs/expo-config-plugin/template/ios/ReactNativeHostManager.swift +0 -63
- package/lib/module/expo-config-plugin/template/ios/ReactNativeHostManager.swift +0 -63
- package/src/expo-config-plugin/template/ios/ReactNativeHostManager.swift +0 -63
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @callstack/react-native-brownfield
|
|
2
2
|
|
|
3
|
+
## 3.0.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#255](https://github.com/callstack/react-native-brownfield/pull/255) [`48358b2`](https://github.com/callstack/react-native-brownfield/commit/48358b2dcce578aa5052e66cc3454524da8c7992) Thanks [@artus9033](https://github.com/artus9033)! - chore: release stable v3
|
|
8
|
+
|
|
9
|
+
- [#239](https://github.com/callstack/react-native-brownfield/pull/239) [`828bda3`](https://github.com/callstack/react-native-brownfield/commit/828bda32f39153085f5053becc7e9de16d284be5) Thanks [@hurali97](https://github.com/hurali97)! - fix: autodetect iOS app target name for Expo pre-55 patch script phase
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [[`48358b2`](https://github.com/callstack/react-native-brownfield/commit/48358b2dcce578aa5052e66cc3454524da8c7992)]:
|
|
12
|
+
- @callstack/brownfield-cli@3.0.0
|
|
13
|
+
|
|
3
14
|
## 2.2.0
|
|
4
15
|
|
|
5
16
|
### Minor Changes
|
package/ReactBrownfield.podspec
CHANGED
|
@@ -22,6 +22,10 @@ Pod::Spec.new do |spec|
|
|
|
22
22
|
|
|
23
23
|
spec.dependency 'ReactAppDependencyProvider'
|
|
24
24
|
add_dependency(spec, "React-RCTAppDelegate")
|
|
25
|
+
|
|
26
|
+
if ENV['REACT_NATIVE_BROWNFIELD_USE_EXPO_HOST'] == '1'
|
|
27
|
+
spec.dependency 'Expo'
|
|
28
|
+
end
|
|
25
29
|
|
|
26
30
|
install_modules_dependencies(spec)
|
|
27
31
|
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
enum BrownfieldBundlePathResolver {
|
|
4
|
+
enum Error: Swift.Error {
|
|
5
|
+
case invalidBundlePath(String)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
static func resourceComponents(from bundlePath: String) throws -> (
|
|
9
|
+
resourceName: String,
|
|
10
|
+
fileExtension: String
|
|
11
|
+
) {
|
|
12
|
+
let fileExtension = (bundlePath as NSString).pathExtension
|
|
13
|
+
let resourceName = (bundlePath as NSString).deletingPathExtension
|
|
14
|
+
|
|
15
|
+
guard !fileExtension.isEmpty, !resourceName.isEmpty else {
|
|
16
|
+
throw Error.invalidBundlePath(bundlePath)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return (resourceName, fileExtension)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import UIKit
|
|
2
|
+
internal import React
|
|
3
|
+
internal import React_RCTAppDelegate
|
|
4
|
+
internal import ReactAppDependencyProvider
|
|
5
|
+
|
|
6
|
+
#if canImport(Expo)
|
|
7
|
+
internal import Expo
|
|
8
|
+
|
|
9
|
+
final class ExpoHostRuntime {
|
|
10
|
+
static let shared = ExpoHostRuntime()
|
|
11
|
+
|
|
12
|
+
private let jsBundleLoadObserver = JSBundleLoadObserver()
|
|
13
|
+
private var delegate = ExpoHostRuntimeDelegate()
|
|
14
|
+
private var reactNativeFactory: RCTReactNativeFactory?
|
|
15
|
+
private var expoDelegate: ExpoAppDelegate?
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Starts React Native with default parameters.
|
|
19
|
+
*/
|
|
20
|
+
public func startReactNative() {
|
|
21
|
+
startReactNative(onBundleLoaded: nil)
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Starts React Native with optional callback when bundle is loaded.
|
|
25
|
+
*
|
|
26
|
+
* @param onBundleLoaded Optional callback invoked after JS bundle is fully loaded.
|
|
27
|
+
*/
|
|
28
|
+
public func startReactNative(onBundleLoaded: (() -> Void)?) {
|
|
29
|
+
guard reactNativeFactory == nil else { return }
|
|
30
|
+
|
|
31
|
+
let factory = ExpoReactNativeFactory(delegate: delegate)
|
|
32
|
+
delegate.dependencyProvider = RCTAppDependencyProvider()
|
|
33
|
+
|
|
34
|
+
reactNativeFactory = factory
|
|
35
|
+
|
|
36
|
+
let appDelegate = ExpoAppDelegate()
|
|
37
|
+
appDelegate.bindReactNativeFactory(factory)
|
|
38
|
+
expoDelegate = appDelegate
|
|
39
|
+
|
|
40
|
+
if let onBundleLoaded {
|
|
41
|
+
jsBundleLoadObserver.observeOnce(onBundleLoaded: onBundleLoaded)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Path to JavaScript root.
|
|
47
|
+
* Default value: ".expo/.virtual-metro-entry"
|
|
48
|
+
*/
|
|
49
|
+
public var entryFile: String = ".expo/.virtual-metro-entry" {
|
|
50
|
+
didSet {
|
|
51
|
+
delegate.entryFile = entryFile
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Path to JavaScript bundle file.
|
|
57
|
+
* Default value: "main.jsbundle"
|
|
58
|
+
*/
|
|
59
|
+
public var bundlePath: String = "main.jsbundle" {
|
|
60
|
+
didSet {
|
|
61
|
+
delegate.bundlePath = bundlePath
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Bundle instance to lookup the JavaScript bundle.
|
|
66
|
+
* Default value: Bundle.main
|
|
67
|
+
*/
|
|
68
|
+
public var bundle: Bundle = Bundle.main {
|
|
69
|
+
didSet {
|
|
70
|
+
delegate.bundle = bundle
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Dynamic bundle URL provider called on every bundle load.
|
|
75
|
+
* When set, this overrides the default bundleURL() behavior in the delegate.
|
|
76
|
+
* Returns a URL to load a custom bundle, or nil to use default behavior.
|
|
77
|
+
* Default value: nil
|
|
78
|
+
*/
|
|
79
|
+
public var bundleURLOverride: (() -> URL?)? = nil {
|
|
80
|
+
didSet {
|
|
81
|
+
delegate.bundleURLOverride = bundleURLOverride
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
func application(
|
|
86
|
+
_ application: UIApplication,
|
|
87
|
+
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
|
|
88
|
+
) -> Bool {
|
|
89
|
+
return expoDelegate?.application(
|
|
90
|
+
application,
|
|
91
|
+
didFinishLaunchingWithOptions: launchOptions
|
|
92
|
+
) != nil
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
func view(
|
|
96
|
+
moduleName: String,
|
|
97
|
+
initialProps: [AnyHashable: Any]?,
|
|
98
|
+
launchOptions: [AnyHashable: Any]?
|
|
99
|
+
) -> UIView? {
|
|
100
|
+
let bundleURL = delegate.bundleURL()
|
|
101
|
+
|
|
102
|
+
return expoDelegate?.recreateRootView(
|
|
103
|
+
withBundleURL: bundleURL,
|
|
104
|
+
moduleName: moduleName,
|
|
105
|
+
initialProps: initialProps,
|
|
106
|
+
launchOptions: launchOptions
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
class ExpoHostRuntimeDelegate: ExpoReactNativeFactoryDelegate {
|
|
112
|
+
var entryFile = ".expo/.virtual-metro-entry"
|
|
113
|
+
var bundlePath = "main.jsbundle"
|
|
114
|
+
var bundle = Bundle.main
|
|
115
|
+
var bundleURLOverride: (() -> URL?)? = nil
|
|
116
|
+
|
|
117
|
+
override func sourceURL(for bridge: RCTBridge) -> URL? {
|
|
118
|
+
// needed to return the correct URL for expo-dev-client.
|
|
119
|
+
bridge.bundleURL ?? bundleURL()
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
override func bundleURL() -> URL? {
|
|
123
|
+
if let bundleURLProvider = bundleURLOverride { return bundleURLProvider() }
|
|
124
|
+
#if DEBUG
|
|
125
|
+
return RCTBundleURLProvider.sharedSettings().jsBundleURL(
|
|
126
|
+
forBundleRoot: entryFile)
|
|
127
|
+
#else
|
|
128
|
+
do {
|
|
129
|
+
let (resourceName, fileExtension) = try BrownfieldBundlePathResolver.resourceComponents(
|
|
130
|
+
from: bundlePath
|
|
131
|
+
)
|
|
132
|
+
return bundle.url(forResource: resourceName, withExtension: fileExtension)
|
|
133
|
+
} catch {
|
|
134
|
+
assertionFailure("Invalid bundlePath '\(bundlePath)': \(error)")
|
|
135
|
+
return nil
|
|
136
|
+
}
|
|
137
|
+
#endif
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
#endif
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
internal import React
|
|
3
|
+
|
|
4
|
+
final class JSBundleLoadObserver {
|
|
5
|
+
private var onBundleLoaded: (() -> Void)?
|
|
6
|
+
private var observerToken: NSObjectProtocol?
|
|
7
|
+
|
|
8
|
+
func observeOnce(onBundleLoaded: @escaping () -> Void) {
|
|
9
|
+
removeObserverIfNeeded()
|
|
10
|
+
self.onBundleLoaded = onBundleLoaded
|
|
11
|
+
|
|
12
|
+
observerToken = NotificationCenter.default.addObserver(
|
|
13
|
+
forName: NSNotification.Name("RCTInstanceDidLoadBundle"),
|
|
14
|
+
object: nil,
|
|
15
|
+
queue: nil
|
|
16
|
+
) { [weak self] _ in
|
|
17
|
+
self?.notifyAndClear()
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
deinit {
|
|
22
|
+
removeObserverIfNeeded()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private func notifyAndClear() {
|
|
26
|
+
let callback = onBundleLoaded
|
|
27
|
+
onBundleLoaded = nil
|
|
28
|
+
removeObserverIfNeeded()
|
|
29
|
+
callback?()
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
private func removeObserverIfNeeded() {
|
|
33
|
+
if let observerToken {
|
|
34
|
+
NotificationCenter.default.removeObserver(observerToken)
|
|
35
|
+
self.observerToken = nil
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
extension Notification.Name {
|
|
4
|
+
/**
|
|
5
|
+
* Notification sent when React Native wants to navigate back to native screen.
|
|
6
|
+
*/
|
|
7
|
+
public static let popToNative = Notification.Name("PopToNativeNotification")
|
|
8
|
+
/**
|
|
9
|
+
* Notification sent to enable/disable the pop gesture recognizer.
|
|
10
|
+
*/
|
|
11
|
+
public static let togglePopGestureRecognizer = Notification.Name("TogglePopGestureRecognizerNotification")
|
|
12
|
+
}
|
|
@@ -1,74 +1,60 @@
|
|
|
1
1
|
import UIKit
|
|
2
|
-
internal import React
|
|
3
|
-
internal import React_RCTAppDelegate
|
|
4
|
-
internal import ReactAppDependencyProvider
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
var bundlePath = "main.jsbundle"
|
|
9
|
-
var bundle = Bundle.main
|
|
10
|
-
var bundleURLOverride: (() -> URL?)? = nil
|
|
11
|
-
// MARK: - RCTReactNativeFactoryDelegate Methods
|
|
12
|
-
|
|
13
|
-
override func sourceURL(for bridge: RCTBridge) -> URL? {
|
|
14
|
-
return bundleURL()
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
public override func bundleURL() -> URL? {
|
|
18
|
-
if let bundleURLProvider = bundleURLOverride {
|
|
19
|
-
return bundleURLProvider()
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
#if DEBUG
|
|
23
|
-
return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: entryFile)
|
|
24
|
-
#else
|
|
25
|
-
let resourceURLComponents = bundlePath.components(separatedBy: ".")
|
|
26
|
-
let withoutLast = resourceURLComponents[..<(resourceURLComponents.count - 1)]
|
|
27
|
-
let resourceName = withoutLast.joined()
|
|
28
|
-
let fileExtension = resourceURLComponents.last ?? ""
|
|
29
|
-
|
|
30
|
-
return bundle.url(forResource: resourceName, withExtension: fileExtension)
|
|
3
|
+
#if canImport(Expo)
|
|
4
|
+
internal import Expo
|
|
31
5
|
#endif
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
6
|
|
|
35
7
|
@objc public class ReactNativeBrownfield: NSObject {
|
|
36
8
|
public static let shared = ReactNativeBrownfield()
|
|
37
|
-
|
|
38
|
-
private var delegate = ReactNativeBrownfieldDelegate()
|
|
39
|
-
|
|
9
|
+
|
|
40
10
|
/**
|
|
41
11
|
* Path to JavaScript root.
|
|
42
|
-
* Default value: "index"
|
|
12
|
+
* Default value: "index" for bare React Native, ".expo/.virtual-metro-entry" when built with Expo.
|
|
43
13
|
*/
|
|
44
|
-
@objc public var entryFile: String =
|
|
14
|
+
@objc public var entryFile: String = {
|
|
15
|
+
#if canImport(Expo)
|
|
16
|
+
return ".expo/.virtual-metro-entry"
|
|
17
|
+
#else
|
|
18
|
+
return "index"
|
|
19
|
+
#endif
|
|
20
|
+
}() {
|
|
45
21
|
didSet {
|
|
46
|
-
|
|
22
|
+
#if canImport(Expo)
|
|
23
|
+
ExpoHostRuntime.shared.entryFile = entryFile
|
|
24
|
+
#else
|
|
25
|
+
ReactNativeHostRuntime.shared.entryFile = entryFile
|
|
26
|
+
#endif
|
|
47
27
|
}
|
|
48
28
|
}
|
|
49
|
-
|
|
50
|
-
* Path to bundle fallback resource.
|
|
51
|
-
* Default value: nil
|
|
52
|
-
*/
|
|
53
|
-
@objc public var fallbackResource: String? = nil
|
|
29
|
+
|
|
54
30
|
/**
|
|
55
31
|
* Path to JavaScript bundle file.
|
|
56
32
|
* Default value: "main.jsbundle"
|
|
57
33
|
*/
|
|
58
34
|
@objc public var bundlePath: String = "main.jsbundle" {
|
|
59
35
|
didSet {
|
|
60
|
-
|
|
36
|
+
#if canImport(Expo)
|
|
37
|
+
ExpoHostRuntime.shared.bundlePath = bundlePath
|
|
38
|
+
#else
|
|
39
|
+
ReactNativeHostRuntime.shared.bundlePath = bundlePath
|
|
40
|
+
#endif
|
|
61
41
|
}
|
|
62
42
|
}
|
|
43
|
+
|
|
63
44
|
/**
|
|
64
45
|
* Bundle instance to lookup the JavaScript bundle.
|
|
65
46
|
* Default value: Bundle.main
|
|
66
47
|
*/
|
|
67
|
-
@objc public var bundle: Bundle =
|
|
48
|
+
@objc public var bundle: Bundle = .main {
|
|
68
49
|
didSet {
|
|
69
|
-
|
|
50
|
+
#if canImport(Expo)
|
|
51
|
+
ExpoHostRuntime.shared.bundle = bundle
|
|
52
|
+
#else
|
|
53
|
+
ReactNativeHostRuntime.shared.bundle = bundle
|
|
54
|
+
#endif
|
|
70
55
|
}
|
|
71
56
|
}
|
|
57
|
+
|
|
72
58
|
/**
|
|
73
59
|
* Dynamic bundle URL provider called on every bundle load.
|
|
74
60
|
* When set, this overrides the default bundleURL() behavior in the delegate.
|
|
@@ -77,95 +63,75 @@ class ReactNativeBrownfieldDelegate: RCTDefaultReactNativeFactoryDelegate {
|
|
|
77
63
|
*/
|
|
78
64
|
@objc public var bundleURLOverride: (() -> URL?)? = nil {
|
|
79
65
|
didSet {
|
|
80
|
-
|
|
66
|
+
#if canImport(Expo)
|
|
67
|
+
ExpoHostRuntime.shared.bundleURLOverride = bundleURLOverride
|
|
68
|
+
#else
|
|
69
|
+
ReactNativeHostRuntime.shared.bundleURLOverride = bundleURLOverride
|
|
70
|
+
#endif
|
|
81
71
|
}
|
|
82
72
|
}
|
|
83
|
-
|
|
84
|
-
* React Native factory instance created when starting React Native.
|
|
85
|
-
* Default value: nil
|
|
86
|
-
*/
|
|
87
|
-
private var reactNativeFactory: RCTReactNativeFactory? = nil
|
|
88
|
-
/**
|
|
89
|
-
* Root view factory used to create React Native views.
|
|
90
|
-
*/
|
|
91
|
-
lazy private var rootViewFactory: RCTRootViewFactory? = {
|
|
92
|
-
return reactNativeFactory?.rootViewFactory
|
|
93
|
-
}()
|
|
94
|
-
|
|
73
|
+
|
|
95
74
|
/**
|
|
96
75
|
* Starts React Native with default parameters.
|
|
97
76
|
*/
|
|
98
77
|
@objc public func startReactNative() {
|
|
99
|
-
|
|
78
|
+
#if canImport(Expo)
|
|
79
|
+
ExpoHostRuntime.shared.startReactNative()
|
|
80
|
+
#else
|
|
81
|
+
ReactNativeHostRuntime.shared.startReactNative()
|
|
82
|
+
#endif
|
|
100
83
|
}
|
|
101
|
-
|
|
84
|
+
|
|
102
85
|
@objc public func view(
|
|
103
86
|
moduleName: String,
|
|
104
87
|
initialProps: [AnyHashable: Any]?,
|
|
105
88
|
launchOptions: [AnyHashable: Any]? = nil
|
|
106
89
|
) -> UIView? {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
90
|
+
#if canImport(Expo)
|
|
91
|
+
ExpoHostRuntime.shared.view(
|
|
92
|
+
moduleName: moduleName,
|
|
93
|
+
initialProps: initialProps,
|
|
94
|
+
launchOptions: launchOptions
|
|
95
|
+
)
|
|
96
|
+
#else
|
|
97
|
+
ReactNativeHostRuntime.shared.view(
|
|
98
|
+
moduleName: moduleName,
|
|
99
|
+
initialProps: initialProps,
|
|
110
100
|
launchOptions: launchOptions
|
|
111
101
|
)
|
|
102
|
+
#endif
|
|
112
103
|
}
|
|
113
|
-
|
|
104
|
+
|
|
114
105
|
/**
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
* @param onBundleLoaded Optional callback invoked after JS bundle is fully loaded.
|
|
106
|
+
* Mirrors the host runtime app delegate API, forwarding to Expo or bare React Native as appropriate.
|
|
118
107
|
*/
|
|
119
|
-
@objc public func
|
|
120
|
-
|
|
108
|
+
@objc public func application(
|
|
109
|
+
_ application: UIApplication,
|
|
110
|
+
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
|
|
111
|
+
) -> Bool {
|
|
112
|
+
#if canImport(Expo)
|
|
113
|
+
return ExpoHostRuntime.shared.application(
|
|
114
|
+
application,
|
|
115
|
+
didFinishLaunchingWithOptions: launchOptions
|
|
116
|
+
)
|
|
117
|
+
#else
|
|
118
|
+
return ReactNativeHostRuntime.shared.application(
|
|
119
|
+
application,
|
|
120
|
+
didFinishLaunchingWithOptions: launchOptions
|
|
121
|
+
)
|
|
122
|
+
#endif
|
|
121
123
|
}
|
|
122
|
-
|
|
124
|
+
|
|
123
125
|
/**
|
|
124
|
-
* Starts React Native with optional callback
|
|
126
|
+
* Starts React Native with optional callback when bundle is loaded.
|
|
125
127
|
*
|
|
126
128
|
* @param onBundleLoaded Optional callback invoked after JS bundle is fully loaded.
|
|
127
|
-
* @param launchOptions Launch options, typically passed from AppDelegate.
|
|
128
129
|
*/
|
|
129
|
-
@objc public func startReactNative(onBundleLoaded: (() -> Void)
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
if let onBundleLoaded {
|
|
136
|
-
self.onBundleLoaded = onBundleLoaded
|
|
137
|
-
if RCTIsNewArchEnabled() {
|
|
138
|
-
NotificationCenter.default.addObserver(
|
|
139
|
-
self,
|
|
140
|
-
selector: #selector(jsLoaded),
|
|
141
|
-
name: NSNotification.Name("RCTInstanceDidLoadBundle"),
|
|
142
|
-
object: nil
|
|
143
|
-
)
|
|
144
|
-
} else {
|
|
145
|
-
NotificationCenter.default.addObserver(
|
|
146
|
-
self,
|
|
147
|
-
selector: #selector(jsLoaded),
|
|
148
|
-
name: NSNotification.Name("RCTJavaScriptDidLoadNotification"),
|
|
149
|
-
object: nil
|
|
150
|
-
)
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
@objc private func jsLoaded(_ notification: Notification) {
|
|
156
|
-
onBundleLoaded?()
|
|
157
|
-
onBundleLoaded = nil
|
|
158
|
-
NotificationCenter.default.removeObserver(self)
|
|
130
|
+
@objc public func startReactNative(onBundleLoaded: (() -> Void)?) {
|
|
131
|
+
#if canImport(Expo)
|
|
132
|
+
ExpoHostRuntime.shared.startReactNative(onBundleLoaded: onBundleLoaded)
|
|
133
|
+
#else
|
|
134
|
+
ReactNativeHostRuntime.shared.startReactNative(onBundleLoaded: onBundleLoaded)
|
|
135
|
+
#endif
|
|
159
136
|
}
|
|
160
137
|
}
|
|
161
|
-
|
|
162
|
-
extension Notification.Name {
|
|
163
|
-
/**
|
|
164
|
-
* Notification sent when React Native wants to navigate back to native screen.
|
|
165
|
-
*/
|
|
166
|
-
public static let popToNative = Notification.Name("PopToNativeNotification")
|
|
167
|
-
/**
|
|
168
|
-
* Notification sent to enable/disable the pop gesture recognizer.
|
|
169
|
-
*/
|
|
170
|
-
public static let togglePopGestureRecognizer = Notification.Name("TogglePopGestureRecognizerNotification")
|
|
171
|
-
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import UIKit
|
|
2
|
+
internal import React
|
|
3
|
+
internal import React_RCTAppDelegate
|
|
4
|
+
internal import ReactAppDependencyProvider
|
|
5
|
+
|
|
6
|
+
class ReactNativeBrownfieldDelegate: RCTDefaultReactNativeFactoryDelegate {
|
|
7
|
+
var entryFile = "index"
|
|
8
|
+
var bundlePath = "main.jsbundle"
|
|
9
|
+
var bundle = Bundle.main
|
|
10
|
+
var bundleURLOverride: (() -> URL?)? = nil
|
|
11
|
+
// MARK: - RCTReactNativeFactoryDelegate Methods
|
|
12
|
+
|
|
13
|
+
override func sourceURL(for bridge: RCTBridge) -> URL? {
|
|
14
|
+
return bundleURL()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
public override func bundleURL() -> URL? {
|
|
18
|
+
if let bundleURLProvider = bundleURLOverride {
|
|
19
|
+
return bundleURLProvider()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
#if DEBUG
|
|
23
|
+
return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: entryFile)
|
|
24
|
+
#else
|
|
25
|
+
do {
|
|
26
|
+
let (resourceName, fileExtension) = try BrownfieldBundlePathResolver.resourceComponents(
|
|
27
|
+
from: bundlePath
|
|
28
|
+
)
|
|
29
|
+
return bundle.url(forResource: resourceName, withExtension: fileExtension)
|
|
30
|
+
} catch {
|
|
31
|
+
assertionFailure("Invalid bundlePath '\(bundlePath)': \(error)")
|
|
32
|
+
return nil
|
|
33
|
+
}
|
|
34
|
+
#endif
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
final class ReactNativeHostRuntime {
|
|
39
|
+
public static let shared = ReactNativeHostRuntime()
|
|
40
|
+
private let jsBundleLoadObserver = JSBundleLoadObserver()
|
|
41
|
+
private var delegate = ReactNativeBrownfieldDelegate()
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Path to JavaScript root.
|
|
45
|
+
* Default value: "index"
|
|
46
|
+
*/
|
|
47
|
+
public var entryFile: String = "index" {
|
|
48
|
+
didSet {
|
|
49
|
+
delegate.entryFile = entryFile
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Path to JavaScript bundle file.
|
|
55
|
+
* Default value: "main.jsbundle"
|
|
56
|
+
*/
|
|
57
|
+
public var bundlePath: String = "main.jsbundle" {
|
|
58
|
+
didSet {
|
|
59
|
+
delegate.bundlePath = bundlePath
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Bundle instance to lookup the JavaScript bundle.
|
|
64
|
+
* Default value: Bundle.main
|
|
65
|
+
*/
|
|
66
|
+
public var bundle: Bundle = Bundle.main {
|
|
67
|
+
didSet {
|
|
68
|
+
delegate.bundle = bundle
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Dynamic bundle URL provider called on every bundle load.
|
|
73
|
+
* When set, this overrides the default bundleURL() behavior in the delegate.
|
|
74
|
+
* Returns a URL to load a custom bundle, or nil to use default behavior.
|
|
75
|
+
* Default value: nil
|
|
76
|
+
*/
|
|
77
|
+
public var bundleURLOverride: (() -> URL?)? = nil {
|
|
78
|
+
didSet {
|
|
79
|
+
delegate.bundleURLOverride = bundleURLOverride
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* React Native factory instance created when starting React Native.
|
|
84
|
+
* Default value: nil
|
|
85
|
+
*/
|
|
86
|
+
private var reactNativeFactory: RCTReactNativeFactory? = nil
|
|
87
|
+
/**
|
|
88
|
+
* Root view factory used to create React Native views.
|
|
89
|
+
*/
|
|
90
|
+
lazy private var rootViewFactory: RCTRootViewFactory? = {
|
|
91
|
+
return reactNativeFactory?.rootViewFactory
|
|
92
|
+
}()
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Starts React Native with default parameters.
|
|
96
|
+
*/
|
|
97
|
+
public func startReactNative() {
|
|
98
|
+
startReactNative(onBundleLoaded: nil)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public func view(
|
|
102
|
+
moduleName: String,
|
|
103
|
+
initialProps: [AnyHashable: Any]?,
|
|
104
|
+
launchOptions: [AnyHashable: Any]? = nil
|
|
105
|
+
) -> UIView? {
|
|
106
|
+
rootViewFactory?.view(
|
|
107
|
+
withModuleName: moduleName,
|
|
108
|
+
initialProperties: initialProps,
|
|
109
|
+
launchOptions: launchOptions
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Mirrors host manager app delegate API for bare React Native.
|
|
115
|
+
*/
|
|
116
|
+
public func application(
|
|
117
|
+
_ application: UIApplication,
|
|
118
|
+
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
|
|
119
|
+
) -> Bool {
|
|
120
|
+
return true
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Starts React Native with optional callback when bundle is loaded.
|
|
125
|
+
*
|
|
126
|
+
* @param onBundleLoaded Optional callback invoked after JS bundle is fully loaded.
|
|
127
|
+
*/
|
|
128
|
+
public func startReactNative(onBundleLoaded: (() -> Void)?) {
|
|
129
|
+
guard reactNativeFactory == nil else { return }
|
|
130
|
+
|
|
131
|
+
delegate.dependencyProvider = RCTAppDependencyProvider()
|
|
132
|
+
self.reactNativeFactory = RCTReactNativeFactory(delegate: delegate)
|
|
133
|
+
|
|
134
|
+
if let onBundleLoaded {
|
|
135
|
+
jsBundleLoadObserver.observeOnce(onBundleLoaded: onBundleLoaded)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,"__esModule",{value:true});exports.brownfieldGradlePluginDependency=exports.BROWNFIELD_PLUGIN_VERSION=void 0;var BROWNFIELD_PLUGIN_VERSION=exports.BROWNFIELD_PLUGIN_VERSION='0.
|
|
1
|
+
Object.defineProperty(exports,"__esModule",{value:true});exports.brownfieldGradlePluginDependency=exports.BROWNFIELD_PLUGIN_VERSION=void 0;var BROWNFIELD_PLUGIN_VERSION=exports.BROWNFIELD_PLUGIN_VERSION='1.0.1';var brownfieldGradlePluginDependency=exports.brownfieldGradlePluginDependency=`classpath("com.callstack.react:brownfield-gradle-plugin:${BROWNFIELD_PLUGIN_VERSION}")`;
|
|
2
2
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1,31 +1,8 @@
|
|
|
1
|
-
var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.modifyPodfile=modifyPodfile;var _slicedToArray2=_interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));var _SourceModificationError=require("../errors/SourceModificationError");var _logging=require("../logging");var _engine=require("../template/engine");var BROWNFIELD_POD_HOOK_MARKER_START='# >>> react-native-brownfield expo phase ordering >>>';var BROWNFIELD_POD_HOOK_MARKER_END='# <<< react-native-brownfield expo phase ordering <<<';function
|
|
1
|
+
var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.modifyPodfile=modifyPodfile;var _slicedToArray2=_interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));var _SourceModificationError=require("../errors/SourceModificationError");var _logging=require("../logging");var _engine=require("../template/engine");var BROWNFIELD_POD_HOOK_MARKER_START='# >>> react-native-brownfield expo phase ordering >>>';var BROWNFIELD_POD_HOOK_MARKER_END='# <<< react-native-brownfield expo phase ordering <<<';var BROWNFIELD_POST_INTEGRATE_REQUIRE=`require File.join(File.dirname(\`node --print "require.resolve('@callstack/react-native-brownfield/package.json')"\`), "scripts/react_native_brownfield_post_integrate")`;var REACT_NATIVE_PODS_REQUIRE_REGEX=/^require File\.join\(File\.dirname\(`node --print "require\.resolve\('react-native\/package\.json'\)"`\), "scripts\/react_native_pods"\)\s*$/m;function ensureBrownfieldPostIntegrateRequire(podfile){if(podfile.includes('scripts/react_native_brownfield_post_integrate')){return podfile;}var reactNativePodsRequireMatch=podfile.match(REACT_NATIVE_PODS_REQUIRE_REGEX);if(reactNativePodsRequireMatch){var requireLine=reactNativePodsRequireMatch[0];return podfile.replace(requireLine,`${requireLine}\n${BROWNFIELD_POST_INTEGRATE_REQUIRE}\n`);}return`${BROWNFIELD_POST_INTEGRATE_REQUIRE}\n\n${podfile}`;}function ensureExpoPhaseOrderingHook(podfile){var modifiedPodfile=ensureBrownfieldPostIntegrateRequire(podfile);if(modifiedPodfile.includes(BROWNFIELD_POD_HOOK_MARKER_START)){return modifiedPodfile;}var hook=`
|
|
2
2
|
${BROWNFIELD_POD_HOOK_MARKER_START}
|
|
3
|
-
def reorder_brownfield_expo_patch_phase!(installer)
|
|
4
|
-
projects = installer.aggregate_targets.map(&:user_project).compact.uniq
|
|
5
|
-
projects.each do |project|
|
|
6
|
-
modified = false
|
|
7
|
-
|
|
8
|
-
project.native_targets.each do |target|
|
|
9
|
-
phases = target.build_phases
|
|
10
|
-
expo_idx = phases.index { |p| p.respond_to?(:name) && p.name == '[Expo] Configure project' }
|
|
11
|
-
patch_idx = phases.index { |p| p.respond_to?(:name) && p.name == 'Patch ExpoModulesProvider' }
|
|
12
|
-
|
|
13
|
-
next if expo_idx.nil? || patch_idx.nil?
|
|
14
|
-
next if patch_idx > expo_idx
|
|
15
|
-
|
|
16
|
-
patch = phases.delete_at(patch_idx)
|
|
17
|
-
expo_idx = phases.index { |p| p.respond_to?(:name) && p.name == '[Expo] Configure project' }
|
|
18
|
-
phases.insert(expo_idx + 1, patch)
|
|
19
|
-
modified = true
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
project.save if modified
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
3
|
post_integrate do |installer|
|
|
27
|
-
|
|
4
|
+
react_native_brownfield_post_integrate(installer)
|
|
28
5
|
end
|
|
29
6
|
${BROWNFIELD_POD_HOOK_MARKER_END}
|
|
30
|
-
`;
|
|
7
|
+
`;modifiedPodfile=`${modifiedPodfile.trimEnd()}\n\n${hook}\n`;return modifiedPodfile;}function modifyPodfile(podfile,frameworkName,isExpoPre55){if(podfile.includes(`target '${frameworkName}'`)){_logging.Logger.logDebug(`Framework target "${frameworkName}" already in Podfile, skipping modification`);return podfile;}_logging.Logger.logDebug(`Modifying Podfile for framework: ${frameworkName}`);var frameworkTargetBlock=(0,_engine.renderTemplate)('ios','PodfileTargetBlock.rb',{'{{FRAMEWORK_NAME}}':frameworkName});var mainTargetMatch=podfile.match(/(target\s+['"][^'"]+['"]\s+do\s*\n)([\s\S]*?)(^end\s*$)/m);if(!mainTargetMatch){throw new _SourceModificationError.SourceModificationError('Could not find main target in Podfile. Please manually add the framework target.');}var _mainTargetMatch=(0,_slicedToArray2.default)(mainTargetMatch,3),targetStart=_mainTargetMatch[1],targetContent=_mainTargetMatch[2];var insertIndex=podfile.indexOf(mainTargetMatch[0])+targetStart.length+targetContent.length;var modifiedPodfile=podfile.slice(0,insertIndex)+frameworkTargetBlock+podfile.slice(insertIndex);_logging.Logger.logDebug(`Added framework target "${frameworkName}" to Podfile`);if(isExpoPre55){modifiedPodfile=ensureExpoPhaseOrderingHook(modifiedPodfile);}return modifiedPodfile;}
|
|
31
8
|
//# sourceMappingURL=podfileHelpers.js.map
|