33 Commits

Author SHA1 Message Date
  cani1see 5d5bc2b268 Merge remote-tracking branch 'origin/master' into unjetify 4 years ago
  Janic Duplessis f126189030 Add react-native-safe-area-view example 4 years ago
  Janic Duplessis 411672821b 1.0.2 4 years ago
  Janic Duplessis 7a7935f78b Bring back SafeAreaContext for better compat with 0.x 4 years ago
  Janic Duplessis 54961270aa 1.0.1 4 years ago
  Janic Duplessis cf69c90c09 Fix flipper package 4 years ago
  Satyajit Sahoo 72774fffd4
fix: don't use .web extension (#77) 4 years ago
  Janic Duplessis 67616426be Add native stack example 4 years ago
  Janic Duplessis 0ccc32c5dc Add React Navigation 5 example 4 years ago
  Janic Duplessis 1eae2f5599 Add react-navigation 4 example 4 years ago
  Janic Duplessis e25bf577b5
Update .eslintrc.js 4 years ago
  Janic Duplessis 908744fa14
Update README.md 4 years ago
  Janic Duplessis 1b8c4d1ed8 1.0.0 4 years ago
  Janic Duplessis 8627e747b2 1.0.0-beta.3 4 years ago
  Janic Duplessis 7edb171db1 Fix prettier 4 years ago
  Juan David Nicholls Cardona 79ab4dd028
Add withSafeAreaConsumer HOC (#57) 4 years ago
  Janic Duplessis 05bdb89f95 Make example app easier to run 4 years ago
  luancurti 2e542e71c9
refactor(podfile): remove unnecessary use_native_modules! (#70) 4 years ago
  Janic Duplessis 24018ffa38 1.0.0-beta.2 4 years ago
  Janic Duplessis 9c2ab9c78a Fix tests 4 years ago
  Janic Duplessis 12da572a91 Use getWindowVisibleDisplayFrame to calculate edge insets on api < 20 4 years ago
  Janic Duplessis dad9cc41a6 Better backwards compat 4 years ago
  Janic Duplessis 3a25f1610b Properly disable flipper in iOS example ap 4 years ago
  Janic Duplessis 7620e8046d 1.0.0-beta.1 4 years ago
  Janic Duplessis 98ddd6c65e Fix crash in SafeAreaUtils.getFrame when view parent is null 4 years ago
  Janic Duplessis 960e7e5c6a Disable flipper in ios example app 4 years ago
  Janic Duplessis fdb7c0accf Bring back SafeAreaConsumer with deprecation warning 4 years ago
  Janic Duplessis e2101c6e37 Remove unused WindowChangeEvent, remove log 4 years ago
  Janic Duplessis 7a0b44107e 1.0.0-beta.0 4 years ago
  Janic Duplessis 4515714f01 1.0.0-0 4 years ago
  Janic Duplessis 6c9d3bde46 v2 4 years ago
  Janic Duplessis 436f19b495 Update deps and RN 4 years ago
  dependabot[bot] 1e60db778e
Bump acorn from 6.4.0 to 6.4.1 (#62) 4 years ago
68 changed files with 11156 additions and 2919 deletions
  1. 0
    9
      .eslintrc.js
  2. 4
    0
      .gitignore
  3. 9
    9
      README.md
  4. 6
    6
      android/src/main/java/com/th3rdwave/safeareacontext/EdgeInsets.java
  5. 6
    4
      android/src/main/java/com/th3rdwave/safeareacontext/InsetsChangeEvent.java
  6. 22
    0
      android/src/main/java/com/th3rdwave/safeareacontext/Rect.java
  7. 39
    56
      android/src/main/java/com/th3rdwave/safeareacontext/SafeAreaUtils.java
  8. 15
    14
      android/src/main/java/com/th3rdwave/safeareacontext/SafeAreaView.java
  9. 15
    12
      android/src/main/java/com/th3rdwave/safeareacontext/SafeAreaViewManager.java
  10. 52
    0
      android/src/main/java/com/th3rdwave/safeareacontext/SerializationUtils.java
  11. 10
    0
      babel.config.js
  12. 0
    56
      example/App.tsx
  13. 23
    3
      example/android/app/build.gradle
  14. 67
    0
      example/android/app/src/debug/java/com/safeareaviewexample/ReactNativeFlipper.java
  15. 2
    1
      example/android/app/src/main/AndroidManifest.xml
  16. 36
    0
      example/android/app/src/main/java/com/safeareaviewexample/MainActivity.java
  17. 43
    0
      example/android/app/src/main/java/com/safeareaviewexample/MainApplication.java
  18. 7
    0
      example/android/app/src/main/res/values-v28/styles.xml
  19. 5
    6
      example/android/build.gradle
  20. 6
    0
      example/android/gradle.properties
  21. 1
    1
      example/android/gradle/wrapper/gradle-wrapper.properties
  22. 15
    20
      example/android/gradlew
  23. 4
    1
      example/android/gradlew.bat
  24. 9
    0
      example/android/settings.gradle
  25. 1
    1
      example/app.json
  26. 5
    0
      example/index.expo.js
  27. 1
    1
      example/index.js
  28. 15
    32
      example/ios/Podfile
  29. 251
    190
      example/ios/Podfile.lock
  30. 4
    0
      example/ios/SafeAreaViewExample-Bridging-Header.h
  31. 0
    53
      example/ios/SafeAreaViewExample-tvOS/Info.plist
  32. 0
    24
      example/ios/SafeAreaViewExample-tvOSTests/Info.plist
  33. 47
    2
      example/ios/SafeAreaViewExample.xcodeproj/project.pbxproj
  34. 11
    15
      example/ios/SafeAreaViewExample.xcodeproj/xcshareddata/xcschemes/SafeAreaViewExample.xcscheme
  35. 0
    7
      example/ios/SafeAreaViewExample/AppDelegate.h
  36. 22
    7
      example/ios/SafeAreaViewExample/AppDelegate.m
  37. 9
    0
      example/ios/SafeAreaViewExample/File.swift
  38. 0
    7
      example/ios/SafeAreaViewExample/main.m
  39. 22
    0
      example/package.json
  40. 83
    0
      example/src/App.tsx
  41. 74
    0
      example/src/NativeStackExample.tsx
  42. 14
    0
      example/src/ReactNativeSafeAreaView.tsx
  43. 76
    0
      example/src/ReactNavigation4Example.tsx
  44. 76
    0
      example/src/ReactNavigation5Example.tsx
  45. 92
    0
      example/src/SimpleExample.tsx
  46. 15
    2
      ios/SafeAreaView/RNCSafeAreaView.m
  47. 13
    5
      ios/SafeAreaView/RNCSafeAreaViewManager.m
  48. 0
    17
      metro.config.js
  49. 39
    21
      package.json
  50. 17
    0
      src/InitialWindow.native.ts
  51. 8
    0
      src/InitialWindow.ts
  52. 0
    12
      src/InitialWindowSafeAreaInsets.ts
  53. 0
    4
      src/InitialWindowSafeAreaInsets.web.ts
  54. 6
    0
      src/NativeSafeAreaView.native.tsx
  55. 128
    2
      src/NativeSafeAreaView.tsx
  56. 0
    122
      src/NativeSafeAreaView.web.tsx
  57. 20
    2
      src/SafeArea.types.ts
  58. 123
    0
      src/SafeAreaContext.tsx
  59. 25
    0
      src/SafeAreaView.tsx
  60. 121
    0
      src/__tests__/SafeAreaContext-test.tsx
  61. 35
    0
      src/__tests__/SafeAreaView-test.tsx
  62. 32
    72
      src/__tests__/__snapshots__/SafeAreaContext-test.tsx.snap
  63. 57
    0
      src/__tests__/__snapshots__/SafeAreaView-test.tsx.snap
  64. 0
    169
      src/__tests__/index-test.tsx
  65. 41
    0
      src/__tests__/initialWindowMetrics-test.tsx
  66. 4
    80
      src/index.tsx
  67. 5
    1
      tsconfig.json
  68. 9268
    1873
      yarn.lock

+ 0
- 9
.eslintrc.js 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
- * @format
8
- */
9
-
10
 const typescriptEslintRecommended = require('@typescript-eslint/eslint-plugin/dist/configs/recommended.json');
1
 const typescriptEslintRecommended = require('@typescript-eslint/eslint-plugin/dist/configs/recommended.json');
11
 const typescriptEslintPrettier = require('eslint-config-prettier/@typescript-eslint');
2
 const typescriptEslintPrettier = require('eslint-config-prettier/@typescript-eslint');
12
 
3
 

+ 4
- 0
.gitignore View File

60
 
60
 
61
 # generated by bob
61
 # generated by bob
62
 lib/
62
 lib/
63
+
64
+# Expo
65
+web-build
66
+.expo

+ 9
- 9
README.md View File

96
 Usage with hooks api:
96
 Usage with hooks api:
97
 
97
 
98
 ```js
98
 ```js
99
-import { useSafeArea } from 'react-native-safe-area-context';
99
+import { useSafeAreaInsets } from 'react-native-safe-area-context';
100
 
100
 
101
 function HookComponent() {
101
 function HookComponent() {
102
-  const insets = useSafeArea();
102
+  const insets = useSafeAreaInsets();
103
 
103
 
104
   return <View style={{ paddingTop: insets.top }} />;
104
   return <View style={{ paddingTop: insets.top }} />;
105
 }
105
 }
108
 Usage with consumer api:
108
 Usage with consumer api:
109
 
109
 
110
 ```js
110
 ```js
111
-import { SafeAreaConsumer } from 'react-native-safe-area-context';
111
+import { SafeAreaInsetsContext } from 'react-native-safe-area-context';
112
 
112
 
113
 class ClassComponent extends React.Component {
113
 class ClassComponent extends React.Component {
114
   render() {
114
   render() {
115
     return (
115
     return (
116
-      <SafeAreaConsumer>
116
+      <SafeAreaInsetsContext.Consumer>
117
         {insets => <View style={{ paddingTop: insets.top }} />}
117
         {insets => <View style={{ paddingTop: insets.top }} />}
118
-      </SafeAreaConsumer>
118
+      </SafeAreaInsetsContext.Consumer>
119
     );
119
     );
120
   }
120
   }
121
 }
121
 }
137
 
137
 
138
 ### Web SSR
138
 ### Web SSR
139
 
139
 
140
-If you are doing server side rendering on the web you can use `initialSafeAreaInsets` to inject insets value based on the device the user has, or simply pass zero values. Since insets measurement is async it will break rendering your page content otherwise.
140
+If you are doing server side rendering on the web you can use `initialMetrics` to inject insets and frame value based on the device the user has, or simply pass zero values. Since insets measurement is async it will break rendering your page content otherwise.
141
 
141
 
142
 ### Optimization
142
 ### Optimization
143
 
143
 
144
-To speed up the initial render, you can import `initialWindowSafeAreaInsets` from this package and set as the `initialSafeAreaInsets` prop on the provider as described in Web SSR. You cannot do this if your provider remounts, or you are using `react-native-navigation`.
144
+To speed up the initial render, you can import `initialWindowMetrics` from this package and set as the `initialMetrics` prop on the provider as described in Web SSR. You cannot do this if your provider remounts, or you are using `react-native-navigation`.
145
 
145
 
146
 ```js
146
 ```js
147
 import {
147
 import {
148
   SafeAreaProvider,
148
   SafeAreaProvider,
149
-  initialWindowSafeAreaInsets
149
+  initialWindowMetrics
150
 } from 'react-native-safe-area-context';
150
 } from 'react-native-safe-area-context';
151
 
151
 
152
 function App() {
152
 function App() {
153
   return (
153
   return (
154
-    <SafeAreaProvider initialSafeAreaInsets={initialWindowSafeAreaInsets}>
154
+    <SafeAreaProvider initialMetrics={initialWindowMetrics}>
155
       ...
155
       ...
156
     </SafeAreaProvider>
156
     </SafeAreaProvider>
157
   );
157
   );

+ 6
- 6
android/src/main/java/com/th3rdwave/safeareacontext/EdgeInsets.java View File

1
 package com.th3rdwave.safeareacontext;
1
 package com.th3rdwave.safeareacontext;
2
 
2
 
3
 /* package */ class EdgeInsets {
3
 /* package */ class EdgeInsets {
4
-  public float top;
5
-  public float right;
6
-  public float bottom;
7
-  public float left;
4
+  float top;
5
+  float right;
6
+  float bottom;
7
+  float left;
8
 
8
 
9
-  public EdgeInsets(float top, float right, float bottom, float left) {
9
+  EdgeInsets(float top, float right, float bottom, float left) {
10
     this.top = top;
10
     this.top = top;
11
     this.right = right;
11
     this.right = right;
12
     this.bottom = bottom;
12
     this.bottom = bottom;
13
     this.left = left;
13
     this.left = left;
14
   }
14
   }
15
 
15
 
16
-  public boolean equalsToEdgeInsets(EdgeInsets other) {
16
+  boolean equalsToEdgeInsets(EdgeInsets other) {
17
     if (this == other) {
17
     if (this == other) {
18
       return true;
18
       return true;
19
     }
19
     }

+ 6
- 4
android/src/main/java/com/th3rdwave/safeareacontext/InsetsChangeEvent.java View File

2
 
2
 
3
 import com.facebook.react.bridge.Arguments;
3
 import com.facebook.react.bridge.Arguments;
4
 import com.facebook.react.bridge.WritableMap;
4
 import com.facebook.react.bridge.WritableMap;
5
-import com.facebook.react.uimanager.PixelUtil;
6
 import com.facebook.react.uimanager.events.Event;
5
 import com.facebook.react.uimanager.events.Event;
7
 import com.facebook.react.uimanager.events.RCTEventEmitter;
6
 import com.facebook.react.uimanager.events.RCTEventEmitter;
8
 
7
 
9
 /* package */  class InsetsChangeEvent extends Event<InsetsChangeEvent> {
8
 /* package */  class InsetsChangeEvent extends Event<InsetsChangeEvent> {
10
-  public static final String EVENT_NAME = "topInsetsChange";
9
+  static final String EVENT_NAME = "topInsetsChange";
11
 
10
 
12
   private EdgeInsets mInsets;
11
   private EdgeInsets mInsets;
12
+  private Rect mFrame;
13
 
13
 
14
-  protected InsetsChangeEvent(int viewTag, EdgeInsets insets) {
14
+  InsetsChangeEvent(int viewTag, EdgeInsets insets, Rect frame) {
15
     super(viewTag);
15
     super(viewTag);
16
 
16
 
17
     mInsets = insets;
17
     mInsets = insets;
18
+    mFrame = frame;
18
   }
19
   }
19
 
20
 
20
   @Override
21
   @Override
25
   @Override
26
   @Override
26
   public void dispatch(RCTEventEmitter rctEventEmitter) {
27
   public void dispatch(RCTEventEmitter rctEventEmitter) {
27
     WritableMap event = Arguments.createMap();
28
     WritableMap event = Arguments.createMap();
28
-    event.putMap("insets", SafeAreaUtils.edgeInsetsToJsMap(mInsets));
29
+    event.putMap("insets", SerializationUtils.edgeInsetsToJsMap(mInsets));
30
+    event.putMap("frame", SerializationUtils.rectToJsMap(mFrame));
29
     rctEventEmitter.receiveEvent(getViewTag(), getEventName(), event);
31
     rctEventEmitter.receiveEvent(getViewTag(), getEventName(), event);
30
   }
32
   }
31
 }
33
 }

+ 22
- 0
android/src/main/java/com/th3rdwave/safeareacontext/Rect.java View File

1
+package com.th3rdwave.safeareacontext;
2
+
3
+/* package */ class Rect {
4
+  float x;
5
+  float y;
6
+  float width;
7
+  float height;
8
+
9
+  Rect(float x, float y, float width, float height) {
10
+    this.x = x;
11
+    this.y = y;
12
+    this.width = width;
13
+    this.height = height;
14
+  }
15
+
16
+  boolean equalsToRect(Rect other) {
17
+    if (this == other) {
18
+      return true;
19
+    }
20
+    return this.x == other.x && this.y == other.y && this.width == other.width && this.height == other.height;
21
+  }
22
+}

+ 39
- 56
android/src/main/java/com/th3rdwave/safeareacontext/SafeAreaUtils.java View File

2
 
2
 
3
 import android.graphics.Rect;
3
 import android.graphics.Rect;
4
 import android.os.Build;
4
 import android.os.Build;
5
-import android.view.Surface;
6
 import android.view.View;
5
 import android.view.View;
6
+import android.view.ViewGroup;
7
 import android.view.WindowInsets;
7
 import android.view.WindowInsets;
8
-import android.view.WindowManager;
9
-
10
-import com.facebook.react.bridge.Arguments;
11
-import com.facebook.react.bridge.WritableMap;
12
-import com.facebook.react.common.MapBuilder;
13
-import com.facebook.react.uimanager.PixelUtil;
14
-
15
-import java.util.Map;
16
 
8
 
17
 import android.support.annotation.Nullable;
9
 import android.support.annotation.Nullable;
18
 
10
 
19
 /* package */ class SafeAreaUtils {
11
 /* package */ class SafeAreaUtils {
20
-  static WritableMap edgeInsetsToJsMap(EdgeInsets insets) {
21
-    WritableMap insetsMap = Arguments.createMap();
22
-    insetsMap.putDouble("top", PixelUtil.toDIPFromPixel(insets.top));
23
-    insetsMap.putDouble("right", PixelUtil.toDIPFromPixel(insets.right));
24
-    insetsMap.putDouble("bottom", PixelUtil.toDIPFromPixel(insets.bottom));
25
-    insetsMap.putDouble("left", PixelUtil.toDIPFromPixel(insets.left));
26
-    return insetsMap;
27
-  }
28
 
12
 
29
-  static Map<String, Float> edgeInsetsToJavaMap(EdgeInsets insets) {
30
-    return MapBuilder.of(
31
-        "top",
32
-        PixelUtil.toDIPFromPixel(insets.top),
33
-        "right",
34
-        PixelUtil.toDIPFromPixel(insets.right),
35
-        "bottom",
36
-        PixelUtil.toDIPFromPixel(insets.bottom),
37
-        "left",
38
-        PixelUtil.toDIPFromPixel(insets.left));
39
-  }
40
-
41
-  static @Nullable EdgeInsets getSafeAreaInsets(WindowManager windowManager, View rootView) {
42
-    // Window insets are parts of the window that are covered by system views (status bar,
43
-    // navigation bar, notches). There are no apis the get these values for android < M so we
44
-    // do a best effort polyfill.
45
-    EdgeInsets windowInsets;
13
+  private static @Nullable EdgeInsets getRootWindowInsetsCompat(View rootView) {
46
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
14
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
47
       WindowInsets insets = rootView.getRootWindowInsets();
15
       WindowInsets insets = rootView.getRootWindowInsets();
48
       if (insets == null) {
16
       if (insets == null) {
49
         return null;
17
         return null;
50
       }
18
       }
51
-      windowInsets = new EdgeInsets(
19
+      return new EdgeInsets(
52
           insets.getSystemWindowInsetTop(),
20
           insets.getSystemWindowInsetTop(),
53
           insets.getSystemWindowInsetRight(),
21
           insets.getSystemWindowInsetRight(),
54
           insets.getSystemWindowInsetBottom(),
22
           insets.getSystemWindowInsetBottom(),
55
           insets.getSystemWindowInsetLeft());
23
           insets.getSystemWindowInsetLeft());
56
     } else {
24
     } else {
57
-      int rotation = windowManager.getDefaultDisplay().getRotation();
58
-      int statusBarHeight = 0;
59
-      int resourceId = rootView.getResources().getIdentifier("status_bar_height", "dimen", "android");
60
-      if (resourceId > 0) {
61
-        statusBarHeight = rootView.getResources().getDimensionPixelSize(resourceId);
62
-      }
63
-      int navbarHeight = 0;
64
-      resourceId = rootView.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
65
-      if (resourceId > 0) {
66
-        navbarHeight = rootView.getResources().getDimensionPixelSize(resourceId);
67
-      }
25
+      Rect visibleRect = new Rect();
26
+      rootView.getWindowVisibleDisplayFrame(visibleRect);
27
+      return new EdgeInsets(
28
+          visibleRect.top,
29
+          rootView.getWidth() - visibleRect.right,
30
+          rootView.getHeight() - visibleRect.bottom,
31
+          visibleRect.left);
32
+    }
33
+  }
68
 
34
 
69
-      windowInsets = new EdgeInsets(
70
-          statusBarHeight,
71
-          rotation == Surface.ROTATION_90 ? navbarHeight : 0,
72
-          rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ? navbarHeight : 0,
73
-          rotation == Surface.ROTATION_270 ? navbarHeight : 0);
35
+  static @Nullable EdgeInsets getSafeAreaInsets(View rootView, View view) {
36
+    EdgeInsets windowInsets = getRootWindowInsetsCompat(rootView);
37
+    if (windowInsets == null) {
38
+      return null;
74
     }
39
     }
75
 
40
 
76
-    // Calculate the part of the root view that overlaps with window insets.
77
-    View contentView = rootView.findViewById(android.R.id.content);
41
+    // Calculate the part of the view that overlaps with window insets.
78
     float windowWidth = rootView.getWidth();
42
     float windowWidth = rootView.getWidth();
79
     float windowHeight = rootView.getHeight();
43
     float windowHeight = rootView.getHeight();
80
     Rect visibleRect = new Rect();
44
     Rect visibleRect = new Rect();
81
-    contentView.getGlobalVisibleRect(visibleRect);
45
+    view.getGlobalVisibleRect(visibleRect);
82
 
46
 
83
     windowInsets.top = Math.max(windowInsets.top - visibleRect.top, 0);
47
     windowInsets.top = Math.max(windowInsets.top - visibleRect.top, 0);
84
     windowInsets.left = Math.max(windowInsets.left - visibleRect.left, 0);
48
     windowInsets.left = Math.max(windowInsets.left - visibleRect.left, 0);
85
-    windowInsets.bottom = Math.max(visibleRect.top + contentView.getHeight() + windowInsets.bottom - windowHeight, 0);
86
-    windowInsets.right = Math.max(visibleRect.left + contentView.getWidth() + windowInsets.right - windowWidth, 0);
49
+    windowInsets.bottom = Math.max(visibleRect.top + view.getHeight() + windowInsets.bottom - windowHeight, 0);
50
+    windowInsets.right = Math.max(visibleRect.left + view.getWidth() + windowInsets.right - windowWidth, 0);
87
     return windowInsets;
51
     return windowInsets;
88
   }
52
   }
53
+
54
+  static @Nullable com.th3rdwave.safeareacontext.Rect getFrame(ViewGroup rootView, View view) {
55
+    // This can happen while the view gets unmounted.
56
+    if (view.getParent() == null) {
57
+      return null;
58
+    }
59
+    Rect offset = new Rect();
60
+    view.getDrawingRect(offset);
61
+    try {
62
+      rootView.offsetDescendantRectToMyCoords(view, offset);
63
+    } catch (IllegalArgumentException ex) {
64
+      // This can throw if the view is not a descendant of rootView. This should not
65
+      // happen but avoid potential crashes.
66
+      ex.printStackTrace();
67
+      return null;
68
+    }
69
+
70
+    return new com.th3rdwave.safeareacontext.Rect(offset.left, offset.top, view.getWidth(), view.getHeight());
71
+  }
89
 }
72
 }

+ 15
- 14
android/src/main/java/com/th3rdwave/safeareacontext/SafeAreaView.java View File

1
 package com.th3rdwave.safeareacontext;
1
 package com.th3rdwave.safeareacontext;
2
 
2
 
3
+import android.annotation.SuppressLint;
3
 import android.content.Context;
4
 import android.content.Context;
4
-import android.graphics.Rect;
5
-import android.os.Build;
6
-import android.view.Surface;
7
-import android.view.View;
5
+import android.view.ViewGroup;
8
 import android.view.ViewTreeObserver;
6
 import android.view.ViewTreeObserver;
9
-import android.view.WindowInsets;
10
-import android.view.WindowManager;
11
 
7
 
12
 import com.facebook.infer.annotation.Assertions;
8
 import com.facebook.infer.annotation.Assertions;
13
 import com.facebook.react.views.view.ReactViewGroup;
9
 import com.facebook.react.views.view.ReactViewGroup;
14
 
10
 
15
 import android.support.annotation.Nullable;
11
 import android.support.annotation.Nullable;
16
 
12
 
13
+@SuppressLint("ViewConstructor")
17
 public class SafeAreaView extends ReactViewGroup implements ViewTreeObserver.OnGlobalLayoutListener {
14
 public class SafeAreaView extends ReactViewGroup implements ViewTreeObserver.OnGlobalLayoutListener {
18
   public interface OnInsetsChangeListener {
15
   public interface OnInsetsChangeListener {
19
-    void onInsetsChange(SafeAreaView view, EdgeInsets insets);
16
+    void onInsetsChange(SafeAreaView view, EdgeInsets insets, Rect frame);
20
   }
17
   }
21
 
18
 
22
   private @Nullable OnInsetsChangeListener mInsetsChangeListener;
19
   private @Nullable OnInsetsChangeListener mInsetsChangeListener;
23
-  private final WindowManager mWindowManager;
24
   private @Nullable EdgeInsets mLastInsets;
20
   private @Nullable EdgeInsets mLastInsets;
21
+  private @Nullable Rect mLastFrame;
25
 
22
 
26
-  public SafeAreaView(Context context, WindowManager windowManager) {
23
+  public SafeAreaView(Context context) {
27
     super(context);
24
     super(context);
28
-
29
-    mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
30
   }
25
   }
31
 
26
 
32
   private void maybeUpdateInsets() {
27
   private void maybeUpdateInsets() {
33
-    EdgeInsets edgeInsets = SafeAreaUtils.getSafeAreaInsets(mWindowManager, getRootView());
34
-    if (edgeInsets != null && (mLastInsets == null || !mLastInsets.equalsToEdgeInsets(edgeInsets))) {
35
-      Assertions.assertNotNull(mInsetsChangeListener).onInsetsChange(this, edgeInsets);
28
+    EdgeInsets edgeInsets = SafeAreaUtils.getSafeAreaInsets(getRootView(), this);
29
+    Rect frame = SafeAreaUtils.getFrame((ViewGroup) getRootView(), this);
30
+    if (edgeInsets != null && frame != null &&
31
+        (mLastInsets == null ||
32
+            mLastFrame == null ||
33
+            !mLastInsets.equalsToEdgeInsets(edgeInsets) ||
34
+            !mLastFrame.equalsToRect(frame))) {
35
+      Assertions.assertNotNull(mInsetsChangeListener).onInsetsChange(this, edgeInsets, frame);
36
       mLastInsets = edgeInsets;
36
       mLastInsets = edgeInsets;
37
+      mLastFrame = frame;
37
     }
38
     }
38
   }
39
   }
39
 
40
 

+ 15
- 12
android/src/main/java/com/th3rdwave/safeareacontext/SafeAreaViewManager.java View File

1
 package com.th3rdwave.safeareacontext;
1
 package com.th3rdwave.safeareacontext;
2
 
2
 
3
 import android.app.Activity;
3
 import android.app.Activity;
4
-import android.content.Context;
5
 import android.view.View;
4
 import android.view.View;
6
-import android.view.WindowManager;
5
+import android.view.ViewGroup;
7
 
6
 
8
 import com.facebook.react.bridge.ReactApplicationContext;
7
 import com.facebook.react.bridge.ReactApplicationContext;
9
 import com.facebook.react.common.MapBuilder;
8
 import com.facebook.react.common.MapBuilder;
19
 
18
 
20
 public class SafeAreaViewManager extends ViewGroupManager<SafeAreaView> {
19
 public class SafeAreaViewManager extends ViewGroupManager<SafeAreaView> {
21
   private final ReactApplicationContext mContext;
20
   private final ReactApplicationContext mContext;
22
-  private final WindowManager mWindowManager;
23
 
21
 
24
   public SafeAreaViewManager(ReactApplicationContext context) {
22
   public SafeAreaViewManager(ReactApplicationContext context) {
25
     super();
23
     super();
26
 
24
 
27
     mContext = context;
25
     mContext = context;
28
-    mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
29
   }
26
   }
30
 
27
 
31
   @Override
28
   @Override
37
   @Override
34
   @Override
38
   @NonNull
35
   @NonNull
39
   public SafeAreaView createViewInstance(@NonNull ThemedReactContext context) {
36
   public SafeAreaView createViewInstance(@NonNull ThemedReactContext context) {
40
-    return new SafeAreaView(context, mWindowManager);
37
+    return new SafeAreaView(context);
41
   }
38
   }
42
 
39
 
43
   @Override
40
   @Override
46
         reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
43
         reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
47
     view.setOnInsetsChangeListener(new SafeAreaView.OnInsetsChangeListener() {
44
     view.setOnInsetsChangeListener(new SafeAreaView.OnInsetsChangeListener() {
48
       @Override
45
       @Override
49
-      public void onInsetsChange(SafeAreaView view, EdgeInsets insets) {
50
-        dispatcher.dispatchEvent(new InsetsChangeEvent(view.getId(), insets));
46
+      public void onInsetsChange(SafeAreaView view, EdgeInsets insets, Rect frame) {
47
+        dispatcher.dispatchEvent(new InsetsChangeEvent(view.getId(), insets, frame));
51
       }
48
       }
52
     });
49
     });
53
   }
50
   }
67
       return null;
64
       return null;
68
     }
65
     }
69
 
66
 
70
-    View decorView = activity.getWindow().getDecorView();
67
+    ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
71
     if (decorView == null) {
68
     if (decorView == null) {
72
       return null;
69
       return null;
73
     }
70
     }
74
 
71
 
75
-    EdgeInsets insets = SafeAreaUtils.getSafeAreaInsets(mWindowManager, decorView);
76
-    if (insets == null) {
72
+    View contentView = decorView.findViewById(android.R.id.content);
73
+    EdgeInsets insets = SafeAreaUtils.getSafeAreaInsets(decorView, contentView);
74
+    Rect frame = SafeAreaUtils.getFrame(decorView, contentView);
75
+    if (insets == null || frame == null) {
77
       return null;
76
       return null;
78
     }
77
     }
79
     return MapBuilder.<String, Object>of(
78
     return MapBuilder.<String, Object>of(
80
-        "initialWindowSafeAreaInsets",
81
-        SafeAreaUtils.edgeInsetsToJavaMap(insets));
79
+        "initialWindowMetrics",
80
+        MapBuilder.<String, Object>of(
81
+            "insets",
82
+            SerializationUtils.edgeInsetsToJavaMap(insets),
83
+            "frame",
84
+            SerializationUtils.rectToJavaMap(frame)));
82
 
85
 
83
   }
86
   }
84
 }
87
 }

+ 52
- 0
android/src/main/java/com/th3rdwave/safeareacontext/SerializationUtils.java View File

1
+package com.th3rdwave.safeareacontext;
2
+
3
+import com.facebook.react.bridge.Arguments;
4
+import com.facebook.react.bridge.WritableMap;
5
+import com.facebook.react.common.MapBuilder;
6
+import com.facebook.react.uimanager.PixelUtil;
7
+
8
+import java.util.Map;
9
+
10
+/* package */ class SerializationUtils {
11
+  static WritableMap edgeInsetsToJsMap(EdgeInsets insets) {
12
+    WritableMap insetsMap = Arguments.createMap();
13
+    insetsMap.putDouble("top", PixelUtil.toDIPFromPixel(insets.top));
14
+    insetsMap.putDouble("right", PixelUtil.toDIPFromPixel(insets.right));
15
+    insetsMap.putDouble("bottom", PixelUtil.toDIPFromPixel(insets.bottom));
16
+    insetsMap.putDouble("left", PixelUtil.toDIPFromPixel(insets.left));
17
+    return insetsMap;
18
+  }
19
+
20
+  static Map<String, Float> edgeInsetsToJavaMap(EdgeInsets insets) {
21
+    return MapBuilder.of(
22
+        "top",
23
+        PixelUtil.toDIPFromPixel(insets.top),
24
+        "right",
25
+        PixelUtil.toDIPFromPixel(insets.right),
26
+        "bottom",
27
+        PixelUtil.toDIPFromPixel(insets.bottom),
28
+        "left",
29
+        PixelUtil.toDIPFromPixel(insets.left));
30
+  }
31
+
32
+  static WritableMap rectToJsMap(Rect rect) {
33
+    WritableMap rectMap = Arguments.createMap();
34
+    rectMap.putDouble("x", PixelUtil.toDIPFromPixel(rect.x));
35
+    rectMap.putDouble("y", PixelUtil.toDIPFromPixel(rect.y));
36
+    rectMap.putDouble("width", PixelUtil.toDIPFromPixel(rect.width));
37
+    rectMap.putDouble("height", PixelUtil.toDIPFromPixel(rect.height));
38
+    return rectMap;
39
+  }
40
+
41
+  static Map<String, Float> rectToJavaMap(Rect rect) {
42
+    return MapBuilder.of(
43
+        "x",
44
+        PixelUtil.toDIPFromPixel(rect.x),
45
+        "y",
46
+        PixelUtil.toDIPFromPixel(rect.y),
47
+        "width",
48
+        PixelUtil.toDIPFromPixel(rect.width),
49
+        "height",
50
+        PixelUtil.toDIPFromPixel(rect.height));
51
+  }
52
+}

+ 10
- 0
babel.config.js View File

1
 module.exports = {
1
 module.exports = {
2
   presets: ['module:metro-react-native-babel-preset'],
2
   presets: ['module:metro-react-native-babel-preset'],
3
+  plugins: [
4
+    [
5
+      'module-resolver',
6
+      {
7
+        alias: {
8
+          'react-native-safe-area-context': './src',
9
+        },
10
+      },
11
+    ],
12
+  ],
3
 };
13
 };

+ 0
- 56
example/App.tsx View File

1
-import * as React from 'react';
2
-import { View, Text, StatusBar } from 'react-native';
3
-
4
-// import { SafeAreaProvider, useSafeArea } from 'react-native-safe-area-context'; in your app.
5
-import {
6
-  SafeAreaProvider,
7
-  useSafeArea,
8
-  initialWindowSafeAreaInsets,
9
-} from '../src';
10
-
11
-const Screen = () => {
12
-  const insets = useSafeArea();
13
-
14
-  return (
15
-    <>
16
-      <StatusBar
17
-        barStyle="dark-content"
18
-        translucent
19
-        backgroundColor="transparent"
20
-      />
21
-      <View
22
-        style={{
23
-          flex: 1,
24
-          backgroundColor: 'red',
25
-          paddingTop: insets.top,
26
-          paddingLeft: insets.left,
27
-          paddingBottom: insets.bottom,
28
-          paddingRight: insets.right,
29
-        }}
30
-      >
31
-        <View
32
-          style={{
33
-            flex: 1,
34
-            backgroundColor: 'white',
35
-            alignItems: 'center',
36
-            justifyContent: 'center',
37
-          }}
38
-        >
39
-          <Text>Insets: {JSON.stringify(insets, null, 2)}</Text>
40
-          <Text>
41
-            Initial insets:{' '}
42
-            {JSON.stringify(initialWindowSafeAreaInsets, null, 2)}
43
-          </Text>
44
-        </View>
45
-      </View>
46
-    </>
47
-  );
48
-};
49
-
50
-export default function App() {
51
-  return (
52
-    <SafeAreaProvider>
53
-      <Screen />
54
-    </SafeAreaProvider>
55
-  );
56
-}

+ 23
- 3
example/android/app/build.gradle View File

15
  *   // the name of the generated asset file containing your JS bundle
15
  *   // the name of the generated asset file containing your JS bundle
16
  *   bundleAssetName: "index.android.bundle",
16
  *   bundleAssetName: "index.android.bundle",
17
  *
17
  *
18
- *   // the entry file for bundle generation
18
+ *   // the entry file for bundle generation. If none specified and
19
+ *   // "index.android.js" exists, it will be used. Otherwise "index.js" is
20
+ *   // default. Can be overridden with ENTRY_FILE environment variable.
19
  *   entryFile: "index.android.js",
21
  *   entryFile: "index.android.js",
20
  *
22
  *
21
- *   // https://facebook.github.io/react-native/docs/performance#enable-the-ram-format
23
+ *   // https://reactnative.dev/docs/performance#enable-the-ram-format
22
  *   bundleCommand: "ram-bundle",
24
  *   bundleCommand: "ram-bundle",
23
  *
25
  *
24
  *   // whether to bundle JS and assets in debug mode
26
  *   // whether to bundle JS and assets in debug mode
148
         }
150
         }
149
         release {
151
         release {
150
             // Caution! In production, you need to generate your own keystore file.
152
             // Caution! In production, you need to generate your own keystore file.
151
-            // see https://facebook.github.io/react-native/docs/signed-apk-android.
153
+            // see https://reactnative.dev/docs/signed-apk-android.
152
             signingConfig signingConfigs.debug
154
             signingConfig signingConfigs.debug
153
             minifyEnabled enableProguardInReleaseBuilds
155
             minifyEnabled enableProguardInReleaseBuilds
154
             proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
156
             proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
155
         }
157
         }
156
     }
