react-native-screens 3.35.0-rc.0 → 4.0.0-beta.0
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/build.gradle +2 -2
- package/android/src/main/java/com/swmansion/rnscreens/InsetsObserverProxy.kt +67 -0
- package/android/src/main/java/com/swmansion/rnscreens/RNScreensPackage.kt +2 -0
- package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +101 -4
- package/android/src/main/java/com/swmansion/rnscreens/ScreenContentWrapper.kt +38 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenContentWrapperManager.kt +25 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenFooter.kt +287 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenFooterManager.kt +25 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.kt +11 -19
- package/android/src/main/java/com/swmansion/rnscreens/ScreenFragmentWrapper.kt +4 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenModalFragment.kt +281 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +62 -19
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +403 -41
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragmentWrapper.kt +4 -1
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +2 -2
- package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +95 -11
- package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +39 -28
- package/android/src/main/java/com/swmansion/rnscreens/bottomsheet/BottomSheetDialogRootView.kt +104 -0
- package/android/src/main/java/com/swmansion/rnscreens/bottomsheet/BottomSheetDialogScreen.kt +26 -0
- package/android/src/main/java/com/swmansion/rnscreens/bottomsheet/DimmingFragment.kt +488 -0
- package/android/src/main/java/com/swmansion/rnscreens/bottomsheet/DimmingView.kt +66 -0
- package/android/src/main/java/com/swmansion/rnscreens/bottomsheet/GestureTransparentViewGroup.kt +24 -0
- package/android/src/main/java/com/swmansion/rnscreens/bottomsheet/SheetUtils.kt +127 -0
- package/android/src/main/java/com/swmansion/rnscreens/events/SheetDetentChangedEvent.kt +27 -0
- package/android/src/main/java/com/swmansion/rnscreens/ext/NumericExt.kt +12 -0
- package/android/src/main/java/com/swmansion/rnscreens/ext/ViewExt.kt +32 -0
- package/android/src/main/java/com/swmansion/rnscreens/utils/ScreenDummyLayoutHelper.kt +45 -8
- package/android/src/main/res/base/drawable/rns_rounder_top_corners_shape.xml +8 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenContentWrapperManagerDelegate.java +25 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenContentWrapperManagerInterface.java +16 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenFooterManagerDelegate.java +25 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenFooterManagerInterface.java +16 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerDelegate.java +9 -2
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerInterface.java +5 -2
- package/ios/RNSConvert.h +5 -3
- package/ios/RNSConvert.mm +14 -20
- package/ios/RNSScreen.h +3 -2
- package/ios/RNSScreen.mm +433 -49
- package/ios/RNSScreenContentWrapper.h +44 -0
- package/ios/RNSScreenContentWrapper.mm +61 -0
- package/ios/RNSScreenFooter.h +30 -0
- package/ios/RNSScreenFooter.mm +137 -0
- package/lib/commonjs/components/Screen.js +6 -2
- package/lib/commonjs/components/Screen.js.map +1 -1
- package/lib/commonjs/components/ScreenContentWrapper.js +19 -0
- package/lib/commonjs/components/ScreenContentWrapper.js.map +1 -0
- package/lib/commonjs/components/ScreenFooter.js +23 -0
- package/lib/commonjs/components/ScreenFooter.js.map +1 -0
- package/lib/commonjs/fabric/ModalScreenNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/ScreenContentWrapperNativeComponent.js +10 -0
- package/lib/commonjs/fabric/ScreenContentWrapperNativeComponent.js.map +1 -0
- package/lib/commonjs/fabric/ScreenFooterNativeComponent.js +10 -0
- package/lib/commonjs/fabric/ScreenFooterNativeComponent.js.map +1 -0
- package/lib/commonjs/fabric/ScreenNativeComponent.js.map +1 -1
- package/lib/commonjs/index.js +30 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/native-stack/views/FooterComponent.js +18 -0
- package/lib/commonjs/native-stack/views/FooterComponent.js.map +1 -0
- package/lib/commonjs/native-stack/views/NativeStackView.js +59 -14
- package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -1
- package/lib/module/components/Screen.js +6 -2
- package/lib/module/components/Screen.js.map +1 -1
- package/lib/module/components/ScreenContentWrapper.js +12 -0
- package/lib/module/components/ScreenContentWrapper.js.map +1 -0
- package/lib/module/components/ScreenFooter.js +17 -0
- package/lib/module/components/ScreenFooter.js.map +1 -0
- package/lib/module/fabric/ModalScreenNativeComponent.js.map +1 -1
- package/lib/module/fabric/ScreenContentWrapperNativeComponent.js +3 -0
- package/lib/module/fabric/ScreenContentWrapperNativeComponent.js.map +1 -0
- package/lib/module/fabric/ScreenFooterNativeComponent.js +3 -0
- package/lib/module/fabric/ScreenFooterNativeComponent.js.map +1 -0
- package/lib/module/fabric/ScreenNativeComponent.js.map +1 -1
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/native-stack/views/FooterComponent.js +11 -0
- package/lib/module/native-stack/views/FooterComponent.js.map +1 -0
- package/lib/module/native-stack/views/NativeStackView.js +61 -15
- package/lib/module/native-stack/views/NativeStackView.js.map +1 -1
- package/lib/typescript/components/Screen.d.ts.map +1 -1
- package/lib/typescript/components/ScreenContentWrapper.d.ts +6 -0
- package/lib/typescript/components/ScreenContentWrapper.d.ts.map +1 -0
- package/lib/typescript/components/ScreenFooter.d.ts +12 -0
- package/lib/typescript/components/ScreenFooter.d.ts.map +1 -0
- package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts +2 -3
- package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts.map +1 -1
- package/lib/typescript/fabric/ScreenContentWrapperNativeComponent.d.ts +7 -0
- package/lib/typescript/fabric/ScreenContentWrapperNativeComponent.d.ts.map +1 -0
- package/lib/typescript/fabric/ScreenFooterNativeComponent.d.ts +7 -0
- package/lib/typescript/fabric/ScreenFooterNativeComponent.d.ts.map +1 -0
- package/lib/typescript/fabric/ScreenNativeComponent.d.ts +9 -3
- package/lib/typescript/fabric/ScreenNativeComponent.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +2 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/native-stack/types.d.ts +63 -23
- package/lib/typescript/native-stack/types.d.ts.map +1 -1
- package/lib/typescript/native-stack/views/FooterComponent.d.ts +7 -0
- package/lib/typescript/native-stack/views/FooterComponent.d.ts.map +1 -0
- package/lib/typescript/native-stack/views/NativeStackView.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +42 -17
- package/lib/typescript/types.d.ts.map +1 -1
- package/native-stack/README.md +16 -14
- package/package.json +1 -1
- package/react-native.config.js +18 -16
- package/src/components/Screen.tsx +6 -2
- package/src/components/ScreenContentWrapper.tsx +12 -0
- package/src/components/ScreenFooter.tsx +18 -0
- package/src/fabric/ModalScreenNativeComponent.ts +2 -4
- package/src/fabric/ScreenContentWrapperNativeComponent.ts +9 -0
- package/src/fabric/ScreenFooterNativeComponent.ts +6 -0
- package/src/fabric/ScreenNativeComponent.ts +10 -4
- package/src/index.tsx +10 -0
- package/src/native-stack/types.tsx +57 -23
- package/src/native-stack/views/FooterComponent.tsx +10 -0
- package/src/native-stack/views/NativeStackView.tsx +74 -11
- package/src/types.tsx +41 -16
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
package com.swmansion.rnscreens
|
|
2
2
|
|
|
3
|
+
import android.view.View
|
|
3
4
|
import com.facebook.react.bridge.JSApplicationIllegalArgumentException
|
|
5
|
+
import com.facebook.react.bridge.ReadableArray
|
|
4
6
|
import com.facebook.react.bridge.ReadableMap
|
|
5
7
|
import com.facebook.react.common.MapBuilder
|
|
6
8
|
import com.facebook.react.module.annotations.ReactModule
|
|
@@ -20,6 +22,7 @@ import com.swmansion.rnscreens.events.ScreenDismissedEvent
|
|
|
20
22
|
import com.swmansion.rnscreens.events.ScreenTransitionProgressEvent
|
|
21
23
|
import com.swmansion.rnscreens.events.ScreenWillAppearEvent
|
|
22
24
|
import com.swmansion.rnscreens.events.ScreenWillDisappearEvent
|
|
25
|
+
import com.swmansion.rnscreens.events.SheetDetentChangedEvent
|
|
23
26
|
|
|
24
27
|
@ReactModule(name = ScreenViewManager.REACT_CLASS)
|
|
25
28
|
open class ScreenViewManager :
|
|
@@ -42,6 +45,42 @@ open class ScreenViewManager :
|
|
|
42
45
|
setActivityState(view, activityState.toInt())
|
|
43
46
|
}
|
|
44
47
|
|
|
48
|
+
override fun addView(
|
|
49
|
+
parent: Screen,
|
|
50
|
+
child: View,
|
|
51
|
+
index: Int,
|
|
52
|
+
) {
|
|
53
|
+
if (child is ScreenContentWrapper) {
|
|
54
|
+
parent.registerLayoutCallbackForWrapper(child)
|
|
55
|
+
} else if (child is ScreenFooter) {
|
|
56
|
+
parent.footer = child
|
|
57
|
+
}
|
|
58
|
+
super.addView(parent, child, index)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Overriding all three remove methods despite the fact, that they all do use removeViewAt in parent
|
|
62
|
+
// class implementation to make it safe in case this changes. Relying on implementation details in this
|
|
63
|
+
// case in unnecessary.
|
|
64
|
+
override fun removeViewAt(
|
|
65
|
+
parent: Screen,
|
|
66
|
+
index: Int,
|
|
67
|
+
) {
|
|
68
|
+
if (parent.getChildAt(index) is ScreenFooter) {
|
|
69
|
+
parent.footer = null
|
|
70
|
+
}
|
|
71
|
+
super.removeViewAt(parent, index)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
override fun removeView(
|
|
75
|
+
parent: Screen,
|
|
76
|
+
view: View,
|
|
77
|
+
) {
|
|
78
|
+
super.removeView(parent, view)
|
|
79
|
+
if (view is ScreenFooter) {
|
|
80
|
+
parent.footer = null
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
45
84
|
override fun updateState(
|
|
46
85
|
view: Screen,
|
|
47
86
|
props: ReactStylesDiffMap?,
|
|
@@ -81,7 +120,8 @@ open class ScreenViewManager :
|
|
|
81
120
|
view.stackPresentation =
|
|
82
121
|
when (presentation) {
|
|
83
122
|
"push" -> Screen.StackPresentation.PUSH
|
|
84
|
-
"
|
|
123
|
+
"formSheet" -> Screen.StackPresentation.FORM_SHEET
|
|
124
|
+
"modal", "containedModal", "fullScreenModal" ->
|
|
85
125
|
Screen.StackPresentation.MODAL
|
|
86
126
|
"transparentModal", "containedTransparentModal" ->
|
|
87
127
|
Screen.StackPresentation.TRANSPARENT_MODAL
|
|
@@ -210,6 +250,14 @@ open class ScreenViewManager :
|
|
|
210
250
|
view.nativeBackButtonDismissalEnabled = nativeBackButtonDismissalEnabled
|
|
211
251
|
}
|
|
212
252
|
|
|
253
|
+
@ReactProp(name = "sheetElevation")
|
|
254
|
+
override fun setSheetElevation(
|
|
255
|
+
view: Screen?,
|
|
256
|
+
value: Int,
|
|
257
|
+
) {
|
|
258
|
+
view?.sheetElevation = value.toFloat()
|
|
259
|
+
}
|
|
260
|
+
|
|
213
261
|
// these props are not available on Android, however we must override their setters
|
|
214
262
|
override fun setFullScreenSwipeEnabled(
|
|
215
263
|
view: Screen?,
|
|
@@ -256,30 +304,65 @@ open class ScreenViewManager :
|
|
|
256
304
|
value: String?,
|
|
257
305
|
) = Unit
|
|
258
306
|
|
|
307
|
+
@ReactProp(name = "sheetAllowedDetents")
|
|
259
308
|
override fun setSheetAllowedDetents(
|
|
260
309
|
view: Screen,
|
|
261
|
-
value:
|
|
262
|
-
)
|
|
310
|
+
value: ReadableArray?,
|
|
311
|
+
) {
|
|
312
|
+
view.sheetDetents.clear()
|
|
313
|
+
|
|
314
|
+
if (value == null || value.size() == 0) {
|
|
315
|
+
view.sheetDetents.add(1.0)
|
|
316
|
+
return
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
IntProgression
|
|
320
|
+
.fromClosedRange(0, value.size() - 1, 1)
|
|
321
|
+
.asSequence()
|
|
322
|
+
.map { idx -> value.getDouble(idx) }
|
|
323
|
+
.toCollection(view.sheetDetents)
|
|
324
|
+
}
|
|
263
325
|
|
|
326
|
+
@ReactProp(name = "sheetLargestUndimmedDetent")
|
|
264
327
|
override fun setSheetLargestUndimmedDetent(
|
|
265
328
|
view: Screen,
|
|
266
|
-
value:
|
|
267
|
-
)
|
|
329
|
+
value: Int,
|
|
330
|
+
) {
|
|
331
|
+
check(value in -1..2) { "[RNScreens] sheetLargestUndimmedDetent on Android supports values between -1 and 2" }
|
|
332
|
+
view.sheetLargestUndimmedDetentIndex = value
|
|
333
|
+
}
|
|
268
334
|
|
|
335
|
+
@ReactProp(name = "sheetGrabberVisible")
|
|
269
336
|
override fun setSheetGrabberVisible(
|
|
270
|
-
view: Screen
|
|
337
|
+
view: Screen,
|
|
271
338
|
value: Boolean,
|
|
272
|
-
)
|
|
339
|
+
) {
|
|
340
|
+
view.isSheetGrabberVisible = value
|
|
341
|
+
}
|
|
273
342
|
|
|
343
|
+
@ReactProp(name = "sheetCornerRadius")
|
|
274
344
|
override fun setSheetCornerRadius(
|
|
275
|
-
view: Screen
|
|
345
|
+
view: Screen,
|
|
276
346
|
value: Float,
|
|
277
|
-
)
|
|
347
|
+
) {
|
|
348
|
+
view.sheetCornerRadius = value
|
|
349
|
+
}
|
|
278
350
|
|
|
351
|
+
@ReactProp(name = "sheetExpandsWhenScrolledToEdge")
|
|
279
352
|
override fun setSheetExpandsWhenScrolledToEdge(
|
|
280
|
-
view: Screen
|
|
353
|
+
view: Screen,
|
|
281
354
|
value: Boolean,
|
|
282
|
-
)
|
|
355
|
+
) {
|
|
356
|
+
view.sheetExpandsWhenScrolledToEdge = value
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
@ReactProp(name = "sheetInitialDetent")
|
|
360
|
+
override fun setSheetInitialDetent(
|
|
361
|
+
view: Screen,
|
|
362
|
+
value: Int,
|
|
363
|
+
) {
|
|
364
|
+
view.sheetInitialDetentIndex = value
|
|
365
|
+
}
|
|
283
366
|
|
|
284
367
|
override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> =
|
|
285
368
|
mutableMapOf(
|
|
@@ -291,6 +374,7 @@ open class ScreenViewManager :
|
|
|
291
374
|
HeaderHeightChangeEvent.EVENT_NAME to MapBuilder.of("registrationName", "onHeaderHeightChange"),
|
|
292
375
|
HeaderBackButtonClickedEvent.EVENT_NAME to MapBuilder.of("registrationName", "onHeaderBackButtonClicked"),
|
|
293
376
|
ScreenTransitionProgressEvent.EVENT_NAME to MapBuilder.of("registrationName", "onTransitionProgress"),
|
|
377
|
+
SheetDetentChangedEvent.EVENT_NAME to MapBuilder.of("registrationName", "onSheetDetentChanged"),
|
|
294
378
|
)
|
|
295
379
|
|
|
296
380
|
protected override fun getDelegate(): ViewManagerDelegate<Screen> = delegate
|
|
@@ -7,8 +7,10 @@ import android.app.Activity
|
|
|
7
7
|
import android.content.pm.ActivityInfo
|
|
8
8
|
import android.graphics.Color
|
|
9
9
|
import android.os.Build
|
|
10
|
+
import android.view.View
|
|
10
11
|
import android.view.ViewParent
|
|
11
12
|
import androidx.core.graphics.Insets
|
|
13
|
+
import androidx.core.view.OnApplyWindowInsetsListener
|
|
12
14
|
import androidx.core.view.ViewCompat
|
|
13
15
|
import androidx.core.view.WindowCompat
|
|
14
16
|
import androidx.core.view.WindowInsetsCompat
|
|
@@ -26,6 +28,40 @@ object ScreenWindowTraits {
|
|
|
26
28
|
private var didSetNavigationBarAppearance = false
|
|
27
29
|
private var defaultStatusBarColor: Int? = null
|
|
28
30
|
|
|
31
|
+
private var windowInsetsListener =
|
|
32
|
+
object : OnApplyWindowInsetsListener {
|
|
33
|
+
override fun onApplyWindowInsets(
|
|
34
|
+
v: View,
|
|
35
|
+
insets: WindowInsetsCompat,
|
|
36
|
+
): WindowInsetsCompat {
|
|
37
|
+
val defaultInsets = ViewCompat.onApplyWindowInsets(v, insets)
|
|
38
|
+
|
|
39
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
40
|
+
val windowInsets =
|
|
41
|
+
defaultInsets.getInsets(WindowInsetsCompat.Type.statusBars())
|
|
42
|
+
|
|
43
|
+
return WindowInsetsCompat
|
|
44
|
+
.Builder()
|
|
45
|
+
.setInsets(
|
|
46
|
+
WindowInsetsCompat.Type.statusBars(),
|
|
47
|
+
Insets.of(
|
|
48
|
+
windowInsets.left,
|
|
49
|
+
0,
|
|
50
|
+
windowInsets.right,
|
|
51
|
+
windowInsets.bottom,
|
|
52
|
+
),
|
|
53
|
+
).build()
|
|
54
|
+
} else {
|
|
55
|
+
return defaultInsets.replaceSystemWindowInsets(
|
|
56
|
+
defaultInsets.systemWindowInsetLeft,
|
|
57
|
+
0,
|
|
58
|
+
defaultInsets.systemWindowInsetRight,
|
|
59
|
+
defaultInsets.systemWindowInsetBottom,
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
29
65
|
internal fun applyDidSetOrientation() {
|
|
30
66
|
didSetOrientation = true
|
|
31
67
|
}
|
|
@@ -124,35 +160,10 @@ object ScreenWindowTraits {
|
|
|
124
160
|
// and consume all the top insets so no padding will be added under the status bar.
|
|
125
161
|
val decorView = activity.window.decorView
|
|
126
162
|
if (translucent) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
131
|
-
val windowInsets =
|
|
132
|
-
defaultInsets.getInsets(WindowInsetsCompat.Type.statusBars())
|
|
133
|
-
|
|
134
|
-
WindowInsetsCompat
|
|
135
|
-
.Builder()
|
|
136
|
-
.setInsets(
|
|
137
|
-
WindowInsetsCompat.Type.statusBars(),
|
|
138
|
-
Insets.of(
|
|
139
|
-
windowInsets.left,
|
|
140
|
-
0,
|
|
141
|
-
windowInsets.right,
|
|
142
|
-
windowInsets.bottom,
|
|
143
|
-
),
|
|
144
|
-
).build()
|
|
145
|
-
} else {
|
|
146
|
-
defaultInsets.replaceSystemWindowInsets(
|
|
147
|
-
defaultInsets.systemWindowInsetLeft,
|
|
148
|
-
0,
|
|
149
|
-
defaultInsets.systemWindowInsetRight,
|
|
150
|
-
defaultInsets.systemWindowInsetBottom,
|
|
151
|
-
)
|
|
152
|
-
}
|
|
153
|
-
}
|
|
163
|
+
InsetsObserverProxy.registerOnView(decorView)
|
|
164
|
+
InsetsObserverProxy.addOnApplyWindowInsetsListener(windowInsetsListener)
|
|
154
165
|
} else {
|
|
155
|
-
|
|
166
|
+
InsetsObserverProxy.removeOnApplyWindowInsetsListener(windowInsetsListener)
|
|
156
167
|
}
|
|
157
168
|
ViewCompat.requestApplyInsets(decorView)
|
|
158
169
|
}
|
package/android/src/main/java/com/swmansion/rnscreens/bottomsheet/BottomSheetDialogRootView.kt
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
package com.swmansion.rnscreens.bottomsheet
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint
|
|
4
|
+
import android.view.MotionEvent
|
|
5
|
+
import android.view.View
|
|
6
|
+
import com.facebook.react.bridge.ReactContext
|
|
7
|
+
import com.facebook.react.config.ReactFeatureFlags
|
|
8
|
+
import com.facebook.react.uimanager.JSPointerDispatcher
|
|
9
|
+
import com.facebook.react.uimanager.JSTouchDispatcher
|
|
10
|
+
import com.facebook.react.uimanager.RootView
|
|
11
|
+
import com.facebook.react.uimanager.events.EventDispatcher
|
|
12
|
+
import com.facebook.react.views.view.ReactViewGroup
|
|
13
|
+
|
|
14
|
+
@SuppressLint("ViewConstructor")
|
|
15
|
+
class BottomSheetDialogRootView(
|
|
16
|
+
val reactContext: ReactContext?,
|
|
17
|
+
private val eventDispatcher: EventDispatcher,
|
|
18
|
+
) : ReactViewGroup(reactContext),
|
|
19
|
+
RootView {
|
|
20
|
+
private val jsTouchDispatcher: JSTouchDispatcher = JSTouchDispatcher(this)
|
|
21
|
+
private var jsPointerDispatcher: JSPointerDispatcher? = null
|
|
22
|
+
|
|
23
|
+
init {
|
|
24
|
+
// Can we safely use ReactFeatureFlags?
|
|
25
|
+
if (ReactFeatureFlags.dispatchPointerEvents) {
|
|
26
|
+
jsPointerDispatcher = JSPointerDispatcher(this)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
override fun onLayout(
|
|
31
|
+
changed: Boolean,
|
|
32
|
+
l: Int,
|
|
33
|
+
t: Int,
|
|
34
|
+
r: Int,
|
|
35
|
+
b: Int,
|
|
36
|
+
) {
|
|
37
|
+
if (changed) {
|
|
38
|
+
// This view is used right now only in ScreenModalFragment, where it is injected
|
|
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}"}
|
|
41
|
+
getChildAt(0).layout(l, t, r, b)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
|
|
46
|
+
jsTouchDispatcher.handleTouchEvent(event, eventDispatcher)
|
|
47
|
+
jsPointerDispatcher?.handleMotionEvent(event, eventDispatcher, true)
|
|
48
|
+
return super.onInterceptTouchEvent(event)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
override fun onTouchEvent(event: MotionEvent): Boolean {
|
|
52
|
+
jsTouchDispatcher.handleTouchEvent(event, eventDispatcher)
|
|
53
|
+
jsPointerDispatcher?.handleMotionEvent(event, eventDispatcher, false)
|
|
54
|
+
super.onTouchEvent(event)
|
|
55
|
+
return true
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
override fun onInterceptHoverEvent(event: MotionEvent): Boolean {
|
|
59
|
+
jsPointerDispatcher?.handleMotionEvent(event, eventDispatcher, true)
|
|
60
|
+
// This is how DialogRootViewGroup implements this, it might be a copy-paste mistake
|
|
61
|
+
// on their side.
|
|
62
|
+
return super.onHoverEvent(event)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
override fun onHoverEvent(event: MotionEvent): Boolean {
|
|
66
|
+
jsPointerDispatcher?.handleMotionEvent(event, eventDispatcher, false)
|
|
67
|
+
return super.onHoverEvent(event)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
override fun onChildStartedNativeGesture(
|
|
71
|
+
view: View,
|
|
72
|
+
event: MotionEvent,
|
|
73
|
+
) {
|
|
74
|
+
jsTouchDispatcher.onChildStartedNativeGesture(event, eventDispatcher)
|
|
75
|
+
jsPointerDispatcher?.onChildStartedNativeGesture(view, event, eventDispatcher)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@Deprecated("Deprecated by React Native")
|
|
79
|
+
override fun onChildStartedNativeGesture(event: MotionEvent): Unit =
|
|
80
|
+
throw IllegalStateException("Deprecated onChildStartedNativeGesture was called")
|
|
81
|
+
|
|
82
|
+
override fun onChildEndedNativeGesture(
|
|
83
|
+
view: View,
|
|
84
|
+
event: MotionEvent,
|
|
85
|
+
) {
|
|
86
|
+
jsTouchDispatcher.onChildEndedNativeGesture(event, eventDispatcher)
|
|
87
|
+
jsPointerDispatcher?.onChildEndedNativeGesture()
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {
|
|
91
|
+
// We do not pass through request of our child up the view hierarchy, as we
|
|
92
|
+
// need to keep receiving events.
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
override fun handleException(throwable: Throwable?) {
|
|
96
|
+
// TODO: I need ThemedReactContext here.
|
|
97
|
+
// TODO: Determine where it is initially created & verify its lifecycle
|
|
98
|
+
// reactContext?.reactApplicationContext?.handleException(RuntimeException(throwable))
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
companion object {
|
|
102
|
+
const val TAG = "BottomSheetDialogRootView"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
package com.swmansion.rnscreens.bottomsheet
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import com.google.android.material.bottomsheet.BottomSheetDialog
|
|
5
|
+
import com.swmansion.rnscreens.ScreenModalFragment
|
|
6
|
+
import java.lang.ref.WeakReference
|
|
7
|
+
|
|
8
|
+
class BottomSheetDialogScreen(
|
|
9
|
+
context: Context,
|
|
10
|
+
fragment: ScreenModalFragment,
|
|
11
|
+
) : BottomSheetDialog(context) {
|
|
12
|
+
private val fragmentRef: WeakReference<ScreenModalFragment> = WeakReference(fragment)
|
|
13
|
+
|
|
14
|
+
// There are various code paths leading to this method, however the one I'm concerned with
|
|
15
|
+
// is dismissal via swipe-down. If the sheet is dismissed we don't want the native dismiss logic
|
|
16
|
+
// to run, as this will lead to inconsistencies in ScreenStack state. Instead we intercept
|
|
17
|
+
// dismiss intention and run our logic.
|
|
18
|
+
override fun cancel() {
|
|
19
|
+
fragmentRef.get()!!.dismissFromContainer()
|
|
20
|
+
this.show()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
companion object {
|
|
24
|
+
val TAG = BottomSheetDialogScreen::class.simpleName
|
|
25
|
+
}
|
|
26
|
+
}
|