Browse Source

Merge branch 'master' into sr_injectedjs_startup_android

Salvatore Randazzo 4 years ago
parent
commit
63788f99e8
No account linked to committer's email address
43 changed files with 4515 additions and 124 deletions
  1. 1
    0
      README.md
  2. 1
    1
      android/build.gradle
  3. 25
    5
      android/src/main/java/com/reactnativecommunity/webview/RNCWebViewModule.java
  4. 0
    27
      android/src/main/java/com/reactnativecommunity/webview/RNCWebViewPackage.java
  5. 15
    0
      android/src/main/java/com/reactnativecommunity/webview/RNCWebViewPackage.kt
  6. 38
    0
      docs/Contributing.md
  7. 15
    7
      docs/Getting-Started.md
  8. 10
    4
      docs/Guide.md
  9. 1
    1
      docs/README.portuguese.md
  10. 18
    18
      docs/Reference.md
  11. 4
    1
      example/.gitignore
  12. 15
    0
      example/App.tsx
  13. 1
    0
      example/android/app/src/main/AndroidManifest.xml
  14. 69
    0
      example/examples/Uploads.tsx
  15. 2
    2
      example/ios/Podfile.lock
  16. 16
    0
      example/macos/example-macOS/AppDelegate.h
  17. 39
    0
      example/macos/example-macOS/AppDelegate.m
  18. 45
    0
      example/macos/example-macOS/Info.plist
  19. 713
    0
      example/macos/example-macOS/Main.storyboard
  20. 12
    0
      example/macos/example-macOS/ViewController.h
  21. 29
    0
      example/macos/example-macOS/ViewController.m
  22. 12
    0
      example/macos/example-macOS/main.m
  23. 1569
    0
      example/macos/example.xcodeproj/project.pbxproj
  24. 10
    0
      example/macos/example.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
  25. 92
    0
      example/macos/example.xcodeproj/xcshareddata/xcschemes/example-macOS.xcscheme
  26. 92
    0
      example/macos/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme
  27. 15
    0
      example/macos/example/AppDelegate.h
  28. 42
    0
      example/macos/example/AppDelegate.m
  29. 42
    0
      example/macos/example/Base.lproj/LaunchScreen.xib
  30. 53
    0
      example/macos/example/Images.xcassets/AppIcon.appiconset/Contents.json
  31. 6
    0
      example/macos/example/Images.xcassets/Contents.json
  32. 57
    0
      example/macos/example/Info.plist
  33. 16
    0
      example/macos/example/main.m
  34. 168
    38
      ios/RNCWebView.m
  35. 6
    0
      ios/RNCWebViewManager.m
  36. 363
    0
      macos/RNCWebView.xcodeproj/project.pbxproj
  37. 12
    0
      metro.config.js
  38. 19
    0
      metro.config.macos.js
  39. 8
    3
      package.json
  40. 26
    0
      react-native.config.js
  41. 347
    0
      src/WebView.macos.tsx
  42. 175
    14
      src/WebViewTypes.ts
  43. 316
    3
      yarn.lock

+ 1
- 0
README.md View File

20
 
20
 
21
 - [x] iOS
21
 - [x] iOS
22
 - [x] Android
22
 - [x] Android
23
+- [x] macOS
23
 
24
 
24
 _Note: Expo support for React Native WebView started with [Expo SDK v33.0.0](https://blog.expo.io/expo-sdk-v33-0-0-is-now-available-52d1c99dfe4c)._
25
 _Note: Expo support for React Native WebView started with [Expo SDK v33.0.0](https://blog.expo.io/expo-sdk-v33-0-0-is-now-available-52d1c99dfe4c)._
25
 
26
 

+ 1
- 1
android/build.gradle View File

123
 
123
 
124
 dependencies {
124
 dependencies {
125
   //noinspection GradleDynamicVersion
125
   //noinspection GradleDynamicVersion
126
-  api 'com.facebook.react:react-native:+'
126
+  implementation 'com.facebook.react:react-native:+'
127
   implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
127
   implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
128
 }
128
 }

+ 25
- 5
android/src/main/java/com/reactnativecommunity/webview/RNCWebViewModule.java View File

32
 import java.io.File;
32
 import java.io.File;
33
 import java.io.IOException;
33
 import java.io.IOException;
34
 import java.util.ArrayList;
34
 import java.util.ArrayList;
35
+import java.util.Arrays;
35
 
36
 
36
 import static android.app.Activity.RESULT_OK;
37
 import static android.app.Activity.RESULT_OK;
37
 
38
 
180
     filePathCallback = callback;
181
     filePathCallback = callback;
181
 
182
 
182
     ArrayList<Parcelable> extraIntents = new ArrayList<>();
183
     ArrayList<Parcelable> extraIntents = new ArrayList<>();
183
-    if (acceptsImages(acceptTypes)) {
184
-      extraIntents.add(getPhotoIntent());
185
-    }
186
-    if (acceptsVideo(acceptTypes)) {
187
-      extraIntents.add(getVideoIntent());
184
+    if (! needsCameraPermission()) {
185
+      if (acceptsImages(acceptTypes)) {
186
+        extraIntents.add(getPhotoIntent());
187
+      }
188
+      if (acceptsVideo(acceptTypes)) {
189
+        extraIntents.add(getVideoIntent());
190
+      }
188
     }
191
     }
189
 
192
 
190
     Intent fileSelectionIntent = getFileChooserIntent(acceptTypes, allowMultiple);
193
     Intent fileSelectionIntent = getFileChooserIntent(acceptTypes, allowMultiple);
233
     return result;
236
     return result;
234
   }
237
   }
235
 
238
 
239
+  protected boolean needsCameraPermission() {
240
+    boolean needed = false;
241
+
242
+    PackageManager packageManager = getCurrentActivity().getPackageManager();
243
+    try {
244
+      String[] requestedPermissions = packageManager.getPackageInfo(getReactApplicationContext().getPackageName(), PackageManager.GET_PERMISSIONS).requestedPermissions;
245
+      if (Arrays.asList(requestedPermissions).contains(Manifest.permission.CAMERA)
246
+        && ContextCompat.checkSelfPermission(getCurrentActivity(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
247
+        needed = true;
248
+      }
249
+    } catch (PackageManager.NameNotFoundException e) {
250
+      needed = true;
251
+    }
252
+
253
+    return needed;
254
+  }
255
+
236
   private Intent getPhotoIntent() {
256
   private Intent getPhotoIntent() {
237
     Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
257
     Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
238
     outputFileUri = getOutputUri(MediaStore.ACTION_IMAGE_CAPTURE);
258
     outputFileUri = getOutputUri(MediaStore.ACTION_IMAGE_CAPTURE);

+ 0
- 27
android/src/main/java/com/reactnativecommunity/webview/RNCWebViewPackage.java View File

1
-package com.reactnativecommunity.webview;
2
-
3
-import com.facebook.react.ReactPackage;
4
-import com.facebook.react.bridge.JavaScriptModule;
5
-import com.facebook.react.bridge.NativeModule;
6
-import com.facebook.react.bridge.ReactApplicationContext;
7
-import com.facebook.react.uimanager.ViewManager;
8
-
9
-import java.util.Collections;
10
-import java.util.List;
11
-
12
-public class RNCWebViewPackage implements ReactPackage {
13
-  @Override
14
-  public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
15
-    return Collections.singletonList(new RNCWebViewModule(reactContext));
16
-  }
17
-
18
-  // Deprecated from RN 0.47
19
-  public List<Class<? extends JavaScriptModule>> createJSModules() {
20
-    return Collections.emptyList();
21
-  }
22
-
23
-  @Override
24
-  public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
25
-    return Collections.singletonList(new RNCWebViewManager());
26
-  }
27
-}

+ 15
- 0
android/src/main/java/com/reactnativecommunity/webview/RNCWebViewPackage.kt View File

1
+package com.reactnativecommunity.webview
2
+
3
+import com.facebook.react.ReactPackage
4
+import com.facebook.react.bridge.ReactApplicationContext
5
+
6
+
7
+class RNCWebViewPackage: ReactPackage {
8
+  override fun createNativeModules(reactContext: ReactApplicationContext) = listOf(
9
+    RNCWebViewModule(reactContext)
10
+  )
11
+
12
+  override fun createViewManagers(reactContext: ReactApplicationContext) = listOf(
13
+    RNCWebViewManager()
14
+  )
15
+}

+ 38
- 0
docs/Contributing.md View File

8
 
8
 
9
 After you fork the repo, clone it to your machine, and make your changes, you'll want to test them in an app.
9
 After you fork the repo, clone it to your machine, and make your changes, you'll want to test them in an app.
10
 
10
 
11
+There are two methods of testing:
12
+1) Testing within a clone of react-native-webview
13
+2) Testing in a new `react-native init` project
14
+
15
+### Testing within react-native-webview
16
+
17
+#### For all platforms:
18
+```
19
+$ yarn install
20
+```
21
+
22
+#### For Android:
23
+```
24
+$ yarn start:android
25
+```
26
+
27
+The Android example app will built, the Metro Bundler will launch, and the example app will be installed and started in the Android emulator.
28
+
29
+#### For iOS:
30
+```
31
+$ cd example/ios
32
+$ pod install
33
+$ cd ../..
34
+$ yarn start:ios
35
+```
36
+
37
+The iOS example app will be built, the Metro bundler will launch, and the example app will be install and started in the Simulator.
38
+
39
+#### for macOS:
40
+```
41
+$ open example/macos/example.xcodeproj
42
+$ yarn start:macos
43
+```
44
+
45
+The Metro Bundler will now be running in the Terminal for react-native-macos.  In XCode select the `example-macos` target and Run.
46
+
47
+### Testing in a new `react-native init` project
48
+
11
 In a new `react-native init` project, do this:
49
 In a new `react-native init` project, do this:
12
 
50
 
13
 ```
51
 ```

+ 15
- 7
docs/Getting-Started.md View File

2
 
2
 
3
 Here's how to get started quickly with the React Native WebView.
3
 Here's how to get started quickly with the React Native WebView.
4
 
4
 
5
-#### 1. Add react-native-webview to your dependencies
5
+## 1. Add react-native-webview to your dependencies
6
 
6
 
7
 ```
7
 ```
8
 $ yarn add react-native-webview
8
 $ yarn add react-native-webview
14
 $ npm install --save react-native-webview
14
 $ npm install --save react-native-webview
15
 ```
15
 ```
16
 
16
 
17
-#### 2. Link native dependencies
17
+## 2. Link native dependencies
18
 
18
 
19
 From react-native 0.60 autolinking will take care of the link step but don't forget to run `pod install`
19
 From react-native 0.60 autolinking will take care of the link step but don't forget to run `pod install`
20
 
20
 
24
 $ react-native link react-native-webview
24
 $ react-native link react-native-webview
25
 ```
25
 ```
26
 
26
 
27
-iOS:
27
+_NOTE: If you ever need to uninstall React Native WebView, run `react-native unlink react-native-webview` to unlink it._
28
+
29
+### iOS:
28
 
30
 
29
 If using cocoapods in the `ios/` directory run
31
 If using cocoapods in the `ios/` directory run
30
 ```
32
 ```
31
 $ pod install
33
 $ pod install
32
 ```
34
 ```
33
 
35
 
