react-native-screens 4.5.0 → 4.6.0-beta.1

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.
Files changed (68) hide show
  1. package/android/build.gradle +1 -1
  2. package/android/src/fabric/java/com/swmansion/rnscreens/FabricEnabledHeaderConfigViewGroup.kt +31 -10
  3. package/android/src/fabric/java/com/swmansion/rnscreens/FabricEnabledHeaderSubviewViewGroup.kt +51 -0
  4. package/android/src/main/java/com/swmansion/rnscreens/CustomToolbar.kt +12 -2
  5. package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +0 -26
  6. package/android/src/main/java/com/swmansion/rnscreens/ScreenModalFragment.kt +4 -1
  7. package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +16 -7
  8. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +5 -0
  9. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigViewManager.kt +1 -0
  10. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubview.kt +12 -7
  11. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderSubviewManager.kt +13 -0
  12. package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +7 -0
  13. package/android/src/main/java/com/swmansion/rnscreens/bottomsheet/BottomSheetBehaviorExt.kt +6 -3
  14. package/android/src/main/java/com/swmansion/rnscreens/bottomsheet/BottomSheetDialogRootView.kt +1 -1
  15. package/android/src/main/java/com/swmansion/rnscreens/bottomsheet/DimmingView.kt +1 -2
  16. package/android/src/main/java/com/swmansion/rnscreens/bottomsheet/GestureTransparentViewGroup.kt +0 -1
  17. package/android/src/main/java/com/swmansion/rnscreens/bottomsheet/SheetUtils.kt +2 -2
  18. package/android/src/main/java/com/swmansion/rnscreens/utils/ScreenDummyLayoutHelper.kt +6 -3
  19. package/android/src/main/jni/rnscreens.h +1 -0
  20. package/android/src/paper/java/com/swmansion/rnscreens/FabricEnabledHeaderConfigViewGroup.kt +9 -1
  21. package/android/src/paper/java/com/swmansion/rnscreens/FabricEnabledHeaderSubviewViewGroup.kt +19 -0
  22. package/common/cpp/react/renderer/components/rnscreens/RNSFullWindowOverlayComponentDescriptor.h +17 -0
  23. package/common/cpp/react/renderer/components/rnscreens/RNSFullWindowOverlayShadowNode.cpp +7 -0
  24. package/common/cpp/react/renderer/components/rnscreens/RNSFullWindowOverlayShadowNode.h +35 -0
  25. package/common/cpp/react/renderer/components/rnscreens/RNSFullWindowOverlayState.h +30 -0
  26. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigComponentDescriptor.h +12 -2
  27. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigShadowNode.cpp +12 -0
  28. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigShadowNode.h +4 -0
  29. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigState.cpp +4 -10
  30. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigState.h +15 -9
  31. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewComponentDescriptor.h +20 -0
  32. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewShadowNode.cpp +14 -0
  33. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewShadowNode.h +2 -0
  34. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewState.cpp +3 -1
  35. package/common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewState.h +16 -2
  36. package/ios/RNSFullWindowOverlay.mm +10 -0
  37. package/ios/RNSScreenStack.mm +11 -7
  38. package/ios/RNSScreenStackHeaderConfig.h +21 -7
  39. package/ios/RNSScreenStackHeaderConfig.mm +77 -17
  40. package/ios/RNSScreenStackHeaderSubview.h +4 -0
  41. package/ios/RNSScreenStackHeaderSubview.mm +26 -1
  42. package/lib/commonjs/components/ScreenStackHeaderConfig.js +0 -1
  43. package/lib/commonjs/components/ScreenStackHeaderConfig.js.map +1 -1
  44. package/lib/commonjs/fabric/FullWindowOverlayNativeComponent.js +3 -1
  45. package/lib/commonjs/fabric/FullWindowOverlayNativeComponent.js.map +1 -1
  46. package/lib/commonjs/gesture-handler/ScreenGestureDetector.js +12 -0
  47. package/lib/commonjs/gesture-handler/ScreenGestureDetector.js.map +1 -1
  48. package/lib/commonjs/gesture-handler/defaults.js +1 -2
  49. package/lib/commonjs/gesture-handler/defaults.js.map +1 -1
  50. package/lib/module/components/ScreenStackHeaderConfig.js +0 -1
  51. package/lib/module/components/ScreenStackHeaderConfig.js.map +1 -1
  52. package/lib/module/fabric/FullWindowOverlayNativeComponent.js +3 -1
  53. package/lib/module/fabric/FullWindowOverlayNativeComponent.js.map +1 -1
  54. package/lib/module/gesture-handler/ScreenGestureDetector.js +12 -0
  55. package/lib/module/gesture-handler/ScreenGestureDetector.js.map +1 -1
  56. package/lib/module/gesture-handler/defaults.js +1 -2
  57. package/lib/module/gesture-handler/defaults.js.map +1 -1
  58. package/lib/typescript/fabric/FullWindowOverlayNativeComponent.d.ts.map +1 -1
  59. package/lib/typescript/gesture-handler/ScreenGestureDetector.d.ts.map +1 -1
  60. package/lib/typescript/gesture-handler/defaults.d.ts.map +1 -1
  61. package/lib/typescript/types.d.ts +25 -3
  62. package/lib/typescript/types.d.ts.map +1 -1
  63. package/package.json +10 -9
  64. package/src/components/ScreenStackHeaderConfig.tsx +0 -1
  65. package/src/fabric/FullWindowOverlayNativeComponent.ts +3 -1
  66. package/src/gesture-handler/ScreenGestureDetector.tsx +14 -2
  67. package/src/gesture-handler/defaults.ts +0 -1
  68. package/src/types.tsx +25 -3
