@lodev09/react-native-true-sheet 4.0.0-beta.2 → 4.0.0-beta.20
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/README.md +25 -4
- package/android/build.gradle +22 -1
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerView.kt +50 -16
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentView.kt +302 -184
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentViewManager.kt +5 -1
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterView.kt +21 -110
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetOverlayView.kt +116 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetOverlayViewManager.kt +45 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetPackage.kt +2 -1
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetStateUpdater.kt +18 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +119 -50
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +360 -163
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +54 -12
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetBottomSheetView.kt +22 -9
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetCoordinatorLayout.kt +84 -5
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDetentCalculator.kt +104 -39
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDimView.kt +3 -0
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetOverlayRootView.kt +137 -0
- package/android/src/main/java/com/lodev09/truesheet/events/TrueSheetLifecycleEvents.kt +15 -0
- package/android/src/main/java/com/lodev09/truesheet/utils/KeyboardUtils.kt +15 -2
- package/android/src/main/java/com/lodev09/truesheet/utils/ScreenUtils.kt +0 -12
- package/android/src/main/java/com/lodev09/truesheet/utils/ViewUtils.kt +19 -7
- package/android/src/main/jni/TrueSheetSpec.h +1 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewComponentDescriptor.h +1 -9
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.cpp +110 -30
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewShadowNode.h +30 -7
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewState.cpp +2 -2
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContentViewState.h +9 -8
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewComponentDescriptor.h +3 -5
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewShadowNode.cpp +9 -3
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewShadowNode.h +3 -6
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewState.cpp +1 -1
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetFooterViewState.h +4 -6
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetInsets.cpp +1 -1
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetInsets.h +1 -1
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetLayoutUtils.h +43 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetOverlayViewComponentDescriptor.h +21 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetOverlayViewShadowNode.cpp +17 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetOverlayViewShadowNode.h +33 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewComponentDescriptor.h +3 -5
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.cpp +7 -40
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.h +3 -7
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewState.cpp +3 -5
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewState.h +4 -5
- package/ios/TrueSheetContainerView.h +27 -7
- package/ios/TrueSheetContainerView.mm +31 -11
- package/ios/TrueSheetContentView.h +43 -15
- package/ios/TrueSheetContentView.mm +211 -189
- package/ios/TrueSheetFooterView.h +6 -0
- package/ios/TrueSheetFooterView.mm +93 -17
- package/ios/TrueSheetModule.h +2 -7
- package/ios/TrueSheetModule.mm +7 -16
- package/ios/TrueSheetOverlayView.h +32 -0
- package/ios/TrueSheetOverlayView.mm +161 -0
- package/ios/TrueSheetView.mm +212 -55
- package/ios/TrueSheetViewController.h +31 -3
- package/ios/TrueSheetViewController.mm +393 -94
- package/ios/core/TrueSheetBlurView.h +0 -2
- package/ios/core/TrueSheetBlurView.mm +3 -36
- package/ios/core/TrueSheetDetentCalculator.h +7 -1
- package/ios/core/TrueSheetDetentCalculator.mm +27 -4
- package/ios/core/TrueSheetGrabberView.mm +13 -3
- package/ios/core/TrueSheetKeyboardObserver.mm +2 -0
- package/ios/core/TrueSheetOverlayContainerView.h +31 -0
- package/ios/core/TrueSheetOverlayContainerView.mm +35 -0
- package/ios/events/TrueSheetLifecycleEvents.h +2 -0
- package/ios/events/TrueSheetLifecycleEvents.mm +8 -0
- package/ios/tvos/TrueSheetStubs.mm +12 -0
- package/ios/utils/UIView+ScrollEdgeInteraction.h +1 -0
- package/ios/utils/UIView+ScrollEdgeInteraction.mm +24 -2
- package/lib/module/TrueSheet.js +173 -39
- package/lib/module/TrueSheet.js.map +1 -1
- package/lib/module/TrueSheet.web.js +218 -243
- package/lib/module/TrueSheet.web.js.map +1 -1
- package/lib/module/TrueSheetBackground.js +15 -0
- package/lib/module/TrueSheetBackground.js.map +1 -0
- package/lib/module/TrueSheetOverlay.js +30 -0
- package/lib/module/TrueSheetOverlay.js.map +1 -0
- package/lib/module/TrueSheetOverlay.web.js +35 -0
- package/lib/module/TrueSheetOverlay.web.js.map +1 -0
- package/lib/module/TrueSheetPeek.web.js +20 -15
- package/lib/module/TrueSheetPeek.web.js.map +1 -1
- package/lib/module/detentBackgrounds.js +21 -0
- package/lib/module/detentBackgrounds.js.map +1 -0
- package/lib/module/fabric/TrueSheetContentViewNativeComponent.ts +1 -1
- package/lib/module/fabric/TrueSheetOverlayViewNativeComponent.ts +12 -0
- package/lib/module/fabric/TrueSheetViewNativeComponent.ts +14 -10
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/mocks/index.js +18 -2
- package/lib/module/mocks/index.js.map +1 -1
- package/lib/module/mocks/navigationExpoRouter.js.map +1 -1
- package/lib/module/navigation/base-types.js +2 -0
- package/lib/module/navigation/base-types.js.map +1 -0
- package/lib/module/navigation/createTrueSheetRouter.js +0 -9
- package/lib/module/navigation/createTrueSheetRouter.js.map +1 -1
- package/lib/module/navigation/expo-router/base-types.js +2 -0
- package/lib/module/navigation/expo-router/base-types.js.map +1 -0
- package/lib/module/navigation/expo-router/index.js +10 -7
- package/lib/module/navigation/expo-router/index.js.map +1 -1
- package/lib/module/navigation/expo-router/types.js +4 -0
- package/lib/module/navigation/expo-router/types.js.map +1 -0
- package/lib/module/navigation/index.js.map +1 -1
- package/lib/module/navigation/screen/useSheetScreenState.js +1 -0
- package/lib/module/navigation/screen/useSheetScreenState.js.map +1 -1
- package/lib/module/web/constants.js +1 -1
- package/lib/module/web/constants.js.map +1 -1
- package/lib/module/web/layout.js +168 -0
- package/lib/module/web/layout.js.map +1 -0
- package/lib/module/web/vaul/constants.js +4 -0
- package/lib/module/web/vaul/constants.js.map +1 -1
- package/lib/module/web/vaul/context.js.map +1 -1
- package/lib/module/web/vaul/helpers.js +1 -0
- package/lib/module/web/vaul/helpers.js.map +1 -1
- package/lib/module/web/vaul/index.js +44 -6
- package/lib/module/web/vaul/index.js.map +1 -1
- package/lib/module/web/vaul/use-snap-points.js +6 -8
- package/lib/module/web/vaul/use-snap-points.js.map +1 -1
- package/lib/typescript/src/TrueSheet.d.ts +6 -0
- package/lib/typescript/src/TrueSheet.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheet.types.d.ts +135 -34
- package/lib/typescript/src/TrueSheet.types.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheet.web.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheetBackground.d.ts +3 -0
- package/lib/typescript/src/TrueSheetBackground.d.ts.map +1 -0
- package/lib/typescript/src/TrueSheetOverlay.d.ts +8 -0
- package/lib/typescript/src/TrueSheetOverlay.d.ts.map +1 -0
- package/lib/typescript/src/TrueSheetOverlay.web.d.ts +8 -0
- package/lib/typescript/src/TrueSheetOverlay.web.d.ts.map +1 -0
- package/lib/typescript/src/TrueSheetPeek.web.d.ts +8 -4
- package/lib/typescript/src/TrueSheetPeek.web.d.ts.map +1 -1
- package/lib/typescript/src/detentBackgrounds.d.ts +10 -0
- package/lib/typescript/src/detentBackgrounds.d.ts.map +1 -0
- package/lib/typescript/src/fabric/TrueSheetOverlayViewNativeComponent.d.ts +6 -0
- package/lib/typescript/src/fabric/TrueSheetOverlayViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts +11 -7
- package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/mocks/index.d.ts +4 -0
- package/lib/typescript/src/mocks/index.d.ts.map +1 -1
- package/lib/typescript/src/mocks/navigationExpoRouter.d.ts +3 -3
- package/lib/typescript/src/mocks/navigationExpoRouter.d.ts.map +1 -1
- package/lib/typescript/src/navigation/base-types.d.ts +9 -0
- package/lib/typescript/src/navigation/base-types.d.ts.map +1 -0
- package/lib/typescript/src/navigation/createTrueSheetRouter.d.ts +2 -13
- package/lib/typescript/src/navigation/createTrueSheetRouter.d.ts.map +1 -1
- package/lib/typescript/src/navigation/expo-router/base-types.d.ts +8 -0
- package/lib/typescript/src/navigation/expo-router/base-types.d.ts.map +1 -0
- package/lib/typescript/src/navigation/expo-router/index.d.ts +8 -6
- package/lib/typescript/src/navigation/expo-router/index.d.ts.map +1 -1
- package/lib/typescript/src/navigation/expo-router/types.d.ts +44 -0
- package/lib/typescript/src/navigation/expo-router/types.d.ts.map +1 -0
- package/lib/typescript/src/navigation/index.d.ts +3 -4
- package/lib/typescript/src/navigation/index.d.ts.map +1 -1
- package/lib/typescript/src/navigation/screen/useSheetScreenState.d.ts +2 -1
- package/lib/typescript/src/navigation/screen/useSheetScreenState.d.ts.map +1 -1
- package/lib/typescript/src/navigation/types.d.ts +41 -5
- package/lib/typescript/src/navigation/types.d.ts.map +1 -1
- package/lib/typescript/src/web/constants.d.ts +1 -1
- package/lib/typescript/src/web/constants.d.ts.map +1 -1
- package/lib/typescript/src/web/layout.d.ts +19 -0
- package/lib/typescript/src/web/layout.d.ts.map +1 -0
- package/lib/typescript/src/web/vaul/constants.d.ts +1 -0
- package/lib/typescript/src/web/vaul/constants.d.ts.map +1 -1
- package/lib/typescript/src/web/vaul/context.d.ts +1 -0
- package/lib/typescript/src/web/vaul/context.d.ts.map +1 -1
- package/lib/typescript/src/web/vaul/helpers.d.ts +1 -0
- package/lib/typescript/src/web/vaul/helpers.d.ts.map +1 -1
- package/lib/typescript/src/web/vaul/index.d.ts +7 -1
- package/lib/typescript/src/web/vaul/index.d.ts.map +1 -1
- package/lib/typescript/src/web/vaul/use-snap-points.d.ts.map +1 -1
- package/package.json +17 -8
- package/react-native.config.js +1 -0
- package/src/TrueSheet.tsx +206 -48
- package/src/TrueSheet.types.ts +142 -35
- package/src/TrueSheet.web.tsx +270 -290
- package/src/TrueSheetBackground.tsx +17 -0
- package/src/TrueSheetOverlay.tsx +24 -0
- package/src/TrueSheetOverlay.web.tsx +33 -0
- package/src/TrueSheetPeek.web.tsx +25 -23
- package/src/detentBackgrounds.ts +24 -0
- package/src/fabric/TrueSheetContentViewNativeComponent.ts +1 -1
- package/src/fabric/TrueSheetOverlayViewNativeComponent.ts +12 -0
- package/src/fabric/TrueSheetViewNativeComponent.ts +14 -10
- package/src/index.ts +1 -0
- package/src/mocks/index.ts +17 -2
- package/src/mocks/navigationExpoRouter.ts +6 -5
- package/src/navigation/base-types.ts +20 -0
- package/src/navigation/createTrueSheetRouter.ts +5 -33
- package/src/navigation/expo-router/base-types.ts +18 -0
- package/src/navigation/expo-router/index.ts +28 -30
- package/src/navigation/expo-router/types.ts +116 -0
- package/src/navigation/index.ts +6 -7
- package/src/navigation/screen/useSheetScreenState.ts +2 -0
- package/src/navigation/types.ts +75 -22
- package/src/web/constants.ts +1 -1
- package/src/web/layout.ts +196 -0
- package/src/web/vaul/constants.ts +4 -0
- package/src/web/vaul/context.ts +1 -0
- package/src/web/vaul/helpers.ts +5 -0
- package/src/web/vaul/index.tsx +67 -5
- package/src/web/vaul/use-snap-points.ts +6 -14
|
@@ -1,28 +1,18 @@
|
|
|
1
1
|
package com.lodev09.truesheet
|
|
2
2
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
|
-
import android.view.MotionEvent
|
|
5
|
-
import android.view.View
|
|
6
|
-
import android.view.ViewParent
|
|
7
4
|
import com.facebook.react.bridge.WritableNativeMap
|
|
8
|
-
import com.facebook.react.uimanager.JSPointerDispatcher
|
|
9
|
-
import com.facebook.react.uimanager.JSTouchDispatcher
|
|
10
5
|
import com.facebook.react.uimanager.PixelUtil.pxToDp
|
|
11
|
-
import com.facebook.react.uimanager.PointerEvents
|
|
12
|
-
import com.facebook.react.uimanager.RootView
|
|
13
6
|
import com.facebook.react.uimanager.StateWrapper
|
|
14
7
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
15
|
-
import com.facebook.react.uimanager.events.EventDispatcher
|
|
16
8
|
import com.facebook.react.views.view.ReactViewGroup
|
|
17
|
-
import com.lodev09.truesheet.core.TrueSheetCoordinatorLayout
|
|
18
|
-
import com.lodev09.truesheet.utils.TouchEventDeduper
|
|
19
9
|
|
|
20
10
|
/**
|
|
21
|
-
* Delegate interface for footer view size changes
|
|
11
|
+
* Delegate interface for footer view size changes
|
|
22
12
|
*/
|
|
23
13
|
interface TrueSheetFooterViewDelegate {
|
|
24
14
|
fun footerViewDidChangeSize(width: Int, height: Int)
|
|
25
|
-
|
|
15
|
+
fun footerViewDidLayout()
|
|
26
16
|
}
|
|
27
17
|
|
|
28
18
|
/**
|
|
@@ -30,40 +20,29 @@ interface TrueSheetFooterViewDelegate {
|
|
|
30
20
|
* This is the second child of TrueSheetContainerView
|
|
31
21
|
* Positioned absolutely at the bottom of the sheet
|
|
32
22
|
*
|
|
33
|
-
*
|
|
23
|
+
* Touches reach it through the controller's RootView like any other sheet
|
|
24
|
+
* content — the container tracks the sheet's visible height, so the footer
|
|
25
|
+
* always lays out inside the container's bounds.
|
|
34
26
|
*/
|
|
35
27
|
@SuppressLint("ViewConstructor")
|
|
36
|
-
class TrueSheetFooterView(
|
|
37
|
-
ReactViewGroup(reactContext),
|
|
38
|
-
RootView {
|
|
28
|
+
class TrueSheetFooterView(reactContext: ThemedReactContext) : ReactViewGroup(reactContext) {
|
|
39
29
|
|
|
40
30
|
var delegate: TrueSheetFooterViewDelegate? = null
|
|
41
31
|
var stateWrapper: StateWrapper? = null
|
|
42
32
|
|
|
43
|
-
private val eventDispatcher: EventDispatcher?
|
|
44
|
-
get() = delegate?.eventDispatcher
|
|
45
|
-
|
|
46
33
|
private var lastWidth = 0
|
|
47
34
|
private var lastHeight = 0
|
|
48
|
-
private var bottomInset = 0
|
|
49
35
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
* above the keyboard, so the inset would leave a gap.
|
|
53
|
-
*/
|
|
54
|
-
var keyboardVisible = false
|
|
55
|
-
set(value) {
|
|
56
|
-
if (field == value) return
|
|
57
|
-
field = value
|
|
58
|
-
pushBottomInsetState()
|
|
59
|
-
}
|
|
36
|
+
var bottomInset = 0
|
|
37
|
+
private set
|
|
60
38
|
|
|
61
39
|
/**
|
|
62
40
|
* Height the footer occupies above the keyboard — its layout height minus
|
|
63
|
-
* the safe-area inset
|
|
41
|
+
* the safe-area inset, which rides below the keyboard's top edge while the
|
|
42
|
+
* keyboard is open (see positionFooter).
|
|
64
43
|
*/
|
|
65
44
|
val keyboardOcclusionHeight: Int
|
|
66
|
-
get() = maxOf(0, height -
|
|
45
|
+
get() = maxOf(0, height - bottomInset)
|
|
67
46
|
|
|
68
47
|
/**
|
|
69
48
|
* Tells the shadow node to pad the footer's bottom edge with the sheet's
|
|
@@ -73,12 +52,9 @@ class TrueSheetFooterView(private val reactContext: ThemedReactContext) :
|
|
|
73
52
|
fun setBottomInset(inset: Int) {
|
|
74
53
|
if (bottomInset == inset) return
|
|
75
54
|
bottomInset = inset
|
|
76
|
-
pushBottomInsetState()
|
|
77
|
-
}
|
|
78
55
|
|
|
79
|
-
private fun pushBottomInsetState() {
|
|
80
56
|
val sw = stateWrapper ?: return
|
|
81
|
-
val insetDp =
|
|
57
|
+
val insetDp = bottomInset.toFloat().pxToDp()
|
|
82
58
|
|
|
83
59
|
// Synchronous update — the footer must be padded before detents are
|
|
84
60
|
// configured, otherwise the auto detent is set up an inset short
|
|
@@ -90,14 +66,6 @@ class TrueSheetFooterView(private val reactContext: ThemedReactContext) :
|
|
|
90
66
|
sw.updateState(newState)
|
|
91
67
|
}
|
|
92
68
|
|
|
93
|
-
private val jsTouchDispatcher = JSTouchDispatcher(this)
|
|
94
|
-
private var jsPointerDispatcher: JSPointerDispatcher? = null
|
|
95
|
-
private val touchDeduper = TouchEventDeduper()
|
|
96
|
-
|
|
97
|
-
init {
|
|
98
|
-
jsPointerDispatcher = JSPointerDispatcher(this)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
69
|
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
|
|
102
70
|
super.onSizeChanged(w, h, oldw, oldh)
|
|
103
71
|
|
|
@@ -108,72 +76,15 @@ class TrueSheetFooterView(private val reactContext: ThemedReactContext) :
|
|
|
108
76
|
}
|
|
109
77
|
}
|
|
110
78
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return super.onInterceptTouchEvent(event)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {
|
|
124
|
-
// Mirrors ReactSurfaceView: keep receiving onInterceptTouchEvent so
|
|
125
|
-
// jsTouchDispatcher sees the gesture end, but forward the request up the tree.
|
|
126
|
-
parent?.requestDisallowInterceptTouchEvent(disallowIntercept)
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
override fun onTouchEvent(event: MotionEvent): Boolean {
|
|
130
|
-
if (pointerEvents == PointerEvents.NONE || pointerEvents == PointerEvents.BOX_NONE) {
|
|
131
|
-
return false
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
eventDispatcher?.let { dispatcher ->
|
|
135
|
-
if (touchDeduper.shouldDispatch(event)) {
|
|
136
|
-
jsTouchDispatcher.handleTouchEvent(event, dispatcher, reactContext)
|
|
137
|
-
}
|
|
138
|
-
jsPointerDispatcher?.handleMotionEvent(event, dispatcher, false)
|
|
139
|
-
}
|
|
140
|
-
super.onTouchEvent(event)
|
|
141
|
-
return true
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
override fun onInterceptHoverEvent(event: MotionEvent): Boolean {
|
|
145
|
-
eventDispatcher?.let { jsPointerDispatcher?.handleMotionEvent(event, it, true) }
|
|
146
|
-
return super.onHoverEvent(event)
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
override fun onHoverEvent(event: MotionEvent): Boolean {
|
|
150
|
-
eventDispatcher?.let { jsPointerDispatcher?.handleMotionEvent(event, it, false) }
|
|
151
|
-
return super.onHoverEvent(event)
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
override fun onChildStartedNativeGesture(childView: View?, ev: MotionEvent) {
|
|
155
|
-
findCoordinatorLayout()?.childDidClaimNativeGesture()
|
|
156
|
-
eventDispatcher?.let { dispatcher ->
|
|
157
|
-
jsTouchDispatcher.onChildStartedNativeGesture(ev, dispatcher)
|
|
158
|
-
jsPointerDispatcher?.onChildStartedNativeGesture(childView, ev, dispatcher)
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
private fun findCoordinatorLayout(): TrueSheetCoordinatorLayout? {
|
|
163
|
-
var current: ViewParent? = parent
|
|
164
|
-
while (current != null && current !is TrueSheetCoordinatorLayout) {
|
|
165
|
-
current = current.parent
|
|
166
|
-
}
|
|
167
|
-
return current as? TrueSheetCoordinatorLayout
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
override fun onChildEndedNativeGesture(childView: View, ev: MotionEvent) {
|
|
171
|
-
eventDispatcher?.let { jsTouchDispatcher.onChildEndedNativeGesture(ev, it) }
|
|
172
|
-
jsPointerDispatcher?.onChildEndedNativeGesture()
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
override fun handleException(t: Throwable) {
|
|
176
|
-
reactContext.reactApplicationContext.handleException(RuntimeException(t))
|
|
79
|
+
override fun onLayout(
|
|
80
|
+
changed: Boolean,
|
|
81
|
+
left: Int,
|
|
82
|
+
top: Int,
|
|
83
|
+
right: Int,
|
|
84
|
+
bottom: Int
|
|
85
|
+
) {
|
|
86
|
+
super.onLayout(changed, left, top, right, bottom)
|
|
87
|
+
delegate?.footerViewDidLayout()
|
|
177
88
|
}
|
|
178
89
|
|
|
179
90
|
companion object {
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
package com.lodev09.truesheet
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint
|
|
4
|
+
import android.view.View
|
|
5
|
+
import android.view.ViewGroup
|
|
6
|
+
import android.view.accessibility.AccessibilityEvent
|
|
7
|
+
import com.facebook.react.uimanager.StateWrapper
|
|
8
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
9
|
+
import com.facebook.react.uimanager.events.EventDispatcher
|
|
10
|
+
import com.facebook.react.views.view.ReactViewGroup
|
|
11
|
+
import com.lodev09.truesheet.core.TrueSheetOverlayRootView
|
|
12
|
+
import com.lodev09.truesheet.core.TrueSheetOverlayRootViewDelegate
|
|
13
|
+
import com.lodev09.truesheet.utils.findRootContainerView
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Hidden host that renders its children in a root view attached to the
|
|
17
|
+
* activity's content view, above every presented sheet.
|
|
18
|
+
*/
|
|
19
|
+
@SuppressLint("ViewConstructor")
|
|
20
|
+
class TrueSheetOverlayView(private val reactContext: ThemedReactContext) :
|
|
21
|
+
ReactViewGroup(reactContext),
|
|
22
|
+
TrueSheetOverlayRootViewDelegate {
|
|
23
|
+
|
|
24
|
+
private val rootView = TrueSheetOverlayRootView(reactContext).apply {
|
|
25
|
+
delegate = this@TrueSheetOverlayView
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
private var rootContainerView: ViewGroup? = null
|
|
29
|
+
|
|
30
|
+
override var eventDispatcher: EventDispatcher? = null
|
|
31
|
+
|
|
32
|
+
private var lastWidth = 0
|
|
33
|
+
private var lastHeight = 0
|
|
34
|
+
|
|
35
|
+
// Fabric hands back a new StateWrapper on every state commit — including our
|
|
36
|
+
// own pushes — so pushState dedupes against the last pushed size to break the loop
|
|
37
|
+
private var lastStateWidth = 0
|
|
38
|
+
private var lastStateHeight = 0
|
|
39
|
+
|
|
40
|
+
var stateWrapper: StateWrapper? = null
|
|
41
|
+
set(value) {
|
|
42
|
+
field = value
|
|
43
|
+
pushState()
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
init {
|
|
47
|
+
// The host stays in the React tree for layout only — children render in the root view
|
|
48
|
+
visibility = GONE
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ==================== View Hierarchy Management ====================
|
|
52
|
+
|
|
53
|
+
override fun onAttachedToWindow() {
|
|
54
|
+
super.onAttachedToWindow()
|
|
55
|
+
attachRootView()
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
override fun onDetachedFromWindow() {
|
|
59
|
+
detachRootView()
|
|
60
|
+
super.onDetachedFromWindow()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private fun attachRootView() {
|
|
64
|
+
if (rootView.parent != null) return
|
|
65
|
+
|
|
66
|
+
val container = findRootContainerView(reactContext) ?: return
|
|
67
|
+
container.addView(rootView)
|
|
68
|
+
rootContainerView = container
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private fun detachRootView() {
|
|
72
|
+
rootContainerView?.removeView(rootView)
|
|
73
|
+
rootContainerView = null
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
fun onDropInstance() {
|
|
77
|
+
detachRootView()
|
|
78
|
+
rootView.delegate = null
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
override fun addView(child: View?, index: Int) {
|
|
82
|
+
rootView.addView(child, index)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
override fun getChildCount(): Int = rootView.childCount
|
|
86
|
+
|
|
87
|
+
override fun getChildAt(index: Int): View? = rootView.getChildAt(index)
|
|
88
|
+
|
|
89
|
+
override fun removeViewAt(index: Int) {
|
|
90
|
+
rootView.removeViewAt(index)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Accessibility: children live in the root view since this view is hidden
|
|
94
|
+
override fun addChildrenForAccessibility(outChildren: ArrayList<View>) {}
|
|
95
|
+
override fun dispatchPopulateAccessibilityEvent(event: AccessibilityEvent): Boolean = false
|
|
96
|
+
|
|
97
|
+
// ==================== State ====================
|
|
98
|
+
|
|
99
|
+
override fun overlayRootViewDidChangeSize(width: Int, height: Int) {
|
|
100
|
+
if (width == lastWidth && height == lastHeight) return
|
|
101
|
+
|
|
102
|
+
lastWidth = width
|
|
103
|
+
lastHeight = height
|
|
104
|
+
pushState()
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private fun pushState() {
|
|
108
|
+
if (lastWidth == 0 && lastHeight == 0) return
|
|
109
|
+
if (lastWidth == lastStateWidth && lastHeight == lastStateHeight) return
|
|
110
|
+
val sw = stateWrapper ?: return
|
|
111
|
+
|
|
112
|
+
lastStateWidth = lastWidth
|
|
113
|
+
lastStateHeight = lastHeight
|
|
114
|
+
TrueSheetStateUpdater.updateContainerSize(sw, lastWidth, lastHeight)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
package com.lodev09.truesheet
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
4
|
+
import com.facebook.react.uimanager.PointerEvents
|
|
5
|
+
import com.facebook.react.uimanager.ReactStylesDiffMap
|
|
6
|
+
import com.facebook.react.uimanager.StateWrapper
|
|
7
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
8
|
+
import com.facebook.react.uimanager.UIManagerHelper
|
|
9
|
+
import com.facebook.react.uimanager.ViewGroupManager
|
|
10
|
+
import com.facebook.react.uimanager.annotations.ReactProp
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* ViewManager for TrueSheetOverlayView
|
|
14
|
+
* Renders content above every presented sheet
|
|
15
|
+
*/
|
|
16
|
+
@ReactModule(name = TrueSheetOverlayViewManager.REACT_CLASS)
|
|
17
|
+
class TrueSheetOverlayViewManager : ViewGroupManager<TrueSheetOverlayView>() {
|
|
18
|
+
|
|
19
|
+
override fun getName(): String = REACT_CLASS
|
|
20
|
+
|
|
21
|
+
override fun createViewInstance(reactContext: ThemedReactContext): TrueSheetOverlayView = TrueSheetOverlayView(reactContext)
|
|
22
|
+
|
|
23
|
+
override fun onDropViewInstance(view: TrueSheetOverlayView) {
|
|
24
|
+
super.onDropViewInstance(view)
|
|
25
|
+
view.onDropInstance()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
override fun addEventEmitters(reactContext: ThemedReactContext, view: TrueSheetOverlayView) {
|
|
29
|
+
view.eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, view.id)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
override fun updateState(view: TrueSheetOverlayView, props: ReactStylesDiffMap?, stateWrapper: StateWrapper?): Any? {
|
|
33
|
+
view.stateWrapper = stateWrapper
|
|
34
|
+
return null
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@ReactProp(name = "pointerEvents")
|
|
38
|
+
fun setPointerEvents(view: TrueSheetOverlayView, pointerEventsStr: String?) {
|
|
39
|
+
view.pointerEvents = PointerEvents.parsePointerEvents(pointerEventsStr)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
companion object {
|
|
43
|
+
const val REACT_CLASS = "TrueSheetOverlayView"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
package com.lodev09.truesheet
|
|
2
2
|
|
|
3
|
+
import com.facebook.react.bridge.WritableNativeMap
|
|
4
|
+
import com.facebook.react.uimanager.PixelUtil.pxToDp
|
|
3
5
|
import com.facebook.react.uimanager.StateWrapper
|
|
4
6
|
|
|
5
7
|
/**
|
|
@@ -22,6 +24,22 @@ object TrueSheetStateUpdater {
|
|
|
22
24
|
fun updateState(stateWrapper: StateWrapper, widthDp: Float, heightDp: Float): Boolean =
|
|
23
25
|
isAvailable && nativeUpdateState(stateWrapper, widthDp, heightDp)
|
|
24
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Pushes the container size (px) into the Fabric state — synchronously when
|
|
29
|
+
* the bridge is available, async otherwise.
|
|
30
|
+
*/
|
|
31
|
+
fun updateContainerSize(stateWrapper: StateWrapper, widthPx: Int, heightPx: Int) {
|
|
32
|
+
val widthDp = widthPx.toFloat().pxToDp()
|
|
33
|
+
val heightDp = heightPx.toFloat().pxToDp()
|
|
34
|
+
|
|
35
|
+
if (updateState(stateWrapper, widthDp, heightDp)) return
|
|
36
|
+
|
|
37
|
+
val newStateData = WritableNativeMap()
|
|
38
|
+
newStateData.putDouble("containerWidth", widthDp.toDouble())
|
|
39
|
+
newStateData.putDouble("containerHeight", heightDp.toDouble())
|
|
40
|
+
stateWrapper.updateState(newStateData)
|
|
41
|
+
}
|
|
42
|
+
|
|
25
43
|
/** Returns false when unavailable — caller should fall back to async updateState. */
|
|
26
44
|
fun updateFooterState(stateWrapper: StateWrapper, bottomInsetDp: Float): Boolean =
|
|
27
45
|
isAvailable && nativeUpdateFooterState(stateWrapper, bottomInsetDp)
|
|
@@ -6,7 +6,6 @@ import android.view.ViewGroup
|
|
|
6
6
|
import android.view.accessibility.AccessibilityEvent
|
|
7
7
|
import androidx.annotation.UiThread
|
|
8
8
|
import com.facebook.react.bridge.LifecycleEventListener
|
|
9
|
-
import com.facebook.react.bridge.WritableNativeMap
|
|
10
9
|
import com.facebook.react.uimanager.PixelUtil.dpToPx
|
|
11
10
|
import com.facebook.react.uimanager.PixelUtil.pxToDp
|
|
12
11
|
import com.facebook.react.uimanager.StateWrapper
|
|
@@ -22,6 +21,7 @@ import com.lodev09.truesheet.core.RNScreensEventObserverDelegate
|
|
|
22
21
|
import com.lodev09.truesheet.core.TrueSheetStackManager
|
|
23
22
|
import com.lodev09.truesheet.events.*
|
|
24
23
|
import com.lodev09.truesheet.utils.KeyboardUtils
|
|
24
|
+
import com.lodev09.truesheet.utils.findRootContainerView
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* Main TrueSheet host view that manages the sheet and dispatches events to JavaScript.
|
|
@@ -101,13 +101,30 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
101
101
|
|
|
102
102
|
override fun onAttachedToWindow() {
|
|
103
103
|
super.onAttachedToWindow()
|
|
104
|
+
presentInitialIfNeeded()
|
|
105
|
+
}
|
|
104
106
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
107
|
+
/**
|
|
108
|
+
* JS holds initialDetentIndex back one commit so effect-driven content (e.g. a
|
|
109
|
+
* navigation footer set via setOptions) commits together with it. The prop then
|
|
110
|
+
* arrives after attach, so the ViewManager triggers this on prop update too.
|
|
111
|
+
* Posted so sibling mounts from the current transaction land before measuring.
|
|
112
|
+
*/
|
|
113
|
+
fun presentInitialIfNeeded() {
|
|
114
|
+
if (initialDetentIndex < 0 || didInitiallyPresent || !isAttachedToWindow) return
|
|
115
|
+
|
|
116
|
+
didInitiallyPresent = true
|
|
117
|
+
post {
|
|
118
|
+
// The view may have been dropped (flag reset) or detached before this
|
|
119
|
+
// ran — roll back so a later attach retries instead of presenting a
|
|
120
|
+
// sheet with no live host.
|
|
121
|
+
if (!didInitiallyPresent) return@post
|
|
122
|
+
if (!isAttachedToWindow) {
|
|
123
|
+
didInitiallyPresent = false
|
|
124
|
+
return@post
|
|
125
|
+
}
|
|
126
|
+
if (!viewController.isPresented) {
|
|
127
|
+
present(initialDetentIndex, initialDetentAnimated) { }
|
|
111
128
|
}
|
|
112
129
|
}
|
|
113
130
|
}
|
|
@@ -187,6 +204,7 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
187
204
|
setupScrollable()
|
|
188
205
|
|
|
189
206
|
if (viewController.isPresented) {
|
|
207
|
+
viewController.setupBackground()
|
|
190
208
|
viewController.sheetView?.setupBackground()
|
|
191
209
|
viewController.sheetView?.setupGrabber()
|
|
192
210
|
viewController.sheetView?.updateGravity()
|
|
@@ -207,15 +225,15 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
207
225
|
viewController.maxContentWidth = width
|
|
208
226
|
}
|
|
209
227
|
|
|
210
|
-
fun
|
|
211
|
-
val value =
|
|
212
|
-
if (viewController.
|
|
213
|
-
viewController.
|
|
228
|
+
fun setPlacement(placement: String?) {
|
|
229
|
+
val value = TrueSheetPlacement.fromString(placement)
|
|
230
|
+
if (viewController.placement == value) return
|
|
231
|
+
viewController.placement = value
|
|
214
232
|
}
|
|
215
233
|
|
|
216
|
-
fun
|
|
217
|
-
if (viewController.
|
|
218
|
-
viewController.
|
|
234
|
+
fun setPlacementOffset(offset: Int) {
|
|
235
|
+
if (viewController.placementOffset == offset) return
|
|
236
|
+
viewController.placementOffset = offset
|
|
219
237
|
}
|
|
220
238
|
|
|
221
239
|
fun setDimmed(dimmed: Boolean) {
|
|
@@ -243,9 +261,12 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
243
261
|
viewController.sheetCornerRadius = radius
|
|
244
262
|
}
|
|
245
263
|
|
|
264
|
+
fun setDetentBackgrounds(colors: List<Int?>) {
|
|
265
|
+
viewController.detentBackgrounds = colors
|
|
266
|
+
}
|
|
267
|
+
|
|
246
268
|
fun setSheetBackgroundColor(color: Int?) {
|
|
247
|
-
|
|
248
|
-
viewController.sheetBackgroundColor = color
|
|
269
|
+
viewController.backgroundColor = color
|
|
249
270
|
}
|
|
250
271
|
|
|
251
272
|
fun setDismissible(dismissible: Boolean) {
|
|
@@ -287,6 +308,12 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
287
308
|
setupScrollable()
|
|
288
309
|
}
|
|
289
310
|
|
|
311
|
+
fun setScrollableHandle(handle: Int) {
|
|
312
|
+
if (viewController.scrollableHandle == handle) return
|
|
313
|
+
viewController.scrollableHandle = handle
|
|
314
|
+
setupScrollable()
|
|
315
|
+
}
|
|
316
|
+
|
|
290
317
|
fun setAbsoluteHeader(absolute: Boolean) {
|
|
291
318
|
viewController.absoluteHeader = absolute
|
|
292
319
|
}
|
|
@@ -300,14 +327,20 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
300
327
|
viewController.positionFooter()
|
|
301
328
|
}
|
|
302
329
|
|
|
330
|
+
fun setFooterAvoidsKeyboard(avoids: Boolean) {
|
|
331
|
+
viewController.footerAvoidsKeyboard = avoids
|
|
332
|
+
viewController.containerView?.footerAvoidsKeyboard = avoids
|
|
333
|
+
viewController.positionFooter()
|
|
334
|
+
}
|
|
335
|
+
|
|
303
336
|
private fun setupScrollable() {
|
|
304
337
|
viewController.containerView?.let {
|
|
305
|
-
it.insetAdjustment = viewController.insetAdjustment
|
|
306
|
-
it.scrollViewBottomInset = viewController.contentBottomInset
|
|
307
338
|
it.scrollableOptions = viewController.scrollableOptions
|
|
308
|
-
it.
|
|
339
|
+
it.scrollableHandle = viewController.scrollableHandle
|
|
340
|
+
it.scrollableBottomInset = viewController.contentBottomInset
|
|
309
341
|
it.footerBottomInset = viewController.contentBottomInset
|
|
310
342
|
it.absoluteFooter = viewController.absoluteFooter
|
|
343
|
+
it.footerAvoidsKeyboard = viewController.footerAvoidsKeyboard
|
|
311
344
|
it.setupScrollable()
|
|
312
345
|
}
|
|
313
346
|
|
|
@@ -354,18 +387,7 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
354
387
|
lastContainerWidth = width
|
|
355
388
|
lastContainerHeight = height
|
|
356
389
|
|
|
357
|
-
|
|
358
|
-
val widthDp = width.toFloat().pxToDp()
|
|
359
|
-
val heightDp = height.toFloat().pxToDp()
|
|
360
|
-
|
|
361
|
-
// Synchronous update — commits and mounts within the same UI-thread frame
|
|
362
|
-
if (TrueSheetStateUpdater.updateState(sw, widthDp, heightDp)) return
|
|
363
|
-
|
|
364
|
-
// Fallback: async state update
|
|
365
|
-
val newStateData = WritableNativeMap()
|
|
366
|
-
newStateData.putDouble("containerWidth", widthDp.toDouble())
|
|
367
|
-
newStateData.putDouble("containerHeight", heightDp.toDouble())
|
|
368
|
-
sw.updateState(newStateData)
|
|
390
|
+
stateWrapper?.let { TrueSheetStateUpdater.updateContainerSize(it, width, height) }
|
|
369
391
|
}
|
|
370
392
|
|
|
371
393
|
// ==================== Sheet Actions ====================
|
|
@@ -385,11 +407,22 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
385
407
|
val parentSheet = TrueSheetStackManager.getTopmostSheet()
|
|
386
408
|
val isFocusedViewWithinSheet = parentSheet?.viewController?.isFocusedViewWithinSheet() == true
|
|
387
409
|
val shouldDismissKeyboard = isFocusedViewWithinSheet || viewController.isDimmedAtDetentIndex(detentIndex)
|
|
388
|
-
if (KeyboardUtils.isKeyboardVisible(reactContext)
|
|
410
|
+
if (shouldDismissKeyboard && KeyboardUtils.isKeyboardVisible(reactContext)) {
|
|
389
411
|
viewController.saveFocusedView()
|
|
390
412
|
KeyboardUtils.dismiss(this) {
|
|
391
|
-
post {
|
|
413
|
+
post { presentSheet(detentIndex, animated, promiseCallback) }
|
|
392
414
|
}
|
|
415
|
+
// Blur like iOS so JS focus state stays in sync until restoreFocusedView() refocuses it
|
|
416
|
+
rootView.findFocus()?.clearFocus()
|
|
417
|
+
return
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
presentSheet(detentIndex, animated, promiseCallback)
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
private fun presentSheet(detentIndex: Int, animated: Boolean, promiseCallback: () -> Unit) {
|
|
424
|
+
if (viewController.isPresented) {
|
|
425
|
+
promiseCallback()
|
|
393
426
|
return
|
|
394
427
|
}
|
|
395
428
|
|
|
@@ -469,7 +502,13 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
469
502
|
if (viewController.containerView == null) return@post
|
|
470
503
|
|
|
471
504
|
viewController.setupSheetDetentsForSizeChange()
|
|
472
|
-
|
|
505
|
+
// While settling, onSlide drives the parent translation in realtime —
|
|
506
|
+
// an animated update here would race it frame-by-frame, staggering the
|
|
507
|
+
// emitted position. Keyboard-driven resizes leave the parent alone (like
|
|
508
|
+
// iOS); keyboardDidHide resizes again once the detents are keyboard-free.
|
|
509
|
+
if (!viewController.isSettling && !viewController.isKeyboardActive) {
|
|
510
|
+
TrueSheetStackManager.updateParentTranslation(this)
|
|
511
|
+
}
|
|
473
512
|
}
|
|
474
513
|
}
|
|
475
514
|
|
|
@@ -497,14 +536,46 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
497
536
|
}
|
|
498
537
|
}
|
|
499
538
|
|
|
539
|
+
/**
|
|
540
|
+
* Realtime counterpart of updateTranslationForChild, driven by the child's
|
|
541
|
+
* onSlide frames so stacked sheets move in lockstep instead of on
|
|
542
|
+
* independently-timed animations.
|
|
543
|
+
*/
|
|
544
|
+
fun syncTranslationForChild(childSheetTop: Int, childMinSheetTop: Int) {
|
|
545
|
+
if (!viewController.isSheetVisible || viewController.isExpanded) return
|
|
546
|
+
|
|
547
|
+
val mySheetTop = viewController.detentCalculator.getSheetTopForDetentIndex(viewController.currentDetentIndex)
|
|
548
|
+
val targetTranslation = maxOf(0, childMinSheetTop - mySheetTop)
|
|
549
|
+
val actualTranslation = maxOf(0, childSheetTop - mySheetTop)
|
|
550
|
+
val currentTranslation = viewController.currentTranslationY
|
|
551
|
+
|
|
552
|
+
// Ride the child's actual position, but only between the current
|
|
553
|
+
// translation and the settled target — tracks the child frame-by-frame
|
|
554
|
+
// when the alignment changes (auto detent resize) while staying put when
|
|
555
|
+
// the child moves between detents above its minimum. Returning early on
|
|
556
|
+
// no-ops avoids cancelling an in-flight realign animation.
|
|
557
|
+
val newTranslation = actualTranslation.coerceIn(
|
|
558
|
+
minOf(currentTranslation, targetTranslation),
|
|
559
|
+
maxOf(currentTranslation, targetTranslation)
|
|
560
|
+
)
|
|
561
|
+
if (newTranslation == currentTranslation) return
|
|
562
|
+
|
|
563
|
+
viewController.translateSheet(newTranslation, animated = false)
|
|
564
|
+
|
|
565
|
+
val additionalTranslation = newTranslation - currentTranslation
|
|
566
|
+
if (additionalTranslation > 0) {
|
|
567
|
+
TrueSheetStackManager.getParentSheet(this)?.addTranslation(additionalTranslation, animated = false)
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
500
571
|
/**
|
|
501
572
|
* Recursively adds translation to this sheet and all parent sheets.
|
|
502
573
|
*/
|
|
503
|
-
private fun addTranslation(amount: Int) {
|
|
574
|
+
private fun addTranslation(amount: Int, animated: Boolean = true) {
|
|
504
575
|
if (viewController.isExpanded) return
|
|
505
576
|
|
|
506
|
-
viewController.translateSheet(viewController.currentTranslationY + amount)
|
|
507
|
-
TrueSheetStackManager.getParentSheet(this)?.addTranslation(amount)
|
|
577
|
+
viewController.translateSheet(viewController.currentTranslationY + amount, animated)
|
|
578
|
+
TrueSheetStackManager.getParentSheet(this)?.addTranslation(amount, animated)
|
|
508
579
|
}
|
|
509
580
|
|
|
510
581
|
/**
|
|
@@ -542,6 +613,11 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
542
613
|
eventDispatcher?.dispatchEvent(WillDismissEvent(surfaceId, id))
|
|
543
614
|
}
|
|
544
615
|
|
|
616
|
+
override fun viewControllerDidAttemptDismiss() {
|
|
617
|
+
val surfaceId = UIManagerHelper.getSurfaceId(this)
|
|
618
|
+
eventDispatcher?.dispatchEvent(DismissAttemptEvent(surfaceId, id))
|
|
619
|
+
}
|
|
620
|
+
|
|
545
621
|
override fun viewControllerDidDismiss(parent: TrueSheetView?) {
|
|
546
622
|
// Detach coordinator from the root container view
|
|
547
623
|
viewController.coordinatorLayout?.let { rootContainerView?.removeView(it) }
|
|
@@ -626,7 +702,7 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
626
702
|
viewController.commitKeyboardDetent()
|
|
627
703
|
}
|
|
628
704
|
|
|
629
|
-
// When the ScrollView changes (e.g. conditional remount), re-
|
|
705
|
+
// When the ScrollView changes (e.g. conditional remount), re-detect the new ScrollView
|
|
630
706
|
// and request layout so BottomSheetBehavior re-discovers the nested scrolling child.
|
|
631
707
|
override fun containerViewScrollViewDidChange() {
|
|
632
708
|
setupScrollable()
|
|
@@ -643,6 +719,10 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
643
719
|
viewController.positionFooter()
|
|
644
720
|
}
|
|
645
721
|
|
|
722
|
+
override fun containerViewFooterDidLayout() {
|
|
723
|
+
viewController.positionFooter()
|
|
724
|
+
}
|
|
725
|
+
|
|
646
726
|
override fun containerViewPeekDidChangeSize(width: Int, height: Int) {
|
|
647
727
|
// Peek content height affects peek detents
|
|
648
728
|
updateSheetIfNeeded()
|
|
@@ -672,16 +752,5 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
672
752
|
* of whichever window this view is in - whether that's the activity's window or a
|
|
673
753
|
* Modal's dialog window.
|
|
674
754
|
*/
|
|
675
|
-
override fun findRootContainerView(): ViewGroup?
|
|
676
|
-
var current: android.view.ViewParent? = parent
|
|
677
|
-
|
|
678
|
-
while (current != null) {
|
|
679
|
-
if (current is ViewGroup && current.id == android.R.id.content) {
|
|
680
|
-
return current
|
|
681
|
-
}
|
|
682
|
-
current = current.parent
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
return reactContext.currentActivity?.findViewById(android.R.id.content)
|
|
686
|
-
}
|
|
755
|
+
override fun findRootContainerView(): ViewGroup? = findRootContainerView(reactContext)
|
|
687
756
|
}
|