36
+For iOS, while you can manually link the old way using [react-native own tutorial](https://facebook.github.io/react-native/docs/linking-libraries-ios), we find it easier to use cocoapods.
37
+If you wish to use cocoapods and haven't set it up yet, please instead refer to [that article](https://engineering.brigad.co/demystifying-react-native-modules-linking-ae6c017a6b4a).
38
+
39
+### Android:
40
+
34
 Android - react-native-webview version <6:
41
 Android - react-native-webview version <6:
35
 This module does not require any extra step after running the link command 🎉
42
 This module does not require any extra step after running the link command 🎉
36
 
43
 
44
 
51
 
45
 For Android manual installation, please refer to [this article](https://engineering.brigad.co/demystifying-react-native-modules-linking-964399ec731b) where you can find detailed step on how to link any react-native project.
52
 For Android manual installation, please refer to [this article](https://engineering.brigad.co/demystifying-react-native-modules-linking-964399ec731b) where you can find detailed step on how to link any react-native project.
46
 
53
 
47
-For iOS, while you can manually link the old way using [react-native own tutorial](https://facebook.github.io/react-native/docs/linking-libraries-ios), we find it easier to use cocoapods.
48
-If you wish to use cocoapods and haven't set it up yet, please instead refer to [that article](https://engineering.brigad.co/demystifying-react-native-modules-linking-ae6c017a6b4a).
54
+### macOS:
49
 
55
 
50
-_NOTE: If you ever need to uninstall React Native WebView, run `react-native unlink react-native-webview` to unlink it._
56
+Cocoapod and autolinking is not yet support for react-native macOS but is coming soon.  In the meantime you must manually link.
57
+
58
+The method is nearly identical to the [manual linking method for iOS](https://facebook.github.io/react-native/docs/linking-libraries-ios#manual-linking) except that you will include the `node_modules/react-native-webview/macos/RNCWebView.xcodeproj` project in your main project and link the `RNCWebView-macOS.a` library. 
51
 
59
 
52
-#### 3. Import the webview into your component
60
+## 3. Import the webview into your component
53
 
61
 
54
 ```js
62
 ```js
55
 import React, { Component } from 'react';
63
 import React, { Component } from 'react';

+ 10
- 4
docs/Guide.md View File

74
 }
74
 }
75
 ```
75
 ```
76
 
76
 
77
-However on Android, you need to place the HTML file inside your android project's asset directory. For example, if `local-site.html` is your HTML file and you'd like to load it into the webview, you should move the file to your project's android asset directory which is `your-project/android/src/main/assets/`. Then you can load the html file as shown in the following code block
77
+However on Android, you need to place the HTML file inside your android project's asset directory. For example, if `local-site.html` is your HTML file and you'd like to load it into the webview, you should move the file to your project's android asset directory which is `your-project/android/app/src/main/assets/`. Then you can load the html file as shown in the following code block
78
 
78
 
79
 ```js
79
 ```js
80
 import React, { Component } from 'react';
80
 import React, { Component } from 'react';
191
 </manifest>
191
 </manifest>
192
 ```
192
 ```
193
 
193
 
194
+###### Camera option availability in uploading for Android
195
+
196
+If the file input indicates that images or video is desired with [`accept`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept), then the WebView will attempt to provide options to the user to use their camera to take a picture or video.
197
+
198
+Normally, apps that do not have permission to use the camera can prompt the user to use an external app so that the requesting app has no need for permission. However, Android has made a special exception for this around the camera to reduce confusion for users. If an app *can* request the camera permission because it has been declared, and the user has not granted the permission, it may not fire an intent that would use the camera (`MediaStore.ACTION_IMAGE_CAPTURE` or `MediaStore.ACTION_VIDEO_CAPTURE`). In this scenario, it is up to the developer to request camera permission before a file upload directly using the camera is necessary.
199
+
194
 ##### Check for File Upload support, with `static isFileUploadSupported()`
200
 ##### Check for File Upload support, with `static isFileUploadSupported()`
195
 
201
 
196
 File Upload using `<input type="file" />` is not supported for Android 4.4 KitKat (see [details](https://github.com/delight-im/Android-AdvancedWebView/issues/4#issuecomment-70372146)):
202
 File Upload using `<input type="file" />` is not supported for Android 4.4 KitKat (see [details](https://github.com/delight-im/Android-AdvancedWebView/issues/4#issuecomment-70372146)):
301
 
307
 
302
 #### The `injectedJavaScriptBeforeContentLoaded` prop
308
 #### The `injectedJavaScriptBeforeContentLoaded` prop
303
 
309
 
304
-This is a script that runs **before** the web page loads for the first time. It only runs once, even if the page is reloaded or navigated away. This is useful if you want to inject anything into the window, localstorage, or document prior to the web code executing. 
310
+This is a script that runs **before** the web page loads for the first time. It only runs once, even if the page is reloaded or navigated away. This is useful if you want to inject anything into the window, localstorage, or document prior to the web code executing.
305
 
311
 
306
 > Android Compatibility: Applications targeting Build.VERSION_CODES.N or later, JavaScript state from an empty WebView is no longer persisted across navigations like loadUrl(java.lang.String). 
312
 > Android Compatibility: Applications targeting Build.VERSION_CODES.N or later, JavaScript state from an empty WebView is no longer persisted across navigations like loadUrl(java.lang.String). 
307
 For example, global variables and functions defined before calling loadUrl(java.lang.String) will not exist in the loaded page. 
313
 For example, global variables and functions defined before calling loadUrl(java.lang.String) will not exist in the loaded page. 
335
 }
341
 }
336
 ```
342
 ```
337
 
343
 
338
-This runs the JavaScript in the `runFirst` string before the page is loaded. In this case, the value of `window.isNativeApp` will be set to true before the web code executes. 
344
+This runs the JavaScript in the `runFirst` string before the page is loaded. In this case, the value of `window.isNativeApp` will be set to true before the web code executes.
339
 
345
 
340
 #### The `injectJavaScript` method
346
 #### The `injectJavaScript` method
341
 
347
 
481
 
487
 
482
 #### Managing Cookies
488
 #### Managing Cookies
483
 
489
 
484
-You can set cookies on the React Native side using the [react-native-cookies](https://github.com/joeferraro/react-native-cookies) package.
490
+You can set cookies on the React Native side using the [@react-native-community/cookies](https://github.com/react-native-community/cookies) package.
485
 
491
 
486
 When you do, you'll likely want to enable the [sharedCookiesEnabled](Reference#sharedCookiesEnabled) prop as well.
492
 When you do, you'll likely want to enable the [sharedCookiesEnabled](Reference#sharedCookiesEnabled) prop as well.
487
 
493
 

+ 1
- 1
docs/README.portuguese.md View File

36
 
36
 
37
 - [7.0.1](https://github.com/react-native-community/react-native-webview/releases/tag/v7.0.1) - UIWebView removido
37
 - [7.0.1](https://github.com/react-native-community/react-native-webview/releases/tag/v7.0.1) - UIWebView removido
38
 
38
 
39
-- [6.0.**2**](https://github.com/react-native-community/react-native-webview/releases/tag/v6.0.2) - Update para AndroidX. Tenha certeza de habilitar no `android/gradle.properties` do seu projeto. Veja o [Getting Started Guide](docs/Getting-Started.md).
39
+- [6.0.**2**](https://github.com/react-native-community/react-native-webview/releases/tag/v6.0.2) - Update para AndroidX. Tenha certeza de habilitar no `android/gradle.properties` do seu projeto. Veja o [Getting Started Guide](https://github.com/react-native-community/react-native-webview/blob/master/docs/Getting-Started.md).
40
 
40
 
41
 - [5.0.**1**](https://github.com/react-native-community/react-native-webview/releases/tag/v5.0.0) - Refatorou a antiga implementação postMessage para comunicação da visualização da webview para nativa.
41
 - [5.0.**1**](https://github.com/react-native-community/react-native-webview/releases/tag/v5.0.0) - Refatorou a antiga implementação postMessage para comunicação da visualização da webview para nativa.
42
 - [4.0.0](https://github.com/react-native-community/react-native-webview/releases/tag/v4.0.0) - Cache adicionada(habilitada por padrão).
42
 - [4.0.0](https://github.com/react-native-community/react-native-webview/releases/tag/v4.0.0) - Cache adicionada(habilitada por padrão).

+ 18
- 18
docs/Reference.md View File

474
 
474
 
475
 Function that is invoked when the `WebView` content process is terminated.
475
 Function that is invoked when the `WebView` content process is terminated.
476
 
476
 
477
-| Type     | Required | Platform      |
478
-| -------- | -------- | ------------- |
479
-| function | No       | iOS WKWebView |
477
+| Type     | Required | Platform                |
478
+| -------- | -------- | ----------------------- |
479
+| function | No       | iOS and macOS WKWebView |
480
 
480
 
481
 Example:
481
 Example:
482
 
482
 
863
 
863
 
864
 Boolean value that determines whether scrolling is enabled in the `WebView`. The default value is `true`. Setting this to `false` will prevent the webview from moving the document body when the keyboard appears over an input.
864
 Boolean value that determines whether scrolling is enabled in the `WebView`. The default value is `true`. Setting this to `false` will prevent the webview from moving the document body when the keyboard appears over an input.
865
 
865
 
866
-| Type | Required | Platform |
867
-| ---- | -------- | -------- |
868
-| bool | No       | iOS      |
866
+| Type | Required | Platform      |
867
+| ---- | -------- | ------------- |
868
+| bool | No       | iOS and macOS |
869
 
869
 
870
 ---
870
 ---
871
 
871
 
934
 
934
 
935
 A String value that indicates which URLs the WebView's file can then reference in scripts, AJAX requests, and CSS imports. This is only used in for WebViews that are loaded with a source.uri set to a `'file://'` URL. If not provided, the default is to only allow read access to the URL provided in source.uri itself.
935
 A String value that indicates which URLs the WebView's file can then reference in scripts, AJAX requests, and CSS imports. This is only used in for WebViews that are loaded with a source.uri set to a `'file://'` URL. If not provided, the default is to only allow read access to the URL provided in source.uri itself.
936
 
936
 
937
-| Type   | Required | Platform |
938
-| ------ | -------- | -------- |
939
-| string | No       | iOS      |
937
+| Type   | Required | Platform      |
938
+| ------ | -------- | ------------- |
939
+| string | No       | iOS and macOS |
940
 
940
 
941
 ---
941
 ---
942
 
942
 
984
 
984
 
985
 If true, this will be able horizontal swipe gestures. The default value is `false`.
985
 If true, this will be able horizontal swipe gestures. The default value is `false`.
986
 
986
 
987
-| Type    | Required | Platform |
988
-| ------- | -------- | -------- |
989
-| boolean | No       | iOS      |
987
+| Type    | Required | Platform          |
988
+| ------- | -------- | ----------------- |
989
+| boolean | No       | iOS and macOS     |
990
 
990
 
991
 ---
991
 ---
992
 
992
 
1061
 
1061
 
1062
 A Boolean value that determines whether pressing on a link displays a preview of the destination for the link. In iOS this property is available on devices that support 3D Touch. In iOS 10 and later, the default value is true; before that, the default value is false.
1062
 A Boolean value that determines whether pressing on a link displays a preview of the destination for the link. In iOS this property is available on devices that support 3D Touch. In iOS 10 and later, the default value is true; before that, the default value is false.
1063
 
1063
 
1064
-| Type    | Required | Platform |
1065
-| ------- | -------- | -------- |
1066
-| boolean | No       | iOS      |
1064
+| Type    | Required | Platform          |
1065
+| ------- | -------- | ----------------- |
1066
+| boolean | No       | iOS and macOS     |
1067
 
1067
 
1068
 ---
1068
 ---
1069
 
1069
 
1071
 
1071
 
1072
 Set `true` if shared cookies from `[NSHTTPCookieStorage sharedHTTPCookieStorage]` should used for every load request in the WebView. The default value is `false`. For more on cookies, read the [Guide](Guide.md#Managing-Cookies)
1072
 Set `true` if shared cookies from `[NSHTTPCookieStorage sharedHTTPCookieStorage]` should used for every load request in the WebView. The default value is `false`. For more on cookies, read the [Guide](Guide.md#Managing-Cookies)
1073
 
1073
 
1074
-| Type    | Required | Platform |
1075
-| ------- | -------- | -------- |
1076
-| boolean | No       | iOS      |
1074
+| Type    | Required | Platform          |
1075
+| ------- | -------- | ----------------- |
1076
+| boolean | No       | iOS and macOS     |
1077
 
1077
 
1078
 ---
1078
 ---
1079
 
1079
 

+ 4
- 1
example/.gitignore View File

20
 *.hmap
20
 *.hmap
21
 *.ipa
21
 *.ipa
22
 *.xcuserstate
22
 *.xcuserstate
23
-project.xcworkspace
23
+# exclude project.xcworkspace except for xcshareddata/WorkspaceSettings.xcsettings
24
+project.xcworkspace/*
25
+**/project.xcworkspace/contents.xcworkspacedata
26
+**/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
24
 
27
 
25
 # Android/IntelliJ
28
 # Android/IntelliJ
26
 #
29
 #

+ 15
- 0
example/App.tsx View File

7
   View,
7
   View,
8
   Keyboard,
8
   Keyboard,
9
   Button,
9
   Button,
10
+  Platform,
10
 } from 'react-native';
11
 } from 'react-native';
11
 
12
 
12
 import Alerts from './examples/Alerts';
13
 import Alerts from './examples/Alerts';
13
 import Scrolling from './examples/Scrolling';
14
 import Scrolling from './examples/Scrolling';
14
 import Background from './examples/Background';
15
 import Background from './examples/Background';
16
+import Uploads from './examples/Uploads';
15
 
17
 
16
 const TESTS = {
18
 const TESTS = {
17
   Alerts: {
19
   Alerts: {
38
       return <Background />;
40
       return <Background />;
39
     },
41
     },
40
   },
42
   },
43
+  Uploads: {
44
+    title: 'Uploads',
45
+    testId: 'uploads',
46
+    description: 'Upload test',
47
+    render() {
48
+      return <Uploads />;
49
+    },
50
+  },
41
 };
51
 };
42
 
52
 
43
 type Props = {};
53
 type Props = {};
91
             title="Background"
101
             title="Background"
92
             onPress={() => this._changeTest('Background')}
102
             onPress={() => this._changeTest('Background')}
93
           />
103
           />
104
+          {Platform.OS === 'android' && <Button
105
+            testID="testType_uploads"
106
+            title="Uploads"
107
+            onPress={() => this._changeTest('Uploads')}
108
+          />}
94
         </View>
109
         </View>
95
 
110
 
96
         {restarting ? null : (
111
         {restarting ? null : (

+ 1
- 0
example/android/app/src/main/AndroidManifest.xml View File

2
   package="com.example">
2
   package="com.example">
3
 
3
 
4
     <uses-permission android:name="android.permission.INTERNET" />
4
     <uses-permission android:name="android.permission.INTERNET" />
5
+    <uses-permission android:name="android.permission.CAMERA" />
5
 
6
 
6
     <application
7
     <application
7
       android:name=".MainApplication"
8
       android:name=".MainApplication"

+ 69
- 0
example/examples/Uploads.tsx View File

1
+import React, {Component} from 'react';
2
+import {Button, Linking, Text, View} from 'react-native';
3
+
4
+import WebView from 'react-native-webview';
5
+
6
+const HTML = `
7
+<!DOCTYPE html>\n
8
+<html>
9
+  <head>
10
+    <title>Uploads</title>
11
+    <meta http-equiv="content-type" content="text/html; charset=utf-8">
12
+    <meta name="viewport" content="width=320, user-scalable=no">
13
+    <style type="text/css">
14
+      body {
15
+        margin: 0;
16
+        padding: 0;
17
+        font: 62.5% arial, sans-serif;
18
+        background: #ccc;
19
+      }
20
+    </style>
21
+  </head>
22
+  <body>
23
+    <p>
24
+      <label for="images-only">Images only file upload</label>
25
+      <input name="images-only" type="file" accept="image/*">
26
+    </p>
27
+    <p>
28
+      <label for="video-only">Video only file upload</label>
29
+      <input name="video-only" type="file" accept="video/*">
30
+    </p>
31
+    <p>
32
+      <label for="any-file">Any file upload</label>
33
+      <input name="any-file" type="file">
34
+    </p>
35
+  </body>
36
+</html>
37
+`;
38
+
39
+type Props = {};
40
+type State = {};
41
+
42
+export default class Uploads extends Component<Props, State> {
43
+  state = {};
44
+
45
+  render() {
46
+    return (
47
+      <View>
48
+        <View style={{ height: 120 }}>
49
+          <WebView
50
+            source={{html: HTML}}
51
+            automaticallyAdjustContentInsets={false}
52
+          />
53
+        </View>
54
+        <Text>
55
+            Android limitation: If the file input should show camera options for the user,
56
+            and the app has the ability to request the camera permission, then the user must
57
+            grant permission first in order to see the options. Since this example app does
58
+            have the permission declared, you must allow it in settings to be able to see
59
+            camera options. If your app does not have the camera permission declared, then
60
+            there is no restriction to showing the camera options.
61
+        </Text>
62
+        <Button
63
+          title="Open settings"
64
+          onPress={() => Linking.openSettings()}
65
+        />
66
+      </View>
67
+    );
68
+  }
69
+}

+ 2
- 2
example/ios/Podfile.lock View File

182
     - React-cxxreact (= 0.61.5)
182
     - React-cxxreact (= 0.61.5)
183
     - React-jsi (= 0.61.5)
183
     - React-jsi (= 0.61.5)
184
   - React-jsinspector (0.61.5)
184
   - React-jsinspector (0.61.5)
185
-  - react-native-webview (8.0.4):
185
+  - react-native-webview (8.0.6):
186
     - React
186
     - React
187
   - React-RCTActionSheet (0.61.5):
187
   - React-RCTActionSheet (0.61.5):
188
     - React-Core/RCTActionSheetHeaders (= 0.61.5)
188
     - React-Core/RCTActionSheetHeaders (= 0.61.5)
326
   React-jsi: cb2cd74d7ccf4cffb071a46833613edc79cdf8f7
326
   React-jsi: cb2cd74d7ccf4cffb071a46833613edc79cdf8f7
327
   React-jsiexecutor: d5525f9ed5f782fdbacb64b9b01a43a9323d2386
327
   React-jsiexecutor: d5525f9ed5f782fdbacb64b9b01a43a9323d2386
328
   React-jsinspector: fa0ecc501688c3c4c34f28834a76302233e29dc0
328
   React-jsinspector: fa0ecc501688c3c4c34f28834a76302233e29dc0
329
-  react-native-webview: 3f5aa91c3cb083ea4762e006b9653291a96a777a
329
+  react-native-webview: 222d83c9c489e09b5d3541519110a637490ad4fa
330
   React-RCTActionSheet: 600b4d10e3aea0913b5a92256d2719c0cdd26d76
330
   React-RCTActionSheet: 600b4d10e3aea0913b5a92256d2719c0cdd26d76
331
   React-RCTAnimation: 791a87558389c80908ed06cc5dfc5e7920dfa360
331
   React-RCTAnimation: 791a87558389c80908ed06cc5dfc5e7920dfa360
332
   React-RCTBlob: d89293cc0236d9cb0933d85e430b0bbe81ad1d72
332
   React-RCTBlob: d89293cc0236d9cb0933d85e430b0bbe81ad1d72

+ 16
- 0
example/macos/example-macOS/AppDelegate.h View File

1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
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
+
8
+#import <Cocoa/Cocoa.h>
9
+
10
+@class RCTBridge;
11
+
12
+@interface AppDelegate : NSObject <NSApplicationDelegate>
13
+
14
+@property (nonatomic, readonly) RCTBridge *bridge;
15
+
16
+@end

+ 39
- 0
example/macos/example-macOS/AppDelegate.m View File

1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
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
+
8
+#import "AppDelegate.h"
9
+
10
+#import <React/RCTBridge.h>
11
+#import <React/RCTBundleURLProvider.h>
12
+
13
+@interface AppDelegate () <RCTBridgeDelegate>
14
+
15
+@end
16
+
17
+@implementation AppDelegate
18
+
19
+- (void)awakeFromNib {
20
+  [super awakeFromNib];
21
+
22
+  _bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:nil];
23
+}
24
+
25
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
26
+  // Insert code here to initialize your application
27
+}
28
+
29
+- (void)applicationWillTerminate:(NSNotification *)aNotification {
30
+  // Insert code here to tear down your application
31
+}
32
+
33
+#pragma mark - RCTBridgeDelegate Methods
34
+
35
+- (NSURL *)sourceURLForBridge:(__unused RCTBridge *)bridge {
36
+  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"example/index" fallbackResource:@"main"]; // .jsbundle;
37
+}
38
+
39
+@end

+ 45
- 0
example/macos/example-macOS/Info.plist View File

1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>CFBundleDevelopmentRegion</key>
6
+	<string>$(DEVELOPMENT_LANGUAGE)</string>
7
+	<key>CFBundleExecutable</key>
8
+	<string>$(EXECUTABLE_NAME)</string>
9
+	<key>CFBundleIconFile</key>
10
+	<string></string>
11
+	<key>CFBundleIdentifier</key>
12
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
13
+	<key>CFBundleInfoDictionaryVersion</key>
14
+	<string>6.0</string>
15
+	<key>CFBundleName</key>
16
+	<string>$(PRODUCT_NAME)</string>
17
+	<key>CFBundlePackageType</key>
18
+	<string>APPL</string>
19
+	<key>CFBundleShortVersionString</key>
20
+	<string>1.0</string>
21
+	<key>CFBundleVersion</key>
22
+	<string>1</string>
23
+	<key>LSMinimumSystemVersion</key>
24
+	<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
25
+	<key>NSAppTransportSecurity</key>
26
+	<dict>
27
+		<key>NSAllowsArbitraryLoads</key>
28
+		<true/>
29
+		<key>NSExceptionDomains</key>
30
+		<dict>
31
+			<key>localhost</key>
32
+			<dict>
33
+				<key>NSExceptionAllowsInsecureHTTPLoads</key>
34
+				<true/>
35
+			</dict>
36
+		</dict>
37
+	</dict>
38
+	<key>NSHumanReadableCopyright</key>
39
+	<string>Copyright © 2017 Facebook. All rights reserved.</string>
40
+	<key>NSMainStoryboardFile</key>
41
+	<string>Main</string>
42
+	<key>NSPrincipalClass</key>
43
+	<string>NSApplication</string>
44
+</dict>
45
+</plist>

+ 713
- 0
example/macos/example-macOS/Main.storyboard View File

1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="15505" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
3
+    <dependencies>
4
+        <deployment identifier="macosx"/>
5
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15505"/>
6
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
7
+    </dependencies>
8
+    <scenes>
9
+        <!--Application-->
10
+        <scene sceneID="JPo-4y-FX3">
11
+            <objects>
12
+                <application id="hnw-xV-0zn" sceneMemberID="viewController">
13
+                    <menu key="mainMenu" title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
14
+                        <items>
15
+                            <menuItem title="rncTesterApp-macOS" id="1Xt-HY-uBw">
16
+                                <modifierMask key="keyEquivalentModifierMask"/>
17
+                                <menu key="submenu" title="rncTesterApp-macOS" systemMenu="apple" id="uQy-DD-JDr">
18
+                                    <items>
19
+                                        <menuItem title="About rncTesterApp-macOS" id="5kV-Vb-QxS">
20
+                                            <modifierMask key="keyEquivalentModifierMask"/>
21
+                                            <connections>
22
+                                                <action selector="orderFrontStandardAboutPanel:" target="Ady-hI-5gd" id="Exp-CZ-Vem"/>
23
+                                            </connections>
24
+                                        </menuItem>
25
+                                        <menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
26
+                                        <menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
27
+                                        <menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
28
+                                        <menuItem title="Services" id="NMo-om-nkz">
29
+                                            <modifierMask key="keyEquivalentModifierMask"/>
30
+                                            <menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
31
+                                        </menuItem>
32
+                                        <menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
33
+                                        <menuItem title="Hide rncTesterApp-macOS" keyEquivalent="h" id="Olw-nP-bQN">
34
+                                            <connections>
35
+                                                <action selector="hide:" target="Ady-hI-5gd" id="PnN-Uc-m68"/>
36
+                                            </connections>
37
+                                        </menuItem>
38
+                                        <menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
39
+                                            <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
40
+                                            <connections>
41
+                                                <action selector="hideOtherApplications:" target="Ady-hI-5gd" id="VT4-aY-XCT"/>
42
+                                            </connections>
43
+                                        </menuItem>
44
+                                        <menuItem title="Show All" id="Kd2-mp-pUS">
45
+                                            <modifierMask key="keyEquivalentModifierMask"/>
46
+                                            <connections>
47
+                                                <action selector="unhideAllApplications:" target="Ady-hI-5gd" id="Dhg-Le-xox"/>
48
+                                            </connections>
49
+                                        </menuItem>
50
+                                        <menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
51
+                                        <menuItem title="Quit rncTesterApp-macOS" keyEquivalent="q" id="4sb-4s-VLi">
52
+                                            <connections>
53
+                                                <action selector="terminate:" target="Ady-hI-5gd" id="Te7-pn-YzF"/>
54
+                                            </connections>
55
+                                        </menuItem>
56
+                                    </items>
57
+                                </menu>
58
+                            </menuItem>
59
+                            <menuItem title="File" id="dMs-cI-mzQ">
60
+                                <modifierMask key="keyEquivalentModifierMask"/>
61
+                                <menu key="submenu" title="File" id="bib-Uj-vzu">
62
+                                    <items>
63
+                                        <menuItem title="New" keyEquivalent="n" id="Was-JA-tGl">
64
+                                            <connections>
65
+                                                <action selector="newDocument:" target="Ady-hI-5gd" id="4Si-XN-c54"/>
66
+                                            </connections>
67
+                                        </menuItem>
68
+                                        <menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9">
69
+                                            <connections>
70
+                                                <action selector="openDocument:" target="Ady-hI-5gd" id="bVn-NM-KNZ"/>
71
+                                            </connections>
72
+                                        </menuItem>
73
+                                        <menuItem title="Open Recent" id="tXI-mr-wws">
74
+                                            <modifierMask key="keyEquivalentModifierMask"/>
75
+                                            <menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="oas-Oc-fiZ">
76
+                                                <items>
77
+                                                    <menuItem title="Clear Menu" id="vNY-rz-j42">
78
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
79
+                                                        <connections>
80
+                                                            <action selector="clearRecentDocuments:" target="Ady-hI-5gd" id="Daa-9d-B3U"/>
81
+                                                        </connections>
82
+                                                    </menuItem>
83
+                                                </items>
84
+                                            </menu>
85
+                                        </menuItem>
86
+                                        <menuItem isSeparatorItem="YES" id="m54-Is-iLE"/>
87
+                                        <menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG">
88
+                                            <connections>
89
+                                                <action selector="performClose:" target="Ady-hI-5gd" id="HmO-Ls-i7Q"/>
90
+                                            </connections>
91
+                                        </menuItem>
92
+                                        <menuItem title="Save…" keyEquivalent="s" id="pxx-59-PXV">
93
+                                            <connections>
94
+                                                <action selector="saveDocument:" target="Ady-hI-5gd" id="teZ-XB-qJY"/>
95
+                                            </connections>
96
+                                        </menuItem>
97
+                                        <menuItem title="Save As…" keyEquivalent="S" id="Bw7-FT-i3A">
98
+                                            <connections>
99
+                                                <action selector="saveDocumentAs:" target="Ady-hI-5gd" id="mDf-zr-I0C"/>
100
+                                            </connections>
101
+                                        </menuItem>
102
+                                        <menuItem title="Revert to Saved" keyEquivalent="r" id="KaW-ft-85H">
103
+                                            <connections>
104
+                                                <action selector="revertDocumentToSaved:" target="Ady-hI-5gd" id="iJ3-Pv-kwq"/>
105
+                                            </connections>
106
+                                        </menuItem>
107
+                                        <menuItem isSeparatorItem="YES" id="aJh-i4-bef"/>
108
+                                        <menuItem title="Page Setup…" keyEquivalent="P" id="qIS-W8-SiK">
109
+                                            <modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
110
+                                            <connections>
111
+                                                <action selector="runPageLayout:" target="Ady-hI-5gd" id="Din-rz-gC5"/>
112
+                                            </connections>
113
+                                        </menuItem>
114
+                                        <menuItem title="Print…" keyEquivalent="p" id="aTl-1u-JFS">
115
+                                            <connections>
116
+                                                <action selector="print:" target="Ady-hI-5gd" id="qaZ-4w-aoO"/>
117
+                                            </connections>
118
+                                        </menuItem>
119
+                                    </items>
120
+                                </menu>
121
+                            </menuItem>
122
+                            <menuItem title="Edit" id="5QF-Oa-p0T">
123
+                                <modifierMask key="keyEquivalentModifierMask"/>
124
+                                <menu key="submenu" title="Edit" id="W48-6f-4Dl">
125
+                                    <items>
126
+                                        <menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
127
+                                            <connections>
128
+                                                <action selector="undo:" target="Ady-hI-5gd" id="M6e-cu-g7V"/>
129
+                                            </connections>
130
+                                        </menuItem>
131
+                                        <menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
132
+                                            <connections>
133
+                                                <action selector="redo:" target="Ady-hI-5gd" id="oIA-Rs-6OD"/>
134
+                                            </connections>
135
+                                        </menuItem>
136
+                                        <menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
137
+                                        <menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
138
+                                            <connections>
139
+                                                <action selector="cut:" target="Ady-hI-5gd" id="YJe-68-I9s"/>
140
+                                            </connections>
141
+                                        </menuItem>
142
+                                        <menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
143
+                                            <connections>
144
+                                                <action selector="copy:" target="Ady-hI-5gd" id="G1f-GL-Joy"/>
145
+                                            </connections>
146
+                                        </menuItem>
147
+                                        <menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
148
+                                            <connections>
149
+                                                <action selector="paste:" target="Ady-hI-5gd" id="UvS-8e-Qdg"/>
150
+                                            </connections>
151
+                                        </menuItem>
152
+                                        <menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
153
+                                            <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
154
+                                            <connections>
155
+                                                <action selector="pasteAsPlainText:" target="Ady-hI-5gd" id="cEh-KX-wJQ"/>
156
+                                            </connections>
157
+                                        </menuItem>
158
+                                        <menuItem title="Delete" id="pa3-QI-u2k">
159
+                                            <modifierMask key="keyEquivalentModifierMask"/>
160
+                                            <connections>
161
+                                                <action selector="delete:" target="Ady-hI-5gd" id="0Mk-Ml-PaM"/>
162
+                                            </connections>
163
+                                        </menuItem>
164
+                                        <menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
165
+                                            <connections>
166
+                                                <action selector="selectAll:" target="Ady-hI-5gd" id="VNm-Mi-diN"/>
167
+                                            </connections>
168
+                                        </menuItem>
169
+                                        <menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
170
+                                        <menuItem title="Find" id="4EN-yA-p0u">
171
+                                            <modifierMask key="keyEquivalentModifierMask"/>
172
+                                            <menu key="submenu" title="Find" id="1b7-l0-nxx">
173
+                                                <items>
174
+                                                    <menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
175
+                                                        <connections>
176
+                                                            <action selector="performFindPanelAction:" target="Ady-hI-5gd" id="cD7-Qs-BN4"/>
177
+                                                        </connections>
178
+                                                    </menuItem>
179
+                                                    <menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
180
+                                                        <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
181
+                                                        <connections>
182
+                                                            <action selector="performFindPanelAction:" target="Ady-hI-5gd" id="WD3-Gg-5AJ"/>
183
+                                                        </connections>
184
+                                                    </menuItem>
185
+                                                    <menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
186
+                                                        <connections>
187
+                                                            <action selector="performFindPanelAction:" target="Ady-hI-5gd" id="NDo-RZ-v9R"/>
188
+                                                        </connections>
189
+                                                    </menuItem>
190
+                                                    <menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
191
+                                                        <connections>
192
+                                                            <action selector="performFindPanelAction:" target="Ady-hI-5gd" id="HOh-sY-3ay"/>
193
+                                                        </connections>
194
+                                                    </menuItem>
195
+                                                    <menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
196
+                                                        <connections>
197
+                                                            <action selector="performFindPanelAction:" target="Ady-hI-5gd" id="U76-nv-p5D"/>
198
+                                                        </connections>
199
+                                                    </menuItem>
200
+                                                    <menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
201
+                                                        <connections>
202
+                                                            <action selector="centerSelectionInVisibleArea:" target="Ady-hI-5gd" id="IOG-6D-g5B"/>
203
+                                                        </connections>
204
+                                                    </menuItem>
205
+                                                </items>
206
+                                            </menu>
207
+                                        </menuItem>
208
+                                        <menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
209
+                                            <modifierMask key="keyEquivalentModifierMask"/>
210
+                                            <menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
211
+                                                <items>
212
+                                                    <menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
213
+                                                        <connections>
214
+                                                            <action selector="showGuessPanel:" target="Ady-hI-5gd" id="vFj-Ks-hy3"/>
215
+                                                        </connections>
216
+                                                    </menuItem>
217
+                                                    <menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
218
+                                                        <connections>
219
+                                                            <action selector="checkSpelling:" target="Ady-hI-5gd" id="fz7-VC-reM"/>
220
+                                                        </connections>
221
+                                                    </menuItem>
222
+                                                    <menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
223
+                                                    <menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
224
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
225
+                                                        <connections>
226
+                                                            <action selector="toggleContinuousSpellChecking:" target="Ady-hI-5gd" id="7w6-Qz-0kB"/>
227
+                                                        </connections>
228
+                                                    </menuItem>
229
+                                                    <menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
230
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
231
+                                                        <connections>
232
+                                                            <action selector="toggleGrammarChecking:" target="Ady-hI-5gd" id="muD-Qn-j4w"/>
233
+                                                        </connections>
234
+                                                    </menuItem>
235
+                                                    <menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
236
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
237
+                                                        <connections>
238
+                                                            <action selector="toggleAutomaticSpellingCorrection:" target="Ady-hI-5gd" id="2lM-Qi-WAP"/>
239
+                                                        </connections>
240
+                                                    </menuItem>
241
+                                                </items>
242
+                                            </menu>
243
+                                        </menuItem>
244
+                                        <menuItem title="Substitutions" id="9ic-FL-obx">
245
+                                            <modifierMask key="keyEquivalentModifierMask"/>
246
+                                            <menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
247
+                                                <items>
248
+                                                    <menuItem title="Show Substitutions" id="z6F-FW-3nz">
249
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
250
+                                                        <connections>
251
+                                                            <action selector="orderFrontSubstitutionsPanel:" target="Ady-hI-5gd" id="oku-mr-iSq"/>
252
+                                                        </connections>
253
+                                                    </menuItem>
254
+                                                    <menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
255
+                                                    <menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
256
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
257
+                                                        <connections>
258
+                                                            <action selector="toggleSmartInsertDelete:" target="Ady-hI-5gd" id="3IJ-Se-DZD"/>
259
+                                                        </connections>
260
+                                                    </menuItem>
261
+                                                    <menuItem title="Smart Quotes" id="hQb-2v-fYv">
262
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
263
+                                                        <connections>
264
+                                                            <action selector="toggleAutomaticQuoteSubstitution:" target="Ady-hI-5gd" id="ptq-xd-QOA"/>
265
+                                                        </connections>
266
+                                                    </menuItem>
267
+                                                    <menuItem title="Smart Dashes" id="rgM-f4-ycn">
268
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
269
+                                                        <connections>
270
+                                                            <action selector="toggleAutomaticDashSubstitution:" target="Ady-hI-5gd" id="oCt-pO-9gS"/>
271
+                                                        </connections>
272
+                                                    </menuItem>
273
+                                                    <menuItem title="Smart Links" id="cwL-P1-jid">
274
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
275
+                                                        <connections>
276
+                                                            <action selector="toggleAutomaticLinkDetection:" target="Ady-hI-5gd" id="Gip-E3-Fov"/>
277
+                                                        </connections>
278
+                                                    </menuItem>
279
+                                                    <menuItem title="Data Detectors" id="tRr-pd-1PS">
280
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
281
+                                                        <connections>
282
+                                                            <action selector="toggleAutomaticDataDetection:" target="Ady-hI-5gd" id="R1I-Nq-Kbl"/>
283
+                                                        </connections>
284
+                                                    </menuItem>
285
+                                                    <menuItem title="Text Replacement" id="HFQ-gK-NFA">
286
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
287
+                                                        <connections>
288
+                                                            <action selector="toggleAutomaticTextReplacement:" target="Ady-hI-5gd" id="DvP-Fe-Py6"/>
289
+                                                        </connections>
290
+                                                    </menuItem>
291
+                                                </items>
292
+                                            </menu>
293
+                                        </menuItem>
294
+                                        <menuItem title="Transformations" id="2oI-Rn-ZJC">
295
+                                            <modifierMask key="keyEquivalentModifierMask"/>
296
+                                            <menu key="submenu" title="Transformations" id="c8a-y6-VQd">
297
+                                                <items>
298
+                                                    <menuItem title="Make Upper Case" id="vmV-6d-7jI">
299
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
300
+                                                        <connections>
301
+                                                            <action selector="uppercaseWord:" target="Ady-hI-5gd" id="sPh-Tk-edu"/>
302
+                                                        </connections>
303
+                                                    </menuItem>
304
+                                                    <menuItem title="Make Lower Case" id="d9M-CD-aMd">
305
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
306
+                                                        <connections>
307
+                                                            <action selector="lowercaseWord:" target="Ady-hI-5gd" id="iUZ-b5-hil"/>
308
+                                                        </connections>
309
+                                                    </menuItem>
310
+                                                    <menuItem title="Capitalize" id="UEZ-Bs-lqG">
311
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
312
+                                                        <connections>
313
+                                                            <action selector="capitalizeWord:" target="Ady-hI-5gd" id="26H-TL-nsh"/>
314
+                                                        </connections>
315
+                                                    </menuItem>
316
+                                                </items>
317
+                                            </menu>
318
+                                        </menuItem>
319
+                                        <menuItem title="Speech" id="xrE-MZ-jX0">
320
+                                            <modifierMask key="keyEquivalentModifierMask"/>
321
+                                            <menu key="submenu" title="Speech" id="3rS-ZA-NoH">
322
+                                                <items>
323
+                                                    <menuItem title="Start Speaking" id="Ynk-f8-cLZ">
324
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
325
+                                                        <connections>
326
+                                                            <action selector="startSpeaking:" target="Ady-hI-5gd" id="654-Ng-kyl"/>
327
+                                                        </connections>
328
+                                                    </menuItem>
329
+                                                    <menuItem title="Stop Speaking" id="Oyz-dy-DGm">
330
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
331
+                                                        <connections>
332
+                                                            <action selector="stopSpeaking:" target="Ady-hI-5gd" id="dX8-6p-jy9"/>
333
+                                                        </connections>
334
+                                                    </menuItem>
335
+                                                </items>
336
+                                            </menu>
337
+                                        </menuItem>
338
+                                    </items>
339
+                                </menu>
340
+                            </menuItem>
341
+                            <menuItem title="Format" id="jxT-CU-nIS">
342
+                                <modifierMask key="keyEquivalentModifierMask"/>
343
+                                <menu key="submenu" title="Format" id="GEO-Iw-cKr">
344
+                                    <items>
345
+                                        <menuItem title="Font" id="Gi5-1S-RQB">
346
+                                            <modifierMask key="keyEquivalentModifierMask"/>
347
+                                            <menu key="submenu" title="Font" systemMenu="font" id="aXa-aM-Jaq">
348
+                                                <items>
349
+                                                    <menuItem title="Show Fonts" keyEquivalent="t" id="Q5e-8K-NDq">
350
+                                                        <connections>
351
+                                                            <action selector="orderFrontFontPanel:" target="YLy-65-1bz" id="WHr-nq-2xA"/>
352
+                                                        </connections>
353
+                                                    </menuItem>
354
+                                                    <menuItem title="Bold" tag="2" keyEquivalent="b" id="GB9-OM-e27">
355
+                                                        <connections>
356
+                                                            <action selector="addFontTrait:" target="YLy-65-1bz" id="hqk-hr-sYV"/>
357
+                                                        </connections>
358
+                                                    </menuItem>
359
+                                                    <menuItem title="Italic" tag="1" keyEquivalent="i" id="Vjx-xi-njq">
360
+                                                        <connections>
361
+                                                            <action selector="addFontTrait:" target="YLy-65-1bz" id="IHV-OB-c03"/>
362
+                                                        </connections>
363
+                                                    </menuItem>
364
+                                                    <menuItem title="Underline" keyEquivalent="u" id="WRG-CD-K1S">
365
+                                                        <connections>
366
+                                                            <action selector="underline:" target="Ady-hI-5gd" id="FYS-2b-JAY"/>
367
+                                                        </connections>
368
+                                                    </menuItem>
369
+                                                    <menuItem isSeparatorItem="YES" id="5gT-KC-WSO"/>
370
+                                                    <menuItem title="Bigger" tag="3" keyEquivalent="+" id="Ptp-SP-VEL">
371
+                                                        <connections>
372
+                                                            <action selector="modifyFont:" target="YLy-65-1bz" id="Uc7-di-UnL"/>
373
+                                                        </connections>
374
+                                                    </menuItem>
375
+                                                    <menuItem title="Smaller" tag="4" keyEquivalent="-" id="i1d-Er-qST">
376
+                                                        <connections>
377
+                                                            <action selector="modifyFont:" target="YLy-65-1bz" id="HcX-Lf-eNd"/>
378
+                                                        </connections>
379
+                                                    </menuItem>
380
+                                                    <menuItem isSeparatorItem="YES" id="kx3-Dk-x3B"/>
381
+                                                    <menuItem title="Kern" id="jBQ-r6-VK2">
382
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
383
+                                                        <menu key="submenu" title="Kern" id="tlD-Oa-oAM">
384
+                                                            <items>
385
+                                                                <menuItem title="Use Default" id="GUa-eO-cwY">
386
+                                                                    <modifierMask key="keyEquivalentModifierMask"/>
387
+                                                                    <connections>
388
+                                                                        <action selector="useStandardKerning:" target="Ady-hI-5gd" id="6dk-9l-Ckg"/>
389
+                                                                    </connections>
390
+                                                                </menuItem>
391
+                                                                <menuItem title="Use None" id="cDB-IK-hbR">
392
+                                                                    <modifierMask key="keyEquivalentModifierMask"/>
393
+                                                                    <connections>
394
+                                                                        <action selector="turnOffKerning:" target="Ady-hI-5gd" id="U8a-gz-Maa"/>
395
+                                                                    </connections>
396
+                                                                </menuItem>
397
+                                                                <menuItem title="Tighten" id="46P-cB-AYj">
398
+                                                                    <modifierMask key="keyEquivalentModifierMask"/>
399
+                                                                    <connections>
400
+                                                                        <action selector="tightenKerning:" target="Ady-hI-5gd" id="hr7-Nz-8ro"/>
401
+                                                                    </connections>
402
+                                                                </menuItem>
403
+                                                                <menuItem title="Loosen" id="ogc-rX-tC1">
404
+                                                                    <modifierMask key="keyEquivalentModifierMask"/>
405
+                                                                    <connections>
406
+                                                                        <action selector="loosenKerning:" target="Ady-hI-5gd" id="8i4-f9-FKE"/>
407
+                                                                    </connections>
408
+                                                                </menuItem>
409
+                                                            </items>
410
+                                                        </menu>
411
+                                                    </menuItem>
412
+                                                    <menuItem title="Ligatures" id="o6e-r0-MWq">
413
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
414
+                                                        <menu key="submenu" title="Ligatures" id="w0m-vy-SC9">
415
+                                                            <items>
416
+                                                                <menuItem title="Use Default" id="agt-UL-0e3">
417
+                                                                    <modifierMask key="keyEquivalentModifierMask"/>
418
+                                                                    <connections>
419
+                                                                        <action selector="useStandardLigatures:" target="Ady-hI-5gd" id="7uR-wd-Dx6"/>
420
+                                                                    </connections>
421
+                                                                </menuItem>
422
+                                                                <menuItem title="Use None" id="J7y-lM-qPV">
423
+                                                                    <modifierMask key="keyEquivalentModifierMask"/>
424
+                                                                    <connections>
425
+                                                                        <action selector="turnOffLigatures:" target="Ady-hI-5gd" id="iX2-gA-Ilz"/>
426
+                                                                    </connections>
427
+                                                                </menuItem>
428
+                                                                <menuItem title="Use All" id="xQD-1f-W4t">
429
+                                                                    <modifierMask key="keyEquivalentModifierMask"/>
430
+                                                                    <connections>
431
+                                                                        <action selector="useAllLigatures:" target="Ady-hI-5gd" id="KcB-kA-TuK"/>
432
+                                                                    </connections>
433
+                                                                </menuItem>
434
+                                                            </items>
435
+                                                        </menu>
436
+                                                    </menuItem>
437
+                                                    <menuItem title="Baseline" id="OaQ-X3-Vso">
438
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
439
+                                                        <menu key="submenu" title="Baseline" id="ijk-EB-dga">
440
+                                                            <items>
441
+                                                                <menuItem title="Use Default" id="3Om-Ey-2VK">
442
+                                                                    <modifierMask key="keyEquivalentModifierMask"/>
443
+                                                                    <connections>
444
+                                                                        <action selector="unscript:" target="Ady-hI-5gd" id="0vZ-95-Ywn"/>
445
+                                                                    </connections>
446
+                                                                </menuItem>
447
+                                                                <menuItem title="Superscript" id="Rqc-34-cIF">
448
+                                                                    <modifierMask key="keyEquivalentModifierMask"/>
449
+                                                                    <connections>
450
+                                                                        <action selector="superscript:" target="Ady-hI-5gd" id="3qV-fo-wpU"/>
451
+                                                                    </connections>
452
+                                                                </menuItem>
453
+                                                                <menuItem title="Subscript" id="I0S-gh-46l">
454
+                                                                    <modifierMask key="keyEquivalentModifierMask"/>
455
+                                                                    <connections>
456
+                                                                        <action selector="subscript:" target="Ady-hI-5gd" id="Q6W-4W-IGz"/>
457
+                                                                    </connections>
458
+                                                                </menuItem>
459
+                                                                <menuItem title="Raise" id="2h7-ER-AoG">
460
+                                                                    <modifierMask key="keyEquivalentModifierMask"/>
461
+                                                                    <connections>
462
+                                                                        <action selector="raiseBaseline:" target="Ady-hI-5gd" id="4sk-31-7Q9"/>
463
+                                                                    </connections>
464
+                                                                </menuItem>
465
+                                                                <menuItem title="Lower" id="1tx-W0-xDw">
466
+                                                                    <modifierMask key="keyEquivalentModifierMask"/>
467
+                                                                    <connections>
468
+                                                                        <action selector="lowerBaseline:" target="Ady-hI-5gd" id="OF1-bc-KW4"/>
469
+                                                                    </connections>
470
+                                                                </menuItem>
471
+                                                            </items>
472
+                                                        </menu>
473
+                                                    </menuItem>
474
+                                                    <menuItem isSeparatorItem="YES" id="Ndw-q3-faq"/>
475
+                                                    <menuItem title="Show Colors" keyEquivalent="C" id="bgn-CT-cEk">
476
+                                                        <connections>
477
+                                                            <action selector="orderFrontColorPanel:" target="Ady-hI-5gd" id="mSX-Xz-DV3"/>
478
+                                                        </connections>
479
+                                                    </menuItem>
480
+                                                    <menuItem isSeparatorItem="YES" id="iMs-zA-UFJ"/>
481
+                                                    <menuItem title="Copy Style" keyEquivalent="c" id="5Vv-lz-BsD">
482
+                                                        <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
483
+                                                        <connections>
484
+                                                            <action selector="copyFont:" target="Ady-hI-5gd" id="GJO-xA-L4q"/>
485
+                                                        </connections>
486
+                                                    </menuItem>
487
+                                                    <menuItem title="Paste Style" keyEquivalent="v" id="vKC-jM-MkH">
488
+                                                        <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
489
+                                                        <connections>
490
+                                                            <action selector="pasteFont:" target="Ady-hI-5gd" id="JfD-CL-leO"/>
491
+                                                        </connections>
492
+                                                    </menuItem>
493
+                                                </items>
494
+                                            </menu>
495
+                                        </menuItem>
496
+                                        <menuItem title="Text" id="Fal-I4-PZk">
497
+                                            <modifierMask key="keyEquivalentModifierMask"/>
498
+                                            <menu key="submenu" title="Text" id="d9c-me-L2H">
499
+                                                <items>
500
+                                                    <menuItem title="Align Left" keyEquivalent="{" id="ZM1-6Q-yy1">
501
+                                                        <connections>
502
+                                                            <action selector="alignLeft:" target="Ady-hI-5gd" id="zUv-R1-uAa"/>
503
+                                                        </connections>
504
+                                                    </menuItem>
505
+                                                    <menuItem title="Center" keyEquivalent="|" id="VIY-Ag-zcb">
506
+                                                        <connections>
507
+                                                            <action selector="alignCenter:" target="Ady-hI-5gd" id="spX-mk-kcS"/>
508
+                                                        </connections>
509
+                                                    </menuItem>
510
+                                                    <menuItem title="Justify" id="J5U-5w-g23">
511
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
512
+                                                        <connections>
513
+                                                            <action selector="alignJustified:" target="Ady-hI-5gd" id="ljL-7U-jND"/>
514
+                                                        </connections>
515
+                                                    </menuItem>
516
+                                                    <menuItem title="Align Right" keyEquivalent="}" id="wb2-vD-lq4">
517
+                                                        <connections>
518
+                                                            <action selector="alignRight:" target="Ady-hI-5gd" id="r48-bG-YeY"/>
519
+                                                        </connections>
520
+                                                    </menuItem>
521
+                                                    <menuItem isSeparatorItem="YES" id="4s2-GY-VfK"/>
522
+                                                    <menuItem title="Writing Direction" id="H1b-Si-o9J">
523
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
524
+                                                        <menu key="submenu" title="Writing Direction" id="8mr-sm-Yjd">
525
+                                                            <items>
526
+                                                                <menuItem title="Paragraph" enabled="NO" id="ZvO-Gk-QUH">
527
+                                                                    <modifierMask key="keyEquivalentModifierMask"/>
528
+                                                                </menuItem>
529
+                                                                <menuItem title="  Default" id="YGs-j5-SAR">
530
+                                                                    <modifierMask key="keyEquivalentModifierMask"/>
531
+                                                                    <connections>
532
+                                                                        <action selector="makeBaseWritingDirectionNatural:" target="Ady-hI-5gd" id="qtV-5e-UBP"/>
533
+                                                                    </connections>
534
+                                                                </menuItem>
535
+                                                                <menuItem title="  Left to Right" id="Lbh-J2-qVU">
536
+                                                                    <modifierMask key="keyEquivalentModifierMask"/>
537
+                                                                    <connections>
538
+                                                                        <action selector="makeBaseWritingDirectionLeftToRight:" target="Ady-hI-5gd" id="S0X-9S-QSf"/>
539
+                                                                    </connections>
540
+                                                                </menuItem>
541
+                                                                <menuItem title="  Right to Left" id="jFq-tB-4Kx">
542
+                                                                    <modifierMask key="keyEquivalentModifierMask"/>
543
+                                                                    <connections>
544
+                                                                        <action selector="makeBaseWritingDirectionRightToLeft:" target="Ady-hI-5gd" id="5fk-qB-AqJ"/>
545
+                                                                    </connections>
546
+                                                                </menuItem>
547
+                                                                <menuItem isSeparatorItem="YES" id="swp-gr-a21"/>
548
+                                                                <menuItem title="Selection" enabled="NO" id="cqv-fj-IhA">
549
+                                                                    <modifierMask key="keyEquivalentModifierMask"/>
550
+                                                                </menuItem>
551
+                                                                <menuItem title="  Default" id="Nop-cj-93Q">
552
+                                                                    <modifierMask key="keyEquivalentModifierMask"/>
553
+                                                                    <connections>
554
+                                                                        <action selector="makeTextWritingDirectionNatural:" target="Ady-hI-5gd" id="lPI-Se-ZHp"/>
555
+                                                                    </connections>
556
+                                                                </menuItem>
557
+                                                                <menuItem title="  Left to Right" id="BgM-ve-c93">
558
+                                                                    <modifierMask key="keyEquivalentModifierMask"/>
559
+                                                                    <connections>
560
+                                                                        <action selector="makeTextWritingDirectionLeftToRight:" target="Ady-hI-5gd" id="caW-Bv-w94"/>
561
+                                                                    </connections>
562
+                                                                </menuItem>
563
+                                                                <menuItem title="  Right to Left" id="RB4-Sm-HuC">
564
+                                                                    <modifierMask key="keyEquivalentModifierMask"/>
565
+                                                                    <connections>
566
+                                                                        <action selector="makeTextWritingDirectionRightToLeft:" target="Ady-hI-5gd" id="EXD-6r-ZUu"/>
567
+                                                                    </connections>
568
+                                                                </menuItem>
569
+                                                            </items>
570
+                                                        </menu>
571
+                                                    </menuItem>
572
+                                                    <menuItem isSeparatorItem="YES" id="fKy-g9-1gm"/>
573
+                                                    <menuItem title="Show Ruler" id="vLm-3I-IUL">
574
+                                                        <modifierMask key="keyEquivalentModifierMask"/>
575
+                                                        <connections>
576
+                                                            <action selector="toggleRuler:" target="Ady-hI-5gd" id="FOx-HJ-KwY"/>
577
+                                                        </connections>
578
+                                                    </menuItem>
579
+                                                    <menuItem title="Copy Ruler" keyEquivalent="c" id="MkV-Pr-PK5">
580
+                                                        <modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
581
+                                                        <connections>
582
+                                                            <action selector="copyRuler:" target="Ady-hI-5gd" id="71i-fW-3W2"/>
583
+                                                        </connections>
584
+                                                    </menuItem>
585
+                                                    <menuItem title="Paste Ruler" keyEquivalent="v" id="LVM-kO-fVI">
586
+                                                        <modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
587
+                                                        <connections>
588
+                                                            <action selector="pasteRuler:" target="Ady-hI-5gd" id="cSh-wd-qM2"/>
589
+                                                        </connections>
590
+                                                    </menuItem>
591
+                                                </items>
592
+                                            </menu>
593
+                                        </menuItem>
594
+                                    </items>
595
+                                </menu>
596
+                            </menuItem>
597
+                            <menuItem title="View" id="H8h-7b-M4v">
598
+                                <modifierMask key="keyEquivalentModifierMask"/>
599
+                                <menu key="submenu" title="View" id="HyV-fh-RgO">
600
+                                    <items>
601
+                                        <menuItem title="Show Toolbar" keyEquivalent="t" id="snW-S8-Cw5">
602
+                                            <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
603
+                                            <connections>
604
+                                                <action selector="toggleToolbarShown:" target="Ady-hI-5gd" id="BXY-wc-z0C"/>
605
+                                            </connections>
606
+                                        </menuItem>
607
+                                        <menuItem title="Customize Toolbar…" id="1UK-8n-QPP">
608
+                                            <modifierMask key="keyEquivalentModifierMask"/>
609
+                                            <connections>
610
+                                                <action selector="runToolbarCustomizationPalette:" target="Ady-hI-5gd" id="pQI-g3-MTW"/>
611
+                                            </connections>
612
+                                        </menuItem>
613
+                                        <menuItem isSeparatorItem="YES" id="hB3-LF-h0Y"/>
614
+                                        <menuItem title="Show Sidebar" keyEquivalent="s" id="kIP-vf-haE">
615
+                                            <modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
616
+                                            <connections>
617
+                                                <action selector="toggleSidebar:" target="Ady-hI-5gd" id="iwa-gc-5KM"/>
618
+                                            </connections>
619
+                                        </menuItem>
620
+                                        <menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
621
+                                            <modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
622
+                                            <connections>
623
+                                                <action selector="toggleFullScreen:" target="Ady-hI-5gd" id="dU3-MA-1Rq"/>
624
+                                            </connections>
625
+                                        </menuItem>
626
+                                    </items>
627
+                                </menu>
628
+                            </menuItem>
629
+                            <menuItem title="Window" id="aUF-d1-5bR">
630
+                                <modifierMask key="keyEquivalentModifierMask"/>
631
+                                <menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
632
+                                    <items>
633
+                                        <menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
634
+                                            <connections>
635
+                                                <action selector="performMiniaturize:" target="Ady-hI-5gd" id="VwT-WD-YPe"/>
636
+                                            </connections>
637
+                                        </menuItem>
638
+                                        <menuItem title="Zoom" id="R4o-n2-Eq4">
639
+                                            <modifierMask key="keyEquivalentModifierMask"/>
640
+                                            <connections>
641
+                                                <action selector="performZoom:" target="Ady-hI-5gd" id="DIl-cC-cCs"/>
642
+                                            </connections>
643
+                                        </menuItem>
644
+                                        <menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
645
+                                        <menuItem title="Bring All to Front" id="LE2-aR-0XJ">
646
+                                            <modifierMask key="keyEquivalentModifierMask"/>
647
+                                            <connections>
648
+                                                <action selector="arrangeInFront:" target="Ady-hI-5gd" id="DRN-fu-gQh"/>
649
+                                            </connections>
650
+                                        </menuItem>
651
+                                    </items>
652
+                                </menu>
653
+                            </menuItem>
654
+                            <menuItem title="Help" id="wpr-3q-Mcd">
655
+                                <modifierMask key="keyEquivalentModifierMask"/>
656
+                                <menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
657
+                                    <items>
658
+                                        <menuItem title="rncTesterApp-macOS Help" keyEquivalent="?" id="FKE-Sm-Kum">
659
+                                            <connections>
660
+                                                <action selector="showHelp:" target="Ady-hI-5gd" id="y7X-2Q-9no"/>
661
+                                            </connections>
662
+                                        </menuItem>
663
+                                    </items>
664
+                                </menu>
665
+                            </menuItem>
666
+                        </items>
667
+                    </menu>
668
+                    <connections>
669
+                        <outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
670
+                    </connections>
671
+                </application>
672
+                <customObject id="Voe-Tx-rLC" customClass="AppDelegate"/>
673
+                <customObject id="YLy-65-1bz" customClass="NSFontManager"/>
674
+                <customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
675
+            </objects>
676
+            <point key="canvasLocation" x="75" y="0.0"/>
677
+        </scene>
678
+        <!--Window Controller-->
679
+        <scene sceneID="R2V-B0-nI4">
680
+            <objects>
681
+                <windowController id="B8D-0N-5wS" sceneMemberID="viewController">
682
+                    <window key="window" title="example macOS" allowsToolTipsWhenApplicationIsInactive="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA">
683
+                        <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
684
+                        <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
685
+                        <rect key="contentRect" x="196" y="240" width="480" height="270"/>
686
+                        <rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
687
+                        <connections>
688
+                            <outlet property="delegate" destination="B8D-0N-5wS" id="98r-iN-zZc"/>
689
+                        </connections>
690
+                    </window>
691
+                    <connections>
692
+                        <segue destination="XfG-lQ-9wD" kind="relationship" relationship="window.shadowedContentViewController" id="cq2-FE-JQM"/>
693
+                    </connections>
694
+                </windowController>
695
+                <customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
696
+            </objects>
697
+            <point key="canvasLocation" x="75" y="250"/>
698
+        </scene>
699
+        <!--View Controller-->
700
+        <scene sceneID="hIz-AP-VOD">
701
+            <objects>
702
+                <viewController id="XfG-lQ-9wD" customClass="ViewController" sceneMemberID="viewController">
703
+                    <view key="view" wantsLayer="YES" id="m2S-Jp-Qdl">
704
+                        <rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
705
+                        <autoresizingMask key="autoresizingMask"/>
706
+                    </view>
707
+                </viewController>
708
+                <customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
709
+            </objects>
710
+            <point key="canvasLocation" x="75" y="655"/>
711
+        </scene>
712
+    </scenes>
713
+</document>

+ 12
- 0
example/macos/example-macOS/ViewController.h View File

1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
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
+
8
+#import <Cocoa/Cocoa.h>
9
+
10
+@interface ViewController : NSViewController
11
+
12
+@end

+ 29
- 0
example/macos/example-macOS/ViewController.m View File

1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
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
+
8
+#import "ViewController.h"
9
+#import "AppDelegate.h"
10
+
11
+#import <React/RCTRootView.h>
12
+
13
+@implementation ViewController
14
+
15
+- (void)viewDidLoad {
16
+  [super viewDidLoad];
17
+
18
+  RCTBridge *bridge = [((AppDelegate *)[NSApp delegate])bridge];
19
+  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"example" initialProperties:nil];
20
+
21
+  NSView *view = [self view];
22
+
23
+  [view addSubview:rootView];
24
+  [rootView setBackgroundColor:[NSColor windowBackgroundColor]];
25
+  [rootView setFrame:[view bounds]];
26
+  [rootView setAutoresizingMask:(NSViewMinXMargin | NSViewMinXMargin | NSViewMinYMargin | NSViewMaxYMargin | NSViewWidthSizable | NSViewHeightSizable)];
27
+}
28
+
29
+@end

+ 12
- 0
example/macos/example-macOS/main.m View File

1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
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
+
8
+#import <Cocoa/Cocoa.h>
9
+
10
+int main(int argc, const char *argv[]) {
11
+  return NSApplicationMain(argc, argv);
12
+}

+ 1569
- 0
example/macos/example.xcodeproj/project.pbxproj
File diff suppressed because it is too large
View File


+ 10
- 0
example/macos/example.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings View File

1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>BuildSystemType</key>
6
+	<string>Original</string>
7
+	<key>PreviewsEnabled</key>
8
+	<false/>
9
+</dict>
10
+</plist>

+ 92
- 0
example/macos/example.xcodeproj/xcshareddata/xcschemes/example-macOS.xcscheme View File

1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<Scheme
3
+   LastUpgradeVersion = "1120"
4
+   version = "1.3">
5
+   <BuildAction
6
+      parallelizeBuildables = "NO"
7
+      buildImplicitDependencies = "YES">
8
+      <BuildActionEntries>
9
+         <BuildActionEntry
10
+            buildForTesting = "YES"
11
+            buildForRunning = "YES"
12
+            buildForProfiling = "YES"
13
+            buildForArchiving = "YES"
14
+            buildForAnalyzing = "YES">
15
+            <BuildableReference
16
+               BuildableIdentifier = "primary"
17
+               BlueprintIdentifier = "6B857DA21EC51FC600A9D063"
18
+               BuildableName = "libReact.a"
19
+               BlueprintName = "React-macOS"
20
+               ReferencedContainer = "container:../../node_modules/react-native-macos/React/React.xcodeproj">
21
+            </BuildableReference>
22
+         </BuildActionEntry>
23
+         <BuildActionEntry
24
+            buildForTesting = "YES"
25
+            buildForRunning = "YES"
26
+            buildForProfiling = "YES"
27
+            buildForArchiving = "YES"
28
+            buildForAnalyzing = "YES">
29
+            <BuildableReference
30
+               BuildableIdentifier = "primary"
31
+               BlueprintIdentifier = "38C1415723BBE33000902604"
32
+               BuildableName = "example-macOS.app"
33
+               BlueprintName = "example-macOS"
34
+               ReferencedContainer = "container:example.xcodeproj">
35
+            </BuildableReference>
36
+         </BuildActionEntry>
37
+      </BuildActionEntries>
38
+   </BuildAction>
39
+   <TestAction
40
+      buildConfiguration = "Debug"
41
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
42
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
43
+      shouldUseLaunchSchemeArgsEnv = "YES">
44
+      <Testables>
45
+      </Testables>
46
+   </TestAction>
47
+   <LaunchAction
48
+      buildConfiguration = "Debug"
49
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
50
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
51
+      launchStyle = "0"
52
+      useCustomWorkingDirectory = "NO"
53
+      ignoresPersistentStateOnLaunch = "NO"
54
+      debugDocumentVersioning = "YES"
55
+      debugServiceExtension = "internal"
56
+      allowLocationSimulation = "YES">
57
+      <BuildableProductRunnable
58
+         runnableDebuggingMode = "0">
59
+         <BuildableReference
60
+            BuildableIdentifier = "primary"
61
+            BlueprintIdentifier = "38C1415723BBE33000902604"
62
+            BuildableName = "example-macOS.app"
63
+            BlueprintName = "example-macOS"
64
+            ReferencedContainer = "container:example.xcodeproj">
65
+         </BuildableReference>
66
+      </BuildableProductRunnable>
67
+   </LaunchAction>
68
+   <ProfileAction
69
+      buildConfiguration = "Release"
70
+      shouldUseLaunchSchemeArgsEnv = "YES"
71
+      savedToolIdentifier = ""
72
+      useCustomWorkingDirectory = "NO"
73
+      debugDocumentVersioning = "YES">
74
+      <BuildableProductRunnable
75
+         runnableDebuggingMode = "0">
76
+         <BuildableReference
77
+            BuildableIdentifier = "primary"
78
+            BlueprintIdentifier = "38C1415723BBE33000902604"
79
+            BuildableName = "example-macOS.app"
80
+            BlueprintName = "example-macOS"
81
+            ReferencedContainer = "container:example.xcodeproj">
82
+         </BuildableReference>
83
+      </BuildableProductRunnable>
84
+   </ProfileAction>
85
+   <AnalyzeAction
86
+      buildConfiguration = "Debug">
87
+   </AnalyzeAction>
88
+   <ArchiveAction
89
+      buildConfiguration = "Release"
90
+      revealArchiveInOrganizer = "YES">
91
+   </ArchiveAction>
92
+</Scheme>

+ 92
- 0
example/macos/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme View File

1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<Scheme
3
+   LastUpgradeVersion = "1120"
4
+   version = "1.3">
5
+   <BuildAction
6
+      parallelizeBuildables = "NO"
7
+      buildImplicitDependencies = "YES">
8
+      <BuildActionEntries>
9
+         <BuildActionEntry
10
+            buildForTesting = "YES"
11
+            buildForRunning = "YES"
12
+            buildForProfiling = "YES"
13
+            buildForArchiving = "YES"
14
+            buildForAnalyzing = "YES">
15
+            <BuildableReference
16
+               BuildableIdentifier = "primary"
17
+               BlueprintIdentifier = "83CBBA2D1A601D0E00E9B192"
18
+               BuildableName = "libReact.a"
19
+               BlueprintName = "React"
20
+               ReferencedContainer = "container:../../node_modules/react-native-macos/React/React.xcodeproj">
21
+            </BuildableReference>
22
+         </BuildActionEntry>
23
+         <BuildActionEntry
24
+            buildForTesting = "YES"
25
+            buildForRunning = "YES"
26
+            buildForProfiling = "YES"
27
+            buildForArchiving = "YES"
28
+            buildForAnalyzing = "YES">
29
+            <BuildableReference
30
+               BuildableIdentifier = "primary"
31
+               BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
32
+               BuildableName = "example.app"
33
+               BlueprintName = "example"
34
+               ReferencedContainer = "container:example.xcodeproj">
35
+            </BuildableReference>
36
+         </BuildActionEntry>
37
+      </BuildActionEntries>
38
+   </BuildAction>
39
+   <TestAction
40
+      buildConfiguration = "Debug"
41
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
42
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
43
+      shouldUseLaunchSchemeArgsEnv = "YES">
44
+      <Testables>
45
+      </Testables>
46
+   </TestAction>
47
+   <LaunchAction
48
+      buildConfiguration = "Debug"
49
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
50
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
51
+      launchStyle = "0"
52
+      useCustomWorkingDirectory = "NO"
53
+      ignoresPersistentStateOnLaunch = "NO"
54
+      debugDocumentVersioning = "YES"
55
+      debugServiceExtension = "internal"
56
+      allowLocationSimulation = "YES">
57
+      <BuildableProductRunnable
58
+         runnableDebuggingMode = "0">
59
+         <BuildableReference
60
+            BuildableIdentifier = "primary"
61
+            BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
62
+            BuildableName = "example.app"
63
+            BlueprintName = "example"
64
+            ReferencedContainer = "container:example.xcodeproj">
65
+         </BuildableReference>
66
+      </BuildableProductRunnable>
67
+   </LaunchAction>
68
+   <ProfileAction
69
+      buildConfiguration = "Release"
70
+      shouldUseLaunchSchemeArgsEnv = "YES"
71
+      savedToolIdentifier = ""
72
+      useCustomWorkingDirectory = "NO"
73
+      debugDocumentVersioning = "YES">
74
+      <BuildableProductRunnable
75
+         runnableDebuggingMode = "0">
76
+         <BuildableReference
77
+            BuildableIdentifier = "primary"
78
+            BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
79
+            BuildableName = "example.app"
80
+            BlueprintName = "example"
81
+            ReferencedContainer = "container:example.xcodeproj">
82
+         </BuildableReference>
83
+      </BuildableProductRunnable>
84
+   </ProfileAction>
85
+   <AnalyzeAction
86
+      buildConfiguration = "Debug">
87
+   </AnalyzeAction>
88
+   <ArchiveAction
89
+      buildConfiguration = "Release"
90
+      revealArchiveInOrganizer = "YES">
91
+   </ArchiveAction>
92
+</Scheme>

+ 15
- 0
example/macos/example/AppDelegate.h View File

1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
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
+
8
+#import <React/RCTBridgeDelegate.h>
9
+#import <UIKit/UIKit.h>
10
+
11
+@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate>
12
+
13
+@property (nonatomic, strong) UIWindow *window;
14
+
15
+@end

+ 42
- 0
example/macos/example/AppDelegate.m View File

1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
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
+
8
+#import "AppDelegate.h"
9
+
10
+#import <React/RCTBridge.h>
11
+#import <React/RCTBundleURLProvider.h>
12
+#import <React/RCTRootView.h>
13
+
14
+@implementation AppDelegate
15
+
16
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
17
+{
18
+  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
19
+  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
20
+                                                   moduleName:@"example"
21
+                                            initialProperties:nil];
22
+
23
+  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
24
+
25
+  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
26
+  UIViewController *rootViewController = [UIViewController new];
27
+  rootViewController.view = rootView;
28
+  self.window.rootViewController = rootViewController;
29
+  [self.window makeKeyAndVisible];
30
+  return YES;
31
+}
32
+
33
+- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
34
+{
35
+#if DEBUG
36
+  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"example/index" fallbackResource:nil];
37
+#else
38
+  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
39
+#endif
40
+}
41
+
42
+@end

+ 42
- 0
example/macos/example/Base.lproj/LaunchScreen.xib View File

1
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7702" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
3
+    <dependencies>
4
+        <deployment identifier="iOS"/>
5
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7701"/>
6
+        <capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
7
+    </dependencies>
8
+    <objects>
9
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
10
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
11
+        <view contentMode="scaleToFill" id="iN0-l3-epB">
12
+            <rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
13
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
14
+            <subviews>
15
+                <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Powered by React Native" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
16
+                    <rect key="frame" x="20" y="439" width="441" height="21"/>
17
+                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
18
+                    <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
19
+                    <nil key="highlightedColor"/>
20
+                </label>
21
+                <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="example" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
22
+                    <rect key="frame" x="20" y="140" width="441" height="43"/>
23
+                    <fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
24
+                    <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
25
+                    <nil key="highlightedColor"/>
26
+                </label>
27
+            </subviews>
28
+            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
29
+            <constraints>
30
+                <constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
31
+                <constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
32
+                <constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
33
+                <constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
34
+                <constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
35
+                <constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
36
+            </constraints>
37
+            <nil key="simulatedStatusBarMetrics"/>
38
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
39
+            <point key="canvasLocation" x="548" y="455"/>
40
+        </view>
41
+    </objects>
42
+</document>

+ 53
- 0
example/macos/example/Images.xcassets/AppIcon.appiconset/Contents.json View File

1
+{
2
+  "images" : [
3
+    {
4
+      "idiom" : "iphone",
5
+      "size" : "20x20",
6
+      "scale" : "2x"
7
+    },
8
+    {
9
+      "idiom" : "iphone",
10
+      "size" : "20x20",
11
+      "scale" : "3x"
12
+    },
13
+    {
14
+      "idiom" : "iphone",
15
+      "size" : "29x29",
16
+      "scale" : "2x"
17
+    },
18
+    {
19
+      "idiom" : "iphone",
20
+      "size" : "29x29",
21
+      "scale" : "3x"
22
+    },
23
+    {
24
+      "idiom" : "iphone",
25
+      "size" : "40x40",
26
+      "scale" : "2x"
27
+    },
28
+    {
29
+      "idiom" : "iphone",
30
+      "size" : "40x40",
31
+      "scale" : "3x"
32
+    },
33
+    {
34
+      "idiom" : "iphone",
35
+      "size" : "60x60",
36
+      "scale" : "2x"
37
+    },
38
+    {
39
+      "idiom" : "iphone",
40
+      "size" : "60x60",
41
+      "scale" : "3x"
42
+    },
43
+    {
44
+      "idiom" : "ios-marketing",
45
+      "size" : "1024x1024",
46
+      "scale" : "1x"
47
+    }
48
+  ],
49
+  "info" : {
50
+    "version" : 1,
51
+    "author" : "xcode"
52
+  }
53
+}

+ 6
- 0
example/macos/example/Images.xcassets/Contents.json View File

1
+{
2
+  "info" : {
3
+    "version" : 1,
4
+    "author" : "xcode"
5
+  }
6
+}

+ 57
- 0
example/macos/example/Info.plist View File

1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>CFBundleDevelopmentRegion</key>
6
+	<string>en</string>
7
+	<key>CFBundleDisplayName</key>
8
+	<string>example</string>
9
+	<key>CFBundleExecutable</key>
10
+	<string>$(EXECUTABLE_NAME)</string>
11
+	<key>CFBundleIdentifier</key>
12
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
13
+	<key>CFBundleInfoDictionaryVersion</key>
14
+	<string>6.0</string>
15
+	<key>CFBundleName</key>
16
+	<string>$(PRODUCT_NAME)</string>
17
+	<key>CFBundlePackageType</key>
18
+	<string>APPL</string>
19
+	<key>CFBundleShortVersionString</key>
20
+	<string>1.0</string>
21
+	<key>CFBundleSignature</key>
22
+	<string>????</string>
23
+	<key>CFBundleVersion</key>
24
+	<string>1</string>
25
+	<key>LSRequiresIPhoneOS</key>
26
+	<true/>
27
+	<key>NSAppTransportSecurity</key>
28
+	<dict>
29
+		<key>NSAllowsArbitraryLoads</key>
30
+		<true/>
31
+		<key>NSExceptionDomains</key>
32
+		<dict>
33
+			<key>localhost</key>
34
+			<dict>
35
+				<key>NSExceptionAllowsInsecureHTTPLoads</key>
36
+				<true/>
37
+			</dict>
38
+		</dict>
39
+	</dict>
40
+	<key>NSLocationWhenInUseUsageDescription</key>
41
+	<string></string>
42
+	<key>UILaunchStoryboardName</key>
43
+	<string>LaunchScreen</string>
44
+	<key>UIRequiredDeviceCapabilities</key>
45
+	<array>
46
+		<string>armv7</string>
47
+	</array>
48
+	<key>UISupportedInterfaceOrientations</key>
49
+	<array>
50
+		<string>UIInterfaceOrientationPortrait</string>
51
+		<string>UIInterfaceOrientationLandscapeLeft</string>
52
+		<string>UIInterfaceOrientationLandscapeRight</string>
53
+	</array>
54
+	<key>UIViewControllerBasedStatusBarAppearance</key>
55
+	<false/>
56
+</dict>
57
+</plist>

+ 16
- 0
example/macos/example/main.m View File

1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
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
+
8
+#import <UIKit/UIKit.h>
9
+
10
+#import "AppDelegate.h"
11
+
12
+int main(int argc, char * argv[]) {
13
+  @autoreleasepool {
14
+    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15
+  }
16
+}

+ 168
- 38
ios/RNCWebView.m View File

9
 #import <React/RCTConvert.h>
9
 #import <React/RCTConvert.h>
10
 #import <React/RCTAutoInsetsProtocol.h>
10
 #import <React/RCTAutoInsetsProtocol.h>
11
 #import "RNCWKProcessPoolManager.h"
11
 #import "RNCWKProcessPoolManager.h"
12
+#if !TARGET_OS_OSX
12
 #import <UIKit/UIKit.h>
13
 #import <UIKit/UIKit.h>
14
+#else
15
+#import <React/RCTUIKit.h>
16
+#endif // !TARGET_OS_OSX
13
 
17
 
14
 #import "objc/runtime.h"
18
 #import "objc/runtime.h"
15
 
19
 
19
 static NSURLCredential* clientAuthenticationCredential;
23
 static NSURLCredential* clientAuthenticationCredential;
20
 static NSDictionary* customCertificatesForHost;
24
 static NSDictionary* customCertificatesForHost;
21
 
25
 
26
+#if !TARGET_OS_OSX
22
 // runtime trick to remove WKWebView keyboard default toolbar
27
 // runtime trick to remove WKWebView keyboard default toolbar
23
 // see: http://stackoverflow.com/questions/19033292/ios-7-uiwebview-keyboard-issue/19042279#19042279
28
 // see: http://stackoverflow.com/questions/19033292/ios-7-uiwebview-keyboard-issue/19042279#19042279
24
 @interface _SwizzleHelperWK : UIView
29
 @interface _SwizzleHelperWK : UIView
39
     return nil;
44
     return nil;
40
 }
45
 }
41
 @end
46
 @end
47
+#endif // !TARGET_OS_OSX
42
 
48
 
43
-@interface RNCWebView () <WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler, UIScrollViewDelegate, RCTAutoInsetsProtocol>
49
+#if TARGET_OS_OSX
50
+@interface RNCWKWebView : WKWebView
51
+@end
52
+@implementation RNCWKWebView
53
+- (void)scrollWheel:(NSEvent *)theEvent {
54
+  RNCWebView *rncWebView = (RNCWebView *)[self superview];
55
+  RCTAssert([rncWebView isKindOfClass:[rncWebView class]], @"superview must be an RNCWebView");
56
+  if (![rncWebView scrollEnabled]) {
57
+    [[self nextResponder] scrollWheel:theEvent];
58
+    return;
59
+  }
60
+  [super scrollWheel:theEvent];
61
+}
62
+@end
63
+#endif // TARGET_OS_OSX
64
+
65
+@interface RNCWebView () <WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler,
66
+#if !TARGET_OS_OSX
67
+    UIScrollViewDelegate,
68
+#endif // !TARGET_OS_OSX
69
+    RCTAutoInsetsProtocol>
44
 @property (nonatomic, copy) RCTDirectEventBlock onLoadingStart;
70
 @property (nonatomic, copy) RCTDirectEventBlock onLoadingStart;
45
 @property (nonatomic, copy) RCTDirectEventBlock onLoadingFinish;
71
 @property (nonatomic, copy) RCTDirectEventBlock onLoadingFinish;
46
 @property (nonatomic, copy) RCTDirectEventBlock onLoadingError;
72
 @property (nonatomic, copy) RCTDirectEventBlock onLoadingError;
50
 @property (nonatomic, copy) RCTDirectEventBlock onMessage;
76
 @property (nonatomic, copy) RCTDirectEventBlock onMessage;
51
 @property (nonatomic, copy) RCTDirectEventBlock onScroll;
77
 @property (nonatomic, copy) RCTDirectEventBlock onScroll;
52
 @property (nonatomic, copy) RCTDirectEventBlock onContentProcessDidTerminate;
78
 @property (nonatomic, copy) RCTDirectEventBlock onContentProcessDidTerminate;
79
+#if !TARGET_OS_OSX
53
 @property (nonatomic, copy) WKWebView *webView;
80
 @property (nonatomic, copy) WKWebView *webView;
81
+#else
82
+@property (nonatomic, copy) RNCWKWebView *webView;
83
+#endif // !TARGET_OS_OSX
54
 @end
84
 @end
55
 
85
 
56
 @implementation RNCWebView
86
 @implementation RNCWebView
57
 {
87
 {
88
+#if !TARGET_OS_OSX
58
   UIColor * _savedBackgroundColor;
89
   UIColor * _savedBackgroundColor;
90
+#else
91
+  RCTUIColor * _savedBackgroundColor;
92
+#endif // !TARGET_OS_OSX
59
   BOOL _savedHideKeyboardAccessoryView;
93
   BOOL _savedHideKeyboardAccessoryView;
60
   BOOL _savedKeyboardDisplayRequiresUserAction;
94
   BOOL _savedKeyboardDisplayRequiresUserAction;
61
 
95
 
62
   // Workaround for StatusBar appearance bug for iOS 12
96
   // Workaround for StatusBar appearance bug for iOS 12
63
   // https://github.com/react-native-community/react-native-webview/issues/62
97
   // https://github.com/react-native-community/react-native-webview/issues/62
64
   BOOL _isFullScreenVideoOpen;
98
   BOOL _isFullScreenVideoOpen;
99
+#if !TARGET_OS_OSX
65
   UIStatusBarStyle _savedStatusBarStyle;
100
   UIStatusBarStyle _savedStatusBarStyle;
101
+#endif // !TARGET_OS_OSX
66
   BOOL _savedStatusBarHidden;
102
   BOOL _savedStatusBarHidden;
67
 
103
 
68
 #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
104
 #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
73
 - (instancetype)initWithFrame:(CGRect)frame
109
 - (instancetype)initWithFrame:(CGRect)frame
74
 {
110
 {
75
   if ((self = [super initWithFrame:frame])) {
111
   if ((self = [super initWithFrame:frame])) {
112
+    #if !TARGET_OS_OSX
76
     super.backgroundColor = [UIColor clearColor];
113
     super.backgroundColor = [UIColor clearColor];
114
+    #else
115
+    super.backgroundColor = [RCTUIColor clearColor];
116
+    #endif // !TARGET_OS_OSX
77
     _bounces = YES;
117
     _bounces = YES;
78
     _scrollEnabled = YES;
118
     _scrollEnabled = YES;
79
     _showsHorizontalScrollIndicator = YES;
119
     _showsHorizontalScrollIndicator = YES;
82
     _automaticallyAdjustContentInsets = YES;
122
     _automaticallyAdjustContentInsets = YES;
83
     _contentInset = UIEdgeInsetsZero;
123
     _contentInset = UIEdgeInsetsZero;
84
     _savedKeyboardDisplayRequiresUserAction = YES;
124
     _savedKeyboardDisplayRequiresUserAction = YES;
125
+#if !TARGET_OS_OSX
85
     _savedStatusBarStyle = RCTSharedApplication().statusBarStyle;
126
     _savedStatusBarStyle = RCTSharedApplication().statusBarStyle;
86
     _savedStatusBarHidden = RCTSharedApplication().statusBarHidden;
127
     _savedStatusBarHidden = RCTSharedApplication().statusBarHidden;
128
+#endif // !TARGET_OS_OSX
87
 
129
 
88
 #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
130
 #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
89
     _savedContentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
131
     _savedContentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
90
 #endif
132
 #endif
91
   }
133
   }
92
 
134
 
135
+#if !TARGET_OS_OSX
93
   if (@available(iOS 12.0, *)) {
136
   if (@available(iOS 12.0, *)) {
94
     // Workaround for a keyboard dismissal bug present in iOS 12
137
     // Workaround for a keyboard dismissal bug present in iOS 12
95
     // https://openradar.appspot.com/radar?id=5018321736957952
138
     // https://openradar.appspot.com/radar?id=5018321736957952
114
                                                    name:UIWindowDidBecomeHiddenNotification
157
                                                    name:UIWindowDidBecomeHiddenNotification
115
                                                  object:nil];
158
                                                  object:nil];
116
   }
159
   }
117
-
160
+#endif // !TARGET_OS_OSX
118
   return self;
161
   return self;
119
 }
162
 }
120
 
163
 
208
     }
251
     }
209
   }
252
   }
210
 
253
 
254
+#if !TARGET_OS_OSX
211
   wkWebViewConfig.allowsInlineMediaPlayback = _allowsInlineMediaPlayback;
255
   wkWebViewConfig.allowsInlineMediaPlayback = _allowsInlineMediaPlayback;
212
 #if WEBKIT_IOS_10_APIS_AVAILABLE
256
 #if WEBKIT_IOS_10_APIS_AVAILABLE
213
   wkWebViewConfig.mediaTypesRequiringUserActionForPlayback = _mediaPlaybackRequiresUserAction
257
   wkWebViewConfig.mediaTypesRequiringUserActionForPlayback = _mediaPlaybackRequiresUserAction
217
 #else
261
 #else
218
   wkWebViewConfig.mediaPlaybackRequiresUserAction = _mediaPlaybackRequiresUserAction;
262
   wkWebViewConfig.mediaPlaybackRequiresUserAction = _mediaPlaybackRequiresUserAction;
219
 #endif
263
 #endif
264
+#endif // !TARGET_OS_OSX
220
 
265
 
221
   if (_applicationNameForUserAgent) {
266
   if (_applicationNameForUserAgent) {
222
       wkWebViewConfig.applicationNameForUserAgent = [NSString stringWithFormat:@"%@ %@", wkWebViewConfig.applicationNameForUserAgent, _applicationNameForUserAgent];
267
       wkWebViewConfig.applicationNameForUserAgent = [NSString stringWithFormat:@"%@ %@", wkWebViewConfig.applicationNameForUserAgent, _applicationNameForUserAgent];
291
 {
336
 {
292
   if (self.window != nil && _webView == nil) {
337
   if (self.window != nil && _webView == nil) {
293
     WKWebViewConfiguration *wkWebViewConfig = [self setUpWkWebViewConfig];
338
     WKWebViewConfiguration *wkWebViewConfig = [self setUpWkWebViewConfig];
339
+#if !TARGET_OS_OSX
294
     _webView = [[WKWebView alloc] initWithFrame:self.bounds configuration: wkWebViewConfig];
340
     _webView = [[WKWebView alloc] initWithFrame:self.bounds configuration: wkWebViewConfig];
341
+#else
342
+    _webView = [[RNCWKWebView alloc] initWithFrame:self.bounds configuration: wkWebViewConfig];
343
+#endif // !TARGET_OS_OSX
344
+
295
     [self setBackgroundColor: _savedBackgroundColor];
345
     [self setBackgroundColor: _savedBackgroundColor];
346
+#if !TARGET_OS_OSX
296
     _webView.scrollView.delegate = self;
347
     _webView.scrollView.delegate = self;
348
+#endif // !TARGET_OS_OSX
297
     _webView.UIDelegate = self;
349
     _webView.UIDelegate = self;
298
     _webView.navigationDelegate = self;
350
     _webView.navigationDelegate = self;
351
+#if !TARGET_OS_OSX
299
     _webView.scrollView.scrollEnabled = _scrollEnabled;
352
     _webView.scrollView.scrollEnabled = _scrollEnabled;
300
     _webView.scrollView.pagingEnabled = _pagingEnabled;
353
     _webView.scrollView.pagingEnabled = _pagingEnabled;
301
     _webView.scrollView.bounces = _bounces;
354
     _webView.scrollView.bounces = _bounces;
302
     _webView.scrollView.showsHorizontalScrollIndicator = _showsHorizontalScrollIndicator;
355
     _webView.scrollView.showsHorizontalScrollIndicator = _showsHorizontalScrollIndicator;
303
     _webView.scrollView.showsVerticalScrollIndicator = _showsVerticalScrollIndicator;
356
     _webView.scrollView.showsVerticalScrollIndicator = _showsVerticalScrollIndicator;
304
     _webView.scrollView.directionalLockEnabled = _directionalLockEnabled;
357
     _webView.scrollView.directionalLockEnabled = _directionalLockEnabled;
358
+#endif // !TARGET_OS_OSX
305
     _webView.allowsLinkPreview = _allowsLinkPreview;
359
     _webView.allowsLinkPreview = _allowsLinkPreview;
306
     [_webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
360
     [_webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
307
     _webView.allowsBackForwardNavigationGestures = _allowsBackForwardNavigationGestures;
361
     _webView.allowsBackForwardNavigationGestures = _allowsBackForwardNavigationGestures;
335
         [_webView.configuration.userContentController removeScriptMessageHandlerForName:MessageHandlerName];
389
         [_webView.configuration.userContentController removeScriptMessageHandlerForName:MessageHandlerName];
336
         [_webView removeObserver:self forKeyPath:@"estimatedProgress"];
390
         [_webView removeObserver:self forKeyPath:@"estimatedProgress"];
337
         [_webView removeFromSuperview];
391
         [_webView removeFromSuperview];
392
+#if !TARGET_OS_OSX
338
         _webView.scrollView.delegate = nil;
393
         _webView.scrollView.delegate = nil;
394
+#endif // !TARGET_OS_OSX
339
         _webView = nil;
395
         _webView = nil;
340
     }
396
     }
341
 
397
 
342
     [super removeFromSuperview];
398
     [super removeFromSuperview];
343
 }
399
 }
344
 
400
 
401
+#if !TARGET_OS_OSX
345
 -(void)showFullScreenVideoStatusBars
402
 -(void)showFullScreenVideoStatusBars
346
 {
403
 {
347
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
404
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
389
       }];
446
       }];
390
     }
447
     }
391
 }
448
 }
449
+#endif // !TARGET_OS_OSX
392
 
450
 
393
 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
451
 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
394
     if ([keyPath isEqual:@"estimatedProgress"] && object == self.webView) {
452
     if ([keyPath isEqual:@"estimatedProgress"] && object == self.webView) {
402
     }
460
     }
403
 }
461
 }
404
 
462
 
463
+#if !TARGET_OS_OSX
405
 - (void)setBackgroundColor:(UIColor *)backgroundColor
464
 - (void)setBackgroundColor:(UIColor *)backgroundColor
465
+#else
466
+- (void)setBackgroundColor:(RCTUIColor *)backgroundColor
467
+#endif // !TARGET_OS_OSX
406
 {
468
 {
407
   _savedBackgroundColor = backgroundColor;
469
   _savedBackgroundColor = backgroundColor;
408
   if (_webView == nil) {
470
   if (_webView == nil) {
410
   }
472
   }
411
 
473
 
412
   CGFloat alpha = CGColorGetAlpha(backgroundColor.CGColor);
474
   CGFloat alpha = CGColorGetAlpha(backgroundColor.CGColor);
413
-  self.opaque = _webView.opaque = (alpha == 1.0);
475
+  BOOL opaque = (alpha == 1.0);
476
+#if !TARGET_OS_OSX
477
+  self.opaque = _webView.opaque = opaque;
414
   _webView.scrollView.backgroundColor = backgroundColor;
478
   _webView.scrollView.backgroundColor = backgroundColor;
415
   _webView.backgroundColor = backgroundColor;
479
   _webView.backgroundColor = backgroundColor;
480
+#else
481
+  // https://stackoverflow.com/questions/40007753/macos-wkwebview-background-transparency
482
+  NSOperatingSystemVersion version = { 10, 12, 0 };
483
+  if ([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:version]) {
484
+    [_webView setValue:@(opaque) forKey: @"drawsBackground"];
485
+  } else {
486
+    [_webView setValue:@(!opaque) forKey: @"drawsTransparentBackground"];
487
+  }
488
+#endif // !TARGET_OS_OSX
416
 }
489
 }
417
 
490
 
418
 #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
491
 #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
475
   }