158
     }
159
+
157
     // applicationVariants are e.g. debug, release
160
     // applicationVariants are e.g. debug, release
158
     applicationVariants.all { variant ->
161
     applicationVariants.all { variant ->
159
         variant.outputs.each { output ->
162
         variant.outputs.each { output ->
181
 
184
 
182
 dependencies {
185
 dependencies {
183
     implementation fileTree(dir: "libs", include: ["*.jar"])
186
     implementation fileTree(dir: "libs", include: ["*.jar"])
187
+    //noinspection GradleDynamicVersion
184
     implementation "com.facebook.react:react-native:+"  // From node_modules
188
     implementation "com.facebook.react:react-native:+"  // From node_modules
185
 
189
 
190
+    implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
191
+    debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
192
+      exclude group:'com.facebook.fbjni'
193
+    }
194
+    debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
195
+        exclude group:'com.facebook.flipper'
196
+    }
197
+    debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
198
+        exclude group:'com.facebook.flipper'
199
+    }
200
+
186
     if (enableHermes) {
201
     if (enableHermes) {
187
       def hermesPath = "../../../node_modules/hermesvm/android/";
202
       def hermesPath = "../../../node_modules/hermesvm/android/";
188
       debugImplementation files(hermesPath + "hermes-debug.aar")
203
       debugImplementation files(hermesPath + "hermes-debug.aar")
191
       implementation jscFlavor
206
       implementation jscFlavor
192
     }
207
     }
193
 
208
 
209
+    implementation project(":react-native-community-async-storage")
210
+    implementation project(":react-native-gesture-handler")
211
+    implementation project(":react-native-reanimated")
212
+    implementation project(":react-native-screens")
213
+
194
     implementation project(":react-native-safe-area-context")
214
     implementation project(":react-native-safe-area-context")
195
 }
215
 }
196
 
216
 

+ 67
- 0
example/android/app/src/debug/java/com/safeareaviewexample/ReactNativeFlipper.java View File

1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * <p>This source code is licensed under the MIT license found in the LICENSE file in the root
5
+ * directory of this source tree.
6
+ */
7
+package com.safeareaviewexample;
8
+import android.content.Context;
9
+import com.facebook.flipper.android.AndroidFlipperClient;
10
+import com.facebook.flipper.android.utils.FlipperUtils;
11
+import com.facebook.flipper.core.FlipperClient;
12
+import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
13
+import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
14
+import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
15
+import com.facebook.flipper.plugins.inspector.DescriptorMapping;
16
+import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
17
+import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
18
+import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
19
+import com.facebook.flipper.plugins.react.ReactFlipperPlugin;
20
+import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
21
+import com.facebook.react.ReactInstanceManager;
22
+import com.facebook.react.bridge.ReactContext;
23
+import com.facebook.react.modules.network.NetworkingModule;
24
+import okhttp3.OkHttpClient;
25
+public class ReactNativeFlipper {
26
+  public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
27
+    if (FlipperUtils.shouldEnableFlipper(context)) {
28
+      final FlipperClient client = AndroidFlipperClient.getInstance(context);
29
+      client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
30
+      client.addPlugin(new ReactFlipperPlugin());
31
+      client.addPlugin(new DatabasesFlipperPlugin(context));
32
+      client.addPlugin(new SharedPreferencesFlipperPlugin(context));
33
+      client.addPlugin(CrashReporterPlugin.getInstance());
34
+      NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
35
+      NetworkingModule.setCustomClientBuilder(
36
+          new NetworkingModule.CustomClientBuilder() {
37
+            @Override
38
+            public void apply(OkHttpClient.Builder builder) {
39
+              builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
40
+            }
41
+          });
42
+      client.addPlugin(networkFlipperPlugin);
43
+      client.start();
44
+      // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
45
+      // Hence we run if after all native modules have been initialized
46
+      ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
47
+      if (reactContext == null) {
48
+        reactInstanceManager.addReactInstanceEventListener(
49
+            new ReactInstanceManager.ReactInstanceEventListener() {
50
+              @Override
51
+              public void onReactContextInitialized(ReactContext reactContext) {
52
+                reactInstanceManager.removeReactInstanceEventListener(this);
53
+                reactContext.runOnNativeModulesQueueThread(
54
+                    new Runnable() {
55
+                      @Override
56
+                      public void run() {
57
+                        client.addPlugin(new FrescoFlipperPlugin());
58
+                      }
59
+                    });
60
+              }
61
+            });
62
+      } else {
63
+        client.addPlugin(new FrescoFlipperPlugin());
64
+      }
65
+    }
66
+  }
67
+}

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

13
       <activity
13
       <activity
14
         android:name=".MainActivity"
14
         android:name=".MainActivity"
15
         android:label="@string/app_name"
15
         android:label="@string/app_name"
16
-        android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
16
+        android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
17
+        android:launchMode="singleTask"
17
         android:windowSoftInputMode="adjustResize">
18
         android:windowSoftInputMode="adjustResize">
18
         <intent-filter>
19
         <intent-filter>
19
             <action android:name="android.intent.action.MAIN" />
20
             <action android:name="android.intent.action.MAIN" />

+ 36
- 0
example/android/app/src/main/java/com/safeareaviewexample/MainActivity.java View File

1
 package com.safeareaviewexample;
1
 package com.safeareaviewexample;
2
 
2
 
3
+import android.os.Bundle;
4
+import android.view.View;
5
+import android.view.WindowManager;
6
+
3
 import com.facebook.react.ReactActivity;
7
 import com.facebook.react.ReactActivity;
8
+import com.facebook.react.ReactActivityDelegate;
9
+import com.facebook.react.ReactRootView;
10
+import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
4
 
11
 
5
 public class MainActivity extends ReactActivity {
12
 public class MainActivity extends ReactActivity {
6
 
13
 
14
+    private static final boolean TEST_TRANSLUCENT_STATUS_BAR = true;
15
+    private static final boolean TEST_TRANSLUCENT_NAVBAR = true;
16
+
7
     /**
17
     /**
8
      * Returns the name of the main component registered from JavaScript.
18
      * Returns the name of the main component registered from JavaScript.
9
      * This is used to schedule rendering of the component.
19
      * This is used to schedule rendering of the component.
12
     protected String getMainComponentName() {
22
     protected String getMainComponentName() {
13
         return "SafeAreaViewExample";
23
         return "SafeAreaViewExample";
14
     }
24
     }
25
+
26
+    @Override
27
+    protected ReactActivityDelegate createReactActivityDelegate() {
28
+      return new ReactActivityDelegate(this, getMainComponentName()) {
29
+        @Override
30
+        protected ReactRootView createRootView() {
31
+          return new RNGestureHandlerEnabledRootView(MainActivity.this);
32
+        }
33
+      };
34
+    }
35
+
36
+    @Override
37
+    protected void onCreate(Bundle savedInstanceState) {
38
+        super.onCreate(savedInstanceState);
39
+
40
+        if (TEST_TRANSLUCENT_STATUS_BAR) {
41
+            getWindow().getDecorView().setSystemUiVisibility(
42
+                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
43
+        }
44
+        if (TEST_TRANSLUCENT_NAVBAR) {
45
+            getWindow().setFlags(
46
+                WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
47
+                WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
48
+        }
49
+
50
+    }
15
 }
51
 }

+ 43
- 0
example/android/app/src/main/java/com/safeareaviewexample/MainApplication.java View File

1
 package com.safeareaviewexample;
1
 package com.safeareaviewexample;
2
 
2
 
3
 import android.app.Application;
3
 import android.app.Application;
4
+import android.content.Context;
4
 
5
 
5
 import com.facebook.react.ReactApplication;
6
 import com.facebook.react.ReactApplication;
7
+import com.facebook.react.ReactInstanceManager;
6
 import com.facebook.react.ReactNativeHost;
8
 import com.facebook.react.ReactNativeHost;
7
 import com.facebook.react.ReactPackage;
9
 import com.facebook.react.ReactPackage;
8
 import com.facebook.react.shell.MainReactPackage;
10
 import com.facebook.react.shell.MainReactPackage;
9
 import com.facebook.soloader.SoLoader;
11
 import com.facebook.soloader.SoLoader;
10
 import com.th3rdwave.safeareacontext.SafeAreaContextPackage;
12
 import com.th3rdwave.safeareacontext.SafeAreaContextPackage;
13
+import com.swmansion.rnscreens.RNScreensPackage;
14
+import com.swmansion.gesturehandler.react.RNGestureHandlerPackage;
15
+import com.swmansion.reanimated.ReanimatedPackage;
16
+import com.reactnativecommunity.asyncstorage.AsyncStoragePackage;
11
 
17
 
18
+import java.lang.reflect.InvocationTargetException;
12
 import java.util.Arrays;
19
 import java.util.Arrays;
13
 import java.util.List;
20
 import java.util.List;
14
 
21
 
24
     protected List<ReactPackage> getPackages() {
31
     protected List<ReactPackage> getPackages() {
25
       return Arrays.asList(
32
       return Arrays.asList(
26
           new MainReactPackage(),
33
           new MainReactPackage(),
34
+          new RNScreensPackage(),
35
+          new RNGestureHandlerPackage(),
36
+          new ReanimatedPackage(),
37
+          new AsyncStoragePackage(),
27
           new SafeAreaContextPackage());
38
           new SafeAreaContextPackage());
28
     }
39
     }
29
 
40
 
42
   public void onCreate() {
53
   public void onCreate() {
43
     super.onCreate();
54
     super.onCreate();
44
     SoLoader.init(this, /* native exopackage */ false);
55
     SoLoader.init(this, /* native exopackage */ false);
56
+    initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
57
+  }
58
+
59
+  /**
60
+   * Loads Flipper in React Native templates. Call this in the onCreate method with something like
61
+   * initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
62
+   *
63
+   * @param context
64
+   * @param reactInstanceManager
65
+   */
66
+  private static void initializeFlipper(
67
+      Context context, ReactInstanceManager reactInstanceManager) {
68
+    if (BuildConfig.DEBUG) {
69
+      try {
70
+        /*
71
+         We use reflection here to pick up the class that initializes Flipper,
72
+         since Flipper library is not available in release mode
73
+        */
74
+        Class<?> aClass = Class.forName("com.safeareaviewexample.ReactNativeFlipper");
75
+        aClass
76
+            .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
77
+            .invoke(null, context, reactInstanceManager);
78
+      } catch (ClassNotFoundException e) {
79
+        e.printStackTrace();
80
+      } catch (NoSuchMethodException e) {
81
+        e.printStackTrace();
82
+      } catch (IllegalAccessException e) {
83
+        e.printStackTrace();
84
+      } catch (InvocationTargetException e) {
85
+        e.printStackTrace();
86
+      }
87
+    }
45
   }
