Skip to content

Commit

Permalink
Merge pull request #9 from commandiron/1.0.0/actors-pading
Browse files Browse the repository at this point in the history
actors-paging impl.
  • Loading branch information
commandiron authored Oct 2, 2022
2 parents 7ad0a9d + 1611ebf commit 0b09aae
Show file tree
Hide file tree
Showing 13 changed files with 157 additions and 94 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.commandiron.toprated10films.data.mapper

import com.commandiron.toprated10films.data.model.movie_db_actor.MovieDbActor
import com.commandiron.toprated10films.ui.model.Actor
import com.commandiron.toprated10films.domain.model.Actor

fun MovieDbActor.toActor(): Actor {
return Actor(
id = id,
name = name,
imageUrl = "https://image.tmdb.org/t/p/original/$profile_path"
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.commandiron.toprated10films.data.paging

import androidx.paging.PagingSource
import androidx.paging.PagingState
import com.commandiron.toprated10films.data.mapper.toActor
import com.commandiron.toprated10films.data.remote.MovieApi
import com.commandiron.toprated10films.domain.model.Actor

class ActorPagingSource(
private val api: MovieApi
) : PagingSource<Int, Actor>() {

override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Actor> {
val currentPage = params.key ?: 1
return try {
val response = api.getActors(currentPage)
val endOfPaginationReached = response.page == response.total_pages
if (!endOfPaginationReached) {
LoadResult.Page(
data = response.movieDbActors.map { it.toActor() },
prevKey = if (currentPage == 1) null else currentPage - 1,
nextKey = currentPage + 1
)
} else {
LoadResult.Page(
data = emptyList(),
prevKey = null,
nextKey = null
)
}
} catch (e: Exception) {
LoadResult.Error(e)
}
}

override fun getRefreshKey(state: PagingState<Int, Actor>): Int? {
return state.anchorPosition
}

}
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package com.commandiron.toprated10films.data.repository

import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.commandiron.toprated10films.data.local.AppDao
import com.commandiron.toprated10films.data.mapper.toActor
import com.commandiron.toprated10films.data.mapper.toGenre
import com.commandiron.toprated10films.data.paging.ActorPagingSource
import com.commandiron.toprated10films.data.remote.MovieApi
import com.commandiron.toprated10films.domain.model.Genre
import com.commandiron.toprated10films.domain.repository.AppRepository
import com.commandiron.toprated10films.ui.model.Actor
import com.commandiron.toprated10films.domain.model.Actor
import com.commandiron.toprated10films.util.Response
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
Expand Down Expand Up @@ -37,14 +40,10 @@ class AppRepositoryImpl(
dao.insertGenre(*genres.toTypedArray())
}

override suspend fun getActors(page: Int): Flow<Response<List<Actor>>> = flow {
emit(Response.Loading)
try {
val actors: List<Actor> = api.getActors(page).movieDbActors.map { it.toActor() }
emit(Response.Success(actors))
}catch (e: Exception) {
emit(Response.Error(e.message ?: "AN_ERROR_OCCURRED"))
e.printStackTrace()
}
override suspend fun getActors(): Flow<PagingData<Actor>> {
return Pager(
config = PagingConfig(pageSize = 20),
pagingSourceFactory = { ActorPagingSource(api) }
).flow
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.commandiron.toprated10films.domain.model

data class Actor(
val id: Int,
val name: String,
val imageUrl: String
)
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package com.commandiron.toprated10films.domain.repository

import androidx.paging.PagingData
import com.commandiron.toprated10films.domain.model.Genre
import com.commandiron.toprated10films.ui.model.Actor
import com.commandiron.toprated10films.domain.model.Actor
import com.commandiron.toprated10films.util.Response
import kotlinx.coroutines.flow.Flow

interface AppRepository {
suspend fun getGenres(): Flow<Response<List<Genre>>>
suspend fun saveGenres(genres: List<Genre>)
suspend fun getActors(page: Int): Flow<Response<List<Actor>>>
suspend fun getActors(): Flow<PagingData<Actor>>
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package com.commandiron.toprated10films.domain.use_cases

import androidx.paging.PagingData
import com.commandiron.toprated10films.domain.repository.AppRepository
import com.commandiron.toprated10films.ui.model.Actor
import com.commandiron.toprated10films.util.Response
import com.commandiron.toprated10films.domain.model.Actor
import kotlinx.coroutines.flow.Flow

class GetActors(
private val repository: AppRepository
) {
suspend operator fun invoke(page: Int): Flow<Response<List<Actor>>> = repository.getActors(page)
suspend operator fun invoke(): Flow<PagingData<Actor>> = repository.getActors()
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
Expand All @@ -20,7 +19,9 @@ import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.text.style.TextAlign
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.paging.compose.collectAsLazyPagingItems
import com.commandiron.toprated10films.ui.presentation.actor.components.ActorCard
import com.commandiron.toprated10films.ui.presentation.actor.components.items
import com.commandiron.toprated10films.ui.presentation.components.SearchTextField
import com.commandiron.toprated10films.ui.theme.spacing

Expand All @@ -31,7 +32,7 @@ fun ActorScreen(
onClick: (actorName: String) -> Unit
) {
val searchText = viewModel.searchText.collectAsState().value
val actors = viewModel.actors.collectAsState().value
val actors = viewModel.actors.collectAsLazyPagingItems()
val isLoading = viewModel.isLoading.collectAsState().value
val keyboardController = LocalSoftwareKeyboardController.current
val focusManager = LocalFocusManager.current
Expand Down Expand Up @@ -94,28 +95,32 @@ fun ActorScreen(
horizontal = MaterialTheme.spacing.spaceMedium
)
){
items(actors) { actor ->
ActorCard(
modifier = Modifier
.padding(MaterialTheme.spacing.spaceExtraSmall)
.clip(MaterialTheme.shapes.medium)
.aspectRatio(0.75f)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null
) {
if (isImeVisible) {
focusManager.clearFocus()
keyboardController?.hide()
} else {
onClick(actor.name)
}
},
actor = actor
)
}
item {
Spacer(Modifier.height(MaterialTheme.spacing.spaceXXXLarge))
items(
items = actors,
key = { actor ->
actor.id
}
) { actor ->
actor?.let {
ActorCard(
modifier = Modifier
.padding(MaterialTheme.spacing.spaceExtraSmall)
.clip(MaterialTheme.shapes.medium)
.aspectRatio(0.75f)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null
) {
if (isImeVisible) {
focusManager.clearFocus()
keyboardController?.hide()
} else {
onClick(it.name)
}
},
actor = it
)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ package com.commandiron.toprated10films.ui.presentation.actor

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData
import androidx.paging.cachedIn
import com.commandiron.toprated10films.domain.use_cases.UseCases
import com.commandiron.toprated10films.ui.model.Actor.Companion.defaultActorList
import com.commandiron.toprated10films.util.Response
import com.commandiron.toprated10films.domain.model.Actor
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
Expand All @@ -16,8 +17,8 @@ class ActorViewModel @Inject constructor(
private val useCases: UseCases
): ViewModel() {

private val _actors = MutableStateFlow(defaultActorList)
val actors = _actors.asStateFlow()
private val _actors = MutableStateFlow<PagingData<Actor>>(PagingData.empty())
val actors = _actors

private val _searchText = MutableStateFlow("")
val searchText = _searchText.asStateFlow()
Expand All @@ -27,19 +28,8 @@ class ActorViewModel @Inject constructor(

init {
viewModelScope.launch {
useCases.getActors(2).collect { response ->
when(response) {
is Response.Error -> {

}
Response.Loading -> {

}
is Response.Success -> {
println(response.data)
_actors.value = response.data
}
}
useCases.getActors().cachedIn(viewModelScope).collect { response ->
actors.value = response
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextOverflow
import com.commandiron.toprated10films.ui.model.Actor
import com.commandiron.toprated10films.domain.model.Actor
import com.commandiron.toprated10films.ui.presentation.components.CustomAsyncImage
import com.commandiron.toprated10films.ui.presentation.components.TopTenSticker
import com.commandiron.toprated10films.ui.theme.spacing
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.commandiron.toprated10films.ui.presentation.actor.components

import android.annotation.SuppressLint
import android.os.Parcel
import android.os.Parcelable
import androidx.compose.foundation.lazy.grid.LazyGridItemScope
import androidx.compose.foundation.lazy.grid.LazyGridScope
import androidx.compose.runtime.Composable
import androidx.paging.compose.LazyPagingItems

fun <T : Any> LazyGridScope.items(
items: LazyPagingItems<T>,
key: ((item: T) -> Any)? = null,
itemContent: @Composable LazyGridItemScope.(item: T?) -> Unit
) {
items(
count = items.itemCount,
key = if (key == null) null else { index ->
val item = items.peek(index)
if (item == null) {
PagingPlaceholderKey(index)
} else {
key(item)
}
}
) { index ->
itemContent(items[index])
}
}

@SuppressLint("BanParcelableUsage")
private data class PagingPlaceholderKey(private val index: Int) : Parcelable {
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeInt(index)
}

override fun describeContents(): Int {
return 0
}

companion object {
@Suppress("unused")
@JvmField
val CREATOR: Parcelable.Creator<PagingPlaceholderKey> =
object : Parcelable.Creator<PagingPlaceholderKey> {
override fun createFromParcel(parcel: Parcel) =
PagingPlaceholderKey(parcel.readInt())

override fun newArray(size: Int) = arrayOfNulls<PagingPlaceholderKey?>(size)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ class SelectionViewModel @Inject constructor(

private val _populars = MutableStateFlow(defaultPopularList)
val populars = _populars.asStateFlow()

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
import com.commandiron.toprated10films.domain.model.Actor
import com.commandiron.toprated10films.domain.model.Genre
import com.commandiron.toprated10films.ui.model.*
import com.commandiron.toprated10films.ui.presentation.actor.components.ActorCard
Expand All @@ -24,6 +25,7 @@ fun PopularCard(
Category.ByActor -> {
ActorCard(
actor = Actor(
id = 0,
name = popular.title,
imageUrl = popular.imageUrl ?: ""
),
Expand Down

0 comments on commit 0b09aae

Please sign in to comment.