@momo-kits/native-kits 0.156.6-dialog.1-debug → 0.156.6-newcompose.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/compose/build.gradle.kts +1 -4
- package/compose/build.gradle.kts.backup +0 -3
- package/compose/compose.podspec +11 -5
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +2 -162
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +12 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +19 -17
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +198 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +42 -51
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +23 -10
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +15 -12
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +14 -13
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +6 -7
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +576 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +0 -4
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +1 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +1 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +1 -49
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +152 -48
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +14 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +29 -12
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +4 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +2 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +4 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +1 -22
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +15 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +2 -178
- package/gradle/libs.versions.toml +1 -1
- package/gradle.properties +1 -1
- package/ios/Application/FloatingButton.swift +1 -1
- package/ios/Badge/BadgeRibbon.swift +2 -2
- package/ios/Image/Image.swift +5 -1
- package/ios/Input/Input.swift +2 -2
- package/ios/Input/InputPhoneNumber.swift +7 -3
- package/ios/Popup/PopupDisplay.swift +6 -12
- package/local.properties +1 -1
- package/package.json +1 -1
- package/publish.sh +26 -1
- package/compose/MoMoComposeKits.podspec +0 -54
|
@@ -18,10 +18,8 @@ import androidx.compose.runtime.remember
|
|
|
18
18
|
import androidx.compose.runtime.staticCompositionLocalOf
|
|
19
19
|
import androidx.compose.ui.unit.Dp
|
|
20
20
|
import androidx.compose.ui.unit.dp
|
|
21
|
-
import androidx.compose.ui.window.DialogProperties
|
|
22
21
|
import androidx.navigation.compose.NavHost
|
|
23
22
|
import androidx.navigation.compose.composable
|
|
24
|
-
import androidx.navigation.compose.dialog
|
|
25
23
|
import androidx.navigation.compose.rememberNavController
|
|
26
24
|
import androidx.navigation.toRoute
|
|
27
25
|
import vn.momo.kits.application.AppConfig
|
|
@@ -32,11 +30,9 @@ import vn.momo.kits.application.MiniAppContext
|
|
|
32
30
|
import vn.momo.kits.const.AppNavigationBar
|
|
33
31
|
import vn.momo.kits.const.AppStatusBar
|
|
34
32
|
import vn.momo.kits.const.AppTheme
|
|
35
|
-
import vn.momo.kits.const.AppThemeController
|
|
36
33
|
import vn.momo.kits.const.Theme
|
|
37
34
|
import vn.momo.kits.const.ThemeAssets
|
|
38
35
|
import vn.momo.kits.const.defaultTheme
|
|
39
|
-
import vn.momo.kits.platform.ConfigureDialogWindow
|
|
40
36
|
import vn.momo.kits.utils.getAppStatusBarHeight
|
|
41
37
|
import vn.momo.maxapi.IMaxApi
|
|
42
38
|
|
|
@@ -83,7 +79,6 @@ fun NavigationContainer(
|
|
|
83
79
|
LocalNavigator provides navigator,
|
|
84
80
|
LocalMaxApi provides maxApi,
|
|
85
81
|
AppTheme provides theme.value,
|
|
86
|
-
AppThemeController provides { theme.value = it },
|
|
87
82
|
AppStatusBar provides statusBarHeight,
|
|
88
83
|
AppNavigationBar provides navigationBarHeight,
|
|
89
84
|
ApplicationContext provides mergedContext,
|
|
@@ -95,7 +90,6 @@ fun NavigationContainer(
|
|
|
95
90
|
}
|
|
96
91
|
|
|
97
92
|
NavHost(navController, startDestination = startDestination) {
|
|
98
|
-
// ── Stack screens (push/replace/reset) ──────────────────────────
|
|
99
93
|
composable<DynamicScreenRoute>(
|
|
100
94
|
enterTransition = {
|
|
101
95
|
slideInHorizontally(
|
|
@@ -124,7 +118,6 @@ fun NavigationContainer(
|
|
|
124
118
|
}
|
|
125
119
|
}
|
|
126
120
|
|
|
127
|
-
// ── Present screens (vertical slide dialog) ──────────────────────
|
|
128
121
|
composable<DynamicDialogRoute>(
|
|
129
122
|
enterTransition = {
|
|
130
123
|
slideInVertically (
|
|
@@ -152,48 +145,6 @@ fun NavigationContainer(
|
|
|
152
145
|
)
|
|
153
146
|
}
|
|
154
147
|
}
|
|
155
|
-
|
|
156
|
-
// ── Bottom Sheet dialog ──────────────────────────────────────────
|
|
157
|
-
dialog<DynamicBottomSheetRoute>(
|
|
158
|
-
dialogProperties = DialogProperties(
|
|
159
|
-
dismissOnBackPress = false,
|
|
160
|
-
dismissOnClickOutside = false,
|
|
161
|
-
usePlatformDefaultWidth = false
|
|
162
|
-
)
|
|
163
|
-
) { backStackEntry ->
|
|
164
|
-
val route = backStackEntry.toRoute<DynamicBottomSheetRoute>()
|
|
165
|
-
val screen = DynamicScreenRegistry.getScreen(route.id)
|
|
166
|
-
ConfigureDialogWindow()
|
|
167
|
-
screen?.content?.invoke()
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// ── Modal dialog ─────────────────────────────────────────────────
|
|
171
|
-
dialog<DynamicModalRoute>(
|
|
172
|
-
dialogProperties = DialogProperties(
|
|
173
|
-
dismissOnBackPress = false,
|
|
174
|
-
dismissOnClickOutside = false,
|
|
175
|
-
usePlatformDefaultWidth = false,
|
|
176
|
-
)
|
|
177
|
-
) { backStackEntry ->
|
|
178
|
-
val route = backStackEntry.toRoute<DynamicModalRoute>()
|
|
179
|
-
val screen = DynamicScreenRegistry.getScreen(route.id)
|
|
180
|
-
ConfigureDialogWindow()
|
|
181
|
-
screen?.content?.invoke()
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// ── Snack Bar dialog ─────────────────────────────────────────────
|
|
185
|
-
dialog<DynamicSnackBarRoute>(
|
|
186
|
-
dialogProperties = DialogProperties(
|
|
187
|
-
dismissOnBackPress = false,
|
|
188
|
-
dismissOnClickOutside = false,
|
|
189
|
-
usePlatformDefaultWidth = false
|
|
190
|
-
)
|
|
191
|
-
) { backStackEntry ->
|
|
192
|
-
val route = backStackEntry.toRoute<DynamicSnackBarRoute>()
|
|
193
|
-
val screen = DynamicScreenRegistry.getScreen(route.id)
|
|
194
|
-
ConfigureDialogWindow()
|
|
195
|
-
screen?.content?.invoke()
|
|
196
|
-
}
|
|
197
148
|
}
|
|
198
149
|
}
|
|
199
150
|
|
|
@@ -207,3 +158,4 @@ fun NavigationContainer(
|
|
|
207
158
|
val LocalMaxApi = staticCompositionLocalOf<IMaxApi?> {
|
|
208
159
|
error("No MaxApi provided")
|
|
209
160
|
}
|
|
161
|
+
|
|
@@ -3,6 +3,8 @@ package vn.momo.kits.navigation
|
|
|
3
3
|
import androidx.compose.foundation.layout.Box
|
|
4
4
|
import androidx.compose.foundation.layout.fillMaxSize
|
|
5
5
|
import androidx.compose.runtime.Composable
|
|
6
|
+
import androidx.compose.runtime.MutableState
|
|
7
|
+
import androidx.compose.runtime.mutableStateOf
|
|
6
8
|
import androidx.compose.runtime.staticCompositionLocalOf
|
|
7
9
|
import androidx.compose.ui.Alignment
|
|
8
10
|
import androidx.compose.ui.Modifier
|
|
@@ -70,18 +72,31 @@ class Navigator(
|
|
|
70
72
|
fun pop(count: Int = 1, callBack: (() -> Unit)? = null) {
|
|
71
73
|
scope.launch {
|
|
72
74
|
repeat(count) {
|
|
73
|
-
|
|
75
|
+
if (OverplayComponentRegistry.getOverplayType() == OverplayComponentType.SNACK_BAR){
|
|
76
|
+
dismissScreen()
|
|
77
|
+
OverplayComponentRegistry.hardClearAfterDismiss()
|
|
78
|
+
}
|
|
79
|
+
else if (OverplayComponentRegistry.isOverplayShowing()){
|
|
80
|
+
dismissOverplay()
|
|
81
|
+
} else {
|
|
82
|
+
dismissScreen()
|
|
83
|
+
}
|
|
74
84
|
}
|
|
75
85
|
callBack?.invoke()
|
|
76
86
|
}
|
|
77
87
|
}
|
|
88
|
+
private suspend fun dismissOverplay(isDelay: Boolean = true) {
|
|
89
|
+
OverplayComponentRegistry.clear()
|
|
90
|
+
if (isDelay) delay(300L)
|
|
91
|
+
OverplayComponentRegistry.hardClearAfterDismiss()
|
|
92
|
+
}
|
|
78
93
|
|
|
79
|
-
private suspend fun
|
|
80
|
-
if (navController.previousBackStackEntry != null)
|
|
94
|
+
private suspend fun dismissScreen() {
|
|
95
|
+
if (navController.previousBackStackEntry != null){
|
|
81
96
|
navController.popBackStack()
|
|
82
97
|
delay(300L)
|
|
83
|
-
DynamicScreenRegistry.getLatestScreen()?.let {
|
|
84
|
-
DynamicScreenRegistry.unregisterScreen(
|
|
98
|
+
DynamicScreenRegistry.getLatestScreen()?.let { it1 ->
|
|
99
|
+
DynamicScreenRegistry.unregisterScreen(it1.id)
|
|
85
100
|
}
|
|
86
101
|
} else {
|
|
87
102
|
maxApi?.dismiss { }
|
|
@@ -107,14 +122,8 @@ class Navigator(
|
|
|
107
122
|
barrierDismissible: Boolean = true,
|
|
108
123
|
onDismiss: (() -> Unit)? = null
|
|
109
124
|
){
|
|
110
|
-
val
|
|
111
|
-
|
|
112
|
-
content = content,
|
|
113
|
-
barrierDismissible = barrierDismissible,
|
|
114
|
-
onDismiss = onDismiss
|
|
115
|
-
)
|
|
116
|
-
}, null)
|
|
117
|
-
navController.navigate(DynamicModalRoute(route.id))
|
|
125
|
+
val id = DynamicScreenRegistry.getLatestScreen()?.id ?: -1
|
|
126
|
+
OverplayComponentRegistry.registerOverplay(id, content, OverplayComponentType.MODAL, false, barrierDismissible, onDismiss)
|
|
118
127
|
}
|
|
119
128
|
|
|
120
129
|
fun showBottomSheet(
|
|
@@ -124,42 +133,32 @@ class Navigator(
|
|
|
124
133
|
onDismiss: (() -> Unit)? = null,
|
|
125
134
|
bottomSheetHeader: BottomHeader? = null
|
|
126
135
|
){
|
|
127
|
-
val
|
|
128
|
-
|
|
129
|
-
content = content,
|
|
130
|
-
header = bottomSheetHeader ?: Title(),
|
|
131
|
-
isSurface = isSurface,
|
|
132
|
-
barrierDismissible = barrierDismissible,
|
|
133
|
-
onDismiss = onDismiss
|
|
134
|
-
)
|
|
135
|
-
}, null)
|
|
136
|
-
navController.navigate(DynamicBottomSheetRoute(route.id))
|
|
136
|
+
val id = DynamicScreenRegistry.getLatestScreen()?.id ?: -1
|
|
137
|
+
OverplayComponentRegistry.registerOverplay(id, content, OverplayComponentType.BOTTOM_SHEET, isSurface, barrierDismissible, onDismiss, bottomSheetHeader)
|
|
137
138
|
}
|
|
138
139
|
|
|
139
140
|
fun showSnackBar(snackBar: SnackBar, onDismiss: (() -> Unit)? = null) {
|
|
140
|
-
val
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
141
|
+
val id = DynamicScreenRegistry.getLatestScreen()?.id ?: -1
|
|
142
|
+
scope.launch {
|
|
143
|
+
OverplayComponentRegistry.registerOverplay(
|
|
144
|
+
id = id,
|
|
145
|
+
content = {
|
|
146
|
+
SnackBar(snackBar, onDismiss)
|
|
147
|
+
},
|
|
148
|
+
type = OverplayComponentType.SNACK_BAR,
|
|
149
|
+
onDismiss = onDismiss
|
|
150
|
+
)
|
|
151
|
+
}
|
|
148
152
|
}
|
|
149
153
|
|
|
150
154
|
fun hideSnackBar() {
|
|
151
155
|
scope.launch {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
DynamicScreenRegistry.getLatestScreen()?.let {
|
|
156
|
-
DynamicScreenRegistry.unregisterScreen(it.id)
|
|
157
|
-
}
|
|
158
|
-
}
|
|
156
|
+
OverplayComponentRegistry.clear()
|
|
157
|
+
delay(250L)
|
|
158
|
+
OverplayComponentRegistry.hardClearAfterDismiss()
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
-
|
|
163
162
|
fun dispose(){
|
|
164
163
|
scope.cancel()
|
|
165
164
|
}
|
|
@@ -175,15 +174,6 @@ data class DynamicScreenRoute(val id: Int)
|
|
|
175
174
|
@Serializable
|
|
176
175
|
data class DynamicDialogRoute(val id: Int)
|
|
177
176
|
|
|
178
|
-
@Serializable
|
|
179
|
-
data class DynamicBottomSheetRoute(val id: Int)
|
|
180
|
-
|
|
181
|
-
@Serializable
|
|
182
|
-
data class DynamicModalRoute(val id: Int)
|
|
183
|
-
|
|
184
|
-
@Serializable
|
|
185
|
-
data class DynamicSnackBarRoute(val id: Int)
|
|
186
|
-
|
|
187
177
|
data class DynamicScreen(
|
|
188
178
|
val id: Int,
|
|
189
179
|
val content: @Composable () -> Unit,
|
|
@@ -225,3 +215,117 @@ object DynamicScreenRegistry {
|
|
|
225
215
|
screens[id]?.options = options
|
|
226
216
|
}
|
|
227
217
|
}
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
sealed class OverplayComponentParams {
|
|
221
|
+
class Modal(
|
|
222
|
+
val onDismiss: (() -> Unit)? = null,
|
|
223
|
+
val barrierDismissible: Boolean = true
|
|
224
|
+
) : OverplayComponentParams()
|
|
225
|
+
|
|
226
|
+
class BottomSheet(
|
|
227
|
+
val isSurface: Boolean = false,
|
|
228
|
+
val onDismiss: (() -> Unit)? = null,
|
|
229
|
+
val barrierDismissible: Boolean = true,
|
|
230
|
+
val bottomSheetHeader: BottomHeader? = null,
|
|
231
|
+
) : OverplayComponentParams()
|
|
232
|
+
|
|
233
|
+
class SnackBar() : OverplayComponentParams()
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
data class OverplayComponent(
|
|
237
|
+
val id: Int,
|
|
238
|
+
val type: OverplayComponentType? = null,
|
|
239
|
+
val content: @Composable () -> Unit,
|
|
240
|
+
val params: OverplayComponentParams? = null
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
enum class OverplayComponentType {
|
|
244
|
+
MODAL, BOTTOM_SHEET, SNACK_BAR
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
object OverplayComponentRegistry {
|
|
248
|
+
private var currentOverlayComponent : MutableState<OverplayComponent?> = mutableStateOf(null)
|
|
249
|
+
private var requestClose: (() -> Unit)? = null
|
|
250
|
+
internal fun bindClose(handler: (() -> Unit)?) {
|
|
251
|
+
requestClose = handler
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
fun registerOverplay(
|
|
255
|
+
id: Int,
|
|
256
|
+
content: @Composable () -> Unit,
|
|
257
|
+
type: OverplayComponentType,
|
|
258
|
+
isSurface: Boolean = false,
|
|
259
|
+
barrierDismissible: Boolean = true,
|
|
260
|
+
onDismiss: (() -> Unit)?,
|
|
261
|
+
bottomSheetHeader: BottomHeader? = null,
|
|
262
|
+
){
|
|
263
|
+
val params = when(type){
|
|
264
|
+
OverplayComponentType.MODAL -> OverplayComponentParams.Modal(onDismiss, barrierDismissible)
|
|
265
|
+
OverplayComponentType.BOTTOM_SHEET -> OverplayComponentParams.BottomSheet(isSurface, onDismiss, barrierDismissible, bottomSheetHeader)
|
|
266
|
+
OverplayComponentType.SNACK_BAR -> OverplayComponentParams.SnackBar()
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
currentOverlayComponent.value = OverplayComponent(
|
|
270
|
+
id = id,
|
|
271
|
+
type = type,
|
|
272
|
+
content = content,
|
|
273
|
+
params = params
|
|
274
|
+
)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
fun isOverplayShowing(): Boolean = currentOverlayComponent.value != null
|
|
278
|
+
|
|
279
|
+
fun getOverplayType(): OverplayComponentType? = currentOverlayComponent.value?.type
|
|
280
|
+
|
|
281
|
+
fun currentRootId(): Int? = currentOverlayComponent.value?.id
|
|
282
|
+
|
|
283
|
+
fun clear(){
|
|
284
|
+
if (requestClose != null) {
|
|
285
|
+
requestClose?.invoke()
|
|
286
|
+
} else {
|
|
287
|
+
currentOverlayComponent.value = null
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
internal fun hardClearAfterDismiss() {
|
|
292
|
+
currentOverlayComponent.value = null
|
|
293
|
+
requestClose = null
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
@Composable
|
|
297
|
+
fun OverlayComponent(){
|
|
298
|
+
val overplay = currentOverlayComponent.value ?: return
|
|
299
|
+
|
|
300
|
+
when (val params = overplay.params) {
|
|
301
|
+
is OverplayComponentParams.BottomSheet -> {
|
|
302
|
+
BottomSheet(
|
|
303
|
+
content = overplay.content,
|
|
304
|
+
header = params.bottomSheetHeader ?: Title(),
|
|
305
|
+
isSurface = params.isSurface,
|
|
306
|
+
barrierDismissible = params.barrierDismissible,
|
|
307
|
+
onDismiss = params.onDismiss
|
|
308
|
+
)
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
is OverplayComponentParams.Modal -> {
|
|
312
|
+
ModalScreen(
|
|
313
|
+
content = overplay.content,
|
|
314
|
+
barrierDismissible = params.barrierDismissible,
|
|
315
|
+
onDismiss = params.onDismiss
|
|
316
|
+
)
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
is OverplayComponentParams.SnackBar -> {
|
|
320
|
+
Box(
|
|
321
|
+
modifier = Modifier.fillMaxSize(),
|
|
322
|
+
contentAlignment = Alignment.BottomCenter
|
|
323
|
+
) {
|
|
324
|
+
overplay.content()
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
null -> {}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
@@ -138,6 +138,8 @@ internal fun StackScreen(
|
|
|
138
138
|
Box(Modifier.zIndex(7f)){
|
|
139
139
|
FloatingContent()
|
|
140
140
|
}
|
|
141
|
+
|
|
142
|
+
OverplayView(bottomTabIndex = bottomTabIndex, id = id)
|
|
141
143
|
}
|
|
142
144
|
}
|
|
143
145
|
}
|
|
@@ -237,7 +239,18 @@ fun FooterContent(){
|
|
|
237
239
|
}
|
|
238
240
|
}
|
|
239
241
|
|
|
240
|
-
|
|
242
|
+
@Composable
|
|
243
|
+
fun OverplayView(bottomTabIndex: Int, id: Int){
|
|
244
|
+
val overplayType = OverplayComponentRegistry.getOverplayType()
|
|
245
|
+
|
|
246
|
+
if (overplayType != null) {
|
|
247
|
+
Box(Modifier.zIndex(if (overplayType == OverplayComponentType.SNACK_BAR) 3f else 8f).fillMaxSize()){
|
|
248
|
+
if (bottomTabIndex != -1) return@Box
|
|
249
|
+
if (OverplayComponentRegistry.currentRootId() != id) return@Box
|
|
250
|
+
OverplayComponentRegistry.OverlayComponent()
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
241
254
|
|
|
242
255
|
@Composable
|
|
243
256
|
fun Footer(footerComponent: @Composable (() -> Unit)?, bottomPadding: Dp) {
|
|
@@ -40,13 +40,15 @@ import vn.momo.kits.const.Colors
|
|
|
40
40
|
import vn.momo.kits.const.Radius
|
|
41
41
|
import vn.momo.kits.const.Spacing
|
|
42
42
|
import vn.momo.kits.application.IsShowBaseLineDebug
|
|
43
|
+
import vn.momo.kits.components.BadgeDot
|
|
44
|
+
import vn.momo.kits.components.DotSize
|
|
43
45
|
import vn.momo.kits.const.Typography
|
|
44
46
|
import vn.momo.kits.modifier.conditional
|
|
45
47
|
import vn.momo.kits.modifier.noFeedbackClickable
|
|
46
48
|
import vn.momo.kits.platform.getScreenDimensions
|
|
47
49
|
|
|
48
50
|
val floatingButtonWidth = 75.dp
|
|
49
|
-
const val BOTTOM_TAB_BAR_HEIGHT =
|
|
51
|
+
const val BOTTOM_TAB_BAR_HEIGHT = 64
|
|
50
52
|
|
|
51
53
|
@Composable
|
|
52
54
|
fun BottomTabBar(
|
|
@@ -142,6 +144,18 @@ fun RowScope.renderTabBarItem(
|
|
|
142
144
|
|
|
143
145
|
@Composable
|
|
144
146
|
fun TabBarItem(item: BottomTabItem, selected: Boolean, onClick: () -> Unit) {
|
|
147
|
+
fun isNumber(label: String): Boolean {
|
|
148
|
+
val numberRegex = "^\\d+$".toRegex()
|
|
149
|
+
return numberRegex.matches(label)
|
|
150
|
+
}
|
|
151
|
+
fun formatLabel(label: String): String? {
|
|
152
|
+
if (isNumber(label) && label.toInt() == 0) {
|
|
153
|
+
return null
|
|
154
|
+
}
|
|
155
|
+
return label
|
|
156
|
+
}
|
|
157
|
+
val badgeLabel = item.badgeLabel?.let { formatLabel(it) }
|
|
158
|
+
|
|
145
159
|
Box(modifier = Modifier
|
|
146
160
|
.fillMaxSize()
|
|
147
161
|
.padding(horizontal = Spacing.XXS)
|
|
@@ -156,31 +170,34 @@ fun TabBarItem(item: BottomTabItem, selected: Boolean, onClick: () -> Unit) {
|
|
|
156
170
|
Column(
|
|
157
171
|
modifier = Modifier
|
|
158
172
|
.fillMaxSize()
|
|
159
|
-
.padding(horizontal = Spacing.
|
|
173
|
+
.padding(horizontal = Spacing.S, vertical = Spacing.S)
|
|
160
174
|
.noFeedbackClickable {
|
|
161
175
|
onClick()
|
|
162
176
|
},
|
|
163
177
|
horizontalAlignment = Alignment.CenterHorizontally,
|
|
164
|
-
verticalArrangement = Arrangement.
|
|
178
|
+
verticalArrangement = Arrangement.Center
|
|
165
179
|
) {
|
|
166
180
|
Icon(
|
|
167
181
|
source = item.icon,
|
|
168
|
-
|
|
182
|
+
size = 28.dp,
|
|
183
|
+
modifier = Modifier.padding(Spacing.XS),
|
|
169
184
|
color = if (selected) AppTheme.current.colors.primary else AppTheme.current.colors.text.hint)
|
|
170
185
|
Text(
|
|
171
186
|
text = item.label,
|
|
172
187
|
color = if (selected) AppTheme.current.colors.primary else AppTheme.current.colors.text.hint,
|
|
173
|
-
style = Typography.labelXsMedium,
|
|
188
|
+
style = if (selected) Typography.labelXsMedium else Typography.descriptionXsRegular,
|
|
174
189
|
maxLines = 1,
|
|
175
190
|
overflow = TextOverflow.Ellipsis
|
|
176
191
|
)
|
|
177
192
|
}
|
|
178
|
-
if(
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
193
|
+
if (badgeLabel != null) {
|
|
194
|
+
if (badgeLabel.isEmpty())
|
|
195
|
+
BadgeDot(
|
|
196
|
+
size = DotSize.Small,
|
|
197
|
+
modifier = Modifier.offset(x = 50.dp, y = (-48).dp)
|
|
198
|
+
)
|
|
199
|
+
else
|
|
200
|
+
Badge(badgeLabel, modifier = Modifier.offset(x = 44.dp, y = (-42).dp))
|
|
184
201
|
}
|
|
185
202
|
}
|
|
186
203
|
}
|
|
@@ -190,7 +207,7 @@ fun FloatingButton(data: BottomTabFloatingButton) {
|
|
|
190
207
|
Column(
|
|
191
208
|
modifier = Modifier
|
|
192
209
|
.width(floatingButtonWidth)
|
|
193
|
-
.padding(horizontal = Spacing.XXS)
|
|
210
|
+
.padding(horizontal = Spacing.XXS, vertical = Spacing.S)
|
|
194
211
|
.conditional(IsShowBaseLineDebug) {
|
|
195
212
|
border(1.dp, Colors.blue_03)
|
|
196
213
|
}
|
|
@@ -35,6 +35,7 @@ import vn.momo.kits.application.IsShowBaseLineDebug
|
|
|
35
35
|
import vn.momo.kits.const.Spacing
|
|
36
36
|
import vn.momo.kits.modifier.activeOpacityClickable
|
|
37
37
|
import vn.momo.kits.modifier.conditional
|
|
38
|
+
import vn.momo.kits.modifier.setAutomationId
|
|
38
39
|
import vn.momo.kits.navigation.LocalHeaderRightWidthPx
|
|
39
40
|
import vn.momo.kits.navigation.LocalNavigator
|
|
40
41
|
import vn.momo.kits.navigation.LocalOptions
|
|
@@ -119,14 +120,15 @@ fun Header(onBackHandler: (() -> Unit)? = null) {
|
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
@Composable
|
|
122
|
-
fun BackButton(borderColor: Color, backgroundButton: Color, tintIconColor: Color, onBackHandler: () -> Unit){
|
|
123
|
+
private fun BackButton(borderColor: Color, backgroundButton: Color, tintIconColor: Color, onBackHandler: () -> Unit){
|
|
123
124
|
Box(
|
|
124
125
|
modifier = Modifier
|
|
125
126
|
.size(28.dp)
|
|
126
127
|
.background(backgroundButton, RoundedCornerShape(100))
|
|
127
128
|
.border(width = 0.2.dp, color = borderColor, shape = RoundedCornerShape(100))
|
|
128
129
|
.activeOpacityClickable(onClick = onBackHandler)
|
|
129
|
-
.padding(Spacing.XS)
|
|
130
|
+
.padding(Spacing.XS)
|
|
131
|
+
.setAutomationId("btn_navigation_back"),
|
|
130
132
|
contentAlignment = Alignment.Center
|
|
131
133
|
) {
|
|
132
134
|
Icon(
|
|
@@ -10,6 +10,7 @@ import androidx.compose.ui.unit.sp
|
|
|
10
10
|
import androidx.compose.ui.zIndex
|
|
11
11
|
import vn.momo.kits.components.Text
|
|
12
12
|
import vn.momo.kits.const.Typography
|
|
13
|
+
import vn.momo.kits.modifier.setAutomationId
|
|
13
14
|
|
|
14
15
|
@Composable
|
|
15
16
|
fun HeaderTitle(
|
|
@@ -17,7 +18,7 @@ fun HeaderTitle(
|
|
|
17
18
|
color: Color? = null,
|
|
18
19
|
) {
|
|
19
20
|
Text(
|
|
20
|
-
modifier = Modifier.fillMaxWidth().zIndex(1f),
|
|
21
|
+
modifier = Modifier.fillMaxWidth().zIndex(1f).setAutomationId("title_navigation_header"),
|
|
21
22
|
text = title,
|
|
22
23
|
textAlign = TextAlign.Start,
|
|
23
24
|
style = Typography.actionSBold.copy(
|
|
@@ -29,7 +29,7 @@ import vn.momo.kits.const.AppNavigationBar
|
|
|
29
29
|
import vn.momo.kits.navigation.LocalFooterHeightPx
|
|
30
30
|
import vn.momo.kits.navigation.LocalNavigator
|
|
31
31
|
import vn.momo.kits.navigation.LocalOptions
|
|
32
|
-
|
|
32
|
+
import vn.momo.kits.navigation.OverplayComponentRegistry
|
|
33
33
|
|
|
34
34
|
sealed class SnackBar(open val duration: Long? = null) {
|
|
35
35
|
data class Custom(
|
|
@@ -102,6 +102,9 @@ fun SnackBar(
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
DisposableEffect(Unit) {
|
|
105
|
+
OverplayComponentRegistry.bindClose {
|
|
106
|
+
closeEvent()
|
|
107
|
+
}
|
|
105
108
|
onDispose {
|
|
106
109
|
onDismiss?.invoke()
|
|
107
110
|
}
|
|
@@ -5,7 +5,6 @@ import androidx.compose.ui.Modifier
|
|
|
5
5
|
import androidx.compose.ui.graphics.Color
|
|
6
6
|
import androidx.compose.ui.graphics.NativePaint
|
|
7
7
|
import androidx.compose.ui.unit.Dp
|
|
8
|
-
import vn.momo.kits.components.Options
|
|
9
8
|
|
|
10
9
|
data class ScreenDimension(
|
|
11
10
|
val width: Int,
|
|
@@ -40,24 +39,4 @@ expect fun LottieAnimation(
|
|
|
40
39
|
|
|
41
40
|
expect fun NativePaint.setColor(
|
|
42
41
|
color: Color = Color.Black
|
|
43
|
-
)
|
|
44
|
-
@Composable
|
|
45
|
-
expect fun NativeImage(
|
|
46
|
-
source: Any,
|
|
47
|
-
options: Options,
|
|
48
|
-
loading: Boolean,
|
|
49
|
-
onLoading: () -> Unit = {},
|
|
50
|
-
onSuccess: () -> Unit = {},
|
|
51
|
-
onError: () -> Unit = {},
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Configures the current Dialog window's system-bar behaviour.
|
|
56
|
-
*
|
|
57
|
-
* @param decorFitsSystemWindows When `false` (the default) the dialog window
|
|
58
|
-
* extends behind the status bar and navigation bar so that a full-screen
|
|
59
|
-
* scrim/background covers the entire display uniformly.
|
|
60
|
-
* Pass `true` to restore the default platform inset handling.
|
|
61
|
-
*/
|
|
62
|
-
@Composable
|
|
63
|
-
expect fun ConfigureDialogWindow(decorFitsSystemWindows: Boolean = false)
|
|
42
|
+
)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
package vn.momo.kits.utils
|
|
2
|
+
|
|
3
|
+
import androidx.compose.runtime.Composable
|
|
4
|
+
import vn.momo.kits.application.LocalComponentInformation
|
|
5
|
+
|
|
6
|
+
@Composable
|
|
7
|
+
fun getComponentId(
|
|
8
|
+
componentName: String? = null,
|
|
9
|
+
accessibilityLabel: String? = null,
|
|
10
|
+
): String {
|
|
11
|
+
val componentInformation = LocalComponentInformation.current
|
|
12
|
+
if (accessibilityLabel != null) return accessibilityLabel
|
|
13
|
+
if (componentInformation?.componentId != null) return componentInformation.componentId
|
|
14
|
+
return ""
|
|
15
|
+
}
|