Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

actors-paging impl. #9

Merged
merged 1 commit into from
Oct 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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