diff --git a/app/build.gradle b/app/build.gradle index 4de2507..2d1be9f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -84,6 +84,9 @@ dependencies { implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.5.0-rc01" implementation "androidx.navigation:navigation-compose:2.5.0-rc01" implementation 'androidx.paging:paging-compose:1.0.0-alpha17' + implementation("androidx.paging:paging-runtime:$paging_version") + // alternatively - without Android dependencies for tests + testImplementation("androidx.paging:paging-common:$paging_version") // coroutines implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1' diff --git a/app/src/main/java/com/smish/abda/data/api/MovieApiService.kt b/app/src/main/java/com/smish/abda/data/api/MovieApiService.kt index 2d44a09..3cd8194 100644 --- a/app/src/main/java/com/smish/abda/data/api/MovieApiService.kt +++ b/app/src/main/java/com/smish/abda/data/api/MovieApiService.kt @@ -15,9 +15,11 @@ interface MovieApiService { searchQuery: String, @Query("page") page: Int, + @Query("type") + type: String, @Query("apikey") apiKey: String = BuildConfig.MOVIE_API_KEY - ): Response + ): Movie @GET(".") suspend fun getMovieDetails( diff --git a/app/src/main/java/com/smish/abda/data/db/MovieDao.kt b/app/src/main/java/com/smish/abda/data/db/MovieDao.kt index d5a179d..7c3c4ca 100644 --- a/app/src/main/java/com/smish/abda/data/db/MovieDao.kt +++ b/app/src/main/java/com/smish/abda/data/db/MovieDao.kt @@ -19,4 +19,7 @@ interface MovieDao { @Query("DELETE FROM movies WHERE imdbID = :imdbID") suspend fun delete(imdbID: String) + + @Query("DELETE FROM movies") + suspend fun deleteAll() } \ No newline at end of file diff --git a/app/src/main/java/com/smish/abda/data/repository/MovieRepositoryImpl.kt b/app/src/main/java/com/smish/abda/data/repository/MovieRepositoryImpl.kt index 777034a..d0a021b 100644 --- a/app/src/main/java/com/smish/abda/data/repository/MovieRepositoryImpl.kt +++ b/app/src/main/java/com/smish/abda/data/repository/MovieRepositoryImpl.kt @@ -1,6 +1,6 @@ package com.smish.abda.data.repository -import com.smish.abda.data.model.movie.Movie +import androidx.paging.PagingData import com.smish.abda.data.model.movie.Search import com.smish.abda.data.model.moviedetail.MovieDetail import com.smish.abda.data.repository.datasource.MovieLocalDataSource @@ -14,9 +14,9 @@ class MovieRepositoryImpl( private val movieLocalDataSource: MovieLocalDataSource ): MovieRepository { - override suspend fun getMovies(searchQuery: String, page: Int): Resource { - val response = movieRemoteDataSource.getMovies(searchQuery, page) - if (response.isSuccessful) { + override fun getMovies(searchQuery: String, type: String, page: Int): Flow> { + return movieRemoteDataSource.getMovies(searchQuery, type, page) + /*if (response.isSuccessful) { response.body()?.let { res -> if (res.response == "True") { return Resource.Success(res) @@ -25,7 +25,7 @@ class MovieRepositoryImpl( } } } - return Resource.Error(response.message() ?: "Unknown error occurred") + return Resource.Error(response.message() ?: "Unknown error occurred")*/ } override suspend fun getMovieDetails(imdbId: String): Resource { diff --git a/app/src/main/java/com/smish/abda/data/repository/datasource/MoviePagingSource.kt b/app/src/main/java/com/smish/abda/data/repository/datasource/MoviePagingSource.kt new file mode 100644 index 0000000..3e27f16 --- /dev/null +++ b/app/src/main/java/com/smish/abda/data/repository/datasource/MoviePagingSource.kt @@ -0,0 +1,60 @@ +package com.smish.abda.data.repository.datasource + +import androidx.paging.PagingSource +import androidx.paging.PagingState +import com.smish.abda.data.api.MovieApiService +import com.smish.abda.data.model.movie.Search +import okio.IOException +import retrofit2.HttpException + +private const val OMDB_STARTING_PAGE_INDEX = 1 + +class MoviePagingSource( + private val query: String, + private val type: String, + private val movieApiService: MovieApiService +): PagingSource() { + + override fun getRefreshKey(state: PagingState): Int? { + /* We need to get the previous key (or next key if previous is null) of the page + that was closest to the most recently accessed index. + Anchor position is the most recently accessed index.*/ + return state.anchorPosition?.let { anchorPosition -> + state.closestPageToPosition(anchorPosition)?.prevKey?.plus(1) + ?: state.closestPageToPosition(anchorPosition)?.nextKey?.minus(1) + } + } + + override suspend fun load(params: LoadParams): LoadResult { + val pageIndex = params.key ?: OMDB_STARTING_PAGE_INDEX + + return try { + val response = movieApiService.getMovies( + searchQuery = query, + type = type, + page = pageIndex + ) + // can return load state . error here + + val movies: List = (response.movies ?: emptyList()) as List + val nextKey = + if (movies.isEmpty()) { + null + } else { + /* By default, initial load size = 3 * NETWORK PAGE SIZE + ensure we're not requesting duplicating items at the 2nd request + pageIndex + (params.loadSize / NETWORK_PAGE_SIZE)*/ + pageIndex + 1 + } + LoadResult.Page( + data = movies, + prevKey = if (pageIndex == OMDB_STARTING_PAGE_INDEX) null else pageIndex, + nextKey = nextKey + ) + } catch (exception: IOException) { + return LoadResult.Error(exception) + } catch (exception: HttpException) { + return LoadResult.Error(exception) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/smish/abda/data/repository/datasource/MovieRemoteDataSource.kt b/app/src/main/java/com/smish/abda/data/repository/datasource/MovieRemoteDataSource.kt index c4da2c3..ebc141c 100644 --- a/app/src/main/java/com/smish/abda/data/repository/datasource/MovieRemoteDataSource.kt +++ b/app/src/main/java/com/smish/abda/data/repository/datasource/MovieRemoteDataSource.kt @@ -1,12 +1,14 @@ package com.smish.abda.data.repository.datasource -import com.smish.abda.data.model.movie.Movie +import androidx.paging.PagingData +import com.smish.abda.data.model.movie.Search import com.smish.abda.data.model.moviedetail.MovieDetail +import kotlinx.coroutines.flow.Flow import retrofit2.Response interface MovieRemoteDataSource { // defining functions to communicate with the API // use for both search and all - suspend fun getMovies(searchQuery: String, page: Int): Response + fun getMovies(searchQuery: String, type: String, page: Int): Flow> suspend fun getMovieDetails(imdbId: String): Response } \ No newline at end of file diff --git a/app/src/main/java/com/smish/abda/data/repository/datasourceimpl/MovieRemoteDataSourceImpl.kt b/app/src/main/java/com/smish/abda/data/repository/datasourceimpl/MovieRemoteDataSourceImpl.kt index 96d37ea..4d95655 100644 --- a/app/src/main/java/com/smish/abda/data/repository/datasourceimpl/MovieRemoteDataSourceImpl.kt +++ b/app/src/main/java/com/smish/abda/data/repository/datasourceimpl/MovieRemoteDataSourceImpl.kt @@ -1,17 +1,30 @@ package com.smish.abda.data.repository.datasourceimpl +import androidx.paging.Pager +import androidx.paging.PagingConfig +import androidx.paging.PagingData import com.smish.abda.data.api.MovieApiService -import com.smish.abda.data.model.movie.Movie +import com.smish.abda.data.model.movie.Search import com.smish.abda.data.model.moviedetail.MovieDetail +import com.smish.abda.data.repository.datasource.MoviePagingSource import com.smish.abda.data.repository.datasource.MovieRemoteDataSource +import kotlinx.coroutines.flow.Flow import retrofit2.Response class MovieRemoteDataSourceImpl( private val movieAPI: MovieApiService ): MovieRemoteDataSource { - override suspend fun getMovies(searchQuery: String, page: Int): Response { - return movieAPI.getMovies(searchQuery, page) + override fun getMovies(searchQuery: String, type: String, page: Int): Flow> { + return Pager( + config = PagingConfig( + pageSize = 10, + enablePlaceholders = false + ), + pagingSourceFactory = { + MoviePagingSource(query = searchQuery, type = type, movieApiService = movieAPI) + } + ).flow } override suspend fun getMovieDetails(imdbId: String): Response { diff --git a/app/src/main/java/com/smish/abda/domain/repository/MovieRepository.kt b/app/src/main/java/com/smish/abda/domain/repository/MovieRepository.kt index 0050219..1943d00 100644 --- a/app/src/main/java/com/smish/abda/domain/repository/MovieRepository.kt +++ b/app/src/main/java/com/smish/abda/domain/repository/MovieRepository.kt @@ -1,6 +1,6 @@ package com.smish.abda.domain.repository -import com.smish.abda.data.model.movie.Movie +import androidx.paging.PagingData import com.smish.abda.data.model.movie.Search import com.smish.abda.data.model.moviedetail.MovieDetail import com.smish.abda.util.Resource @@ -8,7 +8,7 @@ import kotlinx.coroutines.flow.Flow interface MovieRepository { // this will be used for both get all movies and search - suspend fun getMovies(searchQuery: String, page: Int): Resource + fun getMovies(searchQuery: String, type: String, page: Int): Flow> suspend fun getMovieDetails(imdbId: String): Resource suspend fun bookmarkMovie(movie: Search) diff --git a/app/src/main/java/com/smish/abda/domain/usecase/GetMovies.kt b/app/src/main/java/com/smish/abda/domain/usecase/GetMovies.kt index 263835c..2577d8e 100644 --- a/app/src/main/java/com/smish/abda/domain/usecase/GetMovies.kt +++ b/app/src/main/java/com/smish/abda/domain/usecase/GetMovies.kt @@ -1,11 +1,12 @@ package com.smish.abda.domain.usecase -import com.smish.abda.data.model.movie.Movie +import androidx.paging.PagingData +import com.smish.abda.data.model.movie.Search import com.smish.abda.domain.repository.MovieRepository -import com.smish.abda.util.Resource +import kotlinx.coroutines.flow.Flow class GetMovies(private val movieRepository: MovieRepository) { - suspend fun getMovies(searchQuery: String, page: Int): Resource { - return movieRepository.getMovies(searchQuery, page) + fun getMovies(searchQuery: String, type: String, page: Int): Flow> { + return movieRepository.getMovies(searchQuery, type, page) } } \ No newline at end of file diff --git a/app/src/main/java/com/smish/abda/ui/movieList/components/MovieList.kt b/app/src/main/java/com/smish/abda/ui/movieList/components/MovieList.kt new file mode 100644 index 0000000..b1d9dd7 --- /dev/null +++ b/app/src/main/java/com/smish/abda/ui/movieList/components/MovieList.kt @@ -0,0 +1,82 @@ +package com.smish.abda.ui.movieList.components + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material.CircularProgressIndicator +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.paging.LoadState +import androidx.paging.compose.LazyPagingItems +import androidx.paging.compose.items +import com.smish.abda.data.model.movie.Search + +@Composable +fun MovieList( + movies: LazyPagingItems, + modifier: Modifier = Modifier, + onMovieClick: (Search) -> Unit, + onBookmarkClick: (isChecked: Boolean, movie: Search) -> Unit +) { + when (movies.loadState.refresh) { + LoadState.Loading -> { + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + CircularProgressIndicator() + } + } + is LoadState.Error -> { + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text(text = "Something went wrong") + } + } + else -> { + /*LazyColumn(modifier = modifier) { + itemsIndexed(books) { index, item -> + item?.let { + BookItem( + book = item, + modifier = Modifier + .fillMaxWidth() + .background(getBackgroundForIndex(index)) + .padding(vertical = 15.dp) + ) + } + } + }*/ + LazyColumn( + modifier = Modifier.fillMaxSize() + ) { + items(movies) { movie -> + if (movie != null) { + val (isChecked, setChecked) = remember { mutableStateOf(false) } + MovieListItem( + movie = movie, + onMovieClick = { + // call the movie detail api and trigger the bottom sheet + onMovieClick(movie) + }, + isChecked, + onBookmarkClick = { + setChecked(!isChecked) + onBookmarkClick(isChecked, movie) + } + ) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/smish/abda/ui/movieList/components/MovieListScreen.kt b/app/src/main/java/com/smish/abda/ui/movieList/components/MovieListScreen.kt index 2f6bbb1..b70c9e7 100644 --- a/app/src/main/java/com/smish/abda/ui/movieList/components/MovieListScreen.kt +++ b/app/src/main/java/com/smish/abda/ui/movieList/components/MovieListScreen.kt @@ -1,12 +1,8 @@ package com.smish.abda.ui.movieList.components -import androidx.compose.animation.core.animateIntAsState import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyRow -import androidx.compose.foundation.lazy.grid.GridCells -import androidx.compose.foundation.lazy.grid.LazyVerticalGrid -import androidx.compose.foundation.lazy.grid.items import androidx.compose.foundation.lazy.items import androidx.compose.foundation.selection.toggleable import androidx.compose.foundation.shape.RoundedCornerShape @@ -20,7 +16,6 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.res.colorResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight @@ -32,6 +27,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.paging.compose.collectAsLazyPagingItems import com.smish.abda.R import com.smish.abda.data.model.movie.Type import com.smish.abda.data.model.movie.getAllTypes @@ -40,16 +36,12 @@ import com.smish.abda.data.model.moviedetail.MovieDetail import com.smish.abda.ui.viewmodel.MoviesViewmodel import kotlinx.coroutines.launch -enum class ExpandedType { - HALF, FULL, COLLAPSED -} @OptIn(ExperimentalMaterialApi::class) @Composable fun MovieListScreen( viewmodel: MoviesViewmodel = hiltViewModel() ) { - val state = viewmodel.movieState.value val movieDetailState = viewmodel.movieDetailState.value val textState = remember { mutableStateOf(TextFieldValue("")) } @@ -65,19 +57,7 @@ fun MovieListScreen( mutableStateOf(false) } - val configuration = LocalConfiguration.current - val screenHeight = configuration.screenHeightDp - var expandedType by remember { - mutableStateOf(ExpandedType.COLLAPSED) - } - val height by animateIntAsState( - when (expandedType) { - ExpandedType.HALF -> screenHeight / 2 - ExpandedType.FULL -> screenHeight - ExpandedType.COLLAPSED -> 0 - } - ) - + val movieList = viewmodel.getPagingMovies().collectAsLazyPagingItems() ModalBottomSheetLayout( sheetState = bottomSheetModalState, sheetContent = { @@ -86,7 +66,6 @@ fun MovieListScreen( movie = movieDetailState.movies LaunchedEffect(bottomSheetModalState) { bottomSheetModalState.show() -// bottomSheetScaffoldState.bottomSheetState.expand() } } Column( @@ -137,15 +116,30 @@ fun MovieListScreen( selectedType = selectedType.value, onSelectedChanged = { selectedType.value = getType(it) - viewmodel.getSpecificType(it) + viewmodel.setSpecificType(it) + } + ) + + + MovieList( + movies = movieList, + onMovieClick = { + showModalSheet.value = !showModalSheet.value + viewmodel.getMovieDetails(it.imdbID) + }, + onBookmarkClick = { isChecked, movie -> + if (!isChecked) + viewmodel.bookmarkMovie(movie) + else + viewmodel.removeMovie(movie) } ) - LazyVerticalGrid( + /*LazyVerticalGrid( modifier = Modifier.fillMaxSize(), columns = GridCells.Adaptive(minSize = 135.dp) ) { - items(state.movies?.movies ?: emptyList()) { movie -> + items(movieList) { movie -> if (movie != null) { val (isChecked, setChecked) = remember { mutableStateOf(false) } MovieListItem( @@ -166,10 +160,10 @@ fun MovieListScreen( ) } } - } + }*/ } - if (state.error.isNotBlank()) { + /*if (state.error.isNotBlank()) { Text( text = state.error, color = MaterialTheme.colors.error, @@ -179,12 +173,12 @@ fun MovieListScreen( .padding(horizontal = 20.dp) .align(Alignment.Center) ) - } + }*/ // Progress Bar - if (state.isLoading) { + /*if (state.isLoading) { CircularProgressIndicator(modifier = Modifier.align(Alignment.Center)) - } + }*/ } } @@ -197,8 +191,10 @@ fun SearchView(state: MutableState, viewmodel: MoviesViewmodel) value = state.value, onValueChange = { value -> state.value = value - if (state.value.text.length > 3) - viewmodel.performQuery(state.value.text, 1) + if (state.value.text.length > 3) { +// viewmodel.performQuery(state.value.text, 1) + viewmodel.setQuery(state.value.text) + } }, leadingIcon = { Icon( @@ -215,7 +211,8 @@ fun SearchView(state: MutableState, viewmodel: MoviesViewmodel) onClick = { state.value = TextFieldValue("") // Remove text from TextField when you press the 'X' icon - viewmodel.performQuery("why", 1) +// viewmodel.performQuery("why", 1) + viewmodel.setQuery("why") } ) { Icon( @@ -278,8 +275,8 @@ fun ChipGroup( Chip( name = it.value, isSelected = selectedType == it, - onSelectionChanged = { - onSelectedChanged(it) + onSelectionChanged = { type -> + onSelectedChanged(type) }, ) } @@ -318,13 +315,6 @@ fun Chip( } } -@Preview(showBackground = false) -@Composable -fun SearchViewPreview() { - val textState = remember { mutableStateOf(TextFieldValue("")) } -// SearchView(textState) -} - @Preview(showBackground = false) @Composable fun TypeGroupPreview() { diff --git a/app/src/main/java/com/smish/abda/ui/viewmodel/MoviesViewmodel.kt b/app/src/main/java/com/smish/abda/ui/viewmodel/MoviesViewmodel.kt index 7bab475..d6a6364 100644 --- a/app/src/main/java/com/smish/abda/ui/viewmodel/MoviesViewmodel.kt +++ b/app/src/main/java/com/smish/abda/ui/viewmodel/MoviesViewmodel.kt @@ -4,19 +4,23 @@ import android.app.Application import android.content.Context import android.net.ConnectivityManager import android.net.NetworkCapabilities -import android.util.Log import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf -import androidx.lifecycle.* +import androidx.lifecycle.AndroidViewModel +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.liveData +import androidx.lifecycle.viewModelScope +import androidx.paging.PagingData +import androidx.paging.cachedIn import com.smish.abda.data.model.movie.Movie import com.smish.abda.data.model.movie.Search import com.smish.abda.data.model.movie.Type import com.smish.abda.domain.usecase.* import com.smish.abda.ui.movieList.MovieDetailState -import com.smish.abda.ui.movieList.MovieListState import com.smish.abda.util.Resource import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.launch import javax.inject.Inject @@ -32,67 +36,28 @@ class MoviesViewmodel @Inject constructor( val movies: MutableLiveData> = MutableLiveData() - private val _movieState = mutableStateOf(MovieListState()) - val movieState: State = _movieState - - private var topMovies: List? = emptyList() - private val _movieDetailState = mutableStateOf(MovieDetailState()) val movieDetailState: State = _movieDetailState - init { - getMovies("why", 1) + private var query = mutableStateOf("") + private var _type = mutableStateOf("") + + fun getPagingMovies(): Flow> { + val pager = getMovies.getMovies(query.value, _type.value, 1) + pager.cachedIn(viewModelScope) + return pager } - fun getMovies(searchQuery: String, page: Int) = viewModelScope.launch { Dispatchers.IO -// movies.postValue(Resource.Loading()) - _movieState.value = MovieListState(isLoading = true) - try { - if (isNetworkAvailable(app)) { - val result = getMovies.getMovies(searchQuery, page) - Log.d("movies", "getMovies: ${result.data}") - when (result) { - is Resource.Error -> _movieState.value = - MovieListState(error = result.message ?: "Unexpected Error occurred") - is Resource.Loading -> _movieState.value = MovieListState(isLoading = true) - is Resource.Success -> { - _movieState.value = MovieListState(movies = result.data) - topMovies = _movieState.value.movies?.movies - /*if (page == 5) - _movieState.value = MovieListState( - movies = Movie( - "True", - topMovies, - topMovies.size.toString() - ) - ) - else { - result.data?.movies?.forEach { - if (it != null) { - topMovies.add(it) - } - } - }*/ - } - } -// movies.postValue(result) - } else { -// movies.postValue(Resource.Error("Internet is not available")) - _movieState.value = MovieListState(error = "Internet is not available") - } - } catch (e: Exception) { -// movies.postValue(Resource.Error(e.message ?: "An unknown error occurred")) - _movieState.value = MovieListState(error = e.message ?: "An unknown error occurred") - } + fun setQuery(query: String) { + this.query.value = query } + fun getMovieDetails(imdbId: String) = viewModelScope.launch { Dispatchers.IO _movieDetailState.value = MovieDetailState(isLoading = true) try { if (isNetworkAvailable(app)) { - val result = getMovieDetail.getMovieDetails(imdbId) - Log.d("movies", "getMovieDetails: ${result.data}") - when (result) { + when (val result = getMovieDetail.getMovieDetails(imdbId)) { is Resource.Error -> _movieDetailState.value = MovieDetailState(error = result.message ?: "Unexpected Error occurred") is Resource.Loading -> _movieDetailState.value = MovieDetailState(isLoading = true) is Resource.Success -> { @@ -100,10 +65,10 @@ class MoviesViewmodel @Inject constructor( } } } else { - _movieState.value = MovieListState(error = "Internet is not available") + _movieDetailState.value = MovieDetailState(error = "Internet is not available") } } catch (e: Exception) { - _movieState.value = MovieListState(error = e.message ?: "An unknown error occurred") + _movieDetailState.value = MovieDetailState(error = e.message ?: "An unknown error occurred") } } @@ -123,50 +88,21 @@ class MoviesViewmodel @Inject constructor( return result } - fun performQuery(query: String, page: Int) { - getMovies(query, page) - } - - fun getSpecificType(type: String) { + fun setSpecificType(type: String) { when (type) { Type.HOME.value -> { - if (topMovies.isNullOrEmpty()) - _movieState.value = MovieListState(error = "Unknown error occurred, please try again") - else - _movieState.value = MovieListState(movies = Movie("True", topMovies, topMovies?.size.toString())) + _type.value = "" } Type.MOVIE.value -> { - var movieList = topMovies - movieList = movieList?.filter { - it?.type == Type.MOVIE.value - } - if (movieList.isNullOrEmpty()) - _movieState.value = MovieListState(error = "Match not found") - else - _movieState.value = MovieListState(movies = Movie("True", movieList, movieList.size.toString())) + _type.value = Type.MOVIE.value } Type.SERIES.value -> { - var movieList = topMovies - movieList = movieList?.filter { - it?.type == Type.SERIES.value - } - if (movieList.isNullOrEmpty()) - _movieState.value = MovieListState(error = "Match not found") - else - _movieState.value = MovieListState(movies = Movie("True", movieList, movieList.size.toString())) + _type.value = Type.SERIES.value } - Type.EPISODE.value -> { - var movieList = topMovies - movieList = movieList?.filter { - it?.type == Type.EPISODE.value - } - if (movieList.isNullOrEmpty()) - _movieState.value = MovieListState(error = "Match not found") - else - _movieState.value = MovieListState(movies = Movie("True", movieList, movieList.size.toString())) + _type.value = Type.EPISODE.value } } } diff --git a/build.gradle b/build.gradle index 09a0ca6..033cad1 100644 --- a/build.gradle +++ b/build.gradle @@ -4,6 +4,7 @@ buildscript { compose_version = '1.4.0-alpha02' nav_version = '2.5.3' lifecycle_version = '2.5.1' + paging_version = "3.1.1" } }// Top-level build file where you can add configuration options common to all sub-projects/modules.