@callstack/react-native-brownfield 5.3.0 → 6.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 +12 -0
- package/android/build.gradle +1 -0
- package/android/consumer-rules.pro +6 -0
- package/android/src/main/java/com/callstack/reactnativebrownfield/BrownfieldPerformance.kt +384 -0
- package/android/src/main/java/com/callstack/reactnativebrownfield/BrownfieldPerformanceModule.kt +15 -0
- package/android/src/main/java/com/callstack/reactnativebrownfield/ReactDelegateWrapper.kt +8 -5
- package/android/src/main/java/com/callstack/reactnativebrownfield/ReactNativeBrownfield.kt +78 -23
- package/android/src/main/java/com/callstack/reactnativebrownfield/ReactNativeBrownfieldPackage.kt +1 -0
- package/android/src/main/java/com/callstack/reactnativebrownfield/ReactNativeFragment.kt +89 -3
- package/android/src/main/java/com/callstack/reactnativebrownfield/constants/ReactNativeFragmentArgNames.kt +2 -0
- package/android/src/test/java/com/callstack/reactnativebrownfield/PerformanceMetricsTest.kt +54 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNSourceSets.kt +59 -15
- package/gradle-plugin/brownfield/src/test/kotlin/com/callstack/react/brownfield/plugin/AgpCompatibilityMatrixTest.kt +6 -8
- package/gradle-plugin/brownfield/src/test/kotlin/com/callstack/react/brownfield/plugin/LegacyConsumerConfigurationTest.kt +6 -4
- package/gradle-plugin/brownfield/src/test/kotlin/com/callstack/react/brownfield/plugin/RNBundleTaskStubs.kt +27 -0
- package/ios/BrownfieldDisplayMetrics.swift +265 -0
- package/ios/BrownfieldPerformanceBridge.h +8 -0
- package/ios/BrownfieldPerformanceBridge.mm +103 -0
- package/ios/Expo/ExpoHostRuntime.swift +58 -14
- package/ios/Expo/ExpoUpdatesStartup.swift +49 -0
- package/ios/JSBundleLoadObserver.swift +56 -19
- package/ios/JSBundleTimingObserver.h +26 -0
- package/ios/JSBundleTimingObserver.m +140 -0
- package/ios/ReactHostPreloading.swift +7 -3
- package/ios/ReactNativeBrownfield.swift +82 -14
- package/ios/ReactNativeBrownfield.xcodeproj/project.pbxproj +16 -0
- package/ios/Vanilla/ReactNativeHostRuntime.swift +1 -1
- package/ios/Views/ReactNativeView.swift +21 -3
- package/ios/Views/ReactNativeViewController.swift +44 -42
- package/lib/commonjs/expo-config-plugin/template/android/consumer-rules.pro +7 -0
- package/lib/commonjs/index.js +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/expo-config-plugin/template/android/consumer-rules.pro +7 -0
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/commonjs/src/index.d.ts +7 -0
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
- package/lib/typescript/module/src/index.d.ts +7 -0
- package/lib/typescript/module/src/index.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/expo-config-plugin/template/android/consumer-rules.pro +7 -0
- package/src/index.ts +13 -1
|
@@ -4,6 +4,35 @@ import UIKit
|
|
|
4
4
|
internal import Expo
|
|
5
5
|
#endif
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* JS bundle timings from React Native's performance logger.
|
|
9
|
+
*
|
|
10
|
+
* - `jsBundleLoadTime` is `RCTPLScriptDownload` (Metro HTTP in Debug, file read in Release).
|
|
11
|
+
* - `jsBundleEvaluationTime` is `RCTPLScriptExecution`.
|
|
12
|
+
*
|
|
13
|
+
* A tag field is `nil` when the tag never completed (failed load, logger missing, or
|
|
14
|
+
* bridgeless React Native below 0.87).
|
|
15
|
+
*/
|
|
16
|
+
@objc public class JSBundleTimings: NSObject {
|
|
17
|
+
@objc public let jsBundleLoadTime: NSNumber?
|
|
18
|
+
@objc public let jsBundleEvaluationTime: NSNumber?
|
|
19
|
+
@objc public let timeline: [[String: Any]]
|
|
20
|
+
|
|
21
|
+
@objc public init(jsBundleLoadTime: NSNumber?, jsBundleEvaluationTime: NSNumber?) {
|
|
22
|
+
self.timeline = []
|
|
23
|
+
self.jsBundleLoadTime = jsBundleLoadTime
|
|
24
|
+
self.jsBundleEvaluationTime = jsBundleEvaluationTime
|
|
25
|
+
super.init()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@objc public init(jsBundleLoadTime: NSNumber?, jsBundleEvaluationTime: NSNumber?, timeline: [[String: Any]]) {
|
|
29
|
+
self.jsBundleLoadTime = jsBundleLoadTime
|
|
30
|
+
self.jsBundleEvaluationTime = jsBundleEvaluationTime
|
|
31
|
+
self.timeline = timeline
|
|
32
|
+
super.init()
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
7
36
|
@objc public class ReactNativeBrownfield: NSObject {
|
|
8
37
|
public static let shared = ReactNativeBrownfield()
|
|
9
38
|
|
|
@@ -100,6 +129,7 @@ internal import Expo
|
|
|
100
129
|
* Stops React Native.
|
|
101
130
|
*/
|
|
102
131
|
@objc public func stopReactNative() {
|
|
132
|
+
NotificationCenter.default.post(name: Notification.Name("BrownfieldPerformanceStop"), object: nil)
|
|
103
133
|
#if canImport(Expo)
|
|
104
134
|
ExpoHostRuntime.shared.stopReactNative()
|
|
105
135
|
#else
|
|
@@ -112,19 +142,57 @@ internal import Expo
|
|
|
112
142
|
initialProps: [AnyHashable: Any]?,
|
|
113
143
|
launchOptions: [AnyHashable: Any]? = nil
|
|
114
144
|
) -> UIView? {
|
|
145
|
+
makeView(moduleName: moduleName, initialProps: initialProps, launchOptions: launchOptions,
|
|
146
|
+
session: nil, isHostVisible: nil)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/// Creates a measured presentation. The completion receives one immutable snapshot on main.
|
|
150
|
+
/// Opt in to wait for JS `markFullyDisplayed(brownfieldPresentationID)`.
|
|
151
|
+
/// Thread sampling requires both collectThreadMetrics and an onMetrics callback.
|
|
152
|
+
@objc public func view(
|
|
153
|
+
moduleName: String,
|
|
154
|
+
initialProps: [AnyHashable: Any]?,
|
|
155
|
+
launchOptions: [AnyHashable: Any]? = nil,
|
|
156
|
+
waitForFullDisplay: Bool = false,
|
|
157
|
+
collectThreadMetrics: Bool = false,
|
|
158
|
+
onMetrics: ((BrownfieldDisplayMetrics) -> Void)?
|
|
159
|
+
) -> UIView? {
|
|
160
|
+
let session = BrownfieldDisplaySession(moduleName: moduleName,
|
|
161
|
+
waitForFullDisplay: waitForFullDisplay, collectThreadMetrics: collectThreadMetrics,
|
|
162
|
+
callback: onMetrics)
|
|
163
|
+
return makeView(moduleName: moduleName, initialProps: initialProps,
|
|
164
|
+
launchOptions: launchOptions, session: session, isHostVisible: nil)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/// Only measured presentations get a session. Without one, `initialProps` pass through as is.
|
|
168
|
+
/// `isHostVisible` is set by `ReactNativeViewController`, which reports appearance itself.
|
|
169
|
+
internal func makeView(moduleName: String, initialProps: [AnyHashable: Any]?,
|
|
170
|
+
launchOptions: [AnyHashable: Any]?, session: BrownfieldDisplaySession?,
|
|
171
|
+
isHostVisible: (() -> Bool)?) -> UIView? {
|
|
172
|
+
var props = initialProps
|
|
173
|
+
if let session {
|
|
174
|
+
props = (props ?? [:]).merging(["brownfieldPresentationID": session.id]) { $1 }
|
|
175
|
+
}
|
|
176
|
+
// The probe goes into the React Native root, not into a placeholder, so initial display
|
|
177
|
+
// can't complete before the root exists.
|
|
178
|
+
let attachProbe: (UIView?) -> Void = { rootView in
|
|
179
|
+
guard let session else { return }
|
|
180
|
+
guard let rootView else { session.cancel(); return }
|
|
181
|
+
let probe = BrownfieldAppearanceProbe(session: session)
|
|
182
|
+
probe.isHostVisible = isHostVisible
|
|
183
|
+
session.hasRootView = true
|
|
184
|
+
rootView.addSubview(probe)
|
|
185
|
+
}
|
|
115
186
|
#if canImport(Expo)
|
|
116
|
-
ExpoHostRuntime.shared.view(
|
|
117
|
-
|
|
118
|
-
initialProps: initialProps,
|
|
119
|
-
launchOptions: launchOptions
|
|
120
|
-
)
|
|
187
|
+
let view = ExpoHostRuntime.shared.view(moduleName: moduleName, initialProps: props,
|
|
188
|
+
launchOptions: launchOptions, onRootView: attachProbe)
|
|
121
189
|
#else
|
|
122
|
-
ReactNativeHostRuntime.shared.view(
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
launchOptions: launchOptions
|
|
126
|
-
)
|
|
190
|
+
let view = ReactNativeHostRuntime.shared.view(moduleName: moduleName, initialProps: props,
|
|
191
|
+
launchOptions: launchOptions)
|
|
192
|
+
attachProbe(view)
|
|
127
193
|
#endif
|
|
194
|
+
if view == nil { session?.cancel() }
|
|
195
|
+
return view
|
|
128
196
|
}
|
|
129
197
|
|
|
130
198
|
/**
|
|
@@ -193,10 +261,10 @@ internal import Expo
|
|
|
193
261
|
* Starts React Native with optional callback when bundle is loaded.
|
|
194
262
|
*
|
|
195
263
|
* @param onBundleLoaded Optional callback invoked on the main thread after the JS bundle is
|
|
196
|
-
* fully loaded. It runs in the next turn of the main run loop
|
|
197
|
-
* loaded. A new callback replaces the callback that waits.
|
|
264
|
+
* fully loaded. It receives `JSBundleTimings`. It runs in the next turn of the main run loop
|
|
265
|
+
* when the bundle is already loaded. A new callback replaces the callback that waits.
|
|
198
266
|
*/
|
|
199
|
-
@objc public func startReactNative(onBundleLoaded: (() -> Void)?) {
|
|
267
|
+
@objc public func startReactNative(onBundleLoaded: ((JSBundleTimings) -> Void)?) {
|
|
200
268
|
#if canImport(Expo)
|
|
201
269
|
ExpoHostRuntime.shared.startReactNative(onBundleLoaded: onBundleLoaded)
|
|
202
270
|
#else
|
|
@@ -220,7 +288,7 @@ internal import Expo
|
|
|
220
288
|
@objc public func startReactNative(
|
|
221
289
|
launchOptions: [AnyHashable: Any]?,
|
|
222
290
|
preloadBundle: Bool,
|
|
223
|
-
onBundleLoaded: (() -> Void)?
|
|
291
|
+
onBundleLoaded: ((JSBundleTimings) -> Void)?
|
|
224
292
|
) {
|
|
225
293
|
#if canImport(Expo)
|
|
226
294
|
ExpoHostRuntime.shared.startReactNative(
|
|
@@ -17,6 +17,9 @@
|
|
|
17
17
|
79FEE77E2FB499E400E407DE /* ReactNativeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79FEE77C2FB499E400E407DE /* ReactNativeViewController.swift */; };
|
|
18
18
|
79FEE7802FB499EC00E407DE /* ReactNativeHostRuntime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79FEE77F2FB499EC00E407DE /* ReactNativeHostRuntime.swift */; };
|
|
19
19
|
79FEE7822FB499F300E407DE /* ExpoHostRuntime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79FEE7812FB499F300E407DE /* ExpoHostRuntime.swift */; };
|
|
20
|
+
79FEE7852FB500A100E407DE /* JSBundleTimingObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 79FEE7842FB500A100E407DE /* JSBundleTimingObserver.m */; };
|
|
21
|
+
BEAF10000000000000000000 /* BrownfieldDisplayMetrics.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEAF00000000000000000000 /* BrownfieldDisplayMetrics.swift */; };
|
|
22
|
+
BEAF10000000000000000002 /* BrownfieldPerformanceBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = BEAF00000000000000000002 /* BrownfieldPerformanceBridge.mm */; };
|
|
20
23
|
/* End PBXBuildFile section */
|
|
21
24
|
|
|
22
25
|
/* Begin PBXCopyFilesBuildPhase section */
|
|
@@ -44,6 +47,11 @@
|
|
|
44
47
|
79FEE77C2FB499E400E407DE /* ReactNativeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactNativeViewController.swift; sourceTree = "<group>"; };
|
|
45
48
|
79FEE77F2FB499EC00E407DE /* ReactNativeHostRuntime.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactNativeHostRuntime.swift; sourceTree = "<group>"; };
|
|
46
49
|
79FEE7812FB499F300E407DE /* ExpoHostRuntime.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpoHostRuntime.swift; sourceTree = "<group>"; };
|
|
50
|
+
79FEE7832FB500A100E407DE /* JSBundleTimingObserver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSBundleTimingObserver.h; sourceTree = "<group>"; };
|
|
51
|
+
79FEE7842FB500A100E407DE /* JSBundleTimingObserver.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JSBundleTimingObserver.m; sourceTree = "<group>"; };
|
|
52
|
+
BEAF00000000000000000000 /* BrownfieldDisplayMetrics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrownfieldDisplayMetrics.swift; sourceTree = "<group>"; };
|
|
53
|
+
BEAF00000000000000000001 /* BrownfieldPerformanceBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BrownfieldPerformanceBridge.h; sourceTree = "<group>"; };
|
|
54
|
+
BEAF00000000000000000002 /* BrownfieldPerformanceBridge.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = BrownfieldPerformanceBridge.mm; sourceTree = "<group>"; };
|
|
47
55
|
/* End PBXFileReference section */
|
|
48
56
|
|
|
49
57
|
/* Begin PBXFrameworksBuildPhase section */
|
|
@@ -65,7 +73,12 @@
|
|
|
65
73
|
79FEE7692FB4997100E407DE /* Expo */,
|
|
66
74
|
696CB22A230EF910000207AF /* Products */,
|
|
67
75
|
79FEE76D2FB499C700E407DE /* BrownfieldBundlePathResolver.swift */,
|
|
76
|
+
BEAF00000000000000000000 /* BrownfieldDisplayMetrics.swift */,
|
|
77
|
+
BEAF00000000000000000001 /* BrownfieldPerformanceBridge.h */,
|
|
78
|
+
BEAF00000000000000000002 /* BrownfieldPerformanceBridge.mm */,
|
|
68
79
|
79FEE76E2FB499C700E407DE /* JSBundleLoadObserver.swift */,
|
|
80
|
+
79FEE7832FB500A100E407DE /* JSBundleTimingObserver.h */,
|
|
81
|
+
79FEE7842FB500A100E407DE /* JSBundleTimingObserver.m */,
|
|
69
82
|
79FEE76F2FB499C700E407DE /* Notification+Brownfield.swift */,
|
|
70
83
|
79FEE7702FB499C700E407DE /* ReactNativeBrownfield.swift */,
|
|
71
84
|
79FEE7712FB499C700E407DE /* ReactNativeBrownfieldModule.h */,
|
|
@@ -170,7 +183,10 @@
|
|
|
170
183
|
79FEE7762FB499C700E407DE /* Notification+Brownfield.swift in Sources */,
|
|
171
184
|
79FEE7822FB499F300E407DE /* ExpoHostRuntime.swift in Sources */,
|
|
172
185
|
79FEE7772FB499C700E407DE /* ReactNativeBrownfieldModule.swift in Sources */,
|
|
186
|
+
BEAF10000000000000000000 /* BrownfieldDisplayMetrics.swift in Sources */,
|
|
187
|
+
BEAF10000000000000000002 /* BrownfieldPerformanceBridge.mm in Sources */,
|
|
173
188
|
79FEE7782FB499C700E407DE /* JSBundleLoadObserver.swift in Sources */,
|
|
189
|
+
79FEE7852FB500A100E407DE /* JSBundleTimingObserver.m in Sources */,
|
|
174
190
|
79FEE7792FB499C700E407DE /* ReactNativeBrownfield.swift in Sources */,
|
|
175
191
|
79FEE77D2FB499E400E407DE /* ReactNativeView.swift in Sources */,
|
|
176
192
|
79FEE77E2FB499E400E407DE /* ReactNativeViewController.swift in Sources */,
|
|
@@ -191,7 +191,7 @@ final class ReactNativeHostRuntime {
|
|
|
191
191
|
*
|
|
192
192
|
* @param onBundleLoaded Optional callback invoked on the main thread after JS bundle is fully loaded.
|
|
193
193
|
*/
|
|
194
|
-
public func startReactNative(onBundleLoaded: (() -> Void)?) {
|
|
194
|
+
public func startReactNative(onBundleLoaded: ((JSBundleTimings) -> Void)?) {
|
|
195
195
|
// The callback registration is outside of the guard below. An earlier `startReactNative` call
|
|
196
196
|
// can already have made the factory, and the callback must still run.
|
|
197
197
|
if let onBundleLoaded {
|
|
@@ -17,11 +17,17 @@ struct ReactNativeViewRepresentable: UIViewControllerRepresentable {
|
|
|
17
17
|
var moduleName: String
|
|
18
18
|
var initialProperties: [String: Any] = [:]
|
|
19
19
|
var host: BrownfieldSurfaceHost
|
|
20
|
+
var waitForFullDisplay = false
|
|
21
|
+
var collectThreadMetrics = false
|
|
22
|
+
var onMetrics: ((BrownfieldDisplayMetrics) -> Void)?
|
|
20
23
|
|
|
21
24
|
func makeUIViewController(context: Context) -> UIViewController {
|
|
22
25
|
let controller = ReactNativeViewController(
|
|
23
26
|
moduleName: moduleName,
|
|
24
|
-
initialProperties: initialProperties
|
|
27
|
+
initialProperties: initialProperties,
|
|
28
|
+
waitForFullDisplay: waitForFullDisplay,
|
|
29
|
+
collectThreadMetrics: collectThreadMetrics,
|
|
30
|
+
onMetrics: onMetrics
|
|
25
31
|
)
|
|
26
32
|
controller.isHostedBySwiftUI = true
|
|
27
33
|
host.controller = controller
|
|
@@ -45,17 +51,29 @@ public struct ReactNativeView: View {
|
|
|
45
51
|
@State private var host = BrownfieldSurfaceHost()
|
|
46
52
|
var moduleName: String
|
|
47
53
|
var initialProperties: [String: Any] = [:]
|
|
54
|
+
var waitForFullDisplay = false
|
|
55
|
+
var collectThreadMetrics = false
|
|
56
|
+
var onMetrics: ((BrownfieldDisplayMetrics) -> Void)?
|
|
48
57
|
|
|
49
|
-
public init(moduleName: String, initialProperties: [String : Any] = [:]
|
|
58
|
+
public init(moduleName: String, initialProperties: [String : Any] = [:],
|
|
59
|
+
waitForFullDisplay: Bool = false,
|
|
60
|
+
collectThreadMetrics: Bool = false,
|
|
61
|
+
onMetrics: ((BrownfieldDisplayMetrics) -> Void)? = nil) {
|
|
50
62
|
self.moduleName = moduleName
|
|
51
63
|
self.initialProperties = initialProperties
|
|
64
|
+
self.waitForFullDisplay = waitForFullDisplay
|
|
65
|
+
self.collectThreadMetrics = collectThreadMetrics
|
|
66
|
+
self.onMetrics = onMetrics
|
|
52
67
|
}
|
|
53
68
|
|
|
54
69
|
public var body: some View {
|
|
55
70
|
ReactNativeViewRepresentable(
|
|
56
71
|
moduleName: moduleName,
|
|
57
72
|
initialProperties: initialProperties,
|
|
58
|
-
host: host
|
|
73
|
+
host: host,
|
|
74
|
+
waitForFullDisplay: waitForFullDisplay,
|
|
75
|
+
collectThreadMetrics: collectThreadMetrics,
|
|
76
|
+
onMetrics: onMetrics
|
|
59
77
|
)
|
|
60
78
|
.ignoresSafeArea(.all)
|
|
61
79
|
// `.popToNative` is public API and may be posted from any thread, while
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import UIKit
|
|
2
2
|
internal import React
|
|
3
|
-
#if canImport(EXUpdates)
|
|
4
|
-
internal import EXUpdates
|
|
5
|
-
#endif
|
|
6
3
|
|
|
7
4
|
@objc public class ReactNativeViewController: UIViewController {
|
|
8
5
|
private var moduleName: String
|
|
@@ -26,38 +23,46 @@ internal import EXUpdates
|
|
|
26
23
|
guard let surfaceID else { return false }
|
|
27
24
|
return BrownfieldSurfaceRegistry.shared.isPopTarget(surfaceID)
|
|
28
25
|
}
|
|
26
|
+
private var waitForFullDisplay = false
|
|
27
|
+
private var collectThreadMetrics = false
|
|
28
|
+
private var onMetrics: ((BrownfieldDisplayMetrics) -> Void)?
|
|
29
|
+
private var isMeasured = false
|
|
30
|
+
private var displaySession: BrownfieldDisplaySession?
|
|
31
|
+
private var isVisible = false
|
|
29
32
|
|
|
30
|
-
#if canImport(EXUpdates)
|
|
31
|
-
private let expoUpdatesDelegate = ReactNativeExpoUpdatesDelegate()
|
|
32
|
-
#endif
|
|
33
|
-
|
|
34
33
|
|
|
35
34
|
@objc public init(moduleName: String, initialProperties: [String: Any]? = nil) {
|
|
36
35
|
self.moduleName = moduleName
|
|
37
36
|
self.initialProperties = initialProperties
|
|
38
|
-
#if canImport(EXUpdates)
|
|
39
|
-
AppController.sharedInstance.delegate = expoUpdatesDelegate
|
|
40
|
-
AppController.sharedInstance.start()
|
|
41
|
-
#endif
|
|
42
37
|
super.init(nibName: nil, bundle: nil)
|
|
43
38
|
}
|
|
44
39
|
|
|
40
|
+
@objc public convenience init(moduleName: String, initialProperties: [String: Any]? = nil,
|
|
41
|
+
waitForFullDisplay: Bool = false,
|
|
42
|
+
collectThreadMetrics: Bool = false,
|
|
43
|
+
onMetrics: ((BrownfieldDisplayMetrics) -> Void)?) {
|
|
44
|
+
self.init(moduleName: moduleName, initialProperties: initialProperties)
|
|
45
|
+
self.waitForFullDisplay = waitForFullDisplay
|
|
46
|
+
self.collectThreadMetrics = collectThreadMetrics
|
|
47
|
+
self.onMetrics = onMetrics
|
|
48
|
+
self.isMeasured = true
|
|
49
|
+
}
|
|
50
|
+
|
|
45
51
|
required init?(coder: NSCoder) {
|
|
46
52
|
fatalError("init(coder:) has not been implemented")
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
public override func viewDidLoad() {
|
|
50
56
|
super.viewDidLoad()
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
if isMeasured {
|
|
58
|
+
displaySession = BrownfieldDisplaySession(moduleName: moduleName,
|
|
59
|
+
waitForFullDisplay: waitForFullDisplay, collectThreadMetrics: collectThreadMetrics,
|
|
60
|
+
callback: onMetrics)
|
|
54
61
|
}
|
|
55
|
-
|
|
62
|
+
onMetrics = nil
|
|
56
63
|
|
|
57
64
|
if !moduleName.isEmpty {
|
|
58
|
-
#if !canImport(EXUpdates)
|
|
59
65
|
renderReactNativeView()
|
|
60
|
-
#endif
|
|
61
66
|
|
|
62
67
|
// Visibility is resolved live: SwiftUI recreates hosted controllers, so a
|
|
63
68
|
// cached lifecycle flag is stale when the notification arrives.
|
|
@@ -100,7 +105,23 @@ internal import EXUpdates
|
|
|
100
105
|
isDisappearing = true
|
|
101
106
|
}
|
|
102
107
|
|
|
108
|
+
public override func viewDidAppear(_ animated: Bool) {
|
|
109
|
+
super.viewDidAppear(animated)
|
|
110
|
+
isVisible = true
|
|
111
|
+
// Expo Updates may not have created the RN root yet. The probe reports it when it arrives.
|
|
112
|
+
if displaySession?.hasRootView == true {
|
|
113
|
+
displaySession?.appeared()
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
public override func viewDidDisappear(_ animated: Bool) {
|
|
118
|
+
super.viewDidDisappear(animated)
|
|
119
|
+
isVisible = false
|
|
120
|
+
displaySession?.cancel()
|
|
121
|
+
}
|
|
122
|
+
|
|
103
123
|
deinit {
|
|
124
|
+
displaySession?.cancel()
|
|
104
125
|
NotificationCenter.default.removeObserver(self)
|
|
105
126
|
|
|
106
127
|
if let surfaceID {
|
|
@@ -202,35 +223,16 @@ internal import EXUpdates
|
|
|
202
223
|
|
|
203
224
|
DispatchQueue.main.async { [weak self] in
|
|
204
225
|
guard let self else { return }
|
|
205
|
-
|
|
226
|
+
let session = self.displaySession
|
|
227
|
+
guard let reactView = ReactNativeBrownfield.shared.makeView(
|
|
206
228
|
moduleName: self.moduleName,
|
|
207
229
|
initialProps: self.initialProperties,
|
|
208
|
-
launchOptions: nil
|
|
230
|
+
launchOptions: nil,
|
|
231
|
+
session: session,
|
|
232
|
+
isHostVisible: { [weak self] in self?.isVisible == true }
|
|
209
233
|
) else { return }
|
|
210
234
|
self.view = reactView
|
|
235
|
+
if self.isVisible, session?.hasRootView == true { session?.appeared() }
|
|
211
236
|
}
|
|
212
237
|
}
|
|
213
238
|
}
|
|
214
|
-
|
|
215
|
-
#if canImport(EXUpdates)
|
|
216
|
-
private final class ReactNativeExpoUpdatesDelegate: NSObject, AppControllerDelegate {
|
|
217
|
-
private var didStartSuccessfully = false
|
|
218
|
-
var onDidStart: (() -> Void)? {
|
|
219
|
-
didSet {
|
|
220
|
-
if didStartSuccessfully {
|
|
221
|
-
onDidStart?()
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
func appController(_ appController: any EXUpdates.AppControllerInterface, didStartWithSuccess success: Bool) {
|
|
227
|
-
guard success else {
|
|
228
|
-
NSLog("%@", "Expo Updates failed to start React Native.")
|
|
229
|
-
return
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
didStartSuccessfully = true
|
|
233
|
-
onDidStart?()
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
#endif
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
-keep interface com.callstack.reactnativebrownfield.OnJSBundleLoaded { *; }
|
|
2
|
+
-keep interface com.callstack.reactnativebrownfield.OnDisplayMetrics { *; }
|
|
3
|
+
-keep class com.callstack.reactnativebrownfield.JSBundleTimings { *; }
|
|
4
|
+
-keep class com.callstack.reactnativebrownfield.BrownfieldDisplayMetrics { *; }
|
|
5
|
+
-keep class com.callstack.reactnativebrownfield.BrownfieldDisplayInterval { *; }
|
|
6
|
+
-keep class com.callstack.reactnativebrownfield.BrownfieldThreadMetrics { *; }
|
|
7
|
+
-keep class com.callstack.reactnativebrownfield.BrownfieldPerformanceModule { *; }
|
package/lib/commonjs/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.default=void 0;var _reactNative=require("react-native");var _NativeReactNativeBrownfieldModule=_interopRequireDefault(require("./NativeReactNativeBrownfieldModule"));var ReactNativeBrownfield={popToNative:function popToNative(animated){if(_reactNative.Platform.OS==='ios'){_NativeReactNativeBrownfieldModule.default.popToNative(!!animated);}else if(_reactNative.Platform.OS==='android'){_NativeReactNativeBrownfieldModule.default.popToNative(false);}else{console.warn('Not implemented: popToNative');}},setNativeBackGestureAndButtonEnabled:function setNativeBackGestureAndButtonEnabled(enabled){if(_reactNative.Platform.OS==='ios'){_NativeReactNativeBrownfieldModule.default.setPopGestureRecognizerEnabled(enabled);}else if(_reactNative.Platform.OS==='android'){_NativeReactNativeBrownfieldModule.default.setHardwareBackButtonEnabled(enabled);}else{console.warn('Not implemented: setNativeGesturesAndButtonsEnabled');}},postMessage:function postMessage(data){var serialized=JSON.stringify(data);_NativeReactNativeBrownfieldModule.default.postMessage(serialized);},onMessage:function onMessage(callback){var subscription=_NativeReactNativeBrownfieldModule.default.onBrownfieldMessage(function(payload){try{callback({data:JSON.parse(payload.text)});}catch(_unused){callback({data:payload.text});}});return{remove:function remove(){return subscription.remove();}};}};var _default=exports.default=ReactNativeBrownfield;
|
|
1
|
+
var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.default=void 0;var _reactNative=require("react-native");var _NativeReactNativeBrownfieldModule=_interopRequireDefault(require("./NativeReactNativeBrownfieldModule"));var ReactNativeBrownfield={markFullyDisplayed:function markFullyDisplayed(presentationID){if(_reactNative.Platform.OS==='ios'||_reactNative.Platform.OS==='android'){_reactNative.NativeModules.BrownfieldPerformance.markFullyDisplayed(presentationID);}},popToNative:function popToNative(animated){if(_reactNative.Platform.OS==='ios'){_NativeReactNativeBrownfieldModule.default.popToNative(!!animated);}else if(_reactNative.Platform.OS==='android'){_NativeReactNativeBrownfieldModule.default.popToNative(false);}else{console.warn('Not implemented: popToNative');}},setNativeBackGestureAndButtonEnabled:function setNativeBackGestureAndButtonEnabled(enabled){if(_reactNative.Platform.OS==='ios'){_NativeReactNativeBrownfieldModule.default.setPopGestureRecognizerEnabled(enabled);}else if(_reactNative.Platform.OS==='android'){_NativeReactNativeBrownfieldModule.default.setHardwareBackButtonEnabled(enabled);}else{console.warn('Not implemented: setNativeGesturesAndButtonsEnabled');}},postMessage:function postMessage(data){var serialized=JSON.stringify(data);_NativeReactNativeBrownfieldModule.default.postMessage(serialized);},onMessage:function onMessage(callback){var subscription=_NativeReactNativeBrownfieldModule.default.onBrownfieldMessage(function(payload){try{callback({data:JSON.parse(payload.text)});}catch(_unused){callback({data:payload.text});}});return{remove:function remove(){return subscription.remove();}};}};var _default=exports.default=ReactNativeBrownfield;
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","_NativeReactNativeBrownfieldModule","_interopRequireDefault","ReactNativeBrownfield","
|
|
1
|
+
{"version":3,"names":["_reactNative","require","_NativeReactNativeBrownfieldModule","_interopRequireDefault","ReactNativeBrownfield","markFullyDisplayed","presentationID","Platform","OS","NativeModules","BrownfieldPerformance","popToNative","animated","ReactNativeBrownfieldModule","console","warn","setNativeBackGestureAndButtonEnabled","enabled","setPopGestureRecognizerEnabled","setHardwareBackButtonEnabled","postMessage","data","serialized","JSON","stringify","onMessage","callback","subscription","onBrownfieldMessage","payload","parse","text","_unused","remove","_default","exports","default"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"mKAAA,IAAAA,YAAA,CAAAC,OAAA,iBAEA,IAAAC,kCAAA,CAAAC,sBAAA,CAAAF,OAAA,yCAeA,GAAM,CAAAG,qBAAqB,CAAG,CAO5BC,kBAAkB,CAAE,QAApB,CAAAA,kBAAkBA,CAAGC,cAAsB,CAAW,CACpD,GAAIC,qBAAQ,CAACC,EAAE,GAAK,KAAK,EAAID,qBAAQ,CAACC,EAAE,GAAK,SAAS,CAAE,CACtDC,0BAAa,CAACC,qBAAqB,CAACL,kBAAkB,CAACC,cAAc,CAAC,CACxE,CACF,CAAC,CASDK,WAAW,CAAE,QAAb,CAAAA,WAAWA,CAAGC,QAAkB,CAAW,CACzC,GAAIL,qBAAQ,CAACC,EAAE,GAAK,KAAK,CAAE,CACzBK,0CAA2B,CAACF,WAAW,CAAC,CAAC,CAACC,QAAQ,CAAC,CACrD,CAAC,IAAM,IAAIL,qBAAQ,CAACC,EAAE,GAAK,SAAS,CAAE,CACpCK,0CAA2B,CAACF,WAAW,CAAC,KAAK,CAAC,CAChD,CAAC,IAAM,CACLG,OAAO,CAACC,IAAI,CAAC,8BAA8B,CAAC,CAC9C,CACF,CAAC,CAUDC,oCAAoC,CAAE,QAAtC,CAAAA,oCAAoCA,CAAGC,OAAgB,CAAW,CAChE,GAAIV,qBAAQ,CAACC,EAAE,GAAK,KAAK,CAAE,CACzBK,0CAA2B,CAACK,8BAA8B,CAACD,OAAO,CAAC,CACrE,CAAC,IAAM,IAAIV,qBAAQ,CAACC,EAAE,GAAK,SAAS,CAAE,CACpCK,0CAA2B,CAACM,4BAA4B,CAACF,OAAO,CAAC,CACnE,CAAC,IAAM,CACLH,OAAO,CAACC,IAAI,CAAC,qDAAqD,CAAC,CACrE,CACF,CAAC,CAYDK,WAAW,CAAE,QAAb,CAAAA,WAAWA,CAAGC,IAAa,CAAW,CACpC,GAAM,CAAAC,UAAU,CAAGC,IAAI,CAACC,SAAS,CAACH,IAAI,CAAC,CACvCR,0CAA2B,CAACO,WAAW,CAACE,UAAU,CAAC,CACrD,CAAC,CAeDG,SAAS,CAAE,QAAX,CAAAA,SAASA,CACPC,QAAuC,CACZ,CAC3B,GAAM,CAAAC,YAAY,CAAGd,0CAA2B,CAACe,mBAAmB,CAClE,SAACC,OAAO,CAAK,CACX,GAAI,CACFH,QAAQ,CAAC,CAAEL,IAAI,CAAEE,IAAI,CAACO,KAAK,CAACD,OAAO,CAACE,IAAI,CAAE,CAAC,CAAC,CAC9C,CAAE,MAAAC,OAAA,CAAM,CACNN,QAAQ,CAAC,CAAEL,IAAI,CAAEQ,OAAO,CAACE,IAAK,CAAC,CAAC,CAClC,CACF,CACF,CAAC,CACD,MAAO,CAAEE,MAAM,CAAE,QAAR,CAAAA,MAAMA,CAAA,QAAQ,CAAAN,YAAY,CAACM,MAAM,CAAC,CAAC,EAAC,CAAC,CAChD,CACF,CAAC,CAAC,IAAAC,QAAA,CAAAC,OAAA,CAAAC,OAAA,CAEahC,qBAAqB","ignoreList":[]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
-keep interface com.callstack.reactnativebrownfield.OnJSBundleLoaded { *; }
|
|
2
|
+
-keep interface com.callstack.reactnativebrownfield.OnDisplayMetrics { *; }
|
|
3
|
+
-keep class com.callstack.reactnativebrownfield.JSBundleTimings { *; }
|
|
4
|
+
-keep class com.callstack.reactnativebrownfield.BrownfieldDisplayMetrics { *; }
|
|
5
|
+
-keep class com.callstack.reactnativebrownfield.BrownfieldDisplayInterval { *; }
|
|
6
|
+
-keep class com.callstack.reactnativebrownfield.BrownfieldThreadMetrics { *; }
|
|
7
|
+
-keep class com.callstack.reactnativebrownfield.BrownfieldPerformanceModule { *; }
|
package/lib/module/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.default=void 0;var _reactNative=require("react-native");var _NativeReactNativeBrownfieldModule=_interopRequireDefault(require("./NativeReactNativeBrownfieldModule"));var ReactNativeBrownfield={popToNative:function popToNative(animated){if(_reactNative.Platform.OS==='ios'){_NativeReactNativeBrownfieldModule.default.popToNative(!!animated);}else if(_reactNative.Platform.OS==='android'){_NativeReactNativeBrownfieldModule.default.popToNative(false);}else{console.warn('Not implemented: popToNative');}},setNativeBackGestureAndButtonEnabled:function setNativeBackGestureAndButtonEnabled(enabled){if(_reactNative.Platform.OS==='ios'){_NativeReactNativeBrownfieldModule.default.setPopGestureRecognizerEnabled(enabled);}else if(_reactNative.Platform.OS==='android'){_NativeReactNativeBrownfieldModule.default.setHardwareBackButtonEnabled(enabled);}else{console.warn('Not implemented: setNativeGesturesAndButtonsEnabled');}},postMessage:function postMessage(data){var serialized=JSON.stringify(data);_NativeReactNativeBrownfieldModule.default.postMessage(serialized);},onMessage:function onMessage(callback){var subscription=_NativeReactNativeBrownfieldModule.default.onBrownfieldMessage(function(payload){try{callback({data:JSON.parse(payload.text)});}catch(_unused){callback({data:payload.text});}});return{remove:function remove(){return subscription.remove();}};}};var _default=exports.default=ReactNativeBrownfield;
|
|
1
|
+
var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.default=void 0;var _reactNative=require("react-native");var _NativeReactNativeBrownfieldModule=_interopRequireDefault(require("./NativeReactNativeBrownfieldModule"));var ReactNativeBrownfield={markFullyDisplayed:function markFullyDisplayed(presentationID){if(_reactNative.Platform.OS==='ios'||_reactNative.Platform.OS==='android'){_reactNative.NativeModules.BrownfieldPerformance.markFullyDisplayed(presentationID);}},popToNative:function popToNative(animated){if(_reactNative.Platform.OS==='ios'){_NativeReactNativeBrownfieldModule.default.popToNative(!!animated);}else if(_reactNative.Platform.OS==='android'){_NativeReactNativeBrownfieldModule.default.popToNative(false);}else{console.warn('Not implemented: popToNative');}},setNativeBackGestureAndButtonEnabled:function setNativeBackGestureAndButtonEnabled(enabled){if(_reactNative.Platform.OS==='ios'){_NativeReactNativeBrownfieldModule.default.setPopGestureRecognizerEnabled(enabled);}else if(_reactNative.Platform.OS==='android'){_NativeReactNativeBrownfieldModule.default.setHardwareBackButtonEnabled(enabled);}else{console.warn('Not implemented: setNativeGesturesAndButtonsEnabled');}},postMessage:function postMessage(data){var serialized=JSON.stringify(data);_NativeReactNativeBrownfieldModule.default.postMessage(serialized);},onMessage:function onMessage(callback){var subscription=_NativeReactNativeBrownfieldModule.default.onBrownfieldMessage(function(payload){try{callback({data:JSON.parse(payload.text)});}catch(_unused){callback({data:payload.text});}});return{remove:function remove(){return subscription.remove();}};}};var _default=exports.default=ReactNativeBrownfield;
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","_NativeReactNativeBrownfieldModule","_interopRequireDefault","ReactNativeBrownfield","
|
|
1
|
+
{"version":3,"names":["_reactNative","require","_NativeReactNativeBrownfieldModule","_interopRequireDefault","ReactNativeBrownfield","markFullyDisplayed","presentationID","Platform","OS","NativeModules","BrownfieldPerformance","popToNative","animated","ReactNativeBrownfieldModule","console","warn","setNativeBackGestureAndButtonEnabled","enabled","setPopGestureRecognizerEnabled","setHardwareBackButtonEnabled","postMessage","data","serialized","JSON","stringify","onMessage","callback","subscription","onBrownfieldMessage","payload","parse","text","_unused","remove","_default","exports","default"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"mKAAA,IAAAA,YAAA,CAAAC,OAAA,iBAEA,IAAAC,kCAAA,CAAAC,sBAAA,CAAAF,OAAA,yCAeA,GAAM,CAAAG,qBAAqB,CAAG,CAO5BC,kBAAkB,CAAE,QAApB,CAAAA,kBAAkBA,CAAGC,cAAsB,CAAW,CACpD,GAAIC,qBAAQ,CAACC,EAAE,GAAK,KAAK,EAAID,qBAAQ,CAACC,EAAE,GAAK,SAAS,CAAE,CACtDC,0BAAa,CAACC,qBAAqB,CAACL,kBAAkB,CAACC,cAAc,CAAC,CACxE,CACF,CAAC,CASDK,WAAW,CAAE,QAAb,CAAAA,WAAWA,CAAGC,QAAkB,CAAW,CACzC,GAAIL,qBAAQ,CAACC,EAAE,GAAK,KAAK,CAAE,CACzBK,0CAA2B,CAACF,WAAW,CAAC,CAAC,CAACC,QAAQ,CAAC,CACrD,CAAC,IAAM,IAAIL,qBAAQ,CAACC,EAAE,GAAK,SAAS,CAAE,CACpCK,0CAA2B,CAACF,WAAW,CAAC,KAAK,CAAC,CAChD,CAAC,IAAM,CACLG,OAAO,CAACC,IAAI,CAAC,8BAA8B,CAAC,CAC9C,CACF,CAAC,CAUDC,oCAAoC,CAAE,QAAtC,CAAAA,oCAAoCA,CAAGC,OAAgB,CAAW,CAChE,GAAIV,qBAAQ,CAACC,EAAE,GAAK,KAAK,CAAE,CACzBK,0CAA2B,CAACK,8BAA8B,CAACD,OAAO,CAAC,CACrE,CAAC,IAAM,IAAIV,qBAAQ,CAACC,EAAE,GAAK,SAAS,CAAE,CACpCK,0CAA2B,CAACM,4BAA4B,CAACF,OAAO,CAAC,CACnE,CAAC,IAAM,CACLH,OAAO,CAACC,IAAI,CAAC,qDAAqD,CAAC,CACrE,CACF,CAAC,CAYDK,WAAW,CAAE,QAAb,CAAAA,WAAWA,CAAGC,IAAa,CAAW,CACpC,GAAM,CAAAC,UAAU,CAAGC,IAAI,CAACC,SAAS,CAACH,IAAI,CAAC,CACvCR,0CAA2B,CAACO,WAAW,CAACE,UAAU,CAAC,CACrD,CAAC,CAeDG,SAAS,CAAE,QAAX,CAAAA,SAASA,CACPC,QAAuC,CACZ,CAC3B,GAAM,CAAAC,YAAY,CAAGd,0CAA2B,CAACe,mBAAmB,CAClE,SAACC,OAAO,CAAK,CACX,GAAI,CACFH,QAAQ,CAAC,CAAEL,IAAI,CAAEE,IAAI,CAACO,KAAK,CAACD,OAAO,CAACE,IAAI,CAAE,CAAC,CAAC,CAC9C,CAAE,MAAAC,OAAA,CAAM,CACNN,QAAQ,CAAC,CAAEL,IAAI,CAAEQ,OAAO,CAACE,IAAK,CAAC,CAAC,CAClC,CACF,CACF,CAAC,CACD,MAAO,CAAEE,MAAM,CAAE,QAAR,CAAAA,MAAMA,CAAA,QAAQ,CAAAN,YAAY,CAACM,MAAM,CAAC,CAAC,EAAC,CAAC,CAChD,CACF,CAAC,CAAC,IAAAC,QAAA,CAAAC,OAAA,CAAAC,OAAA,CAEahC,qBAAqB","ignoreList":[]}
|
|
@@ -3,6 +3,13 @@ export interface MessageEvent {
|
|
|
3
3
|
data: unknown;
|
|
4
4
|
}
|
|
5
5
|
declare const ReactNativeBrownfield: {
|
|
6
|
+
/**
|
|
7
|
+
* Finish this presentation's full-display measurement after data and UI are ready.
|
|
8
|
+
* Pass the `brownfieldPresentationID` injected into the root component's props.
|
|
9
|
+
* Native must opt in with `waitForFullDisplay: true`. Repeated/stale IDs are ignored.
|
|
10
|
+
* @platform android, ios
|
|
11
|
+
*/
|
|
12
|
+
markFullyDisplayed: (presentationID: string) => void;
|
|
6
13
|
/**
|
|
7
14
|
* Pop to the native screen.
|
|
8
15
|
* @param animated - Whether to animate the transition (iOS only).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.ts"],"names":[],"mappings":"AAWA,YAAY,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAExE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,CAAC;CACf;AAED,QAAA,MAAM,qBAAqB;IACzB;;;;;;OAMG;6BACsB,OAAO,KAAG,IAAI;IAUvC;;;;;;;OAOG;oDAC6C,OAAO,KAAG,IAAI;IAU9D;;;;;;;;;OASG;wBACiB,OAAO,KAAG,IAAI;IAKlC;;;;;;;;;;;;OAYG;0BAES,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,KACtC;QAAE,MAAM,EAAE,MAAM,IAAI,CAAA;KAAE;CAY1B,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.ts"],"names":[],"mappings":"AAWA,YAAY,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAExE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,CAAC;CACf;AAED,QAAA,MAAM,qBAAqB;IACzB;;;;;OAKG;yCACkC,MAAM,KAAG,IAAI;IAMlD;;;;;;OAMG;6BACsB,OAAO,KAAG,IAAI;IAUvC;;;;;;;OAOG;oDAC6C,OAAO,KAAG,IAAI;IAU9D;;;;;;;;;OASG;wBACiB,OAAO,KAAG,IAAI;IAKlC;;;;;;;;;;;;OAYG;0BAES,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,KACtC;QAAE,MAAM,EAAE,MAAM,IAAI,CAAA;KAAE;CAY1B,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
|
@@ -3,6 +3,13 @@ export interface MessageEvent {
|
|
|
3
3
|
data: unknown;
|
|
4
4
|
}
|
|
5
5
|
declare const ReactNativeBrownfield: {
|
|
6
|
+
/**
|
|
7
|
+
* Finish this presentation's full-display measurement after data and UI are ready.
|
|
8
|
+
* Pass the `brownfieldPresentationID` injected into the root component's props.
|
|
9
|
+
* Native must opt in with `waitForFullDisplay: true`. Repeated/stale IDs are ignored.
|
|
10
|
+
* @platform android, ios
|
|
11
|
+
*/
|
|
12
|
+
markFullyDisplayed: (presentationID: string) => void;
|
|
6
13
|
/**
|
|
7
14
|
* Pop to the native screen.
|
|
8
15
|
* @param animated - Whether to animate the transition (iOS only).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.ts"],"names":[],"mappings":"AAWA,YAAY,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAExE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,CAAC;CACf;AAED,QAAA,MAAM,qBAAqB;IACzB;;;;;;OAMG;6BACsB,OAAO,KAAG,IAAI;IAUvC;;;;;;;OAOG;oDAC6C,OAAO,KAAG,IAAI;IAU9D;;;;;;;;;OASG;wBACiB,OAAO,KAAG,IAAI;IAKlC;;;;;;;;;;;;OAYG;0BAES,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,KACtC;QAAE,MAAM,EAAE,MAAM,IAAI,CAAA;KAAE;CAY1B,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.ts"],"names":[],"mappings":"AAWA,YAAY,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAExE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,CAAC;CACf;AAED,QAAA,MAAM,qBAAqB;IACzB;;;;;OAKG;yCACkC,MAAM,KAAG,IAAI;IAMlD;;;;;;OAMG;6BACsB,OAAO,KAAG,IAAI;IAUvC;;;;;;;OAOG;oDAC6C,OAAO,KAAG,IAAI;IAU9D;;;;;;;;;OASG;wBACiB,OAAO,KAAG,IAAI;IAKlC;;;;;;;;;;;;OAYG;0BAES,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,KACtC;QAAE,MAAM,EAAE,MAAM,IAAI,CAAA;KAAE;CAY1B,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@callstack/react-native-brownfield",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Michal Chudziak <mike.chudziak@callstack.com>",
|
|
6
6
|
"bin": {
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"@expo/config-plugins": ">=54 <100"
|
|
101
101
|
},
|
|
102
102
|
"dependencies": {
|
|
103
|
-
"@callstack/brownfield-cli": "^
|
|
103
|
+
"@callstack/brownfield-cli": "^6.0.0",
|
|
104
104
|
"@react-native-community/cli-config": "^20.0.0",
|
|
105
105
|
"@react-native-community/cli-types": "^20.0.0",
|
|
106
106
|
"xcode": "^3.0.1"
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
-keep interface com.callstack.reactnativebrownfield.OnJSBundleLoaded { *; }
|
|
2
|
+
-keep interface com.callstack.reactnativebrownfield.OnDisplayMetrics { *; }
|
|
3
|
+
-keep class com.callstack.reactnativebrownfield.JSBundleTimings { *; }
|
|
4
|
+
-keep class com.callstack.reactnativebrownfield.BrownfieldDisplayMetrics { *; }
|
|
5
|
+
-keep class com.callstack.reactnativebrownfield.BrownfieldDisplayInterval { *; }
|
|
6
|
+
-keep class com.callstack.reactnativebrownfield.BrownfieldThreadMetrics { *; }
|
|
7
|
+
-keep class com.callstack.reactnativebrownfield.BrownfieldPerformanceModule { *; }
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Platform } from 'react-native';
|
|
1
|
+
import { NativeModules, Platform } from 'react-native';
|
|
2
2
|
|
|
3
3
|
import ReactNativeBrownfieldModule from './NativeReactNativeBrownfieldModule';
|
|
4
4
|
|
|
@@ -16,6 +16,18 @@ export interface MessageEvent {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
const ReactNativeBrownfield = {
|
|
19
|
+
/**
|
|
20
|
+
* Finish this presentation's full-display measurement after data and UI are ready.
|
|
21
|
+
* Pass the `brownfieldPresentationID` injected into the root component's props.
|
|
22
|
+
* Native must opt in with `waitForFullDisplay: true`. Repeated/stale IDs are ignored.
|
|
23
|
+
* @platform android, ios
|
|
24
|
+
*/
|
|
25
|
+
markFullyDisplayed: (presentationID: string): void => {
|
|
26
|
+
if (Platform.OS === 'ios' || Platform.OS === 'android') {
|
|
27
|
+
NativeModules.BrownfieldPerformance.markFullyDisplayed(presentationID);
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
|
|
19
31
|
/**
|
|
20
32
|
* Pop to the native screen.
|
|
21
33
|
* @param animated - Whether to animate the transition (iOS only).
|