@momo-kits/native-kits 0.162.7-debug → 0.162.8-debug
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/build.gradle.kts +2 -1
- package/compose/build.gradle.kts.backup +1 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +69 -26
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +25 -16
- package/gradle/libs.versions.toml +2 -0
- package/gradle.properties +1 -1
- package/package.json +1 -1
package/compose/build.gradle.kts
CHANGED
|
@@ -40,7 +40,7 @@ kotlin {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
cocoapods {
|
|
43
|
-
version = "0.162.
|
|
43
|
+
version = "0.162.8-debug"
|
|
44
44
|
summary = "IOS Shared module"
|
|
45
45
|
homepage = "https://momo.vn"
|
|
46
46
|
ios.deploymentTarget = "15.0"
|
|
@@ -77,6 +77,7 @@ kotlin {
|
|
|
77
77
|
implementation(libs.kotlinx.datetime)
|
|
78
78
|
api(libs.native.max.api)
|
|
79
79
|
implementation(libs.compottie)
|
|
80
|
+
implementation(libs.gif.image)
|
|
80
81
|
}
|
|
81
82
|
androidMain.dependencies {
|
|
82
83
|
implementation(libs.ktor.client.okhttp)
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
package vn.momo.kits.components
|
|
2
2
|
|
|
3
3
|
import androidx.compose.foundation.border
|
|
4
|
+
import androidx.compose.foundation.layout.Box
|
|
4
5
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
|
6
|
+
import androidx.compose.foundation.layout.fillMaxSize
|
|
5
7
|
import androidx.compose.runtime.Composable
|
|
6
8
|
import androidx.compose.runtime.getValue
|
|
7
9
|
import androidx.compose.runtime.mutableStateOf
|
|
@@ -17,10 +19,12 @@ import androidx.compose.ui.semantics.contentDescription
|
|
|
17
19
|
import androidx.compose.ui.semantics.semantics
|
|
18
20
|
import androidx.compose.ui.platform.LocalDensity
|
|
19
21
|
import androidx.compose.ui.unit.dp
|
|
20
|
-
import coil3.compose.AsyncImage
|
|
22
|
+
import coil3.compose.AsyncImage as CoilAsyncImage
|
|
21
23
|
import vn.momo.kits.application.IsShowBaseLineDebug
|
|
22
24
|
import vn.momo.kits.const.AppTheme
|
|
23
25
|
import vn.momo.kits.const.Colors
|
|
26
|
+
import vn.momo.kits.gifimage.GifImage
|
|
27
|
+
import vn.momo.kits.gifimage.GifImageState
|
|
24
28
|
import vn.momo.kits.modifier.conditional
|
|
25
29
|
|
|
26
30
|
data class Options(
|
|
@@ -73,6 +77,19 @@ private fun getHostFromUrl(url: String): String? {
|
|
|
73
77
|
}
|
|
74
78
|
}
|
|
75
79
|
|
|
80
|
+
private fun isGifUrl(url: String): Boolean {
|
|
81
|
+
val path = url.substringBefore('#').substringBefore('?')
|
|
82
|
+
return path.endsWith(".gif", ignoreCase = true)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private fun GifImageState.toImageState(): ImageState {
|
|
86
|
+
return when (this) {
|
|
87
|
+
GifImageState.Success -> ImageState.Success
|
|
88
|
+
GifImageState.Error -> ImageState.Error
|
|
89
|
+
GifImageState.Loading -> ImageState.Loading
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
76
93
|
// Optimized query parameter appending
|
|
77
94
|
private fun appendSizeQueryParam(url: String, value: String): String {
|
|
78
95
|
val fragmentIndex = url.indexOf('#')
|
|
@@ -95,12 +112,12 @@ fun Image(
|
|
|
95
112
|
modifier: Modifier = Modifier,
|
|
96
113
|
options: Options? = null,
|
|
97
114
|
loading: Boolean = true,
|
|
115
|
+
onStateChanged: (ImageState) -> Unit = {},
|
|
98
116
|
) {
|
|
99
117
|
val imageOptions = remember(options) {
|
|
100
118
|
options ?: Options()
|
|
101
119
|
}
|
|
102
120
|
|
|
103
|
-
var imageState by remember { mutableStateOf(ImageState.Loading) }
|
|
104
121
|
val density = LocalDensity.current
|
|
105
122
|
|
|
106
123
|
BoxWithConstraints(
|
|
@@ -121,34 +138,46 @@ fun Image(
|
|
|
121
138
|
processedUrl
|
|
122
139
|
}
|
|
123
140
|
}
|
|
124
|
-
else -> source
|
|
141
|
+
else -> source.toString()
|
|
125
142
|
}
|
|
126
143
|
}
|
|
127
144
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
145
|
+
var imageState by remember(urlToLoad) { mutableStateOf(ImageState.Loading) }
|
|
146
|
+
fun updateImageState(state: ImageState) {
|
|
147
|
+
imageState = state
|
|
148
|
+
onStateChanged(state)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (isGifUrl(urlToLoad)) {
|
|
152
|
+
GifImage(
|
|
153
|
+
modifier = Modifier.matchParentSize(),
|
|
154
|
+
url = urlToLoad,
|
|
155
|
+
contentDescription = null,
|
|
156
|
+
contentScale = imageOptions.contentScale,
|
|
157
|
+
alignment = imageOptions.alignment,
|
|
158
|
+
colorFilter = imageOptions.colorFilter,
|
|
159
|
+
alpha = imageOptions.alpha,
|
|
160
|
+
onStateChanged = { updateImageState(it.toImageState()) },
|
|
161
|
+
)
|
|
162
|
+
} else {
|
|
163
|
+
CoilAsyncImage(
|
|
164
|
+
modifier = Modifier.matchParentSize(),
|
|
165
|
+
model = urlToLoad,
|
|
166
|
+
contentDescription = null,
|
|
167
|
+
contentScale = imageOptions.contentScale,
|
|
168
|
+
alignment = imageOptions.alignment,
|
|
169
|
+
colorFilter = imageOptions.colorFilter,
|
|
170
|
+
alpha = imageOptions.alpha,
|
|
171
|
+
onLoading = { updateImageState(ImageState.Loading) },
|
|
172
|
+
onSuccess = { updateImageState(ImageState.Success) },
|
|
173
|
+
onError = { updateImageState(ImageState.Error) },
|
|
174
|
+
)
|
|
175
|
+
}
|
|
140
176
|
|
|
141
177
|
when (imageState) {
|
|
142
|
-
ImageState.Loading -> if (loading) Skeleton()
|
|
143
|
-
ImageState.Error -> {
|
|
144
|
-
val theme = AppTheme.current
|
|
145
|
-
Icon(
|
|
146
|
-
source = "media_fail",
|
|
147
|
-
color = theme.colors.text.disable,
|
|
148
|
-
modifier = Modifier.align(Alignment.Center)
|
|
149
|
-
)
|
|
150
|
-
}
|
|
151
178
|
ImageState.Success -> {}
|
|
179
|
+
ImageState.Error -> ImageError()
|
|
180
|
+
ImageState.Loading -> if (loading) Skeleton()
|
|
152
181
|
}
|
|
153
182
|
}
|
|
154
183
|
}
|
|
@@ -156,7 +185,7 @@ fun Image(
|
|
|
156
185
|
// Extracted URL processing logic for better performance
|
|
157
186
|
private fun processImageUrl(url: String, maxWidth: androidx.compose.ui.unit.Dp, density: androidx.compose.ui.unit.Density): String {
|
|
158
187
|
val host = getHostFromUrl(url)
|
|
159
|
-
return if (host != null && supportedDomains.contains(host)) {
|
|
188
|
+
return if (!isGifUrl(url) && host != null && supportedDomains.contains(host)) {
|
|
160
189
|
val widthPx = with(density) { maxWidth.roundToPx() }
|
|
161
190
|
val pixelRatio = density.density
|
|
162
191
|
val pixelFitForWidth = widthPx * pixelRatio
|
|
@@ -167,6 +196,20 @@ private fun processImageUrl(url: String, maxWidth: androidx.compose.ui.unit.Dp,
|
|
|
167
196
|
}
|
|
168
197
|
}
|
|
169
198
|
|
|
199
|
+
@Composable
|
|
200
|
+
private fun ImageError() {
|
|
201
|
+
val theme = AppTheme.current
|
|
202
|
+
Box(
|
|
203
|
+
modifier = Modifier.fillMaxSize(),
|
|
204
|
+
contentAlignment = Alignment.Center
|
|
205
|
+
) {
|
|
206
|
+
Icon(
|
|
207
|
+
source = "media_fail",
|
|
208
|
+
color = theme.colors.text.disable,
|
|
209
|
+
)
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
170
213
|
@Composable
|
|
171
214
|
fun Image(
|
|
172
215
|
source: Painter,
|
|
@@ -185,4 +228,4 @@ fun Image(
|
|
|
185
228
|
colorFilter = colorFilter,
|
|
186
229
|
alpha = alpha,
|
|
187
230
|
)
|
|
188
|
-
}
|
|
231
|
+
}
|
|
@@ -23,7 +23,6 @@ import vn.momo.kits.navigation.LocalNavigator
|
|
|
23
23
|
import vn.momo.kits.navigation.NavigationOptions
|
|
24
24
|
import vn.momo.kits.navigation.StackScreen
|
|
25
25
|
import vn.momo.kits.navigation.component.HeaderType
|
|
26
|
-
import vn.momo.kits.platform.getScreenHeight
|
|
27
26
|
|
|
28
27
|
private var bottomTabOptionItems : MutableList<NavigationOptions?> = mutableListOf()
|
|
29
28
|
internal fun setBottomTabOption(index: Int, options: NavigationOptions){
|
|
@@ -45,6 +44,8 @@ fun BottomTab(
|
|
|
45
44
|
val navigation = LocalNavigation.current
|
|
46
45
|
val navigator = LocalNavigator.current
|
|
47
46
|
val navController = rememberNavController()
|
|
47
|
+
val keyboardBottomPadding = WindowInsets.ime.asPaddingValues().calculateBottomPadding()
|
|
48
|
+
val shouldShowBottomTab = keyboardBottomPadding == 0.dp
|
|
48
49
|
|
|
49
50
|
bottomTabOptionItems = items.mapIndexed { index, item ->
|
|
50
51
|
item.options ?: NavigationOptions()
|
|
@@ -57,10 +58,16 @@ fun BottomTab(
|
|
|
57
58
|
)
|
|
58
59
|
}
|
|
59
60
|
|
|
60
|
-
Box(modifier = Modifier.
|
|
61
|
+
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) {
|
|
61
62
|
Box(modifier = Modifier
|
|
62
63
|
.fillMaxSize()
|
|
63
|
-
.padding(
|
|
64
|
+
.padding(
|
|
65
|
+
bottom = if (shouldShowBottomTab) {
|
|
66
|
+
BOTTOM_TAB_BAR_HEIGHT.dp + AppNavigationBar.current
|
|
67
|
+
} else {
|
|
68
|
+
0.dp
|
|
69
|
+
}
|
|
70
|
+
)
|
|
64
71
|
) {
|
|
65
72
|
NavHost(
|
|
66
73
|
navController = navController,
|
|
@@ -119,20 +126,22 @@ fun BottomTab(
|
|
|
119
126
|
}
|
|
120
127
|
}
|
|
121
128
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
129
|
+
if (shouldShowBottomTab) {
|
|
130
|
+
Column {
|
|
131
|
+
BottomTabBar(
|
|
132
|
+
items = items,
|
|
133
|
+
floatingButton = floatingButton,
|
|
134
|
+
navController = navController,
|
|
135
|
+
onTabSelected = {
|
|
136
|
+
val currentRoute = navController.currentBackStackEntry?.destination?.route
|
|
137
|
+
val targetRoute = "option$it"
|
|
138
|
+
if (currentRoute != targetRoute) {
|
|
139
|
+
navController.navigate(targetRoute)
|
|
140
|
+
}
|
|
132
141
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
142
|
+
)
|
|
143
|
+
Spacer(modifier = Modifier.fillMaxWidth().height(AppNavigationBar.current + Spacing.S).background(AppTheme.current.colors.background.surface))
|
|
144
|
+
}
|
|
136
145
|
}
|
|
137
146
|
}
|
|
138
147
|
}
|
|
@@ -21,6 +21,7 @@ maxapi = "0.1.1"
|
|
|
21
21
|
vanniktechMavenPublish = "0.34.0"
|
|
22
22
|
kits = "0.159.1-beta.7"
|
|
23
23
|
nativemaxapi = "0.0.6"
|
|
24
|
+
gif-image = "0.1.2"
|
|
24
25
|
|
|
25
26
|
[libraries]
|
|
26
27
|
ktor-client-core = { group = "io.ktor", name = "ktor-client-core", version.ref = "ktor-version" }
|
|
@@ -53,6 +54,7 @@ androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "a
|
|
|
53
54
|
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity" }
|
|
54
55
|
material = { module = "com.google.android.material:material", version.ref = "material" }
|
|
55
56
|
|
|
57
|
+
gif-image = { module = "vn.momo.kits:gif-image", version.ref = "gif-image" }
|
|
56
58
|
[plugins]
|
|
57
59
|
jetbrains-kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
|
58
60
|
jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
package/gradle.properties
CHANGED