88
   }
46
 }
89
 }

+ 7
- 0
example/android/app/src/main/res/values-v28/styles.xml View File

1
+<?xml version="1.0" encoding="utf-8"?>
2
+<resources>
3
+
4
+    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
5
+        <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
6
+    </style>
7
+</resources>

+ 5
- 6
example/android/build.gradle View File

2
 
2
 
3
 buildscript {
3
 buildscript {
4
     ext {
4
     ext {
5
-        buildToolsVersion = "28.0.3"
5
+        buildToolsVersion = "29.0.2"
6
         minSdkVersion = 16
6
         minSdkVersion = 16
7
-        compileSdkVersion = 28
8
-        targetSdkVersion = 28
9
-        supportLibVersion = "28.0.0"
7
+        compileSdkVersion = 29
8
+        targetSdkVersion = 29
10
     }
9
     }
11
     repositories {
10
     repositories {
12
         google()
11
         google()
13
         jcenter()
12
         jcenter()
14
     }
13
     }
15
     dependencies {
14
     dependencies {
16
-        classpath("com.android.tools.build:gradle:3.4.1")
17
-
15
+        classpath("com.android.tools.build:gradle:3.5.3")
18
         // NOTE: Do not place your application dependencies here; they belong
16
         // NOTE: Do not place your application dependencies here; they belong
19
         // in the individual module build.gradle files
17
         // in the individual module build.gradle files
20
     }
18
     }
34
 
32
 
35
         google()
33
         google()
36
         jcenter()
34
         jcenter()
35
+        maven { url 'https://www.jitpack.io' }
37
     }
36
     }
38
 }
37
 }

+ 6
- 0
example/android/gradle.properties View File

17
 # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17
 # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18
 # org.gradle.parallel=true
18
 # org.gradle.parallel=true
19
 
19
 
20
+# AndroidX package structure to make it clearer which packages are bundled with the
21
+# Android operating system, and which are packaged with your app's APK
22
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
20
 android.useAndroidX=true
23
 android.useAndroidX=true
24
+# Automatically convert third-party libraries to use AndroidX
21
 android.enableJetifier=true
25
 android.enableJetifier=true
26
+# Version of flipper SDK to use with React Native
27
+FLIPPER_VERSION=0.33.1

+ 1
- 1
example/android/gradle/wrapper/gradle-wrapper.properties View File

1
 distributionBase=GRADLE_USER_HOME
1
 distributionBase=GRADLE_USER_HOME
2
 distributionPath=wrapper/dists
2
 distributionPath=wrapper/dists
3
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
3
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.2-all.zip
4
 zipStoreBase=GRADLE_USER_HOME
4
 zipStoreBase=GRADLE_USER_HOME
5
 zipStorePath=wrapper/dists
5
 zipStorePath=wrapper/dists

+ 15
- 20
example/android/gradlew View File

7
 # you may not use this file except in compliance with the License.
7
 # you may not use this file except in compliance with the License.
8
 # You may obtain a copy of the License at
8
 # You may obtain a copy of the License at
9
 #
9
 #
10
-#      http://www.apache.org/licenses/LICENSE-2.0
10
+#      https://www.apache.org/licenses/LICENSE-2.0
11
 #
11
 #
12
 # Unless required by applicable law or agreed to in writing, software
12
 # Unless required by applicable law or agreed to in writing, software
13
 # distributed under the License is distributed on an "AS IS" BASIS,
13
 # distributed under the License is distributed on an "AS IS" BASIS,
125
     GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
125
     GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
126
 fi
126
 fi
127
 
127
 
128
-# For Cygwin, switch paths to Windows format before running java
129
-if $cygwin ; then
128
+# For Cygwin or MSYS, switch paths to Windows format before running java
129
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
130
     APP_HOME=`cygpath --path --mixed "$APP_HOME"`
130
     APP_HOME=`cygpath --path --mixed "$APP_HOME"`
131
     CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
131
     CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
132
     JAVACMD=`cygpath --unix "$JAVACMD"`
132
     JAVACMD=`cygpath --unix "$JAVACMD"`
154
         else
154
         else
155
             eval `echo args$i`="\"$arg\""
155
             eval `echo args$i`="\"$arg\""
156
         fi
156
         fi
157
-        i=$((i+1))
157
+        i=`expr $i + 1`
158
     done
158
     done
159
     case $i in
159
     case $i in
160
-        (0) set -- ;;
161
-        (1) set -- "$args0" ;;
162
-        (2) set -- "$args0" "$args1" ;;
163
-        (3) set -- "$args0" "$args1" "$args2" ;;
164
-        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
165
-        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
166
-        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
167
-        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
168
-        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
169
-        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
160
+        0) set -- ;;
161
+        1) set -- "$args0" ;;
162
+        2) set -- "$args0" "$args1" ;;
163
+        3) set -- "$args0" "$args1" "$args2" ;;
164
+        4) set -- "$args0" "$args1" "$args2" "$args3" ;;
165
+        5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
166
+        6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
167
+        7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
168
+        8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
169
+        9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
170
     esac
170
     esac
171
 fi
171
 fi
172
 
172
 
175
     for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
175
     for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
176
     echo " "
176
     echo " "
177
 }
177
 }
178
-APP_ARGS=$(save "$@")
178
+APP_ARGS=`save "$@"`
179
 
179
 
180
 # Collect all arguments for the java command, following the shell quoting and substitution rules
180
 # Collect all arguments for the java command, following the shell quoting and substitution rules
181
 eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
181
 eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
182
 
182
 
183
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
184
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
185
-  cd "$(dirname "$0")"
186
-fi
187
-
188
 exec "$JAVACMD" "$@"
183
 exec "$JAVACMD" "$@"

+ 4
- 1
example/android/gradlew.bat View File

5
 @rem you may not use this file except in compliance with the License.
5
 @rem you may not use this file except in compliance with the License.
6
 @rem You may obtain a copy of the License at
6
 @rem You may obtain a copy of the License at
7
 @rem
7
 @rem
8
-@rem      http://www.apache.org/licenses/LICENSE-2.0
8
+@rem      https://www.apache.org/licenses/LICENSE-2.0
9
 @rem
9
 @rem
10
 @rem Unless required by applicable law or agreed to in writing, software
10
 @rem Unless required by applicable law or agreed to in writing, software
11
 @rem distributed under the License is distributed on an "AS IS" BASIS,
11
 @rem distributed under the License is distributed on an "AS IS" BASIS,
29
 set APP_BASE_NAME=%~n0
29
 set APP_BASE_NAME=%~n0
30
 set APP_HOME=%DIRNAME%
30
 set APP_HOME=%DIRNAME%
31
 
31
 
32
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
33
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34
+
32
 @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
35
 @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
33
 set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
36
 set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
34
 
37
 

+ 9
- 0
example/android/settings.gradle View File

3
 
3
 
4
 include ':react-native-safe-area-context'
4
 include ':react-native-safe-area-context'
5
 project(':react-native-safe-area-context').projectDir = new File(rootProject.projectDir, '../../android')
5
 project(':react-native-safe-area-context').projectDir = new File(rootProject.projectDir, '../../android')
6
+
7
+include ':react-native-community-async-storage'
8
+project(':react-native-community-async-storage').projectDir = new File(rootProject.projectDir, '../../node_modules/@react-native-community/async-storage/android')
9
+include ':react-native-gesture-handler'
10
+project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, '../../node_modules/react-native-gesture-handler/android')
11
+include ':react-native-reanimated'
12
+project(':react-native-reanimated').projectDir = new File(rootProject.projectDir, '../../node_modules/react-native-reanimated/android')
13
+include ':react-native-screens'
14
+project(':react-native-screens').projectDir = new File(rootProject.projectDir, '../../node_modules/react-native-screens/android')

+ 1
- 1
example/app.json View File

2
   "name": "SafeAreaViewExample",
2
   "name": "SafeAreaViewExample",
3
   "displayName": "SafeAreaViewExample",
3
   "displayName": "SafeAreaViewExample",