548
   }
476
 }
549
 }
477
 
550
 
551
+#if !TARGET_OS_OSX
478
 - (void)setContentInset:(UIEdgeInsets)contentInset
552
 - (void)setContentInset:(UIEdgeInsets)contentInset
479
 {
553
 {
480
   _contentInset = contentInset;
554
   _contentInset = contentInset;
489
                     withScrollView:_webView.scrollView
563
                     withScrollView:_webView.scrollView
490
                       updateOffset:YES];
564
                       updateOffset:YES];
491
 }
565
 }
566
+#endif // !TARGET_OS_OSX
492
 
567
 
493
 - (void)visitSource
568
 - (void)visitSource
494
 {
569
 {
525
     }
600
     }
526
 }
601
 }
527
 
602
 
603
+#if !TARGET_OS_OSX
528
 -(void)setKeyboardDisplayRequiresUserAction:(BOOL)keyboardDisplayRequiresUserAction
604
 -(void)setKeyboardDisplayRequiresUserAction:(BOOL)keyboardDisplayRequiresUserAction
529
 {
605
 {
530
     if (_webView == nil) {
606
     if (_webView == nil) {
630
     object_setClass(subview, newClass);
706
     object_setClass(subview, newClass);
631
 }
707
 }
632
 
708
 
709
+// UIScrollViewDelegate method
633
 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
710
 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
634
 {
711
 {
635
   scrollView.decelerationRate = _decelerationRate;
712
   scrollView.decelerationRate = _decelerationRate;
636
 }
713
 }
714
+#endif // !TARGET_OS_OSX
637
 
715
 
638
 - (void)setScrollEnabled:(BOOL)scrollEnabled
716
 - (void)setScrollEnabled:(BOOL)scrollEnabled
639
 {
717
 {
640
   _scrollEnabled = scrollEnabled;
718
   _scrollEnabled = scrollEnabled;
719
+#if !TARGET_OS_OSX
641
   _webView.scrollView.scrollEnabled = scrollEnabled;
720
   _webView.scrollView.scrollEnabled = scrollEnabled;
721
+#endif // !TARGET_OS_OSX
642
 }
722
 }
643
 
723
 
724
+#if !TARGET_OS_OSX
725
+// UIScrollViewDelegate method
644
 - (void)scrollViewDidScroll:(UIScrollView *)scrollView
726
 - (void)scrollViewDidScroll:(UIScrollView *)scrollView
645
 {
727
 {
646
   // Don't allow scrolling the scrollView.
728
   // Don't allow scrolling the scrollView.
690
     _showsVerticalScrollIndicator = showsVerticalScrollIndicator;
772
     _showsVerticalScrollIndicator = showsVerticalScrollIndicator;
691
     _webView.scrollView.showsVerticalScrollIndicator = showsVerticalScrollIndicator;
773
     _webView.scrollView.showsVerticalScrollIndicator = showsVerticalScrollIndicator;
692
 }
774
 }
775
+#endif // !TARGET_OS_OSX
693
 
776
 
694
 - (void)postMessage:(NSString *)message
777
 - (void)postMessage:(NSString *)message
695
 {
778
 {
707
 
790
 
708
   // Ensure webview takes the position and dimensions of RNCWebView
791
   // Ensure webview takes the position and dimensions of RNCWebView
709
   _webView.frame = self.bounds;
792
   _webView.frame = self.bounds;
793
+#if !TARGET_OS_OSX
710
   _webView.scrollView.contentInset = _contentInset;
794
   _webView.scrollView.contentInset = _contentInset;
795
+#endif // !TARGET_OS_OSX
711
 }
796
 }
712
 
797
 
713
 - (NSMutableDictionary<NSString *, id> *)baseEvent
798
 - (NSMutableDictionary<NSString *, id> *)baseEvent
769
 #pragma mark - WKNavigationDelegate methods
854
 #pragma mark - WKNavigationDelegate methods
770
 
855
 
771
 /**
856
 /**
772
-* alert
773
-*/
857
+ * alert
858
+ */
774
 - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
859
 - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
775
 {
860
 {
776
-    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:message preferredStyle:UIAlertControllerStyleAlert];
777
-    [alert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
778
-        completionHandler();
779
-    }]];
780
-    [[self topViewController] presentViewController:alert animated:YES completion:NULL];
781
-
861
+#if !TARGET_OS_OSX
862
+  UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:message preferredStyle:UIAlertControllerStyleAlert];
863
+  [alert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
864
+    completionHandler();
865
+  }]];
866
+  [[self topViewController] presentViewController:alert animated:YES completion:NULL];
867
+#else
868
+  NSAlert *alert = [[NSAlert alloc] init];
869
+  [alert setMessageText:message];
870
+  [alert beginSheetModalForWindow:[NSApp keyWindow] completionHandler:^(__unused NSModalResponse response){
871
+    completionHandler();
872
+  }];
873
+#endif // !TARGET_OS_OSX
782
 }
