Browse Source

🦉 WIP: Update to WKWebView - WebView.ios.js

Jamon Holmgren 5 years ago
parent
commit
86ec597ea2
1 changed files with 113 additions and 17 deletions
  1. 113
    17
      js/WebView.ios.js

+ 113
- 17
js/WebView.ios.js View File

1
+/**
2
+ * Copyright (c) 2015-present, Facebook, Inc.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @format
8
+ * @noflow
9
+ */
10
+
1
 'use strict';
11
 'use strict';
2
 
12
 
3
 import React from 'react';
13
 import React from 'react';
73
   'link',
83
   'link',
74
   'address',
84
   'address',
75
   'calendarEvent',
85
   'calendarEvent',
86
+  'trackingNumber',
87
+  'flightNumber',
88
+  'lookupSuggestion',
76
   'none',
89
   'none',
77
   'all',
90
   'all',
78
 ];
91
 ];
117
   static JSNavigationScheme = JSNavigationScheme;
130
   static JSNavigationScheme = JSNavigationScheme;
118
   static NavigationType = NavigationType;
131
   static NavigationType = NavigationType;
119
   static propTypes = {
132
   static propTypes = {
120
-    ...ViewPropTypes,
133
+    ...DeprecatedViewPropTypes,
121
 
134
 
122
     html: deprecatedPropType(
135
     html: deprecatedPropType(
123
       PropTypes.string,
136
       PropTypes.string,
169
       PropTypes.number,
182
       PropTypes.number,
170
     ]),
183
     ]),
171
 
184
 
185
+    /**
186
+     * If true, use WKWebView instead of UIWebView.
187
+     * @platform ios
188
+     */
189
+    useWebKit: PropTypes.bool,
190
+
172
     /**
191
     /**
173
      * Function that returns a view to show if there's an error.
192
      * Function that returns a view to show if there's an error.
174
      */
193
      */
254
     /**
273
     /**
255
      * The style to apply to the `WebView`.
274
      * The style to apply to the `WebView`.
256
      */
275
      */
257
-    style: ViewPropTypes.style,
276
+    style: DeprecatedViewPropTypes.style,
258
 
277
 
259
     /**
278
     /**
260
      * Determines the types of data converted to clickable URLs in the web view's content.
279
      * Determines the types of data converted to clickable URLs in the web view's content.
271
      * - `'none'`
290
      * - `'none'`
272
      * - `'all'`
291
      * - `'all'`
273
      *
292
      *
293
+     * With the new WebKit implementation, we have three new values:
294
+     * - `'trackingNumber'`,
295
+     * - `'flightNumber'`,
296
+     * - `'lookupSuggestion'`,
297
+     *
274
      * @platform ios
298
      * @platform ios
275
      */
299
      */
