From a165c94b8869c06bc1dfbe8e1ecf4aed705b7932 Mon Sep 17 00:00:00 2001 From: Bassant Mohammed Date: Fri, 22 Aug 2025 00:12:20 +0300 Subject: [PATCH 1/6] fix: show dot only for non-zero rates in TextWithIcon --- .../details/movie/MovieDetailsScreen.kt | 4 ++-- .../london/presentation/shared/TextWithIcon.kt | 18 +++++++++++------- 2 files changed, 13 insertions(+), 9 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 de2cf1818..4dfe1a1cd 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 @@ -399,8 +399,7 @@ private fun RatingAndMetaRow( TextWithIcon( text = rate.toLocalizedNumbers(), icon = painterResource(drawable.star), - tint = NovixTheme.colors.yellowAccent, - hasInitialDot = false + tint = NovixTheme.colors.yellowAccent ) } @@ -415,6 +414,7 @@ private fun RatingAndMetaRow( TextWithIcon( icon = painterResource(drawable.time_04), text = text, + hasInitialDot = false ) if (!date.isNullOrBlank()) { diff --git a/presentation/src/main/java/com/london/presentation/shared/TextWithIcon.kt b/presentation/src/main/java/com/london/presentation/shared/TextWithIcon.kt index 62c625880..2d4b8c04a 100644 --- a/presentation/src/main/java/com/london/presentation/shared/TextWithIcon.kt +++ b/presentation/src/main/java/com/london/presentation/shared/TextWithIcon.kt @@ -20,6 +20,7 @@ import com.london.designsystem.component.Icon import com.london.designsystem.component.Text import com.london.designsystem.theme.NovixTheme import com.london.presentation.R +import com.london.presentation.utils.isNotZeroRate @Composable fun TextWithIcon( @@ -29,6 +30,8 @@ fun TextWithIcon( hasInitialDot: Boolean = true ) { if (text.isEmpty()) return + val shouldShowDot = hasInitialDot && text.isNotZeroRate() + Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(4.dp) @@ -36,7 +39,7 @@ fun TextWithIcon( val scale = LocalDensity.current.fontScale val baseIconSize = 12.dp - if (hasInitialDot) + if (shouldShowDot) { Box( modifier = Modifier .padding(4.dp) @@ -46,12 +49,13 @@ fun TextWithIcon( .align(alignment = Alignment.CenterVertically) ) - Icon( - painter = icon, - contentDescription = stringResource(R.string.image_dot), - tint = tint, - modifier = Modifier.size(baseIconSize * scale) - ) + Icon( + painter = icon, + contentDescription = stringResource(R.string.image_dot), + tint = tint, + modifier = Modifier.size(baseIconSize * scale) + ) + } Text( text = text, style = NovixTheme.typography.label.small, From c18e9a34b71652bcfc000ba551028b196cb15623 Mon Sep 17 00:00:00 2001 From: Bassant Mohammed Date: Fri, 22 Aug 2025 01:50:17 +0300 Subject: [PATCH 2/6] refactor: navigation to pass ids for login flows --- .../java/com/london/app/NovixApplication.kt | 1 - .../london/app/navigation/appDestination.kt | 4 ++-- .../app/navigation/graph/authNavGraph.kt | 10 +++++++-- .../app/navigation/graph/mainNavGraph.kt | 20 +++++++++++++---- .../details/movie/MovieDetailsContract.kt | 2 +- .../details/movie/MovieDetailsEffect.kt | 2 +- .../details/movie/MovieDetailsScreen.kt | 14 ++++++------ .../details/movie/MovieDetailsViewModel.kt | 4 ++-- .../tvshow/episode/EpisodeDetailScreen.kt | 22 +++++++++++++++---- .../tvshow/episode/EpisodeDetailsContract.kt | 2 +- .../tvshow/episode/EpisodeDetailsEffect.kt | 8 ++++++- .../tvshow/episode/EpisodeDetailsViewModel.kt | 10 +++++++-- .../details/tvshow/info/TvShowDetailScreen.kt | 10 ++++----- .../tvshow/info/TvShowDetailsContract.kt | 2 +- .../tvshow/info/TvShowDetailsEffect.kt | 2 +- .../tvshow/info/TvShowDetailsViewModel.kt | 2 +- .../london/presentation/navigation/Screen.kt | 2 +- .../shared/bookmarkSheet/BookmarkSheet.kt | 2 +- 18 files changed, 81 insertions(+), 38 deletions(-) diff --git a/app/src/main/java/com/london/app/NovixApplication.kt b/app/src/main/java/com/london/app/NovixApplication.kt index a0f792579..758814a92 100644 --- a/app/src/main/java/com/london/app/NovixApplication.kt +++ b/app/src/main/java/com/london/app/NovixApplication.kt @@ -5,7 +5,6 @@ import androidx.hilt.work.HiltWorkerFactory import androidx.work.Configuration import androidx.work.WorkManager import com.london.data.BuildConfig -import com.london.data.worker.MovieListSyncWorker import dagger.hilt.android.HiltAndroidApp import timber.log.Timber import javax.inject.Inject diff --git a/app/src/main/java/com/london/app/navigation/appDestination.kt b/app/src/main/java/com/london/app/navigation/appDestination.kt index 3ccc63746..7e933a284 100644 --- a/app/src/main/java/com/london/app/navigation/appDestination.kt +++ b/app/src/main/java/com/london/app/navigation/appDestination.kt @@ -59,9 +59,9 @@ fun NavController.navigateToMovieCategory(genre: MovieGenreUi) = fun NavController.navigateToReviews(movieId: Int, mediaType: MediaType) = navigate(Reviews(movieId, mediaType)) -fun NavController.navigateToLoginWithPopUp() = navigateTo(Login) +fun NavController.navigateToLoginWithPopUp() = navigateTo(Login()) -fun NavController.navigateToLogin() = navigate(Login) +fun NavController.navigateToLogin(source: Screen? = null) = navigate(Login(source = source)) fun NavController.navigateToWatchingHistory() = navigate(WatchingHistory) diff --git a/app/src/main/java/com/london/app/navigation/graph/authNavGraph.kt b/app/src/main/java/com/london/app/navigation/graph/authNavGraph.kt index 688da9c07..2acea6833 100644 --- a/app/src/main/java/com/london/app/navigation/graph/authNavGraph.kt +++ b/app/src/main/java/com/london/app/navigation/graph/authNavGraph.kt @@ -3,8 +3,10 @@ package com.london.app.navigation.graph import androidx.navigation.NavGraphBuilder import androidx.navigation.NavHostController import androidx.navigation.navigation +import androidx.navigation.toRoute import com.london.app.navigation.AppNavGraph import com.london.app.navigation.appComposable +import com.london.app.navigation.navigateTo import com.london.app.navigation.navigateToLoginWithPopUp import com.london.app.navigation.navigateToMainGraph import com.london.app.navigation.navigateToRegister @@ -16,10 +18,14 @@ import com.london.presentation.navigation.Screen.Register fun NavGraphBuilder.authNavGraph( navController: NavHostController -) = navigation(startDestination = Login) { +) = navigation(startDestination = Login()) { appComposable { + val currentRoute = it.toRoute() LoginScreen( - onNavigateToHome = navController::navigateToMainGraph, + onNavigateToHome = { + currentRoute.source?.let(navController::navigateTo) + ?: navController.navigateToMainGraph() + }, onNavigateBack = navController::navigateToWelcome, onNavigateToRegister = navController::navigateToRegister ) 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 83c4f22fc..ff3d100bf 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 @@ -172,7 +172,7 @@ private fun NavGraphBuilder.onListNavGraph(navController: NavHostController) = appComposable { ListScreen( onNavigateToListDetails = ::navigateToListDetails, - onNavigateToLogin = ::navigateToLogin, + onNavigateToLogin = { navigateToLogin(source = Lists()) }, ) } appComposable { @@ -192,7 +192,9 @@ private fun NavGraphBuilder.movieDetailsNavGraph(navController: NavHostControlle onNavigateToMovie = ::navigateToMovieDetails, onNavigateToActor = ::navigateToActorDetails, onNavigateToReviews = ::navigateToReviews, - onNavigateToLogin = ::navigateToLogin, + onNavigateToLogin = { movieId -> + navigateToLogin(source = MovieDetails(movieId = movieId)) + }, ) } @@ -213,7 +215,9 @@ private fun NavGraphBuilder.tvShowDetailsNavGraph(navController: NavHostControll onNavigateToActorDetails = ::navigateToActorDetails, onNavigateBack = ::navigateUp, onNavigateToTvShowCategory = ::navigateToTvShowsByCategory, - onNavigateToLogin = ::navigateToLogin + onNavigateToLogin = { tvShowId -> + navigateToLogin(source = TvShowDetails(tvShowId = tvShowId)) + } ) } @@ -221,7 +225,15 @@ private fun NavGraphBuilder.tvShowDetailsNavGraph(navController: NavHostControll EpisodeDetailsScreen( onNavigateBack = ::navigateUp, onNavigateToActorDetails = ::navigateToActorDetails, - onNavigateToLogin = ::navigateToLogin + onNavigateToLogin = { tvShowId, seasonNumber, episodeNumber -> + navigateToLogin( + source = EpisodeDetails( + tvShowId = tvShowId, + seasonNumber = seasonNumber, + episodeNumber = episodeNumber + ) + ) + } ) } diff --git a/presentation/src/main/java/com/london/presentation/feature/details/movie/MovieDetailsContract.kt b/presentation/src/main/java/com/london/presentation/feature/details/movie/MovieDetailsContract.kt index 4a8dbba5f..9cd7e4419 100644 --- a/presentation/src/main/java/com/london/presentation/feature/details/movie/MovieDetailsContract.kt +++ b/presentation/src/main/java/com/london/presentation/feature/details/movie/MovieDetailsContract.kt @@ -5,7 +5,7 @@ import com.london.presentation.shared.genre.MovieGenreUi interface MovieDetailsContract { fun onBackClick() - fun onLoginClick() + fun onLoginClick(movieId: Int) fun onRetryClick() fun onExpandClick() fun onRateBottomSheetClick() diff --git a/presentation/src/main/java/com/london/presentation/feature/details/movie/MovieDetailsEffect.kt b/presentation/src/main/java/com/london/presentation/feature/details/movie/MovieDetailsEffect.kt index 0faaf318b..54f67011f 100644 --- a/presentation/src/main/java/com/london/presentation/feature/details/movie/MovieDetailsEffect.kt +++ b/presentation/src/main/java/com/london/presentation/feature/details/movie/MovieDetailsEffect.kt @@ -5,7 +5,7 @@ import com.london.presentation.shared.genre.MovieGenreUi sealed interface MovieDetailsEffect { data object BackNavigation : MovieDetailsEffect - data object LoginNavigation : MovieDetailsEffect + data class LoginNavigation(val movieId: Int) : MovieDetailsEffect data class MovieNavigation(val movieId: Int) : MovieDetailsEffect data class ActorNavigation(val actorId: Int) : MovieDetailsEffect data class GenreNavigation(val genre: MovieGenreUi) : MovieDetailsEffect 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 4dfe1a1cd..56e9dddf8 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 @@ -87,11 +87,11 @@ import com.london.presentation.utils.toLocalizedNumbers @Composable fun MovieDetailsScreen( onNavigateBack: () -> Unit, - onNavigateToLogin: () -> Unit, - onNavigateToMovie: (Int) -> Unit, - onNavigateToActor: (Int) -> Unit, - onNavigateToReviews: (Int, MediaType) -> Unit, - onNavigateToMovieCategory: (MovieGenreUi) -> Unit, + onNavigateToLogin: (movieId: Int) -> Unit, + onNavigateToMovie: (movieId: Int) -> Unit, + onNavigateToActor: (movieId: Int) -> Unit, + onNavigateToReviews: (movieId: Int, mediaType: MediaType) -> Unit, + onNavigateToMovieCategory: (genre: MovieGenreUi) -> Unit, viewModel: MovieDetailsViewModel = hiltViewModel() ) { val state by viewModel.state.collectAsStateWithLifecycle() @@ -108,7 +108,7 @@ fun MovieDetailsScreen( currentEffect.mediaType ) - is MovieDetailsEffect.LoginNavigation -> onNavigateToLogin() + is MovieDetailsEffect.LoginNavigation -> onNavigateToLogin(currentEffect.movieId) } } @@ -381,7 +381,7 @@ private fun BottomSheetsHandler( ) else if (uiState.isGuestUserBottomSheetVisible) GuestUserLoginBottomSheet( onDismissClick = movieDetailsContract::onRateBottomSheetClick, - onLoginClick = movieDetailsContract::onLoginClick, + onLoginClick = { movieDetailsContract.onLoginClick(uiState.movieId) }, ) } diff --git a/presentation/src/main/java/com/london/presentation/feature/details/movie/MovieDetailsViewModel.kt b/presentation/src/main/java/com/london/presentation/feature/details/movie/MovieDetailsViewModel.kt index 41397477e..5b3897bbb 100644 --- a/presentation/src/main/java/com/london/presentation/feature/details/movie/MovieDetailsViewModel.kt +++ b/presentation/src/main/java/com/london/presentation/feature/details/movie/MovieDetailsViewModel.kt @@ -235,8 +235,8 @@ class MovieDetailsViewModel @Inject constructor( emitEffect(MovieDetailsEffect.ActorNavigation(actorId)) } - override fun onLoginClick() { - emitEffect(MovieDetailsEffect.LoginNavigation) + override fun onLoginClick(movieId: Int) { + emitEffect(MovieDetailsEffect.LoginNavigation(movieId)) } override fun onReviewsClick(movieId: Int, mediaType: MediaType) { diff --git a/presentation/src/main/java/com/london/presentation/feature/details/tvshow/episode/EpisodeDetailScreen.kt b/presentation/src/main/java/com/london/presentation/feature/details/tvshow/episode/EpisodeDetailScreen.kt index 2703f0100..915a9782e 100644 --- a/presentation/src/main/java/com/london/presentation/feature/details/tvshow/episode/EpisodeDetailScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/details/tvshow/episode/EpisodeDetailScreen.kt @@ -65,7 +65,7 @@ import com.london.designsystem.R as Res @Composable fun EpisodeDetailsScreen( onNavigateBack: () -> Unit, - onNavigateToLogin: () -> Unit, + onNavigateToLogin: (tvShowId: Int, seasonNumber: Int, episodeNumber: Int) -> Unit, onNavigateToActorDetails: (Int) -> Unit, viewModel: EpisodeDetailsViewModel = hiltViewModel() ) { @@ -76,7 +76,11 @@ fun EpisodeDetailsScreen( when (currentEffect) { EpisodeDetailsEffect.BackNavigation -> onNavigateBack() is EpisodeDetailsEffect.CastNavigation -> onNavigateToActorDetails(currentEffect.episodeId) - is EpisodeDetailsEffect.LoginNavigation -> onNavigateToLogin() + is EpisodeDetailsEffect.LoginNavigation -> onNavigateToLogin( + currentEffect.tvShowId, + currentEffect.seasonNumber, + currentEffect.episodeNumber + ) } } @@ -124,7 +128,9 @@ private fun Content( ) { BackgroundGradient( - modifier = Modifier.align(Alignment.TopStart).zIndex(2f) + modifier = Modifier + .align(Alignment.TopStart) + .zIndex(2f) ) TopBar( @@ -190,7 +196,15 @@ private fun Content( ) if (uiState.isGuestUserBottomSheetVisible) GuestUserLoginBottomSheet( onDismissClick = contract::onRateEpisodeClick, - onLoginClick = contract::onLoginClick, + onLoginClick = { + uiState.episode?.let { + contract.onLoginClick( + tvShowId = it.tvShowId, + episodeNumber = it.id, + seasonNumber = it.seasonNumber + ) + } + }, ) } diff --git a/presentation/src/main/java/com/london/presentation/feature/details/tvshow/episode/EpisodeDetailsContract.kt b/presentation/src/main/java/com/london/presentation/feature/details/tvshow/episode/EpisodeDetailsContract.kt index bc349c021..6cf62d9d2 100644 --- a/presentation/src/main/java/com/london/presentation/feature/details/tvshow/episode/EpisodeDetailsContract.kt +++ b/presentation/src/main/java/com/london/presentation/feature/details/tvshow/episode/EpisodeDetailsContract.kt @@ -2,7 +2,7 @@ package com.london.presentation.feature.details.tvshow.episode interface EpisodeDetailsContract { fun onBackClick() - fun onLoginClick() + fun onLoginClick(tvShowId: Int, seasonNumber: Int, episodeNumber: Int) fun onRateEpisodeClick() fun onSelectRatingClick(rating: Int) } diff --git a/presentation/src/main/java/com/london/presentation/feature/details/tvshow/episode/EpisodeDetailsEffect.kt b/presentation/src/main/java/com/london/presentation/feature/details/tvshow/episode/EpisodeDetailsEffect.kt index c60c765f4..6dd441df3 100644 --- a/presentation/src/main/java/com/london/presentation/feature/details/tvshow/episode/EpisodeDetailsEffect.kt +++ b/presentation/src/main/java/com/london/presentation/feature/details/tvshow/episode/EpisodeDetailsEffect.kt @@ -2,6 +2,12 @@ package com.london.presentation.feature.details.tvshow.episode sealed interface EpisodeDetailsEffect { data object BackNavigation : EpisodeDetailsEffect - data object LoginNavigation : EpisodeDetailsEffect + data class LoginNavigation( + val tvShowId: Int, + val seasonNumber: Int, + val episodeNumber: Int + ) : + EpisodeDetailsEffect + data class CastNavigation(val episodeId: Int) : EpisodeDetailsEffect } diff --git a/presentation/src/main/java/com/london/presentation/feature/details/tvshow/episode/EpisodeDetailsViewModel.kt b/presentation/src/main/java/com/london/presentation/feature/details/tvshow/episode/EpisodeDetailsViewModel.kt index d81ad1b4a..f7c371dea 100644 --- a/presentation/src/main/java/com/london/presentation/feature/details/tvshow/episode/EpisodeDetailsViewModel.kt +++ b/presentation/src/main/java/com/london/presentation/feature/details/tvshow/episode/EpisodeDetailsViewModel.kt @@ -32,7 +32,7 @@ class EpisodeDetailsViewModel @Inject constructor( getEpisodeDetails() } - private fun getEpisodeDetails(){ + private fun getEpisodeDetails() { loadEpisodeDetails() loadEpisodeRating() loadVideoProvider() @@ -40,7 +40,13 @@ class EpisodeDetailsViewModel @Inject constructor( override fun onBackClick() = emitEffect(EpisodeDetailsEffect.BackNavigation) - override fun onLoginClick() = emitEffect(EpisodeDetailsEffect.LoginNavigation) + override fun onLoginClick(tvShowId: Int, seasonNumber: Int, episodeNumber: Int) = emitEffect( + EpisodeDetailsEffect.LoginNavigation( + tvShowId = tvShowId, + seasonNumber = seasonNumber, + episodeNumber = episodeNumber + ) + ) override fun onRateEpisodeClick() { tryToExecute( 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 314ad5005..077a49a31 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 @@ -84,9 +84,9 @@ import com.london.presentation.utils.toLocalizedNumbers @Composable fun TvShowsDetailsScreen( - onNavigateToLogin: () -> Unit, - onNavigateToActorDetails: (Int) -> Unit, - onNavigateToTvShowCategory: (TvShowGenreUi) -> Unit, + onNavigateToLogin: (tvShowId: Int) -> Unit, + onNavigateToActorDetails: (tvShowId: Int) -> Unit, + onNavigateToTvShowCategory: (genre: TvShowGenreUi) -> Unit, onNavigateToReviews: (tvShowId: Int, mediaType: MediaType) -> Unit, onNavigateBack: () -> Unit = {}, onNavigateToEpisodeDetails: (tvShowId: Int, episodeNumber: Int, seasonNumber: Int) -> Unit, @@ -116,7 +116,7 @@ fun TvShowsDetailsScreen( currentEffect.category ) - is TvShowDetailsEffect.OnLoginNavigation -> onNavigateToLogin() + is TvShowDetailsEffect.OnLoginNavigation -> onNavigateToLogin(currentEffect.tvShowId) } } @@ -318,7 +318,7 @@ private fun Content( ) else if (uiState.isGuestUserBottomSheetVisible) GuestUserLoginBottomSheet( onDismissClick = tvShowDetailsContract::onRateBottomSheetClick, - onLoginClick = tvShowDetailsContract::onLoginClick, + onLoginClick = { tvShowDetailsContract.onLoginClick(uiState.id) }, ) } diff --git a/presentation/src/main/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailsContract.kt b/presentation/src/main/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailsContract.kt index fa1883044..5e1e3ae1f 100644 --- a/presentation/src/main/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailsContract.kt +++ b/presentation/src/main/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailsContract.kt @@ -4,7 +4,7 @@ import com.london.domain.entity.shared.MediaType import com.london.presentation.shared.genre.TvShowGenreUi interface TvShowDetailsContract { - fun onLoginClick() + fun onLoginClick(tvShowId: Int) fun onBackClicked() fun onRateBottomSheetClick() fun onCastClicked(tvShowId: Int) diff --git a/presentation/src/main/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailsEffect.kt b/presentation/src/main/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailsEffect.kt index 3218c5b94..61b7aeae1 100644 --- a/presentation/src/main/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailsEffect.kt +++ b/presentation/src/main/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailsEffect.kt @@ -11,7 +11,7 @@ sealed interface TvShowDetailsEffect { ) : TvShowDetailsEffect data object NavigateBack : TvShowDetailsEffect - data object OnLoginNavigation : TvShowDetailsEffect + data class OnLoginNavigation(val tvShowId: Int) : TvShowDetailsEffect data class NavigateToCast(val tvShowId: Int) : TvShowDetailsEffect data class NavigateToTvShowsByCategoryId(val category: TvShowGenreUi) : TvShowDetailsEffect data class NavigateToReviews(val tvShowId: Int, val mediaType: MediaType) : TvShowDetailsEffect diff --git a/presentation/src/main/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailsViewModel.kt b/presentation/src/main/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailsViewModel.kt index 3fa6ff919..feb4a2979 100644 --- a/presentation/src/main/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailsViewModel.kt +++ b/presentation/src/main/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailsViewModel.kt @@ -145,7 +145,7 @@ class TvShowDetailsViewModel @Inject constructor( ) } - override fun onLoginClick() = emitEffect(TvShowDetailsEffect.OnLoginNavigation) + override fun onLoginClick(tvShowId: Int) = emitEffect(TvShowDetailsEffect.OnLoginNavigation(tvShowId)) override fun onBackClicked() { emitEffect(TvShowDetailsEffect.NavigateBack) diff --git a/presentation/src/main/java/com/london/presentation/navigation/Screen.kt b/presentation/src/main/java/com/london/presentation/navigation/Screen.kt index 81bbdecf4..220bfa2d8 100644 --- a/presentation/src/main/java/com/london/presentation/navigation/Screen.kt +++ b/presentation/src/main/java/com/london/presentation/navigation/Screen.kt @@ -18,7 +18,7 @@ sealed interface Screen { } @Serializable - data object Login : Screen + data class Login(val source: Screen? = null) : Screen @Serializable data object Home : Screen diff --git a/presentation/src/main/java/com/london/presentation/shared/bookmarkSheet/BookmarkSheet.kt b/presentation/src/main/java/com/london/presentation/shared/bookmarkSheet/BookmarkSheet.kt index e0335dab9..a5f29a8dd 100644 --- a/presentation/src/main/java/com/london/presentation/shared/bookmarkSheet/BookmarkSheet.kt +++ b/presentation/src/main/java/com/london/presentation/shared/bookmarkSheet/BookmarkSheet.kt @@ -93,7 +93,7 @@ fun BookmarkBottomSheet( BookmarkSheetEffect.LoginNavigation -> { hideSheet() - navController.navigate(Screen.Login) + navController.navigate(Screen.Login()) } } } From 3931f066fbb95d61ff4da461d2eab4c62985d667 Mon Sep 17 00:00:00 2001 From: Ahmed Mones <68463985+Al-Taie@users.noreply.github.com> Date: Fri, 22 Aug 2025 05:51:47 +0300 Subject: [PATCH 3/6] Refactor: Enhance bookmark and navigation logic This commit refactors the bookmark functionality and navigation logic within the application. **Key Changes:** * **BookmarkSheet:** * Reordered parameters in `BookmarkBottomSheet` for better readability. * Modified `LoginNavigation` effect to pass the source screen (MovieDetails with bookmark sheet visibility) when navigating to Login. * **HomeViewModel:** * Reorganized initialization logic into a new `initializeData` function. * Improved loading state management by introducing separate loading flags for popular and top-rated media (`isPopularLoading`, `isTopRatedLoading`). * Refactored retry logic to re-initialize all relevant data sections. * Streamlined function definitions and parameter order. * **MovieDetailsViewModel:** * Added logic to update `isBookmarkSheetVisible` in the UI state based on navigation arguments. * **Navigation:** * Updated `navigateToLogin` and `navigateToLoginWithPopUp` to correctly pass the source screen. * Adjusted `navigateToMovieDetails` to include `isBookmarkSheetVisible` parameter. * Modified `Login` screen definition in `Screen.kt` to handle source screen passing more effectively. * Updated navigation graphs (`mainNavGraph.kt`, `authNavGraph.kt`) to reflect changes in screen definitions and navigation arguments. * **HomeScreenUiState:** * Added `isRecentWatchLoading` flag. * Updated the general `isLoading` property to consider all individual loading states. * **HomeScreen:** * Passed `bookmarkedMovieId` to `BookmarkBottomSheet`. * Updated loading state checks for Popular and Continue Watching sections to use specific loading flags. * Renamed `homeScreenContract` to `contract` in `HomeScreenContent` for conciseness. --- .../london/app/navigation/appDestination.kt | 6 +- .../app/navigation/graph/authNavGraph.kt | 2 +- .../app/navigation/graph/mainNavGraph.kt | 42 +++-- .../details/movie/MovieDetailsViewModel.kt | 1 + .../presentation/feature/home/HomeScreen.kt | 53 +++--- .../feature/home/HomeScreenUiState.kt | 7 +- .../feature/home/HomeViewModel.kt | 162 ++++++++---------- .../london/presentation/navigation/Screen.kt | 10 +- .../shared/bookmarkSheet/BookmarkSheet.kt | 11 +- 9 files changed, 148 insertions(+), 146 deletions(-) diff --git a/app/src/main/java/com/london/app/navigation/appDestination.kt b/app/src/main/java/com/london/app/navigation/appDestination.kt index 7e933a284..9dbaa9af4 100644 --- a/app/src/main/java/com/london/app/navigation/appDestination.kt +++ b/app/src/main/java/com/london/app/navigation/appDestination.kt @@ -33,7 +33,7 @@ fun NavController.navigateToEpisodeDetails(tvShowId: Int, seasonNumber: Int, epi navigate(EpisodeDetails(tvShowId, episodeNumber, seasonNumber)) fun NavController.navigateToMovieDetails(movieId: Int) = - navigate(MovieDetails(movieId)) + navigate(MovieDetails(movieId = movieId)) fun NavController.navigateToTvShowDetails(tvShowId: Int) = navigate(TvShowDetails(tvShowId)) @@ -59,9 +59,9 @@ fun NavController.navigateToMovieCategory(genre: MovieGenreUi) = fun NavController.navigateToReviews(movieId: Int, mediaType: MediaType) = navigate(Reviews(movieId, mediaType)) -fun NavController.navigateToLoginWithPopUp() = navigateTo(Login()) +fun NavController.navigateToLoginWithPopUp(source: Screen? = null) = navigateTo(Login.withSource(source)) -fun NavController.navigateToLogin(source: Screen? = null) = navigate(Login(source = source)) +fun NavController.navigateToLogin(source: Screen? = null) = navigate(Login.withSource(source)) fun NavController.navigateToWatchingHistory() = navigate(WatchingHistory) diff --git a/app/src/main/java/com/london/app/navigation/graph/authNavGraph.kt b/app/src/main/java/com/london/app/navigation/graph/authNavGraph.kt index 2acea6833..8ea1be80c 100644 --- a/app/src/main/java/com/london/app/navigation/graph/authNavGraph.kt +++ b/app/src/main/java/com/london/app/navigation/graph/authNavGraph.kt @@ -18,7 +18,7 @@ import com.london.presentation.navigation.Screen.Register fun NavGraphBuilder.authNavGraph( navController: NavHostController -) = navigation(startDestination = Login()) { +) = navigation(startDestination = Login) { appComposable { val currentRoute = it.toRoute() LoginScreen( 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 ff3d100bf..ce5d1a5c0 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 @@ -104,7 +104,7 @@ fun NavGraphBuilder.mainNavGraph( AccountScreen( onNavigateToWatchingHistory = ::navigateToWatchingHistory, onNavigateToMyRating = ::navigateToMyRating, - onNavigateToLogin = ::navigateToLoginWithPopUp + onNavigateToLogin = { navigateToLoginWithPopUp(source = Account) } ) } @@ -183,28 +183,27 @@ private fun NavGraphBuilder.onListNavGraph(navController: NavHostController) = } } -private fun NavGraphBuilder.movieDetailsNavGraph(navController: NavHostController) = - with(navController) { - appComposable { - MovieDetailsScreen( - onNavigateBack = ::navigateUp, - onNavigateToMovieCategory = ::navigateToMovieCategory, - onNavigateToMovie = ::navigateToMovieDetails, - onNavigateToActor = ::navigateToActorDetails, - onNavigateToReviews = ::navigateToReviews, - onNavigateToLogin = { movieId -> - navigateToLogin(source = MovieDetails(movieId = movieId)) - }, - ) - } +private fun NavGraphBuilder.movieDetailsNavGraph(navController: NavHostController) = with(navController) { + appComposable { + MovieDetailsScreen( + onNavigateBack = ::navigateUp, + onNavigateToMovieCategory = ::navigateToMovieCategory, + onNavigateToMovie = ::navigateToMovieDetails, + onNavigateToActor = ::navigateToActorDetails, + onNavigateToReviews = ::navigateToReviews, + onNavigateToLogin = { movieId -> + navigateToLogin(source = MovieDetails(movieId = movieId)) + }, + ) + } - appComposable { - MoviesByCategoryScreen( - onNavigateToMovieDetails = ::navigateToMovieDetails, - onNavigateBack = ::navigateUp, - ) - } + appComposable { + MoviesByCategoryScreen( + onNavigateToMovieDetails = ::navigateToMovieDetails, + onNavigateBack = ::navigateUp, + ) } +} private fun NavGraphBuilder.tvShowDetailsNavGraph(navController: NavHostController) = with(navController) { @@ -296,5 +295,4 @@ private fun NavGraphBuilder.trendingNavGraph(navController: NavHostController) = onNavigateBack = ::navigateUp ) } - } diff --git a/presentation/src/main/java/com/london/presentation/feature/details/movie/MovieDetailsViewModel.kt b/presentation/src/main/java/com/london/presentation/feature/details/movie/MovieDetailsViewModel.kt index 5b3897bbb..64dc1bda5 100644 --- a/presentation/src/main/java/com/london/presentation/feature/details/movie/MovieDetailsViewModel.kt +++ b/presentation/src/main/java/com/london/presentation/feature/details/movie/MovieDetailsViewModel.kt @@ -35,6 +35,7 @@ class MovieDetailsViewModel @Inject constructor( init { loadMovieDetails() + args?.let { updateState { copy(isBookmarkSheetVisible = it.isBookmarkSheetVisible) } } } private fun loadMovieDetails() { diff --git a/presentation/src/main/java/com/london/presentation/feature/home/HomeScreen.kt b/presentation/src/main/java/com/london/presentation/feature/home/HomeScreen.kt index 10bdfbc71..8303f0f04 100644 --- a/presentation/src/main/java/com/london/presentation/feature/home/HomeScreen.kt +++ b/presentation/src/main/java/com/london/presentation/feature/home/HomeScreen.kt @@ -89,14 +89,14 @@ fun HomeScreen( HomeScreenContent( uiState = uiState, - homeScreenContract = viewModel + contract = viewModel ) } @Composable private fun HomeScreenContent( uiState: HomeScreenUiState, - homeScreenContract: HomeScreenContract, + contract: HomeScreenContract, ) { val screenDimensions = rememberScreenDimensions() val lazyGridState = rememberLazyGridState() @@ -117,7 +117,7 @@ private fun HomeScreenContent( recentWatchedMedia = recentWatchedMedia, upcomingMoviesLazyList = upcomingMoviesLazyList, scrollState = scrollState, - homeScreenContract = homeScreenContract + homeScreenContract = contract ) } @@ -181,10 +181,14 @@ private fun HomeScreenLayout( homeScreenContract: HomeScreenContract ) { Box( - modifier = Modifier.fillMaxSize().navBarBottomPadding() + modifier = Modifier + .fillMaxSize() + .navBarBottomPadding() ) { BackgroundGradient( - modifier = Modifier.align(Alignment.TopStart).zIndex(1f) + modifier = Modifier + .align(Alignment.TopStart) + .zIndex(1f) ) Column(modifier = Modifier.fillMaxSize()) { @@ -213,9 +217,9 @@ private fun HomeScreenLayout( } BookmarkBottomSheet( - onSheetDismiss = homeScreenContract::onBookmarkSheetDismiss, + bookmarkedMovieId = uiState.bookmarkedMovieId, isSheetVisible = uiState.isBookmarkSheetVisible, - bookmarkedMovieId = uiState.bookmarkedMovieId + onSheetDismiss = homeScreenContract::onBookmarkSheetDismiss, ) } @@ -286,7 +290,7 @@ private fun HomeContentGrid( continueWatchingSection( screenWidth = screenWidth, recentWatchedMedia = recentWatchedMedia, - isLoading = uiState.isLoading, + isLoading = uiState.isRecentWatchLoading, homeScreenContract = homeScreenContract ) } @@ -309,27 +313,28 @@ private fun LazyGridScope.popularSection( homeScreenContract: HomeScreenContract ) { item(span = { GridItemSpan(maxLineSpan) }) { - if (uiState.popularMediaList.isNotEmpty()) { - PopularSection( - modifier = Modifier.requiredWidth(screenWidth), - pagerState = pagerState, - uiMediaList = uiState.popularMediaList, - onManageBookmarkClicked = { movieId -> - homeScreenContract.onManageBookmarkClicked(movieId) - }, - onCardClick = { id, mediaType -> - when (mediaType) { - MediaType.TvShow -> homeScreenContract.onTvShowClick(id) - MediaType.Movie -> homeScreenContract.onMovieClick(id) - } - } - ) - } else { + if (uiState.isPopularLoading || uiState.popularMediaList.isEmpty()) { ShimmerPopularSection( modifier = Modifier.requiredWidth(screenWidth), pagerState = pagerState, ) + return@item } + + PopularSection( + modifier = Modifier.requiredWidth(screenWidth), + pagerState = pagerState, + uiMediaList = uiState.popularMediaList, + onManageBookmarkClicked = { movieId -> + homeScreenContract.onManageBookmarkClicked(movieId) + }, + onCardClick = { id, mediaType -> + when (mediaType) { + MediaType.TvShow -> homeScreenContract.onTvShowClick(id) + MediaType.Movie -> homeScreenContract.onMovieClick(id) + } + } + ) } } diff --git a/presentation/src/main/java/com/london/presentation/feature/home/HomeScreenUiState.kt b/presentation/src/main/java/com/london/presentation/feature/home/HomeScreenUiState.kt index 29a6a5428..e306ebb8b 100644 --- a/presentation/src/main/java/com/london/presentation/feature/home/HomeScreenUiState.kt +++ b/presentation/src/main/java/com/london/presentation/feature/home/HomeScreenUiState.kt @@ -11,10 +11,10 @@ import kotlinx.coroutines.flow.emptyFlow data class HomeScreenUiState( val error: ErrorState? = null, - val isLoading: Boolean = false, val bookmarkedMovieId: Int = 0, val isPopularLoading: Boolean = false, val isTopRatedLoading: Boolean = false, + val isRecentWatchLoading: Boolean = false, val isBookmarkSheetVisible: Boolean = false, val topRatedMediaList: List = emptyList(), val selectedMovieGenre: MovieGenreUi = MovieGenreUi.All, @@ -23,4 +23,7 @@ data class HomeScreenUiState( val upcomingMovies: Flow> = emptyFlow(), val recentWatchedMediaFlow: Flow> = emptyFlow(), val selectedCategoryFlow: MutableStateFlow = MutableStateFlow(null) -) +) { + val isLoading: Boolean + get() = isPopularLoading || isRecentWatchLoading || isTopRatedLoading +} diff --git a/presentation/src/main/java/com/london/presentation/feature/home/HomeViewModel.kt b/presentation/src/main/java/com/london/presentation/feature/home/HomeViewModel.kt index 2a6f7d8e4..dd50659c4 100644 --- a/presentation/src/main/java/com/london/presentation/feature/home/HomeViewModel.kt +++ b/presentation/src/main/java/com/london/presentation/feature/home/HomeViewModel.kt @@ -1,5 +1,6 @@ package com.london.presentation.feature.home +import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import androidx.paging.PagingData import androidx.paging.cachedIn @@ -37,25 +38,71 @@ class HomeViewModel @Inject constructor( ) : BaseViewModel(HomeScreenUiState()), HomeScreenContract { init { - getHomeInfo() + initializeData() } - private fun getHomeInfo() { - initializePopularMedia() + override fun loadUpcomingMoviesClick(genre: MovieGenreUi) { + updateState { + copy(selectedCategoryFlow = selectedCategoryFlow.apply { value = genre }) + } + } + + override fun onMovieClick(id: Int) = + emitEffect(HomeScreenEffect.MovieDetailsNavigation(id)) + + override fun onTvShowClick(id: Int) = + emitEffect(HomeScreenEffect.TvShowDetailsNavigation(id)) + + override fun onMovieGenreSelect(genre: MovieGenreUi) { + if (genre == state.value.selectedMovieGenre) return + updateState { copy(selectedMovieGenre = genre) } + loadUpcomingMoviesClick(genre) + } + + override fun onTopRatedClick() = emitEffect(HomeScreenEffect.TopRatedNavigation) + + override fun onContinueWatchingClick() = emitEffect(HomeScreenEffect.ContinueWatchingNavigation) + + override fun onTrendingMoviesCardClick() = emitEffect(HomeScreenEffect.TrendingMovieNavigation) + + override fun onTrendingTvShowsCardClick() = emitEffect(HomeScreenEffect.TrendingTvShowsNavigation) + + override fun onTrendingActorsCardClick() = emitEffect(HomeScreenEffect.TrendingActorNavigation) + + override fun onRetryClick() { + updateState { copy(error = null) } initializeTopRatedMedia() handleRecentWatchedMedia() - initializeUpcomingMoviesFlow() + initializePopularMedia() } - private fun initializeUpcomingMoviesFlow() = - updateState { copy(upcomingMovies = createUpComingFlow()) } + override fun onManageBookmarkClicked(movieId: Int) { + updateState { + copy( + isBookmarkSheetVisible = true, + bookmarkedMovieId = movieId + ) + } + } - override fun loadUpcomingMoviesClick(genre: MovieGenreUi) { + override fun onBookmarkSheetDismiss() { updateState { - copy(selectedCategoryFlow = selectedCategoryFlow.apply { value = genre }) + copy( + isBookmarkSheetVisible = false, + bookmarkedMovieId = 0 + ) } } + private fun initializeData() { + initializePopularMedia() + initializeTopRatedMedia() + handleRecentWatchedMedia() + initializeUpcomingMoviesFlow() + } + + private fun initializeUpcomingMoviesFlow() = updateState { copy(upcomingMovies = createUpComingFlow()) } + private fun createUpComingFlow(): Flow> { val upcomingMoviesFlow: Flow> = state.value.selectedCategoryFlow @@ -74,15 +121,13 @@ class HomeViewModel @Inject constructor( } } - private fun initializeTopRatedMedia() { - tryToExecute( - block = { fetchTopRatedMedia() }, - onStart = { updateLoadingState(true) }, - onSuccess = { topRatedMedia -> handleTopRatedSuccess(topRatedMedia) }, - onError = { errorState -> updateErrorState(errorState) }, - onCompleted = { updateLoadingState(false) }, - ) - } + private fun initializeTopRatedMedia() = tryToExecute( + block = { fetchTopRatedMedia() }, + onStart = { updateState { copy(isTopRatedLoading = true) } }, + onSuccess = { topRatedMedia -> handleTopRatedSuccess(topRatedMedia) }, + onError = { errorState -> updateErrorState(errorState) }, + onCompleted = { updateState { copy(isTopRatedLoading = false) } }, + ) private fun handleTopRatedSuccess(topRatedMediaList: List) = updateState { copy(topRatedMediaList = topRatedMediaList.toUiMedia().shuffled()) } @@ -97,24 +142,20 @@ class HomeViewModel @Inject constructor( private fun handleRecentWatchedMedia() { tryToCollect( block = { fetchRecentWatchedMedia() }, - onStart = { updateLoadingState(true) }, onNewValue = { recentWatchedMedia -> handleRecentWatchedMediaSuccess(recentWatchedMedia) }, onError = { errorState -> updateErrorState(errorState) }, - onCompleted = { updateLoadingState(false) }, ) } - private fun initializePopularMedia() { - tryToExecute( - block = { fetchPopularMediaList() }, - onStart = { updateLoadingState(true) }, - onSuccess = { popularMedia -> handlePopularMediaSuccess(popularMedia) }, - onError = { errorState -> updateErrorState(errorState) }, - onCompleted = { updateLoadingState(false) }, - ) - } + private fun initializePopularMedia() = tryToExecute( + block = { fetchPopularMediaList() }, + onStart = { updateState { copy(isPopularLoading = true) } }, + onSuccess = { popularMedia -> handlePopularMediaSuccess(popularMedia) }, + onError = { errorState -> updateErrorState(errorState) }, + onCompleted = { updateState { copy(isPopularLoading = false) } }, + ) private fun handleRecentWatchedMediaSuccess(recentWatchedMedia: List) = updateState { copy(recentWatchedMediaFlow = flowOf(recentWatchedMedia)) } @@ -128,20 +169,14 @@ class HomeViewModel @Inject constructor( private fun combineRecentMedia( movies: Flow>, shows: Flow> - ): Flow> { - return combine(movies, shows) { movieList, showList -> - movieList.toUiMedia() + showList.toUiMedia() - } + ): Flow> = combine(movies, shows) { movieList, showList -> + movieList.toUiMedia() + showList.toUiMedia() } private fun handlePopularMediaSuccess(popularMedia: List) = updateState { copy(popularMediaList = popularMedia) } - private fun updateErrorState(errorState: ErrorState) = - updateState { copy(error = errorState) } - - private fun updateLoadingState(isLoading: Boolean) = - updateState { copy(isPopularLoading = isLoading) } + private fun updateErrorState(errorState: ErrorState) = updateState { copy(error = errorState) } private suspend fun fetchPopularMediaList(): List { val movies = getMovieUseCase.getPopularMovies() @@ -149,57 +184,4 @@ class HomeViewModel @Inject constructor( return movies.toPopularUiMedia() + tvShows.toPopularUiMedia() } - - override fun onRetryClick() { - updateState { copy(error = null) } - initializeTopRatedMedia() - handleRecentWatchedMedia() - initializePopularMedia() - } - - override fun onManageBookmarkClicked(movieId: Int) { - updateState { - copy( - isBookmarkSheetVisible = true, - bookmarkedMovieId = movieId - ) - } - } - - override fun onBookmarkSheetDismiss() { - updateState { - copy( - isBookmarkSheetVisible = false, - bookmarkedMovieId = 0 - ) - } - } - - override fun onMovieClick(id: Int) = - emitEffect(HomeScreenEffect.MovieDetailsNavigation(id)) - - override fun onTvShowClick(id: Int) = - emitEffect(HomeScreenEffect.TvShowDetailsNavigation(id)) - - override fun onMovieGenreSelect(genre: MovieGenreUi) { - if (genre == state.value.selectedMovieGenre) return - updateState { copy(selectedMovieGenre = genre) } - loadUpcomingMoviesClick(genre) - } - - override fun onTopRatedClick() = - emitEffect(HomeScreenEffect.TopRatedNavigation) - - override fun onContinueWatchingClick() = - emitEffect(HomeScreenEffect.ContinueWatchingNavigation) - - override fun onTrendingMoviesCardClick() = - emitEffect(HomeScreenEffect.TrendingMovieNavigation) - - override fun onTrendingTvShowsCardClick() = - emitEffect(HomeScreenEffect.TrendingTvShowsNavigation) - - override fun onTrendingActorsCardClick() = - emitEffect(HomeScreenEffect.TrendingActorNavigation) - } diff --git a/presentation/src/main/java/com/london/presentation/navigation/Screen.kt b/presentation/src/main/java/com/london/presentation/navigation/Screen.kt index 220bfa2d8..b32db9b74 100644 --- a/presentation/src/main/java/com/london/presentation/navigation/Screen.kt +++ b/presentation/src/main/java/com/london/presentation/navigation/Screen.kt @@ -18,7 +18,13 @@ sealed interface Screen { } @Serializable - data class Login(val source: Screen? = null) : Screen + data object Login : Screen { + private var _source: Screen? = null + val source: Screen? + get() = _source?.also { _source = null } + + fun withSource(value: Screen?): Login = this.also { _source = value } + } @Serializable data object Home : Screen @@ -51,7 +57,7 @@ sealed interface Screen { data class TvShowDetails(val tvShowId: Int) : Screen @Serializable - data class MovieDetails(val movieId: Int) : Screen + data class MovieDetails(val movieId: Int, val isBookmarkSheetVisible: Boolean = false) : Screen @Serializable data class ActorDetails(val actorId: Int) : Screen diff --git a/presentation/src/main/java/com/london/presentation/shared/bookmarkSheet/BookmarkSheet.kt b/presentation/src/main/java/com/london/presentation/shared/bookmarkSheet/BookmarkSheet.kt index a5f29a8dd..63d743a94 100644 --- a/presentation/src/main/java/com/london/presentation/shared/bookmarkSheet/BookmarkSheet.kt +++ b/presentation/src/main/java/com/london/presentation/shared/bookmarkSheet/BookmarkSheet.kt @@ -56,10 +56,10 @@ import kotlinx.coroutines.launch fun BookmarkBottomSheet( isSheetVisible: Boolean, bookmarkedMovieId: Int, - onSheetDismiss: () -> Unit, modifier: Modifier = Modifier, viewModel: BookmarkSheetViewModel = hiltViewModel(), sheetState: SheetState = rememberModalBottomSheetState(), + onSheetDismiss: () -> Unit, ) { val coroutineScope = rememberCoroutineScope() val navController = LocalNavController.current @@ -93,7 +93,14 @@ fun BookmarkBottomSheet( BookmarkSheetEffect.LoginNavigation -> { hideSheet() - navController.navigate(Screen.Login()) + navController.navigate( + Screen.Login.withSource( + value = Screen.MovieDetails( + movieId = bookmarkedMovieId, + isBookmarkSheetVisible = true + ) + ) + ) } } } From 4ea465614ff13b7b660aaae24e85da6087e881e7 Mon Sep 17 00:00:00 2001 From: Yusuf Nasser Date: Fri, 22 Aug 2025 09:21:27 +0300 Subject: [PATCH 4/6] fix: update string resources --- presentation/src/main/res/values-ar/strings.xml | 9 +++++---- presentation/src/main/res/values/strings.xml | 5 +++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/presentation/src/main/res/values-ar/strings.xml b/presentation/src/main/res/values-ar/strings.xml index fc7131cd4..0f632e4f5 100644 --- a/presentation/src/main/res/values-ar/strings.xml +++ b/presentation/src/main/res/values-ar/strings.xml @@ -1,7 +1,7 @@ بحث - ابحث... + ابحث… شوهد مؤخرًا عمليات البحث الأخيرة مسح الكل @@ -150,8 +150,9 @@ الفيلم غير موجود تم اضافه القائمه بنجاح تم حذف القائمة بنجاح - حدث خطا ما لا يمكن اضافه القائمه - تم حذف القائمة بنجاح + حدث خطأ ما لا يمكن اضافه القائمه + حدث خطأ ما، فشل حذف التقييم!"> + تم حذف القائمة بنجاح لا توجد عناصر هنا! حذف القائمة حذف القائمة المحفوظة سيحذف جميع عناصرها. هل أنت متأكد أنك تريد المتابعة؟ @@ -161,7 +162,7 @@ غلق مجموعاتي تم اضافه القائمه بنجاح - حدث خطا ما لا يمكن اضافه القائمه + حدث خطأ ما، فشل الإضافه للقائمه يرجى تسجيل الدخول للتمكن من الإضافة إالي قائمة لا يوجد قوائم متاحة لهذا الفيلم!\nقم بإنشاء واحدة جديدة الآن. تمت الإضافة إلى القائمة بنجاح diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml index 41ae0c138..420df8e36 100644 --- a/presentation/src/main/res/values/strings.xml +++ b/presentation/src/main/res/values/strings.xml @@ -1,7 +1,7 @@ Search - Search... + Search… Recent Viewed Recent Search Clear all @@ -153,7 +153,8 @@ list added successfully list removed successfully can not delete list - Delete rating successfully"> + Rating deleted successfully"> + Something went wrong, could not delete rating"> There is no items here! Delete list Deleting the saved list will remove all items it contains. Are you sure you want to proceed? From 40ecae6096ad98cf6da8798d03aa76b40796d112 Mon Sep 17 00:00:00 2001 From: Yusuf Nasser Date: Fri, 22 Aug 2025 09:21:47 +0300 Subject: [PATCH 5/6] refactor: use string resources for SnackBar messages --- .../presentation/feature/account/rating/MyRatingScreen.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 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 1720c0735..889b94ed3 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 @@ -22,6 +22,7 @@ import com.london.designsystem.component.NovixChip import com.london.designsystem.component.TopBar import com.london.designsystem.theme.NovixTheme import com.london.designsystem.theme.ThemePreviews +import com.london.designsystem.utils.string import com.london.domain.entity.shared.MediaType import com.london.presentation.R import com.london.presentation.shared.BackgroundGradient @@ -145,11 +146,11 @@ private fun RatingSnackBar(state: MyRatingUiState) { if (!state.isSnackBarVisible) return if (state.errorState is ErrorState.RequestFailed) { - SnackBarAnimation(state.errorState.message) + SnackBarAnimation(message = R.string.rating_delete_fail.string) } else { SnackBarAnimation( - stringResource(R.string.delete_list_successfully), - dsR.drawable.ic_success + message = R.string.rating_delete_success.string, + icon = dsR.drawable.ic_success ) } } From 159319ea0f2635e7c678a98a04328b81243fb4fc Mon Sep 17 00:00:00 2001 From: Yusuf Nasser Date: Fri, 22 Aug 2025 11:12:46 +0300 Subject: [PATCH 6/6] test: fix onboarding tests and navigation clarity --- .../feature/details/movie/info/MovieDetailsViewModelTest.kt | 4 ++-- .../feature/details/tvshow/info/TvShowDetailsViewModelTest.kt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/presentation/src/test/java/com/london/presentation/feature/details/movie/info/MovieDetailsViewModelTest.kt b/presentation/src/test/java/com/london/presentation/feature/details/movie/info/MovieDetailsViewModelTest.kt index f3982c4b1..a10998b5a 100644 --- a/presentation/src/test/java/com/london/presentation/feature/details/movie/info/MovieDetailsViewModelTest.kt +++ b/presentation/src/test/java/com/london/presentation/feature/details/movie/info/MovieDetailsViewModelTest.kt @@ -177,8 +177,8 @@ class MovieDetailsViewModelTest { // When & Then viewModel?.effect?.test { - viewModel?.onLoginClick() - assertThat(awaitItem()).isEqualTo(MovieDetailsEffect.LoginNavigation) + viewModel?.onLoginClick(0) + assertThat(awaitItem()).isEqualTo(MovieDetailsEffect.LoginNavigation(0)) } } diff --git a/presentation/src/test/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailsViewModelTest.kt b/presentation/src/test/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailsViewModelTest.kt index 5ba316f6e..e8710c317 100644 --- a/presentation/src/test/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailsViewModelTest.kt +++ b/presentation/src/test/java/com/london/presentation/feature/details/tvshow/info/TvShowDetailsViewModelTest.kt @@ -249,8 +249,8 @@ class TvShowDetailsViewModelTest { fun `onLoginClick should emit OnLoginNavigation effect when clicked`() = runTest { // When & Then viewModel?.effect?.test { - viewModel?.onLoginClick() - assertThat(awaitItem()).isEqualTo(TvShowDetailsEffect.OnLoginNavigation) + viewModel?.onLoginClick(0) + assertThat(awaitItem()).isEqualTo(TvShowDetailsEffect.OnLoginNavigation(0)) cancelAndIgnoreRemainingEvents() } }