From 22cada7527278e0f0b21a478b1cdccd5824ce044 Mon Sep 17 00:00:00 2001 From: Ali Date: Mon, 23 Sep 2024 17:26:56 +0330 Subject: [PATCH] Sort out with Spotless --- .editorconfig | 4 + .github/workflows/spotless.yml | 30 + app/build.gradle | 2 +- .../main/java/com/sample/tmdb/Application.kt | 2 +- .../java/com/sample/tmdb/ui/MainActivity.kt | 43 +- .../main/java/com/sample/tmdb/ui/TMDbApp.kt | 105 ++-- .../java/com/sample/tmdb/ui/TMDbAppState.kt | 19 +- build.gradle | 17 +- buildSrc/src/main/java/Dependencies.kt | 6 +- .../tmdb/common/test/TestCoroutineRule.kt | 9 +- .../common/ui/component/DestinationBarTest.kt | 13 +- .../common/ui/component/ErrorScreenTest.kt | 9 +- .../common/ui/component/PersonCardTest.kt | 22 +- .../tmdb/common/ui/component/TMDbCardTest.kt | 20 +- .../common/ui/component/TMDbContentTest.kt | 35 +- .../sample/tmdb/common/MainDestinations.kt | 4 +- .../sample/tmdb/common/base/BaseRepository.kt | 21 +- .../sample/tmdb/common/base/BaseViewModel.kt | 5 +- .../sample/tmdb/common/base/TMDbViewModel.kt | 5 +- .../com/sample/tmdb/common/model/Credit.kt | 9 +- .../com/sample/tmdb/common/model/TMDbItem.kt | 2 +- .../java/com/sample/tmdb/common/ui/Content.kt | 14 +- .../java/com/sample/tmdb/common/ui/Dimens.kt | 3 +- .../common/ui/component/DestinationBar.kt | 29 +- .../tmdb/common/ui/component/ErrorScreen.kt | 24 +- .../tmdb/common/ui/component/LoadingRow.kt | 11 +- .../tmdb/common/ui/component/PersonCard.kt | 62 +- .../tmdb/common/ui/component/TMDbCard.kt | 27 +- .../tmdb/common/ui/component/TMDbContent.kt | 140 +++-- .../tmdb/common/ui/component/TMDbDivider.kt | 6 +- .../common/ui/component/TMDbProgressBar.kt | 54 +- .../com/sample/tmdb/common/ui/theme/Color.kt | 19 +- .../com/sample/tmdb/common/ui/theme/Shape.kt | 11 +- .../com/sample/tmdb/common/ui/theme/Theme.kt | 44 +- .../com/sample/tmdb/common/ui/theme/Type.kt | 20 +- .../utils/CircleTopCropTransformation.kt | 8 +- .../com/sample/tmdb/common/utils/Constants.kt | 2 +- .../com/sample/tmdb/common/utils/IntExt.kt | 2 +- .../com/sample/tmdb/common/utils/Resource.kt | 12 +- .../sample/tmdb/common/utils/TMDbException.kt | 4 +- .../com/sample/tmdb/data/di/DataModule.kt | 12 +- .../com/sample/tmdb/data/di/DatabaseModule.kt | 18 +- .../sample/tmdb/data/di/DispatcherModule.kt | 3 +- .../sample/tmdb/data/di/RepositoryModule.kt | 106 ++-- .../sample/tmdb/data/network/MovieService.kt | 47 +- .../sample/tmdb/data/network/PersonService.kt | 9 +- .../sample/tmdb/data/network/TVShowService.kt | 47 +- .../movie/DiscoverMoviesPagingSource.kt | 8 +- .../movie/NowPlayingMoviesPagingSource.kt | 8 +- .../paging/movie/PopularMoviesPagingSource.kt | 8 +- .../paging/movie/SearchMoviesPagingSource.kt | 8 +- .../paging/movie/SimilarMoviesPagingSource.kt | 8 +- .../movie/TopRatedMoviesPagingSource.kt | 8 +- .../movie/TrendingMoviesPagingSource.kt | 8 +- .../movie/UpcomingMoviesPagingSource.kt | 8 +- .../tvshow/AiringTodayTvSeriesPagingSource.kt | 8 +- .../tvshow/DiscoverTvSeriesPagingSource.kt | 8 +- .../tvshow/OnTheAirTvSeriesPagingSource.kt | 8 +- .../tvshow/PopularTvSeriesPagingSource.kt | 8 +- .../tvshow/SearchTvSeriesPagingSource.kt | 8 +- .../tvshow/SimilarTvSeriesPagingSource.kt | 8 +- .../tvshow/TopRatedTvSeriesPagingSource.kt | 8 +- .../tvshow/TrendingTvSeriesPagingSource.kt | 8 +- .../tmdb/data/repository/PersonRepository.kt | 20 +- .../repository/movie/MovieFeedRepository.kt | 39 +- .../BookmarkMovieDetailsRepositoryImpl.kt | 23 +- .../movie/detail/BookmarkMovieRepository.kt | 18 +- .../movie/detail/MovieDetailRepository.kt | 38 +- .../paging/DiscoverMoviesPagingRepository.kt | 19 +- .../NowPlayingMoviesPagingRepository.kt | 21 +- .../paging/PopularMoviesPagingRepository.kt | 21 +- .../paging/SearchMoviesPagingRepository.kt | 21 +- .../paging/SimilarMoviesPagingRepository.kt | 19 +- .../paging/TopRatedMoviesPagingRepository.kt | 21 +- .../paging/TrendingMoviesPagingRepository.kt | 21 +- .../paging/UpcomingMoviesPagingRepository.kt | 21 +- .../repository/tvshow/TVShowFeedRepository.kt | 39 +- .../BookmarkTVShowDetailsRepositoryImpl.kt | 23 +- .../tvshow/detail/BookmarkTVShowRepository.kt | 20 +- .../tvshow/detail/TVShowDetailRepository.kt | 38 +- .../AiringTodayTvSeriesPagingRepository.kt | 21 +- .../DiscoverTvSeriesPagingRepository.kt | 19 +- .../OnTheAirTvSeriesPagingRepository.kt | 21 +- .../paging/PopularTvSeriesPagingRepository.kt | 21 +- .../paging/SearchTvSeriesPagingRepository.kt | 21 +- .../paging/SimilarTvSeriesPagingRepository.kt | 19 +- .../TopRatedTvSeriesPagingRepository.kt | 21 +- .../TrendingTvSeriesPagingRepository.kt | 21 +- .../sample/tmdb/data/response/CreditDto.kt | 68 +-- .../sample/tmdb/data/response/DetailDto.kt | 131 +++-- .../com/sample/tmdb/data/response/ImageDto.kt | 13 +- .../sample/tmdb/data/response/PersonDto.kt | 11 +- .../com/sample/tmdb/data/response/TMDbDto.kt | 22 +- .../sample/tmdb/data/response/WrapperDto.kt | 6 +- .../tmdb/data/source/entity/MovieEntity.kt | 48 +- .../tmdb/data/source/entity/TVShowEntity.kt | 48 +- .../sample/tmdb/data/source/local/MovieDao.kt | 3 +- .../tmdb/data/source/local/TMDbDatabase.kt | 2 +- .../tmdb/data/source/local/TVShowDao.kt | 3 +- .../sample/tmdb/data/utils/NetworkUtils.kt | 18 +- .../BaseBookmarkDetailsRepositoryTest.kt | 3 +- .../repository/BaseBookmarkRepositoryTest.kt | 20 +- .../repository/BaseDetailRepositoryTest.kt | 5 +- .../data/repository/BaseFeedRepositoryTest.kt | 5 +- .../data/repository/BaseRepositoryTest.kt | 3 +- .../data/repository/PersonRepositoryTest.kt | 28 +- .../movie/MovieFeedRepositoryTest.kt | 20 +- .../BookmarkMovieDetailsRepositoryTest.kt | 12 +- .../detail/BookmarkMovieRepositoryTest.kt | 12 +- .../movie/detail/MovieDetailRepositoryTest.kt | 52 +- .../tvshow/TVShowFeedRepositoryTest.kt | 22 +- .../BookmarkTVShowDetailsRepositoryTest.kt | 12 +- .../detail/BookmarkTVShowRepositoryTest.kt | 14 +- .../detail/TVShowDetailRepositoryTest.kt | 52 +- .../sample/tmdb/domain/model/CreditModels.kt | 6 +- .../sample/tmdb/domain/model/DetailWrapper.kt | 4 +- .../sample/tmdb/domain/model/FeedWrapper.kt | 4 +- .../com/sample/tmdb/domain/model/Person.kt | 4 +- .../com/sample/tmdb/domain/model/SortType.kt | 4 +- .../tmdb/domain/model/TMDbDetailsModels.kt | 8 +- .../com/sample/tmdb/domain/model/TMDbImage.kt | 5 +- .../sample/tmdb/domain/model/TMDbModels.kt | 6 +- .../tmdb/domain/paging/BasePagingSource.kt | 14 +- .../domain/repository/BaseDetailRepository.kt | 7 +- .../domain/repository/BaseFeedRepository.kt | 19 +- .../domain/repository/BasePagingRepository.kt | 20 +- .../repository/BookmarkDetailsRepository.kt | 5 +- .../sample/tmdb/domain/utils/Annotations.kt | 2 +- .../tmdb/bookmark/BookmarkScreenTest.kt | 21 +- .../tmdb/bookmark/BookmarkMovieViewModel.kt | 8 +- .../sample/tmdb/bookmark/BookmarkScreen.kt | 114 ++-- .../tmdb/bookmark/BookmarkTVShowViewModel.kt | 8 +- .../sample/tmdb/credit/CreditScreenTest.kt | 9 +- .../sample/tmdb/credit/PersonScreenTest.kt | 30 +- .../com/sample/tmdb/credit/CreditScreen.kt | 34 +- .../com/sample/tmdb/credit/PersonScreen.kt | 160 +++--- .../com/sample/tmdb/credit/PersonViewModel.kt | 20 +- .../sample/tmdb/credit/PersonViewModelTest.kt | 3 +- .../sample/tmdb/detail/DetailScreenTest.kt | 7 +- .../sample/tmdb/detail/BaseDetailViewModel.kt | 37 +- .../com/sample/tmdb/detail/DetailScreen.kt | 533 ++++++++++-------- .../tmdb/detail/MovieDetailViewModel.kt | 12 +- .../tmdb/detail/TVShowDetailViewModel.kt | 12 +- .../com/sample/tmdb/detail/utils/StringExt.kt | 7 +- .../tmdb/detail/BaseDetailViewModelTest.kt | 5 +- .../tmdb/detail/MovieDetailViewModelTest.kt | 18 +- .../tmdb/detail/TVShowDetailViewModelTest.kt | 18 +- .../com/sample/tmdb/feed/FeedScreenTest.kt | 134 +++-- .../java/com/sample/tmdb/feed/FeedScreen.kt | 150 +++-- .../sample/tmdb/feed/MovieFeedViewModel.kt | 7 +- .../sample/tmdb/feed/TVShowFeedViewModel.kt | 7 +- .../com/sample/tmdb/feed/utils/ModifierExt.kt | 19 +- .../sample/tmdb/feed/BaseFeedViewModelTest.kt | 5 +- .../tmdb/feed/MovieFeedViewModelTest.kt | 5 +- .../tmdb/feed/TVShowFeedViewModelTest.kt | 5 +- .../com/sample/tmdb/image/ImageScreenTest.kt | 5 +- .../java/com/sample/tmdb/image/ImageScreen.kt | 72 ++- .../tmdb/paging/search/SearchBarTest.kt | 19 +- .../sample/tmdb/paging/BasePagingViewModel.kt | 3 +- .../com/sample/tmdb/paging/PagingScreen.kt | 130 +++-- .../paging/main/BaseMainPagingViewModel.kt | 5 +- .../tmdb/paging/main/MainPagingScreens.kt | 164 +++--- .../main/movie/DiscoverMoviesViewModel.kt | 10 +- .../main/movie/NowPlayingMoviesViewModel.kt | 10 +- .../main/movie/PopularMoviesViewModel.kt | 10 +- .../main/movie/SimilarMoviesViewModel.kt | 10 +- .../main/movie/TopRatedMoviesViewModel.kt | 10 +- .../main/movie/TrendingMoviesViewModel.kt | 10 +- .../main/movie/UpcomingMoviesViewModel.kt | 10 +- .../tvshow/AiringTodayTvSeriesViewModel.kt | 10 +- .../main/tvshow/DiscoverTvSeriesViewModel.kt | 10 +- .../main/tvshow/OnTheAirTvSeriesViewModel.kt | 10 +- .../main/tvshow/PopularTvSeriesViewModel.kt | 10 +- .../main/tvshow/SimilarTvSeriesViewModel.kt | 10 +- .../main/tvshow/TopRatedTvSeriesViewModel.kt | 10 +- .../main/tvshow/TrendingTvSeriesViewModel.kt | 10 +- .../tmdb/paging/search/AnimatedSearch.kt | 62 +- .../search/BaseSearchPagingViewModel.kt | 18 +- .../paging/search/InfiniteFlowingCircle.kt | 42 +- .../paging/search/SearchMoviesViewModel.kt | 12 +- .../tmdb/paging/search/SearchScreens.kt | 129 +++-- .../paging/search/SearchTvSeriesViewModel.kt | 12 +- .../sample/tmdb/setting/SettingScreenTest.kt | 9 +- .../com/sample/tmdb/setting/SettingScreen.kt | 129 +++-- spotless.gradle | 20 + 185 files changed, 2783 insertions(+), 2147 deletions(-) create mode 100644 .editorconfig create mode 100644 .github/workflows/spotless.yml create mode 100644 spotless.gradle diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..91eed1e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +root = true + +[*.{kt,kts}] +ktlint_function_naming_ignore_when_annotated_with=Composable, Test \ No newline at end of file diff --git a/.github/workflows/spotless.yml b/.github/workflows/spotless.yml new file mode 100644 index 0000000..63bbf3e --- /dev/null +++ b/.github/workflows/spotless.yml @@ -0,0 +1,30 @@ +name: Spotless Check + +on: [push, pull_request] + +jobs: + spotlessCheck: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: 17 + distribution: 'adopt' + + - name: Cache Gradle dependencies + uses: actions/cache@v3 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle + + - name: Run Spotless Check + run: ./gradlew spotlessCheck \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 6515989..8f8815f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -82,4 +82,4 @@ dependencies { implementation Deps.hilt ksp Deps.hilt_compiler implementation Deps.gson -} \ No newline at end of file +} diff --git a/app/src/main/java/com/sample/tmdb/Application.kt b/app/src/main/java/com/sample/tmdb/Application.kt index 6c2b68c..2a95c16 100644 --- a/app/src/main/java/com/sample/tmdb/Application.kt +++ b/app/src/main/java/com/sample/tmdb/Application.kt @@ -3,4 +3,4 @@ package com.sample.tmdb import dagger.hilt.android.HiltAndroidApp @HiltAndroidApp -class Application : android.app.Application() \ No newline at end of file +class Application : android.app.Application() diff --git a/app/src/main/java/com/sample/tmdb/ui/MainActivity.kt b/app/src/main/java/com/sample/tmdb/ui/MainActivity.kt index 41dc932..078f4fd 100644 --- a/app/src/main/java/com/sample/tmdb/ui/MainActivity.kt +++ b/app/src/main/java/com/sample/tmdb/ui/MainActivity.kt @@ -12,14 +12,12 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.graphics.toArgb import androidx.core.view.WindowCompat import com.sample.tmdb.common.ui.theme.AlphaNavigationBar - import com.sample.tmdb.common.ui.theme.AlphaNearOpaque import com.sample.tmdb.common.ui.theme.TmdbPagingComposeTheme import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint class MainActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -37,29 +35,40 @@ class MainActivity : ComponentActivity() { @Composable private fun ChangeSystemBarsTheme(lightTheme: Boolean) { - val statusBarColor = MaterialTheme.colors.background.copy(alpha = AlphaNearOpaque).toArgb() + val statusBarColor = + MaterialTheme.colors.background + .copy(alpha = AlphaNearOpaque) + .toArgb() val navigationBarColor = - MaterialTheme.colors.background.copy(alpha = AlphaNavigationBar).toArgb() + MaterialTheme.colors.background + .copy(alpha = AlphaNavigationBar) + .toArgb() LaunchedEffect(lightTheme) { if (lightTheme) { enableEdgeToEdge( - statusBarStyle = SystemBarStyle.light( - statusBarColor, statusBarColor, - ), - navigationBarStyle = SystemBarStyle.light( - navigationBarColor, navigationBarColor, - ), + statusBarStyle = + SystemBarStyle.light( + statusBarColor, + statusBarColor, + ), + navigationBarStyle = + SystemBarStyle.light( + navigationBarColor, + navigationBarColor, + ), ) } else { enableEdgeToEdge( - statusBarStyle = SystemBarStyle.dark( - statusBarColor - ), - navigationBarStyle = SystemBarStyle.dark( - navigationBarColor, - ), + statusBarStyle = + SystemBarStyle.dark( + statusBarColor, + ), + navigationBarStyle = + SystemBarStyle.dark( + navigationBarColor, + ), ) } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/sample/tmdb/ui/TMDbApp.kt b/app/src/main/java/com/sample/tmdb/ui/TMDbApp.kt index 434a74c..9e6cf58 100644 --- a/app/src/main/java/com/sample/tmdb/ui/TMDbApp.kt +++ b/app/src/main/java/com/sample/tmdb/ui/TMDbApp.kt @@ -83,18 +83,19 @@ fun TMDbApp() { navigateToRoute = appState::navigateToBottomBarRoute, ) } - } + }, ) { innerPaddingModifier -> - val newPadding = PaddingValues( - start = innerPaddingModifier.calculateStartPadding(LocalLayoutDirection.current), - end = innerPaddingModifier.calculateEndPadding(LocalLayoutDirection.current), - top = innerPaddingModifier.calculateTopPadding(), - bottom = 0.dp, - ) + val newPadding = + PaddingValues( + start = innerPaddingModifier.calculateStartPadding(LocalLayoutDirection.current), + end = innerPaddingModifier.calculateEndPadding(LocalLayoutDirection.current), + top = innerPaddingModifier.calculateTopPadding(), + bottom = 0.dp, + ) NavHost( navController = appState.navController, startDestination = MainDestinations.HOME_ROUTE, - modifier = Modifier.padding(newPadding) + modifier = Modifier.padding(newPadding), ) { navigationScreens(appState.navController) detailScreens(appState.navController) @@ -112,16 +113,16 @@ fun TMDbApp() { private fun TMDbBottomBar( tabs: Array, currentRoute: String, - navigateToRoute: (String) -> Unit + navigateToRoute: (String) -> Unit, ) { val currentSection = tabs.first { it.route == currentRoute } Box( - Modifier.navigationBarsPadding() + Modifier.navigationBarsPadding(), ) { BottomNavigation( backgroundColor = MaterialTheme.colors.background.copy(alpha = AlphaNavigationBar), - elevation = TMDb_0_dp + elevation = TMDb_0_dp, ) { tabs.forEach { section -> val selected = section == currentSection @@ -132,13 +133,13 @@ private fun TMDbBottomBar( icon = { Icon( imageVector = if (selected) section.selectedIcon else section.unselectedIcon, - contentDescription = stringResource(id = section.title) + contentDescription = stringResource(id = section.title), ) }, selected = selected, unselectedContentColor = MaterialTheme.colors.onBackground.copy(alpha = ContentAlpha.disabled), selectedContentColor = MaterialTheme.colors.onBackground, - onClick = { navigateToRoute(section.route) } + onClick = { navigateToRoute(section.route) }, ) } } @@ -148,7 +149,7 @@ private fun TMDbBottomBar( private fun NavGraphBuilder.navigationScreens(navController: NavController) { navigation( route = MainDestinations.HOME_ROUTE, - startDestination = HomeSections.MOVIE_SECTION.route + startDestination = HomeSections.MOVIE_SECTION.route, ) { composable(route = HomeSections.MOVIE_SECTION.route) { MovieFeedScreen(navController = navController) @@ -168,15 +169,19 @@ private fun NavGraphBuilder.navigationScreens(navController: NavController) { private fun NavGraphBuilder.detailScreens(navController: NavController) { composable( route = "${MainDestinations.TMDB_MOVIE_DETAIL_ROUTE}/{${MainDestinations.TMDB_ID_KEY}}", - arguments = listOf( - navArgument(MainDestinations.TMDB_ID_KEY) { type = NavType.IntType }) + arguments = + listOf( + navArgument(MainDestinations.TMDB_ID_KEY) { type = NavType.IntType }, + ), ) { MovieDetailScreen(navController) } composable( route = "${MainDestinations.TMDB_TV_SHOW_DETAIL_ROUTE}/{${MainDestinations.TMDB_ID_KEY}}", - arguments = listOf( - navArgument(MainDestinations.TMDB_ID_KEY) { type = NavType.IntType }) + arguments = + listOf( + navArgument(MainDestinations.TMDB_ID_KEY) { type = NavType.IntType }, + ), ) { TVShowDetailScreen(navController) } @@ -203,8 +208,10 @@ private fun NavGraphBuilder.moviePagingScreens(navController: NavController) { } composable( route = "${MainDestinations.TMDB_SIMILAR_MOVIES_ROUTE}/{${MainDestinations.TMDB_SIMILAR_ID}}", - arguments = listOf( - navArgument(MainDestinations.TMDB_SIMILAR_ID) { type = NavType.IntType }) + arguments = + listOf( + navArgument(MainDestinations.TMDB_SIMILAR_ID) { type = NavType.IntType }, + ), ) { SimilarMovieScreen(navController = navController) } @@ -231,8 +238,10 @@ private fun NavGraphBuilder.tvShowPagingScreens(navController: NavController) { } composable( route = "${MainDestinations.TMDB_SIMILAR_TV_SHOW_ROUTE}/{${MainDestinations.TMDB_SIMILAR_ID}}", - arguments = listOf( - navArgument(MainDestinations.TMDB_SIMILAR_ID) { type = NavType.IntType }) + arguments = + listOf( + navArgument(MainDestinations.TMDB_SIMILAR_ID) { type = NavType.IntType }, + ), ) { SimilarTVShowScreen(navController = navController) } @@ -250,30 +259,34 @@ private fun NavGraphBuilder.searchScreens(navController: NavController) { private fun NavGraphBuilder.creditScreens(navController: NavController) { composable( route = "${MainDestinations.TMDB_CAST_ROUTE}/{${MainDestinations.TMDB_CREDIT_KEY}}", - arguments = listOf( - navArgument(MainDestinations.TMDB_CREDIT_KEY) { type = NavType.StringType }) + arguments = + listOf( + navArgument(MainDestinations.TMDB_CREDIT_KEY) { type = NavType.StringType }, + ), ) { from -> CreditScreen( R.string.cast, navController, gson.fromJson>( from.arguments?.getString(MainDestinations.TMDB_CREDIT_KEY), - object : TypeToken>() {}.type - ) + object : TypeToken>() {}.type, + ), ) } composable( route = "${MainDestinations.TMDB_CREW_ROUTE}/{${MainDestinations.TMDB_CREDIT_KEY}}", - arguments = listOf( - navArgument(MainDestinations.TMDB_CREDIT_KEY) { type = NavType.StringType }) + arguments = + listOf( + navArgument(MainDestinations.TMDB_CREDIT_KEY) { type = NavType.StringType }, + ), ) { from -> CreditScreen( R.string.crew, navController, gson.fromJson>( from.arguments?.getString(MainDestinations.TMDB_CREDIT_KEY), - object : TypeToken>() {}.type - ) + object : TypeToken>() {}.type, + ), ) } } @@ -281,8 +294,10 @@ private fun NavGraphBuilder.creditScreens(navController: NavController) { private fun NavGraphBuilder.personScreen(navController: NavController) { composable( route = "${MainDestinations.TMDB_PERSON_ROUTE}/{${MainDestinations.TMDB_PERSON_KEY}}", - arguments = listOf( - navArgument(MainDestinations.TMDB_PERSON_KEY) { type = NavType.StringType }) + arguments = + listOf( + navArgument(MainDestinations.TMDB_PERSON_KEY) { type = NavType.StringType }, + ), ) { PersonScreen({ navController.navigateUp() }) } @@ -291,17 +306,19 @@ private fun NavGraphBuilder.personScreen(navController: NavController) { private fun NavGraphBuilder.imagesScreen() { composable( route = "${MainDestinations.TMDB_IMAGES_ROUTE}/{${MainDestinations.TMDB_IMAGES_KEY}}/{${MainDestinations.TMDB_IMAGE_PAGE}}", - arguments = listOf( - navArgument(MainDestinations.TMDB_IMAGES_KEY) { type = NavType.StringType }, - navArgument(MainDestinations.TMDB_IMAGE_PAGE) { type = NavType.IntType } - ) + arguments = + listOf( + navArgument(MainDestinations.TMDB_IMAGES_KEY) { type = NavType.StringType }, + navArgument(MainDestinations.TMDB_IMAGE_PAGE) { type = NavType.IntType }, + ), ) { from -> ImagesScreen( - images = gson.fromJson( - from.arguments?.getString(MainDestinations.TMDB_IMAGES_KEY), - object : TypeToken>() {}.type - ), - initialPage = from.arguments?.getInt(MainDestinations.TMDB_IMAGE_PAGE)!! + images = + gson.fromJson( + from.arguments?.getString(MainDestinations.TMDB_IMAGES_KEY), + object : TypeToken>() {}.type, + ), + initialPage = from.arguments?.getInt(MainDestinations.TMDB_IMAGE_PAGE)!!, ) } } @@ -310,12 +327,12 @@ enum class HomeSections( val route: String, @StringRes val title: Int, val unselectedIcon: ImageVector, - val selectedIcon: ImageVector + val selectedIcon: ImageVector, ) { MOVIE_SECTION("Movie", R.string.movie, Icons.Outlined.Movie, Icons.Filled.Movie), TV_SHOW_SECTION("TVShow", R.string.tv_show, Icons.Outlined.Tv, Icons.Filled.Tv), BOOKMARK_SECTION("Bookmark", R.string.favorite, Icons.Outlined.Favorite, Icons.Filled.Favorite), - SETTING_SECTION("Setting", R.string.setting, Icons.Outlined.Settings, Icons.Filled.Settings) + SETTING_SECTION("Setting", R.string.setting, Icons.Outlined.Settings, Icons.Filled.Settings), } -private val gson = Gson() \ No newline at end of file +private val gson = Gson() diff --git a/app/src/main/java/com/sample/tmdb/ui/TMDbAppState.kt b/app/src/main/java/com/sample/tmdb/ui/TMDbAppState.kt index 6a41376..5731310 100644 --- a/app/src/main/java/com/sample/tmdb/ui/TMDbAppState.kt +++ b/app/src/main/java/com/sample/tmdb/ui/TMDbAppState.kt @@ -9,14 +9,11 @@ import androidx.navigation.NavHostController import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController - /** * Remembers and creates an instance of [TMDbAppState] */ @Composable -fun rememberTMDbAppState( - navController: NavHostController = rememberNavController(), -) = +fun rememberTMDbAppState(navController: NavHostController = rememberNavController()) = remember(navController) { TMDbAppState(navController) } @@ -25,7 +22,6 @@ fun rememberTMDbAppState( class TMDbAppState( val navController: NavHostController, ) { - // ---------------------------------------------------------- // BottomBar state source of truth // ---------------------------------------------------------- @@ -36,8 +32,12 @@ class TMDbAppState( // Reading this attribute will cause recompositions when the bottom bar needs shown, or not. // Not all routes need to show the bottom bar. val shouldShowBottomBar: Boolean - @Composable get() = navController - .currentBackStackEntryAsState().value?.destination?.route in bottomBarRoutes + @Composable get() = + navController + .currentBackStackEntryAsState() + .value + ?.destination + ?.route in bottomBarRoutes // ---------------------------------------------------------- // Navigation state source of truth @@ -69,6 +69,5 @@ private val NavGraph.startDestination: NavDestination? * * https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:navigation/navigation-ui/src/main/java/androidx/navigation/ui/NavigationUI.kt */ -private tailrec fun findStartDestination(graph: NavDestination): NavDestination { - return if (graph is NavGraph) findStartDestination(graph.startDestination!!) else graph -} \ No newline at end of file +private tailrec fun findStartDestination(graph: NavDestination): NavDestination = + if (graph is NavGraph) findStartDestination(graph.startDestination!!) else graph diff --git a/build.gradle b/build.gradle index f862cac..24b98ef 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,7 @@ buildscript { dependencies { classpath "com.google.dagger:hilt-android-gradle-plugin:${Versions.hilt}" + classpath("com.diffplug.spotless:spotless-plugin-gradle:${Versions.spotless}") } }// Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { @@ -8,8 +9,18 @@ plugins { id 'com.android.library' version '8.3.1' apply false id 'org.jetbrains.kotlin.android' version '1.9.23' apply false id 'com.google.devtools.ksp' version "1.9.23-1.0.19" apply false + id 'com.diffplug.spotless' version '7.0.0.BETA2' apply false } -tasks.register('clean', Delete) { - delete rootProject.layout.buildDirectory -} \ No newline at end of file +apply from: "$project.rootDir/spotless.gradle" + +task createSpotlessPreCommitHook() { + def gitHooksDirectory = new File("$project.rootDir/.git/hooks/") + if (!gitHooksDirectory.exists()) gitHooksDirectory.mkdirs() + new File("$project.rootDir/.git/hooks", "pre-commit").text = """ + #!/bin/bash + echo "Running spotless check" + ./gradlew spotlessApply +""" + "chmod +x .git/hooks/pre-commit".execute() +} diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index df450c3..3c87b69 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -1,6 +1,3 @@ -import org.gradle.internal.impldep.com.esotericsoftware.minlog.Log -import java.io.File - object Versions { const val compose = "1.6.4" const val compose_paging = "3.2.1" @@ -29,6 +26,7 @@ object Versions { const val junit = "4.13.2" const val mockk = "1.13.12" const val turbine = "1.1.0" + const val spotless = "7.0.0.BETA2" } object AppMetaData { @@ -131,4 +129,4 @@ object Deps { const val junit4 = "junit:junit:${Versions.junit}" const val mockk = "io.mockk:mockk:${Versions.mockk}" const val turbine = "app.cash.turbine:turbine:${Versions.turbine}" -} \ No newline at end of file +} diff --git a/common-test/src/main/java/com/sample/tmdb/common/test/TestCoroutineRule.kt b/common-test/src/main/java/com/sample/tmdb/common/test/TestCoroutineRule.kt index 96b9226..fe30c81 100644 --- a/common-test/src/main/java/com/sample/tmdb/common/test/TestCoroutineRule.kt +++ b/common-test/src/main/java/com/sample/tmdb/common/test/TestCoroutineRule.kt @@ -10,9 +10,10 @@ import org.junit.runners.model.Statement @OptIn(ExperimentalCoroutinesApi::class) class TestCoroutineRule : TestRule { - - override fun apply(base: Statement, description: Description?) = object : Statement() { - + override fun apply( + base: Statement, + description: Description?, + ) = object : Statement() { override fun evaluate() { Dispatchers.setMain(Dispatchers.Unconfined) @@ -21,4 +22,4 @@ class TestCoroutineRule : TestRule { Dispatchers.resetMain() } } -} \ No newline at end of file +} diff --git a/common/src/androidTest/java/com/sample/tmdb/common/ui/component/DestinationBarTest.kt b/common/src/androidTest/java/com/sample/tmdb/common/ui/component/DestinationBarTest.kt index 88c067f..824ae72 100644 --- a/common/src/androidTest/java/com/sample/tmdb/common/ui/component/DestinationBarTest.kt +++ b/common/src/androidTest/java/com/sample/tmdb/common/ui/component/DestinationBarTest.kt @@ -11,7 +11,6 @@ import org.junit.Rule import org.junit.Test class DestinationBarTest { - @get:Rule val composeTestRule = createAndroidComposeRule() @@ -19,19 +18,19 @@ class DestinationBarTest { fun destinationBarTest() { with(composeTestRule) { setContent { - DestinationBar(Modifier,"title", {}, {}) + DestinationBar(Modifier, "title", {}, {}) } onNodeWithText("title").assertIsDisplayed() onNodeWithContentDescription( activity.getString( - R.string.back - ) + R.string.back, + ), ).assertIsDisplayed() onNodeWithContentDescription( activity.getString( - R.string.search_desc - ) + R.string.search_desc, + ), ).assertIsDisplayed() } } -} \ No newline at end of file +} diff --git a/common/src/androidTest/java/com/sample/tmdb/common/ui/component/ErrorScreenTest.kt b/common/src/androidTest/java/com/sample/tmdb/common/ui/component/ErrorScreenTest.kt index f9aa1d3..8d22303 100644 --- a/common/src/androidTest/java/com/sample/tmdb/common/ui/component/ErrorScreenTest.kt +++ b/common/src/androidTest/java/com/sample/tmdb/common/ui/component/ErrorScreenTest.kt @@ -2,14 +2,13 @@ package com.sample.tmdb.common.ui.component import androidx.activity.ComponentActivity import androidx.compose.ui.test.assertIsDisplayed -import org.junit.Rule import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onNodeWithText import com.sample.tmdb.common.R +import org.junit.Rule import org.junit.Test class ErrorScreenTest { - @get:Rule val composeTestRule = createAndroidComposeRule() @@ -23,9 +22,9 @@ class ErrorScreenTest { onNodeWithText("Message").assertIsDisplayed() onNodeWithText( activity.getString( - R.string.retry - ) + R.string.retry, + ), ).assertIsDisplayed() } } -} \ No newline at end of file +} diff --git a/common/src/androidTest/java/com/sample/tmdb/common/ui/component/PersonCardTest.kt b/common/src/androidTest/java/com/sample/tmdb/common/ui/component/PersonCardTest.kt index 254f16e..fae0821 100644 --- a/common/src/androidTest/java/com/sample/tmdb/common/ui/component/PersonCardTest.kt +++ b/common/src/androidTest/java/com/sample/tmdb/common/ui/component/PersonCardTest.kt @@ -13,7 +13,6 @@ import org.junit.Rule import org.junit.Test class PersonCardTest { - @get:Rule val composeTestRule = createAndroidComposeRule() @@ -22,23 +21,26 @@ class PersonCardTest { with(composeTestRule) { setContent { PersonCard( - person = Cast( - "role", "name", null, - Gender.MALE, 1 - ), - navController = rememberNavController() + person = + Cast( + "role", + "name", + null, + Gender.MALE, + 1, + ), + navController = rememberNavController(), ) } onNodeWithContentDescription( activity.getString( R.string.person_content_description, "name", - "role" - ) + "role", + ), ).assertIsDisplayed() onNodeWithText("role").assertIsDisplayed() onNodeWithText("name").assertIsDisplayed() - } } -} \ No newline at end of file +} diff --git a/common/src/androidTest/java/com/sample/tmdb/common/ui/component/TMDbCardTest.kt b/common/src/androidTest/java/com/sample/tmdb/common/ui/component/TMDbCardTest.kt index 1ff759a..4806818 100644 --- a/common/src/androidTest/java/com/sample/tmdb/common/ui/component/TMDbCardTest.kt +++ b/common/src/androidTest/java/com/sample/tmdb/common/ui/component/TMDbCardTest.kt @@ -9,7 +9,6 @@ import org.junit.Rule import org.junit.Test class TMDbCardTest { - @get:Rule val composeTestRule = createComposeRule() @@ -17,12 +16,23 @@ class TMDbCardTest { fun tmdbCardTest() { with(composeTestRule) { setContent { - TMDbCard(tmdbItem = Movie(1, "overview", - "releaseDate", null, null, "name", - 1.1, 1), {}) + TMDbCard( + tmdbItem = + Movie( + 1, + "overview", + "releaseDate", + null, + null, + "name", + 1.1, + 1, + ), + {}, + ) } onNodeWithText("name").assertIsDisplayed() onNodeWithContentDescription("name").assertIsDisplayed() } } -} \ No newline at end of file +} diff --git a/common/src/androidTest/java/com/sample/tmdb/common/ui/component/TMDbContentTest.kt b/common/src/androidTest/java/com/sample/tmdb/common/ui/component/TMDbContentTest.kt index 972db41..bf62ecb 100644 --- a/common/src/androidTest/java/com/sample/tmdb/common/ui/component/TMDbContentTest.kt +++ b/common/src/androidTest/java/com/sample/tmdb/common/ui/component/TMDbContentTest.kt @@ -12,7 +12,6 @@ import org.junit.Rule import org.junit.Test class TMDbContentTest { - @get:Rule val composeTestRule = createComposeRule() @@ -20,9 +19,19 @@ class TMDbContentTest { fun tmdbContentTest() { with(composeTestRule) { setContent { - TMDbContent(tmdbItem = Movie(1, "overview", - "releaseDate", null, null, "name", - 1.1, 1)) { + TMDbContent( + tmdbItem = + Movie( + 1, + "overview", + "releaseDate", + null, + null, + "name", + 1.1, + 1, + ), + ) { } } onNodeWithText("name").assertIsDisplayed() @@ -59,9 +68,19 @@ class TMDbContentTest { fun tmdbItemInfo() { with(composeTestRule) { setContent { - TMDbItemInfo(tmdbItem = Movie(1, "overview", - "releaseDate", null, null, "name", - 1.1, 1)) + TMDbItemInfo( + tmdbItem = + Movie( + 1, + "overview", + "releaseDate", + null, + null, + "name", + 1.1, + 1, + ), + ) } onNodeWithText("name").assertIsDisplayed() onNodeWithText("releaseDate").assertIsDisplayed() @@ -88,4 +107,4 @@ class TMDbContentTest { onNodeWithText("releaseDate").assertIsDisplayed() } } -} \ No newline at end of file +} diff --git a/common/src/main/java/com/sample/tmdb/common/MainDestinations.kt b/common/src/main/java/com/sample/tmdb/common/MainDestinations.kt index 406c1d8..d9a1552 100644 --- a/common/src/main/java/com/sample/tmdb/common/MainDestinations.kt +++ b/common/src/main/java/com/sample/tmdb/common/MainDestinations.kt @@ -21,7 +21,7 @@ object MainDestinations { const val TMDB_SEARCH_TV_SHOW_ROUTE = "search_tv_show" const val TMDB_CAST_ROUTE = "cast_list" const val TMDB_CREW_ROUTE = "crew_list" - const val TMDB_CREDIT_KEY = "credit_list" + const val TMDB_CREDIT_KEY = "credit_list" const val TMDB_PERSON_ROUTE = "person" const val TMDB_PERSON_KEY = "personId" const val TMDB_IMAGES_ROUTE = "images" @@ -30,4 +30,4 @@ object MainDestinations { const val TMDB_SIMILAR_MOVIES_ROUTE = "similar_movies" const val TMDB_SIMILAR_TV_SHOW_ROUTE = "similar_tv_show" const val TMDB_SIMILAR_ID = "similarId" -} \ No newline at end of file +} diff --git a/common/src/main/java/com/sample/tmdb/common/base/BaseRepository.kt b/common/src/main/java/com/sample/tmdb/common/base/BaseRepository.kt index 8d578c4..39c9218 100644 --- a/common/src/main/java/com/sample/tmdb/common/base/BaseRepository.kt +++ b/common/src/main/java/com/sample/tmdb/common/base/BaseRepository.kt @@ -10,16 +10,17 @@ import kotlinx.coroutines.flow.flowOn abstract class BaseRepository( private val context: Context, - private val ioDispatcher: CoroutineDispatcher + private val ioDispatcher: CoroutineDispatcher, ) { protected abstract suspend fun getSuccessResult(id: Any?): T - fun getResult(id: Any?): Flow> = flow { - emit(Resource.Loading) - try { - emit(Resource.Success(getSuccessResult(id))) - } catch (t: Throwable) { - emit(Resource.Error(context.getString(R.string.failed_loading_msg))) - } - }.flowOn(ioDispatcher) -} \ No newline at end of file + fun getResult(id: Any?): Flow> = + flow { + emit(Resource.Loading) + try { + emit(Resource.Success(getSuccessResult(id))) + } catch (t: Throwable) { + emit(Resource.Error(context.getString(R.string.failed_loading_msg))) + } + }.flowOn(ioDispatcher) +} diff --git a/common/src/main/java/com/sample/tmdb/common/base/BaseViewModel.kt b/common/src/main/java/com/sample/tmdb/common/base/BaseViewModel.kt index fa3cbb2..e3f6fad 100644 --- a/common/src/main/java/com/sample/tmdb/common/base/BaseViewModel.kt +++ b/common/src/main/java/com/sample/tmdb/common/base/BaseViewModel.kt @@ -9,9 +9,8 @@ import kotlinx.coroutines.launch open class BaseViewModel( private val repository: BaseRepository, - private val id: Any? = null + private val id: Any? = null, ) : ViewModel() { - private val _stateFlow = MutableStateFlow>(Resource.Loading) val stateFlow: StateFlow> get() = _stateFlow @@ -23,4 +22,4 @@ open class BaseViewModel( } } } -} \ No newline at end of file +} diff --git a/common/src/main/java/com/sample/tmdb/common/base/TMDbViewModel.kt b/common/src/main/java/com/sample/tmdb/common/base/TMDbViewModel.kt index 474d59b..4fb9c4d 100644 --- a/common/src/main/java/com/sample/tmdb/common/base/TMDbViewModel.kt +++ b/common/src/main/java/com/sample/tmdb/common/base/TMDbViewModel.kt @@ -2,10 +2,9 @@ package com.sample.tmdb.common.base open class TMDbViewModel( repository: BaseRepository, - id: Any? = null + id: Any? = null, ) : BaseViewModel(repository, id) { - init { refresh() } -} \ No newline at end of file +} diff --git a/common/src/main/java/com/sample/tmdb/common/model/Credit.kt b/common/src/main/java/com/sample/tmdb/common/model/Credit.kt index 3541a36..4bde636 100644 --- a/common/src/main/java/com/sample/tmdb/common/model/Credit.kt +++ b/common/src/main/java/com/sample/tmdb/common/model/Credit.kt @@ -16,7 +16,8 @@ interface Credit : Parcelable { enum class Gender { MALE, FEMALE } val Gender.placeholderIcon - get() = when (this) { - Gender.MALE -> Icons.Rounded.Man - Gender.FEMALE -> Icons.Rounded.Woman - } \ No newline at end of file + get() = + when (this) { + Gender.MALE -> Icons.Rounded.Man + Gender.FEMALE -> Icons.Rounded.Woman + } diff --git a/common/src/main/java/com/sample/tmdb/common/model/TMDbItem.kt b/common/src/main/java/com/sample/tmdb/common/model/TMDbItem.kt index 0be1f3f..842aa2c 100644 --- a/common/src/main/java/com/sample/tmdb/common/model/TMDbItem.kt +++ b/common/src/main/java/com/sample/tmdb/common/model/TMDbItem.kt @@ -11,4 +11,4 @@ interface TMDbItem : Parcelable { val name: String val voteAverage: Double val voteCount: Int -} \ No newline at end of file +} diff --git a/common/src/main/java/com/sample/tmdb/common/ui/Content.kt b/common/src/main/java/com/sample/tmdb/common/ui/Content.kt index 5e1a262..21b4210 100644 --- a/common/src/main/java/com/sample/tmdb/common/ui/Content.kt +++ b/common/src/main/java/com/sample/tmdb/common/ui/Content.kt @@ -12,14 +12,16 @@ import com.sample.tmdb.common.utils.Resource @Composable fun Content( viewModel: BaseViewModel, - successScreen: @Composable (T) -> Unit + successScreen: @Composable (T) -> Unit, ) { when (val resource = viewModel.stateFlow.collectAsState().value) { is Resource.Loading -> TMDbProgressBar() is Resource.Success -> successScreen(resource.data) - is Resource.Error -> ErrorScreen( - message = resource.message, Modifier.fillMaxSize(), - refresh = viewModel::refresh - ) + is Resource.Error -> + ErrorScreen( + message = resource.message, + Modifier.fillMaxSize(), + refresh = viewModel::refresh, + ) } -} \ No newline at end of file +} diff --git a/common/src/main/java/com/sample/tmdb/common/ui/Dimens.kt b/common/src/main/java/com/sample/tmdb/common/ui/Dimens.kt index 8bc7054..8e2e1a1 100644 --- a/common/src/main/java/com/sample/tmdb/common/ui/Dimens.kt +++ b/common/src/main/java/com/sample/tmdb/common/ui/Dimens.kt @@ -7,7 +7,6 @@ import androidx.compose.ui.unit.dp import com.sample.tmdb.common.R object Dimens { - val TMDb_0_dp: Dp @Composable get() = dimensionResource(R.dimen.TMDb_0_dp) @@ -36,4 +35,4 @@ object Dimens { @Composable get() = dimensionResource(R.dimen.TMDb_32_dp) val TMDb_120_dp = 120.dp -} \ No newline at end of file +} diff --git a/common/src/main/java/com/sample/tmdb/common/ui/component/DestinationBar.kt b/common/src/main/java/com/sample/tmdb/common/ui/component/DestinationBar.kt index c77ab6a..b9de0e4 100644 --- a/common/src/main/java/com/sample/tmdb/common/ui/component/DestinationBar.kt +++ b/common/src/main/java/com/sample/tmdb/common/ui/component/DestinationBar.kt @@ -32,17 +32,18 @@ fun DestinationBar( TopAppBar( backgroundColor = MaterialTheme.colors.background.copy(alpha = AlphaNearOpaque), contentColor = MaterialTheme.colors.onSurface, - elevation = TMDb_0_dp + elevation = TMDb_0_dp, ) { IconButton( onClick = { upPress?.invoke() }, - modifier = Modifier - .alpha(if (upPress == null) 0f else 1f) - .align(Alignment.CenterVertically) + modifier = + Modifier + .alpha(if (upPress == null) 0f else 1f) + .align(Alignment.CenterVertically), ) { Icon( imageVector = Icons.AutoMirrored.Filled.ArrowBack, - contentDescription = stringResource(R.string.back) + contentDescription = stringResource(R.string.back), ) } Text( @@ -52,22 +53,24 @@ fun DestinationBar( textAlign = TextAlign.Center, maxLines = 1, overflow = TextOverflow.Ellipsis, - modifier = Modifier - .weight(1f) - .align(Alignment.CenterVertically) + modifier = + Modifier + .weight(1f) + .align(Alignment.CenterVertically), ) IconButton( onClick = { onSearchClicked?.invoke() }, - modifier = Modifier - .alpha(if (onSearchClicked == null) 0f else 1f) - .align(Alignment.CenterVertically) + modifier = + Modifier + .alpha(if (onSearchClicked == null) 0f else 1f) + .align(Alignment.CenterVertically), ) { Icon( painter = painterResource(R.drawable.ic_search), - contentDescription = stringResource(id = R.string.search_desc) + contentDescription = stringResource(id = R.string.search_desc), ) } } TMDbDivider() } -} \ No newline at end of file +} diff --git a/common/src/main/java/com/sample/tmdb/common/ui/component/ErrorScreen.kt b/common/src/main/java/com/sample/tmdb/common/ui/component/ErrorScreen.kt index 7cdf8d3..b1d12c8 100644 --- a/common/src/main/java/com/sample/tmdb/common/ui/component/ErrorScreen.kt +++ b/common/src/main/java/com/sample/tmdb/common/ui/component/ErrorScreen.kt @@ -18,25 +18,29 @@ import com.sample.tmdb.common.R import com.sample.tmdb.common.ui.Dimens.TMDb_16_dp @Composable -fun ErrorScreen(message: String, modifier: Modifier = Modifier, refresh: () -> Unit) { +fun ErrorScreen( + message: String, + modifier: Modifier = Modifier, + refresh: () -> Unit, +) { Column( modifier = modifier, verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { Text( text = message, - style = MaterialTheme.typography.subtitle1.copy( - color = MaterialTheme.colors.onSurface, - letterSpacing = 1.5.sp, - fontFamily = FontFamily.SansSerif, - fontWeight = FontWeight.W400 - ) - + style = + MaterialTheme.typography.subtitle1.copy( + color = MaterialTheme.colors.onSurface, + letterSpacing = 1.5.sp, + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.W400, + ), ) Spacer(Modifier.height(TMDb_16_dp)) Button(onClick = refresh) { Text(text = stringResource(id = R.string.retry)) } } -} \ No newline at end of file +} diff --git a/common/src/main/java/com/sample/tmdb/common/ui/component/LoadingRow.kt b/common/src/main/java/com/sample/tmdb/common/ui/component/LoadingRow.kt index ebf3132..93ab98e 100644 --- a/common/src/main/java/com/sample/tmdb/common/ui/component/LoadingRow.kt +++ b/common/src/main/java/com/sample/tmdb/common/ui/component/LoadingRow.kt @@ -16,11 +16,12 @@ import com.sample.tmdb.common.ui.Dimens.TMDb_8_dp @Composable fun LoadingRow(modifier: Modifier = Modifier) { Row( - modifier = modifier - .fillMaxWidth() - .padding(TMDb_8_dp), + modifier = + modifier + .fillMaxWidth() + .padding(TMDb_8_dp), horizontalArrangement = Arrangement.spacedBy(TMDb_8_dp, Alignment.CenterHorizontally), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { CircularProgressIndicator(modifier = Modifier.size(40.dp)) } @@ -30,4 +31,4 @@ fun LoadingRow(modifier: Modifier = Modifier) { @Composable fun LoadingRowPreview() { LoadingRow() -} \ No newline at end of file +} diff --git a/common/src/main/java/com/sample/tmdb/common/ui/component/PersonCard.kt b/common/src/main/java/com/sample/tmdb/common/ui/component/PersonCard.kt index 57ced43..c2e2501 100644 --- a/common/src/main/java/com/sample/tmdb/common/ui/component/PersonCard.kt +++ b/common/src/main/java/com/sample/tmdb/common/ui/component/PersonCard.kt @@ -39,7 +39,7 @@ import com.sample.tmdb.common.utils.CircleTopCropTransformation fun PersonCard( person: Credit, navController: NavController, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, ) { Column( modifier @@ -47,41 +47,46 @@ fun PersonCard( .clickable { navController.navigate("${MainDestinations.TMDB_PERSON_ROUTE}/${person.id}") }, - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { Card( shape = CircleShape, elevation = TMDb_8_dp, - modifier = Modifier.size(TMDb_120_dp) + modifier = Modifier.size(TMDb_120_dp), ) { - val request = ImageRequest.Builder(LocalContext.current) - .data(person.profileUrl) - .crossfade(true) - .transformations(CircleTopCropTransformation()) - .build() + val request = + ImageRequest + .Builder(LocalContext.current) + .data(person.profileUrl) + .crossfade(true) + .transformations(CircleTopCropTransformation()) + .build() val placeholderPainter = rememberVectorPainter(person.gender.placeholderIcon) val painter = rememberAsyncImagePainter( model = request, error = placeholderPainter, - placeholder = placeholderPainter - ) - val colorFilter = when (painter.state) { - is AsyncImagePainter.State.Error, is AsyncImagePainter.State.Loading -> ColorFilter.tint( - MaterialTheme.colors.imageTint + placeholder = placeholderPainter, ) + val colorFilter = + when (painter.state) { + is AsyncImagePainter.State.Error, is AsyncImagePainter.State.Loading -> + ColorFilter.tint( + MaterialTheme.colors.imageTint, + ) - else -> null - } + else -> null + } Image( painter = painter, colorFilter = colorFilter, - contentDescription = stringResource( - id = R.string.person_content_description, - person.name, - person.role - ), - contentScale = ContentScale.FillHeight + contentDescription = + stringResource( + id = R.string.person_content_description, + person.name, + person.role, + ), + contentScale = ContentScale.FillHeight, ) } Text( @@ -89,17 +94,18 @@ fun PersonCard( style = MaterialTheme.typography.subtitle1.copy(fontWeight = FontWeight.SemiBold), maxLines = 1, overflow = TextOverflow.Ellipsis, - modifier = Modifier.padding(top = TMDb_4_dp) + modifier = Modifier.padding(top = TMDb_4_dp), ) Text( text = person.role, - style = MaterialTheme.typography.subtitle2.copy( - fontWeight = FontWeight.Normal, - fontStyle = FontStyle.Italic - ), + style = + MaterialTheme.typography.subtitle2.copy( + fontWeight = FontWeight.Normal, + fontStyle = FontStyle.Italic, + ), maxLines = 1, overflow = TextOverflow.Ellipsis, - modifier = Modifier.padding(top = TMDb_2_dp) + modifier = Modifier.padding(top = TMDb_2_dp), ) } -} \ No newline at end of file +} diff --git a/common/src/main/java/com/sample/tmdb/common/ui/component/TMDbCard.kt b/common/src/main/java/com/sample/tmdb/common/ui/component/TMDbCard.kt index 4bcaef1..7f0df56 100644 --- a/common/src/main/java/com/sample/tmdb/common/ui/component/TMDbCard.kt +++ b/common/src/main/java/com/sample/tmdb/common/ui/component/TMDbCard.kt @@ -27,21 +27,23 @@ fun TMDbCard( tmdbItem: TMDbItem, onFeedClick: (TMDbItem) -> Unit, imageUrl: String? = tmdbItem.posterUrl, - itemWidth: Dp = TMDb_120_dp + itemWidth: Dp = TMDb_120_dp, ) { Card( - modifier = Modifier - .padding(TMDb_6_dp) - .clickable(onClick = { onFeedClick(tmdbItem) }), - shape = RoundedCornerShape(10.dp) + modifier = + Modifier + .padding(TMDb_6_dp) + .clickable(onClick = { onFeedClick(tmdbItem) }), + shape = RoundedCornerShape(10.dp), ) { Column { AsyncImage( model = imageUrl, contentDescription = tmdbItem.name, - modifier = Modifier - .size(width = itemWidth, height = 180.dp), - contentScale = ContentScale.Crop + modifier = + Modifier + .size(width = itemWidth, height = 180.dp), + contentScale = ContentScale.Crop, ) Text( text = tmdbItem.name, @@ -50,10 +52,11 @@ fun TMDbCard( textAlign = TextAlign.Center, maxLines = 2, overflow = TextOverflow.Ellipsis, - modifier = Modifier - .size(width = itemWidth, height = 36.dp) - .wrapContentHeight() + modifier = + Modifier + .size(width = itemWidth, height = 36.dp) + .wrapContentHeight(), ) } } -} \ No newline at end of file +} diff --git a/common/src/main/java/com/sample/tmdb/common/ui/component/TMDbContent.kt b/common/src/main/java/com/sample/tmdb/common/ui/component/TMDbContent.kt index aa360e4..6360a80 100644 --- a/common/src/main/java/com/sample/tmdb/common/ui/component/TMDbContent.kt +++ b/common/src/main/java/com/sample/tmdb/common/ui/component/TMDbContent.kt @@ -55,31 +55,34 @@ import com.sample.tmdb.common.ui.theme.rateColors fun TMDbContent( tmdbItem: T, modifier: Modifier = Modifier, - onClick: (TMDbItem) -> Unit + onClick: (TMDbItem) -> Unit, ) { Box(modifier = modifier) { TMDbItemRate( tmdbItem.voteAverage, - modifier = Modifier - .align(Alignment.TopCenter) - .zIndex(2f) + modifier = + Modifier + .align(Alignment.TopCenter) + .zIndex(2f), ) Card( - modifier = Modifier - .fillMaxSize() - .offset(y = TMDb_12_dp), + modifier = + Modifier + .fillMaxSize() + .offset(y = TMDb_12_dp), shape = RoundedCornerShape(size = TMDb_8_dp), elevation = TMDb_8_dp, - onClick = { onClick.invoke(tmdbItem) } + onClick = { onClick.invoke(tmdbItem) }, ) { Box { TMDbItemPoster(tmdbItem.posterUrl, tmdbItem.name) TMDbItemInfo( tmdbItem, - modifier = Modifier - .align(Alignment.BottomCenter) - .fillMaxWidth() - .background(Color(0x97000000)) + modifier = + Modifier + .align(Alignment.BottomCenter) + .fillMaxWidth() + .background(Color(0x97000000)), ) } } @@ -87,36 +90,46 @@ fun TMDbContent( } @Composable -fun TMDbItemRate(rate: Double, modifier: Modifier = Modifier) { +fun TMDbItemRate( + rate: Double, + modifier: Modifier = Modifier, +) { val shape = RoundedCornerShape(percent = 50) Surface( shape = shape, elevation = TMDb_12_dp, - modifier = modifier + modifier = modifier, ) { Text( text = rate.toString(), style = MaterialTheme.typography.body1.copy(color = Color.White), - modifier = Modifier - .background(Brush.horizontalGradient(Color.rateColors(movieRate = rate))) - .padding(horizontal = 10.dp) + modifier = + Modifier + .background(Brush.horizontalGradient(Color.rateColors(movieRate = rate))) + .padding(horizontal = 10.dp), ) } } @Composable -fun BoxScope.TMDbItemPoster(posterUrl: String?, tmdbItemName: String) { - val painter = rememberAsyncImagePainter( - model = posterUrl, - error = rememberVectorPainter(Icons.Filled.BrokenImage), - placeholder = rememberVectorPainter(Icons.Default.Movie) - ) - val colorFilter = when (painter.state) { - is AsyncImagePainter.State.Loading, is AsyncImagePainter.State.Error -> ColorFilter.tint( - MaterialTheme.colors.imageTint +fun BoxScope.TMDbItemPoster( + posterUrl: String?, + tmdbItemName: String, +) { + val painter = + rememberAsyncImagePainter( + model = posterUrl, + error = rememberVectorPainter(Icons.Filled.BrokenImage), + placeholder = rememberVectorPainter(Icons.Default.Movie), ) - else -> null - } + val colorFilter = + when (painter.state) { + is AsyncImagePainter.State.Loading, is AsyncImagePainter.State.Error -> + ColorFilter.tint( + MaterialTheme.colors.imageTint, + ) + else -> null + } val scale = if (painter.state !is AsyncImagePainter.State.Success) ContentScale.Fit else ContentScale.FillBounds @@ -125,25 +138,30 @@ fun BoxScope.TMDbItemPoster(posterUrl: String?, tmdbItemName: String) { colorFilter = colorFilter, contentDescription = tmdbItemName, contentScale = scale, - modifier = Modifier - .fillMaxSize() - .align(Alignment.Center) + modifier = + Modifier + .fillMaxSize() + .align(Alignment.Center), ) } @Composable -fun TMDbItemInfo(tmdbItem: T, modifier: Modifier = Modifier) { +fun TMDbItemInfo( + tmdbItem: T, + modifier: Modifier = Modifier, +) { Column( verticalArrangement = Arrangement.spacedBy(TMDb_4_dp), - modifier = modifier.padding( - horizontal = TMDb_6_dp, - vertical = TMDb_4_dp - ) + modifier = + modifier.padding( + horizontal = TMDb_6_dp, + vertical = TMDb_4_dp, + ), ) { TMDbItemName(name = tmdbItem.name) Row( horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), ) { tmdbItem.releaseDate?.let { TMDbItemFeature(Icons.Default.DateRange, it) } TMDbItemFeature(Icons.Default.ThumbUp, tmdbItem.voteCount.toString()) @@ -152,38 +170,44 @@ fun TMDbItemInfo(tmdbItem: T, modifier: Modifier = Modifier) { } @Composable -fun TMDbItemName(name: String) = Text( - text = name, - style = MaterialTheme.typography.subtitle1.copy( - color = Color.White, - letterSpacing = 1.5.sp, - fontFamily = FontFamily.Serif, - fontWeight = FontWeight.W500 - ), - maxLines = 1, - overflow = TextOverflow.Ellipsis -) +fun TMDbItemName(name: String) = + Text( + text = name, + style = + MaterialTheme.typography.subtitle1.copy( + color = Color.White, + letterSpacing = 1.5.sp, + fontFamily = FontFamily.Serif, + fontWeight = FontWeight.W500, + ), + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) @Composable -fun TMDbItemFeature(icon: ImageVector, field: String) { +fun TMDbItemFeature( + icon: ImageVector, + field: String, +) { Row(verticalAlignment = Alignment.CenterVertically) { Icon( imageVector = icon, contentDescription = null, tint = Color.White, - modifier = Modifier.size(13.dp) + modifier = Modifier.size(13.dp), ) Text( text = field, - style = MaterialTheme.typography.subtitle2.copy( - color = Color.White, - letterSpacing = 1.5.sp, - fontFamily = FontFamily.SansSerif, - fontWeight = FontWeight.W400 - ), + style = + MaterialTheme.typography.subtitle2.copy( + color = Color.White, + letterSpacing = 1.5.sp, + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.W400, + ), overflow = TextOverflow.Ellipsis, maxLines = 1, - modifier = Modifier.padding(horizontal = TMDb_2_dp) + modifier = Modifier.padding(horizontal = TMDb_2_dp), ) } -} \ No newline at end of file +} diff --git a/common/src/main/java/com/sample/tmdb/common/ui/component/TMDbDivider.kt b/common/src/main/java/com/sample/tmdb/common/ui/component/TMDbDivider.kt index fa5824c..77f5826 100644 --- a/common/src/main/java/com/sample/tmdb/common/ui/component/TMDbDivider.kt +++ b/common/src/main/java/com/sample/tmdb/common/ui/component/TMDbDivider.kt @@ -19,13 +19,13 @@ fun TMDbDivider( modifier: Modifier = Modifier, color: Color = MaterialTheme.colors.onSurface.copy(alpha = DIVIDER_ALPHA), thickness: Dp = 1.dp, - startIndent: Dp = 0.dp + startIndent: Dp = 0.dp, ) { Divider( modifier = modifier, color = color, thickness = thickness, - startIndent = startIndent + startIndent = startIndent, ) } @@ -40,4 +40,4 @@ private fun DividerPreview() { TMDbDivider(Modifier.align(Alignment.Center)) } } -} \ No newline at end of file +} diff --git a/common/src/main/java/com/sample/tmdb/common/ui/component/TMDbProgressBar.kt b/common/src/main/java/com/sample/tmdb/common/ui/component/TMDbProgressBar.kt index 4758ba6..95a6b60 100644 --- a/common/src/main/java/com/sample/tmdb/common/ui/component/TMDbProgressBar.kt +++ b/common/src/main/java/com/sample/tmdb/common/ui/component/TMDbProgressBar.kt @@ -18,7 +18,7 @@ fun TMDbProgressBar() { Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { HorizontalDottedProgressBar() } @@ -29,51 +29,53 @@ fun HorizontalDottedProgressBar() { val color = MaterialTheme.colors.primary val infiniteTransition = rememberInfiniteTransition(label = "") - val state = infiniteTransition.animateFloat( - initialValue = 0f, - targetValue = 6f, - animationSpec = infiniteRepeatable( - animation = tween( - durationMillis = 700, - easing = LinearEasing - ) - ), label = "" - ) + val state = + infiniteTransition.animateFloat( + initialValue = 0f, + targetValue = 6f, + animationSpec = + infiniteRepeatable( + animation = + tween( + durationMillis = 700, + easing = LinearEasing, + ), + ), + label = "", + ) DrawCanvas(state = state.value, radius = 15.dp, color = color) } - @Composable fun DrawCanvas( state: Float, radius: Dp, color: Color, -){ +) { Canvas( - modifier = Modifier - .fillMaxWidth() - .height(55.dp), - ){ - + modifier = + Modifier + .fillMaxWidth() + .height(55.dp), + ) { val radiusValue = radius.value val padding = (radiusValue + (radiusValue * 0.5f)) - for(i in 1..5) { - if(i-1 == state.toInt()){ + for (i in 1..5) { + if (i - 1 == state.toInt()) { drawCircle( - radius = radiusValue*2, + radius = radiusValue * 2, brush = SolidColor(color), - center = Offset(x = this.center.x + radiusValue * 2 * (i-3) + padding * (i-3), y = this.center.y) + center = Offset(x = this.center.x + radiusValue * 2 * (i - 3) + padding * (i - 3), y = this.center.y), ) - } - else{ + } else { drawCircle( radius = radiusValue, brush = SolidColor(color), - center = Offset(x = this.center.x + radiusValue * 2 * (i-3) + padding * (i-3), y = this.center.y) + center = Offset(x = this.center.x + radiusValue * 2 * (i - 3) + padding * (i - 3), y = this.center.y), ) } } } -} \ No newline at end of file +} diff --git a/common/src/main/java/com/sample/tmdb/common/ui/theme/Color.kt b/common/src/main/java/com/sample/tmdb/common/ui/theme/Color.kt index 07cc667..a36cf1f 100644 --- a/common/src/main/java/com/sample/tmdb/common/ui/theme/Color.kt +++ b/common/src/main/java/com/sample/tmdb/common/ui/theme/Color.kt @@ -1,3 +1,5 @@ +@file:Suppress("ktlint:standard:property-naming") + package com.sample.tmdb.common.ui.theme import androidx.compose.material.Colors @@ -16,14 +18,15 @@ const val AlphaNearOpaque = 0.65f const val AlphaNavigationBar = 0.85f @Composable -fun Color.Companion.rateColors(movieRate: Double): List = remember(movieRate) { - when { - movieRate <= 4.5 -> listOf(Color(0xffe32d20), Color(0xff9c180e)) - movieRate < 7 -> listOf(Color(0xffe36922), Color(0xff963d09)) - movieRate < 8.5 -> listOf(Color(0xff87bf32), Color(0xff578216)) - else -> listOf(Color(0xff34c937), Color(0xff0d750f)) +fun Color.Companion.rateColors(movieRate: Double): List = + remember(movieRate) { + when { + movieRate <= 4.5 -> listOf(Color(0xffe32d20), Color(0xff9c180e)) + movieRate < 7 -> listOf(Color(0xffe36922), Color(0xff963d09)) + movieRate < 8.5 -> listOf(Color(0xff87bf32), Color(0xff578216)) + else -> listOf(Color(0xff34c937), Color(0xff0d750f)) + } } -} val Colors.imageTint: Color - get() = if (isLight) Color.Gray else Color.DarkGray \ No newline at end of file + get() = if (isLight) Color.Gray else Color.DarkGray diff --git a/common/src/main/java/com/sample/tmdb/common/ui/theme/Shape.kt b/common/src/main/java/com/sample/tmdb/common/ui/theme/Shape.kt index a0d6998..259ef79 100644 --- a/common/src/main/java/com/sample/tmdb/common/ui/theme/Shape.kt +++ b/common/src/main/java/com/sample/tmdb/common/ui/theme/Shape.kt @@ -4,8 +4,9 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Shapes import androidx.compose.ui.unit.dp -val Shapes = Shapes( - small = RoundedCornerShape(4.dp), - medium = RoundedCornerShape(4.dp), - large = RoundedCornerShape(0.dp) -) \ No newline at end of file +val Shapes = + Shapes( + small = RoundedCornerShape(4.dp), + medium = RoundedCornerShape(4.dp), + large = RoundedCornerShape(0.dp), + ) diff --git a/common/src/main/java/com/sample/tmdb/common/ui/theme/Theme.kt b/common/src/main/java/com/sample/tmdb/common/ui/theme/Theme.kt index f39d027..9823b76 100644 --- a/common/src/main/java/com/sample/tmdb/common/ui/theme/Theme.kt +++ b/common/src/main/java/com/sample/tmdb/common/ui/theme/Theme.kt @@ -20,20 +20,21 @@ object TmdbPagingComposeTheme { @Immutable data class FontSizes( - val sp_11: TextUnit = 11.sp + val sp_11: TextUnit = 11.sp, ) -private val DarkColorPalette = darkColors( - primary = AshGray, - primaryVariant = DarkGray, - secondary = Teal200 -) - -private val LightColorPalette = lightColors( - primary = GRAY, - primaryVariant = DarkGray, - secondary = Teal200 +private val DarkColorPalette = + darkColors( + primary = AshGray, + primaryVariant = DarkGray, + secondary = Teal200, + ) +private val LightColorPalette = + lightColors( + primary = GRAY, + primaryVariant = DarkGray, + secondary = Teal200, /* Other default colors to override background = Color.White, surface = Color.White, @@ -41,24 +42,25 @@ private val LightColorPalette = lightColors( onSecondary = Color.Black, onBackground = Color.Black, onSurface = Color.Black, - */ -) + */ + ) @Composable fun TmdbPagingComposeTheme( darkTheme: Boolean = isSystemInDarkTheme(), - content: @Composable () -> Unit + content: @Composable () -> Unit, ) { - val colors = if (darkTheme) { - DarkColorPalette - } else { - LightColorPalette - } + val colors = + if (darkTheme) { + DarkColorPalette + } else { + LightColorPalette + } MaterialTheme( colors = colors, typography = Typography, shapes = Shapes, - content = content + content = content, ) -} \ No newline at end of file +} diff --git a/common/src/main/java/com/sample/tmdb/common/ui/theme/Type.kt b/common/src/main/java/com/sample/tmdb/common/ui/theme/Type.kt index a2252b5..c2c4b0f 100644 --- a/common/src/main/java/com/sample/tmdb/common/ui/theme/Type.kt +++ b/common/src/main/java/com/sample/tmdb/common/ui/theme/Type.kt @@ -7,13 +7,15 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.sp // Set of Material typography styles to start with -val Typography = Typography( - body1 = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Normal, - fontSize = 16.sp - ) - /* Other default text styles to override +val Typography = + Typography( + body1 = + TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + ), + /* Other default text styles to override button = TextStyle( fontFamily = FontFamily.Default, fontWeight = FontWeight.W500, @@ -24,5 +26,5 @@ val Typography = Typography( fontWeight = FontWeight.Normal, fontSize = 12.sp ) - */ -) \ No newline at end of file + */ + ) diff --git a/common/src/main/java/com/sample/tmdb/common/utils/CircleTopCropTransformation.kt b/common/src/main/java/com/sample/tmdb/common/utils/CircleTopCropTransformation.kt index 7c0d27e..cc53fdb 100644 --- a/common/src/main/java/com/sample/tmdb/common/utils/CircleTopCropTransformation.kt +++ b/common/src/main/java/com/sample/tmdb/common/utils/CircleTopCropTransformation.kt @@ -10,10 +10,12 @@ import coil.transform.Transformation import kotlin.math.min class CircleTopCropTransformation : Transformation { - override val cacheKey: String = CircleTopCropTransformation::class.java.name - override suspend fun transform(input: Bitmap, size: Size): Bitmap { + override suspend fun transform( + input: Bitmap, + size: Size, + ): Bitmap { val minSize = min(input.width, input.height) val radius = minSize / 2f val output = Bitmap.createBitmap(minSize, minSize, input.config) @@ -29,4 +31,4 @@ class CircleTopCropTransformation : Transformation { companion object { private val MODE = PorterDuffXfermode(PorterDuff.Mode.SRC_IN) } -} \ No newline at end of file +} diff --git a/common/src/main/java/com/sample/tmdb/common/utils/Constants.kt b/common/src/main/java/com/sample/tmdb/common/utils/Constants.kt index 912ee39..7cdac74 100644 --- a/common/src/main/java/com/sample/tmdb/common/utils/Constants.kt +++ b/common/src/main/java/com/sample/tmdb/common/utils/Constants.kt @@ -14,4 +14,4 @@ object Constants { const val FIRST_AIR_DATE = "first_air_date" const val VOTE_AVERAGE = "vote_average" const val VOTE_COUNT = "vote_count" -} \ No newline at end of file +} diff --git a/common/src/main/java/com/sample/tmdb/common/utils/IntExt.kt b/common/src/main/java/com/sample/tmdb/common/utils/IntExt.kt index de4a8ed..dc8fe5e 100644 --- a/common/src/main/java/com/sample/tmdb/common/utils/IntExt.kt +++ b/common/src/main/java/com/sample/tmdb/common/utils/IntExt.kt @@ -14,4 +14,4 @@ fun Int.dpToPx(): Float { fun Int.toDp(): Float { val density = LocalDensity.current.density return remember(this) { this / density } -} \ No newline at end of file +} diff --git a/common/src/main/java/com/sample/tmdb/common/utils/Resource.kt b/common/src/main/java/com/sample/tmdb/common/utils/Resource.kt index 0e538a0..6af86c3 100644 --- a/common/src/main/java/com/sample/tmdb/common/utils/Resource.kt +++ b/common/src/main/java/com/sample/tmdb/common/utils/Resource.kt @@ -2,6 +2,12 @@ package com.sample.tmdb.common.utils sealed class Resource { object Loading : Resource() - data class Success(val data: T) : Resource() - data class Error(val message: String) : Resource() -} \ No newline at end of file + + data class Success( + val data: T, + ) : Resource() + + data class Error( + val message: String, + ) : Resource() +} diff --git a/common/src/main/java/com/sample/tmdb/common/utils/TMDbException.kt b/common/src/main/java/com/sample/tmdb/common/utils/TMDbException.kt index 5fdde86..965d92c 100644 --- a/common/src/main/java/com/sample/tmdb/common/utils/TMDbException.kt +++ b/common/src/main/java/com/sample/tmdb/common/utils/TMDbException.kt @@ -1,3 +1,5 @@ package com.sample.tmdb.common.utils -class TMDbException(message: String): Exception(message) \ No newline at end of file +class TMDbException( + message: String, +) : Exception(message) diff --git a/core/data/src/main/java/com/sample/tmdb/data/di/DataModule.kt b/core/data/src/main/java/com/sample/tmdb/data/di/DataModule.kt index a97683f..d30fe5e 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/di/DataModule.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/di/DataModule.kt @@ -15,23 +15,19 @@ import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) class DataModule { - @Singleton @Provides fun provideNetworkClient(): Retrofit = createNetworkClient(BuildConfig.TMDB_BASE_URL) @Singleton @Provides - fun provideMovieService(retrofit: Retrofit): MovieService = - retrofit.create(MovieService::class.java) + fun provideMovieService(retrofit: Retrofit): MovieService = retrofit.create(MovieService::class.java) @Singleton @Provides - fun provideTVShowService(retrofit: Retrofit): TVShowService = - retrofit.create(TVShowService::class.java) + fun provideTVShowService(retrofit: Retrofit): TVShowService = retrofit.create(TVShowService::class.java) @Singleton @Provides - fun providePersonService(retrofit: Retrofit): PersonService = - retrofit.create(PersonService::class.java) -} \ No newline at end of file + fun providePersonService(retrofit: Retrofit): PersonService = retrofit.create(PersonService::class.java) +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/di/DatabaseModule.kt b/core/data/src/main/java/com/sample/tmdb/data/di/DatabaseModule.kt index bcc93ac..112ede8 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/di/DatabaseModule.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/di/DatabaseModule.kt @@ -15,15 +15,17 @@ import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) class DatabaseModule { - @Singleton @Provides - fun provideTMDbDatabase(@ApplicationContext context: Context): TMDbDatabase = - Room.databaseBuilder( - context, - TMDbDatabase::class.java, - "TMDb.db" - ).build() + fun provideTMDbDatabase( + @ApplicationContext context: Context, + ): TMDbDatabase = + Room + .databaseBuilder( + context, + TMDbDatabase::class.java, + "TMDb.db", + ).build() @Provides @Singleton @@ -32,4 +34,4 @@ class DatabaseModule { @Provides @Singleton fun provideTVShowDao(db: TMDbDatabase): TVShowDao = db.tvShowDao -} \ No newline at end of file +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/di/DispatcherModule.kt b/core/data/src/main/java/com/sample/tmdb/data/di/DispatcherModule.kt index 822eb53..c7cca79 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/di/DispatcherModule.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/di/DispatcherModule.kt @@ -11,7 +11,6 @@ import javax.inject.Qualifier @Module @InstallIn(SingletonComponent::class) object DispatcherModule { - @IoDispatcher @Provides fun provideIoDispatcher(): CoroutineDispatcher = Dispatchers.IO @@ -19,4 +18,4 @@ object DispatcherModule { @Retention(AnnotationRetention.BINARY) @Qualifier -annotation class IoDispatcher \ No newline at end of file +annotation class IoDispatcher diff --git a/core/data/src/main/java/com/sample/tmdb/data/di/RepositoryModule.kt b/core/data/src/main/java/com/sample/tmdb/data/di/RepositoryModule.kt index 81c2f35..07a5ae4 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/di/RepositoryModule.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/di/RepositoryModule.kt @@ -1,13 +1,12 @@ package com.sample.tmdb.data.di import com.sample.tmdb.common.base.BaseRepository -import com.sample.tmdb.domain.model.* -import com.sample.tmdb.data.repository.* +import com.sample.tmdb.data.repository.PersonRepository +import com.sample.tmdb.data.repository.movie.MovieFeedRepository import com.sample.tmdb.data.repository.movie.detail.BookmarkMovieDetailsRepositoryImpl import com.sample.tmdb.data.repository.movie.detail.BookmarkMovieRepository -import com.sample.tmdb.data.repository.movie.paging.DiscoverMoviesPagingRepository import com.sample.tmdb.data.repository.movie.detail.MovieDetailRepository -import com.sample.tmdb.data.repository.movie.MovieFeedRepository +import com.sample.tmdb.data.repository.movie.paging.DiscoverMoviesPagingRepository import com.sample.tmdb.data.repository.movie.paging.NowPlayingMoviesPagingRepository import com.sample.tmdb.data.repository.movie.paging.PopularMoviesPagingRepository import com.sample.tmdb.data.repository.movie.paging.SearchMoviesPagingRepository @@ -15,30 +14,35 @@ import com.sample.tmdb.data.repository.movie.paging.SimilarMoviesPagingRepositor import com.sample.tmdb.data.repository.movie.paging.TopRatedMoviesPagingRepository import com.sample.tmdb.data.repository.movie.paging.TrendingMoviesPagingRepository import com.sample.tmdb.data.repository.movie.paging.UpcomingMoviesPagingRepository -import com.sample.tmdb.data.repository.tvshow.paging.AiringTodayTvSeriesPagingRepository +import com.sample.tmdb.data.repository.tvshow.TVShowFeedRepository import com.sample.tmdb.data.repository.tvshow.detail.BookmarkTVShowDetailsRepositoryImpl import com.sample.tmdb.data.repository.tvshow.detail.BookmarkTVShowRepository +import com.sample.tmdb.data.repository.tvshow.detail.TVShowDetailRepository +import com.sample.tmdb.data.repository.tvshow.paging.AiringTodayTvSeriesPagingRepository import com.sample.tmdb.data.repository.tvshow.paging.DiscoverTvSeriesPagingRepository import com.sample.tmdb.data.repository.tvshow.paging.OnTheAirTvSeriesPagingRepository import com.sample.tmdb.data.repository.tvshow.paging.PopularTvSeriesPagingRepository import com.sample.tmdb.data.repository.tvshow.paging.SearchTvSeriesPagingRepository import com.sample.tmdb.data.repository.tvshow.paging.SimilarTvSeriesPagingRepository -import com.sample.tmdb.data.repository.tvshow.detail.TVShowDetailRepository -import com.sample.tmdb.data.repository.tvshow.TVShowFeedRepository import com.sample.tmdb.data.repository.tvshow.paging.TopRatedTvSeriesPagingRepository import com.sample.tmdb.data.repository.tvshow.paging.TrendingTvSeriesPagingRepository +import com.sample.tmdb.domain.model.Movie +import com.sample.tmdb.domain.model.MovieDetails +import com.sample.tmdb.domain.model.Person +import com.sample.tmdb.domain.model.TVShow +import com.sample.tmdb.domain.model.TvDetails +import com.sample.tmdb.domain.repository.BaseDetailRepository +import com.sample.tmdb.domain.repository.BaseFeedRepository +import com.sample.tmdb.domain.repository.BasePagingRepository +import com.sample.tmdb.domain.repository.BookmarkDetailsRepository import com.sample.tmdb.domain.utils.Discover import com.sample.tmdb.domain.utils.Latest import com.sample.tmdb.domain.utils.NowPlaying import com.sample.tmdb.domain.utils.Popular import com.sample.tmdb.domain.utils.Search +import com.sample.tmdb.domain.utils.Similar import com.sample.tmdb.domain.utils.TopRated import com.sample.tmdb.domain.utils.Trending -import com.sample.tmdb.domain.repository.BaseDetailRepository -import com.sample.tmdb.domain.repository.BaseFeedRepository -import com.sample.tmdb.domain.repository.BasePagingRepository -import com.sample.tmdb.domain.repository.BookmarkDetailsRepository -import com.sample.tmdb.domain.utils.Similar import dagger.Binds import dagger.Module import dagger.hilt.InstallIn @@ -48,7 +52,6 @@ import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) abstract class RepositoryModule { - @Singleton @Binds internal abstract fun bindMovieFeedRepository(movieFeedRepository: MovieFeedRepository): BaseFeedRepository @@ -68,84 +71,114 @@ abstract class RepositoryModule { @Singleton @Trending @Binds - internal abstract fun bindTrendingMoviesRepository(trendingMoviesPagingRepository: TrendingMoviesPagingRepository): BasePagingRepository + internal abstract fun bindTrendingMoviesRepository( + trendingMoviesPagingRepository: TrendingMoviesPagingRepository, + ): BasePagingRepository @Singleton @Popular @Binds - internal abstract fun bindPopularMoviesRepository(popularMoviesPagingRepository: PopularMoviesPagingRepository): BasePagingRepository + internal abstract fun bindPopularMoviesRepository( + popularMoviesPagingRepository: PopularMoviesPagingRepository, + ): BasePagingRepository @Singleton @NowPlaying @Binds - internal abstract fun bindNowPlayingMoviesRepository(nowPlayingMoviesPagingRepository: NowPlayingMoviesPagingRepository): BasePagingRepository + internal abstract fun bindNowPlayingMoviesRepository( + nowPlayingMoviesPagingRepository: NowPlayingMoviesPagingRepository, + ): BasePagingRepository @Singleton @Latest @Binds - internal abstract fun bindUpcomingMoviesRepository(upcomingMoviesPagingRepository: UpcomingMoviesPagingRepository): BasePagingRepository + internal abstract fun bindUpcomingMoviesRepository( + upcomingMoviesPagingRepository: UpcomingMoviesPagingRepository, + ): BasePagingRepository @Singleton @TopRated @Binds - internal abstract fun bindTopRatedMoviesRepository(topRatedMoviesPagingRepository: TopRatedMoviesPagingRepository): BasePagingRepository + internal abstract fun bindTopRatedMoviesRepository( + topRatedMoviesPagingRepository: TopRatedMoviesPagingRepository, + ): BasePagingRepository @Singleton @Discover @Binds - internal abstract fun bindDiscoverMoviesRepository(discoverMoviesPagingRepository: DiscoverMoviesPagingRepository): BasePagingRepository + internal abstract fun bindDiscoverMoviesRepository( + discoverMoviesPagingRepository: DiscoverMoviesPagingRepository, + ): BasePagingRepository @Singleton @Similar @Binds - internal abstract fun bindSimilarMoviesRepository(similarMoviesPagingRepository: SimilarMoviesPagingRepository): BasePagingRepository - + internal abstract fun bindSimilarMoviesRepository( + similarMoviesPagingRepository: SimilarMoviesPagingRepository, + ): BasePagingRepository @Singleton @Search @Binds - internal abstract fun bindSearchMoviesRepository(searchMoviesPagingRepository: SearchMoviesPagingRepository): BasePagingRepository + internal abstract fun bindSearchMoviesRepository( + searchMoviesPagingRepository: SearchMoviesPagingRepository, + ): BasePagingRepository @Singleton @Trending @Binds - internal abstract fun bindTrendingTVShowRepository(trendingTvSeriesPagingRepository: TrendingTvSeriesPagingRepository): BasePagingRepository + internal abstract fun bindTrendingTVShowRepository( + trendingTvSeriesPagingRepository: TrendingTvSeriesPagingRepository, + ): BasePagingRepository @Singleton @Popular @Binds - internal abstract fun bindPopularTVShowRepository(popularTvSeriesPagingRepository: PopularTvSeriesPagingRepository): BasePagingRepository + internal abstract fun bindPopularTVShowRepository( + popularTvSeriesPagingRepository: PopularTvSeriesPagingRepository, + ): BasePagingRepository @Singleton @NowPlaying @Binds - internal abstract fun bindAiringTodayTVShowRepository(airingTodayTvSeriesPagingRepository: AiringTodayTvSeriesPagingRepository): BasePagingRepository + internal abstract fun bindAiringTodayTVShowRepository( + airingTodayTvSeriesPagingRepository: AiringTodayTvSeriesPagingRepository, + ): BasePagingRepository @Singleton @Latest @Binds - internal abstract fun bindOnTheAirTVShowRepository(onTheAirTvSeriesPagingRepository: OnTheAirTvSeriesPagingRepository): BasePagingRepository + internal abstract fun bindOnTheAirTVShowRepository( + onTheAirTvSeriesPagingRepository: OnTheAirTvSeriesPagingRepository, + ): BasePagingRepository @Singleton @TopRated @Binds - internal abstract fun bindTopRatedTVShowRepository(topRatedTvSeriesPagingRepository: TopRatedTvSeriesPagingRepository): BasePagingRepository + internal abstract fun bindTopRatedTVShowRepository( + topRatedTvSeriesPagingRepository: TopRatedTvSeriesPagingRepository, + ): BasePagingRepository @Singleton @Discover @Binds - internal abstract fun bindDiscoverTVShowRepository(discoverTvSeriesPagingRepository: DiscoverTvSeriesPagingRepository): BasePagingRepository + internal abstract fun bindDiscoverTVShowRepository( + discoverTvSeriesPagingRepository: DiscoverTvSeriesPagingRepository, + ): BasePagingRepository @Singleton @Similar @Binds - internal abstract fun bindSimilarTVShowRepository(similarTvSeriesPagingRepository: SimilarTvSeriesPagingRepository): BasePagingRepository - + internal abstract fun bindSimilarTVShowRepository( + similarTvSeriesPagingRepository: SimilarTvSeriesPagingRepository, + ): BasePagingRepository @Singleton @Search @Binds - internal abstract fun bindSearchTVShowRepository(searchTvSeriesPagingRepository: SearchTvSeriesPagingRepository): BasePagingRepository + internal abstract fun bindSearchTVShowRepository( + searchTvSeriesPagingRepository: SearchTvSeriesPagingRepository, + ): BasePagingRepository @Singleton @Binds @@ -153,11 +186,15 @@ abstract class RepositoryModule { @Singleton @Binds - internal abstract fun bindBookmarkMovieDetailsRepository(bookmarkMovieDetailsRepository: BookmarkMovieDetailsRepositoryImpl): BookmarkDetailsRepository + internal abstract fun bindBookmarkMovieDetailsRepository( + bookmarkMovieDetailsRepository: BookmarkMovieDetailsRepositoryImpl, + ): BookmarkDetailsRepository @Singleton @Binds - internal abstract fun bindBookmarkTVShowDetailsRepository(bookmarkTVShowDetailsRepository: BookmarkTVShowDetailsRepositoryImpl): BookmarkDetailsRepository + internal abstract fun bindBookmarkTVShowDetailsRepository( + bookmarkTVShowDetailsRepository: BookmarkTVShowDetailsRepositoryImpl, + ): BookmarkDetailsRepository @Singleton @Binds @@ -168,5 +205,4 @@ abstract class RepositoryModule { @Binds @JvmSuppressWildcards internal abstract fun bindBookmarkTVShowRepository(bookmarkTVShowRepository: BookmarkTVShowRepository): BaseRepository> - -} \ No newline at end of file +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/network/MovieService.kt b/core/data/src/main/java/com/sample/tmdb/data/network/MovieService.kt index d91b627..e8d6a62 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/network/MovieService.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/network/MovieService.kt @@ -10,7 +10,6 @@ import retrofit2.http.Path import retrofit2.http.Query interface MovieService { - @GET("3/trending/movie/day") suspend fun trendingMovies(): TMDbWrapper @@ -30,44 +29,64 @@ interface MovieService { suspend fun discoverMovies(): TMDbWrapper @GET("3/trending/movie/day") - suspend fun trendingMovies(@Query("page") page: Int): TMDbWrapper + suspend fun trendingMovies( + @Query("page") page: Int, + ): TMDbWrapper @GET("3/movie/popular") - suspend fun popularMovies(@Query("page") page: Int): TMDbWrapper + suspend fun popularMovies( + @Query("page") page: Int, + ): TMDbWrapper @GET("3/movie/now_playing") - suspend fun nowPlayingMovies(@Query("page") page: Int): TMDbWrapper + suspend fun nowPlayingMovies( + @Query("page") page: Int, + ): TMDbWrapper @GET("3/movie/upcoming") - suspend fun upcomingMovies(@Query("page") page: Int): TMDbWrapper + suspend fun upcomingMovies( + @Query("page") page: Int, + ): TMDbWrapper @GET("3/movie/top_rated") - suspend fun topRatedMovies(@Query("page") page: Int): TMDbWrapper + suspend fun topRatedMovies( + @Query("page") page: Int, + ): TMDbWrapper @GET("3/discover/movie") - suspend fun discoverMovies(@Query("page") page: Int): TMDbWrapper + suspend fun discoverMovies( + @Query("page") page: Int, + ): TMDbWrapper @GET("3/movie/{movieId}/credits") - suspend fun movieCredit(@Path("movieId") movieId: Int): NetworkCreditWrapper + suspend fun movieCredit( + @Path("movieId") movieId: Int, + ): NetworkCreditWrapper @GET("3/movie/{movie_id}") - suspend fun fetchMovieDetail(@Path("movie_id") movieId: Int): MovieDetailResponse + suspend fun fetchMovieDetail( + @Path("movie_id") movieId: Int, + ): MovieDetailResponse @GET("3/search/movie") suspend fun searchMovies( @Query("page") page: Int, - @Query("query") query: String + @Query("query") query: String, ): TMDbWrapper @GET("3/movie/{movie_id}/images") - suspend fun fetchImages(@Path("movie_id") movieId: Int): ImagesResponse + suspend fun fetchImages( + @Path("movie_id") movieId: Int, + ): ImagesResponse @GET("3/movie/{movie_id}/similar") - suspend fun fetchSimilarMovies(@Path("movie_id") movieId: Int): TMDbWrapper + suspend fun fetchSimilarMovies( + @Path("movie_id") movieId: Int, + ): TMDbWrapper @GET("3/movie/{movie_id}/similar") suspend fun fetchSimilarMovies( @Path("movie_id") movieId: Int, - @Query("page") page: Int + @Query("page") page: Int, ): TMDbWrapper -} \ No newline at end of file +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/network/PersonService.kt b/core/data/src/main/java/com/sample/tmdb/data/network/PersonService.kt index d228429..bf77eea 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/network/PersonService.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/network/PersonService.kt @@ -1,11 +1,12 @@ package com.sample.tmdb.data.network -import com.sample.tmdb.data.response.PersonResponse +import com.sample.tmdb.data.response.PersonDto import retrofit2.http.GET import retrofit2.http.Path interface PersonService { - @GET("3/person/{personId}") - suspend fun getPerson(@Path("personId") personId: String): PersonResponse -} \ No newline at end of file + suspend fun getPerson( + @Path("personId") personId: String, + ): PersonDto +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/network/TVShowService.kt b/core/data/src/main/java/com/sample/tmdb/data/network/TVShowService.kt index c513303..6a791ab 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/network/TVShowService.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/network/TVShowService.kt @@ -10,7 +10,6 @@ import retrofit2.http.Path import retrofit2.http.Query interface TVShowService { - @GET("3/trending/tv/day") suspend fun trendingTVSeries(): TMDbWrapper @@ -30,44 +29,64 @@ interface TVShowService { suspend fun discoverTVSeries(): TMDbWrapper @GET("3/trending/tv/day") - suspend fun trendingTVSeries(@Query("page") page: Int): TMDbWrapper + suspend fun trendingTVSeries( + @Query("page") page: Int, + ): TMDbWrapper @GET("3/tv/popular") - suspend fun popularTVSeries(@Query("page") page: Int): TMDbWrapper + suspend fun popularTVSeries( + @Query("page") page: Int, + ): TMDbWrapper @GET("3/tv/airing_today") - suspend fun airingTodayTVSeries(@Query("page") page: Int): TMDbWrapper + suspend fun airingTodayTVSeries( + @Query("page") page: Int, + ): TMDbWrapper @GET("3/tv/on_the_air") - suspend fun onTheAirTVSeries(@Query("page") page: Int): TMDbWrapper + suspend fun onTheAirTVSeries( + @Query("page") page: Int, + ): TMDbWrapper @GET("3/tv/top_rated") - suspend fun topRatedTVSeries(@Query("page") page: Int): TMDbWrapper + suspend fun topRatedTVSeries( + @Query("page") page: Int, + ): TMDbWrapper @GET("3/discover/tv") - suspend fun discoverTVSeries(@Query("page") page: Int): TMDbWrapper + suspend fun discoverTVSeries( + @Query("page") page: Int, + ): TMDbWrapper @GET("3/tv/{tvId}/credits") - suspend fun tvCredit(@Path("tvId") tvId: Int): NetworkCreditWrapper + suspend fun tvCredit( + @Path("tvId") tvId: Int, + ): NetworkCreditWrapper @GET("3/tv/{tvId}") - suspend fun fetchTvDetail(@Path("tvId") tvId: Int): TvDetailResponse + suspend fun fetchTvDetail( + @Path("tvId") tvId: Int, + ): TvDetailResponse @GET("3/search/tv") suspend fun searchTVSeries( @Query("page") page: Int, - @Query("query") query: String + @Query("query") query: String, ): TMDbWrapper @GET("3/tv/{tvId}/images") - suspend fun fetchImages(@Path("tvId") tvId: Int): ImagesResponse + suspend fun fetchImages( + @Path("tvId") tvId: Int, + ): ImagesResponse @GET("3/tv/{tvId}/similar") - suspend fun fetchSimilarMovies(@Path("tvId") tvId: Int): TMDbWrapper + suspend fun fetchSimilarMovies( + @Path("tvId") tvId: Int, + ): TMDbWrapper @GET("3/tv/{TvId}/similar") suspend fun fetchSimilarMovies( @Path("TvId") tvId: Int, - @Query("page") page: Int + @Query("page") page: Int, ): TMDbWrapper -} \ No newline at end of file +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/paging/movie/DiscoverMoviesPagingSource.kt b/core/data/src/main/java/com/sample/tmdb/data/paging/movie/DiscoverMoviesPagingSource.kt index 576b315..c98f97c 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/paging/movie/DiscoverMoviesPagingSource.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/paging/movie/DiscoverMoviesPagingSource.kt @@ -8,9 +8,7 @@ import com.sample.tmdb.domain.paging.BasePagingSource class DiscoverMoviesPagingSource( context: Context, - private val movieApi: MovieService + private val movieApi: MovieService, ) : BasePagingSource(context) { - - override suspend fun fetchItems(page: Int): List = - movieApi.discoverMovies(page).items.asMovieDomainModel() -} \ No newline at end of file + override suspend fun fetchItems(page: Int): List = movieApi.discoverMovies(page).items.asMovieDomainModel() +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/paging/movie/NowPlayingMoviesPagingSource.kt b/core/data/src/main/java/com/sample/tmdb/data/paging/movie/NowPlayingMoviesPagingSource.kt index 0fb344f..b3741f3 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/paging/movie/NowPlayingMoviesPagingSource.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/paging/movie/NowPlayingMoviesPagingSource.kt @@ -8,9 +8,7 @@ import com.sample.tmdb.domain.paging.BasePagingSource class NowPlayingMoviesPagingSource( context: Context, - private val movieApi: MovieService + private val movieApi: MovieService, ) : BasePagingSource(context) { - - override suspend fun fetchItems(page: Int): List = - movieApi.nowPlayingMovies(page).items.asMovieDomainModel() -} \ No newline at end of file + override suspend fun fetchItems(page: Int): List = movieApi.nowPlayingMovies(page).items.asMovieDomainModel() +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/paging/movie/PopularMoviesPagingSource.kt b/core/data/src/main/java/com/sample/tmdb/data/paging/movie/PopularMoviesPagingSource.kt index 4eeadd8..d9e6ba5 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/paging/movie/PopularMoviesPagingSource.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/paging/movie/PopularMoviesPagingSource.kt @@ -8,9 +8,7 @@ import com.sample.tmdb.domain.paging.BasePagingSource class PopularMoviesPagingSource( context: Context, - private val movieApi: MovieService + private val movieApi: MovieService, ) : BasePagingSource(context) { - - override suspend fun fetchItems(page: Int): List = - movieApi.popularMovies(page).items.asMovieDomainModel() -} \ No newline at end of file + override suspend fun fetchItems(page: Int): List = movieApi.popularMovies(page).items.asMovieDomainModel() +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/paging/movie/SearchMoviesPagingSource.kt b/core/data/src/main/java/com/sample/tmdb/data/paging/movie/SearchMoviesPagingSource.kt index 2ef8820..23b82ce 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/paging/movie/SearchMoviesPagingSource.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/paging/movie/SearchMoviesPagingSource.kt @@ -9,9 +9,7 @@ import com.sample.tmdb.domain.paging.BasePagingSource class SearchMoviesPagingSource( context: Context, private val movieApi: MovieService, - private val query: String + private val query: String, ) : BasePagingSource(context) { - - override suspend fun fetchItems(page: Int): List = - movieApi.searchMovies(page, query).items.asMovieDomainModel() -} \ No newline at end of file + override suspend fun fetchItems(page: Int): List = movieApi.searchMovies(page, query).items.asMovieDomainModel() +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/paging/movie/SimilarMoviesPagingSource.kt b/core/data/src/main/java/com/sample/tmdb/data/paging/movie/SimilarMoviesPagingSource.kt index 35e07a3..10ec99c 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/paging/movie/SimilarMoviesPagingSource.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/paging/movie/SimilarMoviesPagingSource.kt @@ -9,9 +9,7 @@ import com.sample.tmdb.domain.paging.BasePagingSource class SimilarMoviesPagingSource( context: Context, private val movieApi: MovieService, - private val movieId: Int + private val movieId: Int, ) : BasePagingSource(context) { - - override suspend fun fetchItems(page: Int): List = - movieApi.fetchSimilarMovies(movieId, page).items.asMovieDomainModel() -} \ No newline at end of file + override suspend fun fetchItems(page: Int): List = movieApi.fetchSimilarMovies(movieId, page).items.asMovieDomainModel() +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/paging/movie/TopRatedMoviesPagingSource.kt b/core/data/src/main/java/com/sample/tmdb/data/paging/movie/TopRatedMoviesPagingSource.kt index 4bbe846..709f4bd 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/paging/movie/TopRatedMoviesPagingSource.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/paging/movie/TopRatedMoviesPagingSource.kt @@ -8,9 +8,7 @@ import com.sample.tmdb.domain.paging.BasePagingSource class TopRatedMoviesPagingSource( context: Context, - private val movieApi: MovieService + private val movieApi: MovieService, ) : BasePagingSource(context) { - - override suspend fun fetchItems(page: Int): List = - movieApi.topRatedMovies(page).items.asMovieDomainModel() -} \ No newline at end of file + override suspend fun fetchItems(page: Int): List = movieApi.topRatedMovies(page).items.asMovieDomainModel() +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/paging/movie/TrendingMoviesPagingSource.kt b/core/data/src/main/java/com/sample/tmdb/data/paging/movie/TrendingMoviesPagingSource.kt index 158b224..b4b6a4b 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/paging/movie/TrendingMoviesPagingSource.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/paging/movie/TrendingMoviesPagingSource.kt @@ -8,9 +8,7 @@ import com.sample.tmdb.domain.paging.BasePagingSource class TrendingMoviesPagingSource( context: Context, - private val movieApi: MovieService + private val movieApi: MovieService, ) : BasePagingSource(context) { - - override suspend fun fetchItems(page: Int): List = - movieApi.trendingMovies(page).items.asMovieDomainModel() -} \ No newline at end of file + override suspend fun fetchItems(page: Int): List = movieApi.trendingMovies(page).items.asMovieDomainModel() +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/paging/movie/UpcomingMoviesPagingSource.kt b/core/data/src/main/java/com/sample/tmdb/data/paging/movie/UpcomingMoviesPagingSource.kt index 151ba58..0968244 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/paging/movie/UpcomingMoviesPagingSource.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/paging/movie/UpcomingMoviesPagingSource.kt @@ -8,9 +8,7 @@ import com.sample.tmdb.domain.paging.BasePagingSource class UpcomingMoviesPagingSource( context: Context, - private val movieApi: MovieService + private val movieApi: MovieService, ) : BasePagingSource(context) { - - override suspend fun fetchItems(page: Int): List = - movieApi.upcomingMovies(page).items.asMovieDomainModel() -} \ No newline at end of file + override suspend fun fetchItems(page: Int): List = movieApi.upcomingMovies(page).items.asMovieDomainModel() +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/AiringTodayTvSeriesPagingSource.kt b/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/AiringTodayTvSeriesPagingSource.kt index 0a8a4bb..93fa360 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/AiringTodayTvSeriesPagingSource.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/AiringTodayTvSeriesPagingSource.kt @@ -8,9 +8,7 @@ import com.sample.tmdb.domain.paging.BasePagingSource class AiringTodayTvSeriesPagingSource( context: Context, - private val tvShowApi: TVShowService + private val tvShowApi: TVShowService, ) : BasePagingSource(context) { - - override suspend fun fetchItems(page: Int): List = - tvShowApi.airingTodayTVSeries(page).items.asTVShowDomainModel() -} \ No newline at end of file + override suspend fun fetchItems(page: Int): List = tvShowApi.airingTodayTVSeries(page).items.asTVShowDomainModel() +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/DiscoverTvSeriesPagingSource.kt b/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/DiscoverTvSeriesPagingSource.kt index a879169..f2b00d1 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/DiscoverTvSeriesPagingSource.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/DiscoverTvSeriesPagingSource.kt @@ -8,9 +8,7 @@ import com.sample.tmdb.domain.paging.BasePagingSource class DiscoverTvSeriesPagingSource( context: Context, - private val tvShowApi: TVShowService + private val tvShowApi: TVShowService, ) : BasePagingSource(context) { - - override suspend fun fetchItems(page: Int): List = - tvShowApi.discoverTVSeries(page).items.asTVShowDomainModel() -} \ No newline at end of file + override suspend fun fetchItems(page: Int): List = tvShowApi.discoverTVSeries(page).items.asTVShowDomainModel() +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/OnTheAirTvSeriesPagingSource.kt b/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/OnTheAirTvSeriesPagingSource.kt index 6ddbf6f..7aceeac 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/OnTheAirTvSeriesPagingSource.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/OnTheAirTvSeriesPagingSource.kt @@ -8,9 +8,7 @@ import com.sample.tmdb.domain.paging.BasePagingSource class OnTheAirTvSeriesPagingSource( context: Context, - private val tvShowApi: TVShowService + private val tvShowApi: TVShowService, ) : BasePagingSource(context) { - - override suspend fun fetchItems(page: Int): List = - tvShowApi.onTheAirTVSeries(page).items.asTVShowDomainModel() -} \ No newline at end of file + override suspend fun fetchItems(page: Int): List = tvShowApi.onTheAirTVSeries(page).items.asTVShowDomainModel() +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/PopularTvSeriesPagingSource.kt b/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/PopularTvSeriesPagingSource.kt index 156913e..69a609a 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/PopularTvSeriesPagingSource.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/PopularTvSeriesPagingSource.kt @@ -8,9 +8,7 @@ import com.sample.tmdb.domain.paging.BasePagingSource class PopularTvSeriesPagingSource( context: Context, - private val tvShowApi: TVShowService + private val tvShowApi: TVShowService, ) : BasePagingSource(context) { - - override suspend fun fetchItems(page: Int): List = - tvShowApi.popularTVSeries(page).items.asTVShowDomainModel() -} \ No newline at end of file + override suspend fun fetchItems(page: Int): List = tvShowApi.popularTVSeries(page).items.asTVShowDomainModel() +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/SearchTvSeriesPagingSource.kt b/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/SearchTvSeriesPagingSource.kt index 837220c..45468d6 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/SearchTvSeriesPagingSource.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/SearchTvSeriesPagingSource.kt @@ -9,9 +9,7 @@ import com.sample.tmdb.domain.paging.BasePagingSource class SearchTvSeriesPagingSource( context: Context, private val tvShowApi: TVShowService, - private val query: String + private val query: String, ) : BasePagingSource(context) { - - override suspend fun fetchItems(page: Int): List = - tvShowApi.searchTVSeries(page, query).items.asTVShowDomainModel() -} \ No newline at end of file + override suspend fun fetchItems(page: Int): List = tvShowApi.searchTVSeries(page, query).items.asTVShowDomainModel() +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/SimilarTvSeriesPagingSource.kt b/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/SimilarTvSeriesPagingSource.kt index dc3d0a2..41ad113 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/SimilarTvSeriesPagingSource.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/SimilarTvSeriesPagingSource.kt @@ -9,9 +9,7 @@ import com.sample.tmdb.domain.paging.BasePagingSource class SimilarTvSeriesPagingSource( context: Context, private val tvShowApi: TVShowService, - private val tvId: Int + private val tvId: Int, ) : BasePagingSource(context) { - - override suspend fun fetchItems(page: Int): List = - tvShowApi.fetchSimilarMovies(tvId, page).items.asTVShowDomainModel() -} \ No newline at end of file + override suspend fun fetchItems(page: Int): List = tvShowApi.fetchSimilarMovies(tvId, page).items.asTVShowDomainModel() +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/TopRatedTvSeriesPagingSource.kt b/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/TopRatedTvSeriesPagingSource.kt index 9110018..10f378f 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/TopRatedTvSeriesPagingSource.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/TopRatedTvSeriesPagingSource.kt @@ -8,9 +8,7 @@ import com.sample.tmdb.domain.paging.BasePagingSource class TopRatedTvSeriesPagingSource( context: Context, - private val tvShowApi: TVShowService + private val tvShowApi: TVShowService, ) : BasePagingSource(context) { - - override suspend fun fetchItems(page: Int): List = - tvShowApi.topRatedTVSeries(page).items.asTVShowDomainModel() -} \ No newline at end of file + override suspend fun fetchItems(page: Int): List = tvShowApi.topRatedTVSeries(page).items.asTVShowDomainModel() +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/TrendingTvSeriesPagingSource.kt b/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/TrendingTvSeriesPagingSource.kt index d9e2972..9ba0e5e 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/TrendingTvSeriesPagingSource.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/paging/tvshow/TrendingTvSeriesPagingSource.kt @@ -8,9 +8,7 @@ import com.sample.tmdb.domain.paging.BasePagingSource class TrendingTvSeriesPagingSource( context: Context, - private val tvShowApi: TVShowService + private val tvShowApi: TVShowService, ) : BasePagingSource(context) { - - override suspend fun fetchItems(page: Int): List = - tvShowApi.trendingTVSeries(page).items.asTVShowDomainModel() -} \ No newline at end of file + override suspend fun fetchItems(page: Int): List = tvShowApi.trendingTVSeries(page).items.asTVShowDomainModel() +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/PersonRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/PersonRepository.kt index c0d33a7..178a7f0 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/PersonRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/PersonRepository.kt @@ -2,9 +2,9 @@ package com.sample.tmdb.data.repository import android.content.Context import com.sample.tmdb.common.base.BaseRepository +import com.sample.tmdb.data.di.IoDispatcher import com.sample.tmdb.data.network.PersonService import com.sample.tmdb.data.response.asDomainModel -import com.sample.tmdb.data.di.IoDispatcher import com.sample.tmdb.domain.model.Person import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.CoroutineDispatcher @@ -12,12 +12,12 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class PersonRepository @Inject constructor( - private val personApi: PersonService, - @ApplicationContext context: Context, - @IoDispatcher ioDispatcher: CoroutineDispatcher, -) : BaseRepository(context, ioDispatcher) { - - override suspend fun getSuccessResult(id: Any?): Person = - personApi.getPerson(id as String).asDomainModel() -} \ No newline at end of file +class PersonRepository + @Inject + constructor( + private val personApi: PersonService, + @ApplicationContext context: Context, + @IoDispatcher ioDispatcher: CoroutineDispatcher, + ) : BaseRepository(context, ioDispatcher) { + override suspend fun getSuccessResult(id: Any?): Person = personApi.getPerson(id as String).asDomainModel() + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/MovieFeedRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/MovieFeedRepository.kt index 5e2e3cc..69d99f4 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/MovieFeedRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/MovieFeedRepository.kt @@ -2,9 +2,9 @@ package com.sample.tmdb.data.repository.movie import android.content.Context import com.sample.tmdb.data.R +import com.sample.tmdb.data.di.IoDispatcher import com.sample.tmdb.data.network.MovieService import com.sample.tmdb.data.response.asMovieDomainModel -import com.sample.tmdb.data.di.IoDispatcher import com.sample.tmdb.domain.model.Movie import com.sample.tmdb.domain.repository.BaseFeedRepository import dagger.hilt.android.qualifiers.ApplicationContext @@ -13,31 +13,26 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class MovieFeedRepository @Inject constructor( - @ApplicationContext context: Context, - @IoDispatcher ioDispatcher: CoroutineDispatcher, - private val movieApi: MovieService, -) : BaseFeedRepository(context, ioDispatcher) { - - override suspend fun popularItems(): List = - movieApi.popularMovies().items.asMovieDomainModel() +class MovieFeedRepository + @Inject + constructor( + @ApplicationContext context: Context, + @IoDispatcher ioDispatcher: CoroutineDispatcher, + private val movieApi: MovieService, + ) : BaseFeedRepository(context, ioDispatcher) { + override suspend fun popularItems(): List = movieApi.popularMovies().items.asMovieDomainModel() - override suspend fun latestItems(): List = - movieApi.upcomingMovies().items.asMovieDomainModel() + override suspend fun latestItems(): List = movieApi.upcomingMovies().items.asMovieDomainModel() - override suspend fun topRatedItems(): List = - movieApi.topRatedMovies().items.asMovieDomainModel() + override suspend fun topRatedItems(): List = movieApi.topRatedMovies().items.asMovieDomainModel() - override suspend fun trendingItems(): List = - movieApi.trendingMovies().items.asMovieDomainModel() + override suspend fun trendingItems(): List = movieApi.trendingMovies().items.asMovieDomainModel() - override suspend fun nowPlayingItems(): List = - movieApi.nowPlayingMovies().items.asMovieDomainModel() + override suspend fun nowPlayingItems(): List = movieApi.nowPlayingMovies().items.asMovieDomainModel() - override suspend fun discoverItems(): List = - movieApi.discoverMovies().items.asMovieDomainModel() + override suspend fun discoverItems(): List = movieApi.discoverMovies().items.asMovieDomainModel() - override fun getNowPlayingResId(): Int = R.string.text_now_playing + override fun getNowPlayingResId(): Int = R.string.text_now_playing - override fun getLatestResId(): Int = R.string.text_upcoming -} \ No newline at end of file + override fun getLatestResId(): Int = R.string.text_upcoming + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/detail/BookmarkMovieDetailsRepositoryImpl.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/detail/BookmarkMovieDetailsRepositoryImpl.kt index e0b6acc..d78505c 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/detail/BookmarkMovieDetailsRepositoryImpl.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/detail/BookmarkMovieDetailsRepositoryImpl.kt @@ -8,17 +8,18 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class BookmarkMovieDetailsRepositoryImpl @Inject constructor( - private val movieDao: MovieDao -) : BookmarkDetailsRepository { +class BookmarkMovieDetailsRepositoryImpl + @Inject + constructor( + private val movieDao: MovieDao, + ) : BookmarkDetailsRepository { + override suspend fun addBookmark(item: Movie) { + movieDao.addBookmark(item.asDatabaseModel()) + } - override suspend fun addBookmark(item: Movie) { - movieDao.addBookmark(item.asDatabaseModel()) - } + override suspend fun deleteBookmark(id: Int) { + movieDao.deleteBookmark(id) + } - override suspend fun deleteBookmark(id: Int) { - movieDao.deleteBookmark(id) + override suspend fun isBookmarked(id: Int): Boolean = movieDao.isBookmarked(id) } - - override suspend fun isBookmarked(id: Int): Boolean = movieDao.isBookmarked(id) -} \ No newline at end of file diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/detail/BookmarkMovieRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/detail/BookmarkMovieRepository.kt index 962f37b..c876f62 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/detail/BookmarkMovieRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/detail/BookmarkMovieRepository.kt @@ -12,12 +12,12 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class BookmarkMovieRepository @Inject constructor( - private val movieDao: MovieDao, - @ApplicationContext context: Context, - @IoDispatcher ioDispatcher: CoroutineDispatcher, -) : BaseRepository>(context, ioDispatcher) { - - override suspend fun getSuccessResult(id: Any?): List = - movieDao.getBookmarks().asDomainModel() -} \ No newline at end of file +class BookmarkMovieRepository + @Inject + constructor( + private val movieDao: MovieDao, + @ApplicationContext context: Context, + @IoDispatcher ioDispatcher: CoroutineDispatcher, + ) : BaseRepository>(context, ioDispatcher) { + override suspend fun getSuccessResult(id: Any?): List = movieDao.getBookmarks().asDomainModel() + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/detail/MovieDetailRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/detail/MovieDetailRepository.kt index 72a8e88..fd386d3 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/detail/MovieDetailRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/detail/MovieDetailRepository.kt @@ -19,26 +19,24 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class MovieDetailRepository @Inject constructor( - private val movieApi: MovieService, - @ApplicationContext context: Context, - @IoDispatcher ioDispatcher: CoroutineDispatcher, -) : BaseDetailRepository(context, ioDispatcher) { +class MovieDetailRepository + @Inject + constructor( + private val movieApi: MovieService, + @ApplicationContext context: Context, + @IoDispatcher ioDispatcher: CoroutineDispatcher, + ) : BaseDetailRepository(context, ioDispatcher) { + override suspend fun getDetails(id: Int): MovieDetails = movieApi.fetchMovieDetail(id).asDomainModel() - override suspend fun getDetails(id: Int): MovieDetails = - movieApi.fetchMovieDetail(id).asDomainModel() + override suspend fun getCredit(id: Int): Pair, List> { + val networkCreditWrapper = movieApi.movieCredit(id) + return Pair( + networkCreditWrapper.cast.asCastDomainModel(), + networkCreditWrapper.crew.asCrewDomainModel(), + ) + } - override suspend fun getCredit(id: Int): Pair, List> { - val networkCreditWrapper = movieApi.movieCredit(id) - return Pair( - networkCreditWrapper.cast.asCastDomainModel(), - networkCreditWrapper.crew.asCrewDomainModel() - ) - } - - override suspend fun getImages(id: Int): List = - movieApi.fetchImages(id).asDomainModel() + override suspend fun getImages(id: Int): List = movieApi.fetchImages(id).asDomainModel() - override suspend fun getSimilarItems(id: Int): List = - movieApi.fetchSimilarMovies(id).items.asMovieDomainModel() -} \ No newline at end of file + override suspend fun getSimilarItems(id: Int): List = movieApi.fetchSimilarMovies(id).items.asMovieDomainModel() + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/DiscoverMoviesPagingRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/DiscoverMoviesPagingRepository.kt index 4f6e29d..8a1ffd4 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/DiscoverMoviesPagingRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/DiscoverMoviesPagingRepository.kt @@ -11,11 +11,14 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class DiscoverMoviesPagingRepository @Inject constructor( - @ApplicationContext private val context: Context, - private val movieApi: MovieService -) : BasePagingRepository() { - - override fun pagingSource(query: String?, id: Int?): BasePagingSource = - DiscoverMoviesPagingSource(context, movieApi) -} \ No newline at end of file +class DiscoverMoviesPagingRepository + @Inject + constructor( + @ApplicationContext private val context: Context, + private val movieApi: MovieService, + ) : BasePagingRepository() { + override fun pagingSource( + query: String?, + id: Int?, + ): BasePagingSource = DiscoverMoviesPagingSource(context, movieApi) + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/NowPlayingMoviesPagingRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/NowPlayingMoviesPagingRepository.kt index 67ae2eb..a1600bf 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/NowPlayingMoviesPagingRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/NowPlayingMoviesPagingRepository.kt @@ -3,19 +3,22 @@ package com.sample.tmdb.data.repository.movie.paging import android.content.Context import com.sample.tmdb.data.network.MovieService import com.sample.tmdb.data.paging.movie.NowPlayingMoviesPagingSource -import com.sample.tmdb.domain.repository.BasePagingRepository import com.sample.tmdb.domain.model.Movie import com.sample.tmdb.domain.paging.BasePagingSource +import com.sample.tmdb.domain.repository.BasePagingRepository import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton @Singleton -class NowPlayingMoviesPagingRepository @Inject constructor( - @ApplicationContext private val context: Context, - private val movieApi: MovieService -) : BasePagingRepository() { - - override fun pagingSource(query: String?, id: Int?): BasePagingSource = - NowPlayingMoviesPagingSource(context, movieApi) -} \ No newline at end of file +class NowPlayingMoviesPagingRepository + @Inject + constructor( + @ApplicationContext private val context: Context, + private val movieApi: MovieService, + ) : BasePagingRepository() { + override fun pagingSource( + query: String?, + id: Int?, + ): BasePagingSource = NowPlayingMoviesPagingSource(context, movieApi) + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/PopularMoviesPagingRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/PopularMoviesPagingRepository.kt index d484539..8148904 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/PopularMoviesPagingRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/PopularMoviesPagingRepository.kt @@ -3,19 +3,22 @@ package com.sample.tmdb.data.repository.movie.paging import android.content.Context import com.sample.tmdb.data.network.MovieService import com.sample.tmdb.data.paging.movie.PopularMoviesPagingSource -import com.sample.tmdb.domain.repository.BasePagingRepository import com.sample.tmdb.domain.model.Movie import com.sample.tmdb.domain.paging.BasePagingSource +import com.sample.tmdb.domain.repository.BasePagingRepository import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton @Singleton -class PopularMoviesPagingRepository @Inject constructor( - @ApplicationContext private val context: Context, - private val movieApi: MovieService -) : BasePagingRepository() { - - override fun pagingSource(query: String?, id: Int?): BasePagingSource = - PopularMoviesPagingSource(context, movieApi) -} \ No newline at end of file +class PopularMoviesPagingRepository + @Inject + constructor( + @ApplicationContext private val context: Context, + private val movieApi: MovieService, + ) : BasePagingRepository() { + override fun pagingSource( + query: String?, + id: Int?, + ): BasePagingSource = PopularMoviesPagingSource(context, movieApi) + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/SearchMoviesPagingRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/SearchMoviesPagingRepository.kt index 513c775..5256c96 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/SearchMoviesPagingRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/SearchMoviesPagingRepository.kt @@ -3,19 +3,22 @@ package com.sample.tmdb.data.repository.movie.paging import android.content.Context import com.sample.tmdb.data.network.MovieService import com.sample.tmdb.data.paging.movie.SearchMoviesPagingSource -import com.sample.tmdb.domain.repository.BasePagingRepository import com.sample.tmdb.domain.model.Movie import com.sample.tmdb.domain.paging.BasePagingSource +import com.sample.tmdb.domain.repository.BasePagingRepository import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton @Singleton -class SearchMoviesPagingRepository @Inject constructor( - @ApplicationContext private val context: Context, - private val movieApi: MovieService -) : BasePagingRepository() { - - override fun pagingSource(query: String?, id: Int?): BasePagingSource = - SearchMoviesPagingSource(context, movieApi, query!!) -} \ No newline at end of file +class SearchMoviesPagingRepository + @Inject + constructor( + @ApplicationContext private val context: Context, + private val movieApi: MovieService, + ) : BasePagingRepository() { + override fun pagingSource( + query: String?, + id: Int?, + ): BasePagingSource = SearchMoviesPagingSource(context, movieApi, query!!) + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/SimilarMoviesPagingRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/SimilarMoviesPagingRepository.kt index a82c885..aeab2e4 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/SimilarMoviesPagingRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/SimilarMoviesPagingRepository.kt @@ -11,11 +11,14 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class SimilarMoviesPagingRepository @Inject constructor( - @ApplicationContext private val context: Context, - private val movieApi: MovieService -) : BasePagingRepository() { - - override fun pagingSource(query: String?, id: Int?): BasePagingSource = - SimilarMoviesPagingSource(context, movieApi, id!!) -} \ No newline at end of file +class SimilarMoviesPagingRepository + @Inject + constructor( + @ApplicationContext private val context: Context, + private val movieApi: MovieService, + ) : BasePagingRepository() { + override fun pagingSource( + query: String?, + id: Int?, + ): BasePagingSource = SimilarMoviesPagingSource(context, movieApi, id!!) + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/TopRatedMoviesPagingRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/TopRatedMoviesPagingRepository.kt index aa19e36..d5425f7 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/TopRatedMoviesPagingRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/TopRatedMoviesPagingRepository.kt @@ -3,19 +3,22 @@ package com.sample.tmdb.data.repository.movie.paging import android.content.Context import com.sample.tmdb.data.network.MovieService import com.sample.tmdb.data.paging.movie.TopRatedMoviesPagingSource -import com.sample.tmdb.domain.repository.BasePagingRepository import com.sample.tmdb.domain.model.Movie import com.sample.tmdb.domain.paging.BasePagingSource +import com.sample.tmdb.domain.repository.BasePagingRepository import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton @Singleton -class TopRatedMoviesPagingRepository @Inject constructor( - @ApplicationContext private val context: Context, - private val movieApi: MovieService -) : BasePagingRepository() { - - override fun pagingSource(query: String?, id: Int?): BasePagingSource = - TopRatedMoviesPagingSource(context, movieApi) -} \ No newline at end of file +class TopRatedMoviesPagingRepository + @Inject + constructor( + @ApplicationContext private val context: Context, + private val movieApi: MovieService, + ) : BasePagingRepository() { + override fun pagingSource( + query: String?, + id: Int?, + ): BasePagingSource = TopRatedMoviesPagingSource(context, movieApi) + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/TrendingMoviesPagingRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/TrendingMoviesPagingRepository.kt index f4610e1..a61d4af 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/TrendingMoviesPagingRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/TrendingMoviesPagingRepository.kt @@ -3,19 +3,22 @@ package com.sample.tmdb.data.repository.movie.paging import android.content.Context import com.sample.tmdb.data.network.MovieService import com.sample.tmdb.data.paging.movie.TrendingMoviesPagingSource -import com.sample.tmdb.domain.repository.BasePagingRepository import com.sample.tmdb.domain.model.Movie import com.sample.tmdb.domain.paging.BasePagingSource +import com.sample.tmdb.domain.repository.BasePagingRepository import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton @Singleton -class TrendingMoviesPagingRepository @Inject constructor( - @ApplicationContext private val context: Context, - private val movieApi: MovieService -) : BasePagingRepository() { - - override fun pagingSource(query: String?, id: Int?): BasePagingSource = - TrendingMoviesPagingSource(context, movieApi) -} \ No newline at end of file +class TrendingMoviesPagingRepository + @Inject + constructor( + @ApplicationContext private val context: Context, + private val movieApi: MovieService, + ) : BasePagingRepository() { + override fun pagingSource( + query: String?, + id: Int?, + ): BasePagingSource = TrendingMoviesPagingSource(context, movieApi) + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/UpcomingMoviesPagingRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/UpcomingMoviesPagingRepository.kt index d24a497..443dff0 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/UpcomingMoviesPagingRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/movie/paging/UpcomingMoviesPagingRepository.kt @@ -3,19 +3,22 @@ package com.sample.tmdb.data.repository.movie.paging import android.content.Context import com.sample.tmdb.data.network.MovieService import com.sample.tmdb.data.paging.movie.UpcomingMoviesPagingSource -import com.sample.tmdb.domain.repository.BasePagingRepository import com.sample.tmdb.domain.model.Movie import com.sample.tmdb.domain.paging.BasePagingSource +import com.sample.tmdb.domain.repository.BasePagingRepository import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton @Singleton -class UpcomingMoviesPagingRepository @Inject constructor( - @ApplicationContext private val context: Context, - private val movieApi: MovieService -) : BasePagingRepository() { - - override fun pagingSource(query: String?, id: Int?): BasePagingSource = - UpcomingMoviesPagingSource(context, movieApi) -} \ No newline at end of file +class UpcomingMoviesPagingRepository + @Inject + constructor( + @ApplicationContext private val context: Context, + private val movieApi: MovieService, + ) : BasePagingRepository() { + override fun pagingSource( + query: String?, + id: Int?, + ): BasePagingSource = UpcomingMoviesPagingSource(context, movieApi) + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/TVShowFeedRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/TVShowFeedRepository.kt index 45b313b..1bd9e5a 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/TVShowFeedRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/TVShowFeedRepository.kt @@ -2,9 +2,9 @@ package com.sample.tmdb.data.repository.tvshow import android.content.Context import com.sample.tmdb.data.R +import com.sample.tmdb.data.di.IoDispatcher import com.sample.tmdb.data.network.TVShowService import com.sample.tmdb.data.response.asTVShowDomainModel -import com.sample.tmdb.data.di.IoDispatcher import com.sample.tmdb.domain.model.TVShow import com.sample.tmdb.domain.repository.BaseFeedRepository import dagger.hilt.android.qualifiers.ApplicationContext @@ -13,31 +13,26 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class TVShowFeedRepository @Inject constructor( - @ApplicationContext context: Context, - @IoDispatcher ioDispatcher: CoroutineDispatcher, - private val tvShowApi: TVShowService, -) : BaseFeedRepository(context, ioDispatcher) { - - override suspend fun popularItems(): List = - tvShowApi.popularTVSeries().items.asTVShowDomainModel() +class TVShowFeedRepository + @Inject + constructor( + @ApplicationContext context: Context, + @IoDispatcher ioDispatcher: CoroutineDispatcher, + private val tvShowApi: TVShowService, + ) : BaseFeedRepository(context, ioDispatcher) { + override suspend fun popularItems(): List = tvShowApi.popularTVSeries().items.asTVShowDomainModel() - override suspend fun latestItems(): List = - tvShowApi.onTheAirTVSeries().items.asTVShowDomainModel() + override suspend fun latestItems(): List = tvShowApi.onTheAirTVSeries().items.asTVShowDomainModel() - override suspend fun topRatedItems(): List = - tvShowApi.topRatedTVSeries().items.asTVShowDomainModel() + override suspend fun topRatedItems(): List = tvShowApi.topRatedTVSeries().items.asTVShowDomainModel() - override suspend fun trendingItems(): List = - tvShowApi.trendingTVSeries().items.asTVShowDomainModel() + override suspend fun trendingItems(): List = tvShowApi.trendingTVSeries().items.asTVShowDomainModel() - override suspend fun nowPlayingItems(): List = - tvShowApi.airingTodayTVSeries().items.asTVShowDomainModel() + override suspend fun nowPlayingItems(): List = tvShowApi.airingTodayTVSeries().items.asTVShowDomainModel() - override suspend fun discoverItems(): List = - tvShowApi.discoverTVSeries().items.asTVShowDomainModel() + override suspend fun discoverItems(): List = tvShowApi.discoverTVSeries().items.asTVShowDomainModel() - override fun getNowPlayingResId(): Int = R.string.text_airing_today + override fun getNowPlayingResId(): Int = R.string.text_airing_today - override fun getLatestResId(): Int = R.string.text_on_the_air -} \ No newline at end of file + override fun getLatestResId(): Int = R.string.text_on_the_air + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/detail/BookmarkTVShowDetailsRepositoryImpl.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/detail/BookmarkTVShowDetailsRepositoryImpl.kt index 8dbf3ef..1672d6c 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/detail/BookmarkTVShowDetailsRepositoryImpl.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/detail/BookmarkTVShowDetailsRepositoryImpl.kt @@ -8,17 +8,18 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class BookmarkTVShowDetailsRepositoryImpl @Inject constructor( - private val tvShowDao: TVShowDao -) : BookmarkDetailsRepository { +class BookmarkTVShowDetailsRepositoryImpl + @Inject + constructor( + private val tvShowDao: TVShowDao, + ) : BookmarkDetailsRepository { + override suspend fun addBookmark(item: TVShow) { + tvShowDao.addBookmark(item.asDatabaseModel()) + } - override suspend fun addBookmark(item: TVShow) { - tvShowDao.addBookmark(item.asDatabaseModel()) - } + override suspend fun deleteBookmark(id: Int) { + tvShowDao.deleteBookmark(id) + } - override suspend fun deleteBookmark(id: Int) { - tvShowDao.deleteBookmark(id) + override suspend fun isBookmarked(id: Int): Boolean = tvShowDao.isBookmarked(id) } - - override suspend fun isBookmarked(id: Int): Boolean = tvShowDao.isBookmarked(id) -} \ No newline at end of file diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/detail/BookmarkTVShowRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/detail/BookmarkTVShowRepository.kt index d0ab492..739b80a 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/detail/BookmarkTVShowRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/detail/BookmarkTVShowRepository.kt @@ -2,9 +2,9 @@ package com.sample.tmdb.data.repository.tvshow.detail import android.content.Context import com.sample.tmdb.common.base.BaseRepository +import com.sample.tmdb.data.di.IoDispatcher import com.sample.tmdb.data.source.entity.asDomainModel import com.sample.tmdb.data.source.local.TVShowDao -import com.sample.tmdb.data.di.IoDispatcher import com.sample.tmdb.domain.model.TVShow import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.CoroutineDispatcher @@ -12,12 +12,12 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class BookmarkTVShowRepository @Inject constructor( - private val tvShowDao: TVShowDao, - @ApplicationContext context: Context, - @IoDispatcher ioDispatcher: CoroutineDispatcher, -) : BaseRepository>(context, ioDispatcher) { - - override suspend fun getSuccessResult(id: Any?): List = - tvShowDao.getBookmarks().asDomainModel() -} \ No newline at end of file +class BookmarkTVShowRepository + @Inject + constructor( + private val tvShowDao: TVShowDao, + @ApplicationContext context: Context, + @IoDispatcher ioDispatcher: CoroutineDispatcher, + ) : BaseRepository>(context, ioDispatcher) { + override suspend fun getSuccessResult(id: Any?): List = tvShowDao.getBookmarks().asDomainModel() + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/detail/TVShowDetailRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/detail/TVShowDetailRepository.kt index 2335658..41fdb33 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/detail/TVShowDetailRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/detail/TVShowDetailRepository.kt @@ -19,26 +19,24 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class TVShowDetailRepository @Inject constructor( - private val tvShowApi: TVShowService, - @ApplicationContext context: Context, - @IoDispatcher ioDispatcher: CoroutineDispatcher, -) : BaseDetailRepository(context, ioDispatcher) { +class TVShowDetailRepository + @Inject + constructor( + private val tvShowApi: TVShowService, + @ApplicationContext context: Context, + @IoDispatcher ioDispatcher: CoroutineDispatcher, + ) : BaseDetailRepository(context, ioDispatcher) { + override suspend fun getDetails(id: Int): TvDetails = tvShowApi.fetchTvDetail(id).asDomainModel() - override suspend fun getDetails(id: Int): TvDetails = - tvShowApi.fetchTvDetail(id).asDomainModel() + override suspend fun getCredit(id: Int): Pair, List> { + val networkCreditWrapper = tvShowApi.tvCredit(id) + return Pair( + networkCreditWrapper.cast.asCastDomainModel(), + networkCreditWrapper.crew.asCrewDomainModel(), + ) + } - override suspend fun getCredit(id: Int): Pair, List> { - val networkCreditWrapper = tvShowApi.tvCredit(id) - return Pair( - networkCreditWrapper.cast.asCastDomainModel(), - networkCreditWrapper.crew.asCrewDomainModel() - ) - } - - override suspend fun getImages(id: Int): List = - tvShowApi.fetchImages(id).asDomainModel() + override suspend fun getImages(id: Int): List = tvShowApi.fetchImages(id).asDomainModel() - override suspend fun getSimilarItems(id: Int): List = - tvShowApi.fetchSimilarMovies(id).items.asTVShowDomainModel() -} \ No newline at end of file + override suspend fun getSimilarItems(id: Int): List = tvShowApi.fetchSimilarMovies(id).items.asTVShowDomainModel() + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/AiringTodayTvSeriesPagingRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/AiringTodayTvSeriesPagingRepository.kt index 2658bb0..5da55ed 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/AiringTodayTvSeriesPagingRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/AiringTodayTvSeriesPagingRepository.kt @@ -3,19 +3,22 @@ package com.sample.tmdb.data.repository.tvshow.paging import android.content.Context import com.sample.tmdb.data.network.TVShowService import com.sample.tmdb.data.paging.tvshow.AiringTodayTvSeriesPagingSource -import com.sample.tmdb.domain.repository.BasePagingRepository import com.sample.tmdb.domain.model.TVShow import com.sample.tmdb.domain.paging.BasePagingSource +import com.sample.tmdb.domain.repository.BasePagingRepository import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton @Singleton -class AiringTodayTvSeriesPagingRepository @Inject constructor( - @ApplicationContext private val context: Context, - private val tvShowApi: TVShowService -) : BasePagingRepository() { - - override fun pagingSource(query: String?, id: Int?): BasePagingSource = - AiringTodayTvSeriesPagingSource(context, tvShowApi) -} \ No newline at end of file +class AiringTodayTvSeriesPagingRepository + @Inject + constructor( + @ApplicationContext private val context: Context, + private val tvShowApi: TVShowService, + ) : BasePagingRepository() { + override fun pagingSource( + query: String?, + id: Int?, + ): BasePagingSource = AiringTodayTvSeriesPagingSource(context, tvShowApi) + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/DiscoverTvSeriesPagingRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/DiscoverTvSeriesPagingRepository.kt index 357e4e0..a71de78 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/DiscoverTvSeriesPagingRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/DiscoverTvSeriesPagingRepository.kt @@ -11,11 +11,14 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class DiscoverTvSeriesPagingRepository @Inject constructor( - @ApplicationContext private val context: Context, - private val tvShowApi: TVShowService -) : BasePagingRepository() { - - override fun pagingSource(query: String?, id: Int?): BasePagingSource = - DiscoverTvSeriesPagingSource(context, tvShowApi) -} \ No newline at end of file +class DiscoverTvSeriesPagingRepository + @Inject + constructor( + @ApplicationContext private val context: Context, + private val tvShowApi: TVShowService, + ) : BasePagingRepository() { + override fun pagingSource( + query: String?, + id: Int?, + ): BasePagingSource = DiscoverTvSeriesPagingSource(context, tvShowApi) + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/OnTheAirTvSeriesPagingRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/OnTheAirTvSeriesPagingRepository.kt index d171102..7fdb8ba 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/OnTheAirTvSeriesPagingRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/OnTheAirTvSeriesPagingRepository.kt @@ -3,19 +3,22 @@ package com.sample.tmdb.data.repository.tvshow.paging import android.content.Context import com.sample.tmdb.data.network.TVShowService import com.sample.tmdb.data.paging.tvshow.OnTheAirTvSeriesPagingSource -import com.sample.tmdb.domain.repository.BasePagingRepository import com.sample.tmdb.domain.model.TVShow import com.sample.tmdb.domain.paging.BasePagingSource +import com.sample.tmdb.domain.repository.BasePagingRepository import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton @Singleton -class OnTheAirTvSeriesPagingRepository @Inject constructor( - @ApplicationContext private val context: Context, - private val tvShowApi: TVShowService -) : BasePagingRepository() { - - override fun pagingSource(query: String?, id: Int?): BasePagingSource = - OnTheAirTvSeriesPagingSource(context, tvShowApi) -} \ No newline at end of file +class OnTheAirTvSeriesPagingRepository + @Inject + constructor( + @ApplicationContext private val context: Context, + private val tvShowApi: TVShowService, + ) : BasePagingRepository() { + override fun pagingSource( + query: String?, + id: Int?, + ): BasePagingSource = OnTheAirTvSeriesPagingSource(context, tvShowApi) + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/PopularTvSeriesPagingRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/PopularTvSeriesPagingRepository.kt index 8c9365c..3ca80a1 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/PopularTvSeriesPagingRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/PopularTvSeriesPagingRepository.kt @@ -3,19 +3,22 @@ package com.sample.tmdb.data.repository.tvshow.paging import android.content.Context import com.sample.tmdb.data.network.TVShowService import com.sample.tmdb.data.paging.tvshow.PopularTvSeriesPagingSource -import com.sample.tmdb.domain.repository.BasePagingRepository import com.sample.tmdb.domain.model.TVShow import com.sample.tmdb.domain.paging.BasePagingSource +import com.sample.tmdb.domain.repository.BasePagingRepository import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton @Singleton -class PopularTvSeriesPagingRepository @Inject constructor( - @ApplicationContext private val context: Context, - private val tvShowApi: TVShowService -) : BasePagingRepository() { - - override fun pagingSource(query: String?, id: Int?): BasePagingSource = - PopularTvSeriesPagingSource(context, tvShowApi) -} \ No newline at end of file +class PopularTvSeriesPagingRepository + @Inject + constructor( + @ApplicationContext private val context: Context, + private val tvShowApi: TVShowService, + ) : BasePagingRepository() { + override fun pagingSource( + query: String?, + id: Int?, + ): BasePagingSource = PopularTvSeriesPagingSource(context, tvShowApi) + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/SearchTvSeriesPagingRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/SearchTvSeriesPagingRepository.kt index 1d04d3b..65aa366 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/SearchTvSeriesPagingRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/SearchTvSeriesPagingRepository.kt @@ -3,17 +3,20 @@ package com.sample.tmdb.data.repository.tvshow.paging import android.content.Context import com.sample.tmdb.data.network.TVShowService import com.sample.tmdb.data.paging.tvshow.SearchTvSeriesPagingSource -import com.sample.tmdb.domain.repository.BasePagingRepository import com.sample.tmdb.domain.model.TVShow import com.sample.tmdb.domain.paging.BasePagingSource +import com.sample.tmdb.domain.repository.BasePagingRepository import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject -class SearchTvSeriesPagingRepository@Inject constructor( - @ApplicationContext private val context: Context, - private val tvShowApi: TVShowService -) : BasePagingRepository() { - - override fun pagingSource(query: String?, id: Int?): BasePagingSource = - SearchTvSeriesPagingSource(context, tvShowApi, query!!) -} \ No newline at end of file +class +SearchTvSeriesPagingRepository@Inject + constructor( + @ApplicationContext private val context: Context, + private val tvShowApi: TVShowService, + ) : BasePagingRepository() { + override fun pagingSource( + query: String?, + id: Int?, + ): BasePagingSource = SearchTvSeriesPagingSource(context, tvShowApi, query!!) + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/SimilarTvSeriesPagingRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/SimilarTvSeriesPagingRepository.kt index 12de91b..f0062cf 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/SimilarTvSeriesPagingRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/SimilarTvSeriesPagingRepository.kt @@ -11,11 +11,14 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class SimilarTvSeriesPagingRepository @Inject constructor( - @ApplicationContext private val context: Context, - private val tvShowApi: TVShowService -) : BasePagingRepository() { - - override fun pagingSource(query: String?, id: Int?): BasePagingSource = - SimilarTvSeriesPagingSource(context, tvShowApi, id!!) -} \ No newline at end of file +class SimilarTvSeriesPagingRepository + @Inject + constructor( + @ApplicationContext private val context: Context, + private val tvShowApi: TVShowService, + ) : BasePagingRepository() { + override fun pagingSource( + query: String?, + id: Int?, + ): BasePagingSource = SimilarTvSeriesPagingSource(context, tvShowApi, id!!) + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/TopRatedTvSeriesPagingRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/TopRatedTvSeriesPagingRepository.kt index f0deac5..81fae29 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/TopRatedTvSeriesPagingRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/TopRatedTvSeriesPagingRepository.kt @@ -3,19 +3,22 @@ package com.sample.tmdb.data.repository.tvshow.paging import android.content.Context import com.sample.tmdb.data.network.TVShowService import com.sample.tmdb.data.paging.tvshow.TopRatedTvSeriesPagingSource -import com.sample.tmdb.domain.repository.BasePagingRepository import com.sample.tmdb.domain.model.TVShow import com.sample.tmdb.domain.paging.BasePagingSource +import com.sample.tmdb.domain.repository.BasePagingRepository import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton @Singleton -class TopRatedTvSeriesPagingRepository @Inject constructor( - @ApplicationContext private val context: Context, - private val tvShowApi: TVShowService -) : BasePagingRepository() { - - override fun pagingSource(query: String?, id: Int?): BasePagingSource = - TopRatedTvSeriesPagingSource(context, tvShowApi) -} \ No newline at end of file +class TopRatedTvSeriesPagingRepository + @Inject + constructor( + @ApplicationContext private val context: Context, + private val tvShowApi: TVShowService, + ) : BasePagingRepository() { + override fun pagingSource( + query: String?, + id: Int?, + ): BasePagingSource = TopRatedTvSeriesPagingSource(context, tvShowApi) + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/TrendingTvSeriesPagingRepository.kt b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/TrendingTvSeriesPagingRepository.kt index 9cc5879..d0f343c 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/TrendingTvSeriesPagingRepository.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/repository/tvshow/paging/TrendingTvSeriesPagingRepository.kt @@ -3,19 +3,22 @@ package com.sample.tmdb.data.repository.tvshow.paging import android.content.Context import com.sample.tmdb.data.network.TVShowService import com.sample.tmdb.data.paging.tvshow.TrendingTvSeriesPagingSource -import com.sample.tmdb.domain.repository.BasePagingRepository import com.sample.tmdb.domain.model.TVShow import com.sample.tmdb.domain.paging.BasePagingSource +import com.sample.tmdb.domain.repository.BasePagingRepository import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton @Singleton -class TrendingTvSeriesPagingRepository @Inject constructor( - @ApplicationContext private val context: Context, - private val tvShowApi: TVShowService -) : BasePagingRepository() { - - override fun pagingSource(query: String?, id: Int?): BasePagingSource = - TrendingTvSeriesPagingSource(context, tvShowApi) -} \ No newline at end of file +class TrendingTvSeriesPagingRepository + @Inject + constructor( + @ApplicationContext private val context: Context, + private val tvShowApi: TVShowService, + ) : BasePagingRepository() { + override fun pagingSource( + query: String?, + id: Int?, + ): BasePagingSource = TrendingTvSeriesPagingSource(context, tvShowApi) + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/response/CreditDto.kt b/core/data/src/main/java/com/sample/tmdb/data/response/CreditDto.kt index f93cf4c..ed79b75 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/response/CreditDto.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/response/CreditDto.kt @@ -1,11 +1,11 @@ package com.sample.tmdb.data.response -import com.sample.tmdb.domain.model.Cast -import com.sample.tmdb.domain.model.Crew import com.sample.tmdb.common.model.Gender import com.sample.tmdb.common.utils.Constants.BASE_WIDTH_342_PATH import com.sample.tmdb.common.utils.Constants.ID import com.sample.tmdb.common.utils.Constants.NAME +import com.sample.tmdb.domain.model.Cast +import com.sample.tmdb.domain.model.Crew import com.squareup.moshi.Json import com.squareup.moshi.JsonClass @@ -20,7 +20,7 @@ data class NetworkCast( @Json(name = GENDER) val gender: Int, @Json(name = ID) - val id: Int + val id: Int, ) @JsonClass(generateAdapter = true) @@ -34,40 +34,42 @@ data class NetworkCrew( @Json(name = GENDER) val gender: Int, @Json(name = ID) - val id: String + val id: String, ) -fun List.asCastDomainModel(): List = map { - Cast( - it.role, - it.name, - it.profilePath?.let { profilePath -> - String.format( - BASE_WIDTH_342_PATH, - profilePath - ) - }, - it.gender.toGender(), - it.id - ) -} +fun List.asCastDomainModel(): List = + map { + Cast( + it.role, + it.name, + it.profilePath?.let { profilePath -> + String.format( + BASE_WIDTH_342_PATH, + profilePath, + ) + }, + it.gender.toGender(), + it.id, + ) + } -fun List.asCrewDomainModel(): List = map { - Crew( - it.role, - it.name, - it.profilePath?.let { profilePath -> - String.format( - BASE_WIDTH_342_PATH, - profilePath - ) - }, - it.gender.toGender(), - it.id - ) -} +fun List.asCrewDomainModel(): List = + map { + Crew( + it.role, + it.name, + it.profilePath?.let { profilePath -> + String.format( + BASE_WIDTH_342_PATH, + profilePath, + ) + }, + it.gender.toGender(), + it.id, + ) + } private fun Int.toGender() = if (this == 1) Gender.FEMALE else Gender.MALE private const val PROFILE_PATH = "profile_path" -private const val GENDER = "gender" \ No newline at end of file +private const val GENDER = "gender" diff --git a/core/data/src/main/java/com/sample/tmdb/data/response/DetailDto.kt b/core/data/src/main/java/com/sample/tmdb/data/response/DetailDto.kt index fdd6494..08c3e7b 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/response/DetailDto.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/response/DetailDto.kt @@ -1,9 +1,5 @@ package com.sample.tmdb.data.response -import com.sample.tmdb.domain.model.Genre -import com.sample.tmdb.domain.model.MovieDetails -import com.sample.tmdb.domain.model.SpokenLanguage -import com.sample.tmdb.domain.model.TvDetails import com.sample.tmdb.common.utils.Constants.BACKDROP_PATH import com.sample.tmdb.common.utils.Constants.BASE_WIDTH_342_PATH import com.sample.tmdb.common.utils.Constants.BASE_WIDTH_780_PATH @@ -16,6 +12,10 @@ import com.sample.tmdb.common.utils.Constants.RELEASE_DATE import com.sample.tmdb.common.utils.Constants.TITLE import com.sample.tmdb.common.utils.Constants.VOTE_AVERAGE import com.sample.tmdb.common.utils.Constants.VOTE_COUNT +import com.sample.tmdb.domain.model.Genre +import com.sample.tmdb.domain.model.MovieDetails +import com.sample.tmdb.domain.model.SpokenLanguage +import com.sample.tmdb.domain.model.TvDetails import com.squareup.moshi.Json import com.squareup.moshi.JsonClass @@ -55,7 +55,7 @@ data class MovieDetailResponse( @Json(name = TAGLINE) override val tagline: String, @Json(name = TITLE) override val title: String, @Json(name = VOTE_AVERAGE) override val voteAverage: Double, - @Json(name = VOTE_COUNT) override val voteCount: Int + @Json(name = VOTE_COUNT) override val voteCount: Int, ) : TMDbItemDetailsResponse @JsonClass(generateAdapter = true) @@ -76,72 +76,89 @@ data class TvDetailResponse( @Json(name = NAME) override val title: String, @Json(name = VOTE_AVERAGE) override val voteAverage: Double, @Json(name = VOTE_COUNT) override val voteCount: Int, - ) : TMDbItemDetailsResponse +) : TMDbItemDetailsResponse @JsonClass(generateAdapter = true) data class GenreResponse( @Json(name = ID) val id: Int, - @Json(name = NAME) val name: String? + @Json(name = NAME) val name: String?, ) @JsonClass(generateAdapter = true) data class SpokenLanguageResponse( @Json(name = "iso_639_1") val iso6391: String, - @Json(name = NAME) val name: String + @Json(name = NAME) val name: String, ) -fun MovieDetailResponse.asDomainModel(): MovieDetails = MovieDetails( - backdropPath?.let { - String.format( - BASE_WIDTH_780_PATH, - it - ) - }, genres.asGenreDomainModel(), - homepage, id, originalLanguage, originalTitle, overview, popularity, posterPath?.let { - String.format( - BASE_WIDTH_342_PATH, - it - ) - }, releaseDate, - spokenLanguages.asLanguageDomainModel(), status, tagline, title, voteAverage, voteCount -) +fun MovieDetailResponse.asDomainModel(): MovieDetails = + MovieDetails( + backdropPath?.let { + String.format( + BASE_WIDTH_780_PATH, + it, + ) + }, + genres.asGenreDomainModel(), + homepage, + id, + originalLanguage, + originalTitle, + overview, + popularity, + posterPath?.let { + String.format( + BASE_WIDTH_342_PATH, + it, + ) + }, + releaseDate, + spokenLanguages.asLanguageDomainModel(), + status, + tagline, + title, + voteAverage, + voteCount, + ) -fun TvDetailResponse.asDomainModel(): TvDetails = TvDetails( - backdropPath?.let { - String.format( - BASE_WIDTH_780_PATH, - it - ) - }, - genres.asGenreDomainModel(), - homepage, - id, - originalLanguage, - originalTitle, - overview, - popularity, - posterPath?.let { - String.format( - BASE_WIDTH_342_PATH, - it - ) - }, - releaseDate, - spokenLanguages.asLanguageDomainModel(), - status, - tagline, - title, - voteAverage, - voteCount -) +fun TvDetailResponse.asDomainModel(): TvDetails = + TvDetails( + backdropPath?.let { + String.format( + BASE_WIDTH_780_PATH, + it, + ) + }, + genres.asGenreDomainModel(), + homepage, + id, + originalLanguage, + originalTitle, + overview, + popularity, + posterPath?.let { + String.format( + BASE_WIDTH_342_PATH, + it, + ) + }, + releaseDate, + spokenLanguages.asLanguageDomainModel(), + status, + tagline, + title, + voteAverage, + voteCount, + ) -private fun List.asGenreDomainModel(): List = map { - Genre(it.id, it.name) -} +private fun List.asGenreDomainModel(): List = + map { + Genre(it.id, it.name) + } -private fun List.asLanguageDomainModel(): List = map { - SpokenLanguage(it.iso6391, it.name) -} +private fun List.asLanguageDomainModel(): List = + map { + SpokenLanguage(it.iso6391, it.name) + } private const val GENRES = "genres" private const val HOMEPAGE = "homepage" diff --git a/core/data/src/main/java/com/sample/tmdb/data/response/ImageDto.kt b/core/data/src/main/java/com/sample/tmdb/data/response/ImageDto.kt index ea9821d..e21c46f 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/response/ImageDto.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/response/ImageDto.kt @@ -26,11 +26,12 @@ data class ImageResponse( @Json(name = WIDTH) val width: Int, ) -fun ImagesResponse.asDomainModel(): List = buildList { - addAll(backdrops.map { TMDbImage(String.format(BASE_IMAGE_PATH, it.filePath), it.voteCount) }) - addAll(posters.map { TMDbImage(String.format(BASE_IMAGE_PATH, it.filePath), it.voteCount) }) - sortByDescending { it.voteCount } -} +fun ImagesResponse.asDomainModel(): List = + buildList { + addAll(backdrops.map { TMDbImage(String.format(BASE_IMAGE_PATH, it.filePath), it.voteCount) }) + addAll(posters.map { TMDbImage(String.format(BASE_IMAGE_PATH, it.filePath), it.voteCount) }) + sortByDescending { it.voteCount } + } private const val BACKDROPS = "backdrops" private const val POSTERS = "posters" @@ -38,4 +39,4 @@ private const val ASPECT_RATIO = "aspect_ratio" private const val FILE_PATH = "file_path" private const val HEIGHT = "height" private const val ISO_639_1 = "iso_639_1" -private const val WIDTH = "width" \ No newline at end of file +private const val WIDTH = "width" diff --git a/core/data/src/main/java/com/sample/tmdb/data/response/PersonDto.kt b/core/data/src/main/java/com/sample/tmdb/data/response/PersonDto.kt index 54bdca8..a659b2a 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/response/PersonDto.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/response/PersonDto.kt @@ -1,14 +1,14 @@ package com.sample.tmdb.data.response -import com.sample.tmdb.domain.model.Person import com.sample.tmdb.common.utils.Constants import com.sample.tmdb.common.utils.Constants.ID import com.sample.tmdb.common.utils.Constants.NAME +import com.sample.tmdb.domain.model.Person import com.squareup.moshi.Json import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) -data class PersonResponse( +data class PersonDto( @Json(name = "birthday") val birthDay: String?, @Json(name = "deathday") @@ -25,7 +25,7 @@ data class PersonResponse( val profilePath: String?, ) -fun PersonResponse.asDomainModel(): Person = +fun PersonDto.asDomainModel(): Person = Person( birthDay, deathDay, @@ -36,6 +36,7 @@ fun PersonResponse.asDomainModel(): Person = profilePath?.let { profilePath -> String.format( Constants.BASE_WIDTH_342_PATH, - profilePath + profilePath, ) - }) \ No newline at end of file + }, + ) diff --git a/core/data/src/main/java/com/sample/tmdb/data/response/TMDbDto.kt b/core/data/src/main/java/com/sample/tmdb/data/response/TMDbDto.kt index ab73a87..e1c5488 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/response/TMDbDto.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/response/TMDbDto.kt @@ -1,7 +1,5 @@ package com.sample.tmdb.data.response -import com.sample.tmdb.domain.model.Movie -import com.sample.tmdb.domain.model.TVShow import com.sample.tmdb.common.utils.Constants.BACKDROP_PATH import com.sample.tmdb.common.utils.Constants.BASE_WIDTH_342_PATH import com.sample.tmdb.common.utils.Constants.BASE_WIDTH_780_PATH @@ -14,6 +12,8 @@ import com.sample.tmdb.common.utils.Constants.RELEASE_DATE import com.sample.tmdb.common.utils.Constants.TITLE import com.sample.tmdb.common.utils.Constants.VOTE_AVERAGE import com.sample.tmdb.common.utils.Constants.VOTE_COUNT +import com.sample.tmdb.domain.model.Movie +import com.sample.tmdb.domain.model.TVShow import com.squareup.moshi.Json import com.squareup.moshi.JsonClass @@ -45,7 +45,7 @@ data class NetworkMovie( @Json(name = VOTE_AVERAGE) override val voteAverage: Double, @Json(name = VOTE_COUNT) - override val voteCount: Int + override val voteCount: Int, ) : NetworkTMDbItem @JsonClass(generateAdapter = true) @@ -65,7 +65,7 @@ data class NetworkTVShow( @Json(name = VOTE_AVERAGE) override val voteAverage: Double, @Json(name = VOTE_COUNT) - override val voteCount: Int + override val voteCount: Int, ) : NetworkTMDbItem fun List.asMovieDomainModel(): List = @@ -77,18 +77,18 @@ fun List.asMovieDomainModel(): List = it.posterPath?.let { posterPath -> String.format( BASE_WIDTH_342_PATH, - posterPath + posterPath, ) }, it.backdropPath?.let { backdropPath -> String.format( BASE_WIDTH_780_PATH, - backdropPath + backdropPath, ) }, it.name, it.voteAverage, - it.voteCount + it.voteCount, ) } @@ -101,17 +101,17 @@ fun List.asTVShowDomainModel(): List = it.posterPath?.let { posterPath -> String.format( BASE_WIDTH_342_PATH, - posterPath + posterPath, ) }, it.backdropPath?.let { backdropPath -> String.format( BASE_WIDTH_780_PATH, - backdropPath + backdropPath, ) }, it.name, it.voteAverage, - it.voteCount + it.voteCount, ) - } \ No newline at end of file + } diff --git a/core/data/src/main/java/com/sample/tmdb/data/response/WrapperDto.kt b/core/data/src/main/java/com/sample/tmdb/data/response/WrapperDto.kt index 3d537d2..32ddcdc 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/response/WrapperDto.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/response/WrapperDto.kt @@ -6,7 +6,7 @@ import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) data class TMDbWrapper( @Json(name = "results") - val items: List + val items: List, ) @JsonClass(generateAdapter = true) @@ -14,5 +14,5 @@ data class NetworkCreditWrapper( @Json(name = "cast") val cast: List, @Json(name = "crew") - val crew: List -) \ No newline at end of file + val crew: List, +) diff --git a/core/data/src/main/java/com/sample/tmdb/data/source/entity/MovieEntity.kt b/core/data/src/main/java/com/sample/tmdb/data/source/entity/MovieEntity.kt index 3786e40..14d32c9 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/source/entity/MovieEntity.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/source/entity/MovieEntity.kt @@ -13,29 +13,31 @@ class MovieEntity( val backdropUrl: String?, val name: String, val voteAverage: Double, - val voteCount: Int + val voteCount: Int, ) -fun List.asDomainModel(): List = map { - Movie( - id = it.id, - overview = it.overview, - releaseDate = it.releaseDate, - posterUrl = it.posterUrl, - backdropUrl = it.backdropUrl, - name = it.name, - voteAverage = it.voteAverage, - voteCount = it.voteCount - ) -} +fun List.asDomainModel(): List = + map { + Movie( + id = it.id, + overview = it.overview, + releaseDate = it.releaseDate, + posterUrl = it.posterUrl, + backdropUrl = it.backdropUrl, + name = it.name, + voteAverage = it.voteAverage, + voteCount = it.voteCount, + ) + } -fun Movie.asDatabaseModel(): MovieEntity = MovieEntity( - id = id, - overview = overview, - releaseDate = releaseDate, - posterUrl = posterUrl, - backdropUrl = backdropUrl, - name = name, - voteAverage = voteAverage, - voteCount = voteCount -) \ No newline at end of file +fun Movie.asDatabaseModel(): MovieEntity = + MovieEntity( + id = id, + overview = overview, + releaseDate = releaseDate, + posterUrl = posterUrl, + backdropUrl = backdropUrl, + name = name, + voteAverage = voteAverage, + voteCount = voteCount, + ) diff --git a/core/data/src/main/java/com/sample/tmdb/data/source/entity/TVShowEntity.kt b/core/data/src/main/java/com/sample/tmdb/data/source/entity/TVShowEntity.kt index 844d113..cd910ca 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/source/entity/TVShowEntity.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/source/entity/TVShowEntity.kt @@ -13,29 +13,31 @@ class TVShowEntity( val backdropUrl: String?, val name: String, val voteAverage: Double, - val voteCount: Int + val voteCount: Int, ) -fun List.asDomainModel(): List = map { - TVShow( - id = it.id, - overview = it.overview, - releaseDate = it.releaseDate, - posterUrl = it.posterUrl, - backdropUrl = it.backdropUrl, - name = it.name, - voteAverage = it.voteAverage, - voteCount = it.voteCount - ) -} +fun List.asDomainModel(): List = + map { + TVShow( + id = it.id, + overview = it.overview, + releaseDate = it.releaseDate, + posterUrl = it.posterUrl, + backdropUrl = it.backdropUrl, + name = it.name, + voteAverage = it.voteAverage, + voteCount = it.voteCount, + ) + } -fun TVShow.asDatabaseModel(): TVShowEntity = TVShowEntity( - id = id, - overview = overview, - releaseDate = releaseDate, - posterUrl = posterUrl, - backdropUrl = backdropUrl, - name = name, - voteAverage = voteAverage, - voteCount = voteCount -) \ No newline at end of file +fun TVShow.asDatabaseModel(): TVShowEntity = + TVShowEntity( + id = id, + overview = overview, + releaseDate = releaseDate, + posterUrl = posterUrl, + backdropUrl = backdropUrl, + name = name, + voteAverage = voteAverage, + voteCount = voteCount, + ) diff --git a/core/data/src/main/java/com/sample/tmdb/data/source/local/MovieDao.kt b/core/data/src/main/java/com/sample/tmdb/data/source/local/MovieDao.kt index 7ce84ab..19efffe 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/source/local/MovieDao.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/source/local/MovieDao.kt @@ -8,7 +8,6 @@ import com.sample.tmdb.data.source.entity.MovieEntity @Dao interface MovieDao { - @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun addBookmark(movieEntity: MovieEntity) @@ -20,4 +19,4 @@ interface MovieDao { @Query("SELECT * FROM Movies ORDER BY releaseDate DESC") suspend fun getBookmarks(): List -} \ No newline at end of file +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/source/local/TMDbDatabase.kt b/core/data/src/main/java/com/sample/tmdb/data/source/local/TMDbDatabase.kt index a512ba1..d6c5858 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/source/local/TMDbDatabase.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/source/local/TMDbDatabase.kt @@ -9,4 +9,4 @@ import com.sample.tmdb.data.source.entity.TVShowEntity abstract class TMDbDatabase : RoomDatabase() { abstract val movieDao: MovieDao abstract val tvShowDao: TVShowDao -} \ No newline at end of file +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/source/local/TVShowDao.kt b/core/data/src/main/java/com/sample/tmdb/data/source/local/TVShowDao.kt index 4d0b56f..77a833c 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/source/local/TVShowDao.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/source/local/TVShowDao.kt @@ -8,7 +8,6 @@ import com.sample.tmdb.data.source.entity.TVShowEntity @Dao interface TVShowDao { - @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun addBookmark(tvShowEntity: TVShowEntity) @@ -20,4 +19,4 @@ interface TVShowDao { @Query("SELECT * FROM TVShows ORDER BY releaseDate DESC") suspend fun getBookmarks(): List -} \ No newline at end of file +} diff --git a/core/data/src/main/java/com/sample/tmdb/data/utils/NetworkUtils.kt b/core/data/src/main/java/com/sample/tmdb/data/utils/NetworkUtils.kt index f859041..626bdbc 100644 --- a/core/data/src/main/java/com/sample/tmdb/data/utils/NetworkUtils.kt +++ b/core/data/src/main/java/com/sample/tmdb/data/utils/NetworkUtils.kt @@ -9,8 +9,7 @@ import retrofit2.Retrofit import retrofit2.converter.moshi.MoshiConverterFactory import java.util.concurrent.TimeUnit -fun createNetworkClient(baseUrl: String) = - retrofitClient(baseUrl, httpClient()) +fun createNetworkClient(baseUrl: String) = retrofitClient(baseUrl, httpClient()) private fun httpClient(): OkHttpClient { val httpLoggingInterceptor = HttpLoggingInterceptor(HttpLoggingInterceptor.Logger.DEFAULT) @@ -23,9 +22,11 @@ private fun httpClient(): OkHttpClient { val original = chain.request() val originalHttpUrl = original.url - val url = originalHttpUrl.newBuilder() - .addQueryParameter("api_key", BuildConfig.TMDB_API_KEY) - .build() + val url = + originalHttpUrl + .newBuilder() + .addQueryParameter("api_key", BuildConfig.TMDB_API_KEY) + .build() val request = original.newBuilder().url(url).build() chain.proceed(request) @@ -39,10 +40,11 @@ private val moshiBuilder = Moshi.Builder().add(KotlinJsonAdapterFactory()).build private fun retrofitClient( baseUrl: String, - httpClient: OkHttpClient + httpClient: OkHttpClient, ): Retrofit = - Retrofit.Builder() + Retrofit + .Builder() .baseUrl(baseUrl) .client(httpClient) .addConverterFactory(MoshiConverterFactory.create(moshiBuilder)) - .build() \ No newline at end of file + .build() diff --git a/core/data/src/test/java/com/sample/tmdb/data/repository/BaseBookmarkDetailsRepositoryTest.kt b/core/data/src/test/java/com/sample/tmdb/data/repository/BaseBookmarkDetailsRepositoryTest.kt index 0f47f9e..812f362 100644 --- a/core/data/src/test/java/com/sample/tmdb/data/repository/BaseBookmarkDetailsRepositoryTest.kt +++ b/core/data/src/test/java/com/sample/tmdb/data/repository/BaseBookmarkDetailsRepositoryTest.kt @@ -8,7 +8,6 @@ import org.junit.Test import org.mockito.ArgumentMatchers.anyInt abstract class BaseBookmarkDetailsRepositoryTest : BaseRepositoryTest() { - protected lateinit var repository: BookmarkDetailsRepository @Test @@ -18,4 +17,4 @@ abstract class BaseBookmarkDetailsRepositoryTest : BaseRepositoryT assertEquals(true, repository.isBookmarked(anyInt())) } } -} \ No newline at end of file +} diff --git a/core/data/src/test/java/com/sample/tmdb/data/repository/BaseBookmarkRepositoryTest.kt b/core/data/src/test/java/com/sample/tmdb/data/repository/BaseBookmarkRepositoryTest.kt index d99c187..bf31d04 100644 --- a/core/data/src/test/java/com/sample/tmdb/data/repository/BaseBookmarkRepositoryTest.kt +++ b/core/data/src/test/java/com/sample/tmdb/data/repository/BaseBookmarkRepositoryTest.kt @@ -15,7 +15,6 @@ import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mockito.`when` abstract class BaseBookmarkRepositoryTest : BaseRepositoryTest() { - protected lateinit var repository: BaseRepository> @Test @@ -29,13 +28,14 @@ abstract class BaseBookmarkRepositoryTest : BaseRepositoryTest() { } @Test - fun `load bookmark failed`() = runTest { - val errorMsg = "error message" - `when`(context.getString(anyInt())).thenReturn(errorMsg) - repository.getResult(null).test { - assertEquals(Resource.Loading, awaitItem()) - assertEquals(Resource.Error(errorMsg), awaitItem()) - awaitComplete() + fun `load bookmark failed`() = + runTest { + val errorMsg = "error message" + `when`(context.getString(anyInt())).thenReturn(errorMsg) + repository.getResult(null).test { + assertEquals(Resource.Loading, awaitItem()) + assertEquals(Resource.Error(errorMsg), awaitItem()) + awaitComplete() + } } - } -} \ No newline at end of file +} diff --git a/core/data/src/test/java/com/sample/tmdb/data/repository/BaseDetailRepositoryTest.kt b/core/data/src/test/java/com/sample/tmdb/data/repository/BaseDetailRepositoryTest.kt index 8a16205..60174e0 100644 --- a/core/data/src/test/java/com/sample/tmdb/data/repository/BaseDetailRepositoryTest.kt +++ b/core/data/src/test/java/com/sample/tmdb/data/repository/BaseDetailRepositoryTest.kt @@ -20,8 +20,7 @@ import org.junit.Test import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mockito.`when` -abstract class BaseDetailRepositoryTest: BaseRepositoryTest() { - +abstract class BaseDetailRepositoryTest : BaseRepositoryTest() { protected lateinit var repository: BaseDetailRepository @Test @@ -82,4 +81,4 @@ abstract class BaseDetailRepositoryTest: BaseRepositoryTest const val VOTE_AVERAGE = 1.0 const val VOTE_COUNT = 10 } -} \ No newline at end of file +} diff --git a/core/data/src/test/java/com/sample/tmdb/data/repository/BaseFeedRepositoryTest.kt b/core/data/src/test/java/com/sample/tmdb/data/repository/BaseFeedRepositoryTest.kt index b2b3379..c2f4bfc 100644 --- a/core/data/src/test/java/com/sample/tmdb/data/repository/BaseFeedRepositoryTest.kt +++ b/core/data/src/test/java/com/sample/tmdb/data/repository/BaseFeedRepositoryTest.kt @@ -14,8 +14,7 @@ import org.junit.Test import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mockito.`when` -abstract class BaseFeedRepositoryTest: BaseRepositoryTest() { - +abstract class BaseFeedRepositoryTest : BaseRepositoryTest() { protected lateinit var repository: BaseFeedRepository @Test @@ -45,4 +44,4 @@ abstract class BaseFeedRepositoryTest: BaseRepositoryTest() { } } } -} \ No newline at end of file +} diff --git a/core/data/src/test/java/com/sample/tmdb/data/repository/BaseRepositoryTest.kt b/core/data/src/test/java/com/sample/tmdb/data/repository/BaseRepositoryTest.kt index ceb0969..7fb1e40 100644 --- a/core/data/src/test/java/com/sample/tmdb/data/repository/BaseRepositoryTest.kt +++ b/core/data/src/test/java/com/sample/tmdb/data/repository/BaseRepositoryTest.kt @@ -7,7 +7,6 @@ import org.junit.Rule import org.mockito.Mock abstract class BaseRepositoryTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() @@ -22,4 +21,4 @@ abstract class BaseRepositoryTest { fun setup() { initRepository() } -} \ No newline at end of file +} diff --git a/core/data/src/test/java/com/sample/tmdb/data/repository/PersonRepositoryTest.kt b/core/data/src/test/java/com/sample/tmdb/data/repository/PersonRepositoryTest.kt index a8bf28b..dace553 100644 --- a/core/data/src/test/java/com/sample/tmdb/data/repository/PersonRepositoryTest.kt +++ b/core/data/src/test/java/com/sample/tmdb/data/repository/PersonRepositoryTest.kt @@ -4,7 +4,7 @@ import app.cash.turbine.test import com.sample.tmdb.common.base.BaseRepository import com.sample.tmdb.common.utils.Resource import com.sample.tmdb.data.network.PersonService -import com.sample.tmdb.data.response.PersonResponse +import com.sample.tmdb.data.response.PersonDto import com.sample.tmdb.data.response.asDomainModel import com.sample.tmdb.domain.model.Person import junit.framework.TestCase.assertEquals @@ -20,24 +20,30 @@ import org.mockito.junit.MockitoJUnitRunner @RunWith(MockitoJUnitRunner::class) class PersonRepositoryTest : BaseRepositoryTest() { - @Mock private lateinit var api: PersonService private lateinit var repository: BaseRepository - private val personResponse = PersonResponse( - "birth", "death", 1, "name", - "biography", "placeOfBirth", "profilePath" - ) + private val personDto = + PersonDto( + "birth", + "death", + 1, + "name", + "biography", + "placeOfBirth", + "profilePath", + ) override fun initRepository() { repository = PersonRepository(api, context, Dispatchers.Main) } - override fun mockApiResponse() = runTest { - `when`(api.getPerson(anyString())).thenReturn(personResponse) - } + override fun mockApiResponse() = + runTest { + `when`(api.getPerson(anyString())).thenReturn(personDto) + } @Test fun `load person success`() { @@ -46,7 +52,7 @@ class PersonRepositoryTest : BaseRepositoryTest() { repository.getResult(anyString()).test { assertEquals(Resource.Loading, awaitItem()) awaitItem() - val person = Resource.Success(personResponse.asDomainModel()).data + val person = Resource.Success(personDto.asDomainModel()).data assertEquals("birth", person.birthDay) assertEquals("death", person.deathDay) assertEquals(1, person.id) @@ -72,4 +78,4 @@ class PersonRepositoryTest : BaseRepositoryTest() { } } } -} \ No newline at end of file +} diff --git a/core/data/src/test/java/com/sample/tmdb/data/repository/movie/MovieFeedRepositoryTest.kt b/core/data/src/test/java/com/sample/tmdb/data/repository/movie/MovieFeedRepositoryTest.kt index 5e2e46e..73d99a7 100644 --- a/core/data/src/test/java/com/sample/tmdb/data/repository/movie/MovieFeedRepositoryTest.kt +++ b/core/data/src/test/java/com/sample/tmdb/data/repository/movie/MovieFeedRepositoryTest.kt @@ -13,7 +13,6 @@ import org.mockito.junit.MockitoJUnitRunner @RunWith(MockitoJUnitRunner::class) class MovieFeedRepositoryTest : BaseFeedRepositoryTest() { - @Mock private lateinit var api: MovieService @@ -21,12 +20,13 @@ class MovieFeedRepositoryTest : BaseFeedRepositoryTest() { repository = MovieFeedRepository(context, Dispatchers.Main, api) } - override fun mockApiResponse() = runTest { - `when`(api.trendingMovies()).thenReturn(TMDbWrapper(emptyList())) - `when`(api.popularMovies()).thenReturn(TMDbWrapper(emptyList())) - `when`(api.nowPlayingMovies()).thenReturn(TMDbWrapper(emptyList())) - `when`(api.upcomingMovies()).thenReturn(TMDbWrapper(emptyList())) - `when`(api.topRatedMovies()).thenReturn(TMDbWrapper(emptyList())) - `when`(api.discoverMovies()).thenReturn(TMDbWrapper(emptyList())) - } -} \ No newline at end of file + override fun mockApiResponse() = + runTest { + `when`(api.trendingMovies()).thenReturn(TMDbWrapper(emptyList())) + `when`(api.popularMovies()).thenReturn(TMDbWrapper(emptyList())) + `when`(api.nowPlayingMovies()).thenReturn(TMDbWrapper(emptyList())) + `when`(api.upcomingMovies()).thenReturn(TMDbWrapper(emptyList())) + `when`(api.topRatedMovies()).thenReturn(TMDbWrapper(emptyList())) + `when`(api.discoverMovies()).thenReturn(TMDbWrapper(emptyList())) + } +} diff --git a/core/data/src/test/java/com/sample/tmdb/data/repository/movie/detail/BookmarkMovieDetailsRepositoryTest.kt b/core/data/src/test/java/com/sample/tmdb/data/repository/movie/detail/BookmarkMovieDetailsRepositoryTest.kt index 3b32c1b..f4f2c44 100644 --- a/core/data/src/test/java/com/sample/tmdb/data/repository/movie/detail/BookmarkMovieDetailsRepositoryTest.kt +++ b/core/data/src/test/java/com/sample/tmdb/data/repository/movie/detail/BookmarkMovieDetailsRepositoryTest.kt @@ -11,8 +11,7 @@ import org.mockito.Mockito.`when` import org.mockito.junit.MockitoJUnitRunner @RunWith(MockitoJUnitRunner::class) -class BookmarkMovieDetailsRepositoryTest: BaseBookmarkDetailsRepositoryTest() { - +class BookmarkMovieDetailsRepositoryTest : BaseBookmarkDetailsRepositoryTest() { @Mock private lateinit var dao: MovieDao @@ -20,7 +19,8 @@ class BookmarkMovieDetailsRepositoryTest: BaseBookmarkDetailsRepositoryTest() { - +class BookmarkMovieRepositoryTest : BaseBookmarkRepositoryTest() { @Mock private lateinit var dao: MovieDao @@ -20,7 +19,8 @@ class BookmarkMovieRepositoryTest: BaseBookmarkRepositoryTest() { repository = BookmarkMovieRepository(dao, context, Dispatchers.Main) } - override fun mockApiResponse() = runTest { - `when`(dao.getBookmarks()).thenReturn(emptyList()) - } -} \ No newline at end of file + override fun mockApiResponse() = + runTest { + `when`(dao.getBookmarks()).thenReturn(emptyList()) + } +} diff --git a/core/data/src/test/java/com/sample/tmdb/data/repository/movie/detail/MovieDetailRepositoryTest.kt b/core/data/src/test/java/com/sample/tmdb/data/repository/movie/detail/MovieDetailRepositoryTest.kt index ddfeab0..549b267 100644 --- a/core/data/src/test/java/com/sample/tmdb/data/repository/movie/detail/MovieDetailRepositoryTest.kt +++ b/core/data/src/test/java/com/sample/tmdb/data/repository/movie/detail/MovieDetailRepositoryTest.kt @@ -17,7 +17,6 @@ import org.mockito.junit.MockitoJUnitRunner @RunWith(MockitoJUnitRunner::class) class MovieDetailRepositoryTest : BaseDetailRepositoryTest() { - @Mock private lateinit var api: MovieService @@ -25,29 +24,30 @@ class MovieDetailRepositoryTest : BaseDetailRepositoryTest() { repository = MovieDetailRepository(api, context, Dispatchers.Main) } - override fun mockApiResponse() = runTest { - `when`(api.fetchMovieDetail(anyInt())).thenReturn( - MovieDetailResponse( - BACKDROP_PATH, - emptyList(), - HOMEPAGE, - ID, - ORIGINAL_LANGUAGE, - ORIGINAL_TITLE, - OVERVIEW, - POPULARITY, - POSTER_PATH, - RELEASE_DATE, - emptyList(), - STATUS, - TAG_LINE, - TITLE, - VOTE_AVERAGE, - VOTE_COUNT + override fun mockApiResponse() = + runTest { + `when`(api.fetchMovieDetail(anyInt())).thenReturn( + MovieDetailResponse( + BACKDROP_PATH, + emptyList(), + HOMEPAGE, + ID, + ORIGINAL_LANGUAGE, + ORIGINAL_TITLE, + OVERVIEW, + POPULARITY, + POSTER_PATH, + RELEASE_DATE, + emptyList(), + STATUS, + TAG_LINE, + TITLE, + VOTE_AVERAGE, + VOTE_COUNT, + ), ) - ) - `when`(api.movieCredit(anyInt())).thenReturn(NetworkCreditWrapper(emptyList(), emptyList())) - `when`(api.fetchImages(anyInt())).thenReturn(ImagesResponse(emptyList(), ID, emptyList())) - `when`(api.fetchSimilarMovies(anyInt())).thenReturn(TMDbWrapper(emptyList())) - } -} \ No newline at end of file + `when`(api.movieCredit(anyInt())).thenReturn(NetworkCreditWrapper(emptyList(), emptyList())) + `when`(api.fetchImages(anyInt())).thenReturn(ImagesResponse(emptyList(), ID, emptyList())) + `when`(api.fetchSimilarMovies(anyInt())).thenReturn(TMDbWrapper(emptyList())) + } +} diff --git a/core/data/src/test/java/com/sample/tmdb/data/repository/tvshow/TVShowFeedRepositoryTest.kt b/core/data/src/test/java/com/sample/tmdb/data/repository/tvshow/TVShowFeedRepositoryTest.kt index ede2c07..6fb192d 100644 --- a/core/data/src/test/java/com/sample/tmdb/data/repository/tvshow/TVShowFeedRepositoryTest.kt +++ b/core/data/src/test/java/com/sample/tmdb/data/repository/tvshow/TVShowFeedRepositoryTest.kt @@ -12,8 +12,7 @@ import org.mockito.Mockito.`when` import org.mockito.junit.MockitoJUnitRunner @RunWith(MockitoJUnitRunner::class) -class TVShowFeedRepositoryTest: BaseFeedRepositoryTest() { - +class TVShowFeedRepositoryTest : BaseFeedRepositoryTest() { @Mock private lateinit var api: TVShowService @@ -21,12 +20,13 @@ class TVShowFeedRepositoryTest: BaseFeedRepositoryTest() { repository = TVShowFeedRepository(context, Dispatchers.Main, api) } - override fun mockApiResponse() = runTest { - `when`(api.trendingTVSeries()).thenReturn(TMDbWrapper(emptyList())) - `when`(api.popularTVSeries()).thenReturn(TMDbWrapper(emptyList())) - `when`(api.airingTodayTVSeries()).thenReturn(TMDbWrapper(emptyList())) - `when`(api.onTheAirTVSeries()).thenReturn(TMDbWrapper(emptyList())) - `when`(api.topRatedTVSeries()).thenReturn(TMDbWrapper(emptyList())) - `when`(api.discoverTVSeries()).thenReturn(TMDbWrapper(emptyList())) - } -} \ No newline at end of file + override fun mockApiResponse() = + runTest { + `when`(api.trendingTVSeries()).thenReturn(TMDbWrapper(emptyList())) + `when`(api.popularTVSeries()).thenReturn(TMDbWrapper(emptyList())) + `when`(api.airingTodayTVSeries()).thenReturn(TMDbWrapper(emptyList())) + `when`(api.onTheAirTVSeries()).thenReturn(TMDbWrapper(emptyList())) + `when`(api.topRatedTVSeries()).thenReturn(TMDbWrapper(emptyList())) + `when`(api.discoverTVSeries()).thenReturn(TMDbWrapper(emptyList())) + } +} diff --git a/core/data/src/test/java/com/sample/tmdb/data/repository/tvshow/detail/BookmarkTVShowDetailsRepositoryTest.kt b/core/data/src/test/java/com/sample/tmdb/data/repository/tvshow/detail/BookmarkTVShowDetailsRepositoryTest.kt index 4936bd2..e1cb613 100644 --- a/core/data/src/test/java/com/sample/tmdb/data/repository/tvshow/detail/BookmarkTVShowDetailsRepositoryTest.kt +++ b/core/data/src/test/java/com/sample/tmdb/data/repository/tvshow/detail/BookmarkTVShowDetailsRepositoryTest.kt @@ -11,8 +11,7 @@ import org.mockito.Mockito.`when` import org.mockito.junit.MockitoJUnitRunner @RunWith(MockitoJUnitRunner::class) -class BookmarkTVShowDetailsRepositoryTest: BaseBookmarkDetailsRepositoryTest() { - +class BookmarkTVShowDetailsRepositoryTest : BaseBookmarkDetailsRepositoryTest() { @Mock private lateinit var dao: TVShowDao @@ -20,7 +19,8 @@ class BookmarkTVShowDetailsRepositoryTest: BaseBookmarkDetailsRepositoryTest() { - +class BookmarkTVShowRepositoryTest : BaseBookmarkRepositoryTest() { @Mock private lateinit var dao: TVShowDao override fun initRepository() { - repository = BookmarkTVShowRepository(dao, context, Dispatchers.Main) + repository = BookmarkTVShowRepository(dao, context, Dispatchers.Main) } - override fun mockApiResponse() = runTest { - `when`(dao.getBookmarks()).thenReturn(emptyList()) - } -} \ No newline at end of file + override fun mockApiResponse() = + runTest { + `when`(dao.getBookmarks()).thenReturn(emptyList()) + } +} diff --git a/core/data/src/test/java/com/sample/tmdb/data/repository/tvshow/detail/TVShowDetailRepositoryTest.kt b/core/data/src/test/java/com/sample/tmdb/data/repository/tvshow/detail/TVShowDetailRepositoryTest.kt index f130cc3..012e11f 100644 --- a/core/data/src/test/java/com/sample/tmdb/data/repository/tvshow/detail/TVShowDetailRepositoryTest.kt +++ b/core/data/src/test/java/com/sample/tmdb/data/repository/tvshow/detail/TVShowDetailRepositoryTest.kt @@ -17,7 +17,6 @@ import org.mockito.junit.MockitoJUnitRunner @RunWith(MockitoJUnitRunner::class) class TVShowDetailRepositoryTest : BaseDetailRepositoryTest() { - @Mock private lateinit var api: TVShowService @@ -25,29 +24,30 @@ class TVShowDetailRepositoryTest : BaseDetailRepositoryTest() { repository = TVShowDetailRepository(api, context, Dispatchers.Main) } - override fun mockApiResponse() = runTest { - `when`(api.fetchTvDetail(anyInt())).thenReturn( - TvDetailResponse( - BACKDROP_PATH, - emptyList(), - HOMEPAGE, - ID, - ORIGINAL_LANGUAGE, - ORIGINAL_TITLE, - OVERVIEW, - POPULARITY, - POSTER_PATH, - RELEASE_DATE, - emptyList(), - STATUS, - TAG_LINE, - TITLE, - VOTE_AVERAGE, - VOTE_COUNT + override fun mockApiResponse() = + runTest { + `when`(api.fetchTvDetail(anyInt())).thenReturn( + TvDetailResponse( + BACKDROP_PATH, + emptyList(), + HOMEPAGE, + ID, + ORIGINAL_LANGUAGE, + ORIGINAL_TITLE, + OVERVIEW, + POPULARITY, + POSTER_PATH, + RELEASE_DATE, + emptyList(), + STATUS, + TAG_LINE, + TITLE, + VOTE_AVERAGE, + VOTE_COUNT, + ), ) - ) - `when`(api.tvCredit(anyInt())).thenReturn(NetworkCreditWrapper(emptyList(), emptyList())) - `when`(api.fetchImages(anyInt())).thenReturn(ImagesResponse(emptyList(), ID, emptyList())) - `when`(api.fetchSimilarMovies(anyInt())).thenReturn(TMDbWrapper(emptyList())) - } -} \ No newline at end of file + `when`(api.tvCredit(anyInt())).thenReturn(NetworkCreditWrapper(emptyList(), emptyList())) + `when`(api.fetchImages(anyInt())).thenReturn(ImagesResponse(emptyList(), ID, emptyList())) + `when`(api.fetchSimilarMovies(anyInt())).thenReturn(TMDbWrapper(emptyList())) + } +} diff --git a/core/domain/src/main/java/com/sample/tmdb/domain/model/CreditModels.kt b/core/domain/src/main/java/com/sample/tmdb/domain/model/CreditModels.kt index c2e8c0d..7b23ae2 100644 --- a/core/domain/src/main/java/com/sample/tmdb/domain/model/CreditModels.kt +++ b/core/domain/src/main/java/com/sample/tmdb/domain/model/CreditModels.kt @@ -10,7 +10,7 @@ class Cast( override val name: String, override val profileUrl: String?, override val gender: Gender, - override val id: Int + override val id: Int, ) : Credit @Parcelize @@ -19,5 +19,5 @@ class Crew( override val name: String, override val profileUrl: String?, override val gender: Gender, - override val id: String -) : Credit \ No newline at end of file + override val id: String, +) : Credit diff --git a/core/domain/src/main/java/com/sample/tmdb/domain/model/DetailWrapper.kt b/core/domain/src/main/java/com/sample/tmdb/domain/model/DetailWrapper.kt index 52da349..713644a 100644 --- a/core/domain/src/main/java/com/sample/tmdb/domain/model/DetailWrapper.kt +++ b/core/domain/src/main/java/com/sample/tmdb/domain/model/DetailWrapper.kt @@ -7,5 +7,5 @@ class DetailWrapper( val crew: List, val details: TMDbItemDetails, val images: List, - val similarItems: List -) \ No newline at end of file + val similarItems: List, +) diff --git a/core/domain/src/main/java/com/sample/tmdb/domain/model/FeedWrapper.kt b/core/domain/src/main/java/com/sample/tmdb/domain/model/FeedWrapper.kt index e13c948..37175e3 100644 --- a/core/domain/src/main/java/com/sample/tmdb/domain/model/FeedWrapper.kt +++ b/core/domain/src/main/java/com/sample/tmdb/domain/model/FeedWrapper.kt @@ -6,5 +6,5 @@ import com.sample.tmdb.common.model.TMDbItem class FeedWrapper( val feeds: List, @StringRes val sortTypeResourceId: Int, - val sortType: SortType -) \ No newline at end of file + val sortType: SortType, +) diff --git a/core/domain/src/main/java/com/sample/tmdb/domain/model/Person.kt b/core/domain/src/main/java/com/sample/tmdb/domain/model/Person.kt index 836da6b..2cd01a9 100644 --- a/core/domain/src/main/java/com/sample/tmdb/domain/model/Person.kt +++ b/core/domain/src/main/java/com/sample/tmdb/domain/model/Person.kt @@ -7,5 +7,5 @@ class Person( val name: String, val biography: String, val placeOfBirth: String?, - val profilePath: String? -) \ No newline at end of file + val profilePath: String?, +) diff --git a/core/domain/src/main/java/com/sample/tmdb/domain/model/SortType.kt b/core/domain/src/main/java/com/sample/tmdb/domain/model/SortType.kt index 4dda05f..1b57cd8 100644 --- a/core/domain/src/main/java/com/sample/tmdb/domain/model/SortType.kt +++ b/core/domain/src/main/java/com/sample/tmdb/domain/model/SortType.kt @@ -6,5 +6,5 @@ enum class SortType { NOW_PLAYING, UPCOMING, HIGHEST_RATED, - DISCOVER -} \ No newline at end of file + DISCOVER, +} diff --git a/core/domain/src/main/java/com/sample/tmdb/domain/model/TMDbDetailsModels.kt b/core/domain/src/main/java/com/sample/tmdb/domain/model/TMDbDetailsModels.kt index 5314f4e..5b4ecfb 100644 --- a/core/domain/src/main/java/com/sample/tmdb/domain/model/TMDbDetailsModels.kt +++ b/core/domain/src/main/java/com/sample/tmdb/domain/model/TMDbDetailsModels.kt @@ -35,7 +35,7 @@ data class MovieDetails( override val tagline: String, override val title: String, override val voteAverage: Double, - override val voteCount: Int + override val voteCount: Int, ) : TMDbItemDetails data class TvDetails( @@ -59,10 +59,10 @@ data class TvDetails( data class Genre( val id: Int, - val name: String? + val name: String?, ) data class SpokenLanguage( val iso6391: String, - val name: String -) \ No newline at end of file + val name: String, +) diff --git a/core/domain/src/main/java/com/sample/tmdb/domain/model/TMDbImage.kt b/core/domain/src/main/java/com/sample/tmdb/domain/model/TMDbImage.kt index f40e3f0..ae27f89 100644 --- a/core/domain/src/main/java/com/sample/tmdb/domain/model/TMDbImage.kt +++ b/core/domain/src/main/java/com/sample/tmdb/domain/model/TMDbImage.kt @@ -1,3 +1,6 @@ package com.sample.tmdb.domain.model -data class TMDbImage(val url: String, val voteCount: Int) \ No newline at end of file +data class TMDbImage( + val url: String, + val voteCount: Int, +) diff --git a/core/domain/src/main/java/com/sample/tmdb/domain/model/TMDbModels.kt b/core/domain/src/main/java/com/sample/tmdb/domain/model/TMDbModels.kt index 735d17b..922ae23 100644 --- a/core/domain/src/main/java/com/sample/tmdb/domain/model/TMDbModels.kt +++ b/core/domain/src/main/java/com/sample/tmdb/domain/model/TMDbModels.kt @@ -12,7 +12,7 @@ data class Movie( override val backdropUrl: String?, override val name: String, override val voteAverage: Double, - override val voteCount: Int + override val voteCount: Int, ) : TMDbItem @Parcelize @@ -24,5 +24,5 @@ data class TVShow( override val backdropUrl: String?, override val name: String, override val voteAverage: Double, - override val voteCount: Int -) : TMDbItem \ No newline at end of file + override val voteCount: Int, +) : TMDbItem diff --git a/core/domain/src/main/java/com/sample/tmdb/domain/paging/BasePagingSource.kt b/core/domain/src/main/java/com/sample/tmdb/domain/paging/BasePagingSource.kt index 747505f..1eec882 100644 --- a/core/domain/src/main/java/com/sample/tmdb/domain/paging/BasePagingSource.kt +++ b/core/domain/src/main/java/com/sample/tmdb/domain/paging/BasePagingSource.kt @@ -10,8 +10,9 @@ import java.io.IOException private const val STARTING_PAGE_INDEX = 1 -abstract class BasePagingSource(private val context: Context) : PagingSource() { - +abstract class BasePagingSource( + private val context: Context, +) : PagingSource() { protected abstract suspend fun fetchItems(page: Int): List override suspend fun load(params: LoadParams): LoadResult { @@ -21,7 +22,7 @@ abstract class BasePagingSource(private val context: Context) : Pa LoadResult.Page( data = response, prevKey = if (page == STARTING_PAGE_INDEX) null else page - 1, - nextKey = if (response.isEmpty()) null else page + 1 + nextKey = if (response.isEmpty()) null else page + 1, ) } catch (exception: IOException) { LoadResult.Error(TMDbException(context.getString(R.string.failed_loading_msg))) @@ -30,10 +31,9 @@ abstract class BasePagingSource(private val context: Context) : Pa } } - override fun getRefreshKey(state: PagingState): Int? { - return state.anchorPosition?.let { + override fun getRefreshKey(state: PagingState): Int? = + state.anchorPosition?.let { state.closestPageToPosition(it)?.prevKey?.plus(1) ?: state.closestPageToPosition(it)?.nextKey?.minus(1) } - } -} \ No newline at end of file +} diff --git a/core/domain/src/main/java/com/sample/tmdb/domain/repository/BaseDetailRepository.kt b/core/domain/src/main/java/com/sample/tmdb/domain/repository/BaseDetailRepository.kt index 37a4afb..4aae857 100644 --- a/core/domain/src/main/java/com/sample/tmdb/domain/repository/BaseDetailRepository.kt +++ b/core/domain/src/main/java/com/sample/tmdb/domain/repository/BaseDetailRepository.kt @@ -15,9 +15,8 @@ import kotlinx.coroutines.coroutineScope abstract class BaseDetailRepository( context: Context, - ioDispatcher: CoroutineDispatcher + ioDispatcher: CoroutineDispatcher, ) : BaseRepository(context, ioDispatcher) { - protected abstract suspend fun getDetails(id: Int): T protected abstract suspend fun getCredit(id: Int): Pair, List> @@ -47,7 +46,7 @@ abstract class BaseDetailRepository( creditWrapper.second, details, images, - similarItems + similarItems, ) } -} \ No newline at end of file +} diff --git a/core/domain/src/main/java/com/sample/tmdb/domain/repository/BaseFeedRepository.kt b/core/domain/src/main/java/com/sample/tmdb/domain/repository/BaseFeedRepository.kt index d8a4935..bb11c18 100644 --- a/core/domain/src/main/java/com/sample/tmdb/domain/repository/BaseFeedRepository.kt +++ b/core/domain/src/main/java/com/sample/tmdb/domain/repository/BaseFeedRepository.kt @@ -13,9 +13,8 @@ import kotlinx.coroutines.coroutineScope abstract class BaseFeedRepository( context: Context, - ioDispatcher: CoroutineDispatcher + ioDispatcher: CoroutineDispatcher, ) : BaseRepository>(context, ioDispatcher) { - protected abstract suspend fun popularItems(): List protected abstract suspend fun nowPlayingItems(): List @@ -51,33 +50,33 @@ abstract class BaseFeedRepository( FeedWrapper( trendingDeferred.await(), R.string.text_trending, - SortType.TRENDING + SortType.TRENDING, ), FeedWrapper( popularDeferred.await(), R.string.text_popular, - SortType.MOST_POPULAR + SortType.MOST_POPULAR, ), FeedWrapper( nowPlayingDeferred.await(), getNowPlayingResId(), - SortType.NOW_PLAYING + SortType.NOW_PLAYING, ), FeedWrapper( discoverDeferred.await(), R.string.text_discover, - SortType.DISCOVER + SortType.DISCOVER, ), FeedWrapper( latestDeferred.await(), getLatestResId(), - SortType.UPCOMING + SortType.UPCOMING, ), FeedWrapper( topRatedDeferred.await(), R.string.text_highest_rate, - SortType.HIGHEST_RATED - ) + SortType.HIGHEST_RATED, + ), ) } -} \ No newline at end of file +} diff --git a/core/domain/src/main/java/com/sample/tmdb/domain/repository/BasePagingRepository.kt b/core/domain/src/main/java/com/sample/tmdb/domain/repository/BasePagingRepository.kt index be944ad..5a2417a 100644 --- a/core/domain/src/main/java/com/sample/tmdb/domain/repository/BasePagingRepository.kt +++ b/core/domain/src/main/java/com/sample/tmdb/domain/repository/BasePagingRepository.kt @@ -8,15 +8,21 @@ import com.sample.tmdb.domain.paging.BasePagingSource import kotlinx.coroutines.flow.Flow abstract class BasePagingRepository { + protected abstract fun pagingSource( + query: String?, + id: Int?, + ): BasePagingSource - protected abstract fun pagingSource(query: String?, id: Int?): BasePagingSource - - fun fetchResultStream(query: String? = null, id: Int? = null): Flow> = Pager( - config = PagingConfig(pageSize = NETWORK_PAGE_SIZE), - pagingSourceFactory = { pagingSource(query, id) } - ).flow + fun fetchResultStream( + query: String? = null, + id: Int? = null, + ): Flow> = + Pager( + config = PagingConfig(pageSize = NETWORK_PAGE_SIZE), + pagingSourceFactory = { pagingSource(query, id) }, + ).flow companion object { private const val NETWORK_PAGE_SIZE = 20 } -} \ No newline at end of file +} diff --git a/core/domain/src/main/java/com/sample/tmdb/domain/repository/BookmarkDetailsRepository.kt b/core/domain/src/main/java/com/sample/tmdb/domain/repository/BookmarkDetailsRepository.kt index 208e902..2f128cd 100644 --- a/core/domain/src/main/java/com/sample/tmdb/domain/repository/BookmarkDetailsRepository.kt +++ b/core/domain/src/main/java/com/sample/tmdb/domain/repository/BookmarkDetailsRepository.kt @@ -2,11 +2,10 @@ package com.sample.tmdb.domain.repository import com.sample.tmdb.common.model.TMDbItem -interface BookmarkDetailsRepository { - +interface BookmarkDetailsRepository { suspend fun addBookmark(item: T) suspend fun deleteBookmark(id: Int) suspend fun isBookmarked(id: Int): Boolean -} \ No newline at end of file +} diff --git a/core/domain/src/main/java/com/sample/tmdb/domain/utils/Annotations.kt b/core/domain/src/main/java/com/sample/tmdb/domain/utils/Annotations.kt index 03e3332..a8f4c65 100644 --- a/core/domain/src/main/java/com/sample/tmdb/domain/utils/Annotations.kt +++ b/core/domain/src/main/java/com/sample/tmdb/domain/utils/Annotations.kt @@ -32,4 +32,4 @@ annotation class Search @Retention(AnnotationRetention.BINARY) @Qualifier -annotation class Similar \ No newline at end of file +annotation class Similar diff --git a/features/feature-bookmark/src/androidTest/java/com/sample/tmdb/bookmark/BookmarkScreenTest.kt b/features/feature-bookmark/src/androidTest/java/com/sample/tmdb/bookmark/BookmarkScreenTest.kt index ccaf1ff..6056a78 100644 --- a/features/feature-bookmark/src/androidTest/java/com/sample/tmdb/bookmark/BookmarkScreenTest.kt +++ b/features/feature-bookmark/src/androidTest/java/com/sample/tmdb/bookmark/BookmarkScreenTest.kt @@ -10,7 +10,6 @@ import org.junit.Rule import org.junit.Test class BookmarkScreenTest { - @get:Rule val composeTestRule = createAndroidComposeRule() @@ -18,9 +17,21 @@ class BookmarkScreenTest { fun bookmarkScreenTest() { with(composeTestRule) { setContent { - TabContent(items = listOf(Movie(1, "overview", "releaseDate", - null, null, "name", 5.0,5))) { - + TabContent( + items = + listOf( + Movie( + 1, + "overview", + "releaseDate", + null, + null, + "name", + 5.0, + 5, + ), + ), + ) { } } onNodeWithText("releaseDate").assertIsDisplayed() @@ -40,4 +51,4 @@ class BookmarkScreenTest { onNodeWithText(activity.getString(R.string.empty_list, activity.getString(R.string.movie))) } } -} \ No newline at end of file +} diff --git a/features/feature-bookmark/src/main/java/com/sample/tmdb/bookmark/BookmarkMovieViewModel.kt b/features/feature-bookmark/src/main/java/com/sample/tmdb/bookmark/BookmarkMovieViewModel.kt index 9519b08..016b0b0 100644 --- a/features/feature-bookmark/src/main/java/com/sample/tmdb/bookmark/BookmarkMovieViewModel.kt +++ b/features/feature-bookmark/src/main/java/com/sample/tmdb/bookmark/BookmarkMovieViewModel.kt @@ -7,6 +7,8 @@ import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class BookmarkMovieViewModel @Inject constructor( - repository: @JvmSuppressWildcards BaseRepository> -) : BaseViewModel>(repository) \ No newline at end of file +class BookmarkMovieViewModel + @Inject + constructor( + repository: @JvmSuppressWildcards BaseRepository>, + ) : BaseViewModel>(repository) diff --git a/features/feature-bookmark/src/main/java/com/sample/tmdb/bookmark/BookmarkScreen.kt b/features/feature-bookmark/src/main/java/com/sample/tmdb/bookmark/BookmarkScreen.kt index e49d678..408347f 100644 --- a/features/feature-bookmark/src/main/java/com/sample/tmdb/bookmark/BookmarkScreen.kt +++ b/features/feature-bookmark/src/main/java/com/sample/tmdb/bookmark/BookmarkScreen.kt @@ -42,8 +42,8 @@ import com.sample.tmdb.common.model.TMDbItem import com.sample.tmdb.common.ui.Content import com.sample.tmdb.common.ui.Dimens.TMDb_16_dp import com.sample.tmdb.common.ui.Dimens.TMDb_8_dp -import com.sample.tmdb.common.ui.component.TMDbDivider import com.sample.tmdb.common.ui.component.TMDbContent +import com.sample.tmdb.common.ui.component.TMDbDivider import com.sample.tmdb.common.ui.theme.AlphaNearOpaque import com.sample.tmdb.common.utils.toDp import kotlinx.coroutines.CoroutineScope @@ -54,23 +54,25 @@ import com.sample.tmdb.common.R as R1 @Composable fun BookmarkScreen( navController: NavController, - coroutineScope: CoroutineScope = rememberCoroutineScope() + coroutineScope: CoroutineScope = rememberCoroutineScope(), ) { val tabs = remember { MediaTab.values() } - val pagerState = rememberPagerState(pageCount = { - tabs.size - }) + val pagerState = + rememberPagerState(pageCount = { + tabs.size + }) val selectedTabIndex = pagerState.currentPage Column( - modifier = Modifier - .fillMaxSize() - .statusBarsPadding() + modifier = + Modifier + .fillMaxSize() + .statusBarsPadding(), ) { TabRow( selectedTabIndex = selectedTabIndex, backgroundColor = MaterialTheme.colors.background.copy(alpha = AlphaNearOpaque), - divider = { TMDbDivider() } + divider = { TMDbDivider() }, ) { tabs.forEach { tab -> val index = tab.ordinal @@ -81,9 +83,9 @@ fun BookmarkScreen( text = { Text( text = stringResource(id = tab.titleResourceId), - style = MaterialTheme.typography.subtitle1 + style = MaterialTheme.typography.subtitle1, ) - } + }, ) } } @@ -91,7 +93,7 @@ fun BookmarkScreen( HorizontalPager( modifier = Modifier.fillMaxSize(), state = pagerState, - verticalAlignment = Alignment.Top + verticalAlignment = Alignment.Top, ) { page -> when (page) { MediaTab.Movies.ordinal -> MoviesTabContent(navController) @@ -104,24 +106,24 @@ fun BookmarkScreen( @Composable private fun MoviesTabContent( navController: NavController, - viewModel: BookmarkMovieViewModel = hiltViewModel() + viewModel: BookmarkMovieViewModel = hiltViewModel(), ) { TabContent( viewModel = viewModel, onClick = { navController.navigate("${MainDestinations.TMDB_MOVIE_DETAIL_ROUTE}/${it.id}") }, - textResourceId = R1.string.movies + textResourceId = R1.string.movies, ) } @Composable private fun TVShowsTabContent( navController: NavController, - viewModel: BookmarkTVShowViewModel = hiltViewModel() + viewModel: BookmarkTVShowViewModel = hiltViewModel(), ) { TabContent( viewModel = viewModel, onClick = { navController.navigate("${MainDestinations.TMDB_TV_SHOW_DETAIL_ROUTE}/${it.id}") }, - textResourceId = R1.string.tv_series + textResourceId = R1.string.tv_series, ) } @@ -129,7 +131,7 @@ private fun TVShowsTabContent( private fun TabContent( viewModel: BaseViewModel>, onClick: (TMDbItem) -> Unit, - @StringRes textResourceId: Int + @StringRes textResourceId: Int, ) { viewModel.refresh() Content(viewModel = viewModel) { @@ -142,19 +144,28 @@ private fun TabContent( } @Composable -fun TabContent(items: List, onClick: (TMDbItem) -> Unit) { +fun TabContent( + items: List, + onClick: (TMDbItem) -> Unit, +) { LazyVerticalGrid( columns = GridCells.Adaptive(minSize = 140.dp), - contentPadding = PaddingValues( - start = TMDb_8_dp, - end = TMDb_8_dp, - bottom = WindowInsets.navigationBars.getBottom(LocalDensity.current) - .toDp().dp.plus(56.dp) - ), - horizontalArrangement = Arrangement.spacedBy( - TMDb_8_dp, - Alignment.CenterHorizontally - ), + contentPadding = + PaddingValues( + start = TMDb_8_dp, + end = TMDb_8_dp, + bottom = + WindowInsets.navigationBars + .getBottom(LocalDensity.current) + .toDp() + .dp + .plus(56.dp), + ), + horizontalArrangement = + Arrangement.spacedBy( + TMDb_8_dp, + Alignment.CenterHorizontally, + ), content = { items(items.size) { index -> TMDbContent( @@ -162,36 +173,40 @@ fun TabContent(items: List, onClick: (TMDbItem) -> Unit) { Modifier .height(320.dp) .padding(vertical = TMDb_8_dp), - onClick + onClick, ) } - } + }, ) } @Composable -fun EmptyView(@StringRes textResourceId: Int) { +fun EmptyView( + @StringRes textResourceId: Int, +) { Column( - modifier = Modifier - .fillMaxSize() - .padding(bottom = 64.dp), + modifier = + Modifier + .fillMaxSize() + .padding(bottom = 64.dp), verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { if (isEmptyImageVisible()) { Image( modifier = Modifier.padding(bottom = TMDb_16_dp), painter = painterResource(id = R.drawable.ic_empty), - contentDescription = stringResource(id = R.string.empty_list) + contentDescription = stringResource(id = R.string.empty_list), ) } Text( - text = stringResource( - id = R.string.empty_list, - stringResource(id = textResourceId) - ), + text = + stringResource( + id = R.string.empty_list, + stringResource(id = textResourceId), + ), style = MaterialTheme.typography.subtitle1.copy(fontWeight = FontWeight.SemiBold), - textAlign = TextAlign.Center + textAlign = TextAlign.Center, ) } } @@ -199,10 +214,11 @@ fun EmptyView(@StringRes textResourceId: Int) { @Composable private fun isEmptyImageVisible(): Boolean { val configuration = LocalConfiguration.current - val isPortrait = when (configuration.orientation) { - Configuration.ORIENTATION_PORTRAIT -> true - else -> false - } + val isPortrait = + when (configuration.orientation) { + Configuration.ORIENTATION_PORTRAIT -> true + else -> false + } if (isPortrait) { return true } else { @@ -214,7 +230,9 @@ private fun isEmptyImageVisible(): Boolean { return false } -enum class MediaTab(@StringRes val titleResourceId: Int) { +enum class MediaTab( + @StringRes val titleResourceId: Int, +) { Movies(titleResourceId = R.string.movie), - TvShows(titleResourceId = R.string.tv_show) -} \ No newline at end of file + TvShows(titleResourceId = R.string.tv_show), +} diff --git a/features/feature-bookmark/src/main/java/com/sample/tmdb/bookmark/BookmarkTVShowViewModel.kt b/features/feature-bookmark/src/main/java/com/sample/tmdb/bookmark/BookmarkTVShowViewModel.kt index 7c33d7a..5863a89 100644 --- a/features/feature-bookmark/src/main/java/com/sample/tmdb/bookmark/BookmarkTVShowViewModel.kt +++ b/features/feature-bookmark/src/main/java/com/sample/tmdb/bookmark/BookmarkTVShowViewModel.kt @@ -7,6 +7,8 @@ import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class BookmarkTVShowViewModel @Inject constructor( - repository: @JvmSuppressWildcards BaseRepository> -) : BaseViewModel>(repository) \ No newline at end of file +class BookmarkTVShowViewModel + @Inject + constructor( + repository: @JvmSuppressWildcards BaseRepository>, + ) : BaseViewModel>(repository) diff --git a/features/feature-credit/src/androidTest/java/com/sample/tmdb/credit/CreditScreenTest.kt b/features/feature-credit/src/androidTest/java/com/sample/tmdb/credit/CreditScreenTest.kt index 46720b5..c617aa4 100644 --- a/features/feature-credit/src/androidTest/java/com/sample/tmdb/credit/CreditScreenTest.kt +++ b/features/feature-credit/src/androidTest/java/com/sample/tmdb/credit/CreditScreenTest.kt @@ -13,7 +13,6 @@ import org.junit.Test import com.sample.tmdb.common.R as commonR class CreditScreenTest { - @get:Rule val composeTestRule = createAndroidComposeRule() @@ -24,7 +23,7 @@ class CreditScreenTest { CreditScreen( R.string.biography, rememberNavController(), - listOf(Cast("role", "name", null, Gender.MALE, 1)) + listOf(Cast("role", "name", null, Gender.MALE, 1)), ) } onNodeWithText(activity.getString(R.string.biography)).assertIsDisplayed() @@ -34,9 +33,9 @@ class CreditScreenTest { activity.getString( commonR.string.person_content_description, "name", - "role" - ) + "role", + ), ).assertIsDisplayed() } } -} \ No newline at end of file +} diff --git a/features/feature-credit/src/androidTest/java/com/sample/tmdb/credit/PersonScreenTest.kt b/features/feature-credit/src/androidTest/java/com/sample/tmdb/credit/PersonScreenTest.kt index b630d4f..b9d8246 100644 --- a/features/feature-credit/src/androidTest/java/com/sample/tmdb/credit/PersonScreenTest.kt +++ b/features/feature-credit/src/androidTest/java/com/sample/tmdb/credit/PersonScreenTest.kt @@ -15,7 +15,6 @@ import org.mockito.ArgumentMatchers.anyInt import com.sample.tmdb.common.R as commonR class PersonScreenTest { - @get:Rule val composeTestRule = createAndroidComposeRule() @@ -23,9 +22,17 @@ class PersonScreenTest { fun personScreenTest() { with(composeTestRule) { setContent { - PersonScreen(Person("birthDay","deathDay", anyInt(), "name", - "biography", "PlaceOfBirth", null)) { - + PersonScreen( + Person( + "birthDay", + "deathDay", + anyInt(), + "name", + "biography", + "PlaceOfBirth", + null, + ), + ) { } } onNodeWithText("name").assertIsDisplayed() @@ -64,8 +71,17 @@ class PersonScreenTest { val titleHeight = mutableStateOf(0.dp) with(composeTestRule) { setContent { - Title(Person("birthDay","deathDay", anyInt(), "name", - "biography", "PlaceOfBirth", null), titleHeight + Title( + Person( + "birthDay", + "deathDay", + anyInt(), + "name", + "biography", + "PlaceOfBirth", + null, + ), + titleHeight, ) { 0 } } onNodeWithText("name").assertExists() @@ -74,4 +90,4 @@ class PersonScreenTest { onNodeWithText(activity.getString(R.string.from, "PlaceOfBirth")).assertExists() } } -} \ No newline at end of file +} diff --git a/features/feature-credit/src/main/java/com/sample/tmdb/credit/CreditScreen.kt b/features/feature-credit/src/main/java/com/sample/tmdb/credit/CreditScreen.kt index 362f9ce..4715aef 100644 --- a/features/feature-credit/src/main/java/com/sample/tmdb/credit/CreditScreen.kt +++ b/features/feature-credit/src/main/java/com/sample/tmdb/credit/CreditScreen.kt @@ -29,35 +29,39 @@ import com.sample.tmdb.common.utils.toDp fun CreditScreen( @StringRes resourceId: Int, navController: NavController, - items: List + items: List, ) { LazyVerticalGrid( columns = GridCells.Adaptive(TMDb_120_dp), - contentPadding = PaddingValues( - start = TMDb_6_dp, - end = TMDb_6_dp, - top = TMDb_6_dp, - bottom = WindowInsets.navigationBars.getBottom(LocalDensity.current) - .toDp().dp.plus( - TMDb_8_dp - ) - ), + contentPadding = + PaddingValues( + start = TMDb_6_dp, + end = TMDb_6_dp, + top = TMDb_6_dp, + bottom = + WindowInsets.navigationBars + .getBottom(LocalDensity.current) + .toDp() + .dp + .plus( + TMDb_8_dp, + ), + ), content = { - item(span = { GridItemSpan(maxLineSpan) }) { Spacer( Modifier.windowInsetsTopHeight( - WindowInsets.statusBars.add(WindowInsets(top = 56.dp)) - ) + WindowInsets.statusBars.add(WindowInsets(top = 56.dp)), + ), ) } items(items.size) { index -> PersonCard(person = items[index], navController = navController) } - } + }, ) DestinationBar(title = stringResource(resourceId), upPress = { navController.navigateUp() }) -} \ No newline at end of file +} diff --git a/features/feature-credit/src/main/java/com/sample/tmdb/credit/PersonScreen.kt b/features/feature-credit/src/main/java/com/sample/tmdb/credit/PersonScreen.kt index add5296..2e388d1 100644 --- a/features/feature-credit/src/main/java/com/sample/tmdb/credit/PersonScreen.kt +++ b/features/feature-credit/src/main/java/com/sample/tmdb/credit/PersonScreen.kt @@ -79,7 +79,7 @@ private val HzPadding = Modifier.padding(horizontal = 24.dp) @Composable fun PersonScreen( upPress: () -> Unit, - viewModel: PersonViewModel = hiltViewModel() + viewModel: PersonViewModel = hiltViewModel(), ) { Content(viewModel = viewModel) { PersonScreen(it, upPress) @@ -87,10 +87,13 @@ fun PersonScreen( } @Composable -fun PersonScreen(person: Person, upPress: () -> Unit) { +fun PersonScreen( + person: Person, + upPress: () -> Unit, +) { val titleHeight = remember { mutableStateOf(0.dp) } Box( - modifier = Modifier.fillMaxSize() + modifier = Modifier.fillMaxSize(), ) { val scroll = rememberScrollState(0) Header() @@ -106,10 +109,11 @@ fun PersonScreen(person: Person, upPress: () -> Unit) { @Composable private fun Header() { Spacer( - modifier = Modifier - .height(280.dp) - .fillMaxWidth() - .background(Brush.horizontalGradient(Tornado)) + modifier = + Modifier + .height(280.dp) + .fillMaxWidth() + .background(Brush.horizontalGradient(Tornado)), ) } @@ -117,19 +121,20 @@ private fun Header() { fun Up(upPress: () -> Unit) { IconButton( onClick = upPress, - modifier = Modifier - .statusBarsPadding() - .padding(horizontal = TMDb_16_dp, vertical = 10.dp) - .size(36.dp) - .background( - color = Neutral8.copy(alpha = 0.32f), - shape = CircleShape - ) + modifier = + Modifier + .statusBarsPadding() + .padding(horizontal = TMDb_16_dp, vertical = 10.dp) + .size(36.dp) + .background( + color = Neutral8.copy(alpha = 0.32f), + shape = CircleShape, + ), ) { Icon( imageVector = Icons.AutoMirrored.Filled.ArrowBack, tint = MaterialTheme.colors.onSurface, - contentDescription = stringResource(R1.string.back) + contentDescription = stringResource(R1.string.back), ) } } @@ -138,17 +143,18 @@ fun Up(upPress: () -> Unit) { fun Body( biography: String, titleHeight: MutableState, - scroll: ScrollState + scroll: ScrollState, ) { Column { Spacer( - modifier = Modifier - .fillMaxWidth() - .statusBarsPadding() - .height(MinTitleOffset) + modifier = + Modifier + .fillMaxWidth() + .statusBarsPadding() + .height(MinTitleOffset), ) Column( - modifier = Modifier.verticalScroll(scroll) + modifier = Modifier.verticalScroll(scroll), ) { Spacer(Modifier.height(GradientScroll)) Surface(Modifier.fillMaxWidth()) { @@ -161,26 +167,28 @@ fun Body( text = stringResource(R.string.biography), style = MaterialTheme.typography.overline, color = MaterialTheme.colors.onSurface, - modifier = HzPadding + modifier = HzPadding, ) Spacer(Modifier.height(TMDb_16_dp)) Text( text = biography, - style = MaterialTheme.typography.body2.copy( - letterSpacing = 2.sp, - lineHeight = 30.sp, - fontFamily = FontFamily.SansSerif - ), + style = + MaterialTheme.typography.body2.copy( + letterSpacing = 2.sp, + lineHeight = 30.sp, + fontFamily = FontFamily.SansSerif, + ), color = MaterialTheme.colors.onSurface, overflow = TextOverflow.Ellipsis, - modifier = HzPadding + modifier = HzPadding, ) } Spacer( - modifier = Modifier - .padding(bottom = BottomBarHeight) - .navigationBarsPadding() - .height(TMDb_8_dp) + modifier = + Modifier + .padding(bottom = BottomBarHeight) + .navigationBarsPadding() + .height(TMDb_8_dp), ) } } @@ -192,34 +200,34 @@ fun Body( fun Title( person: Person, titleHeight: MutableState, - scrollProvider: () -> Int + scrollProvider: () -> Int, ) { val localDestiny = LocalDensity.current - val maxOffset = with(localDestiny) { - (if (person.profilePath == null) MediumTitleOffset else MaxTitleOffset).toPx() - } + val maxOffset = + with(localDestiny) { + (if (person.profilePath == null) MediumTitleOffset else MaxTitleOffset).toPx() + } val minOffset = with(localDestiny) { MinTitleOffset.toPx() } Column( verticalArrangement = Arrangement.Bottom, - modifier = Modifier - .onGloballyPositioned { coordinates -> - with(localDestiny) { titleHeight.value = coordinates.size.height.toDp() } - } - .heightIn(min = titleHeight.value) - .statusBarsPadding() - .offset { - val scroll = scrollProvider() - val offset = (maxOffset - scroll).coerceAtLeast(minOffset) - IntOffset(x = 0, y = offset.toInt()) - } - .background(color = MaterialTheme.colors.surface) + modifier = + Modifier + .onGloballyPositioned { coordinates -> + with(localDestiny) { titleHeight.value = coordinates.size.height.toDp() } + }.heightIn(min = titleHeight.value) + .statusBarsPadding() + .offset { + val scroll = scrollProvider() + val offset = (maxOffset - scroll).coerceAtLeast(minOffset) + IntOffset(x = 0, y = offset.toInt()) + }.background(color = MaterialTheme.colors.surface), ) { Spacer(Modifier.height(TMDb_16_dp)) Text( text = person.name, style = MaterialTheme.typography.h4, color = MaterialTheme.colors.onSurface, - modifier = HzPadding + modifier = HzPadding, ) Spacer(Modifier.height(TMDb_2_dp)) person.placeOfBirth?.let { @@ -227,7 +235,7 @@ fun Title( text = stringResource(id = R.string.from, it), style = MaterialTheme.typography.subtitle1.copy(fontWeight = FontWeight.SemiBold), color = MaterialTheme.colors.onSurface, - modifier = HzPadding + modifier = HzPadding, ) Spacer(Modifier.height(TMDb_4_dp)) } @@ -236,7 +244,7 @@ fun Title( text = stringResource(id = R.string.born, it), style = MaterialTheme.typography.subtitle2.copy(fontWeight = FontWeight.Normal), color = MaterialTheme.colors.onSurface, - modifier = HzPadding + modifier = HzPadding, ) Spacer(Modifier.height(TMDb_4_dp)) } @@ -245,7 +253,7 @@ fun Title( text = stringResource(id = R.string.death, it), style = MaterialTheme.typography.subtitle2.copy(fontWeight = FontWeight.Normal), color = MaterialTheme.colors.onSurface, - modifier = HzPadding + modifier = HzPadding, ) Spacer(Modifier.height(TMDb_4_dp)) } @@ -257,7 +265,7 @@ fun Title( @Composable private fun Image( imageUrl: String, - scrollProvider: () -> Int + scrollProvider: () -> Int, ) { val collapseRange = with(LocalDensity.current) { (MaxTitleOffset - MinTitleOffset).toPx() } val collapseFractionProvider = { @@ -266,17 +274,19 @@ private fun Image( CollapsingImageLayout( collapseFractionProvider = collapseFractionProvider, - modifier = HzPadding.then(Modifier.statusBarsPadding()) + modifier = HzPadding.then(Modifier.statusBarsPadding()), ) { - val request = ImageRequest.Builder(LocalContext.current) - .data(imageUrl) - .transformations(CircleTopCropTransformation()) - .build() + val request = + ImageRequest + .Builder(LocalContext.current) + .data(imageUrl) + .transformations(CircleTopCropTransformation()) + .build() val painter = rememberAsyncImagePainter(model = request) Image( painter = painter, contentDescription = null, - contentScale = ContentScale.FillHeight + contentScale = ContentScale.FillHeight, ) } } @@ -285,11 +295,11 @@ private fun Image( private fun CollapsingImageLayout( collapseFractionProvider: () -> Float, modifier: Modifier = Modifier, - content: @Composable () -> Unit + content: @Composable () -> Unit, ) { Layout( modifier = modifier, - content = content + content = content, ) { measurables, constraints -> check(measurables.size == 1) @@ -298,24 +308,26 @@ private fun CollapsingImageLayout( val imageMaxSize = min(ExpandedImageSize.roundToPx(), constraints.maxWidth).toDp() val imageMinSize = max(CollapsedImageSize.roundToPx(), constraints.minWidth).toDp() val imageWidth = lerp(imageMaxSize, imageMinSize, collapseFraction).roundToPx() - val imagePlaceable = measurables[0].measure( - Constraints.fixed( - imageWidth, - imageWidth + val imagePlaceable = + measurables[0].measure( + Constraints.fixed( + imageWidth, + imageWidth, + ), ) - ) val imageY = lerp(MinTitleOffset, MinImageOffset, collapseFraction).roundToPx() - val imageX = lerp( - ((constraints.maxWidth - imageWidth) / 2).toDp(), // centered when expanded - (constraints.maxWidth - imageWidth).toDp(), // right aligned when collapsed - collapseFraction - ).roundToPx() + val imageX = + lerp( + ((constraints.maxWidth - imageWidth) / 2).toDp(), // centered when expanded + (constraints.maxWidth - imageWidth).toDp(), // right aligned when collapsed + collapseFraction, + ).roundToPx() layout( width = constraints.maxWidth, - height = imageY + imageWidth + height = imageY + imageWidth, ) { imagePlaceable.placeRelative(imageX, imageY) } } -} \ No newline at end of file +} diff --git a/features/feature-credit/src/main/java/com/sample/tmdb/credit/PersonViewModel.kt b/features/feature-credit/src/main/java/com/sample/tmdb/credit/PersonViewModel.kt index a1cda44..c841aea 100644 --- a/features/feature-credit/src/main/java/com/sample/tmdb/credit/PersonViewModel.kt +++ b/features/feature-credit/src/main/java/com/sample/tmdb/credit/PersonViewModel.kt @@ -1,18 +1,20 @@ package com.sample.tmdb.credit import androidx.lifecycle.SavedStateHandle -import com.sample.tmdb.common.base.TMDbViewModel -import com.sample.tmdb.common.base.BaseRepository import com.sample.tmdb.common.MainDestinations +import com.sample.tmdb.common.base.BaseRepository +import com.sample.tmdb.common.base.TMDbViewModel import com.sample.tmdb.domain.model.Person import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class PersonViewModel @Inject constructor( - repository: BaseRepository, - savedStateHandle: SavedStateHandle -) : TMDbViewModel( - repository, - savedStateHandle[MainDestinations.TMDB_PERSON_KEY] -) \ No newline at end of file +class PersonViewModel + @Inject + constructor( + repository: BaseRepository, + savedStateHandle: SavedStateHandle, + ) : TMDbViewModel( + repository, + savedStateHandle[MainDestinations.TMDB_PERSON_KEY], + ) diff --git a/features/feature-credit/src/test/java/com/sample/tmdb/credit/PersonViewModelTest.kt b/features/feature-credit/src/test/java/com/sample/tmdb/credit/PersonViewModelTest.kt index a13931e..9cbb351 100644 --- a/features/feature-credit/src/test/java/com/sample/tmdb/credit/PersonViewModelTest.kt +++ b/features/feature-credit/src/test/java/com/sample/tmdb/credit/PersonViewModelTest.kt @@ -13,7 +13,6 @@ import org.junit.Rule import org.junit.Test class PersonViewModelTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() @@ -45,4 +44,4 @@ class PersonViewModelTest { viewModel = PersonViewModel(repository, savedStateHandle) assertEquals(Resource.Error(""), viewModel.stateFlow.value) } -} \ No newline at end of file +} diff --git a/features/feature-detail/src/androidTest/java/com/sample/tmdb/detail/DetailScreenTest.kt b/features/feature-detail/src/androidTest/java/com/sample/tmdb/detail/DetailScreenTest.kt index a365dc0..67f18c0 100644 --- a/features/feature-detail/src/androidTest/java/com/sample/tmdb/detail/DetailScreenTest.kt +++ b/features/feature-detail/src/androidTest/java/com/sample/tmdb/detail/DetailScreenTest.kt @@ -18,7 +18,6 @@ import org.mockito.ArgumentMatchers.anyString import com.sample.tmdb.common.R as commonR class DetailScreenTest { - @get:Rule val composeTestRule = createAndroidComposeRule() @@ -53,8 +52,8 @@ class DetailScreenTest { anyString(), anyString(), 1.0, - 1 - ) + 1, + ), ) } onNodeWithText(activity.getString(R.string.release_date)).assertIsDisplayed() @@ -109,4 +108,4 @@ class DetailScreenTest { onNodeWithContentDescription(activity.getString(R.string.un_favorite)).assertIsDisplayed() } } -} \ No newline at end of file +} diff --git a/features/feature-detail/src/main/java/com/sample/tmdb/detail/BaseDetailViewModel.kt b/features/feature-detail/src/main/java/com/sample/tmdb/detail/BaseDetailViewModel.kt index b45bef0..fe92389 100644 --- a/features/feature-detail/src/main/java/com/sample/tmdb/detail/BaseDetailViewModel.kt +++ b/features/feature-detail/src/main/java/com/sample/tmdb/detail/BaseDetailViewModel.kt @@ -2,8 +2,8 @@ package com.sample.tmdb.detail import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope -import com.sample.tmdb.common.base.TMDbViewModel import com.sample.tmdb.common.MainDestinations +import com.sample.tmdb.common.base.TMDbViewModel import com.sample.tmdb.common.model.TMDbItem import com.sample.tmdb.domain.model.DetailWrapper import com.sample.tmdb.domain.model.TMDbItemDetails @@ -16,26 +16,29 @@ import kotlinx.coroutines.launch open class BaseDetailViewModel( private val bookmarkRepository: BookmarkDetailsRepository, repository: BaseDetailRepository, - savedStateHandle: SavedStateHandle + savedStateHandle: SavedStateHandle, ) : TMDbViewModel( - repository, - savedStateHandle[MainDestinations.TMDB_ID_KEY] -) { + repository, + savedStateHandle[MainDestinations.TMDB_ID_KEY], + ) { private val _isBookmarked = MutableStateFlow(false) val isBookmarked: StateFlow get() = _isBookmarked - fun addBookmark(item: R) = viewModelScope.launch { - bookmarkRepository.addBookmark(item) - isBookmarked(item.id) - } + fun addBookmark(item: R) = + viewModelScope.launch { + bookmarkRepository.addBookmark(item) + isBookmarked(item.id) + } - fun removeBookmark(id: Int) = viewModelScope.launch { - bookmarkRepository.deleteBookmark(id) - isBookmarked(id) - } + fun removeBookmark(id: Int) = + viewModelScope.launch { + bookmarkRepository.deleteBookmark(id) + isBookmarked(id) + } - fun isBookmarked(id: Int) = viewModelScope.launch { - _isBookmarked.emit(bookmarkRepository.isBookmarked(id)) - } -} \ No newline at end of file + fun isBookmarked(id: Int) = + viewModelScope.launch { + _isBookmarked.emit(bookmarkRepository.isBookmarked(id)) + } +} diff --git a/features/feature-detail/src/main/java/com/sample/tmdb/detail/DetailScreen.kt b/features/feature-detail/src/main/java/com/sample/tmdb/detail/DetailScreen.kt index e13a79a..a2be04d 100644 --- a/features/feature-detail/src/main/java/com/sample/tmdb/detail/DetailScreen.kt +++ b/features/feature-detail/src/main/java/com/sample/tmdb/detail/DetailScreen.kt @@ -135,13 +135,13 @@ import com.sample.tmdb.common.R as R1 @Composable fun MovieDetailScreen( navController: NavController, - viewModel: MovieDetailViewModel = hiltViewModel() + viewModel: MovieDetailViewModel = hiltViewModel(), ) { DetailScreen( viewModel = viewModel, navController = navController, onTMDbItemSelected = { navController.navigate("${MainDestinations.TMDB_MOVIE_DETAIL_ROUTE}/${it.id}") }, - onAllSimilarSelected = { navController.navigate("${MainDestinations.TMDB_SIMILAR_MOVIES_ROUTE}/$it") } + onAllSimilarSelected = { navController.navigate("${MainDestinations.TMDB_SIMILAR_MOVIES_ROUTE}/$it") }, ) { details -> Movie( id = details.id, @@ -151,7 +151,7 @@ fun MovieDetailScreen( posterUrl = details.posterPath, name = details.title, voteAverage = details.voteAverage, - voteCount = details.voteCount + voteCount = details.voteCount, ) } } @@ -159,13 +159,13 @@ fun MovieDetailScreen( @Composable fun TVShowDetailScreen( navController: NavController, - viewModel: TVShowDetailViewModel = hiltViewModel() + viewModel: TVShowDetailViewModel = hiltViewModel(), ) { DetailScreen( viewModel = viewModel, navController = navController, onTMDbItemSelected = { navController.navigate("${MainDestinations.TMDB_TV_SHOW_DETAIL_ROUTE}/${it.id}") }, - onAllSimilarSelected = { navController.navigate("${MainDestinations.TMDB_SIMILAR_TV_SHOW_ROUTE}/$it") } + onAllSimilarSelected = { navController.navigate("${MainDestinations.TMDB_SIMILAR_TV_SHOW_ROUTE}/$it") }, ) { details -> TVShow( id = details.id, @@ -175,7 +175,7 @@ fun TVShowDetailScreen( posterUrl = details.posterPath, name = details.title, voteAverage = details.voteAverage, - voteCount = details.voteCount + voteCount = details.voteCount, ) } } @@ -186,7 +186,7 @@ private fun DetailScreen( navController: NavController, onTMDbItemSelected: (TMDbItem) -> Unit, onAllSimilarSelected: (Int) -> Unit, - getBookmarkedItem: (TMDbItemDetails) -> E + getBookmarkedItem: (TMDbItemDetails) -> E, ) { DetailScreen( viewModel = viewModel, @@ -195,9 +195,9 @@ private fun DetailScreen( navController.navigate( "${MainDestinations.TMDB_IMAGES_ROUTE}/${ Uri.encode( - gson.toJson(images, object : TypeToken>() {}.type) + gson.toJson(images, object : TypeToken>() {}.type), ) - }/$index" + }/$index", ) }, onTMDbItemSelected = onTMDbItemSelected, @@ -210,7 +210,7 @@ private fun DetailScreen( viewModel.addBookmark(getBookmarkedItem.invoke(details)) } } - } + }, ) } @@ -224,7 +224,7 @@ fun DetailScreen( onImagesSelected: (List, Int) -> Unit, onTMDbItemSelected: (TMDbItem) -> Unit, onAllSimilarSelected: (Int) -> Unit, - fab: @Composable (MutableState, Boolean, TMDbItemDetails) -> Unit + fab: @Composable (MutableState, Boolean, TMDbItemDetails) -> Unit, ) { // Visibility for FAB val isFabVisible = rememberSaveable { mutableStateOf(true) } @@ -233,21 +233,25 @@ fun DetailScreen( Content(viewModel = viewModel) { viewModel.isBookmarked(it.details.id) // Nested scroll for control FAB - val nestedScrollConnection = remember { - object : NestedScrollConnection { - override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { - // Hide FAB - if (available.y < -1) { - isFabVisible.value = false - } - // Show FAB - if (available.y > 1) { - isFabVisible.value = true + val nestedScrollConnection = + remember { + object : NestedScrollConnection { + override fun onPreScroll( + available: Offset, + source: NestedScrollSource, + ): Offset { + // Hide FAB + if (available.y < -1) { + isFabVisible.value = false + } + // Show FAB + if (available.y > 1) { + isFabVisible.value = true + } + return Offset.Zero } - return Offset.Zero } } - } CompositionLocalProvider( localVibrantColor provides vibrantColor, ) { @@ -260,14 +264,14 @@ fun DetailScreen( it.details, ) }, - floatingActionButtonPosition = FabPosition.End + floatingActionButtonPosition = FabPosition.End, ) { contentPadding -> ConstraintLayout( Modifier .fillMaxSize() .background(MaterialTheme.colors.surface) .verticalScroll(rememberScrollState()) - .padding(contentPadding) + .padding(contentPadding), ) { val (appbar, backdrop, poster, title, originalTitle, genres, specs, rateStars, tagline, overview) = createRefs() val (castSection, crewSection, imagesSection, similarSection, space) = createRefs() @@ -277,7 +281,7 @@ fun DetailScreen( it.details.posterPath?.let { posterPath -> GetVibrantColorFromPoster( posterPath, - localVibrantColor.current + localVibrantColor.current, ) } it.details.backdropPath?.let { backdropPath -> @@ -286,16 +290,18 @@ fun DetailScreen( it.details.title, Modifier.constrainAs(backdrop) { top.linkTo(parent.top) - }) + }, + ) } val posterWidth = 160.dp AppBar( homepage = it.details.homepage, upPress = { navController.navigateUp() }, - modifier = Modifier - .requiredWidth(posterWidth * 2.2f) - .constrainAs(appbar) { centerTo(poster) } - .offset(y = TMDb_24_dp) + modifier = + Modifier + .requiredWidth(posterWidth * 2.2f) + .constrainAs(appbar) { centerTo(poster) } + .offset(y = TMDb_24_dp), ) Poster( it.details.posterPath, @@ -307,99 +313,111 @@ fun DetailScreen( .constrainAs(poster) { centerAround(backdrop.bottom) linkTo(startGuideline, endGuideline) - } + }, ) Text( text = it.details.title, - style = MaterialTheme.typography.subtitle1.copy( - fontSize = 26.sp, - letterSpacing = 3.sp, - fontWeight = FontWeight.SemiBold, - textAlign = TextAlign.Center - ), - modifier = Modifier - .padding(horizontal = TMDb_16_dp) - .constrainAs(title) { - top.linkTo(poster.bottom, 8.dp) - linkTo(startGuideline, endGuideline) - } + style = + MaterialTheme.typography.subtitle1.copy( + fontSize = 26.sp, + letterSpacing = 3.sp, + fontWeight = FontWeight.SemiBold, + textAlign = TextAlign.Center, + ), + modifier = + Modifier + .padding(horizontal = TMDb_16_dp) + .constrainAs(title) { + top.linkTo(poster.bottom, 8.dp) + linkTo(startGuideline, endGuideline) + }, ) if (it.details.title != it.details.originalTitle) { Text( text = "(${it.details.originalTitle})", - style = MaterialTheme.typography.subtitle2.copy( - fontStyle = FontStyle.Italic, - letterSpacing = 2.sp - ), - modifier = Modifier - .padding(horizontal = TMDb_16_dp) - .constrainAs(originalTitle) { - top.linkTo(title.bottom) - linkTo(startGuideline, endGuideline) - } + style = + MaterialTheme.typography.subtitle2.copy( + fontStyle = FontStyle.Italic, + letterSpacing = 2.sp, + ), + modifier = + Modifier + .padding(horizontal = TMDb_16_dp) + .constrainAs(originalTitle) { + top.linkTo(title.bottom) + linkTo(startGuideline, endGuideline) + }, ) } else { Spacer( - modifier = Modifier.constrainAs(originalTitle) { - top.linkTo(title.bottom) - linkTo(startGuideline, endGuideline) - } + modifier = + Modifier.constrainAs(originalTitle) { + top.linkTo(title.bottom) + linkTo(startGuideline, endGuideline) + }, ) } GenreChips( it.details.genres.take(4), - modifier = Modifier.constrainAs(genres) { - top.linkTo(originalTitle.bottom, 16.dp) - linkTo(startGuideline, endGuideline) - } + modifier = + Modifier.constrainAs(genres) { + top.linkTo(originalTitle.bottom, 16.dp) + linkTo(startGuideline, endGuideline) + }, ) TMDbItemFields( it.details, - modifier = Modifier.constrainAs(specs) { - top.linkTo(genres.bottom, 12.dp) - linkTo(startGuideline, endGuideline) - } + modifier = + Modifier.constrainAs(specs) { + top.linkTo(genres.bottom, 12.dp) + linkTo(startGuideline, endGuideline) + }, ) RateStars( it.details.voteAverage, - modifier = Modifier.constrainAs(rateStars) { - top.linkTo(specs.bottom, 12.dp) - linkTo(startGuideline, endGuideline) - } + modifier = + Modifier.constrainAs(rateStars) { + top.linkTo(specs.bottom, 12.dp) + linkTo(startGuideline, endGuideline) + }, ) Text( text = it.details.tagline, color = localVibrantColor.current.value, - style = MaterialTheme.typography.body1.copy( - letterSpacing = 2.sp, - lineHeight = 24.sp, - fontFamily = FontFamily.Serif, - fontWeight = FontWeight.Bold - ), - modifier = Modifier - .padding(horizontal = TMDb_16_dp) - .constrainAs(tagline) { - top.linkTo(rateStars.bottom, 32.dp) - } + style = + MaterialTheme.typography.body1.copy( + letterSpacing = 2.sp, + lineHeight = 24.sp, + fontFamily = FontFamily.Serif, + fontWeight = FontWeight.Bold, + ), + modifier = + Modifier + .padding(horizontal = TMDb_16_dp) + .constrainAs(tagline) { + top.linkTo(rateStars.bottom, 32.dp) + }, ) Text( text = it.details.overview, - style = MaterialTheme.typography.body2.copy( - letterSpacing = 2.sp, - lineHeight = 30.sp, - fontFamily = FontFamily.SansSerif - ), - modifier = Modifier - .padding(horizontal = TMDb_16_dp) - .constrainAs(overview) { - top.linkTo(tagline.bottom, 8.dp) - linkTo(startGuideline, endGuideline) - } + style = + MaterialTheme.typography.body2.copy( + letterSpacing = 2.sp, + lineHeight = 30.sp, + fontFamily = FontFamily.SansSerif, + ), + modifier = + Modifier + .padding(horizontal = TMDb_16_dp) + .constrainAs(overview) { + top.linkTo(tagline.bottom, 8.dp) + linkTo(startGuideline, endGuideline) + }, ) TMDbDetailItemSection( items = it.cast, @@ -408,22 +426,23 @@ fun DetailScreen( PersonCard( item, navController, - Modifier.width(140.dp) + Modifier.width(140.dp), ) }, onSeeAllClicked = { cast -> navController.navigate( "${MainDestinations.TMDB_CAST_ROUTE}/${ Uri.encode( - gson.toJson(cast, object : TypeToken>() {}.type) + gson.toJson(cast, object : TypeToken>() {}.type), ) - }" + }", ) }, - modifier = Modifier.constrainAs(castSection) { - top.linkTo(overview.bottom, 16.dp) - linkTo(startGuideline, endGuideline) - } + modifier = + Modifier.constrainAs(castSection) { + top.linkTo(overview.bottom, 16.dp) + linkTo(startGuideline, endGuideline) + }, ) TMDbDetailItemSection( @@ -433,22 +452,23 @@ fun DetailScreen( PersonCard( item, navController, - Modifier.width(140.dp) + Modifier.width(140.dp), ) }, onSeeAllClicked = { crew -> navController.navigate( "${MainDestinations.TMDB_CREW_ROUTE}/${ Uri.encode( - gson.toJson(crew, object : TypeToken>() {}.type) + gson.toJson(crew, object : TypeToken>() {}.type), ) - }" + }", ) }, - modifier = Modifier.constrainAs(crewSection) { - top.linkTo(castSection.bottom, 16.dp) - linkTo(startGuideline, endGuideline) - } + modifier = + Modifier.constrainAs(crewSection) { + top.linkTo(castSection.bottom, 16.dp) + linkTo(startGuideline, endGuideline) + }, ) TMDbDetailItemSection( @@ -460,10 +480,11 @@ fun DetailScreen( item, ) { onImagesSelected.invoke(it.images, index) } }, - modifier = Modifier.constrainAs(imagesSection) { - top.linkTo(crewSection.bottom, 16.dp) - linkTo(startGuideline, endGuideline) - }, + modifier = + Modifier.constrainAs(imagesSection) { + top.linkTo(crewSection.bottom, 16.dp) + linkTo(startGuideline, endGuideline) + }, ) TMDbDetailItemSection( @@ -474,18 +495,20 @@ fun DetailScreen( TMDbCard(item, onTMDbItemSelected) }, showSize = false, - modifier = Modifier.constrainAs(similarSection) { - top.linkTo(imagesSection.bottom, 16.dp) - linkTo(startGuideline, endGuideline) - }, + modifier = + Modifier.constrainAs(similarSection) { + top.linkTo(imagesSection.bottom, 16.dp) + linkTo(startGuideline, endGuideline) + }, ) Spacer( - modifier = Modifier - .windowInsetsBottomHeight(WindowInsets.navigationBars) - .constrainAs(space) { - top.linkTo(similarSection.bottom) - } + modifier = + Modifier + .windowInsetsBottomHeight(WindowInsets.navigationBars) + .constrainAs(space) { + top.linkTo(similarSection.bottom) + }, ) } } @@ -496,47 +519,62 @@ fun DetailScreen( @Composable fun GetVibrantColorFromPoster( posterUrl: String, - color: Animatable + color: Animatable, ) { val context = LocalContext.current LaunchedEffect(posterUrl) { val loader = ImageLoader(context) - val request = ImageRequest.Builder(context) - .data(posterUrl) - .size(128, 128) - .allowHardware(false) - .build() - - val bitmap = (loader.execute(request) as? SuccessResult)?.drawable?.toBitmap() - ?: return@LaunchedEffect + val request = + ImageRequest + .Builder(context) + .data(posterUrl) + .size(128, 128) + .allowHardware(false) + .build() + + val bitmap = + (loader.execute(request) as? SuccessResult)?.drawable?.toBitmap() + ?: return@LaunchedEffect val vibrantColor = Palette.from(bitmap).generate().getVibrantColor(color.value.toArgb()) color.animateTo(Color(vibrantColor), tween(400)) } } @Composable -private fun Backdrop(backdropUrl: String, tmdbItemName: String, modifier: Modifier) { +private fun Backdrop( + backdropUrl: String, + tmdbItemName: String, + modifier: Modifier, +) { Card( elevation = TMDb_16_dp, shape = BottomArcShape(arcHeight = 120.dpToPx()), backgroundColor = localVibrantColor.current.value.copy(alpha = 0.1f), - modifier = modifier.height(360.dp) + modifier = modifier.height(360.dp), ) { AsyncImage( - model = ImageRequest.Builder(LocalContext.current).data(data = backdropUrl) - .crossfade(1500).build(), + model = + ImageRequest + .Builder(LocalContext.current) + .data(data = backdropUrl) + .crossfade(1500) + .build(), contentScale = ContentScale.FillHeight, contentDescription = tmdbItemName, - modifier = modifier.fillMaxWidth() + modifier = modifier.fillMaxWidth(), ) } } @Composable -private fun AppBar(modifier: Modifier, homepage: String?, upPress: () -> Unit) { +private fun AppBar( + modifier: Modifier, + homepage: String?, + upPress: () -> Unit, +) { Row( horizontalArrangement = Arrangement.SpaceBetween, - modifier = modifier + modifier = modifier, ) { val vibrantColor = localVibrantColor.current.value val scaleModifier = Modifier.scale(1.1f) @@ -545,7 +583,7 @@ private fun AppBar(modifier: Modifier, homepage: String?, upPress: () -> Unit) { Icons.AutoMirrored.Filled.ArrowBack, contentDescription = stringResource(id = R1.string.back), tint = vibrantColor, - modifier = scaleModifier + modifier = scaleModifier, ) } if (!homepage.isNullOrBlank()) { @@ -555,57 +593,67 @@ private fun AppBar(modifier: Modifier, homepage: String?, upPress: () -> Unit) { Icons.AutoMirrored.Rounded.OpenInNew, contentDescription = stringResource(id = R.string.open), tint = vibrantColor, - modifier = scaleModifier + modifier = scaleModifier, ) } } } } -private val springAnimation = spring( - dampingRatio = Spring.DampingRatioMediumBouncy, - stiffness = Spring.StiffnessLow, - visibilityThreshold = 0.001f -) +private val springAnimation = + spring( + dampingRatio = Spring.DampingRatioMediumBouncy, + stiffness = Spring.StiffnessLow, + visibilityThreshold = 0.001f, + ) @OptIn(ExperimentalMaterialApi::class) @Composable -fun Poster(posterUrl: String?, tmdbItemName: String, modifier: Modifier = Modifier) { +fun Poster( + posterUrl: String?, + tmdbItemName: String, + modifier: Modifier = Modifier, +) { val isScaled = remember { mutableStateOf(false) } val scale = animateFloatAsState( targetValue = if (isScaled.value) 2.2f else 1f, - animationSpec = springAnimation, label = "" + animationSpec = springAnimation, + label = "", ).value Card( elevation = TMDb_24_dp, shape = RoundedCornerShape(TMDb_8_dp), modifier = modifier.scale(scale), - onClick = { isScaled.value = !isScaled.value } + onClick = { isScaled.value = !isScaled.value }, ) { AsyncImage( model = posterUrl, contentDescription = tmdbItemName, - contentScale = ContentScale.FillHeight + contentScale = ContentScale.FillHeight, ) } } @Composable -private fun GenreChips(genres: List, modifier: Modifier) { +private fun GenreChips( + genres: List, + modifier: Modifier, +) { Row( modifier .horizontalScroll(rememberScrollState()) - .padding(horizontal = TMDb_16_dp) + .padding(horizontal = TMDb_16_dp), ) { genres.map(Genre::name).forEachIndexed { index, name -> Text( text = name.orEmpty(), style = MaterialTheme.typography.subtitle1.copy(letterSpacing = 2.sp), - modifier = Modifier - .border(1.25.dp, localVibrantColor.current.value, RoundedCornerShape(50)) - .padding(horizontal = TMDb_6_dp, vertical = 3.dp) + modifier = + Modifier + .border(1.25.dp, localVibrantColor.current.value, RoundedCornerShape(50)) + .padding(horizontal = TMDb_6_dp, vertical = 3.dp), ) if (index != genres.lastIndex) { @@ -616,60 +664,72 @@ private fun GenreChips(genres: List, modifier: Modifier) { } @Composable -fun TMDbItemFields(tmdbItemDetails: TMDbItemDetails, modifier: Modifier = Modifier) { +fun TMDbItemFields( + tmdbItemDetails: TMDbItemDetails, + modifier: Modifier = Modifier, +) { Row(horizontalArrangement = Arrangement.spacedBy(20.dp), modifier = modifier) { val context = LocalContext.current tmdbItemDetails.releaseDate?.let { TMDbItemField( context.getString(R.string.release_date), - it + it, ) } TMDbItemField( context.getString(R.string.vote_average), - tmdbItemDetails.voteAverage.toString() + tmdbItemDetails.voteAverage.toString(), ) TMDbItemField(context.getString(R.string.votes), tmdbItemDetails.voteCount.toString()) } } @Composable -fun TMDbItemField(name: String, value: String) { +fun TMDbItemField( + name: String, + value: String, +) { Column { Text( text = name, - style = MaterialTheme.typography.subtitle2.copy( - fontSize = 13.sp, - letterSpacing = 1.sp - ), - modifier = Modifier.align(Alignment.CenterHorizontally) + style = + MaterialTheme.typography.subtitle2.copy( + fontSize = 13.sp, + letterSpacing = 1.sp, + ), + modifier = Modifier.align(Alignment.CenterHorizontally), ) Text( text = value, style = MaterialTheme.typography.subtitle1.copy(fontWeight = FontWeight.SemiBold), - modifier = Modifier - .align(Alignment.CenterHorizontally) - .padding(top = TMDb_4_dp) + modifier = + Modifier + .align(Alignment.CenterHorizontally) + .padding(top = TMDb_4_dp), ) } } @Composable -private fun RateStars(voteAverage: Double, modifier: Modifier) { +private fun RateStars( + voteAverage: Double, + modifier: Modifier, +) { Row(modifier.padding(start = TMDb_4_dp)) { val maxVote = 10 val starCount = 5 repeat(starCount) { starIndex -> val voteStarCount = voteAverage / (maxVote / starCount) - val asset = when { - voteStarCount >= starIndex + 1 -> Icons.Filled.Star - voteStarCount in starIndex.toDouble()..(starIndex + 1).toDouble() -> Icons.AutoMirrored.Filled.StarHalf - else -> Icons.Filled.StarOutline - } + val asset = + when { + voteStarCount >= starIndex + 1 -> Icons.Filled.Star + voteStarCount in starIndex.toDouble()..(starIndex + 1).toDouble() -> Icons.AutoMirrored.Filled.StarHalf + else -> Icons.Filled.StarOutline + } Icon( imageVector = asset, contentDescription = null, - tint = localVibrantColor.current.value + tint = localVibrantColor.current.value, ) Spacer(modifier = Modifier.width(TMDb_4_dp)) } @@ -707,33 +767,35 @@ private fun SectionHeader( @StringRes headerResId: Int, items: List, onAllSelected: (List) -> Unit, - showSize: Boolean + showSize: Boolean, ) { Row( horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = TMDb_16_dp) + modifier = + Modifier + .fillMaxWidth() + .padding(horizontal = TMDb_16_dp), ) { Text( text = stringResource(headerResId), color = localVibrantColor.current.value, - style = MaterialTheme.typography.body1.copy(fontWeight = FontWeight.Bold) + style = MaterialTheme.typography.body1.copy(fontWeight = FontWeight.Bold), ) Row( verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .padding(TMDb_4_dp) - .clickable { - onAllSelected.invoke(items) - } + modifier = + Modifier + .padding(TMDb_4_dp) + .clickable { + onAllSelected.invoke(items) + }, ) { Text( text = getHeaderText(showSize, items), color = localVibrantColor.current.value, style = MaterialTheme.typography.body2.copy(fontWeight = FontWeight.Bold), - modifier = Modifier.padding(end = TMDb_4_dp) + modifier = Modifier.padding(end = TMDb_4_dp), ) Icon( Icons.AutoMirrored.Filled.ArrowForward, @@ -757,21 +819,25 @@ fun ImageSection( shape = RoundedCornerShape(TMDb_12_dp), elevation = TMDb_8_dp, ) { - val request = ImageRequest.Builder(LocalContext.current) - .data(image.url) - .crossfade(true) - .build() - val painter = rememberAsyncImagePainter( - model = request, - placeholder = rememberVectorPainter(Icons.Default.Image), - error = rememberVectorPainter(Icons.Default.BrokenImage), - ) - val (colorFilter, contentScale) = when (painter.state) { - is AsyncImagePainter.State.Error, is AsyncImagePainter.State.Loading -> - ColorFilter.tint(MaterialTheme.colors.imageTint) to ContentScale.Fit + val request = + ImageRequest + .Builder(LocalContext.current) + .data(image.url) + .crossfade(true) + .build() + val painter = + rememberAsyncImagePainter( + model = request, + placeholder = rememberVectorPainter(Icons.Default.Image), + error = rememberVectorPainter(Icons.Default.BrokenImage), + ) + val (colorFilter, contentScale) = + when (painter.state) { + is AsyncImagePainter.State.Error, is AsyncImagePainter.State.Loading -> + ColorFilter.tint(MaterialTheme.colors.imageTint) to ContentScale.Fit - else -> null to ContentScale.Crop - } + else -> null to ContentScale.Crop + } Image( painter = painter, colorFilter = colorFilter, @@ -785,7 +851,7 @@ fun ImageSection( fun ToggleBookmarkFab( isBookmark: Boolean, isVisible: MutableState, - onClick: () -> Unit + onClick: () -> Unit, ) { AnimatedVisibility( visible = isVisible.value, @@ -793,53 +859,72 @@ fun ToggleBookmarkFab( exit = slideOutVertically(targetOffsetY = { it * 2 }), ) { FloatingActionButton( - modifier = Modifier.padding( - bottom = WindowInsets.navigationBars - .getBottom(LocalDensity.current).toDp().dp - ), + modifier = + Modifier.padding( + bottom = + WindowInsets.navigationBars + .getBottom(LocalDensity.current) + .toDp() + .dp, + ), shape = CircleShape, - onClick = onClick + onClick = onClick, ) { Icon( imageVector = Icons.Filled.Favorite, tint = if (isBookmark) Color.Red else MaterialTheme.colors.surface, - contentDescription = if (isBookmark) stringResource(R.string.favorite) else stringResource( - R.string.un_favorite - ) + contentDescription = + if (isBookmark) { + stringResource(R.string.favorite) + } else { + stringResource( + R.string.un_favorite, + ) + }, ) } } } -class BottomArcShape(private val arcHeight: Float) : Shape { +class BottomArcShape( + private val arcHeight: Float, +) : Shape { override fun createOutline( size: Size, layoutDirection: LayoutDirection, - density: Density + density: Density, ): Outline { - val path = Path().apply { - moveTo(size.width, 0f) - lineTo(size.width, size.height) - val arcOffset = arcHeight / 10 - val rect = Rect( - left = 0f - arcOffset, - top = size.height - arcHeight, - right = size.width + arcOffset, - bottom = size.height - ) - arcTo(rect, 0f, 180f, false) - lineTo(0f, 0f) - close() - } + val path = + Path().apply { + moveTo(size.width, 0f) + lineTo(size.width, size.height) + val arcOffset = arcHeight / 10 + val rect = + Rect( + left = 0f - arcOffset, + top = size.height - arcHeight, + right = size.width + arcOffset, + bottom = size.height, + ) + arcTo(rect, 0f, 180f, false) + lineTo(0f, 0f) + close() + } return Outline.Generic(path) } } @Composable -private fun getHeaderText(showSize: Boolean, items: List) = - if (showSize) stringResource( +private fun getHeaderText( + showSize: Boolean, + items: List, +) = if (showSize) { + stringResource( R.string.see_all, - items.size - ) else stringResource(R.string.see_all_items) + items.size, + ) +} else { + stringResource(R.string.see_all_items) +} private val gson = Gson() diff --git a/features/feature-detail/src/main/java/com/sample/tmdb/detail/MovieDetailViewModel.kt b/features/feature-detail/src/main/java/com/sample/tmdb/detail/MovieDetailViewModel.kt index b887564..0702d50 100644 --- a/features/feature-detail/src/main/java/com/sample/tmdb/detail/MovieDetailViewModel.kt +++ b/features/feature-detail/src/main/java/com/sample/tmdb/detail/MovieDetailViewModel.kt @@ -9,8 +9,10 @@ import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class MovieDetailViewModel @Inject constructor( - bookmarkRepository: BookmarkDetailsRepository, - repository: BaseDetailRepository, - savedStateHandle: SavedStateHandle -) : BaseDetailViewModel(bookmarkRepository, repository, savedStateHandle) \ No newline at end of file +class MovieDetailViewModel + @Inject + constructor( + bookmarkRepository: BookmarkDetailsRepository, + repository: BaseDetailRepository, + savedStateHandle: SavedStateHandle, + ) : BaseDetailViewModel(bookmarkRepository, repository, savedStateHandle) diff --git a/features/feature-detail/src/main/java/com/sample/tmdb/detail/TVShowDetailViewModel.kt b/features/feature-detail/src/main/java/com/sample/tmdb/detail/TVShowDetailViewModel.kt index 8fda8f1..5ab4855 100644 --- a/features/feature-detail/src/main/java/com/sample/tmdb/detail/TVShowDetailViewModel.kt +++ b/features/feature-detail/src/main/java/com/sample/tmdb/detail/TVShowDetailViewModel.kt @@ -9,8 +9,10 @@ import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class TVShowDetailViewModel @Inject constructor( - bookmarkRepository: BookmarkDetailsRepository, - repository: BaseDetailRepository, - savedStateHandle: SavedStateHandle -) : BaseDetailViewModel(bookmarkRepository, repository, savedStateHandle) \ No newline at end of file +class TVShowDetailViewModel + @Inject + constructor( + bookmarkRepository: BookmarkDetailsRepository, + repository: BaseDetailRepository, + savedStateHandle: SavedStateHandle, + ) : BaseDetailViewModel(bookmarkRepository, repository, savedStateHandle) diff --git a/features/feature-detail/src/main/java/com/sample/tmdb/detail/utils/StringExt.kt b/features/feature-detail/src/main/java/com/sample/tmdb/detail/utils/StringExt.kt index 63bd4e9..009da4e 100644 --- a/features/feature-detail/src/main/java/com/sample/tmdb/detail/utils/StringExt.kt +++ b/features/feature-detail/src/main/java/com/sample/tmdb/detail/utils/StringExt.kt @@ -7,8 +7,11 @@ import androidx.browser.customtabs.CustomTabsIntent import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb -fun String.openInChromeCustomTab(context: Context, color: Color) { +fun String.openInChromeCustomTab( + context: Context, + color: Color, +) { val schemeParams = CustomTabColorSchemeParams.Builder().setToolbarColor(color.toArgb()).build() val customTabsIntent = CustomTabsIntent.Builder().setDefaultColorSchemeParams(schemeParams).build() customTabsIntent.launchUrl(context, Uri.parse(this)) -} \ No newline at end of file +} diff --git a/features/feature-detail/src/test/java/com/sample/tmdb/detail/BaseDetailViewModelTest.kt b/features/feature-detail/src/test/java/com/sample/tmdb/detail/BaseDetailViewModelTest.kt index f7ae6ae..c4d7873 100644 --- a/features/feature-detail/src/test/java/com/sample/tmdb/detail/BaseDetailViewModelTest.kt +++ b/features/feature-detail/src/test/java/com/sample/tmdb/detail/BaseDetailViewModelTest.kt @@ -19,7 +19,6 @@ import org.junit.Rule import org.junit.Test abstract class BaseDetailViewModelTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() @@ -35,7 +34,7 @@ abstract class BaseDetailViewModelTest { private val detailWrapper = mockk() - protected abstract val tmdbItem : R + protected abstract val tmdbItem: R @Test fun `load details`() { @@ -97,4 +96,4 @@ abstract class BaseDetailViewModelTest { companion object { const val TMDB_ITEM_ID = 1 } -} \ No newline at end of file +} diff --git a/features/feature-detail/src/test/java/com/sample/tmdb/detail/MovieDetailViewModelTest.kt b/features/feature-detail/src/test/java/com/sample/tmdb/detail/MovieDetailViewModelTest.kt index a00cc37..f87a030 100644 --- a/features/feature-detail/src/test/java/com/sample/tmdb/detail/MovieDetailViewModelTest.kt +++ b/features/feature-detail/src/test/java/com/sample/tmdb/detail/MovieDetailViewModelTest.kt @@ -4,14 +4,20 @@ import com.sample.tmdb.domain.model.Movie import com.sample.tmdb.domain.model.MovieDetails class MovieDetailViewModelTest : BaseDetailViewModelTest() { - override fun initViewModel() { super.viewModel = MovieDetailViewModel(bookmarkRepository, repository, savedStateHandle) } override val tmdbItem: Movie - get() = Movie( - TMDB_ITEM_ID, "overview", null, null, null, - "name", 1.0, 1 - ) -} \ No newline at end of file + get() = + Movie( + TMDB_ITEM_ID, + "overview", + null, + null, + null, + "name", + 1.0, + 1, + ) +} diff --git a/features/feature-detail/src/test/java/com/sample/tmdb/detail/TVShowDetailViewModelTest.kt b/features/feature-detail/src/test/java/com/sample/tmdb/detail/TVShowDetailViewModelTest.kt index 127a616..77ff5e0 100644 --- a/features/feature-detail/src/test/java/com/sample/tmdb/detail/TVShowDetailViewModelTest.kt +++ b/features/feature-detail/src/test/java/com/sample/tmdb/detail/TVShowDetailViewModelTest.kt @@ -4,14 +4,20 @@ import com.sample.tmdb.domain.model.TVShow import com.sample.tmdb.domain.model.TvDetails class TVShowDetailViewModelTest : BaseDetailViewModelTest() { - override fun initViewModel() { super.viewModel = TVShowDetailViewModel(bookmarkRepository, repository, savedStateHandle) } override val tmdbItem: TVShow - get() = TVShow( - TMDB_ITEM_ID, "overview", null, null, null, - "name", 1.0, 1 - ) -} \ No newline at end of file + get() = + TVShow( + TMDB_ITEM_ID, + "overview", + null, + null, + null, + "name", + 1.0, + 1, + ) +} diff --git a/features/feature-feed/src/androidTest/java/com/sample/tmdb/feed/FeedScreenTest.kt b/features/feature-feed/src/androidTest/java/com/sample/tmdb/feed/FeedScreenTest.kt index bfb40bb..d232c5c 100644 --- a/features/feature-feed/src/androidTest/java/com/sample/tmdb/feed/FeedScreenTest.kt +++ b/features/feature-feed/src/androidTest/java/com/sample/tmdb/feed/FeedScreenTest.kt @@ -8,7 +8,6 @@ import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithText import androidx.navigation.compose.rememberNavController -import com.sample.tmdb.domain.R as domainR import com.sample.tmdb.domain.model.FeedWrapper import com.sample.tmdb.domain.model.Movie import com.sample.tmdb.domain.model.SortType @@ -17,34 +16,55 @@ import org.junit.Test import org.mockito.ArgumentMatchers.anyDouble import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.anyString +import com.sample.tmdb.domain.R as domainR class FeedScreenTest { - @get:Rule - val composeTestRule = createAndroidComposeRule< ComponentActivity>() + val composeTestRule = createAndroidComposeRule() @Test fun feedCollectionListTest() { with(composeTestRule) { setContent { FeedCollectionList( - navController = rememberNavController(), collection = listOf( - FeedWrapper( - feeds = listOf( - Movie( - anyInt(), anyString(), anyString(), anyString(), - anyString(), "title", anyDouble(), anyInt() - ) - ), domainR.string.text_trending, SortType.TRENDING - ), FeedWrapper( - feeds = listOf( - Movie( - anyInt(), anyString(), anyString(), anyString(), - anyString(), "name", anyDouble(), anyInt() - ) - ), domainR.string.text_popular, SortType.MOST_POPULAR - ) - ) + navController = rememberNavController(), + collection = + listOf( + FeedWrapper( + feeds = + listOf( + Movie( + anyInt(), + anyString(), + anyString(), + anyString(), + anyString(), + "title", + anyDouble(), + anyInt(), + ), + ), + domainR.string.text_trending, + SortType.TRENDING, + ), + FeedWrapper( + feeds = + listOf( + Movie( + anyInt(), + anyString(), + anyString(), + anyString(), + anyString(), + "name", + anyDouble(), + anyInt(), + ), + ), + domainR.string.text_popular, + SortType.MOST_POPULAR, + ), + ), ) {} } onNodeWithText(activity.getString(domainR.string.text_trending)).assertIsDisplayed() @@ -60,30 +80,42 @@ class FeedScreenTest { with(composeTestRule) { setContent { PagerTMDbItemContainer( - item = FeedWrapper( - feeds = listOf( - Movie( - anyInt(), anyString(), anyString(), anyString(), - anyString(), "title", anyDouble(), anyInt() - ) - ), domainR.string.text_popular, SortType.MOST_POPULAR - ), navController = rememberNavController() + item = + FeedWrapper( + feeds = + listOf( + Movie( + anyInt(), + anyString(), + anyString(), + anyString(), + anyString(), + "title", + anyDouble(), + anyInt(), + ), + ), + domainR.string.text_popular, + SortType.MOST_POPULAR, + ), + navController = rememberNavController(), ) {} } onNodeWithText(activity.getString(domainR.string.text_popular)).assertIsDisplayed() onNodeWithText(activity.getString(R.string.more_item)).assertIsDisplayed() onNodeWithText("title").assertIsDisplayed() } - } @Test fun trendingItemTest() { with(composeTestRule) { setContent { - TrendingItem(stringResource(id = domainR.string.text_trending), + TrendingItem( + stringResource(id = domainR.string.text_trending), null, - "2024-12-29", {} + "2024-12-29", + {}, ) } onNodeWithText(activity.getString(domainR.string.text_trending)).assertIsDisplayed() @@ -107,14 +139,21 @@ class FeedScreenTest { with(composeTestRule) { setContent { Feeds( - feeds = listOf( - Movie( - anyInt(), anyString(), anyString(), anyString(), - anyString(), "title", anyDouble(), anyInt() - ) - ), + feeds = + listOf( + Movie( + anyInt(), + anyString(), + anyString(), + anyString(), + anyString(), + "title", + anyDouble(), + anyInt(), + ), + ), onFeedClick = {}, - index = 0 + index = 0, ) } onNodeWithText("title").assertIsDisplayed() @@ -126,15 +165,22 @@ class FeedScreenTest { with(composeTestRule) { setContent { TMDbItem( - tmdbItem = Movie( - anyInt(), anyString(), anyString(), anyString(), - anyString(), "title", anyDouble(), anyInt() - ), + tmdbItem = + Movie( + anyInt(), + anyString(), + anyString(), + anyString(), + anyString(), + "title", + anyDouble(), + anyInt(), + ), onFeedClick = {}, - index = 0 + index = 0, ) } onNodeWithText("title").assertIsDisplayed() } } -} \ No newline at end of file +} diff --git a/features/feature-feed/src/main/java/com/sample/tmdb/feed/FeedScreen.kt b/features/feature-feed/src/main/java/com/sample/tmdb/feed/FeedScreen.kt index 8d50259..e31d366 100644 --- a/features/feature-feed/src/main/java/com/sample/tmdb/feed/FeedScreen.kt +++ b/features/feature-feed/src/main/java/com/sample/tmdb/feed/FeedScreen.kt @@ -68,27 +68,29 @@ import com.sample.tmdb.common.R as R1 @Composable fun MovieFeedScreen( - navController: NavController, viewModel: MovieFeedViewModel = hiltViewModel() + navController: NavController, + viewModel: MovieFeedViewModel = hiltViewModel(), ) { FeedScreen( viewModel = viewModel, navController = navController, onSearchClicked = { navController.navigate(MainDestinations.TMDB_SEARCH_MOVIE_ROUTE) }, onClick = { navController.navigate("${MainDestinations.TMDB_MOVIE_DETAIL_ROUTE}/${it.id}") }, - R1.string.movies + R1.string.movies, ) } @Composable fun TVShowFeedScreen( - navController: NavController, viewModel: TVShowFeedViewModel = hiltViewModel() + navController: NavController, + viewModel: TVShowFeedViewModel = hiltViewModel(), ) { FeedScreen( viewModel = viewModel, navController = navController, onSearchClicked = { navController.navigate(MainDestinations.TMDB_SEARCH_TV_SHOW_ROUTE) }, onClick = { navController.navigate("${MainDestinations.TMDB_TV_SHOW_DETAIL_ROUTE}/${it.id}") }, - R1.string.tv_series + R1.string.tv_series, ) } @@ -98,16 +100,18 @@ private fun FeedScreen( navController: NavController, onSearchClicked: () -> Unit, onClick: (TMDbItem) -> Unit, - @StringRes resourceId: Int - + @StringRes resourceId: Int, ) { Content(viewModel = viewModel) { feeds -> Box { FeedCollectionList(navController, feeds, onClick) DestinationBar( - title = stringResource( - R.string.app_title, stringResource(resourceId) - ), onSearchClicked = onSearchClicked + title = + stringResource( + R.string.app_title, + stringResource(resourceId), + ), + onSearchClicked = onSearchClicked, ) } } @@ -115,14 +119,16 @@ private fun FeedScreen( @Composable fun FeedCollectionList( - navController: NavController, collection: List, onFeedClick: (TMDbItem) -> Unit + navController: NavController, + collection: List, + onFeedClick: (TMDbItem) -> Unit, ) { LazyColumn { item { Spacer( Modifier.windowInsetsTopHeight( - WindowInsets.statusBars.add(WindowInsets(top = 56.dp)) - ) + WindowInsets.statusBars.add(WindowInsets(top = 56.dp)), + ), ) } item { @@ -137,14 +143,14 @@ fun FeedCollectionList( navController = navController, feedCollection = feedCollection, onFeedClick = onFeedClick, - index = index + index = index, ) } item { Spacer( Modifier .navigationBarsPadding() - .windowInsetsTopHeight(WindowInsets(top = 56.dp)) + .windowInsetsTopHeight(WindowInsets(top = 56.dp)), ) } } @@ -153,7 +159,9 @@ fun FeedCollectionList( @OptIn(ExperimentalFoundationApi::class) @Composable fun PagerTMDbItemContainer( - item: FeedWrapper, navController: NavController, onFeedClick: (TMDbItem) -> Unit + item: FeedWrapper, + navController: NavController, + onFeedClick: (TMDbItem) -> Unit, ) { val pagerState = rememberPagerState(pageCount = { item.feeds.size }) @@ -176,32 +184,39 @@ fun PagerTMDbItemContainer( } HorizontalPager( - state = pagerState, contentPadding = PaddingValues(horizontal = Dimens.TMDb_16_dp) + state = pagerState, + contentPadding = PaddingValues(horizontal = Dimens.TMDb_16_dp), ) { page -> with(item.feeds[page]) { - TrendingItem(modifier = Modifier.pagerTransition( - pagerState = pagerState, page = page - ), + TrendingItem( + modifier = + Modifier.pagerTransition( + pagerState = pagerState, + page = page, + ), title = name, imageUrl = backdropUrl, releaseDate = releaseDate, - onClick = { onFeedClick(this) }) + onClick = { onFeedClick(this) }, + ) } } Spacer(modifier = Modifier.height(20.dp)) Row( - modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center, ) { repeat(pagerState.pageCount) { iteration -> val color = if (pagerState.currentPage == iteration) MaterialTheme.colors.primary else Teal200 Box( - modifier = Modifier - .padding(Dimens.TMDb_4_dp) - .clip(CircleShape) - .background(color) - .size(TMDb_6_dp) + modifier = + Modifier + .padding(Dimens.TMDb_4_dp) + .clip(CircleShape) + .background(color) + .size(TMDb_6_dp), ) } } @@ -213,35 +228,36 @@ fun TrendingItem( imageUrl: String?, releaseDate: String?, onClick: () -> Unit, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, ) { Card( - modifier = modifier - .fillMaxWidth() - .height(180.dp) - .clip(RoundedCornerShape(10.dp)) - .then(Modifier.clickable(onClick = onClick)) + modifier = + modifier + .fillMaxWidth() + .height(180.dp) + .clip(RoundedCornerShape(10.dp)) + .then(Modifier.clickable(onClick = onClick)), ) { Box(modifier = Modifier.fillMaxSize()) { - AsyncImage( model = imageUrl, contentDescription = null, modifier = Modifier.fillMaxWidth(), - contentScale = ContentScale.Crop + contentScale = ContentScale.Crop, ) Column( - modifier = Modifier - .padding( - start = TMDb_12_dp, bottom = TMDb_6_dp - ) - .align(Alignment.BottomStart) + modifier = + Modifier + .padding( + start = TMDb_12_dp, + bottom = TMDb_6_dp, + ).align(Alignment.BottomStart), ) { Text( text = title, fontWeight = FontWeight.Bold, - color = Color.White + color = Color.White, ) Spacer(modifier = Modifier.height(TMDb_6_dp)) releaseDate?.let { releaseDate -> @@ -271,9 +287,10 @@ private fun FeedCollection( SortType.MOST_POPULAR -> navController.navigate(MainDestinations.TMDB_POPULAR_MOVIES_ROUTE) SortType.NOW_PLAYING -> navController.navigate(MainDestinations.TMDB_NOW_PLAYING_MOVIES_ROUTE) SortType.UPCOMING -> navController.navigate(MainDestinations.TMDB_UPCOMING_MOVIES_ROUTE) - SortType.HIGHEST_RATED -> navController.navigate( - MainDestinations.TMDB_TOP_RATED_MOVIES_ROUTE - ) + SortType.HIGHEST_RATED -> + navController.navigate( + MainDestinations.TMDB_TOP_RATED_MOVIES_ROUTE, + ) SortType.DISCOVER -> navController.navigate(MainDestinations.TMDB_DISCOVER_MOVIES_ROUTE) else -> throw RuntimeException("Movie feed item Sort type is not valid") @@ -285,9 +302,10 @@ private fun FeedCollection( SortType.MOST_POPULAR -> navController.navigate(MainDestinations.TMDB_POPULAR_TV_SHOW_ROUTE) SortType.NOW_PLAYING -> navController.navigate(MainDestinations.TMDB_AIRING_TODAY_TV_SHOW_ROUTE) SortType.UPCOMING -> navController.navigate(MainDestinations.TMDB_ON_THE_AIR_TV_SHOW_ROUTE) - SortType.HIGHEST_RATED -> navController.navigate( - MainDestinations.TMDB_TOP_RATED_TV_SHOW_ROUTE - ) + SortType.HIGHEST_RATED -> + navController.navigate( + MainDestinations.TMDB_TOP_RATED_TV_SHOW_ROUTE, + ) SortType.DISCOVER -> navController.navigate(MainDestinations.TMDB_DISCOVER_TV_SHOW_ROUTE) else -> throw RuntimeException("TV show feed item Sort type is not valid") @@ -301,29 +319,33 @@ private fun FeedCollection( @Composable fun Header( - @StringRes titleId: Int, onMoreClick: () -> Unit + @StringRes titleId: Int, + onMoreClick: () -> Unit, ) { Row( verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .heightIn(min = 36.dp) - .padding(start = TMDb_12_dp) + modifier = + Modifier + .heightIn(min = 36.dp) + .padding(start = TMDb_12_dp), ) { Text( text = stringResource(id = titleId), maxLines = 1, color = MaterialTheme.colors.onSurface, - modifier = Modifier - .weight(1f) - .wrapContentWidth(Alignment.Start) + modifier = + Modifier + .weight(1f) + .wrapContentWidth(Alignment.Start), ) Text( text = stringResource(R.string.more_item), color = MaterialTheme.colors.onSurface, - modifier = Modifier - .align(Alignment.CenterVertically) - .padding(TMDb_12_dp) - .clickable(onClick = onMoreClick) + modifier = + Modifier + .align(Alignment.CenterVertically) + .padding(TMDb_12_dp) + .clickable(onClick = onMoreClick), ) } } @@ -333,11 +355,11 @@ fun Feeds( feeds: List, onFeedClick: (TMDbItem) -> Unit, index: Int, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, ) { LazyRow( modifier = modifier, - contentPadding = PaddingValues(start = TMDb_2_dp, end = TMDb_2_dp) + contentPadding = PaddingValues(start = TMDb_2_dp, end = TMDb_2_dp), ) { items(feeds) { feed -> TMDbItem(feed, onFeedClick, index) @@ -347,7 +369,9 @@ fun Feeds( @Composable fun TMDbItem( - tmdbItem: TMDbItem, onFeedClick: (TMDbItem) -> Unit, index: Int + tmdbItem: TMDbItem, + onFeedClick: (TMDbItem) -> Unit, + index: Int, ) { val itemWidth: Dp val imageUrl: String? @@ -367,7 +391,9 @@ fun FeedCardPreview() { TmdbPagingComposeTheme { val movie = Movie(1, "", null, null, null, "Movie", 1.0, 2) TMDbItem( - tmdbItem = movie, onFeedClick = {}, 0 + tmdbItem = movie, + onFeedClick = {}, + 0, ) } -} \ No newline at end of file +} diff --git a/features/feature-feed/src/main/java/com/sample/tmdb/feed/MovieFeedViewModel.kt b/features/feature-feed/src/main/java/com/sample/tmdb/feed/MovieFeedViewModel.kt index c04936b..f177794 100644 --- a/features/feature-feed/src/main/java/com/sample/tmdb/feed/MovieFeedViewModel.kt +++ b/features/feature-feed/src/main/java/com/sample/tmdb/feed/MovieFeedViewModel.kt @@ -6,5 +6,8 @@ import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class MovieFeedViewModel @Inject constructor(repository: BaseFeedRepository) : - BaseFeedViewModel(repository) \ No newline at end of file +class MovieFeedViewModel + @Inject + constructor( + repository: BaseFeedRepository, + ) : BaseFeedViewModel(repository) diff --git a/features/feature-feed/src/main/java/com/sample/tmdb/feed/TVShowFeedViewModel.kt b/features/feature-feed/src/main/java/com/sample/tmdb/feed/TVShowFeedViewModel.kt index 79aa175..7fa763f 100644 --- a/features/feature-feed/src/main/java/com/sample/tmdb/feed/TVShowFeedViewModel.kt +++ b/features/feature-feed/src/main/java/com/sample/tmdb/feed/TVShowFeedViewModel.kt @@ -6,5 +6,8 @@ import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class TVShowFeedViewModel @Inject constructor(repository: BaseFeedRepository) : - BaseFeedViewModel(repository) \ No newline at end of file +class TVShowFeedViewModel + @Inject + constructor( + repository: BaseFeedRepository, + ) : BaseFeedViewModel(repository) diff --git a/features/feature-feed/src/main/java/com/sample/tmdb/feed/utils/ModifierExt.kt b/features/feature-feed/src/main/java/com/sample/tmdb/feed/utils/ModifierExt.kt index cb42bb1..a91f5b3 100644 --- a/features/feature-feed/src/main/java/com/sample/tmdb/feed/utils/ModifierExt.kt +++ b/features/feature-feed/src/main/java/com/sample/tmdb/feed/utils/ModifierExt.kt @@ -9,22 +9,27 @@ import kotlin.math.absoluteValue @OptIn(ExperimentalFoundationApi::class) fun Modifier.pagerTransition( - pagerState: PagerState, page: Int + pagerState: PagerState, + page: Int, ) = graphicsLayer { val pageOffset = pagerState.calculatePageOffset(page) lerp( - start = 0.85f, stop = 1f, fraction = 1f - pageOffset.coerceIn(0f, 1f) + start = 0.85f, + stop = 1f, + fraction = 1f - pageOffset.coerceIn(0f, 1f), ).also { scale -> scaleX = scale scaleY = scale } - alpha = lerp( - start = 0.5f, stop = 1f, fraction = 1f - pageOffset.coerceIn(0f, 1f) - ) + alpha = + lerp( + start = 0.5f, + stop = 1f, + fraction = 1f - pageOffset.coerceIn(0f, 1f), + ) } @OptIn(ExperimentalFoundationApi::class) -private fun PagerState.calculatePageOffset(page: Int) = - ((currentPage - page) + currentPageOffsetFraction).absoluteValue \ No newline at end of file +private fun PagerState.calculatePageOffset(page: Int) = ((currentPage - page) + currentPageOffsetFraction).absoluteValue diff --git a/features/feature-feed/src/test/java/com/sample/tmdb/feed/BaseFeedViewModelTest.kt b/features/feature-feed/src/test/java/com/sample/tmdb/feed/BaseFeedViewModelTest.kt index a676b6c..2aaabee 100644 --- a/features/feature-feed/src/test/java/com/sample/tmdb/feed/BaseFeedViewModelTest.kt +++ b/features/feature-feed/src/test/java/com/sample/tmdb/feed/BaseFeedViewModelTest.kt @@ -12,8 +12,7 @@ import kotlinx.coroutines.flow.flowOf import org.junit.Rule import org.junit.Test -abstract class BaseFeedViewModelTest { - +abstract class BaseFeedViewModelTest { @get:Rule val testCoroutineRule = TestCoroutineRule() @@ -43,4 +42,4 @@ abstract class BaseFeedViewModelTest { initViewModel() assertEquals(Resource.Error(""), viewModel.stateFlow.value) } -} \ No newline at end of file +} diff --git a/features/feature-feed/src/test/java/com/sample/tmdb/feed/MovieFeedViewModelTest.kt b/features/feature-feed/src/test/java/com/sample/tmdb/feed/MovieFeedViewModelTest.kt index dce9e1c..ffba06f 100644 --- a/features/feature-feed/src/test/java/com/sample/tmdb/feed/MovieFeedViewModelTest.kt +++ b/features/feature-feed/src/test/java/com/sample/tmdb/feed/MovieFeedViewModelTest.kt @@ -2,9 +2,8 @@ package com.sample.tmdb.feed import com.sample.tmdb.domain.model.Movie -class MovieFeedViewModelTest: BaseFeedViewModelTest() { - +class MovieFeedViewModelTest : BaseFeedViewModelTest() { override fun initViewModel() { super.viewModel = MovieFeedViewModel(repository) } -} \ No newline at end of file +} diff --git a/features/feature-feed/src/test/java/com/sample/tmdb/feed/TVShowFeedViewModelTest.kt b/features/feature-feed/src/test/java/com/sample/tmdb/feed/TVShowFeedViewModelTest.kt index 199ba94..d1557ec 100644 --- a/features/feature-feed/src/test/java/com/sample/tmdb/feed/TVShowFeedViewModelTest.kt +++ b/features/feature-feed/src/test/java/com/sample/tmdb/feed/TVShowFeedViewModelTest.kt @@ -2,9 +2,8 @@ package com.sample.tmdb.feed import com.sample.tmdb.domain.model.TVShow -class TVShowFeedViewModelTest: BaseFeedViewModelTest() { - +class TVShowFeedViewModelTest : BaseFeedViewModelTest() { override fun initViewModel() { super.viewModel = TVShowFeedViewModel(repository) } -} \ No newline at end of file +} diff --git a/features/feature-image/src/androidTest/java/com/sample/tmdb/image/ImageScreenTest.kt b/features/feature-image/src/androidTest/java/com/sample/tmdb/image/ImageScreenTest.kt index 3fd4fe5..af29028 100644 --- a/features/feature-image/src/androidTest/java/com/sample/tmdb/image/ImageScreenTest.kt +++ b/features/feature-image/src/androidTest/java/com/sample/tmdb/image/ImageScreenTest.kt @@ -5,13 +5,12 @@ import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithText +import com.sample.tmdb.common.R import com.sample.tmdb.domain.model.TMDbImage import org.junit.Rule import org.junit.Test -import com.sample.tmdb.common.R class ImageScreenTest { - @get:Rule val composeTestRule = createAndroidComposeRule() @@ -34,4 +33,4 @@ class ImageScreenTest { onNodeWithContentDescription(activity.getString(R.string.poster_content_description)) } } -} \ No newline at end of file +} diff --git a/features/feature-image/src/main/java/com/sample/tmdb/image/ImageScreen.kt b/features/feature-image/src/main/java/com/sample/tmdb/image/ImageScreen.kt index 4fa0836..d6f9a06 100644 --- a/features/feature-image/src/main/java/com/sample/tmdb/image/ImageScreen.kt +++ b/features/feature-image/src/main/java/com/sample/tmdb/image/ImageScreen.kt @@ -42,13 +42,17 @@ import com.sample.tmdb.common.R as R1 @OptIn(ExperimentalFoundationApi::class) @Composable -fun ImagesScreen(images: List, initialPage: Int) { +fun ImagesScreen( + images: List, + initialPage: Int, +) { if (images.isEmpty() || initialPage !in images.indices) return - val pagerState = rememberPagerState( - initialPage = initialPage, - initialPageOffsetFraction = 0f - ) { images.size } + val pagerState = + rememberPagerState( + initialPage = initialPage, + initialPageOffsetFraction = 0f, + ) { images.size } Box { HorizontalPager(state = pagerState, key = { images[it].url + it }, beyondBoundsPageCount = 4) { Poster(images[it]) @@ -67,16 +71,17 @@ fun Poster(image: TMDbImage) { .padding(TMDb_12_dp) .shadow(TMDb_16_dp, RoundedCornerShape(TMDb_12_dp)) .animateContentSize() - .wrapContentSize() + .wrapContentSize(), ) { Box { Image( painter = rememberAsyncImagePainter(image.url), contentDescription = null, - modifier = Modifier - .align(Alignment.Center) - .fillMaxWidth() - .wrapContentHeight(), + modifier = + Modifier + .align(Alignment.Center) + .fillMaxWidth() + .wrapContentHeight(), contentScale = ContentScale.FillWidth, ) VoteCount(image.voteCount) @@ -91,10 +96,11 @@ fun BlurImage(url: String) { model = url, contentDescription = stringResource(id = R1.string.poster_content_description), contentScale = ContentScale.FillHeight, - modifier = Modifier - .fillMaxSize() - .background(MaterialTheme.colors.surface) - .blur(TMDb_16_dp), + modifier = + Modifier + .fillMaxSize() + .background(MaterialTheme.colors.surface) + .blur(TMDb_16_dp), ) } @@ -102,14 +108,14 @@ fun BlurImage(url: String) { private fun BoxScope.VoteCount(voteCount: Int) { Row( verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .wrapContentSize() - .align(Alignment.BottomStart) - .background( - color = MaterialTheme.colors.surface.copy(alpha = 0.3f), - shape = RoundedCornerShape(bottomStart = TMDb_12_dp, topEnd = TMDb_12_dp), - ) - .padding(TMDb_4_dp), + modifier = + Modifier + .wrapContentSize() + .align(Alignment.BottomStart) + .background( + color = MaterialTheme.colors.surface.copy(alpha = 0.3f), + shape = RoundedCornerShape(bottomStart = TMDb_12_dp, topEnd = TMDb_12_dp), + ).padding(TMDb_4_dp), ) { Icon( imageVector = Icons.Filled.Favorite, @@ -122,16 +128,20 @@ private fun BoxScope.VoteCount(voteCount: Int) { } @Composable -private fun BoxScope.Index(position: Int, imageCount: Int) { +private fun BoxScope.Index( + position: Int, + imageCount: Int, +) { Text( text = "$position / $imageCount", style = MaterialTheme.typography.body2, - modifier = Modifier - .align(Alignment.BottomCenter) - .navigationBarsPadding() - .padding(TMDb_4_dp) - .shadow(TMDb_16_dp, RoundedCornerShape(TMDb_16_dp)) - .background(color = MaterialTheme.colors.surface.copy(alpha = 0.3f)) - .padding(horizontal = TMDb_8_dp, vertical = TMDb_2_dp), + modifier = + Modifier + .align(Alignment.BottomCenter) + .navigationBarsPadding() + .padding(TMDb_4_dp) + .shadow(TMDb_16_dp, RoundedCornerShape(TMDb_16_dp)) + .background(color = MaterialTheme.colors.surface.copy(alpha = 0.3f)) + .padding(horizontal = TMDb_8_dp, vertical = TMDb_2_dp), ) -} \ No newline at end of file +} diff --git a/features/feature-paging/src/androidTest/java/com/sample/tmdb/paging/search/SearchBarTest.kt b/features/feature-paging/src/androidTest/java/com/sample/tmdb/paging/search/SearchBarTest.kt index 507c79c..609dbd1 100644 --- a/features/feature-paging/src/androidTest/java/com/sample/tmdb/paging/search/SearchBarTest.kt +++ b/features/feature-paging/src/androidTest/java/com/sample/tmdb/paging/search/SearchBarTest.kt @@ -6,12 +6,11 @@ import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithText import com.sample.tmdb.common.R -import com.sample.tmdb.paging.R as pagingR import org.junit.Rule import org.junit.Test +import com.sample.tmdb.paging.R as pagingR class SearchBarTest { - @get:Rule val composeTestRule = createAndroidComposeRule() @@ -25,7 +24,8 @@ class SearchBarTest { onQueryChange = {}, searchFocused = true, onSearchFocusChange = {}, - onClearQuery = {}) + onClearQuery = {}, + ) } onNodeWithText("query").assertIsDisplayed() } @@ -41,13 +41,14 @@ class SearchBarTest { onQueryChange = {}, searchFocused = true, onSearchFocusChange = {}, - onClearQuery = {}) + onClearQuery = {}, + ) } onNodeWithText( activity.getString( pagingR.string.search, - activity.getString(R.string.movies) - ) + activity.getString(R.string.movies), + ), ).assertIsDisplayed() } } @@ -62,9 +63,9 @@ class SearchBarTest { onNodeWithText( activity.getString( pagingR.string.search, - activity.getString(R.string.movies) - ) + activity.getString(R.string.movies), + ), ).assertIsDisplayed() } } -} \ No newline at end of file +} diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/BasePagingViewModel.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/BasePagingViewModel.kt index b0e9940..6f52e3a 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/BasePagingViewModel.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/BasePagingViewModel.kt @@ -6,6 +6,5 @@ import com.sample.tmdb.common.model.TMDbItem import kotlinx.coroutines.flow.Flow abstract class BasePagingViewModel : ViewModel() { - abstract val pagingDataFlow: Flow> -} \ No newline at end of file +} diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/PagingScreen.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/PagingScreen.kt index 36f88b3..d7ff892 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/PagingScreen.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/PagingScreen.kt @@ -54,9 +54,11 @@ fun PagingScreen( val message = (lazyTMDbItems.loadState.refresh as? LoadState.Error)?.error?.message ?: return - ErrorScreen(message = message, + ErrorScreen( + message = message, modifier = Modifier.fillMaxSize(), - refresh = { lazyTMDbItems.retry() }) + refresh = { lazyTMDbItems.retry() }, + ) } else -> { @@ -71,83 +73,97 @@ fun PagingScreen( } } - @Composable private fun LazyTMDbItemGrid( lazyTMDbItems: LazyPagingItems, onClick: (TMDbItem) -> Unit, ) { - LazyVerticalGrid(columns = GridCells.Adaptive(minSize = 140.dp), contentPadding = PaddingValues( - start = TMDb_8_dp, - end = TMDb_8_dp, - bottom = WindowInsets.navigationBars.getBottom(LocalDensity.current).toDp().dp.plus( - TMDb_8_dp - ) - ), horizontalArrangement = Arrangement.spacedBy( - TMDb_8_dp, Alignment.CenterHorizontally - ), content = { - - item(span = { - GridItemSpan(maxLineSpan) - }) { - Spacer( - Modifier.windowInsetsTopHeight( - WindowInsets.statusBars.add(WindowInsets(top = 56.dp)) - ) - ) - } - - items(lazyTMDbItems.itemCount) { index -> - val tmdbItem = lazyTMDbItems[index] - tmdbItem?.let { - TMDbContent( - it, - Modifier - .height(320.dp) - .padding(vertical = TMDb_8_dp), - onClick + LazyVerticalGrid( + columns = GridCells.Adaptive(minSize = 140.dp), + contentPadding = + PaddingValues( + start = TMDb_8_dp, + end = TMDb_8_dp, + bottom = + WindowInsets.navigationBars.getBottom(LocalDensity.current).toDp().dp.plus( + TMDb_8_dp, + ), + ), + horizontalArrangement = + Arrangement.spacedBy( + TMDb_8_dp, + Alignment.CenterHorizontally, + ), + content = { + item(span = { + GridItemSpan(maxLineSpan) + }) { + Spacer( + Modifier.windowInsetsTopHeight( + WindowInsets.statusBars.add(WindowInsets(top = 56.dp)), + ), ) } - } - when (lazyTMDbItems.loadState.append) { - is LoadState.Loading -> { - item(span = { - GridItemSpan(maxLineSpan) - }) { - LoadingRow(modifier = Modifier.padding(vertical = TMDb_8_dp)) + items(lazyTMDbItems.itemCount) { index -> + val tmdbItem = lazyTMDbItems[index] + tmdbItem?.let { + TMDbContent( + it, + Modifier + .height(320.dp) + .padding(vertical = TMDb_8_dp), + onClick, + ) } } - is LoadState.Error -> { - val message = (lazyTMDbItems.loadState.append as? LoadState.Error)?.error?.message - ?: return@LazyVerticalGrid + when (lazyTMDbItems.loadState.append) { + is LoadState.Loading -> { + item(span = { + GridItemSpan(maxLineSpan) + }) { + LoadingRow(modifier = Modifier.padding(vertical = TMDb_8_dp)) + } + } + + is LoadState.Error -> { + val message = + (lazyTMDbItems.loadState.append as? LoadState.Error)?.error?.message + ?: return@LazyVerticalGrid - item(span = { - GridItemSpan(maxLineSpan) - }) { - ErrorScreen(message = message, - modifier = Modifier.padding(vertical = TMDb_8_dp), - refresh = { lazyTMDbItems.retry() }) + item(span = { + GridItemSpan(maxLineSpan) + }) { + ErrorScreen( + message = message, + modifier = Modifier.padding(vertical = TMDb_8_dp), + refresh = { lazyTMDbItems.retry() }, + ) + } } - } - else -> Unit - } - }) + else -> Unit + } + }, + ) } @Composable private fun NoDataFoundAnimation(modifier: Modifier = Modifier) { val preloaderLottieComposition by rememberLottieComposition( LottieCompositionSpec.RawRes( - R.raw.no_data_found - ) + R.raw.no_data_found, + ), ) val preloaderProgress by animateLottieCompositionAsState( - preloaderLottieComposition, iterations = LottieConstants.IterateForever, isPlaying = true + preloaderLottieComposition, + iterations = LottieConstants.IterateForever, + isPlaying = true, ) LottieAnimation( - composition = preloaderLottieComposition, progress = preloaderProgress, modifier = modifier + composition = preloaderLottieComposition, + progress = preloaderProgress, + modifier = modifier, ) -} \ No newline at end of file +} diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/BaseMainPagingViewModel.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/BaseMainPagingViewModel.kt index 8e447b0..c2734f1 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/BaseMainPagingViewModel.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/BaseMainPagingViewModel.kt @@ -10,9 +10,8 @@ import kotlinx.coroutines.flow.Flow open class BaseMainPagingViewModel( repository: BasePagingRepository, - id: Int? = null + id: Int? = null, ) : BasePagingViewModel() { - override val pagingDataFlow: Flow> = repository.fetchResultStream(id = id).cachedIn(viewModelScope) -} \ No newline at end of file +} diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/MainPagingScreens.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/MainPagingScreens.kt index b48c1e6..1ce4523 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/MainPagingScreens.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/MainPagingScreens.kt @@ -36,205 +36,219 @@ fun TrendingMovieScreen( MoviePagingScreen( viewModel = viewModel, navController = navController, - title = stringResource( - R.string.trending, - stringResource(com.sample.tmdb.common.R.string.movies) - ) + title = + stringResource( + R.string.trending, + stringResource(com.sample.tmdb.common.R.string.movies), + ), ) } @Composable fun PopularMovieScreen( navController: NavController, - viewModel: PopularMoviesViewModel = hiltViewModel() + viewModel: PopularMoviesViewModel = hiltViewModel(), ) { MoviePagingScreen( viewModel = viewModel, navController = navController, - title = stringResource( - R.string.popular, - stringResource(com.sample.tmdb.common.R.string.movies) - ) + title = + stringResource( + R.string.popular, + stringResource(com.sample.tmdb.common.R.string.movies), + ), ) } @Composable fun NowPlayingMovieScreen( navController: NavController, - viewModel: NowPlayingMoviesViewModel = hiltViewModel() + viewModel: NowPlayingMoviesViewModel = hiltViewModel(), ) { MoviePagingScreen( viewModel = viewModel, navController = navController, - title = stringResource( - R.string.now_playing, - stringResource(com.sample.tmdb.common.R.string.movies) - ) + title = + stringResource( + R.string.now_playing, + stringResource(com.sample.tmdb.common.R.string.movies), + ), ) } @Composable fun UpcomingMovieScreen( navController: NavController, - viewModel: UpcomingMoviesViewModel = hiltViewModel() + viewModel: UpcomingMoviesViewModel = hiltViewModel(), ) { MoviePagingScreen( viewModel = viewModel, navController = navController, - title = stringResource( - R.string.upcoming, - stringResource(com.sample.tmdb.common.R.string.movies) - ) + title = + stringResource( + R.string.upcoming, + stringResource(com.sample.tmdb.common.R.string.movies), + ), ) } @Composable fun TopRatedMovieScreen( navController: NavController, - viewModel: TopRatedMoviesViewModel = hiltViewModel() + viewModel: TopRatedMoviesViewModel = hiltViewModel(), ) { MoviePagingScreen( viewModel = viewModel, navController = navController, - title = stringResource( - R.string.highest_rate, - stringResource(com.sample.tmdb.common.R.string.movies) - ) + title = + stringResource( + R.string.highest_rate, + stringResource(com.sample.tmdb.common.R.string.movies), + ), ) } @Composable fun DiscoverMovieScreen( navController: NavController, - viewModel: DiscoverMoviesViewModel = hiltViewModel() + viewModel: DiscoverMoviesViewModel = hiltViewModel(), ) { MoviePagingScreen( viewModel = viewModel, navController = navController, - title = stringResource( - R.string.discover, - stringResource(com.sample.tmdb.common.R.string.movies) - ) + title = + stringResource( + R.string.discover, + stringResource(com.sample.tmdb.common.R.string.movies), + ), ) } @Composable fun SimilarMovieScreen( navController: NavController, - viewModel: SimilarMoviesViewModel = hiltViewModel() + viewModel: SimilarMoviesViewModel = hiltViewModel(), ) { MoviePagingScreen( viewModel = viewModel, navController = navController, - title = stringResource( - R.string.similar_items, - stringResource(com.sample.tmdb.common.R.string.movies) - ) + title = + stringResource( + R.string.similar_items, + stringResource(com.sample.tmdb.common.R.string.movies), + ), ) } @Composable fun TrendingTVShowScreen( navController: NavController, - viewModel: TrendingTvSeriesViewModel = hiltViewModel() + viewModel: TrendingTvSeriesViewModel = hiltViewModel(), ) { TVShowPagingScreen( viewModel = viewModel, navController = navController, - title = stringResource( - R.string.trending, - stringResource(com.sample.tmdb.common.R.string.tv_series) - ) + title = + stringResource( + R.string.trending, + stringResource(com.sample.tmdb.common.R.string.tv_series), + ), ) } @Composable fun PopularTVShowScreen( navController: NavController, - viewModel: PopularTvSeriesViewModel = hiltViewModel() + viewModel: PopularTvSeriesViewModel = hiltViewModel(), ) { TVShowPagingScreen( viewModel = viewModel, navController = navController, - title = stringResource( - R.string.popular, - stringResource(com.sample.tmdb.common.R.string.tv_series) - ) + title = + stringResource( + R.string.popular, + stringResource(com.sample.tmdb.common.R.string.tv_series), + ), ) } @Composable fun AiringTodayTVShowScreen( navController: NavController, - viewModel: AiringTodayTvSeriesViewModel = hiltViewModel() + viewModel: AiringTodayTvSeriesViewModel = hiltViewModel(), ) { TVShowPagingScreen( viewModel = viewModel, navController = navController, - title = stringResource( - R.string.airing_today, - stringResource(com.sample.tmdb.common.R.string.tv_series) - ) + title = + stringResource( + R.string.airing_today, + stringResource(com.sample.tmdb.common.R.string.tv_series), + ), ) } @Composable fun OnTheAirTVShowScreen( navController: NavController, - viewModel: OnTheAirTvSeriesViewModel = hiltViewModel() + viewModel: OnTheAirTvSeriesViewModel = hiltViewModel(), ) { TVShowPagingScreen( viewModel = viewModel, navController = navController, - title = stringResource( - R.string.on_the_air, - stringResource(com.sample.tmdb.common.R.string.tv_series) - ) + title = + stringResource( + R.string.on_the_air, + stringResource(com.sample.tmdb.common.R.string.tv_series), + ), ) } @Composable fun TopRatedTVShowScreen( navController: NavController, - viewModel: TopRatedTvSeriesViewModel = hiltViewModel() + viewModel: TopRatedTvSeriesViewModel = hiltViewModel(), ) { TVShowPagingScreen( viewModel = viewModel, navController = navController, - title = stringResource( - R.string.highest_rate, - stringResource(com.sample.tmdb.common.R.string.tv_series) - ) + title = + stringResource( + R.string.highest_rate, + stringResource(com.sample.tmdb.common.R.string.tv_series), + ), ) } @Composable fun DiscoverTVShowScreen( navController: NavController, - viewModel: DiscoverTvSeriesViewModel = hiltViewModel() + viewModel: DiscoverTvSeriesViewModel = hiltViewModel(), ) { TVShowPagingScreen( viewModel = viewModel, navController = navController, - title = stringResource( - R.string.discover, - stringResource(com.sample.tmdb.common.R.string.tv_series) - ) + title = + stringResource( + R.string.discover, + stringResource(com.sample.tmdb.common.R.string.tv_series), + ), ) } @Composable fun SimilarTVShowScreen( navController: NavController, - viewModel: SimilarTvSeriesViewModel = hiltViewModel() + viewModel: SimilarTvSeriesViewModel = hiltViewModel(), ) { TVShowPagingScreen( viewModel = viewModel, navController = navController, - title = stringResource( - R.string.similar_items, - stringResource(com.sample.tmdb.common.R.string.tv_series) - ) + title = + stringResource( + R.string.similar_items, + stringResource(com.sample.tmdb.common.R.string.tv_series), + ), ) } @@ -242,14 +256,14 @@ fun SimilarTVShowScreen( private fun MoviePagingScreen( viewModel: BasePagingViewModel, navController: NavController, - title: String + title: String, ) { PagingScreen( viewModel = viewModel, navController = navController, onClick = { navController.navigate("${MainDestinations.TMDB_MOVIE_DETAIL_ROUTE}/${it.id}") }, onSearchClicked = { navController.navigate(MainDestinations.TMDB_SEARCH_MOVIE_ROUTE) }, - title = title + title = title, ) } @@ -257,14 +271,14 @@ private fun MoviePagingScreen( private fun TVShowPagingScreen( viewModel: BasePagingViewModel, navController: NavController, - title: String + title: String, ) { PagingScreen( viewModel = viewModel, navController = navController, onClick = { navController.navigate("${MainDestinations.TMDB_TV_SHOW_DETAIL_ROUTE}/${it.id}") }, onSearchClicked = { navController.navigate(MainDestinations.TMDB_SEARCH_TV_SHOW_ROUTE) }, - title = title + title = title, ) } @@ -281,7 +295,7 @@ private fun PagingScreen( DestinationBar( title = title, upPress = { navController.navigateUp() }, - onSearchClicked = onSearchClicked + onSearchClicked = onSearchClicked, ) } -} \ No newline at end of file +} diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/DiscoverMoviesViewModel.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/DiscoverMoviesViewModel.kt index 9079e9d..7c9e54b 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/DiscoverMoviesViewModel.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/DiscoverMoviesViewModel.kt @@ -1,13 +1,15 @@ package com.sample.tmdb.paging.main.movie -import com.sample.tmdb.domain.utils.Discover import com.sample.tmdb.domain.model.Movie import com.sample.tmdb.domain.repository.BasePagingRepository +import com.sample.tmdb.domain.utils.Discover import com.sample.tmdb.paging.main.BaseMainPagingViewModel import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class DiscoverMoviesViewModel @Inject constructor( - @Discover repository: BasePagingRepository -) : BaseMainPagingViewModel(repository) \ No newline at end of file +class DiscoverMoviesViewModel + @Inject + constructor( + @Discover repository: BasePagingRepository, + ) : BaseMainPagingViewModel(repository) diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/NowPlayingMoviesViewModel.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/NowPlayingMoviesViewModel.kt index cd4178d..d54b0f1 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/NowPlayingMoviesViewModel.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/NowPlayingMoviesViewModel.kt @@ -1,13 +1,15 @@ package com.sample.tmdb.paging.main.movie -import com.sample.tmdb.domain.utils.NowPlaying import com.sample.tmdb.domain.model.Movie import com.sample.tmdb.domain.repository.BasePagingRepository +import com.sample.tmdb.domain.utils.NowPlaying import com.sample.tmdb.paging.main.BaseMainPagingViewModel import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class NowPlayingMoviesViewModel @Inject constructor( - @NowPlaying repository: BasePagingRepository -) : BaseMainPagingViewModel(repository) \ No newline at end of file +class NowPlayingMoviesViewModel + @Inject + constructor( + @NowPlaying repository: BasePagingRepository, + ) : BaseMainPagingViewModel(repository) diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/PopularMoviesViewModel.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/PopularMoviesViewModel.kt index 9be105e..816a60b 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/PopularMoviesViewModel.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/PopularMoviesViewModel.kt @@ -1,13 +1,15 @@ package com.sample.tmdb.paging.main.movie -import com.sample.tmdb.domain.utils.Popular import com.sample.tmdb.domain.model.Movie import com.sample.tmdb.domain.repository.BasePagingRepository +import com.sample.tmdb.domain.utils.Popular import com.sample.tmdb.paging.main.BaseMainPagingViewModel import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class PopularMoviesViewModel @Inject constructor( - @Popular repository: BasePagingRepository -) : BaseMainPagingViewModel(repository) \ No newline at end of file +class PopularMoviesViewModel + @Inject + constructor( + @Popular repository: BasePagingRepository, + ) : BaseMainPagingViewModel(repository) diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/SimilarMoviesViewModel.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/SimilarMoviesViewModel.kt index 63e7887..56840e0 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/SimilarMoviesViewModel.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/SimilarMoviesViewModel.kt @@ -10,7 +10,9 @@ import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class SimilarMoviesViewModel @Inject constructor( - @Similar repository: BasePagingRepository, - savedStateHandle: SavedStateHandle, -) : BaseMainPagingViewModel(repository, savedStateHandle[MainDestinations.TMDB_SIMILAR_ID]) \ No newline at end of file +class SimilarMoviesViewModel + @Inject + constructor( + @Similar repository: BasePagingRepository, + savedStateHandle: SavedStateHandle, + ) : BaseMainPagingViewModel(repository, savedStateHandle[MainDestinations.TMDB_SIMILAR_ID]) diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/TopRatedMoviesViewModel.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/TopRatedMoviesViewModel.kt index 6dbe2a3..09b16ab 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/TopRatedMoviesViewModel.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/TopRatedMoviesViewModel.kt @@ -1,13 +1,15 @@ package com.sample.tmdb.paging.main.movie -import com.sample.tmdb.domain.utils.TopRated import com.sample.tmdb.domain.model.Movie import com.sample.tmdb.domain.repository.BasePagingRepository +import com.sample.tmdb.domain.utils.TopRated import com.sample.tmdb.paging.main.BaseMainPagingViewModel import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class TopRatedMoviesViewModel @Inject constructor( - @TopRated repository: BasePagingRepository -) : BaseMainPagingViewModel(repository) \ No newline at end of file +class TopRatedMoviesViewModel + @Inject + constructor( + @TopRated repository: BasePagingRepository, + ) : BaseMainPagingViewModel(repository) diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/TrendingMoviesViewModel.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/TrendingMoviesViewModel.kt index 7c83106..7f589cf 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/TrendingMoviesViewModel.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/TrendingMoviesViewModel.kt @@ -1,13 +1,15 @@ package com.sample.tmdb.paging.main.movie -import com.sample.tmdb.domain.utils.Trending import com.sample.tmdb.domain.model.Movie import com.sample.tmdb.domain.repository.BasePagingRepository +import com.sample.tmdb.domain.utils.Trending import com.sample.tmdb.paging.main.BaseMainPagingViewModel import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class TrendingMoviesViewModel @Inject constructor( - @Trending repository: BasePagingRepository -) : BaseMainPagingViewModel(repository) \ No newline at end of file +class TrendingMoviesViewModel + @Inject + constructor( + @Trending repository: BasePagingRepository, + ) : BaseMainPagingViewModel(repository) diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/UpcomingMoviesViewModel.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/UpcomingMoviesViewModel.kt index 0b45c7c..44431aa 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/UpcomingMoviesViewModel.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/movie/UpcomingMoviesViewModel.kt @@ -1,13 +1,15 @@ package com.sample.tmdb.paging.main.movie -import com.sample.tmdb.domain.utils.Latest import com.sample.tmdb.domain.model.Movie import com.sample.tmdb.domain.repository.BasePagingRepository +import com.sample.tmdb.domain.utils.Latest import com.sample.tmdb.paging.main.BaseMainPagingViewModel import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class UpcomingMoviesViewModel @Inject constructor( - @Latest repository: BasePagingRepository -) : BaseMainPagingViewModel(repository) \ No newline at end of file +class UpcomingMoviesViewModel + @Inject + constructor( + @Latest repository: BasePagingRepository, + ) : BaseMainPagingViewModel(repository) diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/AiringTodayTvSeriesViewModel.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/AiringTodayTvSeriesViewModel.kt index 8c7b842..4ddb85f 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/AiringTodayTvSeriesViewModel.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/AiringTodayTvSeriesViewModel.kt @@ -1,13 +1,15 @@ package com.sample.tmdb.paging.main.tvshow -import com.sample.tmdb.domain.utils.NowPlaying import com.sample.tmdb.domain.model.TVShow import com.sample.tmdb.domain.repository.BasePagingRepository +import com.sample.tmdb.domain.utils.NowPlaying import com.sample.tmdb.paging.main.BaseMainPagingViewModel import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class AiringTodayTvSeriesViewModel @Inject constructor( - @NowPlaying repository: BasePagingRepository -) : BaseMainPagingViewModel(repository) \ No newline at end of file +class AiringTodayTvSeriesViewModel + @Inject + constructor( + @NowPlaying repository: BasePagingRepository, + ) : BaseMainPagingViewModel(repository) diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/DiscoverTvSeriesViewModel.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/DiscoverTvSeriesViewModel.kt index 4465d06..0142c60 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/DiscoverTvSeriesViewModel.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/DiscoverTvSeriesViewModel.kt @@ -1,13 +1,15 @@ package com.sample.tmdb.paging.main.tvshow -import com.sample.tmdb.domain.utils.Discover import com.sample.tmdb.domain.model.TVShow import com.sample.tmdb.domain.repository.BasePagingRepository +import com.sample.tmdb.domain.utils.Discover import com.sample.tmdb.paging.main.BaseMainPagingViewModel import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class DiscoverTvSeriesViewModel @Inject constructor( - @Discover repository: BasePagingRepository -) : BaseMainPagingViewModel(repository) \ No newline at end of file +class DiscoverTvSeriesViewModel + @Inject + constructor( + @Discover repository: BasePagingRepository, + ) : BaseMainPagingViewModel(repository) diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/OnTheAirTvSeriesViewModel.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/OnTheAirTvSeriesViewModel.kt index 55ef91d..bb976fb 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/OnTheAirTvSeriesViewModel.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/OnTheAirTvSeriesViewModel.kt @@ -1,13 +1,15 @@ package com.sample.tmdb.paging.main.tvshow -import com.sample.tmdb.domain.utils.Latest import com.sample.tmdb.domain.model.TVShow import com.sample.tmdb.domain.repository.BasePagingRepository +import com.sample.tmdb.domain.utils.Latest import com.sample.tmdb.paging.main.BaseMainPagingViewModel import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class OnTheAirTvSeriesViewModel @Inject constructor( - @Latest repository: BasePagingRepository -) : BaseMainPagingViewModel(repository) \ No newline at end of file +class OnTheAirTvSeriesViewModel + @Inject + constructor( + @Latest repository: BasePagingRepository, + ) : BaseMainPagingViewModel(repository) diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/PopularTvSeriesViewModel.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/PopularTvSeriesViewModel.kt index cb122cd..4ba57e5 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/PopularTvSeriesViewModel.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/PopularTvSeriesViewModel.kt @@ -1,13 +1,15 @@ package com.sample.tmdb.paging.main.tvshow -import com.sample.tmdb.domain.utils.Popular import com.sample.tmdb.domain.model.TVShow import com.sample.tmdb.domain.repository.BasePagingRepository +import com.sample.tmdb.domain.utils.Popular import com.sample.tmdb.paging.main.BaseMainPagingViewModel import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class PopularTvSeriesViewModel @Inject constructor( - @Popular repository: BasePagingRepository -) : BaseMainPagingViewModel(repository) \ No newline at end of file +class PopularTvSeriesViewModel + @Inject + constructor( + @Popular repository: BasePagingRepository, + ) : BaseMainPagingViewModel(repository) diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/SimilarTvSeriesViewModel.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/SimilarTvSeriesViewModel.kt index d55a47d..37be02b 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/SimilarTvSeriesViewModel.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/SimilarTvSeriesViewModel.kt @@ -10,7 +10,9 @@ import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class SimilarTvSeriesViewModel @Inject constructor( - @Similar repository: BasePagingRepository, - savedStateHandle: SavedStateHandle, -) : BaseMainPagingViewModel(repository, savedStateHandle[MainDestinations.TMDB_SIMILAR_ID]) \ No newline at end of file +class SimilarTvSeriesViewModel + @Inject + constructor( + @Similar repository: BasePagingRepository, + savedStateHandle: SavedStateHandle, + ) : BaseMainPagingViewModel(repository, savedStateHandle[MainDestinations.TMDB_SIMILAR_ID]) diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/TopRatedTvSeriesViewModel.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/TopRatedTvSeriesViewModel.kt index 0dc3614..511b94d 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/TopRatedTvSeriesViewModel.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/TopRatedTvSeriesViewModel.kt @@ -1,13 +1,15 @@ package com.sample.tmdb.paging.main.tvshow -import com.sample.tmdb.domain.utils.TopRated import com.sample.tmdb.domain.model.TVShow import com.sample.tmdb.domain.repository.BasePagingRepository +import com.sample.tmdb.domain.utils.TopRated import com.sample.tmdb.paging.main.BaseMainPagingViewModel import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class TopRatedTvSeriesViewModel @Inject constructor( - @TopRated repository: BasePagingRepository -) : BaseMainPagingViewModel(repository) \ No newline at end of file +class TopRatedTvSeriesViewModel + @Inject + constructor( + @TopRated repository: BasePagingRepository, + ) : BaseMainPagingViewModel(repository) diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/TrendingTvSeriesViewModel.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/TrendingTvSeriesViewModel.kt index 92ec4ff..a6c4ef5 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/TrendingTvSeriesViewModel.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/main/tvshow/TrendingTvSeriesViewModel.kt @@ -1,13 +1,15 @@ package com.sample.tmdb.paging.main.tvshow -import com.sample.tmdb.domain.utils.Trending import com.sample.tmdb.domain.model.TVShow import com.sample.tmdb.domain.repository.BasePagingRepository +import com.sample.tmdb.domain.utils.Trending import com.sample.tmdb.paging.main.BaseMainPagingViewModel import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class TrendingTvSeriesViewModel @Inject constructor( - @Trending repository: BasePagingRepository -) : BaseMainPagingViewModel(repository) \ No newline at end of file +class TrendingTvSeriesViewModel + @Inject + constructor( + @Trending repository: BasePagingRepository, + ) : BaseMainPagingViewModel(repository) diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/AnimatedSearch.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/AnimatedSearch.kt index b5404f3..7967d39 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/AnimatedSearch.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/AnimatedSearch.kt @@ -1,6 +1,11 @@ package com.sample.tmdb.paging.search -import androidx.compose.animation.core.* +import androidx.compose.animation.core.Animatable +import androidx.compose.animation.core.AnimationVector1D +import androidx.compose.animation.core.LinearEasing +import androidx.compose.animation.core.RepeatMode +import androidx.compose.animation.core.infiniteRepeatable +import androidx.compose.animation.core.tween import androidx.compose.foundation.Canvas import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable @@ -21,18 +26,20 @@ import androidx.compose.ui.graphics.drawscope.Stroke private fun AnimateShapeInfinitely( animateShape: Animatable, targetValue: Float = 1f, - durationMillis: Int = 1000 + durationMillis: Int = 1000, ) { LaunchedEffect(animateShape) { animateShape.animateTo( targetValue = targetValue, - animationSpec = infiniteRepeatable( - animation = tween( - durationMillis = durationMillis, - easing = LinearEasing + animationSpec = + infiniteRepeatable( + animation = + tween( + durationMillis = durationMillis, + easing = LinearEasing, + ), + repeatMode = RepeatMode.Restart, ), - repeatMode = RepeatMode.Restart - ) ) } } @@ -46,24 +53,25 @@ private fun AnimateShapeInfinitely( */ @Composable fun AnimatedSearch() { - // Simple progressive circle looking animation - val animateCircle = remember { Animatable(0f) }.apply { - AnimateShapeInfinitely(this) - } + val animateCircle = + remember { Animatable(0f) }.apply { + AnimateShapeInfinitely(this) + } // 0.6f for initial value to reduce floating time of line to reach it's final state. // Settings it to 0f -> final animation output looks kind of aggressive movements. - val animateLine = remember { Animatable(0.6f) }.apply { - AnimateShapeInfinitely(this) - } + val animateLine = + remember { Animatable(0.6f) }.apply { + AnimateShapeInfinitely(this) + } // Appears different for dark/light theme colors. val surfaceColor = MaterialTheme.colors.surface // Arcs & Line drawn in canvas at animation final state looks like search icon. Canvas( - modifier = Modifier + modifier = Modifier, ) { drawArc( color = surfaceColor, @@ -71,21 +79,23 @@ fun AnimatedSearch() { sweepAngle = 360f * animateCircle.value, useCenter = false, size = Size(80f, 80f), - style = Stroke(16f, cap = StrokeCap.Round) + style = Stroke(16f, cap = StrokeCap.Round), ) drawLine( color = surfaceColor, strokeWidth = 16f, cap = StrokeCap.Round, - start = Offset( - animateLine.value * 80f, - animateLine.value * 80f - ), - end = Offset( - animateLine.value * 110f, - animateLine.value * 110f - ) + start = + Offset( + animateLine.value * 80f, + animateLine.value * 80f, + ), + end = + Offset( + animateLine.value * 110f, + animateLine.value * 110f, + ), ) } -} \ No newline at end of file +} diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/BaseSearchPagingViewModel.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/BaseSearchPagingViewModel.kt index cb69829..ebb269d 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/BaseSearchPagingViewModel.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/BaseSearchPagingViewModel.kt @@ -14,25 +14,25 @@ import kotlinx.coroutines.flow.flatMapLatest open class BaseSearchPagingViewModel( repository: BasePagingRepository, - private val savedStateHandle: SavedStateHandle + private val savedStateHandle: SavedStateHandle, ) : BasePagingViewModel() { - @OptIn(ExperimentalCoroutinesApi::class) override val pagingDataFlow: Flow> = - savedStateHandle.getLiveData(KEY_QUERY).asFlow().flatMapLatest { - repository.fetchResultStream(it) - }.cachedIn(viewModelScope) - + savedStateHandle + .getLiveData(KEY_QUERY) + .asFlow() + .flatMapLatest { + repository.fetchResultStream(it) + }.cachedIn(viewModelScope) fun showResult(query: String) { if (!shouldShowResult(query)) return savedStateHandle[KEY_QUERY] = query } - private fun shouldShowResult(query: String): Boolean = - savedStateHandle.get(KEY_QUERY) != query + private fun shouldShowResult(query: String): Boolean = savedStateHandle.get(KEY_QUERY) != query companion object { private const val KEY_QUERY = "query" } -} \ No newline at end of file +} diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/InfiniteFlowingCircle.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/InfiniteFlowingCircle.kt index 5884f3b..a4745ce 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/InfiniteFlowingCircle.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/InfiniteFlowingCircle.kt @@ -16,7 +16,6 @@ import androidx.compose.ui.graphics.graphicsLayer */ @Composable fun InfinitelyFlowingCircles() { - // Same color with different variants for different circles. val primaryColor = MaterialTheme.colors.primary val frontCircle = primaryColor.copy(0.75f) @@ -26,19 +25,19 @@ fun InfinitelyFlowingCircles() { DrawCircleOnCanvas( scale = scaleInfiniteTransition(targetValue = 2f, durationMillis = 600), color = backCircle, - radiusRatio = 4f + radiusRatio = 4f, ) DrawCircleOnCanvas( scale = scaleInfiniteTransition(targetValue = 2.5f, durationMillis = 800), color = midCircle, - radiusRatio = 6f + radiusRatio = 6f, ) DrawCircleOnCanvas( scale = scaleInfiniteTransition(targetValue = 3f, durationMillis = 1000), color = frontCircle, - radiusRatio = 12f + radiusRatio = 12f, ) } @@ -51,24 +50,26 @@ fun InfinitelyFlowingCircles() { private fun DrawCircleOnCanvas( scale: Float, color: Color, - radiusRatio: Float + radiusRatio: Float, ) { Canvas( - modifier = Modifier - .fillMaxSize() - .graphicsLayer { - scaleX = scale - scaleY = scale - } + modifier = + Modifier + .fillMaxSize() + .graphicsLayer { + scaleX = scale + scaleY = scale + }, ) { val canvasWidth = size.width val canvasHeight = size.height drawCircle( color = color, - center = Offset( - x = canvasWidth / 2, - y = canvasHeight / 2 - ), + center = + Offset( + x = canvasWidth / 2, + y = canvasHeight / 2, + ), radius = size.minDimension / radiusRatio, ) } @@ -91,10 +92,11 @@ private fun scaleInfiniteTransition( val scale: Float by infiniteTransition.animateFloat( initialValue = initialValue, targetValue = targetValue, - animationSpec = infiniteRepeatable( - animation = tween(durationMillis, easing = LinearEasing), - repeatMode = RepeatMode.Reverse - ) + animationSpec = + infiniteRepeatable( + animation = tween(durationMillis, easing = LinearEasing), + repeatMode = RepeatMode.Reverse, + ), ) return scale -} \ No newline at end of file +} diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/SearchMoviesViewModel.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/SearchMoviesViewModel.kt index 089593c..513c64a 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/SearchMoviesViewModel.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/SearchMoviesViewModel.kt @@ -1,14 +1,16 @@ package com.sample.tmdb.paging.search import androidx.lifecycle.SavedStateHandle -import com.sample.tmdb.domain.utils.Search import com.sample.tmdb.domain.model.Movie import com.sample.tmdb.domain.repository.BasePagingRepository +import com.sample.tmdb.domain.utils.Search import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class SearchMoviesViewModel @Inject constructor( - @Search repository: BasePagingRepository, - savedStateHandle: SavedStateHandle -) : BaseSearchPagingViewModel(repository, savedStateHandle) \ No newline at end of file +class SearchMoviesViewModel + @Inject + constructor( + @Search repository: BasePagingRepository, + savedStateHandle: SavedStateHandle, + ) : BaseSearchPagingViewModel(repository, savedStateHandle) diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/SearchScreens.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/SearchScreens.kt index 589b4d0..7a660c4 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/SearchScreens.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/SearchScreens.kt @@ -58,26 +58,26 @@ import com.sample.tmdb.common.R as R1 @Composable fun SearchMoviesScreen( navController: NavController, - viewModel: SearchMoviesViewModel = hiltViewModel() + viewModel: SearchMoviesViewModel = hiltViewModel(), ) { Search( viewModel = viewModel, onClick = { navController.navigate("${MainDestinations.TMDB_MOVIE_DETAIL_ROUTE}/${it.id}") }, upPress = { navController.navigateUp() }, - resourceId = R1.string.movies + resourceId = R1.string.movies, ) } @Composable fun SearchTVSeriesScreen( navController: NavController, - viewModel: SearchTvSeriesViewModel = hiltViewModel() + viewModel: SearchTvSeriesViewModel = hiltViewModel(), ) { Search( viewModel = viewModel, onClick = { navController.navigate("${MainDestinations.TMDB_TV_SHOW_DETAIL_ROUTE}/${it.id}") }, upPress = { navController.navigateUp() }, - resourceId = R1.string.tv_series + resourceId = R1.string.tv_series, ) } @@ -87,7 +87,7 @@ fun Search( onClick: (TMDbItem) -> Unit, upPress: () -> Unit, @StringRes resourceId: Int, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, ) { var query by rememberSaveable { mutableStateOf("") } var focused by rememberSaveable { mutableStateOf(false) } @@ -95,10 +95,11 @@ fun Search( if (query.isEmpty()) { InfinitelyFlowingCircles() Box( - modifier = Modifier - .fillMaxSize() - .padding(bottom = 28.dp, end = 28.dp), - contentAlignment = Alignment.Center + modifier = + Modifier + .fillMaxSize() + .padding(bottom = 28.dp, end = 28.dp), + contentAlignment = Alignment.Center, ) { AnimatedSearch() } @@ -106,44 +107,48 @@ fun Search( viewModel.showResult(query) PagingScreen( viewModel = viewModel, - onClick = onClick + onClick = onClick, ) } Column( - modifier = Modifier - .statusBarsPadding() - .background(MaterialTheme.colors.background.copy(alpha = AlphaNearOpaque)) + modifier = + Modifier + .statusBarsPadding() + .background(MaterialTheme.colors.background.copy(alpha = AlphaNearOpaque)), ) { Row( - modifier = modifier - .fillMaxWidth() - .padding(TMDb_8_dp), - horizontalArrangement = Arrangement.spacedBy( - TMDb_16_dp, - Alignment.CenterHorizontally - ), - verticalAlignment = Alignment.CenterVertically + modifier = + modifier + .fillMaxWidth() + .padding(TMDb_8_dp), + horizontalArrangement = + Arrangement.spacedBy( + TMDb_16_dp, + Alignment.CenterHorizontally, + ), + verticalAlignment = Alignment.CenterVertically, ) { - val iconModifier = Modifier - .sizeIn( - maxWidth = TMDb_32_dp, - maxHeight = TMDb_32_dp - ) - .border(1.dp, MaterialTheme.colors.primary, CircleShape) - .background( - color = MaterialTheme.colors.background, - shape = CircleShape - ) + val iconModifier = + Modifier + .sizeIn( + maxWidth = TMDb_32_dp, + maxHeight = TMDb_32_dp, + ).border(1.dp, MaterialTheme.colors.primary, CircleShape) + .background( + color = MaterialTheme.colors.background, + shape = CircleShape, + ) IconButton( onClick = upPress, - modifier = Modifier - .padding(start = TMDb_12_dp) - .then(iconModifier) + modifier = + Modifier + .padding(start = TMDb_12_dp) + .then(iconModifier), ) { Icon( Icons.AutoMirrored.Filled.ArrowBack, contentDescription = stringResource(id = R1.string.back), - tint = MaterialTheme.colors.primary + tint = MaterialTheme.colors.primary, ) } SearchBar( @@ -168,49 +173,52 @@ fun SearchBar( searchFocused: Boolean, onSearchFocusChange: (Boolean) -> Unit, onClearQuery: () -> Unit, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, ) { Surface( contentColor = MaterialTheme.colors.surface, shape = MaterialTheme.shapes.small, - modifier = modifier - .fillMaxWidth() - .height(46.dp) - .border(1.dp, MaterialTheme.colors.primary, CircleShape) - .background(MaterialTheme.colors.background, CircleShape) - .padding(horizontal = TMDb_24_dp, vertical = TMDb_8_dp) + modifier = + modifier + .fillMaxWidth() + .height(46.dp) + .border(1.dp, MaterialTheme.colors.primary, CircleShape) + .background(MaterialTheme.colors.background, CircleShape) + .padding(horizontal = TMDb_24_dp, vertical = TMDb_8_dp), ) { Box( Modifier .fillMaxSize() - .background(MaterialTheme.colors.background) + .background(MaterialTheme.colors.background), ) { if (query.isEmpty()) { SearchHint(resourceId) } Row( verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .fillMaxSize() - .wrapContentHeight() + modifier = + Modifier + .fillMaxSize() + .wrapContentHeight(), ) { BasicTextField( value = query, textStyle = LocalTextStyle.current.copy(color = MaterialTheme.colors.onBackground), cursorBrush = SolidColor(MaterialTheme.colors.onBackground), onValueChange = onQueryChange, - modifier = Modifier - .weight(1f) - .onFocusChanged { - onSearchFocusChange(it.isFocused) - } + modifier = + Modifier + .weight(1f) + .onFocusChanged { + onSearchFocusChange(it.isFocused) + }, ) if (searchFocused && query.isNotEmpty()) { IconButton(onClick = onClearQuery) { Icon( imageVector = Icons.Default.Clear, tint = MaterialTheme.colors.primary, - contentDescription = stringResource(id = R.string.clear) + contentDescription = stringResource(id = R.string.clear), ) } } @@ -220,22 +228,25 @@ fun SearchBar( } @Composable -fun SearchHint(@StringRes resourceId: Int) { +fun SearchHint( + @StringRes resourceId: Int, +) { Row( verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .fillMaxSize() - .wrapContentSize() + modifier = + Modifier + .fillMaxSize() + .wrapContentSize(), ) { Icon( imageVector = Icons.Outlined.Search, tint = MaterialTheme.colors.primary, - contentDescription = stringResource(id = R.string.search_desc) + contentDescription = stringResource(id = R.string.search_desc), ) Spacer(Modifier.width(TMDb_8_dp)) Text( text = stringResource(R.string.search, stringResource(resourceId)), - color = MaterialTheme.colors.primary + color = MaterialTheme.colors.primary, ) } -} \ No newline at end of file +} diff --git a/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/SearchTvSeriesViewModel.kt b/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/SearchTvSeriesViewModel.kt index a7a8507..6aeaf54 100644 --- a/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/SearchTvSeriesViewModel.kt +++ b/features/feature-paging/src/main/java/com/sample/tmdb/paging/search/SearchTvSeriesViewModel.kt @@ -1,14 +1,16 @@ package com.sample.tmdb.paging.search import androidx.lifecycle.SavedStateHandle -import com.sample.tmdb.domain.utils.Search import com.sample.tmdb.domain.model.TVShow import com.sample.tmdb.domain.repository.BasePagingRepository +import com.sample.tmdb.domain.utils.Search import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class SearchTvSeriesViewModel @Inject constructor( - @Search repository: BasePagingRepository, - savedStateHandle: SavedStateHandle -) : BaseSearchPagingViewModel(repository, savedStateHandle) \ No newline at end of file +class SearchTvSeriesViewModel + @Inject + constructor( + @Search repository: BasePagingRepository, + savedStateHandle: SavedStateHandle, + ) : BaseSearchPagingViewModel(repository, savedStateHandle) diff --git a/features/feature-setting/src/androidTest/java/com/sample/tmdb/setting/SettingScreenTest.kt b/features/feature-setting/src/androidTest/java/com/sample/tmdb/setting/SettingScreenTest.kt index 2e53721..f3ed6c8 100644 --- a/features/feature-setting/src/androidTest/java/com/sample/tmdb/setting/SettingScreenTest.kt +++ b/features/feature-setting/src/androidTest/java/com/sample/tmdb/setting/SettingScreenTest.kt @@ -8,7 +8,6 @@ import org.junit.Rule import org.junit.Test class SettingScreenTest { - @get:Rule val composeTestRule = createAndroidComposeRule() @@ -34,9 +33,9 @@ class SettingScreenTest { Settings.Info( R.drawable.ic_info, R.string.version, - "1.1" - ) - ) + "1.1", + ), + ), ) } onNodeWithText(activity.getString(R.string.version)).assertIsDisplayed() @@ -53,4 +52,4 @@ class SettingScreenTest { onNodeWithText("title").assertIsDisplayed() } } -} \ No newline at end of file +} diff --git a/features/feature-setting/src/main/java/com/sample/tmdb/setting/SettingScreen.kt b/features/feature-setting/src/main/java/com/sample/tmdb/setting/SettingScreen.kt index 1cb2f28..8a0a114 100644 --- a/features/feature-setting/src/main/java/com/sample/tmdb/setting/SettingScreen.kt +++ b/features/feature-setting/src/main/java/com/sample/tmdb/setting/SettingScreen.kt @@ -45,35 +45,39 @@ import com.sample.tmdb.common.ui.theme.Teal200 @Composable fun SettingsScreen(modifier: Modifier = Modifier) { - val aboutSettings = listOf( - Settings.IntentAction( - iconResourceId = R.drawable.ic_github, - titleResourceId = R.string.source_code_github, - intent = Intent(Intent.ACTION_VIEW, Uri.parse(TMDB_REPO_URL)) - ), - Settings.IntentAction( - iconResourceId = R.drawable.ic_shield, - titleResourceId = R.string.privacy_policy, - intent = Intent(Intent.ACTION_VIEW, Uri.parse(TMDB_POLICY_URL)) - ), - Settings.Info( - iconResourceId = R.drawable.ic_info, - titleResourceId = R.string.version, - value = BuildConfig.VERSION_NAME + val aboutSettings = + listOf( + Settings.IntentAction( + iconResourceId = R.drawable.ic_github, + titleResourceId = R.string.source_code_github, + intent = Intent(Intent.ACTION_VIEW, Uri.parse(TMDB_REPO_URL)), + ), + Settings.IntentAction( + iconResourceId = R.drawable.ic_shield, + titleResourceId = R.string.privacy_policy, + intent = Intent(Intent.ACTION_VIEW, Uri.parse(TMDB_POLICY_URL)), + ), + Settings.Info( + iconResourceId = R.drawable.ic_info, + titleResourceId = R.string.version, + value = BuildConfig.VERSION_NAME, + ), ) - ) Box( - modifier = Modifier - .fillMaxSize() - .statusBarsPadding() + modifier = + Modifier + .fillMaxSize() + .statusBarsPadding(), ) { SettingsGroupItem( - settings = aboutSettings, modifier = modifier - .padding( - top = 56.dp + TMDb_16_dp, - start = TMDb_12_dp, - end = TMDb_12_dp - ) + settings = aboutSettings, + modifier = + modifier + .padding( + top = 56.dp + TMDb_16_dp, + start = TMDb_12_dp, + end = TMDb_12_dp, + ), ) DestinationBar(title = stringResource(R.string.about)) } @@ -82,15 +86,16 @@ fun SettingsScreen(modifier: Modifier = Modifier) { @Composable fun SettingsGroupItem( settings: List, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, ) { Card( modifier = modifier, shape = RoundedCornerShape(TMDb_16_dp), - border = BorderStroke( - width = 1.dp, - color = MaterialTheme.colors.onSurface.copy(alpha = DIVIDER_ALPHA) - ) + border = + BorderStroke( + width = 1.dp, + color = MaterialTheme.colors.onSurface.copy(alpha = DIVIDER_ALPHA), + ), ) { Column { settings.forEachIndexed { index, settingsItem -> @@ -110,30 +115,31 @@ fun SettingsGroupItem( private fun SettingsItem( settings: Settings, modifier: Modifier = Modifier, - context: Context = LocalContext.current + context: Context = LocalContext.current, ) { Row( - modifier = modifier - .then( - when (settings) { - is Settings.Action -> Modifier.clickable(onClick = settings.onClick) - is Settings.IntentAction -> Modifier.clickable { context.startActivity(settings.intent) } - is Settings.Info -> Modifier - } - ) - .padding(TMDb_12_dp) - .fillMaxWidth(), + modifier = + modifier + .then( + when (settings) { + is Settings.Action -> Modifier.clickable(onClick = settings.onClick) + is Settings.IntentAction -> Modifier.clickable { context.startActivity(settings.intent) } + is Settings.Info -> Modifier + }, + ).padding(TMDb_12_dp) + .fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, ) { IconBox( iconResourceId = settings.iconResourceId, - contentDescription = stringResource(id = settings.titleResourceId) + contentDescription = stringResource(id = settings.titleResourceId), ) TitleText( - modifier = Modifier - .padding(TMDb_8_dp) - .weight(1f), - titleResourceId = settings.titleResourceId + modifier = + Modifier + .padding(TMDb_8_dp) + .weight(1f), + titleResourceId = settings.titleResourceId, ) when (settings) { is Settings.Info -> TitleText(title = settings.value) @@ -146,20 +152,20 @@ private fun SettingsItem( private fun IconBox( @DrawableRes iconResourceId: Int, contentDescription: String?, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, ) { Box( - modifier = modifier - .size(TMDb_32_dp) - .background(color = MaterialTheme.colors.background, shape = CircleShape), - contentAlignment = Alignment.Center - + modifier = + modifier + .size(TMDb_32_dp) + .background(color = MaterialTheme.colors.background, shape = CircleShape), + contentAlignment = Alignment.Center, ) { Icon( painter = painterResource(id = iconResourceId), contentDescription = contentDescription, modifier = modifier, - tint = MaterialTheme.colors.onSurface + tint = MaterialTheme.colors.onSurface, ) } } @@ -177,7 +183,7 @@ private fun TitleText( style = style, color = color, maxLines = 1, - overflow = TextOverflow.Ellipsis + overflow = TextOverflow.Ellipsis, ) } @@ -194,20 +200,20 @@ fun TitleText( style = style, color = color, maxLines = 1, - overflow = TextOverflow.Ellipsis + overflow = TextOverflow.Ellipsis, ) } @Composable private fun ForwardButton( modifier: Modifier = Modifier, - color: Color = Teal200 + color: Color = Teal200, ) { Icon( modifier = modifier.size(TMDb_32_dp), painter = painterResource(id = R.drawable.ic_arrow_forward), contentDescription = stringResource(id = R.string.forward), - tint = color + tint = color, ) } @@ -221,24 +227,23 @@ sealed interface Settings { data class Info( @DrawableRes override val iconResourceId: Int, @StringRes override val titleResourceId: Int, - val value: String + val value: String, ) : Settings data class Action( @DrawableRes override val iconResourceId: Int, @StringRes override val titleResourceId: Int, - val onClick: () -> Unit + val onClick: () -> Unit, ) : Settings data class IntentAction( @DrawableRes override val iconResourceId: Int, @StringRes override val titleResourceId: Int, - val intent: Intent + val intent: Intent, ) : Settings } - private const val TMDB_REPO_URL = "https://github.com/alirezaeiii/TMDb-Compose-Playground" private const val TMDB_POLICY_URL = "https://docs.google.com/document/d/10tQW2au7MCCYI8D1CZKU5jkpdbsUvsB6wCQ-7ysoT04/edit" -private const val DIVIDER_ALPHA = 0.12f \ No newline at end of file +private const val DIVIDER_ALPHA = 0.12f diff --git a/spotless.gradle b/spotless.gradle new file mode 100644 index 0000000..4172186 --- /dev/null +++ b/spotless.gradle @@ -0,0 +1,20 @@ +apply plugin: "com.diffplug.spotless" +spotless { + format 'misc', { + // define the files to apply `misc` to + target '**/*.gradle', '**/*.md', '**/.gitignore' + + // define the steps to apply to those files + indentWithSpaces() + trimTrailingWhitespace() + endWithNewline() + } + kotlin { + target "**/*.kt" + trimTrailingWhitespace() + ktlint() + indentWithSpaces() + endWithNewline() + targetExclude("**/Dependencies.kt") + } +}