@ansight/react-native 1.3.0-preview.3 → 1.3.0-preview.5

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 CHANGED
@@ -77,8 +77,8 @@ bundle; its API requires the native Ansight module.
77
77
 
78
78
  This package version expects matching native SDK packages:
79
79
 
80
- - CocoaPods: `Ansight`, `AnsightObjC` version `1.3.0-preview.3`
81
- - Maven: `ai.ansight:ansight-android:1.3.0-preview.3`
80
+ - CocoaPods: `Ansight`, `AnsightObjC` version `1.3.0-preview.5`
81
+ - Maven: `ai.ansight:ansight-android:1.3.0-preview.5`
82
82
 
83
83
  ## Quickstart
84
84
 
@@ -136,10 +136,12 @@ The TypeScript `AnsightOptions` surface mirrors Android `AnsightOptions`, iOS
136
136
  | `retentionPeriodSeconds` | Local metric/event retention window. |
137
137
  | `enableFramesPerSecond` | Enables native FPS sampling. |
138
138
  | `enableBatteryLevel` | Enables battery sampling where available. |
139
+ | `enableOpenFileHandleTracking` | Enables native process open-file-handle sampling. Disabled by default. |
140
+ | `enableJniReferenceCountTracking` | Enables JNI reference-count tracking where the runtime can supply it. Disabled by default. |
139
141
  | `defaultMemoryChannels` | Selects built-in memory channels. Prefer `managedHeap`, `nativeHeap`, `residentSetSize`, and `physicalFootprint`; `javaHeap` and `rss` are accepted as Android/RN compatibility aliases. |
140
142
  | `reactNativeMemory` | Controls native React Native runtime memory channels. Enabled by default; set to `false` to disable, or use `{ jsHeapUsed, jsHeapTotal }`. |
141
143
  | `additionalChannels` | Registers custom metric channels. |
142
- | `sessionJpegCapture` | Object to enable/configure capture, or `false` to disable. Supports `captureGpuBackedSurfaces`; on iOS it defaults to `true` so Metal, SceneKit, and similar GPU-backed views are included. |
144
+ | `sessionJpegCapture` | Object to enable/configure capture, or `false` to disable. `mode` accepts `screenshotOnly`, `screenshotAndVisualTree`, or `screenshotWithVisualTreeOnTouch`. Supports `captureGpuBackedSurfaces`; on iOS it defaults to `true` so Metal, SceneKit, and similar GPU-backed views are included. |
143
145
  | `touchCapture` | Object to enable/configure capture, or `false` to disable. |
144
146
  | `lifecycleCapture` | Native lifecycle and screen-view capture options. |
145
147
  | `toolGuard` | `"disabled"`, `"readOnly"`, `"readWrite"`, or `"fullAccess"`. |
@@ -150,6 +152,11 @@ The TypeScript `AnsightOptions` surface mirrors Android `AnsightOptions`, iOS
150
152
  | `remoteTools` | Native visual tree, file, database, preferences, reflection, and secure-storage tool options. |
151
153
  | `lifecycle` | JS AppState tracking toggle. Defaults to true. |
152
154
 
155
+ Use `withOpenFileHandleTracking()` and `withJniReferenceCountTracking()` to
156
+ opt in through the builder. Matching `without...` methods disable the channels
157
+ again. Open handles are sampled by the native Android/iOS runtime. JNI counts
158
+ are available on Android only when the host integration can supply them.
159
+
153
160
  Cellular host connections are disabled by default. The restriction applies to
154
161
  enrollment and reconnect requests. Opt in only for a trusted development host
155
162
  or personal hotspot:
