瀏覽代碼

Got macOS working.

Tom Underhill 5 年之前
父節點
當前提交
290c68a819

+ 2
- 2
example/examples/InlineWebView.js 查看文件

@@ -17,7 +17,7 @@ const HTML = `
17 17
 <!DOCTYPE html>\n
18 18
 <html>
19 19
   <head>
20
-    <title>Hello Static World</title>
20
+    <title>Hello World</title>
21 21
     <meta http-equiv="content-type" content="text/html; charset=utf-8">
22 22
     <meta name="viewport" content="width=320, user-scalable=no">
23 23
     <style type="text/css">
@@ -36,7 +36,7 @@ const HTML = `
36 36
     </style>
37 37
   </head>
38 38
   <body>
39
-    <h1>Hello Static World</h1>
39
+    <h1>Hello World</h1>
40 40
   </body>
41 41
 </html>
42 42
 `;

+ 30
- 0
example/macos/RNCWebViewExample.xcodeproj/project.pbxproj 查看文件

@@ -20,6 +20,7 @@
20 20
 		13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
21 21
 		13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
22 22
 		146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };
23
+		38116A3723BBECFB00ACE311 /* libRNCWebView-macOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 38116A3623BBECFB00ACE311 /* libRNCWebView-macOS.a */; };
23 24
 		38C1421623BBE5B500902604 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 38C1421523BBE5B500902604 /* main.m */; };
24 25
 		38C1421823BBE65C00902604 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 38C1421723BBE65C00902604 /* AppDelegate.m */; };
25 26
 		38C1421C23BBE70D00902604 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 38C1421B23BBE70D00902604 /* ViewController.m */; };
@@ -142,6 +143,20 @@
142 143
 			remoteGlobalIDString = 3D383D621EBD27B9005632C8;
143 144
 			remoteInfo = "double-conversion-tvOS";
144 145
 		};
146
+		38116A3523BBECFB00ACE311 /* PBXContainerItemProxy */ = {
147
+			isa = PBXContainerItemProxy;
148
+			containerPortal = 3DC5395A220F2C940035D3A3 /* RNCWebView.xcodeproj */;
149
+			proxyType = 2;
150
+			remoteGlobalIDString = 38116A3323BBECB700ACE311;
151
+			remoteInfo = "RNCWebView-macOS";
152
+		};
153
+		38116A6E23BBED1000ACE311 /* PBXContainerItemProxy */ = {
154
+			isa = PBXContainerItemProxy;
155
+			containerPortal = 3DC5395A220F2C940035D3A3 /* RNCWebView.xcodeproj */;
156
+			proxyType = 1;
157
+			remoteGlobalIDString = 38116A2923BBECB700ACE311;
158
+			remoteInfo = "RNCWebView-macOS";
159
+		};
145 160
 		38C1417523BBE33000902604 /* PBXContainerItemProxy */ = {
146 161
 			isa = PBXContainerItemProxy;
147 162
 			containerPortal = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;
@@ -491,6 +506,7 @@
491 506
 			isa = PBXFrameworksBuildPhase;
492 507
 			buildActionMask = 2147483647;
493 508
 			files = (
509
+				38116A3723BBECFB00ACE311 /* libRNCWebView-macOS.a in Frameworks */,
494 510
 				38C1422523BBEC1D00902604 /* libRCTAnimation.a in Frameworks */,
495 511
 				38C1422423BBEB8300902604 /* libRCTText.a in Frameworks */,
496 512
 				38C1422323BBEB6400902604 /* libRCTNetwork.a in Frameworks */,
@@ -637,6 +653,7 @@
637 653
 			isa = PBXGroup;
638 654
 			children = (
639 655
 				3DC5398C220F2C940035D3A3 /* libRNCWebView.a */,
656
+				38116A3623BBECFB00ACE311 /* libRNCWebView-macOS.a */,
640 657
 			);
641 658
 			name = Products;
642 659
 			sourceTree = "<group>";
@@ -757,6 +774,7 @@
757 774
 			buildRules = (
758 775
 			);
759 776
 			dependencies = (
777
+				38116A6F23BBED1000ACE311 /* PBXTargetDependency */,
760 778
 			);
761 779
 			name = "RNCWebViewExample-macOS";
762 780
 			productName = "Hello World";
@@ -941,6 +959,13 @@
941 959
 			remoteRef = 2DF0FFE82056DD460020B375 /* PBXContainerItemProxy */;
942 960
 			sourceTree = BUILT_PRODUCTS_DIR;
943 961
 		};
962
+		38116A3623BBECFB00ACE311 /* libRNCWebView-macOS.a */ = {
963
+			isa = PBXReferenceProxy;
964
+			fileType = archive.ar;
965
+			path = "libRNCWebView-macOS.a";
966
+			remoteRef = 38116A3523BBECFB00ACE311 /* PBXContainerItemProxy */;
967
+			sourceTree = BUILT_PRODUCTS_DIR;
968
+		};
944 969
 		38C1417623BBE33000902604 /* libRCTActionSheet.a */ = {
945 970
 			isa = PBXReferenceProxy;
946 971
 			fileType = archive.ar;
@@ -1309,6 +1334,11 @@
1309 1334
 			name = RNCWebView;
1310 1335
 			targetProxy = 1990B95122398FC4009E5EA1 /* PBXContainerItemProxy */;
1311 1336
 		};
1337
+		38116A6F23BBED1000ACE311 /* PBXTargetDependency */ = {
1338
+			isa = PBXTargetDependency;
1339
+			name = "RNCWebView-macOS";
1340
+			targetProxy = 38116A6E23BBED1000ACE311 /* PBXContainerItemProxy */;
1341
+		};
1312 1342
 /* End PBXTargetDependency section */
1313 1343
 
1314 1344
 /* Begin PBXVariantGroup section */

+ 2
- 2
example/macos/RNCWebViewExample.xcodeproj/xcshareddata/xcschemes/RNCWebViewExample-macOS.xcscheme 查看文件

@@ -3,8 +3,8 @@
3 3
    LastUpgradeVersion = "1120"
4 4
    version = "1.3">
5 5
    <BuildAction
6
-      parallelizeBuildables = "YES"
7
-      buildImplicitDependencies = "YES">
6
+      parallelizeBuildables = "NO"
7
+      buildImplicitDependencies = "NO">
8 8
       <BuildActionEntries>
9 9
          <BuildActionEntry
10 10
             buildForTesting = "YES"

+ 69
- 10
ios/RNCWebView.m 查看文件

@@ -9,7 +9,7 @@
9 9
 #import <React/RCTConvert.h>
10 10
 #import <React/RCTAutoInsetsProtocol.h>
11 11
 #import "RNCWKProcessPoolManager.h"
12
-#import <UIKit/UIKit.h>
12
+#import <React/RCTUIKit.h>
13 13
 
14 14
 #import "objc/runtime.h"
15 15
 
@@ -19,6 +19,7 @@ static NSString *const MessageHandlerName = @"ReactNativeWebView";
19 19
 static NSURLCredential* clientAuthenticationCredential;
20 20
 static NSDictionary* customCertificatesForHost;
21 21
 
22
+#if !TARGET_OS_OSX
22 23
 // runtime trick to remove WKWebView keyboard default toolbar
23 24
 // see: http://stackoverflow.com/questions/19033292/ios-7-uiwebview-keyboard-issue/19042279#19042279
24 25
 @interface _SwizzleHelperWK : UIView
@@ -39,8 +40,13 @@ static NSDictionary* customCertificatesForHost;
39 40
     return nil;
40 41
 }
41 42
 @end
43
+#endif // !TARGET_OS_OSX
42 44
 
43
-@interface RNCWebView () <WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler, UIScrollViewDelegate, RCTAutoInsetsProtocol>
45
+@interface RNCWebView () <WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler,
46
+#if !TARGET_OS_OSX
47
+    UIScrollViewDelegate,
48
+#endif // !TARGET_OS_OSX
49
+    RCTAutoInsetsProtocol>
44 50
 @property (nonatomic, copy) RCTDirectEventBlock onLoadingStart;
45 51
 @property (nonatomic, copy) RCTDirectEventBlock onLoadingFinish;
46 52
 @property (nonatomic, copy) RCTDirectEventBlock onLoadingError;
@@ -55,14 +61,16 @@ static NSDictionary* customCertificatesForHost;
55 61
 
56 62
 @implementation RNCWebView
57 63
 {
58
-  UIColor * _savedBackgroundColor;
64
+  RCTUIColor * _savedBackgroundColor;
59 65
   BOOL _savedHideKeyboardAccessoryView;
60 66
   BOOL _savedKeyboardDisplayRequiresUserAction;
61 67
 
62 68
   // Workaround for StatusBar appearance bug for iOS 12
63 69
   // https://github.com/react-native-community/react-native-webview/issues/62
64 70
   BOOL _isFullScreenVideoOpen;
71
+#if !TARGET_OS_OSX
65 72
   UIStatusBarStyle _savedStatusBarStyle;
73
+#endif // !TARGET_OS_OSX
66 74
   BOOL _savedStatusBarHidden;
67 75
 
68 76
 #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
@@ -73,7 +81,7 @@ static NSDictionary* customCertificatesForHost;
73 81
 - (instancetype)initWithFrame:(CGRect)frame
74 82
 {
75 83
   if ((self = [super initWithFrame:frame])) {
76
-    super.backgroundColor = [UIColor clearColor];
84
+    super.backgroundColor = [RCTUIColor clearColor];
77 85
     _bounces = YES;
78 86
     _scrollEnabled = YES;
79 87
     _showsHorizontalScrollIndicator = YES;
@@ -82,14 +90,17 @@ static NSDictionary* customCertificatesForHost;
82 90
     _automaticallyAdjustContentInsets = YES;
83 91
     _contentInset = UIEdgeInsetsZero;
84 92
     _savedKeyboardDisplayRequiresUserAction = YES;
93
+#if !TARGET_OS_OSX
85 94
     _savedStatusBarStyle = RCTSharedApplication().statusBarStyle;
86 95
     _savedStatusBarHidden = RCTSharedApplication().statusBarHidden;
96
+#endif // !TARGET_OS_OSX
87 97
 
88 98
 #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
89 99
     _savedContentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
90 100
 #endif
91 101
   }
92 102
 
103
+#if !TARGET_OS_OSX
93 104
   if (@available(iOS 12.0, *)) {
94 105
     // Workaround for a keyboard dismissal bug present in iOS 12
95 106
     // https://openradar.appspot.com/radar?id=5018321736957952
@@ -114,7 +125,7 @@ static NSDictionary* customCertificatesForHost;
114 125
                                                    name:UIWindowDidBecomeHiddenNotification
115 126
                                                  object:nil];
116 127
   }
117
-
128
+#endif // !TARGET_OS_OSX
118 129
   return self;
119 130
 }
120 131
 
@@ -209,6 +220,7 @@ static NSDictionary* customCertificatesForHost;
209 220
       }
210 221
     }
211 222
 
223
+#if !TARGET_OS_OSX
212 224
     wkWebViewConfig.allowsInlineMediaPlayback = _allowsInlineMediaPlayback;
213 225
 #if WEBKIT_IOS_10_APIS_AVAILABLE
214 226
     wkWebViewConfig.mediaTypesRequiringUserActionForPlayback = _mediaPlaybackRequiresUserAction
@@ -218,6 +230,7 @@ static NSDictionary* customCertificatesForHost;
218 230
 #else
219 231
     wkWebViewConfig.mediaPlaybackRequiresUserAction = _mediaPlaybackRequiresUserAction;
220 232
 #endif
233
+#endif // !TARGET_OS_OSX
221 234
 
222 235
     if (_applicationNameForUserAgent) {
223 236
         wkWebViewConfig.applicationNameForUserAgent = [NSString stringWithFormat:@"%@ %@", wkWebViewConfig.applicationNameForUserAgent, _applicationNameForUserAgent];
@@ -287,15 +300,19 @@ static NSDictionary* customCertificatesForHost;
287 300
 
288 301
     _webView = [[WKWebView alloc] initWithFrame:self.bounds configuration: wkWebViewConfig];
289 302
     [self setBackgroundColor: _savedBackgroundColor];
303
+#if !TARGET_OS_OSX
290 304
     _webView.scrollView.delegate = self;
305
+#endif // !TARGET_OS_OSX
291 306
     _webView.UIDelegate = self;
292 307
     _webView.navigationDelegate = self;
308
+#if !TARGET_OS_OSX
293 309
     _webView.scrollView.scrollEnabled = _scrollEnabled;
294 310
     _webView.scrollView.pagingEnabled = _pagingEnabled;
295 311
     _webView.scrollView.bounces = _bounces;
296 312
     _webView.scrollView.showsHorizontalScrollIndicator = _showsHorizontalScrollIndicator;
297 313
     _webView.scrollView.showsVerticalScrollIndicator = _showsVerticalScrollIndicator;
298 314
     _webView.scrollView.directionalLockEnabled = _directionalLockEnabled;
315
+#endif // !TARGET_OS_OSX
299 316
     _webView.allowsLinkPreview = _allowsLinkPreview;
300 317
     [_webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
301 318
     _webView.allowsBackForwardNavigationGestures = _allowsBackForwardNavigationGestures;
@@ -329,13 +346,16 @@ static NSDictionary* customCertificatesForHost;
329 346
         [_webView.configuration.userContentController removeScriptMessageHandlerForName:MessageHandlerName];
330 347
         [_webView removeObserver:self forKeyPath:@"estimatedProgress"];
331 348
         [_webView removeFromSuperview];
349
+#if !TARGET_OS_OSX
332 350
         _webView.scrollView.delegate = nil;
351
+#endif // !TARGET_OS_OSX
333 352
         _webView = nil;
334 353
     }
335 354
 
336 355
     [super removeFromSuperview];
337 356
 }
338 357
 
358
+#if !TARGET_OS_OSX
339 359
 -(void)showFullScreenVideoStatusBars
340 360
 {
341 361
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
@@ -383,6 +403,7 @@ static NSDictionary* customCertificatesForHost;
383 403
       }];
384 404
     }
385 405
 }
406
+#endif // !TARGET_OS_OSX
386 407
 
387 408
 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
388 409
     if ([keyPath isEqual:@"estimatedProgress"] && object == self.webView) {
@@ -396,7 +417,7 @@ static NSDictionary* customCertificatesForHost;
396 417
     }
397 418
 }
398 419
 
399
-- (void)setBackgroundColor:(UIColor *)backgroundColor
420
+- (void)setBackgroundColor:(RCTUIColor *)backgroundColor
400 421
 {
401 422
   _savedBackgroundColor = backgroundColor;
402 423
   if (_webView == nil) {
@@ -404,9 +425,11 @@ static NSDictionary* customCertificatesForHost;
404 425
   }
405 426
 
406 427
   CGFloat alpha = CGColorGetAlpha(backgroundColor.CGColor);
428
+#if !TARGET_OS_OSX
407 429
   self.opaque = _webView.opaque = (alpha == 1.0);
408 430
   _webView.scrollView.backgroundColor = backgroundColor;
409 431
   _webView.backgroundColor = backgroundColor;
432
+#endif // !TARGET_OS_OSX
410 433
 }
411 434
 
412 435
 #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
@@ -473,14 +496,22 @@ static NSDictionary* customCertificatesForHost;
473 496
 {
474 497
   _contentInset = contentInset;
475 498
   [RCTView autoAdjustInsetsForView:self
499
+#if !TARGET_OS_OSX
476 500
                     withScrollView:_webView.scrollView
501
+#else
502
+                    withScrollView:nil
503
+#endif // !TARGET_OS_OSX
477 504
                       updateOffset:NO];
478 505
 }
479 506
 
480 507
 - (void)refreshContentInset
481 508
 {
482 509
   [RCTView autoAdjustInsetsForView:self
510
+#if !TARGET_OS_OSX
483 511
                     withScrollView:_webView.scrollView
512
+#else
513
+                    withScrollView:nil
514
+#endif // !TARGET_OS_OSX
484 515
                       updateOffset:YES];
485 516
 }
486 517
 
@@ -519,6 +550,7 @@ static NSDictionary* customCertificatesForHost;
519 550
     }
520 551
 }
521 552
 
553
+#if !TARGET_OS_OSX
522 554
 -(void)setKeyboardDisplayRequiresUserAction:(BOOL)keyboardDisplayRequiresUserAction
523 555
 {
524 556
     if (_webView == nil) {
@@ -623,19 +655,24 @@ static NSDictionary* customCertificatesForHost;
623 655
 
624 656
     object_setClass(subview, newClass);
625 657
 }
658
+#endif // !TARGET_OS_OSX
626 659
 
627
-- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
660
+- (void)scrollViewWillBeginDragging:(RCTUIScrollView *)scrollView
628 661
 {
662
+#if !TARGET_OS_OSX
629 663
   scrollView.decelerationRate = _decelerationRate;
664
+#endif // !TARGET_OS_OSX
630 665
 }
631 666
 
632 667
 - (void)setScrollEnabled:(BOOL)scrollEnabled
633 668
 {
634 669
   _scrollEnabled = scrollEnabled;
670
+#if !TARGET_OS_OSX
635 671
   _webView.scrollView.scrollEnabled = scrollEnabled;
672
+#endif // !TARGET_OS_OSX
636 673
 }
637 674
 
638
-- (void)scrollViewDidScroll:(UIScrollView *)scrollView
675
+- (void)scrollViewDidScroll:(RCTUIScrollView *)scrollView
639 676
 {
640 677
   // Don't allow scrolling the scrollView.
641 678
   if (!_scrollEnabled) {
@@ -670,19 +707,25 @@ static NSDictionary* customCertificatesForHost;
670 707
 - (void)setDirectionalLockEnabled:(BOOL)directionalLockEnabled
671 708
 {
672 709
     _directionalLockEnabled = directionalLockEnabled;
710
+#if !TARGET_OS_OSX
673 711
     _webView.scrollView.directionalLockEnabled = directionalLockEnabled;
712
+#endif // !TARGET_OS_OSX
674 713
 }
675 714
 
676 715
 - (void)setShowsHorizontalScrollIndicator:(BOOL)showsHorizontalScrollIndicator
677 716
 {
678 717
     _showsHorizontalScrollIndicator = showsHorizontalScrollIndicator;
718
+#if !TARGET_OS_OSX
679 719
     _webView.scrollView.showsHorizontalScrollIndicator = showsHorizontalScrollIndicator;
720
+#endif // !TARGET_OS_OSX
680 721
 }
681 722
 
682 723
 - (void)setShowsVerticalScrollIndicator:(BOOL)showsVerticalScrollIndicator
683 724
 {
684 725
     _showsVerticalScrollIndicator = showsVerticalScrollIndicator;
726
+#if !TARGET_OS_OSX
685 727
     _webView.scrollView.showsVerticalScrollIndicator = showsVerticalScrollIndicator;
728
+#endif // !TARGET_OS_OSX
686 729
 }
687 730
 
688 731
 - (void)postMessage:(NSString *)message
@@ -701,7 +744,9 @@ static NSDictionary* customCertificatesForHost;
701 744
 
702 745
   // Ensure webview takes the position and dimensions of RNCWebView
703 746
   _webView.frame = self.bounds;
747
+#if !TARGET_OS_OSX
704 748
   _webView.scrollView.contentInset = _contentInset;
749
+#endif // !TARGET_OS_OSX
705 750
 }
706 751
 
707 752
 - (NSMutableDictionary<NSString *, id> *)baseEvent
@@ -767,18 +812,22 @@ static NSDictionary* customCertificatesForHost;
767 812
 */
768 813
 - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
769 814
 {
815
+#if !TARGET_OS_OSX
770 816
     UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:message preferredStyle:UIAlertControllerStyleAlert];
771 817
     [alert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
772 818
         completionHandler();
773 819
     }]];
774 820
     [[self topViewController] presentViewController:alert animated:YES completion:NULL];
775
-
821
+#else
822
+  // TODO
823
+#endif // !TARGET_OS_OSX
776 824
 }
777 825
 
778 826
 /**
779 827
 * confirm
780 828
 */
781 829
 - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler{
830
+#if !TARGET_OS_OSX
782 831
     UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:message preferredStyle:UIAlertControllerStyleAlert];
783 832
     [alert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
784 833
         completionHandler(YES);
@@ -787,12 +836,16 @@ static NSDictionary* customCertificatesForHost;
787 836
         completionHandler(NO);
788 837
     }]];
789 838
     [[self topViewController] presentViewController:alert animated:YES completion:NULL];
839
+#else
840
+  // TODO
841
+#endif // !TARGET_OS_OSX
790 842
 }
791 843
 
792 844
 /**
793 845
 * prompt
794 846
 */
795 847
 - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString *))completionHandler{
848
+#if !TARGET_OS_OSX
796 849
     UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:prompt preferredStyle:UIAlertControllerStyleAlert];
797 850
     [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
798 851
         textField.text = defaultText;
@@ -807,8 +860,12 @@ static NSDictionary* customCertificatesForHost;
807 860
     [alert addAction:cancelAction];
808 861
     alert.preferredAction = okAction;
809 862
     [[self topViewController] presentViewController:alert animated:YES completion:NULL];
863
+#else
864
+  // TODO
865
+#endif // !TARGET_OS_OSX
810 866
 }
811 867
 
868
+#if !TARGET_OS_OSX
812 869
 /**
813 870
  * topViewController
814 871
  */
@@ -847,7 +904,7 @@ static NSDictionary* customCertificatesForHost;
847 904
   }
848 905
   return window;
849 906
 }
850
-
907
+#endif // !TARGET_OS_OSX
851 908
 
852 909
 /**
853 910
  * Decides whether to allow or cancel a navigation.
@@ -1055,7 +1112,9 @@ static NSDictionary* customCertificatesForHost;
1055 1112
 - (void)setBounces:(BOOL)bounces
1056 1113
 {
1057 1114
   _bounces = bounces;
1115
+#if !TARGET_OS_OSX
1058 1116
   _webView.scrollView.bounces = bounces;
1117
+#endif // !TARGET_OS_OSX
1059 1118
 }
1060 1119
 
1061 1120
 - (NSURLRequest *)requestForSource:(id)json {

+ 92
- 0
ios/RNCWebView.xcodeproj/project.pbxproj 查看文件

@@ -8,11 +8,23 @@
8 8
 
9 9
 /* Begin PBXBuildFile section */
10 10
 		3515965E21A3C86000623BFA /* RNCWKProcessPoolManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3515965D21A3C86000623BFA /* RNCWKProcessPoolManager.m */; };
11
+		38116A2B23BBECB700ACE311 /* RNCWebViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E91B351B21446E6C00F9801F /* RNCWebViewManager.m */; };
12
+		38116A2C23BBECB700ACE311 /* RNCWebView.m in Sources */ = {isa = PBXBuildFile; fileRef = E91B351C21446E6C00F9801F /* RNCWebView.m */; };
13
+		38116A2D23BBECB700ACE311 /* RNCWKProcessPoolManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3515965D21A3C86000623BFA /* RNCWKProcessPoolManager.m */; };
11 14
 		E91B351D21446E6C00F9801F /* RNCWebViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E91B351B21446E6C00F9801F /* RNCWebViewManager.m */; };
12 15
 		E91B351E21446E6C00F9801F /* RNCWebView.m in Sources */ = {isa = PBXBuildFile; fileRef = E91B351C21446E6C00F9801F /* RNCWebView.m */; };
13 16
 /* End PBXBuildFile section */
14 17
 
15 18
 /* Begin PBXCopyFilesBuildPhase section */
19
+		38116A2F23BBECB700ACE311 /* CopyFiles */ = {
20
+			isa = PBXCopyFilesBuildPhase;
21
+			buildActionMask = 2147483647;
22
+			dstPath = "include/$(PRODUCT_NAME)";
23
+			dstSubfolderSpec = 16;
24
+			files = (
25
+			);
26
+			runOnlyForDeploymentPostprocessing = 0;
27
+		};
16 28
 		58B511D91A9E6C8500147676 /* CopyFiles */ = {
17 29
 			isa = PBXCopyFilesBuildPhase;
18 30
 			buildActionMask = 2147483647;
@@ -28,6 +40,7 @@
28 40
 		134814201AA4EA6300B7C361 /* libRNCWebView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNCWebView.a; sourceTree = BUILT_PRODUCTS_DIR; };
29 41
 		3515965D21A3C86000623BFA /* RNCWKProcessPoolManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNCWKProcessPoolManager.m; sourceTree = "<group>"; };
30 42
 		3515965F21A3C87E00623BFA /* RNCWKProcessPoolManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNCWKProcessPoolManager.h; sourceTree = "<group>"; };
43
+		38116A3323BBECB700ACE311 /* libRNCWebView-macOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libRNCWebView-macOS.a"; sourceTree = BUILT_PRODUCTS_DIR; };
31 44
 		E91B351921446E6C00F9801F /* RNCWebViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCWebViewManager.h; sourceTree = "<group>"; };
32 45
 		E91B351A21446E6C00F9801F /* RNCWebView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCWebView.h; sourceTree = "<group>"; };
33 46
 		E91B351B21446E6C00F9801F /* RNCWebViewManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNCWebViewManager.m; sourceTree = "<group>"; };
@@ -35,6 +48,13 @@
35 48
 /* End PBXFileReference section */
36 49
 
37 50
 /* Begin PBXFrameworksBuildPhase section */
51
+		38116A2E23BBECB700ACE311 /* Frameworks */ = {
52
+			isa = PBXFrameworksBuildPhase;
53
+			buildActionMask = 2147483647;
54
+			files = (
55
+			);
56
+			runOnlyForDeploymentPostprocessing = 0;
57
+		};
38 58
 		58B511D81A9E6C8500147676 /* Frameworks */ = {
39 59
 			isa = PBXFrameworksBuildPhase;
40 60
 			buildActionMask = 2147483647;
@@ -63,12 +83,30 @@
63 83
 				3515965D21A3C86000623BFA /* RNCWKProcessPoolManager.m */,
64 84
 				3515965F21A3C87E00623BFA /* RNCWKProcessPoolManager.h */,
65 85
 				134814211AA4EA7D00B7C361 /* Products */,
86
+				38116A3323BBECB700ACE311 /* libRNCWebView-macOS.a */,
66 87
 			);
67 88
 			sourceTree = "<group>";
68 89
 		};
69 90
 /* End PBXGroup section */
70 91
 
71 92
 /* Begin PBXNativeTarget section */
93
+		38116A2923BBECB700ACE311 /* RNCWebView-macOS */ = {
94
+			isa = PBXNativeTarget;
95
+			buildConfigurationList = 38116A3023BBECB700ACE311 /* Build configuration list for PBXNativeTarget "RNCWebView-macOS" */;
96
+			buildPhases = (
97
+				38116A2A23BBECB700ACE311 /* Sources */,
98
+				38116A2E23BBECB700ACE311 /* Frameworks */,
99
+				38116A2F23BBECB700ACE311 /* CopyFiles */,
100
+			);
101
+			buildRules = (
102
+			);
103
+			dependencies = (
104
+			);
105
+			name = "RNCWebView-macOS";
106
+			productName = RCTDataManager;
107
+			productReference = 38116A3323BBECB700ACE311 /* libRNCWebView-macOS.a */;
108
+			productType = "com.apple.product-type.library.static";
109
+		};
72 110
 		58B511DA1A9E6C8500147676 /* RNCWebView */ = {
73 111
 			isa = PBXNativeTarget;
74 112
 			buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNCWebView" */;
@@ -113,11 +151,22 @@
113 151
 			projectRoot = "";
114 152
 			targets = (
115 153
 				58B511DA1A9E6C8500147676 /* RNCWebView */,
154
+				38116A2923BBECB700ACE311 /* RNCWebView-macOS */,
116 155
 			);
117 156
 		};
118 157
 /* End PBXProject section */
119 158
 
120 159
 /* Begin PBXSourcesBuildPhase section */
160
+		38116A2A23BBECB700ACE311 /* Sources */ = {
161
+			isa = PBXSourcesBuildPhase;
162
+			buildActionMask = 2147483647;
163
+			files = (
164
+				38116A2B23BBECB700ACE311 /* RNCWebViewManager.m in Sources */,
165
+				38116A2C23BBECB700ACE311 /* RNCWebView.m in Sources */,
166
+				38116A2D23BBECB700ACE311 /* RNCWKProcessPoolManager.m in Sources */,
167
+			);
168
+			runOnlyForDeploymentPostprocessing = 0;
169
+		};
121 170
 		58B511D71A9E6C8500147676 /* Sources */ = {
122 171
 			isa = PBXSourcesBuildPhase;
123 172
 			buildActionMask = 2147483647;
@@ -131,6 +180,40 @@
131 180
 /* End PBXSourcesBuildPhase section */
132 181
 
133 182
 /* Begin XCBuildConfiguration section */
183
+		38116A3123BBECB700ACE311 /* Debug */ = {
184
+			isa = XCBuildConfiguration;
185
+			buildSettings = {
186
+				FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../node_modules/react-native/**";
187
+				HEADER_SEARCH_PATHS = (
188
+					"$(inherited)",
189
+					"$(SRCROOT)/../node_modules/react-native/React/**",
190
+				);
191
+				LIBRARY_SEARCH_PATHS = "$(inherited)";
192
+				MACOSX_DEPLOYMENT_TARGET = 10.14;
193
+				OTHER_LDFLAGS = "-ObjC";
194
+				PRODUCT_NAME = "$(TARGET_NAME)";
195
+				SDKROOT = macosx;
196
+				SKIP_INSTALL = YES;
197
+			};
198
+			name = Debug;
199
+		};
200
+		38116A3223BBECB700ACE311 /* Release */ = {
201
+			isa = XCBuildConfiguration;
202
+			buildSettings = {
203
+				FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../node_modules/react-native/**";
204
+				HEADER_SEARCH_PATHS = (
205
+					"$(inherited)",
206
+					"$(SRCROOT)/../node_modules/react-native/React/**",
207
+				);
208
+				LIBRARY_SEARCH_PATHS = "$(inherited)";
209
+				MACOSX_DEPLOYMENT_TARGET = 10.14;
210
+				OTHER_LDFLAGS = "-ObjC";
211
+				PRODUCT_NAME = "$(TARGET_NAME)";
212
+				SDKROOT = macosx;
213
+				SKIP_INSTALL = YES;
214
+			};
215
+			name = Release;
216
+		};
134 217
 		58B511ED1A9E6C8500147676 /* Debug */ = {
135 218
 			isa = XCBuildConfiguration;
136 219
 			buildSettings = {
@@ -247,6 +330,15 @@
247 330
 /* End XCBuildConfiguration section */
248 331
 
249 332
 /* Begin XCConfigurationList section */
333
+		38116A3023BBECB700ACE311 /* Build configuration list for PBXNativeTarget "RNCWebView-macOS" */ = {
334
+			isa = XCConfigurationList;
335
+			buildConfigurations = (
336
+				38116A3123BBECB700ACE311 /* Debug */,
337
+				38116A3223BBECB700ACE311 /* Release */,
338
+			);
339
+			defaultConfigurationIsVisible = 0;
340
+			defaultConfigurationName = Release;
341
+		};
250 342
 		58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNCWebView" */ = {
251 343
 			isa = XCConfigurationList;
252 344
 			buildConfigurations = (

+ 3
- 1
ios/RNCWebViewManager.m 查看文件

@@ -35,7 +35,7 @@ RCT_ENUM_CONVERTER(UIScrollViewContentInsetAdjustmentBehavior, (@{
35 35
 
36 36
 RCT_EXPORT_MODULE()
37 37
 
38
-- (UIView *)view
38
+- (RCTUIView *)view
39 39
 {
40 40
   RNCWebView *webView = [RNCWebView new];
41 41
   webView.delegate = self;
@@ -110,9 +110,11 @@ RCT_CUSTOM_VIEW_PROPERTY(sharedCookiesEnabled, BOOL, RNCWebView) {
110 110
     view.sharedCookiesEnabled = json == nil ? false : [RCTConvert BOOL: json];
111 111
 }
112 112
 
113
+#if !TARGET_OS_OSX
113 114
 RCT_CUSTOM_VIEW_PROPERTY(decelerationRate, CGFloat, RNCWebView) {
114 115
   view.decelerationRate = json == nil ? UIScrollViewDecelerationRateNormal : [RCTConvert CGFloat: json];
115 116
 }
117
+#endif // !TARGET_OS_OSX
116 118
 
117 119
 RCT_CUSTOM_VIEW_PROPERTY(directionalLockEnabled, BOOL, RNCWebView) {
118 120
     view.directionalLockEnabled = json == nil ? true : [RCTConvert BOOL: json];

+ 364
- 0
src/WebView.macos.tsx 查看文件

@@ -0,0 +1,364 @@
1
+import React from 'react';
2
+import {
3
+  UIManager as NotTypedUIManager,
4
+  View,
5
+  requireNativeComponent,
6
+  NativeModules,
7
+  Image,
8
+  findNodeHandle,
9
+  ImageSourcePropType,
10
+} from 'react-native';
11
+import invariant from 'invariant';
12
+
13
+import {
14
+  defaultOriginWhitelist,
15
+  createOnShouldStartLoadWithRequest,
16
+  defaultRenderError,
17
+  defaultRenderLoading,
18
+} from './WebViewShared';
19
+import {
20
+  WebViewErrorEvent,
21
+  WebViewHttpErrorEvent,
22
+  WebViewMessageEvent,
23
+  WebViewNavigationEvent,
24
+  WebViewProgressEvent,
25
+  WebViewTerminatedEvent,
26
+  IOSWebViewProps,
27
+  DecelerationRateConstant,
28
+  NativeWebViewIOS,
29
+  ViewManager,
30
+  State,
31
+  RNCWebViewUIManagerIOS,
32
+} from './WebViewTypes';
33
+
34
+import styles from './WebView.styles';
35
+
36
+const UIManager = NotTypedUIManager as RNCWebViewUIManagerIOS;
37
+
38
+const { resolveAssetSource } = Image;
39
+const processDecelerationRate = (
40
+  decelerationRate: DecelerationRateConstant | number | undefined,
41
+) => {
42
+  let newDecelerationRate = decelerationRate;
43
+  if (newDecelerationRate === 'normal') {
44
+    newDecelerationRate = 0.998;
45
+  } else if (newDecelerationRate === 'fast') {
46
+    newDecelerationRate = 0.99;
47
+  }
48
+  return newDecelerationRate;
49
+};
50
+
51
+const RNCWebViewManager = NativeModules.RNCWebViewManager as ViewManager;
52
+
53
+const RNCWebView: typeof NativeWebViewIOS = requireNativeComponent(
54
+  'RNCWebView',
55
+);
56
+
57
+class WebView extends React.Component<IOSWebViewProps, State> {
58
+  static defaultProps = {
59
+    javaScriptEnabled: true,
60
+    cacheEnabled: true,
61
+    originWhitelist: defaultOriginWhitelist,
62
+    useSharedProcessPool: true,
63
+  };
64
+
65
+  static isFileUploadSupported = async () => {
66
+    // no native implementation for iOS, depends only on permissions
67
+    return true;
68
+  };
69
+
70
+  state: State = {
71
+    viewState: this.props.startInLoadingState ? 'LOADING' : 'IDLE',
72
+    lastErrorEvent: null,
73
+  };
74
+
75
+  webViewRef = React.createRef<NativeWebViewIOS>();
76
+
77
+  // eslint-disable-next-line react/sort-comp
78
+  getCommands = () => UIManager.getViewManagerConfig('RNCWebView').Commands;
79
+
80
+  /**
81
+   * Go forward one page in the web view's history.
82
+   */
83
+  goForward = () => {
84
+    UIManager.dispatchViewManagerCommand(
85
+      this.getWebViewHandle(),
86
+      this.getCommands().goForward,
87
+      undefined,
88
+    );
89
+  };
90
+
91
+  /**
92
+   * Go back one page in the web view's history.
93
+   */
94
+  goBack = () => {
95
+    UIManager.dispatchViewManagerCommand(
96
+      this.getWebViewHandle(),
97
+      this.getCommands().goBack,
98
+      undefined,
99
+    );
100
+  };
101
+
102
+  /**
103
+   * Reloads the current page.
104
+   */
105
+  reload = () => {
106
+    this.setState({ viewState: 'LOADING' });
107
+    UIManager.dispatchViewManagerCommand(
108
+      this.getWebViewHandle(),
109
+      this.getCommands().reload,
110
+      undefined,
111
+    );
112
+  };
113
+
114
+  /**
115
+   * Stop loading the current page.
116
+   */
117
+  stopLoading = () => {
118
+    UIManager.dispatchViewManagerCommand(
119
+      this.getWebViewHandle(),
120
+      this.getCommands().stopLoading,
121
+      undefined,
122
+    );
123
+  };
124
+
125
+  /**
126
+   * Request focus on WebView rendered page.
127
+   */
128
+  requestFocus = () => {
129
+    UIManager.dispatchViewManagerCommand(
130
+      this.getWebViewHandle(),
131
+      this.getCommands().requestFocus,
132
+      undefined,
133
+    );
134
+  };
135
+
136
+  /**
137
+   * Posts a message to the web view, which will emit a `message` event.
138
+   * Accepts one argument, `data`, which must be a string.
139
+   *
140
+   * In your webview, you'll need to something like the following.
141
+   *
142
+   * ```js
143
+   * document.addEventListener('message', e => { document.title = e.data; });
144
+   * ```
145
+   */
146
+  postMessage = (data: string) => {
147
+    UIManager.dispatchViewManagerCommand(
148
+      this.getWebViewHandle(),
149
+      this.getCommands().postMessage,
150
+      [String(data)],
151
+    );
152
+  };
153
+
154
+  /**
155
+   * Injects a javascript string into the referenced WebView. Deliberately does not
156
+   * return a response because using eval() to return a response breaks this method
157
+   * on pages with a Content Security Policy that disallows eval(). If you need that
158
+   * functionality, look into postMessage/onMessage.
159
+   */
160
+  injectJavaScript = (data: string) => {
161
+    UIManager.dispatchViewManagerCommand(
162
+      this.getWebViewHandle(),
163
+      this.getCommands().injectJavaScript,
164
+      [data],
165
+    );
166
+  };
167
+
168
+  /**
169
+   * We return an event with a bunch of fields including:
170
+   *  url, title, loading, canGoBack, canGoForward
171
+   */
172
+  updateNavigationState = (event: WebViewNavigationEvent) => {
173
+    if (this.props.onNavigationStateChange) {
174
+      this.props.onNavigationStateChange(event.nativeEvent);
175
+    }
176
+  };
177
+
178
+  /**
179
+   * Returns the native `WebView` node.
180
+   */
181
+  getWebViewHandle = () => {
182
+    const nodeHandle = findNodeHandle(this.webViewRef.current);
183
+    invariant(nodeHandle != null, 'nodeHandle expected to be non-null');
184
+    return nodeHandle as number;
185
+  };
186
+
187
+  onLoadingStart = (event: WebViewNavigationEvent) => {
188
+    const { onLoadStart } = this.props;
189
+    if (onLoadStart) {
190
+      onLoadStart(event);
191
+    }
192
+    this.updateNavigationState(event);
193
+  };
194
+
195
+  onLoadingError = (event: WebViewErrorEvent) => {
196
+    event.persist(); // persist this event because we need to store it
197
+    const { onError, onLoadEnd } = this.props;
198
+    if (onLoadEnd) {
199
+      onLoadEnd(event);
200
+    }
201
+    if (onError) {
202
+      onError(event);
203
+    }
204
+    console.warn('Encountered an error loading page', event.nativeEvent);
205
+
206
+    this.setState({
207
+      lastErrorEvent: event.nativeEvent,
208
+      viewState: 'ERROR',
209
+    });
210
+  };
211
+
212
+  onHttpError = (event: WebViewHttpErrorEvent) => {
213
+    const { onHttpError } = this.props;
214
+    if (onHttpError) {
215
+      onHttpError(event);
216
+    }
217
+  }
218
+
219
+  onLoadingFinish = (event: WebViewNavigationEvent) => {
220
+    const { onLoad, onLoadEnd } = this.props;
221
+    if (onLoad) {
222
+      onLoad(event);
223
+    }
224
+    if (onLoadEnd) {
225
+      onLoadEnd(event);
226
+    }
227
+    this.setState({
228
+      viewState: 'IDLE',
229
+    });
230
+    this.updateNavigationState(event);
231
+  };
232
+
233
+  onMessage = (event: WebViewMessageEvent) => {
234
+    const { onMessage } = this.props;
235
+    if (onMessage) {
236
+      onMessage(event);
237
+    }
238
+  };
239
+
240
+  onLoadingProgress = (event: WebViewProgressEvent) => {
241
+    const { onLoadProgress } = this.props;
242
+    if (onLoadProgress) {
243
+      onLoadProgress(event);
244
+    }
245
+  };
246
+
247
+  onShouldStartLoadWithRequestCallback = (
248
+    shouldStart: boolean,
249
+    _url: string,
250
+    lockIdentifier: number,
251
+  ) => {
252
+    const viewManager
253
+      = (this.props.nativeConfig && this.props.nativeConfig.viewManager)
254
+      || RNCWebViewManager;
255
+
256
+    viewManager.startLoadWithResult(!!shouldStart, lockIdentifier);
257
+  };
258
+
259
+  onContentProcessDidTerminate = (event: WebViewTerminatedEvent) => {
260
+    const { onContentProcessDidTerminate } = this.props;
261
+    if (onContentProcessDidTerminate) {
262
+      onContentProcessDidTerminate(event);
263
+    }
264
+  };
265
+
266
+  componentDidUpdate(prevProps: IOSWebViewProps) {
267
+    this.showRedboxOnPropChanges(prevProps, 'allowsInlineMediaPlayback');
268
+    this.showRedboxOnPropChanges(prevProps, 'incognito');
269
+    this.showRedboxOnPropChanges(prevProps, 'mediaPlaybackRequiresUserAction');
270
+    this.showRedboxOnPropChanges(prevProps, 'dataDetectorTypes');
271
+  }
272
+
273
+  showRedboxOnPropChanges(
274
+    prevProps: IOSWebViewProps,
275
+    propName: keyof IOSWebViewProps,
276
+  ) {
277
+    if (this.props[propName] !== prevProps[propName]) {
278
+      console.error(
279
+        `Changes to property ${propName} do nothing after the initial render.`,
280
+      );
281
+    }
282
+  }
283
+
284
+  render() {
285
+    const {
286
+      decelerationRate: decelerationRateProp,
287
+      nativeConfig = {},
288
+      onMessage,
289
+      onShouldStartLoadWithRequest: onShouldStartLoadWithRequestProp,
290
+      originWhitelist,
291
+      renderError,
292
+      renderLoading,
293
+      style,
294
+      containerStyle,
295
+      ...otherProps
296
+    } = this.props;
297
+
298
+    let otherView = null;
299
+
300
+    if (this.state.viewState === 'LOADING') {
301
+      otherView = (renderLoading || defaultRenderLoading)();
302
+    } else if (this.state.viewState === 'ERROR') {
303
+      const errorEvent = this.state.lastErrorEvent;
304
+      invariant(errorEvent != null, 'lastErrorEvent expected to be non-null');
305
+      otherView = (renderError || defaultRenderError)(
306
+        errorEvent.domain,
307
+        errorEvent.code,
308
+        errorEvent.description,
309
+      );
310
+    } else if (this.state.viewState !== 'IDLE') {
311
+      console.error(
312
+        `RNCWebView invalid state encountered: ${this.state.viewState}`,
313
+      );
314
+    }
315
+
316
+    const webViewStyles = [styles.container, styles.webView, style];
317
+    const webViewContainerStyle = [styles.container, containerStyle];
318
+
319
+    const onShouldStartLoadWithRequest = createOnShouldStartLoadWithRequest(
320
+      this.onShouldStartLoadWithRequestCallback,
321
+      // casting cause it's in the default props
322
+      originWhitelist as readonly string[],
323
+      onShouldStartLoadWithRequestProp,
324
+    );
325
+
326
+    const decelerationRate = processDecelerationRate(decelerationRateProp);
327
+
328
+    const NativeWebView
329
+      = (nativeConfig.component as typeof NativeWebViewIOS | undefined)
330
+      || RNCWebView;
331
+
332
+    const webView = (
333
+      <NativeWebView
334
+        key="webViewKey"
335
+        {...otherProps}
336
+        decelerationRate={decelerationRate}
337
+        messagingEnabled={typeof onMessage === 'function'}
338
+        onLoadingError={this.onLoadingError}
339
+        onLoadingFinish={this.onLoadingFinish}
340
+        onLoadingProgress={this.onLoadingProgress}
341
+        onLoadingStart={this.onLoadingStart}
342
+        onHttpError={this.onHttpError}
343
+        onMessage={this.onMessage}
344
+        onScroll={this.props.onScroll}
345
+        onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
346
+        onContentProcessDidTerminate={this.onContentProcessDidTerminate}
347
+        ref={this.webViewRef}
348
+        // TODO: find a better way to type this.
349
+        source={resolveAssetSource(this.props.source as ImageSourcePropType)}
350
+        style={webViewStyles}
351
+        {...nativeConfig.props}
352
+      />
353
+    );
354
+
355
+    return (
356
+      <View style={webViewContainerStyle}>
357
+        {webView}
358
+        {otherView}
359
+      </View>
360
+    );
361
+  }
362
+}
363
+
364
+export default WebView;