874
 }
783
 
875
 
784
 /**
876
 /**
785
-* confirm
786
-*/
877
+ * confirm
878
+ */
787
 - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler{
879
 - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler{
788
-    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:message preferredStyle:UIAlertControllerStyleAlert];
789
-    [alert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
790
-        completionHandler(YES);
791
-    }]];
792
-    [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
793
-        completionHandler(NO);
794
-    }]];
795
-    [[self topViewController] presentViewController:alert animated:YES completion:NULL];
880
+#if !TARGET_OS_OSX
881
+  UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:message preferredStyle:UIAlertControllerStyleAlert];
882
+  [alert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
883
+    completionHandler(YES);
884
+  }]];
885
+  [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
886
+    completionHandler(NO);
887
+  }]];
888
+  [[self topViewController] presentViewController:alert animated:YES completion:NULL];
889
+#else
890
+  NSAlert *alert = [[NSAlert alloc] init];
891
+  [alert setMessageText:message];
892
+  [alert addButtonWithTitle:NSLocalizedString(@"OK", @"OK button")];
893
+  [alert addButtonWithTitle:NSLocalizedString(@"Cancel", @"Cancel button")];
894
+  void (^callbacksHandlers)(NSModalResponse response) = ^void(NSModalResponse response) {
895
+    completionHandler(response == NSAlertFirstButtonReturn);
896
+  };
897
+  [alert beginSheetModalForWindow:[NSApp keyWindow] completionHandler:callbacksHandlers];
898
+#endif // !TARGET_OS_OSX
796
 }
