@kontextso/sdk-react-native 3.3.0 → 3.3.1-rc.0

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.js CHANGED
@@ -57,14 +57,16 @@ function handleIframeMessage(handler, opts) {
57
57
  // src/formats/Format.tsx
58
58
  var import_sdk_react = require("@kontextso/sdk-react");
59
59
  var import_react2 = require("react");
60
- var import_react_native4 = require("react-native");
60
+ var import_react_native5 = require("react-native");
61
61
 
62
62
  // src/frame-webview.tsx
63
63
  var import_react = require("react");
64
+ var import_react_native = require("react-native");
64
65
  var import_react_native_webview = require("react-native-webview");
65
66
  var import_jsx_runtime = require("react/jsx-runtime");
66
67
  var FrameWebView = (0, import_react.forwardRef)(
67
68
  ({ iframeUrl, onMessage, style, onError, onLoad }, forwardedRef) => {
69
+ const isLoadedRef = (0, import_react.useRef)(false);
68
70
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
69
71
  import_react_native_webview.WebView,
70
72
  {
@@ -89,9 +91,25 @@ var FrameWebView = (0, import_react.forwardRef)(
89
91
  window.ReactNativeWebView.postMessage(JSON.stringify(event.data));
90
92
  }
91
93
  }, false);
94
+
92
95
  `,
93
- onError,
94
- onLoad
96
+ onError: (event) => onError(
97
+ new Error(`${event.nativeEvent.title}: ${event.nativeEvent.description} [${event.nativeEvent.url}]`),
98
+ true
99
+ ),
100
+ onLoad: () => {
101
+ isLoadedRef.current = true;
102
+ onLoad();
103
+ },
104
+ onShouldStartLoadWithRequest: (request) => {
105
+ if (!isLoadedRef.current || request.url.match(/^about:/) || request.url.startsWith(iframeUrl)) {
106
+ return true;
107
+ }
108
+ import_react_native.Linking.openURL(request.url).catch((err) => {
109
+ onError(new Error(`Failed to open URL: ${request.url} [${err.message}]`));
110
+ });
111
+ return false;
112
+ }
95
113
  }
96
114
  );
97
115
  }
@@ -99,11 +117,11 @@ var FrameWebView = (0, import_react.forwardRef)(
99
117
  var frame_webview_default = FrameWebView;
100
118
 
101
119
  // src/services/SkOverlay.ts
102
- var import_react_native2 = require("react-native");
120
+ var import_react_native3 = require("react-native");
103
121
 
104
122
  // src/NativeRNKontext.ts
105
- var import_react_native = require("react-native");
106
- var NativeRNKontext_default = import_react_native.TurboModuleRegistry.getEnforcing("RNKontext");
123
+ var import_react_native2 = require("react-native");
124
+ var NativeRNKontext_default = import_react_native2.TurboModuleRegistry.getEnforcing("RNKontext");
107
125
 
108
126
  // src/services/utils.ts
109
127
  var isValidAppStoreId = (id) => {
@@ -115,7 +133,7 @@ var isValidPosition = (p) => {
115
133
  return p === "bottom" || p === "bottomRaised";
116
134
  };
117
135
  async function presentSKOverlay(params) {
118
- if (import_react_native2.Platform.OS !== "ios") {
136
+ if (import_react_native3.Platform.OS !== "ios") {
119
137
  return false;
120
138
  }
121
139
  let { appStoreId, position, dismissible } = params;
@@ -131,16 +149,16 @@ async function presentSKOverlay(params) {
131
149
  return NativeRNKontext_default.presentSKOverlay(appStoreId, position, dismissible);
132
150
  }
133
151
  async function dismissSKOverlay() {
134
- if (import_react_native2.Platform.OS !== "ios") {
152
+ if (import_react_native3.Platform.OS !== "ios") {
135
153
  return false;
136
154
  }
137
155
  return NativeRNKontext_default.dismissSKOverlay();
138
156
  }
139
157
 
140
158
  // src/services/SkStoreProduct.ts
141
- var import_react_native3 = require("react-native");
159
+ var import_react_native4 = require("react-native");
142
160
  async function presentSKStoreProduct(appStoreId) {
143
- if (import_react_native3.Platform.OS !== "ios") {
161
+ if (import_react_native4.Platform.OS !== "ios") {
144
162
  return false;
145
163
  }
146
164
  if (!isValidAppStoreId(appStoreId)) {
@@ -149,7 +167,7 @@ async function presentSKStoreProduct(appStoreId) {
149
167
  return NativeRNKontext_default.presentSKStoreProduct(appStoreId);
150
168
  }
151
169
  async function dismissSKStoreProduct() {
152
- if (import_react_native3.Platform.OS !== "ios") {
170
+ if (import_react_native4.Platform.OS !== "ios") {
153
171
  return false;
154
172
  }
155
173
  return NativeRNKontext_default.dismissSKStoreProduct();
@@ -194,7 +212,7 @@ var Format = ({ code, messageId, wrapper, onEvent, ...otherParams }) => {
194
212
  const messageStatusRef = (0, import_react2.useRef)("none" /* None */);
195
213
  const modalInitTimeoutRef = (0, import_react2.useRef)(null);
196
214
  const isModalInitRef = (0, import_react2.useRef)(false);
197
- const { height: windowHeight, width: windowWidth } = (0, import_react_native4.useWindowDimensions)();
215
+ const { height: windowHeight, width: windowWidth } = (0, import_react_native5.useWindowDimensions)();
198
216
  const keyboardHeightRef = (0, import_react2.useRef)(0);
199
217
  const isAdViewVisible = showIframe && iframeLoaded;
200
218
  const reset = () => {
@@ -205,7 +223,6 @@ var Format = ({ code, messageId, wrapper, onEvent, ...otherParams }) => {
205
223
  setIframeLoaded(false);
206
224
  resetModal();
207
225
  context?.resetAll();
208
- context?.captureError(new Error("Processing iframe error"));
209
226
  };
210
227
  const resetModal = () => {
211
228
  if (modalInitTimeoutRef.current) {
@@ -316,7 +333,7 @@ var Format = ({ code, messageId, wrapper, onEvent, ...otherParams }) => {
316
333
  return;
317
334
  }
318
335
  try {
319
- await import_react_native4.Linking.openURL(`${context?.adServerUrl}${message.data.url}`);
336
+ await import_react_native5.Linking.openURL(`${context?.adServerUrl}${message.data.url}`);
320
337
  } catch (e) {
321
338
  console.error("error opening url", e);
322
339
  }
@@ -451,7 +468,6 @@ var Format = ({ code, messageId, wrapper, onEvent, ...otherParams }) => {
451
468
  case "error-component-iframe":
452
469
  case "error-iframe":
453
470
  resetModal();
454
- context?.captureError(new Error("Processing modal iframe error"));
455
471
  break;
456
472
  case "open-skoverlay-iframe":
457
473
  openSkOverlay(
@@ -550,10 +566,10 @@ var Format = ({ code, messageId, wrapper, onEvent, ...otherParams }) => {
550
566
  return () => clearInterval(interval);
551
567
  }, [isAdViewVisible]);
552
568
  (0, import_react2.useEffect)(() => {
553
- const showSubscription = import_react_native4.Keyboard.addListener("keyboardDidShow", (e) => {
569
+ const showSubscription = import_react_native5.Keyboard.addListener("keyboardDidShow", (e) => {
554
570
  keyboardHeightRef.current = e?.endCoordinates?.height ?? 0;
555
571
  });
556
- const hideSubscription = import_react_native4.Keyboard.addListener("keyboardDidHide", () => {
572
+ const hideSubscription = import_react_native5.Keyboard.addListener("keyboardDidHide", () => {
557
573
  keyboardHeightRef.current = 0;
558
574
  });
559
575
  return () => {
@@ -578,9 +594,14 @@ var Format = ({ code, messageId, wrapper, onEvent, ...otherParams }) => {
578
594
  borderWidth: 0,
579
595
  ...iframeStyles
580
596
  },
581
- onError: () => {
582
- debug("iframe-error");
583
- reset();
597
+ onError: (error, shouldReset) => {
598
+ debug("iframe-error", {
599
+ error: error.toString()
600
+ });
601
+ context?.captureError(error);
602
+ if (shouldReset) {
603
+ reset();
604
+ }
584
605
  },
585
606
  onLoad: () => {
586
607
  debug("iframe-load");
@@ -589,7 +610,7 @@ var Format = ({ code, messageId, wrapper, onEvent, ...otherParams }) => {
589
610
  }
590
611
  );
591
612
  const interstitialContent = /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
592
- import_react_native4.Modal,
613
+ import_react_native5.Modal,
593
614
  {
594
615
  visible: modalOpen,
595
616
  transparent: true,
@@ -597,7 +618,7 @@ var Format = ({ code, messageId, wrapper, onEvent, ...otherParams }) => {
597
618
  animationType: "slide",
598
619
  statusBarTranslucent: true,
599
620
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
600
- import_react_native4.View,
621
+ import_react_native5.View,
601
622
  {
602
623
  style: {
603
624
  flex: 1,
@@ -616,9 +637,14 @@ var Format = ({ code, messageId, wrapper, onEvent, ...otherParams }) => {
616
637
  width: "100%",
617
638
  borderWidth: 0
618
639
  },
619
- onError: () => {
620
- debug("modal-error");
621
- resetModal();
640
+ onError: (error, shouldReset) => {
641
+ debug("modal-error", {
642
+ error: error.toString()
643
+ });
644
+ context?.captureError(error);
645
+ if (shouldReset) {
646
+ resetModal();
647
+ }
622
648
  },
623
649
  onLoad: () => {
624
650
  debug("modal-load");
@@ -632,7 +658,7 @@ var Format = ({ code, messageId, wrapper, onEvent, ...otherParams }) => {
632
658
  );
633
659
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
634
660
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
635
- import_react_native4.View,
661
+ import_react_native5.View,
636
662
  {
637
663
  style: isAdViewVisible ? containerStyles : {
638
664
  height: 0,
@@ -658,11 +684,11 @@ var InlineAd_default = InlineAd;
658
684
  // src/context/AdsProvider.tsx
659
685
  var import_sdk_react2 = require("@kontextso/sdk-react");
660
686
  var import_netinfo = require("@react-native-community/netinfo");
661
- var import_react_native5 = require("react-native");
687
+ var import_react_native6 = require("react-native");
662
688
  var import_react_native_device_info = __toESM(require("react-native-device-info"));
663
689
 
664
690
  // package.json
665
- var version = "3.3.0";
691
+ var version = "3.3.1-rc.0";
666
692
 
667
693
  // src/context/AdsProvider.tsx
668
694
  var import_jsx_runtime4 = require("react/jsx-runtime");
@@ -683,7 +709,7 @@ var getDevice = async () => {
683
709
  const powerState = await import_react_native_device_info.default.getPowerState();
684
710
  const deviceType = import_react_native_device_info.default.getDeviceType();
685
711
  const soundOn = await NativeRNKontext_default.isSoundOn();
686
- const screen = import_react_native5.Dimensions.get("screen");
712
+ const screen = import_react_native6.Dimensions.get("screen");
687
713
  const networkInfo = await (0, import_netinfo.fetch)();
688
714
  const mapDeviceTypeToHardwareType = () => {
689
715
  switch (deviceType) {
@@ -720,14 +746,14 @@ var getDevice = async () => {
720
746
  detail: networkInfo.type === import_netinfo.NetInfoStateType.cellular && networkInfo.details.cellularGeneration || void 0
721
747
  },
722
748
  os: {
723
- name: import_react_native5.Platform.OS,
749
+ name: import_react_native6.Platform.OS,
724
750
  version: import_react_native_device_info.default.getSystemVersion(),
725
751
  locale: Intl.DateTimeFormat().resolvedOptions().locale,
726
752
  timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
727
753
  },
728
754
  screen: {
729
- darkMode: import_react_native5.Appearance.getColorScheme() === "dark",
730
- dpr: import_react_native5.PixelRatio.get(),
755
+ darkMode: import_react_native6.Appearance.getColorScheme() === "dark",
756
+ dpr: import_react_native6.PixelRatio.get(),
731
757
  height: screen.height,
732
758
  width: screen.width,
733
759
  orientation: screen.width > screen.height ? "landscape" : "portrait"
@@ -760,7 +786,7 @@ var getApp = async () => {
760
786
  };
761
787
  var getSdk = async () => ({
762
788
  name: "sdk-react-native",
763
- platform: import_react_native5.Platform.OS === "ios" ? "ios" : "android",
789
+ platform: import_react_native6.Platform.OS === "ios" ? "ios" : "android",
764
790
  version
765
791
  });
766
792
  var getTcf = async () => {
package/dist/index.mjs CHANGED
@@ -25,15 +25,17 @@ import {
25
25
  useBid,
26
26
  useIframeUrl
27
27
  } from "@kontextso/sdk-react";
28
- import { useContext, useEffect, useRef, useState } from "react";
29
- import { Keyboard, Linking, Modal, useWindowDimensions, View } from "react-native";
28
+ import { useContext, useEffect, useRef as useRef2, useState } from "react";
29
+ import { Keyboard, Linking as Linking2, Modal, useWindowDimensions, View } from "react-native";
30
30
 
31
31
  // src/frame-webview.tsx
32
- import { forwardRef } from "react";
32
+ import { forwardRef, useRef } from "react";
33
+ import { Linking } from "react-native";
33
34
  import { WebView } from "react-native-webview";
34
35
  import { jsx } from "react/jsx-runtime";
35
36
  var FrameWebView = forwardRef(
36
37
  ({ iframeUrl, onMessage, style, onError, onLoad }, forwardedRef) => {
38
+ const isLoadedRef = useRef(false);
37
39
  return /* @__PURE__ */ jsx(
38
40
  WebView,
39
41
  {
@@ -58,9 +60,25 @@ var FrameWebView = forwardRef(
58
60
  window.ReactNativeWebView.postMessage(JSON.stringify(event.data));
59
61
  }
60
62
  }, false);
63
+
61
64
  `,
62
- onError,
63
- onLoad
65
+ onError: (event) => onError(
66
+ new Error(`${event.nativeEvent.title}: ${event.nativeEvent.description} [${event.nativeEvent.url}]`),
67
+ true
68
+ ),
69
+ onLoad: () => {
70
+ isLoadedRef.current = true;
71
+ onLoad();
72
+ },
73
+ onShouldStartLoadWithRequest: (request) => {
74
+ if (!isLoadedRef.current || request.url.match(/^about:/) || request.url.startsWith(iframeUrl)) {
75
+ return true;
76
+ }
77
+ Linking.openURL(request.url).catch((err) => {
78
+ onError(new Error(`Failed to open URL: ${request.url} [${err.message}]`));
79
+ });
80
+ return false;
81
+ }
64
82
  }
65
83
  );
