@momo-kits/native-kits 0.0.2-alpha.1 → 0.0.2-alpha.1-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/build.gradle.kts +11 -0
- package/compose/build.gradle.kts +189 -0
- package/compose/build.gradle.kts.backup +189 -0
- package/compose/compose.podspec +47 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/const/HostFont.android.kt +19 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/navigation/ScrollToTop.android.kt +6 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/BackGesture.android.kt +12 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +7 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +151 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +52 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +124 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +183 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +207 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +39 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +86 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +76 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +76 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +293 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +33 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +831 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +269 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +110 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +378 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +65 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +69 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +157 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +82 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +32 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +338 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +175 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +356 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +113 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +89 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +128 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +209 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +542 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +49 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +86 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +125 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +231 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +189 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +475 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +114 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +266 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +240 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +223 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +264 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +185 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +343 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +108 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +56 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +41 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +84 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +40 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +328 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +97 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +310 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +59 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +87 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +21 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +90 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +323 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +220 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +473 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +122 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +199 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +91 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +552 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +88 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +125 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +207 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +498 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +176 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +182 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +193 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +29 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +234 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +188 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +325 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/HostFont.kt +16 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitDesignSystem.kt +18 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +22 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +12 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +16 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +194 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +282 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +54 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +51 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +41 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +52 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +66 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +11 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +104 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +48 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +51 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +299 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/HostBackGestureBridge.kt +58 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +129 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +106 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +211 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +398 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScrollToTop.kt +8 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +595 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackTransition.kt +148 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/SwipeBackHaptic.kt +40 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +184 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +225 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +86 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +169 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +357 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +83 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderJourney.kt +106 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderLocation.kt +75 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +326 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +39 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +364 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +132 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/ToolkitRequests.kt +33 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +135 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/BackGesture.kt +12 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +91 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +9 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +71 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +1329 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +55 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +15 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +105 -0
- package/compose/src/commonTest/kotlin/vn/momo/kits/navigation/component/ToolkitRequestsTest.kt +47 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/const/HostFont.ios.kt +40 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/HostBackGesture.ios.kt +45 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +36 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/BackGesture.ios.kt +38 -0
- 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 +213 -0
- package/gradle/libs.versions.toml +71 -0
- package/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/gradle/wrapper/gradle-wrapper.properties +8 -0
- package/gradle.properties +26 -0
- package/gradlew +252 -0
- package/gradlew.bat +94 -0
- package/ios-demo/README.md +120 -0
- package/package.json +1 -1
- package/settings.gradle.kts +64 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
package vn.momo.kits.navigation
|
|
2
|
+
|
|
3
|
+
import androidx.compose.animation.core.Animatable
|
|
4
|
+
import androidx.compose.animation.core.CubicBezierEasing
|
|
5
|
+
import androidx.compose.animation.core.tween
|
|
6
|
+
import androidx.compose.foundation.background
|
|
7
|
+
import androidx.compose.foundation.border
|
|
8
|
+
import androidx.compose.foundation.clickable
|
|
9
|
+
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
10
|
+
import androidx.compose.foundation.layout.Box
|
|
11
|
+
import androidx.compose.foundation.layout.fillMaxSize
|
|
12
|
+
import androidx.compose.foundation.layout.wrapContentSize
|
|
13
|
+
import androidx.compose.runtime.*
|
|
14
|
+
import androidx.compose.ui.Alignment
|
|
15
|
+
import androidx.compose.ui.Modifier
|
|
16
|
+
import androidx.compose.ui.draw.alpha
|
|
17
|
+
import androidx.compose.ui.draw.scale
|
|
18
|
+
import androidx.compose.ui.graphics.Color
|
|
19
|
+
import androidx.compose.ui.unit.dp
|
|
20
|
+
import kotlinx.coroutines.launch
|
|
21
|
+
import vn.momo.kits.application.LocalContext
|
|
22
|
+
import vn.momo.kits.application.IsShowBaseLineDebug
|
|
23
|
+
import vn.momo.kits.const.Colors
|
|
24
|
+
import vn.momo.kits.modifier.conditional
|
|
25
|
+
import vn.momo.kits.modifier.noFeedbackClickable
|
|
26
|
+
import vn.momo.kits.navigation.tracking.ScreenTracker
|
|
27
|
+
import vn.momo.kits.platform.BackHandler
|
|
28
|
+
|
|
29
|
+
@Composable
|
|
30
|
+
internal fun ModalScreen(
|
|
31
|
+
content: @Composable () -> Unit,
|
|
32
|
+
barrierDismissible: Boolean = true,
|
|
33
|
+
onDismiss: (() -> Unit)? = null
|
|
34
|
+
) {
|
|
35
|
+
val navigator = LocalNavigator.current
|
|
36
|
+
|
|
37
|
+
val alpha = remember { Animatable(0f) }
|
|
38
|
+
val scale = remember { Animatable(0.8f) }
|
|
39
|
+
|
|
40
|
+
val coroutineScope = rememberCoroutineScope()
|
|
41
|
+
|
|
42
|
+
val maxApi = LocalMaxApi.current
|
|
43
|
+
val context = LocalContext.current
|
|
44
|
+
|
|
45
|
+
DisposableEffect(Unit) {
|
|
46
|
+
ScreenTracker.trackPopupDisplayed(
|
|
47
|
+
maxApi = maxApi,
|
|
48
|
+
context = context,
|
|
49
|
+
parentScreenName = ScreenTracker.getLastScreenName()
|
|
50
|
+
)
|
|
51
|
+
onDispose { }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
fun openEvent() {
|
|
55
|
+
coroutineScope.launch {
|
|
56
|
+
launch {
|
|
57
|
+
alpha.animateTo(
|
|
58
|
+
targetValue = 1f,
|
|
59
|
+
animationSpec = tween(durationMillis = 250)
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
launch {
|
|
63
|
+
scale.animateTo(
|
|
64
|
+
targetValue = 1f,
|
|
65
|
+
animationSpec = tween(
|
|
66
|
+
durationMillis = 250,
|
|
67
|
+
easing = CubicBezierEasing(0.2f, 0.0f, 0f, 1f)
|
|
68
|
+
)
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
fun closeEvent() {
|
|
75
|
+
coroutineScope.launch {
|
|
76
|
+
alpha.animateTo(
|
|
77
|
+
targetValue = 0f,
|
|
78
|
+
animationSpec = tween(durationMillis = 200)
|
|
79
|
+
)
|
|
80
|
+
scale.animateTo(
|
|
81
|
+
targetValue = 0.8f,
|
|
82
|
+
animationSpec = tween(durationMillis = 200)
|
|
83
|
+
)
|
|
84
|
+
OverplayComponentRegistry.hardClearAfterDismiss()
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
LaunchedEffect(Unit) {
|
|
89
|
+
openEvent()
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
DisposableEffect(Unit) {
|
|
93
|
+
OverplayComponentRegistry.bindClose { closeEvent() }
|
|
94
|
+
onDispose {
|
|
95
|
+
onDismiss?.invoke()
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
BackHandler(enabled = true) {
|
|
100
|
+
closeEvent()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
Box(
|
|
104
|
+
modifier = Modifier
|
|
105
|
+
.fillMaxSize()
|
|
106
|
+
.background(Color.Black.copy(alpha = 0.6f * alpha.value))
|
|
107
|
+
.noFeedbackClickable {
|
|
108
|
+
if(barrierDismissible) closeEvent()
|
|
109
|
+
},
|
|
110
|
+
contentAlignment = Alignment.Center
|
|
111
|
+
) {
|
|
112
|
+
Box(
|
|
113
|
+
modifier = Modifier
|
|
114
|
+
.scale(scale.value)
|
|
115
|
+
.alpha(alpha.value)
|
|
116
|
+
.wrapContentSize()
|
|
117
|
+
.conditional(IsShowBaseLineDebug) {
|
|
118
|
+
border(1.dp, Colors.blue_03)
|
|
119
|
+
}
|
|
120
|
+
.clickable(
|
|
121
|
+
indication = null,
|
|
122
|
+
interactionSource = remember { MutableInteractionSource() }
|
|
123
|
+
) {},
|
|
124
|
+
contentAlignment = Alignment.Center
|
|
125
|
+
) {
|
|
126
|
+
content()
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
package vn.momo.kits.navigation
|
|
2
|
+
|
|
3
|
+
import androidx.compose.foundation.gestures.ScrollableState
|
|
4
|
+
import androidx.compose.runtime.*
|
|
5
|
+
import androidx.compose.ui.graphics.Color
|
|
6
|
+
import vn.momo.kits.navigation.bottomtab.setBottomTabOption
|
|
7
|
+
import vn.momo.kits.navigation.component.*
|
|
8
|
+
|
|
9
|
+
class Navigation(
|
|
10
|
+
val id: Int = -1,
|
|
11
|
+
val bottomTabIndex: Int = -1,
|
|
12
|
+
val initOptions: NavigationOptions? = null,
|
|
13
|
+
private val registry: DynamicScreenRegistry? = null
|
|
14
|
+
) {
|
|
15
|
+
private val _options = mutableStateOf(initOptions ?: NavigationOptions())
|
|
16
|
+
val currentOptions: State<NavigationOptions> get() = _options
|
|
17
|
+
val options: NavigationOptions get() = _options.value
|
|
18
|
+
|
|
19
|
+
private val _isBottomTabRoot = mutableStateOf(false)
|
|
20
|
+
internal val isBottomTabRoot: Boolean get() = _isBottomTabRoot.value
|
|
21
|
+
internal fun markAsBottomTabRoot() { _isBottomTabRoot.value = true }
|
|
22
|
+
|
|
23
|
+
fun setOptions(
|
|
24
|
+
onBackHandler: (() -> Unit)? = null,
|
|
25
|
+
hiddenBack: Boolean? = null,
|
|
26
|
+
headerBackProps: HeaderBackProps? = null,
|
|
27
|
+
headerTitle: HeaderTitle? = null,
|
|
28
|
+
titlePosition: TitlePosition? = null,
|
|
29
|
+
headerRight: HeaderRight? = null,
|
|
30
|
+
headerType: HeaderType? = null,
|
|
31
|
+
scrollData: ScrollData? = null,
|
|
32
|
+
backgroundColor: Color? = null,
|
|
33
|
+
tintColor: Color? = null,
|
|
34
|
+
footerComponent: (@Composable () -> Unit)? = null,
|
|
35
|
+
footerTransparent: Boolean? = null,
|
|
36
|
+
footerUseMargin: Boolean? = null,
|
|
37
|
+
floatingButtonProps: FloatingButtonProps? = null,
|
|
38
|
+
keyboardOptions: KeyboardOptions? = null
|
|
39
|
+
) {
|
|
40
|
+
updateOptions(
|
|
41
|
+
options.copy(
|
|
42
|
+
onBackHandler = onBackHandler ?: options.onBackHandler,
|
|
43
|
+
hiddenBack = hiddenBack ?: options.hiddenBack,
|
|
44
|
+
headerBackProps = headerBackProps ?: options.headerBackProps,
|
|
45
|
+
headerTitle = headerTitle ?: options.headerTitle,
|
|
46
|
+
titlePosition = titlePosition ?: options.titlePosition,
|
|
47
|
+
headerRight = headerRight ?: options.headerRight,
|
|
48
|
+
headerType = headerType ?: options.headerType,
|
|
49
|
+
scrollData = scrollData ?: options.scrollData,
|
|
50
|
+
backgroundColor = backgroundColor ?: options.backgroundColor,
|
|
51
|
+
tintColor = tintColor ?: options.tintColor,
|
|
52
|
+
footerComponent = footerComponent ?: options.footerComponent,
|
|
53
|
+
footerTransparent = footerTransparent ?: options.footerTransparent,
|
|
54
|
+
footerUseMargin = footerUseMargin ?: options.footerUseMargin,
|
|
55
|
+
floatingButtonProps = floatingButtonProps ?: options.floatingButtonProps,
|
|
56
|
+
keyboardOptions = keyboardOptions ?: options.keyboardOptions,
|
|
57
|
+
)
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
fun setOptions(newOptions: NavigationOptions) {
|
|
62
|
+
updateOptions(newOptions)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private fun updateOptions(updated: NavigationOptions) {
|
|
66
|
+
_options.value = updated
|
|
67
|
+
if (bottomTabIndex != -1) setBottomTabOption(bottomTabIndex, updated)
|
|
68
|
+
if (id != -1) registry?.setOptions(id, updated)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
val LocalNavigation = staticCompositionLocalOf<Navigation> {
|
|
73
|
+
error("No NavigationStack provided")
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@Stable
|
|
77
|
+
data class NavigationOptions(
|
|
78
|
+
val screenName: String? = null,
|
|
79
|
+
val onBackHandler: (() -> Unit)? = null,
|
|
80
|
+
val hiddenBack: Boolean = false,
|
|
81
|
+
val headerBackProps: HeaderBackProps = HeaderBackProps(),
|
|
82
|
+
val headerTitle: HeaderTitle = HeaderTitle.Default("Stack"),
|
|
83
|
+
val titlePosition: TitlePosition = TitlePosition.LEFT,
|
|
84
|
+
val headerRight: HeaderRight = HeaderRight.Toolkit(),
|
|
85
|
+
val headerType: HeaderType = HeaderType.Default(),
|
|
86
|
+
val scrollData: ScrollData = ScrollData(),
|
|
87
|
+
val backgroundColor: Color? = null,
|
|
88
|
+
val tintColor: Color? = null,
|
|
89
|
+
val footerComponent: @Composable (() -> Unit)? = null,
|
|
90
|
+
val footerTransparent: Boolean = false,
|
|
91
|
+
val footerUseMargin: Boolean = true,
|
|
92
|
+
val floatingButtonProps: FloatingButtonProps? = null,
|
|
93
|
+
val keyboardOptions: KeyboardOptions = KeyboardOptions()
|
|
94
|
+
) {
|
|
95
|
+
internal fun hasFooter() : Boolean = footerComponent != null
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
data class KeyboardOptions(
|
|
99
|
+
val keyboardShouldPersistTaps: Boolean = false,
|
|
100
|
+
val useAvoidKeyboard: Boolean = true
|
|
101
|
+
)
|
|
102
|
+
data class ScrollData(
|
|
103
|
+
val scrollable: Boolean = true,
|
|
104
|
+
val scrollState: ScrollableState? = null,
|
|
105
|
+
val scrollToTopCallback: (() -> Unit)? = null,
|
|
106
|
+
)
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
package vn.momo.kits.navigation
|
|
2
|
+
|
|
3
|
+
import androidx.compose.animation.core.tween
|
|
4
|
+
import androidx.compose.animation.fadeIn
|
|
5
|
+
import androidx.compose.animation.slideInVertically
|
|
6
|
+
import androidx.compose.animation.slideOutVertically
|
|
7
|
+
import androidx.compose.runtime.Composable
|
|
8
|
+
import androidx.compose.runtime.CompositionLocalProvider
|
|
9
|
+
import androidx.compose.runtime.DisposableEffect
|
|
10
|
+
import androidx.compose.runtime.LaunchedEffect
|
|
11
|
+
import androidx.compose.runtime.mutableStateOf
|
|
12
|
+
import androidx.compose.runtime.remember
|
|
13
|
+
import androidx.compose.runtime.saveable.rememberSaveable
|
|
14
|
+
import androidx.compose.runtime.staticCompositionLocalOf
|
|
15
|
+
import androidx.compose.ui.unit.Dp
|
|
16
|
+
import androidx.navigation.compose.NavHost
|
|
17
|
+
import androidx.navigation.compose.composable
|
|
18
|
+
import androidx.navigation.compose.rememberNavController
|
|
19
|
+
import androidx.navigation.toRoute
|
|
20
|
+
import kotlinx.coroutines.delay
|
|
21
|
+
import kotlinx.coroutines.flow.collectLatest
|
|
22
|
+
import vn.momo.kits.application.DesignSystemConfig
|
|
23
|
+
import vn.momo.kits.application.KitDesignSystemConfig
|
|
24
|
+
import vn.momo.kits.application.LocalContext
|
|
25
|
+
import vn.momo.kits.application.LocalDesignSystemConfig
|
|
26
|
+
import vn.momo.kits.application.LocalLocalize
|
|
27
|
+
import vn.momo.kits.application.Localize
|
|
28
|
+
import vn.momo.kits.application.MiniAppContext
|
|
29
|
+
import vn.momo.kits.const.AppNavigationBar
|
|
30
|
+
import vn.momo.kits.const.AppStatusBar
|
|
31
|
+
import vn.momo.kits.const.AppTheme
|
|
32
|
+
import vn.momo.kits.const.Theme
|
|
33
|
+
import vn.momo.kits.const.defaultTheme
|
|
34
|
+
import vn.momo.kits.platform.ProvideNavigationEventDispatcherOwner
|
|
35
|
+
import vn.momo.kits.platform.ProvideOsFontScale
|
|
36
|
+
import vn.momo.kits.utils.getAppStatusBarHeight
|
|
37
|
+
import vn.momo.kits.utils.getNavigationBarHeight
|
|
38
|
+
// AI-GENERATED START: consume typed NativeMaxApi results
|
|
39
|
+
import vn.momo.maxapi.IMaxApi
|
|
40
|
+
import vn.momo.maxapi.runtime.ApiResult
|
|
41
|
+
// AI-GENERATED END: consume typed NativeMaxApi results
|
|
42
|
+
import kotlin.time.Duration.Companion.milliseconds
|
|
43
|
+
|
|
44
|
+
@Composable
|
|
45
|
+
fun NavigationContainer(
|
|
46
|
+
initialScreenName: String,
|
|
47
|
+
initialScreen: @Composable () -> Unit,
|
|
48
|
+
maxApi: IMaxApi,
|
|
49
|
+
options: NavigationOptions? = null,
|
|
50
|
+
initialTheme: Theme = defaultTheme,
|
|
51
|
+
miniAppContext: MiniAppContext? = null,
|
|
52
|
+
setNavigator: ((Navigator) -> Unit)? = null,
|
|
53
|
+
statusBarHeight: Dp? = null,
|
|
54
|
+
localize: Localize? = null,
|
|
55
|
+
designSystemConfig: DesignSystemConfig? = null,
|
|
56
|
+
) {
|
|
57
|
+
val navController = rememberNavController()
|
|
58
|
+
val registry = remember { DynamicScreenRegistry() }
|
|
59
|
+
// AI-GENERATED START: retain the current host client after recomposition
|
|
60
|
+
val navigator = remember(navController, maxApi, registry) {
|
|
61
|
+
Navigator(navController = navController, maxApi = maxApi, registry = registry)
|
|
62
|
+
}
|
|
63
|
+
// AI-GENERATED END: retain the current host client after recomposition
|
|
64
|
+
val statusBarHeight = statusBarHeight ?: getAppStatusBarHeight()
|
|
65
|
+
val navigationBarHeight = getNavigationBarHeight()
|
|
66
|
+
|
|
67
|
+
val parentContext = LocalContext.current
|
|
68
|
+
val mergedContext = MiniAppContext.merge(parentContext, miniAppContext)
|
|
69
|
+
|
|
70
|
+
val stackTransition = remember { StackTransitionCoordinator() }
|
|
71
|
+
val theme = remember { mutableStateOf(initialTheme) }
|
|
72
|
+
val resolvedDesignSystemConfig =
|
|
73
|
+
designSystemConfig ?: LocalDesignSystemConfig.current ?: KitDesignSystemConfig.config
|
|
74
|
+
val headerBar = resolvedDesignSystemConfig?.headerBar
|
|
75
|
+
// RN parity: the theme's own header image wins; config headerBar is only the fallback.
|
|
76
|
+
val resolvedTheme = remember(theme.value, headerBar) {
|
|
77
|
+
if (theme.value.isHeaderImage() || headerBar.isNullOrEmpty()) {
|
|
78
|
+
theme.value
|
|
79
|
+
} else {
|
|
80
|
+
theme.value.copy(assets = theme.value.assets.copy(headerBackground = headerBar))
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
val fallbackLocalize = remember { Localize() }
|
|
84
|
+
|
|
85
|
+
val resolvedLocalize = localize ?: fallbackLocalize
|
|
86
|
+
|
|
87
|
+
// AI-GENERATED START: cancel language delivery when its composition owner changes
|
|
88
|
+
DisposableEffect(maxApi, resolvedLocalize) {
|
|
89
|
+
val api = maxApi
|
|
90
|
+
val target = resolvedLocalize
|
|
91
|
+
var active = true
|
|
92
|
+
val handle = runCatching {
|
|
93
|
+
api.getLanguage { result ->
|
|
94
|
+
if (active && result is ApiResult.Success &&
|
|
95
|
+
result.value.trim().lowercase().startsWith(Localize.EN)) {
|
|
96
|
+
target.changeLanguage(Localize.EN)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}.getOrNull()
|
|
100
|
+
onDispose {
|
|
101
|
+
active = false
|
|
102
|
+
handle?.cancel()
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// AI-GENERATED END: cancel language delivery when its composition owner changes
|
|
106
|
+
|
|
107
|
+
val screenId = rememberSaveable { registry.nextId() }
|
|
108
|
+
registry.bind(screenId, initialScreenName, initialScreen, options)
|
|
109
|
+
val startDestination = remember(screenId) { DynamicScreenRoute(screenId) }
|
|
110
|
+
|
|
111
|
+
ProvideOsFontScale {
|
|
112
|
+
ProvideNavigationEventDispatcherOwner(navigator) {
|
|
113
|
+
CompositionLocalProvider(
|
|
114
|
+
LocalNavigator provides navigator,
|
|
115
|
+
LocalDynamicScreenRegistry provides registry,
|
|
116
|
+
LocalMaxApi provides maxApi,
|
|
117
|
+
AppTheme provides resolvedTheme,
|
|
118
|
+
AppStatusBar provides statusBarHeight,
|
|
119
|
+
AppNavigationBar provides navigationBarHeight,
|
|
120
|
+
LocalContext provides mergedContext,
|
|
121
|
+
LocalDesignSystemConfig provides resolvedDesignSystemConfig,
|
|
122
|
+
LocalLocalize provides resolvedLocalize,
|
|
123
|
+
LocalStackTransition provides stackTransition,
|
|
124
|
+
) {
|
|
125
|
+
LaunchedEffect(Unit) {
|
|
126
|
+
setNavigator?.invoke(navigator)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
SwipeBackHaptic(maxApi)
|
|
130
|
+
|
|
131
|
+
LaunchedEffect(navController, registry) {
|
|
132
|
+
navController.currentBackStack.collectLatest { entries ->
|
|
133
|
+
delay(STACK_TRANSITION_DURATION.milliseconds)
|
|
134
|
+
val aliveIds = entries.mapNotNullTo(mutableSetOf()) { entry ->
|
|
135
|
+
runCatching { entry.toRoute<DynamicScreenRoute>().id }.getOrNull()
|
|
136
|
+
?: runCatching { entry.toRoute<DynamicDialogRoute>().id }.getOrNull()
|
|
137
|
+
}
|
|
138
|
+
aliveIds.add(screenId)
|
|
139
|
+
registry.retainOnly(aliveIds)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
NavHost(
|
|
144
|
+
navController,
|
|
145
|
+
startDestination = startDestination,
|
|
146
|
+
enterTransition = { stackEnter() },
|
|
147
|
+
exitTransition = { stackExit() },
|
|
148
|
+
popEnterTransition = { stackPopEnter() },
|
|
149
|
+
popExitTransition = { stackPopExit() },
|
|
150
|
+
) {
|
|
151
|
+
composable<DynamicScreenRoute> { backStackEntry ->
|
|
152
|
+
val route = backStackEntry.toRoute<DynamicScreenRoute>()
|
|
153
|
+
val screen = registry.getScreen(route.id)
|
|
154
|
+
|
|
155
|
+
if (screen != null) {
|
|
156
|
+
StackTransitionDecor(id = route.id, isStackRoute = true) {
|
|
157
|
+
StackScreen(
|
|
158
|
+
id = route.id,
|
|
159
|
+
name = screen.name,
|
|
160
|
+
content = screen.content,
|
|
161
|
+
navigationOptions = screen.options
|
|
162
|
+
)
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
composable<DynamicDialogRoute>(
|
|
168
|
+
enterTransition = {
|
|
169
|
+
slideInVertically(
|
|
170
|
+
animationSpec = tween(300),
|
|
171
|
+
initialOffsetY = { it }
|
|
172
|
+
)
|
|
173
|
+
},
|
|
174
|
+
exitTransition = null,
|
|
175
|
+
popEnterTransition = { fadeIn(animationSpec = tween(0)) },
|
|
176
|
+
popExitTransition = {
|
|
177
|
+
slideOutVertically(
|
|
178
|
+
animationSpec = tween(300),
|
|
179
|
+
targetOffsetY = { it }
|
|
180
|
+
)
|
|
181
|
+
}
|
|
182
|
+
) { backStackEntry ->
|
|
183
|
+
val route = backStackEntry.toRoute<DynamicDialogRoute>()
|
|
184
|
+
val screen = registry.getScreen(route.id)
|
|
185
|
+
|
|
186
|
+
if (screen != null) {
|
|
187
|
+
StackTransitionDecor(id = route.id, isStackRoute = false) {
|
|
188
|
+
StackScreen(
|
|
189
|
+
id = route.id,
|
|
190
|
+
name = screen.name,
|
|
191
|
+
content = screen.content,
|
|
192
|
+
navigationOptions = screen.options
|
|
193
|
+
)
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
DisposableEffect(Unit) {
|
|
203
|
+
onDispose {
|
|
204
|
+
navigator.dispose()
|
|
205
|
+
registry.unregisterScreen(screenId)
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
val LocalMaxApi = staticCompositionLocalOf<IMaxApi?> { null }
|
|
211
|
+
|