899
 }
797
 
900
 
798
 /**
901
 /**
799
-* prompt
800
-*/
902
+ * prompt
903
+ */
801
 - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString *))completionHandler{
904
 - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString *))completionHandler{
802
-    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:prompt preferredStyle:UIAlertControllerStyleAlert];
803
-    [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
804
-        textField.text = defaultText;
805
-    }];
806
-    UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
807
-        completionHandler([[alert.textFields lastObject] text]);
808
-    }];
809
-    [alert addAction:okAction];
810
-    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
811
-        completionHandler(nil);
812
-    }];
813
-    [alert addAction:cancelAction];
814
-    alert.preferredAction = okAction;
815
-    [[self topViewController] presentViewController:alert animated:YES completion:NULL];
905
+#if !TARGET_OS_OSX
906
+  UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:prompt preferredStyle:UIAlertControllerStyleAlert];
907
+  [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
908
+    textField.text = defaultText;
909
+  }];
910
+  UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
911
+    completionHandler([[alert.textFields lastObject] text]);
912
+  }];
913
+  [alert addAction:okAction];
914
+  UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
915
+    completionHandler(nil);
916
+  }];
917
+  [alert addAction:cancelAction];
918
+  alert.preferredAction = okAction;
919
+  [[self topViewController] presentViewController:alert animated:YES completion:NULL];
920
+#else
921
+  NSAlert *alert = [[NSAlert alloc] init];
922
+  [alert setMessageText:prompt];
923
+
924
+  const NSRect RCTSingleTextFieldFrame = NSMakeRect(0.0, 0.0, 275.0, 22.0);
925
+  NSTextField *textField = [[NSTextField alloc] initWithFrame:RCTSingleTextFieldFrame];
926
+  textField.cell.scrollable = YES;
927
+  if (@available(macOS 10.11, *)) {
928
+    textField.maximumNumberOfLines = 1;
929
+  }
930
+  textField.stringValue = defaultText;
931
+  [alert setAccessoryView:textField];
932
+
933
+  [alert addButtonWithTitle:NSLocalizedString(@"OK", @"OK button")];
934
+  [alert addButtonWithTitle:NSLocalizedString(@"Cancel", @"Cancel button")];
935
+  [alert beginSheetModalForWindow:[NSApp keyWindow] completionHandler:^(NSModalResponse response) {
936
+    if (response == NSAlertFirstButtonReturn) {
937
+      completionHandler([textField stringValue]);
938
+    } else {
939
+      completionHandler(nil);
940
+    }
941
+  }];
942
+#endif // !TARGET_OS_OSX
816
 }
943
 }
817
 
944
 
945
+#if !TARGET_OS_OSX
818
 /**
946
 /**
819
  * topViewController
947
  * topViewController
820
  */
948
  */
853
   }
981
   }
854
   return window;
982
   return window;
855
 }
983
 }
856
-
984
+#endif // !TARGET_OS_OSX
857
 
985
 
