@momo-kits/native-kits 0.161.2-search-header.1-debug → 0.161.3-beta.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 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +14 -8
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +26 -21
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +0 -4
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +12 -27
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +28 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +1 -1
- package/example/ios/Example.xcodeproj/xcuserdata/{vunh.xcuserdatad → huynhdung.xcuserdatad}/xcschemes/xcschememanagement.plist +1 -1
- package/example/ios/Example.xcworkspace/xcuserdata/huynhdung.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/{vunh.xcuserdatad → huynhdung.xcuserdatad}/xcschemes/xcschememanagement.plist +5 -5
- package/gradle/libs.versions.toml +1 -1
- package/gradle.properties +1 -1
- package/ios/Application/ApplicationEnvironment.swift +6 -2
- package/ios/Input/Input.swift +19 -19
- package/ios/Input/InputPhoneNumber.swift +17 -17
- package/ios/Typography/Text.swift +14 -19
- package/ios/Typography/Typography.swift +1 -22
- package/local.properties +2 -2
- package/package.json +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +0 -17
- package/example/ios/Example.xcodeproj/xcuserdata/vunh.xcuserdatad/xcschemes/ios.xcscheme +0 -36
- /package/example/ios/Example.xcworkspace/xcuserdata/{vunh.xcuserdatad → huynhdung.xcuserdatad}/xcschemes/xcschememanagement.plist +0 -0
- /package/example/ios/Pods/Pods.xcodeproj/xcuserdata/{vunh.xcuserdatad → huynhdung.xcuserdatad}/xcschemes/MoMoUIKits.xcscheme +0 -0
- /package/example/ios/Pods/Pods.xcodeproj/xcuserdata/{vunh.xcuserdatad → huynhdung.xcuserdatad}/xcschemes/Pods-Example.xcscheme +0 -0
- /package/example/ios/Pods/Pods.xcodeproj/xcuserdata/{vunh.xcuserdatad → huynhdung.xcuserdatad}/xcschemes/SDWebImage.xcscheme +0 -0
- /package/example/ios/Pods/Pods.xcodeproj/xcuserdata/{vunh.xcuserdatad → huynhdung.xcuserdatad}/xcschemes/SDWebImageSwiftUI.xcscheme +0 -0
- /package/example/ios/Pods/Pods.xcodeproj/xcuserdata/{vunh.xcuserdatad → huynhdung.xcuserdatad}/xcschemes/SkeletonUI.xcscheme +0 -0
package/compose/build.gradle.kts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
package vn.momo.kits.application
|
|
2
2
|
|
|
3
3
|
import androidx.compose.runtime.Immutable
|
|
4
|
+
import androidx.compose.runtime.mutableStateOf
|
|
4
5
|
import androidx.compose.runtime.staticCompositionLocalOf
|
|
5
6
|
import vn.momo.kits.components.TrustBannerData
|
|
6
7
|
|
|
7
8
|
@Immutable
|
|
8
9
|
data class FeatureFlags(
|
|
9
|
-
val
|
|
10
|
+
val isBaselineEnabled: Boolean? = false,
|
|
11
|
+
val isWhiteList: Boolean? = false,
|
|
12
|
+
val allowFontScale: Boolean? = true,
|
|
10
13
|
)
|
|
11
14
|
|
|
12
15
|
@Immutable
|
|
@@ -28,7 +31,6 @@ data class MiniAppContext(
|
|
|
28
31
|
val providerId: String = "",
|
|
29
32
|
val permissions: List<Map<String, Any>>? = emptyList(),
|
|
30
33
|
val features: FeatureFlags? = null,
|
|
31
|
-
val scaleSizeMaxRate: Float? = null,
|
|
32
34
|
) {
|
|
33
35
|
companion object {
|
|
34
36
|
|
|
@@ -60,7 +62,6 @@ data class MiniAppContext(
|
|
|
60
62
|
providerId = parent.providerId.ifBlank { child.providerId },
|
|
61
63
|
permissions = if (!parent.permissions.isNullOrEmpty()) parent.permissions else child.permissions,
|
|
62
64
|
features = mergeFeatureFlags(parent.features, child.features),
|
|
63
|
-
scaleSizeMaxRate = parent.scaleSizeMaxRate ?: child.scaleSizeMaxRate,
|
|
64
65
|
)
|
|
65
66
|
}
|
|
66
67
|
|
|
@@ -74,7 +75,7 @@ data class MiniAppContext(
|
|
|
74
75
|
if (child == null) return parent
|
|
75
76
|
|
|
76
77
|
return FeatureFlags(
|
|
77
|
-
|
|
78
|
+
isBaselineEnabled = parent.isBaselineEnabled ?: child.isBaselineEnabled
|
|
78
79
|
)
|
|
79
80
|
}
|
|
80
81
|
}
|
|
@@ -88,12 +89,19 @@ data class ComponentInformation(
|
|
|
88
89
|
val action: String? = null
|
|
89
90
|
)
|
|
90
91
|
|
|
91
|
-
var IsShowBaseLineDebug = false
|
|
92
|
-
|
|
93
92
|
val ApplicationContext = staticCompositionLocalOf<MiniAppContext?> {
|
|
94
93
|
null
|
|
95
94
|
}
|
|
96
95
|
|
|
96
|
+
var IsShowBaseLineDebug = false
|
|
97
|
+
|
|
98
|
+
private val UseFontScaleSystemState = mutableStateOf(true)
|
|
99
|
+
var UseFontScaleSystem: Boolean
|
|
100
|
+
get() = UseFontScaleSystemState.value
|
|
101
|
+
set(value) {
|
|
102
|
+
UseFontScaleSystemState.value = value
|
|
103
|
+
}
|
|
104
|
+
|
|
97
105
|
val AppConfig = staticCompositionLocalOf<KitConfig?> {
|
|
98
106
|
null
|
|
99
107
|
}
|
|
@@ -105,5 +113,3 @@ val AppLanguage = staticCompositionLocalOf<String?> {
|
|
|
105
113
|
val LocalComponentInformation = staticCompositionLocalOf<ComponentInformation?> {
|
|
106
114
|
null
|
|
107
115
|
}
|
|
108
|
-
|
|
109
|
-
val ScaleSizeMaxRate = staticCompositionLocalOf<Float?> { null }
|
|
@@ -69,9 +69,10 @@ import androidx.compose.ui.unit.LayoutDirection
|
|
|
69
69
|
import androidx.compose.ui.unit.dp
|
|
70
70
|
import androidx.compose.ui.unit.sp
|
|
71
71
|
import androidx.compose.runtime.staticCompositionLocalOf
|
|
72
|
-
import androidx.compose.ui.
|
|
72
|
+
import androidx.compose.ui.graphics.Color.Companion
|
|
73
73
|
import androidx.compose.ui.graphics.SolidColor
|
|
74
74
|
import androidx.compose.ui.unit.lerp
|
|
75
|
+
import kotlinx.coroutines.flow.StateFlow
|
|
75
76
|
import kotlinx.coroutines.flow.collectLatest
|
|
76
77
|
import kotlinx.coroutines.flow.mapNotNull
|
|
77
78
|
import vn.momo.kits.components.Icon
|
|
@@ -80,11 +81,11 @@ import vn.momo.kits.const.AppTheme
|
|
|
80
81
|
import vn.momo.kits.const.Colors
|
|
81
82
|
import vn.momo.kits.const.Spacing
|
|
82
83
|
import vn.momo.kits.const.Typography
|
|
84
|
+
import vn.momo.kits.modifier.conditional
|
|
83
85
|
import vn.momo.kits.modifier.kitsAutomationId
|
|
84
86
|
import vn.momo.kits.modifier.noFeedbackClickable
|
|
85
87
|
import vn.momo.kits.modifier.setAutomationId
|
|
86
88
|
import vn.momo.kits.modifier.shadow
|
|
87
|
-
import vn.momo.kits.navigation.component.HEADER_HEIGHT
|
|
88
89
|
import vn.momo.kits.utils.getAppStatusBarHeight
|
|
89
90
|
import kotlin.math.max
|
|
90
91
|
import kotlin.math.roundToInt
|
|
@@ -440,7 +441,6 @@ private class LiteScreenLayoutPolicy(
|
|
|
440
441
|
val spacing12 = Spacing.M.roundToPx()
|
|
441
442
|
val spaceBetween = headerSpaceBetween?.roundToPx() ?: spacing12
|
|
442
443
|
val statusBarPx = statusBarHeight.roundToPx()
|
|
443
|
-
val headerRowDefault = HEADER_HEIGHT.dp.roundToPx()
|
|
444
444
|
val scrollPercent = scrollPercentage.value
|
|
445
445
|
|
|
446
446
|
val contentMeasurable = measurables.find { it.layoutId == HeaderId.CONTENT_ID }
|
|
@@ -484,20 +484,26 @@ private class LiteScreenLayoutPolicy(
|
|
|
484
484
|
)
|
|
485
485
|
)
|
|
486
486
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
487
|
+
val firstRowMaxHeight = buildList {
|
|
488
|
+
add(backIconPlaceable.safeHeight)
|
|
489
|
+
add(headerRightPlaceable.safeHeight)
|
|
490
|
+
if (!isHeaderExtend) {
|
|
491
|
+
add(inputSearchPlaceable.safeHeight)
|
|
492
|
+
}
|
|
493
|
+
add(HEADER_HEIGHT.dp.roundToPx())
|
|
494
|
+
if (isHeaderExtend) {
|
|
495
|
+
add(titlePlaceable.safeHeight)
|
|
496
|
+
}
|
|
497
|
+
}.max()
|
|
498
|
+
|
|
499
|
+
var defaultHeight = statusBarPx + spacing12 + firstRowMaxHeight + spacing12
|
|
491
500
|
if (isHeaderExtend) {
|
|
492
|
-
defaultHeight
|
|
501
|
+
defaultHeight += inputSearchPlaceable.safeHeight + spacing12
|
|
493
502
|
}
|
|
494
503
|
val headerHeight = when {
|
|
495
504
|
isHeaderNone -> statusBarPx
|
|
496
505
|
!useAnimationSearch && !isHeaderExtend -> defaultHeight
|
|
497
|
-
else ->
|
|
498
|
-
val collapsableSpace = defaultHeight - statusBarPx - headerRowDefault
|
|
499
|
-
(defaultHeight - scrollPercent * collapsableSpace).toInt()
|
|
500
|
-
}
|
|
506
|
+
else -> (defaultHeight - scrollPercent * (defaultHeight - statusBarPx - HEADER_HEIGHT.dp.roundToPx())).toInt()
|
|
501
507
|
}
|
|
502
508
|
|
|
503
509
|
val layoutWidth = constraints.maxWidth
|
|
@@ -560,14 +566,14 @@ private class LiteScreenLayoutPolicy(
|
|
|
560
566
|
if (backIconPlaceable != null) {
|
|
561
567
|
backIconPlaceable.place(
|
|
562
568
|
x = startX,
|
|
563
|
-
y = startY + backIconPlaceable.verticalCenterOffset(
|
|
569
|
+
y = startY + backIconPlaceable.verticalCenterOffset(firstRowMaxHeight),
|
|
564
570
|
)
|
|
565
571
|
curX += backIconPlaceable.safeWidth + spaceBetween
|
|
566
572
|
}
|
|
567
573
|
|
|
568
574
|
headerRightPlaceable?.place(
|
|
569
575
|
x = layoutWidth - spacing12 - headerRightPlaceable.safeWidth,
|
|
570
|
-
y = startY + headerRightPlaceable.verticalCenterOffset(
|
|
576
|
+
y = startY + headerRightPlaceable.verticalCenterOffset(firstRowMaxHeight),
|
|
571
577
|
)
|
|
572
578
|
|
|
573
579
|
val titleOffset = IntOffset(
|
|
@@ -576,19 +582,19 @@ private class LiteScreenLayoutPolicy(
|
|
|
576
582
|
space = layoutWidth,
|
|
577
583
|
layoutDirection = layoutDirection,
|
|
578
584
|
),
|
|
579
|
-
y = startY + titlePlaceable.verticalCenterOffset(
|
|
585
|
+
y = startY + titlePlaceable.verticalCenterOffset(firstRowMaxHeight),
|
|
580
586
|
)
|
|
581
587
|
|
|
582
588
|
titlePlaceable?.place(titleOffset)
|
|
583
589
|
|
|
584
590
|
if (backIconPlaceable != null || headerRightPlaceable != null || titlePlaceable != null) {
|
|
585
|
-
curY +=
|
|
591
|
+
curY += firstRowMaxHeight
|
|
586
592
|
}
|
|
587
593
|
|
|
588
594
|
val inputSearchOffset = if (isHeaderExtend) {
|
|
589
|
-
val baseY = curY + inputSearchPlaceable.verticalCenterOffset(
|
|
595
|
+
val baseY = curY + inputSearchPlaceable.verticalCenterOffset(firstRowMaxHeight)
|
|
590
596
|
val y = (baseY * (1 - scrollPercent)).toInt().coerceAtLeast(
|
|
591
|
-
startY + inputSearchPlaceable.verticalCenterOffset(
|
|
597
|
+
startY + inputSearchPlaceable.verticalCenterOffset(firstRowMaxHeight)
|
|
592
598
|
)
|
|
593
599
|
IntOffset(
|
|
594
600
|
x = startX + ((backIconPlaceable.safeWidth + spaceBetween) * (scrollPercent * 2f).coerceIn(
|
|
@@ -599,7 +605,7 @@ private class LiteScreenLayoutPolicy(
|
|
|
599
605
|
} else {
|
|
600
606
|
IntOffset(
|
|
601
607
|
x = curX,
|
|
602
|
-
y = startY + inputSearchPlaceable.verticalCenterOffset(
|
|
608
|
+
y = startY + inputSearchPlaceable.verticalCenterOffset(firstRowMaxHeight),
|
|
603
609
|
)
|
|
604
610
|
}
|
|
605
611
|
val finalPosition = lerp(
|
|
@@ -817,8 +823,7 @@ private fun LiteInputSearch(
|
|
|
817
823
|
if (!placeHolder.isNullOrEmpty()) {
|
|
818
824
|
inputSearchProps.customPlaceHolder?.invoke() ?: Text(
|
|
819
825
|
text = placeHolder ?: "",
|
|
820
|
-
style = inputSearchProps.customTextStyle
|
|
821
|
-
?: Typography.bodyDefaultRegular,
|
|
826
|
+
style = inputSearchProps.customTextStyle ?: Typography.bodyDefaultRegular,
|
|
822
827
|
maxLines = 1,
|
|
823
828
|
color = theme.colors.text.hint,
|
|
824
829
|
overflow = TextOverflow.Ellipsis
|
|
@@ -21,10 +21,6 @@ import androidx.compose.ui.graphics.Color
|
|
|
21
21
|
import androidx.compose.ui.graphics.PathEffect
|
|
22
22
|
import androidx.compose.ui.graphics.StrokeCap
|
|
23
23
|
import androidx.compose.ui.unit.dp
|
|
24
|
-
import io.ktor.util.Platform
|
|
25
|
-
import vn.momo.kits.application.IsShowBaseLineDebug
|
|
26
|
-
import vn.momo.kits.const.Colors
|
|
27
|
-
import vn.momo.kits.modifier.conditional
|
|
28
24
|
import vn.momo.kits.platform.getPlatformName
|
|
29
25
|
import vn.momo.kits.platform.getStatusBarHeight
|
|
30
26
|
|
|
@@ -7,15 +7,11 @@ 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.UseFontScaleSystem
|
|
19
15
|
import vn.momo.kits.platform.getScreenDimensions
|
|
20
16
|
import vn.momo.uikits.resources.Res
|
|
21
17
|
import vn.momo.uikits.resources.momosignature
|
|
@@ -33,34 +29,23 @@ import kotlin.math.max
|
|
|
33
29
|
import kotlin.math.min
|
|
34
30
|
|
|
35
31
|
const val DEFAULT_SCREEN_SIZE = 375f
|
|
36
|
-
const val MAX_FONT_SCALE = 1.
|
|
37
|
-
const val MAX_DEVICE_SCALE = 5
|
|
32
|
+
const val MAX_FONT_SCALE = 1.2f
|
|
38
33
|
|
|
39
34
|
@Composable
|
|
40
35
|
fun scaleSize(size: Float): Float {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
if (UseFontScaleSystem) {
|
|
37
|
+
val deviceWidth = getScreenDimensions().width
|
|
38
|
+
val deviceScale = deviceWidth / DEFAULT_SCREEN_SIZE
|
|
39
|
+
val fontScale = LocalDensity.current.fontScale
|
|
44
40
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
var fontSizeScaleDevice = size
|
|
49
|
-
var fontSizeScaleOS = size
|
|
41
|
+
val maxSize = size * MAX_FONT_SCALE
|
|
42
|
+
val fontSizeScaleDevice = if (deviceScale > 1) deviceScale * size else size
|
|
43
|
+
val fontSizeScaleOS = if (fontScale > 1) fontScale * size else size
|
|
50
44
|
|
|
51
|
-
|
|
52
|
-
fontSizeScaleDevice =
|
|
53
|
-
min(deviceScale * fontSizeScaleDevice, fontSizeScaleDevice + MAX_DEVICE_SCALE)
|
|
45
|
+
return min(max(fontSizeScaleDevice, fontSizeScaleOS), maxSize)
|
|
54
46
|
}
|
|
55
47
|
|
|
56
|
-
|
|
57
|
-
fontSizeScaleOS = min(fontScale * fontSizeScaleOS, fontSizeScaleOS * scaleSizeMaxRate)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return max(
|
|
61
|
-
fontSizeScaleDevice,
|
|
62
|
-
fontSizeScaleOS
|
|
63
|
-
)
|
|
48
|
+
return size
|
|
64
49
|
}
|
|
65
50
|
|
|
66
51
|
@Composable
|
|
@@ -9,6 +9,9 @@ import androidx.navigation.compose.NavHost
|
|
|
9
9
|
import androidx.navigation.compose.composable
|
|
10
10
|
import androidx.navigation.compose.rememberNavController
|
|
11
11
|
import androidx.navigation.toRoute
|
|
12
|
+
import kotlinx.coroutines.flow.catch
|
|
13
|
+
import kotlinx.coroutines.flow.distinctUntilChanged
|
|
14
|
+
import kotlinx.coroutines.flow.map
|
|
12
15
|
import vn.momo.kits.application.*
|
|
13
16
|
import vn.momo.kits.const.*
|
|
14
17
|
import vn.momo.kits.platform.ProvideNavigationEventDispatcherOwner
|
|
@@ -54,6 +57,19 @@ fun NavigationContainer(
|
|
|
54
57
|
DynamicScreenRegistry.bind(screenId, initialScreenName, initialScreen, options)
|
|
55
58
|
val startDestination = remember(screenId) { DynamicScreenRoute(screenId) }
|
|
56
59
|
|
|
60
|
+
LaunchedEffect(maxApi) {
|
|
61
|
+
val api = maxApi ?: return@LaunchedEffect
|
|
62
|
+
runCatching {
|
|
63
|
+
api.observer("use_font_scale")
|
|
64
|
+
.map { parseUseFontScale(it) }
|
|
65
|
+
.distinctUntilChanged()
|
|
66
|
+
.catch { /* ignore observer errors, keep current value */ }
|
|
67
|
+
.collect { enabled ->
|
|
68
|
+
UseFontScaleSystem = enabled
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
57
73
|
ProvideNavigationEventDispatcherOwner {
|
|
58
74
|
CompositionLocalProvider(
|
|
59
75
|
LocalNavigator provides navigator,
|
|
@@ -64,7 +80,6 @@ fun NavigationContainer(
|
|
|
64
80
|
ApplicationContext provides mergedContext,
|
|
65
81
|
AppConfig provides config,
|
|
66
82
|
AppLanguage provides language,
|
|
67
|
-
ScaleSizeMaxRate provides mergedContext?.scaleSizeMaxRate,
|
|
68
83
|
) {
|
|
69
84
|
LaunchedEffect(Unit) {
|
|
70
85
|
setNavigator?.invoke(navigator)
|
|
@@ -143,3 +158,15 @@ fun NavigationContainer(
|
|
|
143
158
|
val LocalMaxApi = staticCompositionLocalOf<IMaxApi?> {
|
|
144
159
|
error("No MaxApi provided")
|
|
145
160
|
}
|
|
161
|
+
|
|
162
|
+
private fun parseUseFontScale(raw: Any?): Boolean = when (raw) {
|
|
163
|
+
null -> true
|
|
164
|
+
is Boolean -> raw
|
|
165
|
+
is String -> raw.isBlank() || !raw.equals("false", ignoreCase = true)
|
|
166
|
+
is Number -> raw.toInt() != 0
|
|
167
|
+
is Map<*, *> -> {
|
|
168
|
+
val nested = raw["response"] ?: raw["value"] ?: raw["data"]
|
|
169
|
+
if (nested === raw) true else parseUseFontScale(nested)
|
|
170
|
+
}
|
|
171
|
+
else -> true
|
|
172
|
+
}
|
|
@@ -274,7 +274,7 @@ fun ScreenContent(content: @Composable () -> Unit) {
|
|
|
274
274
|
Box(Modifier.fillMaxWidth().aspectRatio(animatedHeader.aspectRatio.value)) {
|
|
275
275
|
animatedHeader.composable.invoke(scrollState.value)
|
|
276
276
|
}
|
|
277
|
-
Box(Modifier.
|
|
277
|
+
Box(Modifier.padding(top = AppStatusBar.current + HEADER_HEIGHT.dp + animatedHeader.layoutOffSet)) {
|
|
278
278
|
content()
|
|
279
279
|
}
|
|
280
280
|
}
|
|
Binary file
|
|
@@ -9,35 +9,35 @@
|
|
|
9
9
|
<key>isShown</key>
|
|
10
10
|
<false />
|
|
11
11
|
<key>orderHint</key>
|
|
12
|
-
<integer>
|
|
12
|
+
<integer>0</integer>
|
|
13
13
|
</dict>
|
|
14
14
|
<key>Pods-Example.xcscheme</key>
|
|
15
15
|
<dict>
|
|
16
16
|
<key>isShown</key>
|
|
17
17
|
<false />
|
|
18
18
|
<key>orderHint</key>
|
|
19
|
-
<integer>
|
|
19
|
+
<integer>1</integer>
|
|
20
20
|
</dict>
|
|
21
21
|
<key>SDWebImage.xcscheme</key>
|
|
22
22
|
<dict>
|
|
23
23
|
<key>isShown</key>
|
|
24
24
|
<false />
|
|
25
25
|
<key>orderHint</key>
|
|
26
|
-
<integer>
|
|
26
|
+
<integer>2</integer>
|
|
27
27
|
</dict>
|
|
28
28
|
<key>SDWebImageSwiftUI.xcscheme</key>
|
|
29
29
|
<dict>
|
|
30
30
|
<key>isShown</key>
|
|
31
31
|
<false />
|
|
32
32
|
<key>orderHint</key>
|
|
33
|
-
<integer>
|
|
33
|
+
<integer>3</integer>
|
|
34
34
|
</dict>
|
|
35
35
|
<key>SkeletonUI.xcscheme</key>
|
|
36
36
|
<dict>
|
|
37
37
|
<key>isShown</key>
|
|
38
38
|
<false />
|
|
39
39
|
<key>orderHint</key>
|
|
40
|
-
<integer>
|
|
40
|
+
<integer>4</integer>
|
|
41
41
|
</dict>
|
|
42
42
|
</dict>
|
|
43
43
|
<key>SuppressBuildableAutocreation</key>
|
package/gradle.properties
CHANGED
|
@@ -18,7 +18,7 @@ kotlin.apple.xcodeCompatibility.nowarn=true
|
|
|
18
18
|
name="ComposeKits"
|
|
19
19
|
group=vn.momo.kits
|
|
20
20
|
artifact.id=kits
|
|
21
|
-
version=0.161.
|
|
21
|
+
version=0.161.3-beta.1
|
|
22
22
|
|
|
23
23
|
repo=GitLab
|
|
24
24
|
url=https://gitlab.mservice.com.vn/api/v4/projects/5400/packages/maven
|
|
@@ -17,7 +17,7 @@ public class MiniAppContext {
|
|
|
17
17
|
public var toolkitConfig: [String: Any] = [:]
|
|
18
18
|
public var providerId: String = "momo"
|
|
19
19
|
public var permissions: [[String: Any]] = []
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
public init(appId: String, appCode: String, appName: Any? = nil, appIcon: String, description: Any? = nil, support: [String: Any] = [:], toolkitConfig: [String: Any] = [:], providerId: String = "momo", permissions: [[String: Any]] = []) {
|
|
22
22
|
self.appId = appId
|
|
23
23
|
self.appCode = appCode
|
|
@@ -37,11 +37,15 @@ public class KitConfig {
|
|
|
37
37
|
public var headerGradient: String? = nil
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
public var IsShowBaseLineDebug = false
|
|
41
|
+
|
|
42
|
+
public var UseFontScaleSystem = true
|
|
43
|
+
|
|
40
44
|
public class ApplicationEnvironment: ObservableObject {
|
|
41
45
|
let applicationContext: MiniAppContext?
|
|
42
46
|
let composeApi: KitComposeApi?
|
|
43
47
|
let config: KitConfig?
|
|
44
|
-
|
|
48
|
+
|
|
45
49
|
public init(applicationContext: MiniAppContext? = nil, composeApi: KitComposeApi? = nil, config: KitConfig? = nil) {
|
|
46
50
|
self.applicationContext = applicationContext
|
|
47
51
|
self.composeApi = composeApi
|
package/ios/Input/Input.swift
CHANGED
|
@@ -4,7 +4,7 @@ import Combine
|
|
|
4
4
|
|
|
5
5
|
public struct Input: View {
|
|
6
6
|
@Binding public var text: String
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
public var placeholder: String
|
|
9
9
|
public var floatingValue: String
|
|
10
10
|
public var floatingIcon: String
|
|
@@ -30,10 +30,10 @@ public struct Input: View {
|
|
|
30
30
|
public var onFocus: (() -> Void)?
|
|
31
31
|
public var onBlur: (() -> Void)?
|
|
32
32
|
public var onRightIconPressed: (() -> Void)?
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
@State private var isFocused: Bool = false
|
|
35
35
|
@State private var isPasswordHidden: Bool = true
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
public init(
|
|
38
38
|
text: Binding<String>,
|
|
39
39
|
placeholder: String = "",
|
|
@@ -118,7 +118,7 @@ public struct Input: View {
|
|
|
118
118
|
.offset(x: Spacing.S, y: -8)
|
|
119
119
|
.zIndex(10)
|
|
120
120
|
}
|
|
121
|
-
|
|
121
|
+
|
|
122
122
|
// Input container
|
|
123
123
|
HStack(alignment: .center, spacing: 0) {
|
|
124
124
|
// Leading icon
|
|
@@ -126,7 +126,7 @@ public struct Input: View {
|
|
|
126
126
|
Icon(source: leadingIcon, size: size == .small ? 24 : 32, color: leadingIconColor)
|
|
127
127
|
.padding(.trailing, Spacing.M)
|
|
128
128
|
}
|
|
129
|
-
|
|
129
|
+
|
|
130
130
|
// Text input field
|
|
131
131
|
ZStack(alignment: .leading) {
|
|
132
132
|
if text.isEmpty {
|
|
@@ -136,7 +136,7 @@ public struct Input: View {
|
|
|
136
136
|
color: getPlaceholderColor()
|
|
137
137
|
)
|
|
138
138
|
}
|
|
139
|
-
|
|
139
|
+
|
|
140
140
|
if secureTextEntry && isPasswordHidden {
|
|
141
141
|
SecureInputField(
|
|
142
142
|
text: $text,
|
|
@@ -168,7 +168,7 @@ public struct Input: View {
|
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
|
-
|
|
171
|
+
|
|
172
172
|
// Clear button (only show when focused and has text)
|
|
173
173
|
if isFocused && !text.isEmpty {
|
|
174
174
|
SwiftUI.Button(action: {
|
|
@@ -179,14 +179,14 @@ public struct Input: View {
|
|
|
179
179
|
.padding(.leading, Spacing.S).accessibility(identifier: "ic_clear")
|
|
180
180
|
}
|
|
181
181
|
}
|
|
182
|
-
|
|
182
|
+
|
|
183
183
|
// Loading indicator
|
|
184
184
|
if loading {
|
|
185
185
|
ActivityIndicator(isAnimating: .constant(true), style: .medium)
|
|
186
186
|
.frame(width: 16, height: 16)
|
|
187
187
|
.padding(.leading, Spacing.S)
|
|
188
188
|
}
|
|
189
|
-
|
|
189
|
+
|
|
190
190
|
// Right icon (password toggle or custom icon)
|
|
191
191
|
if secureTextEntry {
|
|
192
192
|
if !text.isEmpty {
|
|
@@ -207,7 +207,7 @@ public struct Input: View {
|
|
|
207
207
|
}
|
|
208
208
|
}
|
|
209
209
|
.padding(.horizontal, Spacing.M)
|
|
210
|
-
.frame(height: scaleSize(size == .small ? 48 : 56
|
|
210
|
+
.frame(height: scaleSize(size == .small ? 48 : 56))
|
|
211
211
|
.background(
|
|
212
212
|
RoundedRectangle(cornerRadius: Radius.S)
|
|
213
213
|
.fill(Colors.black01)
|
|
@@ -217,7 +217,7 @@ public struct Input: View {
|
|
|
217
217
|
.stroke(borderColor(), lineWidth: 1)
|
|
218
218
|
)
|
|
219
219
|
}
|
|
220
|
-
|
|
220
|
+
|
|
221
221
|
// Error or hint
|
|
222
222
|
ErrorView(
|
|
223
223
|
errorMessage: error,
|
|
@@ -233,9 +233,9 @@ public struct Input: View {
|
|
|
233
233
|
}
|
|
234
234
|
}
|
|
235
235
|
}
|
|
236
|
-
|
|
236
|
+
|
|
237
237
|
// MARK: - Helpers
|
|
238
|
-
|
|
238
|
+
|
|
239
239
|
private func handleFocusChange(_ focused: Bool) {
|
|
240
240
|
isFocused = focused
|
|
241
241
|
if focused {
|
|
@@ -244,7 +244,7 @@ public struct Input: View {
|
|
|
244
244
|
onBlur?()
|
|
245
245
|
}
|
|
246
246
|
}
|
|
247
|
-
|
|
247
|
+
|
|
248
248
|
private func togglePasswordVisibility() {
|
|
249
249
|
isPasswordHidden.toggle()
|
|
250
250
|
onRightIconPressed?()
|
|
@@ -256,7 +256,7 @@ public struct Input: View {
|
|
|
256
256
|
}
|
|
257
257
|
return String(value.prefix(maxLength))
|
|
258
258
|
}
|
|
259
|
-
|
|
259
|
+
|
|
260
260
|
private func borderColor() -> Color {
|
|
261
261
|
if disabled {
|
|
262
262
|
return Colors.black04 // border.disable
|
|
@@ -269,19 +269,19 @@ public struct Input: View {
|
|
|
269
269
|
}
|
|
270
270
|
return Colors.black04 // border.default
|
|
271
271
|
}
|
|
272
|
-
|
|
272
|
+
|
|
273
273
|
private func getTextColor() -> Color {
|
|
274
274
|
return disabled ? Colors.black09 : Colors.black17
|
|
275
275
|
}
|
|
276
|
-
|
|
276
|
+
|
|
277
277
|
private func getPlaceholderColor() -> Color {
|
|
278
278
|
return disabled ? Colors.black09 : Colors.black12
|
|
279
279
|
}
|
|
280
|
-
|
|
280
|
+
|
|
281
281
|
private func getFloatingColor() -> Color {
|
|
282
282
|
return disabled ? Colors.black09 : Colors.black12
|
|
283
283
|
}
|
|
284
|
-
|
|
284
|
+
|
|
285
285
|
private func getFloatingIconColor() -> Color {
|
|
286
286
|
return disabled ? Colors.black09 : floatingIconColor
|
|
287
287
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import SwiftUI
|
|
9
9
|
public struct InputPhoneNumber: View {
|
|
10
10
|
@Binding public var text: String
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
public var placeholder: String
|
|
13
13
|
public var size: InputSize
|
|
14
14
|
public var hintText: String
|
|
@@ -22,9 +22,9 @@ public struct InputPhoneNumber: View {
|
|
|
22
22
|
public var onBlur: (() -> Void)?
|
|
23
23
|
public var onRightIconPressed: (() -> Void)?
|
|
24
24
|
public var accessibilityLabel: String?
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
@State private var isFocused: Bool = false
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
public init(
|
|
29
29
|
text: Binding<String>,
|
|
30
30
|
placeholder: String = "0123456789",
|
|
@@ -57,7 +57,7 @@ public struct InputPhoneNumber: View {
|
|
|
57
57
|
self.onRightIconPressed = onRightIconPressed
|
|
58
58
|
self.accessibilityLabel = accessibilityLabel
|
|
59
59
|
}
|
|
60
|
-
|
|
60
|
+
|
|
61
61
|
// MARK: - Body
|
|
62
62
|
public var body: some View {
|
|
63
63
|
let textBinding = Binding<String>(
|
|
@@ -67,28 +67,28 @@ public struct InputPhoneNumber: View {
|
|
|
67
67
|
self.onChangeText?(newValue)
|
|
68
68
|
}
|
|
69
69
|
)
|
|
70
|
-
|
|
70
|
+
|
|
71
71
|
VStack(alignment: .leading, spacing: 4) {
|
|
72
72
|
HStack(spacing: 0) {
|
|
73
73
|
// 🇻🇳 Flag
|
|
74
74
|
ImageView("https://static.momocdn.net/app/img/icon/ic-qrcode-package/ic_vn_flag.png")
|
|
75
75
|
.frame(width: 24, height: 24)
|
|
76
76
|
.padding(.trailing, Spacing.XS)
|
|
77
|
-
|
|
77
|
+
|
|
78
78
|
MomoText("+84", typography: size == .small ? .headerSSemibold : .headerMBold)
|
|
79
79
|
.foregroundColor(Colors.black17)
|
|
80
|
-
|
|
80
|
+
|
|
81
81
|
Rectangle()
|
|
82
82
|
.fill(Colors.black04)
|
|
83
83
|
.frame(width: 1, height: size == .small ? 24 : 32)
|
|
84
84
|
.padding(.horizontal, Spacing.M)
|
|
85
|
-
|
|
85
|
+
|
|
86
86
|
// Text input
|
|
87
87
|
ZStack(alignment: .leading) {
|
|
88
88
|
if text.isEmpty {
|
|
89
89
|
MomoText(placeholder, typography: size == .small ? .headerSSemibold : .headerMBold, color: Colors.black12)
|
|
90
90
|
}
|
|
91
|
-
|
|
91
|
+
|
|
92
92
|
TextField("", text: textBinding, onEditingChanged: { focused in
|
|
93
93
|
handleFocusChange(focused)
|
|
94
94
|
})
|
|
@@ -100,7 +100,7 @@ public struct InputPhoneNumber: View {
|
|
|
100
100
|
.accessibility(identifier: accessibilityLabel ?? "")
|
|
101
101
|
.accessibilityValue(textBinding.wrappedValue.isEmpty ? placeholder : textBinding.wrappedValue)
|
|
102
102
|
}
|
|
103
|
-
|
|
103
|
+
|
|
104
104
|
// Clear button
|
|
105
105
|
if isFocused && !text.isEmpty {
|
|
106
106
|
SwiftUI.Button(action: {
|
|
@@ -111,13 +111,13 @@ public struct InputPhoneNumber: View {
|
|
|
111
111
|
.padding(.leading, Spacing.S).accessibility(identifier: "ic_clear")
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
|
-
|
|
114
|
+
|
|
115
115
|
// Loading indicator
|
|
116
116
|
if loading {
|
|
117
117
|
ActivityIndicator(isAnimating: .constant(true), style: .medium)
|
|
118
118
|
.frame(width: 16, height: 16)
|
|
119
119
|
}
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
// ✅ Right icon
|
|
122
122
|
if !rightIcon.isEmpty {
|
|
123
123
|
SwiftUI.Button(action: { onRightIconPressed?() }) {
|
|
@@ -127,7 +127,7 @@ public struct InputPhoneNumber: View {
|
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
.padding(.horizontal, Spacing.M)
|
|
130
|
-
.frame(height: scaleSize(size == .small ? 48 : 56
|
|
130
|
+
.frame(height: scaleSize(size == .small ? 48 : 56))
|
|
131
131
|
.background(
|
|
132
132
|
RoundedRectangle(cornerRadius: Radius.S)
|
|
133
133
|
.fill(Colors.black01)
|
|
@@ -136,7 +136,7 @@ public struct InputPhoneNumber: View {
|
|
|
136
136
|
RoundedRectangle(cornerRadius: Radius.S)
|
|
137
137
|
.stroke(borderColor(), lineWidth: isFocused ? 1.5 : 1)
|
|
138
138
|
)
|
|
139
|
-
|
|
139
|
+
|
|
140
140
|
// Error or hint
|
|
141
141
|
ErrorView(
|
|
142
142
|
errorMessage: error,
|
|
@@ -145,9 +145,9 @@ public struct InputPhoneNumber: View {
|
|
|
145
145
|
)
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
|
-
|
|
148
|
+
|
|
149
149
|
// MARK: - Helpers
|
|
150
|
-
|
|
150
|
+
|
|
151
151
|
private func handleFocusChange(_ focused: Bool) {
|
|
152
152
|
isFocused = focused
|
|
153
153
|
if focused {
|
|
@@ -156,7 +156,7 @@ public struct InputPhoneNumber: View {
|
|
|
156
156
|
onBlur?()
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
|
-
|
|
159
|
+
|
|
160
160
|
private func borderColor() -> Color {
|
|
161
161
|
if !error.isEmpty { return Colors.red03 }
|
|
162
162
|
if isFocused { return Colors.primary }
|
|
@@ -1,30 +1,25 @@
|
|
|
1
1
|
import SwiftUI
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
let maxFontScale: CGFloat = scaleRate ?? 1.5
|
|
6
|
-
let maxDeviceScale: CGFloat = 5
|
|
3
|
+
private let DEFAULT_SCREEN_SIZE: CGFloat = 375
|
|
4
|
+
private let MAX_FONT_SCALE: CGFloat = 1.2
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
public func scaleSize(_ size: CGFloat) -> CGFloat {
|
|
7
|
+
if UseFontScaleSystem {
|
|
8
|
+
let deviceWidth = UIScreen.main.bounds.width
|
|
9
|
+
let deviceScale = deviceWidth / DEFAULT_SCREEN_SIZE
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
let defaultFont = UIFont.systemFont(ofSize: UIFont.labelFontSize)
|
|
12
|
+
let scaledFont = UIFontMetrics.default.scaledFont(for: defaultFont)
|
|
13
|
+
let fontScale = scaledFont.pointSize / defaultFont.pointSize
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
let maxSize = size * MAX_FONT_SCALE
|
|
16
|
+
let fontSizeScaleDevice = deviceScale > 1 ? deviceScale * size : size
|
|
17
|
+
let fontSizeScaleOS = fontScale > 1 ? fontScale * size : size
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
if deviceScale > 1 {
|
|
20
|
-
fontSizeDeviceScale = min(fontSizeDeviceScale * deviceScale, fontSizeDeviceScale + maxDeviceScale)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if fontScale > 1 {
|
|
24
|
-
fontSizeOSScale = min(fontSizeOSScale * fontScale, fontSizeOSScale * maxFontScale)
|
|
19
|
+
return min(max(fontSizeScaleDevice, fontSizeScaleOS), maxSize)
|
|
25
20
|
}
|
|
26
21
|
|
|
27
|
-
return
|
|
22
|
+
return size
|
|
28
23
|
}
|
|
29
24
|
|
|
30
25
|
public enum TypographyStyle {
|
|
@@ -2,28 +2,7 @@ import SwiftUI
|
|
|
2
2
|
|
|
3
3
|
public extension Font {
|
|
4
4
|
static func appFont(size: CGFloat) -> Font {
|
|
5
|
-
|
|
6
|
-
let maxFontScale: CGFloat = 1.5
|
|
7
|
-
let maxDeviceScale: CGFloat = 5
|
|
8
|
-
|
|
9
|
-
let deviceWidth = UIScreen.main.bounds.width
|
|
10
|
-
let deviceScale = deviceWidth / defaultScreenSize
|
|
11
|
-
|
|
12
|
-
let defaultFont = UIFont.systemFont(ofSize: UIFont.labelFontSize)
|
|
13
|
-
let scaledFont = UIFontMetrics.default.scaledFont(for: defaultFont)
|
|
14
|
-
let fontScale = scaledFont.pointSize / defaultFont.pointSize
|
|
15
|
-
|
|
16
|
-
var fontSize = size
|
|
17
|
-
|
|
18
|
-
if deviceScale > 1 {
|
|
19
|
-
fontSize = min(fontSize * deviceScale, fontSize + maxDeviceScale)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if fontScale > 1 {
|
|
23
|
-
fontSize = min(fontSize * fontScale, fontSize * maxFontScale)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return Font.system(size: fontSize)
|
|
5
|
+
return Font.system(size: scaleSize(size))
|
|
27
6
|
}
|
|
28
7
|
|
|
29
8
|
// New supported typography styles
|
package/local.properties
CHANGED
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
# Location of the SDK. This is only used by Gradle.
|
|
5
5
|
# For customization when using a Version Control System, please read the
|
|
6
6
|
# header note.
|
|
7
|
-
#
|
|
8
|
-
sdk.dir=/Users/
|
|
7
|
+
#Wed Aug 21 14:20:12 ICT 2024
|
|
8
|
+
sdk.dir=/Users/huynhdung/Library/Android/sdk
|
package/package.json
CHANGED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
package vn.momo.kits.components
|
|
2
|
-
|
|
3
|
-
import androidx.compose.runtime.Composable
|
|
4
|
-
import androidx.compose.runtime.CompositionLocalProvider
|
|
5
|
-
import vn.momo.kits.application.ScaleSizeMaxRate
|
|
6
|
-
|
|
7
|
-
@Composable
|
|
8
|
-
fun ScaleSizeScope(
|
|
9
|
-
scaleSizeMaxRate: Float? = null,
|
|
10
|
-
content: @Composable () -> Unit
|
|
11
|
-
) {
|
|
12
|
-
CompositionLocalProvider(
|
|
13
|
-
ScaleSizeMaxRate provides scaleSizeMaxRate,
|
|
14
|
-
) {
|
|
15
|
-
content()
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<Scheme
|
|
3
|
-
version = "1.3">
|
|
4
|
-
<BuildAction>
|
|
5
|
-
<BuildActionEntries>
|
|
6
|
-
<BuildActionEntry
|
|
7
|
-
buildForRunning = "YES">
|
|
8
|
-
<BuildableReference
|
|
9
|
-
BuildableIdentifier = "primary"
|
|
10
|
-
BlueprintIdentifier = "A6A920D22B2ADD1E00C1A11F"
|
|
11
|
-
BuildableName = "Example"
|
|
12
|
-
BlueprintName = "Example"
|
|
13
|
-
ReferencedContainer = "container:Example.xcodeproj">
|
|
14
|
-
</BuildableReference>
|
|
15
|
-
</BuildActionEntry>
|
|
16
|
-
</BuildActionEntries>
|
|
17
|
-
</BuildAction>
|
|
18
|
-
<LaunchAction
|
|
19
|
-
useCustomWorkingDirectory = "NO"
|
|
20
|
-
buildConfiguration = "Debug"
|
|
21
|
-
allowLocationSimulation = "YES">
|
|
22
|
-
<BuildableProductRunnable>
|
|
23
|
-
<BuildableReference
|
|
24
|
-
BuildableIdentifier = "primary"
|
|
25
|
-
BlueprintIdentifier = "A6A920D22B2ADD1E00C1A11F"
|
|
26
|
-
BuildableName = "Example"
|
|
27
|
-
BlueprintName = "Example"
|
|
28
|
-
ReferencedContainer = "container:Example.xcodeproj">
|
|
29
|
-
</BuildableReference>
|
|
30
|
-
</BuildableProductRunnable>
|
|
31
|
-
<LocationScenarioReference
|
|
32
|
-
identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
|
|
33
|
-
referenceType = "1">
|
|
34
|
-
</LocationScenarioReference>
|
|
35
|
-
</LaunchAction>
|
|
36
|
-
</Scheme>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|