-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathReactNativeBrownfield.swift
119 lines (106 loc) · 3.72 KB
/
ReactNativeBrownfield.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import React
import React_RCTAppDelegate
import ReactAppDependencyProvider
@objc public class ReactNativeBrownfield: RCTDefaultReactNativeFactoryDelegate {
@objc public static let shared = ReactNativeBrownfield()
private var onBundleLoaded: (() -> Void)?
/**
* Path to JavaScript root.
* Default value: "index"
*/
@objc public var entryFile: String = "index"
/**
* Path to bundle fallback resource.
* Default value: nil
*/
@objc public var fallbackResource: String? = nil
/**
* Path to JavaScript bundle file.
* Default value: "main.jsbundle"
*/
@objc public var bundlePath: String = "main.jsbundle"
/**
* React Native factory instance created when starting React Native.
* Default value: nil
*/
@objc public var reactNativeFactory: RCTReactNativeFactory? = nil
/**
* Root view factory used to create React Native views.
*/
@objc lazy public var rootViewFactory: RCTRootViewFactory? = {
return reactNativeFactory?.rootViewFactory
}()
/**
* Starts React Native with default parameters.
*/
@objc public func startReactNative() {
startReactNative(onBundleLoaded: nil)
}
/**
* Starts React Native with optional callback when bundle is loaded.
*
* @param onBundleLoaded Optional callback invoked after JS bundle is fully loaded.
*/
@objc public func startReactNative(onBundleLoaded: (() -> Void)?) {
startReactNative(onBundleLoaded: onBundleLoaded, launchOptions: nil)
}
/**
* Starts React Native with optional callback and launch options.
*
* @param onBundleLoaded Optional callback invoked after JS bundle is fully loaded.
* @param launchOptions Launch options, typically passed from AppDelegate.
*/
@objc public func startReactNative(onBundleLoaded: (() -> Void)?, launchOptions: [AnyHashable: Any]?) {
guard reactNativeFactory == nil else { return }
self.dependencyProvider = RCTAppDependencyProvider()
self.reactNativeFactory = RCTReactNativeFactory(delegate: self)
if let onBundleLoaded {
self.onBundleLoaded = onBundleLoaded
if RCTIsNewArchEnabled() {
NotificationCenter.default.addObserver(
self,
selector: #selector(jsLoaded),
name: NSNotification.Name("RCTInstanceDidLoadBundle"),
object: nil
)
} else {
NotificationCenter.default.addObserver(
self,
selector: #selector(jsLoaded),
name: NSNotification.Name("RCTJavaScriptDidLoadNotification"),
object: nil
)
}
}
}
@objc private func jsLoaded(_ notification: Notification) {
onBundleLoaded?()
onBundleLoaded = nil
NotificationCenter.default.removeObserver(self)
}
// MARK: - RCTReactNativeFactoryDelegate Methods
@objc public override func sourceURL(for bridge: RCTBridge) -> URL? {
return bundleURL()
}
public override func bundleURL() -> URL? {
#if DEBUG
return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: entryFile)
#else
let resourceURLComponents = bundlePath.components(separatedBy: ".")
let withoutLast = resourceURLComponents[..<(resourceURLComponents.count - 1)]
let resourceName = withoutLast.joined()
let fileExtension = resourceURLComponents.last ?? ""
return Bundle.main.url(forResource: resourceName, withExtension: fileExtension)
#endif
}
}
extension Notification.Name {
/**
* Notification sent when React Native wants to navigate back to native screen.
*/
public static let popToNative = Notification.Name("PopToNativeNotification")
/**
* Notification sent to enable/disable the pop gesture recognizer.
*/
public static let togglePopGestureRecognizer = Notification.Name("TogglePopGestureRecognizerNotification")
}