858
 /**
986
 /**
859
  * Decides whether to allow or cancel a navigation.
987
  * Decides whether to allow or cancel a navigation.
1058
   [_webView stopLoading];
1186
   [_webView stopLoading];
1059
 }
1187
 }
1060
 
1188
 
1189
+#if !TARGET_OS_OSX
1061
 - (void)setBounces:(BOOL)bounces
1190
 - (void)setBounces:(BOOL)bounces
1062
 {
1191
 {
1063
   _bounces = bounces;
1192
   _bounces = bounces;
1064
   _webView.scrollView.bounces = bounces;
1193
   _webView.scrollView.bounces = bounces;
1065
 }
1194
 }
1195
+#endif // !TARGET_OS_OSX
1066
 
1196
 
1067
 - (NSURLRequest *)requestForSource:(id)json {
1197
 - (NSURLRequest *)requestForSource:(id)json {
1068
   NSURLRequest *request = [RCTConvert NSURLRequest:self.source];
1198
   NSURLRequest *request = [RCTConvert NSURLRequest:self.source];

+ 6
- 0
ios/RNCWebViewManager.m View File

22
 
22
 
23
 RCT_EXPORT_MODULE()
23
 RCT_EXPORT_MODULE()
24
 
24
 
25
+#if !TARGET_OS_OSX
25
 - (UIView *)view
26
 - (UIView *)view
27
+#else
28
+- (RCTUIView *)view
29
+#endif // !TARGET_OS_OSX
26
 {
30
 {
27
   RNCWebView *webView = [RNCWebView new];
31
   RNCWebView *webView = [RNCWebView new];
28
   webView.delegate = self;
32
   webView.delegate = self;
97
     view.sharedCookiesEnabled = json == nil ? false : [RCTConvert BOOL: json];
101
     view.sharedCookiesEnabled = json == nil ? false : [RCTConvert BOOL: json];
98
 }
102
 }
99
 
103
 
104
+#if !TARGET_OS_OSX
100
 RCT_CUSTOM_VIEW_PROPERTY(decelerationRate, CGFloat, RNCWebView) {
105
 RCT_CUSTOM_VIEW_PROPERTY(decelerationRate, CGFloat, RNCWebView) {
101
   view.decelerationRate = json == nil ? UIScrollViewDecelerationRateNormal : [RCTConvert CGFloat: json];
106
   view.decelerationRate = json == nil ? UIScrollViewDecelerationRateNormal : [RCTConvert CGFloat: json];
102
 }
107
 }
108
+#endif // !TARGET_OS_OSX
103
 
109
 
104
 RCT_CUSTOM_VIEW_PROPERTY(directionalLockEnabled, BOOL, RNCWebView) {
110
 RCT_CUSTOM_VIEW_PROPERTY(directionalLockEnabled, BOOL, RNCWebView) {
105
     view.directionalLockEnabled = json == nil ? true : [RCTConvert BOOL: json];
111
     view.directionalLockEnabled = json == nil ? true : [RCTConvert BOOL: json];

+ 363
- 0
macos/RNCWebView.xcodeproj/project.pbxproj View File

1
+// !$*UTF8*$!
2
+{
3
+	archiveVersion = 1;
4
+	classes = {
5
+	};
6
+	objectVersion = 46;
7
+	objects = {
8
+
9
+/* Begin PBXBuildFile section */
10
+		3515965E21A3C86000623BFA /* ../ios/RNCWKProcessPoolManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3515965D21A3C86000623BFA /* ../ios/RNCWKProcessPoolManager.m */; };
11
+		38116A2B23BBECB700ACE311 /* ../ios/RNCWebViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E91B351B21446E6C00F9801F /* ../ios/RNCWebViewManager.m */; };
12
+		38116A2C23BBECB700ACE311 /* ../ios/RNCWebView.m in Sources */ = {isa = PBXBuildFile; fileRef = E91B351C21446E6C00F9801F /* ../ios/RNCWebView.m */; };
13
+		38116A2D23BBECB700ACE311 /* ../ios/RNCWKProcessPoolManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3515965D21A3C86000623BFA /* ../ios/RNCWKProcessPoolManager.m */; };
14
+		E91B351D21446E6C00F9801F /* ../ios/RNCWebViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E91B351B21446E6C00F9801F /* ../ios/RNCWebViewManager.m */; };
15
+		E91B351E21446E6C00F9801F /* ../ios/RNCWebView.m in Sources */ = {isa = PBXBuildFile; fileRef = E91B351C21446E6C00F9801F /* ../ios/RNCWebView.m */; };
16
+/* End PBXBuildFile section */
17
+
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
+		};
28
+		58B511D91A9E6C8500147676 /* CopyFiles */ = {
29
+			isa = PBXCopyFilesBuildPhase;
30
+			buildActionMask = 2147483647;
31
+			dstPath = "include/$(PRODUCT_NAME)";
32
+			dstSubfolderSpec = 16;
33
+			files = (
34
+			);
35
+			runOnlyForDeploymentPostprocessing = 0;
36
+		};
37
+/* End PBXCopyFilesBuildPhase section */
38
+
39
+/* Begin PBXFileReference section */
40
+		134814201AA4EA6300B7C361 /* libRNCWebView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNCWebView.a; sourceTree = BUILT_PRODUCTS_DIR; };
41
+		3515965D21A3C86000623BFA /* ../ios/RNCWKProcessPoolManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ../ios/RNCWKProcessPoolManager.m; sourceTree = "<group>"; };
42
+		3515965F21A3C87E00623BFA /* ../ios/RNCWKProcessPoolManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ../ios/RNCWKProcessPoolManager.h; sourceTree = "<group>"; };
43
+		38116A3323BBECB700ACE311 /* libRNCWebView-macOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libRNCWebView-macOS.a"; sourceTree = BUILT_PRODUCTS_DIR; };
44
+		E91B351921446E6C00F9801F /* ../ios/RNCWebViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ../ios/RNCWebViewManager.h; sourceTree = "<group>"; };
45
+		E91B351A21446E6C00F9801F /* ../ios/RNCWebView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ../ios/RNCWebView.h; sourceTree = "<group>"; };
46
+		E91B351B21446E6C00F9801F /* ../ios/RNCWebViewManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ../ios/RNCWebViewManager.m; sourceTree = "<group>"; };
47
+		E91B351C21446E6C00F9801F /* ../ios/RNCWebView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ../ios/RNCWebView.m; sourceTree = "<group>"; };
48
+/* End PBXFileReference section */
49
+
50
+/* Begin PBXFrameworksBuildPhase section */
51
+		38116A2E23BBECB700ACE311 /* Frameworks */ = {
52
+			isa = PBXFrameworksBuildPhase;
53
+			buildActionMask = 2147483647;
54
+			files = (
55
+			);
56
+			runOnlyForDeploymentPostprocessing = 0;
57
+		};
58
+		58B511D81A9E6C8500147676 /* Frameworks */ = {
59
+			isa = PBXFrameworksBuildPhase;
60
+			buildActionMask = 2147483647;
61
+			files = (
62
+			);
63
+			runOnlyForDeploymentPostprocessing = 0;
64
+		};
65
+/* End PBXFrameworksBuildPhase section */
66
+
67
+/* Begin PBXGroup section */
68
+		134814211AA4EA7D00B7C361 /* Products */ = {
69
+			isa = PBXGroup;
70
+			children = (
71
+				134814201AA4EA6300B7C361 /* libRNCWebView.a */,
72
+			);
73
+			name = Products;
74
+			sourceTree = "<group>";
75
+		};
76
+		58B511D21A9E6C8500147676 = {
77
+			isa = PBXGroup;
78
+			children = (
79
+				E91B351A21446E6C00F9801F /* ../ios/RNCWebView.h */,
80
+				E91B351C21446E6C00F9801F /* ../ios/RNCWebView.m */,
81
+				E91B351921446E6C00F9801F /* ../ios/RNCWebViewManager.h */,
82
+				E91B351B21446E6C00F9801F /* ../ios/RNCWebViewManager.m */,
83
+				3515965D21A3C86000623BFA /* ../ios/RNCWKProcessPoolManager.m */,
84
+				3515965F21A3C87E00623BFA /* ../ios/RNCWKProcessPoolManager.h */,
85
+				134814211AA4EA7D00B7C361 /* Products */,
86
+				38116A3323BBECB700ACE311 /* libRNCWebView-macOS.a */,
87
+			);
88
+			sourceTree = "<group>";
89
+		};
90
+/* End PBXGroup section */
91
+
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
+		};
110
+		58B511DA1A9E6C8500147676 /* RNCWebView */ = {
111
+			isa = PBXNativeTarget;
112
+			buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNCWebView" */;
113
+			buildPhases = (
114
+				58B511D71A9E6C8500147676 /* Sources */,
115
+				58B511D81A9E6C8500147676 /* Frameworks */,
116
+				58B511D91A9E6C8500147676 /* CopyFiles */,
117
+			);
118
+			buildRules = (
119
+			);
120
+			dependencies = (
121
+			);
122
+			name = RNCWebView;
123
+			productName = RCTDataManager;
124
+			productReference = 134814201AA4EA6300B7C361 /* libRNCWebView.a */;
125
+			productType = "com.apple.product-type.library.static";
126
+		};
127
+/* End PBXNativeTarget section */
128
+
129
+/* Begin PBXProject section */
130
+		58B511D31A9E6C8500147676 /* Project object */ = {
131
+			isa = PBXProject;
132
+			attributes = {
133
+				LastUpgradeCheck = 0830;
134
+				ORGANIZATIONNAME = Facebook;
135
+				TargetAttributes = {
136
+					58B511DA1A9E6C8500147676 = {
137
+						CreatedOnToolsVersion = 6.1.1;
138
+					};
139
+				};
140
+			};
141
+			buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNCWebView" */;
142
+			compatibilityVersion = "Xcode 3.2";
143
+			developmentRegion = en;
144
+			hasScannedForEncodings = 0;
145
+			knownRegions = (
146
+				en,
147
+			);
148
+			mainGroup = 58B511D21A9E6C8500147676;
149
+			productRefGroup = 58B511D21A9E6C8500147676;
150
+			projectDirPath = "";
151
+			projectRoot = "";
152
+			targets = (
153
+				58B511DA1A9E6C8500147676 /* RNCWebView */,
154
+				38116A2923BBECB700ACE311 /* RNCWebView-macOS */,
155
+			);
156
+		};
157
+/* End PBXProject section */
158
+
159
+/* Begin PBXSourcesBuildPhase section */
160
+		38116A2A23BBECB700ACE311 /* Sources */ = {
161
+			isa = PBXSourcesBuildPhase;
162
+			buildActionMask = 2147483647;
163
+			files = (
164
+				38116A2B23BBECB700ACE311 /* ../ios/RNCWebViewManager.m in Sources */,
165
+				38116A2C23BBECB700ACE311 /* ../ios/RNCWebView.m in Sources */,
166
+				38116A2D23BBECB700ACE311 /* ../ios/RNCWKProcessPoolManager.m in Sources */,
167
+			);
168
+			runOnlyForDeploymentPostprocessing = 0;
169
+		};
170
+		58B511D71A9E6C8500147676 /* Sources */ = {
171
+			isa = PBXSourcesBuildPhase;
172
+			buildActionMask = 2147483647;
173
+			files = (
174
+				E91B351D21446E6C00F9801F /* ../ios/RNCWebViewManager.m in Sources */,
175
+				E91B351E21446E6C00F9801F /* ../ios/RNCWebView.m in Sources */,
176
+				3515965E21A3C86000623BFA /* ../ios/RNCWKProcessPoolManager.m in Sources */,
177
+			);
178
+			runOnlyForDeploymentPostprocessing = 0;
179
+		};
180
+/* End PBXSourcesBuildPhase section */
181
+
182
+/* Begin XCBuildConfiguration section */
183
+		38116A3123BBECB700ACE311 /* Debug */ = {
184
+			isa = XCBuildConfiguration;
185
+			buildSettings = {
186
+				FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../node_modules/react-native-macos/React/**";
187
+				HEADER_SEARCH_PATHS = (
188
+					"$(inherited)",
189
+					"$(SRCROOT)/../node_modules/react-native-macos/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-macos/React/**";
204
+				HEADER_SEARCH_PATHS = (
205
+					"$(inherited)",
206
+					"$(SRCROOT)/../node_modules/react-native-macos/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
+		};
217
+		58B511ED1A9E6C8500147676 /* Debug */ = {
218
+			isa = XCBuildConfiguration;
219
+			buildSettings = {
220
+				ALWAYS_SEARCH_USER_PATHS = NO;
221
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
222
+				CLANG_CXX_LIBRARY = "libc++";
223
+				CLANG_ENABLE_MODULES = YES;
224
+				CLANG_ENABLE_OBJC_ARC = YES;
225
+				CLANG_WARN_BOOL_CONVERSION = YES;
226
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
227
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
228
+				CLANG_WARN_EMPTY_BODY = YES;
229
+				CLANG_WARN_ENUM_CONVERSION = YES;
230
+				CLANG_WARN_INFINITE_RECURSION = YES;
231
+				CLANG_WARN_INT_CONVERSION = YES;
232
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
233
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
234
+				CLANG_WARN_UNREACHABLE_CODE = YES;
235
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
236
+				COPY_PHASE_STRIP = NO;
237
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
238
+				ENABLE_TESTABILITY = YES;
239
+				GCC_C_LANGUAGE_STANDARD = gnu99;
240
+				GCC_DYNAMIC_NO_PIC = NO;
241
+				GCC_NO_COMMON_BLOCKS = YES;
242
+				GCC_OPTIMIZATION_LEVEL = 0;
243
+				GCC_PREPROCESSOR_DEFINITIONS = (
244
+					"DEBUG=1",
245
+					"$(inherited)",
246
+				);
247
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
248
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
249
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
250
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
251
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
252
+				GCC_WARN_UNUSED_FUNCTION = YES;
253
+				GCC_WARN_UNUSED_VARIABLE = YES;
254
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
255
+				MTL_ENABLE_DEBUG_INFO = YES;
256
+				ONLY_ACTIVE_ARCH = YES;
257
+				SDKROOT = iphoneos;
258
+			};
259
+			name = Debug;
260
+		};
261
+		58B511EE1A9E6C8500147676 /* Release */ = {
262
+			isa = XCBuildConfiguration;
263
+			buildSettings = {
264
+				ALWAYS_SEARCH_USER_PATHS = NO;
265
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
266
+				CLANG_CXX_LIBRARY = "libc++";
267
+				CLANG_ENABLE_MODULES = YES;
268
+				CLANG_ENABLE_OBJC_ARC = YES;
269
+				CLANG_WARN_BOOL_CONVERSION = YES;
270
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
271
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
272
+				CLANG_WARN_EMPTY_BODY = YES;
273
+				CLANG_WARN_ENUM_CONVERSION = YES;
274
+				CLANG_WARN_INFINITE_RECURSION = YES;
275
+				CLANG_WARN_INT_CONVERSION = YES;
276
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
277
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
278
+				CLANG_WARN_UNREACHABLE_CODE = YES;
279
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
280
+				COPY_PHASE_STRIP = YES;
281
+				ENABLE_NS_ASSERTIONS = NO;
282
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
283
+				GCC_C_LANGUAGE_STANDARD = gnu99;
284
+				GCC_NO_COMMON_BLOCKS = YES;
285
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
286
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
287
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
288
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
289
+				GCC_WARN_UNUSED_FUNCTION = YES;
290
+				GCC_WARN_UNUSED_VARIABLE = YES;
291
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
292
+				MTL_ENABLE_DEBUG_INFO = NO;
293
+				SDKROOT = iphoneos;
294
+				VALIDATE_PRODUCT = YES;
295
+			};
296
+			name = Release;
297
+		};
298
+		58B511F01A9E6C8500147676 /* Debug */ = {
299
+			isa = XCBuildConfiguration;
300
+			buildSettings = {
301
+				FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../node_modules/react-native-macos/React/**";
302
+				HEADER_SEARCH_PATHS = (
303
+					"$(inherited)",
304
+					"$(SRCROOT)/../node_modules/react-native-macos/React/**",
305
+					"$(SRCROOT)/../../react-native-macos/React/**",
306
+				);
307
+				LIBRARY_SEARCH_PATHS = "$(inherited)";
308
+				OTHER_LDFLAGS = "-ObjC";
309
+				PRODUCT_NAME = RNCWebView;
310
+				SKIP_INSTALL = YES;
311
+			};
312
+			name = Debug;
313
+		};
314
+		58B511F11A9E6C8500147676 /* Release */ = {
315
+			isa = XCBuildConfiguration;
316
+			buildSettings = {
317
+				FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../node_modules/react-native-macos/React/**";
318
+				HEADER_SEARCH_PATHS = (
319
+					"$(inherited)",
320
+					"$(SRCROOT)/../node_modules/react-native-macos/React/**",
321
+					"$(SRCROOT)/../../react-native-macos/React/**",
322
+				);
323
+				LIBRARY_SEARCH_PATHS = "$(inherited)";
324
+				OTHER_LDFLAGS = "-ObjC";
325
+				PRODUCT_NAME = RNCWebView;
326
+				SKIP_INSTALL = YES;
327
+			};
328
+			name = Release;
329
+		};
330
+/* End XCBuildConfiguration section */
331
+
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
+		};
342
+		58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNCWebView" */ = {
343
+			isa = XCConfigurationList;
344
+			buildConfigurations = (
345
+				58B511ED1A9E6C8500147676 /* Debug */,
346
+				58B511EE1A9E6C8500147676 /* Release */,
347
+			);
348
+			defaultConfigurationIsVisible = 0;
349
+			defaultConfigurationName = Release;
350
+		};
351
+		58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNCWebView" */ = {
352
+			isa = XCConfigurationList;
353
+			buildConfigurations = (
354
+				58B511F01A9E6C8500147676 /* Debug */,
355
+				58B511F11A9E6C8500147676 /* Release */,
356
+			);
357
+			defaultConfigurationIsVisible = 0;
358
+			defaultConfigurationName = Release;
359
+		};
360
+/* End XCConfigurationList section */
361
+	};
362
+	rootObject = 58B511D31A9E6C8500147676 /* Project object */;
363
+}

+ 12
- 0
metro.config.js View File

1
+/**
2
+ * This cli config is needed for development purposes, e.g. for running
3
+ * integration tests during local development or on CI services.
4
+ */
5
+
6
+const blacklist = require('metro-config/src/defaults/blacklist');
7
+
8
+module.exports = {
9
+  resolver: {
10
+    blacklistRE: blacklist([/node_modules\/react-native-macos\/.*/])
11
+  },
12
+};

+ 19
- 0
metro.config.macos.js View File

1
+/**
2
+ * This cli config is needed for development purposes, e.g. for running
3
+ * integration tests during local development or on CI services.
4
+ */
5
+
6
+const path = require('path');
7
+const blacklist = require('metro-config/src/defaults/blacklist');
8
+
9
+const rnmPath = path.resolve(__dirname, 'node_modules/react-native-macos');
10
+
11
+module.exports = {
12
+  resolver: {
13
+    extraNodeModules: {
14
+      'react-native': rnmPath,
15
+    },
16
+    platforms: ['macos', 'ios', 'android'],
17
+    blacklistRE: blacklist([/node_modules\/react-native\/.*/])
18
+  },
19
+};

+ 8
- 3
package.json View File

1
 {
1
 {
2
   "name": "react-native-webview",
2
   "name": "react-native-webview",
3
-  "description": "React Native WebView component for iOS, Android, and Windows 10 (coming soon)",
3
+  "description": "React Native WebView component for iOS, Android, and macOS",
4
   "main": "index.js",
4
   "main": "index.js",
5
   "typings": "index.d.ts",
5
   "typings": "index.d.ts",
6
   "author": "Jamon Holmgren <jamon@infinite.red>",
6
   "author": "Jamon Holmgren <jamon@infinite.red>",
8
     "Thibault Malbranche <malbranche.thibault@gmail.com>"
8
     "Thibault Malbranche <malbranche.thibault@gmail.com>"
9
   ],
9
   ],
10
   "license": "MIT",
10
   "license": "MIT",
11
-  "version": "8.0.4",
11
+  "version": "8.1.1",
12
   "homepage": "https://github.com/react-native-community/react-native-webview#readme",
12
   "homepage": "https://github.com/react-native-community/react-native-webview#readme",
13
   "scripts": {
13
   "scripts": {
14
     "start": "node node_modules/react-native/local-cli/cli.js start",
14
     "start": "node node_modules/react-native/local-cli/cli.js start",
15
     "start:android": "react-native run-android --root example/",
15
     "start:android": "react-native run-android --root example/",
16
     "start:ios": "react-native run-ios --project-path example/ios --scheme example",
16
     "start:ios": "react-native run-ios --project-path example/ios --scheme example",
17
+    "start:macos": "node node_modules/react-native-macos/local-cli/cli.js start --use-react-native-macos",
17
     "ci": "CI=true && yarn lint && yarn test",
18
     "ci": "CI=true && yarn lint && yarn test",
18
     "ci:publish": "yarn semantic-release",
19
     "ci:publish": "yarn semantic-release",
19
     "lint": "yarn tsc --noEmit && yarn eslint ./src --ext .ts,.tsx",
20
     "lint": "yarn tsc --noEmit && yarn eslint ./src --ext .ts,.tsx",
36
   "devDependencies": {
37
   "devDependencies": {
37
     "@babel/core": "7.4.5",
38
     "@babel/core": "7.4.5",
38
     "@babel/runtime": "7.4.5",
39
     "@babel/runtime": "7.4.5",
40
+    "@react-native-community/cli-platform-ios": "^3.0.0",
41
+    "@react-native-community/cli-platform-android": "^3.0.0",
39
     "@semantic-release/git": "7.0.16",
42
     "@semantic-release/git": "7.0.16",
40
     "@types/invariant": "^2.2.30",
43
     "@types/invariant": "^2.2.30",
41
     "@types/jest": "24.0.18",
44
     "@types/jest": "24.0.18",
57
     "metro-react-native-babel-preset": "0.54.1",
60
     "metro-react-native-babel-preset": "0.54.1",
58
     "react": "16.9.0",
61
     "react": "16.9.0",
59
     "react-native": "0.61.5",
62
     "react-native": "0.61.5",
63
+    "react-native-macos": "0.60.0-microsoft.49",
60
     "semantic-release": "15.13.24",
64
     "semantic-release": "15.13.24",
61
     "typescript": "3.6.2"
65
     "typescript": "3.6.2"
62
   },
66
   },
67
   "files": [
71
   "files": [
68
     "android",
72
     "android",
69
     "ios",
73
     "ios",
74
+    "macos",
70
     "lib",
75
     "lib",
71
     "index.js",
76
     "index.js",
72
     "index.d.ts",
77
     "index.d.ts",
73
     "react-native-webview.podspec"
78
     "react-native-webview.podspec"
74
   ]
79
   ]
75
-}
80
+}

+ 26
- 0
react-native.config.js View File

1
+/**
2
+ * This cli config is needed for the coexistance of react-native and other
3
+ * out-of-tree implementations such react-native-macos.
4
+ * The following issue is tracked by
5
+ * https://github.com/react-native-community/discussions-and-proposals/issues/182
6
+ *
7
+ * The work-around involves having a metro.config.js for each out-of-tree
8
+ * platform, i.e. metro.config.js for react-native and 
9
+ * metro.config.macos.js for react-native-macos.
10
+ * This react-native.config.js looks for a --use-react-native-macos
11
+ * switch and when present pushes --config=metro.config.macos.js 
12
+ * and specifies reactNativePath: 'node_modules/react-native-macos'.
13
+ * The metro.config.js has to blacklist 'node_modules/react-native-macos', 
14
+ * and conversely metro.config.macos.js has to blacklist 'node_modules/react-native'.
15
+ */
16
+'use strict';
17
+
18
+const macSwitch = '--use-react-native-macos';
19
+
20
+if (process.argv.includes(macSwitch)) {
21
+  process.argv = process.argv.filter(arg => arg !== macSwitch);
22
+  process.argv.push('--config=metro.config.macos.js');
23
+  module.exports = {
24
+    reactNativePath: 'node_modules/react-native-macos',
25
+  };
26
+}

+ 347
- 0
src/WebView.macos.tsx View File

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

+ 175
- 14
src/WebViewTypes.ts View File

28
 
28
 
29
 export type RNCWebViewUIManagerAndroid = RNCWebViewUIManager<WebViewCommands | AndroidWebViewCommands>
29
 export type RNCWebViewUIManagerAndroid = RNCWebViewUIManager<WebViewCommands | AndroidWebViewCommands>
30
 export type RNCWebViewUIManagerIOS = RNCWebViewUIManager<WebViewCommands>
30
 export type RNCWebViewUIManagerIOS = RNCWebViewUIManager<WebViewCommands>
31
-
31
+export type RNCWebViewUIManagerMacOS = RNCWebViewUIManager<WebViewCommands>
32
 
32
 
33
 
33
 
34
 type WebViewState = 'IDLE' | 'LOADING' | 'ERROR';
34
 type WebViewState = 'IDLE' | 'LOADING' | 'ERROR';
57
   typeof NativeWebViewIOSComponent;
57
   typeof NativeWebViewIOSComponent;
58
 export class NativeWebViewIOS extends NativeWebViewIOSBase {}
58
 export class NativeWebViewIOS extends NativeWebViewIOSBase {}
59
 
59
 
60
+// eslint-disable-next-line react/prefer-stateless-function
61
+declare class NativeWebViewMacOSComponent extends Component<
62
+  MacOSNativeWebViewProps
63
+> {}
64
+declare const NativeWebViewMacOSBase: Constructor<NativeMethodsMixin> &
65
+  typeof NativeWebViewMacOSComponent;
66
+export class NativeWebViewMacOS extends NativeWebViewMacOSBase {}
67
+
60
 // eslint-disable-next-line react/prefer-stateless-function
68
 // eslint-disable-next-line react/prefer-stateless-function
61
 declare class NativeWebViewAndroidComponent extends Component<
69
 declare class NativeWebViewAndroidComponent extends Component<
62
   AndroidNativeWebViewProps
70
   AndroidNativeWebViewProps
104
 
112
 
105
 export interface WebViewError extends WebViewNativeEvent {
113
 export interface WebViewError extends WebViewNativeEvent {
106
   /**
114
   /**
107
-   * `domain` is only used on iOS
115
+   * `domain` is only used on iOS and macOS
108
    */
116
    */
109
   domain?: string;
117
   domain?: string;
110
   code: number;
118
   code: number;
195
   /**
203
   /**
196
    * The native component used to render the WebView.
204
    * The native component used to render the WebView.
197
    */
205
    */
198
-  component?: typeof NativeWebViewIOS | typeof NativeWebViewAndroid;
206
+  component?: typeof NativeWebViewIOS | typeof NativeWebViewMacOS | typeof NativeWebViewAndroid;
199
   /**
207
   /**
200
    * Set props directly on the native component WebView. Enables custom props which the
208
    * Set props directly on the native component WebView. Enables custom props which the
201
    * original WebView doesn't pass through.
209
    * original WebView doesn't pass through.
203
   props?: Object;
211
   props?: Object;
204
   /**
212
   /**
205
    * Set the ViewManager to use for communication with the native side.
213
    * Set the ViewManager to use for communication with the native side.
206
-   * @platform ios
214
+   * @platform ios, macos
207
    */
215
    */
208
   viewManager?: ViewManager;
216
   viewManager?: ViewManager;
209
 }
217
 }
258
   urlPrefixesForDefaultIntent?: readonly string[];
266
   urlPrefixesForDefaultIntent?: readonly string[];
259
 }
