@craft-native/android 0.0.220 → 0.0.222
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/package.json
CHANGED
|
@@ -894,6 +894,7 @@ internal class CraftNativeChrome(context: Context, private val tabs: List<CraftN
|
|
|
894
894
|
accessory.background = GradientDrawable().apply { setColor(surface); cornerRadius = dp(32).toFloat() }
|
|
895
895
|
accessorySpec?.let { accessoryIcon.setImageDrawable(CraftNativeIcons.drawable(context, null, it.optString("symbol"), text)) }
|
|
896
896
|
tabViews.forEachIndexed { index, (icon, label) ->
|
|
897
|
+
tabBar.getChildAt(index).isSelected = index == selectedTab
|
|
897
898
|
val color = if (index == selectedTab) accent else muted
|
|
898
899
|
val number = tabIconText[tabs[index].id]
|
|
899
900
|
icon.setTextColor(if (number != null) Color.parseColor("#FF2D55") else color)
|
|
@@ -3780,6 +3780,8 @@ class MainActivity : AppCompatActivity() {
|
|
|
3780
3780
|
private var tabSwipeTarget: Screen? = null
|
|
3781
3781
|
private var tabSwipeTargetIndex = -1
|
|
3782
3782
|
private var tabSwipeDirection = 0
|
|
3783
|
+
private var tabSwipeGeneration = 0
|
|
3784
|
+
private var tabSwipeSettling = false
|
|
3783
3785
|
/** The app script's isolate (`nativeApp`), when the app has one. */
|
|
3784
3786
|
private var appScreen: Screen? = null
|
|
3785
3787
|
private val urlSchemes = mutableSetOf<String>()
|
|
@@ -3960,6 +3962,7 @@ class MainActivity : AppCompatActivity() {
|
|
|
3960
3962
|
bars.onAccessory = { path -> navigateOpen(path) }
|
|
3961
3963
|
bars.onButton = { id -> visibleScreen?.takeIf { it.active }?.let { send(it, "NAV_BUTTON", JSONObject().put("id", id)) } }
|
|
3962
3964
|
bars.onTab = { index ->
|
|
3965
|
+
interruptTabSwipe()
|
|
3963
3966
|
haptic()
|
|
3964
3967
|
if (index == currentTab) popToRoot() else selectTab(index)
|
|
3965
3968
|
}
|
|
@@ -3996,6 +3999,7 @@ class MainActivity : AppCompatActivity() {
|
|
|
3996
3999
|
/** A tab chosen: its stack shows, its root screen opened the first time. */
|
|
3997
4000
|
private fun selectTab(index: Int) {
|
|
3998
4001
|
if (index !in tabStacks.indices) return
|
|
4002
|
+
interruptTabSwipe()
|
|
3999
4003
|
currentTab = index
|
|
4000
4004
|
screens = tabStacks[index]
|
|
4001
4005
|
chrome?.selectTab(index)
|
|
@@ -4017,6 +4021,7 @@ class MainActivity : AppCompatActivity() {
|
|
|
4017
4021
|
|
|
4018
4022
|
/** Start an interactive horizontal transition to the adjacent tab. */
|
|
4019
4023
|
private fun beginTabSwipe(dx: Float, x: Float, y: Float): Boolean {
|
|
4024
|
+
if (tabSwipeSettling) interruptTabSwipe()
|
|
4020
4025
|
if (tabSwipeTarget != null || screens.size != 1 || chrome?.tabSwipeEnabled != true) return false
|
|
4021
4026
|
val direction = if (dx < 0) 1 else -1
|
|
4022
4027
|
val targetIndex = currentTab + direction
|
|
@@ -4055,16 +4060,23 @@ class MainActivity : AppCompatActivity() {
|
|
|
4055
4060
|
val host = chrome?.content ?: return
|
|
4056
4061
|
val width = host.width.toFloat().coerceAtLeast(1f)
|
|
4057
4062
|
val complete = !cancelled && kotlin.math.abs(dx) >= width * 0.28f
|
|
4063
|
+
val generation = ++tabSwipeGeneration
|
|
4064
|
+
val targetIndex = tabSwipeTargetIndex
|
|
4065
|
+
tabSwipeSettling = true
|
|
4058
4066
|
val endOffset = if (complete) {
|
|
4059
4067
|
if (tabSwipeDirection > 0) -width else width
|
|
4060
4068
|
} else 0f
|
|
4061
4069
|
val targetOffset = if (complete) 0f else if (tabSwipeDirection > 0) width else -width
|
|
4062
4070
|
current.view.animate().translationX(endOffset).setDuration(180).start()
|
|
4063
4071
|
target.view.animate().translationX(targetOffset).setDuration(180).withEndAction {
|
|
4072
|
+
// A later tab tap or gesture owns the display even if Android
|
|
4073
|
+
// delivers this animator's completion after it was cancelled.
|
|
4074
|
+
if (generation != tabSwipeGeneration || tabSwipeTarget !== target || visibleScreen !== current) return@withEndAction
|
|
4064
4075
|
target.view.animate().setListener(null)
|
|
4076
|
+
tabSwipeSettling = false
|
|
4065
4077
|
if (complete) {
|
|
4066
4078
|
current.view.translationX = 0f
|
|
4067
|
-
currentTab =
|
|
4079
|
+
currentTab = targetIndex
|
|
4068
4080
|
screens = tabStacks[currentTab]
|
|
4069
4081
|
tabSwipeTarget = null
|
|
4070
4082
|
tabSwipeTargetIndex = -1
|
|
@@ -4082,6 +4094,24 @@ class MainActivity : AppCompatActivity() {
|
|
|
4082
4094
|
}.start()
|
|
4083
4095
|
}
|
|
4084
4096
|
|
|
4097
|
+
/** Restore the owning stack before a newer navigation action takes over. */
|
|
4098
|
+
private fun interruptTabSwipe() {
|
|
4099
|
+
val target = tabSwipeTarget ?: return
|
|
4100
|
+
++tabSwipeGeneration
|
|
4101
|
+
tabSwipeTarget = null
|
|
4102
|
+
tabSwipeTargetIndex = -1
|
|
4103
|
+
tabSwipeDirection = 0
|
|
4104
|
+
tabSwipeSettling = false
|
|
4105
|
+
val current = visibleScreen
|
|
4106
|
+
current?.view?.animate()?.withEndAction(null)?.setListener(null)?.cancel()
|
|
4107
|
+
target.view.animate().withEndAction(null).setListener(null).cancel()
|
|
4108
|
+
current?.view?.translationX = 0f
|
|
4109
|
+
target.view.translationX = 0f
|
|
4110
|
+
if (target !== current) (target.view.parent as? ViewGroup)?.removeView(target.view)
|
|
4111
|
+
chrome?.selectTab(currentTab)
|
|
4112
|
+
current?.let(::applyChrome)
|
|
4113
|
+
}
|
|
4114
|
+
|
|
4085
4115
|
/**
|
|
4086
4116
|
* Returns true when the exact screen gesture point is over a horizontal
|
|
4087
4117
|
* child that still has room in the gesture's direction. Screen coordinates
|
|
@@ -4172,6 +4202,7 @@ class MainActivity : AppCompatActivity() {
|
|
|
4172
4202
|
}
|
|
4173
4203
|
|
|
4174
4204
|
private fun openScreen(route: String?, params: JSONObject = JSONObject(), headless: Boolean = false, showImmediately: Boolean = true): Screen? {
|
|
4205
|
+
if (showImmediately && !headless) interruptTabSwipe()
|
|
4175
4206
|
val engine = sandbox ?: return null
|
|
4176
4207
|
val isolate = engine.createIsolate()
|
|
4177
4208
|
val view = CraftNativeFlexLayout(this).apply {
|
|
@@ -6943,6 +6974,7 @@ class MainActivity : AppCompatActivity() {
|
|
|
6943
6974
|
|
|
6944
6975
|
/** Back to the first screen in one move. */
|
|
6945
6976
|
private fun popToRoot() {
|
|
6977
|
+
interruptTabSwipe()
|
|
6946
6978
|
val stack = screens
|
|
6947
6979
|
val removed = mutableListOf<Screen>()
|
|
6948
6980
|
while (stack.size > 1) removed.add(stack.removeAt(stack.lastIndex))
|
|
@@ -6954,6 +6986,7 @@ class MainActivity : AppCompatActivity() {
|
|
|
6954
6986
|
|
|
6955
6987
|
/** Back: the screen below in this tab, then the first tab, then out of the app. */
|
|
6956
6988
|
private fun back() {
|
|
6989
|
+
interruptTabSwipe()
|
|
6957
6990
|
// A previous back is still draining its screen's teardown messages.
|
|
6958
6991
|
if (visibleScreen == null) return
|
|
6959
6992
|
if (screens.size > 1) {
|
|
@@ -7281,6 +7314,7 @@ class MainActivity : AppCompatActivity() {
|
|
|
7281
7314
|
}
|
|
7282
7315
|
|
|
7283
7316
|
override fun onDestroy() {
|
|
7317
|
+
interruptTabSwipe()
|
|
7284
7318
|
if (animationScaleObserverRegistered) contentResolver.unregisterContentObserver(animationScaleObserver)
|
|
7285
7319
|
CraftNativeBackground.foreground = null
|
|
7286
7320
|
backgroundWaiters.values.forEach { it(false) }
|