4
   "expo": {
4
   "expo": {
5
-    "entryPoint": "node_modules/expo/AppEntry",
5
+    "entryPoint": "./example/index.expo",
6
     "name": "react-native-safe-area-context",
6
     "name": "react-native-safe-area-context",
7
     "slug": "react-native-safe-area-context",
7
     "slug": "react-native-safe-area-context",
8
     "version": "0.1.0",
8
     "version": "0.1.0",

+ 5
- 0
example/index.expo.js View File

1
+import registerRootComponent from 'expo/build/launch/registerRootComponent';
2
+
3
+import App from './src/App';
4
+
5
+registerRootComponent(App);

+ 1
- 1
example/index.js View File

1
 import { AppRegistry } from 'react-native';
1
 import { AppRegistry } from 'react-native';
2
-import App from './App';
2
+import App from './src/App';
3
 import { name as appName } from './app.json';
3
 import { name as appName } from './app.json';
4
 
4
 
5
 AppRegistry.registerComponent(appName, () => App);
5
 AppRegistry.registerComponent(appName, () => App);

+ 15
- 32
example/ios/Podfile View File

1
-platform :ios, '9.0'
1
+$root_path = "../.."
2
+$node_modules = "#{$root_path}/node_modules"
3
+$react_native_path = "#{$node_modules}/react-native"
2
 
4
 
3
-target 'SafeAreaViewExample' do
4
-  # Pods for SafeAreaViewExample
5
-  pod 'FBLazyVector', :path => "../../node_modules/react-native/Libraries/FBLazyVector"
6
-  pod 'FBReactNativeSpec', :path => "../../node_modules/react-native/Libraries/FBReactNativeSpec"
7
-  pod 'RCTRequired', :path => "../../node_modules/react-native/Libraries/RCTRequired"
8
-  pod 'RCTTypeSafety', :path => "../../node_modules/react-native/Libraries/TypeSafety"
9
-  pod 'React', :path => '../../node_modules/react-native/'
10
-  pod 'React-Core', :path => '../../node_modules/react-native/'
11
-  pod 'React-CoreModules', :path => '../../node_modules/react-native/React/CoreModules'
12
-  pod 'React-Core/DevSupport', :path => '../../node_modules/react-native/'
13
-  pod 'React-RCTActionSheet', :path => '../../node_modules/react-native/Libraries/ActionSheetIOS'
14
-  pod 'React-RCTAnimation', :path => '../../node_modules/react-native/Libraries/NativeAnimation'
15
-  pod 'React-RCTBlob', :path => '../../node_modules/react-native/Libraries/Blob'
16
-  pod 'React-RCTImage', :path => '../../node_modules/react-native/Libraries/Image'
17
-  pod 'React-RCTLinking', :path => '../../node_modules/react-native/Libraries/LinkingIOS'
18
-  pod 'React-RCTNetwork', :path => '../../node_modules/react-native/Libraries/Network'
19
-  pod 'React-RCTSettings', :path => '../../node_modules/react-native/Libraries/Settings'
20
-  pod 'React-RCTText', :path => '../../node_modules/react-native/Libraries/Text'
21
-  pod 'React-RCTVibration', :path => '../../node_modules/react-native/Libraries/Vibration'
22
-  pod 'React-Core/RCTWebSocket', :path => '../../node_modules/react-native/'
5
+require_relative "#{$node_modules}/react-native/scripts/react_native_pods"
6
+require_relative "#{$node_modules}/@react-native-community/cli-platform-ios/native_modules"
23
 
7
 
24
-  pod 'React-cxxreact', :path => '../../node_modules/react-native/ReactCommon/cxxreact'
25
-  pod 'React-jsi', :path => '../../node_modules/react-native/ReactCommon/jsi'
26
-  pod 'React-jsiexecutor', :path => '../../node_modules/react-native/ReactCommon/jsiexecutor'
27
-  pod 'React-jsinspector', :path => '../../node_modules/react-native/ReactCommon/jsinspector'
28
-  pod 'ReactCommon/jscallinvoker', :path => "../../node_modules/react-native/ReactCommon"
29
-  pod 'ReactCommon/turbomodule/core', :path => "../../node_modules/react-native/ReactCommon"
30
-  pod 'Yoga', :path => '../../node_modules/react-native/ReactCommon/yoga'
8
+platform :ios, "10.0"
31
 
9
 
32
-  pod 'DoubleConversion', :podspec => '../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
33
-  pod 'glog', :podspec => '../../node_modules/react-native/third-party-podspecs/glog.podspec'
34
-  pod 'Folly', :podspec => '../../node_modules/react-native/third-party-podspecs/Folly.podspec'
10
+target "SafeAreaViewExample" do
11
+  use_react_native!(path: $react_native_path)
35
 
12
 
36
-  pod 'react-native-safe-area-context', :path => '../../'
13
+  pod "react-native-safe-area-context", :path => $root_path
14
+  pod "RNCAsyncStorage", :path => "#{$node_modules}/@react-native-community/async-storage"
15
+  pod "RNCMaskedView", :path => "#{$node_modules}/@react-native-community/masked-view"
16
+  pod "RNGestureHandler", :path => "#{$node_modules}/react-native-gesture-handler"
17
+  pod "RNReanimated", :path => "#{$node_modules}/react-native-reanimated"
18
+  pod "RNScreens", :path => "#{$node_modules}/react-native-screens"
37
 end
19
 end
20
+

+ 251
- 190
example/ios/Podfile.lock View File

1
 PODS:
1
 PODS:
2
   - boost-for-react-native (1.63.0)
2
   - boost-for-react-native (1.63.0)
3
   - DoubleConversion (1.1.6)
3
   - DoubleConversion (1.1.6)
4
-  - FBLazyVector (0.61.5)
5
-  - FBReactNativeSpec (0.61.5):
6
-    - Folly (= 2018.10.22.00)
7
-    - RCTRequired (= 0.61.5)
8
-    - RCTTypeSafety (= 0.61.5)
9
-    - React-Core (= 0.61.5)
10
-    - React-jsi (= 0.61.5)
11
-    - ReactCommon/turbomodule/core (= 0.61.5)
12
-  - Folly (2018.10.22.00):
4
+  - FBLazyVector (0.63.0-rc.0)
5
+  - FBReactNativeSpec (0.63.0-rc.0):
6
+    - Folly (= 2020.01.13.00)
7
+    - RCTRequired (= 0.63.0-rc.0)
8
+    - RCTTypeSafety (= 0.63.0-rc.0)
9
+    - React-Core (= 0.63.0-rc.0)
10
+    - React-jsi (= 0.63.0-rc.0)
11
+    - ReactCommon/turbomodule/core (= 0.63.0-rc.0)
12
+  - Folly (2020.01.13.00):
13
     - boost-for-react-native
13
     - boost-for-react-native
14
     - DoubleConversion
14
     - DoubleConversion
15
-    - Folly/Default (= 2018.10.22.00)
15
+    - Folly/Default (= 2020.01.13.00)
16
     - glog
16
     - glog
17
-  - Folly/Default (2018.10.22.00):
17
+  - Folly/Default (2020.01.13.00):
18
     - boost-for-react-native
18
     - boost-for-react-native
19
     - DoubleConversion
19
     - DoubleConversion
20
     - glog
20
     - glog
21
   - glog (0.3.5)
21
   - glog (0.3.5)
22
-  - RCTRequired (0.61.5)
23
-  - RCTTypeSafety (0.61.5):
24
-    - FBLazyVector (= 0.61.5)
25
-    - Folly (= 2018.10.22.00)
26
-    - RCTRequired (= 0.61.5)
27
-    - React-Core (= 0.61.5)
28
-  - React (0.61.5):
29
-    - React-Core (= 0.61.5)
30
-    - React-Core/DevSupport (= 0.61.5)
31
-    - React-Core/RCTWebSocket (= 0.61.5)
32
-    - React-RCTActionSheet (= 0.61.5)
33
-    - React-RCTAnimation (= 0.61.5)
34
-    - React-RCTBlob (= 0.61.5)
35
-    - React-RCTImage (= 0.61.5)
36
-    - React-RCTLinking (= 0.61.5)
37
-    - React-RCTNetwork (= 0.61.5)
38
-    - React-RCTSettings (= 0.61.5)
39
-    - React-RCTText (= 0.61.5)
40
-    - React-RCTVibration (= 0.61.5)
41
-  - React-Core (0.61.5):
42
-    - Folly (= 2018.10.22.00)
22
+  - RCTRequired (0.63.0-rc.0)
23
+  - RCTTypeSafety (0.63.0-rc.0):
24
+    - FBLazyVector (= 0.63.0-rc.0)
25
+    - Folly (= 2020.01.13.00)
26
+    - RCTRequired (= 0.63.0-rc.0)
27
+    - React-Core (= 0.63.0-rc.0)
28
+  - React (0.63.0-rc.0):
29
+    - React-Core (= 0.63.0-rc.0)
30
+    - React-Core/DevSupport (= 0.63.0-rc.0)
31
+    - React-Core/RCTWebSocket (= 0.63.0-rc.0)
32
+    - React-RCTActionSheet (= 0.63.0-rc.0)
33
+    - React-RCTAnimation (= 0.63.0-rc.0)
34
+    - React-RCTBlob (= 0.63.0-rc.0)
35
+    - React-RCTImage (= 0.63.0-rc.0)
36
+    - React-RCTLinking (= 0.63.0-rc.0)
37
+    - React-RCTNetwork (= 0.63.0-rc.0)
38
+    - React-RCTSettings (= 0.63.0-rc.0)
39
+    - React-RCTText (= 0.63.0-rc.0)
40
+    - React-RCTVibration (= 0.63.0-rc.0)
41
+  - React-callinvoker (0.63.0-rc.0)
42
+  - React-Core (0.63.0-rc.0):
43
+    - Folly (= 2020.01.13.00)
43
     - glog
44
     - glog
44
-    - React-Core/Default (= 0.61.5)
45
-    - React-cxxreact (= 0.61.5)
46
-    - React-jsi (= 0.61.5)
47
-    - React-jsiexecutor (= 0.61.5)
45
+    - React-Core/Default (= 0.63.0-rc.0)
46
+    - React-cxxreact (= 0.63.0-rc.0)
47
+    - React-jsi (= 0.63.0-rc.0)
48
+    - React-jsiexecutor (= 0.63.0-rc.0)
48
     - Yoga
49
     - Yoga
49
-  - React-Core/CoreModulesHeaders (0.61.5):
50
-    - Folly (= 2018.10.22.00)
50
+  - React-Core/CoreModulesHeaders (0.63.0-rc.0):
51
+    - Folly (= 2020.01.13.00)
51
     - glog
52
     - glog
52
     - React-Core/Default
53
     - React-Core/Default
53
-    - React-cxxreact (= 0.61.5)
54
-    - React-jsi (= 0.61.5)
55
-    - React-jsiexecutor (= 0.61.5)
54
+    - React-cxxreact (= 0.63.0-rc.0)
55
+    - React-jsi (= 0.63.0-rc.0)
56
+    - React-jsiexecutor (= 0.63.0-rc.0)
56
     - Yoga
57
     - Yoga
57
-  - React-Core/Default (0.61.5):
58
-    - Folly (= 2018.10.22.00)
58
+  - React-Core/Default (0.63.0-rc.0):
59
+    - Folly (= 2020.01.13.00)
59
     - glog
60
     - glog
60
-    - React-cxxreact (= 0.61.5)
61
-    - React-jsi (= 0.61.5)
62
-    - React-jsiexecutor (= 0.61.5)
61
+    - React-cxxreact (= 0.63.0-rc.0)
62
+    - React-jsi (= 0.63.0-rc.0)
63
+    - React-jsiexecutor (= 0.63.0-rc.0)
63
     - Yoga
64
     - Yoga
64
-  - React-Core/DevSupport (0.61.5):
65
-    - Folly (= 2018.10.22.00)
65
+  - React-Core/DevSupport (0.63.0-rc.0):
66
+    - Folly (= 2020.01.13.00)
66
     - glog
67
     - glog
67
-    - React-Core/Default (= 0.61.5)
68
-    - React-Core/RCTWebSocket (= 0.61.5)
69
-    - React-cxxreact (= 0.61.5)
70
-    - React-jsi (= 0.61.5)
71
-    - React-jsiexecutor (= 0.61.5)
72
-    - React-jsinspector (= 0.61.5)
68
+    - React-Core/Default (= 0.63.0-rc.0)
69
+    - React-Core/RCTWebSocket (= 0.63.0-rc.0)
70
+    - React-cxxreact (= 0.63.0-rc.0)
71
+    - React-jsi (= 0.63.0-rc.0)
72
+    - React-jsiexecutor (= 0.63.0-rc.0)
73
+    - React-jsinspector (= 0.63.0-rc.0)
73
     - Yoga
74
     - Yoga
74
-  - React-Core/RCTActionSheetHeaders (0.61.5):
75
-    - Folly (= 2018.10.22.00)
75
+  - React-Core/RCTActionSheetHeaders (0.63.0-rc.0):
76
+    - Folly (= 2020.01.13.00)
76
     - glog
77
     - glog
77
     - React-Core/Default
78
     - React-Core/Default
78
-    - React-cxxreact (= 0.61.5)
79
-    - React-jsi (= 0.61.5)
80
-    - React-jsiexecutor (= 0.61.5)
79
+    - React-cxxreact (= 0.63.0-rc.0)
80
+    - React-jsi (= 0.63.0-rc.0)
81
+    - React-jsiexecutor (= 0.63.0-rc.0)
81
     - Yoga
82
     - Yoga
82
-  - React-Core/RCTAnimationHeaders (0.61.5):
83
-    - Folly (= 2018.10.22.00)
83
+  - React-Core/RCTAnimationHeaders (0.63.0-rc.0):
84
+    - Folly (= 2020.01.13.00)
84
     - glog
85
     - glog
85
     - React-Core/Default
86
     - React-Core/Default
86
-    - React-cxxreact (= 0.61.5)
87
-    - React-jsi (= 0.61.5)
88
-    - React-jsiexecutor (= 0.61.5)
87
+    - React-cxxreact (= 0.63.0-rc.0)
88
+    - React-jsi (= 0.63.0-rc.0)
89
+    - React-jsiexecutor (= 0.63.0-rc.0)
89
     - Yoga
90
     - Yoga
90
-  - React-Core/RCTBlobHeaders (0.61.5):
91
-    - Folly (= 2018.10.22.00)
91
+  - React-Core/RCTBlobHeaders (0.63.0-rc.0):
92
+    - Folly (= 2020.01.13.00)
92
     - glog
93
     - glog
93
     - React-Core/Default
94
     - React-Core/Default
94
-    - React-cxxreact (= 0.61.5)
95
-    - React-jsi (= 0.61.5)
96
-    - React-jsiexecutor (= 0.61.5)
95
+    - React-cxxreact (= 0.63.0-rc.0)
96
+    - React-jsi (= 0.63.0-rc.0)
97
+    - React-jsiexecutor (= 0.63.0-rc.0)
97
     - Yoga
98
     - Yoga
98
-  - React-Core/RCTImageHeaders (0.61.5):
99
-    - Folly (= 2018.10.22.00)
99
+  - React-Core/RCTImageHeaders (0.63.0-rc.0):
100
+    - Folly (= 2020.01.13.00)
100
     - glog
101
     - glog
101
     - React-Core/Default
102
     - React-Core/Default
102
-    - React-cxxreact (= 0.61.5)
103
-    - React-jsi (= 0.61.5)
104
-    - React-jsiexecutor (= 0.61.5)
103
+    - React-cxxreact (= 0.63.0-rc.0)
104
+    - React-jsi (= 0.63.0-rc.0)
105
+    - React-jsiexecutor (= 0.63.0-rc.0)
105
     - Yoga
106
     - Yoga
106
-  - React-Core/RCTLinkingHeaders (0.61.5):
107
-    - Folly (= 2018.10.22.00)
107
+  - React-Core/RCTLinkingHeaders (0.63.0-rc.0):
108
+    - Folly (= 2020.01.13.00)
108
     - glog
109
     - glog
109
     - React-Core/Default
110
     - React-Core/Default
110
-    - React-cxxreact (= 0.61.5)
111
-    - React-jsi (= 0.61.5)
112
-    - React-jsiexecutor (= 0.61.5)
111
+    - React-cxxreact (= 0.63.0-rc.0)
112
+    - React-jsi (= 0.63.0-rc.0)
113
+    - React-jsiexecutor (= 0.63.0-rc.0)
113
     - Yoga
114
     - Yoga
114
-  - React-Core/RCTNetworkHeaders (0.61.5):
115
-    - Folly (= 2018.10.22.00)
115
+  - React-Core/RCTNetworkHeaders (0.63.0-rc.0):
116
+    - Folly (= 2020.01.13.00)
116
     - glog
117
     - glog
117
     - React-Core/Default
118
     - React-Core/Default
118
-    - React-cxxreact (= 0.61.5)
119
-    - React-jsi (= 0.61.5)
120
-    - React-jsiexecutor (= 0.61.5)
119
+    - React-cxxreact (= 0.63.0-rc.0)
120
+    - React-jsi (= 0.63.0-rc.0)
121
+    - React-jsiexecutor (= 0.63.0-rc.0)
121
     - Yoga
122
     - Yoga
122
-  - React-Core/RCTSettingsHeaders (0.61.5):
123
-    - Folly (= 2018.10.22.00)
123
+  - React-Core/RCTSettingsHeaders (0.63.0-rc.0):
124
+    - Folly (= 2020.01.13.00)
124
     - glog
125
     - glog
125
     - React-Core/Default
126
     - React-Core/Default
126
-    - React-cxxreact (= 0.61.5)
127
-    - React-jsi (= 0.61.5)
128
-    - React-jsiexecutor (= 0.61.5)
127
+    - React-cxxreact (= 0.63.0-rc.0)
128
+    - React-jsi (= 0.63.0-rc.0)
129
+    - React-jsiexecutor (= 0.63.0-rc.0)
129
     - Yoga
130
     - Yoga
130
-  - React-Core/RCTTextHeaders (0.61.5):
131
-    - Folly (= 2018.10.22.00)
131
+  - React-Core/RCTTextHeaders (0.63.0-rc.0):
132
+    - Folly (= 2020.01.13.00)
132
     - glog
133
     - glog
133
     - React-Core/Default
134
     - React-Core/Default
134
-    - React-cxxreact (= 0.61.5)
135
-    - React-jsi (= 0.61.5)
136
-    - React-jsiexecutor (= 0.61.5)
135
+    - React-cxxreact (= 0.63.0-rc.0)
136
+    - React-jsi (= 0.63.0-rc.0)
137
+    - React-jsiexecutor (= 0.63.0-rc.0)
137
     - Yoga
138
     - Yoga
138
-  - React-Core/RCTVibrationHeaders (0.61.5):
139
-    - Folly (= 2018.10.22.00)
139
+  - React-Core/RCTVibrationHeaders (0.63.0-rc.0):
140
+    - Folly (= 2020.01.13.00)
140
     - glog
141
     - glog
141
     - React-Core/Default
142
     - React-Core/Default
142
-    - React-cxxreact (= 0.61.5)
143
-    - React-jsi (= 0.61.5)
144
-    - React-jsiexecutor (= 0.61.5)
143
+    - React-cxxreact (= 0.63.0-rc.0)
144
+    - React-jsi (= 0.63.0-rc.0)
145
+    - React-jsiexecutor (= 0.63.0-rc.0)
145
     - Yoga
146
     - Yoga
146
-  - React-Core/RCTWebSocket (0.61.5):
147
-    - Folly (= 2018.10.22.00)
147
+  - React-Core/RCTWebSocket (0.63.0-rc.0):
148
+    - Folly (= 2020.01.13.00)
148
     - glog
149
     - glog
149
-    - React-Core/Default (= 0.61.5)
150
-    - React-cxxreact (= 0.61.5)
151
-    - React-jsi (= 0.61.5)
152
-    - React-jsiexecutor (= 0.61.5)
150
+    - React-Core/Default (= 0.63.0-rc.0)
151
+    - React-cxxreact (= 0.63.0-rc.0)
152
+    - React-jsi (= 0.63.0-rc.0)
153
+    - React-jsiexecutor (= 0.63.0-rc.0)
153
     - Yoga
154
     - Yoga
154
-  - React-CoreModules (0.61.5):
155
-    - FBReactNativeSpec (= 0.61.5)
156
-    - Folly (= 2018.10.22.00)
157
-    - RCTTypeSafety (= 0.61.5)
158
-    - React-Core/CoreModulesHeaders (= 0.61.5)
159
-    - React-RCTImage (= 0.61.5)
160
-    - ReactCommon/turbomodule/core (= 0.61.5)
161
-  - React-cxxreact (0.61.5):
155
+  - React-CoreModules (0.63.0-rc.0):
156
+    - FBReactNativeSpec (= 0.63.0-rc.0)
157
+    - Folly (= 2020.01.13.00)
158
+    - RCTTypeSafety (= 0.63.0-rc.0)
159
+    - React-Core/CoreModulesHeaders (= 0.63.0-rc.0)
160
+    - React-jsi (= 0.63.0-rc.0)
161
+    - React-RCTImage (= 0.63.0-rc.0)
162
+    - ReactCommon/turbomodule/core (= 0.63.0-rc.0)
163
+  - React-cxxreact (0.63.0-rc.0):
162
     - boost-for-react-native (= 1.63.0)
164
     - boost-for-react-native (= 1.63.0)
163
     - DoubleConversion
165
     - DoubleConversion
164
-    - Folly (= 2018.10.22.00)
166
+    - Folly (= 2020.01.13.00)
165
     - glog
167
     - glog
166
-    - React-jsinspector (= 0.61.5)
167
-  - React-jsi (0.61.5):
168
+    - React-callinvoker (= 0.63.0-rc.0)
169
+    - React-jsinspector (= 0.63.0-rc.0)
170
+  - React-jsi (0.63.0-rc.0):
168
     - boost-for-react-native (= 1.63.0)
171
     - boost-for-react-native (= 1.63.0)
169
     - DoubleConversion
172
     - DoubleConversion
170
-    - Folly (= 2018.10.22.00)
173
+    - Folly (= 2020.01.13.00)
171
     - glog
174
     - glog
172
-    - React-jsi/Default (= 0.61.5)
173
-  - React-jsi/Default (0.61.5):
175
+    - React-jsi/Default (= 0.63.0-rc.0)
176
+  - React-jsi/Default (0.63.0-rc.0):
174
     - boost-for-react-native (= 1.63.0)
177
     - boost-for-react-native (= 1.63.0)
175
     - DoubleConversion
178
     - DoubleConversion
176
-    - Folly (= 2018.10.22.00)
179
+    - Folly (= 2020.01.13.00)
177
     - glog
180
     - glog
178
-  - React-jsiexecutor (0.61.5):
181
+  - React-jsiexecutor (0.63.0-rc.0):
179
     - DoubleConversion
182
     - DoubleConversion
180
-    - Folly (= 2018.10.22.00)
183
+    - Folly (= 2020.01.13.00)
181
     - glog
184
     - glog
182
-    - React-cxxreact (= 0.61.5)
183
-    - React-jsi (= 0.61.5)
184
-  - React-jsinspector (0.61.5)
185
-  - react-native-safe-area-context (0.6.4):
185
+    - React-cxxreact (= 0.63.0-rc.0)
186
+    - React-jsi (= 0.63.0-rc.0)
187
+  - React-jsinspector (0.63.0-rc.0)
188
+  - react-native-safe-area-context (1.0.0):
186
     - React
189
     - React
187
-  - React-RCTActionSheet (0.61.5):
188
-    - React-Core/RCTActionSheetHeaders (= 0.61.5)
189
-  - React-RCTAnimation (0.61.5):
190
-    - React-Core/RCTAnimationHeaders (= 0.61.5)
191
-  - React-RCTBlob (0.61.5):
192
-    - React-Core/RCTBlobHeaders (= 0.61.5)
193
-    - React-Core/RCTWebSocket (= 0.61.5)
194
-    - React-jsi (= 0.61.5)
195
-    - React-RCTNetwork (= 0.61.5)
196
-  - React-RCTImage (0.61.5):
197
-    - React-Core/RCTImageHeaders (= 0.61.5)
198
-    - React-RCTNetwork (= 0.61.5)
199
-  - React-RCTLinking (0.61.5):
200
-    - React-Core/RCTLinkingHeaders (= 0.61.5)
201
-  - React-RCTNetwork (0.61.5):
202
-    - React-Core/RCTNetworkHeaders (= 0.61.5)
203
-  - React-RCTSettings (0.61.5):
204
-    - React-Core/RCTSettingsHeaders (= 0.61.5)
205
-  - React-RCTText (0.61.5):
206
-    - React-Core/RCTTextHeaders (= 0.61.5)
207
-  - React-RCTVibration (0.61.5):
208
-    - React-Core/RCTVibrationHeaders (= 0.61.5)
209
-  - ReactCommon/jscallinvoker (0.61.5):
190
+  - React-RCTActionSheet (0.63.0-rc.0):
191
+    - React-Core/RCTActionSheetHeaders (= 0.63.0-rc.0)
192
+  - React-RCTAnimation (0.63.0-rc.0):
193
+    - FBReactNativeSpec (= 0.63.0-rc.0)
194
+    - Folly (= 2020.01.13.00)
195
+    - RCTTypeSafety (= 0.63.0-rc.0)
196
+    - React-Core/RCTAnimationHeaders (= 0.63.0-rc.0)
197
+    - React-jsi (= 0.63.0-rc.0)
198
+    - ReactCommon/turbomodule/core (= 0.63.0-rc.0)
199
+  - React-RCTBlob (0.63.0-rc.0):
200
+    - FBReactNativeSpec (= 0.63.0-rc.0)
201
+    - Folly (= 2020.01.13.00)
202
+    - React-Core/RCTBlobHeaders (= 0.63.0-rc.0)
203
+    - React-Core/RCTWebSocket (= 0.63.0-rc.0)
204
+    - React-jsi (= 0.63.0-rc.0)
205
+    - React-RCTNetwork (= 0.63.0-rc.0)
206
+    - ReactCommon/turbomodule/core (= 0.63.0-rc.0)
207
+  - React-RCTImage (0.63.0-rc.0):
208
+    - FBReactNativeSpec (= 0.63.0-rc.0)
209
+    - Folly (= 2020.01.13.00)
210
+    - RCTTypeSafety (= 0.63.0-rc.0)
211
+    - React-Core/RCTImageHeaders (= 0.63.0-rc.0)
212
+    - React-jsi (= 0.63.0-rc.0)
213
+    - React-RCTNetwork (= 0.63.0-rc.0)
214
+    - ReactCommon/turbomodule/core (= 0.63.0-rc.0)
215
+  - React-RCTLinking (0.63.0-rc.0):
216
+    - FBReactNativeSpec (= 0.63.0-rc.0)
217
+    - React-Core/RCTLinkingHeaders (= 0.63.0-rc.0)
218
+    - React-jsi (= 0.63.0-rc.0)
219
+    - ReactCommon/turbomodule/core (= 0.63.0-rc.0)
220
+  - React-RCTNetwork (0.63.0-rc.0):
221
+    - FBReactNativeSpec (= 0.63.0-rc.0)
222
+    - Folly (= 2020.01.13.00)
223
+    - RCTTypeSafety (= 0.63.0-rc.0)
224
+    - React-Core/RCTNetworkHeaders (= 0.63.0-rc.0)
225
+    - React-jsi (= 0.63.0-rc.0)
226
+    - ReactCommon/turbomodule/core (= 0.63.0-rc.0)
227
+  - React-RCTSettings (0.63.0-rc.0):
228
+    - FBReactNativeSpec (= 0.63.0-rc.0)
229
+    - Folly (= 2020.01.13.00)
230
+    - RCTTypeSafety (= 0.63.0-rc.0)
231
+    - React-Core/RCTSettingsHeaders (= 0.63.0-rc.0)
232
+    - React-jsi (= 0.63.0-rc.0)
233
+    - ReactCommon/turbomodule/core (= 0.63.0-rc.0)
234
+  - React-RCTText (0.63.0-rc.0):
235
+    - React-Core/RCTTextHeaders (= 0.63.0-rc.0)
236
+  - React-RCTVibration (0.63.0-rc.0):
237
+    - FBReactNativeSpec (= 0.63.0-rc.0)
238
+    - Folly (= 2020.01.13.00)
239
+    - React-Core/RCTVibrationHeaders (= 0.63.0-rc.0)
240
+    - React-jsi (= 0.63.0-rc.0)
241
+    - ReactCommon/turbomodule/core (= 0.63.0-rc.0)
242
+  - ReactCommon/turbomodule/core (0.63.0-rc.0):
210
     - DoubleConversion
243
     - DoubleConversion
211
-    - Folly (= 2018.10.22.00)
244
+    - Folly (= 2020.01.13.00)
212
     - glog
245
     - glog
213
-    - React-cxxreact (= 0.61.5)
214
-  - ReactCommon/turbomodule/core (0.61.5):
215
-    - DoubleConversion
216
-    - Folly (= 2018.10.22.00)
217
-    - glog
218
-    - React-Core (= 0.61.5)
219
-    - React-cxxreact (= 0.61.5)
220
-    - React-jsi (= 0.61.5)
221
-    - ReactCommon/jscallinvoker (= 0.61.5)
246
+    - React-callinvoker (= 0.63.0-rc.0)
247
+    - React-Core (= 0.63.0-rc.0)
248
+    - React-cxxreact (= 0.63.0-rc.0)
249
+    - React-jsi (= 0.63.0-rc.0)
250
+  - RNCAsyncStorage (1.10.1):
251
+    - React
252
+  - RNCMaskedView (0.1.10):
253
+    - React
254
+  - RNGestureHandler (1.6.1):
255
+    - React
256
+  - RNReanimated (1.8.0):
257
+    - React
258
+  - RNScreens (2.7.0):
259
+    - React
222
   - Yoga (1.14.0)
260
   - Yoga (1.14.0)
223
 
261
 
224
 DEPENDENCIES:
262
 DEPENDENCIES:
230
   - RCTRequired (from `../../node_modules/react-native/Libraries/RCTRequired`)
268
   - RCTRequired (from `../../node_modules/react-native/Libraries/RCTRequired`)
231
   - RCTTypeSafety (from `../../node_modules/react-native/Libraries/TypeSafety`)
269
   - RCTTypeSafety (from `../../node_modules/react-native/Libraries/TypeSafety`)
232
   - React (from `../../node_modules/react-native/`)
270
   - React (from `../../node_modules/react-native/`)
271
+  - React-callinvoker (from `../../node_modules/react-native/ReactCommon/callinvoker`)
233
   - React-Core (from `../../node_modules/react-native/`)
272
   - React-Core (from `../../node_modules/react-native/`)
234
   - React-Core/DevSupport (from `../../node_modules/react-native/`)
273
   - React-Core/DevSupport (from `../../node_modules/react-native/`)
235
   - React-Core/RCTWebSocket (from `../../node_modules/react-native/`)
274
   - React-Core/RCTWebSocket (from `../../node_modules/react-native/`)
238
   - React-jsi (from `../../node_modules/react-native/ReactCommon/jsi`)
277
   - React-jsi (from `../../node_modules/react-native/ReactCommon/jsi`)
239
   - React-jsiexecutor (from `../../node_modules/react-native/ReactCommon/jsiexecutor`)
278
   - React-jsiexecutor (from `../../node_modules/react-native/ReactCommon/jsiexecutor`)
240
   - React-jsinspector (from `../../node_modules/react-native/ReactCommon/jsinspector`)
279
   - React-jsinspector (from `../../node_modules/react-native/ReactCommon/jsinspector`)
241
-  - react-native-safe-area-context (from `../../`)
280
+  - react-native-safe-area-context (from `../..`)
242
   - React-RCTActionSheet (from `../../node_modules/react-native/Libraries/ActionSheetIOS`)
281
   - React-RCTActionSheet (from `../../node_modules/react-native/Libraries/ActionSheetIOS`)
243
   - React-RCTAnimation (from `../../node_modules/react-native/Libraries/NativeAnimation`)
282
   - React-RCTAnimation (from `../../node_modules/react-native/Libraries/NativeAnimation`)
244
   - React-RCTBlob (from `../../node_modules/react-native/Libraries/Blob`)
283
   - React-RCTBlob (from `../../node_modules/react-native/Libraries/Blob`)
248
   - React-RCTSettings (from `../../node_modules/react-native/Libraries/Settings`)
287
   - React-RCTSettings (from `../../node_modules/react-native/Libraries/Settings`)
249
   - React-RCTText (from `../../node_modules/react-native/Libraries/Text`)
288
   - React-RCTText (from `../../node_modules/react-native/Libraries/Text`)
250
   - React-RCTVibration (from `../../node_modules/react-native/Libraries/Vibration`)
289
   - React-RCTVibration (from `../../node_modules/react-native/Libraries/Vibration`)
251
-  - ReactCommon/jscallinvoker (from `../../node_modules/react-native/ReactCommon`)
252
   - ReactCommon/turbomodule/core (from `../../node_modules/react-native/ReactCommon`)
290
   - ReactCommon/turbomodule/core (from `../../node_modules/react-native/ReactCommon`)
291
+  - "RNCAsyncStorage (from `../../node_modules/@react-native-community/async-storage`)"
292
+  - "RNCMaskedView (from `../../node_modules/@react-native-community/masked-view`)"
293
+  - RNGestureHandler (from `../../node_modules/react-native-gesture-handler`)
294
+  - RNReanimated (from `../../node_modules/react-native-reanimated`)
295
+  - RNScreens (from `../../node_modules/react-native-screens`)
253
   - Yoga (from `../../node_modules/react-native/ReactCommon/yoga`)
296
   - Yoga (from `../../node_modules/react-native/ReactCommon/yoga`)
254
 
297
 
255
 SPEC REPOS:
298
 SPEC REPOS:
273
     :path: "../../node_modules/react-native/Libraries/TypeSafety"
316
     :path: "../../node_modules/react-native/Libraries/TypeSafety"
274
   React:
317
   React:
275
     :path: "../../node_modules/react-native/"
318
     :path: "../../node_modules/react-native/"
319
+  React-callinvoker:
320
+    :path: "../../node_modules/react-native/ReactCommon/callinvoker"
276
   React-Core:
321
   React-Core:
277
     :path: "../../node_modules/react-native/"
322
     :path: "../../node_modules/react-native/"
278
   React-CoreModules:
323
   React-CoreModules:
286
   React-jsinspector:
331
   React-jsinspector:
287
     :path: "../../node_modules/react-native/ReactCommon/jsinspector"
332
     :path: "../../node_modules/react-native/ReactCommon/jsinspector"
288
   react-native-safe-area-context:
333
   react-native-safe-area-context:
289
-    :path: "../../"
334
+    :path: "../.."
290
   React-RCTActionSheet:
335
   React-RCTActionSheet:
291
     :path: "../../node_modules/react-native/Libraries/ActionSheetIOS"
336
     :path: "../../node_modules/react-native/Libraries/ActionSheetIOS"
292
   React-RCTAnimation:
337
   React-RCTAnimation:
307
     :path: "../../node_modules/react-native/Libraries/Vibration"
352
     :path: "../../node_modules/react-native/Libraries/Vibration"
308
   ReactCommon:
353
   ReactCommon:
309
     :path: "../../node_modules/react-native/ReactCommon"
354
     :path: "../../node_modules/react-native/ReactCommon"
355
+  RNCAsyncStorage:
356
+    :path: "../../node_modules/@react-native-community/async-storage"
357
+  RNCMaskedView:
358
+    :path: "../../node_modules/@react-native-community/masked-view"
359
+  RNGestureHandler:
360
+    :path: "../../node_modules/react-native-gesture-handler"
361
+  RNReanimated:
362
+    :path: "../../node_modules/react-native-reanimated"
363
+  RNScreens:
364
+    :path: "../../node_modules/react-native-screens"
310
   Yoga:
365
   Yoga:
311
     :path: "../../node_modules/react-native/ReactCommon/yoga"
366
     :path: "../../node_modules/react-native/ReactCommon/yoga"
312
 
367
 
313
 SPEC CHECKSUMS:
368
 SPEC CHECKSUMS:
314
   boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
369
   boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
315
-  DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
316
-  FBLazyVector: aaeaf388755e4f29cd74acbc9e3b8da6d807c37f
317
-  FBReactNativeSpec: 118d0d177724c2d67f08a59136eb29ef5943ec75
318
-  Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
319
-  glog: 1f3da668190260b06b429bb211bfbee5cd790c28
320
-  RCTRequired: b153add4da6e7dbc44aebf93f3cf4fcae392ddf1
321
-  RCTTypeSafety: 9aa1b91d7f9310fc6eadc3cf95126ffe818af320
322
-  React: b6a59ef847b2b40bb6e0180a97d0ca716969ac78
323
-  React-Core: 688b451f7d616cc1134ac95295b593d1b5158a04
324
-  React-CoreModules: d04f8494c1a328b69ec11db9d1137d667f916dcb
325
-  React-cxxreact: d0f7bcafa196ae410e5300736b424455e7fb7ba7
326
-  React-jsi: cb2cd74d7ccf4cffb071a46833613edc79cdf8f7
327
-  React-jsiexecutor: d5525f9ed5f782fdbacb64b9b01a43a9323d2386
328
-  React-jsinspector: fa0ecc501688c3c4c34f28834a76302233e29dc0
329
-  react-native-safe-area-context: 52342d2d80ea8faadd0ffa76d83b6051f20c5329
330
-  React-RCTActionSheet: 600b4d10e3aea0913b5a92256d2719c0cdd26d76
331
-  React-RCTAnimation: 791a87558389c80908ed06cc5dfc5e7920dfa360
332
-  React-RCTBlob: d89293cc0236d9cb0933d85e430b0bbe81ad1d72
333
-  React-RCTImage: 6b8e8df449eb7c814c99a92d6b52de6fe39dea4e
334
-  React-RCTLinking: 121bb231c7503cf9094f4d8461b96a130fabf4a5
335
-  React-RCTNetwork: fb353640aafcee84ca8b78957297bd395f065c9a
336
-  React-RCTSettings: 8db258ea2a5efee381fcf7a6d5044e2f8b68b640
337
-  React-RCTText: 9ccc88273e9a3aacff5094d2175a605efa854dbe
338
-  React-RCTVibration: a49a1f42bf8f5acf1c3e297097517c6b3af377ad
339
-  ReactCommon: 198c7c8d3591f975e5431bec1b0b3b581aa1c5dd
340
-  Yoga: f2a7cd4280bfe2cca5a7aed98ba0eb3d1310f18b
370
+  DoubleConversion: cde416483dac037923206447da6e1454df403714
371
+  FBLazyVector: 78609f00baec7c48492967441897aa8cee25a612
372
+  FBReactNativeSpec: 78b0d7c0ecca12a7306ce8c04f041bc358c60beb
373
+  Folly: b73c3869541e86821df3c387eb0af5f65addfab4
374
+  glog: 40a13f7840415b9a77023fbcae0f1e6f43192af3
375
+  RCTRequired: c5302fd1e3225d47b041121363398dc265a964ac
376
+  RCTTypeSafety: a42f9e52df553d6bdc3a007376e948252f250cba
377
+  React: 6c9152bc1b9fefba67ca0344c6e242f01039dd6b
378
+  React-callinvoker: 99716fad454984727741acd315e653385869b592
379
+  React-Core: 548f0e70be73b463b16acf6a05c1668ab1dc9697
380
+  React-CoreModules: 814839144329ae12bf51a3e87938e77e205e6915
381
+  React-cxxreact: 3c30dbf55f1d1847a3c7e140f249a0c4a296d93e
382
+  React-jsi: 87b6b899f6c81c29487d0416969c261b73f46a2d
383
+  React-jsiexecutor: 0ca3a8a0a65f9eb9aec3273c4cf44f6d31277937
384
+  React-jsinspector: 09b8cb3fefdf81b2889a13cc1a645e905e514ddb
385
+  react-native-safe-area-context: a346c75f2288147527365ce27b59ca6d38c27805
386
+  React-RCTActionSheet: b6d2445d7317359997ed0c650421d0a0b9dd58cb
387
+  React-RCTAnimation: 2f48bd93a4f5317cd5ab7189c6b5e469b60fb7bf
388
+  React-RCTBlob: b8da9c90135ee183f3ad35b521313390370b5ed2
389
+  React-RCTImage: 705db0bdff4609796e8548716ce19a34488bb7a3
390
+  React-RCTLinking: ecc90e00cc0604ddb2276d828c6227a7251eaa5e
391
+  React-RCTNetwork: b05b4e09038cac3e63b7ddbdac0d7abb8e18655d
392
+  React-RCTSettings: bbd1601b51a6475157bc03f39d6378ce15ed0954
393
+  React-RCTText: 32e3c891fa74b1b2544517e59ee5fbc96f672983
394
+  React-RCTVibration: ab7fb7b10ca373d7e931b15e18b5f6d1663367ca
395
+  ReactCommon: 14ae20c83bd846c1790e45ad95e0f0717dcd034f
396
+  RNCAsyncStorage: 39831e0dc5f547a1fb2669eb9e091d460a9be2be
397
+  RNCMaskedView: 5a8ec07677aa885546a0d98da336457e2bea557f
398
+  RNGestureHandler: 8f09cd560f8d533eb36da5a6c5a843af9f056b38
399
+  RNReanimated: 955cf4068714003d2f1a6e2bae3fb1118f359aff
400
+  RNScreens: cf198f915f8a2bf163de94ca9f5bfc8d326c3706
401
+  Yoga: 5ffb724bde6d20a1828a1dc9a368085f404a1203
341
 
402
 
342
-PODFILE CHECKSUM: 3385dd94e97e53501bf5b4afd25375c777edd67d
403
+PODFILE CHECKSUM: 90edcd974101399fc4c4cb2f6ffd1ccb481b16ff
343
 
404
 
344
-COCOAPODS: 1.8.4
405
+COCOAPODS: 1.9.1

+ 4
- 0
example/ios/SafeAreaViewExample-Bridging-Header.h View File

1
+//
2
+//  Use this file to import your target's public headers that you would like to expose to Swift.
3
+//
4
+

+ 0
- 53
example/ios/SafeAreaViewExample-tvOS/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>CFBundleExecutable</key>
8
-	<string>$(EXECUTABLE_NAME)</string>
9
-	<key>CFBundleIdentifier</key>
10
-	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
11
-	<key>CFBundleInfoDictionaryVersion</key>
12
-	<string>6.0</string>
13
-	<key>CFBundleName</key>
14
-	<string>$(PRODUCT_NAME)</string>
15
-	<key>CFBundlePackageType</key>
16
-	<string>APPL</string>
17
-	<key>CFBundleShortVersionString</key>
18
-	<string>1.0</string>
19
-	<key>CFBundleSignature</key>
20
-	<string>????</string>
21
-	<key>CFBundleVersion</key>
22
-	<string>1</string>
23
-	<key>LSRequiresIPhoneOS</key>
24
-	<true/>
25
-	<key>NSAppTransportSecurity</key>
26
-	<dict>
27
-		<key>NSExceptionDomains</key>
28
-		<dict>
29
-			<key>localhost</key>
30
-			<dict>
31
-				<key>NSExceptionAllowsInsecureHTTPLoads</key>
32
-				<true/>
33
-			</dict>
34
-		</dict>
35
-	</dict>
36
-	<key>NSLocationWhenInUseUsageDescription</key>
37
-	<string></string>
38
-	<key>UILaunchStoryboardName</key>
39
-	<string>LaunchScreen</string>
40
-	<key>UIRequiredDeviceCapabilities</key>
41
-	<array>
42
-		<string>armv7</string>
43
-	</array>
44
-	<key>UISupportedInterfaceOrientations</key>
45
-	<array>
46
-		<string>UIInterfaceOrientationPortrait</string>
47
-		<string>UIInterfaceOrientationLandscapeLeft</string>
48
-		<string>UIInterfaceOrientationLandscapeRight</string>
49
-	</array>
50
-	<key>UIViewControllerBasedStatusBarAppearance</key>
51
-	<false/>
52
-</dict>
53
-</plist>

+ 0
- 24
example/ios/SafeAreaViewExample-tvOSTests/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>CFBundleExecutable</key>
8
-	<string>$(EXECUTABLE_NAME)</string>
9
-	<key>CFBundleIdentifier</key>
10
-	<string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>
11
-	<key>CFBundleInfoDictionaryVersion</key>
12
-	<string>6.0</string>
13
-	<key>CFBundleName</key>
14
-	<string>$(PRODUCT_NAME)</string>
15
-	<key>CFBundlePackageType</key>
16
-	<string>BNDL</string>
17
-	<key>CFBundleShortVersionString</key>
18
-	<string>1.0</string>
19
-	<key>CFBundleSignature</key>
20
-	<string>????</string>
21
-	<key>CFBundleVersion</key>
22
-	<string>1</string>
23
-</dict>
24
-</plist>

+ 47
- 2
example/ios/SafeAreaViewExample.xcodeproj/project.pbxproj View File

11
 		13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
11
 		13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
12
 		13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
12
 		13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13
 		13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
13
 		13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
14
+		19CA4076245DE96A00FEEC94 /* File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19CA4075245DE96A00FEEC94 /* File.swift */; };
14
 		D590E4D001221F6B5AF11381 /* libPods-SafeAreaViewExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 275F94A75481D4E6C652CF4F /* libPods-SafeAreaViewExample.a */; };
