@kontextso/sdk-react-native 3.0.7-rc.1 → 3.0.7-rc.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/dist/index.mjs CHANGED
@@ -20,52 +20,12 @@ function handleIframeMessage(handler, opts) {
20
20
  // src/formats/Format.tsx
21
21
  import {
22
22
  AdsContext,
23
- convertParamsToString,
24
- ErrorBoundary,
25
- useBid,
26
- useIframeUrl
23
+ useBid
27
24
  } from "@kontextso/sdk-react";
28
- import { useContext, useEffect, useRef, useState } from "react";
29
- import { Keyboard, Linking, Modal, useWindowDimensions, View } from "react-native";
30
-
31
- // src/frame-webview.tsx
32
- import { forwardRef } from "react";
25
+ import { useContext, useRef } from "react";
26
+ import { View } from "react-native";
33
27
  import { WebView } from "react-native-webview";
34
28
  import { jsx } from "react/jsx-runtime";
35
- var FrameWebView = forwardRef(
36
- ({ iframeUrl, onMessage, style, onError, onLoad }, forwardedRef) => {
37
- return /* @__PURE__ */ jsx(
38
- WebView,
39
- {
40
- ref: forwardedRef,
41
- source: {
42
- uri: iframeUrl
43
- },
44
- onMessage,
45
- style,
46
- allowsInlineMediaPlayback: true,
47
- mediaPlaybackRequiresUserAction: false,
48
- javaScriptEnabled: true,
49
- domStorageEnabled: true,
50
- allowsFullscreenVideo: false,
51
- injectedJavaScript: `
52
- window.addEventListener("message", function(event) {
53
- if (window.ReactNativeWebView && event.data) {
54
- // ReactNativeWebView.postMessage only supports string data
55
- window.ReactNativeWebView.postMessage(JSON.stringify(event.data));
56
- }
57
- }, false);
58
- `,
59
- onError,
60
- onLoad
61
- }
62
- );
63
- }
64
- );
65
- var frame_webview_default = FrameWebView;
66
-
67
- // src/formats/Format.tsx
68
- import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
69
29
  var sendMessage = (webViewRef, type, code, data) => {
70
30
  const message = makeIframeMessage(type, {
71
31
  data,
@@ -77,56 +37,24 @@ var sendMessage = (webViewRef, type, code, data) => {
77
37
  }));
78
38
  `);
79
39
  };
80
- var getCachedContent = (context, bidId) => {
81
- if (!bidId) {
40
+ var getUrl = (code, messageId, bidId) => {
41
+ const context = useContext(AdsContext);
42
+ if (!context || !bidId) {
82
43
  return null;
83
44
  }
84
- return context?.cachedContentRef?.current?.get(bidId) ?? null;
45
+ const adServerUrl = context?.adServerUrl;
46
+ const params = new URLSearchParams({
47
+ code,
48
+ messageId,
49
+ sdk: "sdk-react-native"
50
+ });
51
+ return `${adServerUrl}/api/frame/${bidId}?${params}`;
85
52
  };
86
53
  var Format = ({ code, messageId, wrapper, onEvent, ...otherParams }) => {
87
54
  const context = useContext(AdsContext);
88
55
  const bid = useBid({ code, messageId });
89
- const [height, setHeight] = useState(0);
90
- const cachedContent = getCachedContent(context, bid?.bidId);
91
- const iframeUrl = useIframeUrl(bid, code, messageId, "sdk-react-native", otherParams.theme, cachedContent);
92
- const modalUrl = iframeUrl.replace("/api/frame/", "/api/modal/");
93
- const [showIframe, setShowIframe] = useState(false);
94
- const [iframeLoaded, setIframeLoaded] = useState(false);
95
- const [modalOpen, setModalOpen] = useState(false);
96
- const [modalShown, setModalShown] = useState(false);
97
- const [modalLoaded, setModalLoaded] = useState(false);
98
- const [containerStyles, setContainerStyles] = useState({});
99
- const [iframeStyles, setIframeStyles] = useState({});
100
- const containerRef = useRef(null);
56
+ const iframeUrl = getUrl(code, messageId, bid?.bidId);
101
57
  const webViewRef = useRef(null);
102
- const modalWebViewRef = useRef(null);
103
- const modalInitTimeoutRef = useRef(null);
104
- const isModalInitRef = useRef(false);
105
- const { height: windowHeight, width: windowWidth } = useWindowDimensions();
106
- const keyboardHeightRef = useRef(0);
107
- const isAdViewVisible = showIframe && iframeLoaded;
108
- const reset = () => {
109
- setHeight(0);
110
- setShowIframe(false);
111
- setContainerStyles({});
112
- setIframeStyles({});
113
- setIframeLoaded(false);
114
- resetModal();
115
- context?.resetAll();
116
- context?.captureError(new Error("Processing iframe error"));
117
- };
118
- const resetModal = () => {
119
- debugModal("Format:resetModal");
120
- if (modalInitTimeoutRef.current) {
121
- debugModal("Format:resetModalTimeout");
122
- clearTimeout(modalInitTimeoutRef.current);
123
- modalInitTimeoutRef.current = null;
124
- }
125
- isModalInitRef.current = false;
126
- setModalOpen(false);
127
- setModalLoaded(false);
128
- setModalShown(false);
129
- };
130
58
  const debug = (name, data = {}) => {
131
59
  context?.onDebugEventInternal?.(name, {
132
60
  code,
@@ -134,42 +62,30 @@ var Format = ({ code, messageId, wrapper, onEvent, ...otherParams }) => {
134
62
  otherParams,
135
63
  bid,
136
64
  iframeUrl,
137
- iframeLoaded,
138
- showIframe,
139
- height,
140
- containerStyles,
141
- iframeStyles,
142
65
  ...data
143
66
  });
144
67
  };
145
- const debugModal = (name, data = {}) => {
146
- context?.onDebugEventInternal?.(name, {
147
- code,
68
+ debug("Format:updateState", {
69
+ params: {
148
70
  messageId,
149
- otherParams,
150
- bid,
151
- modalUrl,
152
- modalOpen,
153
- modalShown,
154
- modalLoaded,
155
- ...data
156
- });
157
- };
158
- debug("Format:updateState");
71
+ code,
72
+ otherParams
73
+ }
74
+ });
159
75
  const onMessage = (event) => {
160
76
  try {
161
77
  const data = JSON.parse(event.nativeEvent.data);
162
78
  debug("Format:iframeMessage", {
163
79
  message: data,
164
- params: { data }
80
+ params: { data, messageId, code, otherParams }
165
81
  });
166
82
  const messageHandler = handleIframeMessage(
167
83
  (message) => {
168
84
  switch (message.type) {
169
85
  case "init-iframe":
170
- setIframeLoaded(true);
171
86
  debug("Format:iframePostMessage", {
172
87
  params: {
88
+ code,
173
89
  messages: context?.messages,
174
90
  sdk: "sdk-react-native",
175
91
  otherParams,
@@ -183,46 +99,6 @@ var Format = ({ code, messageId, wrapper, onEvent, ...otherParams }) => {
183
99
  messageId
184
100
  });
185
101
  break;
186
- case "error-iframe":
187
- reset();
188
- break;
189
- case "resize-iframe":
190
- setHeight(message.data.height);
191
- break;
192
- case "click-iframe":
193
- if (message.data.url) {
194
- Linking.openURL(`${context?.adServerUrl}${message.data.url}`).catch(
195
- (err) => console.error("error opening url", err)
196
- );
197
- }
198
- context?.onAdClickInternal(message.data);
199
- break;
200
- case "view-iframe":
201
- context?.onAdViewInternal(message.data);
202
- break;
203
- case "ad-done-iframe":
204
- if (bid?.bidId && message.data.cachedContent) {
205
- context?.cachedContentRef?.current?.set(bid.bidId, message.data.cachedContent);
206
- }
207
- break;
208
- case "show-iframe":
209
- setShowIframe(true);
210
- break;
211
- case "hide-iframe":
212
- setShowIframe(false);
213
- break;
214
- case "set-styles-iframe":
215
- setContainerStyles(message.data.containerStyles);
216
- setIframeStyles(message.data.iframeStyles);
217
- break;
218
- case "open-component-iframe":
219
- setModalOpen(true);
220
- modalInitTimeoutRef.current = setTimeout(() => {
221
- if (!isModalInitRef.current) {
222
- resetModal();
223
- }
224
- }, message.data.timeout ?? 5e3);
225
- break;
226
102
  case "event-iframe":
227
103
  onEvent?.(message.data);
228
104
  context?.onAdEventInternal(message.data);
@@ -236,253 +112,144 @@ var Format = ({ code, messageId, wrapper, onEvent, ...otherParams }) => {
236
112
  messageHandler({ data });
237
113
  } catch (e) {
238
114
  debug("Format:iframeMessageError", {
239
- params: { error: e },
115
+ params: { error: e, messageId, code, otherParams },
240
116
  error: e
241
117
  });
242
118
  console.error("error parsing message from webview", e);
243
- reset();
244
119
  }
245
120
  };
246
- const onModalMessage = (event) => {
247
- try {
248
- const data = JSON.parse(event.nativeEvent.data);
249
- debugModal("Format:modalIframeMessage", {
250
- params: { data },
251
- message: data
252
- });
253
- const messageHandler = handleIframeMessage(
254
- (message) => {
255
- switch (message.type) {
256
- case "close-component-iframe":
257
- resetModal();
258
- break;
259
- case "init-component-iframe":
260
- isModalInitRef.current = true;
261
- if (modalInitTimeoutRef.current) {
262
- clearTimeout(modalInitTimeoutRef.current);
263
- modalInitTimeoutRef.current = null;
264
- }
265
- setModalShown(true);
266
- break;
267
- case "error-component-iframe":
268
- case "error-iframe":
269
- resetModal();
270
- context?.captureError(new Error("Processing modal iframe error"));
271
- break;
272
- case "click-iframe":
273
- if (message.data.url) {
274
- Linking.openURL(`${context?.adServerUrl}${message.data.url}`).catch(
275
- (err) => console.error("error opening url", err)
276
- );
277
- }
278
- context?.onAdClickInternal(message.data);
279
- break;
280
- case "event-iframe":
281
- onEvent?.(message.data);
282
- context?.onAdEventInternal(message.data);
283
- break;
284
- }
285
- },
286
- {
287
- code,
288
- component: "modal"
289
- }
290
- );
291
- messageHandler({ data });
292
- } catch (e) {
293
- debugModal("Format:modalIframeMessageError", {
294
- params: { error: e },
295
- error: e
296
- });
297
- console.error("error parsing message from webview", e);
298
- resetModal();
299
- }
300
- };
301
- const paramsString = convertParamsToString(otherParams);
302
- useEffect(() => {
303
- if (!iframeLoaded || !context?.adServerUrl || !bid || !webViewRef.current) {
304
- debug("Format:iframePostMessageNotLoaded", {
305
- params: {
306
- iframeLoaded,
307
- contextAdServerUrl: context?.adServerUrl,
308
- bid
309
- }
310
- });
311
- return;
312
- }
313
- debug("Format:iframePostMessage", {
314
- params: {
315
- otherParams
316
- }
317
- });
318
- sendMessage(webViewRef, "update-iframe", code, {
319
- data: { otherParams },
320
- code
321
- });
322
- }, [paramsString, iframeLoaded, context?.adServerUrl, bid, code]);
323
- const checkIfInViewport = () => {
324
- if (!containerRef.current) {
325
- debug("Format:checkIfInViewportNoContainer");
326
- return;
327
- }
328
- debug("Format:checkIfInViewportMeasure", {
329
- params: {
330
- windowWidth,
331
- windowHeight
332
- }
333
- });
334
- containerRef.current.measureInWindow((containerX, containerY, containerWidth, containerHeight) => {
335
- sendMessage(webViewRef, "update-dimensions-iframe", code, {
336
- windowWidth,
337
- windowHeight,
338
- containerWidth,
339
- containerHeight,
340
- containerX,
341
- containerY,
342
- keyboardHeight: keyboardHeightRef.current
343
- });
344
- debug("Format:checkIfInViewportMeasureSend", {
345
- params: {
346
- windowWidth,
347
- windowHeight,
348
- containerWidth,
349
- containerHeight,
350
- containerX,
351
- containerY,
352
- keyboardHeight: keyboardHeightRef.current
353
- }
354
- });
355
- });
356
- };
357
- useEffect(() => {
358
- if (!isAdViewVisible) {
359
- debug("Format:checkIfInViewportNotVisible");
360
- return;
361
- }
362
- const interval = setInterval(() => {
363
- checkIfInViewport();
364
- }, 250);
365
- return () => {
366
- clearInterval(interval);
367
- debug("Format:checkIfInViewportCleanup");
368
- };
369
- }, [isAdViewVisible]);
370
- useEffect(() => {
371
- const showSubscription = Keyboard.addListener("keyboardDidShow", (e) => {
372
- debug("Format:keyboardDidShow", {
373
- params: {
374
- keyboardHeight: e?.endCoordinates?.height ?? 0
375
- }
376
- });
377
- keyboardHeightRef.current = e?.endCoordinates?.height ?? 0;
378
- });
379
- const hideSubscription = Keyboard.addListener("keyboardDidHide", () => {
380
- debug("Format:keyboardDidHide");
381
- keyboardHeightRef.current = 0;
382
- });
383
- return () => {
384
- showSubscription.remove();
385
- hideSubscription.remove();
386
- keyboardHeightRef.current = 0;
387
- debug("Format:keyboardEffectCleanup");
388
- };
389
- }, []);
390
121
  if (!context || !bid || !iframeUrl) {
391
122
  debug("Format:noContextOrBidOrIframeUrl", {
392
123
  params: {
393
124
  context,
394
125
  bid,
395
- iframeUrl
126
+ iframeUrl,
127
+ messageId,
128
+ code,
129
+ otherParams
396
130
  }
397
131
  });
398
132
  return null;
399
133
  }
400
- const inlineContent = /* @__PURE__ */ jsx2(
401
- frame_webview_default,
134
+ return /* @__PURE__ */ jsx(
135
+ View,
402
136
  {
403
- ref: webViewRef,
404
- iframeUrl,
405
- onMessage,
406
137
  style: {
407
- height,
138
+ height: 300,
408
139
  width: "100%",
409
140
  backgroundColor: "transparent",
410
- borderWidth: 0,
411
- ...iframeStyles
141
+ borderWidth: 0
412
142
  },
413
- onError: () => {
414
- debug("Format:iframeError");
415
- reset();
416
- },
417
- onLoad: () => {
418
- debug("Format:iframeLoad");
419
- }
420
- }
421
- );
422
- const interstitialContent = /* @__PURE__ */ jsx2(
423
- Modal,
424
- {
425
- visible: modalOpen,
426
- transparent: true,
427
- onRequestClose: resetModal,
428
- animationType: "slide",
429
- statusBarTranslucent: true,
430
- children: /* @__PURE__ */ jsx2(
431
- View,
143
+ children: /* @__PURE__ */ jsx(
144
+ WebView,
432
145
  {
146
+ ref: webViewRef,
147
+ source: {
148
+ uri: iframeUrl
149
+ },
150
+ onMessage,
433
151
  style: {
434
- flex: 1,
435
- // Don't show the modal until the modal page is loaded and sends 'init-component-iframe' message back to SDK
436
- ...modalShown ? { opacity: 1, pointerEvents: "auto" } : { opacity: 0, pointerEvents: "none" }
152
+ height: 300,
153
+ width: "100%",
154
+ backgroundColor: "transparent",
155
+ borderWidth: 0
437
156
  },
438
- children: /* @__PURE__ */ jsx2(
439
- frame_webview_default,
440
- {
441
- ref: modalWebViewRef,
442
- iframeUrl: modalUrl,
443
- onMessage: onModalMessage,
444
- style: {
445
- backgroundColor: "transparent",
446
- height: "100%",
447
- width: "100%",
448
- borderWidth: 0
449
- },
450
- onError: () => {
451
- debug("Format:modalError");
452
- resetModal();
453
- },
454
- onLoad: () => {
455
- debug("Format:modalLoad");
456
- setModalLoaded(true);
457
- }
157
+ allowsInlineMediaPlayback: true,
158
+ mediaPlaybackRequiresUserAction: false,
159
+ javaScriptEnabled: true,
160
+ domStorageEnabled: true,
161
+ allowsFullscreenVideo: false,
162
+ injectedJavaScript: `
163
+ window.addEventListener("message", function(event) {
164
+ if (window.ReactNativeWebView && event.data) {
165
+ // ReactNativeWebView.postMessage only supports string data
166
+ window.ReactNativeWebView.postMessage(JSON.stringify(event.data));
458
167
  }
459
- )
168
+ }, false);
169
+ `,
170
+ onLoadStart: () => {
171
+ debug("Format:iframeLoadStart", {
172
+ params: {
173
+ messageId,
174
+ code,
175
+ otherParams
176
+ }
177
+ });
178
+ },
179
+ onError: () => {
180
+ debug("Format:iframeError", {
181
+ params: {
182
+ messageId,
183
+ code,
184
+ otherParams
185
+ }
186
+ });
187
+ },
188
+ onLoad: () => {
189
+ debug("Format:iframeLoad", {
190
+ params: {
191
+ messageId,
192
+ code,
193
+ otherParams
194
+ }
195
+ });
196
+ },
197
+ onLoadProgress: () => {
198
+ debug("Format:iframeLoadProgress", {
199
+ params: {
200
+ messageId,
201
+ code,
202
+ otherParams
203
+ }
204
+ });
205
+ },
206
+ onHttpError: () => {
207
+ debug("Format:iframeHttpError", {
208
+ params: {
209
+ messageId,
210
+ code,
211
+ otherParams
212
+ }
213
+ });
214
+ },
215
+ onRenderProcessGone: () => {
216
+ debug("Format:iframeRenderProcessGone", {
217
+ params: {
218
+ messageId,
219
+ code,
220
+ otherParams
221
+ }
222
+ });
223
+ },
224
+ onNavigationStateChange: () => {
225
+ debug("Format:iframeNavigationStateChange", {
226
+ params: {
227
+ messageId,
228
+ code,
229
+ otherParams
230
+ }
231
+ });
232
+ },
233
+ onContentProcessDidTerminate: () => {
234
+ debug("Format:iframeContentProcessDidTerminate", {
235
+ params: {
236
+ messageId,
237
+ code,
238
+ otherParams
239
+ }
240
+ });
241
+ }
460
242
  }
461
243
  )
462
244
  }
463
245
  );
464
- return /* @__PURE__ */ jsxs(Fragment, { children: [
465
- /* @__PURE__ */ jsx2(
466
- View,
467
- {
468
- style: isAdViewVisible ? containerStyles : {
469
- height: 0,
470
- overflow: "hidden"
471
- },
472
- ref: containerRef,
473
- children: wrapper ? wrapper(inlineContent) : inlineContent
474
- }
475
- ),
476
- interstitialContent
477
- ] });
478
246
  };
479
- var FormatWithErrorBoundary = (props) => /* @__PURE__ */ jsx2(ErrorBoundary, { children: /* @__PURE__ */ jsx2(Format, { ...props }) });
480
- var Format_default = FormatWithErrorBoundary;
247
+ var Format_default = Format;
481
248
 
482
249
  // src/formats/InlineAd.tsx
483
- import { jsx as jsx3 } from "react/jsx-runtime";
250
+ import { jsx as jsx2 } from "react/jsx-runtime";
484
251
  var InlineAd = ({ code, messageId, wrapper, ...props }) => {
485
- return /* @__PURE__ */ jsx3(Format_default, { code, messageId, wrapper, ...props });
252
+ return /* @__PURE__ */ jsx2(Format_default, { code, messageId, wrapper, ...props });
486
253
  };
487
254
  var InlineAd_default = InlineAd;
488
255
 
@@ -496,14 +263,14 @@ import { Appearance, Dimensions, PixelRatio, Platform } from "react-native";
496
263
  import DeviceInfo from "react-native-device-info";
497
264
 
498
265
  // package.json
499
- var version = "3.0.7-rc.1";
266
+ var version = "3.0.7-rc.3";
500
267
 
501
268
  // src/NativeRNKontext.ts
502
269
  import { TurboModuleRegistry } from "react-native";
503
270
  var NativeRNKontext_default = TurboModuleRegistry.getEnforcing("RNKontext");
504
271
 
505
272
  // src/context/AdsProvider.tsx
506
- import { jsx as jsx4 } from "react/jsx-runtime";
273
+ import { jsx as jsx3 } from "react/jsx-runtime";
507
274
  ErrorUtils.setGlobalHandler((error, isFatal) => {
508
275
  if (!isFatal) {
509
276
  log.warn(error);
@@ -597,7 +364,7 @@ var getSdk = async () => ({
597
364
  version
598
365
  });
599
366
  var AdsProvider = (props) => {
600
- return /* @__PURE__ */ jsx4(AdsProviderInternal, { ...props, getDevice, getSdk, getApp });
367
+ return /* @__PURE__ */ jsx3(AdsProviderInternal, { ...props, getDevice, getSdk, getApp });
601
368
  };
602
369
  export {
603
370
  AdsProvider,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kontextso/sdk-react-native",
3
- "version": "3.0.7-rc.1",
3
+ "version": "3.0.7-rc.3",
4
4
  "description": "Kontext SDK for React Native",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",