@momo-kits/native-kits 0.89.30-beta.1 → 0.89.30-rc.2
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 +49 -73
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +22 -10
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +11 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +4 -3
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ 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
|
|
7
8
|
import androidx.compose.foundation.layout.Arrangement
|
|
8
9
|
import androidx.compose.foundation.layout.Box
|
|
9
10
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
|
@@ -15,6 +16,7 @@ import androidx.compose.foundation.layout.padding
|
|
|
15
16
|
import androidx.compose.foundation.layout.size
|
|
16
17
|
import androidx.compose.foundation.layout.width
|
|
17
18
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
19
|
+
import androidx.compose.material.ripple.rememberRipple
|
|
18
20
|
import androidx.compose.runtime.Composable
|
|
19
21
|
import androidx.compose.runtime.LaunchedEffect
|
|
20
22
|
import androidx.compose.runtime.getValue
|
|
@@ -24,12 +26,9 @@ import androidx.compose.runtime.setValue
|
|
|
24
26
|
import androidx.compose.runtime.snapshotFlow
|
|
25
27
|
import androidx.compose.ui.Alignment
|
|
26
28
|
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
|
|
33
32
|
import androidx.compose.ui.semantics.contentDescription
|
|
34
33
|
import androidx.compose.ui.semantics.semantics
|
|
35
34
|
import androidx.compose.ui.semantics.testTag
|
|
@@ -61,76 +60,43 @@ data class AnimatedHeader(
|
|
|
61
60
|
)
|
|
62
61
|
|
|
63
62
|
@Composable
|
|
64
|
-
fun
|
|
65
|
-
headerType: HeaderType = HeaderType.DEFAULT
|
|
63
|
+
fun HeaderImage(
|
|
64
|
+
headerType: HeaderType = HeaderType.DEFAULT,
|
|
65
|
+
headerBackground: String?,
|
|
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
|
-
)
|
|
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
|
-
)
|
|
71
|
+
Image(
|
|
72
|
+
source = headerBackground ?: "",
|
|
73
|
+
modifier = Modifier.fillMaxWidth().height(height),
|
|
74
|
+
options = Options(
|
|
75
|
+
contentScale = ContentScale.FillWidth
|
|
92
76
|
)
|
|
93
|
-
|
|
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
|
-
}
|
|
103
|
-
|
|
77
|
+
)
|
|
104
78
|
}
|
|
105
79
|
|
|
106
80
|
HeaderType.EXTENDED -> {
|
|
81
|
+
Image(
|
|
82
|
+
source = headerBackground ?: "",
|
|
83
|
+
modifier = Modifier.fillMaxWidth(),
|
|
84
|
+
options = Options(
|
|
85
|
+
contentScale = ContentScale.FillWidth
|
|
86
|
+
)
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
HeaderType.SURFACE -> {
|
|
91
|
+
val height = statusBarHeight + 52.dp
|
|
107
92
|
Box(
|
|
108
|
-
modifier = Modifier.fillMaxWidth().height(
|
|
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
|
-
)
|
|
93
|
+
modifier = Modifier.fillMaxWidth().height(height)
|
|
94
|
+
.background(AppTheme.current.colors.background.surface)
|
|
119
95
|
.bottomBorder(
|
|
120
|
-
strokeWidth =
|
|
96
|
+
strokeWidth = 2.dp,
|
|
121
97
|
color = AppTheme.current.colors.border.default
|
|
122
98
|
)
|
|
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
|
-
}
|
|
99
|
+
)
|
|
134
100
|
}
|
|
135
101
|
|
|
136
102
|
else -> {
|
|
@@ -152,16 +118,22 @@ fun Header(
|
|
|
152
118
|
scrollState: Int = 0
|
|
153
119
|
) {
|
|
154
120
|
val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
|
|
155
|
-
|
|
156
|
-
|
|
121
|
+
var tintIconColor = Colors.black_01
|
|
122
|
+
var backgroundButton = Colors.black_20.copy(alpha = 0.4f)
|
|
123
|
+
if (headerType == HeaderType.SURFACE) {
|
|
124
|
+
tintIconColor = AppTheme.current.colors.text.default
|
|
125
|
+
backgroundButton = Color.Transparent
|
|
126
|
+
}
|
|
157
127
|
|
|
158
128
|
var colorFraction by remember { mutableStateOf(0f) }
|
|
159
129
|
|
|
160
130
|
LaunchedEffect(scrollState) {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
131
|
+
if (headerType == HeaderType.SURFACE) {
|
|
132
|
+
snapshotFlow { scrollState }
|
|
133
|
+
.map { (it / 50f).coerceIn(0f, 1f) }
|
|
134
|
+
.distinctUntilChanged()
|
|
135
|
+
.collect { fraction -> colorFraction = fraction }
|
|
136
|
+
}
|
|
165
137
|
}
|
|
166
138
|
|
|
167
139
|
val tintIconColorAnim by animateColorAsState(
|
|
@@ -192,11 +164,15 @@ fun Header(
|
|
|
192
164
|
modifier = Modifier
|
|
193
165
|
.size(28.dp)
|
|
194
166
|
.then(
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
167
|
+
if (headerType == HeaderType.SURFACE) {
|
|
168
|
+
Modifier.border(
|
|
169
|
+
0.5.dp,
|
|
170
|
+
Colors.black_20.copy(alpha = 0.4f),
|
|
171
|
+
RoundedCornerShape(100)
|
|
172
|
+
)
|
|
173
|
+
} else {
|
|
174
|
+
Modifier
|
|
175
|
+
}
|
|
200
176
|
)
|
|
201
177
|
.background(
|
|
202
178
|
backgroundButton,
|
|
@@ -214,7 +190,7 @@ fun Header(
|
|
|
214
190
|
) {
|
|
215
191
|
Icon(
|
|
216
192
|
source = "ic_back_ios",
|
|
217
|
-
color = if (animatedHeader !== null) tintIconColorAnim else tintIconColor,
|
|
193
|
+
color = if (headerType == HeaderType.SURFACE && animatedHeader !== null) tintIconColorAnim else tintIconColor,
|
|
218
194
|
size = 20.dp,
|
|
219
195
|
)
|
|
220
196
|
}
|
|
@@ -245,7 +221,7 @@ fun Header(
|
|
|
245
221
|
) {
|
|
246
222
|
HeaderTitle(
|
|
247
223
|
title = title,
|
|
248
|
-
color = if (animatedHeader !== null) tintIconColorAnim else tintIconColor,
|
|
224
|
+
color = if (headerType == HeaderType.SURFACE && animatedHeader !== null) tintIconColorAnim else tintIconColor,
|
|
249
225
|
modifier = Modifier.semantics {
|
|
250
226
|
contentDescription = "title_navigation_header"
|
|
251
227
|
testTag = "title_navigation_header"
|
|
@@ -38,6 +38,7 @@ import vn.momo.kits.platform.getStatusBarHeight
|
|
|
38
38
|
|
|
39
39
|
enum class HeaderType {
|
|
40
40
|
DEFAULT,
|
|
41
|
+
SURFACE,
|
|
41
42
|
EXTENDED,
|
|
42
43
|
NONE
|
|
43
44
|
}
|
|
@@ -45,6 +46,7 @@ enum class HeaderType {
|
|
|
45
46
|
@Composable
|
|
46
47
|
fun Screen(
|
|
47
48
|
backgroundColor: Color? = null,
|
|
49
|
+
headerBackground: String? = null,
|
|
48
50
|
isBack: Boolean = true,
|
|
49
51
|
headerType: HeaderType = HeaderType.DEFAULT,
|
|
50
52
|
verticalArrangement: Arrangement.Vertical = Arrangement.Top,
|
|
@@ -88,14 +90,18 @@ fun Screen(
|
|
|
88
90
|
) {
|
|
89
91
|
|
|
90
92
|
if (animatedHeader === null) {
|
|
91
|
-
|
|
93
|
+
HeaderImage(
|
|
94
|
+
headerType,
|
|
95
|
+
headerBackground ?: AppTheme.current.assets.headerBackground
|
|
96
|
+
)
|
|
92
97
|
} else {
|
|
93
98
|
Box(
|
|
94
|
-
Modifier.zIndex(5f)
|
|
95
|
-
.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
+
Modifier.zIndex(5f).background(Color.White.copy(alpha = opacity))
|
|
100
|
+
.graphicsLayer { alpha = opacity }) {
|
|
101
|
+
HeaderImage(
|
|
102
|
+
headerType,
|
|
103
|
+
headerBackground ?: AppTheme.current.assets.headerBackground
|
|
104
|
+
)
|
|
99
105
|
}
|
|
100
106
|
}
|
|
101
107
|
|
|
@@ -123,7 +129,9 @@ fun Screen(
|
|
|
123
129
|
) {
|
|
124
130
|
|
|
125
131
|
Column(
|
|
126
|
-
modifier = if (scrollable) Modifier.weight(1f).padding(bottom = keyboardSize)
|
|
132
|
+
modifier = if (scrollable) Modifier.weight(1f).padding(bottom = keyboardSize)
|
|
133
|
+
.verticalScroll(scrollState) else
|
|
134
|
+
Modifier.padding(bottom = keyboardSize),
|
|
127
135
|
verticalArrangement = verticalArrangement,
|
|
128
136
|
horizontalAlignment = horizontalAlignment
|
|
129
137
|
) {
|
|
@@ -148,7 +156,8 @@ fun Screen(
|
|
|
148
156
|
scrollPosition = fabProps.scrollState?.value ?: scrollState.value,
|
|
149
157
|
onClick = fabProps.onClick,
|
|
150
158
|
containerColor = AppTheme.current.colors.primary,
|
|
151
|
-
bottom = fabProps.bottom
|
|
159
|
+
bottom = fabProps.bottom
|
|
160
|
+
?: if (footer != null) bottomPadding + 76.dp else bottomPadding + 12.dp,
|
|
152
161
|
icon = fabProps.icon,
|
|
153
162
|
iconColor = fabProps.iconColor,
|
|
154
163
|
text = fabProps.label,
|
|
@@ -177,8 +186,11 @@ fun Footer(footer: @Composable (() -> Unit)? = null, keyboardSize: Dp = 0.dp, bo
|
|
|
177
186
|
.background(AppTheme.current.colors.background.surface)
|
|
178
187
|
) {
|
|
179
188
|
Box(
|
|
180
|
-
Modifier
|
|
181
|
-
|
|
189
|
+
Modifier
|
|
190
|
+
.fillMaxWidth()
|
|
191
|
+
.padding(vertical = Spacing.S, horizontal = Spacing.M)
|
|
192
|
+
)
|
|
193
|
+
{
|
|
182
194
|
footer?.invoke()
|
|
183
195
|
}
|
|
184
196
|
}
|
|
@@ -123,7 +123,10 @@ fun TrustBanner(
|
|
|
123
123
|
modifier = Modifier
|
|
124
124
|
.width(64.dp)
|
|
125
125
|
.height(64.dp)
|
|
126
|
-
.padding(end = 8.dp)
|
|
126
|
+
.padding(end = 8.dp),
|
|
127
|
+
options = Options(
|
|
128
|
+
contentScale = ContentScale.Fit,
|
|
129
|
+
)
|
|
127
130
|
)
|
|
128
131
|
Column {
|
|
129
132
|
Text(
|
|
@@ -141,11 +144,17 @@ fun TrustBanner(
|
|
|
141
144
|
.padding(end = 4.dp)
|
|
142
145
|
.width(52.dp)
|
|
143
146
|
.height(20.dp)
|
|
147
|
+
,options = Options(
|
|
148
|
+
contentScale = ContentScale.Fit,
|
|
149
|
+
)
|
|
144
150
|
)
|
|
145
151
|
Image(
|
|
146
152
|
source = trustBanner.sslImage, modifier = Modifier
|
|
147
153
|
.width(52.dp)
|
|
148
|
-
.height(20.dp)
|
|
154
|
+
.height(20.dp),
|
|
155
|
+
options = Options(
|
|
156
|
+
contentScale = ContentScale.Fit,
|
|
157
|
+
)
|
|
149
158
|
)
|
|
150
159
|
}
|
|
151
160
|
Row(
|
|
@@ -106,7 +106,7 @@ val defaultTheme = Theme(
|
|
|
106
106
|
),
|
|
107
107
|
font = "SFProText",
|
|
108
108
|
assets = ThemeAssets(
|
|
109
|
-
headerBackground =
|
|
109
|
+
headerBackground = "https://static.momocdn.net/app/img/app/img/header-background.png"
|
|
110
110
|
)
|
|
111
111
|
)
|
|
112
112
|
|
|
@@ -168,5 +168,6 @@ val darkTheme = Theme(
|
|
|
168
168
|
|
|
169
169
|
|
|
170
170
|
val AppTheme = staticCompositionLocalOf { defaultTheme }
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
val AppStatusBar = staticCompositionLocalOf<Dp?> {
|
|
172
|
+
null
|
|
173
|
+
}
|