267
 }
260
 
268
 
269
+export enum ContentInsetAdjustmentBehavior {
270
+  automatic = 'automatic',
271
+  scrollableAxes = 'scrollableAxes',
272
+  never = 'never',
273
+  always = 'always'
274
+};
275
+
261
 export interface IOSNativeWebViewProps extends CommonNativeWebViewProps {
276
 export interface IOSNativeWebViewProps extends CommonNativeWebViewProps {
262
   allowingReadAccessToURL?: string;
277
   allowingReadAccessToURL?: string;
263
   allowsBackForwardNavigationGestures?: boolean;
278
   allowsBackForwardNavigationGestures?: boolean;
266
   automaticallyAdjustContentInsets?: boolean;
281
   automaticallyAdjustContentInsets?: boolean;
267
   bounces?: boolean;
282
   bounces?: boolean;
268
   contentInset?: ContentInsetProp;
283
   contentInset?: ContentInsetProp;
269
-  contentInsetAdjustmentBehavior?:
270
-    | 'automatic'
271
-    | 'scrollableAxes'
272
-    | 'never'
273
-    | 'always';
284
+  contentInsetAdjustmentBehavior?: ContentInsetAdjustmentBehavior;
274
   dataDetectorTypes?: DataDetectorTypes | readonly DataDetectorTypes[];
285
   dataDetectorTypes?: DataDetectorTypes | readonly DataDetectorTypes[];
275
   decelerationRate?: number;
286
   decelerationRate?: number;
276
   directionalLockEnabled?: boolean;
287
   directionalLockEnabled?: boolean;
281
   onContentProcessDidTerminate?: (event: WebViewTerminatedEvent) => void;
292
   onContentProcessDidTerminate?: (event: WebViewTerminatedEvent) => void;
282
 }
293
 }
283
 
294
 
