diff --git a/presentation/src/main/java/com/london/presentation/feature/account/AccountScreen.kt b/presentation/src/main/java/com/london/presentation/feature/account/AccountScreen.kt index ab6cb159a..0452ac7b0 100644 --- a/presentation/src/main/java/com/london/presentation/feature/account/AccountScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/account/AccountScreen.kt @@ -21,6 +21,7 @@ import com.london.presentation.feature.account.components.LoggedInContent import com.london.presentation.feature.account.components.NotLoggedInContent import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.utils.Listen +import com.london.presentation.utils.navBarBottomPadding @Composable fun AccountScreen( @@ -60,7 +61,7 @@ private fun Content( uiState: AccountUiState, accountContract: AccountContract, ) { - Column { + Column(Modifier.navBarBottomPadding()) { TopBar( title = stringResource(R.string.my_account), modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp) @@ -117,4 +118,4 @@ private fun Content( else -> {} } -} \ No newline at end of file +} diff --git a/presentation/src/main/java/com/london/presentation/feature/category/main/CategoriesScreen.kt b/presentation/src/main/java/com/london/presentation/feature/category/main/CategoriesScreen.kt index 162f34968..73cade99f 100644 --- a/presentation/src/main/java/com/london/presentation/feature/category/main/CategoriesScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/category/main/CategoriesScreen.kt @@ -35,6 +35,7 @@ import com.london.presentation.shared.genre.MovieGenreUi import com.london.presentation.shared.genre.TvShowGenreUi import com.london.presentation.utils.Listen import com.london.presentation.utils.gridColumns +import com.london.presentation.utils.navBarBottomPadding @Composable fun CategoriesScreen( @@ -64,7 +65,7 @@ private fun Content( state: CategoriesUiState, contract: CategoriesContract, ) { - Column { + Column(Modifier.navBarBottomPadding()) { TopBar( title = stringResource(R.string.categories), modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp), diff --git a/presentation/src/main/java/com/london/presentation/feature/home/HomeScreen.kt b/presentation/src/main/java/com/london/presentation/feature/home/HomeScreen.kt index f20af9fa2..28f46e0e7 100644 --- a/presentation/src/main/java/com/london/presentation/feature/home/HomeScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/home/HomeScreen.kt @@ -61,6 +61,7 @@ import com.london.presentation.shared.bookmarkSheet.BookmarkBottomSheet import com.london.presentation.shared.buildscreen.NetworkErrorScreen import com.london.presentation.utils.Listen import com.london.presentation.utils.gridColumns +import com.london.presentation.utils.navBarBottomPadding @Composable fun HomeScreen( @@ -182,7 +183,7 @@ private fun HomeScreenLayout( homeScreenContract: HomeScreenContract ) { Box( - modifier = Modifier.fillMaxSize() + modifier = Modifier.fillMaxSize().navBarBottomPadding() ) { BackgroundGradient( screenWidth = screenWidth, diff --git a/presentation/src/main/java/com/london/presentation/feature/list/savedlist/ListViewModel.kt b/presentation/src/main/java/com/london/presentation/feature/list/savedlist/ListViewModel.kt index be716be56..a0d36d92b 100644 --- a/presentation/src/main/java/com/london/presentation/feature/list/savedlist/ListViewModel.kt +++ b/presentation/src/main/java/com/london/presentation/feature/list/savedlist/ListViewModel.kt @@ -2,6 +2,8 @@ package com.london.presentation.feature.list.savedlist import androidx.compose.ui.text.input.TextFieldValue import androidx.lifecycle.SavedStateHandle +import androidx.paging.PagingData +import com.london.domain.entity.movie.MovieList import com.london.domain.usecase.authentication.AuthenticationUseCase import com.london.domain.usecase.movielist.ManageGetMovieUseCase import com.london.domain.usecase.movielist.ManageMovieListUseCase @@ -11,6 +13,7 @@ import com.london.presentation.shared.base.BaseViewModel import com.london.presentation.shared.base.createPagingSourceFlow import dagger.hilt.android.lifecycle.HiltViewModel import jakarta.inject.Inject +import kotlinx.coroutines.flow.Flow @HiltViewModel class ListViewModel @Inject constructor( @@ -23,110 +26,87 @@ class ListViewModel @Inject constructor( private val args = savedStateHandle.getArgs() init { - checkUserLoginStatus { isLoggedIn -> if (!isLoggedIn) return@checkUserLoginStatus fetchSavedLists() } - setAddListSheetVisible(args?.createList ?: false) } - override fun onRetry() { fetchSavedLists() } + override fun onRetry() = fetchSavedLists() + override fun onFabClick() = setAddListSheetVisible(true) - override fun onLoginClick() { emitEffect(ListEffect.NavigateToLogin) } + override fun onLoginClick() = emitEffect(ListEffect.NavigateToLogin) + override fun onListClick(id: Int) { updateState { copy(isSnackBarSuccessVisible = false) } emitEffect(ListEffect.NavigateToDetails(id)) } - override fun setAddListSheetVisible(visible: Boolean) { - updateState { - copy(addListSheetState = addListSheetState.copy(isSheetVisible = visible)) - } - } + override fun setAddListSheetVisible(visible: Boolean) = + updateState { copy(addListSheetState = addListSheetState.copy(isSheetVisible = visible)) } - override fun onListNameChanged(listName: TextFieldValue) { - updateState { - copy(addListSheetState = addListSheetState.copy(listName = listName)) - } - } - override fun onAddList(listName: String) { + override fun onListNameChanged(listName: TextFieldValue) = + updateState { copy(addListSheetState = addListSheetState.copy(listName = listName)) } + + override fun onAddList(listName: String) { tryToExecute( - onStart = { - updateState { copy(isSnackBarSuccessVisible = false, isLoading = true) } - }, - block = { - manageMovieListUseCase.createMovieList(listName) - }, - onError = { - updateState { copy(error = it, isLoading = false) } - }, - onSuccess = { - setAddListSheetVisible(false) - updateState { - copy( - isSnackBarSuccessVisible = true, - isLoading = false, - addListSheetState = addListSheetState.copy( - listName = TextFieldValue(""), - ) - ) - } - fetchSavedLists() - } + onStart = { updateState { copy(isSnackBarSuccessVisible = false, isLoading = true) } }, + block = { manageMovieListUseCase.createMovieList(listName) }, + onError = { updateState { copy(error = it, isLoading = false) } }, + onSuccess = { handleAddListSuccess() } ) } - private fun fetchSavedLists() { + private fun handleAddListSuccess() { + setAddListSheetVisible(false) + updateState { + copy( + isSnackBarSuccessVisible = true, + isLoading = false, + addListSheetState = addListSheetState.copy( + listName = TextFieldValue(""), + ) + ) + } + fetchSavedLists() + } + private fun fetchSavedLists() { tryToExecute( - block = { - val moviesFlow = createPagingSourceFlow(query = "") { _, pageNumber -> - val movies = manageGetMovieUseCase.getAllMovieLists( - pageNumber - ) - movies.copy(items = movies.items) - } - moviesFlow - }, - onStart = { - updateState { copy(isLoading = true) } - }, - onSuccess = { moviesFlow -> - updateState { - copy(items = moviesFlow) - } - }, - onError = { errorState -> - updateState { - copy(error = errorState) - } - }, + block = { createListsPagingSource() }, + onStart = { updateState { copy(isLoading = true) } }, + onSuccess = { moviesFlow -> updateState { copy(items = moviesFlow) } }, + onError = { errorState -> updateState { copy(error = errorState,) } }, onCompleted = { updateState { copy(isLoading = false) } }, ) } - private fun checkUserLoginStatus(onResult: (Boolean) -> Unit = {}) { + private fun createListsPagingSource(): Flow> = + createPagingSourceFlow { _, pageNumber -> + manageGetMovieUseCase.getAllMovieLists( + pageNumber + ) + } + private fun checkUserLoginStatus(onResult: (Boolean) -> Unit = {}) { tryToExecute( block = { authenticationUseCase.isLoggedIn() }, - onStart = { - updateState { copy(isLoading = true) } - }, - onSuccess = { isLoggedIn -> - updateState { copy(isGuest = !isLoggedIn, isLoading = false) } - onResult(isLoggedIn) - }, - onError = { - updateState { copy(isGuest = true, isLoading = false) } - onResult(false) - } + onStart = { updateState { copy(isLoading = true) } }, + onSuccess = { isLoggedIn -> handleUserLoginSuccess(isLoggedIn); onResult(isLoggedIn) }, + onError = { handleUserLoginFail(); onResult(false) }, + onCompleted = { updateState { copy(isLoading = false) } }, ) } + + private fun handleUserLoginSuccess(isLoggedIn: Boolean) = + updateState { copy(isGuest = !isLoggedIn, isLoading = false) } + + private fun handleUserLoginFail() = updateState { copy(isGuest = true, isLoading = false) } + } diff --git a/presentation/src/main/java/com/london/presentation/feature/list/savedlist/listScreen.kt b/presentation/src/main/java/com/london/presentation/feature/list/savedlist/listScreen.kt index ce44b39cb..b7e52f9ec 100644 --- a/presentation/src/main/java/com/london/presentation/feature/list/savedlist/listScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/list/savedlist/listScreen.kt @@ -49,6 +49,7 @@ import com.london.presentation.shared.SnackBarAnimation import com.london.presentation.shared.base.ErrorState import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.utils.Listen +import com.london.presentation.utils.navBarBottomPadding import com.london.presentation.utils.toLocalizedNumbers @Composable @@ -86,14 +87,9 @@ private fun Content( isError = state.error is ErrorState.NoInternet, pagingFlow = pagingItems, isGuest = state.isGuest, - guestContent = { - NoListFoundAsGuest( - onLoginClick = contract::onLoginClick - ) - }, - emptyContent = { - EmptyList(contract = contract, addListSheetState = state.addListSheetState) - } + guestContent = { NoListFoundAsGuest(onLoginClick = contract::onLoginClick) }, + emptyContent = { EmptyList(contract = contract, addListSheetState = state.addListSheetState) }, + handlePagingLoadingAutomatically = true ) { ScreenScaffold( titleRes = R.string.saved_list_title, @@ -146,6 +142,7 @@ private fun ScreenScaffold( Column( modifier = Modifier .fillMaxSize() + .navBarBottomPadding() .background(NovixTheme.colors.surface) ) { TopBar( diff --git a/presentation/src/main/java/com/london/presentation/feature/list/viewitems/viewItemsScreen.kt b/presentation/src/main/java/com/london/presentation/feature/list/viewitems/viewItemsScreen.kt index ba6a2089d..55259a847 100644 --- a/presentation/src/main/java/com/london/presentation/feature/list/viewitems/viewItemsScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/list/viewitems/viewItemsScreen.kt @@ -72,7 +72,6 @@ private fun Content( emptyLayoutMessage = R.string.no_items_found, emptyLayoutImage = R.drawable.img_no_result, pagingFlow = listItems, - handlePagingLoadingAutomatically = false ) { MediaLazyPagingGrid( pagingFlow = listItems, diff --git a/presentation/src/main/java/com/london/presentation/feature/search/SearchScreen.kt b/presentation/src/main/java/com/london/presentation/feature/search/SearchScreen.kt index 7471e9767..b35687665 100644 --- a/presentation/src/main/java/com/london/presentation/feature/search/SearchScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/search/SearchScreen.kt @@ -66,6 +66,7 @@ import com.london.presentation.shared.buildscreen.NetworkErrorScreen import com.london.presentation.shared.container.MediaLazyVerticalGrid import com.london.presentation.utils.Listen import com.london.presentation.utils.ResultOrEmpty +import com.london.presentation.utils.navBarBottomPadding import com.london.presentation.utils.toRecentViewed @Composable @@ -142,6 +143,7 @@ private fun SearchMainContent( Box( modifier = Modifier .fillMaxSize() + .navBarBottomPadding() .pointerInput(Unit) { detectTapGestures(onTap = { onClearFocus() }) } ) { TriangleBlurredShape() @@ -683,4 +685,4 @@ private fun Preview() { onNavigateToTvShowDetails = {}, onNavigateToMovieDetails = {} ) -} \ No newline at end of file +} diff --git a/presentation/src/main/java/com/london/presentation/shared/buildscreen/BuildScreen.kt b/presentation/src/main/java/com/london/presentation/shared/buildscreen/BuildScreen.kt index 63102f40e..941d0e5c6 100644 --- a/presentation/src/main/java/com/london/presentation/shared/buildscreen/BuildScreen.kt +++ b/presentation/src/main/java/com/london/presentation/shared/buildscreen/BuildScreen.kt @@ -57,12 +57,15 @@ fun BuildScreen( @StringRes emptyLayoutMessage: Int? = null, @DrawableRes emptyLayoutImage: Int? = null, pagingFlow: LazyPagingItems<*>? = null, - handlePagingLoadingAutomatically: Boolean = false, + handlePagingLoadingAutomatically: Boolean = true, emptyContent: (@Composable () -> Unit)? = null, guestContent: (@Composable () -> Unit)? = null, content: @Composable () -> Unit, ) { when { + + isGuest && guestContent != null -> { guestContent.invoke() } + shouldShowLoading( isLoading = isLoading, handlePagingLoadingAutomatically = handlePagingLoadingAutomatically, @@ -73,7 +76,7 @@ fun BuildScreen( NetworkErrorScreen(onBack = onBack, onRetry = onRetry) } - isGuest && guestContent != null -> { guestContent.invoke() } + (pagingFlow!=null) && pagingFlow.isEmpty() && diff --git a/presentation/src/main/java/com/london/presentation/utils/modifierExtensions.kt b/presentation/src/main/java/com/london/presentation/utils/modifierExtensions.kt index 0c6e24481..3a9fe9f8b 100644 --- a/presentation/src/main/java/com/london/presentation/utils/modifierExtensions.kt +++ b/presentation/src/main/java/com/london/presentation/utils/modifierExtensions.kt @@ -2,8 +2,11 @@ package com.london.presentation.utils import androidx.compose.foundation.background import androidx.compose.foundation.border +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable @@ -51,3 +54,8 @@ fun Modifier.headerDetailsCard() = fillMaxWidth() fun Modifier.detailsTopBar(backgroundAlpha: Float) = fillMaxWidth() .background(NovixTheme.colors.surface.copy(alpha = backgroundAlpha)) .padding(horizontal = 16.dp, vertical = 8.dp) + +@Composable +fun Modifier.navBarBottomPadding() = padding(bottom = 70.dp).padding( + bottom = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() +)