@getuserfeedback/react-native 4.0.7 → 4.0.8
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/dist/core-webview-host-controller.d.ts +1 -0
- package/dist/core-webview-host-controller.js +1 -0
- package/dist/core-webview-host.d.ts +2 -5
- package/dist/native-view-record-controller.d.ts +0 -1
- package/dist/native-view-record-controller.js +33 -77
- package/dist/version.js +1 -1
- package/dist/webview-host-controller.d.ts +1 -0
- package/dist/webview-host-controller.js +5 -0
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@ import type { CoreHostBootstrapTransport } from "@getuserfeedback/protocol/inter
|
|
|
2
2
|
import { type CoreWebViewBridgeMessage } from "./core-webview-bridge-adapter.js";
|
|
3
3
|
import { type WebViewHostController } from "./webview-host-controller.js";
|
|
4
4
|
export type CoreWebViewHostConnection = {
|
|
5
|
+
disconnect: () => void;
|
|
5
6
|
generation: number;
|
|
6
7
|
transport: CoreHostBootstrapTransport;
|
|
7
8
|
};
|
|
@@ -2,6 +2,7 @@ import { buildCoreWebViewBridgeScript, buildCoreWebViewHostMessageScript, } from
|
|
|
2
2
|
import { createWebViewHostController, } from "./webview-host-controller.js";
|
|
3
3
|
export const createCoreWebViewHostController = (input) => createWebViewHostController(Object.assign(Object.assign({}, input), { connectionLabel: "Core WebView host", buildActivationScript: buildCoreWebViewBridgeScript, buildHostMessageScript: buildCoreWebViewHostMessageScript, onConnected: (connection) => {
|
|
4
4
|
input.onConnected({
|
|
5
|
+
disconnect: connection.disconnect,
|
|
5
6
|
generation: connection.generation,
|
|
6
7
|
transport: {
|
|
7
8
|
postMessage: connection.postMessage,
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import type { CoreHostBootstrapTransport } from "@getuserfeedback/protocol/internal/core-host-bootstrap";
|
|
2
1
|
import { type ComponentType, type ReactElement } from "react";
|
|
2
|
+
import { type CoreWebViewHostConnection } from "./core-webview-host-controller.js";
|
|
3
3
|
export type CoreWebViewHostProps = {
|
|
4
4
|
coreUrl: string;
|
|
5
|
-
onConnected: (connection:
|
|
6
|
-
generation: number;
|
|
7
|
-
transport: CoreHostBootstrapTransport;
|
|
8
|
-
}) => void;
|
|
5
|
+
onConnected: (connection: CoreWebViewHostConnection) => void;
|
|
9
6
|
onDisconnected?: () => void;
|
|
10
7
|
onInvalidMessage?: (error: Error, value: unknown) => void;
|
|
11
8
|
webViewComponent?: ComponentType<Record<string, unknown>>;
|
|
@@ -25,6 +25,5 @@ export type NativeViewRecordController = {
|
|
|
25
25
|
export declare function createNativeViewRecordController(input: {
|
|
26
26
|
coreConnection: CoreWebViewHostConnection;
|
|
27
27
|
onError: (error: Error) => void;
|
|
28
|
-
readinessRetryDelayMs?: number;
|
|
29
28
|
}): NativeViewRecordController;
|
|
30
29
|
export {};
|
|
@@ -3,16 +3,14 @@ import { buildEventViewSize, eventViewSizeSchema, } from "@getuserfeedback/proto
|
|
|
3
3
|
import { buildEventViewPrerendered } from "@getuserfeedback/protocol/internal/view-host-lifecycle-events";
|
|
4
4
|
import { createViewPreparationReadinessRegistry, createViewPreparationRegistry, } from "./view-orchestration-runtime.js";
|
|
5
5
|
const createNativeViewReadinessRegistry = () => createViewPreparationReadinessRegistry();
|
|
6
|
-
const DEFAULT_READINESS_RETRY_DELAY_MS = 50;
|
|
7
6
|
export function createNativeViewRecordController(input) {
|
|
8
|
-
var _a;
|
|
9
7
|
const entries = new Map();
|
|
10
8
|
const listeners = new Set();
|
|
11
9
|
const preparations = createViewPreparationRegistry();
|
|
10
|
+
let coreConnectionFailed = false;
|
|
12
11
|
let disposed = false;
|
|
13
12
|
let nextAllocationId = 0;
|
|
14
13
|
let snapshot = Object.freeze([]);
|
|
15
|
-
const readinessRetryDelayMs = (_a = input.readinessRetryDelayMs) !== null && _a !== void 0 ? _a : DEFAULT_READINESS_RETRY_DELAY_MS;
|
|
16
14
|
const reportError = (error, fallbackMessage) => {
|
|
17
15
|
try {
|
|
18
16
|
input.onError(error instanceof Error ? error : new Error(fallbackMessage));
|
|
@@ -54,9 +52,9 @@ export function createNativeViewRecordController(input) {
|
|
|
54
52
|
generation: action.gen,
|
|
55
53
|
instanceId: action.instanceId,
|
|
56
54
|
isActive: false,
|
|
55
|
+
isPreparationCommitted: false,
|
|
57
56
|
openRequest: toOpenRequestMetadata(action.openRequest),
|
|
58
57
|
preparation,
|
|
59
|
-
preparationState: "claimed",
|
|
60
58
|
size: null,
|
|
61
59
|
srcdoc: action.srcdoc,
|
|
62
60
|
viewReadinessDetach: null,
|
|
@@ -91,7 +89,7 @@ export function createNativeViewRecordController(input) {
|
|
|
91
89
|
}
|
|
92
90
|
};
|
|
93
91
|
const handleCoreMessage = (value) => {
|
|
94
|
-
if (disposed) {
|
|
92
|
+
if (coreConnectionFailed || disposed) {
|
|
95
93
|
return;
|
|
96
94
|
}
|
|
97
95
|
const parsed = coreViewHostActionSchema.safeParse(value);
|
|
@@ -111,37 +109,26 @@ export function createNativeViewRecordController(input) {
|
|
|
111
109
|
break;
|
|
112
110
|
}
|
|
113
111
|
};
|
|
114
|
-
const completeConnectionReadiness = (
|
|
115
|
-
if (
|
|
116
|
-
return
|
|
112
|
+
const completeConnectionReadiness = (entry, size) => {
|
|
113
|
+
if (disposed || entries.get(entry.viewId) !== entry) {
|
|
114
|
+
return;
|
|
117
115
|
}
|
|
118
|
-
if (entry.
|
|
116
|
+
if (!entry.isPreparationCommitted) {
|
|
119
117
|
if (!entry.preparation.commit()) {
|
|
120
|
-
return
|
|
118
|
+
return;
|
|
121
119
|
}
|
|
122
|
-
entry.
|
|
123
|
-
}
|
|
124
|
-
if (delivery.stage === "pending-size") {
|
|
125
|
-
input.coreConnection.transport.postMessage(buildEventViewSize(Object.assign({ gen: entry.generation, viewId: entry.viewId }, size)));
|
|
126
|
-
delivery.stage = "pending-prerendered";
|
|
127
|
-
}
|
|
128
|
-
if (delivery.stage === "pending-prerendered") {
|
|
129
|
-
input.coreConnection.transport.postMessage(buildEventViewPrerendered({
|
|
130
|
-
gen: entry.generation,
|
|
131
|
-
viewId: entry.viewId,
|
|
132
|
-
}));
|
|
133
|
-
delivery.stage = "delivered";
|
|
120
|
+
entry.isPreparationCommitted = true;
|
|
134
121
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
122
|
+
input.coreConnection.transport.postMessage(buildEventViewSize(Object.assign({ gen: entry.generation, viewId: entry.viewId }, size)));
|
|
123
|
+
input.coreConnection.transport.postMessage(buildEventViewPrerendered({
|
|
124
|
+
gen: entry.generation,
|
|
125
|
+
viewId: entry.viewId,
|
|
126
|
+
}));
|
|
140
127
|
};
|
|
141
128
|
const stopCoreTransport = input.coreConnection.transport.subscribe(handleCoreMessage);
|
|
142
129
|
return {
|
|
143
130
|
attachViewReadinessConnection({ allocationId, connection }) {
|
|
144
|
-
if (disposed) {
|
|
131
|
+
if (coreConnectionFailed || disposed) {
|
|
145
132
|
return null;
|
|
146
133
|
}
|
|
147
134
|
const { viewId } = connection;
|
|
@@ -153,12 +140,6 @@ export function createNativeViewRecordController(input) {
|
|
|
153
140
|
}
|
|
154
141
|
const previousDetach = entry.viewReadinessDetach;
|
|
155
142
|
const connectionReadiness = createNativeViewReadinessRegistry().begin(viewId);
|
|
156
|
-
const readinessDelivery = {
|
|
157
|
-
stage: "awaiting-readiness",
|
|
158
|
-
};
|
|
159
|
-
let latestReadySize = null;
|
|
160
|
-
let retryState = "available";
|
|
161
|
-
let retryTimer = null;
|
|
162
143
|
let detached = false;
|
|
163
144
|
let subscribed = false;
|
|
164
145
|
let unsubscribe = () => { };
|
|
@@ -168,10 +149,6 @@ export function createNativeViewRecordController(input) {
|
|
|
168
149
|
return;
|
|
169
150
|
}
|
|
170
151
|
detached = true;
|
|
171
|
-
if (retryTimer !== null) {
|
|
172
|
-
clearTimeout(retryTimer);
|
|
173
|
-
retryTimer = null;
|
|
174
|
-
}
|
|
175
152
|
unsubscribe();
|
|
176
153
|
connectionReadiness.release();
|
|
177
154
|
if (entry.viewReadinessDetach === detach) {
|
|
@@ -184,49 +161,33 @@ export function createNativeViewRecordController(input) {
|
|
|
184
161
|
}
|
|
185
162
|
}
|
|
186
163
|
};
|
|
187
|
-
const
|
|
188
|
-
if (
|
|
189
|
-
readinessDelivery.stage === "awaiting-readiness" ||
|
|
190
|
-
readinessDelivery.stage === "delivered" ||
|
|
164
|
+
const deliverReadiness = (size) => {
|
|
165
|
+
if (coreConnectionFailed ||
|
|
191
166
|
detached ||
|
|
192
167
|
disposed ||
|
|
193
168
|
entries.get(viewId) !== entry ||
|
|
194
169
|
entry.viewReadinessDetach !== detach) {
|
|
195
|
-
return
|
|
196
|
-
}
|
|
197
|
-
if ((isRetry && retryState !== "scheduled") ||
|
|
198
|
-
(!isRetry && retryState !== "available")) {
|
|
199
|
-
return "failed";
|
|
200
|
-
}
|
|
201
|
-
if (isRetry) {
|
|
202
|
-
retryState = "exhausted";
|
|
170
|
+
return;
|
|
203
171
|
}
|
|
204
172
|
try {
|
|
205
|
-
|
|
206
|
-
if (retryTimer !== null) {
|
|
207
|
-
clearTimeout(retryTimer);
|
|
208
|
-
retryTimer = null;
|
|
209
|
-
}
|
|
210
|
-
return "delivered";
|
|
211
|
-
}
|
|
212
|
-
return "idle";
|
|
173
|
+
completeConnectionReadiness(entry, size);
|
|
213
174
|
}
|
|
214
175
|
catch (error) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
176
|
+
coreConnectionFailed = true;
|
|
177
|
+
try {
|
|
178
|
+
input.coreConnection.disconnect();
|
|
179
|
+
}
|
|
180
|
+
catch (_a) {
|
|
181
|
+
// Disconnect observers cannot change readiness settlement.
|
|
221
182
|
}
|
|
222
|
-
|
|
183
|
+
finally {
|
|
223
184
|
reportError(error, "Native view readiness delivery failed");
|
|
224
185
|
}
|
|
225
|
-
return "failed";
|
|
226
186
|
}
|
|
227
187
|
};
|
|
228
188
|
const handleMessage = (value) => {
|
|
229
|
-
if (
|
|
189
|
+
if (coreConnectionFailed ||
|
|
190
|
+
detached ||
|
|
230
191
|
disposed ||
|
|
231
192
|
entries.get(viewId) !== entry ||
|
|
232
193
|
entry.viewReadinessDetach !== detach) {
|
|
@@ -242,14 +203,11 @@ export function createNativeViewRecordController(input) {
|
|
|
242
203
|
entry.size = size;
|
|
243
204
|
const readySize = connectionReadiness.recordSize(size);
|
|
244
205
|
if (readySize) {
|
|
245
|
-
|
|
246
|
-
readinessDelivery.stage = "pending-size";
|
|
247
|
-
}
|
|
248
|
-
else if (readinessDelivery.stage === "pending-size" ||
|
|
249
|
-
readinessDelivery.stage === "pending-prerendered") {
|
|
250
|
-
latestReadySize = size;
|
|
206
|
+
deliverReadiness(readySize);
|
|
251
207
|
}
|
|
252
|
-
if (
|
|
208
|
+
if (!coreConnectionFailed &&
|
|
209
|
+
!disposed &&
|
|
210
|
+
entries.get(viewId) === entry) {
|
|
253
211
|
notify();
|
|
254
212
|
}
|
|
255
213
|
};
|
|
@@ -289,10 +247,8 @@ export function createNativeViewRecordController(input) {
|
|
|
289
247
|
}
|
|
290
248
|
const readySize = connectionReadiness.markHostPrepared();
|
|
291
249
|
if (readySize) {
|
|
292
|
-
|
|
293
|
-
readinessDelivery.stage = "pending-size";
|
|
250
|
+
deliverReadiness(readySize);
|
|
294
251
|
}
|
|
295
|
-
attemptReadinessDelivery();
|
|
296
252
|
return detached ? null : detach;
|
|
297
253
|
},
|
|
298
254
|
dispose() {
|
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.
|
|
6
|
+
export const REACT_NATIVE_SDK_VERSION = reactNativeSdkVersion.length > 0 ? reactNativeSdkVersion : "4.0.8";
|
|
@@ -10,6 +10,7 @@ export type WebViewBridgeMessageIdentity = {
|
|
|
10
10
|
};
|
|
11
11
|
export type WebViewHostConnection<TMessage extends WebViewBridgeMessageIdentity> = {
|
|
12
12
|
connectionId: string;
|
|
13
|
+
disconnect: () => void;
|
|
13
14
|
epoch: number;
|
|
14
15
|
generation: number;
|
|
15
16
|
postMessage: (message: unknown) => void;
|
|
@@ -142,6 +142,11 @@ export const createWebViewHostController = (input) => {
|
|
|
142
142
|
const listeners = new Set();
|
|
143
143
|
const connection = {
|
|
144
144
|
connectionId: message.connectionId,
|
|
145
|
+
disconnect: () => {
|
|
146
|
+
if (activeConnection === connection) {
|
|
147
|
+
disconnect();
|
|
148
|
+
}
|
|
149
|
+
},
|
|
145
150
|
epoch: message.epoch,
|
|
146
151
|
generation: message.generation,
|
|
147
152
|
isAnnounced: false,
|