295
+export interface MacOSNativeWebViewProps extends CommonNativeWebViewProps {
296
+  allowingReadAccessToURL?: string;
297
+  allowsBackForwardNavigationGestures?: boolean;
298
+  allowsInlineMediaPlayback?: boolean;
299
+  allowsLinkPreview?: boolean;
300
+  automaticallyAdjustContentInsets?: boolean;
301
+  bounces?: boolean;
302
+  contentInset?: ContentInsetProp;
303
+  contentInsetAdjustmentBehavior?: ContentInsetAdjustmentBehavior;
304
+  directionalLockEnabled?: boolean;
305
+  hideKeyboardAccessoryView?: boolean;
306
+  pagingEnabled?: boolean;
307
+  scrollEnabled?: boolean;
308
+  useSharedProcessPool?: boolean;
309
+  onContentProcessDidTerminate?: (event: WebViewTerminatedEvent) => void;
310
+}
311
+
284
 export interface IOSWebViewProps extends WebViewSharedProps {
312
 export interface IOSWebViewProps extends WebViewSharedProps {
285
   /**
313
   /**
286
    * Does not store any data within the lifetime of the WebView.
314
    * Does not store any data within the lifetime of the WebView.
335
    * content area of the scroll view. The default value of this property is
363
    * content area of the scroll view. The default value of this property is
336
    * "never". Available on iOS 11 and later.
364
    * "never". Available on iOS 11 and later.
337
    */
365
    */
338
-  contentInsetAdjustmentBehavior?:
339
-    | 'automatic'
340
-    | 'scrollableAxes'
341
-    | 'never'
342
-    | 'always';
366
+  contentInsetAdjustmentBehavior?: ContentInsetAdjustmentBehavior;
343
 
367
 
344
   /**
368
   /**
345
    * The amount by which the web view content is inset from the edges of
369
    * The amount by which the web view content is inset from the edges of
460
   onContentProcessDidTerminate?: (event: WebViewTerminatedEvent) => void;
484
   onContentProcessDidTerminate?: (event: WebViewTerminatedEvent) => void;
461
 }
485
 }
462
 
486
 
487
+export interface MacOSWebViewProps extends WebViewSharedProps {
488
+  /**
489
+   * Does not store any data within the lifetime of the WebView.
490
+   */
491
+  incognito?: boolean;
492
+
493
+  /**
494
+   * Boolean value that determines whether the web view bounces
495
+   * when it reaches the edge of the content. The default value is `true`.
496
+   * @platform macos
497
+   */
498
+  bounces?: boolean;
499
+
500
+  /**
501
+   * Boolean value that determines whether scrolling is enabled in the
502
+   * `WebView`. The default value is `true`.
503
+   * @platform macos
504
+   */
505
+  scrollEnabled?: boolean;
506
+
507
+  /**
508
+   * If the value of this property is true, the scroll view stops on multiples
509
+   * of the scroll view’s bounds when the user scrolls.
510
+   * The default value is false.
511
+   * @platform macos
512
+   */
513
+  pagingEnabled?: boolean;
514
+
515
+  /**
516
+   * Controls whether to adjust the content inset for web views that are
517
+   * placed behind a navigation bar, tab bar, or toolbar. The default value
518
+   * is `true`.
519
+   * @platform macos
520
+   */
521
+  automaticallyAdjustContentInsets?: boolean;
522
+
523
+  /**
524
+   * This property specifies how the safe area insets are used to modify the
525
+   * content area of the scroll view. The default value of this property is
526
+   * "never". Available on iOS 11 and later.
527
+   */
528
+  contentInsetAdjustmentBehavior?: ContentInsetAdjustmentBehavior;
529
+
530
+  /**
531
+   * The amount by which the web view content is inset from the edges of
532
+   * the scroll view. Defaults to {top: 0, left: 0, bottom: 0, right: 0}.
533
+   * @platform macos
534
+   */
535
+  contentInset?: ContentInsetProp;
536
+
537
+  /**
538
+   * Boolean that determines whether HTML5 videos play inline or use the
539
+   * native full-screen controller. The default value is `false`.
540
+   *
541
+   * **NOTE** : In order for video to play inline, not only does this
542
+   * property need to be set to `true`, but the video element in the HTML
543
+   * document must also include the `webkit-playsinline` attribute.
544
+   * @platform macos
545
+   */
546
+  allowsInlineMediaPlayback?: boolean;
547
+  /**
548
+   * Hide the accessory view when the keyboard is open. Default is false to be
549
+   * backward compatible.
550
+   */
551
+  hideKeyboardAccessoryView?: boolean;
552
+  /**
553
+   * A Boolean value indicating whether horizontal swipe gestures will trigger
554
+   * back-forward list navigations.
555
+   */
556
+  allowsBackForwardNavigationGestures?: boolean;
557
+  /**
558
+   * A Boolean value indicating whether WebKit WebView should be created using a shared
559
+   * process pool, enabling WebViews to share cookies and localStorage between each other.
560
+   * Default is true but can be set to false for backwards compatibility.
561
+   * @platform macos
562
+   */
563
+  useSharedProcessPool?: boolean;
564
+
565
+  /**
566
+   * The custom user agent string.
567
+   */
568
+  userAgent?: string;
569
+
570
+  /**
571
+   * A Boolean value that determines whether pressing on a link
572
+   * displays a preview of the destination for the link.
573
+   *
574
+   * This property is available on devices that support Force Touch trackpad.
575
+   * @platform macos
576
+   */
577
+  allowsLinkPreview?: boolean;
578
+
579
+  /**
580
+   * Set true if shared cookies from HTTPCookieStorage should used for every load request.
581
+   * The default value is `false`.
582
+   * @platform macos
583
+   */
584
+  sharedCookiesEnabled?: boolean;
585
+
586
+  /**
587
+   * A Boolean value that determines whether scrolling is disabled in a particular direction.
588
+   * The default value is `true`.
589
+   * @platform macos
590
+   */
591
+  directionalLockEnabled?: boolean;
592
+
593
+  /**
594
+   * A Boolean value indicating whether web content can programmatically display the keyboard.
595
+   *
596
+   * When this property is set to true, the user must explicitly tap the elements in the
597
+   * web view to display the keyboard (or other relevant input view) for that element.
598
+   * When set to false, a focus event on an element causes the input view to be displayed
599
+   * and associated with that element automatically.
600
+   *
601
+   * The default value is `true`.
602
+   * @platform macos
603
+   */
604
+  keyboardDisplayRequiresUserAction?: boolean;
605
+
606
+  /**
607
+   * A String value that indicates which URLs the WebView's file can then
608
+   * reference in scripts, AJAX requests, and CSS imports. This is only used
609
+   * for WebViews that are loaded with a source.uri set to a `'file://'` URL.
610
+   *
611
+   * If not provided, the default is to only allow read access to the URL
612
+   * provided in source.uri itself.
613
+   * @platform macos
614
+   */
615
+  allowingReadAccessToURL?: string;
616
+
617
+  /**
618
+   * Function that is invoked when the WebKit WebView content process gets terminated.
619
+   * @platform macos
620
+   */
621
+  onContentProcessDidTerminate?: (event: WebViewTerminatedEvent) => void;
622
+}
623
+
463
 export interface AndroidWebViewProps extends WebViewSharedProps {
624
 export interface AndroidWebViewProps extends WebViewSharedProps {
464
   onNavigationStateChange?: (event: WebViewNavigation) => void;
625
   onNavigationStateChange?: (event: WebViewNavigation) => void;
465
   onContentSizeChange?: (event: WebViewEvent) => void;
626
   onContentSizeChange?: (event: WebViewEvent) => void;

+ 316
- 3
yarn.lock View File

699
   dependencies:
699
   dependencies:
700
     regenerator-runtime "^0.13.2"
700
     regenerator-runtime "^0.13.2"
701
 
701
 
702
-"@babel/runtime@^7.0.0", "@babel/runtime@^7.4.5":
702
+"@babel/runtime@^7.0.0":
703
+  version "7.8.3"
704
+  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.3.tgz#0811944f73a6c926bb2ad35e918dcc1bfab279f1"
705
+  integrity sha512-fVHx1rzEmwB130VTkLnxR+HmxcTjGzH12LYQcFFoBwakMd3aOMD4OsRN7tGG/UOYE2ektgFrS8uACAoRk1CY0w==
706
+  dependencies:
707
+    regenerator-runtime "^0.13.2"
708
+
709
+"@babel/runtime@^7.4.5":
703
   version "7.5.5"
710
   version "7.5.5"
704
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132"
711
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132"
705
   integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==
712
   integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==
1035
   dependencies:
1042
   dependencies:
1036
     serve-static "^1.13.1"
1043
     serve-static "^1.13.1"
1037
 
1044
 
1045
+"@react-native-community/cli-platform-android@^2.6.0", "@react-native-community/cli-platform-android@^2.9.0":
1046
+  version "2.9.0"
1047
+  resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-2.9.0.tgz#28831e61ce565a2c7d1905852fce1eecfd33cb5e"
1048
+  integrity sha512-VEQs4Q6R5tnlYFrQIFoPEWjLc43whRHC9HeH+idbFymwDqysLVUffQbb9D6PJUj+C/AvrDhBhU6S3tDjGbSsag==
1049
+  dependencies:
1050
+    "@react-native-community/cli-tools" "^2.8.3"
1051
+    chalk "^2.4.2"
1052
+    execa "^1.0.0"
1053
+    jetifier "^1.6.2"
1054
+    logkitty "^0.6.0"
1055
+    slash "^3.0.0"
1056
+    xmldoc "^1.1.2"
1057
+
1038
 "@react-native-community/cli-platform-android@^3.0.0":
1058
 "@react-native-community/cli-platform-android@^3.0.0":
1039
   version "3.0.3"
1059
   version "3.0.3"
1040
   resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-3.0.3.tgz#e652abce79a7c1e3a8280228123e99df2c4b97b6"
1060
   resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-3.0.3.tgz#e652abce79a7c1e3a8280228123e99df2c4b97b6"
1048
     slash "^3.0.0"
1068
     slash "^3.0.0"
1049
     xmldoc "^1.1.2"
1069
     xmldoc "^1.1.2"
1050
 
1070
 
1071
+"@react-native-community/cli-platform-ios@^2.10.0", "@react-native-community/cli-platform-ios@^2.4.1":
1072
+  version "2.10.0"
1073
+  resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-2.10.0.tgz#ee494d2f9a8f8727bd5eb3c446f22ebb5429b624"
1074
+  integrity sha512-z5BQKyT/bgTSdHhvsFNf++6VP50vtOOaITnNKvw4954wURjv5JOQh1De3BngyaDOoGfV1mXkCxutqAXqSeuIjw==
1075
+  dependencies:
1076
+    "@react-native-community/cli-tools" "^2.8.3"
1077
+    chalk "^2.4.2"
1078
+    xcode "^2.0.0"
1079
+
1051
 "@react-native-community/cli-platform-ios@^3.0.0":
1080
 "@react-native-community/cli-platform-ios@^3.0.0":
1052
   version "3.0.0"
1081
   version "3.0.0"
1053
   resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-3.0.0.tgz#3a48a449c0c33af3b0b3d19d3256de99388fe15f"
1082
   resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-3.0.0.tgz#3a48a449c0c33af3b0b3d19d3256de99388fe15f"
1058
     js-yaml "^3.13.1"
1087
     js-yaml "^3.13.1"
1059
     xcode "^2.0.0"
1088
     xcode "^2.0.0"
1060
 
1089
 
1090
+"@react-native-community/cli-tools@^2.8.3":
1091
+  version "2.8.3"
1092
+  resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-2.8.3.tgz#0e2249f48cf4603fb8d740a9f0715c31ac131ceb"
1093
+  integrity sha512-N5Pz+pR+GFq3JApjd0SW4jp9KC7kbKsMH65QLRh30JNsxdPvNkYox6/ZZdkvdXaI5ev3EckR7eqlcwi5gpVTYQ==
1094
+  dependencies:
1095
+    chalk "^2.4.2"
1096
+    lodash "^4.17.5"
1097
+    mime "^2.4.1"
1098
+    node-fetch "^2.5.0"
1099
+
1061
 "@react-native-community/cli-tools@^3.0.0":
1100
 "@react-native-community/cli-tools@^3.0.0":
1062
   version "3.0.0"
1101
   version "3.0.0"
1063
   resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-3.0.0.tgz#fe48b80822ed7e49b8af051f9fe41e22a2a710b1"
1102
   resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-3.0.0.tgz#fe48b80822ed7e49b8af051f9fe41e22a2a710b1"
1073
   resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-3.0.0.tgz#488d46605cb05e88537e030f38da236eeda74652"
1112
   resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-3.0.0.tgz#488d46605cb05e88537e030f38da236eeda74652"
1074
   integrity sha512-ng6Tm537E/M42GjE4TRUxQyL8sRfClcL7bQWblOCoxPZzJ2J3bdALsjeG3vDnVCIfI/R0AeFalN9KjMt0+Z/Zg==
1113
   integrity sha512-ng6Tm537E/M42GjE4TRUxQyL8sRfClcL7bQWblOCoxPZzJ2J3bdALsjeG3vDnVCIfI/R0AeFalN9KjMt0+Z/Zg==
1075
 
1114
 
1115
+"@react-native-community/cli@^2.6.0":
1116
+  version "2.10.0"
1117
+  resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-2.10.0.tgz#3bda7a77dadfde006d81ee835263b5ff88f1b590"
1118
+  integrity sha512-KldnMwYzNJlbbJpJQ4AxwTMp89qqwilI1lEvCAwKmiviWuyYGACCQsXI7ikShRaQeakc28zyN2ldbkbrHeOoJA==
1119
+  dependencies:
1120
+    "@hapi/joi" "^15.0.3"
1121
+    "@react-native-community/cli-platform-android" "^2.9.0"
1122
+    "@react-native-community/cli-platform-ios" "^2.10.0"
1123
+    "@react-native-community/cli-tools" "^2.8.3"
1124
+    chalk "^2.4.2"
1125
+    commander "^2.19.0"
1126
+    compression "^1.7.1"
1127
+    connect "^3.6.5"
1128
+    cosmiconfig "^5.1.0"
1129
+    deepmerge "^3.2.0"
1130
+    envinfo "^7.1.0"
1131
+    errorhandler "^1.5.0"
1132
+    execa "^1.0.0"
1133
+    fs-extra "^7.0.1"
1134
+    glob "^7.1.1"
1135
+    graceful-fs "^4.1.3"
1136
+    inquirer "^3.0.6"
1137
+    lodash "^4.17.5"
1138
+    metro "^0.54.1"
1139
+    metro-config "^0.54.1"
1140
+    metro-core "^0.54.1"
1141
+    metro-react-native-babel-transformer "^0.54.1"
1142
+    minimist "^1.2.0"
1143
+    mkdirp "^0.5.1"
1144
+    morgan "^1.9.0"
1145
+    node-notifier "^5.2.1"
1146
+    open "^6.2.0"
1147
+    ora "^3.4.0"
1148
+    plist "^3.0.0"
1149
+    semver "^5.0.3"
1150
+    serve-static "^1.13.1"
1151
+    shell-quote "1.6.1"
1152
+    ws "^1.1.0"
1153
+
1076
 "@react-native-community/cli@^3.0.0":
1154
 "@react-native-community/cli@^3.0.0":
1077
   version "3.0.4"
1155
   version "3.0.4"
1078
   resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-3.0.4.tgz#a9dba1bc77855a6e45fccaabb017360645d936bb"
1156
   resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-3.0.4.tgz#a9dba1bc77855a6e45fccaabb017360645d936bb"
4169
   resolved "https://registry.yarnpkg.com/hermes-engine/-/hermes-engine-0.2.1.tgz#25c0f1ff852512a92cb5c5cc47cf967e1e722ea2"
4247
   resolved "https://registry.yarnpkg.com/hermes-engine/-/hermes-engine-0.2.1.tgz#25c0f1ff852512a92cb5c5cc47cf967e1e722ea2"
4170
   integrity sha512-eNHUQHuadDMJARpaqvlCZoK/Nitpj6oywq3vQ3wCwEsww5morX34mW5PmKWQTO7aU0ck0hgulxR+EVDlXygGxQ==
4248
   integrity sha512-eNHUQHuadDMJARpaqvlCZoK/Nitpj6oywq3vQ3wCwEsww5morX34mW5PmKWQTO7aU0ck0hgulxR+EVDlXygGxQ==
4171
 
4249
 
4250
+hermesvm@^0.1.0:
4251
+  version "0.1.1"
4252
+  resolved "https://registry.yarnpkg.com/hermesvm/-/hermesvm-0.1.1.tgz#bd1df92b4dc504e261c23df34864daf24b844d03"
4253
+  integrity sha512-EosSDeUqTTGvlc9vQiy5Y/9GBlucEyo6lYuxg/FnukHCD/CP3NYeDAGV54TyZ19FgSqMEoPgOH9cyxvv8epQ1g==
4254
+
4172
 hook-std@^2.0.0:
4255
 hook-std@^2.0.0:
4173
   version "2.0.0"
4256
   version "2.0.0"
4174
   resolved "https://registry.yarnpkg.com/hook-std/-/hook-std-2.0.0.tgz#ff9aafdebb6a989a354f729bb6445cf4a3a7077c"
4257
   resolved "https://registry.yarnpkg.com/hook-std/-/hook-std-2.0.0.tgz#ff9aafdebb6a989a354f729bb6445cf4a3a7077c"
5190
   resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
5273
   resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
5191
   integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
5274
   integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
5192
 
5275
 
5193
-jsc-android@^245459.0.0:
5276
+jsc-android@245459.0.0, jsc-android@^245459.0.0:
5194
   version "245459.0.0"
5277
   version "245459.0.0"
5195
   resolved "https://registry.yarnpkg.com/jsc-android/-/jsc-android-245459.0.0.tgz#e584258dd0b04c9159a27fb104cd5d491fd202c9"
5278
   resolved "https://registry.yarnpkg.com/jsc-android/-/jsc-android-245459.0.0.tgz#e584258dd0b04c9159a27fb104cd5d491fd202c9"
5196
   integrity sha512-wkjURqwaB1daNkDi2OYYbsLnIdC/lUM2nPXQKRs5pqEU9chDg435bjvo+LSaHotDENygHQDHe+ntUkkw2gwMtg==
5279
   integrity sha512-wkjURqwaB1daNkDi2OYYbsLnIdC/lUM2nPXQKRs5pqEU9chDg435bjvo+LSaHotDENygHQDHe+ntUkkw2gwMtg==
5902
   resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.4.tgz#c9269589e6885a60cf80605d9522d4b67ca646e3"
5985
   resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.4.tgz#c9269589e6885a60cf80605d9522d4b67ca646e3"
5903
   integrity sha512-FYE8xI+6pjFOhokZu0We3S5NKCirLbCzSh2Usf3qEyr4X8U+0jNg9P8RZ4qz+V2UoECLVwSyzU3LxXBaLGtD3A==
5986
   integrity sha512-FYE8xI+6pjFOhokZu0We3S5NKCirLbCzSh2Usf3qEyr4X8U+0jNg9P8RZ4qz+V2UoECLVwSyzU3LxXBaLGtD3A==
5904
 
5987
 
5988
+metro-babel-register@0.54.1:
5989
+  version "0.54.1"
5990
+  resolved "https://registry.yarnpkg.com/metro-babel-register/-/metro-babel-register-0.54.1.tgz#7d2bfe444b1ccef8de99aedc7d9330891d806076"
5991
+  integrity sha512-j3VydgncUG8HP6AZala6GTIt3V01nptodnnOke3JMYLqgk8EJ1LOVOdotK9pXi80o7EmmNKFs/LyyH8z+uAJzQ==
5992
+  dependencies:
5993
+    "@babel/core" "^7.0.0"
5994
+    "@babel/plugin-proposal-class-properties" "^7.0.0"
5995
+    "@babel/plugin-proposal-nullish-coalescing-operator" "^7.0.0"
5996
+    "@babel/plugin-proposal-object-rest-spread" "^7.0.0"
5997
+    "@babel/plugin-proposal-optional-catch-binding" "^7.0.0"
5998
+    "@babel/plugin-proposal-optional-chaining" "^7.0.0"
5999
+    "@babel/plugin-transform-async-to-generator" "^7.0.0"
6000
+    "@babel/plugin-transform-flow-strip-types" "^7.0.0"
6001
+    "@babel/plugin-transform-modules-commonjs" "^7.0.0"
6002
+    "@babel/register" "^7.0.0"
6003
+    core-js "^2.2.2"
6004
+    escape-string-regexp "^1.0.5"
6005
+
5905
 metro-babel-register@^0.56.0, metro-babel-register@^0.56.4:
6006
 metro-babel-register@^0.56.0, metro-babel-register@^0.56.4:
5906
   version "0.56.4"
6007
   version "0.56.4"
5907
   resolved "https://registry.yarnpkg.com/metro-babel-register/-/metro-babel-register-0.56.4.tgz#b0c627a1cfdd1bdd768f81af79481754e833a902"
6008
   resolved "https://registry.yarnpkg.com/metro-babel-register/-/metro-babel-register-0.56.4.tgz#b0c627a1cfdd1bdd768f81af79481754e833a902"
5920
     core-js "^2.2.2"
6021
     core-js "^2.2.2"
5921
     escape-string-regexp "^1.0.5"
6022
     escape-string-regexp "^1.0.5"
5922
 
6023
 
6024
+metro-babel-transformer@0.54.1:
6025
+  version "0.54.1"
6026
+  resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.54.1.tgz#371ffa2d1118b22cc9e40b3c3ea6738c49dae9dc"
6027
+  integrity sha512-2aiAnuYBdcLV1VINb8ENAA4keIaJIepHgR9+iRvIde+9GSjKnexqx4nNmJN392285gRDp1fVZ7uY0uQawK/A5g==
6028
+  dependencies:
6029
+    "@babel/core" "^7.0.0"
6030
+
5923
 metro-babel-transformer@^0.56.4:
6031
 metro-babel-transformer@^0.56.4:
5924
   version "0.56.4"
6032
   version "0.56.4"
5925
   resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.56.4.tgz#fe1d0dc600fcf90201a5bea4d42caea10b801057"
6033
   resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.56.4.tgz#fe1d0dc600fcf90201a5bea4d42caea10b801057"
5935
   dependencies:
6043
   dependencies:
5936
     "@babel/helper-module-imports" "^7.0.0"
6044
     "@babel/helper-module-imports" "^7.0.0"
5937
 
6045
 
6046
+metro-cache@0.54.1:
6047
+  version "0.54.1"
6048
+  resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.54.1.tgz#2e9017cbd11106837b8c385c9eb8c8175469a8c1"
6049
+  integrity sha512-RxCFoNcANHXZYi4MIQNnqh68gUnC3bMpzCFJY5pBoqqdrkkn8ibYglBweA0/DW7hx1OZTJWelwS1Dp8xxmE2CA==
6050
+  dependencies:
6051
+    jest-serializer "^24.4.0"
6052
+    metro-core "0.54.1"
6053
+    mkdirp "^0.5.1"
6054
+    rimraf "^2.5.4"
6055
+
5938
 metro-cache@^0.56.4:
6056
 metro-cache@^0.56.4:
5939
   version "0.56.4"
6057
   version "0.56.4"
5940
   resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.56.4.tgz#542f9f8a35f8fb9d5576f46fd3ab4d4f42851a7e"
6058
   resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.56.4.tgz#542f9f8a35f8fb9d5576f46fd3ab4d4f42851a7e"
5945
     mkdirp "^0.5.1"
6063
     mkdirp "^0.5.1"
5946
     rimraf "^2.5.4"
6064
     rimraf "^2.5.4"
5947
 
6065
 
6066
+metro-config@0.54.1, metro-config@^0.54.1:
6067
+  version "0.54.1"
6068
+  resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.54.1.tgz#808b4e17625d9f4e9afa34232778fdf8e63cc8dd"
6069
+  integrity sha512-FpxrA+63rGkPGvGI653dvuSreJzU+eOTILItVnnhmqwn2SAK5V00N/qGTOIJe2YIuWEFXwCzw9lXmANrXbwuGg==
6070
+  dependencies:
6071
+    cosmiconfig "^5.0.5"
6072
+    jest-validate "^24.7.0"
6073
+    metro "0.54.1"
6074
+    metro-cache "0.54.1"
6075
+    metro-core "0.54.1"
6076
+    pretty-format "^24.7.0"
6077
+
5948
 metro-config@^0.56.0, metro-config@^0.56.4:
6078
 metro-config@^0.56.0, metro-config@^0.56.4:
5949
   version "0.56.4"
6079
   version "0.56.4"
5950
   resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.56.4.tgz#338fd8165fba59424cec427c1a881757945e57e9"
6080
   resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.56.4.tgz#338fd8165fba59424cec427c1a881757945e57e9"
5957
     metro-core "^0.56.4"
6087
     metro-core "^0.56.4"
5958
     pretty-format "^24.7.0"
6088
     pretty-format "^24.7.0"
5959
 
6089
 
6090
+metro-core@0.54.1, metro-core@^0.54.1:
6091
+  version "0.54.1"
6092
+  resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.54.1.tgz#17f6ecc167918da8819d4af5726349e55714954b"
6093
+  integrity sha512-8oz3Ck7QFBzW9dG9tKFhrXHKPu2Ajx3R7eatf61Gl6Jf/tF7PNouv3wHxPsJW3oXDFiwKLszd89+OgleTGkB5g==
6094
+  dependencies:
6095
+    jest-haste-map "^24.7.1"
6096
+    lodash.throttle "^4.1.1"
6097
+    metro-resolver "0.54.1"
6098
+    wordwrap "^1.0.0"
6099
+
5960
 metro-core@^0.56.0, metro-core@^0.56.4:
6100
 metro-core@^0.56.0, metro-core@^0.56.4:
5961
   version "0.56.4"
6101
   version "0.56.4"
5962
   resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.56.4.tgz#67cc41b3c0bf66e9c2306f50239a1080b1e82312"
6102
   resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.56.4.tgz#67cc41b3c0bf66e9c2306f50239a1080b1e82312"
5967
     metro-resolver "^0.56.4"
6107
     metro-resolver "^0.56.4"
5968
     wordwrap "^1.0.0"
6108
     wordwrap "^1.0.0"
5969
 
6109
 
6110
+metro-inspector-proxy@0.54.1:
6111
+  version "0.54.1"
6112
+  resolved "https://registry.yarnpkg.com/metro-inspector-proxy/-/metro-inspector-proxy-0.54.1.tgz#0ef48ee3feb11c6da47aa100151a9bf2a7c358ee"
6113
+  integrity sha512-sf6kNu7PgFW6U+hU7YGZfbAUKAPVvCJhY8YVu/A1RMKH9nNULrCo+jlWh0gWgmFfWRQiAPCElevROg+5somk8A==
6114
+  dependencies:
6115
+    connect "^3.6.5"
6116
+    debug "^2.2.0"
6117
+    rxjs "^5.4.3"
6118
+    ws "^1.1.5"
6119
+    yargs "^9.0.0"
6120
+
5970
 metro-inspector-proxy@^0.56.4:
6121
 metro-inspector-proxy@^0.56.4:
5971
   version "0.56.4"
6122
   version "0.56.4"
5972
   resolved "https://registry.yarnpkg.com/metro-inspector-proxy/-/metro-inspector-proxy-0.56.4.tgz#7343ff3c5908af4fd99e96b6d646e24e99816be4"
6123
   resolved "https://registry.yarnpkg.com/metro-inspector-proxy/-/metro-inspector-proxy-0.56.4.tgz#7343ff3c5908af4fd99e96b6d646e24e99816be4"
5978
     ws "^1.1.5"
6129
     ws "^1.1.5"
5979
     yargs "^9.0.0"
6130
     yargs "^9.0.0"
5980
 
6131
 
6132
+metro-minify-uglify@0.54.1:
6133
+  version "0.54.1"
6134
+  resolved "https://registry.yarnpkg.com/metro-minify-uglify/-/metro-minify-uglify-0.54.1.tgz#54ed1cb349245ce82dba8cc662bbf69fbca142c3"
6135
+  integrity sha512-z+pOPna/8IxD4OhjW6Xo1mV2EszgqqQHqBm1FdmtdF6IpWkQp33qpDBNEi9NGZTOr7pp2bvcxZnvNJdC2lrK9Q==
6136
+  dependencies:
6137
+    uglify-es "^3.1.9"
6138
+
5981
 metro-minify-uglify@^0.56.4:
6139
 metro-minify-uglify@^0.56.4:
5982
   version "0.56.4"
6140
   version "0.56.4"
5983
   resolved "https://registry.yarnpkg.com/metro-minify-uglify/-/metro-minify-uglify-0.56.4.tgz#13589dfb1d43343608aacb7f78ddfcc052daa63c"
6141
   resolved "https://registry.yarnpkg.com/metro-minify-uglify/-/metro-minify-uglify-0.56.4.tgz#13589dfb1d43343608aacb7f78ddfcc052daa63c"
6068
     "@babel/template" "^7.0.0"
6226
     "@babel/template" "^7.0.0"
6069
     react-refresh "^0.4.0"
6227
     react-refresh "^0.4.0"
6070
 
6228
 
6229
+metro-react-native-babel-transformer@0.54.1, metro-react-native-babel-transformer@^0.54.1:
6230
+  version "0.54.1"
6231
+  resolved "https://registry.yarnpkg.com/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.54.1.tgz#45b56db004421134e10e739f69e8de50775fef17"
6232
+  integrity sha512-ECw7xG91t8dk/PHdiyoC5SP1s9OQzfmJzG5m0YOZaKtHMe534qTDbncxaKfTI3CP99yti2maXFBRVj+xyvph/g==
6233
+  dependencies:
6234
+    "@babel/core" "^7.0.0"
6235
+    babel-preset-fbjs "^3.1.2"
6236
+    metro-babel-transformer "0.54.1"
6237
+    metro-react-native-babel-preset "0.54.1"
6238
+
6071
 metro-react-native-babel-transformer@^0.56.0:
6239
 metro-react-native-babel-transformer@^0.56.0:
6072
   version "0.56.4"
6240
   version "0.56.4"
6073
   resolved "https://registry.yarnpkg.com/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.56.4.tgz#3c6e48b605c305362ee624e45ff338656e35fc1d"
6241
   resolved "https://registry.yarnpkg.com/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.56.4.tgz#3c6e48b605c305362ee624e45ff338656e35fc1d"
6079
     metro-react-native-babel-preset "^0.56.4"
6247
     metro-react-native-babel-preset "^0.56.4"
6080
     metro-source-map "^0.56.4"
6248
     metro-source-map "^0.56.4"
6081
 
6249
 
6250
+metro-resolver@0.54.1:
6251
+  version "0.54.1"
6252
+  resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.54.1.tgz#0295b38624b678b88b16bf11d47288845132b087"
6253
+  integrity sha512-Byv1LIawYAASy9CFRwzrncYnqaFGLe8vpw178EtzStqP05Hu6hXSqkNTrfoXa+3V9bPFGCrVzFx2NY3gFp2btg==
6254
+  dependencies:
6255
+    absolute-path "^0.0.0"
6256
+
6082
 metro-resolver@^0.56.4:
6257
 metro-resolver@^0.56.4:
6083
   version "0.56.4"
6258
   version "0.56.4"
6084
   resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.56.4.tgz#9876f57bca37fd1bfcffd733541e2ee4a89fad7f"
6259
   resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.56.4.tgz#9876f57bca37fd1bfcffd733541e2ee4a89fad7f"
6086
   dependencies:
6261
   dependencies:
6087
     absolute-path "^0.0.0"
6262
     absolute-path "^0.0.0"
6088
 
6263
 
6264
+metro-source-map@0.54.1:
6265
+  version "0.54.1"
6266
+  resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.54.1.tgz#e17bad53c11978197d3c05c9168d799c2e04dcc5"
6267
+  integrity sha512-E9iSYMSUSq5qYi1R2hTQtxH4Mxjzfgr/jaSmQIWi7h3fG2P1qOZNNSzeaeUeTK+s2N/ksVlkcL5kMikol8CDrQ==
6268
+  dependencies:
6269
+    "@babel/traverse" "^7.0.0"
6270
+    "@babel/types" "^7.0.0"
6271
+    source-map "^0.5.6"
6272
+
6273
+metro-source-map@0.55.0, metro-source-map@^0.55.0:
6274
+  version "0.55.0"
6275
+  resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.55.0.tgz#1f6289905f08277c398f2b9b9c13e7e0e5a6f540"
6276
+  integrity sha512-HZODA0KPl5onJNGIztfTHHWurR2nL6Je/X8wwj+bL4ZBB/hSMVeDk7rWReCAvO3twVz7Ztp8Si0jfMmmH4Ruuw==
6277
+  dependencies:
6278
+    "@babel/traverse" "^7.0.0"
6279
+    "@babel/types" "^7.0.0"
6280
+    invariant "^2.2.4"
6281
+    metro-symbolicate "0.55.0"
6282
+    ob1 "0.55.0"
6283
+    source-map "^0.5.6"
6284
+    vlq "^1.0.0"
6285
+
6089
 metro-source-map@^0.56.0, metro-source-map@^0.56.4:
6286
 metro-source-map@^0.56.0, metro-source-map@^0.56.4:
6090
   version "0.56.4"
6287
   version "0.56.4"
6091
   resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.56.4.tgz#868ccac3f3519fe14eca358bc186f63651b2b9bc"
6288
   resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.56.4.tgz#868ccac3f3519fe14eca358bc186f63651b2b9bc"
6099
     source-map "^0.5.6"
6296
     source-map "^0.5.6"
6100
     vlq "^1.0.0"
6297
     vlq "^1.0.0"
6101
 
6298
 
6299
+metro-symbolicate@0.55.0:
6300
+  version "0.55.0"
6301
+  resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.55.0.tgz#4086a2adae54b5e44a4911ca572d8a7b03c71fa1"
6302
+  integrity sha512-3r3Gpv5L4U7rBGpIqw5S1nun5MelfUMLRiScJsPRGZVTX3WY1w+zpaQKlWBi5yuHf5dMQ+ZUVbhb02IdrfJ2Fg==
6303
+  dependencies:
6304
+    metro-source-map "0.55.0"
6305
+    source-map "^0.5.6"
6306
+    through2 "^2.0.1"
6307
+    vlq "^1.0.0"
6308
+
6102
 metro-symbolicate@^0.56.4:
6309
 metro-symbolicate@^0.56.4:
6103
   version "0.56.4"
6310
   version "0.56.4"
6104
   resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.56.4.tgz#53e9d40beac9049fa75a3e620ddd47d4907ff015"
6311
   resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.56.4.tgz#53e9d40beac9049fa75a3e620ddd47d4907ff015"
6110
     through2 "^2.0.1"
6317
     through2 "^2.0.1"
6111
     vlq "^1.0.0"
6318
     vlq "^1.0.0"
6112
 
6319
 
6320
+metro@0.54.1, metro@^0.54.1:
6321
+  version "0.54.1"
6322
+  resolved "https://registry.yarnpkg.com/metro/-/metro-0.54.1.tgz#a629be00abee5a450a25a8f71c24745f70cc9b44"
6323
+  integrity sha512-6ODPT4mEo4FCpbExRNnQAcZmf1VeNvYOTMj2Na03FjGqhNODHhI2U/wF/Ul5gqTyJ2dVdkXeyvKW3gl/LrnJRg==
6324
+  dependencies:
6325
+    "@babel/core" "^7.0.0"
6326
+    "@babel/generator" "^7.0.0"
6327
+    "@babel/parser" "^7.0.0"
6328
+    "@babel/plugin-external-helpers" "^7.0.0"
6329
+    "@babel/template" "^7.0.0"
6330
+    "@babel/traverse" "^7.0.0"
6331
+    "@babel/types" "^7.0.0"
6332
+    absolute-path "^0.0.0"
6333
+    async "^2.4.0"
6334
+    babel-preset-fbjs "^3.1.2"
6335
+    buffer-crc32 "^0.2.13"
6336
+    chalk "^2.4.1"
6337
+    concat-stream "^1.6.0"
6338
+    connect "^3.6.5"
6339
+    debug "^2.2.0"
6340
+    denodeify "^1.2.1"
6341
+    eventemitter3 "^3.0.0"
6342
+    fbjs "^1.0.0"
6343
+    fs-extra "^1.0.0"
6344
+    graceful-fs "^4.1.3"
6345
+    image-size "^0.6.0"
6346
+    invariant "^2.2.4"
6347
+    jest-haste-map "^24.7.1"
6348
+    jest-worker "^24.6.0"
6349
+    json-stable-stringify "^1.0.1"
6350
+    lodash.throttle "^4.1.1"
6351
+    merge-stream "^1.0.1"
6352
+    metro-babel-register "0.54.1"
6353
+    metro-babel-transformer "0.54.1"
6354
+    metro-cache "0.54.1"
6355
+    metro-config "0.54.1"
6356
+    metro-core "0.54.1"
6357
+    metro-inspector-proxy "0.54.1"
6358
+    metro-minify-uglify "0.54.1"
6359
+    metro-react-native-babel-preset "0.54.1"
6360
+    metro-resolver "0.54.1"
6361
+    metro-source-map "0.54.1"
6362
+    mime-types "2.1.11"
6363
+    mkdirp "^0.5.1"
6364
+    node-fetch "^2.2.0"
6365
+    nullthrows "^1.1.0"
6366
+    react-transform-hmr "^1.0.4"
6367
+    resolve "^1.5.0"
6368
+    rimraf "^2.5.4"
6369
+    serialize-error "^2.1.0"
6370
+    source-map "^0.5.6"
6371
+    temp "0.8.3"
6372
+    throat "^4.1.0"
6373
+    wordwrap "^1.0.0"
6374
+    write-file-atomic "^1.2.0"
6375
+    ws "^1.1.5"
6376
+    xpipe "^1.0.5"
6377
+    yargs "^9.0.0"
6378
+
6113
 metro@^0.56.0, metro@^0.56.4:
6379
 metro@^0.56.0, metro@^0.56.4:
6114
   version "0.56.4"
6380
   version "0.56.4"
6115
   resolved "https://registry.yarnpkg.com/metro/-/metro-0.56.4.tgz#be7e1380ee6ac3552c25ead8098eab261029e4d7"
6381
   resolved "https://registry.yarnpkg.com/metro/-/metro-0.56.4.tgz#be7e1380ee6ac3552c25ead8098eab261029e4d7"
6832
   resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
7098
   resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
6833
   integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
7099
   integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
6834
 
7100
 
7101
+ob1@0.55.0:
7102
+  version "0.55.0"
7103
+  resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.55.0.tgz#e393b4ae786ef442b3ef2a298ab70d6ec353dbdd"
7104
+  integrity sha512-pfyiMVsUItl8WiRKMT15eCi662pCRAuYTq2+V3UpE+PpFErJI/TvRh/M/l/9TaLlbFr7krJ7gdl+FXJNcybmvw==
7105
+
6835
 ob1@^0.56.4:
7106
 ob1@^0.56.4:
6836
   version "0.56.4"
7107
   version "0.56.4"
6837
   resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.56.4.tgz#c4acb3baa42f4993a44b35b2da7c8ef443dcccec"
7108
   resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.56.4.tgz#c4acb3baa42f4993a44b35b2da7c8ef443dcccec"
7623
   resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-1.1.2.tgz#3d2ae45c2c9040cbb1772be52f8ea1ade6ca2ee1"
7894
   resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-1.1.2.tgz#3d2ae45c2c9040cbb1772be52f8ea1ade6ca2ee1"
7624
   integrity sha512-WUSQJ4P/wWcusaH+zZmbECOk7H5N2pOIl0vzheeornkIMhu+qrNdGFm0bDZLCb0hSF0jf/kH1SgkNGfBdTc4wA==
7895
   integrity sha512-WUSQJ4P/wWcusaH+zZmbECOk7H5N2pOIl0vzheeornkIMhu+qrNdGFm0bDZLCb0hSF0jf/kH1SgkNGfBdTc4wA==
7625
 
7896
 
7626
-react-devtools-core@^3.6.3:
7897
+react-devtools-core@^3.6.1, react-devtools-core@^3.6.3:
7627
   version "3.6.3"
7898
   version "3.6.3"
7628
   resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-3.6.3.tgz#977d95b684c6ad28205f0c62e1e12c5f16675814"
7899
   resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-3.6.3.tgz#977d95b684c6ad28205f0c62e1e12c5f16675814"
7629
   integrity sha512-+P+eFy/yo8Z/UH9J0DqHZuUM5+RI2wl249TNvMx3J2jpUomLQa4Zxl56GEotGfw3PIP1eI+hVf1s53FlUONStQ==
7900
   integrity sha512-+P+eFy/yo8Z/UH9J0DqHZuUM5+RI2wl249TNvMx3J2jpUomLQa4Zxl56GEotGfw3PIP1eI+hVf1s53FlUONStQ==
7636
   resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.9.0.tgz#21ca9561399aad0ff1a7701c01683e8ca981edcb"
7907
   resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.9.0.tgz#21ca9561399aad0ff1a7701c01683e8ca981edcb"
7637
   integrity sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==
7908
   integrity sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==
7638
 
7909
 
7910
+react-native-macos@0.60.0-microsoft.49:
7911
+  version "0.60.0-microsoft.49"
7912
+  resolved "https://registry.yarnpkg.com/react-native-macos/-/react-native-macos-0.60.0-microsoft.49.tgz#ac506343f7450f12f852769102e6262b531b181f"
7913
+  integrity sha512-2631KIggGpw1RoLC/lWRZ/agFgAAMWuoQrRcmGsN+0neXHggEY5jUzz1uV6LeqKkrcudV+qaz3ajo85UjwqDIA==
7914
+  dependencies:
7915
+    "@babel/runtime" "^7.0.0"
7916
+    "@react-native-community/cli" "^2.6.0"
7917
+    "@react-native-community/cli-platform-android" "^2.6.0"
7918
+    "@react-native-community/cli-platform-ios" "^2.4.1"
7919
+    abort-controller "^3.0.0"
7920
+    art "^0.10.0"
7921
+    base64-js "^1.1.2"
7922
+    connect "^3.6.5"
7923
+    create-react-class "^15.6.3"
7924
+    escape-string-regexp "^1.0.5"
7925
+    event-target-shim "^5.0.1"
7926
+    fbjs "^1.0.0"
7927
+    fbjs-scripts "^1.1.0"
7928
+    hermesvm "^0.1.0"
7929
+    invariant "^2.2.4"
7930
+    jsc-android "245459.0.0"
7931
+    metro-babel-register "0.54.1"
7932
+    metro-react-native-babel-transformer "0.54.1"
7933
+    metro-source-map "^0.55.0"
7934
+    nullthrows "^1.1.0"
7935
+    pretty-format "^24.7.0"
7936
+    promise "^7.1.1"
7937
+    prop-types "^15.7.2"
7938
+    react-devtools-core "^3.6.1"
7939
+    regenerator-runtime "^0.13.2"
7940
+    scheduler "0.14.0"
7941
+    stacktrace-parser "^0.1.3"
7942
+    whatwg-fetch "^3.0.0"
7943
+
7639
 react-native@0.61.5:
7944
 react-native@0.61.5:
7640
   version "0.61.5"
7945
   version "0.61.5"
7641
   resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.61.5.tgz#6e21acb56cbd75a3baeb1f70201a66f42600bba8"
7946
   resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.61.5.tgz#6e21acb56cbd75a3baeb1f70201a66f42600bba8"
8228
   resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
8533
   resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
8229
   integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
8534
   integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
8230
 
8535
 
8536
+scheduler@0.14.0:
8537
+  version "0.14.0"
8538
+  resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.14.0.tgz#b392c23c9c14bfa2933d4740ad5603cc0d59ea5b"
8539
+  integrity sha512-9CgbS06Kki2f4R9FjLSITjZo5BZxPsryiRNyL3LpvrM9WxcVmhlqAOc9E+KQbeI2nqej4JIIbOsfdL51cNb4Iw==
8540
+  dependencies:
8541
+    loose-envify "^1.1.0"
8542
+    object-assign "^4.1.1"
8543
+
8231
 scheduler@0.15.0:
8544
 scheduler@0.15.0:
8232
   version "0.15.0"
8545
   version "0.15.0"
8233
   resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.15.0.tgz#6bfcf80ff850b280fed4aeecc6513bc0b4f17f8e"
8546
   resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.15.0.tgz#6bfcf80ff850b280fed4aeecc6513bc0b4f17f8e"