@react-native-ohos/react-native-webview 13.15.2-rc.1 → 13.15.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
@@ -4,9 +4,9 @@ This project is based on [react-native-webview@13.15.0](https://github.com/react
4
4
 
5
5
  ## Documentation
6
6
 
7
- - [中文](https://gitee.com/react-native-oh-library/usage-docs/blob/master/zh-cn/react-native-webview.md)
7
+ - [中文](https://gitcode.com/OpenHarmony-RN/usage-docs/blob/master/zh-cn/react-native-webview.md)
8
8
 
9
- - [English](https://gitee.com/react-native-oh-library/usage-docs/blob/master/en/react-native-webview.md)
9
+ - [English](https://gitcode.com/OpenHarmony-RN/usage-docs/blob/master/en/react-native-webview.md)
10
10
 
11
11
  ## License
12
12
 
@@ -6,7 +6,7 @@
6
6
  "name": "@react-native-ohos/react-native-webview",
7
7
  "description": "main cpai architecture",
8
8
  "main": "index.ets",
9
- "version": "13.15.2-rc.1",
9
+ "version": "13.15.3",
10
10
  "dependencies": {
11
11
  "@rnoh/react-native-openharmony": "../react_native_openharmony.har"
12
12
  }
@@ -94,6 +94,7 @@ namespace rnoh
94
94
  object.setProperty(rt, "indicatorStyle", true);
95
95
  object.setProperty(rt, "newSource", "Object");
96
96
  object.setProperty(rt, "userAgent", true);
97
+ object.setProperty(rt, "schemeList", true);
97
98
  return object;
98
99
  }
99
100
 
@@ -101,7 +101,8 @@ namespace facebook::react
101
101
  showsVerticalScrollIndicator(convertRawProp(context, rawProps, "showsVerticalScrollIndicator", sourceProps.showsVerticalScrollIndicator, {true})),
102
102
  indicatorStyle(convertRawProp(context, rawProps, "indicatorStyle", sourceProps.indicatorStyle, {RNCWebViewIndicatorStyle::Default})),
103
103
  newSource(convertRawProp(context, rawProps, "newSource", sourceProps.newSource, {})),
104
- userAgent(convertRawProp(context, rawProps, "userAgent", sourceProps.userAgent, {}))
104
+ userAgent(convertRawProp(context, rawProps, "userAgent", sourceProps.userAgent, {})),
105
+ schemeList(convertRawProp(context, rawProps, "schemeList", sourceProps.schemeList, {}))
105
106
  {
106
107
  }
107
108
 
@@ -506,6 +506,7 @@ class RNCWebViewProps final : public ViewProps {
506
506
  RNCWebViewIndicatorStyle indicatorStyle{RNCWebViewIndicatorStyle::Default};
507
507
  RNCWebViewNewSourceStruct newSource{};
508
508
  std::string userAgent{};
509
+ folly::dynamic schemeList{};
509
510
  };
510
511
 
511
512
  } // namespace facebook::react
@@ -45,7 +45,7 @@ export interface WebViewProps extends ViewRawProps {
45
45
  cacheMode: CACHE_MODE
46
46
  domStorageEnabled: boolean
47
47
  scalesPageToFit: boolean
48
- hasOnShouldStartLoadWithRequestEvent?: boolean
48
+ hasOnShouldStartLoadWithRequestEvent?: boolean
49
49
  messagingModuleName: string
50
50
  webviewDebuggingEnabled: boolean
51
51
  scrollEnabled: boolean
@@ -65,8 +65,23 @@ export interface WebViewProps extends ViewRawProps {
65
65
  geolocationEnabled: boolean
66
66
  applicationNameForUserAgent: string
67
67
  pullToRefreshEnabled: boolean
68
+ schemeList: Array<string>
69
+ mediaCapturePermissionGrantType?: 'prompt' | 'grant' | 'deny' | 'grantIfSameHostElsePrompt' | 'grantIfSameHostElseDeny'
70
+ menuItems?: Array<MenuItem> | undefined;
68
71
  }
69
72
 
73
+ export interface MenuItem {
74
+ label: string,
75
+ key: string
76
+ }
77
+
78
+ export enum WebMediaCapturePermissionGrantType {
79
+ GRANT_IF_SAME_HOST_ELSE_PROMPT = "grantIfSameHostElsePrompt",
80
+ GRANT_IF_SAME_HOST_ELSE_DENY = "grantIfSameHostElseDeny",
81
+ DENY = "deny",
82
+ GRANT = "grant",
83
+ PROMPT = "prompt",
84
+ }
70
85
 
71
86
  export class RNCWebViewBridge {
72
87
  postMessage!: (data: string) => void;
@@ -25,9 +25,11 @@ import {
25
25
  WebViewDescriptor,
26
26
  REFRESH_OFFSET,
27
27
  MINHEIGHT,
28
+ WebMediaCapturePermissionGrantType,
29
+ MenuItem
28
30
  } from './Magic';
29
31
 
30
- import { abilityAccessCtrl, bundleManager } from '@kit.AbilityKit';
32
+ import { abilityAccessCtrl, bundleManager, Permissions } from '@kit.AbilityKit';
31
33
  import { WebViewTurboModule, ShouldStartParams, ShouldOverrideCallbackState } from './WebViewTurboModule';
32
34
  import { AnyThreadRNInstance, WorkerTaskRunnable } from '@rnoh/react-native-openharmony/src/main/ets/RNOH';
33
35
  import buffer from '@ohos.buffer';
@@ -62,6 +64,7 @@ export struct RNCWebView {
62
64
  url: string | Resource = "";
63
65
  body: string | undefined = "";
64
66
  controller: webview.WebviewController = new webview.WebviewController();
67
+ schemeHandler: webview.WebSchemeHandler = new webview.WebSchemeHandler();
65
68
  javaScriptEnable: boolean = true;
66
69
  allowFileAccess: boolean = true;
67
70
  forceDark: boolean = true;
@@ -98,6 +101,9 @@ export struct RNCWebView {
98
101
  private debounceTimer: number = -1
99
102
  static readonly DEBOUNCE_TIME: number = 100
100
103
  private isFirstDebounce: boolean = true
104
+ private isMainFrameLoaded:boolean = false;
105
+ private isCatchMainFrameError:boolean = false;
106
+ private isAlreadyRunInject:boolean = false;
101
107
 
102
108
  aboutToAppear() {
103
109
  try {
@@ -168,6 +174,8 @@ export struct RNCWebView {
168
174
  }
169
175
 
170
176
  onLoadingStart() {
177
+ this.isMainFrameLoaded = false;
178
+ this.isCatchMainFrameError = false;
171
179
  this.webViewBaseOperate?.emitLoadingStart({ progress: this.progress })
172
180
  }
173
181
 
@@ -181,6 +189,13 @@ export struct RNCWebView {
181
189
  this.webViewBaseOperate?.emitProgressChange({ progress: this.progress })
182
190
  if (this.progress === ONE_HUNDRED) {
183
191
  this.allowPageStartInProgress = true;
192
+
193
+ if (deviceInfo.sdkApiVersion >= 20 && this.isMainFrameLoaded && !this.isCatchMainFrameError) {
194
+ if (this.isAlreadyRunInject) {
195
+ this.onLoadFinished()
196
+ this.isAlreadyRunInject = false;
197
+ }
198
+ }
184
199
  }
185
200
  }
186
201
 
@@ -190,6 +205,7 @@ export struct RNCWebView {
190
205
  }
191
206
 
192
207
  runInjectedJavaScript() {
208
+ this.isAlreadyRunInject = true;
193
209
  let injectedJS = this.descriptorWrapper.rawProps.injectedJavaScript
194
210
  if (this.javaScriptEnable && injectedJS != "" && this.controllerAttached) {
195
211
  try {
@@ -287,6 +303,20 @@ export struct RNCWebView {
287
303
  this.descriptorWrapper.rawProps.applicationNameForUserAgent)
288
304
  this.webViewBaseOperate.setFraudulentWebsiteWarningEnabled(this.descriptorWrapper.rawProps.fraudulentWebsiteWarningEnabled)
289
305
 
306
+ let schemeList = this.descriptorWrapper.rawProps.schemeList
307
+ if(schemeList?.length){
308
+ schemeList.forEach(scheme=>{
309
+ this.schemeHandler.onRequestStart((request: webview.WebSchemeHandlerRequest, resourceHandler: webview.WebResourceHandler) => {
310
+ console.log("[schemeHandler] onRequestStart");
311
+ return true;
312
+ })
313
+ this.schemeHandler.onRequestStop((request: webview.WebSchemeHandlerRequest) => {
314
+ console.log("[schemeHandler] onRequestStop");
315
+ });
316
+ this.controller.setWebSchemeHandler(scheme, this.schemeHandler);
317
+ })
318
+ }
319
+
290
320
  let baseUrl = this.source.baseUrl
291
321
  let uri = this.source.uri
292
322
  if (this.source.html != undefined && this.source.html != "") {
@@ -425,33 +455,130 @@ export struct RNCWebView {
425
455
  return false
426
456
  }
427
457
 
458
+ onCreateMenu = (menuItems: Array<TextMenuItem>) => {
459
+ let customMenuItems = this.descriptorWrapper.rawProps.menuItems
460
+ if (customMenuItems == undefined) {
461
+ return menuItems;
462
+ } else if (customMenuItems.length == 0) {
463
+ return [];
464
+ } else {
465
+ let menuItemsArray: Array<TextMenuItem> = [];
466
+ for (let index = 0; index < customMenuItems.length; index++) {
467
+ let element: MenuItem = customMenuItems[index];
468
+ let customItem: TextMenuItem = {
469
+ content: element.label,
470
+ id: TextMenuItemId.of(element.key)
471
+ };
472
+ menuItemsArray.push(customItem)
473
+ }
474
+ return menuItemsArray;
475
+ }
476
+ }
477
+
478
+ onMenuItemClick(menuItem: TextMenuItem): boolean {
479
+ if (this.descriptorWrapper.rawProps.menuItems != undefined) {
480
+ this.controller.runJavaScript("(function(){return {selection: window.getSelection().toString()} })()")
481
+ .then((result: string) => {
482
+ this.webViewBaseOperate?.customMenuSelection(menuItem, result)
483
+ })
484
+ .catch((error: string | Error) => {
485
+ Logger.info('[RNOH] function onMenuItemClick error: ' + error);
486
+ })
487
+ // 禁用系统默认行为
488
+ return true;
489
+ }
490
+ return false;
491
+ }
492
+
493
+ onPermissionRequestAlert(event: OnPermissionRequestEvent){
494
+ AlertDialog.show({
495
+ title: this.resourceToString($r('app.string.on_confirm')) + event.request.getOrigin(),
496
+ message: this.getPermissionDialogMessage(event),
497
+ alignment: DialogAlignment.Center,
498
+ primaryButton: {
499
+ value: $r('app.string.deny'),
500
+ action: () => {
501
+ event.request.deny();
502
+ }
503
+ },
504
+ secondaryButton: {
505
+ value: $r('app.string.on_confirm'),
506
+ action: () => {
507
+ event.request.grant(event.request.getAccessibleResource());
508
+ }
509
+ },
510
+ cancel: () => {
511
+ event.request.deny();
512
+ }
513
+ })
514
+ }
515
+
516
+ async handleMediaCapturePermissionGrantType(resources: string[], domain: string) {
517
+ let permissionList: Array<Permissions> = [];
518
+ resources.forEach(resource => {
519
+ switch (resource.toString()) {
520
+ case 'TYPE_VIDEO_CAPTURE':
521
+ permissionList.push('ohos.permission.CAMERA');
522
+ break;
523
+ case 'TYPE_AUDIO_CAPTURE':
524
+ permissionList.push('ohos.permission.MICROPHONE');
525
+ break;
526
+ }
527
+ });
528
+
529
+ await atManager.requestPermissionsFromUser(this.ctx.uiAbilityContext, permissionList);
530
+ }
531
+
428
532
  build() {
429
533
  Stack() {
430
534
  if ( deviceInfo.sdkApiVersion >= 20) {
431
535
  Web({ src: "", controller: this.controller, renderMode: this.renderMode })
432
536
  .mixedMode(this.mode)
433
- .onPermissionRequest((event: OnPermissionRequestEvent) => {
537
+ .onPermissionRequest(async (event: OnPermissionRequestEvent) => {
434
538
  if (event && (this.getPermissionDialogMessage(event) != "TYPE_SENSOR")) {
435
- AlertDialog.show({
436
- title: this.resourceToString($r('app.string.on_confirm')) + event.request.getOrigin(),
437
- message: this.getPermissionDialogMessage(event),
438
- alignment: DialogAlignment.Center,
439
- primaryButton: {
440
- value: $r('app.string.deny'),
441
- action: () => {
539
+ const resources: string[] = event.request.getAccessibleResource();
540
+ if (resources.indexOf('TYPE_AUDIO_CAPTURE') >= 0 || resources.indexOf('TYPE_VIDEO_CAPTURE') >= 0 ) {
541
+ const originUrl = this.webViewBaseOperate?.verifyURLFormat(event.request.getOrigin(), this.source.html,
542
+ this.source.baseUrl);
543
+ const currentUrl = this.webViewBaseOperate?.verifyURLFormat(this.controller.getUrl(), this.source.html,
544
+ this.source.baseUrl);
545
+ const originDomain: string = OSUrl.URL.parseURL(originUrl).hostname;
546
+ const currentDomain: string = OSUrl.URL.parseURL(currentUrl).hostname;
547
+ let mediaCapturePermissionGrantType: string = WebMediaCapturePermissionGrantType.PROMPT
548
+ if (this.descriptorWrapper.rawProps.mediaCapturePermissionGrantType != undefined) {
549
+ mediaCapturePermissionGrantType = this.descriptorWrapper.rawProps.mediaCapturePermissionGrantType;
550
+ }
551
+ if (mediaCapturePermissionGrantType != WebMediaCapturePermissionGrantType.DENY) {
552
+ await this.handleMediaCapturePermissionGrantType(resources, originDomain)
553
+ }
554
+ switch (mediaCapturePermissionGrantType) {
555
+ case WebMediaCapturePermissionGrantType.GRANT_IF_SAME_HOST_ELSE_PROMPT:
556
+ if (originDomain != currentDomain) {
557
+ this.onPermissionRequestAlert(event)
558
+ } else {
559
+ event.request.grant(resources);
560
+ }
561
+ break;
562
+ case WebMediaCapturePermissionGrantType.GRANT_IF_SAME_HOST_ELSE_DENY:
563
+ if (originDomain != currentDomain) {
564
+ event.request.deny();
565
+ } else {
566
+ event.request.grant(resources);
567
+ }
568
+ break;
569
+ case WebMediaCapturePermissionGrantType.DENY:
442
570
  event.request.deny();
443
- }
444
- },
445
- secondaryButton: {
446
- value: $r('app.string.on_confirm'),
447
- action: () => {
448
- event.request.grant(event.request.getAccessibleResource());
449
- }
450
- },
451
- cancel: () => {
452
- event.request.deny();
571
+ break;
572
+ case WebMediaCapturePermissionGrantType.GRANT:
573
+ event.request.grant(resources);
574
+ break;
575
+ case WebMediaCapturePermissionGrantType.PROMPT:
576
+ this.onPermissionRequestAlert(event)
577
+ break;
453
578
  }
454
- })
579
+ } else {
580
+ this.onPermissionRequestAlert(event)
581
+ }
455
582
  }
456
583
  })
457
584
  .width(this.webviewWidth)
@@ -480,11 +607,36 @@ export struct RNCWebView {
480
607
  scrollForward: this.nestedScroll,
481
608
  scrollBackward: this.nestedScroll,
482
609
  })
483
- .onLoadStarted(() => this.onPageBegin())
484
- .onLoadFinished(() => this.onLoadFinished())
485
- .onPageEnd(() => {this.onPageEndExecuteRunInjectedJavaScript()})
486
- .onErrorReceive((event: OnErrorReceiveEvent) => this.webViewBaseOperate?.emitLoadingError(event))
487
- .onHttpErrorReceive((event: OnHttpErrorReceiveEvent) => this.webViewBaseOperate?.emitHttpError(event))
610
+ .onLoadStarted(() => {
611
+ this.isMainFrameLoaded = false;
612
+ this.isCatchMainFrameError = false;
613
+ this.onPageBegin()
614
+ })
615
+ .onPageEnd(() => {
616
+ this.isMainFrameLoaded = true;
617
+ if (this.isCatchMainFrameError) {
618
+ if (this.source.html) {
619
+ this.onLoadFinished();
620
+ }
621
+ return;
622
+ }
623
+ this.onPageEndExecuteRunInjectedJavaScript()
624
+
625
+ })
626
+ .onErrorReceive((event: OnErrorReceiveEvent) => {
627
+ const isMainFrame = event.request.isMainFrame();
628
+ if (isMainFrame) {
629
+ this.isCatchMainFrameError = true;
630
+ }
631
+ this.webViewBaseOperate?.emitLoadingError(event)
632
+ })
633
+ .onHttpErrorReceive((event: OnHttpErrorReceiveEvent) => {
634
+ const isMainFrame = event.request.isMainFrame();
635
+ if (isMainFrame) {
636
+ this.isCatchMainFrameError = true;
637
+ }
638
+ this.webViewBaseOperate?.emitHttpError(event)
639
+ })
488
640
  .onControllerAttached(() => this.controllerAttachedInit())
489
641
  .onAlert((event: AlertEvent) => this.onJavascriptAlert(event))
490
642
  .onConfirm((event: AlertEvent) => this.onJavascriptConfirm(event))
@@ -499,31 +651,58 @@ export struct RNCWebView {
499
651
  .onRenderExited((event: OnRenderExitedEvent) => this.webViewBaseOperate?.onRenderExited(event))
500
652
  .onLoadIntercept((event: OnLoadInterceptEvent) => this.onLoadIntercept(event))
501
653
  .onTitleReceive((event: OnTitleReceiveEvent) => this.webViewBaseOperate?.onTitleReceive(event))
654
+ .editMenuOptions({
655
+ onCreateMenu: this.onCreateMenu.bind(this),
656
+ onMenuItemClick: this.onMenuItemClick.bind(this),
657
+ })
502
658
  } else {
503
659
  Web({ src: "", controller: this.controller, renderMode: this.renderMode })
504
660
  .mixedMode(this.mode)
505
- .onPermissionRequest((event: OnPermissionRequestEvent) => {
661
+ .onPermissionRequest(async (event: OnPermissionRequestEvent) => {
506
662
  if (event && (this.getPermissionDialogMessage(event) != "TYPE_SENSOR")) {
507
- AlertDialog.show({
508
- title: this.resourceToString($r('app.string.on_confirm')) + event.request.getOrigin(),
509
- message: this.getPermissionDialogMessage(event),
510
- alignment: DialogAlignment.Center,
511
- primaryButton: {
512
- value: $r('app.string.deny'),
513
- action: () => {
663
+ const resources: string[] = event.request.getAccessibleResource();
664
+ if (resources.indexOf('TYPE_AUDIO_CAPTURE') >= 0 || resources.indexOf('TYPE_VIDEO_CAPTURE') >= 0 ) {
665
+ const originUrl = this.webViewBaseOperate?.verifyURLFormat(event.request.getOrigin(), this.source.html,
666
+ this.source.baseUrl);
667
+ const currentUrl = this.webViewBaseOperate?.verifyURLFormat(this.controller.getUrl(), this.source.html,
668
+ this.source.baseUrl);
669
+ const originDomain: string = OSUrl.URL.parseURL(originUrl).hostname;
670
+ const currentDomain: string = OSUrl.URL.parseURL(currentUrl).hostname;
671
+ let mediaCapturePermissionGrantType: string = WebMediaCapturePermissionGrantType.PROMPT
672
+ if (this.descriptorWrapper.rawProps.mediaCapturePermissionGrantType != undefined) {
673
+ mediaCapturePermissionGrantType = this.descriptorWrapper.rawProps.mediaCapturePermissionGrantType;
674
+ }
675
+ if (mediaCapturePermissionGrantType != WebMediaCapturePermissionGrantType.DENY) {
676
+ await this.handleMediaCapturePermissionGrantType(resources, originDomain)
677
+ }
678
+ switch (mediaCapturePermissionGrantType) {
679
+ case WebMediaCapturePermissionGrantType.GRANT_IF_SAME_HOST_ELSE_PROMPT:
680
+ if (originDomain != currentDomain) {
681
+ this.onPermissionRequestAlert(event)
682
+ } else {
683
+ event.request.grant(resources);
684
+ }
685
+ break;
686
+ case WebMediaCapturePermissionGrantType.GRANT_IF_SAME_HOST_ELSE_DENY:
687
+ if (originDomain != currentDomain) {
688
+ event.request.deny();
689
+ } else {
690
+ event.request.grant(resources);
691
+ }
692
+ break;
693
+ case WebMediaCapturePermissionGrantType.DENY:
514
694
  event.request.deny();
515
- }
516
- },
517
- secondaryButton: {
518
- value: $r('app.string.on_confirm'),
519
- action: () => {
520
- event.request.grant(event.request.getAccessibleResource());
521
- }
522
- },
523
- cancel: () => {
524
- event.request.deny();
695
+ break;
696
+ case WebMediaCapturePermissionGrantType.GRANT:
697
+ event.request.grant(resources);
698
+ break;
699
+ case WebMediaCapturePermissionGrantType.PROMPT:
700
+ this.onPermissionRequestAlert(event)
701
+ break;
525
702
  }
526
- })
703
+ } else {
704
+ this.onPermissionRequestAlert(event)
705
+ }
527
706
  }
528
707
  })
529
708
 
@@ -571,7 +750,10 @@ export struct RNCWebView {
571
750
  .onRenderExited((event: OnRenderExitedEvent) => this.webViewBaseOperate?.onRenderExited(event))
572
751
  .onLoadIntercept((event: OnLoadInterceptEvent) => this.onLoadIntercept(event))
573
752
  .onTitleReceive((event: OnTitleReceiveEvent) => this.webViewBaseOperate?.onTitleReceive(event))
574
-
753
+ .editMenuOptions({
754
+ onCreateMenu: this.onCreateMenu.bind(this),
755
+ onMenuItemClick: this.onMenuItemClick.bind(this),
756
+ })
575
757
  }
576
758
  }
577
759
  .width(this.webviewWidth)
@@ -454,4 +454,17 @@ export class BaseOperate {
454
454
  Logger.error(TAG, `[RNOH] onTitleReceive Errorcode: ${error.code}`);
455
455
  }
456
456
  }
457
+
458
+ customMenuSelection(menuItem: TextMenuItem, selectionText: string) {
459
+ try {
460
+ selectionText = JSON.parse(selectionText).selection;
461
+ this.eventEmitter!.emit('customMenuSelection', {
462
+ label: menuItem.content.toString(),
463
+ key: JSON.parse(JSON.stringify(menuItem.id)).id_,
464
+ selectedText: selectionText
465
+ })
466
+ } catch (error) {
467
+ Logger.error(TAG, `[RNOH] customMenuSelection Errorcode: ${error.code}`);
468
+ }
469
+ }
457
470
  }
@@ -101,6 +101,7 @@ export namespace RNCWebView {
101
101
  indicatorStyle?: 'default' | 'black' | 'white';
102
102
  newSource: {uri?: string, method?: string, body?: string, headers?: {name: string, value: string}[], html?: string, baseUrl?: string};
103
103
  userAgent?: string;
104
+ schemeList?: unknown;
104
105
  }
105
106
 
106
107
  export interface Props extends ViewBaseProps {}
@@ -425,7 +426,10 @@ export namespace RNCWebView {
425
426
  get userAgent() {
426
427
  return this.rawProps.userAgent;
427
428
  }
428
-
429
+
430
+ get schemeList() {
431
+ return this.rawProps.schemeList;
432
+ }
429
433
 
430
434
  }
431
435
 
Binary file
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "Thibault Malbranche <malbranche.thibault@gmail.com>"
10
10
  ],
11
11
  "license": "MIT",
12
- "version": "13.15.2-rc.1",
12
+ "version": "13.15.3",
13
13
  "homepage": "https://gitcode.com/openharmony-sig/rntpc_react-native-webview/tree/br_rnoh0.77#readme",
14
14
  "scripts": {
15
15
  "macos": "react-native run-macos --scheme WebviewExample --project-path example/macos",
@@ -48,6 +48,7 @@
48
48
  "@react-native/eslint-config": "0.73.2",
49
49
  "@react-native/metro-config": "0.73.5",
50
50
  "@react-native/typescript-config": "0.73.1",
51
+ "@react-native-oh/react-native-harmony-cli": "npm:@react-native-oh/react-native-harmony-cli@0.77.18-1",
51
52
  "@rnx-kit/metro-config": "1.3.15",
52
53
  "@semantic-release/git": "7.0.16",
53
54
  "@types/invariant": "^2.2.30",
@@ -303,6 +303,7 @@ export interface NativeProps extends ViewProps {
303
303
  baseUrl?: string;
304
304
  }>;
305
305
  userAgent?: string;
306
+ schemeList?: ReadonlyArray<string>;
306
307
  }
307
308
 
308
309
  export interface NativeCommands {
@@ -67,7 +67,7 @@ const WebViewComponent = forwardRef<{}, IOSWebViewProps & { scalesPageToFit: boo
67
67
  injectedJavaScript,
68
68
  injectedJavaScriptBeforeContentLoaded,
69
69
  injectedJavaScriptObject,
70
- menuItems = [],
70
+ menuItems,
71
71
  injectedJavaScriptForMainFrameOnly = true,
72
72
  injectedJavaScriptBeforeContentLoadedForMainFrameOnly = true,
73
73
  thirdPartyCookiesEnabled = false,