@momo-kits/native-kits 0.89.30-beta.4 → 0.89.30-beta.6
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/src/commonMain/kotlin/vn/momo/kits/application/Components.kt +79 -59
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +11 -25
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +10 -10
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +1 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +8 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +8 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +7 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +3 -4
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +3 -1
- package/package.json +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/ImageLoader.kt +0 -26
|
@@ -4,7 +4,6 @@ import androidx.compose.animation.animateColorAsState
|
|
|
4
4
|
import androidx.compose.foundation.background
|
|
5
5
|
import androidx.compose.foundation.border
|
|
6
6
|
import androidx.compose.foundation.clickable
|
|
7
|
-
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
8
7
|
import androidx.compose.foundation.layout.Arrangement
|
|
9
8
|
import androidx.compose.foundation.layout.Box
|
|
10
9
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
|
@@ -16,7 +15,6 @@ import androidx.compose.foundation.layout.padding
|
|
|
16
15
|
import androidx.compose.foundation.layout.size
|
|
17
16
|
import androidx.compose.foundation.layout.width
|
|
18
17
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
19
|
-
import androidx.compose.material.ripple.rememberRipple
|
|
20
18
|
import androidx.compose.runtime.Composable
|
|
21
19
|
import androidx.compose.runtime.LaunchedEffect
|
|
22
20
|
import androidx.compose.runtime.getValue
|
|
@@ -26,9 +24,12 @@ import androidx.compose.runtime.setValue
|
|
|
26
24
|
import androidx.compose.runtime.snapshotFlow
|
|
27
25
|
import androidx.compose.ui.Alignment
|
|
28
26
|
import androidx.compose.ui.Modifier
|
|
27
|
+
import androidx.compose.ui.geometry.Offset
|
|
28
|
+
import androidx.compose.ui.graphics.Brush
|
|
29
29
|
import androidx.compose.ui.graphics.Color
|
|
30
30
|
import androidx.compose.ui.graphics.graphicsLayer
|
|
31
31
|
import androidx.compose.ui.layout.ContentScale
|
|
32
|
+
import androidx.compose.ui.platform.LocalDensity
|
|
32
33
|
import androidx.compose.ui.semantics.contentDescription
|
|
33
34
|
import androidx.compose.ui.semantics.semantics
|
|
34
35
|
import androidx.compose.ui.semantics.testTag
|
|
@@ -60,45 +61,76 @@ data class AnimatedHeader(
|
|
|
60
61
|
)
|
|
61
62
|
|
|
62
63
|
@Composable
|
|
63
|
-
fun
|
|
64
|
-
headerType: HeaderType = HeaderType.DEFAULT
|
|
65
|
-
headerBackground: String?,
|
|
64
|
+
fun HeaderBackground(
|
|
65
|
+
headerType: HeaderType = HeaderType.DEFAULT
|
|
66
66
|
) {
|
|
67
67
|
val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
|
|
68
68
|
when (headerType) {
|
|
69
69
|
HeaderType.DEFAULT -> {
|
|
70
70
|
val height = statusBarHeight + 52.dp
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
71
|
+
Box(
|
|
72
|
+
modifier = Modifier.fillMaxWidth().height(height)
|
|
73
|
+
.bottomBorder(
|
|
74
|
+
strokeWidth = 1.dp,
|
|
75
|
+
color = AppTheme.current.colors.border.default
|
|
76
|
+
)
|
|
77
|
+
) {
|
|
78
|
+
Box(
|
|
79
|
+
modifier = Modifier
|
|
80
|
+
.height(height)
|
|
81
|
+
.fillMaxWidth()
|
|
82
|
+
.background(
|
|
83
|
+
Brush.linearGradient(
|
|
84
|
+
colors = listOf(
|
|
85
|
+
Color(0xFFFDCACE),
|
|
86
|
+
Color(0x00FDCACE)
|
|
87
|
+
),
|
|
88
|
+
start = Offset(0f, 0f),
|
|
89
|
+
end = Offset(0f, with(LocalDensity.current) { 154.dp.toPx() })
|
|
90
|
+
)
|
|
91
|
+
)
|
|
77
92
|
)
|
|
78
|
-
|
|
79
|
-
|
|
93
|
+
if (AppTheme.current.assets.headerBackground != null) {
|
|
94
|
+
Image(
|
|
95
|
+
source = AppTheme.current.assets.headerBackground!!,
|
|
96
|
+
modifier = Modifier.fillMaxWidth().height(height),
|
|
97
|
+
options = Options(
|
|
98
|
+
contentScale = ContentScale.FillWidth
|
|
99
|
+
)
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
80
103
|
|
|
81
|
-
HeaderType.EXTENDED -> {
|
|
82
|
-
Image(
|
|
83
|
-
source = headerBackground ?: "",
|
|
84
|
-
loading = false,
|
|
85
|
-
modifier = Modifier.fillMaxWidth(),
|
|
86
|
-
options = Options(
|
|
87
|
-
contentScale = ContentScale.FillWidth
|
|
88
|
-
)
|
|
89
|
-
)
|
|
90
104
|
}
|
|
91
105
|
|
|
92
|
-
HeaderType.
|
|
93
|
-
val height = statusBarHeight + 52.dp
|
|
106
|
+
HeaderType.EXTENDED -> {
|
|
94
107
|
Box(
|
|
95
|
-
modifier = Modifier.fillMaxWidth().height(
|
|
96
|
-
.background(
|
|
108
|
+
modifier = Modifier.fillMaxWidth().height(154.dp)
|
|
109
|
+
.background(
|
|
110
|
+
Brush.linearGradient(
|
|
111
|
+
colors = listOf(
|
|
112
|
+
Color(0xFFFDCACE),
|
|
113
|
+
Color(0x00FDCACE)
|
|
114
|
+
),
|
|
115
|
+
start = Offset(0f, 0f),
|
|
116
|
+
end = Offset(0f, with(LocalDensity.current) { 154.dp.toPx() })
|
|
117
|
+
)
|
|
118
|
+
)
|
|
97
119
|
.bottomBorder(
|
|
98
|
-
strokeWidth =
|
|
120
|
+
strokeWidth = 1.dp,
|
|
99
121
|
color = AppTheme.current.colors.border.default
|
|
100
122
|
)
|
|
101
|
-
)
|
|
123
|
+
) {
|
|
124
|
+
if (AppTheme.current.assets.headerBackground != null) {
|
|
125
|
+
Image(
|
|
126
|
+
source = AppTheme.current.assets.headerBackground!!,
|
|
127
|
+
modifier = Modifier.fillMaxWidth().height(154.dp),
|
|
128
|
+
options = Options(
|
|
129
|
+
contentScale = ContentScale.FillWidth
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
102
134
|
}
|
|
103
135
|
|
|
104
136
|
else -> {
|
|
@@ -112,30 +144,22 @@ fun Header(
|
|
|
112
144
|
headerType: HeaderType = HeaderType.DEFAULT,
|
|
113
145
|
titlePosition: TitlePosition,
|
|
114
146
|
title: String,
|
|
115
|
-
isBack: Boolean,
|
|
116
147
|
headerRight: @Composable (() -> Unit)? = null,
|
|
117
|
-
goBack: (() -> Unit) =
|
|
148
|
+
goBack: (() -> Unit)? = null,
|
|
118
149
|
opacity: Float? = null,
|
|
119
150
|
animatedHeader: AnimatedHeader? = null,
|
|
120
151
|
scrollState: Int = 0
|
|
121
152
|
) {
|
|
122
153
|
val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
|
|
123
|
-
|
|
124
|
-
var backgroundButton = Colors.black_20.copy(alpha = 0.4f)
|
|
125
|
-
if (headerType == HeaderType.SURFACE) {
|
|
126
|
-
tintIconColor = AppTheme.current.colors.text.default
|
|
127
|
-
backgroundButton = Color.Transparent
|
|
128
|
-
}
|
|
154
|
+
val tintIconColor = AppTheme.current.colors.text.default
|
|
129
155
|
|
|
130
156
|
var colorFraction by remember { mutableStateOf(0f) }
|
|
131
157
|
|
|
132
158
|
LaunchedEffect(scrollState) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
.collect { fraction -> colorFraction = fraction }
|
|
138
|
-
}
|
|
159
|
+
snapshotFlow { scrollState }
|
|
160
|
+
.map { (it / 50f).coerceIn(0f, 1f) }
|
|
161
|
+
.distinctUntilChanged()
|
|
162
|
+
.collect { fraction -> colorFraction = fraction }
|
|
139
163
|
}
|
|
140
164
|
|
|
141
165
|
val tintIconColorAnim by animateColorAsState(
|
|
@@ -146,7 +170,7 @@ fun Header(
|
|
|
146
170
|
)
|
|
147
171
|
)
|
|
148
172
|
|
|
149
|
-
if (headerType != HeaderType.NONE) {
|
|
173
|
+
if (headerType != HeaderType.NONE || animatedHeader !== null) {
|
|
150
174
|
BoxWithConstraints(
|
|
151
175
|
Modifier.height(statusBarHeight + 52.dp)
|
|
152
176
|
.fillMaxWidth()
|
|
@@ -161,23 +185,19 @@ fun Header(
|
|
|
161
185
|
horizontalArrangement = Arrangement.SpaceBetween
|
|
162
186
|
) {
|
|
163
187
|
Box {
|
|
164
|
-
if (
|
|
188
|
+
if (goBack !== null) {
|
|
165
189
|
Box(
|
|
166
190
|
modifier = Modifier
|
|
167
191
|
.size(28.dp)
|
|
168
192
|
.then(
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
)
|
|
175
|
-
} else {
|
|
176
|
-
Modifier
|
|
177
|
-
}
|
|
193
|
+
Modifier.border(
|
|
194
|
+
0.2.dp,
|
|
195
|
+
Colors.black_20.copy(alpha = 0.2f),
|
|
196
|
+
RoundedCornerShape(14.dp)
|
|
197
|
+
)
|
|
178
198
|
)
|
|
179
199
|
.background(
|
|
180
|
-
|
|
200
|
+
Colors.black_01.copy(alpha = 0.6f),
|
|
181
201
|
RoundedCornerShape(100)
|
|
182
202
|
)
|
|
183
203
|
.clickable(
|
|
@@ -191,8 +211,8 @@ fun Header(
|
|
|
191
211
|
contentAlignment = Alignment.Center
|
|
192
212
|
) {
|
|
193
213
|
Icon(
|
|
194
|
-
source = "
|
|
195
|
-
color = if (
|
|
214
|
+
source = "arrow_back",
|
|
215
|
+
color = if (animatedHeader !== null) tintIconColorAnim else tintIconColor,
|
|
196
216
|
size = 20.dp,
|
|
197
217
|
)
|
|
198
218
|
}
|
|
@@ -212,7 +232,7 @@ fun Header(
|
|
|
212
232
|
.padding(horizontal = Spacing.M),
|
|
213
233
|
verticalAlignment = Alignment.CenterVertically,
|
|
214
234
|
) {
|
|
215
|
-
if (
|
|
235
|
+
if (goBack !== null) {
|
|
216
236
|
Spacer(Modifier.width(40.dp))
|
|
217
237
|
}
|
|
218
238
|
Box(
|
|
@@ -223,14 +243,14 @@ fun Header(
|
|
|
223
243
|
) {
|
|
224
244
|
HeaderTitle(
|
|
225
245
|
title = title,
|
|
226
|
-
color = if (
|
|
246
|
+
color = if (animatedHeader !== null) tintIconColorAnim else tintIconColor,
|
|
227
247
|
modifier = Modifier.semantics {
|
|
228
248
|
contentDescription = "title_navigation_header"
|
|
229
249
|
testTag = "title_navigation_header"
|
|
230
250
|
}
|
|
231
251
|
)
|
|
232
252
|
}
|
|
233
|
-
if (
|
|
253
|
+
if (goBack !== null) {
|
|
234
254
|
Spacer(Modifier.width(40.dp))
|
|
235
255
|
}
|
|
236
256
|
}
|
|
@@ -38,7 +38,6 @@ import vn.momo.kits.platform.getStatusBarHeight
|
|
|
38
38
|
|
|
39
39
|
enum class HeaderType {
|
|
40
40
|
DEFAULT,
|
|
41
|
-
SURFACE,
|
|
42
41
|
EXTENDED,
|
|
43
42
|
NONE
|
|
44
43
|
}
|
|
@@ -46,14 +45,12 @@ enum class HeaderType {
|
|
|
46
45
|
@Composable
|
|
47
46
|
fun Screen(
|
|
48
47
|
backgroundColor: Color? = null,
|
|
49
|
-
headerBackground: String? = null,
|
|
50
|
-
isBack: Boolean = true,
|
|
51
48
|
headerType: HeaderType = HeaderType.DEFAULT,
|
|
52
49
|
verticalArrangement: Arrangement.Vertical = Arrangement.Top,
|
|
53
50
|
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
|
|
54
51
|
title: String = "Stack",
|
|
55
52
|
titlePosition: TitlePosition = TitlePosition.LEFT,
|
|
56
|
-
goBack: (() -> Unit) =
|
|
53
|
+
goBack: (() -> Unit)? = null,
|
|
57
54
|
scrollable: Boolean = true,
|
|
58
55
|
useAvoidKeyboard: Boolean = true,
|
|
59
56
|
footer: @Composable (() -> Unit)? = null,
|
|
@@ -90,18 +87,14 @@ fun Screen(
|
|
|
90
87
|
) {
|
|
91
88
|
|
|
92
89
|
if (animatedHeader === null) {
|
|
93
|
-
|
|
94
|
-
headerType,
|
|
95
|
-
headerBackground ?: AppTheme.current.assets.headerBackground
|
|
96
|
-
)
|
|
90
|
+
HeaderBackground(headerType)
|
|
97
91
|
} else {
|
|
98
92
|
Box(
|
|
99
|
-
Modifier.zIndex(5f)
|
|
100
|
-
.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
)
|
|
93
|
+
Modifier.zIndex(5f)
|
|
94
|
+
.background(Color.White.copy(alpha = opacity))
|
|
95
|
+
.graphicsLayer { alpha = opacity }
|
|
96
|
+
) {
|
|
97
|
+
HeaderBackground(HeaderType.DEFAULT)
|
|
105
98
|
}
|
|
106
99
|
}
|
|
107
100
|
|
|
@@ -110,7 +103,6 @@ fun Screen(
|
|
|
110
103
|
title = title,
|
|
111
104
|
titlePosition = titlePosition,
|
|
112
105
|
headerRight = headerRight,
|
|
113
|
-
isBack = isBack,
|
|
114
106
|
goBack = goBack,
|
|
115
107
|
opacity = opacity,
|
|
116
108
|
animatedHeader = animatedHeader,
|
|
@@ -129,9 +121,7 @@ fun Screen(
|
|
|
129
121
|
) {
|
|
130
122
|
|
|
131
123
|
Column(
|
|
132
|
-
modifier = if (scrollable) Modifier.weight(1f).padding(bottom = keyboardSize)
|
|
133
|
-
.verticalScroll(scrollState) else
|
|
134
|
-
Modifier.padding(bottom = keyboardSize),
|
|
124
|
+
modifier = if (scrollable) Modifier.weight(1f).padding(bottom = keyboardSize).verticalScroll(scrollState) else Modifier.padding(bottom = keyboardSize),
|
|
135
125
|
verticalArrangement = verticalArrangement,
|
|
136
126
|
horizontalAlignment = horizontalAlignment
|
|
137
127
|
) {
|
|
@@ -156,8 +146,7 @@ fun Screen(
|
|
|
156
146
|
scrollPosition = fabProps.scrollState?.value ?: scrollState.value,
|
|
157
147
|
onClick = fabProps.onClick,
|
|
158
148
|
containerColor = AppTheme.current.colors.primary,
|
|
159
|
-
bottom = fabProps.bottom
|
|
160
|
-
?: if (footer != null) bottomPadding + 76.dp else bottomPadding + 12.dp,
|
|
149
|
+
bottom = fabProps.bottom ?: if (footer != null) bottomPadding + 76.dp else bottomPadding + 12.dp,
|
|
161
150
|
icon = fabProps.icon,
|
|
162
151
|
iconColor = fabProps.iconColor,
|
|
163
152
|
text = fabProps.label,
|
|
@@ -186,11 +175,8 @@ fun Footer(footer: @Composable (() -> Unit)? = null, keyboardSize: Dp = 0.dp, bo
|
|
|
186
175
|
.background(AppTheme.current.colors.background.surface)
|
|
187
176
|
) {
|
|
188
177
|
Box(
|
|
189
|
-
Modifier
|
|
190
|
-
|
|
191
|
-
.padding(vertical = Spacing.S, horizontal = Spacing.M)
|
|
192
|
-
)
|
|
193
|
-
{
|
|
178
|
+
Modifier.fillMaxWidth().padding(vertical = Spacing.S, horizontal = Spacing.M)
|
|
179
|
+
) {
|
|
194
180
|
footer?.invoke()
|
|
195
181
|
}
|
|
196
182
|
}
|
|
@@ -3,7 +3,6 @@ package vn.momo.kits.components
|
|
|
3
3
|
import androidx.compose.foundation.background
|
|
4
4
|
import androidx.compose.foundation.border
|
|
5
5
|
import androidx.compose.foundation.clickable
|
|
6
|
-
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
7
6
|
import androidx.compose.foundation.layout.Arrangement
|
|
8
7
|
import androidx.compose.foundation.layout.Box
|
|
9
8
|
import androidx.compose.foundation.layout.Row
|
|
@@ -13,14 +12,15 @@ import androidx.compose.foundation.layout.height
|
|
|
13
12
|
import androidx.compose.foundation.layout.padding
|
|
14
13
|
import androidx.compose.foundation.layout.size
|
|
15
14
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
16
|
-
import androidx.compose.material.ripple.rememberRipple
|
|
17
15
|
import androidx.compose.material3.CircularProgressIndicator
|
|
18
16
|
import androidx.compose.runtime.Composable
|
|
19
|
-
import androidx.compose.runtime.remember
|
|
20
17
|
import androidx.compose.ui.Alignment
|
|
21
18
|
import androidx.compose.ui.Modifier
|
|
22
19
|
import androidx.compose.ui.draw.clip
|
|
23
20
|
import androidx.compose.ui.graphics.Color
|
|
21
|
+
import androidx.compose.ui.semantics.contentDescription
|
|
22
|
+
import androidx.compose.ui.semantics.semantics
|
|
23
|
+
import androidx.compose.ui.semantics.testTag
|
|
24
24
|
import androidx.compose.ui.text.TextStyle
|
|
25
25
|
import androidx.compose.ui.text.style.TextOverflow
|
|
26
26
|
import androidx.compose.ui.unit.Dp
|
|
@@ -221,9 +221,6 @@ fun getTypeStyle(
|
|
|
221
221
|
* @param iconLeft [String] the icon at the left of title
|
|
222
222
|
* @param title [String] title of button
|
|
223
223
|
* @param loading [Boolean] used when you want to use loading animation
|
|
224
|
-
* @param enabled controls the enabled state of this button. When `false`,
|
|
225
|
-
* this component will not respond to user input, and it will appear
|
|
226
|
-
* visually disabled and disabled to accessibility services.
|
|
227
224
|
* @param useTintColor [Boolean] controls color of the icon.
|
|
228
225
|
*/
|
|
229
226
|
@Composable
|
|
@@ -235,23 +232,23 @@ fun Button(
|
|
|
235
232
|
iconLeft: String = "",
|
|
236
233
|
title: String = "Button",
|
|
237
234
|
loading: Boolean = false,
|
|
238
|
-
enabled: Boolean = true,
|
|
239
235
|
useTintColor: Boolean = true,
|
|
240
236
|
isFull: Boolean = true,
|
|
241
237
|
modifier: Modifier = Modifier,
|
|
242
238
|
) {
|
|
239
|
+
val testId = "btn_${type.toString().lowercase()}_$title"
|
|
243
240
|
val customModifier = if (isFull) {
|
|
244
241
|
modifier
|
|
245
242
|
.fillMaxWidth()
|
|
246
243
|
.clip(RoundedCornerShape(size.value.radius)).clickable(
|
|
247
|
-
enabled =
|
|
244
|
+
enabled = type != ButtonType.DISABLED,
|
|
248
245
|
onClick = onClick
|
|
249
246
|
)
|
|
250
247
|
|
|
251
248
|
} else {
|
|
252
249
|
modifier
|
|
253
250
|
.clip(RoundedCornerShape(size.value.radius)).clickable(
|
|
254
|
-
enabled =
|
|
251
|
+
enabled = type != ButtonType.DISABLED,
|
|
255
252
|
onClick = onClick
|
|
256
253
|
)
|
|
257
254
|
}
|
|
@@ -261,7 +258,10 @@ fun Button(
|
|
|
261
258
|
.padding(horizontal = size.value.padding)
|
|
262
259
|
.defaultMinSize(
|
|
263
260
|
minWidth = size.value.width
|
|
264
|
-
).height(size.value.height)
|
|
261
|
+
).height(size.value.height)
|
|
262
|
+
.semantics {
|
|
263
|
+
contentDescription = testId; testTag = testId
|
|
264
|
+
},
|
|
265
265
|
horizontalArrangement = Arrangement.Center,
|
|
266
266
|
verticalAlignment = Alignment.CenterVertically,
|
|
267
267
|
) {
|
|
@@ -110,7 +110,7 @@ fun IconButton(
|
|
|
110
110
|
.then(getIconStyle(type))
|
|
111
111
|
.clip(RoundedCornerShape(size.value.radius))
|
|
112
112
|
.clickable(
|
|
113
|
-
enabled = type
|
|
113
|
+
enabled = type != ButtonType.DISABLED,
|
|
114
114
|
onClick = onClick
|
|
115
115
|
),
|
|
116
116
|
contentAlignment = Alignment.Center
|
|
@@ -36,7 +36,6 @@ fun Image(
|
|
|
36
36
|
options: Options? = null,
|
|
37
37
|
loading: Boolean = true,
|
|
38
38
|
) {
|
|
39
|
-
modifier.semantics {contentDescription = "img|$source"; testTag = "img|$source"}
|
|
40
39
|
var imageOptions = Options()
|
|
41
40
|
var imageState by remember { mutableStateOf(ImageState.Loading) }
|
|
42
41
|
|
|
@@ -51,7 +50,7 @@ fun Image(
|
|
|
51
50
|
|
|
52
51
|
Box(modifier = modifier) {
|
|
53
52
|
AsyncImage(
|
|
54
|
-
modifier =
|
|
53
|
+
modifier = Modifier.matchParentSize().semantics {contentDescription = "img|$source"; testTag = "img|$source"},
|
|
55
54
|
model = source,
|
|
56
55
|
contentDescription = null,
|
|
57
56
|
contentScale = imageOptions.contentScale,
|
|
@@ -29,6 +29,9 @@ import androidx.compose.ui.Alignment
|
|
|
29
29
|
import androidx.compose.ui.Modifier
|
|
30
30
|
import androidx.compose.ui.focus.onFocusChanged
|
|
31
31
|
import androidx.compose.ui.graphics.Color
|
|
32
|
+
import androidx.compose.ui.semantics.contentDescription
|
|
33
|
+
import androidx.compose.ui.semantics.semantics
|
|
34
|
+
import androidx.compose.ui.semantics.testTag
|
|
32
35
|
import androidx.compose.ui.text.TextStyle
|
|
33
36
|
import androidx.compose.ui.text.font.FontWeight
|
|
34
37
|
import androidx.compose.ui.text.input.KeyboardType
|
|
@@ -198,7 +201,11 @@ fun Input(
|
|
|
198
201
|
iconTintColor = disabledColor
|
|
199
202
|
}
|
|
200
203
|
|
|
201
|
-
|
|
204
|
+
val testId = if (disabled) "input_${floatingValue}_disabled" else "input_$floatingValue"
|
|
205
|
+
|
|
206
|
+
Column(modifier = Modifier.semantics {
|
|
207
|
+
contentDescription = testId; testTag = testId
|
|
208
|
+
}) {
|
|
202
209
|
BasicTextField(
|
|
203
210
|
enabled = !disabled,
|
|
204
211
|
readOnly = readOnly,
|
|
@@ -21,6 +21,9 @@ import androidx.compose.runtime.setValue
|
|
|
21
21
|
import androidx.compose.ui.Alignment
|
|
22
22
|
import androidx.compose.ui.Modifier
|
|
23
23
|
import androidx.compose.ui.graphics.Color
|
|
24
|
+
import androidx.compose.ui.semantics.contentDescription
|
|
25
|
+
import androidx.compose.ui.semantics.semantics
|
|
26
|
+
import androidx.compose.ui.semantics.testTag
|
|
24
27
|
import androidx.compose.ui.text.TextStyle
|
|
25
28
|
import androidx.compose.ui.unit.dp
|
|
26
29
|
import androidx.compose.ui.unit.sp
|
|
@@ -51,7 +54,7 @@ fun InputDropDown(
|
|
|
51
54
|
loading: Boolean = false,
|
|
52
55
|
required: Boolean = false,
|
|
53
56
|
) {
|
|
54
|
-
|
|
57
|
+
val isFocused by remember { mutableStateOf(false) }
|
|
55
58
|
|
|
56
59
|
val disabledColor = AppTheme.current.colors.text.disable
|
|
57
60
|
var textColor = AppTheme.current.colors.text.default
|
|
@@ -72,8 +75,11 @@ fun InputDropDown(
|
|
|
72
75
|
iconTintColor = disabledColor
|
|
73
76
|
}
|
|
74
77
|
|
|
78
|
+
val testId = if (disabled) "input_${floatingValue}_disabled" else "input_$floatingValue"
|
|
75
79
|
|
|
76
|
-
Column(modifier = Modifier.clickable(enabled = !disabled, onClick = onPress)
|
|
80
|
+
Column(modifier = Modifier.clickable(enabled = !disabled, onClick = onPress).semantics {
|
|
81
|
+
contentDescription = testId; testTag = testId
|
|
82
|
+
}) {
|
|
77
83
|
Box {
|
|
78
84
|
if (floatingValue.isNotEmpty() || floatingIcon.isNotEmpty()) {
|
|
79
85
|
Box(
|
|
@@ -27,6 +27,9 @@ import androidx.compose.ui.Alignment
|
|
|
27
27
|
import androidx.compose.ui.Modifier
|
|
28
28
|
import androidx.compose.ui.focus.onFocusChanged
|
|
29
29
|
import androidx.compose.ui.graphics.Color
|
|
30
|
+
import androidx.compose.ui.semantics.contentDescription
|
|
31
|
+
import androidx.compose.ui.semantics.semantics
|
|
32
|
+
import androidx.compose.ui.semantics.testTag
|
|
30
33
|
import androidx.compose.ui.text.AnnotatedString
|
|
31
34
|
import androidx.compose.ui.text.TextStyle
|
|
32
35
|
import androidx.compose.ui.text.input.KeyboardType
|
|
@@ -104,8 +107,11 @@ fun InputMoney(
|
|
|
104
107
|
iconTintColor = disabledColor
|
|
105
108
|
}
|
|
106
109
|
|
|
110
|
+
val testId = if (disabled) "input_${floatingValue}_disabled" else "input_$floatingValue"
|
|
107
111
|
|
|
108
|
-
Column {
|
|
112
|
+
Column(modifier = Modifier.semantics {
|
|
113
|
+
contentDescription = testId; testTag = testId
|
|
114
|
+
}) {
|
|
109
115
|
BasicTextField(
|
|
110
116
|
enabled = !disabled,
|
|
111
117
|
singleLine = true,
|
|
@@ -106,7 +106,7 @@ val defaultTheme = Theme(
|
|
|
106
106
|
),
|
|
107
107
|
font = "SFProText",
|
|
108
108
|
assets = ThemeAssets(
|
|
109
|
-
headerBackground =
|
|
109
|
+
headerBackground = null
|
|
110
110
|
)
|
|
111
111
|
)
|
|
112
112
|
|
|
@@ -168,6 +168,5 @@ val darkTheme = Theme(
|
|
|
168
168
|
|
|
169
169
|
|
|
170
170
|
val AppTheme = staticCompositionLocalOf { defaultTheme }
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
171
|
+
|
|
172
|
+
val AppStatusBar = staticCompositionLocalOf<Dp?> { null }
|
|
@@ -1317,5 +1317,7 @@ val Icons = mapOf(
|
|
|
1317
1317
|
"ic_checked" to "https://img.mservice.com.vn/app/img/kits/checked_ic.png",
|
|
1318
1318
|
"ic_minus" to "https://img.mservice.com.vn/app/img/kits/minus.png",
|
|
1319
1319
|
"ic_navigation" to "https://static.momocdn.net/app/img/kits/ic_navigation.png",
|
|
1320
|
-
"ic_money_bag" to "https://static.momocdn.net/app/img/kits/ic_money_bag.png"
|
|
1320
|
+
"ic_money_bag" to "https://static.momocdn.net/app/img/kits/ic_money_bag.png",
|
|
1321
|
+
"help_center" to "https://static.momocdn.net/app/img/kits/ic_money_bag_2.png",
|
|
1322
|
+
"arrow_back" to "https://static.momocdn.net/app/img/kits/arrow-back.png",
|
|
1321
1323
|
)
|
package/package.json
CHANGED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
package vn.momo.kits.utils
|
|
2
|
-
|
|
3
|
-
import androidx.compose.runtime.Composable
|
|
4
|
-
import coil3.ImageLoader
|
|
5
|
-
import coil3.annotation.ExperimentalCoilApi
|
|
6
|
-
import coil3.compose.setSingletonImageLoaderFactory
|
|
7
|
-
import coil3.disk.DiskCache
|
|
8
|
-
import coil3.memory.MemoryCache
|
|
9
|
-
import coil3.request.CachePolicy
|
|
10
|
-
import coil3.request.crossfade
|
|
11
|
-
import okio.FileSystem
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@OptIn(ExperimentalCoilApi::class)
|
|
15
|
-
@Composable
|
|
16
|
-
fun setImageLoaderSingleton() {
|
|
17
|
-
setSingletonImageLoaderFactory { context ->
|
|
18
|
-
ImageLoader.Builder(context).memoryCachePolicy(CachePolicy.ENABLED).memoryCache {
|
|
19
|
-
MemoryCache.Builder().maxSizePercent(context, 0.3).strongReferencesEnabled(true).build()
|
|
20
|
-
}.diskCachePolicy(CachePolicy.ENABLED).networkCachePolicy(CachePolicy.ENABLED).diskCache {
|
|
21
|
-
DiskCache.Builder().directory(FileSystem.SYSTEM_TEMPORARY_DIRECTORY / "coil3_image_cache")
|
|
22
|
-
.maxSizeBytes(1024L * 1024 * 1024)
|
|
23
|
-
.build()
|
|
24
|
-
}.crossfade(false).build()
|
|
25
|
-
}
|
|
26
|
-
}
|