@momo-kits/native-kits 0.300.4-debug → 0.300.4
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 +1 -1
- package/build.gradle.kts +0 -13
- package/compose/build.gradle.kts +0 -197
- package/compose/build.gradle.kts.backup +0 -197
- package/compose/compose.podspec +0 -47
- package/compose/src/androidMain/kotlin/vn/momo/kits/const/HostFont.android.kt +0 -20
- package/compose/src/androidMain/kotlin/vn/momo/kits/navigation/ScrollToTop.android.kt +0 -6
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/BackGesture.android.kt +0 -12
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +0 -7
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +0 -153
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/ReservedRegions.android.kt +0 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +0 -110
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/DesignSystemKits.kt +0 -62
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +0 -1071
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +0 -269
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +0 -65
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +0 -157
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +0 -81
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +0 -32
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +0 -338
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +0 -175
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +0 -357
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +0 -115
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -89
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +0 -128
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +0 -209
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +0 -542
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +0 -49
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +0 -86
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +0 -125
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +0 -231
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +0 -189
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +0 -478
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +0 -114
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +0 -265
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +0 -235
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +0 -223
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +0 -265
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +0 -185
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +0 -343
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +0 -108
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +0 -56
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +0 -41
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +0 -84
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +0 -40
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +0 -361
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +0 -108
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +0 -308
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +0 -59
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +0 -87
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +0 -21
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +0 -90
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +0 -330
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +0 -220
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +0 -473
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +0 -122
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +0 -207
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +0 -92
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +0 -560
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +0 -86
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +0 -125
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +0 -207
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +0 -501
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +0 -176
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +0 -182
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +0 -193
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +0 -29
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +0 -236
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +0 -180
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +0 -325
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/HostFont.kt +0 -17
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +0 -12
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +0 -16
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +0 -194
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +0 -287
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +0 -54
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +0 -50
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/ScreenLayout.kt +0 -306
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +0 -41
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +0 -52
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +0 -66
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +0 -11
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +0 -104
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +0 -48
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +0 -51
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +0 -338
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/HostBackGestureBridge.kt +0 -58
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +0 -137
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +0 -116
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +0 -215
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +0 -404
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScrollToTop.kt +0 -8
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +0 -732
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackTransition.kt +0 -148
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/SwipeBackHaptic.kt +0 -40
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +0 -233
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +0 -217
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +0 -86
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoBarCompression.kt +0 -97
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoTabBar.kt +0 -377
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +0 -169
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +0 -455
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +0 -103
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderJourney.kt +0 -106
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderLocation.kt +0 -74
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +0 -413
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +0 -39
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +0 -363
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HelpCenterRequest.kt +0 -37
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SideBar.kt +0 -192
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +0 -133
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/ToolkitRequests.kt +0 -41
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +0 -135
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/BackGesture.kt +0 -12
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +0 -91
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +0 -9
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +0 -74
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ReservedRegions.kt +0 -20
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +0 -1329
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +0 -55
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +0 -15
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +0 -118
- package/compose/src/commonTest/kotlin/vn/momo/kits/navigation/component/HelpCenterRequestTest.kt +0 -44
- package/compose/src/commonTest/kotlin/vn/momo/kits/navigation/component/ToolkitRequestsTest.kt +0 -62
- package/compose/src/iosMain/kotlin/vn/momo/kits/const/HostFont.ios.kt +0 -42
- package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/HostBackGesture.ios.kt +0 -45
- package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +0 -36
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/BackGesture.ios.kt +0 -38
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +0 -66
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +0 -217
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/ReservedRegions.ios.kt +0 -138
- package/gradle/libs.versions.toml +0 -68
- package/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/gradle/wrapper/gradle-wrapper.properties +0 -8
- package/gradle.properties +0 -26
- package/gradlew +0 -252
- package/gradlew.bat +0 -94
- package/ios-demo/README.md +0 -120
- package/settings.gradle.kts +0 -64
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
package vn.momo.kits.navigation
|
|
2
|
-
|
|
3
|
-
import androidx.compose.animation.AnimatedContentTransitionScope
|
|
4
|
-
import androidx.compose.animation.AnimatedVisibilityScope
|
|
5
|
-
import androidx.compose.animation.EnterExitState
|
|
6
|
-
import androidx.compose.animation.EnterTransition
|
|
7
|
-
import androidx.compose.animation.ExitTransition
|
|
8
|
-
import androidx.compose.animation.core.LinearEasing
|
|
9
|
-
import androidx.compose.animation.core.animateFloat
|
|
10
|
-
import androidx.compose.animation.core.tween
|
|
11
|
-
import androidx.compose.animation.slideInHorizontally
|
|
12
|
-
import androidx.compose.animation.slideOutHorizontally
|
|
13
|
-
import androidx.compose.foundation.layout.Box
|
|
14
|
-
import androidx.compose.foundation.layout.fillMaxSize
|
|
15
|
-
import androidx.compose.runtime.Composable
|
|
16
|
-
import androidx.compose.runtime.DisposableEffect
|
|
17
|
-
import androidx.compose.runtime.Stable
|
|
18
|
-
import androidx.compose.runtime.derivedStateOf
|
|
19
|
-
import androidx.compose.runtime.getValue
|
|
20
|
-
import androidx.compose.runtime.mutableStateMapOf
|
|
21
|
-
import androidx.compose.runtime.remember
|
|
22
|
-
import androidx.compose.runtime.staticCompositionLocalOf
|
|
23
|
-
import androidx.compose.ui.Modifier
|
|
24
|
-
import androidx.compose.ui.draw.drawBehind
|
|
25
|
-
import androidx.compose.ui.geometry.Offset
|
|
26
|
-
import androidx.compose.ui.geometry.Size
|
|
27
|
-
import androidx.compose.ui.graphics.Brush
|
|
28
|
-
import androidx.compose.ui.graphics.Color
|
|
29
|
-
import androidx.compose.ui.platform.LocalDensity
|
|
30
|
-
import androidx.compose.ui.unit.IntOffset
|
|
31
|
-
import androidx.compose.ui.unit.dp
|
|
32
|
-
import androidx.navigation.NavBackStackEntry
|
|
33
|
-
import androidx.navigation.NavDestination.Companion.hasRoute
|
|
34
|
-
import vn.momo.kits.const.Colors
|
|
35
|
-
import kotlin.math.roundToInt
|
|
36
|
-
|
|
37
|
-
internal const val STACK_TRANSITION_DURATION = 300
|
|
38
|
-
|
|
39
|
-
// Ported 1:1 from the RN kit's `forStackTransitionWithOverlay` so both kits look identical.
|
|
40
|
-
private const val PARALLAX_RATIO = 0.3f
|
|
41
|
-
private const val SCRIM_MAX_ALPHA = 0.6f
|
|
42
|
-
private const val EDGE_SHADOW_MAX_ALPHA = 0.3f
|
|
43
|
-
private val EDGE_SHADOW_WIDTH = 8.dp
|
|
44
|
-
|
|
45
|
-
/** Kill switch: `false` restores pre-DS-760 back handling without a kit release. Transitions
|
|
46
|
-
* stay on the new curve either way. */
|
|
47
|
-
object SwipeBackConfig {
|
|
48
|
-
var enabled: Boolean = true
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// LinearEasing is mandatory: seekTo() maps drag fraction onto the timeline, so a curve would
|
|
52
|
-
// decouple the card from the finger.
|
|
53
|
-
private val stackSpec = tween<IntOffset>(STACK_TRANSITION_DURATION, easing = LinearEasing)
|
|
54
|
-
|
|
55
|
-
internal fun AnimatedContentTransitionScope<NavBackStackEntry>.stackEnter(): EnterTransition =
|
|
56
|
-
slideInHorizontally(stackSpec) { it }
|
|
57
|
-
|
|
58
|
-
internal fun AnimatedContentTransitionScope<NavBackStackEntry>.stackExit(): ExitTransition =
|
|
59
|
-
if (targetState.destination.hasRoute<DynamicDialogRoute>()) ExitTransition.None
|
|
60
|
-
else slideOutHorizontally(stackSpec) { -(it * PARALLAX_RATIO).roundToInt() }
|
|
61
|
-
|
|
62
|
-
internal fun AnimatedContentTransitionScope<NavBackStackEntry>.stackPopEnter(): EnterTransition =
|
|
63
|
-
if (initialState.destination.hasRoute<DynamicDialogRoute>()) EnterTransition.None
|
|
64
|
-
else slideInHorizontally(stackSpec) { -(it * PARALLAX_RATIO).roundToInt() }
|
|
65
|
-
|
|
66
|
-
internal fun AnimatedContentTransitionScope<NavBackStackEntry>.stackPopExit(): ExitTransition =
|
|
67
|
-
slideOutHorizontally(stackSpec) { it }
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Which composed screen is the top card. Ids are monotonic and NavHost keeps both entries composed
|
|
71
|
-
* for the whole segment, so "highest id" is stable both ways. `currentBackStackEntry` is not: it
|
|
72
|
-
* flips at frame 0 of a pop and the scrim would vanish instead of fading.
|
|
73
|
-
*/
|
|
74
|
-
@Stable
|
|
75
|
-
internal class StackTransitionCoordinator {
|
|
76
|
-
private val composedRoutes = mutableStateMapOf<Int, Boolean>()
|
|
77
|
-
|
|
78
|
-
val topStackId: Int by derivedStateOf {
|
|
79
|
-
composedRoutes.entries.filter { it.value }.maxOfOrNull { it.key } ?: -1
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
fun attach(id: Int, isStackRoute: Boolean) {
|
|
83
|
-
composedRoutes[id] = isStackRoute
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
fun detach(id: Int) {
|
|
87
|
-
composedRoutes.remove(id)
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
internal val LocalStackTransition = staticCompositionLocalOf { StackTransitionCoordinator() }
|
|
92
|
-
|
|
93
|
-
/** Draws the covered-screen scrim and the top card's left-edge shadow around a stack destination. */
|
|
94
|
-
@Composable
|
|
95
|
-
internal fun AnimatedVisibilityScope.StackTransitionDecor(
|
|
96
|
-
id: Int,
|
|
97
|
-
isStackRoute: Boolean,
|
|
98
|
-
content: @Composable () -> Unit,
|
|
99
|
-
) {
|
|
100
|
-
val coordinator = LocalStackTransition.current
|
|
101
|
-
coordinator.attach(id, isStackRoute)
|
|
102
|
-
DisposableEffect(coordinator, id) {
|
|
103
|
-
onDispose { coordinator.detach(id) }
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
val isTopCard = isStackRoute && id == coordinator.topStackId
|
|
107
|
-
val isCovered = isStackRoute && !isTopCard
|
|
108
|
-
|
|
109
|
-
val scrimAlpha = transition.animateFloat(
|
|
110
|
-
transitionSpec = { tween(STACK_TRANSITION_DURATION, easing = LinearEasing) },
|
|
111
|
-
label = "stackScrimAlpha",
|
|
112
|
-
) { state -> if (isCovered && state != EnterExitState.Visible) SCRIM_MAX_ALPHA else 0f }
|
|
113
|
-
|
|
114
|
-
val shadowAlpha = transition.animateFloat(
|
|
115
|
-
transitionSpec = { tween(STACK_TRANSITION_DURATION, easing = LinearEasing) },
|
|
116
|
-
label = "stackEdgeShadowAlpha",
|
|
117
|
-
) { state -> if (isTopCard && state == EnterExitState.Visible) EDGE_SHADOW_MAX_ALPHA else 0f }
|
|
118
|
-
|
|
119
|
-
val shadowWidthPx = with(LocalDensity.current) { EDGE_SHADOW_WIDTH.toPx() }
|
|
120
|
-
val shadowBrush = remember(shadowWidthPx) {
|
|
121
|
-
Brush.horizontalGradient(
|
|
122
|
-
colors = listOf(Color.Transparent, Colors.black_20),
|
|
123
|
-
startX = -shadowWidthPx,
|
|
124
|
-
endX = 0f,
|
|
125
|
-
)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
Box(Modifier.fillMaxSize()) {
|
|
129
|
-
content()
|
|
130
|
-
|
|
131
|
-
if (isStackRoute) {
|
|
132
|
-
Box(
|
|
133
|
-
Modifier
|
|
134
|
-
.matchParentSize()
|
|
135
|
-
// read inside drawBehind: in the body this would recompose every gesture frame
|
|
136
|
-
.drawBehind {
|
|
137
|
-
drawRect(
|
|
138
|
-
brush = shadowBrush,
|
|
139
|
-
topLeft = Offset(-shadowWidthPx, 0f),
|
|
140
|
-
size = Size(shadowWidthPx, size.height),
|
|
141
|
-
alpha = shadowAlpha.value,
|
|
142
|
-
)
|
|
143
|
-
drawRect(Colors.pink_09, alpha = scrimAlpha.value)
|
|
144
|
-
}
|
|
145
|
-
)
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
package vn.momo.kits.navigation
|
|
2
|
-
|
|
3
|
-
import androidx.compose.runtime.Composable
|
|
4
|
-
import androidx.compose.runtime.LaunchedEffect
|
|
5
|
-
import androidx.compose.runtime.snapshotFlow
|
|
6
|
-
import vn.momo.kits.platform.getScreenDimensions
|
|
7
|
-
import vn.momo.kits.platform.rememberBackGestureProgress
|
|
8
|
-
import vn.momo.maxapi.IMaxApi
|
|
9
|
-
// AI-GENERATED START: use the typed light vibration pattern
|
|
10
|
-
import vn.momo.maxapi.contract.device.vibration.model.VibrateStyle
|
|
11
|
-
// AI-GENERATED END: use the typed light vibration pattern
|
|
12
|
-
|
|
13
|
-
// Unscaled, so the tick lands at the same physical distance on every device.
|
|
14
|
-
private const val SWIPE_BACK_HAPTIC_THRESHOLD_DP = 50f
|
|
15
|
-
|
|
16
|
-
/** One light tick per crossing, re-armed below the threshold. iOS only. */
|
|
17
|
-
@Composable
|
|
18
|
-
internal fun SwipeBackHaptic(maxApi: IMaxApi?) {
|
|
19
|
-
if (maxApi == null) return
|
|
20
|
-
|
|
21
|
-
val progress = rememberBackGestureProgress()
|
|
22
|
-
val screenWidth = getScreenDimensions().width.toFloat()
|
|
23
|
-
|
|
24
|
-
LaunchedEffect(maxApi, screenWidth) {
|
|
25
|
-
if (screenWidth <= 0f) return@LaunchedEffect
|
|
26
|
-
val threshold = SWIPE_BACK_HAPTIC_THRESHOLD_DP / screenWidth
|
|
27
|
-
var isSendHaptic = false
|
|
28
|
-
snapshotFlow { progress.value }.collect { fraction ->
|
|
29
|
-
val travelled = fraction ?: 0f
|
|
30
|
-
if (travelled >= threshold && !isSendHaptic) {
|
|
31
|
-
// AI-GENERATED START: keep one light tick per threshold crossing
|
|
32
|
-
runCatching { maxApi.vibrate(VibrateStyle.LIGHT) }
|
|
33
|
-
// AI-GENERATED END: keep one light tick per threshold crossing
|
|
34
|
-
isSendHaptic = true
|
|
35
|
-
} else if (travelled < threshold && isSendHaptic) {
|
|
36
|
-
isSendHaptic = false
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
package vn.momo.kits.navigation.bottomtab
|
|
2
|
-
|
|
3
|
-
import androidx.compose.animation.core.Animatable
|
|
4
|
-
import androidx.compose.animation.core.AnimationVector1D
|
|
5
|
-
import androidx.compose.animation.core.Easing
|
|
6
|
-
import androidx.compose.animation.core.tween
|
|
7
|
-
import androidx.compose.foundation.background
|
|
8
|
-
import androidx.compose.foundation.layout.*
|
|
9
|
-
import androidx.compose.runtime.Composable
|
|
10
|
-
import androidx.compose.runtime.CompositionLocalProvider
|
|
11
|
-
import androidx.compose.runtime.DisposableEffect
|
|
12
|
-
import androidx.compose.runtime.LaunchedEffect
|
|
13
|
-
import androidx.compose.runtime.getValue
|
|
14
|
-
import androidx.compose.runtime.key
|
|
15
|
-
import androidx.compose.runtime.mutableIntStateOf
|
|
16
|
-
import androidx.compose.runtime.mutableStateOf
|
|
17
|
-
import androidx.compose.runtime.remember
|
|
18
|
-
import androidx.compose.runtime.saveable.rememberSaveable
|
|
19
|
-
import androidx.compose.runtime.saveable.rememberSaveableStateHolder
|
|
20
|
-
import androidx.compose.runtime.setValue
|
|
21
|
-
import androidx.compose.runtime.staticCompositionLocalOf
|
|
22
|
-
import androidx.compose.ui.Alignment
|
|
23
|
-
import androidx.compose.ui.Modifier
|
|
24
|
-
import androidx.compose.ui.graphics.graphicsLayer
|
|
25
|
-
import androidx.compose.ui.layout.layout
|
|
26
|
-
import androidx.compose.ui.unit.dp
|
|
27
|
-
import androidx.compose.ui.zIndex
|
|
28
|
-
import vn.momo.kits.const.AppNavigationBar
|
|
29
|
-
import vn.momo.kits.const.AppTheme
|
|
30
|
-
import vn.momo.kits.const.Spacing
|
|
31
|
-
import vn.momo.kits.navigation.KeyboardOptions
|
|
32
|
-
import vn.momo.kits.navigation.LocalMaxApi
|
|
33
|
-
import vn.momo.kits.navigation.LocalNavigation
|
|
34
|
-
import vn.momo.kits.navigation.LocalNavigator
|
|
35
|
-
import vn.momo.kits.navigation.NavigationOptions
|
|
36
|
-
import vn.momo.kits.navigation.StackScreen
|
|
37
|
-
import vn.momo.kits.navigation.component.HeaderType
|
|
38
|
-
import vn.momo.kits.platform.BackHandler
|
|
39
|
-
import vn.momo.kits.platform.reportFloatingArrowBack
|
|
40
|
-
import vn.momo.kits.layout.getScreenLayout
|
|
41
|
-
import kotlinx.coroutines.launch
|
|
42
|
-
// AI-GENERATED START: use the typed tab haptic pattern
|
|
43
|
-
import vn.momo.maxapi.contract.device.vibration.model.VibrateStyle
|
|
44
|
-
// AI-GENERATED END: use the typed tab haptic pattern
|
|
45
|
-
|
|
46
|
-
private val inOutQuad = Easing { t -> if (t < 0.5f) 2 * t * t else 1 - 2 * (1 - t) * (1 - t) }
|
|
47
|
-
internal val tabTimingSpec = tween<Float>(durationMillis = 200, easing = inOutQuad)
|
|
48
|
-
|
|
49
|
-
internal val LocalBottomTabFocused = staticCompositionLocalOf { true }
|
|
50
|
-
|
|
51
|
-
private val Hidden = Modifier.layout { measurable, constraints ->
|
|
52
|
-
val placeable = measurable.measure(constraints)
|
|
53
|
-
layout(placeable.width, placeable.height) {}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
private var bottomTabOptionItems : MutableList<NavigationOptions?> = mutableListOf()
|
|
57
|
-
internal fun setBottomTabOption(index: Int, options: NavigationOptions){
|
|
58
|
-
if (index in bottomTabOptionItems.indices) {
|
|
59
|
-
bottomTabOptionItems[index] = options
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
internal fun getBottomTabOption(index: Int): NavigationOptions? {
|
|
63
|
-
return if (index in bottomTabOptionItems.indices) {
|
|
64
|
-
bottomTabOptionItems[index]
|
|
65
|
-
} else null
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
@Composable
|
|
69
|
-
fun BottomTab(
|
|
70
|
-
items: List<BottomTabItem>,
|
|
71
|
-
floatingButton: BottomTabFloatingButton? = null,
|
|
72
|
-
// iPhone Duo: when the side bar can't hold both bars, which one starts compressed;
|
|
73
|
-
// tapping the compressed one swaps them
|
|
74
|
-
compressionBehavior: DuoBarCompressionBehavior = DuoBarCompressionBehavior.TOOLBAR,
|
|
75
|
-
initialRouteName: String? = null,
|
|
76
|
-
onTabPress: ((index: Int, switchTab: () -> Unit) -> Unit)? = null,
|
|
77
|
-
backToInitialTab: Boolean = true,
|
|
78
|
-
) {
|
|
79
|
-
val navigation = LocalNavigation.current
|
|
80
|
-
val navigator = LocalNavigator.current
|
|
81
|
-
val maxApi = LocalMaxApi.current
|
|
82
|
-
val startIndex = remember { items.indexOfFirst { it.name == initialRouteName }.coerceAtLeast(0) }
|
|
83
|
-
|
|
84
|
-
remember(items) {
|
|
85
|
-
bottomTabOptionItems = items.map { it.options ?: NavigationOptions() }.toMutableList()
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
LaunchedEffect(Unit){
|
|
89
|
-
navigation.markAsBottomTabRoot()
|
|
90
|
-
navigation.setOptions(
|
|
91
|
-
headerType = HeaderType.None,
|
|
92
|
-
keyboardOptions = KeyboardOptions(useAvoidKeyboard = false)
|
|
93
|
-
)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
var selectedIndex by rememberSaveable { mutableIntStateOf(startIndex) }
|
|
97
|
-
var loadedTabs by rememberSaveable { mutableStateOf(listOf(startIndex)) }
|
|
98
|
-
val tabStateHolder = rememberSaveableStateHolder()
|
|
99
|
-
val selectTab: (Int) -> Unit = { index ->
|
|
100
|
-
if (index !in loadedTabs) loadedTabs = loadedTabs + index
|
|
101
|
-
selectedIndex = index
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
val onFirstTab = selectedIndex == 0
|
|
105
|
-
val isFirstTab = onFirstTab || !backToInitialTab
|
|
106
|
-
val backToFirstTab = { selectTab(0) }
|
|
107
|
-
|
|
108
|
-
var lastFocusedIndex by rememberSaveable { mutableStateOf<Int?>(null) }
|
|
109
|
-
val tabProgress = remember { mutableMapOf<Int, Animatable<Float, AnimationVector1D>>() }
|
|
110
|
-
fun progressOf(index: Int) = tabProgress.getOrPut(index) {
|
|
111
|
-
Animatable(if (index == lastFocusedIndex) 1f else 0f)
|
|
112
|
-
}
|
|
113
|
-
LaunchedEffect(selectedIndex) {
|
|
114
|
-
lastFocusedIndex = selectedIndex
|
|
115
|
-
tabProgress.forEach { (index, progress) ->
|
|
116
|
-
if (index != selectedIndex) launch { progress.animateTo(0f, tabTimingSpec) }
|
|
117
|
-
}
|
|
118
|
-
progressOf(selectedIndex).animateTo(1f, tabTimingSpec)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
DisposableEffect(isFirstTab) {
|
|
122
|
-
reportFloatingArrowBack(!isFirstTab)
|
|
123
|
-
navigator.tabBackHandler = if (isFirstTab) null else ({ backToFirstTab() })
|
|
124
|
-
|
|
125
|
-
onDispose {
|
|
126
|
-
reportFloatingArrowBack(false)
|
|
127
|
-
navigator.tabBackHandler = null
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
val layout = getScreenLayout()
|
|
132
|
-
val hasQr = floatingButton != null
|
|
133
|
-
val compression = rememberDuoBarCompression(compressionBehavior, items.size, hasQr, layout)
|
|
134
|
-
val railReserve = layout.sideBar?.takeIf { layout.isIPhoneDuo }?.let {
|
|
135
|
-
it.bottom + duoRailHeight(items.size, hasQr, compressed = compression.tabBarCompressed) + DUO_GROUP_GAP
|
|
136
|
-
} ?: 0.dp
|
|
137
|
-
val onTabSelected: (Int) -> Unit = { index ->
|
|
138
|
-
// AI-GENERATED START: preserve the light haptic on tab selection
|
|
139
|
-
runCatching { maxApi?.vibrate(VibrateStyle.LIGHT) }
|
|
140
|
-
// AI-GENERATED END: preserve the light haptic on tab selection
|
|
141
|
-
val switchTab = {
|
|
142
|
-
if (index != selectedIndex) selectTab(index)
|
|
143
|
-
}
|
|
144
|
-
onTabPress?.invoke(index, switchTab) ?: switchTab()
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) {
|
|
148
|
-
Box(modifier = Modifier
|
|
149
|
-
.fillMaxSize()
|
|
150
|
-
.background(AppTheme.current.colors.background.default)
|
|
151
|
-
) {
|
|
152
|
-
CompositionLocalProvider(
|
|
153
|
-
LocalDuoRailReserve provides railReserve,
|
|
154
|
-
LocalDuoBarCompression provides compression,
|
|
155
|
-
) {
|
|
156
|
-
loadedTabs.forEach { index ->
|
|
157
|
-
val item = items.getOrNull(index) ?: return@forEach
|
|
158
|
-
val focused = index == selectedIndex
|
|
159
|
-
val progress = progressOf(index)
|
|
160
|
-
key(index) {
|
|
161
|
-
Box(
|
|
162
|
-
Modifier
|
|
163
|
-
.fillMaxSize()
|
|
164
|
-
.zIndex(if (focused) 0f else -1f)
|
|
165
|
-
.then(if (focused) Modifier.graphicsLayer {
|
|
166
|
-
alpha = 0.3f + 0.7f * progress.value
|
|
167
|
-
scaleX = 0.97f + 0.03f * progress.value
|
|
168
|
-
scaleY = scaleX
|
|
169
|
-
} else Hidden)
|
|
170
|
-
) {
|
|
171
|
-
CompositionLocalProvider(LocalBottomTabFocused provides focused) {
|
|
172
|
-
tabStateHolder.SaveableStateProvider(index) {
|
|
173
|
-
StackScreen(
|
|
174
|
-
content = item.screen,
|
|
175
|
-
navigationOptions = getBottomTabOption(index),
|
|
176
|
-
bottomTabIndex = index,
|
|
177
|
-
onBackHandler = {
|
|
178
|
-
if (backToInitialTab && index != 0) {
|
|
179
|
-
backToFirstTab()
|
|
180
|
-
} else {
|
|
181
|
-
navigator.pop()
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
)
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
BackHandler(enabled = !onFirstTab) {
|
|
193
|
-
if (backToInitialTab) backToFirstTab() else navigator.pop()
|
|
194
|
-
}
|
|
195
|
-
if (layout.isIPhoneDuo) {
|
|
196
|
-
DuoTabBar(
|
|
197
|
-
layout = layout,
|
|
198
|
-
items = items,
|
|
199
|
-
floatingButton = floatingButton,
|
|
200
|
-
selectedIndex = selectedIndex,
|
|
201
|
-
onTabSelected = onTabSelected,
|
|
202
|
-
compression = compression,
|
|
203
|
-
)
|
|
204
|
-
} else {
|
|
205
|
-
Column {
|
|
206
|
-
BottomTabBar(
|
|
207
|
-
items = items,
|
|
208
|
-
floatingButton = floatingButton,
|
|
209
|
-
selectedIndex = selectedIndex,
|
|
210
|
-
onTabSelected = onTabSelected,
|
|
211
|
-
)
|
|
212
|
-
Spacer(modifier = Modifier.fillMaxWidth().height(AppNavigationBar.current + Spacing.S).background(AppTheme.current.colors.background.surface))
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
data class BottomTabItem(
|
|
219
|
-
val name: String,
|
|
220
|
-
val label: String,
|
|
221
|
-
val icon: String,
|
|
222
|
-
val showDot: Boolean = false,
|
|
223
|
-
val badgeLabel: String? = null,
|
|
224
|
-
val screen: @Composable () -> Unit,
|
|
225
|
-
val options: NavigationOptions? = null,
|
|
226
|
-
val initialParams: Any? = null
|
|
227
|
-
)
|
|
228
|
-
|
|
229
|
-
data class BottomTabFloatingButton(
|
|
230
|
-
val icon: String,
|
|
231
|
-
val label: String,
|
|
232
|
-
val onPress: () -> Unit,
|
|
233
|
-
)
|
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
package vn.momo.kits.navigation.bottomtab
|
|
2
|
-
|
|
3
|
-
import androidx.compose.animation.core.Animatable
|
|
4
|
-
import androidx.compose.foundation.background
|
|
5
|
-
import androidx.compose.foundation.border
|
|
6
|
-
import androidx.compose.foundation.layout.*
|
|
7
|
-
import androidx.compose.foundation.shape.CircleShape
|
|
8
|
-
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
9
|
-
import androidx.compose.runtime.Composable
|
|
10
|
-
import androidx.compose.runtime.LaunchedEffect
|
|
11
|
-
import androidx.compose.runtime.getValue
|
|
12
|
-
import androidx.compose.runtime.mutableIntStateOf
|
|
13
|
-
import androidx.compose.runtime.remember
|
|
14
|
-
import androidx.compose.runtime.saveable.rememberSaveable
|
|
15
|
-
import androidx.compose.runtime.setValue
|
|
16
|
-
import androidx.compose.ui.Alignment
|
|
17
|
-
import androidx.compose.ui.Modifier
|
|
18
|
-
import androidx.compose.ui.draw.clip
|
|
19
|
-
import androidx.compose.ui.graphics.Brush
|
|
20
|
-
import androidx.compose.ui.graphics.Color
|
|
21
|
-
import androidx.compose.ui.text.style.TextAlign
|
|
22
|
-
import androidx.compose.ui.text.style.TextOverflow
|
|
23
|
-
import androidx.compose.ui.unit.Dp
|
|
24
|
-
import androidx.compose.ui.unit.IntOffset
|
|
25
|
-
import androidx.compose.ui.unit.dp
|
|
26
|
-
import vn.momo.kits.application.IsShowBaseLineDebug
|
|
27
|
-
import vn.momo.kits.components.*
|
|
28
|
-
import vn.momo.kits.const.*
|
|
29
|
-
import vn.momo.kits.modifier.InternalApi
|
|
30
|
-
import vn.momo.kits.modifier.conditional
|
|
31
|
-
import vn.momo.kits.modifier.activeOpacityClickable
|
|
32
|
-
import vn.momo.kits.layout.getScreenLayout
|
|
33
|
-
import vn.momo.kits.utils.horizontalSafeAreaPadding
|
|
34
|
-
|
|
35
|
-
@InternalApi
|
|
36
|
-
const val BOTTOM_TAB_BAR_HEIGHT = 64
|
|
37
|
-
|
|
38
|
-
@Composable
|
|
39
|
-
internal fun BottomTabBar(
|
|
40
|
-
items: List<BottomTabItem>,
|
|
41
|
-
floatingButton: BottomTabFloatingButton? = null,
|
|
42
|
-
selectedIndex: Int,
|
|
43
|
-
onTabSelected: (Int) -> Unit,
|
|
44
|
-
) {
|
|
45
|
-
|
|
46
|
-
val layout = getScreenLayout()
|
|
47
|
-
val mid = items.size / 2
|
|
48
|
-
|
|
49
|
-
val floating = floatingButton?.takeIf { items.size % 2 == 0 }
|
|
50
|
-
val slotWidth = layout.contentWidth / (items.size + if (floating != null) 1 else 0)
|
|
51
|
-
fun slotOf(index: Int) = if (floating != null && index >= mid) index + 1 else index
|
|
52
|
-
|
|
53
|
-
var indicatorSlot by rememberSaveable { mutableIntStateOf(0) }
|
|
54
|
-
val indicatorX = remember { Animatable(indicatorSlot.toFloat()) }
|
|
55
|
-
LaunchedEffect(selectedIndex) {
|
|
56
|
-
val target = slotOf(selectedIndex)
|
|
57
|
-
indicatorSlot = target
|
|
58
|
-
indicatorX.animateTo(target.toFloat(), tabTimingSpec)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
Box(
|
|
62
|
-
contentAlignment = Alignment.BottomCenter
|
|
63
|
-
) {
|
|
64
|
-
Row(
|
|
65
|
-
modifier = Modifier
|
|
66
|
-
.fillMaxWidth()
|
|
67
|
-
.height(BOTTOM_TAB_BAR_HEIGHT.dp)
|
|
68
|
-
.background(AppTheme.current.colors.background.surface)
|
|
69
|
-
.conditional(IsShowBaseLineDebug) {
|
|
70
|
-
border(1.dp, Colors.blue_03)
|
|
71
|
-
}
|
|
72
|
-
.horizontalSafeAreaPadding(),
|
|
73
|
-
horizontalArrangement = Arrangement.SpaceAround,
|
|
74
|
-
) {
|
|
75
|
-
if (floating == null) {
|
|
76
|
-
RenderTabBarItem(items, 0, items.size, selectedIndex, onTabSelected)
|
|
77
|
-
} else {
|
|
78
|
-
RenderTabBarItem(items, 0, mid, selectedIndex, onTabSelected)
|
|
79
|
-
Spacer(modifier = Modifier.width(slotWidth))
|
|
80
|
-
RenderTabBarItem(items, mid, items.size, selectedIndex, onTabSelected)
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
Box(modifier = Modifier
|
|
85
|
-
.offset { IntOffset((layout.insetLeft + slotWidth * (indicatorX.value + 0.5f) - layout.width / 2).roundToPx(), (-BOTTOM_TAB_BAR_HEIGHT + 2).dp.roundToPx()) }
|
|
86
|
-
.height(2.dp)
|
|
87
|
-
.width(44.dp)
|
|
88
|
-
.background(
|
|
89
|
-
color = AppTheme.current.colors.primary ,
|
|
90
|
-
shape = RoundedCornerShape(bottomStart = 2.dp, bottomEnd = 2.dp)
|
|
91
|
-
)
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
Box(modifier = Modifier
|
|
95
|
-
.fillMaxWidth()
|
|
96
|
-
.height(6.dp)
|
|
97
|
-
.offset(x = 0.dp, y = (-BOTTOM_TAB_BAR_HEIGHT).dp)
|
|
98
|
-
.background(
|
|
99
|
-
brush = Brush.verticalGradient(
|
|
100
|
-
colors = listOf(Color.Transparent, Color.Black.copy(alpha = 0.05f))
|
|
101
|
-
)
|
|
102
|
-
)
|
|
103
|
-
)
|
|
104
|
-
floating?.let {
|
|
105
|
-
Box(Modifier.offset(x = (layout.insetLeft - layout.insetRight) / 2)) {
|
|
106
|
-
FloatingButton(it, slotWidth)
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
@Composable
|
|
113
|
-
internal fun RowScope.RenderTabBarItem(
|
|
114
|
-
items: List<BottomTabItem>,
|
|
115
|
-
fromIndex: Int,
|
|
116
|
-
toIndex: Int,
|
|
117
|
-
selectedIndex: Int,
|
|
118
|
-
onTabSelected: (Int) -> Unit
|
|
119
|
-
){
|
|
120
|
-
for (index in fromIndex until toIndex) {
|
|
121
|
-
Box(modifier = Modifier.weight(1f)) {
|
|
122
|
-
TabBarItem(
|
|
123
|
-
item = items[index],
|
|
124
|
-
selected = index == selectedIndex,
|
|
125
|
-
onClick = { onTabSelected(index) }
|
|
126
|
-
)
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
@Composable
|
|
132
|
-
internal fun TabBarItem(item: BottomTabItem, selected: Boolean, onClick: () -> Unit) {
|
|
133
|
-
// RN parity: "0" hides the badge, "" renders a dot.
|
|
134
|
-
val badgeLabel = item.badgeLabel?.takeUnless { it.toIntOrNull() == 0 }
|
|
135
|
-
val isNumber = badgeLabel?.toIntOrNull() != null
|
|
136
|
-
val showDot = badgeLabel?.isEmpty() ?: item.showDot
|
|
137
|
-
|
|
138
|
-
Box(modifier = Modifier
|
|
139
|
-
.fillMaxSize()
|
|
140
|
-
.padding(horizontal = Spacing.XXS)
|
|
141
|
-
.conditional(IsShowBaseLineDebug) {
|
|
142
|
-
border(1.dp, Colors.blue_03)
|
|
143
|
-
}
|
|
144
|
-
.activeOpacityClickable {
|
|
145
|
-
onClick()
|
|
146
|
-
},
|
|
147
|
-
contentAlignment = Alignment.BottomStart
|
|
148
|
-
){
|
|
149
|
-
Column(
|
|
150
|
-
modifier = Modifier
|
|
151
|
-
.fillMaxSize()
|
|
152
|
-
.padding(horizontal = Spacing.S, vertical = Spacing.S),
|
|
153
|
-
horizontalAlignment = Alignment.CenterHorizontally,
|
|
154
|
-
verticalArrangement = Arrangement.Center
|
|
155
|
-
) {
|
|
156
|
-
Box(modifier = Modifier.padding(Spacing.XS)) {
|
|
157
|
-
Icon(
|
|
158
|
-
source = item.icon,
|
|
159
|
-
size = 28.dp,
|
|
160
|
-
color = if (selected) AppTheme.current.colors.primary else AppTheme.current.colors.text.hint)
|
|
161
|
-
val badgeAnchor = Modifier.matchParentSize().wrapContentSize(Alignment.TopEnd, unbounded = true)
|
|
162
|
-
if (showDot) {
|
|
163
|
-
BadgeDot(size = DotSize.Small, modifier = badgeAnchor.offset(x = 4.dp, y = (-4).dp))
|
|
164
|
-
} else if (!badgeLabel.isNullOrEmpty()) {
|
|
165
|
-
Badge(badgeLabel, modifier = badgeAnchor.offset(x = if (isNumber) 8.dp else 12.dp, y = (-8).dp))
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
Text(
|
|
169
|
-
text = item.label,
|
|
170
|
-
color = if (selected) AppTheme.current.colors.primary else AppTheme.current.colors.text.hint,
|
|
171
|
-
style = if (selected) Typography.labelXsMedium else Typography.descriptionXsRegular,
|
|
172
|
-
maxLines = 1,
|
|
173
|
-
overflow = TextOverflow.Ellipsis
|
|
174
|
-
)
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
@Composable
|
|
180
|
-
internal fun FloatingButton(data: BottomTabFloatingButton, width: Dp) {
|
|
181
|
-
Column(
|
|
182
|
-
modifier = Modifier
|
|
183
|
-
.width(width)
|
|
184
|
-
.padding(horizontal = Spacing.XXS, vertical = Spacing.S)
|
|
185
|
-
.conditional(IsShowBaseLineDebug) {
|
|
186
|
-
border(1.dp, Colors.blue_03)
|
|
187
|
-
}
|
|
188
|
-
.activeOpacityClickable {
|
|
189
|
-
data.onPress()
|
|
190
|
-
},
|
|
191
|
-
verticalArrangement = Arrangement.Bottom,
|
|
192
|
-
horizontalAlignment = Alignment.CenterHorizontally
|
|
193
|
-
|
|
194
|
-
){
|
|
195
|
-
CurvedContainer()
|
|
196
|
-
Box(
|
|
197
|
-
modifier = Modifier
|
|
198
|
-
.size(48.dp)
|
|
199
|
-
.clip(CircleShape)
|
|
200
|
-
.background(AppTheme.current.colors.primary),
|
|
201
|
-
contentAlignment = Alignment.Center
|
|
202
|
-
) {
|
|
203
|
-
Icon(source = data.icon, color = Color.White, size = 28.dp)
|
|
204
|
-
}
|
|
205
|
-
Spacer(modifier = Modifier.height(4.dp))
|
|
206
|
-
Text(
|
|
207
|
-
text = data.label,
|
|
208
|
-
style = Typography.labelXsMedium,
|
|
209
|
-
color = Colors.black_01,
|
|
210
|
-
textAlign = TextAlign.Center,
|
|
211
|
-
modifier = Modifier
|
|
212
|
-
.height(14.dp)
|
|
213
|
-
.fillMaxWidth()
|
|
214
|
-
.background(AppTheme.current.colors.primary, shape = RoundedCornerShape(size = Radius.XL))
|
|
215
|
-
)
|
|
216
|
-
}
|
|
217
|
-
}
|