From 3cb5c635986a09e6c52d7d9de99574be45a562d1 Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 10:42:31 +0300 Subject: [PATCH 01/24] refactor: Standardize navigation parameter names --- .../com/london/app/navigation/graph/mainNavGraph.kt | 10 +++++----- .../home/trending/actor/TrendingActorsScreen.kt | 8 ++++---- .../home/trending/movie/TrendingMoviesScreen.kt | 8 ++++---- .../home/trending/tvshow/TrendingTvShowsScreen.kt | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/london/app/navigation/graph/mainNavGraph.kt b/app/src/main/java/com/london/app/navigation/graph/mainNavGraph.kt index ab5f009bb..ac32d3e0f 100644 --- a/app/src/main/java/com/london/app/navigation/graph/mainNavGraph.kt +++ b/app/src/main/java/com/london/app/navigation/graph/mainNavGraph.kt @@ -266,22 +266,22 @@ private fun NavGraphBuilder.trendingNavGraph(navController: NavHostController) = composable { TrendingMoviesScreen( - onNavigateToMovieDetailsClick = ::navigateToMovieDetails, - onNavigateBackClick = ::navigateUp + onNavigateToMovieDetails = ::navigateToMovieDetails, + onNavigateBack = ::navigateUp ) } composable { TrendingTvShowsScreen( - onNavigateToTvShowDetailsClick = ::navigateToTvShowDetails, + onNavigateToTvShowDetails = ::navigateToTvShowDetails, onNavigateBack = ::navigateUp ) } composable { TrendingActorsScreen( - onNavigateToActorDetailsClick = ::navigateToActorDetails, - onNavigateBackClick = ::navigateUp + onNavigateToActorDetails = ::navigateToActorDetails, + onNavigateBack = ::navigateUp ) } 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 b141d5d31..1fed7519f 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 @@ -26,8 +26,8 @@ import com.london.presentation.utils.Listen @Composable fun TrendingActorsScreen( - onNavigateBackClick: () -> Unit, - onNavigateToActorDetailsClick: (Int) -> Unit, + onNavigateBack: () -> Unit, + onNavigateToActorDetails: (Int) -> Unit, viewModel: TrendingActorsViewModel = hiltViewModel() ) { val state by viewModel.state.collectAsStateWithLifecycle() @@ -35,11 +35,11 @@ fun TrendingActorsScreen( effect?.Listen { currentEffect -> when (currentEffect) { - is TrendingActorsEffect.ActorDetailsNavigation -> onNavigateToActorDetailsClick( + is TrendingActorsEffect.ActorDetailsNavigation -> onNavigateToActorDetails( currentEffect.actorId ) - is TrendingActorsEffect.BackNavigation -> onNavigateBackClick() + is TrendingActorsEffect.BackNavigation -> onNavigateBack() } } 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..76621993d 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 @@ -28,8 +28,8 @@ import com.london.presentation.utils.Listen @Composable fun TrendingMoviesScreen( - onNavigateBackClick: () -> Unit, - onNavigateToMovieDetailsClick: (Int) -> Unit, + onNavigateBack: () -> Unit, + onNavigateToMovieDetails: (Int) -> Unit, viewModel: TrendingMoviesViewModel = hiltViewModel() ) { val state by viewModel.state.collectAsState() @@ -37,11 +37,11 @@ fun TrendingMoviesScreen( effect?.Listen { currentEffect -> when (currentEffect) { - is TrendingMoviesEffect.MovieDetailsNavigation -> onNavigateToMovieDetailsClick( + is TrendingMoviesEffect.MovieDetailsNavigation -> onNavigateToMovieDetails( currentEffect.movieId ) - is TrendingMoviesEffect.BackNavigation -> onNavigateBackClick() + is TrendingMoviesEffect.BackNavigation -> onNavigateBack() } } BuildScreen( 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..e5c7cc1fe 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 @@ -29,7 +29,7 @@ import com.london.presentation.utils.Listen @Composable fun TrendingTvShowsScreen( onNavigateBack: () -> Unit, - onNavigateToTvShowDetailsClick: (Int) -> Unit, + onNavigateToTvShowDetails: (Int) -> Unit, viewModel: TrendingTvShowsViewModel = hiltViewModel() ) { val state by viewModel.state.collectAsStateWithLifecycle() @@ -37,7 +37,7 @@ fun TrendingTvShowsScreen( effect?.Listen { currentEffect -> when (currentEffect) { - is TrendingTvShowsEffect.TvShowDetailsNavigation -> onNavigateToTvShowDetailsClick( + is TrendingTvShowsEffect.TvShowDetailsNavigation -> onNavigateToTvShowDetails( currentEffect.tvShowId ) From 716c25c182295486ca724e6a7dad5d71452373f9 Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 11:57:07 +0300 Subject: [PATCH 02/24] refactor: Reorder parameters and adjust padding in media components --- .../presentation/shared/DefaultAppTopBar.kt | 6 ++--- .../shared/container/MediaGridConfig.kt | 9 +++---- .../container/MediaLazyGridWithFilter.kt | 27 ++++++++----------- .../shared/container/MediaLazyGridWithTabs.kt | 1 - .../shared/container/MediaLazyVerticalGrid.kt | 20 +++++++------- 5 files changed, 28 insertions(+), 35 deletions(-) diff --git a/presentation/src/main/java/com/london/presentation/shared/DefaultAppTopBar.kt b/presentation/src/main/java/com/london/presentation/shared/DefaultAppTopBar.kt index d522e7bd5..e3ee80011 100644 --- a/presentation/src/main/java/com/london/presentation/shared/DefaultAppTopBar.kt +++ b/presentation/src/main/java/com/london/presentation/shared/DefaultAppTopBar.kt @@ -10,13 +10,13 @@ import com.london.designsystem.component.TopBar @Composable fun DefaultAppTopBar( title: String, - onBack: () -> Unit, + onBackClick: () -> Unit, ) { TopBar( modifier = Modifier .fillMaxWidth() - .padding(start = 16.dp, end = 16.dp, top = 12.dp), + .padding(horizontal = 16.dp, vertical = 8.dp), title = title, - onBackClick = onBack + onBackClick = onBackClick ) } diff --git a/presentation/src/main/java/com/london/presentation/shared/container/MediaGridConfig.kt b/presentation/src/main/java/com/london/presentation/shared/container/MediaGridConfig.kt index 890a6847a..b05a3ec08 100644 --- a/presentation/src/main/java/com/london/presentation/shared/container/MediaGridConfig.kt +++ b/presentation/src/main/java/com/london/presentation/shared/container/MediaGridConfig.kt @@ -4,16 +4,15 @@ import com.london.presentation.shared.genre.MovieGenreUi import com.london.presentation.shared.genre.TvShowGenreUi data class MediaGridConfig( - val rate: String? = "", - val isDarkMode: Boolean = true, val showSaveIcon: Boolean = true, + val isDarkMode: Boolean = true, val isMovieSelected: Boolean = true, + val isTvShowSelected: Boolean = false, + val isItemSaved: (Any) -> Boolean = { false }, val onSaveClick: (Any) -> Unit = {}, val onDeleteClick: (Any) -> Unit = {}, - val isTvShowSelected: Boolean = false, val onNavigateToMovie: (Int) -> Unit = {}, val onNavigateToTvShow: (Int) -> Unit = {}, - val isItemSaved: (Any) -> Boolean = { false }, val selectedMovieGenre: MovieGenreUi = MovieGenreUi.All, - val selectedTvShowGenre: TvShowGenreUi = TvShowGenreUi.All, + val selectedTvShowGenre: TvShowGenreUi = TvShowGenreUi.All ) diff --git a/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyGridWithFilter.kt b/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyGridWithFilter.kt index 8fb81abf1..cb7b9e47b 100644 --- a/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyGridWithFilter.kt +++ b/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyGridWithFilter.kt @@ -21,11 +21,11 @@ fun MediaLazyGridWithFilter( modifier: Modifier = Modifier, isLoading: Boolean = false, name: (T) -> String = { it.getName() }, - topBar: @Composable (() -> Unit)? = null, - config: MediaGridConfig = MediaGridConfig(), - onMovieGenreClick: (MovieGenreUi) -> Unit = {}, imageUrl: (T) -> String? = { it.getImageUrl() }, + onMovieGenreClick: (MovieGenreUi) -> Unit = {}, onTvShowGenreClick: (TvShowGenreUi) -> Unit = {}, + config: MediaGridConfig = MediaGridConfig(), + topBar: @Composable (() -> Unit)? = null ) { Column( @@ -52,7 +52,6 @@ fun MediaLazyGridWithFilter( imageUrl = imageUrl, name = name, config = config, - topBar = topBar ) } @@ -90,7 +89,7 @@ fun MediaLazyGridWithFilter( selectedMovieGenre = config.selectedMovieGenre, selectedTvShowGenre = config.selectedTvShowGenre, onMovieGenreClick = onMovieGenreClick, - onTvShowGenreClick = onTvShowGenreClick, + onTvShowGenreClick = onTvShowGenreClick ) if (pagingItems.itemCount > 0) { @@ -98,8 +97,7 @@ fun MediaLazyGridWithFilter( pagingItems = pagingItems, imageUrl = imageUrl, name = name, - config = config, - topBar = topBar + config = config ) } else if (!isLoading) { EmptyGenreLayout() @@ -112,8 +110,7 @@ private fun RenderFilteredItemsGrid( filteredItems: List, imageUrl: (T) -> String?, name: (T) -> String, - config: MediaGridConfig, - topBar: @Composable (() -> Unit)? + config: MediaGridConfig ) { if (filteredItems.isNotEmpty()) { MediaLazyVerticalGrid( @@ -124,8 +121,8 @@ private fun RenderFilteredItemsGrid( onSaveClick = { config.onSaveClick(it) }, isItemSaved = { config.isItemSaved(it) }, onDeleteClick = { config.onDeleteClick(it) }, - rate = { config.rate }, - topBar = topBar, + rate = { null }, + topBar = null, modifier = Modifier.fillMaxSize(), onNavigateToMovie = config.onNavigateToMovie, onNavigateToTvShow = config.onNavigateToTvShow @@ -140,8 +137,7 @@ private fun RenderPagingItemsGrid( pagingItems: LazyPagingItems, imageUrl: (T) -> String?, name: (T) -> String, - config: MediaGridConfig, - topBar: @Composable (() -> Unit)? + config: MediaGridConfig ) { MediaLazyVerticalGrid( pagingItems = pagingItems, @@ -151,8 +147,8 @@ private fun RenderPagingItemsGrid( onSaveClick = { config.onSaveClick(it) }, isItemSaved = { config.isItemSaved(it) }, onDeleteClick = { config.onDeleteClick(it) }, - rate = { config.rate }, - topBar = topBar, + rate = { null }, + topBar = null, modifier = Modifier.fillMaxSize(), onNavigateToMovie = config.onNavigateToMovie, onNavigateToTvShow = config.onNavigateToTvShow @@ -188,7 +184,6 @@ private fun Preview() { config = MediaGridConfig( showSaveIcon = true, isDarkMode = true, - rate = "3", isMovieSelected = true, isTvShowSelected = false, selectedMovieGenre = MovieGenreUi.Action, diff --git a/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyGridWithTabs.kt b/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyGridWithTabs.kt index 65eb16dd3..589f5eddc 100644 --- a/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyGridWithTabs.kt +++ b/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyGridWithTabs.kt @@ -173,7 +173,6 @@ private fun Preview() { config = MediaGridConfig( showSaveIcon = true, isDarkMode = true, - rate = "3", isMovieSelected = true, isTvShowSelected = false, selectedMovieGenre = MovieGenreUi.All, diff --git a/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyVerticalGrid.kt b/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyVerticalGrid.kt index 2cc61cabf..1a5bec7ca 100644 --- a/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyVerticalGrid.kt +++ b/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyVerticalGrid.kt @@ -27,17 +27,17 @@ import com.london.presentation.utils.gridColumns fun MediaLazyVerticalGrid( items: List, modifier: Modifier = Modifier, + rate: (T) -> String? = { null }, + name: (T) -> String = { it.getName() }, + imageUrl: (T) -> String? = { it.getImageUrl() }, hasSaveIcon: Boolean = true, onSaveClick: (T) -> Unit = {}, - onDeleteClick: (T) -> Unit = {}, - rate: (T) -> String? = { null }, + isItemSaved: (T) -> Boolean = { false }, onItemClick: ((T) -> Unit)? = null, + onDeleteClick: (T) -> Unit = {}, onNavigateToMovie: (Int) -> Unit = {}, onNavigateToTvShow: (Int) -> Unit = {}, - name: (T) -> String = { it.getName() }, - isItemSaved: (T) -> Boolean = { false }, - topBar: @Composable (() -> Unit)? = null, - imageUrl: (T) -> String? = { it.getImageUrl() }, + topBar: @Composable (() -> Unit)? = null ) { MediaGridContainer( modifier = modifier, @@ -82,7 +82,7 @@ fun MediaLazyVerticalGrid( name: (T) -> String = { it.getName() }, imageUrl: (T) -> String? = { it.getImageUrl() }, hasSaveIcon: Boolean = true, - onSaveClick: (Int) -> Unit = {}, + onSaveClick: (T) -> Unit = {}, isItemSaved: (T) -> Boolean = { false }, onDeleteClick: (T) -> Unit = {}, topBar: @Composable (() -> Unit)? = null, @@ -139,7 +139,7 @@ private fun MediaGridContainer( modifier = Modifier.fillMaxSize(), horizontalArrangement = Arrangement.spacedBy(12.dp), verticalArrangement = Arrangement.spacedBy(12.dp), - contentPadding = PaddingValues(start = 16.dp, end = 16.dp, bottom = 16.dp), + contentPadding = PaddingValues(start = 16.dp, end = 16.dp, bottom = 16.dp, top = 12.dp), content = content ) } @@ -153,7 +153,7 @@ private fun RenderPagingGridItem( name: (T) -> String, isItemSaved: (T) -> Boolean, hasSaveIcon: Boolean, - onSaveClick: (Int) -> Unit, + onSaveClick: (T) -> Unit, onDeleteClick: (T) -> Unit, rate: (T) -> String?, onNavigateToMovie: (Int) -> Unit, @@ -172,7 +172,7 @@ private fun RenderPagingGridItem( imageDescription = name(item), isSaved = isItemSaved(item), hasSaveIcon = hasSaveIcon, - onSaveClick = { if (item is Movie) onSaveClick(item.id) }, + onSaveClick = { onSaveClick(item) }, onDeleteClick = { onDeleteClick(item) }, rate = rate(item) ) From e69bb1c4e033f59a3288fc566492239a6c89e5e8 Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 11:57:35 +0300 Subject: [PATCH 03/24] refactor: Standardize `onBack` and `onManageBookmark` method names --- .../category/movie/MovieCategoryContract.kt | 4 +- .../category/movie/MovieCategoryScreen.kt | 69 ++++++++----------- .../category/movie/MovieCategoryViewModel.kt | 4 +- .../movie/MovieCategoryViewModelTest.kt | 2 +- 4 files changed, 32 insertions(+), 47 deletions(-) diff --git a/presentation/src/main/java/com/london/presentation/feature/category/movie/MovieCategoryContract.kt b/presentation/src/main/java/com/london/presentation/feature/category/movie/MovieCategoryContract.kt index c005e8d48..dd8fe624e 100644 --- a/presentation/src/main/java/com/london/presentation/feature/category/movie/MovieCategoryContract.kt +++ b/presentation/src/main/java/com/london/presentation/feature/category/movie/MovieCategoryContract.kt @@ -1,8 +1,8 @@ package com.london.presentation.feature.category.movie interface MovieCategoryContract { - fun onBack() + fun onBackClick() fun onMovieClick(movieId: Int) fun onBookmarkSheetDismiss() - fun onManageBookmarkClicked(movieId: Int) + fun onManageBookmarkClick(movieId: Int) } 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..fceec2ff1 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,25 +1,21 @@ package com.london.presentation.feature.category.movie -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -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.Modifier import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.paging.LoadState 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.MediaLazyPagingGrid +import com.london.presentation.shared.DefaultAppTopBar import com.london.presentation.shared.bookmarkSheet.BookmarkBottomSheet import com.london.presentation.shared.buildscreen.BuildScreen +import com.london.presentation.shared.container.MediaLazyVerticalGrid import com.london.presentation.utils.Listen import com.london.presentation.utils.isLoading @@ -54,49 +50,38 @@ private fun Content( ) { val moviesLazyList = state.moviesFlow.collectAsLazyPagingItems() + BuildScreen( - onBack = contract::onBack, + onBack = contract::onBackClick, isLoading = moviesLazyList.isLoading(), isError = moviesLazyList.loadState.refresh is LoadState.Error, onRetry = moviesLazyList::refresh, emptyLayoutMessage = R.string.there_is_no_items_for_this_genre, emptyLayoutImage = R.drawable.empty ) { + MediaLazyVerticalGrid( + pagingItems = moviesLazyList, + imageUrl = { it.posterUrl }, + name = { it.name }, + hasSaveIcon = true, + onSaveClick = { contract.onManageBookmarkClick(it.id) }, + isItemSaved = { false }, + onNavigateToMovie = { id -> contract.onMovieClick(id) }, + topBar = { + DefaultAppTopBar( + title = stringResource(state.genre.stringResId), + onBackClick = contract::onBackClick + ) + }, + modifier = Modifier.fillMaxWidth() + ) - 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) - ) - - 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 + ) - BookmarkBottomSheet( - onSheetDismiss = contract::onBookmarkSheetDismiss, - isSheetVisible = state.isBookmarkSheetVisible, - bookmarkedMovieId = state.bookmarkedMovieId - ) - - } } } @@ -108,8 +93,8 @@ private fun MoviesByCategoryContentPreview() { contract = object : MovieCategoryContract { override fun onMovieClick(movieId: Int) {} override fun onBookmarkSheetDismiss() {} - override fun onManageBookmarkClicked(movieId: Int) {} - override fun onBack() {} + override fun onManageBookmarkClick(movieId: Int) {} + override fun onBackClick() {} }, ) } diff --git a/presentation/src/main/java/com/london/presentation/feature/category/movie/MovieCategoryViewModel.kt b/presentation/src/main/java/com/london/presentation/feature/category/movie/MovieCategoryViewModel.kt index dde1f28a7..b112be57e 100644 --- a/presentation/src/main/java/com/london/presentation/feature/category/movie/MovieCategoryViewModel.kt +++ b/presentation/src/main/java/com/london/presentation/feature/category/movie/MovieCategoryViewModel.kt @@ -33,10 +33,10 @@ class MovieCategoryViewModel @Inject constructor( override fun onMovieClick(movieId: Int) = emitEffect(MovieCategoryEffect.MovieDetailsNavigation(movieId = movieId)) - override fun onBack() = + override fun onBackClick() = emitEffect(MovieCategoryEffect.BackNavigation) - override fun onManageBookmarkClicked(movieId: Int) { + override fun onManageBookmarkClick(movieId: Int) { updateState { copy( isBookmarkSheetVisible = true, diff --git a/presentation/src/test/java/com/london/presentation/feature/category/movie/MovieCategoryViewModelTest.kt b/presentation/src/test/java/com/london/presentation/feature/category/movie/MovieCategoryViewModelTest.kt index 7e3aece55..026727476 100644 --- a/presentation/src/test/java/com/london/presentation/feature/category/movie/MovieCategoryViewModelTest.kt +++ b/presentation/src/test/java/com/london/presentation/feature/category/movie/MovieCategoryViewModelTest.kt @@ -115,7 +115,7 @@ class MovieCategoryViewModelTest { fun `onMovieClick should emit NavigateBack effect`() = runTest { // When & Then viewModel?.effect?.test { - viewModel?.onBack() + viewModel?.onBackClick() assertThat(awaitItem()).isInstanceOf(MovieCategoryEffect.BackNavigation::class.java) cancelAndIgnoreRemainingEvents() } From 4febbbd7244fe51d46b3d14d35878cbb09f47c28 Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 11:58:07 +0300 Subject: [PATCH 04/24] refactor: Rename onManageBookmarkClicked to onManageBookmarkClick --- .../feature/home/trending/actor/TrendingActorsScreen.kt | 2 +- .../com/london/presentation/feature/search/SearchContract.kt | 2 +- .../com/london/presentation/feature/search/SearchViewModel.kt | 2 +- 3 files changed, 3 insertions(+), 3 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 1fed7519f..a4d82e34d 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 @@ -20,7 +20,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.LazyPagingColumn +import com.london.presentation.shared.container.LazyPagingColumn import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.utils.Listen diff --git a/presentation/src/main/java/com/london/presentation/feature/search/SearchContract.kt b/presentation/src/main/java/com/london/presentation/feature/search/SearchContract.kt index 856c84152..7d2bc0b5b 100644 --- a/presentation/src/main/java/com/london/presentation/feature/search/SearchContract.kt +++ b/presentation/src/main/java/com/london/presentation/feature/search/SearchContract.kt @@ -27,5 +27,5 @@ interface SearchContract { fun incrementGenreInterest(genre: Genre, mediaType: String) fun updateRecentData() fun onBookmarkSheetDismiss() - fun onManageBookmarkClicked(movieId: Int) + fun onManageBookmarkClick(movieId: Int) } diff --git a/presentation/src/main/java/com/london/presentation/feature/search/SearchViewModel.kt b/presentation/src/main/java/com/london/presentation/feature/search/SearchViewModel.kt index c6d971ba1..b48d006da 100644 --- a/presentation/src/main/java/com/london/presentation/feature/search/SearchViewModel.kt +++ b/presentation/src/main/java/com/london/presentation/feature/search/SearchViewModel.kt @@ -190,7 +190,7 @@ class SearchViewModel @Inject constructor( setupSearchDebouncing() } - override fun onManageBookmarkClicked(movieId: Int) { + override fun onManageBookmarkClick(movieId: Int) { updateState { copy( isBookmarkSheetVisible = true, From e0664751ee0f5d4a4804363c20acf42e12f2a830 Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 12:18:32 +0300 Subject: [PATCH 05/24] refactor: Update SearchScreen and MyRatingScreen UI --- .../feature/account/rating/MyRatingScreen.kt | 4 +--- .../feature/search/SearchScreen.kt | 20 +++++++++---------- 2 files changed, 10 insertions(+), 14 deletions(-) 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..861d73414 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 @@ -103,10 +103,8 @@ private fun Content( items = items, imageUrl = { it.posterPath }, name = { it.title }, - rate = { rated -> rated.rating.toLocalizedNumbers() }, hasSaveIcon = false, - isItemSaved = { false }, - onSaveClick = {}, + rate = { rated -> rated.rating.toLocalizedNumbers() }, onDeleteClick = { rated -> when (rated.mediaType) { MediaType.Movie -> contract.onDeleteMovieClick(rated.id) 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..7ed64fe0d 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 @@ -53,6 +53,7 @@ import com.london.designsystem.component.Text import com.london.designsystem.component.TopBar import com.london.designsystem.theme.NovixTheme import com.london.designsystem.theme.ThemePreviews +import com.london.domain.entity.movie.Movie import com.london.domain.entity.recent.RecentSearch import com.london.domain.entity.recent.RecentViewed import com.london.domain.entity.shared.MediaType @@ -193,8 +194,7 @@ private fun SearchBody( content = { SearchChipsRow( selected = state.selectedCategory, - onSelect = contract::onCategorySelected, - modifier = Modifier.padding(bottom = 12.dp) + onSelect = contract::onCategorySelected ) } ) @@ -224,8 +224,7 @@ private fun SearchResultsWithCategory( ) { SearchChipsRow( selected = state.selectedCategory, - onSelect = contract::onCategorySelected, - modifier = Modifier.padding(bottom = 12.dp) + onSelect = contract::onCategorySelected ) if (state.error == ErrorState.NoInternet) { @@ -300,8 +299,8 @@ private fun ActorSearchContent(state: SearchUiState, contract: SearchContract) { emptyContent = { if (!isLoading) { EmptyLayout( - text = stringResource(R.string.no_search_result_msg), - image = R.drawable.img_no_search_result, + text = stringResource(R.string.start_exploring_msg), + image = R.drawable.imge_explore, modifier = Modifier .fillMaxSize() .padding(horizontal = 16.dp) @@ -336,8 +335,8 @@ private fun MediaSearchContent( emptyContent = { if (!isLoading) { EmptyLayout( - text = stringResource(R.string.no_search_result_msg), - image = R.drawable.img_no_search_result, + text = stringResource(R.string.start_exploring_msg), + image = R.drawable.imge_explore, modifier = Modifier .fillMaxSize() .padding(horizontal = 16.dp) @@ -348,8 +347,7 @@ private fun MediaSearchContent( MediaLazyVerticalGrid( pagingItems = pagingItems, hasSaveIcon = hasSaveIcon, - onSaveClick = contract::onManageBookmarkClicked, - isItemSaved = { false }, + onSaveClick = { if (it is Movie) contract.onManageBookmarkClick(it.id) }, onNavigateToMovie = onNavigateToMovie, onNavigateToTvShow = onNavigateToTvShow ) @@ -517,7 +515,7 @@ private fun RecentSectionContent( onClearAll = contract::clearRecentViewed, onNavigateToTvShowDetails = onNavigateToTvShowDetails, onNavigateToMovieDetails = onNavigateToMovieDetails, - onManageBookmarkClicked = contract::onManageBookmarkClicked + onManageBookmarkClicked = contract::onManageBookmarkClick ) } } From b2cce6def6c587a44bb82c1a4e3173489c79f282 Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 12:51:54 +0300 Subject: [PATCH 06/24] refactor: Rename ActorsLayout to ActorLazyVerticalColumn and update usage --- .../london/designsystem/component/TopBar.kt | 2 +- .../ContinueWatchingScreen.kt | 5 +- .../trending/actor/TrendingActorsScreen.kt | 72 +++++++++---------- .../feature/search/SearchScreen.kt | 4 +- .../ActorLazyVerticalColumn.kt} | 7 +- 5 files changed, 41 insertions(+), 49 deletions(-) rename presentation/src/main/java/com/london/presentation/shared/{ActorsLayout.kt => container/ActorLazyVerticalColumn.kt} (87%) diff --git a/designSystem/src/main/java/com/london/designsystem/component/TopBar.kt b/designSystem/src/main/java/com/london/designsystem/component/TopBar.kt index 445b7ec04..8e3f1c690 100644 --- a/designSystem/src/main/java/com/london/designsystem/component/TopBar.kt +++ b/designSystem/src/main/java/com/london/designsystem/component/TopBar.kt @@ -118,7 +118,7 @@ private fun ButtonTopBar( @Composable @ThemePreviews -private fun TopBarPreview() { +private fun Preview() { TopBar( onClickOption1 = {}, onClickOption2 = {} 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..e0eb6b9d9 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 @@ -87,13 +87,12 @@ private fun Content( onNavigateToMovie = contract::onNavigateToMovieClick, onNavigateToTvShow = contract::onNavigateToTvShowClick, onSaveClick = { if (it is Movie) contract.onManageBookmarkClicked(it.id) }, - isItemSaved = { false }, - rate = null + isItemSaved = { false } ), topBar = { DefaultAppTopBar( title = screenTitle, - onBack = contract::onBackClick + onBackClick = contract::onBackClick ) }, isLoading = state.isLoading 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 a4d82e34d..af07b9d6b 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,10 +1,10 @@ package com.london.presentation.feature.home.trending.actor import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue @@ -19,10 +19,10 @@ 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.ActorItem -import com.london.presentation.shared.container.LazyPagingColumn +import com.london.presentation.shared.container.ActorLazyVerticalColumn import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.utils.Listen +import com.london.presentation.utils.isLoading @Composable fun TrendingActorsScreen( @@ -43,21 +43,10 @@ fun TrendingActorsScreen( } } - val actorsLazyItems = state.actorsFlow.collectAsLazyPagingItems() - - BuildScreen( - isLoading = state.isLoading, - isError = actorsLazyItems.loadState.refresh is LoadState.Error, - onBack = viewModel::onBackClick, - onRetry = viewModel::onRetryClick, - emptyLayoutMessage = R.string.no_trending_actors_in_genre, - emptyLayoutImage = R.drawable.img_no_result, - ) { - Content( - state = state, - contract = viewModel, - ) - } + Content( + state = state, + contract = viewModel + ) } @Composable @@ -65,35 +54,34 @@ private fun Content( state: TrendingActorsUiState, contract: TrendingActorsContract, ) { - LazyColumn( - modifier = Modifier - .fillMaxSize() - .padding(horizontal = 16.dp) - .background(color = NovixTheme.colors.surface) + val actorsLazyItems = state.actorsFlow.collectAsLazyPagingItems() + + BuildScreen( + isLoading = actorsLazyItems.isLoading(), + isError = actorsLazyItems.loadState.refresh is LoadState.Error, + onBack = contract::onBackClick, + onRetry = contract::onRetryClick, + emptyLayoutMessage = R.string.no_trending_actors_in_genre, + emptyLayoutImage = R.drawable.img_no_result, + pagingFlow = actorsLazyItems ) { - stickyHeader { + Column( + modifier = Modifier + .fillMaxSize() + .background(color = NovixTheme.colors.surface) + ) { TopBar( - title = stringResource(R.string.trending_people), + title = stringResource(com.london.designsystem.R.string.tv_shows), onBackClick = contract::onBackClick, modifier = Modifier .fillMaxWidth() .background(NovixTheme.colors.surface) - .padding(vertical = 12.dp) + .padding(start = 16.dp, end = 16.dp, bottom = 8.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) } - ) - } + ActorLazyVerticalColumn( + items = actorsLazyItems, + onActorClick = { contract.onActorClick(it.id) } ) } } @@ -104,6 +92,10 @@ private fun Content( private fun Preview() = NovixTheme { Content( state = TrendingActorsUiState(), - contract = defaultTrendingActorsContract() + contract = object : TrendingActorsContract { + override fun onActorClick(id: Int) {} + override fun onBackClick() {} + override fun onRetryClick() {} + } ) } 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 7ed64fe0d..e697c3c7b 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 @@ -59,7 +59,7 @@ import com.london.domain.entity.recent.RecentViewed 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.container.ActorLazyVerticalColumn import com.london.presentation.shared.HomeCard import com.london.presentation.shared.TriangleBlurredShape import com.london.presentation.shared.base.ErrorState @@ -308,7 +308,7 @@ private fun ActorSearchContent(state: SearchUiState, contract: SearchContract) { } }, content = { - ActorsLayout( + ActorLazyVerticalColumn( items = actorsLazyList, onActorClick = { contract.onActorClick(it.id) } diff --git a/presentation/src/main/java/com/london/presentation/shared/ActorsLayout.kt b/presentation/src/main/java/com/london/presentation/shared/container/ActorLazyVerticalColumn.kt similarity index 87% rename from presentation/src/main/java/com/london/presentation/shared/ActorsLayout.kt rename to presentation/src/main/java/com/london/presentation/shared/container/ActorLazyVerticalColumn.kt index faca3197f..19c288be3 100644 --- a/presentation/src/main/java/com/london/presentation/shared/ActorsLayout.kt +++ b/presentation/src/main/java/com/london/presentation/shared/container/ActorLazyVerticalColumn.kt @@ -1,4 +1,4 @@ -package com.london.presentation.shared +package com.london.presentation.shared.container import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.PaddingValues @@ -9,16 +9,17 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.paging.compose.LazyPagingItems import com.london.domain.entity.actor.Actor +import com.london.presentation.shared.ActorItem @Composable -fun ActorsLayout( +fun ActorLazyVerticalColumn( items: LazyPagingItems, onActorClick: (Actor) -> Unit, modifier: Modifier = Modifier ) { LazyColumn( modifier = modifier.fillMaxWidth(), - contentPadding = PaddingValues(start = 16.dp, end = 16.dp, bottom = 16.dp), + contentPadding = PaddingValues(start = 16.dp, end = 16.dp, bottom = 16.dp, top = 12.dp), verticalArrangement = Arrangement.spacedBy(12.dp) ) { items(items.itemCount) { index -> From 0f2f79166419b68c3d3835b1ca8a626ba9499d17 Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 12:53:01 +0300 Subject: [PATCH 07/24] refactor: Remove deprecated `MoviesLayOut` and `TvShowLayOut` composable --- .../presentation/shared/MoviesLayout.kt | 79 ------------------ .../presentation/shared/TvShowsLayout.kt | 81 ------------------- 2 files changed, 160 deletions(-) delete mode 100644 presentation/src/main/java/com/london/presentation/shared/MoviesLayout.kt delete mode 100644 presentation/src/main/java/com/london/presentation/shared/TvShowsLayout.kt diff --git a/presentation/src/main/java/com/london/presentation/shared/MoviesLayout.kt b/presentation/src/main/java/com/london/presentation/shared/MoviesLayout.kt deleted file mode 100644 index e4c031b6e..000000000 --- a/presentation/src/main/java/com/london/presentation/shared/MoviesLayout.kt +++ /dev/null @@ -1,79 +0,0 @@ -package com.london.presentation.shared - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.lazy.grid.GridCells -import androidx.compose.foundation.lazy.grid.LazyVerticalGrid -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import androidx.paging.compose.LazyPagingItems -import com.london.domain.entity.movie.Movie -import com.london.presentation.utils.gridColumns - -@Deprecated( - message = "Use MediaLazyVerticalGrid or MediaLazyGridWithFilter instead. This composable will be removed in a future version. Note: Both have two overloads - one for List and one for LazyPagingItems.", - replaceWith = ReplaceWith( - expression = "MediaLazyGridWithFilter(" + - "items = items, " + - "modifier = modifier, " + - "imageUrl = getImageUrl, " + - "name = { it.getName() }, " + - "onSaveClick = onSavedClick, " + - "isItemSaved = isItemSaved, " + - "onDeleteClick = onDeleteClick, " + - "onMovieGenreClick = {}, " + - "onTvShowGenreClick = {}, " + - "config = MediaGridConfig(" + - " showSaveIcon = hasSaveIcon, " + - " isDarkMode = isDarkMode, " + - " myRatingList = myRatingList, " + - " rate = rate, " + - " isMovieSelected = true, " + - " isTvShowSelected = false, " + - " selectedMovieGenre = MovieGenre.All, " + - " onNavigateToMovie = onItemClick, " + - "), " + - "topBar = {" + - " DefaultAppTopBar(" + - " title = title," + - " onBack = onBack" + - " )" + - "}" + - ")", - imports = ["com.london.presentation.shared.container.MediaLazyGridWithFilter", "com.london.presentation.shared.container.MediaGridConfig", "com.london.presentation.utils.MovieGenre", "com.london.presentation.utils.TvShowGenre"] - ), - level = DeprecationLevel.WARNING -) - -@Composable -fun MoviesLayOut( - movieUis: LazyPagingItems, - onSaveClick: (Movie) -> Unit, - isMovieSaved: (Movie) -> Boolean, - onMovieClick: (Movie) -> Unit, - modifier: Modifier = Modifier -) { - LazyVerticalGrid( - columns = GridCells.Fixed(gridColumns()), - modifier = modifier.fillMaxSize(), - horizontalArrangement = Arrangement.spacedBy(12.dp), - verticalArrangement = Arrangement.spacedBy(12.dp), - contentPadding = PaddingValues(bottom = 16.dp) - ) { - items(movieUis.itemCount) { index -> - val movie = movieUis[index] - if (movie != null) { - HomeCard( - imageUrl = movie.posterUrl, - onSaveClick = { onSaveClick(movie) }, - isSaved = isMovieSaved(movie), - imageDescription = movie.name, - modifier = Modifier.clickable { onMovieClick(movie) } - ) - } - } - } -} diff --git a/presentation/src/main/java/com/london/presentation/shared/TvShowsLayout.kt b/presentation/src/main/java/com/london/presentation/shared/TvShowsLayout.kt deleted file mode 100644 index 15282abfa..000000000 --- a/presentation/src/main/java/com/london/presentation/shared/TvShowsLayout.kt +++ /dev/null @@ -1,81 +0,0 @@ -package com.london.presentation.shared - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.grid.GridCells -import androidx.compose.foundation.lazy.grid.LazyVerticalGrid -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import androidx.paging.compose.LazyPagingItems -import com.london.domain.entity.tvshow.TvShow -import com.london.presentation.utils.gridColumns - -@Deprecated( - message = "Use MediaLazyVerticalGrid or MediaLazyGridWithFilter instead. This composable will be removed in a future version. Note: Both have two overloads - one for List and one for LazyPagingItems.", - replaceWith = ReplaceWith( - expression = "MediaLazyGridWithFilter(" + - "items = items, " + - "modifier = modifier, " + - "imageUrl = getImageUrl, " + - "name = { it.getName() }, " + - "onSaveClick = onSavedClick, " + - "isItemSaved = isItemSaved, " + - "onDeleteClick = onDeleteClick, " + - "onMovieGenreClick = {}, " + - "onTvShowGenreClick = {}, " + - "config = MediaGridConfig(" + - " showSaveIcon = hasSaveIcon, " + - " isDarkMode = isDarkMode, " + - " myRatingList = myRatingList, " + - " rate = rate, " + - " isMovieSelected = true, " + - " isTvShowSelected = false, " + - " selectedTvShowGenre = TvShowGenre.All, " + - " onNavigateToMovie = onItemClick, " + - "), " + - "topBar = {" + - " DefaultAppTopBar(" + - " title = title," + - " onBack = onBack" + - " )" + - "}" + - ")", - imports = ["com.london.presentation.shared.container.MediaLazyGridWithFilter", "com.london.presentation.shared.container.MediaGridConfig", "com.london.presentation.utils.MovieGenre", "com.london.presentation.utils.TvShowGenre"] - ), - level = DeprecationLevel.WARNING -) - -@Composable -fun TvShowLayOut( - tvShowUis: LazyPagingItems, - onSaveClick: (TvShow) -> Unit, - isTvShowSaved: (TvShow) -> Boolean, - onTvShowClick: (TvShow) -> Unit -) { - LazyVerticalGrid( - columns = GridCells.Fixed(gridColumns()), - modifier = Modifier - .fillMaxSize() - .padding(horizontal = 16.dp), - horizontalArrangement = Arrangement.spacedBy(12.dp), - verticalArrangement = Arrangement.spacedBy(12.dp), - contentPadding = PaddingValues(bottom = 16.dp) - ) { - items(tvShowUis.itemCount) { index -> - val tvShow = tvShowUis[index] - if (tvShow != null) { - HomeCard( - imageUrl = tvShow.posterPicture, - onSaveClick = { onSaveClick(tvShow) }, - isSaved = isTvShowSaved(tvShow), - imageDescription = tvShow.name, - modifier = Modifier.clickable { onTvShowClick(tvShow) } - ) - } - } - } -} From 51b4aa7b63ee21484da46c25c82923de8825ae78 Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 13:01:37 +0300 Subject: [PATCH 08/24] refactor: Replace MediaLazyGrid with MediaLazyVerticalGrid --- .../topmoviespicks/TopMoviesPicksScreen.kt | 19 +++++---- .../toptvshowspicks/TopTvShowsPicksScreen.kt | 17 +++++--- .../presentation/shared/LazyPagingColumn.kt | 40 ------------------- 3 files changed, 24 insertions(+), 52 deletions(-) delete mode 100644 presentation/src/main/java/com/london/presentation/shared/LazyPagingColumn.kt 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..4654db087 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 @@ -7,10 +7,11 @@ import androidx.compose.ui.res.stringResource import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.london.presentation.R -import com.london.presentation.shared.MediaLazyGrid +import com.london.presentation.shared.DefaultAppTopBar import com.london.presentation.shared.base.ErrorState import com.london.presentation.shared.bookmarkSheet.BookmarkBottomSheet import com.london.presentation.shared.buildscreen.BuildScreen +import com.london.presentation.shared.container.MediaLazyVerticalGrid import com.london.presentation.utils.Listen @Composable @@ -47,14 +48,18 @@ private fun Content( isError = state.errorState is ErrorState.NoInternet, onRetry = contract::onRetryClick, ) { - MediaLazyGrid( - title = stringResource(R.string.top_movies_picks), + MediaLazyVerticalGrid( items = state.movieDetails.mediaItems, - onBack = contract::onBackClick, - getImageUrl = { it.posterUrl }, + imageUrl = { it.posterUrl }, + hasSaveIcon = true, onItemClick = { contract.onMovieClick(it.id) }, - onSavedClick = { contract.onManageBookmarkClicked(it.id) }, - hasSaveIcon = true + onSaveClick = { contract.onManageBookmarkClicked(it.id) }, + topBar = { + DefaultAppTopBar( + title = stringResource(R.string.top_movies_picks), + onBackClick = contract::onBackClick + ) + } ) BookmarkBottomSheet( 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..9a2dcf672 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 @@ -7,9 +7,11 @@ import androidx.compose.ui.res.stringResource import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.london.presentation.R +import com.london.presentation.shared.DefaultAppTopBar import com.london.presentation.shared.MediaLazyGrid import com.london.presentation.shared.base.ErrorState import com.london.presentation.shared.buildscreen.BuildScreen +import com.london.presentation.shared.container.MediaLazyVerticalGrid import com.london.presentation.utils.Listen @Composable @@ -45,12 +47,17 @@ private fun Content( isError = state.errorState is ErrorState.NoInternet, onRetry = contract::onRetryClick ) { - MediaLazyGrid( - title = stringResource(R.string.top_tv_shows_picks), + MediaLazyVerticalGrid( items = state.tvShowDetails.mediaItems, - onBack = contract::onBackClick, - getImageUrl = { it.posterUrl }, - onItemClick = { contract.onTvShowClick(it.id) } + imageUrl = { it.posterUrl }, + onItemClick = { contract.onTvShowClick(it.id) }, + hasSaveIcon = false, + topBar = { + DefaultAppTopBar( + title = stringResource(R.string.top_tv_shows_picks), + onBackClick = contract::onBackClick, + ) + } ) } } diff --git a/presentation/src/main/java/com/london/presentation/shared/LazyPagingColumn.kt b/presentation/src/main/java/com/london/presentation/shared/LazyPagingColumn.kt deleted file mode 100644 index 6f1bc9793..000000000 --- a/presentation/src/main/java/com/london/presentation/shared/LazyPagingColumn.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.london.presentation.shared - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import androidx.paging.compose.LazyPagingItems - -@Composable -fun LazyPagingColumn( - pagingItems: LazyPagingItems, - modifier: Modifier = Modifier, - itemContent: @Composable (T) -> Unit, -) { - Content( - modifier = modifier, - items = pagingItems, - itemContent = itemContent - ) -} - -@Composable -private fun Content( - modifier: Modifier, - items: LazyPagingItems, - itemContent: @Composable (T) -> Unit -) { - Column( - modifier = modifier.fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(12.dp) - ) { - items.itemSnapshotList.forEach { item -> - if (item != null) { - itemContent(item) - } - } - } -} From 46eba7eee4cd4e9045a3b3540d858e1bb46e1610 Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 13:03:10 +0300 Subject: [PATCH 09/24] refactor: Remove deprecated MediaLazyGrid --- .../toptvshowspicks/TopTvShowsPicksScreen.kt | 1 - .../presentation/shared/MediaLazyGrid.kt | 137 ------------------ 2 files changed, 138 deletions(-) delete mode 100644 presentation/src/main/java/com/london/presentation/shared/MediaLazyGrid.kt 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 9a2dcf672..e975a52f8 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 @@ -8,7 +8,6 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.london.presentation.R import com.london.presentation.shared.DefaultAppTopBar -import com.london.presentation.shared.MediaLazyGrid import com.london.presentation.shared.base.ErrorState import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.shared.container.MediaLazyVerticalGrid diff --git a/presentation/src/main/java/com/london/presentation/shared/MediaLazyGrid.kt b/presentation/src/main/java/com/london/presentation/shared/MediaLazyGrid.kt deleted file mode 100644 index 06bcd7783..000000000 --- a/presentation/src/main/java/com/london/presentation/shared/MediaLazyGrid.kt +++ /dev/null @@ -1,137 +0,0 @@ -package com.london.presentation.shared - -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.navigationBarsPadding -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.wrapContentSize -import androidx.compose.foundation.lazy.grid.GridCells -import androidx.compose.foundation.lazy.grid.LazyVerticalGrid -import androidx.compose.foundation.lazy.grid.items -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.london.designsystem.component.CircularLoading -import com.london.designsystem.component.EmptyLayout -import com.london.designsystem.component.TopBar -import com.london.designsystem.theme.NovixTheme -import com.london.presentation.utils.gridColumns - -@Deprecated( - message = "Use MediaLazyVerticalGrid or MediaLazyGridWithFilter instead. This composable will be removed in a future version. Note: Both have two overloads - one for List and one for LazyPagingItems.", - replaceWith = ReplaceWith( - expression = "MediaLazyGridWithFilter(" + - "items = items, " + - "modifier = modifier, " + - "imageUrl = getImageUrl, " + - "name = { it.getName() }, " + - "onSaveClick = onSavedClick, " + - "isItemSaved = isItemSaved, " + - "onDeleteClick = onDeleteClick, " + - "onMovieGenreClick = {}, " + - "onTvShowGenreClick = {}, " + - "config = MediaGridConfig(" + - " showSaveIcon = hasSaveIcon, " + - " isDarkMode = isDarkMode, " + - " myRatingList = myRatingList, " + - " rate = rate, " + - " isMovieSelected = true, " + - " isTvShowSelected = false, " + - " selectedMovieGenre = MovieGenre.All, " + - " selectedTvShowGenre = TvShowGenre.All, " + - " onNavigateToMovie = onItemClick, " + - "), " + - "topBar = {" + - " DefaultAppTopBar(" + - " title = title," + - " onBack = onBack" + - " )" + - "}" + - ")", - imports = ["com.london.presentation.shared.container.MediaLazyGridWithFilter", "com.london.presentation.shared.container.MediaGridConfig", "com.london.presentation.utils.MovieGenre", "com.london.presentation.utils.TvShowGenre"] - ), - level = DeprecationLevel.WARNING -) - -@Composable -fun MediaLazyGrid( - title: String, - items: List, - onBack: () -> Unit, - getImageUrl: (T) -> String, - modifier: Modifier = Modifier, - onItemClick: (T) -> Unit = {}, - onSavedClick: (T) -> Unit = {}, - isItemSaved: (T) -> Boolean = { false }, - isLoading: Boolean = false, - emptyTitle: String = "", - emptyImage: Int? = null, - myRatingList: Boolean = false, - hasSaveIcon: Boolean = false, - rate: String = "5", - onDeleteClick: () -> Unit = {} -) { - Column( - modifier = modifier - .fillMaxSize() - .background(color = NovixTheme.colors.surface) - ) { - TopBar( - modifier = Modifier - .fillMaxWidth() - .padding(start = 16.dp, end = 16.dp, top = 12.dp), - title = title, - onBackClick = onBack - ) - - when { - isLoading -> CircularLoading( - modifier = Modifier - .fillMaxSize() - .wrapContentSize(Alignment.Center) - ) - - !isLoading && items.isEmpty() && emptyImage != null -> EmptyLayout( - text = emptyTitle, - image = emptyImage, - modifier = Modifier - .fillMaxSize() - .navigationBarsPadding() - ) - - else -> { - LazyVerticalGrid( - columns = GridCells.Fixed(gridColumns()), - contentPadding = PaddingValues( - top = 12.dp, - bottom = 16.dp - ), - horizontalArrangement = Arrangement.spacedBy(12.dp), - verticalArrangement = Arrangement.spacedBy(12.dp), - modifier = Modifier - .fillMaxSize() - .navigationBarsPadding() - .padding(horizontal = 16.dp) - ) { - items(items) { item -> - HomeCard( - imageUrl = getImageUrl(item), - isSaved = isItemSaved(item), - onSaveClick = { onSavedClick(item) }, - rate = rate, - onDeleteClick = onDeleteClick, - hasSaveIcon = hasSaveIcon, - modifier = Modifier.clickable { onItemClick(item) } - ) - } - } - } - } - } -} From ea15d094dd2054c53a581826011eb56eee82f15f Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 13:24:10 +0300 Subject: [PATCH 10/24] refactor: Apply consistent styling for BackgroundGradient --- .../london/presentation/feature/account/AccountScreen.kt | 6 ++++-- .../feature/authentication/login/LoginScreen.kt | 4 +++- .../feature/category/main/CategoriesScreen.kt | 6 ++++-- .../feature/category/movie/MovieCategoryScreen.kt | 8 +------- .../feature/category/tvshow/TvShowCategoryScreen.kt | 6 ++++-- .../feature/details/actor/ActorDetailsScreen.kt | 4 +++- .../details/actor/info/gallery/ActorsGalleryScreen.kt | 7 +++++-- .../feature/details/movie/MovieDetailsScreen.kt | 5 ++++- .../feature/home/trending/movie/TrendingMoviesScreen.kt | 6 ++++-- .../feature/home/trending/tvshow/TrendingTvShowsScreen.kt | 6 ++++-- .../london/presentation/feature/search/SearchScreen.kt | 3 +-- 11 files changed, 37 insertions(+), 24 deletions(-) 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 62172e728..e67a9282e 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 @@ -69,9 +69,11 @@ private fun Content( Box( modifier = Modifier.fillMaxSize() - ){ + ) { BackgroundGradient( - modifier = Modifier.align(Alignment.TopStart).zIndex(1f) + modifier = Modifier + .align(Alignment.TopStart) + .zIndex(1f) ) Column(Modifier.navBarBottomPadding()) { 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 bf73b42d9..41f44b304 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 @@ -89,7 +89,9 @@ private fun Content( ) { BackgroundGradient( - modifier = Modifier.align(Alignment.TopStart).zIndex(1f) + modifier = Modifier + .align(Alignment.TopStart) + .zIndex(1f) ) Image( 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 172116865..8ccd45409 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 @@ -71,9 +71,11 @@ private fun Content( Box( modifier = Modifier.fillMaxSize() - ){ + ) { BackgroundGradient( - modifier = Modifier.align(Alignment.TopStart).zIndex(1f) + modifier = Modifier + .align(Alignment.TopStart) + .zIndex(1f) ) Column(Modifier.navBarBottomPadding()) { 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 9cebff9c4..1c14ce7d4 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,8 +1,5 @@ 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.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -13,17 +10,14 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.zIndex -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 import androidx.paging.compose.collectAsLazyPagingItems import com.london.designsystem.theme.ThemePreviews import com.london.presentation.R -import com.london.presentation.shared.DefaultAppTopBar import com.london.presentation.shared.BackgroundGradient -import com.london.presentation.shared.MediaLazyPagingGrid +import com.london.presentation.shared.DefaultAppTopBar import com.london.presentation.shared.bookmarkSheet.BookmarkBottomSheet import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.shared.container.MediaLazyVerticalGrid 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 be9e9a9ef..235e95b45 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 @@ -68,9 +68,11 @@ private fun Content( Box( modifier = Modifier.fillMaxSize() - ){ + ) { BackgroundGradient( - modifier = Modifier.align(Alignment.TopStart).zIndex(1f) + modifier = Modifier + .align(Alignment.TopStart) + .zIndex(1f) ) Column( 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 774310ab4..6b1572a27 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 @@ -127,7 +127,9 @@ private fun Content( ) { BackgroundGradient( - modifier = Modifier.align(Alignment.TopStart).zIndex(1f) + modifier = Modifier + .align(Alignment.TopStart) + .zIndex(1f) ) EmptyScreen(uiState) 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 9b0dc1742..b876a4af1 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 @@ -66,10 +66,13 @@ private fun Content( Box( modifier = Modifier.fillMaxSize() - ){ + ) { BackgroundGradient( - modifier = Modifier.fillMaxSize().align(Alignment.TopStart).zIndex(1f) + modifier = Modifier + .fillMaxSize() + .align(Alignment.TopStart) + .zIndex(1f) ) Column( 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 74eee1b64..1a5bf0c84 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 @@ -161,7 +161,10 @@ private fun Content( ) { BackgroundGradient( - modifier = Modifier.fillMaxSize().align(Alignment.TopStart).zIndex(2f) + modifier = Modifier + .fillMaxSize() + .align(Alignment.TopStart) + .zIndex(2f) ) TopBar( 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 1722c2a41..6b42ce0e6 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 @@ -72,9 +72,11 @@ private fun Content( Box( modifier = Modifier.fillMaxSize() - ){ + ) { BackgroundGradient( - modifier = Modifier.align(Alignment.TopStart).zIndex(1f) + modifier = Modifier + .align(Alignment.TopStart) + .zIndex(1f) ) Column( modifier = Modifier 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 0e60d056f..9ecb93d39 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 @@ -73,9 +73,11 @@ private fun Content( Box( modifier = Modifier.fillMaxSize() - ){ + ) { BackgroundGradient( - modifier = Modifier.align(Alignment.TopStart).zIndex(1f) + modifier = Modifier + .align(Alignment.TopStart) + .zIndex(1f) ) Column( modifier = Modifier 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 99902528e..832151b96 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 @@ -60,14 +60,13 @@ import com.london.domain.entity.recent.RecentViewed 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.container.ActorLazyVerticalColumn -import com.london.presentation.shared.ActorsLayout import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.HomeCard import com.london.presentation.shared.base.ErrorState import com.london.presentation.shared.bookmarkSheet.BookmarkBottomSheet import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.shared.buildscreen.NetworkErrorScreen +import com.london.presentation.shared.container.ActorLazyVerticalColumn import com.london.presentation.shared.container.MediaLazyVerticalGrid import com.london.presentation.utils.Listen import com.london.presentation.utils.ResultOrEmpty From e911fe5ae16ef31d4da425a9b9353401bc677250 Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 14:05:33 +0300 Subject: [PATCH 11/24] refactor: Use MediaLazyVerticalGrid and update contract names --- .../category/tvshow/TvShowCategoryContract.kt | 2 +- .../category/tvshow/TvShowCategoryScreen.kt | 51 +++----- .../tvshow/TvShowCategoryViewModel.kt | 2 +- .../trending/movie/TrendingMoviesScreen.kt | 113 +++++++++--------- .../trending/tvshow/TrendingTvShowsScreen.kt | 95 ++++++++------- .../list/viewitems/ViewItemsContract.kt | 4 +- .../feature/list/viewitems/ViewItemsScreen.kt | 35 +++--- .../list/viewitems/ViewItemsViewModel.kt | 4 +- .../shared/MediaLazyPagingGrid.kt | 85 ------------- .../tvshow/TvShowCategoryViewModelTest.kt | 2 +- 10 files changed, 147 insertions(+), 246 deletions(-) delete mode 100644 presentation/src/main/java/com/london/presentation/shared/MediaLazyPagingGrid.kt diff --git a/presentation/src/main/java/com/london/presentation/feature/category/tvshow/TvShowCategoryContract.kt b/presentation/src/main/java/com/london/presentation/feature/category/tvshow/TvShowCategoryContract.kt index aa63e5d21..b9b2ae301 100644 --- a/presentation/src/main/java/com/london/presentation/feature/category/tvshow/TvShowCategoryContract.kt +++ b/presentation/src/main/java/com/london/presentation/feature/category/tvshow/TvShowCategoryContract.kt @@ -1,7 +1,7 @@ package com.london.presentation.feature.category.tvshow interface TvShowCategoryContract { - fun onBack() + fun onBackClick() fun onSavedClick(tvShowId: Int) fun onTvShowClick(tvShowId: Int) } 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 235e95b45..ef2ac5002 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,28 +1,25 @@ 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 -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 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.DefaultAppTopBar import com.london.presentation.shared.buildscreen.BuildScreen +import com.london.presentation.shared.container.MediaLazyVerticalGrid import com.london.presentation.utils.Listen import com.london.presentation.utils.isLoading @@ -58,7 +55,7 @@ private fun Content( val tvShowLazyList = state.tvShowFlow.collectAsLazyPagingItems() BuildScreen( - onBack = contract::onBack, + onBack = contract::onBackClick, isLoading = tvShowLazyList.isLoading(), isError = tvShowLazyList.loadState.refresh is LoadState.Error, onRetry = tvShowLazyList::refresh, @@ -75,32 +72,20 @@ private fun Content( .zIndex(1f) ) - 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) - ) - - 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 }, - ) - } + MediaLazyVerticalGrid( + pagingItems = tvShowLazyList, + imageUrl = { it.posterPicture }, + name = { it.name }, + hasSaveIcon = false, + onNavigateToTvShow = { id -> contract.onTvShowClick(id) }, + topBar = { + DefaultAppTopBar( + title = stringResource(state.genre.stringResId), + onBackClick = contract::onBackClick + ) + }, + modifier = Modifier.fillMaxWidth() + ) } } } @@ -114,7 +99,7 @@ private fun Preview() { contract = object : TvShowCategoryContract { override fun onSavedClick(tvShowId: Int) {} override fun onTvShowClick(tvShowId: Int) {} - override fun onBack() {} + override fun onBackClick() {} } ) } diff --git a/presentation/src/main/java/com/london/presentation/feature/category/tvshow/TvShowCategoryViewModel.kt b/presentation/src/main/java/com/london/presentation/feature/category/tvshow/TvShowCategoryViewModel.kt index 8a7ca8cdc..a2c9700e5 100644 --- a/presentation/src/main/java/com/london/presentation/feature/category/tvshow/TvShowCategoryViewModel.kt +++ b/presentation/src/main/java/com/london/presentation/feature/category/tvshow/TvShowCategoryViewModel.kt @@ -33,7 +33,7 @@ class TvShowCategoryViewModel @Inject constructor( override fun onTvShowClick(tvShowId: Int) = emitEffect(TvShowCategoryEffect.TvShowDetailsNavigation(tvShowId = tvShowId)) - override fun onBack() = + override fun onBackClick() = emitEffect(TvShowCategoryEffect.BackNavigation) override fun onSavedClick(tvShowId: Int) = Unit //TODO("Save Tv Show Not yet implemented") 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 6b42ce0e6..f972b4ac4 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 @@ -18,6 +18,7 @@ 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 import androidx.paging.compose.collectAsLazyPagingItems import com.london.designsystem.component.TopBar @@ -25,9 +26,9 @@ 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 import com.london.presentation.shared.buildscreen.BuildScreen +import com.london.presentation.shared.container.MediaLazyVerticalGrid import com.london.presentation.utils.Listen @Composable @@ -36,7 +37,7 @@ fun TrendingMoviesScreen( onNavigateToMovieDetails: (Int) -> Unit, viewModel: TrendingMoviesViewModel = hiltViewModel() ) { - val state by viewModel.state.collectAsState() + val state by viewModel.state.collectAsStateWithLifecycle() val effect by viewModel.effect.collectAsState(null) effect?.Listen { currentEffect -> @@ -48,19 +49,11 @@ fun TrendingMoviesScreen( is TrendingMoviesEffect.BackNavigation -> onNavigateBack() } } - BuildScreen( - isLoading = state.isLoading, - isError = state.moviesFlow.collectAsLazyPagingItems().loadState.refresh is LoadState.Error, - onBack = viewModel::onBackClick, - onRetry = viewModel::onRetryClick, - emptyLayoutMessage = R.string.no_trending_movies_in_genre, - emptyLayoutImage = R.drawable.img_no_result, - ) { - Content( - state = state, - contract = viewModel - ) - } + Content( + state = state, + contract = viewModel + ) + } @Composable @@ -70,53 +63,61 @@ private fun Content( ) { val screenWidth = with(LocalDensity.current) { LocalConfiguration.current.screenWidthDp.dp } - Box( - modifier = Modifier.fillMaxSize() + BuildScreen( + isLoading = state.isLoading, + isError = state.moviesFlow.collectAsLazyPagingItems().loadState.refresh is LoadState.Error, + onBack = contract::onBackClick, + onRetry = contract::onRetryClick, + emptyLayoutMessage = R.string.no_trending_movies_in_genre, + emptyLayoutImage = R.drawable.img_no_result, ) { - BackgroundGradient( - modifier = Modifier - .align(Alignment.TopStart) - .zIndex(1f) - ) - Column( - modifier = Modifier - .fillMaxSize() - .background(NovixTheme.colors.surface) + Box( + modifier = Modifier.fillMaxSize() ) { - TopBar( + BackgroundGradient( modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 12.dp), - title = stringResource(R.string.trending_movies), - onBackClick = contract::onBackClick + .align(Alignment.TopStart) + .zIndex(1f) ) - GenresSection( - genres = state.movieGenres, - selectedGenre = state.selectedGenre, - screenWidth = screenWidth, - onGenreClick = contract::onGenreClick, - modifier = Modifier.padding(bottom = 12.dp), - getGenreName = { stringResource(it.stringResId) } - ) - - 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(start = 16.dp, end = 16.dp, bottom = 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 - ) + MediaLazyVerticalGrid( + pagingItems = state.moviesFlow.collectAsLazyPagingItems(), + imageUrl = { it.posterPath }, + name = { it.title }, + hasSaveIcon = true, + onSaveClick = { contract.onManageBookmarkClicked(it.id) }, + onNavigateToMovie = { contract.onMovieClick(it) }, + modifier = Modifier + .weight(1f) + .fillMaxWidth() + ) + + 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 9ecb93d39..ec4a6189e 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 @@ -26,8 +26,8 @@ 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 +import com.london.presentation.shared.container.MediaLazyVerticalGrid import com.london.presentation.utils.Listen @Composable @@ -48,19 +48,11 @@ fun TrendingTvShowsScreen( is TrendingTvShowsEffect.BackNavigation -> onNavigateBack() } } + Content( + state = state, + contract = viewModel, + ) - BuildScreen( - isLoading = state.isLoading, - isError = state.tvShowsFlow.collectAsLazyPagingItems().loadState.refresh is LoadState.Error, - onBack = viewModel::onBackClick, - emptyLayoutMessage = R.string.no_trending_shows_in_genre, - emptyLayoutImage = R.drawable.img_no_result, - ) { - Content( - state = state, - contract = viewModel, - ) - } } @Composable @@ -71,46 +63,53 @@ private fun Content( val screenWidth = with(LocalDensity.current) { LocalConfiguration.current.screenWidthDp.dp } val tvShowsLazyItems = state.tvShowsFlow.collectAsLazyPagingItems() - Box( - modifier = Modifier.fillMaxSize() + BuildScreen( + isLoading = state.isLoading, + isError = state.tvShowsFlow.collectAsLazyPagingItems().loadState.refresh is LoadState.Error, + onBack = contract::onBackClick, + emptyLayoutMessage = R.string.no_trending_shows_in_genre, + emptyLayoutImage = R.drawable.img_no_result, ) { - BackgroundGradient( - modifier = Modifier - .align(Alignment.TopStart) - .zIndex(1f) - ) - Column( - modifier = Modifier - .fillMaxSize() - .background(NovixTheme.colors.surface) + Box( + modifier = Modifier.fillMaxSize() ) { - TopBar( + BackgroundGradient( 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) } + .align(Alignment.TopStart) + .zIndex(1f) ) - 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(start = 16.dp, end = 16.dp, bottom = 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) } + ) + + MediaLazyVerticalGrid( + pagingItems = tvShowsLazyItems, + imageUrl = { it.posterPath }, + name = { it.title }, + hasSaveIcon = false, + onNavigateToTvShow = { tvShowId -> contract.onTvShowClick(tvShowId) }, + modifier = Modifier + .weight(1f) + .fillMaxWidth() + ) + } } } } diff --git a/presentation/src/main/java/com/london/presentation/feature/list/viewitems/ViewItemsContract.kt b/presentation/src/main/java/com/london/presentation/feature/list/viewitems/ViewItemsContract.kt index 45b65befd..6cbbaf74c 100644 --- a/presentation/src/main/java/com/london/presentation/feature/list/viewitems/ViewItemsContract.kt +++ b/presentation/src/main/java/com/london/presentation/feature/list/viewitems/ViewItemsContract.kt @@ -1,8 +1,8 @@ package com.london.presentation.feature.list.viewitems interface ViewListItemsContract { - fun onBack() - fun onRetry() + fun onBackClick() + fun onRetryClick() fun onDeleteClick() fun onConfirmDelete() fun onMovieClick(id: Int) 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 c1b2becce..2164086bb 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 @@ -23,9 +23,9 @@ 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 +import com.london.presentation.shared.container.MediaLazyVerticalGrid import com.london.presentation.utils.Listen @Composable @@ -60,22 +60,24 @@ private fun Content( Box( modifier = Modifier.fillMaxSize() - ){ + ) { BackgroundGradient( - modifier = Modifier.align(Alignment.TopStart).zIndex(1f) + modifier = Modifier + .align(Alignment.TopStart) + .zIndex(1f) ) Column { TopBar( title = state.listTitle, - onBackClick = contract::onBack, + onBackClick = contract::onBackClick, option2Icon = R.drawable.ic_delete, onClickOption2 = contract::onDeleteClick, option2IconTint = NovixTheme.colors.redAccent, - modifier = Modifier - .padding(horizontal = 16.dp, vertical = 12.dp) - ) + modifier = Modifier.padding(start = 16.dp, end = 16.dp, bottom = 12.dp), + + ) BuildScreen( onBack = null, @@ -86,18 +88,17 @@ private fun Content( 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" }, + MediaLazyVerticalGrid( + pagingItems = listItems, + imageUrl = { it.posterUrl }, + name = { it.id.toString() }, + hasSaveIcon = true, onSaveClick = { contract.onRemoveMovieClick(it.id) - contract.onRetry() + contract.onRetryClick() }, isItemSaved = { true }, - hasSaveIcon = true + onNavigateToMovie = { id -> contract.onMovieClick(id) }, ) } } @@ -145,8 +146,8 @@ private fun Preview() { Content( state = ViewItemsUiState(), contract = object : ViewListItemsContract { - override fun onBack() {} - override fun onRetry() {} + override fun onBackClick() {} + override fun onRetryClick() {} override fun onDeleteClick() {} override fun onConfirmDelete() {} override fun onMovieClick(id: Int) {} diff --git a/presentation/src/main/java/com/london/presentation/feature/list/viewitems/ViewItemsViewModel.kt b/presentation/src/main/java/com/london/presentation/feature/list/viewitems/ViewItemsViewModel.kt index 79e5012f1..cde1f0a1c 100644 --- a/presentation/src/main/java/com/london/presentation/feature/list/viewitems/ViewItemsViewModel.kt +++ b/presentation/src/main/java/com/london/presentation/feature/list/viewitems/ViewItemsViewModel.kt @@ -35,11 +35,11 @@ class ViewItemsViewModel @Inject constructor( fetchMovieListDetails(listId = listId) } - override fun onBack() { + override fun onBackClick() { emitEffect(ViewItemsEffect.NavigateBack) } - override fun onRetry() { + override fun onRetryClick() { updateState { copy(error = null) } fetchMovieListDetails(listId) } diff --git a/presentation/src/main/java/com/london/presentation/shared/MediaLazyPagingGrid.kt b/presentation/src/main/java/com/london/presentation/shared/MediaLazyPagingGrid.kt deleted file mode 100644 index 0934df697..000000000 --- a/presentation/src/main/java/com/london/presentation/shared/MediaLazyPagingGrid.kt +++ /dev/null @@ -1,85 +0,0 @@ -package com.london.presentation.shared - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.lazy.grid.GridCells -import androidx.compose.foundation.lazy.grid.LazyVerticalGrid -import androidx.compose.foundation.lazy.grid.rememberLazyGridState -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import androidx.paging.compose.LazyPagingItems -import com.london.presentation.utils.gridColumns - -@Deprecated( - message = "Use MediaLazyVerticalGrid or MediaLazyGridWithFilter instead. This composable will be removed in a future version. Note: Both have two overloads - one for List and one for LazyPagingItems.", - replaceWith = ReplaceWith( - expression = "MediaLazyGridWithFilter(" + - "items = items, " + - "modifier = modifier, " + - "imageUrl = getImageUrl, " + - "name = { it.getName() }, " + - "onSaveClick = onSavedClick, " + - "isItemSaved = isItemSaved, " + - "onDeleteClick = onDeleteClick, " + - "onMovieGenreClick = {}, " + - "onTvShowGenreClick = {}, " + - "config = MediaGridConfig(" + - " showSaveIcon = hasSaveIcon, " + - " isDarkMode = isDarkMode, " + - " myRatingList = myRatingList, " + - " rate = rate, " + - " isMovieSelected = true, " + - " isTvShowSelected = false, " + - " selectedMovieGenre = MovieGenre.All, " + - " selectedTvShowGenre = TvShowGenre.All, " + - " onNavigateToMovie = onItemClick, " + - "), " + - "topBar = {" + - " DefaultAppTopBar(" + - " title = title," + - " onBack = onBack" + - " )" + - "}" + - ")", - imports = ["com.london.presentation.shared.container.MediaLazyGridWithFilter", "com.london.presentation.shared.container.MediaGridConfig", "com.london.presentation.utils.MovieGenre", "com.london.presentation.utils.TvShowGenre"] - ), - level = DeprecationLevel.WARNING -) - -@Composable -fun MediaLazyPagingGrid( - pagingFlow: LazyPagingItems, - onItemClick: (T) -> Unit, - getImageUrl: (T) -> String, - getTitle: (T) -> String, - modifier: Modifier = Modifier, - onSaveClick: (T) -> Unit = {}, - isItemSaved: (T) -> Boolean = { false }, - hasSaveIcon: Boolean = false, -) { - LazyVerticalGrid( - state = rememberLazyGridState(), - columns = GridCells.Fixed(gridColumns()), - modifier = modifier.fillMaxSize(), - horizontalArrangement = Arrangement.spacedBy(12.dp), - verticalArrangement = Arrangement.spacedBy(12.dp), - contentPadding = PaddingValues(bottom = 16.dp) - ) { - items(pagingFlow.itemCount) { index -> - val item = pagingFlow[index] - if (item != null) { - HomeCard( - imageUrl = getImageUrl(item), - hasSaveIcon = hasSaveIcon, - onSaveClick = { onSaveClick(item) }, - isSaved = isItemSaved(item), - imageDescription = getTitle(item), - modifier = Modifier.clickable { onItemClick(item) } - ) - } - } - } -} diff --git a/presentation/src/test/java/com/london/presentation/feature/category/tvshow/TvShowCategoryViewModelTest.kt b/presentation/src/test/java/com/london/presentation/feature/category/tvshow/TvShowCategoryViewModelTest.kt index 175838be7..f77741c59 100644 --- a/presentation/src/test/java/com/london/presentation/feature/category/tvshow/TvShowCategoryViewModelTest.kt +++ b/presentation/src/test/java/com/london/presentation/feature/category/tvshow/TvShowCategoryViewModelTest.kt @@ -125,7 +125,7 @@ class TvShowCategoryViewModelTest { fun `onMovieClick should emit NavigateBack effect`() = runTest { // When & Then viewModel?.effect?.test { - viewModel?.onBack() + viewModel?.onBackClick() assertThat(awaitItem()).isInstanceOf(TvShowCategoryEffect.BackNavigation::class.java) cancelAndIgnoreRemainingEvents() } From 47d9ce924fcd67cd7eb6dc9064382ea82adf9402 Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 14:32:10 +0300 Subject: [PATCH 12/24] refactor: Standardize item click handling in MediaLazyVerticalGrid and HomeCard --- .../feature/details/actor/ActorDetailsScreen.kt | 1 - .../home/trending/movie/TrendingMoviesScreen.kt | 2 +- .../home/trending/tvshow/TrendingTvShowsScreen.kt | 2 +- .../java/com/london/presentation/shared/HomeCard.kt | 2 +- .../shared/container/MediaLazyVerticalGrid.kt | 13 ++++++++++--- 5 files changed, 13 insertions(+), 7 deletions(-) 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 6b1572a27..44ce0605c 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 @@ -338,7 +338,6 @@ private fun TopTvShowsPicksList( imageUrl = tvShow[index].posterUrl, isSaved = false, hasSaveIcon = false, - onSaveClick = {}, modifier = Modifier.clickable { onNavigateToTvShowPicks(tvShow[index].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 f972b4ac4..a8e1ddfd4 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 @@ -106,7 +106,7 @@ private fun Content( name = { it.title }, hasSaveIcon = true, onSaveClick = { contract.onManageBookmarkClicked(it.id) }, - onNavigateToMovie = { contract.onMovieClick(it) }, + onItemClick = { item -> contract.onMovieClick(item.id) }, modifier = Modifier .weight(1f) .fillMaxWidth() 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 ec4a6189e..4c9a2ae79 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 @@ -104,7 +104,7 @@ private fun Content( imageUrl = { it.posterPath }, name = { it.title }, hasSaveIcon = false, - onNavigateToTvShow = { tvShowId -> contract.onTvShowClick(tvShowId) }, + onItemClick = { item -> contract.onTvShowClick(item.id) }, modifier = Modifier .weight(1f) .fillMaxWidth() diff --git a/presentation/src/main/java/com/london/presentation/shared/HomeCard.kt b/presentation/src/main/java/com/london/presentation/shared/HomeCard.kt index cb8793e5c..fe35d8b6f 100644 --- a/presentation/src/main/java/com/london/presentation/shared/HomeCard.kt +++ b/presentation/src/main/java/com/london/presentation/shared/HomeCard.kt @@ -29,9 +29,9 @@ fun HomeCard( imageUrl: Any, modifier: Modifier = Modifier, rate: String? = null, - onSaveClick: () -> Unit, isSaved: Boolean = false, hasSaveIcon: Boolean = true, + onSaveClick: () -> Unit = {}, onDeleteClick: () -> Unit = {}, imageDescription: String? = null, hasOverlay: Boolean = false diff --git a/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyVerticalGrid.kt b/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyVerticalGrid.kt index 1a5bec7ca..82f5b5b3e 100644 --- a/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyVerticalGrid.kt +++ b/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyVerticalGrid.kt @@ -84,6 +84,7 @@ fun MediaLazyVerticalGrid( hasSaveIcon: Boolean = true, onSaveClick: (T) -> Unit = {}, isItemSaved: (T) -> Boolean = { false }, + onItemClick: ((T) -> Unit)? = null, onDeleteClick: (T) -> Unit = {}, topBar: @Composable (() -> Unit)? = null, onNavigateToMovie: (Int) -> Unit = {}, @@ -111,6 +112,7 @@ fun MediaLazyVerticalGrid( isItemSaved = isItemSaved, hasSaveIcon = hasSaveIcon, onSaveClick = onSaveClick, + onItemClick = onItemClick, onDeleteClick = onDeleteClick, rate = rate, onNavigateToMovie = onNavigateToMovie, @@ -154,6 +156,7 @@ private fun RenderPagingGridItem( isItemSaved: (T) -> Boolean, hasSaveIcon: Boolean, onSaveClick: (T) -> Unit, + onItemClick: ((T) -> Unit)?, onDeleteClick: (T) -> Unit, rate: (T) -> String?, onNavigateToMovie: (Int) -> Unit, @@ -164,9 +167,13 @@ private fun RenderPagingGridItem( HomeCard( imageUrl = it, modifier = Modifier.clickable { - when (item) { - is Movie -> onNavigateToMovie(item.id) - is TvShow -> onNavigateToTvShow(item.id) + if (onItemClick != null) { + onItemClick(item) + } else { + when (item) { + is Movie -> onNavigateToMovie(item.id) + is TvShow -> onNavigateToTvShow(item.id) + } } }, imageDescription = name(item), From 22085e5709c821f9b0cabd0ab6c521927c5ada7c Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 14:44:08 +0300 Subject: [PATCH 13/24] refactor: Apply `detailsTopBar` modifier to top bars --- .../feature/home/trending/actor/TrendingActorsScreen.kt | 8 +++----- .../feature/home/trending/movie/TrendingMoviesScreen.kt | 8 ++++---- .../feature/home/trending/tvshow/TrendingTvShowsScreen.kt | 5 ++--- .../com/london/presentation/shared/DefaultAppTopBar.kt | 5 ++--- 4 files changed, 11 insertions(+), 15 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 636617c9d..05aae5ad4 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 @@ -26,6 +26,7 @@ import com.london.presentation.shared.BackgroundGradient import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.shared.container.ActorLazyVerticalColumn import com.london.presentation.utils.Listen +import com.london.presentation.utils.detailsTopBar import com.london.presentation.utils.isLoading @Composable @@ -85,11 +86,8 @@ private fun Content( TopBar( title = stringResource(com.london.designsystem.R.string.tv_shows), onBackClick = contract::onBackClick, - modifier = Modifier - .fillMaxWidth() - .background(NovixTheme.colors.surface) - .padding(start = 16.dp, end = 16.dp, bottom = 8.dp) - ) + modifier = Modifier.detailsTopBar(1f), + ) ActorLazyVerticalColumn( items = actorsLazyItems, 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 a8e1ddfd4..eb13063b6 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 @@ -30,6 +30,7 @@ import com.london.presentation.shared.bookmarkSheet.BookmarkBottomSheet import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.shared.container.MediaLazyVerticalGrid import com.london.presentation.utils.Listen +import com.london.presentation.utils.detailsTopBar @Composable fun TrendingMoviesScreen( @@ -84,10 +85,9 @@ private fun Content( .fillMaxSize() .background(NovixTheme.colors.surface) ) { + TopBar( - modifier = Modifier - .fillMaxWidth() - .padding(start = 16.dp, end = 16.dp, bottom = 12.dp), + modifier = Modifier.detailsTopBar(1f), title = stringResource(R.string.trending_movies), onBackClick = contract::onBackClick ) @@ -96,7 +96,7 @@ private fun Content( selectedGenre = state.selectedGenre, screenWidth = screenWidth, onGenreClick = contract::onGenreClick, - modifier = Modifier.padding(bottom = 12.dp), + modifier = Modifier.padding(vertical = 12.dp), getGenreName = { stringResource(it.stringResId) } ) 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 4c9a2ae79..da29d1606 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 @@ -29,6 +29,7 @@ import com.london.presentation.shared.GenresSection import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.shared.container.MediaLazyVerticalGrid import com.london.presentation.utils.Listen +import com.london.presentation.utils.detailsTopBar @Composable fun TrendingTvShowsScreen( @@ -84,9 +85,7 @@ private fun Content( .background(NovixTheme.colors.surface) ) { TopBar( - modifier = Modifier - .fillMaxWidth() - .padding(start = 16.dp, end = 16.dp, bottom = 12.dp), + modifier = Modifier.detailsTopBar(1f), title = stringResource(R.string.trending_tv_shows), onBackClick = contract::onBackClick ) diff --git a/presentation/src/main/java/com/london/presentation/shared/DefaultAppTopBar.kt b/presentation/src/main/java/com/london/presentation/shared/DefaultAppTopBar.kt index e3ee80011..b001d78bf 100644 --- a/presentation/src/main/java/com/london/presentation/shared/DefaultAppTopBar.kt +++ b/presentation/src/main/java/com/london/presentation/shared/DefaultAppTopBar.kt @@ -6,6 +6,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.london.designsystem.component.TopBar +import com.london.presentation.utils.detailsTopBar @Composable fun DefaultAppTopBar( @@ -13,9 +14,7 @@ fun DefaultAppTopBar( onBackClick: () -> Unit, ) { TopBar( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 8.dp), + modifier = Modifier.detailsTopBar(1f), title = title, onBackClick = onBackClick ) From e489f2200e7f5530079da56220d4316f24fb58da Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 17:05:30 +0300 Subject: [PATCH 14/24] refactor: Remove DefaultAppTopBar and use TopBar directly --- .../feature/account/rating/MyRatingScreen.kt | 15 ++++++++----- .../ContinueWatchingScreen.kt | 11 ++++++++-- .../presentation/shared/DefaultAppTopBar.kt | 21 ------------------- 3 files changed, 19 insertions(+), 28 deletions(-) delete mode 100644 presentation/src/main/java/com/london/presentation/shared/DefaultAppTopBar.kt 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 863d42e0b..cbb334972 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 @@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -31,6 +32,7 @@ import com.london.presentation.shared.base.ErrorState import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.shared.container.MediaLazyVerticalGrid import com.london.presentation.utils.Listen +import com.london.presentation.utils.detailsTopBar import com.london.presentation.utils.toLocalizedNumbers import com.london.designsystem.R as dsR @@ -80,6 +82,7 @@ private fun Content( onBack = contract::onBackClick, onRetry = contract::onRetryClick ) { + Box( modifier = Modifier.fillMaxSize() ) { @@ -90,12 +93,14 @@ private fun Content( ) Column( - modifier = Modifier.fillMaxSize() + modifier = Modifier + .fillMaxSize() + .navigationBarsPadding() + .padding(bottom = 16.dp) + ) { TopBar( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 12.dp), + modifier = Modifier.detailsTopBar(1f), title = stringResource(R.string.my_rating), onBackClick = contract::onBackClick ) @@ -103,7 +108,7 @@ private fun Content( RatingChipsRow( selected = selectedCategory, onSelect = contract::onRatingCategorySelected, - modifier = Modifier.padding(bottom = 12.dp) + modifier = Modifier.padding(vertical = 12.dp) ) if (items.isEmpty()) { 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 e2121922a..3a057f0d6 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 @@ -4,20 +4,23 @@ 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.navigationBarsPadding +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 com.london.designsystem.component.TopBar 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 import com.london.presentation.shared.bookmarkSheet.BookmarkBottomSheet @@ -25,6 +28,7 @@ import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.shared.container.MediaGridConfig import com.london.presentation.shared.container.MediaLazyGridWithTabs import com.london.presentation.utils.Listen +import com.london.presentation.utils.detailsTopBar @Composable fun ContinueWatchingScreen( @@ -83,6 +87,8 @@ private fun Content( Column( modifier = Modifier .fillMaxSize() + .navigationBarsPadding() + .padding(bottom = 16.dp) .background(color = NovixTheme.colors.surface) ) { MediaLazyGridWithTabs( @@ -104,7 +110,8 @@ private fun Content( isItemSaved = { false } ), topBar = { - DefaultAppTopBar( + TopBar( + modifier = Modifier.detailsTopBar(1f), title = screenTitle, onBackClick = contract::onBackClick ) diff --git a/presentation/src/main/java/com/london/presentation/shared/DefaultAppTopBar.kt b/presentation/src/main/java/com/london/presentation/shared/DefaultAppTopBar.kt deleted file mode 100644 index b001d78bf..000000000 --- a/presentation/src/main/java/com/london/presentation/shared/DefaultAppTopBar.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.london.presentation.shared - -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.london.designsystem.component.TopBar -import com.london.presentation.utils.detailsTopBar - -@Composable -fun DefaultAppTopBar( - title: String, - onBackClick: () -> Unit, -) { - TopBar( - modifier = Modifier.detailsTopBar(1f), - title = title, - onBackClick = onBackClick - ) -} From 5f2e6a37d5719983c362536768025cf7673c93b6 Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 17:11:41 +0300 Subject: [PATCH 15/24] refactor: Use DesignSystem TopBar and add padding --- .../category/movie/MovieCategoryScreen.kt | 16 +++++++++++++--- .../category/tvshow/TvShowCategoryScreen.kt | 17 +++++++++++++---- 2 files changed, 26 insertions(+), 7 deletions(-) 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 1c14ce7d4..6468f6755 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 @@ -3,25 +3,29 @@ package com.london.presentation.feature.category.movie import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.navigationBarsPadding +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 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.DefaultAppTopBar import com.london.presentation.shared.bookmarkSheet.BookmarkBottomSheet import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.shared.container.MediaLazyVerticalGrid import com.london.presentation.utils.Listen +import com.london.presentation.utils.detailsTopBar import com.london.presentation.utils.isLoading @Composable @@ -65,7 +69,10 @@ private fun Content( emptyLayoutImage = R.drawable.empty ) { Box( - modifier = Modifier.fillMaxSize() + modifier = Modifier + .fillMaxSize() + .navigationBarsPadding() + .padding(bottom = 16.dp) ) { BackgroundGradient( modifier = Modifier @@ -82,7 +89,10 @@ private fun Content( isItemSaved = { false }, onNavigateToMovie = { id -> contract.onMovieClick(id) }, topBar = { - DefaultAppTopBar( + TopBar( + modifier = Modifier + .detailsTopBar(1f) + .padding(bottom = 12.dp), title = stringResource(state.genre.stringResId), onBackClick = contract::onBackClick ) 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 ef2ac5002..0e4fce800 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 @@ -3,24 +3,28 @@ package com.london.presentation.feature.category.tvshow import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.navigationBarsPadding +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 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.DefaultAppTopBar import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.shared.container.MediaLazyVerticalGrid import com.london.presentation.utils.Listen +import com.london.presentation.utils.detailsTopBar import com.london.presentation.utils.isLoading @Composable @@ -62,9 +66,11 @@ private fun Content( emptyLayoutMessage = R.string.there_is_no_items_for_this_genre, emptyLayoutImage = R.drawable.empty ) { - Box( - modifier = Modifier.fillMaxSize() + modifier = Modifier + .fillMaxSize() + .navigationBarsPadding() + .padding(bottom = 16.dp) ) { BackgroundGradient( modifier = Modifier @@ -79,7 +85,10 @@ private fun Content( hasSaveIcon = false, onNavigateToTvShow = { id -> contract.onTvShowClick(id) }, topBar = { - DefaultAppTopBar( + TopBar( + modifier = Modifier + .detailsTopBar(1f) + .padding(bottom = 12.dp), title = stringResource(state.genre.stringResId), onBackClick = contract::onBackClick ) From f3bee9edfb693f564edb196368d0780c62224c42 Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 17:20:12 +0300 Subject: [PATCH 16/24] refactor: Use design system TopBar in TopMoviesPicksScreen and TopTvShowsPicksScreen --- .../info/topmoviespicks/TopMoviesPicksScreen.kt | 16 +++++++++++++--- .../toptvshowspicks/TopTvShowsPicksScreen.kt | 17 +++++++++++++---- 2 files changed, 26 insertions(+), 7 deletions(-) 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 00f2bd1f6..adc82fff9 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 @@ -2,23 +2,27 @@ package com.london.presentation.feature.details.actor.info.topmoviespicks import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.navigationBarsPadding +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 com.london.designsystem.component.TopBar import com.london.presentation.R import com.london.presentation.shared.BackgroundGradient -import com.london.presentation.shared.DefaultAppTopBar import com.london.presentation.shared.base.ErrorState import com.london.presentation.shared.bookmarkSheet.BookmarkBottomSheet import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.shared.container.MediaLazyVerticalGrid import com.london.presentation.utils.Listen +import com.london.presentation.utils.detailsTopBar @Composable fun TopMoviesPicksScreen( @@ -55,7 +59,10 @@ private fun Content( onRetry = contract::onRetryClick, ) { Box( - modifier = Modifier.fillMaxSize() + modifier = Modifier + .fillMaxSize() + .navigationBarsPadding() + .padding(bottom = 16.dp) ) { BackgroundGradient( @@ -70,7 +77,10 @@ private fun Content( onItemClick = { contract.onMovieClick(it.id) }, onSaveClick = { contract.onManageBookmarkClicked(it.id) }, topBar = { - DefaultAppTopBar( + TopBar( + modifier = Modifier + .detailsTopBar(1f) + .padding(bottom = 12.dp), title = stringResource(R.string.top_movies_picks), onBackClick = contract::onBackClick ) 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 4bbbf8b2d..6903f079e 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 @@ -2,22 +2,26 @@ package com.london.presentation.feature.details.actor.info.toptvshowspicks import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.navigationBarsPadding +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 com.london.designsystem.component.TopBar import com.london.presentation.R import com.london.presentation.shared.BackgroundGradient -import com.london.presentation.shared.DefaultAppTopBar import com.london.presentation.shared.base.ErrorState import com.london.presentation.shared.buildscreen.BuildScreen import com.london.presentation.shared.container.MediaLazyVerticalGrid import com.london.presentation.utils.Listen +import com.london.presentation.utils.detailsTopBar @Composable fun TopTvShowsPicksScreen( @@ -52,9 +56,11 @@ private fun Content( isError = state.errorState is ErrorState.NoInternet, onRetry = contract::onRetryClick ) { - Box( - modifier = Modifier.fillMaxSize() + modifier = Modifier + .fillMaxSize() + .navigationBarsPadding() + .padding(bottom = 16.dp) ) { BackgroundGradient( modifier = Modifier @@ -67,7 +73,10 @@ private fun Content( onItemClick = { contract.onTvShowClick(it.id) }, hasSaveIcon = false, topBar = { - DefaultAppTopBar( + TopBar( + modifier = Modifier + .detailsTopBar(1f) + .padding(bottom = 12.dp), title = stringResource(R.string.top_tv_shows_picks), onBackClick = contract::onBackClick, ) From 3879a77d1fe6c255c59ccb006bfa5e374ab20b45 Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 17:23:11 +0300 Subject: [PATCH 17/24] fix: Adjust vertical padding in TrendingTvShowsScreen --- .../feature/home/trending/tvshow/TrendingTvShowsScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 da29d1606..f1cb8598a 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 @@ -94,7 +94,7 @@ private fun Content( selectedGenre = state.selectedGenre, screenWidth = screenWidth, onGenreClick = contract::onGenreClick, - modifier = Modifier.padding(bottom = 12.dp), + modifier = Modifier.padding(vertical = 12.dp), getGenreName = { stringResource(it.stringResId) } ) From 59474991bde136368a2cbddf5e8b14cc6a8b78cc Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 17:25:16 +0300 Subject: [PATCH 18/24] fix: Adjust padding in SearchScreen and MediaLazyVerticalGrid --- .../presentation/feature/search/SearchScreen.kt | 12 ++++++------ .../shared/container/MediaLazyVerticalGrid.kt | 4 +++- 2 files changed, 9 insertions(+), 7 deletions(-) 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 832151b96..c7734a414 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 @@ -201,7 +201,7 @@ private fun SearchBody( content = { SearchChipsRow( selected = state.selectedCategory, - onSelect = contract::onCategorySelected + onSelect = contract::onCategorySelected, ) } ) @@ -306,8 +306,8 @@ private fun ActorSearchContent(state: SearchUiState, contract: SearchContract) { emptyContent = { if (!isLoading) { EmptyLayout( - text = stringResource(R.string.start_exploring_msg), - image = R.drawable.imge_explore, + text = stringResource(R.string.no_search_result_msg), + image = R.drawable.img_no_search_result, modifier = Modifier .fillMaxSize() .padding(horizontal = 16.dp) @@ -342,8 +342,8 @@ private fun MediaSearchContent( emptyContent = { if (!isLoading) { EmptyLayout( - text = stringResource(R.string.start_exploring_msg), - image = R.drawable.imge_explore, + text = stringResource(R.string.no_search_result_msg), + image = R.drawable.img_no_search_result, modifier = Modifier .fillMaxSize() .padding(horizontal = 16.dp) @@ -667,7 +667,7 @@ private fun SearchChipsRow( Row( modifier = modifier .fillMaxWidth() - .padding(horizontal = 16.dp), + .padding(start = 16.dp, end = 16.dp, bottom = 12.dp), horizontalArrangement = Arrangement.spacedBy(8.dp), ) { SearchCategory.entries.forEach { category -> diff --git a/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyVerticalGrid.kt b/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyVerticalGrid.kt index 82f5b5b3e..3f52f3d5a 100644 --- a/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyVerticalGrid.kt +++ b/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyVerticalGrid.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyGridScope import androidx.compose.foundation.lazy.grid.LazyVerticalGrid @@ -132,6 +133,7 @@ private fun MediaGridContainer( modifier = modifier .fillMaxSize() .background(color = NovixTheme.colors.surface) + .navigationBarsPadding() ) { topBar?.invoke() @@ -141,7 +143,7 @@ private fun MediaGridContainer( modifier = Modifier.fillMaxSize(), horizontalArrangement = Arrangement.spacedBy(12.dp), verticalArrangement = Arrangement.spacedBy(12.dp), - contentPadding = PaddingValues(start = 16.dp, end = 16.dp, bottom = 16.dp, top = 12.dp), + contentPadding = PaddingValues(start = 16.dp, end = 16.dp, bottom = 16.dp), content = content ) } From c30f735c6807255f3c6a248aa9d17ba245246f7e Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 17:40:22 +0300 Subject: [PATCH 19/24] refactor: Delete unused MediaLazyPagingGrid --- .../java/com/london/presentation/shared/MediaLazyPagingGrid.kt | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 presentation/src/main/java/com/london/presentation/shared/MediaLazyPagingGrid.kt diff --git a/presentation/src/main/java/com/london/presentation/shared/MediaLazyPagingGrid.kt b/presentation/src/main/java/com/london/presentation/shared/MediaLazyPagingGrid.kt deleted file mode 100644 index e69de29bb..000000000 From d275507628adfc9c1ee598fb40e134b865089ee1 Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 18:47:48 +0300 Subject: [PATCH 20/24] refactor: Remove redundant padding and apply in MediaLazyVerticalGrid --- .../feature/account/rating/MyRatingScreen.kt | 6 +- .../category/movie/MovieCategoryScreen.kt | 6 +- .../category/tvshow/TvShowCategoryScreen.kt | 6 +- .../topmoviespicks/TopMoviesPicksScreen.kt | 6 +- .../toptvshowspicks/TopTvShowsPicksScreen.kt | 6 +- .../ContinueWatchingScreen.kt | 2 - .../feature/search/SearchScreen.kt | 102 +++++++++--------- .../shared/container/MediaLazyVerticalGrid.kt | 4 +- 8 files changed, 57 insertions(+), 81 deletions(-) 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 cbb334972..8faeb8833 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 @@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -93,10 +92,7 @@ private fun Content( ) Column( - modifier = Modifier - .fillMaxSize() - .navigationBarsPadding() - .padding(bottom = 16.dp) + modifier = Modifier.fillMaxSize() ) { TopBar( 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 6468f6755..e5c160e0e 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 @@ -3,7 +3,6 @@ package com.london.presentation.feature.category.movie import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -69,10 +68,7 @@ private fun Content( emptyLayoutImage = R.drawable.empty ) { Box( - modifier = Modifier - .fillMaxSize() - .navigationBarsPadding() - .padding(bottom = 16.dp) + modifier = Modifier.fillMaxSize() ) { BackgroundGradient( modifier = Modifier 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 0e4fce800..7738eb358 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 @@ -3,7 +3,6 @@ package com.london.presentation.feature.category.tvshow import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -67,10 +66,7 @@ private fun Content( emptyLayoutImage = R.drawable.empty ) { Box( - modifier = Modifier - .fillMaxSize() - .navigationBarsPadding() - .padding(bottom = 16.dp) + modifier = Modifier.fillMaxSize() ) { BackgroundGradient( modifier = Modifier 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 adc82fff9..9a77121ca 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 @@ -2,7 +2,6 @@ package com.london.presentation.feature.details.actor.info.topmoviespicks import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -59,10 +58,7 @@ private fun Content( onRetry = contract::onRetryClick, ) { Box( - modifier = Modifier - .fillMaxSize() - .navigationBarsPadding() - .padding(bottom = 16.dp) + modifier = Modifier.fillMaxSize() ) { BackgroundGradient( 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 6903f079e..226b42681 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 @@ -2,7 +2,6 @@ package com.london.presentation.feature.details.actor.info.toptvshowspicks import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -57,10 +56,7 @@ private fun Content( onRetry = contract::onRetryClick ) { Box( - modifier = Modifier - .fillMaxSize() - .navigationBarsPadding() - .padding(bottom = 16.dp) + modifier = Modifier.fillMaxSize() ) { BackgroundGradient( 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 3a057f0d6..05806cd0b 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 @@ -87,8 +87,6 @@ private fun Content( Column( modifier = Modifier .fillMaxSize() - .navigationBarsPadding() - .padding(bottom = 16.dp) .background(color = NovixTheme.colors.surface) ) { MediaLazyGridWithTabs( 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 c7734a414..b3f5367eb 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 @@ -113,6 +113,23 @@ private fun Content( val interactionSource = remember { MutableInteractionSource() } val focusManager = LocalFocusManager.current + SearchMainContent( + state = state, + contract = contract, + interactionSource = interactionSource, + keyboardController = keyboardController, + onClearFocus = { focusManager.clearFocus() } + ) +} + +@Composable +private fun SearchMainContent( + state: SearchUiState, + contract: SearchContract, + interactionSource: MutableInteractionSource, + keyboardController: SoftwareKeyboardController?, + onClearFocus: () -> Unit +) { val currentPagingFlow = when (state.selectedCategory) { SearchCategory.Movies -> state.moviesFlow.collectAsLazyPagingItems() SearchCategory.TvShows -> state.tvShowsFlow.collectAsLazyPagingItems() @@ -126,65 +143,48 @@ private fun Content( pagingFlow = currentPagingFlow, handlePagingLoadingAutomatically = false ) { - SearchMainContent( - state = state, - contract = contract, - interactionSource = interactionSource, - keyboardController = keyboardController, - onClearFocus = { focusManager.clearFocus() } - ) - } -} - -@Composable -private fun SearchMainContent( - state: SearchUiState, - contract: SearchContract, - interactionSource: MutableInteractionSource, - keyboardController: SoftwareKeyboardController?, - onClearFocus: () -> Unit, -) { - Box( - modifier = Modifier - .fillMaxSize() - .navBarBottomPadding() - .pointerInput(Unit) { detectTapGestures(onTap = { onClearFocus() }) } - ) { - - BackgroundGradient( - modifier = Modifier - .align(Alignment.TopStart) - .zIndex(1f) - ) - - Column( + Box( modifier = Modifier .fillMaxSize() - .background(NovixTheme.colors.surface), - verticalArrangement = Arrangement.Top + .navBarBottomPadding() + .pointerInput(Unit) { detectTapGestures(onTap = { onClearFocus() }) } ) { - TopBar( - modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp), - title = stringResource(R.string.search), - ) - SearchBar( - uiState = state, - contract = contract, - interactionSource = interactionSource, - keyboardController = keyboardController, + BackgroundGradient( modifier = Modifier - .padding(start = 16.dp, end = 16.dp, bottom = 12.dp) - .fillMaxWidth() + .align(Alignment.TopStart) + .zIndex(1f) ) - SearchBody(state = state, contract = contract) + Column( + modifier = Modifier + .fillMaxSize() + .background(NovixTheme.colors.surface), + verticalArrangement = Arrangement.Top + ) { + TopBar( + modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp), + title = stringResource(R.string.search), + ) - BookmarkBottomSheet( - onSheetDismiss = contract::onBookmarkSheetDismiss, - isSheetVisible = state.isBookmarkSheetVisible, - bookmarkedMovieId = state.bookmarkedMovieId - ) + SearchBar( + uiState = state, + contract = contract, + interactionSource = interactionSource, + keyboardController = keyboardController, + modifier = Modifier + .padding(start = 16.dp, end = 16.dp, bottom = 12.dp) + .fillMaxWidth() + ) + + SearchBody(state = state, contract = contract) + + BookmarkBottomSheet( + onSheetDismiss = contract::onBookmarkSheetDismiss, + isSheetVisible = state.isBookmarkSheetVisible, + bookmarkedMovieId = state.bookmarkedMovieId + ) + } } } } diff --git a/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyVerticalGrid.kt b/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyVerticalGrid.kt index 3f52f3d5a..d0ac3eeaa 100644 --- a/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyVerticalGrid.kt +++ b/presentation/src/main/java/com/london/presentation/shared/container/MediaLazyVerticalGrid.kt @@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyGridScope import androidx.compose.foundation.lazy.grid.LazyVerticalGrid @@ -133,7 +132,6 @@ private fun MediaGridContainer( modifier = modifier .fillMaxSize() .background(color = NovixTheme.colors.surface) - .navigationBarsPadding() ) { topBar?.invoke() @@ -143,7 +141,7 @@ private fun MediaGridContainer( modifier = Modifier.fillMaxSize(), horizontalArrangement = Arrangement.spacedBy(12.dp), verticalArrangement = Arrangement.spacedBy(12.dp), - contentPadding = PaddingValues(start = 16.dp, end = 16.dp, bottom = 16.dp), + contentPadding = PaddingValues(start = 16.dp, end = 16.dp, bottom = 24.dp), content = content ) } From b5679c630b6b14981d5bc67cd2bc79ed4690f45f Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 18:52:54 +0300 Subject: [PATCH 21/24] fix: Correct TrendingActorsScreen title --- .../feature/home/trending/actor/TrendingActorsScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 8d00202ce..e3f7b5c30 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 @@ -86,7 +86,7 @@ private fun Content( .background(color = NovixTheme.colors.surface) ) { TopBar( - title = stringResource(com.london.designsystem.R.string.tv_shows), + title = stringResource(R.string.trending_people), onBackClick = contract::onBackClick, modifier = Modifier.detailsTopBar(1f), ) From b19ac15003a60c24b77a89795e3cb83264af4ba3 Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 19:04:21 +0300 Subject: [PATCH 22/24] refactor: Simplify ActorsGalleryScreen structure --- .../actor/info/gallery/ActorsGalleryScreen.kt | 75 +++++++++---------- 1 file changed, 37 insertions(+), 38 deletions(-) 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 b876a4af1..f4fc8579a 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 @@ -45,54 +45,53 @@ fun ActorsGalleryScreen( effect.Listen { onNavigateBack() } - BuildScreen( - onBack = viewModel::onBackClick, - isLoading = uiState.isLoading, - isError = uiState.error != null, - onRetry = viewModel::onRetryClick - ) { - Content( - uiState = uiState, - actorsGalleryContract = viewModel - ) - } + Content( + uiState = uiState, + contract = viewModel + ) } @Composable private fun Content( uiState: ActorsGalleryUiState, - actorsGalleryContract: ActorsGalleryContract + contract: ActorsGalleryContract ) { - - Box( - modifier = Modifier.fillMaxSize() + BuildScreen( + onBack = contract::onBackClick, + isLoading = uiState.isLoading, + isError = uiState.error != null, + onRetry = contract::onRetryClick ) { - - BackgroundGradient( - modifier = Modifier - .fillMaxSize() - .align(Alignment.TopStart) - .zIndex(1f) - ) - - Column( - modifier = Modifier - .fillMaxSize() - .background(NovixTheme.colors.surface) - .navigationBarsPadding() - .padding(horizontal = 16.dp, vertical = 12.dp), + Box( + modifier = Modifier.fillMaxSize() ) { - TopBar( - modifier = Modifier.padding(bottom = 16.dp), - title = stringResource(R.string.gallery), - onBackClick = actorsGalleryContract::onBackClick + + 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 = contract::onBackClick + ) + + Box(modifier = Modifier.weight(1f)) { + if (uiState.isLoading) { + CircularLoading(modifier = Modifier.align(Alignment.Center)) + } else { + GalleryContent(uiState = uiState) + } } } } From 256f7d76a08f746932427b6164cdf82473fe3942 Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 19:04:54 +0300 Subject: [PATCH 23/24] refactor: Update string resource and padding in MovieDetailsScreen --- .../feature/details/movie/MovieDetailsScreen.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 1a5bf0c84..de2cf1818 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 @@ -316,14 +316,14 @@ private fun HomeLazyVerticalGrid( if (uiState.actors.isNotEmpty()) { item(span = { GridItemSpan(maxLineSpan) }) { Text( - text = stringResource(com.london.presentation.R.string.cast), + text = stringResource(R.string.cast), style = NovixTheme.typography.title.medium, - color = NovixTheme.colors.title, + color = NovixTheme.colors.title ) LazyHorizontalGrid( modifier = Modifier - .padding(top = 16.dp) + .padding(top = 25.dp) .requiredWidth(screenWidthDp) .height(100.dp), rows = GridCells.Fixed(1), From 24db01fda98cc7044f8485e6d2862011a954006b Mon Sep 17 00:00:00 2001 From: "Asmaa.Khaled" Date: Wed, 20 Aug 2025 21:01:36 +0300 Subject: [PATCH 24/24] refactor: Conditionally render TvShowDetailScreen sections --- .../details/tvshow/info/TvShowDetailScreen.kt | 142 ++++++++++-------- 1 file changed, 76 insertions(+), 66 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 add6b0464..314ad5005 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 @@ -171,7 +171,10 @@ private fun Content( ) BackgroundGradient( - modifier = Modifier.fillMaxSize().align(Alignment.TopStart).zIndex(1f) + modifier = Modifier + .fillMaxSize() + .align(Alignment.TopStart) + .zIndex(1f) ) LazyColumn( @@ -215,79 +218,85 @@ private fun Content( ) } - // Overview title - item { - Text( - text = stringResource(R.string.overview), - style = NovixTheme.typography.title.medium, - color = NovixTheme.colors.title, - modifier = Modifier.padding(top = 16.dp, start = 16.dp, end = 16.dp) - ) - } - - // Overview content - item { - var isExpanded by remember { mutableStateOf(false) } - ConditionalText( - text = uiState.overview, - expandedState = isExpanded, - modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp) - ) { - isExpanded = !isExpanded - } - } - item { - CastSection( - modifier = Modifier.padding(top = 16.dp), - castMembers = uiState.cast?.cast ?: emptyList(), - onNavigateToCast = tvShowDetailsContract::onCastClicked - ) - } - item { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp) - ) { + if (uiState.overview.isNotBlank()) { + item { Text( - text = stringResource(R.string.season), + text = stringResource(R.string.overview), style = NovixTheme.typography.title.medium, color = NovixTheme.colors.title, - modifier = Modifier.padding(top = 16.dp, bottom = 12.dp) - ) - - SeasonEpisodesDetails( - modifier = Modifier.fillMaxWidth(), - uiState = uiState + modifier = Modifier.padding(top = 16.dp, start = 16.dp, end = 16.dp) ) + } - Text( - text = "${ - uiState.tvShowEpisodeCountBySeason?.episodes?.size.toString() - .toLocalizedNumbers() - } ${stringResource(R.string.episodes)}", - style = NovixTheme.typography.label.small, - color = NovixTheme.colors.hint, - modifier = Modifier.padding(top = 8.dp, bottom = 12.dp) + item { + var isExpanded by remember { mutableStateOf(false) } + ConditionalText( + text = uiState.overview, + expandedState = isExpanded, + modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp) + ) { + isExpanded = !isExpanded + } + } + } + if (uiState.cast?.cast?.isNotEmpty() == true) { + item { + CastSection( + modifier = Modifier.padding(top = 16.dp), + castMembers = uiState.cast.cast, + onNavigateToCast = tvShowDetailsContract::onCastClicked ) } } - items( - items = uiState.tvShowEpisodes, - key = { episode -> "${episode.showId}_${episode.seasonNumber}_${episode.episodeNumber}" } - ) { episode -> - EpisodeItem( - episodes = episode, - onEpisodeClick = { - tvShowDetailsContract.onEpisodeClicked( - episode.showId, - episode.episodeNumber, - episode.seasonNumber, + if (uiState.tvShowEpisodes.isNotEmpty() && uiState.numberOfSeasons > 0) { + item { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp) + ) { + Text( + text = stringResource(R.string.season), + style = NovixTheme.typography.title.medium, + color = NovixTheme.colors.title, + modifier = Modifier.padding(top = 16.dp, bottom = 12.dp) ) - }, - modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp) - ) + + SeasonEpisodesDetails( + modifier = Modifier.fillMaxWidth(), + uiState = uiState + ) + + uiState.tvShowEpisodeCountBySeason?.episodes?.size?.let { episodeCount -> + if (episodeCount > 0) { + Text( + text = "${episodeCount.toLocalizedNumbers()} ${stringResource(R.string.episodes)}", + style = NovixTheme.typography.label.small, + color = NovixTheme.colors.hint, + modifier = Modifier.padding(top = 8.dp, bottom = 12.dp) + ) + } + } + } + } + + items( + items = uiState.tvShowEpisodes, + key = { episode -> "${episode.showId}_${episode.seasonNumber}_${episode.episodeNumber}" } + ) { episode -> + EpisodeItem( + episodes = episode, + onEpisodeClick = { + tvShowDetailsContract.onEpisodeClicked( + episode.showId, + episode.episodeNumber, + episode.seasonNumber, + ) + }, + modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp) + ) + } } } @@ -433,8 +442,9 @@ private fun TvShowBasicDetails( } TvShowDate(date) - - Seasons(numberOfSeasons) + if (numberOfSeasons != 0) { + Seasons(numberOfSeasons) + } } }