@momo-kits/native-kits 0.113.2-beta.4 → 0.113.3-beta.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/application/Header.kt +9 -32
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +39 -25
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +5 -5
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +43 -9
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +2 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +0 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +12 -13
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +22 -14
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +11 -20
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +1 -1
- package/ios/Image/Image.swift +1 -1
- package/ios/Popup/PopupDisplay.swift +13 -6
- package/local.properties +2 -2
- package/package.json +1 -1
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
package vn.momo.kits.application
|
|
2
2
|
|
|
3
|
-
import androidx.compose.animation.animateColorAsState
|
|
4
3
|
import androidx.compose.foundation.background
|
|
5
4
|
import androidx.compose.foundation.border
|
|
6
5
|
import androidx.compose.foundation.clickable
|
|
@@ -24,7 +23,6 @@ import androidx.compose.runtime.setValue
|
|
|
24
23
|
import androidx.compose.runtime.snapshotFlow
|
|
25
24
|
import androidx.compose.ui.Alignment
|
|
26
25
|
import androidx.compose.ui.Modifier
|
|
27
|
-
import androidx.compose.ui.graphics.Color
|
|
28
26
|
import androidx.compose.ui.graphics.graphicsLayer
|
|
29
27
|
import androidx.compose.ui.semantics.semantics
|
|
30
28
|
import androidx.compose.ui.semantics.testTag
|
|
@@ -42,15 +40,6 @@ import vn.momo.kits.const.Spacing
|
|
|
42
40
|
import vn.momo.kits.modifier.setAutomationId
|
|
43
41
|
import vn.momo.kits.platform.getStatusBarHeight
|
|
44
42
|
|
|
45
|
-
enum class TitlePosition {
|
|
46
|
-
LEFT, CENTER,
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
data class AnimatedHeader(
|
|
50
|
-
val type: HeaderType = HeaderType.DEFAULT,
|
|
51
|
-
val composable: @Composable (scrollState: Int) -> Unit = {}
|
|
52
|
-
)
|
|
53
|
-
|
|
54
43
|
@Composable
|
|
55
44
|
fun Header(
|
|
56
45
|
headerType: HeaderType = HeaderType.DEFAULT,
|
|
@@ -67,7 +56,6 @@ fun Header(
|
|
|
67
56
|
val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
|
|
68
57
|
val tintIconColor = AppTheme.current.colors.text.default
|
|
69
58
|
val backgroundButton = Colors.black_01.copy(alpha = 0.6f)
|
|
70
|
-
val miniAppContext = ApplicationContext.current
|
|
71
59
|
|
|
72
60
|
var colorFraction by remember { mutableStateOf(0f) }
|
|
73
61
|
|
|
@@ -78,12 +66,10 @@ fun Header(
|
|
|
78
66
|
.collect { fraction -> colorFraction = fraction }
|
|
79
67
|
}
|
|
80
68
|
|
|
81
|
-
val backgroundSearch
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
colorFraction
|
|
86
|
-
)
|
|
69
|
+
val backgroundSearch = animateColor(
|
|
70
|
+
Colors.black_01,
|
|
71
|
+
AppTheme.current.colors.background.default,
|
|
72
|
+
colorFraction
|
|
87
73
|
)
|
|
88
74
|
|
|
89
75
|
if (headerType != HeaderType.NONE) {
|
|
@@ -132,9 +118,9 @@ fun Header(
|
|
|
132
118
|
}
|
|
133
119
|
}
|
|
134
120
|
|
|
135
|
-
if (
|
|
121
|
+
if (useAnimationSearch || inputSearchProps == null) {
|
|
136
122
|
Box(Modifier.graphicsLayer {
|
|
137
|
-
alpha = if (
|
|
123
|
+
alpha = if (animatedHeader !== null) opacity ?: 1f else 1f
|
|
138
124
|
}) {
|
|
139
125
|
headerRight?.invoke()
|
|
140
126
|
}
|
|
@@ -156,7 +142,7 @@ fun Header(
|
|
|
156
142
|
} else {
|
|
157
143
|
Box(
|
|
158
144
|
Modifier.weight(1f).graphicsLayer {
|
|
159
|
-
alpha = if (useAnimationSearch
|
|
145
|
+
alpha = if (useAnimationSearch) {
|
|
160
146
|
1f - (opacity ?: 1f)
|
|
161
147
|
} else {
|
|
162
148
|
if (animatedHeader !== null) opacity ?: 1f else 1f
|
|
@@ -164,6 +150,7 @@ fun Header(
|
|
|
164
150
|
},
|
|
165
151
|
contentAlignment = if (titlePosition == TitlePosition.LEFT) Alignment.TopStart else Alignment.Center
|
|
166
152
|
) {
|
|
153
|
+
|
|
167
154
|
HeaderTitle(
|
|
168
155
|
title = title,
|
|
169
156
|
color = tintIconColor,
|
|
@@ -176,14 +163,4 @@ fun Header(
|
|
|
176
163
|
}
|
|
177
164
|
}
|
|
178
165
|
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
fun animateColor(start: Color, stop: Color, fraction: Float): Color {
|
|
183
|
-
return Color(
|
|
184
|
-
red = start.red + fraction * (stop.red - start.red),
|
|
185
|
-
green = start.green + fraction * (stop.green - start.green),
|
|
186
|
-
blue = start.blue + fraction * (stop.blue - start.blue),
|
|
187
|
-
alpha = start.alpha + fraction * (stop.alpha - start.alpha)
|
|
188
|
-
)
|
|
189
|
-
}
|
|
166
|
+
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
package vn.momo.kits.application
|
|
2
2
|
|
|
3
|
+
import androidx.compose.animation.animateColorAsState
|
|
4
|
+
import androidx.compose.animation.core.animateFloatAsState
|
|
3
5
|
import androidx.compose.foundation.layout.Box
|
|
4
6
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
5
7
|
import androidx.compose.runtime.Composable
|
|
8
|
+
import androidx.compose.runtime.getValue
|
|
6
9
|
import androidx.compose.ui.Modifier
|
|
7
10
|
import androidx.compose.ui.graphics.Color
|
|
8
11
|
import androidx.compose.ui.unit.Dp
|
|
@@ -10,11 +13,25 @@ import androidx.compose.ui.unit.dp
|
|
|
10
13
|
import vn.momo.kits.components.InputSearchProps
|
|
11
14
|
import vn.momo.kits.const.AppStatusBar
|
|
12
15
|
import vn.momo.kits.const.AppTheme
|
|
13
|
-
import vn.momo.kits.platform.getScreenDimensions
|
|
14
16
|
import vn.momo.kits.platform.getStatusBarHeight
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
enum class TitlePosition {
|
|
19
|
+
LEFT, CENTER,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
data class AnimatedHeader(
|
|
23
|
+
val type: HeaderType = HeaderType.DEFAULT,
|
|
24
|
+
val composable: @Composable (scrollState: Int) -> Unit = {}
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
fun animateColor(start: Color, stop: Color, fraction: Float): Color {
|
|
28
|
+
return Color(
|
|
29
|
+
red = start.red + fraction * (stop.red - start.red),
|
|
30
|
+
green = start.green + fraction * (stop.green - start.green),
|
|
31
|
+
blue = start.blue + fraction * (stop.blue - start.blue),
|
|
32
|
+
alpha = start.alpha + fraction * (stop.alpha - start.alpha)
|
|
33
|
+
)
|
|
34
|
+
}
|
|
18
35
|
|
|
19
36
|
@Composable
|
|
20
37
|
fun HeaderBackground(
|
|
@@ -26,41 +43,38 @@ fun HeaderBackground(
|
|
|
26
43
|
useAnimationSearch: Boolean = false
|
|
27
44
|
) {
|
|
28
45
|
val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
|
|
29
|
-
val screenWidth = getScreenDimensions().width
|
|
30
|
-
val leftPosition = if (isBack) (BACK_WIDTH + 20).dp else 20.dp
|
|
31
|
-
val searchWidth = screenWidth - (SCREEN_PADDING * 2)
|
|
32
46
|
|
|
33
|
-
val
|
|
34
|
-
|
|
35
|
-
statusBarHeight = statusBarHeight,
|
|
36
|
-
leftPosition = leftPosition,
|
|
37
|
-
searchWidth = searchWidth,
|
|
38
|
-
headerRightWidth = headerRightWidth
|
|
47
|
+
val opacityAni by animateFloatAsState(
|
|
48
|
+
targetValue = (1 - (scrollState / 52f)).coerceIn(0f, 1f),
|
|
39
49
|
)
|
|
40
50
|
|
|
41
|
-
val backgroundColor
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
51
|
+
val backgroundColor by animateColorAsState(
|
|
52
|
+
targetValue = animateColor(
|
|
53
|
+
Color.Transparent,
|
|
54
|
+
AppTheme.current.colors.background.surface,
|
|
55
|
+
opacityAni
|
|
56
|
+
),
|
|
57
|
+
)
|
|
46
58
|
|
|
47
59
|
when (headerType) {
|
|
48
60
|
HeaderType.DEFAULT -> {
|
|
49
|
-
val height = statusBarHeight + 52.dp
|
|
50
61
|
HeaderDefault(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
backgroundColor = backgroundColor
|
|
62
|
+
opacityAni = opacityAni,
|
|
63
|
+
statusBarHeight = statusBarHeight,
|
|
54
64
|
)
|
|
55
65
|
}
|
|
56
66
|
|
|
57
67
|
HeaderType.EXTENDED -> {
|
|
58
|
-
|
|
59
|
-
|
|
68
|
+
HeaderExtended(
|
|
69
|
+
scrollState = scrollState,
|
|
60
70
|
inputSearchProps = inputSearchProps,
|
|
71
|
+
headerRightWidth = headerRightWidth,
|
|
61
72
|
useAnimationSearch = useAnimationSearch,
|
|
62
|
-
|
|
63
|
-
|
|
73
|
+
opacityAni = opacityAni,
|
|
74
|
+
isBack = isBack,
|
|
75
|
+
statusBarHeight = statusBarHeight,
|
|
76
|
+
backgroundColor = backgroundColor,
|
|
77
|
+
)
|
|
64
78
|
}
|
|
65
79
|
|
|
66
80
|
else -> {
|
|
@@ -21,13 +21,13 @@ import vn.momo.kits.utils.bottomBorder
|
|
|
21
21
|
|
|
22
22
|
@Composable
|
|
23
23
|
fun HeaderDefault(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
animations: HeaderAnimations
|
|
24
|
+
opacityAni: Float,
|
|
25
|
+
statusBarHeight: Dp,
|
|
27
26
|
) {
|
|
27
|
+
val height = statusBarHeight + 52.dp
|
|
28
28
|
Box(
|
|
29
29
|
modifier = Modifier.fillMaxWidth().height(height)
|
|
30
|
-
.background(
|
|
30
|
+
.background(AppTheme.current.colors.background.surface)
|
|
31
31
|
.bottomBorder(
|
|
32
32
|
strokeWidth = 1.dp,
|
|
33
33
|
color = AppTheme.current.colors.border.default
|
|
@@ -37,7 +37,7 @@ fun HeaderDefault(
|
|
|
37
37
|
modifier = Modifier
|
|
38
38
|
.height(height)
|
|
39
39
|
.fillMaxWidth()
|
|
40
|
-
.alpha(
|
|
40
|
+
.alpha(opacityAni)
|
|
41
41
|
.background(
|
|
42
42
|
Brush.linearGradient(
|
|
43
43
|
colors = listOf(
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
package vn.momo.kits.application
|
|
2
2
|
|
|
3
|
+
import androidx.compose.animation.animateColorAsState
|
|
4
|
+
import androidx.compose.animation.core.animateFloatAsState
|
|
3
5
|
import androidx.compose.foundation.background
|
|
4
6
|
import androidx.compose.foundation.layout.Box
|
|
5
7
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
@@ -9,6 +11,7 @@ import androidx.compose.foundation.layout.padding
|
|
|
9
11
|
import androidx.compose.foundation.layout.width
|
|
10
12
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
11
13
|
import androidx.compose.runtime.Composable
|
|
14
|
+
import androidx.compose.runtime.getValue
|
|
12
15
|
import androidx.compose.ui.Alignment
|
|
13
16
|
import androidx.compose.ui.Modifier
|
|
14
17
|
import androidx.compose.ui.draw.alpha
|
|
@@ -17,30 +20,48 @@ import androidx.compose.ui.graphics.Brush
|
|
|
17
20
|
import androidx.compose.ui.graphics.Color
|
|
18
21
|
import androidx.compose.ui.layout.ContentScale
|
|
19
22
|
import androidx.compose.ui.platform.LocalDensity
|
|
23
|
+
import androidx.compose.ui.unit.Dp
|
|
20
24
|
import androidx.compose.ui.unit.dp
|
|
25
|
+
import androidx.compose.ui.zIndex
|
|
21
26
|
import vn.momo.kits.components.Image
|
|
22
27
|
import vn.momo.kits.components.InputSearch
|
|
23
28
|
import vn.momo.kits.components.InputSearchProps
|
|
24
29
|
import vn.momo.kits.components.Options
|
|
25
30
|
import vn.momo.kits.const.AppTheme
|
|
31
|
+
import vn.momo.kits.const.Colors
|
|
26
32
|
import vn.momo.kits.const.Radius
|
|
27
33
|
import vn.momo.kits.const.Spacing
|
|
34
|
+
import vn.momo.kits.platform.getScreenDimensions
|
|
35
|
+
import vn.momo.kits.utils.bottomBorder
|
|
28
36
|
|
|
29
37
|
@Composable
|
|
30
38
|
fun HeaderExtended(
|
|
31
|
-
|
|
32
|
-
inputSearchProps: InputSearchProps
|
|
33
|
-
useAnimationSearch: Boolean =
|
|
34
|
-
|
|
35
|
-
|
|
39
|
+
opacityAni: Float,
|
|
40
|
+
inputSearchProps: InputSearchProps?,
|
|
41
|
+
useAnimationSearch: Boolean = true,
|
|
42
|
+
scrollState: Int,
|
|
43
|
+
headerRightWidth: Dp,
|
|
44
|
+
isBack: Boolean,
|
|
45
|
+
statusBarHeight: Dp,
|
|
46
|
+
backgroundColor: Color
|
|
47
|
+
) {
|
|
48
|
+
val animations = useHeaderSearchAnimation(
|
|
49
|
+
opacityAni = opacityAni,
|
|
50
|
+
scrollState = scrollState,
|
|
51
|
+
headerRightWidth = headerRightWidth,
|
|
52
|
+
statusBarHeight = statusBarHeight,
|
|
53
|
+
isBack = isBack
|
|
54
|
+
)
|
|
55
|
+
|
|
36
56
|
Box(
|
|
37
|
-
modifier = Modifier.fillMaxWidth()
|
|
57
|
+
modifier = Modifier.fillMaxWidth()
|
|
58
|
+
.height(animations.height.dp)
|
|
38
59
|
) {
|
|
39
60
|
Box(
|
|
40
61
|
modifier = Modifier
|
|
41
62
|
.fillMaxWidth()
|
|
42
63
|
.height(154.dp)
|
|
43
|
-
.alpha(
|
|
64
|
+
.alpha(opacityAni)
|
|
44
65
|
.background(
|
|
45
66
|
Brush.linearGradient(
|
|
46
67
|
colors = listOf(
|
|
@@ -70,6 +91,19 @@ fun HeaderExtended(
|
|
|
70
91
|
}
|
|
71
92
|
}
|
|
72
93
|
|
|
94
|
+
Box(
|
|
95
|
+
modifier = Modifier
|
|
96
|
+
.fillMaxWidth()
|
|
97
|
+
.alpha(1f - opacityAni)
|
|
98
|
+
.height(statusBarHeight + 52.dp)
|
|
99
|
+
.background(
|
|
100
|
+
AppTheme.current.colors.background.surface
|
|
101
|
+
)
|
|
102
|
+
.bottomBorder(
|
|
103
|
+
strokeWidth = 1.dp,
|
|
104
|
+
color = AppTheme.current.colors.border.default
|
|
105
|
+
)
|
|
106
|
+
)
|
|
73
107
|
if (inputSearchProps != null && useAnimationSearch) {
|
|
74
108
|
Box(
|
|
75
109
|
modifier = Modifier
|
|
@@ -79,6 +113,7 @@ fun HeaderExtended(
|
|
|
79
113
|
)
|
|
80
114
|
.padding(vertical = Spacing.S)
|
|
81
115
|
.align(Alignment.BottomStart)
|
|
116
|
+
.zIndex(1f)
|
|
82
117
|
) {
|
|
83
118
|
Box(
|
|
84
119
|
modifier = Modifier
|
|
@@ -98,5 +133,4 @@ fun HeaderExtended(
|
|
|
98
133
|
}
|
|
99
134
|
}
|
|
100
135
|
}
|
|
101
|
-
}
|
|
102
|
-
|
|
136
|
+
}
|
|
@@ -79,12 +79,12 @@ object Spacing {
|
|
|
79
79
|
|
|
80
80
|
@Composable
|
|
81
81
|
fun HeaderRight(
|
|
82
|
-
|
|
82
|
+
headerRight: HeaderRightData? = null,
|
|
83
83
|
) {
|
|
84
84
|
Row(
|
|
85
85
|
verticalAlignment = Alignment.CenterVertically,
|
|
86
86
|
) {
|
|
87
|
-
ToolkitHeaderRight(headerRight =
|
|
87
|
+
ToolkitHeaderRight(headerRight = headerRight)
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -74,7 +74,7 @@ data class KitConfig(
|
|
|
74
74
|
fun ApplicationContainer(
|
|
75
75
|
theme: Theme = defaultTheme,
|
|
76
76
|
composeApi: ComposeApi? = null,
|
|
77
|
-
statusBarHeight: Dp? =
|
|
77
|
+
statusBarHeight: Dp? = AppStatusBar.current,
|
|
78
78
|
applicationContext: MiniAppContext? = null,
|
|
79
79
|
config: KitConfig? = null,
|
|
80
80
|
content: @Composable () -> Unit,
|
|
@@ -68,6 +68,7 @@ fun Screen(
|
|
|
68
68
|
layoutOffset: Dp = 56.dp,
|
|
69
69
|
inputSearchProps: InputSearchProps? = null,
|
|
70
70
|
useAnimationSearch: Boolean = false,
|
|
71
|
+
headerRightWidth: Dp = 0.dp,
|
|
71
72
|
content: @Composable () -> Unit,
|
|
72
73
|
) {
|
|
73
74
|
val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
|
|
@@ -84,7 +85,7 @@ fun Screen(
|
|
|
84
85
|
val bottomPadding = min(indicator, 21.dp)
|
|
85
86
|
|
|
86
87
|
val opacity by animateFloatAsState(
|
|
87
|
-
targetValue = ((scrollState.value /
|
|
88
|
+
targetValue = ((scrollState.value / 52f)).coerceIn(0f, 1f),
|
|
88
89
|
)
|
|
89
90
|
|
|
90
91
|
val headerAnimated =
|
|
@@ -94,15 +95,16 @@ fun Screen(
|
|
|
94
95
|
|
|
95
96
|
Box(
|
|
96
97
|
Modifier.fillMaxSize()
|
|
97
|
-
.background(AppTheme.current.colors.background.
|
|
98
|
+
.background(backgroundColor ?: AppTheme.current.colors.background.default)
|
|
98
99
|
) {
|
|
99
100
|
|
|
100
101
|
if (animatedHeader === null) {
|
|
101
102
|
HeaderBackground(
|
|
102
103
|
headerType = headerType,
|
|
103
104
|
scrollState = scrollState.value,
|
|
104
|
-
inputSearchProps
|
|
105
|
-
useAnimationSearch = useAnimationSearch
|
|
105
|
+
inputSearchProps= inputSearchProps,
|
|
106
|
+
useAnimationSearch = useAnimationSearch,
|
|
107
|
+
headerRightWidth = headerRightWidth
|
|
106
108
|
)
|
|
107
109
|
} else {
|
|
108
110
|
Box(
|
|
@@ -114,8 +116,9 @@ fun Screen(
|
|
|
114
116
|
isBack = isBack,
|
|
115
117
|
headerType = headerType,
|
|
116
118
|
scrollState = scrollState.value,
|
|
117
|
-
inputSearchProps
|
|
118
|
-
useAnimationSearch = useAnimationSearch
|
|
119
|
+
inputSearchProps= inputSearchProps,
|
|
120
|
+
useAnimationSearch = useAnimationSearch,
|
|
121
|
+
headerRightWidth = headerRightWidth
|
|
119
122
|
)
|
|
120
123
|
}
|
|
121
124
|
}
|
|
@@ -130,7 +133,7 @@ fun Screen(
|
|
|
130
133
|
animatedHeader = animatedHeader,
|
|
131
134
|
inputSearchProps = inputSearchProps,
|
|
132
135
|
scrollState = scrollState.value,
|
|
133
|
-
useAnimationSearch = useAnimationSearch
|
|
136
|
+
useAnimationSearch = useAnimationSearch,
|
|
134
137
|
)
|
|
135
138
|
|
|
136
139
|
Column(
|
|
@@ -155,18 +158,14 @@ fun Screen(
|
|
|
155
158
|
verticalArrangement = verticalArrangement,
|
|
156
159
|
horizontalAlignment = horizontalAlignment
|
|
157
160
|
) {
|
|
158
|
-
Box
|
|
159
|
-
modifier = Modifier.background(
|
|
160
|
-
backgroundColor ?: AppTheme.current.colors.background.default
|
|
161
|
-
)
|
|
162
|
-
) {
|
|
161
|
+
Box {
|
|
163
162
|
headerAnimated()
|
|
164
163
|
Column {
|
|
165
164
|
if (animatedHeader !== null) {
|
|
166
165
|
Spacer(modifier = Modifier.padding(top = statusBarHeight + 52.dp + layoutOffset))
|
|
167
166
|
}
|
|
168
167
|
|
|
169
|
-
if (useAnimationSearch && inputSearchProps != null) {
|
|
168
|
+
if (useAnimationSearch && inputSearchProps != null && headerType == HeaderType.EXTENDED) {
|
|
170
169
|
Spacer(modifier = Modifier.padding(top = statusBarHeight))
|
|
171
170
|
}
|
|
172
171
|
content()
|
|
@@ -3,11 +3,13 @@ package vn.momo.kits.application
|
|
|
3
3
|
import androidx.compose.animation.animateColorAsState
|
|
4
4
|
import androidx.compose.animation.core.animateFloatAsState
|
|
5
5
|
import androidx.compose.runtime.Composable
|
|
6
|
+
import androidx.compose.runtime.getValue
|
|
6
7
|
import androidx.compose.ui.graphics.Color
|
|
7
8
|
import androidx.compose.ui.unit.Dp
|
|
9
|
+
import androidx.compose.ui.unit.dp
|
|
8
10
|
import vn.momo.kits.const.AppTheme
|
|
9
11
|
import vn.momo.kits.const.Colors
|
|
10
|
-
import
|
|
12
|
+
import vn.momo.kits.platform.getScreenDimensions
|
|
11
13
|
|
|
12
14
|
data class HeaderAnimations(
|
|
13
15
|
val opacity: Float,
|
|
@@ -17,40 +19,46 @@ data class HeaderAnimations(
|
|
|
17
19
|
val height: Float
|
|
18
20
|
)
|
|
19
21
|
|
|
22
|
+
private const val SCREEN_PADDING = 12
|
|
23
|
+
private const val BACK_WIDTH = 28
|
|
24
|
+
|
|
20
25
|
@Composable
|
|
21
26
|
fun useHeaderSearchAnimation(
|
|
27
|
+
opacityAni: Float,
|
|
22
28
|
scrollState: Int,
|
|
29
|
+
headerRightWidth: Dp,
|
|
23
30
|
statusBarHeight: Dp,
|
|
24
|
-
|
|
25
|
-
searchWidth: Int,
|
|
26
|
-
headerRightWidth: Dp
|
|
31
|
+
isBack: Boolean
|
|
27
32
|
): HeaderAnimations {
|
|
28
|
-
val
|
|
29
|
-
|
|
30
|
-
)
|
|
33
|
+
val screenWidth = getScreenDimensions().width
|
|
34
|
+
val leftPosition = if (isBack) (BACK_WIDTH + 20).dp else 20.dp
|
|
35
|
+
val searchWidth = screenWidth - (SCREEN_PADDING * 2)
|
|
31
36
|
|
|
32
37
|
val backgroundSearch by animateColorAsState(
|
|
33
38
|
targetValue = animateColor(
|
|
34
39
|
AppTheme.current.colors.background.default,
|
|
35
40
|
Colors.black_01,
|
|
36
41
|
opacityAni
|
|
37
|
-
)
|
|
42
|
+
),
|
|
38
43
|
)
|
|
39
44
|
|
|
40
45
|
val animatedTranslateX by animateFloatAsState(
|
|
41
|
-
targetValue = (scrollState / 52f).coerceIn(0f, 1f) * (leftPosition.value - 12) + 12
|
|
46
|
+
targetValue = (scrollState / 52f).coerceIn(0f, 1f) * (leftPosition.value - 12) + 12,
|
|
42
47
|
)
|
|
43
48
|
|
|
44
49
|
val animatedWidth by animateFloatAsState(
|
|
45
|
-
targetValue = (scrollState / 52f).coerceIn(
|
|
46
|
-
|
|
50
|
+
targetValue = (scrollState / 52f).coerceIn(
|
|
51
|
+
0f,
|
|
52
|
+
1f
|
|
53
|
+
) * ((searchWidth - leftPosition.value - headerRightWidth.value + 12) - searchWidth) + searchWidth,
|
|
47
54
|
)
|
|
48
55
|
|
|
49
56
|
val animatedHeight by animateFloatAsState(
|
|
50
|
-
targetValue = (1 - (scrollState / 52f).coerceIn(
|
|
51
|
-
|
|
57
|
+
targetValue = (1 - (scrollState / 52f).coerceIn(
|
|
58
|
+
0f,
|
|
59
|
+
1f
|
|
60
|
+
)) * (statusBarHeight.value + 94 - (statusBarHeight.value + 52)) + (statusBarHeight.value + 52),
|
|
52
61
|
)
|
|
53
|
-
|
|
54
62
|
return HeaderAnimations(
|
|
55
63
|
opacity = opacityAni,
|
|
56
64
|
backgroundSearch = backgroundSearch,
|
|
@@ -35,6 +35,7 @@ import vn.momo.kits.const.AppTheme
|
|
|
35
35
|
import vn.momo.kits.const.Radius
|
|
36
36
|
import vn.momo.kits.const.Spacing
|
|
37
37
|
import vn.momo.kits.const.Typography
|
|
38
|
+
import vn.momo.kits.modifier.setAutomationId
|
|
38
39
|
import vn.momo.kits.utils.ifNotNull
|
|
39
40
|
|
|
40
41
|
data class PopupAction(
|
|
@@ -95,12 +96,12 @@ fun PopupNotify(
|
|
|
95
96
|
callback?.invoke()
|
|
96
97
|
}
|
|
97
98
|
|
|
98
|
-
Box(Modifier.
|
|
99
|
-
|
|
100
|
-
}, contentAlignment = Alignment.TopEnd) {
|
|
99
|
+
Box(Modifier.setAutomationId("popup_notify")
|
|
100
|
+
, contentAlignment = Alignment.TopEnd) {
|
|
101
101
|
Column(
|
|
102
102
|
modifier = Modifier
|
|
103
103
|
.fillMaxWidth()
|
|
104
|
+
.padding(horizontal = 12.dp)
|
|
104
105
|
.clip(RoundedCornerShape(Radius.L))
|
|
105
106
|
.background(
|
|
106
107
|
AppTheme.current.colors.background.surface,
|
|
@@ -115,7 +116,7 @@ fun PopupNotify(
|
|
|
115
116
|
)
|
|
116
117
|
|
|
117
118
|
Column(modifier = Modifier.padding(Spacing.XL)) {
|
|
118
|
-
Text(style = Typography.titleXs, maxLines = 2, text = title)
|
|
119
|
+
Text(style = Typography.titleXs, maxLines = 2, text = title, modifier = Modifier.setAutomationId("title_popup_permission"))
|
|
119
120
|
content(Modifier.padding(top = Spacing.S))
|
|
120
121
|
if (error.isNotEmpty()) {
|
|
121
122
|
Text(
|
|
@@ -142,7 +143,7 @@ fun PopupNotify(
|
|
|
142
143
|
Modifier
|
|
143
144
|
.width(22.dp)
|
|
144
145
|
.height(22.dp)
|
|
145
|
-
.offset(x = Spacing.
|
|
146
|
+
.offset(x = Spacing.M / 2, y = -Spacing.M)
|
|
146
147
|
.background(
|
|
147
148
|
color = AppTheme.current.colors.text.default,
|
|
148
149
|
shape = RoundedCornerShape(Radius.M)
|
|
@@ -164,9 +165,7 @@ fun PopupNotify(
|
|
|
164
165
|
source = "navigation_close",
|
|
165
166
|
color = AppTheme.current.colors.background.surface,
|
|
166
167
|
size = 16.dp,
|
|
167
|
-
modifier = Modifier.
|
|
168
|
-
testTag = "ic_popup_close"
|
|
169
|
-
}
|
|
168
|
+
modifier = Modifier.setAutomationId("ic_popup_close")
|
|
170
169
|
)
|
|
171
170
|
}
|
|
172
171
|
}
|
|
@@ -233,9 +232,7 @@ fun renderRow(
|
|
|
233
232
|
},
|
|
234
233
|
title = it.title,
|
|
235
234
|
type = ButtonType.TEXT,
|
|
236
|
-
modifier = Modifier.
|
|
237
|
-
testTag = "btn_popup_cancel"
|
|
238
|
-
}
|
|
235
|
+
modifier = Modifier.setAutomationId("btn_popup_cancel")
|
|
239
236
|
)
|
|
240
237
|
}
|
|
241
238
|
Spacer(modifier = Modifier.width(Spacing.S))
|
|
@@ -248,9 +245,7 @@ fun renderRow(
|
|
|
248
245
|
onAction(primary?.onPress)
|
|
249
246
|
},
|
|
250
247
|
title = primary?.title ?: "",
|
|
251
|
-
modifier = Modifier.
|
|
252
|
-
testTag = "btn_popup_allow"
|
|
253
|
-
}
|
|
248
|
+
modifier = Modifier.setAutomationId("btn_popup_allow")
|
|
254
249
|
)
|
|
255
250
|
}
|
|
256
251
|
}
|
|
@@ -271,9 +266,7 @@ fun renderColumn(
|
|
|
271
266
|
onAction(primary?.onPress)
|
|
272
267
|
},
|
|
273
268
|
title = primary?.title ?: "",
|
|
274
|
-
modifier = Modifier.
|
|
275
|
-
testTag = "btn_popup_allow"
|
|
276
|
-
}
|
|
269
|
+
modifier = Modifier.setAutomationId("btn_popup_allow")
|
|
277
270
|
)
|
|
278
271
|
secondary?.let {
|
|
279
272
|
Spacer(modifier = Modifier.height(Spacing.S))
|
|
@@ -286,9 +279,7 @@ fun renderColumn(
|
|
|
286
279
|
},
|
|
287
280
|
title = it.title,
|
|
288
281
|
type = ButtonType.TEXT,
|
|
289
|
-
modifier = Modifier.
|
|
290
|
-
testTag = "btn_popup_cancel"
|
|
291
|
-
}
|
|
282
|
+
modifier = Modifier.setAutomationId("btn_popup_cancel")
|
|
292
283
|
)
|
|
293
284
|
}
|
|
294
285
|
}
|
|
@@ -37,7 +37,7 @@ fun Text(
|
|
|
37
37
|
modifier = modifier.setAutomationId(accessibilityId?:text, text),
|
|
38
38
|
text = text,
|
|
39
39
|
color = color ?: AppTheme.current.colors.text.default,
|
|
40
|
-
style = style,
|
|
40
|
+
style = style.copy(fontWeight = null),
|
|
41
41
|
textAlign = textAlign,
|
|
42
42
|
fontSize = fontSize,
|
|
43
43
|
fontFamily = font,
|
package/ios/Image/Image.swift
CHANGED
|
@@ -46,8 +46,10 @@ public struct PopupDisplay: View {
|
|
|
46
46
|
.overlay(RoundedRectangle(cornerRadius: Radius.L).stroke(Colors.black01, lineWidth: 1))
|
|
47
47
|
}.foregroundColor(Colors.black20)
|
|
48
48
|
.background(Colors.black01.cornerRadius(15))
|
|
49
|
-
.
|
|
49
|
+
.padding(.trailing, -Spacing.M )
|
|
50
|
+
.padding(.top, -Spacing.M)
|
|
50
51
|
.zIndex(1)
|
|
52
|
+
.accessibility(identifier: "ic_popup_close")
|
|
51
53
|
|
|
52
54
|
VStack {
|
|
53
55
|
if(!url.isEmpty) {
|
|
@@ -70,6 +72,7 @@ public struct PopupDisplay: View {
|
|
|
70
72
|
.padding(.top, 16)
|
|
71
73
|
.padding(.bottom, 8)
|
|
72
74
|
.lineLimit(2)
|
|
75
|
+
.accessibility(identifier: "title_popup_permission")
|
|
73
76
|
|
|
74
77
|
Text(description)
|
|
75
78
|
.foregroundColor(.black)
|
|
@@ -77,7 +80,9 @@ public struct PopupDisplay: View {
|
|
|
77
80
|
.opacity(0.6)
|
|
78
81
|
.multilineTextAlignment(.leading)
|
|
79
82
|
.padding(.bottom, 20)
|
|
80
|
-
}
|
|
83
|
+
}
|
|
84
|
+
.frame(maxWidth: .infinity, alignment: .leading)
|
|
85
|
+
.padding(.horizontal, 24)
|
|
81
86
|
|
|
82
87
|
if buttonDirection == .row {
|
|
83
88
|
if buttonType == .text {
|
|
@@ -97,7 +102,7 @@ public struct PopupDisplay: View {
|
|
|
97
102
|
}
|
|
98
103
|
}
|
|
99
104
|
.background(Color.white.cornerRadius(15))
|
|
100
|
-
.padding(.horizontal,
|
|
105
|
+
.padding(.horizontal, 12)
|
|
101
106
|
}
|
|
102
107
|
|
|
103
108
|
// MARK: Internal
|
|
@@ -150,8 +155,9 @@ public struct PopupDisplay: View {
|
|
|
150
155
|
|
|
151
156
|
var RowButtons: some View {
|
|
152
157
|
HStack {
|
|
153
|
-
Button(title: closeButtonTitle, action: onPressCloseButton, type: .secondary, size: .medium)
|
|
158
|
+
Button(title: closeButtonTitle, action: onPressCloseButton, type: .secondary, size: .medium).accessibility(identifier: "btn_popup_cancel")
|
|
154
159
|
Button(title: actionButtonTitle, action: onPressAction, size: .medium)
|
|
160
|
+
.accessibility(identifier: "btn_popup_allow")
|
|
155
161
|
}
|
|
156
162
|
.frame(maxWidth: .infinity, alignment: .center)
|
|
157
163
|
.padding(.horizontal, 24)
|
|
@@ -164,8 +170,9 @@ public struct PopupDisplay: View {
|
|
|
164
170
|
title: actionButtonTitle,
|
|
165
171
|
action: onPressAction,
|
|
166
172
|
size: .medium
|
|
167
|
-
)
|
|
168
|
-
Button(title: closeButtonTitle, action: onPressCloseButton, type: .secondary, size: .medium)
|
|
173
|
+
).accessibility(identifier: "btn_popup_allow")
|
|
174
|
+
Button(title: closeButtonTitle, action: onPressCloseButton, type: .secondary, size: .medium).accessibility(identifier: "btn_popup_cancel")
|
|
175
|
+
|
|
169
176
|
}
|
|
170
177
|
.frame(maxWidth: .infinity, alignment: .trailing)
|
|
171
178
|
.padding(.horizontal, 24)
|
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
|
-
#
|
|
8
|
-
sdk.dir=/Users/
|
|
7
|
+
#Tue Apr 23 16:40:15 ICT 2024
|
|
8
|
+
sdk.dir=/Users/hung.dao1/Library/Android/sdk
|