react-native-screens 4.10.0-beta.1 → 4.10.0-beta.3
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.
- package/android/src/fabric/java/com/swmansion/rnscreens/FabricEnabledHeaderConfigViewGroup.kt +3 -8
- package/android/src/main/java/com/swmansion/rnscreens/CustomToolbar.kt +111 -15
- package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +11 -2
- package/android/src/main/java/com/swmansion/rnscreens/ScreenContainer.kt +1 -1
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +174 -199
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +31 -285
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +89 -54
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfigShadowNode.kt +3 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackViewManager.kt +1 -1
- package/android/src/main/java/com/swmansion/rnscreens/bottomsheet/SheetDelegate.kt +257 -3
- package/android/src/main/java/com/swmansion/rnscreens/ext/ViewExt.kt +7 -0
- package/android/src/main/java/com/swmansion/rnscreens/utils/FragmentTransactionKt.kt +103 -0
- package/android/src/main/java/com/swmansion/rnscreens/utils/InsetsKt.kt +31 -0
- package/android/src/main/java/com/swmansion/rnscreens/utils/PaddingBundle.kt +1 -0
- package/android/src/paper/java/com/swmansion/rnscreens/FabricEnabledHeaderConfigViewGroup.kt +14 -5
- package/ios/RNSFullWindowOverlay.mm +6 -6
- package/lib/commonjs/components/Screen.js +5 -3
- package/lib/commonjs/components/Screen.js.map +1 -1
- package/lib/commonjs/native-stack/views/NativeStackView.js +3 -5
- package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -1
- package/lib/module/components/Screen.js +5 -3
- package/lib/module/components/Screen.js.map +1 -1
- package/lib/module/native-stack/views/NativeStackView.js +3 -5
- package/lib/module/native-stack/views/NativeStackView.js.map +1 -1
- package/lib/typescript/components/Screen.d.ts.map +1 -1
- package/lib/typescript/native-stack/views/NativeStackView.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/Screen.tsx +7 -5
- package/src/native-stack/views/NativeStackView.tsx +11 -12
- package/android/src/main/java/com/swmansion/rnscreens/NativeDismissalObserver.kt +0 -12
package/android/src/fabric/java/com/swmansion/rnscreens/FabricEnabledHeaderConfigViewGroup.kt
CHANGED
|
@@ -23,24 +23,19 @@ abstract class FabricEnabledHeaderConfigViewGroup(
|
|
|
23
23
|
mStateWrapper = wrapper
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
fun updatePaddings(
|
|
27
|
-
paddingStart: Int,
|
|
28
|
-
paddingEnd: Int,
|
|
29
|
-
) {
|
|
30
|
-
// Do nothing on Fabric. This method is used only on Paper.
|
|
31
|
-
}
|
|
32
|
-
|
|
33
26
|
fun updateHeaderConfigState(
|
|
34
27
|
width: Int,
|
|
35
28
|
height: Int,
|
|
36
29
|
paddingStart: Int,
|
|
37
30
|
paddingEnd: Int,
|
|
38
31
|
) {
|
|
32
|
+
// Implementation of this method differs between Fabric & Paper!
|
|
39
33
|
updateState(width, height, paddingStart, paddingEnd)
|
|
40
34
|
}
|
|
41
35
|
|
|
36
|
+
// Implementation of this method differs between Fabric & Paper!
|
|
42
37
|
@UiThread
|
|
43
|
-
fun updateState(
|
|
38
|
+
private fun updateState(
|
|
44
39
|
width: Int,
|
|
45
40
|
height: Int,
|
|
46
41
|
paddingStart: Int,
|
|
@@ -3,18 +3,40 @@ package com.swmansion.rnscreens
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
4
|
import android.content.Context
|
|
5
5
|
import android.os.Build
|
|
6
|
+
import android.view.WindowInsets
|
|
6
7
|
import android.view.WindowManager
|
|
7
8
|
import androidx.appcompat.widget.Toolbar
|
|
9
|
+
import androidx.core.view.WindowInsetsCompat
|
|
8
10
|
import com.facebook.react.modules.core.ChoreographerCompat
|
|
9
11
|
import com.facebook.react.modules.core.ReactChoreographer
|
|
10
12
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
13
|
+
import com.swmansion.rnscreens.utils.InsetsCompat
|
|
14
|
+
import com.swmansion.rnscreens.utils.resolveInsetsOrZero
|
|
15
|
+
import kotlin.math.max
|
|
11
16
|
|
|
12
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Main toolbar class representing the native header.
|
|
19
|
+
*
|
|
20
|
+
* This class is used to store config closer to search bar.
|
|
21
|
+
* It also handles inset/padding related logic in coordination with header config.
|
|
22
|
+
*/
|
|
13
23
|
@SuppressLint("ViewConstructor") // Only we construct this view, it is never inflated.
|
|
14
24
|
open class CustomToolbar(
|
|
15
25
|
context: Context,
|
|
16
26
|
val config: ScreenStackHeaderConfig,
|
|
17
27
|
) : Toolbar(context) {
|
|
28
|
+
// Switch this flag to enable/disable display cutout avoidance.
|
|
29
|
+
// Currently this is controlled by isTopInsetEnabled prop.
|
|
30
|
+
private val shouldAvoidDisplayCutout
|
|
31
|
+
get() = config.isTopInsetEnabled
|
|
32
|
+
|
|
33
|
+
private val shouldApplyTopInset
|
|
34
|
+
get() = config.isTopInsetEnabled
|
|
35
|
+
|
|
36
|
+
private var lastInsets = InsetsCompat.NONE
|
|
37
|
+
|
|
38
|
+
private var isForceShadowStateUpdateOnLayoutRequested = false
|
|
39
|
+
|
|
18
40
|
private var isLayoutEnqueued = false
|
|
19
41
|
private val layoutCallback: ChoreographerCompat.FrameCallback =
|
|
20
42
|
object : ChoreographerCompat.FrameCallback() {
|
|
@@ -59,27 +81,101 @@ open class CustomToolbar(
|
|
|
59
81
|
}
|
|
60
82
|
}
|
|
61
83
|
|
|
84
|
+
override fun onApplyWindowInsets(insets: WindowInsets?): WindowInsets? {
|
|
85
|
+
val unhandledInsets = super.onApplyWindowInsets(insets)
|
|
86
|
+
|
|
87
|
+
// There are few UI modes we could be running in
|
|
88
|
+
//
|
|
89
|
+
// 1. legacy non edge-to-edge mode,
|
|
90
|
+
// 2. edge-to-edge with gesture navigation,
|
|
91
|
+
// 3. edge-to-edge with translucent navigation buttons bar.
|
|
92
|
+
//
|
|
93
|
+
// Additionally we need to gracefully handle possible display cutouts.
|
|
94
|
+
|
|
95
|
+
// We use rootWindowInsets in lieu of insets or unhandledInsets here,
|
|
96
|
+
// because cutout sometimes (only in certain scenarios, e.g. with headerLeft view present)
|
|
97
|
+
// happen to be Insets.ZERO and is not reliable.
|
|
98
|
+
val rootWindowInsets = rootWindowInsets
|
|
99
|
+
val cutoutInsets =
|
|
100
|
+
resolveInsetsOrZero(WindowInsetsCompat.Type.displayCutout(), rootWindowInsets)
|
|
101
|
+
val systemBarInsets =
|
|
102
|
+
resolveInsetsOrZero(WindowInsetsCompat.Type.systemBars(), rootWindowInsets)
|
|
103
|
+
val statusBarInsetsStable =
|
|
104
|
+
resolveInsetsOrZero(
|
|
105
|
+
WindowInsetsCompat.Type.systemBars(),
|
|
106
|
+
rootWindowInsets,
|
|
107
|
+
ignoreVisibility = true,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
// This seems to work fine in all tested configurations, because cutout & system bars overlap
|
|
111
|
+
// only in portrait mode & top inset is controlled separately, therefore we don't count
|
|
112
|
+
// any insets twice.
|
|
113
|
+
val horizontalInsets =
|
|
114
|
+
InsetsCompat.of(
|
|
115
|
+
cutoutInsets.left + systemBarInsets.left,
|
|
116
|
+
0,
|
|
117
|
+
cutoutInsets.right + systemBarInsets.right,
|
|
118
|
+
0,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
// We want to handle display cutout always, no matter the HeaderConfig prop values.
|
|
122
|
+
// If there are no cutout displays, we want to apply the additional padding to
|
|
123
|
+
// respect the status bar.
|
|
124
|
+
val verticalInsets =
|
|
125
|
+
InsetsCompat.of(
|
|
126
|
+
0,
|
|
127
|
+
max(cutoutInsets.top, if (shouldApplyTopInset) statusBarInsetsStable.top else 0),
|
|
128
|
+
0,
|
|
129
|
+
max(cutoutInsets.bottom, 0),
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
val newInsets = InsetsCompat.add(horizontalInsets, verticalInsets)
|
|
133
|
+
|
|
134
|
+
if (lastInsets != newInsets) {
|
|
135
|
+
lastInsets = newInsets
|
|
136
|
+
applyExactPadding(
|
|
137
|
+
lastInsets.left,
|
|
138
|
+
lastInsets.top,
|
|
139
|
+
lastInsets.right,
|
|
140
|
+
lastInsets.bottom,
|
|
141
|
+
)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return unhandledInsets
|
|
145
|
+
}
|
|
146
|
+
|
|
62
147
|
override fun onLayout(
|
|
63
|
-
|
|
148
|
+
hasSizeChanged: Boolean,
|
|
64
149
|
l: Int,
|
|
65
150
|
t: Int,
|
|
66
151
|
r: Int,
|
|
67
152
|
b: Int,
|
|
68
153
|
) {
|
|
69
|
-
super.onLayout(
|
|
154
|
+
super.onLayout(hasSizeChanged, l, t, r, b)
|
|
70
155
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
156
|
+
config.onNativeToolbarLayout(
|
|
157
|
+
this,
|
|
158
|
+
hasSizeChanged || isForceShadowStateUpdateOnLayoutRequested,
|
|
159
|
+
)
|
|
160
|
+
isForceShadowStateUpdateOnLayoutRequested = false
|
|
161
|
+
}
|
|
74
162
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
163
|
+
fun updateContentInsets() {
|
|
164
|
+
contentInsetStartWithNavigation = config.preferredContentInsetStartWithNavigation
|
|
165
|
+
setContentInsetsRelative(config.preferredContentInsetStart, config.preferredContentInsetEnd)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private fun applyExactPadding(
|
|
169
|
+
left: Int,
|
|
170
|
+
top: Int,
|
|
171
|
+
right: Int,
|
|
172
|
+
bottom: Int,
|
|
173
|
+
) {
|
|
174
|
+
requestForceShadowStateUpdateOnLayout()
|
|
175
|
+
setPadding(left, top, right, bottom)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private fun requestForceShadowStateUpdateOnLayout() {
|
|
179
|
+
isForceShadowStateUpdateOnLayoutRequested = shouldAvoidDisplayCutout
|
|
84
180
|
}
|
|
85
181
|
}
|
|
@@ -275,7 +275,7 @@ class Screen(
|
|
|
275
275
|
throw IllegalStateException("[RNScreens] activityState can only progress in NativeStack")
|
|
276
276
|
}
|
|
277
277
|
this.activityState = activityState
|
|
278
|
-
container?.
|
|
278
|
+
container?.onChildUpdate()
|
|
279
279
|
}
|
|
280
280
|
|
|
281
281
|
fun setScreenOrientation(screenOrientation: String?) {
|
|
@@ -482,7 +482,14 @@ class Screen(
|
|
|
482
482
|
?.dispatchEvent(HeaderHeightChangeEvent(surfaceId, id, headerHeight))
|
|
483
483
|
}
|
|
484
484
|
|
|
485
|
-
internal fun
|
|
485
|
+
internal fun onSheetDetentChanged(
|
|
486
|
+
detentIndex: Int,
|
|
487
|
+
isStable: Boolean,
|
|
488
|
+
) {
|
|
489
|
+
dispatchSheetDetentChanged(detentIndex, isStable)
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
private fun dispatchSheetDetentChanged(
|
|
486
493
|
detentIndex: Int,
|
|
487
494
|
isStable: Boolean,
|
|
488
495
|
) {
|
|
@@ -571,3 +578,5 @@ class Screen(
|
|
|
571
578
|
const val SHEET_FIT_TO_CONTENTS = -1.0
|
|
572
579
|
}
|
|
573
580
|
}
|
|
581
|
+
|
|
582
|
+
internal fun View.asScreen() = this as Screen
|