mirror of
https://github.com/owenlejeune/TVTime.git
synced 2025-11-17 09:10:55 -05:00
paging for home page people
This commit is contained in:
@@ -108,7 +108,11 @@ class OnboardingActivity: MonetCompatActivity() {
|
|||||||
launchActivity(MainActivity::class.java)
|
launchActivity(MainActivity::class.java)
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Text(text = "Skip")
|
val skipText = if (preferences.firstLaunchTesting)
|
||||||
|
stringResource(id = R.string.action_skip_testing)
|
||||||
|
else
|
||||||
|
stringResource(id = R.string.action_skip)
|
||||||
|
Text(text = skipText)
|
||||||
}
|
}
|
||||||
|
|
||||||
HorizontalPagerIndicator(
|
HorizontalPagerIndicator(
|
||||||
|
|||||||
@@ -1,12 +1,22 @@
|
|||||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.paging.PagingSource
|
import androidx.paging.PagingSource
|
||||||
import androidx.paging.PagingState
|
import androidx.paging.PagingState
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.HomePageService
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.HomePageService
|
||||||
import com.owenlejeune.tvtime.ui.navigation.MediaFetchFun
|
import com.owenlejeune.tvtime.ui.navigation.MediaFetchFun
|
||||||
|
import org.koin.core.Koin
|
||||||
|
import org.koin.core.component.KoinComponent
|
||||||
|
import org.koin.core.component.inject
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
|
|
||||||
class HomePagePagingSource(private val service: HomePageService, private val mediaFetch: MediaFetchFun): PagingSource<Int, TmdbItem>() {
|
class HomePagePagingSource(
|
||||||
|
private val service: HomePageService,
|
||||||
|
private val mediaFetch: MediaFetchFun
|
||||||
|
): PagingSource<Int, TmdbItem>(), KoinComponent {
|
||||||
|
|
||||||
|
private val context: Context by inject()
|
||||||
|
|
||||||
override fun getRefreshKey(state: PagingState<Int, TmdbItem>): Int? {
|
override fun getRefreshKey(state: PagingState<Int, TmdbItem>): Int? {
|
||||||
return state.anchorPosition
|
return state.anchorPosition
|
||||||
@@ -25,6 +35,7 @@ class HomePagePagingSource(private val service: HomePageService, private val med
|
|||||||
nextKey = if (results.isEmpty() || responseBody == null) null else responseBody.page + 1
|
nextKey = if (results.isEmpty() || responseBody == null) null else responseBody.page + 1
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
Toast.makeText(context, "No more results found", Toast.LENGTH_SHORT).show()
|
||||||
LoadResult.Invalid()
|
LoadResult.Invalid()
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.paging.PagingSource
|
||||||
|
import androidx.paging.PagingState
|
||||||
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.PeopleApi
|
||||||
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.PeopleService
|
||||||
|
import org.koin.core.component.KoinComponent
|
||||||
|
import org.koin.core.component.inject
|
||||||
|
|
||||||
|
class HomePagePeoplePagingSource: PagingSource<Int, HomePagePerson>(), KoinComponent {
|
||||||
|
|
||||||
|
private val service: PeopleApi by inject()
|
||||||
|
private val context: Context by inject()
|
||||||
|
|
||||||
|
override fun getRefreshKey(state: PagingState<Int, HomePagePerson>): Int? {
|
||||||
|
return state.anchorPosition
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, HomePagePerson> {
|
||||||
|
return try {
|
||||||
|
val nextPage = params.key ?: 1
|
||||||
|
val peopleResponse = service.getPopular(page = nextPage)
|
||||||
|
if (peopleResponse.isSuccessful) {
|
||||||
|
val responseBody = peopleResponse.body()
|
||||||
|
val results = responseBody?.results ?: emptyList()
|
||||||
|
LoadResult.Page(
|
||||||
|
data = results,
|
||||||
|
prevKey = if (nextPage == 1) null else nextPage - 1,
|
||||||
|
nextKey = if (results.isEmpty() || responseBody == null) null else responseBody.page + 1
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Toast.makeText(context, "No more results found", Toast.LENGTH_SHORT).show()
|
||||||
|
LoadResult.Invalid()
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
return LoadResult.Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package com.owenlejeune.tvtime.extensions
|
|||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.foundation.lazy.LazyItemScope
|
import androidx.compose.foundation.lazy.LazyItemScope
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
|
import androidx.compose.foundation.lazy.grid.GridItemSpan
|
||||||
import androidx.compose.foundation.lazy.grid.LazyGridItemScope
|
import androidx.compose.foundation.lazy.grid.LazyGridItemScope
|
||||||
import androidx.compose.foundation.lazy.grid.LazyGridScope
|
import androidx.compose.foundation.lazy.grid.LazyGridScope
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -27,6 +28,17 @@ fun <T: Any> LazyGridScope.listItems(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun LazyGridScope.header(
|
||||||
|
content: @Composable LazyGridItemScope.() -> Unit
|
||||||
|
) {
|
||||||
|
item(
|
||||||
|
span = {
|
||||||
|
GridItemSpan(maxLineSpan)
|
||||||
|
},
|
||||||
|
content = content
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun <T: Any> LazyListScope.listItems(
|
fun <T: Any> LazyListScope.listItems(
|
||||||
items: Collection<T>,
|
items: Collection<T>,
|
||||||
itemContent: @Composable (value: T) -> Unit
|
itemContent: @Composable (value: T) -> Unit
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ class AppPreferences(context: Context) {
|
|||||||
get() = preferences.getBoolean(FIRST_LAUNCH, true)
|
get() = preferences.getBoolean(FIRST_LAUNCH, true)
|
||||||
set(value) { preferences.put(FIRST_LAUNCH, value) }
|
set(value) { preferences.put(FIRST_LAUNCH, value) }
|
||||||
|
|
||||||
val useV4ApiDefault: Boolean = false
|
val useV4ApiDefault: Boolean = true
|
||||||
var useV4Api: Boolean
|
var useV4Api: Boolean
|
||||||
get() = preferences.getBoolean(USE_V4_API, useV4ApiDefault)
|
get() = preferences.getBoolean(USE_V4_API, useV4ApiDefault)
|
||||||
set(value) { preferences.put(USE_V4_API, value) }
|
set(value) { preferences.put(USE_V4_API, value) }
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import com.owenlejeune.tvtime.api.tmdb.api.v3.model.ImageCollection
|
|||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.Person
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.Person
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TmdbItem
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TmdbItem
|
||||||
import com.owenlejeune.tvtime.extensions.dpToPx
|
import com.owenlejeune.tvtime.extensions.dpToPx
|
||||||
|
import com.owenlejeune.tvtime.extensions.header
|
||||||
import com.owenlejeune.tvtime.extensions.lazyPagingItems
|
import com.owenlejeune.tvtime.extensions.lazyPagingItems
|
||||||
import com.owenlejeune.tvtime.extensions.listItems
|
import com.owenlejeune.tvtime.extensions.listItems
|
||||||
import com.owenlejeune.tvtime.utils.TmdbUtils
|
import com.owenlejeune.tvtime.utils.TmdbUtils
|
||||||
@@ -96,6 +97,46 @@ fun PagingPosterGrid(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun PagingPeoplePosterGrid(
|
||||||
|
lazyPagingItems: LazyPagingItems<HomePagePerson>?,
|
||||||
|
header: @Composable () -> Unit = {},
|
||||||
|
onClick: (id: Int) -> Unit = {}
|
||||||
|
) {
|
||||||
|
lazyPagingItems?.let {
|
||||||
|
LazyVerticalGrid(
|
||||||
|
columns = GridCells.Adaptive(minSize = POSTER_WIDTH),
|
||||||
|
contentPadding = PaddingValues(8.dp),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
header {
|
||||||
|
header()
|
||||||
|
}
|
||||||
|
|
||||||
|
lazyPagingItems(lazyPagingItems) { person ->
|
||||||
|
person?.let {
|
||||||
|
PosterItem(
|
||||||
|
url = TmdbUtils.getFullPersonImagePath(person.profilePath),
|
||||||
|
noDataImage = R.drawable.no_person_photo,
|
||||||
|
modifier = Modifier.padding(5.dp),
|
||||||
|
onClick = {
|
||||||
|
onClick(person.id)
|
||||||
|
},
|
||||||
|
contentDescription = person.name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lazyPagingItems.apply {
|
||||||
|
when {
|
||||||
|
loadState.refresh is LoadState.Loading -> {}
|
||||||
|
loadState.append is LoadState.Loading -> {}
|
||||||
|
loadState.append is LoadState.Error -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun PeoplePosterGrid(
|
fun PeoplePosterGrid(
|
||||||
@@ -187,13 +228,14 @@ fun PosterItem(
|
|||||||
Card(
|
Card(
|
||||||
elevation = elevation,
|
elevation = elevation,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.size(width = width, height = height),
|
.width(width = width)
|
||||||
|
.wrapContentHeight(),
|
||||||
shape = RoundedCornerShape(5.dp)
|
shape = RoundedCornerShape(5.dp)
|
||||||
) {
|
) {
|
||||||
if (url != null) {
|
if (url != null) {
|
||||||
AsyncImage(
|
AsyncImage(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(width = width, height = height)
|
.width(width = width)
|
||||||
.clip(RoundedCornerShape(5.dp))
|
.clip(RoundedCornerShape(5.dp))
|
||||||
.clickable(
|
.clickable(
|
||||||
onClick = onClick
|
onClick = onClick
|
||||||
@@ -201,7 +243,7 @@ fun PosterItem(
|
|||||||
model = url,
|
model = url,
|
||||||
placeholder = rememberAsyncImagePainter(model = placeholder),
|
placeholder = rememberAsyncImagePainter(model = placeholder),
|
||||||
contentDescription = contentDescription,
|
contentDescription = contentDescription,
|
||||||
contentScale = ContentScale.FillBounds
|
contentScale = ContentScale.FillWidth
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Image(
|
Image(
|
||||||
|
|||||||
@@ -1,24 +1,14 @@
|
|||||||
package com.owenlejeune.tvtime.ui.navigation
|
package com.owenlejeune.tvtime.ui.navigation
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import androidx.paging.Pager
|
|
||||||
import androidx.paging.PagingConfig
|
|
||||||
import androidx.paging.PagingData
|
|
||||||
import androidx.paging.cachedIn
|
|
||||||
import com.owenlejeune.tvtime.R
|
import com.owenlejeune.tvtime.R
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.HomePageService
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.HomePageService
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.MoviesService
|
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.TvService
|
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.HomePagePagingSource
|
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.HomePageResponse
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.HomePageResponse
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TmdbItem
|
|
||||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
|
||||||
import com.owenlejeune.tvtime.ui.screens.main.MediaTabContent
|
import com.owenlejeune.tvtime.ui.screens.main.MediaTabContent
|
||||||
|
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||||
|
import com.owenlejeune.tvtime.ui.viewmodel.MediaTabViewModel
|
||||||
import com.owenlejeune.tvtime.utils.ResourceUtils
|
import com.owenlejeune.tvtime.utils.ResourceUtils
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import org.koin.core.component.inject
|
import org.koin.core.component.inject
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
|
|
||||||
@@ -95,19 +85,3 @@ private val screenContent: MediaNavComposableFun = { appNavController, mediaView
|
|||||||
typealias MediaNavComposableFun = @Composable (NavHostController, MediaViewType, MediaTabNavItem) -> Unit
|
typealias MediaNavComposableFun = @Composable (NavHostController, MediaViewType, MediaTabNavItem) -> Unit
|
||||||
|
|
||||||
typealias MediaFetchFun = suspend (service: HomePageService, page: Int) -> Response<out HomePageResponse>
|
typealias MediaFetchFun = suspend (service: HomePageService, page: Int) -> Response<out HomePageResponse>
|
||||||
|
|
||||||
sealed class MediaTabViewModel(service: HomePageService, mediaFetchFun: MediaFetchFun): ViewModel() {
|
|
||||||
val mediaItems: Flow<PagingData<TmdbItem>> = Pager(PagingConfig(pageSize = Int.MAX_VALUE)) {
|
|
||||||
HomePagePagingSource(service = service, mediaFetch = mediaFetchFun)
|
|
||||||
}.flow.cachedIn(viewModelScope)
|
|
||||||
|
|
||||||
object PopularMoviesVM: MediaTabViewModel(MoviesService(), { s, p -> s.getPopular(p) })
|
|
||||||
object TopRatedMoviesVM: MediaTabViewModel(MoviesService(), { s, p -> s.getTopRated(p) })
|
|
||||||
object NowPlayingMoviesVM: MediaTabViewModel(MoviesService(), { s, p -> s.getNowPlaying(p) })
|
|
||||||
object UpcomingMoviesVM: MediaTabViewModel(MoviesService(), { s, p -> s.getUpcoming(p) })
|
|
||||||
object PopularTvVM: MediaTabViewModel(TvService(), { s, p -> s.getPopular(p) })
|
|
||||||
object TopRatedTvVM: MediaTabViewModel(TvService(), { s, p -> s.getTopRated(p) })
|
|
||||||
object AiringTodayTvVM: MediaTabViewModel(TvService(), { s, p -> s.getNowPlaying(p) })
|
|
||||||
object OnTheAirTvVM: MediaTabViewModel(TvService(), { s, p -> s.getUpcoming(p) })
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,14 +1,9 @@
|
|||||||
package com.owenlejeune.tvtime.ui.screens.main
|
package com.owenlejeune.tvtime.ui.screens.main
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.Search
|
|
||||||
import androidx.compose.material3.FloatingActionButton
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import androidx.paging.compose.collectAsLazyPagingItems
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
@@ -17,24 +12,12 @@ import com.google.accompanist.pager.HorizontalPager
|
|||||||
import com.google.accompanist.pager.PagerState
|
import com.google.accompanist.pager.PagerState
|
||||||
import com.google.accompanist.pager.rememberPagerState
|
import com.google.accompanist.pager.rememberPagerState
|
||||||
import com.owenlejeune.tvtime.R
|
import com.owenlejeune.tvtime.R
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.HomePageService
|
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.MoviesService
|
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.TvService
|
|
||||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
|
||||||
import com.owenlejeune.tvtime.ui.components.PagingPosterGrid
|
import com.owenlejeune.tvtime.ui.components.PagingPosterGrid
|
||||||
import com.owenlejeune.tvtime.ui.components.PosterGrid
|
|
||||||
import com.owenlejeune.tvtime.ui.components.SearchBar
|
|
||||||
import com.owenlejeune.tvtime.ui.components.SearchView
|
import com.owenlejeune.tvtime.ui.components.SearchView
|
||||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||||
import com.owenlejeune.tvtime.ui.navigation.MediaFetchFun
|
|
||||||
import com.owenlejeune.tvtime.ui.navigation.MediaTabNavItem
|
import com.owenlejeune.tvtime.ui.navigation.MediaTabNavItem
|
||||||
import com.owenlejeune.tvtime.ui.navigation.MediaTabViewModel
|
|
||||||
import com.owenlejeune.tvtime.ui.screens.main.tabs.top.Tabs
|
import com.owenlejeune.tvtime.ui.screens.main.tabs.top.Tabs
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import com.owenlejeune.tvtime.ui.viewmodel.MediaTabViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import org.koin.java.KoinJavaComponent.get
|
|
||||||
|
|
||||||
@OptIn(ExperimentalPagerApi::class)
|
@OptIn(ExperimentalPagerApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
package com.owenlejeune.tvtime.ui.screens.main
|
package com.owenlejeune.tvtime.ui.screens.main
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
import com.owenlejeune.tvtime.R
|
import com.owenlejeune.tvtime.R
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.PeopleService
|
import com.owenlejeune.tvtime.ui.components.PagingPeoplePosterGrid
|
||||||
import com.owenlejeune.tvtime.ui.components.PeoplePosterGrid
|
|
||||||
import com.owenlejeune.tvtime.ui.components.SearchView
|
import com.owenlejeune.tvtime.ui.components.SearchView
|
||||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import com.owenlejeune.tvtime.ui.viewmodel.PeopleTabViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun PeopleTab(
|
fun PeopleTab(
|
||||||
@@ -23,8 +24,6 @@ fun PeopleTab(
|
|||||||
) {
|
) {
|
||||||
appBarTitle.value = stringResource(id = R.string.nav_people_title)
|
appBarTitle.value = stringResource(id = R.string.nav_people_title)
|
||||||
|
|
||||||
val service = PeopleService()
|
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
SearchView(
|
SearchView(
|
||||||
title = appBarTitle.value,
|
title = appBarTitle.value,
|
||||||
@@ -33,16 +32,15 @@ fun PeopleTab(
|
|||||||
fab = fab
|
fab = fab
|
||||||
)
|
)
|
||||||
|
|
||||||
PeoplePosterGrid(
|
val peopleList = PeopleTabViewModel().popularPeople.collectAsLazyPagingItems()
|
||||||
fetchPeople = { peopleList ->
|
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
PagingPeoplePosterGrid(
|
||||||
val response = service.getPopular()
|
lazyPagingItems = peopleList,
|
||||||
if (response.isSuccessful) {
|
header = {
|
||||||
withContext(Dispatchers.Main) {
|
Text(
|
||||||
peopleList.value = response.body()?.results ?: emptyList()
|
text = stringResource(R.string.popular_today_header),
|
||||||
}
|
modifier = Modifier.padding(start = 8.dp)
|
||||||
}
|
)
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onClick = { id ->
|
onClick = { id ->
|
||||||
appNavController.navigate(
|
appNavController.navigate(
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.owenlejeune.tvtime.ui.viewmodel
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.paging.Pager
|
||||||
|
import androidx.paging.PagingConfig
|
||||||
|
import androidx.paging.PagingData
|
||||||
|
import androidx.paging.cachedIn
|
||||||
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.HomePageService
|
||||||
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.MoviesService
|
||||||
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.TvService
|
||||||
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.HomePagePagingSource
|
||||||
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TmdbItem
|
||||||
|
import com.owenlejeune.tvtime.ui.navigation.MediaFetchFun
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
sealed class MediaTabViewModel(service: HomePageService, mediaFetchFun: MediaFetchFun): ViewModel() {
|
||||||
|
val mediaItems: Flow<PagingData<TmdbItem>> = Pager(PagingConfig(pageSize = Int.MAX_VALUE)) {
|
||||||
|
HomePagePagingSource(service = service, mediaFetch = mediaFetchFun)
|
||||||
|
}.flow.cachedIn(viewModelScope)
|
||||||
|
|
||||||
|
object PopularMoviesVM: MediaTabViewModel(MoviesService(), { s, p -> s.getPopular(p) })
|
||||||
|
object TopRatedMoviesVM: MediaTabViewModel(MoviesService(), { s, p -> s.getTopRated(p) })
|
||||||
|
object NowPlayingMoviesVM: MediaTabViewModel(MoviesService(), { s, p -> s.getNowPlaying(p) })
|
||||||
|
object UpcomingMoviesVM: MediaTabViewModel(MoviesService(), { s, p -> s.getUpcoming(p) })
|
||||||
|
object PopularTvVM: MediaTabViewModel(TvService(), { s, p -> s.getPopular(p) })
|
||||||
|
object TopRatedTvVM: MediaTabViewModel(TvService(), { s, p -> s.getTopRated(p) })
|
||||||
|
object AiringTodayTvVM: MediaTabViewModel(TvService(), { s, p -> s.getNowPlaying(p) })
|
||||||
|
object OnTheAirTvVM: MediaTabViewModel(TvService(), { s, p -> s.getUpcoming(p) })
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.owenlejeune.tvtime.ui.viewmodel
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.paging.Pager
|
||||||
|
import androidx.paging.PagingConfig
|
||||||
|
import androidx.paging.PagingData
|
||||||
|
import androidx.paging.cachedIn
|
||||||
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.HomePagePeoplePagingSource
|
||||||
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.HomePagePerson
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
class PeopleTabViewModel: ViewModel() {
|
||||||
|
|
||||||
|
val popularPeople: Flow<PagingData<HomePagePerson>> = Pager(PagingConfig(pageSize = Int.MAX_VALUE)) {
|
||||||
|
HomePagePeoplePagingSource()
|
||||||
|
}.flow.cachedIn(viewModelScope)
|
||||||
|
|
||||||
|
}
|
||||||
@@ -148,4 +148,7 @@
|
|||||||
<!-- search results -->
|
<!-- search results -->
|
||||||
<string name="search_result_tv_series">TV Series</string>
|
<string name="search_result_tv_series">TV Series</string>
|
||||||
<string name="no_search_results">No search results found</string>
|
<string name="no_search_results">No search results found</string>
|
||||||
|
<string name="action_skip">Skip</string>
|
||||||
|
<string name="action_skip_testing">Skip (testing)</string>
|
||||||
|
<string name="popular_today_header">Popular Today</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user