@@ -20,7 +20,7 @@ buildscript {
20
20
  mavenCentral()
21
21
  }
22
22
  dependencies {
23
- classpath('com.android.tools.build:gradle:4.2.2')
23
+ classpath('com.android.tools.build:gradle:8.2.1')
24
24
  classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${safeExtGet('kotlinVersion', rnsDefaultKotlinVersion)}"
25
25
  classpath "com.diffplug.spotless:spotless-plugin-gradle:6.25.0"
26
26
  }
@@ -14,6 +14,8 @@ abstract class FabricEnabledHeaderConfigViewGroup(
14
14
  ) : ViewGroup(context) {
15
15
  private var mStateWrapper: StateWrapper? = null
16
16
 
17
+ private var lastWidth = 0f
18
+ private var lastHeight = 0f
17
19
  private var lastPaddingStart = 0f
18
20
  private var lastPaddingEnd = 0f
19
21
 
@@ -21,36 +23,55 @@ abstract class FabricEnabledHeaderConfigViewGroup(
21
23
  mStateWrapper = wrapper
22
24
  }
23
25
 
24
- fun updatePaddingsFabric(
26
+ fun updatePaddings(
25
27
  paddingStart: Int,
26
28
  paddingEnd: Int,
27
29
  ) {
28
- updateState(paddingStart, paddingEnd)
30
+ // Do nothing on Fabric. This method is used only on Paper.
31
+ }
32
+
33
+ fun updateHeaderConfigState(
34
+ width: Int,
35
+ height: Int,
36
+ paddingStart: Int,
37
+ paddingEnd: Int,
38
+ ) {
39
+ updateState(width, height, paddingStart, paddingEnd)
29
40
  }
30
41
 
31
42
  @UiThread
32
43
  fun updateState(
44
+ width: Int,
45
+ height: Int,
33
46
  paddingStart: Int,
34
47
  paddingEnd: Int,
35
48
  ) {
36
- val paddingStartDip: Float = PixelUtil.toDIPFromPixel(paddingStart.toFloat())
37
- val paddingEndDip: Float = PixelUtil.toDIPFromPixel(paddingEnd.toFloat())
49
+ val realWidth: Float = PixelUtil.toDIPFromPixel(width.toFloat())
50
+ val realHeight: Float = PixelUtil.toDIPFromPixel(height.toFloat())
51
+ val realPaddingStart: Float = PixelUtil.toDIPFromPixel(paddingStart.toFloat())
52
+ val realPaddingEnd: Float = PixelUtil.toDIPFromPixel(paddingEnd.toFloat())
38
53
 
39
54
  // Check incoming state values. If they're already the correct value, return early to prevent
40
55
  // infinite UpdateState/SetState loop.
41
- if (abs(lastPaddingStart - paddingStart) < DELTA &&
42
- abs(lastPaddingEnd - paddingEnd) < DELTA
56
+ if (abs(lastWidth - realWidth) < DELTA &&
57
+ abs(lastHeight - realHeight) < DELTA &&
58
+ abs(lastPaddingStart - realPaddingStart) < DELTA &&
59
+ abs(lastPaddingEnd - realPaddingEnd) < DELTA
43
60
  ) {
44
61
  return
45
62
  }
46
63
 
47
- lastPaddingStart = paddingStartDip
48
- lastPaddingEnd = paddingEndDip
64
+ lastWidth = realWidth
65
+ lastHeight = realHeight
66
+ lastPaddingStart = realPaddingStart
67
+ lastPaddingEnd = realPaddingEnd
49
68
 
50
69
  val map: WritableMap =
51
70
  WritableNativeMap().apply {
52
- putDouble("paddingStart", paddingStartDip.toDouble())
53
- putDouble("paddingEnd", paddingEndDip.toDouble())
71
+ putDouble("frameWidth", realWidth.toDouble())
72
+ putDouble("frameHeight", realHeight.toDouble())
73
+ putDouble("paddingStart", realPaddingStart.toDouble())
74
+ putDouble("paddingEnd", realPaddingEnd.toDouble())
54
75
  }
55
76
  mStateWrapper?.updateState(map)
56
77
  }
@@ -0,0 +1,51 @@
1
+ package com.swmansion.rnscreens
2
+
3
+ import android.content.Context
4
+ import android.view.ViewGroup
5
+ import androidx.annotation.UiThread
6
+ import com.facebook.react.bridge.WritableMap
7
+ import com.facebook.react.bridge.WritableNativeMap
8
+ import com.facebook.react.uimanager.PixelUtil
9
+ import com.facebook.react.uimanager.StateWrapper
10
+
11
+ abstract class FabricEnabledHeaderSubviewViewGroup(
12
+ context: Context?,
13
+ ) : ViewGroup(context) {
14
+ private var mStateWrapper: StateWrapper? = null
15
+
16
+ fun setStateWrapper(wrapper: StateWrapper?) {
17
+ mStateWrapper = wrapper
18
+ }
19
+
20
+ protected fun updateSubviewFrameState(
21
+ width: Int,
22
+ height: Int,
23
+ offsetX: Int,
24
+ offsetY: Int,
25
+ ) {
26
+ updateState(width, height, offsetX, offsetY)
27
+ }
28
+
29
+ @UiThread
30
+ fun updateState(
31
+ width: Int,
32
+ height: Int,
33
+ offsetX: Int,
34
+ offsetY: Int,
35
+ ) {
36
+ val realWidth: Float = PixelUtil.toDIPFromPixel(width.toFloat())
37
+ val realHeight: Float = PixelUtil.toDIPFromPixel(height.toFloat())
38
+ val offsetXDip: Float = PixelUtil.toDIPFromPixel(offsetX.toFloat())
39
+ val offsetYDip: Float = PixelUtil.toDIPFromPixel(offsetY.toFloat())
40
+
41
+ val map: WritableMap =
42
+ WritableNativeMap().apply {
43
+ putDouble("frameWidth", realWidth.toDouble())
44
+ putDouble("frameHeight", realHeight.toDouble())
45
+ putDouble("contentOffsetX", offsetXDip.toDouble())
46
+ putDouble("contentOffsetY", offsetYDip.toDouble())
47
+ }
48
+
49
+ mStateWrapper?.updateState(map)
50
+ }
51
+ }
@@ -68,8 +68,18 @@ open class CustomToolbar(
68
68
  ) {
69
69
  super.onLayout(changed, l, t, r, b)
70
70
 
71
- // our children are already laid out
71
+ if (!changed) {
72
+ return
73
+ }
74
+
72
75
  val contentInsetStart = if (navigationIcon != null) contentInsetStartWithNavigation else contentInsetStart
73
- config.updatePaddingsFabric(contentInsetStart, contentInsetEnd)
76
+ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
77
+ val width = r - l
78
+ val height = b - t
79
+ config.updateHeaderConfigState(width, height, contentInsetStart, contentInsetEnd)
80
+ } else {
81
+ // our children are already laid out
82
+ config.updatePaddings(contentInsetStart, contentInsetEnd)
83
+ }
74
84
  }
75
85
  }
@@ -17,12 +17,9 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
17
17
  import com.facebook.react.bridge.GuardedRunnable
18
18
  import com.facebook.react.bridge.ReactContext
19
19
  import com.facebook.react.uimanager.PixelUtil
20
- import com.facebook.react.uimanager.ReactClippingViewGroup
21
20
  import com.facebook.react.uimanager.UIManagerHelper
22
21
  import com.facebook.react.uimanager.UIManagerModule
23
22
  import com.facebook.react.uimanager.events.EventDispatcher
24
- import com.facebook.react.views.scroll.ReactHorizontalScrollView
25
- import com.facebook.react.views.scroll.ReactScrollView
26
23
  import com.google.android.material.bottomsheet.BottomSheetBehavior
27
24
  import com.google.android.material.shape.CornerFamily
28
25
  import com.google.android.material.shape.MaterialShapeDrawable
@@ -404,29 +401,6 @@ class Screen(
404
401
  }
405
402
 
406
403
  if (child is ViewGroup) {
407
- // The children are miscounted when there's removeClippedSubviews prop
408
- // set to true (which is the default for FlatLists).
409
- // Unless the child is a ScrollView it's safe to assume that it's true
410
- // and add a simple view for each possibly clipped item to make it work as expected.
411
- // See https://github.com/software-mansion/react-native-screens/pull/2495
412
-
413
- if (child is ReactClippingViewGroup &&
414
- child.removeClippedSubviews &&
415
- child !is ReactScrollView &&
416
- child !is ReactHorizontalScrollView
417
- ) {
418
- // We need to workaround the issue until our changes land in core.
419
- // Some views do not accept any children or have set amount and they throw
420
- // when we want to brute-forcefully manipulate that.
421
- // Is this ugly? Very. Do we have better option before changes land in core?
422
- // I'm not aware of any.
423
- try {
424
- for (j in 0 until child.childCount) {
425
- child.addView(View(context))
426
- }
427
- } catch (_: Exception) {
428
- }
429
- }
430
404
  startTransitionRecursive(child)
431
405
  }
432
406
  }
