@lodev09/react-native-true-sheet 4.0.0-beta.15 → 4.0.0-beta.17
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/main/java/com/lodev09/truesheet/TrueSheetContainerView.kt +0 -5
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterView.kt +5 -95
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetOverlayView.kt +11 -1
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +18 -46
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetCoordinatorLayout.kt +1 -1
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDimView.kt +3 -0
- package/android/src/main/java/com/lodev09/truesheet/utils/ScreenUtils.kt +0 -12
- package/ios/TrueSheetFooterView.mm +27 -11
- package/ios/TrueSheetView.mm +1 -0
- package/lib/module/TrueSheet.web.js +49 -277
- package/lib/module/TrueSheet.web.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/helpers.js +1 -0
- package/lib/module/web/vaul/helpers.js.map +1 -1
- package/lib/module/web/vaul/index.js +9 -4
- 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.web.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/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.map +1 -1
- package/lib/typescript/src/web/vaul/use-snap-points.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/TrueSheet.web.tsx +78 -333
- package/src/web/layout.ts +196 -0
- package/src/web/vaul/helpers.ts +5 -0
- package/src/web/vaul/index.tsx +21 -4
- package/src/web/vaul/use-snap-points.ts +6 -14
|
@@ -4,11 +4,9 @@ import android.annotation.SuppressLint
|
|
|
4
4
|
import android.view.View
|
|
5
5
|
import android.view.ViewGroup
|
|
6
6
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
7
|
-
import com.facebook.react.uimanager.events.EventDispatcher
|
|
8
7
|
import com.facebook.react.views.view.ReactViewGroup
|
|
9
8
|
|
|
10
9
|
interface TrueSheetContainerViewDelegate {
|
|
11
|
-
val eventDispatcher: EventDispatcher?
|
|
12
10
|
fun containerViewContentDidChangeSize(width: Int, height: Int)
|
|
13
11
|
fun containerViewContentDidScroll()
|
|
14
12
|
fun containerViewScrollViewDidChange()
|
|
@@ -107,9 +105,6 @@ class TrueSheetContainerView(reactContext: ThemedReactContext) :
|
|
|
107
105
|
contentView?.bottomInset = value
|
|
108
106
|
}
|
|
109
107
|
|
|
110
|
-
override val eventDispatcher: EventDispatcher?
|
|
111
|
-
get() = delegate?.eventDispatcher
|
|
112
|
-
|
|
113
108
|
init {
|
|
114
109
|
// Allow footer to position outside container bounds
|
|
115
110
|
clipChildren = false
|
|
@@ -1,29 +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
|
-
val eventDispatcher: EventDispatcher?
|
|
27
16
|
}
|
|
28
17
|
|
|
29
18
|
/**
|
|
@@ -31,19 +20,16 @@ interface TrueSheetFooterViewDelegate {
|
|
|
31
20
|
* This is the second child of TrueSheetContainerView
|
|
32
21
|
* Positioned absolutely at the bottom of the sheet
|
|
33
22
|
*
|
|
34
|
-
*
|
|
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.
|
|
35
26
|
*/
|
|
36
27
|
@SuppressLint("ViewConstructor")
|
|
37
|
-
class TrueSheetFooterView(
|
|
38
|
-
ReactViewGroup(reactContext),
|
|
39
|
-
RootView {
|
|
28
|
+
class TrueSheetFooterView(reactContext: ThemedReactContext) : ReactViewGroup(reactContext) {
|
|
40
29
|
|
|
41
30
|
var delegate: TrueSheetFooterViewDelegate? = null
|
|
42
31
|
var stateWrapper: StateWrapper? = null
|
|
43
32
|
|
|
44
|
-
private val eventDispatcher: EventDispatcher?
|
|
45
|
-
get() = delegate?.eventDispatcher
|
|
46
|
-
|
|
47
33
|
private var lastWidth = 0
|
|
48
34
|
private var lastHeight = 0
|
|
49
35
|
|
|
@@ -80,14 +66,6 @@ class TrueSheetFooterView(private val reactContext: ThemedReactContext) :
|
|
|
80
66
|
sw.updateState(newState)
|
|
81
67
|
}
|
|
82
68
|
|
|
83
|
-
private val jsTouchDispatcher = JSTouchDispatcher(this)
|
|
84
|
-
private var jsPointerDispatcher: JSPointerDispatcher? = null
|
|
85
|
-
private val touchDeduper = TouchEventDeduper()
|
|
86
|
-
|
|
87
|
-
init {
|
|
88
|
-
jsPointerDispatcher = JSPointerDispatcher(this)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
69
|
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
|
|
92
70
|
super.onSizeChanged(w, h, oldw, oldh)
|
|
93
71
|
|
|
@@ -109,74 +87,6 @@ class TrueSheetFooterView(private val reactContext: ThemedReactContext) :
|
|
|
109
87
|
delegate?.footerViewDidLayout()
|
|
110
88
|
}
|
|
111
89
|
|
|
112
|
-
// ==================== RootView Implementation ====================
|
|
113
|
-
|
|
114
|
-
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
|
|
115
|
-
eventDispatcher?.let { dispatcher ->
|
|
116
|
-
if (touchDeduper.shouldDispatch(event)) {
|
|
117
|
-
jsTouchDispatcher.handleTouchEvent(event, dispatcher, reactContext)
|
|
118
|
-
}
|
|
119
|
-
jsPointerDispatcher?.handleMotionEvent(event, dispatcher, true)
|
|
120
|
-
}
|
|
121
|
-
return super.onInterceptTouchEvent(event)
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {
|
|
125
|
-
// Mirrors ReactSurfaceView: keep receiving onInterceptTouchEvent so
|
|
126
|
-
// jsTouchDispatcher sees the gesture end, but forward the request up the tree.
|
|
127
|
-
parent?.requestDisallowInterceptTouchEvent(disallowIntercept)
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
override fun onTouchEvent(event: MotionEvent): Boolean {
|
|
131
|
-
if (pointerEvents == PointerEvents.NONE || pointerEvents == PointerEvents.BOX_NONE) {
|
|
132
|
-
return false
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
eventDispatcher?.let { dispatcher ->
|
|
136
|
-
if (touchDeduper.shouldDispatch(event)) {
|
|
137
|
-
jsTouchDispatcher.handleTouchEvent(event, dispatcher, reactContext)
|
|
138
|
-
}
|
|
139
|
-
jsPointerDispatcher?.handleMotionEvent(event, dispatcher, false)
|
|
140
|
-
}
|
|
141
|
-
super.onTouchEvent(event)
|
|
142
|
-
return true
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
override fun onInterceptHoverEvent(event: MotionEvent): Boolean {
|
|
146
|
-
eventDispatcher?.let { jsPointerDispatcher?.handleMotionEvent(event, it, true) }
|
|
147
|
-
return super.onHoverEvent(event)
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
override fun onHoverEvent(event: MotionEvent): Boolean {
|
|
151
|
-
eventDispatcher?.let { jsPointerDispatcher?.handleMotionEvent(event, it, false) }
|
|
152
|
-
return super.onHoverEvent(event)
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
override fun onChildStartedNativeGesture(childView: View?, ev: MotionEvent) {
|
|
156
|
-
findCoordinatorLayout()?.childDidClaimNativeGesture()
|
|
157
|
-
eventDispatcher?.let { dispatcher ->
|
|
158
|
-
jsTouchDispatcher.onChildStartedNativeGesture(ev, dispatcher)
|
|
159
|
-
jsPointerDispatcher?.onChildStartedNativeGesture(childView, ev, dispatcher)
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
private fun findCoordinatorLayout(): TrueSheetCoordinatorLayout? {
|
|
164
|
-
var current: ViewParent? = parent
|
|
165
|
-
while (current != null && current !is TrueSheetCoordinatorLayout) {
|
|
166
|
-
current = current.parent
|
|
167
|
-
}
|
|
168
|
-
return current as? TrueSheetCoordinatorLayout
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
override fun onChildEndedNativeGesture(childView: View, ev: MotionEvent) {
|
|
172
|
-
eventDispatcher?.let { jsTouchDispatcher.onChildEndedNativeGesture(ev, it) }
|
|
173
|
-
jsPointerDispatcher?.onChildEndedNativeGesture()
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
override fun handleException(t: Throwable) {
|
|
177
|
-
reactContext.reactApplicationContext.handleException(RuntimeException(t))
|
|
178
|
-
}
|
|
179
|
-
|
|
180
90
|
companion object {
|
|
181
91
|
const val TAG_NAME = "TrueSheet"
|
|
182
92
|
}
|
|
@@ -32,6 +32,11 @@ class TrueSheetOverlayView(private val reactContext: ThemedReactContext) :
|
|
|
32
32
|
private var lastWidth = 0
|
|
33
33
|
private var lastHeight = 0
|
|
34
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
|
+
|
|
35
40
|
var stateWrapper: StateWrapper? = null
|
|
36
41
|
set(value) {
|
|
37
42
|
field = value
|
|
@@ -101,6 +106,11 @@ class TrueSheetOverlayView(private val reactContext: ThemedReactContext) :
|
|
|
101
106
|
|
|
102
107
|
private fun pushState() {
|
|
103
108
|
if (lastWidth == 0 && lastHeight == 0) return
|
|
104
|
-
|
|
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)
|
|
105
115
|
}
|
|
106
116
|
}
|
|
@@ -209,12 +209,6 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
209
209
|
// Touch Dispatchers
|
|
210
210
|
private val jsTouchDispatcher = JSTouchDispatcher(this)
|
|
211
211
|
private val jsPointerDispatcher = JSPointerDispatcher(this)
|
|
212
|
-
|
|
213
|
-
// True when the active touch stream began inside the footer. Latched on
|
|
214
|
-
// ACTION_DOWN so subsequent MOVE events keep routing to the footer even if
|
|
215
|
-
// the finger drifts outside the footer's rect mid-gesture.
|
|
216
|
-
private var footerOwnsTouchStream = false
|
|
217
|
-
|
|
218
212
|
private val touchDeduper = TouchEventDeduper()
|
|
219
213
|
|
|
220
214
|
private val eventDispatcher
|
|
@@ -1042,13 +1036,25 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
1042
1036
|
animate = isPresented
|
|
1043
1037
|
)
|
|
1044
1038
|
|
|
1045
|
-
updateStateDimensions()
|
|
1046
|
-
|
|
1047
1039
|
if (isPresented && applyState) {
|
|
1048
1040
|
// Prefer the pending target while a resize animation is in flight so a
|
|
1049
1041
|
// layout-driven reconfigure doesn't revert to the stale currentDetentIndex.
|
|
1050
1042
|
val targetIndex = if (pendingDetentIndex >= 0) pendingDetentIndex else currentDetentIndex
|
|
1043
|
+
|
|
1044
|
+
// Track the settle like resize() — the container (and the footer pinned
|
|
1045
|
+
// to its bottom) follows the sheet's visible height instead of jumping
|
|
1046
|
+
// to the target and riding the animation
|
|
1047
|
+
pendingDetentIndex = targetIndex
|
|
1048
|
+
sheetView?.let { updateStateDimensionsForPosition(it.top) }
|
|
1051
1049
|
setStateForDetentIndex(targetIndex)
|
|
1050
|
+
|
|
1051
|
+
// Already at the target — no slide frames will follow
|
|
1052
|
+
if (!isSettling) {
|
|
1053
|
+
pendingDetentIndex = -1
|
|
1054
|
+
updateStateDimensions()
|
|
1055
|
+
}
|
|
1056
|
+
} else {
|
|
1057
|
+
updateStateDimensions()
|
|
1052
1058
|
}
|
|
1053
1059
|
|
|
1054
1060
|
interactionState = InteractionState.Idle
|
|
@@ -1190,9 +1196,10 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
1190
1196
|
val sheetHeight = sheet.height
|
|
1191
1197
|
|
|
1192
1198
|
// Pinned to the screen bottom (above the keyboard) while the sheet sits at
|
|
1193
|
-
// or above its lowest stop; past it the footer rides down with the
|
|
1194
|
-
// instead, like iOS
|
|
1195
|
-
|
|
1199
|
+
// or above its lowest stop; dragged past it the footer rides down with the
|
|
1200
|
+
// sheet instead, like iOS. A resize settle always pins — the sheet may be
|
|
1201
|
+
// animating up from below a stop that just grew
|
|
1202
|
+
val anchorTop = if (pendingDetentIndex >= 0) sheet.top else minOf(sheet.top, detentCalculator.getLowestSheetTop())
|
|
1196
1203
|
val footerY = (sheetHeight - anchorTop - footerHeight - keyboardShift).toFloat()
|
|
1197
1204
|
|
|
1198
1205
|
// Clamp to prevent footer going above safe area
|
|
@@ -1566,41 +1573,6 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
1566
1573
|
// MARK: - RootView Touch Handling
|
|
1567
1574
|
// =============================================================================
|
|
1568
1575
|
|
|
1569
|
-
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
|
|
1570
|
-
val footer = containerView?.footerView
|
|
1571
|
-
val action = event.actionMasked
|
|
1572
|
-
|
|
1573
|
-
if (footer != null && footer.isShown) {
|
|
1574
|
-
if (action == MotionEvent.ACTION_DOWN) {
|
|
1575
|
-
val loc = ScreenUtils.getScreenLocation(footer)
|
|
1576
|
-
val x = event.rawX.toInt()
|
|
1577
|
-
val y = event.rawY.toInt()
|
|
1578
|
-
footerOwnsTouchStream = x >= loc[0] &&
|
|
1579
|
-
x <= loc[0] + footer.width &&
|
|
1580
|
-
y >= loc[1] &&
|
|
1581
|
-
y <= loc[1] + footer.height
|
|
1582
|
-
}
|
|
1583
|
-
|
|
1584
|
-
if (footerOwnsTouchStream) {
|
|
1585
|
-
val loc = ScreenUtils.getScreenLocation(footer)
|
|
1586
|
-
val localEvent = MotionEvent.obtain(event)
|
|
1587
|
-
localEvent.setLocation(event.rawX - loc[0], event.rawY - loc[1])
|
|
1588
|
-
val handled = footer.dispatchTouchEvent(localEvent)
|
|
1589
|
-
localEvent.recycle()
|
|
1590
|
-
|
|
1591
|
-
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
|
|
1592
|
-
footerOwnsTouchStream = false
|
|
1593
|
-
}
|
|
1594
|
-
if (handled) return true
|
|
1595
|
-
}
|
|
1596
|
-
}
|
|
1597
|
-
|
|
1598
|
-
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
|
|
1599
|
-
footerOwnsTouchStream = false
|
|
1600
|
-
}
|
|
1601
|
-
return super.dispatchTouchEvent(event)
|
|
1602
|
-
}
|
|
1603
|
-
|
|
1604
1576
|
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
|
|
1605
1577
|
eventDispatcher?.let {
|
|
1606
1578
|
if (touchDeduper.shouldDispatch(event)) {
|
|
@@ -250,7 +250,7 @@ class TrueSheetCoordinatorLayout(context: Context) :
|
|
|
250
250
|
}
|
|
251
251
|
|
|
252
252
|
/**
|
|
253
|
-
* Called by descendant RootView
|
|
253
|
+
* Called by the descendant RootView (controller) when a child
|
|
254
254
|
* starts a native gesture — e.g. an RNGH handler activated or a scrollable began
|
|
255
255
|
* scrolling. Yields sheet interception for the rest of the touch stream.
|
|
256
256
|
*/
|
|
@@ -139,6 +139,9 @@ class TrueSheetDimView(private val reactContext: ThemedReactContext) :
|
|
|
139
139
|
|
|
140
140
|
override fun onTouchEvent(event: MotionEvent): Boolean {
|
|
141
141
|
if (blockGestures) {
|
|
142
|
+
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
|
|
143
|
+
parent?.requestDisallowInterceptTouchEvent(true)
|
|
144
|
+
}
|
|
142
145
|
// When dimmed, consume touch and trigger click on ACTION_UP
|
|
143
146
|
if (event.action == MotionEvent.ACTION_UP) {
|
|
144
147
|
performClick()
|
|
@@ -104,18 +104,6 @@ object ScreenUtils {
|
|
|
104
104
|
*/
|
|
105
105
|
fun getScreenHeight(reactContext: ReactContext): Int = reactContext.resources.displayMetrics.heightPixels
|
|
106
106
|
|
|
107
|
-
/**
|
|
108
|
-
* Get the location of a view in screen coordinates
|
|
109
|
-
*
|
|
110
|
-
* @param view The view to get screen location for
|
|
111
|
-
* @return IntArray with [x, y] coordinates in screen space
|
|
112
|
-
*/
|
|
113
|
-
fun getScreenLocation(view: View): IntArray {
|
|
114
|
-
val location = IntArray(2)
|
|
115
|
-
view.getLocationOnScreen(location)
|
|
116
|
-
return location
|
|
117
|
-
}
|
|
118
|
-
|
|
119
107
|
/**
|
|
120
108
|
* Returns true if the device is a phone in portrait orientation.
|
|
121
109
|
*/
|
|
@@ -155,6 +155,8 @@ using namespace facebook::react;
|
|
|
155
155
|
_lastHeight = height;
|
|
156
156
|
[self.delegate footerViewDidChangeSize:CGSizeMake(layoutMetrics.frame.size.width, height)];
|
|
157
157
|
}
|
|
158
|
+
|
|
159
|
+
[self applyKeyboardOffset];
|
|
158
160
|
}
|
|
159
161
|
|
|
160
162
|
- (void)prepareForRecycle {
|
|
@@ -184,6 +186,20 @@ using namespace facebook::react;
|
|
|
184
186
|
return controller.absoluteFooter && controller.footerAvoidsKeyboard;
|
|
185
187
|
}
|
|
186
188
|
|
|
189
|
+
- (CGFloat)keyboardSlideForHeight:(CGFloat)height {
|
|
190
|
+
UIWindow *window = self.window;
|
|
191
|
+
if (!window) {
|
|
192
|
+
return 0;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Measure in the transform's coordinate space, excluding the footer's current slide.
|
|
196
|
+
CGFloat footerBottom = self.center.y + self.bounds.size.height / 2;
|
|
197
|
+
CGPoint keyboardTopInWindow = CGPointMake(CGRectGetMidX(window.bounds), CGRectGetMaxY(window.bounds) - height);
|
|
198
|
+
CGFloat keyboardTop = [self.superview convertPoint:keyboardTopInWindow fromView:window].y;
|
|
199
|
+
CGFloat keyboardOffset = self.keyboardObserver.viewController.footerKeyboardOffset;
|
|
200
|
+
return MAX(0, footerBottom - keyboardTop + keyboardOffset);
|
|
201
|
+
}
|
|
202
|
+
|
|
187
203
|
// Yoga owns the footer's frame (pinned to the container's bottom edge), so the
|
|
188
204
|
// keyboard slide is carried by a transform instead of layout.
|
|
189
205
|
- (void)keyboardWillShow:(CGFloat)height duration:(NSTimeInterval)duration curve:(UIViewAnimationOptions)curve {
|
|
@@ -193,18 +209,19 @@ using namespace facebook::react;
|
|
|
193
209
|
|
|
194
210
|
[self setKeyboardVisible:YES];
|
|
195
211
|
|
|
196
|
-
CGFloat
|
|
197
|
-
CGFloat slide = MAX(0, height + keyboardOffset);
|
|
212
|
+
CGFloat slide = [self keyboardSlideForHeight:height];
|
|
198
213
|
_currentKeyboardOffset = slide;
|
|
199
214
|
|
|
200
215
|
[UIView animateWithDuration:duration
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
216
|
+
delay:0
|
|
217
|
+
options:curve | UIViewAnimationOptionBeginFromCurrentState
|
|
218
|
+
animations:^{
|
|
219
|
+
self.transform = CGAffineTransformMakeTranslation(0, -slide);
|
|
220
|
+
[self syncEdgeEffect];
|
|
221
|
+
}
|
|
222
|
+
completion:^(BOOL finished) {
|
|
223
|
+
[self applyKeyboardOffset];
|
|
224
|
+
}];
|
|
208
225
|
}
|
|
209
226
|
|
|
210
227
|
- (void)keyboardWillHide:(NSTimeInterval)duration curve:(UIViewAnimationOptions)curve {
|
|
@@ -252,8 +269,7 @@ using namespace facebook::react;
|
|
|
252
269
|
|
|
253
270
|
[self setKeyboardVisible:YES];
|
|
254
271
|
|
|
255
|
-
CGFloat
|
|
256
|
-
CGFloat slide = MAX(0, height + keyboardOffset);
|
|
272
|
+
CGFloat slide = [self keyboardSlideForHeight:height];
|
|
257
273
|
_currentKeyboardOffset = slide;
|
|
258
274
|
self.transform = CGAffineTransformMakeTranslation(0, -slide);
|
|
259
275
|
}
|
package/ios/TrueSheetView.mm
CHANGED