15
 		D590E4D001221F6B5AF11381 /* libPods-SafeAreaViewExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 275F94A75481D4E6C652CF4F /* libPods-SafeAreaViewExample.a */; };
15
 /* End PBXBuildFile section */
16
 /* End PBXBuildFile section */
16
 
17
 
24
 		13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = SafeAreaViewExample/Images.xcassets; sourceTree = "<group>"; };
25
 		13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = SafeAreaViewExample/Images.xcassets; sourceTree = "<group>"; };
25
 		13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = SafeAreaViewExample/Info.plist; sourceTree = "<group>"; };
26
 		13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = SafeAreaViewExample/Info.plist; sourceTree = "<group>"; };
26
 		13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = SafeAreaViewExample/main.m; sourceTree = "<group>"; };
27
 		13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = SafeAreaViewExample/main.m; sourceTree = "<group>"; };
28
+		19CA4074245DE96A00FEEC94 /* SafeAreaViewExample-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SafeAreaViewExample-Bridging-Header.h"; sourceTree = "<group>"; };
29
+		19CA4075245DE96A00FEEC94 /* File.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = File.swift; path = SafeAreaViewExample/File.swift; sourceTree = "<group>"; };
27
 		275F94A75481D4E6C652CF4F /* libPods-SafeAreaViewExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SafeAreaViewExample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
30
 		275F94A75481D4E6C652CF4F /* libPods-SafeAreaViewExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SafeAreaViewExample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
28
 		69AAEDE94ED39E6A720417AA /* Pods-SafeAreaViewExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SafeAreaViewExample.release.xcconfig"; path = "Target Support Files/Pods-SafeAreaViewExample/Pods-SafeAreaViewExample.release.xcconfig"; sourceTree = "<group>"; };
31
 		69AAEDE94ED39E6A720417AA /* Pods-SafeAreaViewExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SafeAreaViewExample.release.xcconfig"; path = "Target Support Files/Pods-SafeAreaViewExample/Pods-SafeAreaViewExample.release.xcconfig"; sourceTree = "<group>"; };
29
 		ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
32
 		ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
52
 				13B07FB61A68108700A75B9A /* Info.plist */,
55
 				13B07FB61A68108700A75B9A /* Info.plist */,
53
 				13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
56
 				13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
54
 				13B07FB71A68108700A75B9A /* main.m */,
57
 				13B07FB71A68108700A75B9A /* main.m */,
58
+				19CA4075245DE96A00FEEC94 /* File.swift */,
59
+				19CA4074245DE96A00FEEC94 /* SafeAreaViewExample-Bridging-Header.h */,
55
 			);
60
 			);
56
 			name = SafeAreaViewExample;
61
 			name = SafeAreaViewExample;
57
 			sourceTree = "<group>";
62
 			sourceTree = "<group>";
117
 				13B07F8C1A680F5B00A75B9A /* Frameworks */,
122
 				13B07F8C1A680F5B00A75B9A /* Frameworks */,
118
 				13B07F8E1A680F5B00A75B9A /* Resources */,
123
 				13B07F8E1A680F5B00A75B9A /* Resources */,
119
 				00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
124
 				00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
125
+				9C3A0F31C8045DB6E6F56F79 /* [CP] Copy Pods Resources */,
120
 			);
126
 			);
121
 			buildRules = (
127
 			buildRules = (
122
 			);
128
 			);
133
 		83CBB9F71A601CBA00E9B192 /* Project object */ = {
139
 		83CBB9F71A601CBA00E9B192 /* Project object */ = {
134
 			isa = PBXProject;
140
 			isa = PBXProject;
135
 			attributes = {
141
 			attributes = {
136
-				LastUpgradeCheck = 1030;
142
+				LastUpgradeCheck = 1140;
137
 				ORGANIZATIONNAME = Facebook;
143
 				ORGANIZATIONNAME = Facebook;
144
+				TargetAttributes = {
145
+					13B07F861A680F5B00A75B9A = {
146
+						LastSwiftMigration = 1140;
147
+					};
148
+				};
138
 			};
149
 			};
139
 			buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "SafeAreaViewExample" */;
150
 			buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "SafeAreaViewExample" */;
140
 			compatibilityVersion = "Xcode 3.2";
151
 			compatibilityVersion = "Xcode 3.2";
203
 			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
214
 			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
204
 			showEnvVarsInLog = 0;
215
 			showEnvVarsInLog = 0;
205
 		};
216
 		};
217
+		9C3A0F31C8045DB6E6F56F79 /* [CP] Copy Pods Resources */ = {
218
+			isa = PBXShellScriptBuildPhase;
219
+			buildActionMask = 2147483647;
220
+			files = (
221
+			);
222
+			inputPaths = (
223
+				"${PODS_ROOT}/Target Support Files/Pods-SafeAreaViewExample/Pods-SafeAreaViewExample-resources.sh",
224
+				"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle",
225
+			);
226
+			name = "[CP] Copy Pods Resources";
227
+			outputPaths = (
228
+				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle",
229
+			);
230
+			runOnlyForDeploymentPostprocessing = 0;
231
+			shellPath = /bin/sh;
232
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SafeAreaViewExample/Pods-SafeAreaViewExample-resources.sh\"\n";
233
+			showEnvVarsInLog = 0;
234
+		};
206
 		FD10A7F022414F080027D42C /* Start Packager */ = {
235
 		FD10A7F022414F080027D42C /* Start Packager */ = {
207
 			isa = PBXShellScriptBuildPhase;
236
 			isa = PBXShellScriptBuildPhase;
208
 			buildActionMask = 2147483647;
237
 			buildActionMask = 2147483647;
219
 			);
248
 			);
220
 			runOnlyForDeploymentPostprocessing = 0;
249
 			runOnlyForDeploymentPostprocessing = 0;
221
 			shellPath = /bin/sh;
250
 			shellPath = /bin/sh;
222
-			shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > \"${SRCROOT}/../../node_modules/react-native/scripts/.packager.env\"\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n  if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n    if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n      echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n      exit 2\n    fi\n  else\n    open \"$SRCROOT/../node_modules/react-native/scripts/launchPackager.command\" || echo \"Can't start packager automatically\"\n  fi\nfi\n";
251
+			shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > \"${SRCROOT}/../../node_modules/react-native/scripts/.packager.env\"\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n  if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n    if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n      echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n      exit 2\n    fi\n  else\n    open \"$SRCROOT/../../node_modules/react-native/scripts/launchPackager.command\" || echo \"Can't start packager automatically\"\n  fi\nfi\n";
223
 			showEnvVarsInLog = 0;
252
 			showEnvVarsInLog = 0;
224
 		};
253
 		};
225
 /* End PBXShellScriptBuildPhase section */
254
 /* End PBXShellScriptBuildPhase section */
230
 			buildActionMask = 2147483647;
259
 			buildActionMask = 2147483647;
231
 			files = (
260
 			files = (
232
 				13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
261
 				13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
262
+				19CA4076245DE96A00FEEC94 /* File.swift in Sources */,
233
 				13B07FC11A68108700A75B9A /* main.m in Sources */,
263
 				13B07FC11A68108700A75B9A /* main.m in Sources */,
234
 			);
264
 			);
235
 			runOnlyForDeploymentPostprocessing = 0;
265
 			runOnlyForDeploymentPostprocessing = 0;
253
 			isa = XCBuildConfiguration;
283
 			isa = XCBuildConfiguration;
254
 			baseConfigurationReference = 0A89B68A414A9ACE6081995A /* Pods-SafeAreaViewExample.debug.xcconfig */;
284
 			baseConfigurationReference = 0A89B68A414A9ACE6081995A /* Pods-SafeAreaViewExample.debug.xcconfig */;
255
 			buildSettings = {
285
 			buildSettings = {
286
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
256
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
287
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
288
+				CLANG_ENABLE_MODULES = YES;
257
 				CURRENT_PROJECT_VERSION = 1;
289
 				CURRENT_PROJECT_VERSION = 1;
258
 				DEAD_CODE_STRIPPING = NO;
290
 				DEAD_CODE_STRIPPING = NO;
259
 				INFOPLIST_FILE = SafeAreaViewExample/Info.plist;
291
 				INFOPLIST_FILE = SafeAreaViewExample/Info.plist;
265
 				);
297
 				);
266
 				PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
298
 				PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
267
 				PRODUCT_NAME = SafeAreaViewExample;
299
 				PRODUCT_NAME = SafeAreaViewExample;
300
+				SWIFT_OBJC_BRIDGING_HEADER = "SafeAreaViewExample-Bridging-Header.h";
301
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
302
+				SWIFT_VERSION = 5.0;
268
 				VERSIONING_SYSTEM = "apple-generic";
303
 				VERSIONING_SYSTEM = "apple-generic";
269
 			};
304
 			};
270
 			name = Debug;
305
 			name = Debug;
273
 			isa = XCBuildConfiguration;
308
 			isa = XCBuildConfiguration;
274
 			baseConfigurationReference = 69AAEDE94ED39E6A720417AA /* Pods-SafeAreaViewExample.release.xcconfig */;
309
 			baseConfigurationReference = 69AAEDE94ED39E6A720417AA /* Pods-SafeAreaViewExample.release.xcconfig */;
275
 			buildSettings = {
310
 			buildSettings = {
311
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
276
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
312
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
313
+				CLANG_ENABLE_MODULES = YES;
277
 				CURRENT_PROJECT_VERSION = 1;
314
 				CURRENT_PROJECT_VERSION = 1;
278
 				INFOPLIST_FILE = SafeAreaViewExample/Info.plist;
315
 				INFOPLIST_FILE = SafeAreaViewExample/Info.plist;
279
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
316
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
284
 				);
321
 				);
285
 				PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
322
 				PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
286
 				PRODUCT_NAME = SafeAreaViewExample;
323
 				PRODUCT_NAME = SafeAreaViewExample;
324
+				SWIFT_OBJC_BRIDGING_HEADER = "SafeAreaViewExample-Bridging-Header.h";
325
+				SWIFT_VERSION = 5.0;
287
 				VERSIONING_SYSTEM = "apple-generic";
326
 				VERSIONING_SYSTEM = "apple-generic";
288
 			};
327
 			};
289
 			name = Release;
328
 			name = Release;
