@momo-kits/native-kits 0.89.33-rc.4 → 0.89.33-sp.1

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.
@@ -3,6 +3,7 @@ plugins {
3
3
  alias(libs.plugins.jetbrains.kotlin.multiplatform)
4
4
  alias(libs.plugins.compose)
5
5
  alias(libs.plugins.kotlin.compose.compiler)
6
+ kotlin("plugin.serialization")
6
7
  id("maven-publish")
7
8
  }
8
9
 
@@ -39,6 +40,8 @@ kotlin {
39
40
  implementation(libs.coil.multiplatform.compose)
40
41
  implementation(libs.coil.multiplatform.core)
41
42
  implementation(libs.coil.multiplatform.network.ktor)
43
+ implementation("com.google.code.gson:gson:2.10")
44
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")
42
45
  }
43
46
  }
44
47
  val androidMain by getting {
@@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.Box
10
10
  import androidx.compose.foundation.layout.BoxWithConstraints
11
11
  import androidx.compose.foundation.layout.Row
12
12
  import androidx.compose.foundation.layout.Spacer
13
+ import androidx.compose.foundation.layout.fillMaxSize
13
14
  import androidx.compose.foundation.layout.fillMaxWidth
14
15
  import androidx.compose.foundation.layout.height
15
16
  import androidx.compose.foundation.layout.padding
@@ -66,6 +67,7 @@ data class AnimatedHeader(
66
67
  @Composable
67
68
  fun HeaderBackground(
68
69
  headerType: HeaderType = HeaderType.DEFAULT,
70
+ headerBanner: String? = null,
69
71
  scrollState: Int
70
72
  ) {
71
73
  val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
@@ -73,11 +75,20 @@ fun HeaderBackground(
73
75
  targetValue = (1 - (scrollState / 200f)).coerceIn(0f, 1f),
74
76
  )
75
77
 
78
+
79
+ val backgroundColor = if (scrollState == 0) {
80
+ Color.Transparent
81
+ } else {
82
+ AppTheme.current.colors.background.surface
83
+ }
84
+
85
+
76
86
  when (headerType) {
77
87
  HeaderType.DEFAULT -> {
78
88
  val height = statusBarHeight + 52.dp
79
89
  Box(
80
90
  modifier = Modifier.fillMaxWidth().height(height)
91
+ .background(backgroundColor)
81
92
  .bottomBorder(
82
93
  strokeWidth = 1.dp,
83
94
  color = AppTheme.current.colors.border.default
@@ -101,7 +112,7 @@ fun HeaderBackground(
101
112
  )
102
113
  if (AppTheme.current.assets.headerBackground != null) {
103
114
  Image(
104
- source = AppTheme.current.assets.headerBackground!!,
115
+ source = headerBanner ?: AppTheme.current.assets.headerBackground!!,
105
116
  modifier = Modifier.fillMaxWidth().height(height),
106
117
  options = Options(
107
118
  contentScale = ContentScale.FillWidth
@@ -113,28 +124,34 @@ fun HeaderBackground(
113
124
  }
114
125
 
115
126
  HeaderType.EXTENDED -> {
116
- Box(
117
- modifier = Modifier.fillMaxWidth().height(154.dp)
118
- .alpha(opacityAni)
119
- .background(
120
- Brush.linearGradient(
121
- colors = listOf(
122
- Color(0xFFFDCADE),
123
- Color(0x00FDCADE)
124
- ),
125
- start = Offset(0f, 0f),
126
- end = Offset(0f, with(LocalDensity.current) { 154.dp.toPx() })
127
- )
128
- )
129
- ) {
130
- if (AppTheme.current.assets.headerBackground != null) {
131
- Image(
132
- source = AppTheme.current.assets.headerBackground!!,
133
- modifier = Modifier.fillMaxWidth().height(154.dp),
134
- options = Options(
135
- contentScale = ContentScale.FillWidth
127
+
128
+ Box(
129
+ modifier = Modifier.fillMaxWidth().height(154.dp)
130
+ .alpha(opacityAni)
131
+ .background(
132
+ Brush.linearGradient(
133
+ colors = listOf(
134
+ Color(0xFFFDCADE),
135
+ Color(0x00FDCADE)
136
+ ),
137
+ start = Offset(0f, 0f),
138
+ end = Offset(0f, with(LocalDensity.current) { 154.dp.toPx() })
139
+ )
136
140
  )
137
- )
141
+ ) {
142
+ if (AppTheme.current.assets.headerBackground != null) {
143
+ Box(
144
+ modifier = Modifier.fillMaxWidth()
145
+ .background(backgroundColor)
146
+ ) {
147
+ Image(
148
+ source = headerBanner ?: AppTheme.current.assets.headerBackground!!,
149
+ modifier = Modifier.fillMaxWidth().height(154.dp),
150
+ options = Options(
151
+ contentScale = ContentScale.FillWidth
152
+ )
153
+ )
154
+ }
138
155
  }
139
156
  }
140
157
  }
@@ -278,7 +295,7 @@ fun HeaderTitle(
278
295
  modifier = Modifier.then(modifier).zIndex(1f),
279
296
  text = title,
280
297
  textAlign = textAlign,
281
- style = Typography.headerDefault,
298
+ style = Typography.actionS,
282
299
  color = color,
283
300
  maxLines = 1
284
301
  )
@@ -1,8 +1,5 @@
1
1
  package vn.momo.kits.application
2
2
 
3
- import androidx.compose.foundation.layout.WindowInsets
4
- import androidx.compose.foundation.layout.asPaddingValues
5
- import androidx.compose.foundation.layout.systemBars
6
3
  import androidx.compose.runtime.Composable
7
4
  import androidx.compose.runtime.CompositionLocalProvider
8
5
  import androidx.compose.runtime.staticCompositionLocalOf
@@ -17,6 +14,10 @@ val AppNavigator = staticCompositionLocalOf<Navigator> {
17
14
  error("no navigator provided!")
18
15
  }
19
16
 
17
+ val PlatformApi = staticCompositionLocalOf<ComposeApi> {
18
+ error("no api provided!")
19
+ }
20
+
20
21
  class Navigator {
21
22
  fun push(content: @Composable () -> Unit) {
22
23
  }
@@ -49,14 +50,23 @@ class Navigator {
49
50
  }
50
51
  }
51
52
 
53
+ interface ComposeApi {
54
+ fun request(funcName: String, params: String?): String
55
+ fun request(funcName: String, params: String?, onResponse: ((String) -> Unit)?): String
56
+ fun requestCallback(funcName: String, params: String?, onResponse: ((String) -> Unit)?)
57
+ fun removeCallback(id: String)
58
+ }
59
+
52
60
  @Composable
53
61
  fun ApplicationContainer(
54
62
  theme: Theme = defaultTheme,
63
+ composeApi: ComposeApi,
55
64
  content: @Composable () -> Unit,
56
65
  ) {
57
66
  disableOverscroll()
58
67
  CompositionLocalProvider(
59
68
  AppTheme provides theme,
69
+ PlatformApi provides composeApi,
60
70
  AppNavigator provides Navigator(),
61
71
  AppStatusBar provides getStatusBarHeight(),
62
72
  ) {
@@ -32,6 +32,8 @@ import androidx.compose.ui.unit.Dp
32
32
  import androidx.compose.ui.unit.dp
33
33
  import androidx.compose.ui.unit.min
34
34
  import androidx.compose.ui.zIndex
35
+ import kotlinx.serialization.Serializable
36
+ import kotlinx.serialization.json.Json
35
37
  import vn.momo.kits.components.InputSearchProps
36
38
  import vn.momo.kits.const.AppStatusBar
37
39
  import vn.momo.kits.const.AppTheme
@@ -47,6 +49,9 @@ enum class HeaderType {
47
49
  NONE
48
50
  }
49
51
 
52
+ @Serializable
53
+ data class ConfigData(val headerBanner: String? = null)
54
+
50
55
  @Composable
51
56
  fun Screen(
52
57
  backgroundColor: Color? = null,
@@ -79,6 +84,11 @@ fun Screen(
79
84
  else -> 0.dp
80
85
  }
81
86
 
87
+ val platformApi = PlatformApi.current
88
+ val rawData = platformApi.request("GetConfig", "DESIGN_SYSTEM")
89
+ val json = Json { ignoreUnknownKeys = true }
90
+ val headerBanner = json.decodeFromString<ConfigData>(rawData).headerBanner
91
+
82
92
  val indicator = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding()
83
93
  val bottomPadding = min(indicator, 21.dp)
84
94
 
@@ -95,10 +105,14 @@ fun Screen(
95
105
  ) {
96
106
 
97
107
  if (animatedHeader === null) {
98
- HeaderBackground(headerType = headerType, scrollState = scrollState.value)
108
+ HeaderBackground(
109
+ headerType = headerType,
110
+ scrollState = scrollState.value,
111
+ headerBanner = headerBanner
112
+ )
99
113
  } else {
100
114
  Box(
101
- Modifier.zIndex(5f)
115
+ Modifier.zIndex(2f)
102
116
  .background(Color.White.copy(alpha = opacity))
103
117
  .graphicsLayer { alpha = opacity }
104
118
  ) {
@@ -1,13 +1,17 @@
1
1
  package vn.momo.kits.components
2
2
 
3
+ import androidx.compose.foundation.layout.Box
3
4
  import androidx.compose.foundation.layout.size
4
5
  import androidx.compose.runtime.Composable
5
6
  import androidx.compose.ui.Modifier
6
7
  import androidx.compose.ui.graphics.Color
7
8
  import androidx.compose.ui.graphics.ColorFilter
8
9
  import androidx.compose.ui.layout.ContentScale
10
+ import androidx.compose.ui.semantics.contentDescription
11
+ import androidx.compose.ui.semantics.semantics
9
12
  import androidx.compose.ui.unit.Dp
10
13
  import androidx.compose.ui.unit.dp
14
+ import coil3.compose.AsyncImage
11
15
  import vn.momo.kits.const.AppTheme
12
16
  import vn.momo.kits.utils.Icons
13
17
 
@@ -23,14 +27,14 @@ fun Icon(
23
27
  } else {
24
28
  Icons[source] ?: ""
25
29
  }
26
- Image(
27
- modifier = modifier.size(size),
28
- source = icon,
29
- loading = false,
30
- options = Options(
30
+ Box(modifier = modifier.size(size).semantics {contentDescription = "img|$icon"}) {
31
+ AsyncImage(
32
+ modifier = Modifier.matchParentSize(),
33
+ model = icon,
34
+ contentDescription = null,
31
35
  contentScale = ContentScale.Fit,
32
- colorFilter = color?.let { ColorFilter.tint(it) }
33
- ),
34
- )
36
+ colorFilter = color?.let { ColorFilter.tint(it) },
37
+ )
38
+ }
35
39
  }
36
40
 
@@ -15,6 +15,7 @@ import androidx.compose.foundation.layout.size
15
15
  import androidx.compose.foundation.layout.width
16
16
  import androidx.compose.foundation.shape.RoundedCornerShape
17
17
  import androidx.compose.foundation.text.BasicTextField
18
+ import androidx.compose.foundation.text.KeyboardActions
18
19
  import androidx.compose.foundation.text.KeyboardOptions
19
20
  import androidx.compose.material3.CircularProgressIndicator
20
21
  import androidx.compose.runtime.Composable
@@ -29,6 +30,7 @@ import androidx.compose.ui.focus.onFocusChanged
29
30
  import androidx.compose.ui.graphics.Color
30
31
  import androidx.compose.ui.text.TextStyle
31
32
  import androidx.compose.ui.text.input.KeyboardType
33
+ import androidx.compose.ui.text.style.TextOverflow
32
34
  import androidx.compose.ui.unit.dp
33
35
  import androidx.compose.ui.unit.sp
34
36
  import vn.momo.kits.const.AppTheme
@@ -44,6 +46,7 @@ fun RenderRightIconSearch(
44
46
  icon: String,
45
47
  color: Color,
46
48
  onClick: () -> Unit,
49
+ iconModifier: Modifier = Modifier
47
50
  ) {
48
51
  if (loading) {
49
52
  Box(Modifier.padding(horizontal = Spacing.S)) {
@@ -64,7 +67,7 @@ fun RenderRightIconSearch(
64
67
  source = icon,
65
68
  color = color,
66
69
  size = 24.dp,
67
- modifier = Modifier.padding(start = Spacing.S, end = 0.dp).clickable(
70
+ modifier = iconModifier.padding(start = Spacing.S, end = 0.dp).clickable(
68
71
  onClick = onClick,
69
72
  interactionSource = remember { MutableInteractionSource() },
70
73
  indication = null
@@ -90,6 +93,11 @@ data class InputSearchProps(
90
93
  val fontWeight: InputFontWeight = InputFontWeight.REGULAR,
91
94
  val keyboardType: KeyboardType = KeyboardType.Text,
92
95
  val backgroundColor: Color = Colors.black_01,
96
+ val clearCondition: (() -> Boolean)? = null,
97
+ val keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
98
+ val keyboardActions: KeyboardActions = KeyboardActions.Default,
99
+ val modifier: Modifier = Modifier,
100
+ val iconModifier: Modifier = Modifier,
93
101
  )
94
102
 
95
103
  @Composable
@@ -98,7 +106,6 @@ fun InputSearch(
98
106
  text = remember { mutableStateOf("") },
99
107
  iconColor = AppTheme.current.colors.text.default
100
108
  ),
101
-
102
109
  ) {
103
110
  var isFocused by remember { mutableStateOf(false) }
104
111
  var isBlurred = false
@@ -124,8 +131,9 @@ fun InputSearch(
124
131
  lineHeight = 20.sp,
125
132
  fontWeight = inputSearchProps.fontWeight.value
126
133
  ),
127
- keyboardOptions = KeyboardOptions.Default.copy(keyboardType = inputSearchProps.keyboardType),
128
- modifier = Modifier.height(36.dp).onFocusChanged {
134
+ keyboardOptions = inputSearchProps.keyboardOptions.copy(keyboardType = inputSearchProps.keyboardType),
135
+ keyboardActions = inputSearchProps.keyboardActions,
136
+ modifier = inputSearchProps.modifier.height(36.dp).onFocusChanged {
129
137
  isFocused = it.isFocused
130
138
  if (it.isFocused) {
131
139
  inputSearchProps.onFocus()
@@ -137,7 +145,12 @@ fun InputSearch(
137
145
  decorationBox = { innerTextField ->
138
146
  Row(verticalAlignment = Alignment.CenterVertically) {
139
147
  Row(
140
- modifier = Modifier.weight(inputSearchProps.showButtonText.ifTrue(8f, 1f))
148
+ modifier = Modifier.weight(
149
+ inputSearchProps.showButtonText.ifTrue(
150
+ 8f,
151
+ 1f
152
+ )
153
+ )
141
154
  .background(
142
155
  inputSearchProps.backgroundColor,
143
156
  RoundedCornerShape(Radius.XL)
@@ -152,7 +165,6 @@ fun InputSearch(
152
165
  ),
153
166
  verticalAlignment = Alignment.CenterVertically
154
167
  ) {
155
- //leading icon
156
168
  Icon(
157
169
  source = "navigation_search",
158
170
  modifier = Modifier.padding(end = Spacing.XS),
@@ -168,12 +180,14 @@ fun InputSearch(
168
180
  lineHeight = 24.sp,
169
181
  fontWeight = inputSearchProps.fontWeight.value
170
182
  ),
171
- color = placeholderColor
183
+ maxLines = 1,
184
+ color = placeholderColor,
185
+ overflow = TextOverflow.Ellipsis
172
186
  )
173
187
  }
174
188
  innerTextField()
175
189
  }
176
- if (isFocused && inputSearchProps.text.value.isNotEmpty()) {
190
+ if (inputSearchProps.clearCondition?.invoke() == true || (isFocused && inputSearchProps.text.value.isNotEmpty())) {
177
191
  Row {
178
192
  Spacer(Modifier.width(Spacing.XS))
179
193
  Icon(
@@ -192,7 +206,8 @@ fun InputSearch(
192
206
  inputSearchProps.loading,
193
207
  inputSearchProps.icon,
194
208
  iconTintColor,
195
- inputSearchProps.onRightIconPressed
209
+ inputSearchProps.onRightIconPressed,
210
+ iconModifier = inputSearchProps.iconModifier
196
211
  )
197
212
  }
198
213
  }
@@ -5,16 +5,19 @@ import androidx.compose.ui.Modifier
5
5
  import androidx.compose.ui.graphics.Color
6
6
  import androidx.compose.ui.semantics.contentDescription
7
7
  import androidx.compose.ui.semantics.semantics
8
+ import androidx.compose.ui.semantics.testTag
8
9
  import androidx.compose.ui.text.TextLayoutResult
9
10
  import androidx.compose.ui.text.TextStyle
10
11
  import androidx.compose.ui.text.style.TextAlign
11
12
  import androidx.compose.ui.text.style.TextDecoration
12
13
  import androidx.compose.ui.text.style.TextOverflow
13
14
  import androidx.compose.ui.unit.sp
15
+ import vn.momo.kits.application.PlatformApi
14
16
  import vn.momo.kits.const.AppTheme
15
17
  import vn.momo.kits.const.Typography
16
18
  import vn.momo.kits.const.getFontFamily
17
19
  import vn.momo.kits.const.scaleSize
20
+ import vn.momo.kits.platform.getPlatformName
18
21
 
19
22
  @Composable
20
23
  fun Text(
@@ -27,13 +30,15 @@ fun Text(
27
30
  overflow: TextOverflow = TextOverflow.Clip,
28
31
  textDecoration: TextDecoration? = null,
29
32
  onTextLayout: ((TextLayoutResult) -> Unit)? = null,
30
- fontFamily: String = "SFProText"
33
+ fontFamily: String = "SFProText",
34
+ accessibilityId: String? = null
31
35
  ) {
32
36
  val fontSize = scaleSize(style.fontSize.value).sp
33
37
  val font = getFontFamily(fontFamily, style.fontWeight)
34
38
 
35
39
  androidx.compose.material3.Text(
36
- modifier = modifier.semantics { contentDescription = text },
40
+ modifier = modifier.semantics { testTag = accessibilityId ?: text
41
+ contentDescription = if (getPlatformName() == "Android" && accessibilityId != null) accessibilityId else text },
37
42
  text = text,
38
43
  color = color ?: AppTheme.current.colors.text.default,
39
44
  style = style,
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
- #Wed Aug 21 14:20:12 ICT 2024
8
- sdk.dir=/Users/huynhdung/Library/Android/sdk
7
+ #Tue Apr 23 16:40:15 ICT 2024
8
+ sdk.dir=/Users/hung.dao1/Library/Android/sdk
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/native-kits",
3
- "version": "0.89.33-rc.4",
3
+ "version": "0.89.33-sp.01",
4
4
  "private": false,
5
5
  "dependencies": {},
6
6
  "devDependencies": {},