Skip to content

Commit

Permalink
Merge pull request #5 from stslex/dev
Browse files Browse the repository at this point in the history
add images
  • Loading branch information
stslex authored Nov 26, 2023
2 parents be51fdf + bc5ee96 commit c2d7da6
Show file tree
Hide file tree
Showing 17 changed files with 341 additions and 44 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
*.iml
.gradle
**/build/
**/release/
xcuserdata
!src/**/build/
local.properties
Expand Down
6 changes: 4 additions & 2 deletions composeApp/src/androidMain/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.INTERNET" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
Expand All @@ -9,9 +11,9 @@
android:supportsRtl="true"
android:theme="@android:style/Theme.Material.Light.NoActionBar">
<activity
android:exported="true"
android:name=".MainActivity"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden|mnc|colorMode|density|fontScale|fontWeightAdjustment|keyboard|layoutDirection|locale|mcc|navigation|smallestScreenSize|touchscreen|uiMode"
android:name=".MainActivity">
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

Expand Down
8 changes: 8 additions & 0 deletions core/ui/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ kotlin {
@OptIn(ExperimentalComposeLibrary::class)
api(compose.components.resources)
api(libs.bundles.voyager)
api(libs.kamel)
implementation(libs.bundles.ktor)
implementation(libs.kotlinx.serialization.json)
implementation(libs.slf4j.simple)
}
commonTest.dependencies {
implementation(libs.kotlin.test)
Expand All @@ -56,6 +60,10 @@ kotlin {
api(libs.koin.android)
api(libs.koin.androidx.compose)
}
iosMain.dependencies {
// TODO research TLS PROBLEM
implementation("io.ktor:ktor-client-darwin:2.3.2")
}
dependencies {
debugApi(libs.compose.ui.tooling)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.stslex.core.ui.base.image

import io.kamel.core.config.KamelConfig
import io.kamel.core.config.httpFetcher
import io.kamel.core.config.takeFrom
import io.kamel.image.config.Default
import io.ktor.client.plugins.logging.LogLevel
import io.ktor.client.plugins.logging.Logging

object AppKamelConfig {

val KamelLoggingConfig: KamelConfig
get() = KamelConfig {
takeFrom(KamelConfig.Default)
httpFetcher {
install(Logging) {
logger = KamelLogger
level = LogLevel.ALL
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.stslex.core.ui.base.image

enum class ImageType {
KAMEL,
NATIVE;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.stslex.core.ui.base.image

import io.ktor.client.plugins.logging.Logger

object KamelLogger : Logger {

private const val TAG = "KAMEL"

override fun log(message: String) {
com.stslex.core.core.Logger.debug(message, TAG)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.stslex.core.ui.base.image

import androidx.compose.foundation.layout.BoxScope
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import io.kamel.image.KamelImage
import io.kamel.image.asyncPainterResource

@Composable
internal fun KamelNetworkImage(
url: String,
contentDescription: String?,
contentScale: ContentScale,
modifier: Modifier = Modifier,
onLoading: @Composable (BoxScope.(Float) -> Unit)? = null,
onFailure: @Composable (BoxScope.(Throwable) -> Unit)? = null,
) {
// when(val painter = asyncPainterResource(url)){
// is Resource.Failure -> TODO()
// is Resource.Loading -> TODO()
// is Resource.Success -> TODO()
// }
KamelImage(
modifier = modifier,
resource = asyncPainterResource(data = url),
contentDescription = contentDescription,
contentScale = contentScale,
onLoading = onLoading,
onFailure = onFailure
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.stslex.core.ui.base.image

import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.serialization.kotlinx.json.json
import io.ktor.util.InternalAPI
import kotlinx.serialization.json.Json

@OptIn(InternalAPI::class)
@Composable
fun NativeNetworkImage(
url: String,
contentDescription: String?,
contentScale: ContentScale,
modifier: Modifier = Modifier,
) {

}

val client = HttpClient(CIO) {
install(ContentNegotiation) {
json(Json { isLenient = true; ignoreUnknownKeys = true })
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.stslex.core.ui.base.image

import androidx.compose.foundation.layout.BoxScope
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale

@Composable
fun NetworkImage(
url: String,
modifier: Modifier = Modifier,
imageType: ImageType = ImageType.KAMEL,
contentDescription: String? = null,
contentScale: ContentScale = ContentScale.Fit,
onLoading: @Composable (BoxScope.(Float) -> Unit)? = null,
onFailure: @Composable (BoxScope.(Throwable) -> Unit)? = null,
) {
when (imageType) {
ImageType.NATIVE -> NativeNetworkImage(
modifier = modifier,
url = url,
contentDescription = contentDescription,
contentScale = contentScale
)

ImageType.KAMEL -> KamelNetworkImage(
modifier = modifier,
url = url,
contentDescription = contentDescription,
contentScale = contentScale,
onLoading = onLoading,
onFailure = onFailure
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.stslex.core.ui.theme

import androidx.compose.ui.unit.dp

object AppDimension {

val small = 4.dp
val medium = 8.dp
val large = 16.dp
}
15 changes: 11 additions & 4 deletions core/ui/src/commonMain/kotlin/com/stslex/core/ui/theme/AppTheme.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import com.stslex.core.ui.base.image.AppKamelConfig
import io.kamel.image.config.LocalKamelConfig

@Composable
fun AppTheme(
Expand All @@ -16,8 +19,12 @@ fun AppTheme(
} else {
lightColorScheme()
}
MaterialTheme(
colorScheme = colors,
content = content
)
CompositionLocalProvider(
LocalKamelConfig provides AppKamelConfig.KamelLoggingConfig
) {
MaterialTheme(
colorScheme = colors,
content = content
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,36 @@ import com.stslex.feature.feed.data.model.FeedDataModel
import com.stslex.feature.feed.data.model.FilmDataModel
import kotlinx.coroutines.delay

// "https://picsum.photos/200/300"
class MockFeedRepositoryImpl : FeedRepository {

private val url1 =
"https://unsplash.com/photos/CiUR8zISX60/download?ixid=M3wxMjA3fDB8MXxzZWFyY2h8MTV8fGNpbmVtYXxlbnwwfHx8fDE3MDEwMTY0OTZ8MA&force=true&w=640"
private val url2 =
"https://unsplash.com/photos/Geepgu8bCas/download?ixid=M3wxMjA3fDB8MXxzZWFyY2h8MjJ8fGNpbmVtYXxlbnwwfHx8fDE3MDEwMTY1MDN8MA&force=true&w=640"
private val url3 =
"https://unsplash.com/photos/h5cFbbecEuY/download?ixid=M3wxMjA3fDB8MXxzZWFyY2h8MzF8fGNpbmVtYXxlbnwwfHx8fDE3MDEwMTY1MDN8MA&force=true&w=640"

override suspend fun getFeed(
page: Int,
pageSize: Int
): FeedDataModel {
Logger.debug("getFeed page: $page, pageSize: $pageSize")
delay(3000)
delay(1000)
return FeedDataModel(
films = Array(pageSize) { index ->
val itemIndex = page.dec() * pageSize + index
FilmDataModel(
id = itemIndex.toString(),
title = "Title $itemIndex",
description = "Description $itemIndex",
imageUrl = "https://picsum.photos/200/300"
)
imageUrl = when (itemIndex % 3) {
0 -> url1
1 -> url2
else -> url3
},

)
}.toList(),
hasNextPage = true
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
package com.stslex.feature.feed.ui.components

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Modifier
import com.stslex.core.core.Logger
import com.stslex.feature.feed.ui.model.FilmModel
import com.stslex.feature.feed.ui.model.ScreenState
import kotlinx.collections.immutable.ImmutableList
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filterNotNull

@Composable
internal fun FeedScreenContent(
Expand All @@ -28,43 +32,53 @@ internal fun FeedScreenContent(
snapshotFlow {
listState.layoutInfo.visibleItemsInfo.lastOrNull()?.index
}
.filterNotNull()
.distinctUntilChanged()
.collectLatest { index ->
if (
screenState != ScreenState.Content.AppendLoading &&
index != null &&
index >= films.size - 5
screenState != ScreenState.Content.AppendLoading
&& index >= films.size - 5
) {
Logger.debug("index: $index, films.size: ${films.size}")
loadMore()
}
}
}
LazyColumn(
modifier = modifier
.fillMaxSize(),
state = listState
) {
items(
count = films.size,
key = films.key
) { index ->
val film = films.getOrNull(index)
if (film != null) {
FeedScreenFilmItem(
film = film
)
BoxWithConstraints {
val itemHeight = remember(maxWidth, maxHeight) {
if (maxHeight > maxWidth) {
maxWidth / 3 * 4
} else {
maxHeight / 3 * 4
}
}
LazyColumn(
modifier = modifier
.fillMaxSize(),
state = listState
) {
items(
count = films.size,
key = films.key
) { index ->
val film = films.getOrNull(index)
if (film != null) {
FeedScreenFilmItem(
film = film,
itemHeight = itemHeight
)
}
}

if (screenState is ScreenState.Content.AppendLoading) {
item {
Box(
modifier = Modifier.fillMaxWidth(),
contentAlignment = androidx.compose.ui.Alignment.Center
) {
CircularProgressIndicator()
if (screenState is ScreenState.Content.AppendLoading) {
item {
Box(
modifier = Modifier.fillMaxWidth(),
contentAlignment = androidx.compose.ui.Alignment.Center
) {
CircularProgressIndicator()
}
}
// TODO add loading item
}
}
}
Expand Down
Loading

0 comments on commit c2d7da6

Please sign in to comment.