@onekeyfe/react-native-native-overlay 6.7.0-alpha.344 → 6.7.0-alpha.354
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/onekey/nativeoverlay/NativeOverlayAnimation.kt +5 -10
- package/android/src/main/java/com/onekey/nativeoverlay/NativeOverlayEntryRootView.kt +23 -2
- package/android/src/main/java/com/onekey/nativeoverlay/NativeOverlayHost.kt +6 -4
- package/android/src/main/java/com/onekey/nativeoverlay/NativeOverlayView.kt +3 -1
- package/android/src/test/java/com/onekey/nativeoverlay/NativeOverlayBackTest.kt +138 -0
- package/android/src/test/java/com/onekey/nativeoverlay/NativeOverlayMotionTest.kt +101 -0
- package/docs/SPEC.md +52 -11
- package/lib/module/web/useSheetDrag.js +19 -2
- package/lib/module/web/useSheetDrag.js.map +1 -1
- package/lib/typescript/src/web/useSheetDrag.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/web/useSheetDrag.ts +20 -2
|
@@ -69,8 +69,9 @@ internal sealed class OverlayMotion {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
|
-
* Analytic step response of `m·x'' + c·x' + k·x = 0`,
|
|
73
|
-
*
|
|
72
|
+
* Analytic step response of `m·x'' + c·x' + k·x = 0`, with overdamped
|
|
73
|
+
* responses capped at critical damping to match UIKit's sheet response.
|
|
74
|
+
* Driving one ValueAnimator with it
|
|
74
75
|
* keeps alpha, translation, scale and backdrop on the same clock; androidx
|
|
75
76
|
* SpringAnimation would need one animation per property.
|
|
76
77
|
*/
|
|
@@ -89,19 +90,13 @@ internal class SpringInterpolator(private val spring: OverlayMotion.Spring) : Ti
|
|
|
89
90
|
|
|
90
91
|
fun progressAt(spring: OverlayMotion.Spring, t: Double): Double {
|
|
91
92
|
val w0 = sqrt(spring.stiffness / spring.mass)
|
|
92
|
-
val zeta = spring.damping / (2 * sqrt(spring.stiffness * spring.mass))
|
|
93
|
+
val zeta = minOf(1.0, spring.damping / (2 * sqrt(spring.stiffness * spring.mass)))
|
|
93
94
|
return when {
|
|
94
95
|
zeta < 1 -> {
|
|
95
96
|
val wd = w0 * sqrt(1 - zeta * zeta)
|
|
96
97
|
1 - exp(-zeta * w0 * t) * (cos(wd * t) + (zeta * w0 / wd) * sin(wd * t))
|
|
97
98
|
}
|
|
98
|
-
|
|
99
|
-
else -> {
|
|
100
|
-
val root = sqrt(zeta * zeta - 1)
|
|
101
|
-
val r1 = -w0 * (zeta - root)
|
|
102
|
-
val r2 = -w0 * (zeta + root)
|
|
103
|
-
1 - (r2 * exp(r1 * t) - r1 * exp(r2 * t)) / (r2 - r1)
|
|
104
|
-
}
|
|
99
|
+
else -> 1 - exp(-w0 * t) * (1 + w0 * t)
|
|
105
100
|
}
|
|
106
101
|
}
|
|
107
102
|
|
|
@@ -60,7 +60,12 @@ internal class NativeOverlayEntryRootView(
|
|
|
60
60
|
* below), non-blocking ones let it continue past the empty area.
|
|
61
61
|
*/
|
|
62
62
|
override val pointerEvents: PointerEvents
|
|
63
|
-
get() =
|
|
63
|
+
get() = when {
|
|
64
|
+
blocking && isClosing -> PointerEvents.BOX_ONLY
|
|
65
|
+
isClosing -> PointerEvents.NONE
|
|
66
|
+
blocking && isShownForInput -> PointerEvents.AUTO
|
|
67
|
+
else -> PointerEvents.BOX_NONE
|
|
68
|
+
}
|
|
64
69
|
var stackOrder = 0
|
|
65
70
|
var levelOrder = 0
|
|
66
71
|
/** Page scope: the owning page, used by the page host to hide the entry. */
|
|
@@ -74,6 +79,19 @@ internal class NativeOverlayEntryRootView(
|
|
|
74
79
|
var dismissOnBackPress = true
|
|
75
80
|
var dismissOnBackdropPress = false
|
|
76
81
|
var isShownForInput = false
|
|
82
|
+
private var contentAccessibilityBeforeClose: Int? = null
|
|
83
|
+
var isClosing = false
|
|
84
|
+
set(value) {
|
|
85
|
+
if (field == value) return
|
|
86
|
+
field = value
|
|
87
|
+
if (value) {
|
|
88
|
+
contentAccessibilityBeforeClose = contentView.importantForAccessibility
|
|
89
|
+
contentView.importantForAccessibility = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
|
|
90
|
+
} else {
|
|
91
|
+
contentAccessibilityBeforeClose?.let { contentView.importantForAccessibility = it }
|
|
92
|
+
contentAccessibilityBeforeClose = null
|
|
93
|
+
}
|
|
94
|
+
}
|
|
77
95
|
var onRequestDismiss: ((String) -> Unit)? = null
|
|
78
96
|
|
|
79
97
|
val backdropView = View(reactContext).apply { alpha = 0f }
|
|
@@ -90,12 +108,13 @@ internal class NativeOverlayEntryRootView(
|
|
|
90
108
|
/** `sheet` presentation: the draggable surface; otherwise null. */
|
|
91
109
|
var sheetView: FrameLayout? = null
|
|
92
110
|
private set
|
|
111
|
+
private var sheetAnimationView: CoordinatorLayout? = null
|
|
93
112
|
private var sheetBehavior: BottomSheetBehavior<FrameLayout>? = null
|
|
94
113
|
private var handleView: View? = null
|
|
95
114
|
var onSheetHiddenByPan: (() -> Unit)? = null
|
|
96
115
|
|
|
97
116
|
/** The view that enter / exit animations move. */
|
|
98
|
-
val animatedView: View get() =
|
|
117
|
+
val animatedView: View get() = sheetAnimationView ?: contentView
|
|
99
118
|
|
|
100
119
|
private val touchDispatcher = JSTouchDispatcher(this)
|
|
101
120
|
private val pointerDispatcher = if (ReactFeatureFlags.dispatchPointerEvents) {
|
|
@@ -220,6 +239,7 @@ internal class NativeOverlayEntryRootView(
|
|
|
220
239
|
},
|
|
221
240
|
)
|
|
222
241
|
sheetView = sheet
|
|
242
|
+
sheetAnimationView = coordinator
|
|
223
243
|
sheetBehavior = behavior
|
|
224
244
|
handleView = handle
|
|
225
245
|
return sheet
|
|
@@ -350,6 +370,7 @@ internal class NativeOverlayEntryRootView(
|
|
|
350
370
|
}
|
|
351
371
|
|
|
352
372
|
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
|
|
373
|
+
if (isClosing) return blocking
|
|
353
374
|
if (!isShownForInput) return false
|
|
354
375
|
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
|
|
355
376
|
// Non-blocking overlays (toasts) only take touches that land on content.
|
|
@@ -50,7 +50,7 @@ internal class NativeOverlayHost private constructor(
|
|
|
50
50
|
private val backCallback = object : OnBackPressedCallback(false) {
|
|
51
51
|
override fun handleOnBackPressed() {
|
|
52
52
|
topBackEntry()?.let { entry ->
|
|
53
|
-
if (entry.dismissOnBackPress) entry.onRequestDismiss?.invoke("back")
|
|
53
|
+
if (!entry.isClosing && entry.dismissOnBackPress) entry.onRequestDismiss?.invoke("back")
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
}
|
|
@@ -68,7 +68,7 @@ internal class NativeOverlayHost private constructor(
|
|
|
68
68
|
*/
|
|
69
69
|
fun handleBackKey(event: KeyEvent): Boolean {
|
|
70
70
|
val entry = topBackEntry() ?: return false
|
|
71
|
-
if (event.action == KeyEvent.ACTION_UP && !event.isCanceled && entry.dismissOnBackPress) {
|
|
71
|
+
if (event.action == KeyEvent.ACTION_UP && !event.isCanceled && !entry.isClosing && entry.dismissOnBackPress) {
|
|
72
72
|
entry.onRequestDismiss?.invoke("back")
|
|
73
73
|
}
|
|
74
74
|
return true
|
|
@@ -135,10 +135,12 @@ internal class NativeOverlayHost private constructor(
|
|
|
135
135
|
|
|
136
136
|
/** Global overlays win; otherwise the topmost visible page overlay. */
|
|
137
137
|
private fun topBackEntry(): NativeOverlayEntryRootView? =
|
|
138
|
-
orderedEntries().lastOrNull {
|
|
138
|
+
orderedEntries().lastOrNull {
|
|
139
|
+
(it.blocking || it.dismissOnBackPress) && it.isShownForInput && (!it.isClosing || it.blocking)
|
|
140
|
+
}
|
|
139
141
|
?: shownPageHosts()
|
|
140
142
|
.flatMap { it.shownEntries() }
|
|
141
|
-
.lastOrNull { it.blocking || it.dismissOnBackPress }
|
|
143
|
+
.lastOrNull { (it.blocking || it.dismissOnBackPress) && (!it.isClosing || it.blocking) }
|
|
142
144
|
|
|
143
145
|
private fun shownPageHosts(): List<NativeOverlayPageHostView> =
|
|
144
146
|
NativeOverlayPageHostView.allHosts().filter {
|
|
@@ -200,6 +200,7 @@ class NativeOverlayView(
|
|
|
200
200
|
}
|
|
201
201
|
cancelAnimators()
|
|
202
202
|
phase = Phase.ENTERING
|
|
203
|
+
target.isClosing = false
|
|
203
204
|
target.isShownForInput = true
|
|
204
205
|
notifyHostEntriesChanged()
|
|
205
206
|
if (blocking) {
|
|
@@ -226,7 +227,7 @@ class NativeOverlayView(
|
|
|
226
227
|
val target = entry ?: return finishDismiss("programmatic")
|
|
227
228
|
cancelAnimators()
|
|
228
229
|
phase = Phase.EXITING
|
|
229
|
-
target.
|
|
230
|
+
target.isClosing = true
|
|
230
231
|
notifyHostEntriesChanged()
|
|
231
232
|
val transition = config.exit.reduceMotionAdjusted(isReduceMotionEnabled())
|
|
232
233
|
if (transition.kind == "none") return finishDismiss("programmatic")
|
|
@@ -241,6 +242,7 @@ class NativeOverlayView(
|
|
|
241
242
|
phase = Phase.HIDDEN
|
|
242
243
|
entry?.let { target ->
|
|
243
244
|
target.isShownForInput = false
|
|
245
|
+
target.isClosing = false
|
|
244
246
|
stageContent()
|
|
245
247
|
host?.detach(target)
|
|
246
248
|
pageHost?.detach(target)
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
package com.onekey.nativeoverlay
|
|
2
2
|
|
|
3
3
|
import android.view.KeyEvent
|
|
4
|
+
import android.view.MotionEvent
|
|
4
5
|
import android.view.View
|
|
5
6
|
import android.widget.FrameLayout
|
|
6
7
|
import androidx.activity.ComponentActivity
|
|
7
8
|
import com.facebook.react.bridge.BridgeReactContext
|
|
9
|
+
import com.facebook.react.uimanager.PointerEvents
|
|
8
10
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
11
|
+
import com.facebook.react.uimanager.TouchTargetHelper
|
|
12
|
+
import com.facebook.react.views.view.ReactViewGroup
|
|
9
13
|
import java.lang.ref.WeakReference
|
|
10
14
|
import java.util.WeakHashMap
|
|
11
15
|
import org.junit.Assert.assertEquals
|
|
@@ -124,6 +128,140 @@ class NativeOverlayBackTest {
|
|
|
124
128
|
pageHost.invalidateHost()
|
|
125
129
|
}
|
|
126
130
|
|
|
131
|
+
@Test
|
|
132
|
+
fun closingGlobalBlockerKeepsTouchBackAndAccessibilityOwnership() {
|
|
133
|
+
var pageTouches = 0
|
|
134
|
+
val page = View(activity).apply {
|
|
135
|
+
setOnTouchListener { _, _ ->
|
|
136
|
+
pageTouches += 1
|
|
137
|
+
true
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
activity.setContentView(page)
|
|
141
|
+
val lower = entry("lower", true, true)
|
|
142
|
+
val top = entry("top", true, true, 1)
|
|
143
|
+
host.attach(lower, NativeOverlayLevel.MODAL)
|
|
144
|
+
host.attach(top, NativeOverlayLevel.MODAL)
|
|
145
|
+
top.isClosing = true
|
|
146
|
+
host.onEntriesChanged()
|
|
147
|
+
|
|
148
|
+
assertEquals(PointerEvents.BOX_ONLY, top.pointerEvents)
|
|
149
|
+
assertEquals(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS, top.contentView.importantForAccessibility)
|
|
150
|
+
assertEquals(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS, page.importantForAccessibility)
|
|
151
|
+
assertEquals(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS, lower.importantForAccessibility)
|
|
152
|
+
assertTrue(back())
|
|
153
|
+
assertEquals(emptyList<String>(), dismissals)
|
|
154
|
+
|
|
155
|
+
val content = activity.findViewById<FrameLayout>(android.R.id.content)
|
|
156
|
+
val size = View.MeasureSpec.makeMeasureSpec(300, View.MeasureSpec.EXACTLY)
|
|
157
|
+
content.measure(size, size)
|
|
158
|
+
content.layout(0, 0, 300, 300)
|
|
159
|
+
val down = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 150f, 150f, 0)
|
|
160
|
+
try {
|
|
161
|
+
assertTrue(content.dispatchTouchEvent(down))
|
|
162
|
+
assertEquals(0, pageTouches)
|
|
163
|
+
} finally {
|
|
164
|
+
down.recycle()
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
top.isClosing = false
|
|
168
|
+
host.onEntriesChanged()
|
|
169
|
+
assertEquals(PointerEvents.AUTO, top.pointerEvents)
|
|
170
|
+
assertEquals(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO, top.contentView.importantForAccessibility)
|
|
171
|
+
assertTrue(back())
|
|
172
|
+
assertEquals(listOf("top:back"), dismissals)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
@Test
|
|
176
|
+
fun closingPageBlockerStillTakesBack() {
|
|
177
|
+
val pageHost = NativeOverlayPageHostView(context).apply { hostKey = "closing-page" }
|
|
178
|
+
activity.setContentView(pageHost)
|
|
179
|
+
val top = entry("page", true, true)
|
|
180
|
+
pageHost.attach(top)
|
|
181
|
+
top.isClosing = true
|
|
182
|
+
host.onEntriesChanged()
|
|
183
|
+
|
|
184
|
+
assertEquals(PointerEvents.BOX_ONLY, top.pointerEvents)
|
|
185
|
+
assertTrue(back())
|
|
186
|
+
assertEquals(emptyList<String>(), dismissals)
|
|
187
|
+
top.isClosing = false
|
|
188
|
+
host.onEntriesChanged()
|
|
189
|
+
assertEquals(PointerEvents.AUTO, top.pointerEvents)
|
|
190
|
+
assertTrue(back())
|
|
191
|
+
assertEquals(listOf("page:back"), dismissals)
|
|
192
|
+
pageHost.invalidateHost()
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
@Test
|
|
196
|
+
fun pageEntryHitTestingKeepsClosingContentAndLowerPageSeparate() {
|
|
197
|
+
val root = ReactViewGroup(context).apply { id = 101 }
|
|
198
|
+
val below = ReactViewGroup(context).apply { id = 102 }
|
|
199
|
+
val child = ReactViewGroup(context).apply { id = 103 }
|
|
200
|
+
val pageHost = NativeOverlayPageHostView(context).apply { hostKey = "page-hit-test" }
|
|
201
|
+
root.addView(below)
|
|
202
|
+
root.addView(pageHost)
|
|
203
|
+
activity.setContentView(root)
|
|
204
|
+
val overlay = entry("page", true, true)
|
|
205
|
+
overlay.contentView.addView(child)
|
|
206
|
+
pageHost.attach(overlay)
|
|
207
|
+
|
|
208
|
+
val size = View.MeasureSpec.makeMeasureSpec(300, View.MeasureSpec.EXACTLY)
|
|
209
|
+
root.measure(size, size)
|
|
210
|
+
root.layout(0, 0, 300, 300)
|
|
211
|
+
below.layout(0, 0, 300, 300)
|
|
212
|
+
pageHost.layout(0, 0, 300, 300)
|
|
213
|
+
child.layout(0, 0, 300, 300)
|
|
214
|
+
|
|
215
|
+
fun target() = TouchTargetHelper.findTargetTagForTouch(150f, 150f, root)
|
|
216
|
+
assertEquals(child.id, target())
|
|
217
|
+
overlay.isClosing = true
|
|
218
|
+
assertEquals(root.id, target())
|
|
219
|
+
overlay.updateBlocking(false)
|
|
220
|
+
assertEquals(below.id, target())
|
|
221
|
+
overlay.updateBlocking(true)
|
|
222
|
+
overlay.isClosing = false
|
|
223
|
+
assertEquals(child.id, target())
|
|
224
|
+
pageHost.invalidateHost()
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
@Test
|
|
228
|
+
fun reopeningCoveredClosingEntryRestoresItsContentAccessibility() {
|
|
229
|
+
activity.setContentView(View(activity))
|
|
230
|
+
val first = entry("first", true, true)
|
|
231
|
+
val second = entry("second", true, true)
|
|
232
|
+
host.attach(first, NativeOverlayLevel.MODAL)
|
|
233
|
+
first.isClosing = true
|
|
234
|
+
host.onEntriesChanged()
|
|
235
|
+
host.attach(second, NativeOverlayLevel.SECURE)
|
|
236
|
+
|
|
237
|
+
first.isClosing = false
|
|
238
|
+
host.onEntriesChanged()
|
|
239
|
+
assertEquals(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS, first.importantForAccessibility)
|
|
240
|
+
host.detach(second)
|
|
241
|
+
assertEquals(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO, first.importantForAccessibility)
|
|
242
|
+
assertEquals(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO, first.contentView.importantForAccessibility)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
@Test
|
|
246
|
+
fun closingNonBlockingEntryPassesTouchAndBackToLowerBlocker() {
|
|
247
|
+
val lower = entry("lower", true, true)
|
|
248
|
+
val toast = entry("toast", false, true)
|
|
249
|
+
host.attach(lower, NativeOverlayLevel.MODAL)
|
|
250
|
+
host.attach(toast, NativeOverlayLevel.TOAST)
|
|
251
|
+
toast.isClosing = true
|
|
252
|
+
host.onEntriesChanged()
|
|
253
|
+
|
|
254
|
+
assertEquals(PointerEvents.NONE, toast.pointerEvents)
|
|
255
|
+
val down = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 150f, 150f, 0)
|
|
256
|
+
try {
|
|
257
|
+
assertFalse(toast.dispatchTouchEvent(down))
|
|
258
|
+
} finally {
|
|
259
|
+
down.recycle()
|
|
260
|
+
}
|
|
261
|
+
assertTrue(back())
|
|
262
|
+
assertEquals(listOf("lower:back"), dismissals)
|
|
263
|
+
}
|
|
264
|
+
|
|
127
265
|
@Test
|
|
128
266
|
fun hostCacheReusesLiveHostAndSeparatesActivities() {
|
|
129
267
|
assertSame(host, NativeOverlayHost.of(activity))
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
package com.onekey.nativeoverlay
|
|
2
|
+
|
|
3
|
+
import android.graphics.Color
|
|
4
|
+
import android.os.Looper
|
|
5
|
+
import android.view.View
|
|
6
|
+
import androidx.activity.ComponentActivity
|
|
7
|
+
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
|
8
|
+
import com.facebook.react.bridge.BridgeReactContext
|
|
9
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
10
|
+
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
|
11
|
+
import org.junit.Assert.assertEquals
|
|
12
|
+
import org.junit.Assert.assertFalse
|
|
13
|
+
import org.junit.Assert.assertNotSame
|
|
14
|
+
import org.junit.Assert.assertSame
|
|
15
|
+
import org.junit.Assert.assertTrue
|
|
16
|
+
import org.junit.Test
|
|
17
|
+
import org.junit.runner.RunWith
|
|
18
|
+
import org.robolectric.Robolectric
|
|
19
|
+
import org.robolectric.RobolectricTestRunner
|
|
20
|
+
import org.robolectric.Shadows
|
|
21
|
+
import org.robolectric.annotation.Config
|
|
22
|
+
import java.time.Duration
|
|
23
|
+
|
|
24
|
+
@RunWith(RobolectricTestRunner::class)
|
|
25
|
+
@Config(sdk = [34])
|
|
26
|
+
class NativeOverlayMotionTest {
|
|
27
|
+
@Test
|
|
28
|
+
fun sheetAnimationMovesCoordinatorWithoutTakingMaterialsSheetTranslation() {
|
|
29
|
+
val activity = Robolectric.buildActivity(ComponentActivity::class.java).setup().get()
|
|
30
|
+
val reactContext = BridgeReactContext(activity)
|
|
31
|
+
reactContext.onHostResume(activity)
|
|
32
|
+
val context = ThemedReactContext(reactContext, activity, "OverlayMotionTest", 1)
|
|
33
|
+
val entry = NativeOverlayEntryRootView(context)
|
|
34
|
+
assertSame(entry.contentView, entry.animatedView)
|
|
35
|
+
|
|
36
|
+
entry.configureSheet(500, 16f, Color.WHITE, showHandle = true, draggable = true)
|
|
37
|
+
val sheet = entry.sheetView!!
|
|
38
|
+
val animated = entry.animatedView
|
|
39
|
+
assertTrue(animated is CoordinatorLayout)
|
|
40
|
+
assertSame(animated, sheet.parent)
|
|
41
|
+
assertNotSame(sheet, animated)
|
|
42
|
+
assertTrue((sheet.layoutParams as CoordinatorLayout.LayoutParams).behavior is BottomSheetBehavior<*>)
|
|
43
|
+
|
|
44
|
+
animated.translationY = 42f
|
|
45
|
+
assertEquals(0f, sheet.translationY)
|
|
46
|
+
sheet.translationY = 7f
|
|
47
|
+
assertEquals(42f, animated.translationY)
|
|
48
|
+
assertEquals(7f, sheet.translationY)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@Test
|
|
52
|
+
fun quickMatchesMeasuredCriticalResponseWithoutChangingUnderdampedResponse() {
|
|
53
|
+
val quick = OverlayMotion.QUICK
|
|
54
|
+
assertEquals(292L, quick.durationMs())
|
|
55
|
+
assertEquals(0.8238140348, SpringInterpolator.progressAt(quick, 0.1), 0.000001)
|
|
56
|
+
assertEquals(0.9990003945, SpringInterpolator.progressAt(quick, 0.292), 0.000001)
|
|
57
|
+
|
|
58
|
+
val underdamped = OverlayMotion.Spring(1.0, 100.0, 5.0)
|
|
59
|
+
assertEquals(0.3929451508, SpringInterpolator.progressAt(underdamped, 0.1), 0.000001)
|
|
60
|
+
val timing = OverlayMotion.Timing(250L, 0.25f, 0.1f, 0.25f, 1f)
|
|
61
|
+
assertEquals(250L, timing.durationMs())
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@Test
|
|
65
|
+
fun reopeningTheSameEntryDuringExitRetargetsItsAnimation() {
|
|
66
|
+
val activity = Robolectric.buildActivity(ComponentActivity::class.java).setup().visible().get()
|
|
67
|
+
val reactContext = BridgeReactContext(activity)
|
|
68
|
+
reactContext.onHostResume(activity)
|
|
69
|
+
val context = ThemedReactContext(reactContext, activity, "OverlayMotionTest", 1)
|
|
70
|
+
val overlay = NativeOverlayView(context).apply {
|
|
71
|
+
presentation = "sheet"
|
|
72
|
+
sheetHeight = 200.0
|
|
73
|
+
addReactChild(View(context))
|
|
74
|
+
}
|
|
75
|
+
activity.setContentView(overlay)
|
|
76
|
+
var dismissals = 0
|
|
77
|
+
overlay.onDismissed = { dismissals++ }
|
|
78
|
+
overlay.visible = true
|
|
79
|
+
overlay.commitConfiguration()
|
|
80
|
+
|
|
81
|
+
val entryField = NativeOverlayView::class.java.getDeclaredField("entry").apply { isAccessible = true }
|
|
82
|
+
val original = entryField.get(overlay) as NativeOverlayEntryRootView
|
|
83
|
+
overlay.visible = false
|
|
84
|
+
overlay.commitConfiguration()
|
|
85
|
+
assertTrue(original.isClosing)
|
|
86
|
+
|
|
87
|
+
overlay.visible = true
|
|
88
|
+
overlay.commitConfiguration()
|
|
89
|
+
assertSame(original, entryField.get(overlay))
|
|
90
|
+
assertTrue(original.isShownForInput)
|
|
91
|
+
assertFalse(original.isClosing)
|
|
92
|
+
assertEquals(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO, original.contentView.importantForAccessibility)
|
|
93
|
+
Shadows.shadowOf(Looper.getMainLooper()).idleFor(Duration.ofMillis(350))
|
|
94
|
+
assertEquals(0, dismissals)
|
|
95
|
+
|
|
96
|
+
overlay.visible = false
|
|
97
|
+
overlay.commitConfiguration()
|
|
98
|
+
Shadows.shadowOf(Looper.getMainLooper()).idleFor(Duration.ofMillis(350))
|
|
99
|
+
assertEquals(1, dismissals)
|
|
100
|
+
}
|
|
101
|
+
}
|
package/docs/SPEC.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# react-native-native-overlay SPEC
|
|
2
2
|
|
|
3
3
|
Status: Implemented through the P5 caller migration in app-monorepo. Android
|
|
4
|
-
and Web runtime checks passed there; iOS
|
|
5
|
-
|
|
4
|
+
and Web runtime checks passed there; focused iOS 26.5 simulator and Android 16
|
|
5
|
+
emulator checks are recorded below. Broader iOS runtime, physical-device and
|
|
6
|
+
iPad acceptance remain unverified. Packaging in app-modules is validated
|
|
7
|
+
separately.
|
|
6
8
|
|
|
7
9
|
The implementation is migrated from app-monorepo commit
|
|
8
10
|
`376633bd9f1c410dbccb01fb6a0492be9a5c3f38`, package
|
|
@@ -39,13 +41,15 @@ attribution in source comments.
|
|
|
39
41
|
|
|
40
42
|
### Release boundary
|
|
41
43
|
|
|
42
|
-
The earlier `3.0.162-alpha.272` release remains immutable. This branch
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
The earlier `3.0.162-alpha.272` release remains immutable. This branch is
|
|
45
|
+
prepared at `6.7.0-9`: the repository's release validator requires all 43
|
|
46
|
+
publishable workspace manifests and exact internal pins to use the same
|
|
47
|
+
version. Publish only `@onekeyfe/react-native-native-overlay` through the
|
|
48
|
+
manual `package-publish` workflow with `npm_dist_tag=latest` and
|
|
49
|
+
`only_workspace=@onekeyfe/react-native-native-overlay`; verify that exact
|
|
50
|
+
registry tarball before the App pins it and refreshes its dependency and native
|
|
51
|
+
locks. The other workspace version changes are release metadata, not a request
|
|
52
|
+
to publish their packages in this run. Leave the source PR open for review.
|
|
49
53
|
|
|
50
54
|
## 5.1 Purpose, scope, and non-goals
|
|
51
55
|
|
|
@@ -168,8 +172,20 @@ visible)`, `removePage(ownerKey)`.
|
|
|
168
172
|
- `motion` is a preset name or a concrete `{ type: 'spring', spring: { mass, stiffness, damping, overshootClamping } }`
|
|
169
173
|
or `{ type: 'timing', timing: { durationMs, easing: cubicBezier } }`.
|
|
170
174
|
- Presets are resolved per platform:
|
|
171
|
-
- Native
|
|
172
|
-
|
|
175
|
+
- Native `quick` supplies spring m 0.1, k 100, c 20. The iOS sheet's
|
|
176
|
+
measured position and dimming response use the critically damped curve
|
|
177
|
+
at angular frequency `sqrt(k/m)`; UIKit reports an animator duration near
|
|
178
|
+
292 ms. Android caps an overdamped spring's effective damping ratio at 1
|
|
179
|
+
while preserving m and k; underdamped and timing motions retain their
|
|
180
|
+
existing response. This rule
|
|
181
|
+
also applies to custom overdamped springs as a platform compatibility
|
|
182
|
+
inference; only the default `quick` sheet path has been measured on iOS.
|
|
183
|
+
Android's implementation is covered by native tests. In the consumer
|
|
184
|
+
shells, the default `quick` Dialog and ActionList sheet enter/exit motion
|
|
185
|
+
and dimming were compared over three cycles per direction on Android 16
|
|
186
|
+
and iOS 26.5; their normalized visible curves met the recorded parity
|
|
187
|
+
tolerance. This does not verify custom springs, exact cross-device
|
|
188
|
+
rectangles, or callback timing.
|
|
173
189
|
- Web mirrors the CSS driver: `quick` is 150 ms `cubic-bezier(.25,.1,.25,1)`.
|
|
174
190
|
- Converting native springs for web is opt-in (`springToCssLinear`), because
|
|
175
191
|
it would slow web overlays down 4–9×.
|
|
@@ -183,6 +199,13 @@ visible)`, `removePage(ownerKey)`.
|
|
|
183
199
|
| fullscreen | fade, `quick` | none |
|
|
184
200
|
| anchored | scale 0.95 + fade from the resolved anchor placement, `popoverQuick` | fade |
|
|
185
201
|
|
|
202
|
+
- **Android sheet transform ownership (Implemented; Android 16 consumer-shell runtime verified):**
|
|
203
|
+
the overlay's enter/exit transform belongs to the sheet's CoordinatorLayout
|
|
204
|
+
parent. Material's IME insets callback owns the child sheet's `translationY`,
|
|
205
|
+
and the keyboard layer owns the IME avoidance lift. These transforms compose
|
|
206
|
+
while the child sheet remains the BottomSheetBehavior drag target. The
|
|
207
|
+
overlay must not animate the child sheet's `translationY` during IME motion.
|
|
208
|
+
|
|
186
209
|
- Special cases the callers set explicitly:
|
|
187
210
|
- App lock: `enter: none`, `exit: fade lockFade`. The web tamper check reloads
|
|
188
211
|
the page if the lock fades in from opacity 0.
|
|
@@ -216,6 +239,22 @@ request ─► queued ─► active ─► (enter anim) presented
|
|
|
216
239
|
its current value. It does not restart.
|
|
217
240
|
- `onRemoved` fires exactly once per entry, even when a finalize and the
|
|
218
241
|
timeout race.
|
|
242
|
+
- **Android exit ownership (Implemented; blocking page/global touch and global
|
|
243
|
+
Back runtime verified on Android 16; accessibility native-test verified,
|
|
244
|
+
TalkBack device verification pending):** A
|
|
245
|
+
blocking entry keeps ownership of touch, Back, and accessibility isolation
|
|
246
|
+
until its exit animation completes and the native host detaches it. During
|
|
247
|
+
exit, the entry consumes touches and Back without forwarding them to its
|
|
248
|
+
closing React content or requesting a
|
|
249
|
+
second dismissal. Its content is hidden from TalkBack while lower content
|
|
250
|
+
remains isolated. A reopen during exit restores content input and
|
|
251
|
+
accessibility without briefly exposing the page below. Closing non-blocking
|
|
252
|
+
entries pass through touch and Back to the entry below.
|
|
253
|
+
Consumer-shell recordings verify that page and global blocking entries keep
|
|
254
|
+
lower touch targets inert during their visible exit, then release them, and
|
|
255
|
+
that Back does not navigate beneath a closing global entry. Native tests
|
|
256
|
+
cover closing non-blocking entries and same-entry reopen; those paths and
|
|
257
|
+
TalkBack reading during exit have not been verified on device.
|
|
219
258
|
- Page entries:
|
|
220
259
|
- They are suspended (hidden but kept) while the owner page is covered or
|
|
221
260
|
detached.
|
|
@@ -460,6 +499,8 @@ P2 sheet notes:
|
|
|
460
499
|
flick dismisses, never from scrolled content). Reopening kept content after
|
|
461
500
|
a pan dismissal clears the sheet transform, transition and backdrop opacity;
|
|
462
501
|
the next dismissal follows the normal exit path and restores focus.
|
|
502
|
+
Cancelling a tracked pointer resets its drag offset, transition and backdrop
|
|
503
|
+
without dismissing the sheet or swallowing a later click.
|
|
463
504
|
- A fitted sheet measures its content with `onLayout` before presenting.
|
|
464
505
|
Hidden content stays mounted inside the zero-width host (clipped on iOS,
|
|
465
506
|
INVISIBLE on Android), and the host height stays auto: a fixed 0 height
|
|
@@ -111,10 +111,27 @@ export function useSheetDrag({
|
|
|
111
111
|
once: true
|
|
112
112
|
});
|
|
113
113
|
};
|
|
114
|
+
const onPointerCancel = event => {
|
|
115
|
+
if (!tracking || event.pointerId !== pointerId) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
tracking = false;
|
|
119
|
+
dragging = false;
|
|
120
|
+
velocity = 0;
|
|
121
|
+
if (sheet.hasPointerCapture?.(pointerId)) {
|
|
122
|
+
sheet.releasePointerCapture(pointerId);
|
|
123
|
+
}
|
|
124
|
+
pointerId = -1;
|
|
125
|
+
sheet.style.transform = '';
|
|
126
|
+
sheet.style.transition = '';
|
|
127
|
+
if (backdropRef.current) {
|
|
128
|
+
backdropRef.current.style.opacity = '1';
|
|
129
|
+
}
|
|
130
|
+
};
|
|
114
131
|
sheet.addEventListener('pointerdown', onPointerDown);
|
|
115
132
|
sheet.addEventListener('pointermove', onPointerMove);
|
|
116
133
|
sheet.addEventListener('pointerup', onPointerUp);
|
|
117
|
-
sheet.addEventListener('pointercancel',
|
|
134
|
+
sheet.addEventListener('pointercancel', onPointerCancel);
|
|
118
135
|
return () => {
|
|
119
136
|
if (sheet.hasPointerCapture?.(pointerId)) {
|
|
120
137
|
sheet.releasePointerCapture(pointerId);
|
|
@@ -122,7 +139,7 @@ export function useSheetDrag({
|
|
|
122
139
|
sheet.removeEventListener('pointerdown', onPointerDown);
|
|
123
140
|
sheet.removeEventListener('pointermove', onPointerMove);
|
|
124
141
|
sheet.removeEventListener('pointerup', onPointerUp);
|
|
125
|
-
sheet.removeEventListener('pointercancel',
|
|
142
|
+
sheet.removeEventListener('pointercancel', onPointerCancel);
|
|
126
143
|
};
|
|
127
144
|
}, [sheetRef, backdropRef, enabled]);
|
|
128
145
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useEffect","useRef","DRAG_START_THRESHOLD","DISMISS_DISTANCE_RATIO","DISMISS_VELOCITY","UPWARD_RESISTANCE","SETTLE_TRANSITION","scrolledAncestorWithin","target","sheet","node","HTMLElement","scrollTop","scrollHeight","clientHeight","parentElement","undefined","useSheetDrag","sheetRef","backdropRef","enabled","onDismissByPan","onDismissRef","current","startY","lastY","lastTime","velocity","tracking","dragging","pointerId","setOffset","offset","style","transform","backdrop","opacity","String","Math","max","offsetHeight","onPointerDown","event","button","clientY","timeStamp","onPointerMove","dy","setPointerCapture","transition","dt","onPointerUp","height","addEventListener","clickEvent","stopPropagation","preventDefault","capture","once","hasPointerCapture","releasePointerCapture","removeEventListener"],"sourceRoot":"../../../src","sources":["web/useSheetDrag.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"names":["useEffect","useRef","DRAG_START_THRESHOLD","DISMISS_DISTANCE_RATIO","DISMISS_VELOCITY","UPWARD_RESISTANCE","SETTLE_TRANSITION","scrolledAncestorWithin","target","sheet","node","HTMLElement","scrollTop","scrollHeight","clientHeight","parentElement","undefined","useSheetDrag","sheetRef","backdropRef","enabled","onDismissByPan","onDismissRef","current","startY","lastY","lastTime","velocity","tracking","dragging","pointerId","setOffset","offset","style","transform","backdrop","opacity","String","Math","max","offsetHeight","onPointerDown","event","button","clientY","timeStamp","onPointerMove","dy","setPointerCapture","transition","dt","onPointerUp","height","addEventListener","clickEvent","stopPropagation","preventDefault","capture","once","onPointerCancel","hasPointerCapture","releasePointerCapture","removeEventListener"],"sourceRoot":"../../../src","sources":["web/useSheetDrag.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSheetDrag.d.ts","sourceRoot":"","sources":["../../../../src/web/useSheetDrag.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAsBvC;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,WAAW,EACX,OAAO,EACP,cAAc,GACf,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC3C,WAAW,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,IAAI,CAAC;CAC5B,
|
|
1
|
+
{"version":3,"file":"useSheetDrag.d.ts","sourceRoot":"","sources":["../../../../src/web/useSheetDrag.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAsBvC;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,WAAW,EACX,OAAO,EACP,cAAc,GACf,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC3C,WAAW,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,IAAI,CAAC;CAC5B,QA6HA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/react-native-native-overlay",
|
|
3
|
-
"version": "6.7.0-alpha.
|
|
3
|
+
"version": "6.7.0-alpha.354",
|
|
4
4
|
"description": "Native and Web overlay hosts with ordered levels, page scope and Fabric measurement",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
package/src/web/useSheetDrag.ts
CHANGED
|
@@ -129,10 +129,28 @@ export function useSheetDrag({
|
|
|
129
129
|
);
|
|
130
130
|
};
|
|
131
131
|
|
|
132
|
+
const onPointerCancel = (event: PointerEvent) => {
|
|
133
|
+
if (!tracking || event.pointerId !== pointerId) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
tracking = false;
|
|
137
|
+
dragging = false;
|
|
138
|
+
velocity = 0;
|
|
139
|
+
if (sheet.hasPointerCapture?.(pointerId)) {
|
|
140
|
+
sheet.releasePointerCapture(pointerId);
|
|
141
|
+
}
|
|
142
|
+
pointerId = -1;
|
|
143
|
+
sheet.style.transform = '';
|
|
144
|
+
sheet.style.transition = '';
|
|
145
|
+
if (backdropRef.current) {
|
|
146
|
+
backdropRef.current.style.opacity = '1';
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
132
150
|
sheet.addEventListener('pointerdown', onPointerDown);
|
|
133
151
|
sheet.addEventListener('pointermove', onPointerMove);
|
|
134
152
|
sheet.addEventListener('pointerup', onPointerUp);
|
|
135
|
-
sheet.addEventListener('pointercancel',
|
|
153
|
+
sheet.addEventListener('pointercancel', onPointerCancel);
|
|
136
154
|
return () => {
|
|
137
155
|
if (sheet.hasPointerCapture?.(pointerId)) {
|
|
138
156
|
sheet.releasePointerCapture(pointerId);
|
|
@@ -140,7 +158,7 @@ export function useSheetDrag({
|
|
|
140
158
|
sheet.removeEventListener('pointerdown', onPointerDown);
|
|
141
159
|
sheet.removeEventListener('pointermove', onPointerMove);
|
|
142
160
|
sheet.removeEventListener('pointerup', onPointerUp);
|
|
143
|
-
sheet.removeEventListener('pointercancel',
|
|
161
|
+
sheet.removeEventListener('pointercancel', onPointerCancel);
|
|
144
162
|
};
|
|
145
163
|
}, [sheetRef, backdropRef, enabled]);
|
|
146
164
|
}
|