@momo-kits/native-kits 0.151.2-test.12 → 0.151.2-test.13

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,18 +3,25 @@ package vn.momo.kits.platform
3
3
  import android.annotation.SuppressLint
4
4
  import android.content.res.Resources
5
5
  import android.graphics.BlurMaskFilter
6
+ import android.graphics.PorterDuff
7
+ import android.graphics.PorterDuffColorFilter
6
8
  import android.os.Build
7
- import androidx.compose.ui.graphics.Color
8
9
  import androidx.compose.runtime.Composable
9
10
  import androidx.compose.runtime.getValue
10
11
  import androidx.compose.ui.Modifier
12
+ import androidx.compose.ui.graphics.Color
11
13
  import androidx.compose.ui.graphics.NativePaint
14
+ import androidx.compose.ui.graphics.toArgb
12
15
  import androidx.compose.ui.platform.LocalConfiguration
13
16
  import androidx.compose.ui.unit.Dp
14
17
  import androidx.compose.ui.unit.dp
18
+ import com.airbnb.lottie.LottieProperty
19
+ import com.airbnb.lottie.compose.LottieAnimation
15
20
  import com.airbnb.lottie.compose.LottieCompositionSpec
16
21
  import com.airbnb.lottie.compose.LottieConstants
17
22
  import com.airbnb.lottie.compose.rememberLottieComposition
23
+ import com.airbnb.lottie.compose.rememberLottieDynamicProperties
24
+ import com.airbnb.lottie.compose.rememberLottieDynamicProperty
18
25
  import vn.momo.kits.const.AppNavigationBar
19
26
  import vn.momo.kits.const.AppStatusBar
20
27
  import vn.momo.kits.utils.readJson
