@momo-kits/native-kits 0.162.2-sp.1-debug → 0.162.2-sp.10-debug
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/.claude/settings.local.json +15 -1
- package/CLAUDE.md +78 -0
- package/compose/build.gradle.kts +12 -8
- package/compose/build.gradle.kts.backup +11 -7
- package/compose/compose.podspec +1 -1
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +7 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +2 -7
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +8 -11
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +6 -24
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +4 -19
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +1 -10
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +2 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +5 -16
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +6 -101
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +269 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +8 -19
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +8 -33
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +56 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +22 -25
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +27 -29
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +3 -26
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +30 -31
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +3 -13
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -5
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +3 -11
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +3 -18
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +11 -11
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +42 -65
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +69 -26
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +1 -5
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +84 -59
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +13 -71
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +10 -51
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +6 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +4 -21
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +16 -75
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +5 -26
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +3 -11
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +16 -40
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +3 -9
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +0 -28
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +2 -13
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +4 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +4 -10
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +3 -28
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +8 -47
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +4 -25
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +2 -11
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +1 -17
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +1 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +50 -111
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +1 -5
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +1 -5
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +1 -12
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +4 -96
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +5 -7
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +2 -12
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +9 -21
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +2 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +9 -14
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +8 -11
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +22 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +11 -20
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +0 -5
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +0 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +94 -4
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +0 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +2 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +3 -7
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +12 -16
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +120 -93
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +48 -33
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +88 -63
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +9 -14
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +13 -31
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +6 -24
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +11 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +2 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +9 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +3 -13
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +3 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +1 -40
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +0 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +9 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +0 -8
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +2 -17
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +3 -3
- package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +2 -3
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +66 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +0 -2
- package/gradle/libs.versions.toml +2 -0
- package/gradle.properties +1 -1
- package/ios/Application/ApplicationEnvironment.swift +15 -2
- package/ios/Application/Components.swift +16 -0
- package/ios/Application/HeaderRight.swift +79 -45
- package/ios/Application/Localize.swift +277 -0
- package/ios/Application/MaxApi.swift +18 -0
- package/ios/Application/Navigation/BottomTab/BottomTab.swift +3 -1
- package/ios/Application/Navigation/NavigationContainer.swift +53 -4
- package/ios/Application/Navigation/Navigator.swift +54 -29
- package/ios/Application/Navigation/Overplay/BottomSheet.swift +98 -18
- package/ios/Application/Navigation/Overplay/ModalScreen.swift +6 -0
- package/ios/Application/Navigation/Tracking/ScreenTracker.swift +117 -0
- package/ios/Application/Screen.swift +2 -1
- package/ios/Application/StackScreen.swift +55 -3
- package/ios/Badge/BadgeRibbon.swift +80 -0
- package/ios/Button/Button.swift +67 -11
- package/ios/Carousel/Carousel.swift +16 -1
- package/ios/Checkbox/Checkbox.swift +14 -20
- package/ios/Chip/Chip.swift +35 -26
- package/ios/Collapse/Collapse.swift +11 -1
- package/ios/Colors+Radius+Spacing/Colors.swift +20 -17
- package/ios/Colors+Radius+Spacing/Spacing.swift +3 -1
- package/ios/Colors+Radius+Spacing/Theme.swift +15 -15
- package/ios/DateTimePicker/DateTimePicker.swift +4 -2
- package/ios/DateTimePicker/WheelPicker.swift +7 -3
- package/ios/Extensions/ActiveOpacityButtonStyle.swift +14 -0
- package/ios/Extensions/Color++.swift +32 -0
- package/ios/Icon/Icon.swift +5 -1
- package/ios/IconButton/IconButton.swift +35 -7
- package/ios/Image/Image.swift +16 -3
- package/ios/Information/Information.swift +3 -1
- package/ios/Input/ErrorView.swift +3 -1
- package/ios/Input/Input.swift +31 -8
- package/ios/Input/InputPhoneNumber.swift +14 -3
- package/ios/Input/InputSearch.swift +7 -1
- package/ios/Input/InputTextArea.swift +78 -34
- package/ios/InputDropDown/InputDropDown.swift +4 -1
- package/ios/InputMoney/InputMoney.swift +16 -4
- package/ios/Popup/PopupDisplay.swift +3 -4
- package/ios/Popup/PopupNotify.swift +3 -4
- package/ios/ProgressInfo/ProgressInfo.swift +4 -2
- package/ios/Radio/Radio.swift +12 -13
- package/ios/Rating/Rating.swift +1 -1
- package/ios/Resources/MoMoUIKitsColors.xcassets/AccentColor.colorset/Contents.json +11 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Background.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Border.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Card.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Contents.json +6 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Error.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Primary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/PrimaryDark.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/PrimaryLight.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Secondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Success.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Text.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/TextSecondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/Contents.json +9 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-default.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-disable.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-pressed.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-selected.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-surface.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-tonal.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-default.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-disable.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/gradient.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/primary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/secondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-container.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-primary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-secondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-default.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-disable.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-hint.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-secondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Warning.colorset/Contents.json +38 -0
- package/ios/Stepper/Stepper.swift +2 -2
- package/ios/Steps/Steps.swift +22 -6
- package/ios/SuggestAction/SuggestAction.swift +5 -3
- package/ios/Swipeable/SwipeCell.swift +5 -3
- package/ios/Switch/Switch.swift +53 -28
- package/ios/TabView/TabView.swift +18 -14
- package/ios/Template/TrustBanner/TrustBanner.swift +6 -7
- package/ios/Tooltip/Tooltip.swift +3 -0
- package/ios/Typography/FontScaleStore.swift +19 -0
- package/ios/Typography/Text.swift +3 -0
- package/ios/Typography/Typography.swift +8 -5
- package/ios/Uploader/Uploader.swift +0 -9
- package/ios/native-kits.podspec +6 -3
- package/ios-demo/MoMoUIKitsDemo.podspec +5 -3
- package/ios-demo/Sources/MoMoUIKitsDemo/MoMoUIKitsDemoFactory.swift +9 -57
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +21 -3
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LocalizeDemo.swift +188 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +2 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SwiftUIDemoBrowserView.swift +5 -4
- package/package.json +1 -1
|
@@ -9,6 +9,7 @@ import androidx.compose.runtime.staticCompositionLocalOf
|
|
|
9
9
|
import androidx.compose.ui.Alignment
|
|
10
10
|
import androidx.compose.ui.Modifier
|
|
11
11
|
import androidx.navigation.NavController
|
|
12
|
+
import androidx.navigation.toRoute
|
|
12
13
|
import kotlinx.coroutines.CoroutineScope
|
|
13
14
|
import kotlinx.coroutines.Dispatchers
|
|
14
15
|
import kotlinx.coroutines.SupervisorJob
|
|
@@ -21,30 +22,38 @@ import vn.momo.kits.components.PopupNotify
|
|
|
21
22
|
import vn.momo.kits.navigation.BottomHeader.*
|
|
22
23
|
import vn.momo.kits.navigation.component.SnackBar
|
|
23
24
|
import vn.momo.maxapi.IMaxApi
|
|
25
|
+
import kotlin.time.Duration.Companion.milliseconds
|
|
24
26
|
|
|
25
27
|
class Navigator(
|
|
26
28
|
private val navController: NavController,
|
|
27
|
-
private val maxApi: IMaxApi
|
|
29
|
+
private val maxApi: IMaxApi?,
|
|
30
|
+
private val registry: DynamicScreenRegistry
|
|
28
31
|
) {
|
|
29
32
|
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
|
|
30
33
|
|
|
34
|
+
private fun currentScreen(): DynamicScreen? {
|
|
35
|
+
val entry = navController.currentBackStackEntry ?: return null
|
|
36
|
+
val id = runCatching { entry.toRoute<DynamicScreenRoute>().id }.getOrNull()
|
|
37
|
+
?: runCatching { entry.toRoute<DynamicDialogRoute>().id }.getOrNull()
|
|
38
|
+
?: return null
|
|
39
|
+
return registry.getScreen(id)
|
|
40
|
+
}
|
|
41
|
+
|
|
31
42
|
fun push(screenName: String, content: @Composable () -> Unit, options: NavigationOptions? = null) {
|
|
32
|
-
val route =
|
|
43
|
+
val route = registry.register(screenName, content, options)
|
|
33
44
|
navController.navigate(DynamicScreenRoute(route.id))
|
|
34
45
|
}
|
|
35
46
|
|
|
36
47
|
fun replace(screenName: String, content: @Composable () -> Unit, options: NavigationOptions? = null) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
push(screenName, content, options)
|
|
42
|
-
}
|
|
48
|
+
val replacedScreen = currentScreen()
|
|
49
|
+
replacedScreen?.let { registry.unregisterScreen(it.id) }
|
|
50
|
+
navController.popBackStack()
|
|
51
|
+
push(screenName, content, options)
|
|
43
52
|
}
|
|
44
53
|
|
|
45
54
|
fun onBackSafe(callBack: (() -> Unit)? = null) {
|
|
46
|
-
val
|
|
47
|
-
val options =
|
|
55
|
+
val currentScreen = currentScreen()
|
|
56
|
+
val options = currentScreen?.options
|
|
48
57
|
if (options?.onBackHandler != null) {
|
|
49
58
|
options.onBackHandler.invoke()
|
|
50
59
|
return
|
|
@@ -87,31 +96,30 @@ class Navigator(
|
|
|
87
96
|
}
|
|
88
97
|
private suspend fun dismissOverplay(isDelay: Boolean = true) {
|
|
89
98
|
OverplayComponentRegistry.clear()
|
|
90
|
-
if (isDelay) delay(300L)
|
|
99
|
+
if (isDelay) delay(300L.milliseconds)
|
|
91
100
|
OverplayComponentRegistry.hardClearAfterDismiss()
|
|
92
101
|
}
|
|
93
102
|
|
|
94
103
|
private suspend fun dismissScreen() {
|
|
95
104
|
if (navController.previousBackStackEntry != null){
|
|
105
|
+
val dismissing = currentScreen()
|
|
96
106
|
navController.popBackStack()
|
|
97
|
-
delay(300L)
|
|
98
|
-
|
|
99
|
-
DynamicScreenRegistry.unregisterScreen(it1.id)
|
|
100
|
-
}
|
|
107
|
+
delay(300L.milliseconds)
|
|
108
|
+
dismissing?.let { registry.unregisterScreen(it.id) }
|
|
101
109
|
} else {
|
|
102
110
|
maxApi?.dismiss { }
|
|
103
111
|
}
|
|
104
112
|
}
|
|
105
113
|
|
|
106
114
|
fun present(screenName: String, content: @Composable () -> Unit, options: NavigationOptions? = null) {
|
|
107
|
-
val route =
|
|
115
|
+
val route = registry.register(screenName, content, options)
|
|
108
116
|
navController.navigate(DynamicDialogRoute(route.id))
|
|
109
117
|
}
|
|
110
118
|
|
|
111
119
|
fun reset(screenName: String, content: @Composable () -> Unit, options: NavigationOptions? = null) {
|
|
112
|
-
|
|
120
|
+
registry.unregisterAll()
|
|
113
121
|
|
|
114
|
-
val route =
|
|
122
|
+
val route = registry.register(screenName, content, options)
|
|
115
123
|
navController.navigate(DynamicScreenRoute(route.id)) {
|
|
116
124
|
popUpTo(0) { inclusive = true }
|
|
117
125
|
}
|
|
@@ -122,7 +130,7 @@ class Navigator(
|
|
|
122
130
|
barrierDismissible: Boolean = true,
|
|
123
131
|
onDismiss: (() -> Unit)? = null
|
|
124
132
|
){
|
|
125
|
-
val id =
|
|
133
|
+
val id = currentScreen()?.id ?: -1
|
|
126
134
|
OverplayComponentRegistry.registerOverplay(id, content, OverplayComponentType.MODAL, false, barrierDismissible, onDismiss)
|
|
127
135
|
}
|
|
128
136
|
|
|
@@ -133,12 +141,12 @@ class Navigator(
|
|
|
133
141
|
onDismiss: (() -> Unit)? = null,
|
|
134
142
|
bottomSheetHeader: BottomHeader? = null
|
|
135
143
|
){
|
|
136
|
-
val id =
|
|
144
|
+
val id = currentScreen()?.id ?: -1
|
|
137
145
|
OverplayComponentRegistry.registerOverplay(id, content, OverplayComponentType.BOTTOM_SHEET, isSurface, barrierDismissible, onDismiss, bottomSheetHeader)
|
|
138
146
|
}
|
|
139
147
|
|
|
140
148
|
fun showSnackBar(snackBar: SnackBar, onDismiss: (() -> Unit)? = null) {
|
|
141
|
-
val id =
|
|
149
|
+
val id = currentScreen()?.id ?: -1
|
|
142
150
|
scope.launch {
|
|
143
151
|
OverplayComponentRegistry.registerOverplay(
|
|
144
152
|
id = id,
|
|
@@ -154,7 +162,7 @@ class Navigator(
|
|
|
154
162
|
fun hideSnackBar() {
|
|
155
163
|
scope.launch {
|
|
156
164
|
OverplayComponentRegistry.clear()
|
|
157
|
-
delay(250L)
|
|
165
|
+
delay(250L.milliseconds)
|
|
158
166
|
OverplayComponentRegistry.hardClearAfterDismiss()
|
|
159
167
|
}
|
|
160
168
|
}
|
|
@@ -181,12 +189,11 @@ data class DynamicScreen(
|
|
|
181
189
|
var options: NavigationOptions? = null
|
|
182
190
|
)
|
|
183
191
|
|
|
184
|
-
|
|
192
|
+
class DynamicScreenRegistry {
|
|
185
193
|
private val screens = mutableMapOf<Int, DynamicScreen>()
|
|
186
|
-
private var idCounter = 1
|
|
187
194
|
|
|
188
195
|
fun register(screenName: String, content: @Composable () -> Unit, options: NavigationOptions?): DynamicScreenRoute {
|
|
189
|
-
val id =
|
|
196
|
+
val id = nextGlobalId()
|
|
190
197
|
screens[id] = DynamicScreen(
|
|
191
198
|
id = id,
|
|
192
199
|
name = screenName,
|
|
@@ -196,7 +203,7 @@ object DynamicScreenRegistry {
|
|
|
196
203
|
return DynamicScreenRoute(id)
|
|
197
204
|
}
|
|
198
205
|
|
|
199
|
-
fun nextId(): Int =
|
|
206
|
+
fun nextId(): Int = nextGlobalId()
|
|
200
207
|
|
|
201
208
|
fun bind(id: Int, screenName: String, content: @Composable () -> Unit, options: NavigationOptions?) {
|
|
202
209
|
screens[id] = DynamicScreen(
|
|
@@ -205,17 +212,13 @@ object DynamicScreenRegistry {
|
|
|
205
212
|
content = content,
|
|
206
213
|
options = options
|
|
207
214
|
)
|
|
208
|
-
|
|
215
|
+
advanceGlobalIdPast(id) // keep counter ahead after process-death restore
|
|
209
216
|
}
|
|
210
217
|
|
|
211
218
|
fun unregisterScreen(id: Int) {
|
|
212
219
|
screens.remove(id)
|
|
213
220
|
}
|
|
214
221
|
|
|
215
|
-
fun getLatestScreen(): DynamicScreen?{
|
|
216
|
-
return screens.entries.lastOrNull()?.value
|
|
217
|
-
}
|
|
218
|
-
|
|
219
222
|
fun unregisterAll(){
|
|
220
223
|
val ids = screens.keys.toList()
|
|
221
224
|
for (id in ids) {
|
|
@@ -228,8 +231,20 @@ object DynamicScreenRegistry {
|
|
|
228
231
|
fun setOptions(id: Int, options: NavigationOptions){
|
|
229
232
|
screens[id]?.options = options
|
|
230
233
|
}
|
|
234
|
+
|
|
235
|
+
companion object {
|
|
236
|
+
private var globalIdCounter = 1
|
|
237
|
+
|
|
238
|
+
private fun nextGlobalId(): Int = globalIdCounter++
|
|
239
|
+
|
|
240
|
+
private fun advanceGlobalIdPast(id: Int) {
|
|
241
|
+
if (id >= globalIdCounter) globalIdCounter = id + 1
|
|
242
|
+
}
|
|
243
|
+
}
|
|
231
244
|
}
|
|
232
245
|
|
|
246
|
+
val LocalDynamicScreenRegistry = staticCompositionLocalOf<DynamicScreenRegistry?> { null }
|
|
247
|
+
|
|
233
248
|
|
|
234
249
|
sealed class OverplayComponentParams {
|
|
235
250
|
class Modal(
|
|
@@ -244,7 +259,7 @@ sealed class OverplayComponentParams {
|
|
|
244
259
|
val bottomSheetHeader: BottomHeader? = null,
|
|
245
260
|
) : OverplayComponentParams()
|
|
246
261
|
|
|
247
|
-
class SnackBar
|
|
262
|
+
class SnackBar : OverplayComponentParams()
|
|
248
263
|
}
|
|
249
264
|
|
|
250
265
|
data class OverplayComponent(
|
|
@@ -308,7 +323,7 @@ object OverplayComponentRegistry {
|
|
|
308
323
|
}
|
|
309
324
|
|
|
310
325
|
@Composable
|
|
311
|
-
fun OverlayComponent(){
|
|
326
|
+
internal fun OverlayComponent(){
|
|
312
327
|
val overplay = currentOverlayComponent.value ?: return
|
|
313
328
|
|
|
314
329
|
when (val params = overplay.params) {
|
|
@@ -45,8 +45,8 @@ import androidx.compose.ui.layout.onGloballyPositioned
|
|
|
45
45
|
import androidx.compose.ui.platform.LocalDensity
|
|
46
46
|
import androidx.compose.ui.unit.Dp
|
|
47
47
|
import androidx.compose.ui.unit.dp
|
|
48
|
-
import androidx.compose.ui.unit.min
|
|
49
48
|
import androidx.compose.ui.zIndex
|
|
49
|
+
import kotlinx.coroutines.flow.Flow
|
|
50
50
|
import vn.momo.kits.components.InputSearch
|
|
51
51
|
import vn.momo.kits.const.AppNavigationBar
|
|
52
52
|
import vn.momo.kits.const.AppStatusBar
|
|
@@ -56,6 +56,7 @@ import vn.momo.kits.const.Colors
|
|
|
56
56
|
import vn.momo.kits.const.Spacing
|
|
57
57
|
import vn.momo.kits.modifier.conditional
|
|
58
58
|
import vn.momo.kits.modifier.hideKeyboardOnTap
|
|
59
|
+
import vn.momo.kits.navigation.bottomtab.BOTTOM_TAB_BAR_HEIGHT
|
|
59
60
|
import vn.momo.kits.navigation.component.FABPosition
|
|
60
61
|
import vn.momo.kits.navigation.component.FloatingButton
|
|
61
62
|
import vn.momo.kits.navigation.component.HEADER_HEIGHT
|
|
@@ -69,13 +70,21 @@ import vn.momo.kits.platform.supportsImePadding
|
|
|
69
70
|
import vn.momo.kits.navigation.tracking.ScreenTracker
|
|
70
71
|
import vn.momo.kits.navigation.tracking.ScreenTrackingState
|
|
71
72
|
import kotlinx.coroutines.delay
|
|
72
|
-
import vn.momo.kits.application.
|
|
73
|
+
import vn.momo.kits.application.LocalContext
|
|
73
74
|
import kotlin.time.Clock
|
|
75
|
+
import kotlin.time.Duration.Companion.milliseconds
|
|
74
76
|
import kotlin.time.ExperimentalTime
|
|
75
77
|
|
|
76
78
|
internal val LocalFooterHeightPx = staticCompositionLocalOf { mutableIntStateOf(0) }
|
|
77
79
|
internal val LocalHeaderRightWidthPx = staticCompositionLocalOf { mutableIntStateOf(0) }
|
|
78
80
|
|
|
81
|
+
@Composable
|
|
82
|
+
private fun bottomTabBarInset(): Dp {
|
|
83
|
+
if (LocalNavigation.current.bottomTabIndex == -1) return 0.dp
|
|
84
|
+
val keyboard = keyboardSizeState().value
|
|
85
|
+
return (BOTTOM_TAB_BAR_HEIGHT.dp + Spacing.S - keyboard).coerceAtLeast(0.dp)
|
|
86
|
+
}
|
|
87
|
+
|
|
79
88
|
@OptIn(ExperimentalMaterialApi::class, ExperimentalTime::class)
|
|
80
89
|
@Composable
|
|
81
90
|
internal fun StackScreen(
|
|
@@ -88,17 +97,20 @@ internal fun StackScreen(
|
|
|
88
97
|
) {
|
|
89
98
|
val navigator = LocalNavigator.current
|
|
90
99
|
val maxApi = LocalMaxApi.current
|
|
91
|
-
val context =
|
|
100
|
+
val context = LocalContext.current
|
|
92
101
|
val statusBar = AppStatusBar.current
|
|
93
102
|
val density = LocalDensity.current
|
|
94
|
-
val
|
|
103
|
+
val screenRegistry = LocalDynamicScreenRegistry.current
|
|
104
|
+
val navigation = remember { Navigation(id = id, bottomTabIndex = bottomTabIndex, initOptions = navigationOptions, registry = screenRegistry) }
|
|
95
105
|
|
|
96
106
|
val options by navigation.currentOptions
|
|
107
|
+
val isBottomTabChild = bottomTabIndex != -1
|
|
108
|
+
val isBottomTabRoot = navigation.isBottomTabRoot
|
|
97
109
|
|
|
98
110
|
// Auto tracking state
|
|
99
111
|
val trackingState = remember {
|
|
100
112
|
ScreenTrackingState().apply {
|
|
101
|
-
|
|
113
|
+
time = Clock.System.now().toEpochMilliseconds()
|
|
102
114
|
}
|
|
103
115
|
}
|
|
104
116
|
|
|
@@ -119,8 +131,8 @@ internal fun StackScreen(
|
|
|
119
131
|
)
|
|
120
132
|
|
|
121
133
|
// Track screen displayed after 2 seconds (debounce)
|
|
122
|
-
delay(2000)
|
|
123
|
-
val loadTime = Clock.System.now().toEpochMilliseconds() - trackingState.
|
|
134
|
+
delay(2000.milliseconds)
|
|
135
|
+
val loadTime = Clock.System.now().toEpochMilliseconds() - trackingState.time
|
|
124
136
|
ScreenTracker.trackScreenDisplayed(
|
|
125
137
|
maxApi = maxApi,
|
|
126
138
|
context = context,
|
|
@@ -130,7 +142,7 @@ internal fun StackScreen(
|
|
|
130
142
|
)
|
|
131
143
|
|
|
132
144
|
// Track screen interacted after displayed
|
|
133
|
-
val interactionTime = Clock.System.now().toEpochMilliseconds() - trackingState.
|
|
145
|
+
val interactionTime = Clock.System.now().toEpochMilliseconds() - trackingState.time
|
|
134
146
|
ScreenTracker.trackScreenInteracted(
|
|
135
147
|
maxApi = maxApi,
|
|
136
148
|
context = context,
|
|
@@ -191,29 +203,35 @@ internal fun StackScreen(
|
|
|
191
203
|
}
|
|
192
204
|
|
|
193
205
|
Column(Modifier.zIndex(2f).fillMaxSize()) {
|
|
194
|
-
MainContent(content = content)
|
|
206
|
+
MainContent(content = content, isBottomTabRoot = isBottomTabRoot, isBottomTabChild = isBottomTabChild)
|
|
195
207
|
FooterContent()
|
|
196
208
|
}
|
|
197
209
|
|
|
198
210
|
Box(Modifier.zIndex(6f)) {
|
|
199
|
-
FloatingContent()
|
|
211
|
+
FloatingContent(isBottomTabChild = isBottomTabChild)
|
|
200
212
|
}
|
|
201
213
|
|
|
202
|
-
OverplayView(
|
|
214
|
+
OverplayView(isBottomTabChild = isBottomTabChild, id = id)
|
|
203
215
|
}
|
|
204
216
|
}
|
|
205
217
|
}
|
|
206
218
|
|
|
219
|
+
@Suppress("FrequentlyChangingValue")
|
|
207
220
|
@Composable
|
|
208
|
-
fun FloatingContent() {
|
|
221
|
+
internal fun FloatingContent(isBottomTabChild: Boolean) {
|
|
209
222
|
val options = LocalOptions.current
|
|
210
223
|
val density = LocalDensity.current
|
|
211
224
|
val footerHeightPx = LocalFooterHeightPx.current
|
|
212
225
|
val scrollState = LocalScrollState.current
|
|
226
|
+
val navigationBar = AppNavigationBar.current
|
|
213
227
|
|
|
214
228
|
val fabProps = options.floatingButtonProps ?: return
|
|
215
229
|
val bottomPadding = fabProps.bottom
|
|
216
|
-
?: (Spacing.M +
|
|
230
|
+
?: (Spacing.M + when {
|
|
231
|
+
options.hasFooter() -> with(density) { footerHeightPx.intValue.toDp() }
|
|
232
|
+
isBottomTabChild -> bottomTabBarInset() + (navigationBar - keyboardSizeState().value).coerceAtLeast(0.dp)
|
|
233
|
+
else -> navigationBar
|
|
234
|
+
})
|
|
217
235
|
|
|
218
236
|
FloatingButton(
|
|
219
237
|
scrollPosition = fabProps.scrollState?.value ?: scrollState.value,
|
|
@@ -229,11 +247,12 @@ fun FloatingContent() {
|
|
|
229
247
|
}
|
|
230
248
|
|
|
231
249
|
@Composable
|
|
232
|
-
fun ColumnScope.MainContent(content: @Composable () -> Unit) {
|
|
250
|
+
internal fun ColumnScope.MainContent(content: @Composable () -> Unit, isBottomTabRoot: Boolean, isBottomTabChild: Boolean) {
|
|
233
251
|
val options = LocalOptions.current
|
|
234
252
|
val inputSearchType = getInputSearchType(options)
|
|
235
253
|
val density = LocalDensity.current
|
|
236
254
|
val scrollState = LocalScrollState.current
|
|
255
|
+
val navigationBar = AppNavigationBar.current
|
|
237
256
|
|
|
238
257
|
Spacer(
|
|
239
258
|
Modifier.height(
|
|
@@ -257,6 +276,14 @@ fun ColumnScope.MainContent(content: @Composable () -> Unit) {
|
|
|
257
276
|
.conditional(options.scrollData.scrollable && options.scrollData.scrollState is ScrollState) {
|
|
258
277
|
verticalScroll(scrollState)
|
|
259
278
|
}
|
|
279
|
+
.padding(
|
|
280
|
+
bottom = when {
|
|
281
|
+
options.hasFooter() || isBottomTabRoot -> 0.dp
|
|
282
|
+
isBottomTabChild -> bottomTabBarInset() + (navigationBar - keyboardSizeState().value).coerceAtLeast(0.dp)
|
|
283
|
+
!options.scrollData.scrollable -> 0.dp
|
|
284
|
+
else -> navigationBar
|
|
285
|
+
}
|
|
286
|
+
)
|
|
260
287
|
) {
|
|
261
288
|
ScreenContent(content = content)
|
|
262
289
|
}
|
|
@@ -264,7 +291,7 @@ fun ColumnScope.MainContent(content: @Composable () -> Unit) {
|
|
|
264
291
|
}
|
|
265
292
|
|
|
266
293
|
@Composable
|
|
267
|
-
fun ScreenContent(content: @Composable () -> Unit) {
|
|
294
|
+
internal fun ScreenContent(content: @Composable () -> Unit) {
|
|
268
295
|
val scrollState = LocalScrollState.current
|
|
269
296
|
val options = LocalOptions.current
|
|
270
297
|
|
|
@@ -284,9 +311,9 @@ fun ScreenContent(content: @Composable () -> Unit) {
|
|
|
284
311
|
}
|
|
285
312
|
|
|
286
313
|
@Composable
|
|
287
|
-
fun FooterContent() {
|
|
314
|
+
internal fun FooterContent() {
|
|
288
315
|
val options = LocalOptions.current
|
|
289
|
-
if (options.
|
|
316
|
+
if (options.hasFooter()) {
|
|
290
317
|
val keyboardSize = keyboardSizeState()
|
|
291
318
|
val bottomPadding = (AppNavigationBar.current - keyboardSize.value).coerceAtLeast(0.dp)
|
|
292
319
|
Footer(footerComponent = options.footerComponent, bottomPadding = bottomPadding)
|
|
@@ -294,18 +321,18 @@ fun FooterContent() {
|
|
|
294
321
|
}
|
|
295
322
|
|
|
296
323
|
@Composable
|
|
297
|
-
fun keyboardSizeState(): State<Dp> {
|
|
324
|
+
internal fun keyboardSizeState(): State<Dp> {
|
|
298
325
|
val bottom = WindowInsets.ime.asPaddingValues()
|
|
299
326
|
return rememberUpdatedState(bottom.calculateBottomPadding())
|
|
300
327
|
}
|
|
301
328
|
|
|
302
329
|
@Composable
|
|
303
|
-
fun OverplayView(
|
|
330
|
+
internal fun OverplayView(isBottomTabChild: Boolean, id: Int) {
|
|
304
331
|
val overplayType = OverplayComponentRegistry.getOverplayType()
|
|
305
332
|
|
|
306
333
|
if (overplayType != null) {
|
|
307
334
|
Box(Modifier.zIndex(if (overplayType == OverplayComponentType.SNACK_BAR) 3f else 7f).fillMaxSize()) {
|
|
308
|
-
if (
|
|
335
|
+
if (isBottomTabChild) return@Box
|
|
309
336
|
if (OverplayComponentRegistry.currentRootId() != id) return@Box
|
|
310
337
|
OverplayComponentRegistry.OverlayComponent()
|
|
311
338
|
}
|
|
@@ -355,8 +382,9 @@ data class InputSearchLayoutParams(
|
|
|
355
382
|
val endPadding: Dp
|
|
356
383
|
)
|
|
357
384
|
|
|
385
|
+
@Suppress("FrequentlyChangingValue")
|
|
358
386
|
@Composable
|
|
359
|
-
fun SearchAnimated(
|
|
387
|
+
internal fun SearchAnimated(
|
|
360
388
|
isScrollInProgress: Boolean
|
|
361
389
|
) {
|
|
362
390
|
val scrollState = LocalScrollState.current
|
|
@@ -469,64 +497,61 @@ private fun quantize(value: Int, stepPx: Int): Int {
|
|
|
469
497
|
}
|
|
470
498
|
|
|
471
499
|
@Composable
|
|
472
|
-
fun LazyListState.proxyScrollState(
|
|
500
|
+
internal fun LazyListState.proxyScrollState(
|
|
473
501
|
thresholdPx: Int = 200,
|
|
474
502
|
stepPx: Int = 4
|
|
475
|
-
): Pair<ScrollState, Boolean>
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
if (scrollState.value != desired) {
|
|
489
|
-
scrollState.scrollTo(desired.coerceAtLeast(0))
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
val inProgress = remember { mutableStateOf(false) }
|
|
495
|
-
LaunchedEffect(this, thresholdPx) {
|
|
496
|
-
snapshotFlow { isScrollInProgress }
|
|
497
|
-
.collect { progressing ->
|
|
498
|
-
inProgress.value = if (locked.value) false else progressing
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
return scrollState to inProgress.value
|
|
503
|
-
}
|
|
503
|
+
): Pair<ScrollState, Boolean> = proxyScroll(
|
|
504
|
+
source = this,
|
|
505
|
+
thresholdPx = thresholdPx,
|
|
506
|
+
stepPx = stepPx,
|
|
507
|
+
isScrollInProgress = { isScrollInProgress },
|
|
508
|
+
rawTargetFlow = {
|
|
509
|
+
snapshotFlow {
|
|
510
|
+
if (firstVisibleItemIndex == 0) firstVisibleItemScrollOffset
|
|
511
|
+
else SCROLLED_PAST_FIRST_ITEM_THRESHOLD
|
|
512
|
+
}
|
|
513
|
+
},
|
|
514
|
+
)
|
|
504
515
|
|
|
505
516
|
@Composable
|
|
506
|
-
fun ScrollState.proxyLimitedScrollState(
|
|
517
|
+
internal fun ScrollState.proxyLimitedScrollState(
|
|
507
518
|
thresholdPx: Int = 200,
|
|
508
519
|
stepPx: Int = 4
|
|
520
|
+
): Pair<ScrollState, Boolean> = proxyScroll(
|
|
521
|
+
source = this,
|
|
522
|
+
thresholdPx = thresholdPx,
|
|
523
|
+
stepPx = stepPx,
|
|
524
|
+
isScrollInProgress = { isScrollInProgress },
|
|
525
|
+
rawTargetFlow = { snapshotFlow { value } },
|
|
526
|
+
)
|
|
527
|
+
|
|
528
|
+
@Composable
|
|
529
|
+
private fun proxyScroll(
|
|
530
|
+
source: Any,
|
|
531
|
+
thresholdPx: Int,
|
|
532
|
+
stepPx: Int,
|
|
533
|
+
isScrollInProgress: () -> Boolean,
|
|
534
|
+
rawTargetFlow: () -> Flow<Int>,
|
|
509
535
|
): Pair<ScrollState, Boolean> {
|
|
510
536
|
val proxy = rememberScrollState()
|
|
511
537
|
val locked = remember { mutableStateOf(false) }
|
|
512
538
|
|
|
513
|
-
LaunchedEffect(
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
if (locked.value != shouldLock) locked.value = shouldLock
|
|
539
|
+
LaunchedEffect(source, proxy, thresholdPx, stepPx) {
|
|
540
|
+
rawTargetFlow().collect { rawTarget ->
|
|
541
|
+
val shouldLock = rawTarget > thresholdPx
|
|
542
|
+
if (locked.value != shouldLock) locked.value = shouldLock
|
|
518
543
|
|
|
519
|
-
|
|
544
|
+
val desired = if (shouldLock) thresholdPx else quantize(rawTarget, stepPx)
|
|
520
545
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
}
|
|
546
|
+
if (proxy.value != desired) {
|
|
547
|
+
proxy.scrollTo(desired.coerceAtLeast(0))
|
|
524
548
|
}
|
|
549
|
+
}
|
|
525
550
|
}
|
|
526
551
|
|
|
527
552
|
val inProgress = remember { mutableStateOf(false) }
|
|
528
|
-
LaunchedEffect(
|
|
529
|
-
snapshotFlow { isScrollInProgress }
|
|
553
|
+
LaunchedEffect(source, thresholdPx) {
|
|
554
|
+
snapshotFlow { isScrollInProgress() }
|
|
530
555
|
.collect { progressing ->
|
|
531
556
|
inProgress.value = if (locked.value) false else progressing
|
|
532
557
|
}
|
|
@@ -6,13 +6,7 @@ import androidx.compose.animation.fadeOut
|
|
|
6
6
|
import androidx.compose.animation.scaleIn
|
|
7
7
|
import androidx.compose.animation.scaleOut
|
|
8
8
|
import androidx.compose.foundation.background
|
|
9
|
-
import androidx.compose.foundation.layout
|
|
10
|
-
import androidx.compose.foundation.layout.Column
|
|
11
|
-
import androidx.compose.foundation.layout.Spacer
|
|
12
|
-
import androidx.compose.foundation.layout.fillMaxSize
|
|
13
|
-
import androidx.compose.foundation.layout.fillMaxWidth
|
|
14
|
-
import androidx.compose.foundation.layout.height
|
|
15
|
-
import androidx.compose.foundation.layout.padding
|
|
9
|
+
import androidx.compose.foundation.layout.*
|
|
16
10
|
import androidx.compose.runtime.Composable
|
|
17
11
|
import androidx.compose.runtime.LaunchedEffect
|
|
18
12
|
import androidx.compose.ui.Alignment
|
|
@@ -24,20 +18,20 @@ import androidx.navigation.compose.rememberNavController
|
|
|
24
18
|
import vn.momo.kits.const.AppNavigationBar
|
|
25
19
|
import vn.momo.kits.const.AppTheme
|
|
26
20
|
import vn.momo.kits.const.Spacing
|
|
21
|
+
import vn.momo.kits.navigation.KeyboardOptions
|
|
27
22
|
import vn.momo.kits.navigation.LocalNavigation
|
|
28
23
|
import vn.momo.kits.navigation.LocalNavigator
|
|
29
24
|
import vn.momo.kits.navigation.NavigationOptions
|
|
30
25
|
import vn.momo.kits.navigation.StackScreen
|
|
31
26
|
import vn.momo.kits.navigation.component.HeaderType
|
|
32
|
-
import vn.momo.kits.platform.getScreenHeight
|
|
33
27
|
|
|
34
28
|
private var bottomTabOptionItems : MutableList<NavigationOptions?> = mutableListOf()
|
|
35
|
-
fun setBottomTabOption(index: Int, options: NavigationOptions){
|
|
29
|
+
internal fun setBottomTabOption(index: Int, options: NavigationOptions){
|
|
36
30
|
if (index in bottomTabOptionItems.indices) {
|
|
37
31
|
bottomTabOptionItems[index] = options
|
|
38
32
|
}
|
|
39
33
|
}
|
|
40
|
-
fun getBottomTabOption(index: Int): NavigationOptions? {
|
|
34
|
+
internal fun getBottomTabOption(index: Int): NavigationOptions? {
|
|
41
35
|
return if (index in bottomTabOptionItems.indices) {
|
|
42
36
|
bottomTabOptionItems[index]
|
|
43
37
|
} else null
|
|
@@ -58,15 +52,16 @@ fun BottomTab(
|
|
|
58
52
|
|
|
59
53
|
|
|
60
54
|
LaunchedEffect(Unit){
|
|
55
|
+
navigation.markAsBottomTabRoot()
|
|
61
56
|
navigation.setOptions(
|
|
62
|
-
headerType = HeaderType.None
|
|
57
|
+
headerType = HeaderType.None,
|
|
58
|
+
keyboardOptions = KeyboardOptions(useAvoidKeyboard = false)
|
|
63
59
|
)
|
|
64
60
|
}
|
|
65
61
|
|
|
66
|
-
Box(modifier = Modifier.
|
|
62
|
+
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) {
|
|
67
63
|
Box(modifier = Modifier
|
|
68
64
|
.fillMaxSize()
|
|
69
|
-
.padding(bottom = BOTTOM_TAB_BAR_HEIGHT.dp + AppNavigationBar.current)
|
|
70
65
|
) {
|
|
71
66
|
NavHost(
|
|
72
67
|
navController = navController,
|
|
@@ -133,7 +128,7 @@ fun BottomTab(
|
|
|
133
128
|
onTabSelected = {
|
|
134
129
|
val currentRoute = navController.currentBackStackEntry?.destination?.route
|
|
135
130
|
val targetRoute = "option$it"
|
|
136
|
-
if (currentRoute != targetRoute){
|
|
131
|
+
if (currentRoute != targetRoute) {
|
|
137
132
|
navController.navigate(targetRoute)
|
|
138
133
|
}
|
|
139
134
|
}
|
|
@@ -5,19 +5,7 @@ import androidx.compose.animation.core.animateDpAsState
|
|
|
5
5
|
import androidx.compose.animation.core.tween
|
|
6
6
|
import androidx.compose.foundation.background
|
|
7
7
|
import androidx.compose.foundation.border
|
|
8
|
-
import androidx.compose.foundation.layout
|
|
9
|
-
import androidx.compose.foundation.layout.Box
|
|
10
|
-
import androidx.compose.foundation.layout.Column
|
|
11
|
-
import androidx.compose.foundation.layout.Row
|
|
12
|
-
import androidx.compose.foundation.layout.RowScope
|
|
13
|
-
import androidx.compose.foundation.layout.Spacer
|
|
14
|
-
import androidx.compose.foundation.layout.fillMaxSize
|
|
15
|
-
import androidx.compose.foundation.layout.fillMaxWidth
|
|
16
|
-
import androidx.compose.foundation.layout.height
|
|
17
|
-
import androidx.compose.foundation.layout.offset
|
|
18
|
-
import androidx.compose.foundation.layout.padding
|
|
19
|
-
import androidx.compose.foundation.layout.size
|
|
20
|
-
import androidx.compose.foundation.layout.width
|
|
8
|
+
import androidx.compose.foundation.layout.*
|
|
21
9
|
import androidx.compose.foundation.shape.CircleShape
|
|
22
10
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
23
11
|
import androidx.compose.runtime.Composable
|
|
@@ -32,26 +20,20 @@ import androidx.compose.ui.text.style.TextOverflow
|
|
|
32
20
|
import androidx.compose.ui.unit.dp
|
|
33
21
|
import androidx.navigation.NavController
|
|
34
22
|
import androidx.navigation.compose.currentBackStackEntryAsState
|
|
35
|
-
import vn.momo.kits.components.Badge
|
|
36
|
-
import vn.momo.kits.components.Icon
|
|
37
|
-
import vn.momo.kits.components.Text
|
|
38
|
-
import vn.momo.kits.const.AppTheme
|
|
39
|
-
import vn.momo.kits.const.Colors
|
|
40
|
-
import vn.momo.kits.const.Radius
|
|
41
|
-
import vn.momo.kits.const.Spacing
|
|
42
23
|
import vn.momo.kits.application.IsShowBaseLineDebug
|
|
43
|
-
import vn.momo.kits.components
|
|
44
|
-
import vn.momo.kits.
|
|
45
|
-
import vn.momo.kits.
|
|
24
|
+
import vn.momo.kits.components.*
|
|
25
|
+
import vn.momo.kits.const.*
|
|
26
|
+
import vn.momo.kits.modifier.InternalApi
|
|
46
27
|
import vn.momo.kits.modifier.conditional
|
|
47
28
|
import vn.momo.kits.modifier.noFeedbackClickable
|
|
48
29
|
import vn.momo.kits.platform.getScreenDimensions
|
|
49
30
|
|
|
50
|
-
val floatingButtonWidth = 75.dp
|
|
31
|
+
internal val floatingButtonWidth = 75.dp
|
|
32
|
+
@InternalApi
|
|
51
33
|
const val BOTTOM_TAB_BAR_HEIGHT = 64
|
|
52
34
|
|
|
53
35
|
@Composable
|
|
54
|
-
fun BottomTabBar(
|
|
36
|
+
internal fun BottomTabBar(
|
|
55
37
|
items: List<BottomTabItem>,
|
|
56
38
|
floatingButton: BottomTabFloatingButton? = null,
|
|
57
39
|
navController: NavController,
|
|
@@ -91,11 +73,11 @@ fun BottomTabBar(
|
|
|
91
73
|
horizontalArrangement = Arrangement.SpaceAround,
|
|
92
74
|
) {
|
|
93
75
|
if (floatingButton == null) {
|
|
94
|
-
|
|
76
|
+
RenderTabBarItem(items, 0, items.size, selectedIndex, onTabSelected)
|
|
95
77
|
} else {
|
|
96
|
-
|
|
78
|
+
RenderTabBarItem(items, 0, mid, selectedIndex, onTabSelected)
|
|
97
79
|
Spacer(modifier = Modifier.width(floatingButtonWidth).padding(horizontal = Spacing.XXS))
|
|
98
|
-
|
|
80
|
+
RenderTabBarItem(items, mid, items.size, selectedIndex, onTabSelected)
|
|
99
81
|
}
|
|
100
82
|
}
|
|
101
83
|
|
|
@@ -124,7 +106,7 @@ fun BottomTabBar(
|
|
|
124
106
|
}
|
|
125
107
|
|
|
126
108
|
@Composable
|
|
127
|
-
fun RowScope.
|
|
109
|
+
internal fun RowScope.RenderTabBarItem(
|
|
128
110
|
items: List<BottomTabItem>,
|
|
129
111
|
fromIndex: Int,
|
|
130
112
|
toIndex: Int,
|
|
@@ -143,7 +125,7 @@ fun RowScope.renderTabBarItem(
|
|
|
143
125
|
}
|
|
144
126
|
|
|
145
127
|
@Composable
|
|
146
|
-
fun TabBarItem(item: BottomTabItem, selected: Boolean, onClick: () -> Unit) {
|
|
128
|
+
internal fun TabBarItem(item: BottomTabItem, selected: Boolean, onClick: () -> Unit) {
|
|
147
129
|
fun isNumber(label: String): Boolean {
|
|
148
130
|
val numberRegex = "^\\d+$".toRegex()
|
|
149
131
|
return numberRegex.matches(label)
|
|
@@ -203,7 +185,7 @@ fun TabBarItem(item: BottomTabItem, selected: Boolean, onClick: () -> Unit) {
|
|
|
203
185
|
}
|
|
204
186
|
|
|
205
187
|
@Composable
|
|
206
|
-
fun FloatingButton(data: BottomTabFloatingButton) {
|
|
188
|
+
internal fun FloatingButton(data: BottomTabFloatingButton) {
|
|
207
189
|
Column(
|
|
208
190
|
modifier = Modifier
|
|
209
191
|
.width(floatingButtonWidth)
|