@momo-kits/native-kits 0.150.1-beta.3 → 0.151.2-test.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.
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +18 -12
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +10 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +0 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +0 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +14 -12
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +8 -7
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +3 -4
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +385 -0
- package/package.json +1 -1
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
package vn.momo.kits.components
|
|
2
|
+
|
|
1
3
|
import androidx.compose.foundation.background
|
|
2
4
|
import androidx.compose.foundation.border
|
|
3
5
|
import androidx.compose.foundation.layout.Arrangement
|
|
4
6
|
import androidx.compose.foundation.layout.Row
|
|
7
|
+
import androidx.compose.foundation.layout.height
|
|
5
8
|
import androidx.compose.foundation.layout.padding
|
|
6
|
-
import androidx.compose.foundation.layout.wrapContentHeight
|
|
7
9
|
import androidx.compose.foundation.layout.wrapContentWidth
|
|
8
10
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
9
11
|
import androidx.compose.runtime.Composable
|
|
@@ -12,15 +14,15 @@ import androidx.compose.ui.Alignment
|
|
|
12
14
|
import androidx.compose.ui.Modifier
|
|
13
15
|
import androidx.compose.ui.draw.clip
|
|
14
16
|
import androidx.compose.ui.graphics.Color
|
|
17
|
+
import androidx.compose.ui.text.style.TextAlign
|
|
15
18
|
import androidx.compose.ui.text.style.TextOverflow
|
|
16
19
|
import androidx.compose.ui.unit.Dp
|
|
17
20
|
import androidx.compose.ui.unit.dp
|
|
18
|
-
import vn.momo.kits.components.Icon
|
|
19
|
-
import vn.momo.kits.components.Text
|
|
20
21
|
import vn.momo.kits.const.AppTheme
|
|
21
22
|
import vn.momo.kits.const.Colors
|
|
22
23
|
import vn.momo.kits.const.Radius
|
|
23
24
|
import vn.momo.kits.const.Typography
|
|
25
|
+
import vn.momo.kits.const.scaleSize
|
|
24
26
|
import vn.momo.kits.modifier.activeOpacityClickable
|
|
25
27
|
import vn.momo.kits.modifier.conditional
|
|
26
28
|
import vn.momo.kits.modifier.setAutomationId
|
|
@@ -55,10 +57,13 @@ fun Chip(
|
|
|
55
57
|
ChipSize.LARGE -> ChipDefaults.Large
|
|
56
58
|
}
|
|
57
59
|
|
|
60
|
+
val (height, horizontal, iconSize, iconSpacing) =
|
|
61
|
+
listOf(scaleSize(dims.height), scaleSize(dims.horizontal), scaleSize(dims.iconSize), scaleSize(dims.iconSpacing))
|
|
62
|
+
|
|
58
63
|
Row(
|
|
59
64
|
modifier
|
|
60
65
|
.wrapContentWidth()
|
|
61
|
-
.
|
|
66
|
+
.height(height)
|
|
62
67
|
.clip(RoundedCornerShape(Radius.L))
|
|
63
68
|
.background(bg)
|
|
64
69
|
.conditional(selected) {
|
|
@@ -67,12 +72,12 @@ fun Chip(
|
|
|
67
72
|
.activeOpacityClickable {
|
|
68
73
|
onClick()
|
|
69
74
|
}
|
|
70
|
-
.padding(horizontal =
|
|
75
|
+
.padding(horizontal = horizontal)
|
|
71
76
|
.conditional(accessibilityLabel != null) {
|
|
72
77
|
setAutomationId(accessibilityLabel.toString())
|
|
73
78
|
},
|
|
74
79
|
verticalAlignment = Alignment.CenterVertically,
|
|
75
|
-
horizontalArrangement = Arrangement.spacedBy(
|
|
80
|
+
horizontalArrangement = Arrangement.spacedBy(iconSpacing)
|
|
76
81
|
) {
|
|
77
82
|
if (iconLeft != null) {
|
|
78
83
|
Icon(source = iconLeft, size = dims.iconSize, color = leftTint)
|
|
@@ -81,6 +86,7 @@ fun Chip(
|
|
|
81
86
|
if (!label.isNullOrEmpty()) {
|
|
82
87
|
Text(
|
|
83
88
|
text = label,
|
|
89
|
+
textAlign = TextAlign.Center,
|
|
84
90
|
color = textColor,
|
|
85
91
|
style = when (size) {
|
|
86
92
|
ChipSize.SMALL -> Typography.labelSMedium
|
|
@@ -92,7 +98,7 @@ fun Chip(
|
|
|
92
98
|
}
|
|
93
99
|
|
|
94
100
|
if (iconRight != null) {
|
|
95
|
-
Icon(source = iconRight, size =
|
|
101
|
+
Icon(source = iconRight, size = iconSize, color = rightTint)
|
|
96
102
|
}
|
|
97
103
|
}
|
|
98
104
|
}
|
|
@@ -102,23 +108,23 @@ enum class ChipSize { SMALL, LARGE }
|
|
|
102
108
|
object ChipDefaults {
|
|
103
109
|
@Immutable
|
|
104
110
|
data class Dimensions(
|
|
111
|
+
val height: Dp,
|
|
105
112
|
val horizontal: Dp,
|
|
106
|
-
val vertical: Dp,
|
|
107
113
|
val iconSize: Dp,
|
|
108
114
|
val iconSpacing: Dp,
|
|
109
115
|
)
|
|
110
116
|
|
|
111
117
|
val Large = Dimensions(
|
|
118
|
+
height = 32.dp,
|
|
112
119
|
horizontal = 12.dp,
|
|
113
|
-
vertical = 8.dp,
|
|
114
120
|
iconSize = 20.dp,
|
|
115
|
-
iconSpacing =
|
|
121
|
+
iconSpacing = 4.dp,
|
|
116
122
|
)
|
|
117
123
|
|
|
118
124
|
val Small = Dimensions(
|
|
125
|
+
height = 24.dp,
|
|
119
126
|
horizontal = 10.dp,
|
|
120
|
-
vertical = 6.dp,
|
|
121
127
|
iconSize = 16.dp,
|
|
122
|
-
iconSpacing =
|
|
128
|
+
iconSpacing = 4.dp,
|
|
123
129
|
)
|
|
124
130
|
}
|
|
@@ -7,6 +7,7 @@ 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.Dp
|
|
10
11
|
import androidx.compose.ui.unit.sp
|
|
11
12
|
import org.jetbrains.compose.resources.Font
|
|
12
13
|
import org.jetbrains.compose.resources.FontResource
|
|
@@ -58,6 +59,15 @@ fun scaleSize(size: Float): Float {
|
|
|
58
59
|
)
|
|
59
60
|
}
|
|
60
61
|
|
|
62
|
+
@Composable
|
|
63
|
+
fun scaleSize(size: Dp): Dp {
|
|
64
|
+
val density = LocalDensity.current
|
|
65
|
+
val px = with(density) { size.toPx() }
|
|
66
|
+
val scaledPx = scaleSize(px)
|
|
67
|
+
return with(density) { scaledPx.toDp() }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
61
71
|
@OptIn(InternalResourceApi::class)
|
|
62
72
|
@Composable
|
|
63
73
|
fun getFont(font: FontResource): FontFamily {
|
|
@@ -7,7 +7,6 @@ import androidx.compose.runtime.staticCompositionLocalOf
|
|
|
7
7
|
import androidx.navigation.NavController
|
|
8
8
|
import kotlinx.coroutines.CoroutineScope
|
|
9
9
|
import kotlinx.coroutines.Dispatchers
|
|
10
|
-
import kotlinx.coroutines.IO
|
|
11
10
|
import kotlinx.coroutines.SupervisorJob
|
|
12
11
|
import kotlinx.coroutines.cancel
|
|
13
12
|
import kotlinx.coroutines.delay
|
|
@@ -19,7 +18,7 @@ class Navigator(
|
|
|
19
18
|
private val navController: NavController,
|
|
20
19
|
private val maxApi: IMaxApi?
|
|
21
20
|
) {
|
|
22
|
-
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.
|
|
21
|
+
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
|
|
23
22
|
|
|
24
23
|
fun push(content: @Composable () -> Unit, options: NavigationOptions? = null) {
|
|
25
24
|
val route = DynamicScreenRegistry.register(content, options)
|
|
@@ -35,23 +34,26 @@ class Navigator(
|
|
|
35
34
|
}
|
|
36
35
|
}
|
|
37
36
|
|
|
38
|
-
fun pop(count: Int = 1) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
OverplayComponentRegistry.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
37
|
+
fun pop(count: Int = 1, callBack: (() -> Unit)? = null) {
|
|
38
|
+
scope.launch {
|
|
39
|
+
repeat(count) {
|
|
40
|
+
if (OverplayComponentRegistry.isOverplayShowing()){
|
|
41
|
+
OverplayComponentRegistry.clear()
|
|
42
|
+
delay(300L)
|
|
43
|
+
OverplayComponentRegistry.hardClearAfterDismiss()
|
|
44
|
+
} else {
|
|
45
|
+
if (navController.previousBackStackEntry != null){
|
|
46
|
+
navController.popBackStack()
|
|
46
47
|
delay(300L)
|
|
47
48
|
DynamicScreenRegistry.getLatestScreen()?.let { it1 ->
|
|
48
49
|
DynamicScreenRegistry.unregisterScreen(it1.id)
|
|
49
50
|
}
|
|
51
|
+
} else {
|
|
52
|
+
maxApi?.dismiss { }
|
|
50
53
|
}
|
|
51
|
-
} else {
|
|
52
|
-
maxApi?.dismiss { }
|
|
53
54
|
}
|
|
54
55
|
}
|
|
56
|
+
callBack?.invoke()
|
|
55
57
|
}
|
|
56
58
|
}
|
|
57
59
|
|
|
@@ -126,14 +126,16 @@ fun RowScope.renderHeaderContent(headerTitle: HeaderTitle, tintIconColor: Color)
|
|
|
126
126
|
is HeaderTitle.Default -> {
|
|
127
127
|
HeaderTitle(
|
|
128
128
|
title = headerTitle.title,
|
|
129
|
-
color = tintIconColor
|
|
130
|
-
modifier = Modifier.fillMaxWidth(),
|
|
131
|
-
textAlign = TextAlign.Start
|
|
129
|
+
color = tintIconColor
|
|
132
130
|
)
|
|
133
131
|
}
|
|
134
132
|
is HeaderTitle.Journey -> {}
|
|
135
133
|
is HeaderTitle.Location -> {}
|
|
136
|
-
is HeaderTitle.User -> {
|
|
134
|
+
is HeaderTitle.User -> {
|
|
135
|
+
HeaderUser(
|
|
136
|
+
data = headerTitle
|
|
137
|
+
)
|
|
138
|
+
}
|
|
137
139
|
}
|
|
138
140
|
}
|
|
139
141
|
}
|
|
@@ -161,9 +163,8 @@ sealed class HeaderTitle {
|
|
|
161
163
|
val title: String,
|
|
162
164
|
val subTitle: String? = null,
|
|
163
165
|
val image: List<String>? = null,
|
|
164
|
-
val dotColor:
|
|
165
|
-
val
|
|
166
|
-
val tintColor: String? = null,
|
|
166
|
+
val dotColor: Color? = null,
|
|
167
|
+
val tintColor: Color? = null,
|
|
167
168
|
val onPress: (() -> Unit)? = null,
|
|
168
169
|
val icons: List<String> = emptyList(),
|
|
169
170
|
val isLoading: Boolean = false
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
package vn.momo.kits.navigation.component
|
|
2
2
|
|
|
3
|
+
import androidx.compose.foundation.layout.fillMaxWidth
|
|
3
4
|
import androidx.compose.runtime.Composable
|
|
4
5
|
import androidx.compose.ui.Modifier
|
|
5
6
|
import androidx.compose.ui.graphics.Color
|
|
@@ -13,14 +14,12 @@ import vn.momo.kits.const.Typography
|
|
|
13
14
|
@Composable
|
|
14
15
|
fun HeaderTitle(
|
|
15
16
|
title: String = "",
|
|
16
|
-
modifier: Modifier = Modifier,
|
|
17
|
-
textAlign: TextAlign = TextAlign.Start,
|
|
18
17
|
color: Color? = null,
|
|
19
18
|
) {
|
|
20
19
|
Text(
|
|
21
|
-
modifier = Modifier.
|
|
20
|
+
modifier = Modifier.fillMaxWidth().zIndex(1f),
|
|
22
21
|
text = title,
|
|
23
|
-
textAlign =
|
|
22
|
+
textAlign = TextAlign.Start,
|
|
24
23
|
style = Typography.actionSBold.copy(
|
|
25
24
|
fontSize = 15.sp,
|
|
26
25
|
lineHeight = 22.sp,
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
package vn.momo.kits.navigation.component
|
|
2
|
+
|
|
3
|
+
import androidx.compose.foundation.background
|
|
4
|
+
import androidx.compose.foundation.border
|
|
5
|
+
import androidx.compose.foundation.layout.Arrangement
|
|
6
|
+
import androidx.compose.foundation.layout.Box
|
|
7
|
+
import androidx.compose.foundation.layout.Column
|
|
8
|
+
import androidx.compose.foundation.layout.Row
|
|
9
|
+
import androidx.compose.foundation.layout.Spacer
|
|
10
|
+
import androidx.compose.foundation.layout.fillMaxWidth
|
|
11
|
+
import androidx.compose.foundation.layout.height
|
|
12
|
+
import androidx.compose.foundation.layout.padding
|
|
13
|
+
import androidx.compose.foundation.layout.size
|
|
14
|
+
import androidx.compose.foundation.layout.width
|
|
15
|
+
import androidx.compose.foundation.layout.widthIn
|
|
16
|
+
import androidx.compose.foundation.shape.CircleShape
|
|
17
|
+
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
18
|
+
import androidx.compose.runtime.Composable
|
|
19
|
+
import androidx.compose.runtime.Immutable
|
|
20
|
+
import androidx.compose.runtime.remember
|
|
21
|
+
import androidx.compose.ui.Alignment
|
|
22
|
+
import androidx.compose.ui.Modifier
|
|
23
|
+
import androidx.compose.ui.draw.clip
|
|
24
|
+
import androidx.compose.ui.draw.clipToBounds
|
|
25
|
+
import androidx.compose.ui.layout.ContentScale
|
|
26
|
+
import androidx.compose.ui.text.style.TextOverflow
|
|
27
|
+
import androidx.compose.ui.unit.Dp
|
|
28
|
+
import androidx.compose.ui.unit.dp
|
|
29
|
+
import androidx.compose.ui.unit.sp
|
|
30
|
+
import vn.momo.kits.components.Image
|
|
31
|
+
import vn.momo.kits.components.Options
|
|
32
|
+
import vn.momo.kits.components.Skeleton
|
|
33
|
+
import vn.momo.kits.components.Text
|
|
34
|
+
import vn.momo.kits.const.AppTheme
|
|
35
|
+
import vn.momo.kits.const.Colors
|
|
36
|
+
import vn.momo.kits.const.Spacing
|
|
37
|
+
import vn.momo.kits.const.Typography
|
|
38
|
+
import vn.momo.kits.const.scaleSize
|
|
39
|
+
import vn.momo.kits.modifier.activeOpacityClickable
|
|
40
|
+
import vn.momo.kits.navigation.component.HeaderTitle.User
|
|
41
|
+
import vn.momo.kits.platform.getScreenDimensions
|
|
42
|
+
|
|
43
|
+
@Composable
|
|
44
|
+
fun HeaderUser(
|
|
45
|
+
data: HeaderTitle
|
|
46
|
+
) {
|
|
47
|
+
if (data !is User) return
|
|
48
|
+
|
|
49
|
+
if (data.isLoading) {
|
|
50
|
+
return TitleUserShimmer()
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
val maxWidth = getScreenDimensions().width.dp - scaleSize(172.dp)- (data.icons.size * 16).dp
|
|
54
|
+
|
|
55
|
+
Row(
|
|
56
|
+
modifier = Modifier
|
|
57
|
+
.fillMaxWidth()
|
|
58
|
+
.padding(vertical = Spacing.XS)
|
|
59
|
+
.activeOpacityClickable(enabled = data.onPress != null, onClick = { data.onPress?.invoke() }),
|
|
60
|
+
horizontalArrangement = Arrangement.SpaceBetween,
|
|
61
|
+
verticalAlignment = Alignment.CenterVertically
|
|
62
|
+
) {
|
|
63
|
+
Row(
|
|
64
|
+
modifier = Modifier.widthIn(max = maxWidth),
|
|
65
|
+
verticalAlignment = Alignment.CenterVertically
|
|
66
|
+
) {
|
|
67
|
+
Box(modifier = Modifier.size(Spacing.XXL)) {
|
|
68
|
+
AvatarGroup(urls = AvatarUrls(data.image ?: listOf()), title = data.title)
|
|
69
|
+
if (data.dotColor != null) {
|
|
70
|
+
Box(
|
|
71
|
+
modifier = Modifier
|
|
72
|
+
.align(Alignment.BottomEnd)
|
|
73
|
+
.size(10.dp)
|
|
74
|
+
.clip(CircleShape)
|
|
75
|
+
.background(data.dotColor)
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
Spacer(Modifier.width(6.dp))
|
|
81
|
+
|
|
82
|
+
Column(modifier = Modifier.weight(1f, fill = false)) {
|
|
83
|
+
Row(verticalAlignment = Alignment.CenterVertically) {
|
|
84
|
+
Text(
|
|
85
|
+
text = data.title,
|
|
86
|
+
color = data.tintColor,
|
|
87
|
+
style = Typography.actionXsBold,
|
|
88
|
+
maxLines = 1,
|
|
89
|
+
overflow = TextOverflow.Ellipsis
|
|
90
|
+
)
|
|
91
|
+
if (data.icons.isNotEmpty()) {
|
|
92
|
+
Spacer(Modifier.width(6.dp))
|
|
93
|
+
Row(verticalAlignment = Alignment.CenterVertically) {
|
|
94
|
+
data.icons.forEach { icon ->
|
|
95
|
+
RemoteIcon16(url = icon)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (!data.subTitle.isNullOrEmpty()) {
|
|
102
|
+
Spacer(Modifier.height(2.dp))
|
|
103
|
+
Text(
|
|
104
|
+
text = data.subTitle,
|
|
105
|
+
color = data.tintColor,
|
|
106
|
+
style = Typography.descriptionXsRegular,
|
|
107
|
+
maxLines = 1,
|
|
108
|
+
overflow = TextOverflow.Ellipsis
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@Composable
|
|
117
|
+
private fun TitleUserShimmer() {
|
|
118
|
+
val theme = AppTheme.current
|
|
119
|
+
Row(
|
|
120
|
+
modifier = Modifier
|
|
121
|
+
.fillMaxWidth()
|
|
122
|
+
.padding(vertical = Spacing.XS),
|
|
123
|
+
verticalAlignment = Alignment.CenterVertically
|
|
124
|
+
) {
|
|
125
|
+
Box(
|
|
126
|
+
modifier = Modifier
|
|
127
|
+
.size(Spacing.XXL)
|
|
128
|
+
.clip(CircleShape)
|
|
129
|
+
.background(theme.colors.border.default)
|
|
130
|
+
) {
|
|
131
|
+
Skeleton()
|
|
132
|
+
}
|
|
133
|
+
Spacer(Modifier.width(Spacing.M / 2))
|
|
134
|
+
Column(modifier = Modifier.fillMaxWidth()) {
|
|
135
|
+
Box(
|
|
136
|
+
modifier = Modifier
|
|
137
|
+
.height(18.dp)
|
|
138
|
+
.width(120.dp)
|
|
139
|
+
.clip(RoundedCornerShape(8.dp))
|
|
140
|
+
) { Skeleton() }
|
|
141
|
+
Spacer(Modifier.height(Spacing.XXS))
|
|
142
|
+
Box(
|
|
143
|
+
modifier = Modifier
|
|
144
|
+
.height(12.dp)
|
|
145
|
+
.width(120.dp)
|
|
146
|
+
.clip(RoundedCornerShape(8.dp))
|
|
147
|
+
) { Skeleton() }
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
@Composable
|
|
153
|
+
private fun AvatarGroup(
|
|
154
|
+
urls: AvatarUrls?,
|
|
155
|
+
title: String? = null,
|
|
156
|
+
size: Dp = Spacing.XXL
|
|
157
|
+
) {
|
|
158
|
+
val theme = AppTheme.current
|
|
159
|
+
val modifierBorder = remember {
|
|
160
|
+
Modifier.clip(CircleShape).border(width = (0.5).dp, color = theme.colors.border.default, shape = CircleShape)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
when (urls?.items?.size) {
|
|
164
|
+
0 -> InitialsAvatar(
|
|
165
|
+
modifier = modifierBorder,
|
|
166
|
+
name = title ?: "",
|
|
167
|
+
fallbackInitials = null,
|
|
168
|
+
size = size
|
|
169
|
+
)
|
|
170
|
+
1 -> SingleAvatar(modifier = modifierBorder, urls.items[0], size)
|
|
171
|
+
2 -> TwoAvatar(modifier = modifierBorder, urls, size)
|
|
172
|
+
3 -> ThreeAvatar(modifier = modifierBorder, urls, size)
|
|
173
|
+
4 -> FourAvatar(modifier = modifierBorder, urls, size)
|
|
174
|
+
else -> ManyAvatar(modifier = modifierBorder, urls!!, size)
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@Composable
|
|
179
|
+
private fun SingleAvatar(modifier: Modifier = Modifier, url: String, size: Dp) {
|
|
180
|
+
Image(
|
|
181
|
+
source = url,
|
|
182
|
+
options = Options(
|
|
183
|
+
contentScale = ContentScale.Crop
|
|
184
|
+
),
|
|
185
|
+
modifier = modifier
|
|
186
|
+
.size(size)
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
@Composable
|
|
191
|
+
private fun TwoAvatar(modifier: Modifier = Modifier, urls: AvatarUrls, size: Dp) {
|
|
192
|
+
val child = 24.dp
|
|
193
|
+
Box(modifier = Modifier.size(size)) {
|
|
194
|
+
Image(
|
|
195
|
+
source = urls.items[0],
|
|
196
|
+
options = Options(
|
|
197
|
+
contentScale = ContentScale.Crop
|
|
198
|
+
),
|
|
199
|
+
modifier = modifier
|
|
200
|
+
.size(child)
|
|
201
|
+
.align(Alignment.TopEnd)
|
|
202
|
+
)
|
|
203
|
+
Image(
|
|
204
|
+
source = urls.items[1],
|
|
205
|
+
options = Options(
|
|
206
|
+
contentScale = ContentScale.Crop
|
|
207
|
+
),
|
|
208
|
+
modifier = modifier
|
|
209
|
+
.size(child)
|
|
210
|
+
.align(Alignment.BottomStart)
|
|
211
|
+
)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
@Composable
|
|
216
|
+
private fun ThreeAvatar(modifier: Modifier = Modifier, urls: AvatarUrls, size: Dp) {
|
|
217
|
+
val child = 16.dp
|
|
218
|
+
Box(modifier = Modifier.size(size).padding(2.dp)) {
|
|
219
|
+
Image(
|
|
220
|
+
source = urls.items[0],
|
|
221
|
+
options = Options(
|
|
222
|
+
contentScale = ContentScale.Crop
|
|
223
|
+
),
|
|
224
|
+
modifier = modifier
|
|
225
|
+
.size(child)
|
|
226
|
+
.align(Alignment.BottomEnd)
|
|
227
|
+
)
|
|
228
|
+
Image(
|
|
229
|
+
source = urls.items[1],
|
|
230
|
+
options = Options(
|
|
231
|
+
contentScale = ContentScale.Crop
|
|
232
|
+
),
|
|
233
|
+
modifier = modifier
|
|
234
|
+
.size(child)
|
|
235
|
+
.align(Alignment.TopCenter)
|
|
236
|
+
)
|
|
237
|
+
Image(
|
|
238
|
+
source = urls.items[2],
|
|
239
|
+
options = Options(
|
|
240
|
+
contentScale = ContentScale.Crop
|
|
241
|
+
),
|
|
242
|
+
modifier = modifier
|
|
243
|
+
.size(child)
|
|
244
|
+
.align(Alignment.BottomStart)
|
|
245
|
+
)
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
@Composable
|
|
250
|
+
private fun FourAvatar(modifier: Modifier = Modifier, urls: AvatarUrls, size: Dp) {
|
|
251
|
+
val child = 16.dp
|
|
252
|
+
Box(modifier = Modifier.size(size).padding(1.dp)) {
|
|
253
|
+
Image(
|
|
254
|
+
source = urls.items[0],
|
|
255
|
+
options = Options(
|
|
256
|
+
contentScale = ContentScale.Crop
|
|
257
|
+
),
|
|
258
|
+
modifier = modifier
|
|
259
|
+
.size(child)
|
|
260
|
+
.align(Alignment.BottomStart)
|
|
261
|
+
)
|
|
262
|
+
Image(
|
|
263
|
+
source = urls.items[1],
|
|
264
|
+
options = Options(
|
|
265
|
+
contentScale = ContentScale.Crop
|
|
266
|
+
),
|
|
267
|
+
modifier = modifier
|
|
268
|
+
.size(child)
|
|
269
|
+
.align(Alignment.BottomEnd)
|
|
270
|
+
)
|
|
271
|
+
Image(
|
|
272
|
+
source = urls.items[2],
|
|
273
|
+
options = Options(
|
|
274
|
+
contentScale = ContentScale.Crop
|
|
275
|
+
),
|
|
276
|
+
modifier = modifier
|
|
277
|
+
.size(child)
|
|
278
|
+
.align(Alignment.TopEnd)
|
|
279
|
+
)
|
|
280
|
+
Image(
|
|
281
|
+
source = urls.items[3],
|
|
282
|
+
options = Options(
|
|
283
|
+
contentScale = ContentScale.Crop
|
|
284
|
+
),
|
|
285
|
+
modifier = modifier
|
|
286
|
+
.size(child)
|
|
287
|
+
.align(Alignment.TopStart)
|
|
288
|
+
)
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
@Composable
|
|
293
|
+
private fun ManyAvatar(modifier: Modifier = Modifier, urls: AvatarUrls, size: Dp) {
|
|
294
|
+
val child = 16.dp
|
|
295
|
+
val more = urls.items.size - 3
|
|
296
|
+
Box(modifier = Modifier.size(size).padding(1.dp)) {
|
|
297
|
+
Image(
|
|
298
|
+
source = urls.items[0],
|
|
299
|
+
options = Options(
|
|
300
|
+
contentScale = ContentScale.Crop
|
|
301
|
+
),
|
|
302
|
+
modifier = modifier
|
|
303
|
+
.size(child)
|
|
304
|
+
.align(Alignment.BottomStart)
|
|
305
|
+
)
|
|
306
|
+
Image(
|
|
307
|
+
source = urls.items[1],
|
|
308
|
+
options = Options(
|
|
309
|
+
contentScale = ContentScale.Crop
|
|
310
|
+
),
|
|
311
|
+
modifier = modifier
|
|
312
|
+
.size(child)
|
|
313
|
+
.align(Alignment.TopEnd)
|
|
314
|
+
)
|
|
315
|
+
Image(
|
|
316
|
+
source = urls.items[2],
|
|
317
|
+
options = Options(
|
|
318
|
+
contentScale = ContentScale.Crop
|
|
319
|
+
),
|
|
320
|
+
modifier = modifier
|
|
321
|
+
.size(child)
|
|
322
|
+
.align(Alignment.TopStart)
|
|
323
|
+
)
|
|
324
|
+
Box(
|
|
325
|
+
modifier = modifier
|
|
326
|
+
.size(child)
|
|
327
|
+
.align(Alignment.BottomEnd)
|
|
328
|
+
.background(Colors.pink_09)
|
|
329
|
+
.padding(1.dp)
|
|
330
|
+
.clipToBounds(),
|
|
331
|
+
contentAlignment = Alignment.Center
|
|
332
|
+
) {
|
|
333
|
+
Text(
|
|
334
|
+
text = "+$more",
|
|
335
|
+
color = Colors.pink_03,
|
|
336
|
+
style = Typography.descriptionXsRegular.copy(fontSize = 8.sp),
|
|
337
|
+
maxLines = 1,
|
|
338
|
+
overflow = TextOverflow.Visible
|
|
339
|
+
)
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
@Composable
|
|
345
|
+
private fun InitialsAvatar(
|
|
346
|
+
modifier: Modifier = Modifier,
|
|
347
|
+
name: String,
|
|
348
|
+
fallbackInitials: String? = null,
|
|
349
|
+
size: Dp = Spacing.XXL
|
|
350
|
+
) {
|
|
351
|
+
val initials = remember(name, fallbackInitials) {
|
|
352
|
+
fallbackInitials ?: run {
|
|
353
|
+
val words = name.trim().split(Regex("\\s+")).takeLast(2)
|
|
354
|
+
words.joinToString("") { it.firstOrNull()?.uppercase() ?: "" }
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
Box(
|
|
358
|
+
modifier = modifier
|
|
359
|
+
.size(size)
|
|
360
|
+
.background(Colors.pink_09),
|
|
361
|
+
contentAlignment = Alignment.Center
|
|
362
|
+
) {
|
|
363
|
+
Text(
|
|
364
|
+
text = initials,
|
|
365
|
+
color = Colors.pink_03,
|
|
366
|
+
style = Typography.descriptionXsRegular
|
|
367
|
+
)
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
@Composable
|
|
372
|
+
private fun RemoteIcon16(url: String) {
|
|
373
|
+
Image(
|
|
374
|
+
source = url,
|
|
375
|
+
options = Options(
|
|
376
|
+
contentScale = ContentScale.Crop
|
|
377
|
+
),
|
|
378
|
+
modifier = Modifier
|
|
379
|
+
.size(16.dp)
|
|
380
|
+
.clip(RoundedCornerShape(4.dp)),
|
|
381
|
+
)
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
@Immutable
|
|
385
|
+
data class AvatarUrls(val items: List<String>)
|