291
 		83CBBA201A601CBA00E9B192 /* Debug */ = {
330
 		83CBBA201A601CBA00E9B192 /* Debug */ = {
292
 			isa = XCBuildConfiguration;
331
 			isa = XCBuildConfiguration;
293
 			buildSettings = {
332
 			buildSettings = {
333
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
294
 				ALWAYS_SEARCH_USER_PATHS = NO;
334
 				ALWAYS_SEARCH_USER_PATHS = NO;
295
 				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
335
 				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
296
 				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
336
 				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
318
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
358
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
319
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
359
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
320
 				COPY_PHASE_STRIP = NO;
360
 				COPY_PHASE_STRIP = NO;
361
+				ENABLE_BITCODE = NO;
321
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
362
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
322
 				ENABLE_TESTABILITY = YES;
363
 				ENABLE_TESTABILITY = YES;
323
 				GCC_C_LANGUAGE_STANDARD = gnu99;
364
 				GCC_C_LANGUAGE_STANDARD = gnu99;
338
 				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
379
 				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
339
 				MTL_ENABLE_DEBUG_INFO = YES;
380
 				MTL_ENABLE_DEBUG_INFO = YES;
340
 				ONLY_ACTIVE_ARCH = YES;
381
 				ONLY_ACTIVE_ARCH = YES;
382
+				OTHER_CFLAGS = "-DFB_SONARKIT_ENABLED=1";
341
 				SDKROOT = iphoneos;
383
 				SDKROOT = iphoneos;
342
 			};
384
 			};
343
 			name = Debug;
385
 			name = Debug;
345
 		83CBBA211A601CBA00E9B192 /* Release */ = {
387
 		83CBBA211A601CBA00E9B192 /* Release */ = {
346
 			isa = XCBuildConfiguration;
388
 			isa = XCBuildConfiguration;
347
 			buildSettings = {
389
 			buildSettings = {
390
+				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
348
 				ALWAYS_SEARCH_USER_PATHS = NO;
391
 				ALWAYS_SEARCH_USER_PATHS = NO;
349
 				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
392
 				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
350
 				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
393
 				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
372
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
415
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
373
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
416
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
374
 				COPY_PHASE_STRIP = YES;
417
 				COPY_PHASE_STRIP = YES;
418
+				ENABLE_BITCODE = NO;
375
 				ENABLE_NS_ASSERTIONS = NO;
419
 				ENABLE_NS_ASSERTIONS = NO;
376
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
420
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
377
 				GCC_C_LANGUAGE_STANDARD = gnu99;
421
 				GCC_C_LANGUAGE_STANDARD = gnu99;
384
 				GCC_WARN_UNUSED_VARIABLE = YES;
428
 				GCC_WARN_UNUSED_VARIABLE = YES;
385
 				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
429
 				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
386
 				MTL_ENABLE_DEBUG_INFO = NO;
430
 				MTL_ENABLE_DEBUG_INFO = NO;
431
+				OTHER_CFLAGS = "-DFB_SONARKIT_ENABLED=1";
387
 				SDKROOT = iphoneos;
432
 				SDKROOT = iphoneos;
388
 				VALIDATE_PRODUCT = YES;
433
 				VALIDATE_PRODUCT = YES;
389
 			};
434
 			};

+ 11
- 15
example/ios/SafeAreaViewExample.xcodeproj/xcshareddata/xcschemes/SafeAreaViewExample.xcscheme View File

1
 <?xml version="1.0" encoding="UTF-8"?>
1
 <?xml version="1.0" encoding="UTF-8"?>
2
 <Scheme
2
 <Scheme
3
-   LastUpgradeVersion = "1030"
3
+   LastUpgradeVersion = "1140"
4
    version = "1.3">
4
    version = "1.3">
5
    <BuildAction
5
    <BuildAction
6
-      parallelizeBuildables = "NO"
6
+      parallelizeBuildables = "YES"
7
       buildImplicitDependencies = "YES">
7
       buildImplicitDependencies = "YES">
8
       <BuildActionEntries>
8
       <BuildActionEntries>
9
          <BuildActionEntry
9
          <BuildActionEntry
55
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
55
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
56
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
56
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
57
       shouldUseLaunchSchemeArgsEnv = "YES">
57
       shouldUseLaunchSchemeArgsEnv = "YES">
58
+      <MacroExpansion>
59
+         <BuildableReference
60
+            BuildableIdentifier = "primary"
61
+            BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
62
+            BuildableName = "SafeAreaViewExample.app"
63
+            BlueprintName = "SafeAreaViewExample"
64
+            ReferencedContainer = "container:SafeAreaViewExample.xcodeproj">
65
+         </BuildableReference>
66
+      </MacroExpansion>
58
       <Testables>
67
       <Testables>
59
          <TestableReference
68
          <TestableReference
60
             skipped = "NO">
69
             skipped = "NO">
67
             </BuildableReference>
76
             </BuildableReference>
68
          </TestableReference>
77
          </TestableReference>
69
       </Testables>
78
       </Testables>
70
-      <MacroExpansion>
71
-         <BuildableReference
72
-            BuildableIdentifier = "primary"
73
-            BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
74
-            BuildableName = "SafeAreaViewExample.app"
75
-            BlueprintName = "SafeAreaViewExample"
76
-            ReferencedContainer = "container:SafeAreaViewExample.xcodeproj">
77
-         </BuildableReference>
78
-      </MacroExpansion>
79
-      <AdditionalOptions>
80
-      </AdditionalOptions>
81
    </TestAction>
79
    </TestAction>
82
    <LaunchAction
80
    <LaunchAction
83
       buildConfiguration = "Debug"
81
       buildConfiguration = "Debug"
99
             ReferencedContainer = "container:SafeAreaViewExample.xcodeproj">
97
             ReferencedContainer = "container:SafeAreaViewExample.xcodeproj">
100
          </BuildableReference>
98
          </BuildableReference>
101
       </BuildableProductRunnable>
99
       </BuildableProductRunnable>
102
-      <AdditionalOptions>
103
-      </AdditionalOptions>
104
    </LaunchAction>
100
    </LaunchAction>
105
    <ProfileAction
101
    <ProfileAction
106
       buildConfiguration = "Release"
102
       buildConfiguration = "Release"

+ 0
- 7
example/ios/SafeAreaViewExample/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>
1
 #import <React/RCTBridgeDelegate.h>
9
 #import <UIKit/UIKit.h>
2
 #import <UIKit/UIKit.h>
10
 
3
 

+ 22
- 7
example/ios/SafeAreaViewExample/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"
1
 #import "AppDelegate.h"
9
 
2
 
10
 #import <React/RCTBridge.h>
3
 #import <React/RCTBridge.h>
11
 #import <React/RCTBundleURLProvider.h>
4
 #import <React/RCTBundleURLProvider.h>
12
 #import <React/RCTRootView.h>
5
 #import <React/RCTRootView.h>
13
 
6
 
7
+// #if DEBUG
8
+// #import <FlipperKit/FlipperClient.h>
9
+// #import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
10
+// #import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
11
+// #import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
12
+// #import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
13
+// #import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>
14
+// static void InitializeFlipper(UIApplication *application) {
15
+//   FlipperClient *client = [FlipperClient sharedClient];
16
+//   SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
17
+//   [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
18
+//   [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
19
+//   [client addPlugin:[FlipperKitReactPlugin new]];
20
+//   [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
21
+//   [client start];
22
+// }
23
+// #endif
24
+
14
 @implementation AppDelegate
25
 @implementation AppDelegate
15
 
26
 
16
 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
27
 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
17
 {
28
 {
29
+// #if DEBUG
30
+//   InitializeFlipper(application);
31
+// #endif
32
+
18
   RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
33
   RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
19
   RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
34
   RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
20
                                                    moduleName:@"SafeAreaViewExample"
35
                                                    moduleName:@"SafeAreaViewExample"

+ 9
- 0
example/ios/SafeAreaViewExample/File.swift View File

1
+//
2
+//  File.swift
3
+//  SafeAreaViewExample
4
+//
5
+//  Created by Janic Duplessis on 2020-05-02.
6
+//  Copyright © 2020 Facebook. All rights reserved.
7
+//
8
+
9
+import Foundation

+ 0
- 7
example/ios/SafeAreaViewExample/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>
1
 #import <UIKit/UIKit.h>
9
 
2
 
10
 #import "AppDelegate.h"
3
 #import "AppDelegate.h"

+ 22
- 0
example/package.json View File

1
+{
2
+  "name": "example",
3
+  "dependencies": {
4
+    "@react-native-community/async-storage": "^1.10.1",
5
+    "@react-native-community/masked-view": "^0.1.10",
6
+    "@react-navigation/native": "^5.3.2",
7
+    "@react-navigation/stack": "^5.3.6",
8
+    "@react-navigation/bottom-tabs": "^5.4.4",
9
+    "expo": "^37.0.8",
10
+    "react": "^16.13.1",
11
+    "react-dom": "^16.13.1",
12
+    "react-native": "^0.63.0-rc.0",
13
+    "react-native-web": "^0.12.2",
14
+    "react-navigation": "^4.3.9",
15
+    "react-navigation-stack": "^2.5.0",
16
+    "react-navigation-tabs": "^2.8.13",
17
+    "react-native-gesture-handler": "^1.6.1",
18
+    "react-native-screens": "^2.7.0",
19
+    "react-native-reanimated": "^1.8.0",
20
+    "react-native-safe-area-view": "^1.1.1"
21
+  }
22
+}

+ 83
- 0
example/src/App.tsx View File

1
+import 'react-native-gesture-handler';
2
+import * as React from 'react';
3
+import { DevSettings, View, Text } from 'react-native';
4
+import { enableScreens } from 'react-native-screens';
5
+import AsyncStorage from '@react-native-community/async-storage';
6
+import ReactNavigation4Example from './ReactNavigation4Example';
7
+import ReactNavigation5Example from './ReactNavigation5Example';
8
+import SimpleExample from './SimpleExample';
9
+import NativeStackExample from './NativeStackExample';
10
+import ReactNativeSafeAreaView from './ReactNativeSafeAreaView';
11
+
12
+enableScreens();
13
+
14
+const STORAGE_KEY = 'rnsac-current-example';
15
+
16
+export default function App() {
17
+  const [currentExample, setCurrentExample] = React.useState<string | null>(
18
+    null,
19
+  );
20
+
21
+  React.useEffect(() => {
22
+    async function loadCurrentExample() {
23
+      const example = await AsyncStorage.getItem(STORAGE_KEY);
24
+      setCurrentExample(example ?? null);
25
+    }
26
+    loadCurrentExample();
27
+  }, []);
28
+
29
+  React.useEffect(() => {
30
+    async function saveCurrentExample() {
31
+      if (currentExample != null) {
32
+        await AsyncStorage.setItem(STORAGE_KEY, currentExample);
33
+      }
34
+    }
35
+    saveCurrentExample();
36
+  }, [currentExample]);
37
+
38
+  React.useEffect(() => {
39
+    DevSettings.addMenuItem('Show Simple Example', () => {
40
+      setCurrentExample('simple');
41
+    });
42
+    DevSettings.addMenuItem('Show React Navigation 4 Example', () => {
43
+      setCurrentExample('react-navigation-4');
44
+    });
45
+    DevSettings.addMenuItem('Show React Navigation 5 Example', () => {
46
+      setCurrentExample('react-navigation-5');
47
+    });
48
+    DevSettings.addMenuItem('Show Native Stack Example', () => {
49
+      setCurrentExample('native-stack');
50
+    });
51
+    DevSettings.addMenuItem('Show React Native Safe Area View Example', () => {
52
+      setCurrentExample('react-native-safe-area-view');
53
+    });
54
+  }, []);
55
+
56
+  switch (currentExample) {
57
+    case 'simple':
58
+      return <SimpleExample />;
59
+    case 'react-navigation-4':
60
+      return <ReactNavigation4Example />;
61
+    case 'react-navigation-5':
62
+      return <ReactNavigation5Example />;
63
+    case 'native-stack':
64
+      return <NativeStackExample />;
65
+    case 'react-native-safe-area-view':
66
+      return <ReactNativeSafeAreaView />;
67
+    default:
68
+      return (
69
+        <View
70
+          style={{
71
+            flex: 1,
72
+            alignItems: 'center',
73
+            justifyContent: 'center',
74
+            padding: 24,
75
+          }}
76
+        >
77
+          <Text style={{ textAlign: 'center', fontSize: 14 }}>
78
+            Open the dev menu to choose an example
79
+          </Text>
80
+        </View>
81
+      );
82
+  }
83
+}

+ 74
- 0
example/src/NativeStackExample.tsx View File

1
+import * as React from 'react';
2
+import { Text, View, Button } from 'react-native';
3
+import { NavigationContainer } from '@react-navigation/native';
4
+import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
5
+import { createNativeStackNavigator } from 'react-native-screens/native-stack';
6
+import type { StackScreenProps } from '@react-navigation/stack';
7
+
8
+type Routes = {
9
+  Home: undefined;
10
+  Details: undefined;
11
+  Settings: undefined;
12
+};
13
+
14
+function HomeScreen({ navigation }: StackScreenProps<Routes, 'Home'>) {
15
+  return (
16
+    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
17
+      <Text>Home Screen</Text>
18
+      <Button
19
+        title="Go to Details"
20
+        onPress={() => navigation.navigate('Details')}
21
+      />
22
+    </View>
23
+  );
24
+}
25
+
26
+function SettingsScreen({ navigation }: StackScreenProps<Routes, 'Settings'>) {
27
+  return (
28
+    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
29
+      <Text>Settings Screen</Text>
30
+      <Button
31
+        title="Go to Details"
32
+        onPress={() => navigation.navigate('Details')}
33
+      />
34
+    </View>
35
+  );
36
+}
37
+
38
+const Tab = createBottomTabNavigator();
39
+
40
+function TabsScreen() {
41
+  return (
42
+    <Tab.Navigator>
43
+      <Tab.Screen name="Home" component={HomeScreen} />
44
+      <Tab.Screen name="Settings" component={SettingsScreen} />
45
+    </Tab.Navigator>
46
+  );
47
+}
48
+
49
+function DetailsScreen({ navigation }: StackScreenProps<Routes, 'Details'>) {
50
+  return (
51
+    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
52
+      <Text>Details Screen</Text>
53
+      <Button
54
+        title="Go to Details... again"
55
+        onPress={() => navigation.push('Details')}
56
+      />
57
+      <Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
58
+      <Button title="Go back" onPress={() => navigation.goBack()} />
59
+    </View>
60
+  );
61
+}
62
+
63
+const Stack = createNativeStackNavigator();
64
+
65
+export default function NativeStackExample() {
66
+  return (
67
+    <NavigationContainer>
68
+      <Stack.Navigator>
69
+        <Stack.Screen name="Tabs" component={TabsScreen} />
70
+        <Stack.Screen name="Details" component={DetailsScreen} />
71
+      </Stack.Navigator>
72
+    </NavigationContainer>
73
+  );
74
+}

+ 14
- 0
example/src/ReactNativeSafeAreaView.tsx View File

1
+import * as React from 'react';
2
+import { View } from 'react-native';
3
+import { SafeAreaProvider } from 'react-native-safe-area-context';
4
+import SafeAreaView from 'react-native-safe-area-view';
5
+
6
+export default function ReactNativeSafeAreaView() {
7
+  return (
8
+    <SafeAreaProvider>
9
+      <SafeAreaView style={{ flex: 1, backgroundColor: 'red' }}>
10
+        <View style={{ flex: 1, backgroundColor: 'blue' }} />
11
+      </SafeAreaView>
12
+    </SafeAreaProvider>
13
+  );
14
+}

+ 76
- 0
example/src/ReactNavigation4Example.tsx View File

1
+import * as React from 'react';
2
+import { View, Text, Button } from 'react-native';
3
+import { createAppContainer } from 'react-navigation';
4
+import { createBottomTabNavigator } from 'react-navigation-tabs';
5
+import {
6
+  createStackNavigator,
7
+  NavigationStackProp,
8
+} from 'react-navigation-stack';
9
+import { SafeAreaProvider } from 'react-native-safe-area-context';
10
+
11
+type NavigationScreenProps = {
12
+  navigation: NavigationStackProp<{}, {}>;
13
+};
14
+
15
+function HomeScreen({ navigation }: NavigationScreenProps) {
16
+  return (
17
+    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
18
+      <Text>Home Screen</Text>
19
+      <Button
20
+        title="Go to Details"
21
+        onPress={() => navigation.navigate('Details')}
22
+      />
23
+    </View>
24
+  );
25
+}
26
+
27
+function SettingsScreen({ navigation }: NavigationScreenProps) {
28
+  return (
29
+    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
30
+      <Text>Settings Screen</Text>
31
+      <Button
32
+        title="Go to Details"
33
+        onPress={() => navigation.navigate('Details')}
34
+      />
35
+    </View>
36
+  );
37
+}
38
+
39
+const TabNavigator = createBottomTabNavigator({
40
+  Home: HomeScreen,
41
+  Settings: SettingsScreen,
42
+});
43
+
44
+function DetailsScreen({ navigation }: NavigationScreenProps) {
45
+  return (
46
+    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
47
+      <Text>Details Screen</Text>
48
+      <Button
49
+        title="Go to Details... again"
50
+        onPress={() => navigation.push('Details')}
51
+      />
52
+      <Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
53
+      <Button title="Go back" onPress={() => navigation.goBack()} />
54
+    </View>
55
+  );
56
+}
57
+
58
+const AppNavigator = createStackNavigator(
59
+  {
60
+    Tabs: TabNavigator,
61
+    Details: DetailsScreen,
62
+  },
63
+  {
64
+    initialRouteName: 'Tabs',
65
+  },
66
+);
67
+
68
+const AppContainer = createAppContainer(AppNavigator);
69
+
70
+export default function ReactNavigation4Example() {
71
+  return (
72
+    <SafeAreaProvider>
73
+      <AppContainer />
74
+    </SafeAreaProvider>
75
+  );
76
+}

+ 76
- 0
example/src/ReactNavigation5Example.tsx View File

1
+import * as React from 'react';
2
+import { Text, View, Button } from 'react-native';
3
+import { NavigationContainer } from '@react-navigation/native';
4
+import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
5
+import {
6
+  createStackNavigator,
7
+  StackScreenProps,
8
+} from '@react-navigation/stack';
9
+
10
+type Routes = {
11
+  Home: undefined;
12
+  Details: undefined;
13
+  Settings: undefined;
14
+};
15
+
16
+function HomeScreen({ navigation }: StackScreenProps<Routes, 'Home'>) {
17
+  return (
18
+    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
19
+      <Text>Home Screen</Text>
20
+      <Button
21
+        title="Go to Details"
22
+        onPress={() => navigation.navigate('Details')}
23
+      />
24
+    </View>
25
+  );
26
+}
27
+
28
+function SettingsScreen({ navigation }: StackScreenProps<Routes, 'Settings'>) {
29
+  return (
30
+    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
31
+      <Text>Settings Screen</Text>
32
+      <Button
33
+        title="Go to Details"
34
+        onPress={() => navigation.navigate('Details')}
35
+      />
36
+    </View>
37
+  );
38
+}
39
+
40
+const Tab = createBottomTabNavigator();
41
+
42
+function TabsScreen() {
43
+  return (
44
+    <Tab.Navigator>
45
+      <Tab.Screen name="Home" component={HomeScreen} />
46
+      <Tab.Screen name="Settings" component={SettingsScreen} />
47
+    </Tab.Navigator>
48
+  );
49
+}
50
+
51
+function DetailsScreen({ navigation }: StackScreenProps<Routes, 'Details'>) {
52
+  return (
53
+    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
54
+      <Text>Details Screen</Text>
55
+      <Button
56
+        title="Go to Details... again"
57
+        onPress={() => navigation.push('Details')}
58
+      />
59
+      <Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
60
+      <Button title="Go back" onPress={() => navigation.goBack()} />
61
+    </View>
62
+  );
63
+}
64
+
65
+const Stack = createStackNavigator();
66
+
67
+export default function ReactNavigation5Example() {
68
+  return (
69
+    <NavigationContainer>
70
+      <Stack.Navigator>
71
+        <Stack.Screen name="Tabs" component={TabsScreen} />
72
+        <Stack.Screen name="Details" component={DetailsScreen} />
73
+      </Stack.Navigator>
74
+    </NavigationContainer>
75
+  );
76
+}

+ 92
- 0
example/src/SimpleExample.tsx View File

1
+import * as React from 'react';
2
+import { View, Text, StatusBar, ScrollView } from 'react-native';
3
+
4
+import {
5
+  SafeAreaProvider,
6
+  useSafeAreaInsets,
7
+  initialWindowMetrics,
8
+  useSafeAreaFrame,
9
+} from 'react-native-safe-area-context';
10
+
11
+const DataView = ({ data }: { data: object | null | undefined }) => (
12
+  <Text style={{ fontSize: 16, lineHeight: 24, color: '#292929' }}>
13
+    {data == null
14
+      ? 'null'
15
+      : Object.entries(data)
16
+          .map(([key, value]) => `${key}: ${value}`)
17
+          .join('\n')}
18
+  </Text>
19
+);
20
+
21
+const Card = ({
22
+  title,
23
+  children,
24
+}: {
25
+  title: string;
26
+  children: React.ReactNode;
27
+}) => (
28
+  <View style={{ padding: 16, backgroundColor: 'white', marginBottom: 4 }}>
29
+    <Text
30
+      style={{
31
+        fontSize: 20,
32
+        fontWeight: 'bold',
33
+        marginBottom: 16,
34
+        color: '#292929',
35
+      }}
36
+    >
37
+      {title}
38
+    </Text>
39
+    {children}
40
+  </View>
41
+);
42
+
43
+const BORDER_WIDTH = 8;
44
+
45
+function SimpleExampleScreen() {
46
+  const insets = useSafeAreaInsets();
47
+  const frame = useSafeAreaFrame();
48
+
49
+  return (
50
+    <>
51
+      <StatusBar barStyle="dark-content" backgroundColor="transparent" />
52
+      <View
53
+        style={{
54
+          width: frame.width,
55
+          height: frame.height,
56
+          backgroundColor: 'red',
57
+          paddingTop: insets.top - BORDER_WIDTH,
58
+          paddingLeft: insets.left - BORDER_WIDTH,
59
+          paddingBottom: insets.bottom - BORDER_WIDTH,
60
+          paddingRight: insets.right - BORDER_WIDTH,
61
+          borderColor: 'blue',
62
+          borderWidth: BORDER_WIDTH,
63
+        }}
64
+      >
65
+        <ScrollView style={{ flex: 1, backgroundColor: '#eee' }}>
66
+          <Card title="Provider insets">
67
+            <DataView data={insets} />
68
+          </Card>
69
+          <Card title="Provider frame">
70
+            <DataView data={frame} />
71
+          </Card>
72
+          <Card title="Initial window insets">
73
+            <DataView data={initialWindowMetrics?.insets} />
74
+          </Card>
75
+          <Card title="Initial window frame">
76
+            <DataView data={initialWindowMetrics?.frame} />
77
+          </Card>
78
+        </ScrollView>
79
+      </View>
80
+    </>
81
+  );
82
+}
83
+
84
+export default function SimpleExample() {
85
+  return (
86
+    <View style={{ marginTop: 0, flex: 1 }}>
87
+      <SafeAreaProvider>
88
+        <SimpleExampleScreen />
89
+      </SafeAreaProvider>
90
+    </View>
91
+  );
92
+}

+ 15
- 2
ios/SafeAreaView/RNCSafeAreaView.m View File

16
 @implementation RNCSafeAreaView
16
 @implementation RNCSafeAreaView
17
 {
17
 {
18
   UIEdgeInsets _currentSafeAreaInsets;
18
   UIEdgeInsets _currentSafeAreaInsets;
19
+  CGRect _currentFrame;
19
   BOOL _initialInsetsSent;
20
   BOOL _initialInsetsSent;
20
 }
21
 }
21
 
22
 
75
   }
76
   }
76
 
77
 
77
   UIEdgeInsets safeAreaInsets = [self realOrEmulateSafeAreaInsets];
78
   UIEdgeInsets safeAreaInsets = [self realOrEmulateSafeAreaInsets];
79
+  CGRect frame = [self convertRect:self.bounds toView:nil];
78
 
80
 
79
-  if (_initialInsetsSent && UIEdgeInsetsEqualToEdgeInsetsWithThreshold(safeAreaInsets, _currentSafeAreaInsets, 1.0 / RCTScreenScale())) {
81
+  if (
82
+    _initialInsetsSent &&
83
+    UIEdgeInsetsEqualToEdgeInsetsWithThreshold(safeAreaInsets, _currentSafeAreaInsets, 1.0 / RCTScreenScale()) &&
84
+    CGRectEqualToRect(frame, _currentFrame)
85
+  ) {
80
     return;
86
     return;
81
   }
87
   }
82
 
88
 
83
   _initialInsetsSent = YES;
89
   _initialInsetsSent = YES;
84
   _currentSafeAreaInsets = safeAreaInsets;
90
   _currentSafeAreaInsets = safeAreaInsets;
91
+  _currentFrame = frame;
85
 
92
 
86
   self.onInsetsChange(@{
93
   self.onInsetsChange(@{
87
     @"insets": @{
94
     @"insets": @{
89
       @"right": @(safeAreaInsets.right),
96
       @"right": @(safeAreaInsets.right),
90
       @"bottom": @(safeAreaInsets.bottom),
97
       @"bottom": @(safeAreaInsets.bottom),
91
       @"left": @(safeAreaInsets.left),
98
       @"left": @(safeAreaInsets.left),
92
-    }
99
+    },
100
+    @"frame": @{
101
+      @"x": @(frame.origin.x),
102
+      @"y": @(frame.origin.y),
103
+      @"width": @(frame.size.width),
104
+      @"height": @(frame.size.height),
105
+    },
93
   });
106
   });
94
 }
107
 }
95
 
108
 

+ 13
- 5
ios/SafeAreaView/RNCSafeAreaViewManager.m View File

24
     UIWindow* window = [[UIApplication sharedApplication] keyWindow];
24
     UIWindow* window = [[UIApplication sharedApplication] keyWindow];
25
     UIEdgeInsets safeAreaInsets = window.safeAreaInsets;
25
     UIEdgeInsets safeAreaInsets = window.safeAreaInsets;
26
     return @{
26
     return @{
27
-      @"initialWindowSafeAreaInsets": @{
28
-        @"top": @(safeAreaInsets.top),
29
-        @"right": @(safeAreaInsets.right),
30
-        @"bottom": @(safeAreaInsets.bottom),
31
-        @"left": @(safeAreaInsets.left),
27
+      @"initialWindowMetrics": @{
28
+        @"insets": @{
29
+          @"top": @(safeAreaInsets.top),
30
+          @"right": @(safeAreaInsets.right),
31
+          @"bottom": @(safeAreaInsets.bottom),
32
+          @"left": @(safeAreaInsets.left),
33
+        },
34
+        @"frame": @{
35
+          @"x": @(window.frame.origin.x),
36
+          @"y": @(window.frame.origin.y),
37
+          @"width": @(window.frame.size.width),
38
+          @"height": @(window.frame.size.height),
39
+        },
32
       }
40
       }
33
     };
41
     };
34
   } else {
42
   } else {

+ 0
- 17
metro.config.js View File

1
-/**
2
- * Metro configuration for React Native
3
- * https://github.com/facebook/react-native
4
- *
5
- * @format
6
- */
7
-
8
-module.exports = {
9
-  transformer: {
10
-    getTransformOptions: async () => ({
11
-      transform: {
12
-        experimentalImportSupport: false,
13
-        inlineRequires: false,
14
-      },
15
-    }),
16
-  },
17
-};

+ 39
- 21
package.json View File

1
 {
1
 {
2
   "name": "react-native-safe-area-context",
2
   "name": "react-native-safe-area-context",
3
-  "version": "0.7.3",
3
+  "version": "1.0.2",
4
   "description": "A flexible way to handle safe area, also works on Android and web.",
4
   "description": "A flexible way to handle safe area, also works on Android and web.",
5
   "main": "lib/commonjs/index.js",
5
   "main": "lib/commonjs/index.js",
6
   "module": "lib/module/index.js",
6
   "module": "lib/module/index.js",
27
     "validate:typescript": "tsc --project ./ --noEmit",
27
     "validate:typescript": "tsc --project ./ --noEmit",
28
     "validate:prettier": "prettier \"src/**/*.{js,ts,tsx}\" \"example/**/*.{js,ts,tsx}\" --check",
28
     "validate:prettier": "prettier \"src/**/*.{js,ts,tsx}\" \"example/**/*.{js,ts,tsx}\" --check",
29
     "validate:jest": "jest",
29
     "validate:jest": "jest",
30
-    "prepare": "bob build"
30
+    "prepare": "bob build",
31
+    "example:ios": "cd ./example && react-native run-ios",
32
+    "example:android": "cd ./example && react-native run-android --no-jetifier",
33
+    "example:expo": "expo start --config example/app.json"
31
   },
34
   },
32
   "keywords": [
35
   "keywords": [
33
     "react-native",
36
     "react-native",
43
   },
46
   },
44
   "dependencies": {},
47
   "dependencies": {},
45
   "devDependencies": {
48
   "devDependencies": {
46
-    "@react-native-community/bob": "^0.8.0",
47
-    "@react-native-community/eslint-config": "^0.0.7",
48
-    "@types/jest": "^25.1.1",
49
-    "@types/react": "^16.9.19",
50
-    "@types/react-native": "^0.61.10",
49
+    "@react-native-community/async-storage": "^1.10.1",
50
+    "@react-native-community/bob": "^0.10.1",
51
+    "@react-native-community/eslint-config": "^1.1.0",
52
+    "@react-native-community/masked-view": "^0.1.10",
53
+    "@react-navigation/native": "^5.3.2",
54
+    "@react-navigation/stack": "^5.3.6",
55
+    "@react-navigation/bottom-tabs": "^5.4.4",
56
+    "@types/jest": "^25.2.1",
57
+    "@types/react": "^16.9.34",
58
+    "@types/react-native": "^0.62.5",
59
+    "@types/react-dom": "^16.9.7",
51
     "@types/react-test-renderer": "^16.9.2",
60
     "@types/react-test-renderer": "^16.9.2",
52
-    "@typescript-eslint/eslint-plugin": "^2.19.0",
53
-    "@typescript-eslint/parser": "^2.19.0",
61
+    "@typescript-eslint/eslint-plugin": "^2.30.0",
62
+    "@typescript-eslint/parser": "^2.30.0",
63
+    "babel-plugin-module-resolver": "^4.0.0",
54
     "eslint": "6.8.0",
64
     "eslint": "6.8.0",
55
-    "eslint-config-prettier": "^6.10.0",
56
-    "eslint-plugin-prettier": "3.1.2",
57
-    "expo": "^36.0.2",
58
-    "jest": "^25.1.0",
59
-    "metro-react-native-babel-preset": "^0.58.0",
60
-    "prettier": "^1.19.1",
61
-    "react": "^16.11.0",
62
-    "react-dom": "^16.12.0",
63
-    "react-native": "^0.61.0",
64
-    "react-native-web": "^0.12.0",
65
-    "react-test-renderer": "^16.12.0",
66
-    "typescript": "^3.7.5"
65
+    "eslint-config-prettier": "^6.11.0",
66
+    "eslint-plugin-prettier": "3.1.3",
67
+    "expo": "^37.0.8",
68
+    "expo-cli": "^3.20.1",
69
+    "jest": "^25.5.4",
70
+    "metro-react-native-babel-preset": "^0.59.0",
71
+    "prettier": "^2.0.5",
72
+    "react": "^16.13.1",
73
+    "react-dom": "^16.13.1",
74
+    "react-native": "^0.63.0-rc.0",
75
+    "react-native-web": "^0.12.2",
76
+    "react-navigation": "^4.3.9",
77
+    "react-navigation-stack": "^2.5.0",
78
+    "react-navigation-tabs": "^2.8.13",
79
+    "react-native-safe-area-view": "1.1.1",
80
+    "react-native-gesture-handler": "^1.6.1",
81
+    "react-native-screens": "^2.7.0",
82
+    "react-native-reanimated": "^1.8.0",
83
+    "react-test-renderer": "^16.13.1",
84
+    "typescript": "^3.8.3"
67
   },
85
   },
68
   "repository": {
86
   "repository": {
69
     "type": "git",
87
     "type": "git",

+ 17
- 0
src/InitialWindow.native.ts View File

1
+import { UIManager } from 'react-native';
2
+import { Metrics } from './SafeArea.types';
3
+
4
+const RNCSafeAreaViewConfig = UIManager.getViewManagerConfig(
5
+  'RNCSafeAreaView',
6
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
+) as any;
8
+
9
+export const initialWindowMetrics = (RNCSafeAreaViewConfig != null &&
10
+RNCSafeAreaViewConfig.Constants != null
11
+  ? RNCSafeAreaViewConfig.Constants.initialWindowMetrics
12
+  : null) as Metrics | null;
13
+
14
+/**
15
+ * @deprecated
16
+ */
17
+export const initialWindowSafeAreaInsets = initialWindowMetrics?.insets;

+ 8
- 0
src/InitialWindow.ts View File

1
+import { EdgeInsets, Metrics } from './SafeArea.types';
2
+
3
+export const initialWindowMetrics: Metrics | null = null;
4
+
5
+/**
6
+ * @deprecated
7
+ */
8
+export const initialWindowSafeAreaInsets: EdgeInsets | null = null;

+ 0
- 12
src/InitialWindowSafeAreaInsets.ts View File

1
-import { UIManager } from 'react-native';
2
-import { EdgeInsets } from './SafeArea.types';
3
-
4
-const RNCSafeAreaViewConfig = UIManager.getViewManagerConfig(
5
-  'RNCSafeAreaView',
6
-  // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
-) as any;
8
-
9
-export default (RNCSafeAreaViewConfig != null &&
10
-RNCSafeAreaViewConfig.Constants != null
11
-  ? RNCSafeAreaViewConfig.Constants.initialWindowSafeAreaInsets
12
-  : null) as EdgeInsets | null;

+ 0
- 4
src/InitialWindowSafeAreaInsets.web.ts View File

1
-import { EdgeInsets } from './SafeArea.types';
2
-
3
-const initialWindowSafeAreaInsets: EdgeInsets | null = null;
4
-export default initialWindowSafeAreaInsets;

+ 6
- 0
src/NativeSafeAreaView.native.tsx View File

1
+import { requireNativeComponent } from 'react-native';
2
+import { NativeSafeAreaViewProps } from './SafeArea.types';
3
+
4
+export default requireNativeComponent<NativeSafeAreaViewProps>(
5
+  'RNCSafeAreaView',
6
+);

+ 128
- 2
src/NativeSafeAreaView.tsx View File

1
-import { requireNativeComponent } from 'react-native';
1
+import * as React from 'react';
2
+import { View } from 'react-native';
3
+import { NativeSafeAreaViewProps } from './SafeArea.types';
2
 
4
 
3
-export default requireNativeComponent('RNCSafeAreaView');
5
+/**
6
+ * TODO:
7
+ * Currently insets and frame are based on the window and are not
8
+ * relative to the provider view. This is inconsistent with iOS and Android.
9
+ * However in most cases if the provider view covers the screen this is not
10
+ * an issue.
11
+ */
12
+
13
+const CSSTransitions: Record<string, string> = {
14
+  WebkitTransition: 'webkitTransitionEnd',
15
+  Transition: 'transitionEnd',
16
+  MozTransition: 'transitionend',
17
+  MSTransition: 'msTransitionEnd',
18
+  OTransition: 'oTransitionEnd',
19
+};
20
+
21
+export default function NativeSafeAreaView({
22
+  children,
23
+  style,
24
+  onInsetsChange,
25
+}: NativeSafeAreaViewProps) {
26
+  React.useEffect(() => {
27
+    // Skip for SSR.
28
+    if (typeof document === 'undefined') {
29
+      return;
30
+    }
31
+
32
+    const element = createContextElement();
33
+    document.body.appendChild(element);
34
+    const onEnd = () => {
35
+      const {
36
+        paddingTop,
37
+        paddingBottom,
38
+        paddingLeft,
39
+        paddingRight,
40
+      } = window.getComputedStyle(element);
41
+
42
+      const insets = {
43
+        top: paddingTop ? parseInt(paddingTop, 10) : 0,
44
+        bottom: paddingBottom ? parseInt(paddingBottom, 10) : 0,
45
+        left: paddingLeft ? parseInt(paddingLeft, 10) : 0,
46
+        right: paddingRight ? parseInt(paddingRight, 10) : 0,
47
+      };
48
+      const frame = {
49
+        x: 0,
50
+        y: 0,
51
+        width: document.documentElement.offsetWidth,
52
+        height: document.documentElement.offsetHeight,
53
+      };
54
+      // @ts-ignore: missing properties
55
+      onInsetsChange({ nativeEvent: { insets, frame } });
56
+    };
57
+    element.addEventListener(getSupportedTransitionEvent(), onEnd);
58
+    onEnd();
59
+    return () => {
60
+      document.body.removeChild(element);
61
+      element.removeEventListener(getSupportedTransitionEvent(), onEnd);
62
+    };
63
+  }, [onInsetsChange]);
64
+
65
+  return <View style={style}>{children}</View>;
66
+}
67
+
68
+let _supportedTransitionEvent: string | null = null;
69
+function getSupportedTransitionEvent(): string {
70
+  if (_supportedTransitionEvent !== null) {
71
+    return _supportedTransitionEvent;
72
+  }
73
+  const element = document.createElement('invalidtype');
74
+
75
+  _supportedTransitionEvent = CSSTransitions.Transition;
76
+  for (const key in CSSTransitions) {
77
+    if (element.style[key as keyof CSSStyleDeclaration] !== undefined) {
78
+      _supportedTransitionEvent = CSSTransitions[key];
79
+      break;
80
+    }
81
+  }
82
+  return _supportedTransitionEvent;
83
+}
84
+
85
+type CssEnv = 'constant' | 'env';
86
+
87
+let _supportedEnv: CssEnv | null = null;
88
+function getSupportedEnv(): CssEnv {
89
+  if (_supportedEnv !== null) {
90
+    return _supportedEnv;
91
+  }
92
+  const { CSS } = window;
93
+  if (
94
+    CSS &&
95
+    CSS.supports &&
96
+    CSS.supports('top: constant(safe-area-inset-top)')
97
+  ) {
98
+    _supportedEnv = 'constant';
99
+  } else {
100
+    _supportedEnv = 'env';
101
+  }
102
+  return _supportedEnv;
103
+}
104
+
105
+function getInset(side: string): string {
106
+  return `${getSupportedEnv()}(safe-area-inset-${side})`;
107
+}
108
+
109
+function createContextElement(): HTMLElement {
110
+  const element = document.createElement('div');
111
+  const { style } = element;
112
+  style.position = 'fixed';
113
+  style.left = '0';
114
+  style.top = '0';
115
+  style.width = '0';
116
+  style.height = '0';
117
+  style.zIndex = '-1';
118
+  style.overflow = 'hidden';
119
+  style.visibility = 'hidden';
120
+  // Bacon: Anything faster than this and the callback will be invoked too early with the wrong insets
121
+  style.transitionDuration = '0.05s';
122
+  style.transitionProperty = 'padding';
123
+  style.transitionDelay = '0s';
124
+  style.paddingTop = getInset('top');
125
+  style.paddingBottom = getInset('bottom');
126
+  style.paddingLeft = getInset('left');
127
+  style.paddingRight = getInset('right');
128
+  return element;
129
+}

+ 0
- 122
src/NativeSafeAreaView.web.tsx View File

1
-import * as React from 'react';
2
-import { ViewStyle, View } from 'react-native';
3
-
4
-import { InsetChangeNativeCallback } from './SafeArea.types';
5
-
6
-interface NativeSafeAreaViewProps {
7
-  children?: React.ReactNode;
8
-  style: ViewStyle;
9
-  onInsetsChange: InsetChangeNativeCallback;
10
-}
11
-
12
-const CSSTransitions: Record<string, string> = {
13
-  WebkitTransition: 'webkitTransitionEnd',
14
-  Transition: 'transitionEnd',
15
-  MozTransition: 'transitionend',
16
-  MSTransition: 'msTransitionEnd',
17
-  OTransition: 'oTransitionEnd',
18
-};
19
-
20
-export default function NativeSafeAreaView({
21
-  children,
22
-  style,
23
-  onInsetsChange,
24
-}: NativeSafeAreaViewProps) {
25
-  React.useEffect(() => {
26
-    // Skip for SSR.
27
-    if (typeof document === 'undefined') {
28
-      return;
29
-    }
30
-
31
-    const element = createContextElement();
32
-    document.body.appendChild(element);
33
-    const onEnd = () => {
34
-      const {
35
-        paddingTop,
36
-        paddingBottom,
37
-        paddingLeft,
38
-        paddingRight,
39
-      } = window.getComputedStyle(element);
40
-
41
-      const insets = {
42
-        top: paddingTop ? parseInt(paddingTop, 10) : 0,
43
-        bottom: paddingBottom ? parseInt(paddingBottom, 10) : 0,
44
-        left: paddingLeft ? parseInt(paddingLeft, 10) : 0,
45
-        right: paddingRight ? parseInt(paddingRight, 10) : 0,
46
-      };
47
-      // @ts-ignore: missing properties
48
-      onInsetsChange({ nativeEvent: { insets } });
49
-    };
50
-    element.addEventListener(getSupportedTransitionEvent(), onEnd);
51
-    onEnd();
52
-    return () => {
53
-      document.body.removeChild(element);
54
-      element.removeEventListener(getSupportedTransitionEvent(), onEnd);
55
-    };
56
-  }, [onInsetsChange]);
57
-
58
-  return <View style={style}>{children}</View>;
59
-}
60
-
61
-let _supportedTransitionEvent: string | null = null;
62
-function getSupportedTransitionEvent(): string {
63
-  if (_supportedTransitionEvent !== null) {
64
-    return _supportedTransitionEvent;
65
-  }
66
-  const element = document.createElement('invalidtype');
67
-
68
-  _supportedTransitionEvent = CSSTransitions.Transition;
69
-  for (const key in CSSTransitions) {
70
-    if (element.style[key as keyof CSSStyleDeclaration] !== undefined) {
71
-      _supportedTransitionEvent = CSSTransitions[key];
72
-      break;
73
-    }
74
-  }
75
-  return _supportedTransitionEvent;
76
-}
77
-
78
-type CssEnv = 'constant' | 'env';
79
-
80
-let _supportedEnv: CssEnv | null = null;
81
-function getSupportedEnv(): CssEnv {
82
-  if (_supportedEnv !== null) {
83
-    return _supportedEnv;
84
-  }
85
-  const { CSS } = window;
86
-  if (
87
-    CSS &&
88
-    CSS.supports &&
89
-    CSS.supports('top: constant(safe-area-inset-top)')
90
-  ) {
91
-    _supportedEnv = 'constant';
92
-  } else {
93
-    _supportedEnv = 'env';
94
-  }
95
-  return _supportedEnv;
96
-}
97
-
98
-function getInset(side: string): string {
99
-  return `${getSupportedEnv()}(safe-area-inset-${side})`;
100
-}
101
-
102
-function createContextElement(): HTMLElement {
103
-  const element = document.createElement('div');
104
-  const { style } = element;
105
-  style.position = 'fixed';
106
-  style.left = '0';
107
-  style.top = '0';
108
-  style.width = '0';
109
-  style.height = '0';
110
-  style.zIndex = '-1';
111
-  style.overflow = 'hidden';
112
-  style.visibility = 'hidden';
113
-  // Bacon: Anything faster than this and the callback will be invoked too early with the wrong insets
114
-  style.transitionDuration = '0.05s';
115
-  style.transitionProperty = 'padding';
116
-  style.transitionDelay = '0s';
117
-  style.paddingTop = getInset('top');
118
-  style.paddingBottom = getInset('bottom');
119
-  style.paddingLeft = getInset('left');
120
-  style.paddingRight = getInset('right');
121
-  return element;
122
-}

+ 20
- 2
src/SafeArea.types.ts View File

1
-import { NativeSyntheticEvent } from 'react-native';
1
+import { NativeSyntheticEvent, ViewStyle } from 'react-native';
2
 
2
 
3
 export interface EdgeInsets {
3
 export interface EdgeInsets {
4
   top: number;
4
   top: number;
7
   left: number;
7
   left: number;
8
 }
8
 }
9
 
9
 
10
-export type InsetChangedEvent = NativeSyntheticEvent<{ insets: EdgeInsets }>;
10
+export interface Rect {
11
+  x: number;
12
+  y: number;
13
+  width: number;
14
+  height: number;
15
+}
16
+
17
+export interface Metrics {
18
+  insets: EdgeInsets;
19
+  frame: Rect;
20
+}
21
+
22
+export type InsetChangedEvent = NativeSyntheticEvent<Metrics>;
11
 
23
 
12
 export type InsetChangeNativeCallback = (event: InsetChangedEvent) => void;
24
 export type InsetChangeNativeCallback = (event: InsetChangedEvent) => void;
25
+
26
+export interface NativeSafeAreaViewProps {
27
+  children?: React.ReactNode;
28
+  style?: ViewStyle;
29
+  onInsetsChange: InsetChangeNativeCallback;
30
+}

+ 123
- 0
src/SafeAreaContext.tsx View File

1
+import * as React from 'react';
2
+import { StyleSheet, Dimensions } from 'react-native';
3
+import NativeSafeAreaView from './NativeSafeAreaView';
4
+import { EdgeInsets, InsetChangedEvent, Metrics, Rect } from './SafeArea.types';
5
+
6
+export const SafeAreaInsetsContext = React.createContext<EdgeInsets | null>(
7
+  null,
8
+);
9
+
10
+export const SafeAreaFrameContext = React.createContext<Rect | null>(null);
11
+
12
+export interface SafeAreaViewProps {
13
+  children?: React.ReactNode;
14
+  initialMetrics?: Metrics | null;
15
+  /**
16
+   * @deprecated
17
+   */
18
+  initialSafeAreaInsets?: EdgeInsets | null;
19
+}
20
+
21
+export function SafeAreaProvider({
22
+  children,
23
+  initialMetrics,
24
+  initialSafeAreaInsets,
25
+}: SafeAreaViewProps) {
26
+  const parentInsets = useParentSafeAreaInsets();
27
+  const parentFrame = useParentSafeAreaFrame();
28
+  const [insets, setInsets] = React.useState<EdgeInsets | null>(
29
+    initialMetrics?.insets ?? initialSafeAreaInsets ?? parentInsets ?? null,
30
+  );
31
+  const [frame, setFrame] = React.useState<Rect>(
32
+    initialMetrics?.frame ??
33
+      parentFrame ?? {
34
+        // Backwards compat so we render anyway if we don't have frame.
35
+        x: 0,
36
+        y: 0,
37
+        width: Dimensions.get('window').width,
38
+        height: Dimensions.get('window').height,
39
+      },
40
+  );
41
+  const onInsetsChange = React.useCallback((event: InsetChangedEvent) => {
42
+    // Backwards compat with old native code that won't send frame.
43
+    if (event.nativeEvent.frame != null) {
44
+      setFrame(event.nativeEvent.frame);
45
+    }
46
+    setInsets(event.nativeEvent.insets);
47
+  }, []);
48
+
49
+  return (
50
+    <NativeSafeAreaView style={styles.fill} onInsetsChange={onInsetsChange}>
51
+      {insets != null ? (
52
+        <SafeAreaFrameContext.Provider value={frame}>
53
+          <SafeAreaInsetsContext.Provider value={insets}>
54
+            {children}
55
+          </SafeAreaInsetsContext.Provider>
56
+        </SafeAreaFrameContext.Provider>
57
+      ) : null}
58
+    </NativeSafeAreaView>
59
+  );
60
+}
61
+
62
+const styles = StyleSheet.create({
63
+  fill: { flex: 1 },
64
+});
65
+
66
+function useParentSafeAreaInsets(): EdgeInsets | null {
67
+  return React.useContext(SafeAreaInsetsContext);
68
+}
69
+
70
+function useParentSafeAreaFrame(): Rect | null {
71
+  return React.useContext(SafeAreaFrameContext);
72
+}
73
+
74
+export function useSafeAreaInsets(): EdgeInsets {
75
+  const safeArea = React.useContext(SafeAreaInsetsContext);
76
+  if (safeArea == null) {
77
+    throw new Error(
78
+      'No safe area insets value available. Make sure you are rendering `<SafeAreaProvider>` at the top of your app.',
79
+    );
80
+  }
81
+  return safeArea;
82
+}
83
+
84
+export function useSafeAreaFrame(): Rect {
85
+  const frame = React.useContext(SafeAreaFrameContext);
86
+  if (frame == null) {
87
+    throw new Error(
88
+      'No safe area frame value available. Make sure you are rendering `<SafeAreaProvider>` at the top of your app.',
89
+    );
90
+  }
91
+  return frame;
92
+}
93
+
94
+export function withSafeAreaInsets<T>(
95
+  WrappedComponent: React.ComponentType<T>,
96
+) {
97
+  return (props: T) => (
98
+    <SafeAreaConsumer>
99
+      {(insets) => <WrappedComponent {...props} insets={insets} />}
100
+    </SafeAreaConsumer>
101
+  );
102
+}
103
+
104
+/**
105
+ * @deprecated
106
+ */
107
+export function useSafeArea(): EdgeInsets {
108
+  return useSafeAreaInsets();
109
+}
110
+
111
+/**
112
+ * @deprecated
113
+ */
114
+export function SafeAreaConsumer(
115
+  props: React.ComponentProps<typeof SafeAreaInsetsContext.Consumer>,
116
+) {
117
+  return <SafeAreaInsetsContext.Consumer {...props} />;
118
+}
119
+
120
+/**
121
+ * @deprecated
122
+ */
123
+export const SafeAreaContext = SafeAreaInsetsContext;

+ 25
- 0
src/SafeAreaView.tsx View File

1
+import * as React from 'react';
2
+import { View, ViewProps } from 'react-native';
3
+import { useSafeAreaInsets } from './SafeAreaContext';
4
+
5
+export function SafeAreaView({
6
+  style,
7
+  ...rest
8
+}: ViewProps & { children: React.ReactNode }) {
9
+  const insets = useSafeAreaInsets();
10
+
11
+  return (
12
+    <View
13
+      style={[
14
+        {
15
+          paddingTop: insets.top,
16
+          paddingRight: insets.right,
17
+          paddingBottom: insets.bottom,
18
+          paddingLeft: insets.left,
19
+        },
20
+        style,
21
+      ]}
22
+      {...rest}
23
+    />
24
+  );
25
+}

+ 121
- 0
src/__tests__/SafeAreaContext-test.tsx View File

1
+import * as React from 'react';
2
+import { View } from 'react-native';
3
+import * as ReactTestRenderer from 'react-test-renderer';
4
+import NativeSafeAreaView from '../NativeSafeAreaView';
5
+import {
6
+  SafeAreaProvider,
7
+  useSafeAreaInsets,
8
+  useSafeAreaFrame,
9
+} from '../SafeAreaContext';
10
+import { Metrics } from '../SafeArea.types';
11
+
12
+const TEST_METRICS_1: Metrics = {
13
+  insets: { top: 1, left: 2, right: 3, bottom: 4 },
14
+  frame: { x: 0, y: 0, height: 100, width: 100 },
15
+};
16
+const TEST_METRICS_2: Metrics = {
17
+  insets: { top: 2, left: 3, right: 4, bottom: 5 },
18
+  frame: { x: 0, y: 0, width: 10, height: 16 },
19
+};
20
+
21
+const PrintInsetsTestView = () => {
22
+  const insets = useSafeAreaInsets();
23
+  const frame = useSafeAreaFrame();
24
+  return (
25
+    <View
26
+      style={{
27
+        paddingTop: insets.top,
28
+        paddingLeft: insets.left,
29
+        paddingBottom: insets.bottom,
30
+        paddingRight: insets.right,
31
+        top: frame.y,
32
+        left: frame.y,
33
+        width: frame.width,
34
+        height: frame.height,
35
+      }}
36
+    />
37
+  );
38
+};
39
+
40
+describe('SafeAreaProvider', () => {
41
+  it('renders', () => {
42
+    const component = ReactTestRenderer.create(<SafeAreaProvider />);
43
+    expect(component).toMatchSnapshot();
44
+  });
45
+
46
+  it('does not render child until inset values are received', () => {
47
+    const component = ReactTestRenderer.create(
48
+      <SafeAreaProvider>
49
+        <PrintInsetsTestView />
50
+      </SafeAreaProvider>,
51
+    );
52
+    expect(component).toMatchSnapshot();
53
+  });
54
+
55
+  it('renders child when inset values are received', () => {
56
+    const component = ReactTestRenderer.create(
57
+      <SafeAreaProvider>
58
+        <PrintInsetsTestView />
59
+      </SafeAreaProvider>,
60
+    );
61
+    expect(component).toMatchSnapshot();
62
+    const { onInsetsChange } = component.root.findByType(
63
+      NativeSafeAreaView,
64
+    ).props;
65
+    ReactTestRenderer.act(() => {
66
+      onInsetsChange({
67
+        nativeEvent: TEST_METRICS_1,
68
+      });
69
+    });
70
+    expect(component).toMatchSnapshot();
71
+  });
72
+
73
+  it('supports setting initial insets', () => {
74
+    const component = ReactTestRenderer.create(
75
+      <SafeAreaProvider initialMetrics={TEST_METRICS_1}>
76
+        <PrintInsetsTestView />
77
+      </SafeAreaProvider>,
78
+    );
79
+    expect(component).toMatchSnapshot();
80
+  });
81
+
82
+  it('uses parent insets when available', () => {
83
+    const component = ReactTestRenderer.create(
84
+      <SafeAreaProvider initialMetrics={TEST_METRICS_1}>
85
+        <SafeAreaProvider>
86
+          <PrintInsetsTestView />
87
+        </SafeAreaProvider>
88
+      </SafeAreaProvider>,
89
+    );
90
+    expect(component).toMatchSnapshot();
91
+  });
92
+
93
+  it('uses inner insets', () => {
94
+    const component = ReactTestRenderer.create(
95
+      <SafeAreaProvider initialMetrics={TEST_METRICS_1}>
96
+        <SafeAreaProvider initialMetrics={TEST_METRICS_2}>
97
+          <PrintInsetsTestView />
98
+        </SafeAreaProvider>
99
+      </SafeAreaProvider>,
100
+    );
101
+    expect(component).toMatchSnapshot();
102
+  });
103
+
104
+  it('throws when no provider is rendered', () => {
105
+    // Silence the React error boundary warning; we expect an uncaught error.
106
+    const consoleErrorMock = jest
107
+      .spyOn(console, 'error')
108
+      .mockImplementation((message) => {
109
+        if (message.startsWith('The above error occured in the ')) {
110
+          return;
111
+        }
112
+      });
113
+    expect(() => {
114
+      ReactTestRenderer.create(<PrintInsetsTestView />);
115
+    }).toThrow(
116
+      'No safe area insets value available. Make sure you are rendering `<SafeAreaProvider>` at the top of your app.',
117
+    );
118
+
119
+    consoleErrorMock.mockRestore();
120
+  });
121
+});

+ 35
- 0
src/__tests__/SafeAreaView-test.tsx View File

1
+import * as React from 'react';
2
+import { View } from 'react-native';
3
+import * as ReactTestRenderer from 'react-test-renderer';
4
+import { SafeAreaProvider } from '../SafeAreaContext';
5
+import { SafeAreaView } from '../SafeAreaView';
6
+import { Metrics } from '../SafeArea.types';
7
+
8
+const INITIAL_METRICS: Metrics = {
9
+  insets: { top: 1, left: 2, right: 3, bottom: 4 },
10
+  frame: { x: 0, y: 0, height: 100, width: 100 },
11
+};
12
+
13
+describe('SafeAreaView', () => {
14
+  it('renders', () => {
15
+    const component = ReactTestRenderer.create(
16
+      <SafeAreaProvider initialMetrics={INITIAL_METRICS}>
17
+        <SafeAreaView>
18
+          <View />
19
+        </SafeAreaView>
20
+      </SafeAreaProvider>,
21
+    );
22
+    expect(component).toMatchSnapshot();
23
+  });
24
+
25
+  it('can override padding styles', () => {
26
+    const component = ReactTestRenderer.create(
27
+      <SafeAreaProvider initialMetrics={INITIAL_METRICS}>
28
+        <SafeAreaView style={{ paddingTop: 0 }}>
29
+          <View />
30
+        </SafeAreaView>
31
+      </SafeAreaProvider>,
32
+    );
33
+    expect(component).toMatchSnapshot();
34
+  });
35
+});

src/__tests__/__snapshots__/index-test.tsx.snap → src/__tests__/__snapshots__/SafeAreaContext-test.tsx.snap View File

45
   <View
45
   <View
46
     style={
46
     style={
47
       Object {
47
       Object {
48
-        "bottom": 4,
49
-        "left": 2,
50
-        "right": 3,
51
-        "top": 1,
48
+        "height": 100,
49
+        "left": 0,
50
+        "paddingBottom": 4,
51
+        "paddingLeft": 2,
52
+        "paddingRight": 3,
53
+        "paddingTop": 1,
54
+        "top": 0,
55
+        "width": 100,
52
       }
56
       }
53
     }
57
     }
54
   />
58
   />
67
   <View
71
   <View
68
     style={
72
     style={
69
       Object {
73
       Object {
70
-        "bottom": 4,
71
-        "left": 2,
72
-        "right": 3,
73
-        "top": 1,
74
+        "height": 100,
75
+        "left": 0,
76
+        "paddingBottom": 4,
77
+        "paddingLeft": 2,
78
+        "paddingRight": 3,
79
+        "paddingTop": 1,
80
+        "top": 0,
81
+        "width": 100,
74
       }
82
       }
75
     }
83
     }
76
   />
84
   />
97
     <View
105
     <View
98
       style={
106
       style={
99
         Object {
107
         Object {
100
-          "bottom": 5,
101
-          "left": 3,
102
-          "right": 4,
103
-          "top": 2,
108
+          "height": 16,
109
+          "left": 0,
110
+          "paddingBottom": 5,
111
+          "paddingLeft": 3,
112
+          "paddingRight": 4,
113
+          "paddingTop": 2,
114
+          "top": 0,
115
+          "width": 10,
104
         }
116
         }
105
       }
117
       }
106
     />
118
     />
128
     <View
140
     <View
129
       style={
141
       style={
130
         Object {
142
         Object {
131
-          "bottom": 4,
132
-          "left": 2,
133
-          "right": 3,
134
-          "top": 1,
135
-        }
136
-      }
137
-    />
138
-  </RNCSafeAreaView>
139
-</RNCSafeAreaView>
140
-`;
141
-
142
-exports[`SafeAreaView can override padding styles 1`] = `
143
-<RNCSafeAreaView
144
-  onInsetsChange={[Function]}
145
-  style={
146
-    Object {
147
-      "flex": 1,
148
-    }
149
-  }
150
->
151
-  <View
152
-    style={
153
-      Array [
154
-        Object {
143
+          "height": 100,
144
+          "left": 0,
155
           "paddingBottom": 4,
145
           "paddingBottom": 4,
156
           "paddingLeft": 2,
146
           "paddingLeft": 2,
157
           "paddingRight": 3,
147
           "paddingRight": 3,
158
           "paddingTop": 1,
148
           "paddingTop": 1,
159
-        },
160
-        Object {
161
-          "paddingTop": 0,
162
-        },
163
-      ]
164
-    }
165
-  >
166
-    <View />
167
-  </View>
168
-</RNCSafeAreaView>
169
-`;
170
-
171
-exports[`SafeAreaView renders 1`] = `
172
-<RNCSafeAreaView
173
-  onInsetsChange={[Function]}
174
-  style={
175
-    Object {
176
-      "flex": 1,
177
-    }
178
-  }
179
->
180
-  <View
181
-    style={
182
-      Array [
183
-        Object {
184
-          "paddingBottom": 4,
185
-          "paddingLeft": 2,
186
-          "paddingRight": 3,
187
-          "paddingTop": 1,
188
-        },
189
-        undefined,
190
-      ]
191
-    }
192
-  >
193
-    <View />
194
-  </View>
149
+          "top": 0,
150
+          "width": 100,
151
+        }
152
+      }
153
+    />
154
+  </RNCSafeAreaView>
195
 </RNCSafeAreaView>
155
 </RNCSafeAreaView>
196
 `;
156
 `;

+ 57
- 0
src/__tests__/__snapshots__/SafeAreaView-test.tsx.snap View File

1
+// Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+exports[`SafeAreaView can override padding styles 1`] = `
4
+<RNCSafeAreaView
5
+  onInsetsChange={[Function]}
6
+  style={
7
+    Object {
8
+      "flex": 1,
9
+    }
10
+  }
11
+>
12
+  <View
13
+    style={
14
+      Array [
15
+        Object {
16
+          "paddingBottom": 4,
17
+          "paddingLeft": 2,
18
+          "paddingRight": 3,
19
+          "paddingTop": 1,
20
+        },
21
+        Object {
22
+          "paddingTop": 0,
23
+        },
24
+      ]
25
+    }
26
+  >
27
+    <View />
28
+  </View>
29
+</RNCSafeAreaView>
30
+`;
31
+
32
+exports[`SafeAreaView renders 1`] = `
33
+<RNCSafeAreaView
34
+  onInsetsChange={[Function]}
35
+  style={
36
+    Object {
37
+      "flex": 1,
38
+    }
39
+  }
40
+>
41
+  <View
42
+    style={
43
+      Array [
44
+        Object {
45
+          "paddingBottom": 4,
46
+          "paddingLeft": 2,
47
+          "paddingRight": 3,
48
+          "paddingTop": 1,
49
+        },
50
+        undefined,
51
+      ]
52
+    }
53
+  >
54
+    <View />
55
+  </View>
56
+</RNCSafeAreaView>
57
+`;

+ 0
- 169
src/__tests__/index-test.tsx View File

1
-import * as React from 'react';
2
-import * as ReactTestRenderer from 'react-test-renderer';
3
-import { View, UIManager } from 'react-native';
4
-import { SafeAreaProvider, SafeAreaView, useSafeArea } from '../index';
5
-import NativeSafeAreaView from '../NativeSafeAreaView';
6
-
7
-const PrintInsetsTestView = () => {
8
-  const insets = useSafeArea();
9
-  return (
10
-    <View
11
-      style={{
12
-        top: insets.top,
13
-        left: insets.left,
14
-        bottom: insets.bottom,
15
-        right: insets.right,
16
-      }}
17
-    />
18
-  );
19
-};
20
-
21
-describe('SafeAreaProvider', () => {
22
-  it('renders', () => {
23
-    const component = ReactTestRenderer.create(<SafeAreaProvider />);
24
-    expect(component).toMatchSnapshot();
25
-  });
26
-
27
-  it('does not render child until inset values are received', () => {
28
-    const component = ReactTestRenderer.create(
29
-      <SafeAreaProvider>
30
-        <PrintInsetsTestView />
31
-      </SafeAreaProvider>,
32
-    );
33
-    expect(component).toMatchSnapshot();
34
-  });
35
-
36
-  it('renders child when inset values are received', () => {
37
-    const component = ReactTestRenderer.create(
38
-      <SafeAreaProvider>
39
-        <PrintInsetsTestView />
40
-      </SafeAreaProvider>,
41
-    );
42
-    expect(component).toMatchSnapshot();
43
-    const { onInsetsChange } = component.root.findByType(
44
-      NativeSafeAreaView,
45
-    ).props;
46
-    ReactTestRenderer.act(() => {
47
-      onInsetsChange({
48
-        nativeEvent: { insets: { top: 1, left: 2, right: 3, bottom: 4 } },
49
-      });
50
-    });
51
-    expect(component).toMatchSnapshot();
52
-  });
53
-
54
-  it('supports setting initial insets', () => {
55
-    const component = ReactTestRenderer.create(
56
-      <SafeAreaProvider
57
-        initialSafeAreaInsets={{ top: 1, left: 2, right: 3, bottom: 4 }}
58
-      >
59
-        <PrintInsetsTestView />
60
-      </SafeAreaProvider>,
61
-    );
62
-    expect(component).toMatchSnapshot();
63
-  });
64
-
65
-  it('uses parent insets when available', () => {
66
-    const component = ReactTestRenderer.create(
67
-      <SafeAreaProvider
68
-        initialSafeAreaInsets={{ top: 1, left: 2, right: 3, bottom: 4 }}
69
-      >
70
-        <SafeAreaProvider>
71
-          <PrintInsetsTestView />
72
-        </SafeAreaProvider>
73
-      </SafeAreaProvider>,
74
-    );
75
-    expect(component).toMatchSnapshot();
76
-  });
77
-
78
-  it('uses inner insets', () => {
79
-    const component = ReactTestRenderer.create(
80
-      <SafeAreaProvider
81
-        initialSafeAreaInsets={{ top: 1, left: 2, right: 3, bottom: 4 }}
82
-      >
83
-        <SafeAreaProvider
84
-          initialSafeAreaInsets={{ top: 2, left: 3, right: 4, bottom: 5 }}
85
-        >
86
-          <PrintInsetsTestView />
87
-        </SafeAreaProvider>
88
-      </SafeAreaProvider>,
89
-    );
90
-    expect(component).toMatchSnapshot();
91
-  });
92
-
93
-  it('throws when no provider is rendered', () => {
94
-    // Silence the React error boundary warning; we expect an uncaught error.
95
-    const consoleErrorMock = jest
96
-      .spyOn(console, 'error')
97
-      .mockImplementation(message => {
98
-        if (message.startsWith('The above error occured in the ')) {
99
-          return;
100
-        }
101
-      });
102
-    expect(() => {
103
-      ReactTestRenderer.create(<PrintInsetsTestView />);
104
-    }).toThrow(
105
-      'No safe area value available. Make sure you are rendering `<SafeAreaProvider>` at the top of your app.',
106
-    );
107
-
108
-    consoleErrorMock.mockRestore();
109
-  });
110
-});
111
-
112
-describe('SafeAreaView', () => {
113
-  it('renders', () => {
114
-    const component = ReactTestRenderer.create(
115
-      <SafeAreaProvider
116
-        initialSafeAreaInsets={{ top: 1, left: 2, right: 3, bottom: 4 }}
117
-      >
118
-        <SafeAreaView>
119
-          <View />
120
-        </SafeAreaView>
121
-      </SafeAreaProvider>,
122
-    );
123
-    expect(component).toMatchSnapshot();
124
-  });
125
-
126
-  it('can override padding styles', () => {
127
-    const component = ReactTestRenderer.create(
128
-      <SafeAreaProvider
129
-        initialSafeAreaInsets={{ top: 1, left: 2, right: 3, bottom: 4 }}
130
-      >
131
-        <SafeAreaView style={{ paddingTop: 0 }}>
132
-          <View />
133
-        </SafeAreaView>
134
-      </SafeAreaProvider>,
135
-    );
136
-    expect(component).toMatchSnapshot();
137
-  });
138
-});
139
-
140
-describe('initialWindowSafeAreaInsets', () => {
141
-  it('is null when no view config is available', () => {
142
-    jest.resetModules();
143
-    expect(require('../index').initialWindowSafeAreaInsets).toBe(null);
144
-  });
145
-
146
-  it('it uses the constant provided by the view config', () => {
147
-    jest.resetModules();
148
-    const testInsets = {
149
-      top: 20,
150
-      left: 0,
151
-      right: 0,
152
-      bottom: 0,
153
-    };
154
-    UIManager.getViewManagerConfig = jest.fn(name => {
155
-      if (name === 'RNCSafeAreaView') {
156
-        return {
157
-          Commands: {},
158
-          Constants: {
159
-            initialWindowSafeAreaInsets: testInsets,
160
-          },
161
-        };
162
-      }
163
-      return { Commands: {} };
164
-    });
165
-
166
-    expect(require('../index').initialWindowSafeAreaInsets).toBe(testInsets);
167
-    expect(UIManager.getViewManagerConfig).toBeCalledWith('RNCSafeAreaView');
168
-  });
169
-});

+ 41
- 0
src/__tests__/initialWindowMetrics-test.tsx View File

1
+import { UIManager } from 'react-native';
2
+import { Metrics } from '../SafeArea.types';
3
+
4
+describe('initialWindowMetrics', () => {
5
+  it('is null when no view config is available', () => {
6
+    jest.resetModules();
7
+    expect(require('../InitialWindow').initialWindowMetrics).toBe(null);
8
+  });
9
+
10
+  it('it uses the constant provided by the view config', () => {
11
+    jest.resetModules();
12
+    const testMetrics: Metrics = {
13
+      insets: {
14
+        top: 20,
15
+        left: 0,
16
+        right: 0,
17
+        bottom: 0,
18
+      },
19
+      frame: {
20
+        x: 0,
21
+        y: 0,
22
+        height: 100,
23
+        width: 100,
24
+      },
25
+    };
26
+    UIManager.getViewManagerConfig = jest.fn((name) => {
27
+      if (name === 'RNCSafeAreaView') {
28
+        return {
29
+          Commands: {},
30
+          Constants: {
31
+            initialWindowMetrics: testMetrics,
32
+          },
33
+        };
34
+      }
35
+      return { Commands: {} };
36
+    });
37
+
38
+    expect(require('../InitialWindow').initialWindowMetrics).toBe(testMetrics);
39
+    expect(UIManager.getViewManagerConfig).toBeCalledWith('RNCSafeAreaView');
40
+  });
41
+});

+ 4
- 80
src/index.tsx View File

1
-import * as React from 'react';
2
-import { StyleSheet, View, ViewProps } from 'react-native';
3
-import { EdgeInsets as EdgeInsetsT, InsetChangedEvent } from './SafeArea.types';
4
-import NativeSafeAreaView from './NativeSafeAreaView';
5
-
6
-export { default as initialWindowSafeAreaInsets } from './InitialWindowSafeAreaInsets';
7
-
8
-export const SafeAreaContext = React.createContext<EdgeInsetsT | null>(null);
9
-
10
-export interface SafeAreaViewProps {
11
-  children?: React.ReactNode;
12
-  initialSafeAreaInsets?: EdgeInsetsT | null;
13
-}
14
-
15
-export function SafeAreaProvider({
16
-  children,
17
-  initialSafeAreaInsets,
18
-}: SafeAreaViewProps) {
19
-  const parentInsets = useParentSafeArea();
20
-  const [insets, setInsets] = React.useState<EdgeInsetsT | null | undefined>(
21
-    initialSafeAreaInsets || parentInsets,
22
-  );
23
-  const onInsetsChange = React.useCallback((event: InsetChangedEvent) => {
24
-    setInsets(event.nativeEvent.insets);
25
-  }, []);
26
-
27
-  return (
28
-    <NativeSafeAreaView style={styles.fill} onInsetsChange={onInsetsChange}>
29
-      {insets != null ? (
30
-        <SafeAreaContext.Provider value={insets}>
31
-          {children}
32
-        </SafeAreaContext.Provider>
33
-      ) : null}
34
-    </NativeSafeAreaView>
35
-  );
36
-}
37
-
38
-const styles = StyleSheet.create({
39
-  fill: { flex: 1 },
40
-});
41
-
42
-export const SafeAreaConsumer = SafeAreaContext.Consumer;
43
-
44
-function useParentSafeArea(): React.ContextType<typeof SafeAreaContext> {
45
-  return React.useContext(SafeAreaContext);
46
-}
47
-
48
-export function useSafeArea(): EdgeInsetsT {
49
-  const safeArea = React.useContext(SafeAreaContext);
50
-  if (safeArea == null) {
51
-    throw new Error(
52
-      'No safe area value available. Make sure you are rendering `<SafeAreaProvider>` at the top of your app.',
53
-    );
54
-  }
55
-  return safeArea;
56
-}
57
-
58
-export function SafeAreaView({
59
-  style,
60
-  ...rest
61
-}: ViewProps & { children: React.ReactNode }) {
62
-  const insets = useSafeArea();
63
-
64
-  return (
65
-    <View
66
-      style={[
67
-        {
68
-          paddingTop: insets.top,
69
-          paddingRight: insets.right,
70
-          paddingBottom: insets.bottom,
71
-          paddingLeft: insets.left,
72
-        },
73
-        style,
74
-      ]}
75
-      {...rest}
76
-    />
77
-  );
78
-}
79
-
80
-export type EdgeInsets = EdgeInsetsT;
1
+export * from './SafeAreaContext';
2
+export * from './SafeAreaView';
3
+export * from './InitialWindow';
4
+export * from './SafeArea.types';

+ 5
- 1
tsconfig.json View File

12
     "moduleResolution": "node",
12
     "moduleResolution": "node",
13
     "skipLibCheck": true,
13
     "skipLibCheck": true,
14
     "lib": ["dom", "es2015", "es2016", "esnext"],
14
     "lib": ["dom", "es2015", "es2016", "esnext"],
15
-    "jsx": "react-native"
15
+    "jsx": "react-native",
16
+    "baseUrl": ".",
17
+    "paths": {
18
+      "react-native-safe-area-context": ["./src"]
19
+    }
16
   },
20
   },
17
   "exclude": ["node_modules"]
21
   "exclude": ["node_modules"]
18
 }
22
 }

+ 9268
- 1873
yarn.lock
File diff suppressed because it is too large
View File