react-native-screens 4.19.0-nightly-20251113-5110795ca → 4.19.0-nightly-20251115-10ffdf7ce

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -92,21 +92,10 @@ open class CustomToolbar(
92
92
  // 3. edge-to-edge with translucent navigation buttons bar.
93
93
  //
94
94
  // Additionally we need to gracefully handle possible display cutouts.
95
-
96
- // We use rootWindowInsets in lieu of insets or unhandledInsets here,
97
- // because cutout sometimes (only in certain scenarios, e.g. with headerLeft view present)
98
- // happen to be Insets.ZERO and is not reliable.
99
- val rootWindowInsets = rootWindowInsets
100
95
  val cutoutInsets =
101
- resolveInsetsOrZero(WindowInsetsCompat.Type.displayCutout(), rootWindowInsets)
96
+ resolveInsetsOrZero(WindowInsetsCompat.Type.displayCutout(), unhandledInsets)
102
97
  val systemBarInsets =
103
- resolveInsetsOrZero(WindowInsetsCompat.Type.systemBars(), rootWindowInsets)
104
- val statusBarInsetsStable =
105
- resolveInsetsOrZero(
106
- WindowInsetsCompat.Type.systemBars(),
107
- rootWindowInsets,
108
- ignoreVisibility = true,
109
- )
98
+ resolveInsetsOrZero(WindowInsetsCompat.Type.systemBars(), unhandledInsets)
110
99
 
111
100
  // This seems to work fine in all tested configurations, because cutout & system bars overlap
112
101
  // only in portrait mode & top inset is controlled separately, therefore we don't count
@@ -125,7 +114,7 @@ open class CustomToolbar(
125
114
  val verticalInsets =
126
115
  InsetsCompat.of(
127
116
  0,
128
- max(cutoutInsets.top, if (shouldApplyTopInset) statusBarInsetsStable.top else 0),
117
+ max(cutoutInsets.top, if (shouldApplyTopInset) systemBarInsets.top else 0),
129
118
  0,
130
119
  max(cutoutInsets.bottom, 0),
131
120
  )
@@ -3,6 +3,7 @@
3
3
  package com.swmansion.rnscreens.safearea
4
4
 
5
5
  import android.annotation.SuppressLint
6
+ import android.os.Build
6
7
  import android.util.Log
7
8
  import android.view.View
8
9
  import android.view.ViewTreeObserver
@@ -114,28 +115,45 @@ class SafeAreaView(
114
115
  }
115
116
  }
116
117
 
117
- return WindowInsetsCompat
118
- .Builder(insets)
119
- .apply {
120
- if (insetType.containsSystem()) {
121
- setInsets(
122
- WindowInsetsCompat.Type.systemBars(),
123
- getConsumedInsetsFromSelectedEdges(
124
- insets.getInsets(
125
- WindowInsetsCompat.Type.systemBars(),
126
- ),
127
- ),
128
- )
129
- setInsets(
130
- WindowInsetsCompat.Type.displayCutout(),
131
- getConsumedInsetsFromSelectedEdges(
132
- insets.getInsets(
133
- WindowInsetsCompat.Type.displayCutout(),
134
- ),
135
- ),
136
- )
137
- }
138
- }.build()
118
+ var shouldConsumeDisplayCutout = false
119
+ var consumedInsets =
120
+ WindowInsetsCompat
121
+ .Builder(insets)
122
+ .apply {
123
+ if (insetType.containsSystem()) {
124
+ val consumedSystemBarsInsets =
125
+ getConsumedInsetsFromSelectedEdges(
126
+ insets.getInsets(
127
+ WindowInsetsCompat.Type.systemBars(),
128
+ ),
129
+ )
130
+
131
+ val consumedDisplayCutoutInsets =
132
+ getConsumedInsetsFromSelectedEdges(
133
+ insets.getInsets(
134
+ WindowInsetsCompat.Type.displayCutout(),
135
+ ),
136
+ )
137
+ shouldConsumeDisplayCutout = consumedDisplayCutoutInsets == Insets.NONE
138
+
139
+ setInsets(
140
+ WindowInsetsCompat.Type.systemBars(),
141
+ consumedSystemBarsInsets,
142
+ )
143
+ setInsets(
144
+ WindowInsetsCompat.Type.displayCutout(),
145
+ consumedDisplayCutoutInsets,
146
+ )
147
+ }
148
+ }.build()
149
+
150
+ // On Android versions prior to R, setInsets(WindowInsetsCompat.Type.displayCutout(), ...)
151
+ // does not work. We need to use previous API.
152
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R && shouldConsumeDisplayCutout) {
153
+ consumedInsets = consumedInsets.consumeDisplayCutout()
154
+ }
155
+
156
+ return consumedInsets
139
157
  }