@@ -175,6 +182,7 @@ await Ansight.initializeAndActivate({
175
182
  quality: 60,
176
183
  maxWidth: 480,
177
184
  captureGpuBackedSurfaces: true,
185
+ mode: "screenshotWithVisualTreeOnTouch",
178
186
  },
179
187
  touchCapture: {
180
188
  captureMoveEvents: true,
@@ -192,6 +200,10 @@ await Ansight.initializeAndActivate({
192
200
  });
193
201
  ```
194
202
 
203
+ The touch mode captures native visual trees at gesture start, every 250 ms
204
+ throughout the gesture, and at the final up or cancel. It requires native touch
205
+ capture and visual-tree tools/providers to remain enabled.
206
+
195
207
  On iOS, `captureGpuBackedSurfaces` defaults to `true` so Metal, SceneKit, and
196
208
  similar GPU-backed views are included. Set it to `false` to use a lower-overhead
197
209
  capture path when those surfaces are not needed.
@@ -67,6 +67,6 @@ repositories {
67
67
  dependencies {
68
68
  implementation("com.facebook.react:react-android")
69
69
  def ansightAndroidVersion =
70
- findProperty("ansightAndroidVersion") ?: "1.3.0-preview.3"
71
- implementation("ai.ansight:ansight-android:1.3.0-preview.3")
70
+ findProperty("ansightAndroidVersion") ?: "1.3.0-preview.5"
71
+ implementation("ai.ansight:ansight-android:1.3.0-preview.5")
72
72
  }
@@ -6,6 +6,7 @@ import ai.ansight.runtime.AndroidToolExecutionContext
6
6
  import ai.ansight.runtime.AndroidToolResult
7
7
  import ai.ansight.runtime.AnsightChannel
8
8
  import ai.ansight.runtime.AnsightChannels
9
+ import ai.ansight.runtime.AnsightCrashCaptureOptions
9
10
  import ai.ansight.runtime.AnsightHostAutoProbeOptions
10
11
  import ai.ansight.runtime.AnsightHostConnectionOptions
11
12
  import ai.ansight.runtime.AnsightLogCallback
@@ -225,6 +226,21 @@ class AnsightReactNativeModule(
225
226
  }.resolve(promise)
226
227
  }
227
228
 
229
+ @ReactMethod
230
+ fun recordCrashCandidate(input: ReadableMap, promise: Promise) {
231
+ runCatching {
232
+ val candidateId = AnsightRuntime.recordCrashCandidate(
233
+ runtime = input.stringValue("runtime") ?: "react-native-javascript",
234
+ kind = input.stringValue("kind") ?: "unhandled_javascript_error",
235
+ message = input.stringValue("message"),
236
+ stack = input.stringValue("stack"),
237
+ fatal = input.booleanValue("fatal", false),
238
+ metadataJson = input.stringValue("metadata"),
239
+ )
240
+ Arguments.createMap().apply { putString("candidateId", candidateId) }
241
+ }.resolve(promise)
242
+ }
243
+
228
244
  @ReactMethod
229
245
  fun screenViewed(name: String, details: ReadableMap?, promise: Promise) {
230
246
  runCatching {
@@ -693,6 +709,22 @@ class AnsightReactNativeModule(
693
709
  if (map.hasBoolean("enableBatteryLevel")) {
694
710
  options = options.copy(enableBatteryLevel = map.booleanValue("enableBatteryLevel", options.enableBatteryLevel))
695
711
  }
712
+ if (map.hasBoolean("enableOpenFileHandleTracking")) {
713
+ options = options.copy(
714
+ enableOpenFileHandleTracking = map.booleanValue(
715
+ "enableOpenFileHandleTracking",
716
+ options.enableOpenFileHandleTracking,
717
+ ),
718
+ )
719
+ }
720
+ if (map.hasBoolean("enableJniReferenceCountTracking")) {
721
+ options = options.copy(
722
+ enableJniReferenceCountTracking = map.booleanValue(
723
+ "enableJniReferenceCountTracking",
724
+ options.enableJniReferenceCountTracking,
725
+ ),
726
+ )
727
+ }
696
728
  if (map.hasMap("defaultMemoryChannels")) {
697
729
  val memory = map.getMapOrNull("defaultMemoryChannels")
698
730
  val managedHeap = if (memory.hasBoolean("managedHeap")) {
@@ -768,6 +800,24 @@ class AnsightReactNativeModule(
768
800
  },
769
801
  )
770
802
  }
803
+ if (map.hasKey("crashCapture")) {
804
+ options = options.copy(
805
+ crashCapture = if (map.isFalse("crashCapture")) {
806
+ options.crashCapture.copy(enabled = false)
807
+ } else {
808
+ val crash = map.getMapOrNull("crashCapture")
809
+ AnsightCrashCaptureOptions(
810
+ enabled = crash.booleanValue("enabled", true),
811
+ studioHandoffEnabled = crash.booleanValue("studioHandoffEnabled", true),
812
+ offlineCaptureAttachmentEnabled = crash.booleanValue("offlineCaptureAttachmentEnabled", true),
813
+ maximumPendingReports = crash.intValue("maximumPendingReports", 8),
814
+ retentionDays = crash.intValue("retentionDays", 7),
815
+ maximumBreadcrumbs = crash.intValue("maximumBreadcrumbs", 64),
816
+ maximumTraceBytes = crash.intValue("maximumTraceBytes", 1_048_576),
817
+ )
818
+ },
819
+ )
820
+ }
771
821
  if (map.hasString("toolGuard")) {
772
822
  options = options.copy(toolGuard = toolGuard(map.stringValue("toolGuard")))
773
823
  }
@@ -935,10 +985,10 @@ class AnsightReactNativeModule(
935
985
  }
936
986
 
937
987
  private fun sessionJpegCaptureMode(value: String?): AnsightSessionJpegCaptureMode =
938
- if (value == "screenshotAndVisualTree") {
939
- AnsightSessionJpegCaptureMode.ScreenshotAndVisualTree
940
- } else {
941
- AnsightSessionJpegCaptureMode.ScreenshotOnly
988
+ when (value) {
989
+ "screenshotAndVisualTree" -> AnsightSessionJpegCaptureMode.ScreenshotAndVisualTree
990
+ "screenshotWithVisualTreeOnTouch" -> AnsightSessionJpegCaptureMode.ScreenshotWithVisualTreeOnTouch
991
+ else -> AnsightSessionJpegCaptureMode.ScreenshotOnly
942
992
  }
943
993
 
944
994
  private fun toolDefinition(map: ReadableMap): ToolDefinition =
@@ -1111,6 +1161,8 @@ class AnsightReactNativeModule(
1111
1161
  putInt("retentionPeriodSeconds", options.retentionPeriodSeconds)
1112
1162
  putBoolean("enableFramesPerSecond", options.enableFramesPerSecond)
1113
1163
  putBoolean("enableBatteryLevel", options.enableBatteryLevel)
1164
+ putBoolean("enableOpenFileHandleTracking", options.enableOpenFileHandleTracking)
1165
+ putBoolean("enableJniReferenceCountTracking", options.enableJniReferenceCountTracking)
1114
1166
  putMap("defaultMemoryChannels", mapOf(
1115
1167
  "managedHeap" to options.defaultMemoryChannels.javaHeap,
1116
1168
  "javaHeap" to options.defaultMemoryChannels.javaHeap,
@@ -1127,10 +1179,10 @@ class AnsightReactNativeModule(
1127
1179
  "quality" to capture.quality,
1128
1180
  "maxWidth" to capture.maxWidth,
1129
1181
  "captureGpuBackedSurfaces" to capture.captureGpuBackedSurfaces,
1130
- "mode" to if (capture.mode == AnsightSessionJpegCaptureMode.ScreenshotAndVisualTree) {
1131
- "screenshotAndVisualTree"
1132
- } else {
1133
- "screenshotOnly"
1182
+ "mode" to when (capture.mode) {
1183
+ AnsightSessionJpegCaptureMode.ScreenshotAndVisualTree -> "screenshotAndVisualTree"
1184
+ AnsightSessionJpegCaptureMode.ScreenshotWithVisualTreeOnTouch -> "screenshotWithVisualTreeOnTouch"
1185
+ else -> "screenshotOnly"
1134
1186
  },
1135
1187
  ).toWritableMap())
1136
1188
  } ?: putNull("sessionJpegCapture")
package/index.d.ts CHANGED
@@ -37,7 +37,7 @@ export interface AnsightSessionJpegCaptureOptions {
37
37
  quality?: number;
38
38
  maxWidth?: number;
39
39
  captureGpuBackedSurfaces?: boolean;
40
- mode?: "screenshotOnly" | "screenshotAndVisualTree";
40
+ mode?: "screenshotOnly" | "screenshotAndVisualTree" | "screenshotWithVisualTreeOnTouch";
41
41
  }
42
42
 
43
43
  export interface AnsightTouchCaptureOptions {
@@ -110,6 +110,8 @@ export interface AnsightOptions {
110
110
  retentionPeriodSeconds?: number;
111
111
  enableFramesPerSecond?: boolean;
112
112
  enableBatteryLevel?: boolean;
113
+ enableOpenFileHandleTracking?: boolean;
114
+ enableJniReferenceCountTracking?: boolean;
113
115
  defaultMemoryChannels?: {
114
116
  managedHeap?: boolean;
115
117
  physicalFootprint?: boolean;
@@ -121,6 +123,7 @@ export interface AnsightOptions {
121
123
  reactNativeMemory?: false | AnsightReactNativeMemoryOptions;
122
124
  sessionJpegCapture?: false | AnsightSessionJpegCaptureOptions;
123
125
  touchCapture?: false | AnsightTouchCaptureOptions;
126
+ crashCapture?: false | AnsightCrashCaptureOptions;
124
127
  lifecycleCapture?: {
125
128
  enabled?: boolean;
126
129
  captureAppLifecycle?: boolean;
@@ -153,6 +156,25 @@ export interface AnsightOptions {
153
156
  lifecycle?: boolean;
154
157
  }
155
158
 
159
+ export interface AnsightCrashCaptureOptions {
160
+ enabled?: boolean;
161
+ studioHandoffEnabled?: boolean;
162
+ offlineCaptureAttachmentEnabled?: boolean;
163
+ maximumPendingReports?: number;
164
+ retentionDays?: number;
165
+ maximumBreadcrumbs?: number;
166
+ maximumTraceBytes?: number;
167
+ }
168
+
169
+ export interface AnsightCrashCandidate {
170
+ runtime?: string;
171
+ kind?: string;
172
+ message?: string;
173
+ stack?: string;
174
+ fatal?: boolean;
175
+ metadata?: string | Record<string, string>;
176
+ }
177
+
156
178
  export interface AnsightOperationResult {
157
179
  success: boolean;
158
180
  message: string;
@@ -251,6 +273,10 @@ export class AnsightOptionsBuilder {
251
273
  withoutFramesPerSecond(): this;
252
274
  withBatteryLevel(): this;
253
275
  withoutBatteryLevel(): this;
276
+ withOpenFileHandleTracking(): this;
277
+ withoutOpenFileHandleTracking(): this;
278
+ withJniReferenceCountTracking(): this;
279
+ withoutJniReferenceCountTracking(): this;
254
280
  withRetentionPeriodSeconds(retentionPeriodSeconds: number): this;
255
281
  withAdditionalChannels(additionalChannels: AnsightChannel[]): this;
256
282
  addAdditionalChannel(additionalChannel: AnsightChannel): this;
@@ -264,11 +290,13 @@ export class AnsightOptionsBuilder {
264
290
  quality?: number,
265
291
  maxWidth?: number | null,
266
292
  captureGpuBackedSurfaces?: boolean,
267
- mode?: "screenshotOnly" | "screenshotAndVisualTree"
293
+ mode?: "screenshotOnly" | "screenshotAndVisualTree" | "screenshotWithVisualTreeOnTouch"
268
294
  ): this;
269
295
  withoutSessionJpegCapture(): this;
270
296
  withTouchCapture(touchCapture?: AnsightTouchCaptureOptions): this;
271
297
  withoutTouchCapture(): this;
298
+ withCrashCapture(crashCapture?: AnsightCrashCaptureOptions): this;
299
+ withoutCrashCapture(): this;
272
300
  withLifecycleCapture(lifecycleCapture?: NonNullable<AnsightOptions["lifecycleCapture"]>): this;
273
301
  withToolGuard(toolGuard: NonNullable<AnsightOptions["toolGuard"]>): this;
274
302
  withToolsDisabled(): this;
@@ -512,6 +540,7 @@ export function metric(value: number, channel?: number): Promise<AnsightDebugSna
512
540
  export function recordMetric(value: number, channel?: number): Promise<AnsightDebugSnapshot>;
513
541
  export function event(input: string | { label: string; type?: string; details?: string; channel?: number }): Promise<AnsightDebugSnapshot>;
514
542
  export function recordEvent(input: string | { label: string; type?: string; details?: string; channel?: number }): Promise<AnsightDebugSnapshot>;
543
+ export function recordCrashCandidate(input?: AnsightCrashCandidate): Promise<{ candidateId?: string }>;
515
544
  export function screenViewed(name: string, details?: Record<string, string>): Promise<AnsightDebugSnapshot>;
516
545
  export function trackRoute(name: string, details?: Record<string, string>): Promise<AnsightDebugSnapshot>;
517
546
  export function setAppLifecycleState(state: AnsightLifecycleState): Promise<AnsightDebugSnapshot>;
@@ -585,6 +614,7 @@ declare const Ansight: {
585
614
  recordMetric: typeof recordMetric;
586
615
  event: typeof event;
587
616
  recordEvent: typeof recordEvent;
617
+ recordCrashCandidate: typeof recordCrashCandidate;
588
618
  screenViewed: typeof screenViewed;
589
619
  trackRoute: typeof trackRoute;
590
620
  setAppLifecycleState: typeof setAppLifecycleState;
package/index.js CHANGED
@@ -61,6 +61,9 @@ function cloneOptions(options = {}) {
61
61
  if (options.touchCapture && typeof options.touchCapture === "object") {
62
62
  clone.touchCapture = { ...options.touchCapture };
63
63
  }
64
+ if (options.crashCapture && typeof options.crashCapture === "object") {
65
+ clone.crashCapture = { ...options.crashCapture };
66
+ }
64
67
  if (options.lifecycleCapture) {
65
68
  clone.lifecycleCapture = { ...options.lifecycleCapture };
66
69
  }
@@ -157,6 +160,8 @@ class AnsightOptionsBuilder {
157
160
  retentionPeriodSeconds: 120,
158
161
  enableFramesPerSecond: true,
159
162
  enableBatteryLevel: false,
163
+ enableOpenFileHandleTracking: false,
164
+ enableJniReferenceCountTracking: false,
160
165
  sessionJpegCapture: {
161
166
  intervalMilliseconds: 2000,
162
167
  quality: 60,
@@ -209,6 +214,26 @@ class AnsightOptionsBuilder {
209
214
  return this;
210
215
  }
211
216
 
217
+ withOpenFileHandleTracking() {
218
+ this._options.enableOpenFileHandleTracking = true;
219
+ return this;
220
+ }
221
+
222
+ withoutOpenFileHandleTracking() {
223
+ this._options.enableOpenFileHandleTracking = false;
224
+ return this;
225
+ }
226
+
227
+ withJniReferenceCountTracking() {
228
+ this._options.enableJniReferenceCountTracking = true;
229
+ return this;
230
+ }
231
+
232
+ withoutJniReferenceCountTracking() {
233
+ this._options.enableJniReferenceCountTracking = false;
234
+ return this;
235
+ }
236
+
212
237
  withRetentionPeriodSeconds(retentionPeriodSeconds) {
213
238
  this._options.retentionPeriodSeconds = retentionPeriodSeconds;
214
239
  return this;
@@ -297,6 +322,16 @@ class AnsightOptionsBuilder {
297
322
  return this;
298
323
  }
299
324
 
325
+ withCrashCapture(crashCapture = {}) {
326
+ this._options.crashCapture = { ...crashCapture, enabled: true };
327
+ return this;
328
+ }
329
+
330
+ withoutCrashCapture() {
331
+ this._options.crashCapture = false;
332
+ return this;
333
+ }
334
+
300
335
  withLifecycleCapture(lifecycleCapture = {}) {
301
336
  this._options.lifecycleCapture = { ...lifecycleCapture };
302
337
  return this;
@@ -2218,6 +2253,14 @@ function installErrorHandlers(options = {}) {
2218
2253
 
2219
2254
  if (global.ErrorUtils && global.ErrorUtils.setGlobalHandler) {
2220
2255
  global.ErrorUtils.setGlobalHandler((error, isFatal) => {
2256
+ nativeModule.recordCrashCandidate({
2257
+ runtime: "react-native-javascript",
2258
+ kind: "unhandled_javascript_error",
2259
+ message: error && error.message,
2260
+ stack: error && error.stack,
2261
+ fatal: !!isFatal,
2262
+ metadata: JSON.stringify({ name: error && error.name }),
2263
+ }).catch(() => {});
2221
2264
  nativeModule.recordEvent({
2222
2265
  label: error && error.message ? error.message : "Unhandled JavaScript error",
2223
2266
  type: "Exception",
@@ -2240,6 +2283,13 @@ function installErrorHandlers(options = {}) {
2240
2283
  global.__ansightUnhandledRejectionTrackingInstalled = true;
2241
2284
  global.addEventListener("unhandledrejection", (event) => {
2242
2285
  const reason = event && event.reason;
2286
+ nativeModule.recordCrashCandidate({
2287
+ runtime: "react-native-javascript",
2288
+ kind: "unhandled_promise_rejection",
2289
+ message: reason && reason.message ? reason.message : String(reason),
2290
+ stack: reason && reason.stack,
2291
+ fatal: false,
2292
+ }).catch(() => {});
2243
2293
  nativeModule.recordEvent({
2244
2294
  label: reason && reason.message ? reason.message : "Unhandled JavaScript promise rejection",
2245
2295
  type: "Exception",
@@ -2334,6 +2384,16 @@ function recordEvent(input) {
2334
2384
  return nativeModule.recordEvent(input || {});
2335
2385
  }
2336
2386
 
2387
+ function recordCrashCandidate(input = {}) {
2388
+ const metadata = input.metadata && typeof input.metadata === "object"
2389
+ ? JSON.stringify(input.metadata)
2390
+ : input.metadata;
2391
+ return nativeModule.recordCrashCandidate({
2392
+ ...input,
2393
+ metadata,
2394
+ });
2395
+ }
2396
+
2337
2397
  function screenViewed(name, details) {
2338
2398
  return nativeModule.screenViewed(name, details || {});
2339
2399
  }
@@ -2376,6 +2436,7 @@ const Ansight = {
2376
2436
  recordMetric: (value, channel = 255) => nativeModule.recordMetric(value, channel),
2377
2437
  event: recordEvent,
2378
2438
  recordEvent,
2439
+ recordCrashCandidate,
2379
2440
  screenViewed,
2380
2441
  trackRoute,
2381
2442
  setAppLifecycleState: (state) => nativeModule.setAppLifecycleState(state),
@@ -292,6 +292,31 @@ final class AnsightReactNative: RCTEventEmitter {
292
292
  }
293
293
  }
294
294
 
295
+ @objc(recordCrashCandidate:resolver:rejecter:)
296
+ func recordCrashCandidate(
297
+ _ input: NSDictionary,
298
+ resolver resolve: RCTPromiseResolveBlock,
299
+ rejecter reject: RCTPromiseRejectBlock
300
+ ) {
301
+ let metadata: [String: String]
302
+ if let metadataJson = stringValue(input, "metadata"),
303
+ let data = metadataJson.data(using: .utf8),
304
+ let decoded = try? JSONDecoder().decode([String: String].self, from: data) {
305
+ metadata = decoded
306
+ } else {
307
+ metadata = [:]
308
+ }
309
+ let candidateId = AnsightRuntime.shared.recordCrashCandidate(
310
+ runtime: stringValue(input, "runtime") ?? "react-native-javascript",
311
+ kind: stringValue(input, "kind") ?? "unhandled_javascript_error",
312
+ message: stringValue(input, "message"),
313
+ stack: stringValue(input, "stack"),
314
+ fatal: boolValue(input, "fatal", defaultValue: false),
315
+ metadata: metadata
316
+ )
317
+ resolve(candidateId.map { ["candidateId": $0] } ?? [:])
318
+ }
319
+
295
320
  @objc(screenViewed:details:resolver:rejecter:)
296
321
  func screenViewed(
297
322
  _ name: NSString,
@@ -895,6 +920,13 @@ final class AnsightReactNative: RCTEventEmitter {
895
920
  if hasBool(dictionary, "enableBatteryLevel") {
896
921
  options.enableBatteryLevel = boolValue(dictionary, "enableBatteryLevel", defaultValue: options.enableBatteryLevel)
897
922
  }
923
+ if hasBool(dictionary, "enableOpenFileHandleTracking") {
924
+ options.enableOpenFileHandleTracking = boolValue(
925
+ dictionary,
926
+ "enableOpenFileHandleTracking",
927
+ defaultValue: options.enableOpenFileHandleTracking
928
+ )
929
+ }
898
930
  if let memory = dictionary?["defaultMemoryChannels"] as? NSDictionary {
899
931
  var channels: DefaultMemoryChannels = []
900
932
  if boolValue(memory, "managedHeap", defaultValue: boolValue(memory, "javaHeap", defaultValue: false)) {
@@ -942,9 +974,9 @@ final class AnsightReactNative: RCTEventEmitter {
942
974
  "captureGpuBackedSurfaces",
943
975
  defaultValue: AnsightSessionJpegCaptureOptions.defaultCaptureGpuBackedSurfaces
944
976
  ),
945
- mode: stringValue(jpeg, "mode") == "screenshotAndVisualTree"
946
- ? .screenshotAndVisualTree
947
- : .screenshotOnly
977
+ mode: AnsightSessionJpegCaptureMode(
978
+ rawValue: stringValue(jpeg, "mode") ?? ""
979
+ ) ?? .screenshotOnly
948
980
  )
949
981
  }
950
982
  }
@@ -960,6 +992,21 @@ final class AnsightReactNative: RCTEventEmitter {
960
992
  )
961
993
  }
962
994
  }
995
+ if let raw = dictionary?["crashCapture"] {
996
+ if (raw as? Bool) == false {
997
+ options.crashCapture.enabled = false
998
+ } else if let crash = raw as? NSDictionary {
999
+ options.crashCapture = AnsightCrashCaptureOptions(
1000
+ enabled: boolValue(crash, "enabled", defaultValue: true),
1001
+ studioHandoffEnabled: boolValue(crash, "studioHandoffEnabled", defaultValue: true),
1002
+ offlineCaptureAttachmentEnabled: boolValue(crash, "offlineCaptureAttachmentEnabled", defaultValue: true),
1003
+ maximumPendingReports: intValue(crash, "maximumPendingReports", defaultValue: 8),
1004
+ retentionDays: intValue(crash, "retentionDays", defaultValue: 7),
1005
+ maximumBreadcrumbs: intValue(crash, "maximumBreadcrumbs", defaultValue: 64),
1006
+ maximumTraceBytes: intValue(crash, "maximumTraceBytes", defaultValue: 1_048_576)
1007
+ )
1008
+ }
1009
+ }
963
1010
  if let lifecycle = dictionary?["lifecycleCapture"] as? NSDictionary {
964
1011
  options.lifecycleCapture = AnsightLifecycleCaptureOptions(
965
1012
  enabled: boolValue(lifecycle, "enabled", defaultValue: options.lifecycleCapture.enabled),
@@ -1271,9 +1318,9 @@ final class AnsightReactNative: RCTEventEmitter {
1271
1318
  "captureGpuBackedSurfaces",
1272
1319
  defaultValue: AnsightSessionJpegCaptureOptions.defaultCaptureGpuBackedSurfaces
1273
1320
  ),
1274
- mode: stringValue(dictionary, "mode") == "screenshotAndVisualTree"
1275
- ? .screenshotAndVisualTree
1276
- : .screenshotOnly
1321
+ mode: AnsightSessionJpegCaptureMode(
1322
+ rawValue: stringValue(dictionary, "mode") ?? ""
1323
+ ) ?? .screenshotOnly
1277
1324
  )
1278
1325
  }
1279
1326
 
@@ -1283,6 +1330,8 @@ final class AnsightReactNative: RCTEventEmitter {
1283
1330
  "retentionPeriodSeconds": options.retentionPeriodSeconds,
1284
1331
  "enableFramesPerSecond": options.enableFramesPerSecond,
1285
1332
  "enableBatteryLevel": options.enableBatteryLevel,
1333
+ "enableOpenFileHandleTracking": options.enableOpenFileHandleTracking,
1334
+ "enableJniReferenceCountTracking": false,
1286
1335
  "defaultMemoryChannels": [
1287
1336
  "managedHeap": options.defaultMemoryChannels.contains(.managedHeap),
1288
1337
  "javaHeap": options.defaultMemoryChannels.contains(.managedHeap),
@@ -33,6 +33,10 @@ RCT_EXTERN_METHOD(recordEvent:(NSDictionary *)input
33
33
  resolver:(RCTPromiseResolveBlock)resolve
34
34
  rejecter:(RCTPromiseRejectBlock)reject)
35
35
 
36
+ RCT_EXTERN_METHOD(recordCrashCandidate:(NSDictionary *)input
37
+ resolver:(RCTPromiseResolveBlock)resolve
38
+ rejecter:(RCTPromiseRejectBlock)reject)
39
+
36
40
  RCT_EXTERN_METHOD(screenViewed:(NSString *)name
37
41
  details:(NSDictionary *)details
38
42
  resolver:(RCTPromiseResolveBlock)resolve
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ansight/react-native",
3
- "version": "1.3.0-preview.3",
3
+ "version": "1.3.0-preview.5",
4
4
  "description": "React Native bridge for the Ansight mobile SDK.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",