@getuserfeedback/react-native 4.0.13 → 4.0.20

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.
@@ -1,7 +1,8 @@
1
- import { createElement, Fragment, useCallback, useEffect, useMemo, useRef, useSyncExternalStore, } from "react";
1
+ import { createElement, Fragment, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useSyncExternalStore, } from "react";
2
2
  import { NativeViewPresentationSurface } from "./native-view-presentation-surface.js";
3
3
  import { ViewWebViewHost } from "./view-webview-host.js";
4
4
  function NativeViewHostProjectionEntry({ controller, nativeViewComponent, onInvalidMessage, record, webViewComponent, webViewProps, }) {
5
+ var _a;
5
6
  const detachConnectionRef = useRef(null);
6
7
  const detachConnection = useCallback(() => {
7
8
  const detach = detachConnectionRef.current;
@@ -18,6 +19,24 @@ function NativeViewHostProjectionEntry({ controller, nativeViewComponent, onInva
18
19
  }
19
20
  }, [controller, record.allocationId]);
20
21
  const presentedWebViewProps = useMemo(() => (Object.assign(Object.assign({}, webViewProps), { style: [webViewProps === null || webViewProps === void 0 ? void 0 : webViewProps.style, { flex: 1 }] })), [webViewProps]);
22
+ const layoutTransactionId = (_a = record.size) === null || _a === void 0 ? void 0 : _a.layoutTransactionId;
23
+ useLayoutEffect(() => {
24
+ if (!layoutTransactionId) {
25
+ return;
26
+ }
27
+ controller.commitViewLayoutTransaction({
28
+ allocationId: record.allocationId,
29
+ layoutReportRevision: record.layoutReportRevision,
30
+ layoutTransactionId,
31
+ viewId: record.viewId,
32
+ });
33
+ }, [
34
+ controller,
35
+ layoutTransactionId,
36
+ record.allocationId,
37
+ record.layoutReportRevision,
38
+ record.viewId,
39
+ ]);
21
40
  useEffect(() => detachConnection, [detachConnection]);
22
41
  return createElement(NativeViewPresentationSurface, { nativeViewComponent, record }, createElement(ViewWebViewHost, {
23
42
  generation: record.generation,
@@ -28,7 +28,7 @@ const PREPARING_VIEW_FRAME_STYLE = {
28
28
  height: "100%",
29
29
  width: "100%",
30
30
  };
31
- const PRESENTED_VIEW_FRAME_STYLE = {
31
+ const MEASURED_VIEW_FRAME_STYLE = {
32
32
  maxHeight: "100%",
33
33
  maxWidth: "100%",
34
34
  };
@@ -51,16 +51,17 @@ const resolveNativeView = () => {
51
51
  return reactNativeModule.View;
52
52
  };
53
53
  export function NativeViewPresentationSurface({ children, nativeViewComponent, record, }) {
54
- var _a, _b, _c, _d, _e, _f, _g, _h;
54
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
55
55
  const NativeView = nativeViewComponent !== null && nativeViewComponent !== void 0 ? nativeViewComponent : resolveNativeView();
56
56
  const isPresented = record.isActive && record.size !== null;
57
- const cornerRadii = toNativeWidgetCornerRadii((_a = record.size) === null || _a === void 0 ? void 0 : _a.frameAppearance);
58
- const shadow = toNativeWidgetFrameShadow(((_c = (_b = record.size) === null || _b === void 0 ? void 0 : _b.frameAppearance) === null || _c === void 0 ? void 0 : _c.kind) === "page"
57
+ const hasMeasuredFrame = isPresented || ((_a = record.size) === null || _a === void 0 ? void 0 : _a.layoutTransactionId) !== undefined;
58
+ const cornerRadii = toNativeWidgetCornerRadii((_b = record.size) === null || _b === void 0 ? void 0 : _b.frameAppearance);
59
+ const shadow = toNativeWidgetFrameShadow(((_d = (_c = record.size) === null || _c === void 0 ? void 0 : _c.frameAppearance) === null || _d === void 0 ? void 0 : _d.kind) === "page"
59
60
  ? record.size.frameAppearance.resolvedBoxShadow
60
61
  : undefined);
61
62
  const nativeBoxShadow = toNativeWidgetSupportedBoxShadow(shadow, resolveNativeWidgetBoxShadowSupport());
62
63
  const frameOverlayShadowStyle = nativeBoxShadow === undefined ? {} : { boxShadow: nativeBoxShadow };
63
- const borderStyle = toNativeWidgetResolvedBorderStyle(((_e = (_d = record.size) === null || _d === void 0 ? void 0 : _d.frameAppearance) === null || _e === void 0 ? void 0 : _e.kind) === "page"
64
+ const borderStyle = toNativeWidgetResolvedBorderStyle(((_f = (_e = record.size) === null || _e === void 0 ? void 0 : _e.frameAppearance) === null || _f === void 0 ? void 0 : _f.kind) === "page"
64
65
  ? record.size.frameAppearance.resolvedBorder
65
66
  : undefined);
66
67
  const cornerRadiusStyle = {
@@ -71,7 +72,7 @@ export function NativeViewPresentationSurface({ children, nativeViewComponent, r
71
72
  };
72
73
  return createElement(NativeView, {
73
74
  pointerEvents: isPresented ? "box-none" : "none",
74
- style: Object.assign(Object.assign(Object.assign({}, HOST_SURFACE_STYLE), (((_f = record.size) === null || _f === void 0 ? void 0 : _f.placement) === "docked-top"
75
+ style: Object.assign(Object.assign(Object.assign({}, HOST_SURFACE_STYLE), (((_g = record.size) === null || _g === void 0 ? void 0 : _g.placement) === "docked-top"
75
76
  ? TOP_PLACEMENT_STYLE
76
77
  : BOTTOM_PLACEMENT_STYLE)), (isPresented
77
78
  ? PRESENTED_HOST_SURFACE_STYLE
@@ -79,8 +80,8 @@ export function NativeViewPresentationSurface({ children, nativeViewComponent, r
79
80
  testID: `gx-native-view-presentation-${record.viewId}`,
80
81
  }, createElement(NativeView, {
81
82
  pointerEvents: isPresented ? "auto" : "none",
82
- style: isPresented
83
- ? Object.assign(Object.assign(Object.assign({}, PRESENTED_VIEW_FRAME_STYLE), cornerRadiusStyle), { height: (_g = record.size) === null || _g === void 0 ? void 0 : _g.height, width: (_h = record.size) === null || _h === void 0 ? void 0 : _h.width }) : PREPARING_VIEW_FRAME_STYLE,
83
+ style: hasMeasuredFrame
84
+ ? Object.assign(Object.assign(Object.assign({}, MEASURED_VIEW_FRAME_STYLE), cornerRadiusStyle), { height: (_h = record.size) === null || _h === void 0 ? void 0 : _h.height, width: (_j = record.size) === null || _j === void 0 ? void 0 : _j.width }) : PREPARING_VIEW_FRAME_STYLE,
84
85
  testID: `gx-native-view-frame-${record.viewId}`,
85
86
  }, createElement(NativeView, {
86
87
  style: Object.assign(Object.assign({}, VIEW_FRAME_CONTENT_STYLE), cornerRadiusStyle),
@@ -8,6 +8,7 @@ export type NativeViewRecord = Readonly<{
8
8
  generation: number;
9
9
  instanceId: string;
10
10
  isActive: boolean;
11
+ layoutReportRevision: number;
11
12
  openRequest: Readonly<OpenRequestMetadata> | undefined;
12
13
  size: NativeViewSizeReport | null;
13
14
  srcdoc: string;
@@ -18,6 +19,12 @@ export type NativeViewRecordController = {
18
19
  allocationId: number;
19
20
  connection: ViewWebViewHostConnection;
20
21
  }): (() => void) | null;
22
+ commitViewLayoutTransaction(input: {
23
+ allocationId: number;
24
+ layoutReportRevision: number;
25
+ layoutTransactionId: string;
26
+ viewId: string;
27
+ }): void;
21
28
  dispose(): void;
22
29
  getSnapshot(): readonly NativeViewRecord[];
23
30
  subscribe(listener: () => void): () => void;
@@ -1,5 +1,5 @@
1
1
  import { coreViewHostActionSchema, } from "@getuserfeedback/protocol/internal/core-view-host-actions";
2
- import { actionRequestCloseViewSchema, buildEventViewSize, eventViewSizeSchema, } from "@getuserfeedback/protocol/internal/view-host-control-messages";
2
+ import { actionRequestCloseViewSchema, buildEventLayoutTransactionCommitted, buildEventViewSize, eventViewSizeSchema, } from "@getuserfeedback/protocol/internal/view-host-control-messages";
3
3
  import { buildEventViewClosed, buildEventViewPrerendered, } from "@getuserfeedback/protocol/internal/view-host-lifecycle-events";
4
4
  import { createViewPreparationReadinessRegistry, createViewPreparationRegistry, } from "./view-orchestration-runtime.js";
5
5
  const createNativeViewReadinessRegistry = () => createViewPreparationReadinessRegistry();
@@ -74,10 +74,13 @@ export function createNativeViewRecordController(input) {
74
74
  isActive: false,
75
75
  isClosing: false,
76
76
  isPreparationCommitted: false,
77
+ layoutReportRevision: 0,
77
78
  openRequest: toOpenRequestMetadata(action.openRequest),
78
79
  preparation,
79
80
  size: null,
80
81
  srcdoc: action.srcdoc,
82
+ committedLayoutReportOccurrence: null,
83
+ viewConnection: null,
81
84
  viewReadinessDetach: null,
82
85
  viewId: action.viewId,
83
86
  };
@@ -169,6 +172,39 @@ export function createNativeViewRecordController(input) {
169
172
  };
170
173
  const stopCoreTransport = input.coreConnection.transport.subscribe(handleCoreMessage);
171
174
  return {
175
+ commitViewLayoutTransaction({ allocationId, layoutReportRevision, layoutTransactionId, viewId, }) {
176
+ var _a, _b;
177
+ if (coreConnectionFailed || disposed) {
178
+ return;
179
+ }
180
+ const entry = entries.get(viewId);
181
+ const connection = entry === null || entry === void 0 ? void 0 : entry.viewConnection;
182
+ if (!entry ||
183
+ entry.allocationId !== allocationId ||
184
+ !connection ||
185
+ entry.layoutReportRevision !== layoutReportRevision ||
186
+ ((_a = entry.size) === null || _a === void 0 ? void 0 : _a.layoutTransactionId) !== layoutTransactionId ||
187
+ (((_b = entry.committedLayoutReportOccurrence) === null || _b === void 0 ? void 0 : _b.layoutReportRevision) ===
188
+ layoutReportRevision &&
189
+ entry.committedLayoutReportOccurrence.layoutTransactionId ===
190
+ layoutTransactionId)) {
191
+ return;
192
+ }
193
+ entry.committedLayoutReportOccurrence = {
194
+ layoutReportRevision,
195
+ layoutTransactionId,
196
+ };
197
+ try {
198
+ connection.transport.postMessage(buildEventLayoutTransactionCommitted({
199
+ gen: entry.generation,
200
+ layoutTransactionId,
201
+ viewId,
202
+ }));
203
+ }
204
+ catch (error) {
205
+ failCoreConnection(error, "Native view layout commit delivery failed");
206
+ }
207
+ },
172
208
  attachViewReadinessConnection({ allocationId, connection }) {
173
209
  if (coreConnectionFailed || disposed) {
174
210
  return null;
@@ -195,6 +231,8 @@ export function createNativeViewRecordController(input) {
195
231
  connectionReadiness.release();
196
232
  if (entry.viewReadinessDetach === detach) {
197
233
  entry.viewReadinessDetach = null;
234
+ entry.viewConnection = null;
235
+ entry.committedLayoutReportOccurrence = null;
198
236
  if (entry.size !== null) {
199
237
  entry.size = null;
200
238
  if (!disposed && entries.get(viewId) === entry) {
@@ -243,6 +281,7 @@ export function createNativeViewRecordController(input) {
243
281
  }
244
282
  const size = toViewSizeReport(parsed.data);
245
283
  entry.size = size;
284
+ entry.layoutReportRevision += 1;
246
285
  const readySize = connectionReadiness.recordSize(size);
247
286
  if (readySize) {
248
287
  deliverReadiness(readySize);
@@ -275,6 +314,8 @@ export function createNativeViewRecordController(input) {
275
314
  return null;
276
315
  }
277
316
  entry.viewReadinessDetach = detach;
317
+ entry.viewConnection = connection;
318
+ entry.committedLayoutReportOccurrence = null;
278
319
  previousDetach === null || previousDetach === void 0 ? void 0 : previousDetach();
279
320
  if (entry.size !== null) {
280
321
  entry.size = null;
@@ -328,6 +369,7 @@ function toRecord(entry) {
328
369
  generation: entry.generation,
329
370
  instanceId: entry.instanceId,
330
371
  isActive: entry.isActive,
372
+ layoutReportRevision: entry.layoutReportRevision,
331
373
  openRequest: entry.openRequest,
332
374
  size: entry.size,
333
375
  srcdoc: entry.srcdoc,
@@ -362,6 +404,7 @@ function toViewSizeReport(event) {
362
404
  width: event.width,
363
405
  height: event.height,
364
406
  intrinsicWidth: event.intrinsicWidth,
407
+ viewportRevision: event.viewportRevision,
365
408
  frameAppearance: event.frameAppearance,
366
409
  placement: event.placement,
367
410
  transitionPolicy: event.transitionPolicy,
package/dist/version.js CHANGED
@@ -3,4 +3,4 @@ const reactNativeSdkVersion = typeof __GX_REACT_NATIVE_SDK_VERSION__ === "string
3
3
  : "";
4
4
  // Build scripts patch this fallback to the package version for published artifacts.
5
5
  // Source-linked workspace usage keeps the local fallback.
6
- export const REACT_NATIVE_SDK_VERSION = reactNativeSdkVersion.length > 0 ? reactNativeSdkVersion : "4.0.13";
6
+ export const REACT_NATIVE_SDK_VERSION = reactNativeSdkVersion.length > 0 ? reactNativeSdkVersion : "4.0.20";
@@ -81,6 +81,7 @@ const buildViewHostBootstrapScript = () => {
81
81
  width: measurement.width,
82
82
  height: measurement.height,
83
83
  intrinsicWidth: measurement.intrinsicWidth,
84
+ viewportRevision: measurement.viewportRevision,
84
85
  frameAppearance: measurement.frameAppearance,
85
86
  placement: measurement.placement,
86
87
  transitionPolicy: measurement.transitionPolicy,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getuserfeedback/react-native",
3
- "version": "4.0.13",
3
+ "version": "4.0.20",
4
4
  "description": "getuserfeedback React Native SDK",
5
5
  "keywords": [
6
6
  "getuserfeedback",
@@ -44,8 +44,8 @@
44
44
  "lint": "biome check ."
45
45
  },
46
46
  "dependencies": {
47
- "@getuserfeedback/protocol": "^3.25.2",
48
- "@getuserfeedback/sdk": "^0.12.14",
47
+ "@getuserfeedback/protocol": "^3.30.1",
48
+ "@getuserfeedback/sdk": "^0.12.20",
49
49
  "robot3": "^1.2.0"
50
50
  },
51
51
  "peerDependencies": {