From 2d46cfa1393f968c7b549c364e8bbcc54024e9fd Mon Sep 17 00:00:00 2001 From: ahmbd Date: Wed, 20 Aug 2025 12:06:43 +0300 Subject: [PATCH 1/3] feat: Add Background Gradient to Screens --- .../feature/account/AccountScreen.kt | 108 ++++++------ .../feature/account/rating/MyRatingScreen.kt | 91 ++++++----- .../authentication/login/LoginScreen.kt | 7 + .../feature/category/main/CategoriesScreen.kt | 45 +++-- .../category/movie/MovieCategoryScreen.kt | 67 ++++---- .../category/tvshow/TvShowCategoryScreen.kt | 56 ++++--- .../details/actor/ActorDetailsScreen.kt | 6 + .../actor/info/gallery/ActorsGalleryScreen.kt | 44 +++-- .../topmoviespicks/TopMoviesPicksScreen.kt | 43 +++-- .../toptvshowspicks/TopTvShowsPicksScreen.kt | 29 +++- .../details/movie/MovieDetailsScreen.kt | 6 + .../tvshow/episode/EpisodeDetailScreen.kt | 7 + .../details/tvshow/info/TvShowDetailScreen.kt | 6 + .../presentation/feature/home/HomeScreen.kt | 29 +--- .../ContinueWatchingScreen.kt | 86 ++++++---- .../feature/home/toprated/TopRatedScreen.kt | 154 ++++++++++-------- .../feature/list/savedlist/ListScreen.kt | 86 ++++++---- .../feature/list/viewitems/ViewItemsScreen.kt | 134 ++++++++------- .../feature/reviews/ReviewsScreen.kt | 33 ++-- .../feature/search/SearchScreen.kt | 11 +- .../presentation/shared/BackgroundGradient.kt | 44 +++++ 21 files changed, 664 insertions(+), 428 deletions(-) create mode 100644 presentation/src/main/java/com/london/presentation/shared/BackgroundGradient.kt 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 0452ac7b0..62172e728 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 @@ -1,14 +1,18 @@ package com.london.presentation.feature.account +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.london.designsystem.component.TopBar @@ -19,6 +23,7 @@ import com.london.presentation.feature.account.bottomsheet.LanguageBottomSheet import com.london.presentation.feature.account.bottomsheet.LogoutBottomSheet import com.london.presentation.feature.account.components.LoggedInContent import com.london.presentation.feature.account.components.NotLoggedInContent +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.utils.Listen import com.london.presentation.utils.navBarBottomPadding @@ -61,61 +66,70 @@ private fun Content( uiState: AccountUiState, accountContract: AccountContract, ) { - Column(Modifier.navBarBottomPadding()) { - TopBar( - title = stringResource(R.string.my_account), - modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp) + + Box( + modifier = Modifier.fillMaxSize() + ){ + BackgroundGradient( + modifier = Modifier.align(Alignment.TopStart).zIndex(1f) ) - if (uiState.isUserLoggedIn) { - LoggedInContent( - uiState = uiState, - accountContract = accountContract - ) - } else { - NotLoggedInContent( - onLoginClick = accountContract::onLoginClick + Column(Modifier.navBarBottomPadding()) { + TopBar( + title = stringResource(R.string.my_account), + modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp) ) - } - } - when (uiState.activeBottomSheet) { - ActiveBottomSheet.Logout -> { - LogoutBottomSheet( - onBottomSheetDismiss = accountContract::onBottomSheetDismiss, - onLogoutConfirmed = accountContract::onLogoutConfirmed, - isLoading = uiState.isLogoutLoading - ) + if (uiState.isUserLoggedIn) { + LoggedInContent( + uiState = uiState, + accountContract = accountContract + ) + } else { + NotLoggedInContent( + onLoginClick = accountContract::onLoginClick + ) + } } - ActiveBottomSheet.ContentRestriction -> { - ContentRestrictionBottomSheet( - currentLevel = uiState.currentContentRestriction, - onSaveClick = accountContract::onContentRestrictionSave, - onDismiss = accountContract::onBottomSheetDismiss - ) - } + when (uiState.activeBottomSheet) { + ActiveBottomSheet.Logout -> { + LogoutBottomSheet( + onBottomSheetDismiss = accountContract::onBottomSheetDismiss, + onLogoutConfirmed = accountContract::onLogoutConfirmed, + isLoading = uiState.isLogoutLoading + ) + } - ActiveBottomSheet.Appearance -> { - AppearanceBottomSheet( - appTheme = uiState.appTheme, - onBottomSheetDismiss = accountContract::onBottomSheetDismiss, - onDarkModeSelected = accountContract::onDarkModeSelected, - onLightModeSelected = accountContract::onLightModeSelected, - onAppearanceModeSave = accountContract::onAppearanceModeSave, - ) - } + ActiveBottomSheet.ContentRestriction -> { + ContentRestrictionBottomSheet( + currentLevel = uiState.currentContentRestriction, + onSaveClick = accountContract::onContentRestrictionSave, + onDismiss = accountContract::onBottomSheetDismiss + ) + } - ActiveBottomSheet.Language -> { - LanguageBottomSheet( - appLanguage = uiState.appLanguage, - onBottomSheetDismiss = accountContract::onBottomSheetDismiss, - onEnglishSelected = accountContract::onEnglishSelected, - onArabicSelected = accountContract::onArabicSelected, - onLanguageSettingsSave = accountContract::onLanguageSettingsSave, - ) - } + ActiveBottomSheet.Appearance -> { + AppearanceBottomSheet( + appTheme = uiState.appTheme, + onBottomSheetDismiss = accountContract::onBottomSheetDismiss, + onDarkModeSelected = accountContract::onDarkModeSelected, + onLightModeSelected = accountContract::onLightModeSelected, + onAppearanceModeSave = accountContract::onAppearanceModeSave, + ) + } + + ActiveBottomSheet.Language -> { + LanguageBottomSheet( + appLanguage = uiState.appLanguage, + onBottomSheetDismiss = accountContract::onBottomSheetDismiss, + onEnglishSelected = accountContract::onEnglishSelected, + onArabicSelected = accountContract::onArabicSelected, + onLanguageSettingsSave = accountContract::onLanguageSettingsSave, + ) + } - else -> {} + else -> {} + } } } diff --git a/presentation/src/main/java/com/london/presentation/feature/account/rating/MyRatingScreen.kt b/presentation/src/main/java/com/london/presentation/feature/account/rating/MyRatingScreen.kt index 32bb0ccce..9fe9d0272 100644 --- a/presentation/src/main/java/com/london/presentation/feature/account/rating/MyRatingScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/account/rating/MyRatingScreen.kt @@ -1,6 +1,7 @@ package com.london.presentation.feature.account.rating import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize @@ -10,9 +11,11 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.london.designsystem.component.NovixChip @@ -21,6 +24,7 @@ import com.london.designsystem.theme.NovixTheme import com.london.designsystem.theme.ThemePreviews import com.london.domain.entity.shared.MediaType import com.london.presentation.R +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.EmptyGenreLayout import com.london.presentation.shared.SnackBarAnimation import com.london.presentation.shared.base.ErrorState @@ -76,54 +80,65 @@ private fun Content( onBack = contract::onBackClick, onRetry = contract::onRetryClick ) { - Column( + + Box( modifier = Modifier.fillMaxSize() ) { - TopBar( + BackgroundGradient( modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 12.dp), - title = stringResource(R.string.my_rating), - onBackClick = contract::onBackClick + .align(Alignment.TopStart) + .zIndex(1f) ) - RatingChipsRow( - selected = selectedCategory, - onSelect = contract::onRatingCategorySelected, - modifier = Modifier.padding(bottom = 12.dp) - ) + Column( + modifier = Modifier.fillMaxSize() + ) { + TopBar( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 12.dp), + title = stringResource(R.string.my_rating), + onBackClick = contract::onBackClick + ) - if (items.isEmpty()) { - EmptyGenreLayout( - message = stringResource(R.string.there_is_no_items), - modifier = Modifier.fillMaxSize() + RatingChipsRow( + selected = selectedCategory, + onSelect = contract::onRatingCategorySelected, + modifier = Modifier.padding(bottom = 12.dp) ) - } else { - MediaLazyVerticalGrid( - items = items, - imageUrl = { it.posterPath }, - name = { it.title }, - rate = { rated -> rated.rating.toLocalizedNumbers() }, - hasSaveIcon = false, - isItemSaved = { false }, - onSaveClick = {}, - onDeleteClick = { rated -> - when (rated.mediaType) { - MediaType.Movie -> contract.onDeleteMovieClick(rated.id) - MediaType.TvShow -> contract.onDeleteTVShowClick(rated.id) - } - }, - onItemClick = { rated -> - when (rated.mediaType) { - MediaType.Movie -> contract.onMovieClick(rated.id) - MediaType.TvShow -> contract.onTvShowClick(rated.id) + + if (items.isEmpty()) { + EmptyGenreLayout( + message = stringResource(R.string.there_is_no_items), + modifier = Modifier.fillMaxSize() + ) + } else { + MediaLazyVerticalGrid( + items = items, + imageUrl = { it.posterPath }, + name = { it.title }, + rate = { rated -> rated.rating.toLocalizedNumbers() }, + hasSaveIcon = false, + isItemSaved = { false }, + onSaveClick = {}, + onDeleteClick = { rated -> + when (rated.mediaType) { + MediaType.Movie -> contract.onDeleteMovieClick(rated.id) + MediaType.TvShow -> contract.onDeleteTVShowClick(rated.id) + } + }, + onItemClick = { rated -> + when (rated.mediaType) { + MediaType.Movie -> contract.onMovieClick(rated.id) + MediaType.TvShow -> contract.onTvShowClick(rated.id) + } } - } - ) + ) + } } - } - RatingSnackBar(state) + RatingSnackBar(state) + } } } diff --git a/presentation/src/main/java/com/london/presentation/feature/authentication/login/LoginScreen.kt b/presentation/src/main/java/com/london/presentation/feature/authentication/login/LoginScreen.kt index 8a8108ffb..bf73b42d9 100644 --- a/presentation/src/main/java/com/london/presentation/feature/authentication/login/LoginScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/authentication/login/LoginScreen.kt @@ -30,6 +30,7 @@ import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.london.designsystem.component.Icon @@ -39,6 +40,7 @@ import com.london.designsystem.component.TopBar import com.london.designsystem.component.button.PrimaryButton import com.london.designsystem.theme.NovixTheme import com.london.presentation.R +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.SnackBarAnimation import com.london.presentation.shared.base.ErrorState import com.london.presentation.utils.Listen @@ -85,6 +87,11 @@ private fun Content( .background(NovixTheme.colors.surface) .padding(WindowInsets.navigationBars.asPaddingValues()), ) { + + BackgroundGradient( + modifier = Modifier.align(Alignment.TopStart).zIndex(1f) + ) + Image( painter = painterResource(dsR.drawable.polygon1), contentDescription = stringResource(R.string.app_icon), 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 028d793d1..172116865 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 @@ -6,6 +6,7 @@ import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.togetherWith import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize @@ -19,9 +20,11 @@ import androidx.compose.foundation.lazy.items import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.london.designsystem.component.NovixChip @@ -29,6 +32,7 @@ import com.london.designsystem.component.TopBar import com.london.designsystem.theme.ThemePreviews import com.london.designsystem.utils.string import com.london.presentation.R +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.CategoriesItem import com.london.presentation.shared.MediaCategory import com.london.presentation.shared.genre.MovieGenreUi @@ -64,23 +68,32 @@ private fun Content( state: CategoriesUiState, contract: CategoriesContract, ) { - Column(Modifier.navBarBottomPadding()) { - TopBar( - title = stringResource(R.string.categories), - modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp), - ) - CategoriesSelection( - onClick = contract::onCategoryClick, - selectedCategory = state.selectedCategory, - modifier = Modifier.padding(top = 12.dp, bottom = 8.dp), - ) - GenresGrid( - state = state, - contract = contract, - modifier = Modifier - .fillMaxSize() - .padding(horizontal = 16.dp), + + Box( + modifier = Modifier.fillMaxSize() + ){ + BackgroundGradient( + modifier = Modifier.align(Alignment.TopStart).zIndex(1f) ) + + Column(Modifier.navBarBottomPadding()) { + TopBar( + title = stringResource(R.string.categories), + modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp), + ) + CategoriesSelection( + onClick = contract::onCategoryClick, + selectedCategory = state.selectedCategory, + modifier = Modifier.padding(top = 12.dp, bottom = 8.dp), + ) + GenresGrid( + state = state, + contract = contract, + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 16.dp), + ) + } } } diff --git a/presentation/src/main/java/com/london/presentation/feature/category/movie/MovieCategoryScreen.kt b/presentation/src/main/java/com/london/presentation/feature/category/movie/MovieCategoryScreen.kt index 176502033..b8830f1a0 100644 --- a/presentation/src/main/java/com/london/presentation/feature/category/movie/MovieCategoryScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/category/movie/MovieCategoryScreen.kt @@ -1,5 +1,6 @@ package com.london.presentation.feature.category.movie +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -7,9 +8,11 @@ import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.paging.LoadState @@ -17,6 +20,7 @@ import androidx.paging.compose.collectAsLazyPagingItems import com.london.designsystem.component.TopBar import com.london.designsystem.theme.ThemePreviews import com.london.presentation.R +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.MediaLazyPagingGrid import com.london.presentation.shared.bookmarkSheet.BookmarkBottomSheet import com.london.presentation.shared.buildscreen.BuildScreen @@ -63,39 +67,46 @@ private fun Content( emptyLayoutImage = R.drawable.empty ) { - Column( - modifier = Modifier - .fillMaxSize() - .padding(top = 12.dp) - ) { - TopBar( - title = stringResource( - state.genre.stringResId - ), - onBackClick = contract::onBack, - modifier = Modifier.padding(start = 16.dp, end = 16.dp, bottom = 12.dp) + Box( + modifier = Modifier.fillMaxSize() + ){ + BackgroundGradient( + modifier = Modifier.align(Alignment.TopStart).zIndex(1f) ) - MediaLazyPagingGrid( - pagingFlow = moviesLazyList, - onItemClick = { contract.onMovieClick(it.id) }, - getImageUrl = { it.posterUrl }, - getTitle = { "${it.name} movie img" }, + Column( modifier = Modifier - .weight(1f) - .fillMaxWidth() - .padding(horizontal = 16.dp), - onSaveClick = { contract.onManageBookmarkClicked(it.id) }, - isItemSaved = { false }, - hasSaveIcon = true - ) + .fillMaxSize() + .padding(top = 12.dp) + ) { + TopBar( + title = stringResource( + state.genre.stringResId + ), + onBackClick = contract::onBack, + modifier = Modifier.padding(start = 16.dp, end = 16.dp, bottom = 12.dp) + ) - BookmarkBottomSheet( - onSheetDismiss = contract::onBookmarkSheetDismiss, - isSheetVisible = state.isBookmarkSheetVisible, - bookmarkedMovieId = state.bookmarkedMovieId - ) + MediaLazyPagingGrid( + pagingFlow = moviesLazyList, + onItemClick = { contract.onMovieClick(it.id) }, + getImageUrl = { it.posterUrl }, + getTitle = { "${it.name} movie img" }, + modifier = Modifier + .weight(1f) + .fillMaxWidth() + .padding(horizontal = 16.dp), + onSaveClick = { contract.onManageBookmarkClicked(it.id) }, + isItemSaved = { false }, + hasSaveIcon = true + ) + BookmarkBottomSheet( + onSheetDismiss = contract::onBookmarkSheetDismiss, + isSheetVisible = state.isBookmarkSheetVisible, + bookmarkedMovieId = state.bookmarkedMovieId + ) + } } } } diff --git a/presentation/src/main/java/com/london/presentation/feature/category/tvshow/TvShowCategoryScreen.kt b/presentation/src/main/java/com/london/presentation/feature/category/tvshow/TvShowCategoryScreen.kt index f69b84ee6..be9e9a9ef 100644 --- a/presentation/src/main/java/com/london/presentation/feature/category/tvshow/TvShowCategoryScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/category/tvshow/TvShowCategoryScreen.kt @@ -1,5 +1,6 @@ package com.london.presentation.feature.category.tvshow +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -7,9 +8,11 @@ import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.paging.LoadState @@ -17,6 +20,7 @@ import androidx.paging.compose.collectAsLazyPagingItems import com.london.designsystem.component.TopBar import com.london.designsystem.theme.ThemePreviews import com.london.presentation.R +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.MediaLazyPagingGrid import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.utils.Listen @@ -62,31 +66,39 @@ private fun Content( emptyLayoutImage = R.drawable.empty ) { - Column( - modifier = Modifier - .fillMaxSize() - .padding(top = 12.dp) - ) { - TopBar( - title = stringResource( - state.genre.stringResId - ), - onBackClick = contract::onBack, - modifier = Modifier.padding(start = 16.dp, end = 16.dp, bottom = 12.dp) + Box( + modifier = Modifier.fillMaxSize() + ){ + BackgroundGradient( + modifier = Modifier.align(Alignment.TopStart).zIndex(1f) ) - MediaLazyPagingGrid( - pagingFlow = tvShowLazyList, - onItemClick = { contract.onTvShowClick(it.id) }, - getImageUrl = { it.posterPicture }, - getTitle = { "${it.name} tv show img" }, + Column( modifier = Modifier - .weight(1f) - .fillMaxWidth() - .padding(horizontal = 16.dp), - onSaveClick = { /* TODO: Implement save functionality */ }, - isItemSaved = { false }, - ) + .fillMaxSize() + .padding(top = 12.dp) + ) { + TopBar( + title = stringResource( + state.genre.stringResId + ), + onBackClick = contract::onBack, + modifier = Modifier.padding(start = 16.dp, end = 16.dp, bottom = 12.dp) + ) + + MediaLazyPagingGrid( + pagingFlow = tvShowLazyList, + onItemClick = { contract.onTvShowClick(it.id) }, + getImageUrl = { it.posterPicture }, + getTitle = { "${it.name} tv show img" }, + modifier = Modifier + .weight(1f) + .fillMaxWidth() + .padding(horizontal = 16.dp), + onSaveClick = { /* TODO: Implement save functionality */ }, + isItemSaved = { false }, + ) + } } } } diff --git a/presentation/src/main/java/com/london/presentation/feature/details/actor/ActorDetailsScreen.kt b/presentation/src/main/java/com/london/presentation/feature/details/actor/ActorDetailsScreen.kt index df09e6add..774310ab4 100644 --- a/presentation/src/main/java/com/london/presentation/feature/details/actor/ActorDetailsScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/details/actor/ActorDetailsScreen.kt @@ -52,6 +52,7 @@ import com.london.designsystem.component.button.ErrorImage import com.london.designsystem.theme.NovixTheme import com.london.domain.entity.actor.ActorMediaItems import com.london.presentation.R +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.ConditionalText import com.london.presentation.shared.CustomBackDropImagePager import com.london.presentation.shared.HomeCard @@ -124,6 +125,11 @@ private fun Content( .fillMaxSize() .background(NovixTheme.colors.surface) ) { + + BackgroundGradient( + modifier = Modifier.align(Alignment.TopStart).zIndex(1f) + ) + EmptyScreen(uiState) LazyColumn( diff --git a/presentation/src/main/java/com/london/presentation/feature/details/actor/info/gallery/ActorsGalleryScreen.kt b/presentation/src/main/java/com/london/presentation/feature/details/actor/info/gallery/ActorsGalleryScreen.kt index 50673f17c..9b0dc1742 100644 --- a/presentation/src/main/java/com/london/presentation/feature/details/actor/info/gallery/ActorsGalleryScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/details/actor/info/gallery/ActorsGalleryScreen.kt @@ -22,6 +22,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.london.designsystem.component.CircularLoading @@ -29,6 +30,7 @@ import com.london.designsystem.component.TopBar import com.london.designsystem.component.button.ErrorImage import com.london.designsystem.theme.NovixTheme import com.london.presentation.R +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.ImageView import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.utils.Listen @@ -61,24 +63,34 @@ private fun Content( uiState: ActorsGalleryUiState, actorsGalleryContract: ActorsGalleryContract ) { - Column( - modifier = Modifier - .fillMaxSize() - .background(NovixTheme.colors.surface) - .navigationBarsPadding() - .padding(horizontal = 16.dp, vertical = 12.dp), - ) { - TopBar( - modifier = Modifier.padding(bottom = 16.dp), - title = stringResource(R.string.gallery), - onBackClick = actorsGalleryContract::onBackClick + + Box( + modifier = Modifier.fillMaxSize() + ){ + + BackgroundGradient( + modifier = Modifier.fillMaxSize().align(Alignment.TopStart).zIndex(1f) ) - Box(modifier = Modifier.weight(1f)) { - if (uiState.isLoading) { - CircularLoading(modifier = Modifier.align(Alignment.Center)) - } else { - GalleryContent(uiState = uiState) + Column( + modifier = Modifier + .fillMaxSize() + .background(NovixTheme.colors.surface) + .navigationBarsPadding() + .padding(horizontal = 16.dp, vertical = 12.dp), + ) { + TopBar( + modifier = Modifier.padding(bottom = 16.dp), + title = stringResource(R.string.gallery), + onBackClick = actorsGalleryContract::onBackClick + ) + + Box(modifier = Modifier.weight(1f)) { + if (uiState.isLoading) { + CircularLoading(modifier = Modifier.align(Alignment.Center)) + } else { + GalleryContent(uiState = uiState) + } } } } diff --git a/presentation/src/main/java/com/london/presentation/feature/details/actor/info/topmoviespicks/TopMoviesPicksScreen.kt b/presentation/src/main/java/com/london/presentation/feature/details/actor/info/topmoviespicks/TopMoviesPicksScreen.kt index b636ce94a..4df70e698 100644 --- a/presentation/src/main/java/com/london/presentation/feature/details/actor/info/topmoviespicks/TopMoviesPicksScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/details/actor/info/topmoviespicks/TopMoviesPicksScreen.kt @@ -1,12 +1,18 @@ package com.london.presentation.feature.details.actor.info.topmoviespicks +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.london.presentation.R +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.MediaLazyGrid import com.london.presentation.shared.base.ErrorState import com.london.presentation.shared.bookmarkSheet.BookmarkBottomSheet @@ -47,20 +53,29 @@ private fun Content( isError = state.errorState is ErrorState.NoInternet, onRetry = contract::onRetryClick, ) { - MediaLazyGrid( - title = stringResource(R.string.top_movies_picks), - items = state.movieDetails.mediaItems, - onBack = contract::onBackClick, - getImageUrl = { it.posterUrl }, - onItemClick = { contract.onMovieClick(it.id) }, - onSavedClick = { contract.onManageBookmarkClicked(it.id) }, - hasSaveIcon = true - ) - BookmarkBottomSheet( - onSheetDismiss = contract::onBookmarkSheetDismiss, - isSheetVisible = state.isBookmarkSheetVisible, - bookmarkedMovieId = state.bookmarkedMovieId - ) + Box( + modifier = Modifier.fillMaxSize() + ){ + + BackgroundGradient( + modifier = Modifier.align(Alignment.TopStart).zIndex(1f) + ) + MediaLazyGrid( + title = stringResource(R.string.top_movies_picks), + items = state.movieDetails.mediaItems, + onBack = contract::onBackClick, + getImageUrl = { it.posterUrl }, + onItemClick = { contract.onMovieClick(it.id) }, + onSavedClick = { contract.onManageBookmarkClicked(it.id) }, + hasSaveIcon = true + ) + + BookmarkBottomSheet( + onSheetDismiss = contract::onBookmarkSheetDismiss, + isSheetVisible = state.isBookmarkSheetVisible, + bookmarkedMovieId = state.bookmarkedMovieId + ) + } } } diff --git a/presentation/src/main/java/com/london/presentation/feature/details/actor/info/toptvshowspicks/TopTvShowsPicksScreen.kt b/presentation/src/main/java/com/london/presentation/feature/details/actor/info/toptvshowspicks/TopTvShowsPicksScreen.kt index bfab114a8..f9fe372a5 100644 --- a/presentation/src/main/java/com/london/presentation/feature/details/actor/info/toptvshowspicks/TopTvShowsPicksScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/details/actor/info/toptvshowspicks/TopTvShowsPicksScreen.kt @@ -1,12 +1,18 @@ package com.london.presentation.feature.details.actor.info.toptvshowspicks +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.london.presentation.R +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.MediaLazyGrid import com.london.presentation.shared.base.ErrorState import com.london.presentation.shared.buildscreen.BuildScreen @@ -45,12 +51,21 @@ private fun Content( isError = state.errorState is ErrorState.NoInternet, onRetry = contract::onRetryClick ) { - MediaLazyGrid( - title = stringResource(R.string.top_tv_shows_picks), - items = state.tvShowDetails.mediaItems, - onBack = contract::onBackClick, - getImageUrl = { it.posterUrl }, - onItemClick = { contract.onTvShowClick(it.id) } - ) + + Box( + modifier = Modifier.fillMaxSize() + ){ + BackgroundGradient( + modifier = Modifier.align(Alignment.TopStart).zIndex(1f) + ) + + MediaLazyGrid( + title = stringResource(R.string.top_tv_shows_picks), + items = state.tvShowDetails.mediaItems, + onBack = contract::onBackClick, + getImageUrl = { it.posterUrl }, + onItemClick = { contract.onTvShowClick(it.id) } + ) + } } } diff --git a/presentation/src/main/java/com/london/presentation/feature/details/movie/MovieDetailsScreen.kt b/presentation/src/main/java/com/london/presentation/feature/details/movie/MovieDetailsScreen.kt index dea618826..74eee1b64 100644 --- a/presentation/src/main/java/com/london/presentation/feature/details/movie/MovieDetailsScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/details/movie/MovieDetailsScreen.kt @@ -48,6 +48,7 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.london.designsystem.R @@ -63,6 +64,7 @@ import com.london.presentation.R.string.more_like_this import com.london.presentation.R.string.overview import com.london.presentation.R.string.view_reviews import com.london.presentation.shared.ActorItem +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.ConditionalText import com.london.presentation.shared.CustomBackDropImagePager import com.london.presentation.shared.FooterSection @@ -158,6 +160,10 @@ private fun Content( .background(NovixTheme.colors.surface) ) { + BackgroundGradient( + modifier = Modifier.fillMaxSize().align(Alignment.TopStart).zIndex(2f) + ) + TopBar( onBackClick = contract::onBackClick, modifier = Modifier.detailsTopBar(backgroundAlpha), diff --git a/presentation/src/main/java/com/london/presentation/feature/details/tvshow/episode/EpisodeDetailScreen.kt b/presentation/src/main/java/com/london/presentation/feature/details/tvshow/episode/EpisodeDetailScreen.kt index b4ec800d7..2703f0100 100644 --- a/presentation/src/main/java/com/london/presentation/feature/details/tvshow/episode/EpisodeDetailScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/details/tvshow/episode/EpisodeDetailScreen.kt @@ -35,6 +35,7 @@ import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.london.designsystem.component.GuestUserLoginBottomSheet @@ -44,6 +45,7 @@ import com.london.designsystem.component.TopBar import com.london.designsystem.theme.NovixTheme import com.london.presentation.R import com.london.presentation.shared.ActorItem +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.ConditionalText import com.london.presentation.shared.CustomBackDropImagePager import com.london.presentation.shared.FooterSection @@ -120,6 +122,11 @@ private fun Content( .fillMaxSize() .background(NovixTheme.colors.surface) ) { + + BackgroundGradient( + modifier = Modifier.align(Alignment.TopStart).zIndex(2f) + ) + TopBar( onBackClick = contract::onBackClick, modifier = Modifier.detailsTopBar(backgroundAlpha), diff --git a/presentation/src/main/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailScreen.kt b/presentation/src/main/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailScreen.kt index 85e266db0..42aa253e4 100644 --- a/presentation/src/main/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailScreen.kt @@ -44,6 +44,7 @@ import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.london.designsystem.R @@ -62,6 +63,7 @@ import com.london.domain.entity.shared.MediaType import com.london.domain.entity.tvshow.cast.TvShowCastMember import com.london.domain.entity.tvshow.episode.Episodes import com.london.presentation.shared.ActorItem +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.ConditionalText import com.london.presentation.shared.CustomBackDropImagePager import com.london.presentation.shared.FooterSection @@ -167,6 +169,10 @@ private fun Content( option1Icon = R.drawable.icon_remove, ) + BackgroundGradient( + modifier = Modifier.fillMaxSize().align(Alignment.TopStart).zIndex(1f) + ) + LazyColumn( state = lazyListState, modifier = Modifier.fillMaxSize(), 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 314702c47..10bdfbc71 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 @@ -12,7 +12,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.requiredWidth -import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.grid.GridCells @@ -30,13 +29,11 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalWindowInfo import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.paging.compose.LazyPagingItems @@ -56,6 +53,7 @@ import com.london.presentation.feature.home.trending.TrendingSection import com.london.presentation.feature.home.upcoming.UpcomingMovieItem import com.london.presentation.feature.home.upcoming.UpcomingSectionTitle import com.london.presentation.feature.home.upcoming.UpcomingStickyHeader +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.CarousalShimmerEffect import com.london.presentation.shared.bookmarkSheet.BookmarkBottomSheet import com.london.presentation.shared.buildscreen.NetworkErrorScreen @@ -186,8 +184,7 @@ private fun HomeScreenLayout( modifier = Modifier.fillMaxSize().navBarBottomPadding() ) { BackgroundGradient( - screenWidth = screenWidth, - modifier = Modifier.align(Alignment.TopStart) + modifier = Modifier.align(Alignment.TopStart).zIndex(1f) ) Column(modifier = Modifier.fillMaxSize()) { @@ -222,26 +219,6 @@ private fun HomeScreenLayout( ) } -@Composable -private fun BackgroundGradient( - screenWidth: Dp, - modifier: Modifier = Modifier -) { - Box( - modifier = modifier - .size(400.dp) - .background( - Brush.linearGradient( - colors = listOf( - NovixTheme.colors.primary.copy(alpha = 0.09f), - Color.Transparent - ), - start = Offset(0f, 0f), - end = Offset(screenWidth.value, 400f) - ) - ) - ) -} @Composable private fun HomeTopBar(modifier: Modifier = Modifier) { diff --git a/presentation/src/main/java/com/london/presentation/feature/home/continuewatching/ContinueWatchingScreen.kt b/presentation/src/main/java/com/london/presentation/feature/home/continuewatching/ContinueWatchingScreen.kt index f2a5b8bba..1e1387713 100644 --- a/presentation/src/main/java/com/london/presentation/feature/home/continuewatching/ContinueWatchingScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/home/continuewatching/ContinueWatchingScreen.kt @@ -1,18 +1,22 @@ package com.london.presentation.feature.home.continuewatching import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.london.designsystem.theme.NovixTheme import com.london.domain.entity.movie.Movie import com.london.presentation.R +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.DefaultAppTopBar import com.london.presentation.shared.MediaCategory import com.london.presentation.shared.base.ErrorState @@ -66,44 +70,54 @@ private fun Content( contract: ContinueWatchingContract, screenTitle: String = stringResource(R.string.continue_watch) ) { - Column( - modifier = Modifier - .fillMaxSize() - .background(color = NovixTheme.colors.surface) - ) { - MediaLazyGridWithTabs( - items = getCombinedItems(state), - tabSelected = getSelectedTabIndex(state), - onTabSelected = contract::onMediaCategoryTabClick, - onMovieGenreClick = contract::onMovieGenreClick, - onTvShowGenreClick = contract::onTvShowGenreClick, - config = MediaGridConfig( - showSaveIcon = state.selectedMediaCategory == MediaCategory.Movies, - isDarkMode = NovixTheme.isThemeDark, - selectedMovieGenre = state.selectedMovieGenre, - selectedTvShowGenre = state.selectedTvShowGenre, - isMovieSelected = MediaCategory.Movies == state.selectedMediaCategory, - isTvShowSelected = MediaCategory.TvShows == state.selectedMediaCategory, - onNavigateToMovie = contract::onNavigateToMovieClick, - onNavigateToTvShow = contract::onNavigateToTvShowClick, - onSaveClick = { if (it is Movie) contract.onManageBookmarkClicked(it.id) }, - isItemSaved = { false }, - rate = null - ), - topBar = { - DefaultAppTopBar( - title = screenTitle, - onBack = contract::onBackClick - ) - }, - isLoading = state.isLoading - ) - BookmarkBottomSheet( - onSheetDismiss = contract::onBookmarkSheetDismiss, - isSheetVisible = state.isBookmarkSheetVisible, - bookmarkedMovieId = state.bookmarkedMovieId + Box( + modifier = Modifier.fillMaxSize() + ){ + + BackgroundGradient( + modifier = Modifier.align(Alignment.TopStart).zIndex(1f) ) + + Column( + modifier = Modifier + .fillMaxSize() + .background(color = NovixTheme.colors.surface) + ) { + MediaLazyGridWithTabs( + items = getCombinedItems(state), + tabSelected = getSelectedTabIndex(state), + onTabSelected = contract::onMediaCategoryTabClick, + onMovieGenreClick = contract::onMovieGenreClick, + onTvShowGenreClick = contract::onTvShowGenreClick, + config = MediaGridConfig( + showSaveIcon = state.selectedMediaCategory == MediaCategory.Movies, + isDarkMode = NovixTheme.isThemeDark, + selectedMovieGenre = state.selectedMovieGenre, + selectedTvShowGenre = state.selectedTvShowGenre, + isMovieSelected = MediaCategory.Movies == state.selectedMediaCategory, + isTvShowSelected = MediaCategory.TvShows == state.selectedMediaCategory, + onNavigateToMovie = contract::onNavigateToMovieClick, + onNavigateToTvShow = contract::onNavigateToTvShowClick, + onSaveClick = { if (it is Movie) contract.onManageBookmarkClicked(it.id) }, + isItemSaved = { false }, + rate = null + ), + topBar = { + DefaultAppTopBar( + title = screenTitle, + onBack = contract::onBackClick + ) + }, + isLoading = state.isLoading + ) + + BookmarkBottomSheet( + onSheetDismiss = contract::onBookmarkSheetDismiss, + isSheetVisible = state.isBookmarkSheetVisible, + bookmarkedMovieId = state.bookmarkedMovieId + ) + } } } diff --git a/presentation/src/main/java/com/london/presentation/feature/home/toprated/TopRatedScreen.kt b/presentation/src/main/java/com/london/presentation/feature/home/toprated/TopRatedScreen.kt index 34bf3a92b..f522e02a3 100644 --- a/presentation/src/main/java/com/london/presentation/feature/home/toprated/TopRatedScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/home/toprated/TopRatedScreen.kt @@ -3,6 +3,7 @@ package com.london.presentation.feature.home.toprated import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize @@ -16,12 +17,14 @@ import androidx.compose.foundation.lazy.items import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalWindowInfo import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.paging.LoadState @@ -31,6 +34,7 @@ import com.london.designsystem.component.TabLayout import com.london.designsystem.component.TopBar import com.london.designsystem.theme.NovixTheme import com.london.designsystem.utils.string +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.HomeCard import com.london.presentation.shared.MediaCategory import com.london.presentation.shared.bookmarkSheet.BookmarkBottomSheet @@ -82,92 +86,104 @@ private fun Content( ) { val screenWidth = with(LocalDensity.current) { LocalWindowInfo.current.containerSize.width.toDp() } - Column( - modifier = Modifier - .fillMaxSize() - .background(color = NovixTheme.colors.surface) + Box( + modifier = Modifier.fillMaxSize() ) { - TopBar( + + BackgroundGradient( modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp) - .padding(top = 12.dp), - title = com.london.presentation.R.string.top_rated.string, - onBackClick = contract::onBackClicked + .align(Alignment.TopStart) + .zIndex(1f) ) - TabLayout( - tabs = listOf( - MediaCategory.Movies, - MediaCategory.TvShows - ), - selectedTab = state.selectedMediaCategory, - onTabSelected = contract::onMediaCategoryTabSelected, - modifier = Modifier.background(NovixTheme.colors.surface) - ) - if (state.isMovieSelected) - MovieGenreRow( - onGenreClick = contract::movieGenre, - state = state, - screenWidth = screenWidth + Column( + modifier = Modifier + .fillMaxSize() + .background(color = NovixTheme.colors.surface) + + ) { + TopBar( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp) + .padding(top = 12.dp), + title = com.london.presentation.R.string.top_rated.string, + onBackClick = contract::onBackClicked ) - else - TvShowRow( - onGenreClick = contract::tvShowGenre, - state = state, - screenWidth = screenWidth + + TabLayout( + tabs = listOf( + MediaCategory.Movies, + MediaCategory.TvShows + ), + selectedTab = state.selectedMediaCategory, + onTabSelected = contract::onMediaCategoryTabSelected, + modifier = Modifier.background(NovixTheme.colors.surface) ) + if (state.isMovieSelected) + MovieGenreRow( + onGenreClick = contract::movieGenre, + state = state, + screenWidth = screenWidth + ) + else + TvShowRow( + onGenreClick = contract::tvShowGenre, + state = state, + screenWidth = screenWidth + ) - val moviesPagingItems = state.movies.collectAsLazyPagingItems() - val tvSeriesPagingItems = state.tvSeries.collectAsLazyPagingItems() - - LazyVerticalGrid( - columns = GridCells.Fixed(gridColumns()), - contentPadding = PaddingValues( - top = 12.dp, bottom = 16.dp, start = 16.dp, end = 16.dp - ), - horizontalArrangement = Arrangement.spacedBy(12.dp), - verticalArrangement = Arrangement.spacedBy(12.dp), - modifier = Modifier.background(NovixTheme.colors.surface) - ) { + val moviesPagingItems = state.movies.collectAsLazyPagingItems() + val tvSeriesPagingItems = state.tvSeries.collectAsLazyPagingItems() + + LazyVerticalGrid( + columns = GridCells.Fixed(gridColumns()), + contentPadding = PaddingValues( + top = 12.dp, bottom = 16.dp, start = 16.dp, end = 16.dp + ), + horizontalArrangement = Arrangement.spacedBy(12.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), + modifier = Modifier.background(NovixTheme.colors.surface) + ) { - if (state.isMovieSelected) { - items(moviesPagingItems.itemCount) { index -> - val movie = moviesPagingItems[index] - movie?.let { movieItem -> + if (state.isMovieSelected) { + items(moviesPagingItems.itemCount) { index -> + val movie = moviesPagingItems[index] + movie?.let { movieItem -> + HomeCard( + imageUrl = movieItem.posterUrl, + isSaved = false, + hasSaveIcon = true, + onSaveClick = { contract.onManageBookmarkClicked(movieItem.id) }, + modifier = Modifier.clickable { + contract.onMovieClick(movieItem.id) + } + ) + } + } + } + items(tvSeriesPagingItems.itemCount) { index -> + val tvSeries = tvSeriesPagingItems[index] + tvSeries?.let { seriesItem -> HomeCard( - imageUrl = movieItem.posterUrl, + imageUrl = seriesItem.posterUrl, + hasSaveIcon = false, isSaved = false, - hasSaveIcon = true, - onSaveClick = { contract.onManageBookmarkClicked(movieItem.id) }, - modifier = Modifier.clickable { - contract.onMovieClick(movieItem.id) - } + onSaveClick = {}, + modifier = Modifier.clickable { contract.onTvShowClick(seriesItem.id) } ) } } } - items(tvSeriesPagingItems.itemCount) { index -> - val tvSeries = tvSeriesPagingItems[index] - tvSeries?.let { seriesItem -> - HomeCard( - imageUrl = seriesItem.posterUrl, - hasSaveIcon = false, - isSaved = false, - onSaveClick = {}, - modifier = Modifier.clickable { contract.onTvShowClick(seriesItem.id) } - ) - } - } - } - BookmarkBottomSheet( - onSheetDismiss = contract::onBookmarkSheetDismiss, - isSheetVisible = state.isBookmarkSheetVisible, - bookmarkedMovieId = state.bookmarkedMovieId - ) + BookmarkBottomSheet( + onSheetDismiss = contract::onBookmarkSheetDismiss, + isSheetVisible = state.isBookmarkSheetVisible, + bookmarkedMovieId = state.bookmarkedMovieId + ) + } } } 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 e659ead0b..50982f51b 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 @@ -32,6 +32,7 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.paging.compose.collectAsLazyPagingItems @@ -50,6 +51,7 @@ import com.london.designsystem.utils.string import com.london.domain.entity.movie.MovieList import com.london.presentation.R import com.london.presentation.feature.list.bottomsheets.AddListBottomSheet +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.base.ErrorState import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.utils.Listen @@ -94,50 +96,62 @@ private fun Content( emptyContent = { EmptyList(contract = contract, addListSheetState = state.addListSheetState) }, handlePagingLoadingAutomatically = true ) { - ScreenScaffold( - titleRes = R.string.saved_list_title, - onFabClick = contract::onFabClick + + Box( + modifier = Modifier.fillMaxSize() ) { - LazyColumn( - modifier = Modifier.fillMaxSize(), - verticalArrangement = Arrangement.spacedBy(8.dp), - contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp) + + BackgroundGradient( + modifier = Modifier + .align(Alignment.TopStart) + .zIndex(1f) + ) + + ScreenScaffold( + titleRes = R.string.saved_list_title, + onFabClick = contract::onFabClick ) { - items(pagingItems.itemCount) { index -> - val item = pagingItems[index] - item?.let { - SavedListItemRow( - itemUi = item, - onCountClick = contract::onListClick - ) + LazyColumn( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.spacedBy(8.dp), + contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp) + ) { + items(pagingItems.itemCount) { index -> + val item = pagingItems[index] + item?.let { + SavedListItemRow( + itemUi = item, + onCountClick = contract::onListClick + ) + } } } - } - AddListBottomSheet( - addListInteractions = contract, - addListSheetState = state.addListSheetState - ) - } + AddListBottomSheet( + addListInteractions = contract, + addListSheetState = state.addListSheetState + ) + } - val snackBarController = LocalSnackbarController.current + val snackBarController = LocalSnackbarController.current - if (state.error != null) { - snackBarController.showMessage( - message = R.string.list_added_fail.string, - snackBarType = SnackBarType.Error, - onComplete = contract::resetSnackBarErrorState, - icon = null, - ) - } + if (state.error != null) { + snackBarController.showMessage( + message = R.string.list_added_fail.string, + snackBarType = SnackBarType.Error, + onComplete = contract::resetSnackBarErrorState, + icon = null, + ) + } - if (state.isSnackBarSuccessVisible) { - snackBarController.showMessage( - message = R.string.list_added_success.string, - snackBarType = SnackBarType.Success, - onComplete = contract::resetSnackBarSuccessState, - icon = com.london.designsystem.R.drawable.ic_success, - ) + if (state.isSnackBarSuccessVisible) { + snackBarController.showMessage( + message = R.string.list_added_success.string, + snackBarType = SnackBarType.Success, + onComplete = contract::resetSnackBarSuccessState, + icon = com.london.designsystem.R.drawable.ic_success, + ) + } } } } 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 39d2adab1..c1b2becce 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 @@ -1,12 +1,16 @@ package com.london.presentation.feature.list.viewitems +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.paging.compose.collectAsLazyPagingItems @@ -18,6 +22,7 @@ import com.london.designsystem.theme.ThemePreviews import com.london.designsystem.utils.string import com.london.presentation.R import com.london.presentation.feature.list.bottomsheets.DeleteListBottomSheet +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.MediaLazyPagingGrid import com.london.presentation.shared.base.ErrorState import com.london.presentation.shared.buildscreen.BuildScreen @@ -52,76 +57,85 @@ private fun Content( contract: ViewListItemsContract, ) { val listItems = state.listItems.collectAsLazyPagingItems() - Column { - TopBar( - title = state.listTitle, - onBackClick = contract::onBack, - option2Icon = R.drawable.ic_delete, - onClickOption2 = contract::onDeleteClick, - option2IconTint = NovixTheme.colors.redAccent, - modifier = Modifier - .padding(horizontal = 16.dp, vertical = 12.dp) + + Box( + modifier = Modifier.fillMaxSize() + ){ + + BackgroundGradient( + modifier = Modifier.align(Alignment.TopStart).zIndex(1f) ) - BuildScreen( - onBack = null, - onRetry = listItems::refresh, - isLoading = state.isLoading, - isError = state.error == ErrorState.NoInternet, - emptyLayoutMessage = R.string.no_items_found, - emptyLayoutImage = R.drawable.img_no_result, - pagingFlow = listItems, - ) { - MediaLazyPagingGrid( - pagingFlow = listItems, - modifier = Modifier.padding(horizontal = 16.dp), - onItemClick = { contract.onMovieClick(it.id) }, - getImageUrl = { it.posterUrl }, - getTitle = { "${it.id} media img" }, - onSaveClick = { - contract.onRemoveMovieClick(it.id) - contract.onRetry() - }, - isItemSaved = { true }, - hasSaveIcon = true + Column { + TopBar( + title = state.listTitle, + onBackClick = contract::onBack, + option2Icon = R.drawable.ic_delete, + onClickOption2 = contract::onDeleteClick, + option2IconTint = NovixTheme.colors.redAccent, + modifier = Modifier + .padding(horizontal = 16.dp, vertical = 12.dp) ) + + BuildScreen( + onBack = null, + onRetry = listItems::refresh, + isLoading = state.isLoading, + isError = state.error == ErrorState.NoInternet, + emptyLayoutMessage = R.string.no_items_found, + emptyLayoutImage = R.drawable.img_no_result, + pagingFlow = listItems, + ) { + MediaLazyPagingGrid( + pagingFlow = listItems, + modifier = Modifier.padding(horizontal = 16.dp), + onItemClick = { contract.onMovieClick(it.id) }, + getImageUrl = { it.posterUrl }, + getTitle = { "${it.id} media img" }, + onSaveClick = { + contract.onRemoveMovieClick(it.id) + contract.onRetry() + }, + isItemSaved = { true }, + hasSaveIcon = true + ) + } } - } - DeleteListBottomSheet( - isSheetVisible = state.isDeleteBottomSheetVisible, - contract = contract, - ) + DeleteListBottomSheet( + isSheetVisible = state.isDeleteBottomSheetVisible, + contract = contract, + ) - val snackBarController = LocalSnackbarController.current + val snackBarController = LocalSnackbarController.current - if (state.isSnackBarErrorVisible) { - snackBarController.showMessage( - message = R.string.deletion_failed.string, - snackBarType = SnackBarType.Error, - onComplete = contract::resetSnackBarErrorState, - icon = null, - ) - } + if (state.isSnackBarErrorVisible) { + snackBarController.showMessage( + message = R.string.deletion_failed.string, + snackBarType = SnackBarType.Error, + onComplete = contract::resetSnackBarErrorState, + icon = null, + ) + } - if (state.isMovieSnackBarSuccessVisible) { - snackBarController.showMessage( - message = R.string.movie_removed_successfully.string, - snackBarType = SnackBarType.Success, - onComplete = contract::resetMovieSnackBarSuccessState, - icon = com.london.designsystem.R.drawable.ic_success, - ) - } + if (state.isMovieSnackBarSuccessVisible) { + snackBarController.showMessage( + message = R.string.movie_removed_successfully.string, + snackBarType = SnackBarType.Success, + onComplete = contract::resetMovieSnackBarSuccessState, + icon = com.london.designsystem.R.drawable.ic_success, + ) + } - if (state.isListSnackBarSuccess) { - snackBarController.showMessage( - message = R.string.list_removed_successfully.string, - snackBarType = SnackBarType.Success, - onComplete = contract::resetListSnackBarSuccessState, - icon = com.london.designsystem.R.drawable.ic_success, - ) + if (state.isListSnackBarSuccess) { + snackBarController.showMessage( + message = R.string.list_removed_successfully.string, + snackBarType = SnackBarType.Success, + onComplete = contract::resetListSnackBarSuccessState, + icon = com.london.designsystem.R.drawable.ic_success, + ) + } } - } @Composable diff --git a/presentation/src/main/java/com/london/presentation/feature/reviews/ReviewsScreen.kt b/presentation/src/main/java/com/london/presentation/feature/reviews/ReviewsScreen.kt index eebc8295b..e8f32cec7 100644 --- a/presentation/src/main/java/com/london/presentation/feature/reviews/ReviewsScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/reviews/ReviewsScreen.kt @@ -29,6 +29,7 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.paging.LoadState @@ -42,6 +43,7 @@ import com.london.designsystem.component.button.ErrorImage import com.london.designsystem.theme.NovixTheme import com.london.domain.entity.review.Review import com.london.presentation.R +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.ConditionalText import com.london.presentation.shared.ImageView import com.london.presentation.shared.RatingItem @@ -85,19 +87,28 @@ private fun Content( reviewsList: LazyPagingItems, reviewContract: ReviewContract ) { - Column( - modifier = Modifier - .fillMaxSize() - .background(NovixTheme.colors.surface) - ) { - ReviewsTopBar( - onBackClick = reviewContract::onBackClicked - ) - ReviewsContent( - reviewsList = reviewsList, - modifier = Modifier.weight(1f) + Box( + modifier = Modifier.fillMaxSize() + ){ + BackgroundGradient( + modifier = Modifier.align(Alignment.TopStart).zIndex(1f) ) + + Column( + modifier = Modifier + .fillMaxSize() + .background(NovixTheme.colors.surface) + ) { + ReviewsTopBar( + onBackClick = reviewContract::onBackClicked + ) + + ReviewsContent( + reviewsList = reviewsList, + modifier = Modifier.weight(1f) + ) + } } } 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 a4360aa68..e96ba5a40 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 @@ -36,6 +36,7 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.Lifecycle import androidx.lifecycle.compose.LocalLifecycleOwner @@ -59,8 +60,8 @@ import com.london.domain.entity.shared.MediaType import com.london.domain.entity.shared.MediaType.Companion.isMovie import com.london.presentation.R import com.london.presentation.shared.ActorsLayout +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.HomeCard -import com.london.presentation.shared.TriangleBlurredShape import com.london.presentation.shared.base.ErrorState import com.london.presentation.shared.bookmarkSheet.BookmarkBottomSheet import com.london.presentation.shared.buildscreen.BuildScreen @@ -148,7 +149,13 @@ private fun SearchMainContent( .navBarBottomPadding() .pointerInput(Unit) { detectTapGestures(onTap = { onClearFocus() }) } ) { - TriangleBlurredShape() + + BackgroundGradient( + modifier = Modifier + .align(Alignment.TopStart) + .zIndex(1f) + ) + Column( modifier = Modifier .fillMaxSize() diff --git a/presentation/src/main/java/com/london/presentation/shared/BackgroundGradient.kt b/presentation/src/main/java/com/london/presentation/shared/BackgroundGradient.kt new file mode 100644 index 000000000..d72b1f346 --- /dev/null +++ b/presentation/src/main/java/com/london/presentation/shared/BackgroundGradient.kt @@ -0,0 +1,44 @@ +package com.london.presentation.shared + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.unit.IntSize +import com.london.designsystem.theme.NovixTheme + +@Composable +fun BackgroundGradient( + modifier: Modifier = Modifier +) { + var boxSize by remember { mutableStateOf(IntSize.Zero) } + + Box( + modifier = modifier + .fillMaxSize() + .onGloballyPositioned { coordinates -> + boxSize = coordinates.size + } + .background( + brush = Brush.linearGradient( + colors = listOf( + NovixTheme.colors.primary.copy(alpha = 0.08f), + Color.Transparent, + Color.Transparent, + NovixTheme.colors.primary.copy(alpha = 0.04f), + ), + start = Offset(0f, 0f), + end = Offset(boxSize.width.toFloat(), boxSize.height.toFloat()) + ) + ) + ) +} From 906188a88ec8dc238d4336d5190b2a5bc714b39c Mon Sep 17 00:00:00 2001 From: ahmbd Date: Wed, 20 Aug 2025 12:19:06 +0300 Subject: [PATCH 2/3] refactor: Enhance trending screens with background gradient --- .../trending/actor/TrendingActorsScreen.kt | 73 +++++++++------- .../trending/movie/TrendingMoviesScreen.kt | 83 +++++++++++-------- .../trending/tvshow/TrendingTvShowsScreen.kt | 71 +++++++++------- 3 files changed, 131 insertions(+), 96 deletions(-) diff --git a/presentation/src/main/java/com/london/presentation/feature/home/trending/actor/TrendingActorsScreen.kt b/presentation/src/main/java/com/london/presentation/feature/home/trending/actor/TrendingActorsScreen.kt index 9254a7f2d..44a18f946 100644 --- a/presentation/src/main/java/com/london/presentation/feature/home/trending/actor/TrendingActorsScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/home/trending/actor/TrendingActorsScreen.kt @@ -1,6 +1,7 @@ package com.london.presentation.feature.home.trending.actor import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -9,10 +10,12 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.paging.LoadState @@ -21,6 +24,7 @@ import com.london.designsystem.component.TopBar import com.london.designsystem.theme.NovixTheme import com.london.presentation.R import com.london.presentation.shared.ActorItem +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.LazyPagingColumn import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.utils.Listen @@ -66,37 +70,46 @@ private fun Content( state: TrendingActorsUiState, contract: TrendingActorsContract, ) { - LazyColumn( - modifier = Modifier - .fillMaxSize() - .padding(horizontal = 16.dp) - .background(color = NovixTheme.colors.surface), - contentPadding = PaddingValues(bottom = 16.dp) - ) { - stickyHeader { - TopBar( - title = stringResource(R.string.trending_people), - onBackClick = contract::onBackClick, - modifier = Modifier - .fillMaxWidth() - .background(NovixTheme.colors.surface) - .padding(vertical = 12.dp) - ) - } - item { - LazyPagingColumn( - pagingItems = state.actorsFlow.collectAsLazyPagingItems(), - modifier = Modifier.fillMaxSize(), - itemContent = { actor -> - ActorItem( - actorName = actor.name, - characterName = null, - imageRes = actor.profilePictureUrl, - onClick = { contract.onActorClick(actor.id) } - ) - } - ) + Box( + modifier = Modifier.fillMaxSize() + ){ + BackgroundGradient( + modifier = Modifier.align(Alignment.TopStart).zIndex(1f) + ) + + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 16.dp) + .background(color = NovixTheme.colors.surface), + contentPadding = PaddingValues(bottom = 16.dp) + ) { + stickyHeader { + TopBar( + title = stringResource(R.string.trending_people), + onBackClick = contract::onBackClick, + modifier = Modifier + .fillMaxWidth() + .background(NovixTheme.colors.surface) + .padding(vertical = 12.dp) + ) + } + + item { + LazyPagingColumn( + pagingItems = state.actorsFlow.collectAsLazyPagingItems(), + modifier = Modifier.fillMaxSize(), + itemContent = { actor -> + ActorItem( + actorName = actor.name, + characterName = null, + imageRes = actor.profilePictureUrl, + onClick = { contract.onActorClick(actor.id) } + ) + } + ) + } } } } diff --git a/presentation/src/main/java/com/london/presentation/feature/home/trending/movie/TrendingMoviesScreen.kt b/presentation/src/main/java/com/london/presentation/feature/home/trending/movie/TrendingMoviesScreen.kt index 5f1532204..26f8696de 100644 --- a/presentation/src/main/java/com/london/presentation/feature/home/trending/movie/TrendingMoviesScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/home/trending/movie/TrendingMoviesScreen.kt @@ -1,6 +1,7 @@ package com.london.presentation.feature.home.trending.movie import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -8,18 +9,21 @@ import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.paging.LoadState import androidx.paging.compose.collectAsLazyPagingItems import com.london.designsystem.component.TopBar import com.london.designsystem.theme.NovixTheme import com.london.presentation.R +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.GenresSection import com.london.presentation.shared.MediaLazyPagingGrid import com.london.presentation.shared.bookmarkSheet.BookmarkBottomSheet @@ -66,45 +70,52 @@ private fun Content( ) { val screenWidth = with(LocalDensity.current) { LocalConfiguration.current.screenWidthDp.dp } - Column( - modifier = Modifier - .fillMaxSize() - .background(NovixTheme.colors.surface) - ) { - TopBar( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 12.dp), - title = stringResource(R.string.trending_movies), - onBackClick = contract::onBackClick - ) - GenresSection( - genres = state.movieGenres, - selectedGenre = state.selectedGenre, - screenWidth = screenWidth, - onGenreClick = contract::onGenreClick, - modifier = Modifier.padding(bottom = 12.dp), - getGenreName = { stringResource(it.stringResId) } + Box( + modifier = Modifier.fillMaxSize() + ){ + BackgroundGradient( + modifier = Modifier.align(Alignment.TopStart).zIndex(1f) ) - - MediaLazyPagingGrid( - pagingFlow = state.moviesFlow.collectAsLazyPagingItems(), - onItemClick = { contract.onMovieClick(it.id) }, - getImageUrl = { it.posterPath }, - getTitle = { it.title }, + Column( modifier = Modifier - .weight(1f) - .fillMaxWidth() - .padding(horizontal = 16.dp), - onSaveClick = { contract.onManageBookmarkClicked(it.id) }, - hasSaveIcon = true - ) + .fillMaxSize() + .background(NovixTheme.colors.surface) + ) { + TopBar( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 12.dp), + title = stringResource(R.string.trending_movies), + onBackClick = contract::onBackClick + ) + GenresSection( + genres = state.movieGenres, + selectedGenre = state.selectedGenre, + screenWidth = screenWidth, + onGenreClick = contract::onGenreClick, + modifier = Modifier.padding(bottom = 12.dp), + getGenreName = { stringResource(it.stringResId) } + ) - BookmarkBottomSheet( - onSheetDismiss = contract::onBookmarkSheetDismiss, - isSheetVisible = state.isBookmarkSheetVisible, - bookmarkedMovieId = state.bookmarkedMovieId - ) + MediaLazyPagingGrid( + pagingFlow = state.moviesFlow.collectAsLazyPagingItems(), + onItemClick = { contract.onMovieClick(it.id) }, + getImageUrl = { it.posterPath }, + getTitle = { it.title }, + modifier = Modifier + .weight(1f) + .fillMaxWidth() + .padding(horizontal = 16.dp), + onSaveClick = { contract.onManageBookmarkClicked(it.id) }, + hasSaveIcon = true + ) + + BookmarkBottomSheet( + onSheetDismiss = contract::onBookmarkSheetDismiss, + isSheetVisible = state.isBookmarkSheetVisible, + bookmarkedMovieId = state.bookmarkedMovieId + ) + } } } diff --git a/presentation/src/main/java/com/london/presentation/feature/home/trending/tvshow/TrendingTvShowsScreen.kt b/presentation/src/main/java/com/london/presentation/feature/home/trending/tvshow/TrendingTvShowsScreen.kt index 32eab1b9e..069498a54 100644 --- a/presentation/src/main/java/com/london/presentation/feature/home/trending/tvshow/TrendingTvShowsScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/home/trending/tvshow/TrendingTvShowsScreen.kt @@ -1,6 +1,7 @@ package com.london.presentation.feature.home.trending.tvshow import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -8,12 +9,14 @@ import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.paging.LoadState @@ -21,6 +24,7 @@ import androidx.paging.compose.collectAsLazyPagingItems import com.london.designsystem.component.TopBar import com.london.designsystem.theme.NovixTheme import com.london.presentation.R +import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.GenresSection import com.london.presentation.shared.MediaLazyPagingGrid import com.london.presentation.shared.buildscreen.BuildScreen @@ -67,38 +71,45 @@ private fun Content( val screenWidth = with(LocalDensity.current) { LocalConfiguration.current.screenWidthDp.dp } val tvShowsLazyItems = state.tvShowsFlow.collectAsLazyPagingItems() - Column( - modifier = Modifier - .fillMaxSize() - .background(NovixTheme.colors.surface) - ) { - TopBar( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 12.dp), - title = stringResource(R.string.trending_tv_shows), - onBackClick = contract::onBackClick + Box( + modifier = Modifier.fillMaxSize() + ){ + BackgroundGradient( + modifier = Modifier.align(Alignment.TopStart).zIndex(1f) ) - GenresSection( - genres = state.tvShowsGenres, - selectedGenre = state.selectedGenre, - screenWidth = screenWidth, - onGenreClick = contract::onGenreClick, - modifier = Modifier.padding(bottom = 12.dp), - getGenreName = { stringResource(it.stringResId) } - ) - MediaLazyPagingGrid( - pagingFlow = tvShowsLazyItems, - onItemClick = { contract.onTvShowClick(it.id) }, - getImageUrl = { it.posterPath }, - getTitle = { it.title }, + Column( modifier = Modifier - .weight(1f) - .fillMaxWidth() - .padding(horizontal = 16.dp), - onSaveClick = { /* TODO: Implement save functionality */ }, - isItemSaved = { false }, - ) + .fillMaxSize() + .background(NovixTheme.colors.surface) + ) { + TopBar( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 12.dp), + title = stringResource(R.string.trending_tv_shows), + onBackClick = contract::onBackClick + ) + GenresSection( + genres = state.tvShowsGenres, + selectedGenre = state.selectedGenre, + screenWidth = screenWidth, + onGenreClick = contract::onGenreClick, + modifier = Modifier.padding(bottom = 12.dp), + getGenreName = { stringResource(it.stringResId) } + ) + MediaLazyPagingGrid( + pagingFlow = tvShowsLazyItems, + onItemClick = { contract.onTvShowClick(it.id) }, + getImageUrl = { it.posterPath }, + getTitle = { it.title }, + modifier = Modifier + .weight(1f) + .fillMaxWidth() + .padding(horizontal = 16.dp), + onSaveClick = { /* TODO: Implement save functionality */ }, + isItemSaved = { false }, + ) + } } } From 0d742539656afc4b2ad09351481bcb90d945a134 Mon Sep 17 00:00:00 2001 From: ahmbd Date: Wed, 20 Aug 2025 12:43:36 +0300 Subject: [PATCH 3/3] Refactor: BuildScreen for SavedList and TvShowDetail screens --- .../details/tvshow/info/TvShowDetailScreen.kt | 3 +- .../feature/list/savedlist/ListScreen.kt | 35 ++++++++++--------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/presentation/src/main/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailScreen.kt b/presentation/src/main/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailScreen.kt index 42aa253e4..add6b0464 100644 --- a/presentation/src/main/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailScreen.kt @@ -70,6 +70,7 @@ import com.london.presentation.shared.FooterSection import com.london.presentation.shared.ImageView import com.london.presentation.shared.RatingItem import com.london.presentation.shared.SnackBarAnimation +import com.london.presentation.shared.base.ErrorState import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.shared.genre.TvShowGenreUi import com.london.presentation.utils.Listen @@ -122,7 +123,7 @@ fun TvShowsDetailsScreen( BuildScreen( onBack = viewModel::onBackClicked, isLoading = uiState.isLoading, - isError = uiState.error != null, + isError = uiState.error is ErrorState.NoInternet, onRetry = viewModel::onRetry ) { Content( 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 50982f51b..20a7ec6f8 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 @@ -86,26 +86,27 @@ private fun Content( contract: ListContract, ) { val pagingItems = state.items.collectAsLazyPagingItems() - BuildScreen( - onRetry = contract::onRetry, - isLoading = state.isLoading, - isError = state.error is ErrorState.NoInternet, - pagingFlow = pagingItems, - isGuest = state.isGuest, - guestContent = { NoListFoundAsGuest(onLoginClick = contract::onLoginClick) }, - emptyContent = { EmptyList(contract = contract, addListSheetState = state.addListSheetState) }, - handlePagingLoadingAutomatically = true + + Box( + modifier = Modifier.fillMaxSize() ) { - Box( - modifier = Modifier.fillMaxSize() - ) { + BackgroundGradient( + modifier = Modifier + .align(Alignment.TopStart) + .zIndex(1f) + ) - BackgroundGradient( - modifier = Modifier - .align(Alignment.TopStart) - .zIndex(1f) - ) + BuildScreen( + onRetry = contract::onRetry, + isLoading = state.isLoading, + isError = state.error is ErrorState.NoInternet, + pagingFlow = pagingItems, + isGuest = state.isGuest, + guestContent = { NoListFoundAsGuest(onLoginClick = contract::onLoginClick) }, + emptyContent = { EmptyList(contract = contract, addListSheetState = state.addListSheetState) }, + handlePagingLoadingAutomatically = true + ) { ScreenScaffold( titleRes = R.string.saved_list_title,