@@ -61,13 +68,30 @@ actual fun getAndroidBuildVersion(): Int = Build.VERSION.SDK_INT
61
68
  actual fun LottieAnimation(
62
69
  path: String,
63
70
  tintColor: Color?,
71
+ bgColor: Color?,
64
72
  modifier: Modifier
65
73
  ) {
66
- val composition by rememberLottieComposition(LottieCompositionSpec.JsonString(readJson(path)))
74
+ val composition by rememberLottieComposition(
75
+ LottieCompositionSpec.JsonString(readJson(path))
76
+ )
77
+
78
+ val colorFilter = PorterDuffColorFilter(
79
+ tintColor?.toArgb() ?: Color.White.toArgb(),
80
+ PorterDuff.Mode.SRC_ATOP
81
+ )
82
+
83
+ val dynamicProperties = rememberLottieDynamicProperties(
84
+ rememberLottieDynamicProperty(
85
+ property = LottieProperty.COLOR_FILTER,
86
+ value = colorFilter,
87
+ keyPath = arrayOf("**")
88
+ )
89
+ )
67
90
 
68
- com.airbnb.lottie.compose.LottieAnimation(
91
+ LottieAnimation(
69
92
  composition = composition,
70
- modifier = modifier,
71
93
  iterations = LottieConstants.IterateForever,
94
+ dynamicProperties = if (tintColor != null ) dynamicProperties else null,
95
+ modifier = modifier
72
96
  )
73
97
  }
@@ -12,10 +12,11 @@ import androidx.compose.foundation.layout.padding
12
12
  import androidx.compose.foundation.layout.size
13
13
  import androidx.compose.foundation.shape.RoundedCornerShape
14
14
  import androidx.compose.runtime.Composable
15
+ import androidx.compose.runtime.CompositionLocalProvider
15
16
  import androidx.compose.runtime.remember
17
+ import androidx.compose.runtime.staticCompositionLocalOf
16
18
  import androidx.compose.ui.Alignment
17
19
  import androidx.compose.ui.Modifier
18
- import androidx.compose.ui.draw.alpha
19
20
  import androidx.compose.ui.draw.clip
20
21
  import androidx.compose.ui.graphics.Color
21
22
  import androidx.compose.ui.text.TextStyle
@@ -106,8 +107,9 @@ fun getIconSpace(size: Size): Dp {
106
107
  }
107
108
 
108
109
  @Composable
109
- fun getTextColor(type: ButtonType): Color {
110
+ fun getTextColor(loading: Boolean, type: ButtonType): Color {
110
111
  val theme = AppTheme.current
112
+
111
113
  return remember(type, theme) {
112
114
  when (type) {
113
115
  ButtonType.DISABLED -> theme.colors.text.disable
@@ -117,28 +119,28 @@ fun getTextColor(type: ButtonType): Color {
117
119
  ButtonType.TONAL -> theme.colors.primary
118
120
  ButtonType.DANGER -> Colors.black_01
119
121
  ButtonType.TEXT -> theme.colors.primary
120
- }
122
+ }.withLoading(loading)
121
123
  }
122
124
  }
123
125
 
124
126
  @Composable
125
127
  fun RenderTitle(size: Size, title: String = "", type: ButtonType) {
126
128
  val style = remember(size) { getStyle(size) }
127
- val color = getTextColor(type)
129
+ val color = TextColor.current
128
130
  Text(style = style, text = title, color = color, overflow = TextOverflow.Ellipsis, maxLines = 1)
129
131
  }
130
132
 
131
133
  @Composable
132
134
  fun RenderLeading(
133
- loading: Boolean,
134
135
  size: Size,
135
136
  useTintColor: Boolean = true,
136
- type: ButtonType,
137
137
  iconLeft: String = "",
138
138
  ) {
139
+ val loading = IsLoading.current
140
+ val bgColor = BackgroundColor.current
139
141
  val iconSize = remember(size) { getIconSize(size) }
140
142
  val marginRight = remember(size) { getIconSpace(size) }
141
- val color = if (useTintColor) getTextColor(type) else Color.Unspecified
143
+ val color = if (useTintColor) TextColor.current else Color.Unspecified
142
144
 
143
145
  Row(
144
146
  verticalAlignment = Alignment.CenterVertically,
@@ -148,6 +150,8 @@ fun RenderLeading(
148
150
  Box(Modifier.padding(end = marginRight)) {
149
151
  LottieAnimation(
150
152
  modifier = Modifier.size(iconSize),
153
+ bgColor = bgColor,
154
+ tintColor = color,
151
155
  path = "files/lottie_circle_loader"
152
156
  )
153
157
  }
@@ -169,9 +173,8 @@ fun RenderTrailing(
169
173
  iconRight: String,
170
174
  size: Size,
171
175
  useTintColor: Boolean,
172
- type: ButtonType,
173
176
  ) {
174
- val color = if (useTintColor) getTextColor(type) else Color.Unspecified
177
+ val color = if (useTintColor) TextColor.current else Color.Unspecified
175
178
  val marginLeft = remember(size) { getIconSpace(size) }
176
179
 
177
180
  if (iconRight.isNotEmpty()) {
@@ -192,39 +195,60 @@ fun getTypeStyle(
192
195
  size: Size,
193
196
  ): Modifier {
194
197
  val theme = AppTheme.current
198
+ val bgColor = BackgroundColor.current
195
199
  val radius = remember(size) { size.value.radius }
200
+ val modifier = Modifier.background(bgColor)
196
201
 
197
202
  return remember(type, color, theme, radius) {
198
203
  when (type) {
199
- ButtonType.DISABLED -> Modifier.background(theme.colors.background.disable)
204
+ ButtonType.DISABLED -> modifier
200
205
  .border(0.dp, Color.Unspecified, RoundedCornerShape(radius))
201
206
 
202
- ButtonType.PRIMARY -> Modifier.background(theme.colors.primary)
207
+ ButtonType.PRIMARY -> modifier
203
208
  .border(0.dp, Color.Unspecified, RoundedCornerShape(radius))
204
209
 
205
- ButtonType.SECONDARY -> Modifier
206
- .background(theme.colors.background.surface)
210
+ ButtonType.SECONDARY -> modifier
207
211
  .border(1.dp, theme.colors.border.default, RoundedCornerShape(radius))
208
212
 
209
- ButtonType.OUTLINE -> Modifier
210
- .background(theme.colors.background.surface)
213
+ ButtonType.OUTLINE -> modifier
211
214
  .border(
212
215
  1.dp,
213
216
  color ?: theme.colors.primary,
214
217
  RoundedCornerShape(radius)
215
218
  )
216
219
 
217
- ButtonType.TONAL -> Modifier.background(theme.colors.background.tonal)
220
+ ButtonType.TONAL -> modifier
218
221
  .border(0.dp, Color.Unspecified, RoundedCornerShape(radius))
219
222
 
220
- ButtonType.DANGER -> Modifier.background(theme.colors.error.primary)
223
+ ButtonType.DANGER -> modifier
221
224
  .border(0.dp, Color.Unspecified, RoundedCornerShape(radius))
222
225
 
223
- ButtonType.TEXT -> Modifier
226
+ ButtonType.TEXT -> modifier
224
227
  }
225
228
  }
226
229
  }
227
230
 
231
+ @Composable
232
+ fun getButtonBackgroundColor(
233
+ loading: Boolean,
234
+ type: ButtonType
235
+ ): Color {
236
+ val theme = AppTheme.current
237
+
238
+ return when (type) {
239
+ ButtonType.DISABLED -> theme.colors.background.disable.withLoading(loading)
240
+ ButtonType.PRIMARY -> theme.colors.primary.withLoading(loading)
241
+ ButtonType.SECONDARY -> theme.colors.background.surface.withLoading(loading)
242
+ ButtonType.OUTLINE -> theme.colors.background.surface.withLoading(loading)
243
+ ButtonType.TONAL -> theme.colors.background.tonal.withLoading(loading)
244
+ ButtonType.DANGER -> theme.colors.error.primary.withLoading(loading)
245
+ ButtonType.TEXT -> Color.Unspecified
246
+ }
247
+ }
248
+
249
+ fun Color.withLoading(loading: Boolean): Color =
250
+ this.copy(alpha = if (loading) 0.75f else 1f)
251
+
228
252
  /**
229
253
  * @param onClick called when this button is clicked
230
254
  * @param type [ButtonType] that define the type of button.
@@ -266,30 +290,36 @@ fun Button(
266
290
  )
267
291
 
268
292
  val sizeSpecs = remember(size) { size.value }
269
-
270
- Row(
271
- modifier = customModifier
272
- .then(getTypeStyle(type, size = size))
273
- .padding(horizontal = sizeSpecs.padding)
274
- .defaultMinSize(minWidth = sizeSpecs.width)
275
- .height(sizeSpecs.height)
276
- .alpha(if(loading) 0.75f else 1f),
277
- horizontalArrangement = Arrangement.Center,
278
- verticalAlignment = Alignment.CenterVertically,
279
- ) {
280
- RenderLeading(
281
- loading,
282
- size,
283
- useTintColor,
284
- type,
285
- iconLeft = iconLeft
286
- )
287
- RenderTitle(size, title, type = type)
288
- RenderTrailing(
289
- size = size,
290
- useTintColor = useTintColor,
291
- type = type,
292
- iconRight = iconRight
293
- )
293
+ CompositionLocalProvider(
294
+ IsLoading provides loading,
295
+ BackgroundColor provides getButtonBackgroundColor(loading, type),
296
+ TextColor provides getTextColor(loading, type)
297
+ ){
298
+ Row(
299
+ modifier = customModifier
300
+ .then(getTypeStyle(type, size = size))
301
+ .padding(horizontal = sizeSpecs.padding)
302
+ .defaultMinSize(minWidth = sizeSpecs.width)
303
+ .height(sizeSpecs.height),
304
+ horizontalArrangement = Arrangement.Center,
305
+ verticalAlignment = Alignment.CenterVertically,
306
+ ) {
307
+ RenderLeading(
308
+ size = size,
309
+ useTintColor = useTintColor,
310
+ iconLeft = iconLeft
311
+ )
312
+ RenderTitle(size, title, type = type)
313
+ RenderTrailing(
314
+ size = size,
315
+ useTintColor = useTintColor,
316
+ iconRight = iconRight
317
+ )
318
+ }
294
319
  }
295
320
  }
321
+
322
+ private val IsLoading = staticCompositionLocalOf<Boolean> { false }
323
+ private val BackgroundColor = staticCompositionLocalOf<Color> { Color.Transparent }
324
+ private val TextColor = staticCompositionLocalOf<Color> { Color.Transparent }
325
+
@@ -33,5 +33,6 @@ expect fun getAndroidBuildVersion(): Int
33
33
  expect fun LottieAnimation(
34
34
  path: String,
35
35
  tintColor: Color? = null,
36
+ bgColor: Color? = null,
36
37
  modifier: Modifier = Modifier
37
38
  )
@@ -14,11 +14,13 @@ import androidx.compose.runtime.setValue
14
14
  import androidx.compose.ui.Modifier
15
15
  import androidx.compose.ui.graphics.Color
16
16
  import androidx.compose.ui.graphics.NativePaint
17
+ import androidx.compose.ui.graphics.toArgb
17
18
  import androidx.compose.ui.interop.UIKitView
18
19
  import androidx.compose.ui.unit.Dp
19
20
  import androidx.compose.ui.unit.dp
20
21
  import cocoapods.lottie_ios.CompatibleAnimation
21
22
  import cocoapods.lottie_ios.CompatibleAnimationView
23
+ import cocoapods.lottie_ios.CompatibleAnimationKeypath
22
24
  import kotlinx.cinterop.ExperimentalForeignApi
23
25
  import kotlinx.cinterop.get
24
26
  import kotlinx.cinterop.memScoped
@@ -66,6 +68,7 @@ actual fun getAndroidBuildVersion(): Int = 999
66
68
  actual fun LottieAnimation(
67
69
  path: String,
68
70
  tintColor: Color?,
71
+ bgColor: Color?,
69
72
  modifier: Modifier
70
73
  ) {
71
74
  var animation by remember { mutableStateOf<CompatibleAnimation?>(null) }
@@ -84,10 +87,38 @@ actual fun LottieAnimation(
84
87
  {
85
88
  CompatibleAnimationView(value).also {
86
89
  it.translatesAutoresizingMaskIntoConstraints = true
87
- it.setBackgroundColor(UIColor.whiteColor)
90
+ it.setBackgroundColor(bgColor?.toUIColor() ?: UIColor.whiteColor)
88
91
  it.setLoopAnimationCount(-1.0)
89
92
  it.setAnimationSpeed(1.0)
90
93
 
94
+ if (tintColor != null) {
95
+ val uiColor = tintColor.toUIColor()
96
+
97
+ it.setColorValue(
98
+ uiColor,
99
+ CompatibleAnimationKeypath("**.Fill 1.Color")
100
+ )
101
+ it.setColorValue(
102
+ uiColor,
103
+ CompatibleAnimationKeypath("**.Fill.Color")
104
+ )
105
+ it.setColorValue(
106
+ uiColor,
107
+ CompatibleAnimationKeypath("**.Color")
108
+ )
109
+
110
+ it.setColorValue(
111
+ uiColor,
112
+ CompatibleAnimationKeypath("**.Stroke 1.Color")
113
+ )
114
+ it.setColorValue(
115
+ uiColor,
116
+ CompatibleAnimationKeypath("**.Stroke.Color")
117
+ )
118
+ }
119
+
120
+
121
+
91
122
  it.play()
92
123
  }
93
124
  }
@@ -101,4 +132,20 @@ actual fun LottieAnimation(
101
132
  }
102
133
  }
103
134
  }
135
+ }
136
+
137
+ fun Color.toUIColor(): UIColor {
138
+ val argb = this.toArgb()
139
+
140
+ val a = ((argb shr 24) and 0xFF) / 255.0
141
+ val r = ((argb shr 16) and 0xFF) / 255.0
142
+ val g = ((argb shr 8) and 0xFF) / 255.0
143
+ val b = (argb and 0xFF) / 255.0
144
+
145
+ return UIColor(
146
+ red = r,
147
+ green = g,
148
+ blue = b,
149
+ alpha = a
150
+ )
104
151
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/native-kits",
3
- "version": "0.151.2-test.12",
3
+ "version": "0.151.2-test.13",
4
4
  "private": false,
5
5
  "dependencies": {
6
6
  "@momo-platform/native-max-api": "1.0.18"