140
158
 
141
159
  private fun updateInsetsIfNeeded(): Boolean {
@@ -22,7 +22,10 @@ internal fun View.resolveInsetsOrZero(
22
22
  return InsetsCompat.NONE
23
23
  }
24
24
 
25
- val windowInsetsCompat = WindowInsetsCompat.toWindowInsetsCompat(sourceWindowInsets, this)
25
+ // We don't use root view-aware WindowInsetsCompat to make sure we get information about display
26
+ // cutout inset being consumed by one of the ancestor views. Refer to WindowInsetsCompat
27
+ // `Impl20` implementation of getInsetsForType (case Type.DISPLAY_CUTOUT).
28
+ val windowInsetsCompat = WindowInsetsCompat.toWindowInsetsCompat(sourceWindowInsets)
26
29
  return if (!ignoreVisibility) {
27
30
  windowInsetsCompat.getInsets(insetType)
28
31
  } else {
package/ios/RNSScreen.mm CHANGED
@@ -1723,10 +1723,7 @@ Class<RCTComponentViewProtocol> RNSScreenCls(void)
1723
1723
 
1724
1724
  _isSwiping = NO;
1725
1725
  _shouldNotify = YES;
1726
- #ifdef RCT_NEW_ARCH_ENABLED
1727
- #else
1728
- [self traverseForScrollView:self.screenView];
1729
- #endif
1726
+
1730
1727
  if (@available(iOS 26, *)) {
1731
1728
  // Reenable interactions, see willMoveToWindow
1732
1729
  [RNSScreenView.viewInteractionManagerInstance enableInteractionsForLastSubtree];
@@ -2188,33 +2185,7 @@ Class<RCTComponentViewProtocol> RNSScreenCls(void)
2188
2185
  }
2189
2186
  }
2190
2187
 
2191
- #else
2192
- #pragma mark - Paper specific
2193
-
2194
- - (void)traverseForScrollView:(UIView *)view
2195
- {
2196
- if (![[self.view valueForKey:@"_bridge"] valueForKey:@"_jsThread"]) {
2197
- // we don't want to send `scrollViewDidEndDecelerating` event to JS before the JS thread is ready
2198
- return;
2199
- }
2200
-
2201
- if ([NSStringFromClass([view class]) isEqualToString:@"AVPlayerView"]) {
2202
- // Traversing through AVPlayerView is an uncommon edge case that causes the disappearing screen
2203
- // to an excessive traversal through all video player elements
2204
- // (e.g., for react-native-video, this includes all controls and additional video views).
2205
- // Thus, we want to avoid unnecessary traversals through these views.
2206
- return;
2207
- }
2208
-
2209
- if ([view isKindOfClass:[UIScrollView class]] &&
2210
- ([[(UIScrollView *)view delegate] respondsToSelector:@selector(scrollViewDidEndDecelerating:)])) {
2211
- [[(UIScrollView *)view delegate] scrollViewDidEndDecelerating:(id)view];
2212
- }
2213
- [view.subviews enumerateObjectsUsingBlock:^(__kindof UIView *_Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) {
2214
- [self traverseForScrollView:obj];
2215
- }];
2216
- }
2217
- #endif
2188
+ #endif // RCT_NEW_ARCH_ENABLED
2218
2189
 
2219
2190
  @end
2220
2191
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-screens",
3
- "version": "4.19.0-nightly-20251113-5110795ca",
3
+ "version": "4.19.0-nightly-20251115-10ffdf7ce",
4
4
  "description": "Native navigation primitives for your React Native app.",
5
5
  "scripts": {
6
6
  "submodules": "git submodule update --init --recursive && (cd react-navigation && yarn && yarn build && cd ../)",