@callstack/react-native-brownfield 0.1.0 → 1.0.0-rc.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 +24 -1
- package/ReactNativeBrownfield.podspec +10 -3
- package/android/build.gradle +89 -16
- package/android/gradle.properties +5 -0
- package/android/src/main/java/com/callstack/reactnativebrownfield/ReactNativeBrownfield.kt +82 -15
- package/android/src/main/java/com/callstack/reactnativebrownfield/ReactNativeBrownfieldModule.kt +22 -21
- package/android/src/main/java/com/callstack/reactnativebrownfield/ReactNativeBrownfieldPackage.kt +9 -9
- package/android/src/main/java/com/callstack/reactnativebrownfield/ReactNativeFragment.kt +139 -145
- package/ios/ReactNativeBrownfield.swift +119 -0
- package/ios/ReactNativeBrownfieldModule.m +8 -11
- package/ios/ReactNativeBrownfieldModule.swift +18 -0
- package/ios/ReactNativeView.swift +42 -0
- package/ios/ReactNativeViewController.swift +66 -0
- package/lib/commonjs/RNBrownfieldSpec.js +9 -0
- package/lib/commonjs/RNBrownfieldSpec.js.map +1 -0
- package/lib/commonjs/index.js +6 -4
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/package.json +1 -0
- package/lib/module/RNBrownfieldSpec.js +5 -0
- package/lib/module/RNBrownfieldSpec.js.map +1 -0
- package/lib/module/index.js +8 -5
- package/lib/module/index.js.map +1 -1
- package/lib/module/package.json +1 -0
- package/lib/typescript/src/RNBrownfieldSpec.d.ts +20 -0
- package/lib/typescript/src/RNBrownfieldSpec.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +32 -27
- package/src/RNBrownfieldSpec.ts +23 -0
- package/src/index.ts +6 -7
- package/android/src/main/java/com/callstack/reactnativebrownfield/ReactNativeActivity.kt +0 -188
- package/ios/ReactNativeBrownfield.h +0 -24
- package/ios/ReactNativeBrownfield.m +0 -82
- package/ios/ReactNativeBrownfieldNotifications.h +0 -4
- package/ios/ReactNativeBrownfieldNotifications.m +0 -4
- package/ios/ReactNativeViewController.h +0 -15
- package/ios/ReactNativeViewController.m +0 -66
|
@@ -3,174 +3,168 @@ package com.callstack.reactnativebrownfield;
|
|
|
3
3
|
import android.annotation.TargetApi
|
|
4
4
|
import android.os.Build
|
|
5
5
|
import android.os.Bundle
|
|
6
|
-
import androidx.fragment.app.Fragment
|
|
7
6
|
import android.view.KeyEvent
|
|
8
|
-
import android.view.LayoutInflater
|
|
9
|
-
import android.view.View
|
|
10
|
-
import android.view.ViewGroup
|
|
11
7
|
import com.facebook.infer.annotation.Assertions
|
|
12
|
-
import com.facebook.react.
|
|
8
|
+
import com.facebook.react.ReactFragment
|
|
9
|
+
import com.facebook.react.ReactHost
|
|
10
|
+
import com.facebook.react.ReactNativeHost
|
|
13
11
|
import com.facebook.react.bridge.Callback
|
|
14
12
|
import com.facebook.react.bridge.WritableMap
|
|
15
13
|
import com.facebook.react.common.LifecycleState
|
|
14
|
+
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
|
|
16
15
|
import com.facebook.react.devsupport.DoubleTapReloadRecognizer
|
|
17
16
|
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler
|
|
18
17
|
import com.facebook.react.modules.core.PermissionAwareActivity
|
|
19
18
|
import com.facebook.react.modules.core.PermissionListener
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
private
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
reactRootView = ReactRootView(context)
|
|
39
|
-
reactRootView?.startReactApplication(
|
|
40
|
-
ReactNativeBrownfield.shared.reactNativeHost.reactInstanceManager,
|
|
41
|
-
moduleName,
|
|
42
|
-
initialProps
|
|
43
|
-
)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
override fun onCreateView(
|
|
48
|
-
inflater: LayoutInflater,
|
|
49
|
-
container: ViewGroup?,
|
|
50
|
-
savedInstanceState: Bundle?
|
|
51
|
-
): View {
|
|
52
|
-
return reactRootView!!
|
|
20
|
+
class ReactNativeFragment : ReactFragment(), PermissionAwareActivity {
|
|
21
|
+
private lateinit var doubleTapReloadRecognizer: DoubleTapReloadRecognizer
|
|
22
|
+
private lateinit var permissionsCallback: Callback
|
|
23
|
+
private var permissionListener: PermissionListener? = null
|
|
24
|
+
|
|
25
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
26
|
+
super.onCreate(savedInstanceState)
|
|
27
|
+
doubleTapReloadRecognizer = DoubleTapReloadRecognizer()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
override fun getReactHost(): ReactHost? {
|
|
31
|
+
return activity?.let {
|
|
32
|
+
getDefaultReactHost(
|
|
33
|
+
it.applicationContext,
|
|
34
|
+
ReactNativeBrownfield.shared.reactNativeHost
|
|
35
|
+
)
|
|
53
36
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
override fun getReactNativeHost(): ReactNativeHost? {
|
|
40
|
+
return ReactNativeBrownfield.shared.reactNativeHost
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
override fun onResume() {
|
|
44
|
+
super.onResume()
|
|
45
|
+
if (ReactNativeBrownfield.shared.reactNativeHost.hasInstance()) {
|
|
46
|
+
ReactNativeBrownfield.shared.reactNativeHost.reactInstanceManager?.onHostResume(
|
|
47
|
+
activity,
|
|
48
|
+
activity as DefaultHardwareBackBtnHandler
|
|
49
|
+
)
|
|
63
50
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
override fun onPause() {
|
|
54
|
+
super.onPause()
|
|
55
|
+
if (ReactNativeBrownfield.shared.reactNativeHost.hasInstance()) {
|
|
56
|
+
ReactNativeBrownfield.shared.reactNativeHost.reactInstanceManager?.onHostPause(
|
|
57
|
+
activity
|
|
58
|
+
)
|
|
72
59
|
}
|
|
60
|
+
}
|
|
73
61
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (ReactNativeBrownfield.shared.reactNativeHost.hasInstance()) {
|
|
79
|
-
val reactInstanceMgr = ReactNativeBrownfield.shared.reactNativeHost.reactInstanceManager
|
|
80
|
-
|
|
81
|
-
if (reactInstanceMgr.lifecycleState != LifecycleState.RESUMED) {
|
|
82
|
-
reactInstanceMgr.onHostDestroy(activity)
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
62
|
+
override fun onDestroy() {
|
|
63
|
+
super.onDestroy()
|
|
64
|
+
if (ReactNativeBrownfield.shared.reactNativeHost.hasInstance()) {
|
|
65
|
+
val reactInstanceMgr = ReactNativeBrownfield.shared.reactNativeHost.reactInstanceManager
|
|
86
66
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
grantResults: IntArray
|
|
91
|
-
) {
|
|
92
|
-
permissionsCallback = Callback {
|
|
93
|
-
if (permissionListener != null) {
|
|
94
|
-
permissionListener?.onRequestPermissionsResult(
|
|
95
|
-
requestCode,
|
|
96
|
-
permissions,
|
|
97
|
-
grantResults
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
permissionListener = null
|
|
101
|
-
}
|
|
102
|
-
}
|
|
67
|
+
if (reactInstanceMgr.lifecycleState != LifecycleState.RESUMED) {
|
|
68
|
+
reactInstanceMgr.onHostDestroy(activity)
|
|
69
|
+
}
|
|
103
70
|
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
override fun onRequestPermissionsResult(
|
|
74
|
+
requestCode: Int,
|
|
75
|
+
permissions: Array<String>,
|
|
76
|
+
grantResults: IntArray
|
|
77
|
+
) {
|
|
78
|
+
permissionsCallback = Callback {
|
|
79
|
+
if (permissionListener != null) {
|
|
80
|
+
permissionListener?.onRequestPermissionsResult(
|
|
81
|
+
requestCode,
|
|
82
|
+
permissions,
|
|
83
|
+
grantResults
|
|
84
|
+
)
|
|
104
85
|
|
|
105
|
-
|
|
106
|
-
|
|
86
|
+
permissionListener = null
|
|
87
|
+
}
|
|
107
88
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
override fun checkPermission(permission: String, pid: Int, uid: Int): Int {
|
|
92
|
+
return requireActivity().checkPermission(permission, pid, uid)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@TargetApi(Build.VERSION_CODES.M)
|
|
96
|
+
override fun checkSelfPermission(permission: String): Int {
|
|
97
|
+
return requireActivity().checkSelfPermission(permission)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
override fun requestPermissions(
|
|
101
|
+
permissions: Array<String>,
|
|
102
|
+
requestCode: Int,
|
|
103
|
+
listener: PermissionListener?
|
|
104
|
+
) {
|
|
105
|
+
permissionListener = listener
|
|
106
|
+
this.requestPermissions(permissions, requestCode)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
|
|
110
|
+
var handled = false
|
|
111
|
+
if (ReactNativeBrownfield.shared.reactNativeHost.useDeveloperSupport && ReactNativeBrownfield.shared.reactNativeHost.hasInstance()) {
|
|
112
|
+
if (keyCode == KeyEvent.KEYCODE_MENU) {
|
|
113
|
+
ReactNativeBrownfield.shared.reactNativeHost.reactInstanceManager.showDevOptionsDialog()
|
|
114
|
+
handled = true
|
|
115
|
+
}
|
|
116
|
+
val didDoubleTapR = activity?.currentFocus?.let {
|
|
117
|
+
Assertions.assertNotNull(doubleTapReloadRecognizer)
|
|
118
|
+
.didDoubleTapR(keyCode, it)
|
|
119
|
+
}
|
|
120
|
+
if (didDoubleTapR == true) {
|
|
121
|
+
ReactNativeBrownfield.shared.reactNativeHost.reactInstanceManager.devSupportManager.handleReloadJS()
|
|
122
|
+
handled = true
|
|
123
|
+
}
|
|
112
124
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
) {
|
|
120
|
-
|
|
121
|
-
this.requestPermissions(permissions, requestCode)
|
|
125
|
+
return handled
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
fun onBackPressed(backBtnHandler: DefaultHardwareBackBtnHandler) {
|
|
129
|
+
if (ReactNativeBrownfieldModule.shouldPopToNative) {
|
|
130
|
+
backBtnHandler.invokeDefaultOnBackPressed()
|
|
131
|
+
} else if (ReactNativeBrownfield.shared.reactNativeHost.hasInstance()) {
|
|
132
|
+
ReactNativeBrownfield.shared.reactNativeHost.reactInstanceManager.onBackPressed()
|
|
122
133
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
return handled
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
companion object {
|
|
137
|
+
@JvmStatic
|
|
138
|
+
@JvmOverloads
|
|
139
|
+
fun createReactNativeFragment(
|
|
140
|
+
moduleName: String,
|
|
141
|
+
initialProps: Bundle? = null
|
|
142
|
+
): ReactNativeFragment {
|
|
143
|
+
val fragment = ReactNativeFragment()
|
|
144
|
+
val args = Bundle()
|
|
145
|
+
args.putString(ARG_COMPONENT_NAME, moduleName)
|
|
146
|
+
if (initialProps != null) {
|
|
147
|
+
args.putBundle(ARG_LAUNCH_OPTIONS, initialProps)
|
|
148
|
+
}
|
|
149
|
+
fragment.arguments = args
|
|
150
|
+
return fragment
|
|
141
151
|
}
|
|
142
152
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
153
|
+
@JvmStatic
|
|
154
|
+
fun createReactNativeFragment(
|
|
155
|
+
moduleName: String,
|
|
156
|
+
initialProps: HashMap<String, *>
|
|
157
|
+
): ReactNativeFragment {
|
|
158
|
+
return createReactNativeFragment(moduleName, PropsBundle.fromHashMap(initialProps))
|
|
149
159
|
}
|
|
150
160
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
args.putString(MODULE_NAME, moduleName)
|
|
158
|
-
if (initialProps != null) {
|
|
159
|
-
args.putBundle(INITIAL_PROPS, initialProps)
|
|
160
|
-
}
|
|
161
|
-
fragment.arguments = args
|
|
162
|
-
return fragment
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
@JvmStatic
|
|
166
|
-
fun createReactNativeFragment(moduleName: String, initialProps: HashMap<String, *>): ReactNativeFragment {
|
|
167
|
-
return createReactNativeFragment(moduleName, PropsBundle.fromHashMap(initialProps))
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
@JvmStatic
|
|
171
|
-
fun createReactNativeFragment(moduleName: String, initialProps: WritableMap): ReactNativeFragment {
|
|
172
|
-
return createReactNativeFragment(moduleName, initialProps.toHashMap())
|
|
173
|
-
}
|
|
161
|
+
@JvmStatic
|
|
162
|
+
fun createReactNativeFragment(
|
|
163
|
+
moduleName: String,
|
|
164
|
+
initialProps: WritableMap
|
|
165
|
+
): ReactNativeFragment {
|
|
166
|
+
return createReactNativeFragment(moduleName, initialProps.toHashMap())
|
|
174
167
|
}
|
|
168
|
+
}
|
|
175
169
|
|
|
176
|
-
}
|
|
170
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import React
|
|
2
|
+
import React_RCTAppDelegate
|
|
3
|
+
import ReactAppDependencyProvider
|
|
4
|
+
|
|
5
|
+
@objc public class ReactNativeBrownfield: RCTDefaultReactNativeFactoryDelegate {
|
|
6
|
+
@objc public static let shared = ReactNativeBrownfield()
|
|
7
|
+
private var onBundleLoaded: (() -> Void)?
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Path to JavaScript root.
|
|
11
|
+
* Default value: "index"
|
|
12
|
+
*/
|
|
13
|
+
@objc public var entryFile: String = "index"
|
|
14
|
+
/**
|
|
15
|
+
* Path to bundle fallback resource.
|
|
16
|
+
* Default value: nil
|
|
17
|
+
*/
|
|
18
|
+
@objc public var fallbackResource: String? = nil
|
|
19
|
+
/**
|
|
20
|
+
* Path to JavaScript bundle file.
|
|
21
|
+
* Default value: "main.jsbundle"
|
|
22
|
+
*/
|
|
23
|
+
@objc public var bundlePath: String = "main.jsbundle"
|
|
24
|
+
/**
|
|
25
|
+
* React Native factory instance created when starting React Native.
|
|
26
|
+
* Default value: nil
|
|
27
|
+
*/
|
|
28
|
+
@objc public var reactNativeFactory: RCTReactNativeFactory? = nil
|
|
29
|
+
/**
|
|
30
|
+
* Root view factory used to create React Native views.
|
|
31
|
+
*/
|
|
32
|
+
@objc lazy public var rootViewFactory: RCTRootViewFactory? = {
|
|
33
|
+
return reactNativeFactory?.rootViewFactory
|
|
34
|
+
}()
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Starts React Native with default parameters.
|
|
38
|
+
*/
|
|
39
|
+
@objc public func startReactNative() {
|
|
40
|
+
startReactNative(onBundleLoaded: nil)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Starts React Native with optional callback when bundle is loaded.
|
|
45
|
+
*
|
|
46
|
+
* @param onBundleLoaded Optional callback invoked after JS bundle is fully loaded.
|
|
47
|
+
*/
|
|
48
|
+
@objc public func startReactNative(onBundleLoaded: (() -> Void)?) {
|
|
49
|
+
startReactNative(onBundleLoaded: onBundleLoaded, launchOptions: nil)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Starts React Native with optional callback and launch options.
|
|
54
|
+
*
|
|
55
|
+
* @param onBundleLoaded Optional callback invoked after JS bundle is fully loaded.
|
|
56
|
+
* @param launchOptions Launch options, typically passed from AppDelegate.
|
|
57
|
+
*/
|
|
58
|
+
@objc public func startReactNative(onBundleLoaded: (() -> Void)?, launchOptions: [AnyHashable: Any]?) {
|
|
59
|
+
guard reactNativeFactory == nil else { return }
|
|
60
|
+
|
|
61
|
+
self.dependencyProvider = RCTAppDependencyProvider()
|
|
62
|
+
self.reactNativeFactory = RCTReactNativeFactory(delegate: self)
|
|
63
|
+
|
|
64
|
+
if let onBundleLoaded {
|
|
65
|
+
self.onBundleLoaded = onBundleLoaded
|
|
66
|
+
if RCTIsNewArchEnabled() {
|
|
67
|
+
NotificationCenter.default.addObserver(
|
|
68
|
+
self,
|
|
69
|
+
selector: #selector(jsLoaded),
|
|
70
|
+
name: NSNotification.Name("RCTInstanceDidLoadBundle"),
|
|
71
|
+
object: nil
|
|
72
|
+
)
|
|
73
|
+
} else {
|
|
74
|
+
NotificationCenter.default.addObserver(
|
|
75
|
+
self,
|
|
76
|
+
selector: #selector(jsLoaded),
|
|
77
|
+
name: NSNotification.Name("RCTJavaScriptDidLoadNotification"),
|
|
78
|
+
object: nil
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@objc private func jsLoaded(_ notification: Notification) {
|
|
85
|
+
onBundleLoaded?()
|
|
86
|
+
onBundleLoaded = nil
|
|
87
|
+
NotificationCenter.default.removeObserver(self)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// MARK: - RCTReactNativeFactoryDelegate Methods
|
|
91
|
+
|
|
92
|
+
@objc public override func sourceURL(for bridge: RCTBridge) -> URL? {
|
|
93
|
+
return bundleURL()
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public override func bundleURL() -> URL? {
|
|
97
|
+
#if DEBUG
|
|
98
|
+
return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: entryFile)
|
|
99
|
+
#else
|
|
100
|
+
let resourceURLComponents = bundlePath.components(separatedBy: ".")
|
|
101
|
+
let withoutLast = resourceURLComponents[..<(resourceURLComponents.count - 1)]
|
|
102
|
+
let resourceName = withoutLast.joined()
|
|
103
|
+
let fileExtension = resourceURLComponents.last ?? ""
|
|
104
|
+
|
|
105
|
+
return Bundle.main.url(forResource: resourceName, withExtension: fileExtension)
|
|
106
|
+
#endif
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
extension Notification.Name {
|
|
111
|
+
/**
|
|
112
|
+
* Notification sent when React Native wants to navigate back to native screen.
|
|
113
|
+
*/
|
|
114
|
+
public static let popToNative = Notification.Name("PopToNativeNotification")
|
|
115
|
+
/**
|
|
116
|
+
* Notification sent to enable/disable the pop gesture recognizer.
|
|
117
|
+
*/
|
|
118
|
+
public static let togglePopGestureRecognizer = Notification.Name("TogglePopGestureRecognizerNotification")
|
|
119
|
+
}
|
|
@@ -1,24 +1,21 @@
|
|
|
1
1
|
#import "ReactNativeBrownfieldModule.h"
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
#if __has_include("ReactNativeBrownfield/ReactNativeBrownfield-Swift.h")
|
|
4
|
+
#import "ReactNativeBrownfield/ReactNativeBrownfield-Swift.h"
|
|
5
|
+
#else
|
|
6
|
+
#import "ReactNativeBrownfield-Swift.h"
|
|
7
|
+
#endif
|
|
3
8
|
|
|
4
9
|
@implementation ReactNativeBrownfieldModule
|
|
5
10
|
|
|
6
11
|
RCT_EXPORT_MODULE(ReactNativeBrownfield);
|
|
7
12
|
|
|
8
13
|
RCT_EXPORT_METHOD(setPopGestureRecognizerEnabled:(BOOL)enabled) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
[[NSNotificationCenter defaultCenter]
|
|
12
|
-
postNotificationName:TogglePopGestureRecognizerNotification
|
|
13
|
-
object:nil userInfo:userInfo];
|
|
14
|
+
[ReactNativeBrownfieldModuleImpl setPopGestureRecognizerEnabled:enabled];
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
RCT_EXPORT_METHOD(popToNative:(BOOL)animated) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
[[NSNotificationCenter defaultCenter]
|
|
20
|
-
postNotificationName:PopToNativeNotification
|
|
21
|
-
object:nil userInfo:userInfo];
|
|
18
|
+
[ReactNativeBrownfieldModuleImpl popToNativeWithAnimated:animated];
|
|
22
19
|
}
|
|
23
20
|
|
|
24
21
|
@end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React
|
|
2
|
+
|
|
3
|
+
@objcMembers
|
|
4
|
+
public class ReactNativeBrownfieldModuleImpl: NSObject {
|
|
5
|
+
static public func setPopGestureRecognizerEnabled(_ enabled: Bool) {
|
|
6
|
+
let userInfo = ["enabled": enabled]
|
|
7
|
+
DispatchQueue.main.async {
|
|
8
|
+
NotificationCenter.default.post(name: Notification.Name.togglePopGestureRecognizer, object: nil, userInfo: userInfo)
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
static public func popToNative(animated: Bool) {
|
|
13
|
+
let userInfo = ["animated": animated]
|
|
14
|
+
DispatchQueue.main.async {
|
|
15
|
+
NotificationCenter.default.post(name: Notification.Name.popToNative, object: nil, userInfo: userInfo)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import SwiftUI
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
A UIViewControllerRepresentable that bridges ReactNativeViewController to SwiftUI.
|
|
5
|
+
*/
|
|
6
|
+
struct ReactNativeViewRepresentable: UIViewControllerRepresentable {
|
|
7
|
+
var moduleName: String
|
|
8
|
+
var initialProperties: [String: Any] = [:]
|
|
9
|
+
|
|
10
|
+
func makeUIViewController(context: Context) -> UIViewController {
|
|
11
|
+
return ReactNativeViewController(moduleName: moduleName)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
Exposes React Native view to SwiftUI.
|
|
19
|
+
Supports pop to native when using SwiftUI's NavigationView or NavigationStack.
|
|
20
|
+
*/
|
|
21
|
+
public struct ReactNativeView: View {
|
|
22
|
+
@Environment(\.dismiss) var dismiss
|
|
23
|
+
var moduleName: String
|
|
24
|
+
var initialProperties: [String: Any] = [:]
|
|
25
|
+
|
|
26
|
+
public init(moduleName: String, initialProperties: [String : Any] = [:]) {
|
|
27
|
+
self.moduleName = moduleName
|
|
28
|
+
self.initialProperties = initialProperties
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public var body: some View {
|
|
32
|
+
ReactNativeViewRepresentable(
|
|
33
|
+
moduleName: moduleName,
|
|
34
|
+
initialProperties: initialProperties
|
|
35
|
+
)
|
|
36
|
+
.ignoresSafeArea(.all)
|
|
37
|
+
.onReceive(NotificationCenter.default.publisher(for: NSNotification.Name.popToNative))
|
|
38
|
+
{ notification in
|
|
39
|
+
dismiss()
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import UIKit
|
|
2
|
+
import React
|
|
3
|
+
|
|
4
|
+
@objc public class ReactNativeViewController: UIViewController {
|
|
5
|
+
private var moduleName: String
|
|
6
|
+
private var initialProperties: [String: Any]?
|
|
7
|
+
|
|
8
|
+
@objc public init(moduleName: String, initialProperties: [String: Any]? = nil) {
|
|
9
|
+
self.moduleName = moduleName
|
|
10
|
+
self.initialProperties = initialProperties
|
|
11
|
+
super.init(nibName: nil, bundle: nil)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
required init?(coder: NSCoder) {
|
|
15
|
+
fatalError("init(coder:) has not been implemented")
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public override func viewDidLoad() {
|
|
19
|
+
super.viewDidLoad()
|
|
20
|
+
|
|
21
|
+
guard let factory = ReactNativeBrownfield.shared.rootViewFactory else {
|
|
22
|
+
print("Error: You need to start React Native in order to use ReactNativeViewController, make sure to run BridgeManager.shared.startReactNative() before instantiating it.")
|
|
23
|
+
return
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if !moduleName.isEmpty {
|
|
27
|
+
view = factory.view(withModuleName: moduleName, initialProperties: initialProperties)
|
|
28
|
+
|
|
29
|
+
NotificationCenter.default.addObserver(
|
|
30
|
+
self,
|
|
31
|
+
selector: #selector(togglePopGestureRecognizer(_:)),
|
|
32
|
+
name: NSNotification.Name.togglePopGestureRecognizer,
|
|
33
|
+
object: nil
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
NotificationCenter.default.addObserver(
|
|
37
|
+
self,
|
|
38
|
+
selector: #selector(popToNative(_:)),
|
|
39
|
+
name: NSNotification.Name.popToNative,
|
|
40
|
+
object: nil
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
deinit {
|
|
46
|
+
NotificationCenter.default.removeObserver(self)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@objc private func togglePopGestureRecognizer(_ notification: Notification) {
|
|
50
|
+
guard let userInfo = notification.userInfo,
|
|
51
|
+
let enabled = userInfo["enabled"] as? Bool else { return }
|
|
52
|
+
|
|
53
|
+
DispatchQueue.main.async { [weak self] in
|
|
54
|
+
self?.navigationController?.interactivePopGestureRecognizer?.isEnabled = enabled
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@objc private func popToNative(_ notification: Notification) {
|
|
59
|
+
guard let userInfo = notification.userInfo,
|
|
60
|
+
let animated = userInfo["animated"] as? Bool else { return }
|
|
61
|
+
|
|
62
|
+
DispatchQueue.main.async { [weak self] in
|
|
63
|
+
self?.navigationController?.popViewController(animated: animated)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _reactNative = require("react-native");
|
|
8
|
+
var _default = exports.default = _reactNative.TurboModuleRegistry.getEnforcing('ReactNativeBrownfield');
|
|
9
|
+
//# sourceMappingURL=RNBrownfieldSpec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_reactNative","require","_default","exports","default","TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["RNBrownfieldSpec.ts"],"mappings":";;;;;;AACA,IAAAA,YAAA,GAAAC,OAAA;AAAmD,IAAAC,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAqBpCC,gCAAmB,CAACC,YAAY,CAAO,uBAAuB,CAAC","ignoreList":[]}
|
package/lib/commonjs/index.js
CHANGED
|
@@ -5,21 +5,23 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _reactNative = require("react-native");
|
|
8
|
+
var _RNBrownfieldSpec = _interopRequireDefault(require("./RNBrownfieldSpec"));
|
|
9
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
10
|
const ReactNativeBrownfield = {
|
|
9
11
|
popToNative: animated => {
|
|
10
12
|
if (_reactNative.Platform.OS === 'ios') {
|
|
11
|
-
|
|
13
|
+
_RNBrownfieldSpec.default.popToNative(animated);
|
|
12
14
|
} else if (_reactNative.Platform.OS === 'android') {
|
|
13
|
-
|
|
15
|
+
_RNBrownfieldSpec.default.popToNative();
|
|
14
16
|
} else {
|
|
15
17
|
console.warn('Not implemented: popToNative');
|
|
16
18
|
}
|
|
17
19
|
},
|
|
18
20
|
setNativeBackGestureAndButtonEnabled: enabled => {
|
|
19
21
|
if (_reactNative.Platform.OS === 'ios') {
|
|
20
|
-
|
|
22
|
+
_RNBrownfieldSpec.default.setPopGestureRecognizerEnabled(enabled);
|
|
21
23
|
} else if (_reactNative.Platform.OS === 'android') {
|
|
22
|
-
|
|
24
|
+
_RNBrownfieldSpec.default.setHardwareBackButtonEnabled(enabled);
|
|
23
25
|
} else {
|
|
24
26
|
console.warn('Not implemented: setNativeGesturesAndButtonsEnabled');
|
|
25
27
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","ReactNativeBrownfield","popToNative","animated","Platform","OS","
|
|
1
|
+
{"version":3,"names":["_reactNative","require","_RNBrownfieldSpec","_interopRequireDefault","e","__esModule","default","ReactNativeBrownfield","popToNative","animated","Platform","OS","ReactNativeBrownfieldModule","console","warn","setNativeBackGestureAndButtonEnabled","enabled","setPopGestureRecognizerEnabled","setHardwareBackButtonEnabled","_default","exports"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AACA,IAAAC,iBAAA,GAAAC,sBAAA,CAAAF,OAAA;AAA6D,SAAAE,uBAAAC,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAE7D,MAAMG,qBAAqB,GAAG;EAC5BC,WAAW,EAAGC,QAAkB,IAAW;IACzC,IAAIC,qBAAQ,CAACC,EAAE,KAAK,KAAK,EAAE;MACzBC,yBAA2B,CAACJ,WAAW,CAACC,QAAQ,CAAC;IACnD,CAAC,MAAM,IAAIC,qBAAQ,CAACC,EAAE,KAAK,SAAS,EAAE;MACpCC,yBAA2B,CAACJ,WAAW,CAAC,CAAC;IAC3C,CAAC,MAAM;MACLK,OAAO,CAACC,IAAI,CAAC,8BAA8B,CAAC;IAC9C;EACF,CAAC;EAEDC,oCAAoC,EAAGC,OAAgB,IAAW;IAChE,IAAIN,qBAAQ,CAACC,EAAE,KAAK,KAAK,EAAE;MACzBC,yBAA2B,CAACK,8BAA8B,CAACD,OAAO,CAAC;IACrE,CAAC,MAAM,IAAIN,qBAAQ,CAACC,EAAE,KAAK,SAAS,EAAE;MACpCC,yBAA2B,CAACM,4BAA4B,CAACF,OAAO,CAAC;IACnE,CAAC,MAAM;MACLH,OAAO,CAACC,IAAI,CAAC,qDAAqD,CAAC;IACrE;EACF;AACF,CAAC;AAAC,IAAAK,QAAA,GAAAC,OAAA,CAAAd,OAAA,GAEaC,qBAAqB","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["RNBrownfieldSpec.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;AAqBlD,eAAeA,mBAAmB,CAACC,YAAY,CAAO,uBAAuB,CAAC","ignoreList":[]}
|