mirror of
https://github.com/owenlejeune/TVTime.git
synced 2025-11-08 12:42:44 -05:00
fix crash while searching
This commit is contained in:
@@ -20,38 +20,38 @@ import retrofit2.Response
|
|||||||
|
|
||||||
class SearchService: KoinComponent {
|
class SearchService: KoinComponent {
|
||||||
|
|
||||||
private val service: SearchService by inject()
|
private val service: SearchApi by inject()
|
||||||
|
|
||||||
val movieResults = mutableStateOf<Flow<PagingData<SearchResultMovie>>?>(null)
|
val movieResults = mutableStateOf<Flow<PagingData<SearchResultMovie>>?>(null)
|
||||||
val tvResults = mutableStateOf<Flow<PagingData<SearchResultTv>>?>(null)
|
val tvResults = mutableStateOf<Flow<PagingData<SearchResultTv>>?>(null)
|
||||||
val peopleResults = mutableStateOf<Flow<PagingData<SearchResultPerson>>?>(null)
|
val peopleResults = mutableStateOf<Flow<PagingData<SearchResultPerson>>?>(null)
|
||||||
val multiResults = mutableStateOf<Flow<PagingData<SortableSearchResult>>?>(null)
|
val multiResults = mutableStateOf<Flow<PagingData<SortableSearchResult>>?>(null)
|
||||||
|
|
||||||
fun searchCompanies(query: String, page: Int = 1): Response<SearchResult<ProductionCompany>> {
|
suspend fun searchCompanies(query: String, page: Int = 1): Response<SearchResult<ProductionCompany>> {
|
||||||
return service.searchCompanies(query, page)
|
return service.searchCompanies(query, page)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun searchCollections(query: String, page: Int = 1): Response<SearchResult<Collection>> {
|
suspend fun searchCollections(query: String, page: Int = 1): Response<SearchResult<Collection>> {
|
||||||
return service.searchCollections(query, page)
|
return service.searchCollections(query, page)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun searchKeywords(query: String, page: Int = 1): Response<SearchResult<Keyword>> {
|
suspend fun searchKeywords(query: String, page: Int = 1): Response<SearchResult<Keyword>> {
|
||||||
return service.searchKeywords(query, page)
|
return service.searchKeywords(query, page)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun searchMovies(query: String, page: Int): Response<SearchResult<SearchResultMovie>> {
|
suspend fun searchMovies(query: String, page: Int): Response<SearchResult<SearchResultMovie>> {
|
||||||
return service.searchMovies(query, page)
|
return service.searchMovies(query, page)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun searchTv(query: String, page: Int): Response<SearchResult<SearchResultTv>> {
|
suspend fun searchTv(query: String, page: Int): Response<SearchResult<SearchResultTv>> {
|
||||||
return service.searchTv(query, page)
|
return service.searchTv(query, page)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun searchPeople(query: String, page: Int): Response<SearchResult<SearchResultPerson>> {
|
suspend fun searchPeople(query: String, page: Int): Response<SearchResult<SearchResultPerson>> {
|
||||||
return service.searchPeople(query, page)
|
return service.searchPeople(query, page)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun searchMulti(query: String, page: Int): Response<SearchResult<SortableSearchResult>> {
|
suspend fun searchMulti(query: String, page: Int): Response<SearchResult<SortableSearchResult>> {
|
||||||
return service.searchMulti(query, page)
|
return service.searchMulti(query, page)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
package com.owenlejeune.tvtime.ui.screens
|
package com.owenlejeune.tvtime.ui.screens
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.ArrowBack
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
import androidx.compose.material.icons.filled.Clear
|
import androidx.compose.material.icons.filled.Clear
|
||||||
@@ -19,6 +22,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
|
import androidx.paging.LoadState
|
||||||
import androidx.paging.compose.collectAsLazyPagingItems
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||||
import com.owenlejeune.tvtime.R
|
import com.owenlejeune.tvtime.R
|
||||||
@@ -97,20 +101,6 @@ fun SearchScreen(
|
|||||||
)
|
)
|
||||||
Divider(thickness = 2.dp, color = MaterialTheme.colorScheme.surfaceVariant)
|
Divider(thickness = 2.dp, color = MaterialTheme.colorScheme.surfaceVariant)
|
||||||
|
|
||||||
val showLoadingAnimation = remember { mutableStateOf(false) }
|
|
||||||
if (showLoadingAnimation.value) {
|
|
||||||
LinearProgressIndicator(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
trackColor = MaterialTheme.colorScheme.background
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
LinearProgressIndicator(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
trackColor = MaterialTheme.colorScheme.background,
|
|
||||||
progress = 0f
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
when (mediaViewType) {
|
when (mediaViewType) {
|
||||||
MediaViewType.TV -> {
|
MediaViewType.TV -> {
|
||||||
TvResultsView(appNavController = appNavController, searchViewModel = searchViewModel)
|
TvResultsView(appNavController = appNavController, searchViewModel = searchViewModel)
|
||||||
@@ -138,6 +128,8 @@ private fun MovieResultsView(
|
|||||||
appNavController: NavHostController,
|
appNavController: NavHostController,
|
||||||
searchViewModel: SearchViewModel
|
searchViewModel: SearchViewModel
|
||||||
) {
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
val results = remember { searchViewModel.movieResults }
|
val results = remember { searchViewModel.movieResults }
|
||||||
results.value?.let {
|
results.value?.let {
|
||||||
val pagingItems = it.collectAsLazyPagingItems()
|
val pagingItems = it.collectAsLazyPagingItems()
|
||||||
@@ -146,6 +138,7 @@ private fun MovieResultsView(
|
|||||||
modifier = Modifier.padding(all = 12.dp),
|
modifier = Modifier.padding(all = 12.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
) {
|
) {
|
||||||
|
handleLoadState(context, pagingItems.loadState.refresh)
|
||||||
lazyPagingItems(pagingItems) { item ->
|
lazyPagingItems(pagingItems) { item ->
|
||||||
item?.let {
|
item?.let {
|
||||||
MovieSearchResultView(
|
MovieSearchResultView(
|
||||||
@@ -154,6 +147,7 @@ private fun MovieResultsView(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
handleLoadState(context, pagingItems.loadState.append)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Column(
|
Column(
|
||||||
@@ -177,6 +171,8 @@ private fun TvResultsView(
|
|||||||
appNavController: NavHostController,
|
appNavController: NavHostController,
|
||||||
searchViewModel: SearchViewModel
|
searchViewModel: SearchViewModel
|
||||||
) {
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
val results = remember { searchViewModel.tvResults }
|
val results = remember { searchViewModel.tvResults }
|
||||||
results.value?.let {
|
results.value?.let {
|
||||||
val pagingItems = it.collectAsLazyPagingItems()
|
val pagingItems = it.collectAsLazyPagingItems()
|
||||||
@@ -185,6 +181,7 @@ private fun TvResultsView(
|
|||||||
modifier = Modifier.padding(all = 12.dp),
|
modifier = Modifier.padding(all = 12.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
) {
|
) {
|
||||||
|
handleLoadState(context, pagingItems.loadState.refresh)
|
||||||
lazyPagingItems(pagingItems) { item ->
|
lazyPagingItems(pagingItems) { item ->
|
||||||
item?.let {
|
item?.let {
|
||||||
TvSearchResultView(
|
TvSearchResultView(
|
||||||
@@ -193,6 +190,7 @@ private fun TvResultsView(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
handleLoadState(context, pagingItems.loadState.append)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Column(
|
Column(
|
||||||
@@ -216,6 +214,8 @@ private fun PeopleResultsView(
|
|||||||
appNavController: NavHostController,
|
appNavController: NavHostController,
|
||||||
searchViewModel: SearchViewModel
|
searchViewModel: SearchViewModel
|
||||||
) {
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
val results = remember { searchViewModel.peopleResults }
|
val results = remember { searchViewModel.peopleResults }
|
||||||
results.value?.let {
|
results.value?.let {
|
||||||
val pagingItems = it.collectAsLazyPagingItems()
|
val pagingItems = it.collectAsLazyPagingItems()
|
||||||
@@ -224,6 +224,7 @@ private fun PeopleResultsView(
|
|||||||
modifier = Modifier.padding(all = 12.dp),
|
modifier = Modifier.padding(all = 12.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
) {
|
) {
|
||||||
|
handleLoadState(context, pagingItems.loadState.refresh)
|
||||||
lazyPagingItems(pagingItems) { item ->
|
lazyPagingItems(pagingItems) { item ->
|
||||||
item?.let {
|
item?.let {
|
||||||
PeopleSearchResultView(
|
PeopleSearchResultView(
|
||||||
@@ -232,6 +233,7 @@ private fun PeopleResultsView(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
handleLoadState(context, pagingItems.loadState.append)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Column(
|
Column(
|
||||||
@@ -255,6 +257,8 @@ private fun MultiResultsView(
|
|||||||
appNavController: NavHostController,
|
appNavController: NavHostController,
|
||||||
searchViewModel: SearchViewModel
|
searchViewModel: SearchViewModel
|
||||||
) {
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
val results = remember { searchViewModel.multiResults }
|
val results = remember { searchViewModel.multiResults }
|
||||||
results.value?.let {
|
results.value?.let {
|
||||||
val pagingItems = it.collectAsLazyPagingItems()
|
val pagingItems = it.collectAsLazyPagingItems()
|
||||||
@@ -263,6 +267,7 @@ private fun MultiResultsView(
|
|||||||
modifier = Modifier.padding(all = 12.dp),
|
modifier = Modifier.padding(all = 12.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
) {
|
) {
|
||||||
|
handleLoadState(context, pagingItems.loadState.refresh)
|
||||||
lazyPagingItems(pagingItems) { item ->
|
lazyPagingItems(pagingItems) { item ->
|
||||||
item?.let {
|
item?.let {
|
||||||
when (item.mediaType) {
|
when (item.mediaType) {
|
||||||
@@ -288,6 +293,7 @@ private fun MultiResultsView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
handleLoadState(context, pagingItems.loadState.append)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Column(
|
Column(
|
||||||
@@ -306,6 +312,23 @@ private fun MultiResultsView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun LazyListScope.handleLoadState(context: Context, state: LoadState) {
|
||||||
|
when (state) {
|
||||||
|
is LoadState.Loading -> {
|
||||||
|
item {
|
||||||
|
LinearProgressIndicator(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
trackColor = MaterialTheme.colorScheme.background
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is LoadState.Error -> {
|
||||||
|
Toast.makeText(context, "An error occurred", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun <T: SortableSearchResult> SearchResultItemView(
|
private fun <T: SortableSearchResult> SearchResultItemView(
|
||||||
appNavController: NavHostController,
|
appNavController: NavHostController,
|
||||||
@@ -388,18 +411,20 @@ private fun PeopleSearchResultView(
|
|||||||
appNavController: NavHostController,
|
appNavController: NavHostController,
|
||||||
result: SearchResultPerson
|
result: SearchResultPerson
|
||||||
) {
|
) {
|
||||||
val mostKnownFor = result.knownFor.sortedBy { it.popularity }[0]
|
val mostKnownFor = result.knownFor.sortedBy { it.popularity }.takeUnless { it.isEmpty() }?.get(0)
|
||||||
|
|
||||||
|
val additional = mostKnownFor?.let {
|
||||||
|
listOf(
|
||||||
|
"${mostKnownFor.title} (${TmdbUtils.releaseYearFromData(mostKnownFor.releaseDate)})"
|
||||||
|
)
|
||||||
|
} ?: emptyList()
|
||||||
|
|
||||||
SearchResultItemView(
|
SearchResultItemView(
|
||||||
appNavController = appNavController,
|
appNavController = appNavController,
|
||||||
mediaViewType = MediaViewType.PERSON,
|
mediaViewType = MediaViewType.PERSON,
|
||||||
searchResult = result,
|
searchResult = result,
|
||||||
posterModel = { TmdbUtils.getFullPersonImagePath(result.profilePath) },
|
posterModel = { TmdbUtils.getFullPersonImagePath(result.profilePath) },
|
||||||
backdropModel = { TmdbUtils.getFullBackdropPath(mostKnownFor.backdropPath) },
|
backdropModel = { TmdbUtils.getFullBackdropPath(mostKnownFor?.backdropPath) },
|
||||||
additionalDetails = {
|
additionalDetails = { additional }
|
||||||
listOf(
|
|
||||||
"${mostKnownFor.title} (${TmdbUtils.releaseYearFromData(mostKnownFor.releaseDate)})"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,16 @@
|
|||||||
package com.owenlejeune.tvtime.ui.viewmodel
|
package com.owenlejeune.tvtime.ui.viewmodel
|
||||||
|
|
||||||
|
import androidx.compose.runtime.MutableState
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.paging.PagingData
|
import androidx.paging.PagingData
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.createPagingFlow
|
import com.owenlejeune.tvtime.api.tmdb.api.createPagingFlow
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.SearchResultProvider
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.SearchResultProvider
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.SearchService
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.SearchService
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.Searchable
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.Searchable
|
||||||
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.SortableSearchResult
|
||||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||||
|
import com.owenlejeune.tvtime.utils.types.ViewableMediaTypeException
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import org.koin.core.component.KoinComponent
|
import org.koin.core.component.KoinComponent
|
||||||
import org.koin.core.component.inject
|
import org.koin.core.component.inject
|
||||||
|
|||||||
Reference in New Issue
Block a user