66
84
  }
@@ -157,14 +175,14 @@ var Format = ({ code, messageId, wrapper, onEvent, ...otherParams }) => {
157
175
  const [modalLoaded, setModalLoaded] = useState(false);
158
176
  const [containerStyles, setContainerStyles] = useState({});
159
177
  const [iframeStyles, setIframeStyles] = useState({});
160
- const containerRef = useRef(null);
161
- const webViewRef = useRef(null);
162
- const modalWebViewRef = useRef(null);
163
- const messageStatusRef = useRef("none" /* None */);
164
- const modalInitTimeoutRef = useRef(null);
165
- const isModalInitRef = useRef(false);
178
+ const containerRef = useRef2(null);
179
+ const webViewRef = useRef2(null);
180
+ const modalWebViewRef = useRef2(null);
181
+ const messageStatusRef = useRef2("none" /* None */);
182
+ const modalInitTimeoutRef = useRef2(null);
183
+ const isModalInitRef = useRef2(false);
166
184
  const { height: windowHeight, width: windowWidth } = useWindowDimensions();
167
- const keyboardHeightRef = useRef(0);
185
+ const keyboardHeightRef = useRef2(0);
168
186
  const isAdViewVisible = showIframe && iframeLoaded;
169
187
  const reset = () => {
170
188
  setHeight(0);
@@ -174,7 +192,6 @@ var Format = ({ code, messageId, wrapper, onEvent, ...otherParams }) => {
174
192
  setIframeLoaded(false);
175
193
  resetModal();
176
194
  context?.resetAll();
177
- context?.captureError(new Error("Processing iframe error"));
178
195
  };
179
196
  const resetModal = () => {
180
197
  if (modalInitTimeoutRef.current) {
@@ -285,7 +302,7 @@ var Format = ({ code, messageId, wrapper, onEvent, ...otherParams }) => {
285
302
  return;
286
303
  }
287
304
  try {
288
- await Linking.openURL(`${context?.adServerUrl}${message.data.url}`);
305
+ await Linking2.openURL(`${context?.adServerUrl}${message.data.url}`);
289
306
  } catch (e) {
290
307
  console.error("error opening url", e);
291
308
  }
@@ -420,7 +437,6 @@ var Format = ({ code, messageId, wrapper, onEvent, ...otherParams }) => {
420
437
  case "error-component-iframe":
421
438
  case "error-iframe":
422
439
  resetModal();
423
- context?.captureError(new Error("Processing modal iframe error"));
424
440
  break;
425
441
  case "open-skoverlay-iframe":
426
442
  openSkOverlay(
@@ -547,9 +563,14 @@ var Format = ({ code, messageId, wrapper, onEvent, ...otherParams }) => {
547
563
  borderWidth: 0,
548
564
  ...iframeStyles
549
565
  },
550
- onError: () => {
551
- debug("iframe-error");
552
- reset();
566
+ onError: (error, shouldReset) => {
567
+ debug("iframe-error", {
568
+ error: error.toString()
569
+ });
570
+ context?.captureError(error);
571
+ if (shouldReset) {
572
+ reset();
573
+ }
553
574
  },
554
575
  onLoad: () => {
555
576
  debug("iframe-load");
@@ -585,9 +606,14 @@ var Format = ({ code, messageId, wrapper, onEvent, ...otherParams }) => {
585
606
  width: "100%",
586
607
  borderWidth: 0
587
608
  },
588
- onError: () => {
589
- debug("modal-error");
590
- resetModal();
609
+ onError: (error, shouldReset) => {
610
+ debug("modal-error", {
611
+ error: error.toString()
612
+ });
613
+ context?.captureError(error);
614
+ if (shouldReset) {
615
+ resetModal();
616
+ }
591
617
  },
592
618
  onLoad: () => {
593
619
  debug("modal-load");
@@ -634,7 +660,7 @@ import { Appearance, Dimensions, PixelRatio, Platform as Platform3 } from "react
634
660
  import DeviceInfo from "react-native-device-info";
635
661
 
636
662
  // package.json
637
- var version = "3.3.0";
663
+ var version = "3.3.1-rc.0";
638
664
 
639
665
  // src/context/AdsProvider.tsx
640
666
  import { jsx as jsx4 } from "react/jsx-runtime";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kontextso/sdk-react-native",
3
- "version": "3.3.0",
3
+ "version": "3.3.1-rc.0",
4
4
  "description": "Kontext SDK for React Native",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -20,7 +20,7 @@
20
20
  "format": "biome format --write ."
21
21
  },
22
22
  "devDependencies": {
23
- "@kontextso/sdk-common": "^1.0.4",
23
+ "@kontextso/sdk-common": "^1.0.5",
24
24
  "@kontextso/typescript-config": "*",
25
25
  "@react-native-community/netinfo": "11.3.1",
26
26
  "@testing-library/dom": "^10.4.0",
@@ -18,8 +18,8 @@ import { useContext, useEffect, useRef, useState } from 'react'
18
18
  import { Keyboard, Linking, Modal, useWindowDimensions, View } from 'react-native'
19
19
  import type { WebView, WebViewMessageEvent } from 'react-native-webview'
20
20
  import FrameWebView from '../frame-webview'
21
- import { presentSKOverlay, dismissSKOverlay, type SKOverlayPosition } from '../services/SkOverlay'
22
- import { presentSKStoreProduct, dismissSKStoreProduct } from '../services/SkStoreProduct'
21
+ import { dismissSKOverlay, presentSKOverlay, type SKOverlayPosition } from '../services/SkOverlay'
22
+ import { dismissSKStoreProduct, presentSKStoreProduct } from '../services/SkStoreProduct'
23
23
 
24
24
  const sendMessage = (
25
25
  webViewRef: React.RefObject<WebView>,
@@ -97,7 +97,6 @@ const Format = ({ code, messageId, wrapper, onEvent, ...otherParams }: FormatPro
97
97
  setIframeLoaded(false)
98
98
  resetModal()
99
99
  context?.resetAll()
100
- context?.captureError(new Error('Processing iframe error'))
101
100
  }
102
101
 
103
102
  const resetModal = () => {
@@ -380,7 +379,6 @@ const Format = ({ code, messageId, wrapper, onEvent, ...otherParams }: FormatPro
380
379
  case 'error-component-iframe':
381
380
  case 'error-iframe':
382
381
  resetModal()
383
- context?.captureError(new Error('Processing modal iframe error'))
384
382
  break
385
383
 
386
384
  case 'open-skoverlay-iframe':
@@ -532,9 +530,14 @@ const Format = ({ code, messageId, wrapper, onEvent, ...otherParams }: FormatPro
532
530
  borderWidth: 0,
533
531
  ...iframeStyles,
534
532
  }}
535
- onError={() => {
536
- debug('iframe-error')
537
- reset()
533
+ onError={(error, shouldReset) => {
534
+ debug('iframe-error', {
535
+ error: error.toString(),
536
+ })
537
+ context?.captureError(error)
538
+ if (shouldReset) {
539
+ reset()
540
+ }
538
541
  }}
539
542
  onLoad={() => {
540
543
  debug('iframe-load')
@@ -568,9 +571,14 @@ const Format = ({ code, messageId, wrapper, onEvent, ...otherParams }: FormatPro
568
571
  width: '100%',
569
572
  borderWidth: 0,
570
573
  }}
571
- onError={() => {
572
- debug('modal-error')
573
- resetModal()
574
+ onError={(error, shouldReset) => {
575
+ debug('modal-error', {
576
+ error: error.toString(),
577
+ })
578
+ context?.captureError(error)
579
+ if (shouldReset) {
580
+ resetModal()
581
+ }
574
582
  }}
575
583
  onLoad={() => {
576
584
  debug('modal-load')
@@ -1,17 +1,19 @@
1
- import { forwardRef } from 'react'
2
- import type { StyleProp, ViewStyle } from 'react-native'
1
+ import { forwardRef, useRef } from 'react'
2
+ import { Linking, type StyleProp, type ViewStyle } from 'react-native'
3
3
  import { WebView, type WebViewMessageEvent } from 'react-native-webview'
4
4
 
5
5
  interface FrameWebViewProps {
6
6
  iframeUrl: string
7
7
  onMessage: (event: WebViewMessageEvent) => void
8
8
  style: StyleProp<ViewStyle>
9
- onError: () => void
9
+ onError: (error: Error, shouldReset?: boolean) => void
10
10
  onLoad: () => void
11
11
  }
12
12
 
13
13
  const FrameWebView = forwardRef<WebView, FrameWebViewProps>(
14
14
  ({ iframeUrl, onMessage, style, onError, onLoad }, forwardedRef) => {
15
+ const isLoadedRef = useRef(false)
16
+
15
17
  return (
16
18
  <WebView
17
19
  ref={forwardedRef}
@@ -35,9 +37,28 @@ const FrameWebView = forwardRef<WebView, FrameWebViewProps>(
35
37
  window.ReactNativeWebView.postMessage(JSON.stringify(event.data));
36
38
  }
37
39
  }, false);
40
+
38
41
  `}
39
- onError={onError}
40
- onLoad={onLoad}
42
+ onError={(event) =>
43
+ onError(
44
+ new Error(`${event.nativeEvent.title}: ${event.nativeEvent.description} [${event.nativeEvent.url}]`),
45
+ true
46
+ )
47
+ }
48
+ onLoad={() => {
49
+ isLoadedRef.current = true
50
+ onLoad()
51
+ }}
52
+ onShouldStartLoadWithRequest={(request) => {
53
+ if (!isLoadedRef.current || request.url.match(/^about:/) || request.url.startsWith(iframeUrl)) {
54
+ return true
55
+ }
56
+
57
+ Linking.openURL(request.url).catch((err) => {
58
+ onError(new Error(`Failed to open URL: ${request.url} [${err.message}]`))
59
+ })
60
+ return false
61
+ }}
41
62
  />
42
63
  )
43
64
  }