@momo-kits/native-kits 0.162.2-beta.2-debug → 0.162.2-beta.3-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/.codegraph/.gitignore +5 -0
- 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/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +2 -7
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +12 -13
- 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 +6 -17
- 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 +5 -19
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +8 -33
- 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 +27 -26
- 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 +3 -11
- 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/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 +7 -8
- 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/Theme.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +24 -40
- 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 +5 -15
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +65 -24
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +48 -33
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +58 -57
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +28 -25
- 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/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/Platform.ios.kt +0 -2
- package/example/ios/Example.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/Example.xcscheme +32 -0
- package/example/ios/Example.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
- package/example/ios/Example.xcworkspace/xcuserdata/sonnguyen.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/example/ios/Example.xcworkspace/xcuserdata/sonnguyen.xcuserdatad/WorkspaceSettings.xcsettings +16 -0
- package/example/ios/Example.xcworkspace/xcuserdata/sonnguyen.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +6 -0
- package/example/ios/Example.xcworkspace/xcuserdata/sonnguyen.xcuserdatad/xcschemes/xcschememanagement.plist +5 -0
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/MoMoUIKits.xcscheme +58 -0
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/Pods-Example.xcscheme +58 -0
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/SDWebImage.xcscheme +58 -0
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/SDWebImageSwiftUI.xcscheme +58 -0
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/SkeletonUI.xcscheme +58 -0
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/lottie-ios-LottiePrivacyInfo.xcscheme +58 -0
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/lottie-ios.xcscheme +58 -0
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/sonnguyen.xcuserdatad/xcschemes/xcschememanagement.plist +60 -0
- package/gradle/libs.versions.toml +2 -0
- package/gradle.properties +1 -1
- package/ios/Application/ApplicationEnvironment.swift +1 -0
- package/ios/Application/FontScaleStore.swift +59 -0
- package/ios/Typography/Text.swift +12 -7
- package/ios/Typography/Typography.swift +13 -8
- package/local.properties +8 -0
- package/package.json +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +0 -17
package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt
CHANGED
|
@@ -2,15 +2,10 @@ package vn.momo.kits.components.datetimepicker
|
|
|
2
2
|
|
|
3
3
|
import androidx.compose.runtime.Composable
|
|
4
4
|
import androidx.compose.runtime.remember
|
|
5
|
+
import kotlinx.datetime.*
|
|
6
|
+
import kotlinx.datetime.number
|
|
5
7
|
import kotlin.time.Clock
|
|
6
8
|
import kotlin.time.ExperimentalTime
|
|
7
|
-
import kotlinx.datetime.DatePeriod
|
|
8
|
-
import kotlinx.datetime.LocalDateTime
|
|
9
|
-
import kotlinx.datetime.TimeZone
|
|
10
|
-
import kotlinx.datetime.minus
|
|
11
|
-
import kotlinx.datetime.number
|
|
12
|
-
import kotlinx.datetime.plus
|
|
13
|
-
import kotlinx.datetime.toLocalDateTime
|
|
14
9
|
|
|
15
10
|
/**
|
|
16
11
|
* Format a LocalDateTime object into a string
|
|
@@ -19,13 +14,13 @@ fun formatLocalDateTime(dateTime: LocalDateTime, format: String = "yyyy-MM-dd HH
|
|
|
19
14
|
return when (format) {
|
|
20
15
|
"yyyy-MM-dd HH:mm" -> "${dateTime.year}-${paddingNum(dateTime.month.number)}-${
|
|
21
16
|
paddingNum(
|
|
22
|
-
dateTime.
|
|
17
|
+
dateTime.day
|
|
23
18
|
)
|
|
24
19
|
} ${paddingNum(dateTime.hour)}:${paddingNum(dateTime.minute)}"
|
|
25
20
|
|
|
26
|
-
"dd-MM-yyyy" -> "${paddingNum(dateTime.
|
|
21
|
+
"dd-MM-yyyy" -> "${paddingNum(dateTime.day)}-${paddingNum(dateTime.month.number)}-${dateTime.year}"
|
|
27
22
|
"HH:mm" -> "${paddingNum(dateTime.hour)}:${paddingNum(dateTime.minute)}"
|
|
28
|
-
else -> "${dateTime.year}-${paddingNum(dateTime.month.number)}-${paddingNum(dateTime.
|
|
23
|
+
else -> "${dateTime.year}-${paddingNum(dateTime.month.number)}-${paddingNum(dateTime.day)} ${
|
|
29
24
|
paddingNum(
|
|
30
25
|
dateTime.hour
|
|
31
26
|
)
|
|
@@ -60,11 +55,11 @@ fun getDaysInMonth(
|
|
|
60
55
|
var endDay = daysInMonth
|
|
61
56
|
|
|
62
57
|
if (year == minDate.year && month == minDate.month.number) {
|
|
63
|
-
startDay = minDate.
|
|
58
|
+
startDay = minDate.day
|
|
64
59
|
}
|
|
65
60
|
|
|
66
61
|
if (year == maxDate.year && month == maxDate.month.number) {
|
|
67
|
-
endDay = maxDate.
|
|
62
|
+
endDay = maxDate.day
|
|
68
63
|
}
|
|
69
64
|
|
|
70
65
|
val days = mutableListOf<String>()
|
|
@@ -170,8 +165,8 @@ fun createRelativeDate(years: Int): LocalDateTime {
|
|
|
170
165
|
|
|
171
166
|
return LocalDateTime(
|
|
172
167
|
adjustedDate.year,
|
|
173
|
-
adjustedDate.
|
|
174
|
-
adjustedDate.
|
|
168
|
+
adjustedDate.month.number,
|
|
169
|
+
adjustedDate.day,
|
|
175
170
|
currentDateTime.hour,
|
|
176
171
|
currentDateTime.minute
|
|
177
172
|
)
|
|
@@ -10,13 +10,7 @@ import androidx.compose.foundation.lazy.LazyColumn
|
|
|
10
10
|
import androidx.compose.foundation.lazy.LazyListState
|
|
11
11
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
|
12
12
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
13
|
-
import androidx.compose.runtime
|
|
14
|
-
import androidx.compose.runtime.LaunchedEffect
|
|
15
|
-
import androidx.compose.runtime.getValue
|
|
16
|
-
import androidx.compose.runtime.mutableStateOf
|
|
17
|
-
import androidx.compose.runtime.remember
|
|
18
|
-
import androidx.compose.runtime.setValue
|
|
19
|
-
import androidx.compose.runtime.snapshotFlow
|
|
13
|
+
import androidx.compose.runtime.*
|
|
20
14
|
import androidx.compose.ui.Alignment
|
|
21
15
|
import androidx.compose.ui.Modifier
|
|
22
16
|
import androidx.compose.ui.draw.alpha
|
|
@@ -25,6 +19,7 @@ import androidx.compose.ui.platform.LocalDensity
|
|
|
25
19
|
import androidx.compose.ui.unit.Dp
|
|
26
20
|
import androidx.compose.ui.unit.dp
|
|
27
21
|
import androidx.compose.ui.zIndex
|
|
22
|
+
import kotlinx.coroutines.FlowPreview
|
|
28
23
|
import kotlinx.coroutines.delay
|
|
29
24
|
import kotlinx.coroutines.flow.collect
|
|
30
25
|
import kotlinx.coroutines.flow.debounce
|
|
@@ -36,12 +31,14 @@ import vn.momo.kits.const.Colors
|
|
|
36
31
|
import vn.momo.kits.const.Radius
|
|
37
32
|
import vn.momo.kits.const.Typography
|
|
38
33
|
import kotlin.math.abs
|
|
34
|
+
import kotlin.time.Duration.Companion.milliseconds
|
|
39
35
|
|
|
40
36
|
private val wheelItemHeight = 42.dp
|
|
41
37
|
private val wheelPickerBorderWidth = 1.dp
|
|
42
38
|
|
|
39
|
+
@OptIn(FlowPreview::class)
|
|
43
40
|
@Composable
|
|
44
|
-
fun WheelPicker(
|
|
41
|
+
internal fun WheelPicker(
|
|
45
42
|
name: String,
|
|
46
43
|
data: List<String>,
|
|
47
44
|
selectedData: String,
|
|
@@ -68,7 +65,7 @@ fun WheelPicker(
|
|
|
68
65
|
LaunchedEffect(paddedData) {
|
|
69
66
|
snapshotFlow { selectedIndex }
|
|
70
67
|
.distinctUntilChanged()
|
|
71
|
-
.debounce(50)
|
|
68
|
+
.debounce(50.milliseconds)
|
|
72
69
|
.onEach {
|
|
73
70
|
val value = paddedData.getOrNull(it)
|
|
74
71
|
if (!value.isNullOrEmpty()) {
|
|
@@ -95,7 +92,7 @@ fun WheelPicker(
|
|
|
95
92
|
} else {
|
|
96
93
|
-abs(firstItemOffset)
|
|
97
94
|
}
|
|
98
|
-
delay(50)
|
|
95
|
+
delay(50.milliseconds)
|
|
99
96
|
listState.animateScrollBy(offset.toFloat())
|
|
100
97
|
val centeredIndex = firstItemIdx + (if (isScrollUp) 1 else 0) + 2
|
|
101
98
|
if (centeredIndex in 2 until paddedData.size - 2) {
|
|
@@ -145,7 +142,7 @@ fun WheelPicker(
|
|
|
145
142
|
}
|
|
146
143
|
|
|
147
144
|
@Composable
|
|
148
|
-
fun WheelPickerItem(
|
|
145
|
+
internal fun WheelPickerItem(
|
|
149
146
|
text: String,
|
|
150
147
|
isSelected: Boolean,
|
|
151
148
|
index: Int,
|
|
@@ -7,28 +7,13 @@ import androidx.compose.ui.text.TextStyle
|
|
|
7
7
|
import androidx.compose.ui.text.font.FontFamily
|
|
8
8
|
import androidx.compose.ui.text.font.FontWeight
|
|
9
9
|
import androidx.compose.ui.text.style.TextDecoration
|
|
10
|
-
import androidx.compose.ui.unit
|
|
11
|
-
import androidx.compose.ui.unit.TextUnit
|
|
12
|
-
import androidx.compose.ui.unit.TextUnitType
|
|
13
|
-
import androidx.compose.ui.unit.dp
|
|
14
|
-
import androidx.compose.ui.unit.sp
|
|
10
|
+
import androidx.compose.ui.unit.*
|
|
15
11
|
import org.jetbrains.compose.resources.Font
|
|
16
12
|
import org.jetbrains.compose.resources.FontResource
|
|
17
13
|
import org.jetbrains.compose.resources.InternalResourceApi
|
|
18
|
-
import vn.momo.kits.application.
|
|
14
|
+
import vn.momo.kits.application.LocalFontScaleConfig
|
|
19
15
|
import vn.momo.kits.platform.getScreenDimensions
|
|
20
|
-
import vn.momo.uikits.resources
|
|
21
|
-
import vn.momo.uikits.resources.momosignature
|
|
22
|
-
import vn.momo.uikits.resources.momotrustdisplay
|
|
23
|
-
import vn.momo.uikits.resources.sfprotext_black
|
|
24
|
-
import vn.momo.uikits.resources.sfprotext_bold
|
|
25
|
-
import vn.momo.uikits.resources.sfprotext_heavy
|
|
26
|
-
import vn.momo.uikits.resources.sfprotext_light
|
|
27
|
-
import vn.momo.uikits.resources.sfprotext_medium
|
|
28
|
-
import vn.momo.uikits.resources.sfprotext_regular
|
|
29
|
-
import vn.momo.uikits.resources.sfprotext_semibold
|
|
30
|
-
import vn.momo.uikits.resources.sfprotext_thin
|
|
31
|
-
import vn.momo.uikits.resources.sfprotext_ultralight
|
|
16
|
+
import vn.momo.uikits.resources.*
|
|
32
17
|
import kotlin.math.max
|
|
33
18
|
import kotlin.math.min
|
|
34
19
|
|
|
@@ -37,59 +22,58 @@ const val MAX_FONT_SCALE = 1.5f
|
|
|
37
22
|
const val MAX_DEVICE_SCALE = 5
|
|
38
23
|
|
|
39
24
|
@Composable
|
|
40
|
-
fun scaleSize(size: Float): Float {
|
|
41
|
-
val
|
|
42
|
-
val
|
|
43
|
-
val
|
|
25
|
+
fun scaleSize(size: Float, userScaleRate: Float? = null): Float {
|
|
26
|
+
val fontScaleConfig = LocalFontScaleConfig.current
|
|
27
|
+
val useOSFontScale = fontScaleConfig.useOSFontScale
|
|
28
|
+
val customRate = userScaleRate ?: fontScaleConfig.userScaleRate ?: 1f
|
|
44
29
|
|
|
45
|
-
val
|
|
46
|
-
val fontScale =
|
|
30
|
+
val deviceScale = getScreenDimensions().width / DEFAULT_SCREEN_SIZE
|
|
31
|
+
val fontScale = fontScaleConfig.osFontScale ?: LocalDensity.current.fontScale
|
|
32
|
+
|
|
33
|
+
if (!useOSFontScale) {
|
|
34
|
+
return if (customRate > 1f) customRate * size else size
|
|
35
|
+
}
|
|
47
36
|
|
|
48
37
|
var fontSizeScaleDevice = size
|
|
49
38
|
var fontSizeScaleOS = size
|
|
50
|
-
|
|
51
39
|
if (deviceScale > 1) {
|
|
52
40
|
fontSizeScaleDevice =
|
|
53
41
|
min(deviceScale * fontSizeScaleDevice, fontSizeScaleDevice + MAX_DEVICE_SCALE)
|
|
54
42
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
fontSizeScaleOS = min(fontScale * fontSizeScaleOS, fontSizeScaleOS * scaleSizeMaxRate)
|
|
43
|
+
if (fontScale > 1f) {
|
|
44
|
+
fontSizeScaleOS = min(fontScale * fontSizeScaleOS, fontSizeScaleOS * MAX_FONT_SCALE)
|
|
58
45
|
}
|
|
59
46
|
|
|
60
|
-
return max(
|
|
61
|
-
fontSizeScaleDevice,
|
|
62
|
-
fontSizeScaleOS
|
|
63
|
-
)
|
|
47
|
+
return max(fontSizeScaleDevice, fontSizeScaleOS)
|
|
64
48
|
}
|
|
65
49
|
|
|
66
50
|
@Composable
|
|
67
|
-
fun scaleSize(size: TextUnit): TextUnit {
|
|
51
|
+
fun scaleSize(size: TextUnit, userScaleRate: Float? = null): TextUnit {
|
|
68
52
|
if (!size.isSp) return size
|
|
69
53
|
|
|
70
54
|
val density = LocalDensity.current
|
|
71
55
|
|
|
72
|
-
val scaled = scaleSize(size.value)
|
|
56
|
+
val scaled = scaleSize(size.value, userScaleRate)
|
|
73
57
|
val spValue = scaled / density.fontScale
|
|
74
58
|
|
|
75
59
|
return TextUnit(value = spValue, type = TextUnitType.Sp)
|
|
76
60
|
}
|
|
77
61
|
|
|
78
62
|
@Composable
|
|
79
|
-
fun scaleSize(size: Dp): Dp {
|
|
80
|
-
return scaleSize(size.value).dp
|
|
63
|
+
fun scaleSize(size: Dp, userScaleRate: Float? = null): Dp {
|
|
64
|
+
return scaleSize(size.value, userScaleRate).dp
|
|
81
65
|
}
|
|
82
66
|
|
|
83
67
|
@Composable
|
|
84
|
-
fun scaleSize(textStyle: TextStyle): TextStyle {
|
|
68
|
+
fun scaleSize(textStyle: TextStyle, userScaleRate: Float? = null): TextStyle {
|
|
85
69
|
return textStyle.copy(
|
|
86
70
|
fontSize = if (textStyle.fontSize != TextUnit.Unspecified)
|
|
87
|
-
scaleSize(textStyle.fontSize)
|
|
71
|
+
scaleSize(textStyle.fontSize, userScaleRate)
|
|
88
72
|
else
|
|
89
73
|
TextUnit.Unspecified,
|
|
90
74
|
|
|
91
75
|
lineHeight = if (textStyle.lineHeight != TextUnit.Unspecified)
|
|
92
|
-
scaleSize(textStyle.lineHeight)
|
|
76
|
+
scaleSize(textStyle.lineHeight, userScaleRate)
|
|
93
77
|
else
|
|
94
78
|
TextUnit.Unspecified,
|
|
95
79
|
)
|
|
@@ -98,7 +82,7 @@ fun scaleSize(textStyle: TextStyle): TextStyle {
|
|
|
98
82
|
|
|
99
83
|
@OptIn(InternalResourceApi::class)
|
|
100
84
|
@Composable
|
|
101
|
-
fun getFont(font: FontResource): FontFamily {
|
|
85
|
+
internal fun getFont(font: FontResource): FontFamily {
|
|
102
86
|
return FontFamily(Font(font))
|
|
103
87
|
}
|
|
104
88
|
|
|
@@ -20,11 +20,6 @@ fun Modifier.setAutomationId(accessibilityId: String, mergeDescendants: Boolean
|
|
|
20
20
|
}
|
|
21
21
|
}}
|
|
22
22
|
|
|
23
|
-
/**
|
|
24
|
-
* Alternative for [setAutomationId]
|
|
25
|
-
*
|
|
26
|
-
* reason: [link](https://developer.android.com/develop/ui/compose/custom-modifiers#composable_function_modifiers_are_never_skipped)
|
|
27
|
-
* */
|
|
28
23
|
fun Modifier.kitsAutomationId(accessibilityId: String, label: String? = null) =
|
|
29
24
|
this then KitsAutomationIdElement(accessibilityId, label)
|
|
30
25
|
|
|
@@ -1,14 +1,104 @@
|
|
|
1
1
|
package vn.momo.kits.modifier
|
|
2
2
|
|
|
3
|
-
import androidx.compose.
|
|
3
|
+
import androidx.compose.animation.core.LinearEasing
|
|
4
|
+
import androidx.compose.animation.core.RepeatMode
|
|
5
|
+
import androidx.compose.animation.core.animateFloat
|
|
6
|
+
import androidx.compose.animation.core.infiniteRepeatable
|
|
7
|
+
import androidx.compose.animation.core.rememberInfiniteTransition
|
|
8
|
+
import androidx.compose.animation.core.tween
|
|
4
9
|
import androidx.compose.runtime.Composable
|
|
10
|
+
import androidx.compose.runtime.getValue
|
|
5
11
|
import androidx.compose.ui.Modifier
|
|
12
|
+
import androidx.compose.ui.draw.drawWithContent
|
|
13
|
+
import androidx.compose.ui.geometry.Offset
|
|
14
|
+
import androidx.compose.ui.graphics.Color
|
|
15
|
+
import androidx.compose.ui.graphics.drawscope.clipRect
|
|
16
|
+
import androidx.compose.ui.text.TextStyle
|
|
17
|
+
import androidx.compose.ui.text.drawText
|
|
18
|
+
import androidx.compose.ui.text.font.FontWeight
|
|
19
|
+
import androidx.compose.ui.text.rememberTextMeasurer
|
|
20
|
+
import androidx.compose.ui.unit.sp
|
|
6
21
|
import vn.momo.kits.application.IsShowBaseLineDebug
|
|
7
22
|
import vn.momo.kits.const.Colors
|
|
8
23
|
|
|
24
|
+
@Suppress("ExperimentalAnnotationRetention")
|
|
25
|
+
@RequiresOptIn(
|
|
26
|
+
message = "This is internal API of native-kits, become internal in next sprint",
|
|
27
|
+
level = RequiresOptIn.Level.WARNING,
|
|
28
|
+
)
|
|
29
|
+
@Retention(AnnotationRetention.BINARY)
|
|
30
|
+
@Target(
|
|
31
|
+
AnnotationTarget.CLASS,
|
|
32
|
+
AnnotationTarget.FUNCTION,
|
|
33
|
+
AnnotationTarget.PROPERTY,
|
|
34
|
+
)
|
|
35
|
+
annotation class InternalApi
|
|
36
|
+
|
|
37
|
+
@Composable
|
|
38
|
+
fun DeprecatedModifier(text: String = "Deprecated component"): Modifier = debugMarker(
|
|
39
|
+
label = text,
|
|
40
|
+
background = Colors.red_04.copy(alpha = 0.7f),
|
|
41
|
+
textColor = Colors.red_01,
|
|
42
|
+
animationLabel = "deprecatedMarquee",
|
|
43
|
+
)
|
|
44
|
+
|
|
9
45
|
@Composable
|
|
10
|
-
fun
|
|
11
|
-
|
|
12
|
-
|
|
46
|
+
private fun debugMarker(
|
|
47
|
+
label: String,
|
|
48
|
+
background: Color,
|
|
49
|
+
textColor: Color,
|
|
50
|
+
animationLabel: String,
|
|
51
|
+
): Modifier {
|
|
52
|
+
if (!IsShowBaseLineDebug) return Modifier
|
|
53
|
+
|
|
54
|
+
val textMeasurer = rememberTextMeasurer()
|
|
55
|
+
val marquee = rememberInfiniteTransition(label = animationLabel)
|
|
56
|
+
val progress by marquee.animateFloat(
|
|
57
|
+
initialValue = 0f,
|
|
58
|
+
targetValue = 1f,
|
|
59
|
+
animationSpec = infiniteRepeatable(
|
|
60
|
+
animation = tween(durationMillis = 4000, easing = LinearEasing),
|
|
61
|
+
repeatMode = RepeatMode.Restart,
|
|
62
|
+
),
|
|
63
|
+
label = "${animationLabel}Progress",
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
return Modifier.drawWithContent {
|
|
67
|
+
drawContent()
|
|
68
|
+
drawRect(color = background)
|
|
69
|
+
|
|
70
|
+
if (size.width <= 0f || size.height <= 0f) return@drawWithContent
|
|
71
|
+
|
|
72
|
+
val fontPx = (size.width * 0.1f).coerceIn(12.sp.toPx(), 20.sp.toPx())
|
|
73
|
+
val style = TextStyle(
|
|
74
|
+
color = textColor,
|
|
75
|
+
fontSize = fontPx.toSp(),
|
|
76
|
+
fontWeight = FontWeight.Bold,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
val intrinsic = textMeasurer.measure(
|
|
80
|
+
text = label,
|
|
81
|
+
style = style,
|
|
82
|
+
maxLines = 1,
|
|
83
|
+
softWrap = false,
|
|
84
|
+
)
|
|
85
|
+
val textW = intrinsic.size.width
|
|
86
|
+
val textH = intrinsic.size.height
|
|
87
|
+
val y = (size.height - textH) / 2f
|
|
88
|
+
|
|
89
|
+
if (textW <= size.width) {
|
|
90
|
+
drawText(
|
|
91
|
+
textLayoutResult = intrinsic,
|
|
92
|
+
topLeft = Offset((size.width - textW) / 2f, y),
|
|
93
|
+
)
|
|
94
|
+
} else {
|
|
95
|
+
clipRect(right = size.width, bottom = size.height) {
|
|
96
|
+
val gap = textW * 0.5f
|
|
97
|
+
val travel = textW + gap
|
|
98
|
+
val x = -progress * travel
|
|
99
|
+
drawText(textLayoutResult = intrinsic, topLeft = Offset(x, y))
|
|
100
|
+
drawText(textLayoutResult = intrinsic, topLeft = Offset(x + travel, y))
|
|
101
|
+
}
|
|
102
|
+
}
|
|
13
103
|
}
|
|
14
104
|
}
|
|
@@ -41,7 +41,7 @@ import vn.momo.kits.const.AppTheme
|
|
|
41
41
|
import vn.momo.kits.const.Colors
|
|
42
42
|
import vn.momo.kits.const.Radius
|
|
43
43
|
import vn.momo.kits.const.Spacing
|
|
44
|
-
import vn.momo.kits.application.
|
|
44
|
+
import vn.momo.kits.application.LocalContext
|
|
45
45
|
import vn.momo.kits.application.IsShowBaseLineDebug
|
|
46
46
|
import vn.momo.kits.const.Typography
|
|
47
47
|
import vn.momo.kits.navigation.tracking.ScreenTracker
|
|
@@ -73,7 +73,7 @@ internal fun BottomSheet(
|
|
|
73
73
|
val coroutineScope = rememberCoroutineScope()
|
|
74
74
|
|
|
75
75
|
val maxApi = LocalMaxApi.current
|
|
76
|
-
val context =
|
|
76
|
+
val context = LocalContext.current
|
|
77
77
|
|
|
78
78
|
DisposableEffect(Unit) {
|
|
79
79
|
ScreenTracker.trackPopupDisplayed(
|
|
@@ -10,11 +10,7 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
|
10
10
|
import androidx.compose.foundation.layout.Box
|
|
11
11
|
import androidx.compose.foundation.layout.fillMaxSize
|
|
12
12
|
import androidx.compose.foundation.layout.wrapContentSize
|
|
13
|
-
import androidx.compose.runtime
|
|
14
|
-
import androidx.compose.runtime.DisposableEffect
|
|
15
|
-
import androidx.compose.runtime.LaunchedEffect
|
|
16
|
-
import androidx.compose.runtime.remember
|
|
17
|
-
import androidx.compose.runtime.rememberCoroutineScope
|
|
13
|
+
import androidx.compose.runtime.*
|
|
18
14
|
import androidx.compose.ui.Alignment
|
|
19
15
|
import androidx.compose.ui.Modifier
|
|
20
16
|
import androidx.compose.ui.draw.alpha
|
|
@@ -22,7 +18,7 @@ import androidx.compose.ui.draw.scale
|
|
|
22
18
|
import androidx.compose.ui.graphics.Color
|
|
23
19
|
import androidx.compose.ui.unit.dp
|
|
24
20
|
import kotlinx.coroutines.launch
|
|
25
|
-
import vn.momo.kits.application.
|
|
21
|
+
import vn.momo.kits.application.LocalContext
|
|
26
22
|
import vn.momo.kits.application.IsShowBaseLineDebug
|
|
27
23
|
import vn.momo.kits.const.Colors
|
|
28
24
|
import vn.momo.kits.modifier.conditional
|
|
@@ -44,7 +40,7 @@ internal fun ModalScreen(
|
|
|
44
40
|
val coroutineScope = rememberCoroutineScope()
|
|
45
41
|
|
|
46
42
|
val maxApi = LocalMaxApi.current
|
|
47
|
-
val context =
|
|
43
|
+
val context = LocalContext.current
|
|
48
44
|
|
|
49
45
|
DisposableEffect(Unit) {
|
|
50
46
|
ScreenTracker.trackPopupDisplayed(
|
|
@@ -1,24 +1,16 @@
|
|
|
1
1
|
package vn.momo.kits.navigation
|
|
2
2
|
|
|
3
3
|
import androidx.compose.foundation.gestures.ScrollableState
|
|
4
|
-
import androidx.compose.runtime
|
|
5
|
-
import androidx.compose.runtime.Stable
|
|
6
|
-
import androidx.compose.runtime.State
|
|
7
|
-
import androidx.compose.runtime.mutableStateOf
|
|
8
|
-
import androidx.compose.runtime.staticCompositionLocalOf
|
|
4
|
+
import androidx.compose.runtime.*
|
|
9
5
|
import androidx.compose.ui.graphics.Color
|
|
10
6
|
import vn.momo.kits.navigation.bottomtab.setBottomTabOption
|
|
11
|
-
import vn.momo.kits.navigation.component
|
|
12
|
-
import vn.momo.kits.navigation.component.HeaderBackProps
|
|
13
|
-
import vn.momo.kits.navigation.component.HeaderRight
|
|
14
|
-
import vn.momo.kits.navigation.component.HeaderTitle
|
|
15
|
-
import vn.momo.kits.navigation.component.HeaderType
|
|
16
|
-
import vn.momo.kits.navigation.component.TitlePosition
|
|
7
|
+
import vn.momo.kits.navigation.component.*
|
|
17
8
|
|
|
18
9
|
class Navigation(
|
|
19
10
|
val id: Int = -1,
|
|
20
11
|
val bottomTabIndex: Int = -1,
|
|
21
|
-
val initOptions: NavigationOptions? = null
|
|
12
|
+
val initOptions: NavigationOptions? = null,
|
|
13
|
+
private val registry: DynamicScreenRegistry? = null
|
|
22
14
|
) {
|
|
23
15
|
private val _options = mutableStateOf(initOptions ?: NavigationOptions())
|
|
24
16
|
val currentOptions: State<NavigationOptions> get() = _options
|
|
@@ -65,7 +57,7 @@ class Navigation(
|
|
|
65
57
|
private fun updateOptions(updated: NavigationOptions) {
|
|
66
58
|
_options.value = updated
|
|
67
59
|
if (bottomTabIndex != -1) setBottomTabOption(bottomTabIndex, updated)
|
|
68
|
-
if (id != -1)
|
|
60
|
+
if (id != -1) registry?.setOptions(id, updated)
|
|
69
61
|
}
|
|
70
62
|
}
|
|
71
63
|
|
|
@@ -95,8 +87,6 @@ data class KeyboardOptions(
|
|
|
95
87
|
val keyboardShouldPersistTaps: Boolean = false,
|
|
96
88
|
val useAvoidKeyboard: Boolean = true
|
|
97
89
|
)
|
|
98
|
-
|
|
99
|
-
|
|
100
90
|
data class ScrollData(
|
|
101
91
|
val scrollable: Boolean = true,
|
|
102
92
|
val scrollState: ScrollableState? = null,
|
|
@@ -22,50 +22,57 @@ fun NavigationContainer(
|
|
|
22
22
|
initialScreen: @Composable () -> Unit,
|
|
23
23
|
options: NavigationOptions? = null,
|
|
24
24
|
initialTheme: Theme = defaultTheme,
|
|
25
|
-
|
|
25
|
+
miniAppContext: MiniAppContext? = null,
|
|
26
26
|
maxApi: IMaxApi? = null,
|
|
27
27
|
setNavigator: ((Navigator) -> Unit)? = null,
|
|
28
28
|
statusBarHeight: Dp? = null,
|
|
29
|
-
|
|
30
|
-
language: String? = null
|
|
29
|
+
localize: Localize? = null,
|
|
31
30
|
){
|
|
32
31
|
val navController = rememberNavController()
|
|
33
|
-
val
|
|
32
|
+
val registry = remember { DynamicScreenRegistry() }
|
|
33
|
+
val navigator = remember { Navigator(navController = navController, maxApi = maxApi, registry = registry) }
|
|
34
34
|
val statusBarHeight = statusBarHeight ?: getAppStatusBarHeight()
|
|
35
35
|
val navigationBarHeight = getNavigationBarHeight()
|
|
36
36
|
|
|
37
|
-
val parentContext =
|
|
38
|
-
val mergedContext = MiniAppContext.merge(parentContext,
|
|
37
|
+
val parentContext = LocalContext.current
|
|
38
|
+
val mergedContext = MiniAppContext.merge(parentContext, miniAppContext)
|
|
39
39
|
|
|
40
40
|
val theme = remember { mutableStateOf(initialTheme) }
|
|
41
|
+
val fallbackLocalize = remember { Localize() }
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
val resolvedLocalize = localize ?: fallbackLocalize
|
|
44
|
+
|
|
45
|
+
var observerFontScaleConfig by remember { mutableStateOf(mergedContext?.fontScaleConfig) }
|
|
46
|
+
LaunchedEffect(maxApi, resolvedLocalize) {
|
|
47
|
+
val api = maxApi ?: return@LaunchedEffect
|
|
48
|
+
runCatching {
|
|
49
|
+
api.getLanguage(callback = { data ->
|
|
50
|
+
if (parseLanguage(data) == Localize.EN) {
|
|
51
|
+
resolvedLocalize.changeLanguage(Localize.EN)
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
api.observer(FONT_SCALE_OBSERVER_KEY).collect { data ->
|
|
55
|
+
observerFontScaleConfig = parseFontScaleConfig(data)
|
|
56
|
+
}
|
|
50
57
|
}
|
|
51
58
|
}
|
|
52
59
|
|
|
53
|
-
val screenId = rememberSaveable {
|
|
54
|
-
|
|
60
|
+
val screenId = rememberSaveable { registry.nextId() }
|
|
61
|
+
registry.bind(screenId, initialScreenName, initialScreen, options)
|
|
55
62
|
val startDestination = remember(screenId) { DynamicScreenRoute(screenId) }
|
|
56
63
|
|
|
57
64
|
ProvideNavigationEventDispatcherOwner {
|
|
58
65
|
CompositionLocalProvider(
|
|
59
66
|
LocalNavigator provides navigator,
|
|
67
|
+
LocalDynamicScreenRegistry provides registry,
|
|
60
68
|
LocalMaxApi provides maxApi,
|
|
61
69
|
AppTheme provides theme.value,
|
|
62
70
|
AppStatusBar provides statusBarHeight,
|
|
63
71
|
AppNavigationBar provides navigationBarHeight,
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
) {
|
|
72
|
+
LocalContext provides mergedContext,
|
|
73
|
+
LocalLocalize provides resolvedLocalize,
|
|
74
|
+
LocalFontScaleConfig provides (observerFontScaleConfig ?: LocalFontScaleConfig.current),
|
|
75
|
+
) {
|
|
69
76
|
LaunchedEffect(Unit) {
|
|
70
77
|
setNavigator?.invoke(navigator)
|
|
71
78
|
}
|
|
@@ -88,7 +95,7 @@ fun NavigationContainer(
|
|
|
88
95
|
}
|
|
89
96
|
) { backStackEntry ->
|
|
90
97
|
val route = backStackEntry.toRoute<DynamicScreenRoute>()
|
|
91
|
-
val screen =
|
|
98
|
+
val screen = registry.getScreen(route.id)
|
|
92
99
|
|
|
93
100
|
if (screen != null) {
|
|
94
101
|
StackScreen(
|
|
@@ -117,7 +124,7 @@ fun NavigationContainer(
|
|
|
117
124
|
}
|
|
118
125
|
) { backStackEntry ->
|
|
119
126
|
val route = backStackEntry.toRoute<DynamicDialogRoute>()
|
|
120
|
-
val screen =
|
|
127
|
+
val screen = registry.getScreen(route.id)
|
|
121
128
|
|
|
122
129
|
if (screen != null) {
|
|
123
130
|
StackScreen(
|
|
@@ -135,7 +142,7 @@ fun NavigationContainer(
|
|
|
135
142
|
DisposableEffect(Unit) {
|
|
136
143
|
onDispose {
|
|
137
144
|
navigator.dispose()
|
|
138
|
-
|
|
145
|
+
registry.unregisterScreen(screenId)
|
|
139
146
|
}
|
|
140
147
|
}
|
|
141
148
|
}
|
|
@@ -143,3 +150,37 @@ fun NavigationContainer(
|
|
|
143
150
|
val LocalMaxApi = staticCompositionLocalOf<IMaxApi?> {
|
|
144
151
|
error("No MaxApi provided")
|
|
145
152
|
}
|
|
153
|
+
|
|
154
|
+
private const val FONT_SCALE_OBSERVER_KEY = "font_scale_config"
|
|
155
|
+
|
|
156
|
+
private fun parseLanguage(raw: Map<String, Any?>?): String? {
|
|
157
|
+
val code = (raw?.get("response") as? String)?.trim()?.lowercase()
|
|
158
|
+
if (code.isNullOrEmpty()) return null
|
|
159
|
+
return if (code.startsWith(Localize.EN)) Localize.EN else Localize.VI
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
private fun parseFontScaleConfig(raw: Map<String, Any?>?): FontScaleConfig? {
|
|
163
|
+
if (raw.isNullOrEmpty()) return null
|
|
164
|
+
@Suppress("UNCHECKED_CAST")
|
|
165
|
+
val data = (raw["response"] as? Map<String, Any?>)
|
|
166
|
+
?: (raw["data"] as? Map<String, Any?>)
|
|
167
|
+
?: raw
|
|
168
|
+
if (!data.containsKey("useOSFontScale") && !data.containsKey("userScaleRate")) return null
|
|
169
|
+
val useOS = when (val v = data["useOSFontScale"]) {
|
|
170
|
+
is Boolean -> v
|
|
171
|
+
is String -> v.equals("true", ignoreCase = true)
|
|
172
|
+
is Number -> v.toInt() != 0
|
|
173
|
+
else -> true
|
|
174
|
+
}
|
|
175
|
+
val rate = when (val v = data["userScaleRate"]) {
|
|
176
|
+
is Number -> v.toFloat()
|
|
177
|
+
is String -> v.toFloatOrNull()
|
|
178
|
+
else -> null
|
|
179
|
+
}
|
|
180
|
+
val osScale = when (val v = data["osFontScale"]) {
|
|
181
|
+
is Number -> v.toFloat()
|
|
182
|
+
is String -> v.toFloatOrNull()
|
|
183
|
+
else -> null
|
|
184
|
+
}
|
|
185
|
+
return FontScaleConfig(useOSFontScale = useOS, userScaleRate = rate, osFontScale = osScale)
|
|
186
|
+
}
|