@ansight/react-native 1.0.2-preview.1 → 1.0.2-preview.3

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
@@ -25,8 +25,8 @@ npx react-native run-android
25
25
 
26
26
  This package version expects matching native SDK packages:
27
27
 
28
- - CocoaPods: `Ansight`, `AnsightObjC` version `1.0.2-preview.1`
29
- - Maven: `ai.ansight:ansight-android:1.0.2-preview.1`
28
+ - CocoaPods: `Ansight`, `AnsightObjC` version `1.0.2-preview.3`
29
+ - Maven: `ai.ansight:ansight-android:1.0.2-preview.3`
30
30
 
31
31
  ## Quickstart
32
32
 
@@ -38,6 +38,13 @@ const isDevelopmentOnly = __DEV__;
38
38
  await Ansight.initializeAndActivate({
39
39
  useNativeAllInOneDefaults: isDevelopmentOnly,
40
40
  clientName: "My React Native App",
41
+ hostAutoProbe: {
42
+ enabled: isDevelopmentOnly,
43
+ initialDelayMilliseconds: 1000,
44
+ probeIntervalMilliseconds: 5000,
45
+ reconnectDelayMilliseconds: 10000,
46
+ clientName: "My React Native App",
47
+ },
41
48
  hostConnection: isDevelopmentOnly ? {
42
49
  bundledDeveloperConfigJson: process.env.EXPO_PUBLIC_ANSIGHT_PAIRING_CONFIG_JSON,
43
50
  } : undefined,
@@ -59,6 +66,19 @@ does not infer whether the app is a debug build. Gate it with the app's own
59
66
  condition, such as React Native's `__DEV__`, and configure `toolGuard`, capture
60
67
  options, host auto-probe, and host connection separately.
61
68
 
69
+ Host auto-probe uses the native iOS/Android remembered-host retry behavior.
70
+ When enabled and the runtime is active, it retries previous host connections so
71
+ the app can reconnect after the host disappears and later reappears. Probing
72
+ pauses while a live session is connected and resumes after
73
+ `reconnectDelayMilliseconds` when that session is lost. Use
74
+ `withoutHostAutoProbe()` or set `hostAutoProbe.enabled` to `false` for flows
75
+ where reconnects should only happen after an explicit app action.
76
+
77
+ > **Important:** Screen capture will result in an FPS drop while native frames
78
+ > are rendered, encoded, and sent. Use conservative interval, quality, and
79
+ > max-width settings, and disable `sessionJpegCapture` for performance-focused
80
+ > runs unless visual evidence is required.
81
+
62
82
  ## Options
63
83
 
64
84
  The TypeScript `AnsightOptions` surface mirrors Android `AnsightOptions`, iOS
@@ -66,7 +86,7 @@ The TypeScript `AnsightOptions` surface mirrors Android `AnsightOptions`, iOS
66
86
 
67
87
  | Option | Purpose |
68
88
  | --- | --- |
69
- | `useNativeAllInOneDefaults` | Applies native iOS/Android all-in-one defaults when true. Defaults to false. This is not a master enable switch; configure `toolGuard`, capture options, and `hostConnection` separately. |
89
+ | `useNativeAllInOneDefaults` | Applies native iOS/Android all-in-one defaults when true. Defaults to false. This enables the native visual-tree/screenshot tools required by Studio visual tree inspection unless `remoteTools.visualTree` is explicitly false. Configure `toolGuard`, capture options, and `hostConnection` separately. |
70
90
  | `pairingConfigJson` | Legacy top-level pairing JSON. Prefer `hostConnection.*`. |
71
91
  | `clientName` | Default client name for host auto-probe and connections. |
72
92
  | `sampleFrequencyMilliseconds` | Built-in telemetry sampling interval. |
@@ -76,12 +96,12 @@ The TypeScript `AnsightOptions` surface mirrors Android `AnsightOptions`, iOS
76
96
  | `defaultMemoryChannels` | Selects built-in memory channels. Prefer `managedHeap`, `nativeHeap`, `residentSetSize`, and `physicalFootprint`; `javaHeap` and `rss` are accepted as Android/RN compatibility aliases. |
77
97
  | `reactNativeMemory` | Controls native React Native runtime memory channels. Enabled by default; set to `false` to disable, or use `{ jsHeapUsed, jsHeapTotal }`. |
78
98
  | `additionalChannels` | Registers custom metric channels. |
79
- | `sessionJpegCapture` | Object to enable/configure capture, or `false` to disable. |
99
+ | `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. |
80
100
  | `touchCapture` | Object to enable/configure capture, or `false` to disable. |
81
101
  | `lifecycleCapture` | Native lifecycle and screen-view capture options. |
82
102
  | `toolGuard` | `"disabled"`, `"readOnly"`, `"readWrite"`, or `"fullAccess"`. |
83
103
  | `customProperties` | Grouped string properties sent with `session.open`. |
84
- | `hostAutoProbe` | Automatic host reconnect loop settings. |
104
+ | `hostAutoProbe` | Remembered-host retry settings for reconnecting after the host disappears and later reappears. |
85
105
  | `hostConnection` | Saved, bundled, and developer pairing settings. |
86
106
  | `secureStorage` | Compatibility alias for native secure-storage allow-list settings. |
87
107
  | `remoteTools` | Native visual tree, file, database, preferences, reflection, and secure-storage tool options. |
@@ -97,6 +117,7 @@ await Ansight.initializeAndActivate({
97
117
  intervalMilliseconds: 2000,
98
118
  quality: 60,
99
119
  maxWidth: 480,
120
+ captureGpuBackedSurfaces: true,
100
121
  },
101
122
  touchCapture: {
102
123
  captureMoveEvents: true,
@@ -106,14 +127,21 @@ await Ansight.initializeAndActivate({
106
127
  },
107
128
  hostAutoProbe: {
108
129
  enabled: true,
130
+ initialDelayMilliseconds: 1000,
131
+ probeIntervalMilliseconds: 5000,
132
+ reconnectDelayMilliseconds: 10000,
109
133
  clientName: "My React Native App",
110
134
  },
111
135
  });
112
136
  ```
113
137
 
138
+ On iOS, `captureGpuBackedSurfaces` defaults to `true` so Metal, SceneKit, and
139
+ similar GPU-backed views are included. Set it to `false` to use a lower-overhead
140
+ capture path when those surfaces are not needed.
141
+
114
142
  ## Native Tool Options
115
143
 
116
- `remoteTools` configures the native tool suites registered by the bridge. Visual tree tools are opt-in:
144
+ `remoteTools` configures the native tool suites registered by the bridge. `useNativeAllInOneDefaults: true` enables visual tree tools by default so Studio can pair `ui.get_visual_tree` data with `ui.get_screenshot` frames. Apps that do not use all-in-one defaults can opt in explicitly:
117
145
 
118
146
  ```ts
119
147
  await Ansight.initializeAndActivate(
@@ -147,6 +175,12 @@ await Ansight.initializeAndActivate(
147
175
  );
148
176
  ```
149
177
 
178
+ `reflect.list_roots` reports a `hostRuntime` descriptor on each root. Current
179
+ React Native reflection roots are hosted by the native iOS or Android runtime;
180
+ future JavaScript reflection roots should report `kind: "javascript"` and
181
+ `bridge: "react-native"` so callers can route reflection requests to the
182
+ correct runtime boundary.
183
+
150
184
  `secureStorage.preferencesName` is Android-specific. `secureStorage.appleService`
151
185
  is iOS-specific. The top-level `secureStorage` option is still accepted as a
152
186
  compatibility alias for `remoteTools.secureStorage`.
@@ -165,7 +199,7 @@ await Ansight.connect(null, {
165
199
  Automatic connection tries:
166
200
 
167
201
  1. `hostConnection.bundledDeveloperConfigJson`
168
- 2. native cached host profiles where implemented
202
+ 2. native remembered host profiles, newest first
169
203
  3. saved pairing config
170
204
  4. `hostConnection.bundledConfigJson`
171
205
 
@@ -406,7 +440,11 @@ const snapshot = await Ansight.snapshot();
406
440
  const options = await Ansight.currentOptions();
407
441
 
408
442
  await Ansight.captureBuiltInTelemetrySample();
409
- await Ansight.captureScreenFrame({ quality: 60, maxWidth: 480 });
443
+ await Ansight.captureScreenFrame({
444
+ quality: 60,
445
+ maxWidth: 480,
446
+ captureGpuBackedSurfaces: true,
447
+ });
410
448
  await Ansight.enableTouchCapture();
411
449
  await Ansight.disableTouchCapture();
412
450
  ```
@@ -66,5 +66,5 @@ repositories {
66
66
 
67
67
  dependencies {
68
68
  implementation("com.facebook.react:react-android")
69
- implementation("ai.ansight:ansight-android:1.0.2-preview.1")
69
+ implementation("ai.ansight:ansight-android:1.0.2-preview.3")
70
70
  }
@@ -702,6 +702,10 @@ class AnsightReactNativeModule(
702
702
  ),
703
703
  quality = jpeg.intValue("quality", AnsightSessionJpegCaptureOptions.DefaultQuality),
704
704
  maxWidth = jpeg.optionalInt("maxWidth") ?: AnsightSessionJpegCaptureOptions.DefaultMaxWidth,
705
+ captureGpuBackedSurfaces = jpeg.booleanValue(
706
+ "captureGpuBackedSurfaces",
707
+ AnsightSessionJpegCaptureOptions.DefaultCaptureGpuBackedSurfaces,
708
+ ),
705
709
  )
706
710
  },
707
711
  )
@@ -762,13 +766,19 @@ class AnsightReactNativeModule(
762
766
  ),
763
767
  )
764
768
  }
765
- return options.withNativeToolOptions(map)
769
+ return options.withNativeToolOptions(
770
+ map,
771
+ enableVisualTreeToolsByDefault = useNativeAllInOneDefaults,
772
+ )
766
773
  }
767
774
 
768
- private fun AnsightOptions.withNativeToolOptions(map: ReadableMap?): AnsightOptions {
775
+ private fun AnsightOptions.withNativeToolOptions(
776
+ map: ReadableMap?,
777
+ enableVisualTreeToolsByDefault: Boolean,
778
+ ): AnsightOptions {
769
779
  val remoteTools = map.getMapOrNull("remoteTools")
770
780
  val builder = AnsightOptions.createBuilder(this)
771
- if (remoteTools.toolSuiteEnabled("visualTree")) {
781
+ if (remoteTools.toolSuiteEnabled("visualTree", enableVisualTreeToolsByDefault)) {
772
782
  builder.withVisualTreeTools()
773
783
  }
774
784
  builder.withDatabaseTools(databaseToolsOptions(remoteTools.getMapOrNull("database")))
@@ -868,6 +878,10 @@ class AnsightReactNativeModule(
868
878
  ),
869
879
  quality = map.intValue("quality", AnsightSessionJpegCaptureOptions.DefaultQuality),
870
880
  maxWidth = map.optionalInt("maxWidth") ?: AnsightSessionJpegCaptureOptions.DefaultMaxWidth,
881
+ captureGpuBackedSurfaces = map.booleanValue(
882
+ "captureGpuBackedSurfaces",
883
+ AnsightSessionJpegCaptureOptions.DefaultCaptureGpuBackedSurfaces,
884
+ ),
871
885
  )
872
886
  }
873
887
 
@@ -1058,6 +1072,7 @@ class AnsightReactNativeModule(
1058
1072
  "intervalMilliseconds" to capture.intervalMilliseconds,
1059
1073
  "quality" to capture.quality,
1060
1074
  "maxWidth" to capture.maxWidth,
1075
+ "captureGpuBackedSurfaces" to capture.captureGpuBackedSurfaces,
1061
1076
  ).toWritableMap())
1062
1077
  } ?: putNull("sessionJpegCapture")
1063
1078
  options.touchCapture?.let { touch ->
@@ -1206,9 +1221,12 @@ private fun ReadableMap?.hasBoolean(name: String): Boolean = this?.hasKey(name)
1206
1221
  private fun ReadableMap?.hasMap(name: String): Boolean = this?.hasKey(name) == true && this.getType(name) == ReadableType.Map
1207
1222
  private fun ReadableMap?.hasArray(name: String): Boolean = this?.hasKey(name) == true && this.getType(name) == ReadableType.Array
1208
1223
  private fun ReadableMap?.isFalse(name: String): Boolean = this?.hasBoolean(name) == true && !this.getBoolean(name)
1209
- private fun ReadableMap?.toolSuiteEnabled(name: String): Boolean {
1210
- val map = this ?: return false
1211
- if (!map.hasKey(name) || map.isNull(name)) {
1224
+ private fun ReadableMap?.toolSuiteEnabled(name: String, defaultValue: Boolean = false): Boolean {
1225
+ val map = this ?: return defaultValue
1226
+ if (!map.hasKey(name)) {
1227
+ return defaultValue
1228
+ }
1229
+ if (map.isNull(name)) {
1212
1230
  return false
1213
1231
  }
1214
1232
  return when (map.getType(name)) {
package/index.d.ts CHANGED
@@ -36,6 +36,7 @@ export interface AnsightSessionJpegCaptureOptions {
36
36
  intervalMilliseconds?: number;
37
37
  quality?: number;
38
38
  maxWidth?: number;
39
+ captureGpuBackedSurfaces?: boolean;
39
40
  }
40
41
 
41
42
  export interface AnsightTouchCaptureOptions {
@@ -261,7 +262,12 @@ export class AnsightOptionsBuilder {
261
262
  withReactNativeMemoryProfiling(options?: AnsightReactNativeMemoryOptions): this;
262
263
  withoutReactNativeMemoryProfiling(): this;
263
264
  withSessionJpegCapture(options?: AnsightSessionJpegCaptureOptions): this;
264
- withSessionJpegCapture(intervalMilliseconds: number, quality?: number, maxWidth?: number | null): this;
265
+ withSessionJpegCapture(
266
+ intervalMilliseconds: number,
267
+ quality?: number,
268
+ maxWidth?: number | null,
269
+ captureGpuBackedSurfaces?: boolean
270
+ ): this;
265
271
  withoutSessionJpegCapture(): this;
266
272
  withTouchCapture(touchCapture?: AnsightTouchCaptureOptions): this;
267
273
  withoutTouchCapture(): this;
package/index.js CHANGED
@@ -267,6 +267,7 @@ class AnsightOptionsBuilder {
267
267
  intervalMilliseconds: optionsOrIntervalMilliseconds,
268
268
  quality: arguments.length > 1 ? arguments[1] : 60,
269
269
  maxWidth: arguments.length > 2 ? arguments[2] : 480,
270
+ captureGpuBackedSurfaces: arguments.length > 3 ? arguments[3] : true,
270
271
  };
271
272
  return this;
272
273
  }
@@ -925,7 +925,12 @@ final class AnsightReactNative: RCTEventEmitter {
925
925
  defaultValue: AnsightSessionJpegCaptureOptions.defaultIntervalMilliseconds
926
926
  ),
927
927
  quality: intValue(jpeg, "quality", defaultValue: AnsightSessionJpegCaptureOptions.defaultQuality),
928
- maxWidth: optionalInt(jpeg, "maxWidth") ?? AnsightSessionJpegCaptureOptions.defaultMaxWidth
928
+ maxWidth: optionalInt(jpeg, "maxWidth") ?? AnsightSessionJpegCaptureOptions.defaultMaxWidth,
929
+ captureGpuBackedSurfaces: boolValue(
930
+ jpeg,
931
+ "captureGpuBackedSurfaces",
932
+ defaultValue: AnsightSessionJpegCaptureOptions.defaultCaptureGpuBackedSurfaces
933
+ )
929
934
  )
930
935
  }
931
936
  }
@@ -982,8 +987,12 @@ final class AnsightReactNative: RCTEventEmitter {
982
987
 
983
988
  private func remoteToolOptions(_ dictionary: NSDictionary?) -> AnsightRemoteToolOptions {
984
989
  let remoteTools = dictionary?["remoteTools"] as? NSDictionary
990
+ let useNativeAllInOneDefaults = boolValue(dictionary, "useNativeAllInOneDefaults", defaultValue: false)
985
991
  return AnsightRemoteToolOptions(
986
- visualTree: toolSuiteEnabled(remoteTools?["visualTree"]),
992
+ visualTree: toolSuiteEnabled(
993
+ remoteTools?["visualTree"],
994
+ defaultValue: useNativeAllInOneDefaults
995
+ ),
987
996
  database: databaseToolsOptions(remoteTools?["database"] as? NSDictionary),
988
997
  fileSystem: fileSystemToolsOptions(remoteTools?["fileSystem"] as? NSDictionary),
989
998
  preferences: preferencesToolsOptions(remoteTools?["preferences"] as? NSDictionary),
@@ -994,14 +1003,14 @@ final class AnsightReactNative: RCTEventEmitter {
994
1003
  )
995
1004
  }
996
1005
 
997
- private func toolSuiteEnabled(_ value: Any?) -> Bool {
1006
+ private func toolSuiteEnabled(_ value: Any?, defaultValue: Bool = false) -> Bool {
998
1007
  if let enabled = value as? Bool {
999
1008
  return enabled
1000
1009
  }
1001
1010
  if let dictionary = value as? NSDictionary {
1002
1011
  return boolValue(dictionary, "enabled", defaultValue: true)
1003
1012
  }
1004
- return false
1013
+ return defaultValue
1005
1014
  }
1006
1015
 
1007
1016
  private func fileSystemToolsOptions(_ dictionary: NSDictionary?) -> AnsightFileSystemToolsOptions {
@@ -1241,7 +1250,12 @@ final class AnsightReactNative: RCTEventEmitter {
1241
1250
  defaultValue: AnsightSessionJpegCaptureOptions.defaultIntervalMilliseconds
1242
1251
  ),
1243
1252
  quality: intValue(dictionary, "quality", defaultValue: AnsightSessionJpegCaptureOptions.defaultQuality),
1244
- maxWidth: optionalInt(dictionary, "maxWidth") ?? AnsightSessionJpegCaptureOptions.defaultMaxWidth
1253
+ maxWidth: optionalInt(dictionary, "maxWidth") ?? AnsightSessionJpegCaptureOptions.defaultMaxWidth,
1254
+ captureGpuBackedSurfaces: boolValue(
1255
+ dictionary,
1256
+ "captureGpuBackedSurfaces",
1257
+ defaultValue: AnsightSessionJpegCaptureOptions.defaultCaptureGpuBackedSurfaces
1258
+ )
1245
1259
  )
1246
1260
  }
1247
1261
 
@@ -1289,6 +1303,7 @@ final class AnsightReactNative: RCTEventEmitter {
1289
1303
  "intervalMilliseconds": capture.intervalMilliseconds,
1290
1304
  "quality": capture.quality,
1291
1305
  "maxWidth": capture.maxWidth as Any,
1306
+ "captureGpuBackedSurfaces": capture.captureGpuBackedSurfaces,
1292
1307
  ]
1293
1308
  } else {
1294
1309
  dictionary["sessionJpegCapture"] = NSNull()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ansight/react-native",
3
- "version": "1.0.2-preview.1",
3
+ "version": "1.0.2-preview.3",
4
4
  "description": "React Native bridge for the Ansight mobile SDK.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",