276
     dataDetectorTypes: PropTypes.oneOfType([
300
     dataDetectorTypes: PropTypes.oneOfType([
316
      * Boolean that controls whether the web content is scaled to fit
340
      * Boolean that controls whether the web content is scaled to fit
317
      * the view and enables the user to change the scale. The default value
341
      * the view and enables the user to change the scale. The default value
318
      * is `true`.
342
      * is `true`.
343
+     *
344
+     * On iOS, when `useWebKit=true`, this prop will not work.
319
      */
345
      */
320
     scalesPageToFit: PropTypes.bool,
346
     scalesPageToFit: PropTypes.bool,
321
 
347
 
395
 
421
 
396
   static defaultProps = {
422
   static defaultProps = {
397
     originWhitelist: WebViewShared.defaultOriginWhitelist,
423
     originWhitelist: WebViewShared.defaultOriginWhitelist,
398
-    scalesPageToFit: true,
399
   };
424
   };
400
 
425
 
401
   state = {
426
   state = {
408
     if (this.props.startInLoadingState) {
433
     if (this.props.startInLoadingState) {
409
       this.setState({ viewState: WebViewState.LOADING });
434
       this.setState({ viewState: WebViewState.LOADING });
410
     }
435
     }
436
+
437
+    if (
438
+      this.props.useWebKit === true &&
439
+      this.props.scalesPageToFit !== undefined
440
+    ) {
441
+      console.warn(
442
+        'The scalesPageToFit property is not supported when useWebKit = true',
443
+      );
444
+    }
411
   }
445
   }
412
 
446
 
413
   render() {
447
   render() {
414
     let otherView = null;
448
     let otherView = null;
415
 
449
 
450
+    let scalesPageToFit;
451
+
452
+    if (this.props.useWebKit) {
453
+      ({ scalesPageToFit } = this.props);
454
+    } else {
455
+      ({ scalesPageToFit = true } = this.props);
456
+    }
457
+
416
     if (this.state.viewState === WebViewState.LOADING) {
458
     if (this.state.viewState === WebViewState.LOADING) {
417
       otherView = (this.props.renderLoading || defaultRenderLoading)();
459
       otherView = (this.props.renderLoading || defaultRenderLoading)();
418
     } else if (this.state.viewState === WebViewState.ERROR) {
460
     } else if (this.state.viewState === WebViewState.ERROR) {
425
       );
467
       );
426
     } else if (this.state.viewState !== WebViewState.IDLE) {
468
     } else if (this.state.viewState !== WebViewState.IDLE) {
427
       console.error(
469
       console.error(
428
-        'RNCWebView invalid state encountered: ' + this.state.loading,
470
+        'RCTWebView invalid state encountered: ' + this.state.loading,
429
       );
471
       );
430
     }
472
     }
431
 
473
 
440
 
482
 
441
     const nativeConfig = this.props.nativeConfig || {};
483
     const nativeConfig = this.props.nativeConfig || {};
442
 
484
 
443
-    const viewManager = nativeConfig.viewManager || RNCWebViewManager;
485
+    let viewManager = nativeConfig.viewManager;
444
 
486
 
445
-    const compiledWhitelist = (this.props.originWhitelist || []).map(
446
-      WebViewShared.originWhitelistToRegex,
447
-    );
487
+    if (this.props.useWebKit) {
488
+      viewManager = viewManager || RCTWKWebViewManager;
489
+    } else {
490
+      viewManager = viewManager || RCTWebViewManager;
491
+    }
492
+
493
+    const compiledWhitelist = [
494
+      'about:blank',
495
+      ...(this.props.originWhitelist || []),
496
+    ].map(WebViewShared.originWhitelistToRegex);
448
     const onShouldStartLoadWithRequest = (event) => {
497
     const onShouldStartLoadWithRequest = (event) => {
449
       let shouldStart = true;
498
       let shouldStart = true;
450
       const { url } = event.nativeEvent;
499
       const { url } = event.nativeEvent;
480
 
529
 
481
     const messagingEnabled = typeof this.props.onMessage === 'function';
530
     const messagingEnabled = typeof this.props.onMessage === 'function';
482
 
531
 
483
-    const NativeWebView = nativeConfig.component || RNCWebView;
532
+    let NativeWebView = nativeConfig.component;
533
+
534
+    if (this.props.useWebKit) {
535
+      NativeWebView = NativeWebView || RCTWKWebView;
536
+    } else {
537
+      NativeWebView = NativeWebView || RCTWebView;
538
+    }
484
 
539
 
485
     const webView = (
540
     const webView = (
486
       <NativeWebView
541
       <NativeWebView
502
         messagingEnabled={messagingEnabled}
557
         messagingEnabled={messagingEnabled}
503
         onMessage={this._onMessage}
558
         onMessage={this._onMessage}
504
         onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
559
         onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
505
-        scalesPageToFit={this.props.scalesPageToFit}
560
+        scalesPageToFit={scalesPageToFit}
506
         allowsInlineMediaPlayback={this.props.allowsInlineMediaPlayback}
561
         allowsInlineMediaPlayback={this.props.allowsInlineMediaPlayback}
507
         mediaPlaybackRequiresUserAction={
562
         mediaPlaybackRequiresUserAction={
508
           this.props.mediaPlaybackRequiresUserAction
563
           this.props.mediaPlaybackRequiresUserAction
520
     );
575
     );
521
   }
576
   }
522
 
577
 
578
+  _getCommands() {
579
+    if (!this.props.useWebKit) {
580
+      return UIManager.RCTWebView.Commands;
581
+    }
582
+
583
+    return UIManager.RCTWKWebView.Commands;
584
+  }
585
+
523
   /**
586
   /**
524
    * Go forward one page in the web view's history.
587
    * Go forward one page in the web view's history.
525
    */
588
    */
526
   goForward = () => {
589
   goForward = () => {
527
     UIManager.dispatchViewManagerCommand(
590
     UIManager.dispatchViewManagerCommand(
528
       this.getWebViewHandle(),
591
       this.getWebViewHandle(),
529
-      UIManager.RNCWebView.Commands.goForward,
592
+      this._getCommands().goForward,
530
       null,
593
       null,
531
     );
594
     );
532
   };
595
   };
537
   goBack = () => {
600
   goBack = () => {
538
     UIManager.dispatchViewManagerCommand(
601
     UIManager.dispatchViewManagerCommand(
539
       this.getWebViewHandle(),
602
       this.getWebViewHandle(),
540
-      UIManager.RNCWebView.Commands.goBack,
603
+      this._getCommands().goBack,
541
       null,
604
       null,
542
     );
605
     );
543
   };
606
   };
549
     this.setState({ viewState: WebViewState.LOADING });
612
     this.setState({ viewState: WebViewState.LOADING });
550
     UIManager.dispatchViewManagerCommand(
613
     UIManager.dispatchViewManagerCommand(
551
       this.getWebViewHandle(),
614
       this.getWebViewHandle(),
552
-      UIManager.RNCWebView.Commands.reload,
615
+      this._getCommands().reload,
553
       null,
616
       null,
554
     );
617
     );
555
   };
618
   };
560
   stopLoading = () => {
623
   stopLoading = () => {
561
     UIManager.dispatchViewManagerCommand(
624
     UIManager.dispatchViewManagerCommand(
562
       this.getWebViewHandle(),
625
       this.getWebViewHandle(),
563
-      UIManager.RNCWebView.Commands.stopLoading,
626
+      this._getCommands().stopLoading,
564
       null,
627
       null,
565
     );
628
     );
566
   };
629
   };
578
   postMessage = data => {
641
   postMessage = data => {
579
     UIManager.dispatchViewManagerCommand(
642
     UIManager.dispatchViewManagerCommand(
580
       this.getWebViewHandle(),
643
       this.getWebViewHandle(),
581
-      UIManager.RNCWebView.Commands.postMessage,
644
+      this._getCommands().postMessage,
582
       [String(data)],
645
       [String(data)],
583
     );
646
     );
584
   };
647
   };
592
   injectJavaScript = data => {
655
   injectJavaScript = data => {
593
     UIManager.dispatchViewManagerCommand(
656
     UIManager.dispatchViewManagerCommand(
594
       this.getWebViewHandle(),
657
       this.getWebViewHandle(),
595
-      UIManager.RNCWebView.Commands.injectJavaScript,
658
+      this._getCommands().injectJavaScript,
596
       [data],
659
       [data],
597
     );
660
     );
598
   };
661
   };
647
     const { onMessage } = this.props;
710
     const { onMessage } = this.props;
648
     onMessage && onMessage(event);
711
     onMessage && onMessage(event);
649
   };
712
   };
713
+
714
+  componentDidUpdate(prevProps) {
715
+    if (!(prevProps.useWebKit && this.props.useWebKit)) {
716
+      return;
717
+    }
718
+
719
+    this._showRedboxOnPropChanges(prevProps, 'allowsInlineMediaPlayback');
720
+    this._showRedboxOnPropChanges(prevProps, 'mediaPlaybackRequiresUserAction');
721
+    this._showRedboxOnPropChanges(prevProps, 'dataDetectorTypes');
722
+
723
+    if (this.props.scalesPageToFit !== undefined) {
724
+      console.warn(
725
+        'The scalesPageToFit property is not supported when useWebKit = true',
726
+      );
727
+    }
728
+  }
729
+
730
+  _showRedboxOnPropChanges(prevProps, propName: string) {
731
+    if (this.props[propName] !== prevProps[propName]) {
732
+      console.error(
733
+        `Changes to property ${propName} do nothing after the initial render.`,
734
+      );
735
+    }
736
+  }
650
 }
737
 }
651
 
738
 
652
-const RNCWebView = requireNativeComponent('RNCWebView');
739
+const RCTWebView = requireNativeComponent(
740
+  'RCTWebView',
741
+  WebView,
742
+  WebView.extraNativeComponentConfig,
743
+);
744
+const RCTWKWebView = requireNativeComponent(
745
+  'RCTWKWebView',
746
+  WebView,
747
+  WebView.extraNativeComponentConfig,
748
+);
653
 
749
 
654
 const styles = StyleSheet.create({
750
 const styles = StyleSheet.create({
655
   container: {
751
   container: {