@@ -72,7 +72,10 @@ class ScreenModalFragment :
72
72
  override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
73
73
  configureDialogAndBehaviour()
74
74
 
75
- val reactEventDispatcher = checkNotNull(screen.reactEventDispatcher) { "[RNScreens] No ReactEventDispatcher attached to screen while creating modal fragment" }
75
+ val reactEventDispatcher =
76
+ checkNotNull(
77
+ screen.reactEventDispatcher,
78
+ ) { "[RNScreens] No ReactEventDispatcher attached to screen while creating modal fragment" }
76
79
  val rootView = BottomSheetDialogRootView(screen.reactContext, reactEventDispatcher)
77
80
 
78
81
  rootView.addView(screen.recycle())
@@ -248,7 +248,7 @@ class ScreenStack(
248
248
 
249
249
  if (shouldUseOpenAnimation &&
250
250
  newTop != null &&
251
- needsDrawReordering(newTop) &&
251
+ needsDrawReordering(newTop, stackAnimation) &&
252
252
  visibleBottom == null
253
253
  ) {
254
254
  // When using an open animation in which two screens overlap (eg. fade_from_bottom or
@@ -258,6 +258,7 @@ class ScreenStack(
258
258
  // appears on top of the previous one. You can read more about in the comment
259
259
  // for the code we use to change that behavior:
260
260
  // https://github.com/airbnb/native-navigation/blob/9cf50bf9b751b40778f473f3b19fcfe2c4d40599/lib/android/src/main/java/com/airbnb/android/react/navigation/ScreenCoordinatorLayout.java#L18
261
+ // Note: This should not be set in case there is only a single screen in stack or animation `none` is used. Atm needsDrawReordering implementation guards that assuming that first screen on stack uses `NONE` animation.
261
262
  isDetachingCurrentScreen = true
262
263
  }
263
264
 
@@ -426,14 +427,22 @@ class ScreenStack(
426
427
  companion object {
427
428
  const val TAG = "ScreenStack"
428
429
 
429
- private fun needsDrawReordering(fragmentWrapper: ScreenFragmentWrapper): Boolean =
430
+ private fun needsDrawReordering(
431
+ fragmentWrapper: ScreenFragmentWrapper,
432
+ resolvedStackAnimation: StackAnimation?,
433
+ ): Boolean {
434
+ val stackAnimation = if (resolvedStackAnimation != null) resolvedStackAnimation else fragmentWrapper.screen.stackAnimation
430
435
  // On Android sdk 33 and above the animation is different and requires draw reordering.
431
436
  // For React Native 0.70 and lower versions, `Build.VERSION_CODES.TIRAMISU` is not defined yet.
432
437
  // Hence, we're comparing numerical version here.
433
- Build.VERSION.SDK_INT >= 33 ||
434
- fragmentWrapper.screen.stackAnimation === StackAnimation.SLIDE_FROM_BOTTOM ||
435
- fragmentWrapper.screen.stackAnimation === StackAnimation.FADE_FROM_BOTTOM ||
436
- fragmentWrapper.screen.stackAnimation === StackAnimation.IOS_FROM_RIGHT ||
437
- fragmentWrapper.screen.stackAnimation === StackAnimation.IOS_FROM_LEFT
438
+ return (
439
+ Build.VERSION.SDK_INT >= 33 ||
440
+ stackAnimation === StackAnimation.SLIDE_FROM_BOTTOM ||
441
+ stackAnimation === StackAnimation.FADE_FROM_BOTTOM ||
442
+ stackAnimation === StackAnimation.IOS_FROM_RIGHT ||
443
+ stackAnimation === StackAnimation.IOS_FROM_LEFT
444
+ ) &&
445
+ stackAnimation !== StackAnimation.NONE
446
+ }
438
447
  }
439
448
  }
@@ -478,6 +478,11 @@ class ScreenStackFragment :
478
478
  screen.background = shape
479
479
  }
480
480
 
481
+ override fun onStart() {
482
+ lastFocusedChild?.requestFocus()
483
+ super.onStart()
484
+ }
485
+
481
486
  override fun onStop() {
482
487
  if (DeviceUtils.isPlatformAndroidTV(context)) {
483
488
  lastFocusedChild = findLastFocusedChild()
@@ -157,6 +157,7 @@ class ScreenStackHeaderConfigViewManager :
157
157
  config.setHideBackButton(hideBackButton)
158
158
  }
159
159
 
160
+ @Deprecated("For apps targeting SDK 35 or above edge-to-edge is enabled by default.")
160
161
  @ReactProp(name = "topInsetEnabled")
161
162
  override fun setTopInsetEnabled(
162
163
  config: ScreenStackHeaderConfig,
@@ -3,12 +3,11 @@ package com.swmansion.rnscreens
3
3
  import android.annotation.SuppressLint
4
4
  import android.view.View
5
5
  import com.facebook.react.bridge.ReactContext
6
- import com.facebook.react.views.view.ReactViewGroup
7
6
 
8
7
  @SuppressLint("ViewConstructor")
9
8
  class ScreenStackHeaderSubview(
10
9
  context: ReactContext?,
11
- ) : ReactViewGroup(context) {
10
+ ) : FabricEnabledHeaderSubviewViewGroup(context) {
12
11
  private var reactWidth = 0
13
12
  private var reactHeight = 0
14
13
  var type = Type.RIGHT
@@ -37,11 +36,17 @@ class ScreenStackHeaderSubview(
37
36
 
38
37
  override fun onLayout(
39
38
  changed: Boolean,
40
- left: Int,
41
- top: Int,
42
- right: Int,
43
- bottom: Int,
44
- ) = Unit
39
+ l: Int,
40
+ t: Int,
41
+ r: Int,
42
+ b: Int,
43
+ ) {
44
+ if (changed && BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
45
+ val width = r - l
46
+ val height = b - t
47
+ updateSubviewFrameState(width, height, l, t)
48
+ }
49
+ }
45
50
 
46
51
  enum class Type {
47
52
  LEFT,
@@ -2,6 +2,8 @@ package com.swmansion.rnscreens
2
2
 
3
3
  import com.facebook.react.bridge.JSApplicationIllegalArgumentException
4
4
  import com.facebook.react.module.annotations.ReactModule
5
+ import com.facebook.react.uimanager.ReactStylesDiffMap
6
+ import com.facebook.react.uimanager.StateWrapper
5
7
  import com.facebook.react.uimanager.ThemedReactContext
6
8
  import com.facebook.react.uimanager.ViewGroupManager
7
9
  import com.facebook.react.uimanager.ViewManagerDelegate
@@ -39,6 +41,17 @@ class ScreenStackHeaderSubviewManager :
39
41
  }
40
42
  }
41
43
 
44
+ override fun updateState(
45
+ view: ScreenStackHeaderSubview,
46
+ props: ReactStylesDiffMap?,
47
+ stateWrapper: StateWrapper?,
48
+ ): Any? {
49
+ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
50
+ view.setStateWrapper(stateWrapper)
51
+ }
52
+ return super.updateState(view, props, stateWrapper)
53
+ }
54
+
42
55
  protected override fun getDelegate(): ViewManagerDelegate<ScreenStackHeaderSubview> = delegate
43
56
 
44
57
  companion object {
@@ -192,6 +192,10 @@ open class ScreenViewManager :
192
192
  view.isStatusBarAnimated = animated
193
193
  }
194
194
 
195
+ @Deprecated(
196
+ "For apps targeting SDK 35 or above this prop has no effect. " +
197
+ "Since the edge-to-edge is enabled by default the color is always translucent.",
198
+ )
195
199
  @ReactProp(name = "statusBarColor", customType = "Color")
196
200
  override fun setStatusBarColor(
197
201
  view: Screen,
@@ -208,6 +212,7 @@ open class ScreenViewManager :
208
212
  view.statusBarStyle = statusBarStyle
209
213
  }
210
214
 
215
+ @Deprecated("For apps targeting SDK 35 or above edge-to-edge is enabled by default and will be enforced in the future.")
211
216
  @ReactProp(name = "statusBarTranslucent")
212
217
  override fun setStatusBarTranslucent(
213
218
  view: Screen,
@@ -224,6 +229,7 @@ open class ScreenViewManager :
224
229
  view.isStatusBarHidden = statusBarHidden
225
230
  }
226
231
 
232
+ @Deprecated("For apps targeting SDK 35 or above this prop has no effect")
227
233
  @ReactProp(name = "navigationBarColor", customType = "Color")
228
234
  override fun setNavigationBarColor(
229
235
  view: Screen,
@@ -232,6 +238,7 @@ open class ScreenViewManager :
232
238
  view.navigationBarColor = navigationBarColor
233
239
  }
234
240
 
241
+ @Deprecated("For apps targeting SDK 35 or above edge-to-edge is enabled by default")
235
242
  @ReactProp(name = "navigationBarTranslucent")
236
243
  override fun setNavigationBarTranslucent(
237
244
  view: Screen,
@@ -3,7 +3,10 @@ package com.swmansion.rnscreens.bottomsheet
3
3
  import android.view.View
4
4
  import com.google.android.material.bottomsheet.BottomSheetBehavior
5
5
 
6
- internal fun <T : View> BottomSheetBehavior<T>.useSingleDetent(height: Int? = null, forceExpandedState: Boolean = true): BottomSheetBehavior<T> {
6
+ internal fun <T : View> BottomSheetBehavior<T>.useSingleDetent(
7
+ height: Int? = null,
8
+ forceExpandedState: Boolean = true,
9
+ ): BottomSheetBehavior<T> {
7
10
  this.skipCollapsed = true
8
11
  this.isFitToContents = true
9
12
  if (forceExpandedState) {
@@ -16,7 +19,7 @@ internal fun <T : View> BottomSheetBehavior<T>.useSingleDetent(height: Int? = nu
16
19
  internal fun <T : View> BottomSheetBehavior<T>.useTwoDetents(
17
20
  @BottomSheetBehavior.StableState state: Int? = null,
18
21
  firstHeight: Int? = null,
19
- secondHeight: Int? = null
22
+ secondHeight: Int? = null,
20
23
  ): BottomSheetBehavior<T> {
21
24
  skipCollapsed = false
22
25
  isFitToContents = true
@@ -30,7 +33,7 @@ internal fun <T : View> BottomSheetBehavior<T>.useThreeDetents(
30
33
  @BottomSheetBehavior.StableState state: Int? = null,
31
34
  firstHeight: Int? = null,
32
35
  halfExpandedRatio: Float? = null,
33
- expandedOffsetFromTop: Int? = null
36
+ expandedOffsetFromTop: Int? = null,
34
37
  ): BottomSheetBehavior<T> {
35
38
  skipCollapsed = false
36
39
  isFitToContents = false
@@ -37,7 +37,7 @@ class BottomSheetDialogRootView(
37
37
  if (changed) {
38
38
  // This view is used right now only in ScreenModalFragment, where it is injected
39
39
  // to view hierarchy as a parent of a Screen.
40
- assert(childCount == 1) { "[RNScreens] Expected only a single child view under ${TAG}, received: ${childCount}"}
40
+ assert(childCount == 1) { "[RNScreens] Expected only a single child view under $TAG, received: $childCount" }
41
41
  getChildAt(0).layout(l, t, r, b)
42
42
  }
43
43
  }
@@ -57,8 +57,7 @@ class DimmingView(
57
57
  y: Float,
58
58
  ) = blockGestures
59
59
 
60
- override fun getPointerEvents(): PointerEvents =
61
- if (blockGestures) PointerEvents.AUTO else PointerEvents.NONE
60
+ override fun getPointerEvents(): PointerEvents = if (blockGestures) PointerEvents.AUTO else PointerEvents.NONE
62
61
 
63
62
  companion object {
64
63
  const val TAG = "DimmingView"
@@ -15,7 +15,6 @@ class GestureTransparentViewGroup(
15
15
  context: Context,
16
16
  ) : FrameLayout(context),
17
17
  ReactPointerEventsView {
18
-
19
18
  override fun getPointerEvents(): PointerEvents = PointerEvents.BOX_NONE
20
19
 
21
20
  companion object {
@@ -129,7 +129,7 @@ object SheetUtils {
129
129
 
130
130
  fun Screen.isSheetFitToContents(): Boolean =
131
131
  stackPresentation === Screen.StackPresentation.FORM_SHEET &&
132
- sheetDetents.count() == 1 &&
133
- sheetDetents.first() == Screen.SHEET_FIT_TO_CONTENTS
132
+ sheetDetents.count() == 1 &&
133
+ sheetDetents.first() == Screen.SHEET_FIT_TO_CONTENTS
134
134
 
135
135
  fun Screen.usesFormSheetPresentation(): Boolean = stackPresentation === Screen.StackPresentation.FORM_SHEET
@@ -82,7 +82,9 @@ internal class ScreenDummyLayoutHelper(
82
82
  // We need to use activity here, as react context does not have theme attributes required by
83
83
  // AppBarLayout attached leading to crash.
84
84
  val contextWithTheme =
85
- requireNotNull(reactContext.currentActivity) { "[RNScreens] Attempt to use context detached from activity. This could happen only due to race-condition." }
85
+ requireNotNull(reactContext.currentActivity) {
86
+ "[RNScreens] Attempt to use context detached from activity. This could happen only due to race-condition."
87
+ }
86
88
 
87
89
  synchronized(this) {
88
90
  // The layout could have been initialised when this thread waited for access to critical section.
@@ -166,7 +168,7 @@ internal class ScreenDummyLayoutHelper(
166
168
  // is still null at this execution point. We don't wanna crash in such case, thus returning zeroed height.
167
169
  Log.e(
168
170
  TAG,
169
- "[RNScreens] Failed to late-init layout while computing header height. This is most likely a race-condition-bug in react-native-screens, please file an issue at https://github.com/software-mansion/react-native-screens/issues"
171
+ "[RNScreens] Failed to late-init layout while computing header height. This is most likely a race-condition-bug in react-native-screens, please file an issue at https://github.com/software-mansion/react-native-screens/issues",
170
172
  )
171
173
  return 0.0f
172
174
  }
@@ -214,7 +216,8 @@ internal class ScreenDummyLayoutHelper(
214
216
  private fun requireReactContext(lazyMessage: (() -> Any)? = null): ReactApplicationContext =
215
217
  requireNotNull(
216
218
  reactContextRef.get(),
217
- lazyMessage ?: { "[RNScreens] Attempt to require missing react context" })
219
+ lazyMessage ?: { "[RNScreens] Attempt to require missing react context" },
220
+ )
218
221
 
219
222
  private fun requireActivity(): Activity =
220
223
  requireNotNull(requireReactContext().currentActivity) {
@@ -20,6 +20,7 @@
20
20
  #include <react/renderer/components/rnscreens/RNSModalScreenComponentDescriptor.h>
21
21
  #include <react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewComponentDescriptor.h>
22
22
  #include <react/renderer/components/rnscreens/RNSScreenStackHeaderConfigComponentDescriptor.h>
23
+ #include <react/renderer/components/rnscreens/RNSFullWindowOverlayComponentDescriptor.h>
23
24
 
24
25
  namespace facebook {
25
26
  namespace react {
@@ -16,7 +16,15 @@ abstract class FabricEnabledHeaderConfigViewGroup(
16
16
 
17
17
  fun setStateWrapper(wrapper: StateWrapper?) = Unit
18
18
 
19
- fun updatePaddingsFabric(
19
+ // Do nothing on Paper. This method is used only on Fabric.
20
+ fun updateHeaderConfigState(
21
+ width: Int,
22
+ height: Int,
23
+ paddingStart: Int,
24
+ paddingEnd: Int,
25
+ ) = Unit
26
+
27
+ fun updatePaddings(
20
28
  paddingStart: Int,
21
29
  paddingEnd: Int,
22
30
  ) {
@@ -0,0 +1,19 @@
1
+ package com.swmansion.rnscreens
2
+
3
+ import android.content.Context
4
+ import android.view.ViewGroup
5
+ import com.facebook.react.uimanager.StateWrapper
6
+
7
+ abstract class FabricEnabledHeaderSubviewViewGroup(
8
+ context: Context?,
9
+ ) : ViewGroup(context) {
10
+ fun setStateWrapper(wrapper: StateWrapper?) = Unit
11
+
12
+ // Fabric only
13
+ protected fun updateSubviewFrameState(
14
+ width: Int,
15
+ height: Int,
16
+ offsetX: Int,
17
+ offsetY: Int,
18
+ ) = Unit
19
+ }
@@ -0,0 +1,17 @@
1
+ #pragma once
2
+
3
+ #ifdef ANDROID
4
+ #include <fbjni/fbjni.h>
5
+ #endif // ANDROID
6
+ #include <react/renderer/core/ConcreteComponentDescriptor.h>
7
+ #include "RNSFullWindowOverlayShadowNode.h"
8
+
9
+ namespace facebook::react {
10
+
11
+ class RNSFullWindowOverlayComponentDescriptor final
12
+ : public ConcreteComponentDescriptor<RNSFullWindowOverlayShadowNode> {
13
+ public:
14
+ using ConcreteComponentDescriptor::ConcreteComponentDescriptor;
15
+ };
16
+
17
+ } // namespace facebook::react
@@ -0,0 +1,7 @@
1
+ #include "RNSFullWindowOverlayShadowNode.h"
2
+
3
+ namespace facebook::react {
4
+
5
+ extern const char RNSFullWindowOverlayComponentName[] = "RNSFullWindowOverlay";
6
+
7
+ } // namespace facebook::react
@@ -0,0 +1,35 @@
1
+ #pragma once
2
+
3
+ #include <jsi/jsi.h>
4
+ #include <react/renderer/components/rnscreens/EventEmitters.h>
5
+ #include <react/renderer/components/rnscreens/Props.h>
6
+ #include <react/renderer/components/view/ConcreteViewShadowNode.h>
7
+ #include <react/renderer/core/LayoutContext.h>
8
+ #include "RNSFullWindowOverlayState.h"
9
+
10
+ namespace facebook::react {
11
+
12
+ JSI_EXPORT extern const char RNSFullWindowOverlayComponentName[];
13
+
14
+ using ConcreteViewShadowNodeSuperType = ConcreteViewShadowNode<
15
+ RNSFullWindowOverlayComponentName,
16
+ RNSFullWindowOverlayProps,
17
+ RNSFullWindowOverlayEventEmitter,
18
+ RNSFullWindowOverlayState>;
19
+
20
+ class JSI_EXPORT RNSFullWindowOverlayShadowNode final
21
+ : public ConcreteViewShadowNodeSuperType {
22
+ public:
23
+ using ConcreteViewShadowNode::ConcreteViewShadowNode;
24
+ using StateData = ConcreteViewShadowNode::ConcreteStateData;
25
+
26
+ #if !defined(ANDROID)
27
+ static ShadowNodeTraits BaseTraits() {
28
+ auto traits = ConcreteViewShadowNodeSuperType::BaseTraits();
29
+ traits.set(ShadowNodeTraits::Trait::RootNodeKind);
30
+ return traits;
31
+ }
32
+ #endif
33
+ };
34
+
35
+ } // namespace facebook::react
@@ -0,0 +1,30 @@
1
+ #pragma once
2
+
3
+ #if defined(ANDROID)
4
+ #include <folly/dynamic.h>
5
+ #include <react/renderer/mapbuffer/MapBuffer.h>
6
+ #include <react/renderer/mapbuffer/MapBufferBuilder.h>
7
+ #endif // ANDROID
8
+
9
+ #include <react/renderer/core/graphicsConversions.h>
10
+ #include <react/renderer/graphics/Float.h>
11
+
12
+ namespace facebook::react {
13
+
14
+ class JSI_EXPORT RNSFullWindowOverlayState final {
15
+ public:
16
+ using Shared = std::shared_ptr<const RNSFullWindowOverlayState>;
17
+
18
+ RNSFullWindowOverlayState() = default;
19
+
20
+ #if defined(ANDROID)
21
+ RNSFullWindowOverlayState(
22
+ const RNSFullWindowOverlayState &previousState,
23
+ folly::dynamic data) {}
24
+ folly::dynamic getDynamic() const {
25
+ return {};
26
+ }
27
+ #endif
28
+ };
29
+
30
+ } // namespace facebook::react
@@ -34,8 +34,18 @@ class RNSScreenStackHeaderConfigComponentDescriptor final
34
34
  shadowNode.getState());
35
35
  auto stateData = state->getData();
36
36
 
37
- layoutableShadowNode.setPadding(
38
- {stateData.getPaddingStart(), 0, stateData.getPaddingEnd(), 0});
37
+ if (stateData.frameSize.width != 0 && stateData.frameSize.height != 0) {
38
+ layoutableShadowNode.setSize(
39
+ {stateData.frameSize.width, stateData.frameSize.height});
40
+ #ifdef ANDROID
41
+ layoutableShadowNode.setPadding({
42
+ stateData.paddingStart,
43
+ 0,
44
+ stateData.paddingEnd,
45
+ 0,
46
+ });
47
+ #endif // ANDROID
48
+ }
39
49
 
40
50
  ConcreteComponentDescriptor::adopt(shadowNode);
41
51
  #if !defined(ANDROID) && !defined(NDEBUG)