From 663f1fc4fdc4139d33a6ab8a18e4e02d773cc156 Mon Sep 17 00:00:00 2001 From: Company Date: Sat, 30 Mar 2024 10:52:03 +0700 Subject: [PATCH 1/6] Init clean architech --- app/src/main/java/com/sun/android/MainActivity.kt | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 app/src/main/java/com/sun/android/MainActivity.kt diff --git a/app/src/main/java/com/sun/android/MainActivity.kt b/app/src/main/java/com/sun/android/MainActivity.kt deleted file mode 100644 index 81e021a..0000000 --- a/app/src/main/java/com/sun/android/MainActivity.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.sun.android - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity - -class MainActivity : AppCompatActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) - } -} From a2041885f3cfb21d07629e8b24beb8cd438185d6 Mon Sep 17 00:00:00 2001 From: Company Date: Sun, 31 Mar 2024 14:07:14 +0700 Subject: [PATCH 2/6] Rename to presentation --- .idea/deploymentTargetDropDown.xml | 3 +++ {app => presentation}/.gitignore | 0 {app => presentation}/build.gradle.kts | 0 {app => presentation}/ktlint.gradle.kts | 0 {app => presentation}/proguard-rules.pro | 0 {app => presentation}/src/main/AndroidManifest.xml | 0 .../main/java/com/sun/android/AndroidApplication.kt | 0 .../main/java/com/sun/android/base/BaseActivity.kt | 0 .../main/java/com/sun/android/base/BaseFragment.kt | 0 .../java/com/sun/android/data/MovieRepository.kt | 0 .../java/com/sun/android/data/TokenRepository.kt | 0 .../main/java/com/sun/android/data/model/Movie.kt | 0 .../android/data/repository/MovieRepositoryImpl.kt | 0 .../android/data/repository/TokenRepositoryImpl.kt | 0 .../com/sun/android/data/source/MovieDataSource.kt | 0 .../com/sun/android/data/source/TokenDataSource.kt | 0 .../sun/android/data/source/local/MovieLocalImpl.kt | 0 .../sun/android/data/source/local/TokenLocalImpl.kt | 0 .../android/data/source/local/api/SharedPrefsApi.kt | 0 .../source/local/api/sharedpref/SharedPrefsImpl.kt | 0 .../source/local/api/sharedpref/SharedPrefsKey.kt | 0 .../android/data/source/local/room/AppDatabase.kt | 0 .../sun/android/data/source/local/room/MovieDao.kt | 0 .../android/data/source/remote/MovieRemoteImpl.kt | 0 .../android/data/source/remote/api/ApiService.kt | 0 .../data/source/remote/api/error/ErrorResponse.kt | 0 .../source/remote/api/error/RetrofitException.kt | 0 .../android/data/source/remote/api/error/Type.kt | 0 .../source/remote/api/middleware/BooleanAdapter.kt | 0 .../source/remote/api/middleware/DoubleAdapter.kt | 0 .../source/remote/api/middleware/IntegerAdapter.kt | 0 .../source/remote/api/middleware/InterceptorImpl.kt | 0 .../data/source/remote/api/response/BaseResponse.kt | 0 .../src/main/java/com/sun/android/di/AppModule.kt | 0 .../java/com/sun/android/di/DataSourceModule.kt | 0 .../main/java/com/sun/android/di/NetWorkModule.kt | 0 .../java/com/sun/android/di/RepositoryModule.kt | 0 .../main/java/com/sun/android/di/ViewModelModule.kt | 0 .../main/java/com/sun/android/ui/MainActivity.kt | 0 .../main/java/com/sun/android/ui/MainViewModel.kt | 0 .../com/sun/android/ui/detail/DetailFragment.kt | 0 .../sun/android/ui/detail/MovieDetailViewModel.kt | 0 .../com/sun/android/ui/listmovie/MoviesFragment.kt | 0 .../com/sun/android/ui/listmovie/MoviesViewModel.kt | 0 .../android/ui/listmovie/adapter/MoviesAdapter.kt | 0 .../src/main/java/com/sun/android/utils/Constant.kt | 0 .../java/com/sun/android/utils/DateTimeUtils.kt | 0 .../src/main/java/com/sun/android/utils/LogUtils.kt | 0 .../utils/dispatchers/BaseDispatcherProvider.kt | 0 .../android/utils/dispatchers/DispatcherProvider.kt | 0 .../com/sun/android/utils/extension/AnyExtension.kt | 0 .../sun/android/utils/extension/ContextExtension.kt | 0 .../android/utils/extension/FragmentExtension.kt | 0 .../android/utils/extension/ImageViewExtention.kt | 0 .../com/sun/android/utils/livedata/SafeObserver.kt | 0 .../sun/android/utils/livedata/SingleLiveData.kt | 0 .../recycler/OnItemRecyclerViewClickListener.kt | 0 .../src/main/res/anim/slide_in_right.xml | 0 .../src/main/res/anim/slide_out_right.xml | 0 .../res/drawable-v24/ic_launcher_foreground.xml | 0 .../src/main/res/drawable/ic_back.xml | 0 .../src/main/res/drawable/ic_corona.xml | 0 .../main/res/drawable/ic_launcher_background.xml | 0 .../src/main/res/drawable/ic_star.xml | 0 .../src/main/res/layout/activity_main.xml | 0 .../src/main/res/layout/fragment_detail.xml | 0 .../src/main/res/layout/item_layout_movie.xml | 0 .../src/main/res/layout/movies_fragment.xml | 0 .../src/main/res/mipmap-anydpi-v26/ic_launcher.xml | 0 .../res/mipmap-anydpi-v26/ic_launcher_round.xml | 0 .../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin .../src/main/res/mipmap-hdpi/ic_launcher_round.webp | Bin .../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin .../src/main/res/mipmap-mdpi/ic_launcher_round.webp | Bin .../src/main/res/mipmap-xhdpi/ic_launcher.webp | Bin .../main/res/mipmap-xhdpi/ic_launcher_round.webp | Bin .../src/main/res/mipmap-xxhdpi/ic_launcher.webp | Bin .../main/res/mipmap-xxhdpi/ic_launcher_round.webp | Bin .../src/main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin .../main/res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin .../src/main/res/values-night/themes.xml | 0 .../src/main/res/values-sw1024dp/auto_dimens.xml | 0 .../src/main/res/values-sw1080dp/auto_dimens.xml | 0 .../src/main/res/values-sw1280dp/auto_dimens.xml | 0 .../src/main/res/values-sw1440dp/auto_dimens.xml | 0 .../src/main/res/values-sw2560dp/auto_dimens.xml | 0 .../src/main/res/values-sw320dp/auto_dimens.xml | 0 .../src/main/res/values-sw360dp/auto_dimens.xml | 0 .../src/main/res/values-sw3840dp/auto_dimens.xml | 0 .../src/main/res/values-sw384dp/auto_dimens.xml | 0 .../src/main/res/values-sw411dp/auto_dimens.xml | 0 .../src/main/res/values-sw480dp/auto_dimens.xml | 0 .../src/main/res/values-sw540dp/auto_dimens.xml | 0 .../src/main/res/values-sw600dp/auto_dimens.xml | 0 .../src/main/res/values-sw720dp/auto_dimens.xml | 0 .../src/main/res/values-sw800dp/auto_dimens.xml | 0 .../src/main/res/values-sw960dp/auto_dimens.xml | 0 .../src/main/res/values/colors.xml | 0 .../src/main/res/values/dimens.xml | 0 .../src/main/res/values/strings.xml | 0 .../src/main/res/values/themes.xml | 0 .../test/java/com/sun/android/ExampleUnitTest.kt | 0 settings.gradle.kts | 2 +- 103 files changed, 4 insertions(+), 1 deletion(-) rename {app => presentation}/.gitignore (100%) rename {app => presentation}/build.gradle.kts (100%) rename {app => presentation}/ktlint.gradle.kts (100%) rename {app => presentation}/proguard-rules.pro (100%) rename {app => presentation}/src/main/AndroidManifest.xml (100%) rename {app => presentation}/src/main/java/com/sun/android/AndroidApplication.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/base/BaseActivity.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/base/BaseFragment.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/MovieRepository.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/TokenRepository.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/model/Movie.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/repository/MovieRepositoryImpl.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/repository/TokenRepositoryImpl.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/source/MovieDataSource.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/source/TokenDataSource.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/source/local/MovieLocalImpl.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/source/local/TokenLocalImpl.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/source/local/api/SharedPrefsApi.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/source/local/api/sharedpref/SharedPrefsImpl.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/source/local/api/sharedpref/SharedPrefsKey.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/source/local/room/AppDatabase.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/source/local/room/MovieDao.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/source/remote/MovieRemoteImpl.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/source/remote/api/ApiService.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/source/remote/api/error/ErrorResponse.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/source/remote/api/error/RetrofitException.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/source/remote/api/error/Type.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/source/remote/api/middleware/BooleanAdapter.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/source/remote/api/middleware/DoubleAdapter.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/source/remote/api/middleware/IntegerAdapter.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/source/remote/api/middleware/InterceptorImpl.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/data/source/remote/api/response/BaseResponse.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/di/AppModule.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/di/DataSourceModule.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/di/NetWorkModule.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/di/RepositoryModule.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/di/ViewModelModule.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/ui/MainActivity.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/ui/MainViewModel.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/ui/detail/DetailFragment.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/ui/detail/MovieDetailViewModel.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/ui/listmovie/MoviesFragment.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/ui/listmovie/adapter/MoviesAdapter.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/utils/Constant.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/utils/DateTimeUtils.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/utils/LogUtils.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/utils/dispatchers/BaseDispatcherProvider.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/utils/dispatchers/DispatcherProvider.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/utils/extension/AnyExtension.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/utils/extension/ContextExtension.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/utils/extension/FragmentExtension.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/utils/extension/ImageViewExtention.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/utils/livedata/SafeObserver.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/utils/livedata/SingleLiveData.kt (100%) rename {app => presentation}/src/main/java/com/sun/android/utils/recycler/OnItemRecyclerViewClickListener.kt (100%) rename {app => presentation}/src/main/res/anim/slide_in_right.xml (100%) rename {app => presentation}/src/main/res/anim/slide_out_right.xml (100%) rename {app => presentation}/src/main/res/drawable-v24/ic_launcher_foreground.xml (100%) rename {app => presentation}/src/main/res/drawable/ic_back.xml (100%) rename {app => presentation}/src/main/res/drawable/ic_corona.xml (100%) rename {app => presentation}/src/main/res/drawable/ic_launcher_background.xml (100%) rename {app => presentation}/src/main/res/drawable/ic_star.xml (100%) rename {app => presentation}/src/main/res/layout/activity_main.xml (100%) rename {app => presentation}/src/main/res/layout/fragment_detail.xml (100%) rename {app => presentation}/src/main/res/layout/item_layout_movie.xml (100%) rename {app => presentation}/src/main/res/layout/movies_fragment.xml (100%) rename {app => presentation}/src/main/res/mipmap-anydpi-v26/ic_launcher.xml (100%) rename {app => presentation}/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml (100%) rename {app => presentation}/src/main/res/mipmap-hdpi/ic_launcher.webp (100%) rename {app => presentation}/src/main/res/mipmap-hdpi/ic_launcher_round.webp (100%) rename {app => presentation}/src/main/res/mipmap-mdpi/ic_launcher.webp (100%) rename {app => presentation}/src/main/res/mipmap-mdpi/ic_launcher_round.webp (100%) rename {app => presentation}/src/main/res/mipmap-xhdpi/ic_launcher.webp (100%) rename {app => presentation}/src/main/res/mipmap-xhdpi/ic_launcher_round.webp (100%) rename {app => presentation}/src/main/res/mipmap-xxhdpi/ic_launcher.webp (100%) rename {app => presentation}/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp (100%) rename {app => presentation}/src/main/res/mipmap-xxxhdpi/ic_launcher.webp (100%) rename {app => presentation}/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp (100%) rename {app => presentation}/src/main/res/values-night/themes.xml (100%) rename {app => presentation}/src/main/res/values-sw1024dp/auto_dimens.xml (100%) rename {app => presentation}/src/main/res/values-sw1080dp/auto_dimens.xml (100%) rename {app => presentation}/src/main/res/values-sw1280dp/auto_dimens.xml (100%) rename {app => presentation}/src/main/res/values-sw1440dp/auto_dimens.xml (100%) rename {app => presentation}/src/main/res/values-sw2560dp/auto_dimens.xml (100%) rename {app => presentation}/src/main/res/values-sw320dp/auto_dimens.xml (100%) rename {app => presentation}/src/main/res/values-sw360dp/auto_dimens.xml (100%) rename {app => presentation}/src/main/res/values-sw3840dp/auto_dimens.xml (100%) rename {app => presentation}/src/main/res/values-sw384dp/auto_dimens.xml (100%) rename {app => presentation}/src/main/res/values-sw411dp/auto_dimens.xml (100%) rename {app => presentation}/src/main/res/values-sw480dp/auto_dimens.xml (100%) rename {app => presentation}/src/main/res/values-sw540dp/auto_dimens.xml (100%) rename {app => presentation}/src/main/res/values-sw600dp/auto_dimens.xml (100%) rename {app => presentation}/src/main/res/values-sw720dp/auto_dimens.xml (100%) rename {app => presentation}/src/main/res/values-sw800dp/auto_dimens.xml (100%) rename {app => presentation}/src/main/res/values-sw960dp/auto_dimens.xml (100%) rename {app => presentation}/src/main/res/values/colors.xml (100%) rename {app => presentation}/src/main/res/values/dimens.xml (100%) rename {app => presentation}/src/main/res/values/strings.xml (100%) rename {app => presentation}/src/main/res/values/themes.xml (100%) rename {app => presentation}/src/test/java/com/sun/android/ExampleUnitTest.kt (100%) diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index 0c0c338..3211ffb 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -5,6 +5,9 @@ + + + \ No newline at end of file diff --git a/app/.gitignore b/presentation/.gitignore similarity index 100% rename from app/.gitignore rename to presentation/.gitignore diff --git a/app/build.gradle.kts b/presentation/build.gradle.kts similarity index 100% rename from app/build.gradle.kts rename to presentation/build.gradle.kts diff --git a/app/ktlint.gradle.kts b/presentation/ktlint.gradle.kts similarity index 100% rename from app/ktlint.gradle.kts rename to presentation/ktlint.gradle.kts diff --git a/app/proguard-rules.pro b/presentation/proguard-rules.pro similarity index 100% rename from app/proguard-rules.pro rename to presentation/proguard-rules.pro diff --git a/app/src/main/AndroidManifest.xml b/presentation/src/main/AndroidManifest.xml similarity index 100% rename from app/src/main/AndroidManifest.xml rename to presentation/src/main/AndroidManifest.xml diff --git a/app/src/main/java/com/sun/android/AndroidApplication.kt b/presentation/src/main/java/com/sun/android/AndroidApplication.kt similarity index 100% rename from app/src/main/java/com/sun/android/AndroidApplication.kt rename to presentation/src/main/java/com/sun/android/AndroidApplication.kt diff --git a/app/src/main/java/com/sun/android/base/BaseActivity.kt b/presentation/src/main/java/com/sun/android/base/BaseActivity.kt similarity index 100% rename from app/src/main/java/com/sun/android/base/BaseActivity.kt rename to presentation/src/main/java/com/sun/android/base/BaseActivity.kt diff --git a/app/src/main/java/com/sun/android/base/BaseFragment.kt b/presentation/src/main/java/com/sun/android/base/BaseFragment.kt similarity index 100% rename from app/src/main/java/com/sun/android/base/BaseFragment.kt rename to presentation/src/main/java/com/sun/android/base/BaseFragment.kt diff --git a/app/src/main/java/com/sun/android/data/MovieRepository.kt b/presentation/src/main/java/com/sun/android/data/MovieRepository.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/MovieRepository.kt rename to presentation/src/main/java/com/sun/android/data/MovieRepository.kt diff --git a/app/src/main/java/com/sun/android/data/TokenRepository.kt b/presentation/src/main/java/com/sun/android/data/TokenRepository.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/TokenRepository.kt rename to presentation/src/main/java/com/sun/android/data/TokenRepository.kt diff --git a/app/src/main/java/com/sun/android/data/model/Movie.kt b/presentation/src/main/java/com/sun/android/data/model/Movie.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/model/Movie.kt rename to presentation/src/main/java/com/sun/android/data/model/Movie.kt diff --git a/app/src/main/java/com/sun/android/data/repository/MovieRepositoryImpl.kt b/presentation/src/main/java/com/sun/android/data/repository/MovieRepositoryImpl.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/repository/MovieRepositoryImpl.kt rename to presentation/src/main/java/com/sun/android/data/repository/MovieRepositoryImpl.kt diff --git a/app/src/main/java/com/sun/android/data/repository/TokenRepositoryImpl.kt b/presentation/src/main/java/com/sun/android/data/repository/TokenRepositoryImpl.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/repository/TokenRepositoryImpl.kt rename to presentation/src/main/java/com/sun/android/data/repository/TokenRepositoryImpl.kt diff --git a/app/src/main/java/com/sun/android/data/source/MovieDataSource.kt b/presentation/src/main/java/com/sun/android/data/source/MovieDataSource.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/source/MovieDataSource.kt rename to presentation/src/main/java/com/sun/android/data/source/MovieDataSource.kt diff --git a/app/src/main/java/com/sun/android/data/source/TokenDataSource.kt b/presentation/src/main/java/com/sun/android/data/source/TokenDataSource.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/source/TokenDataSource.kt rename to presentation/src/main/java/com/sun/android/data/source/TokenDataSource.kt diff --git a/app/src/main/java/com/sun/android/data/source/local/MovieLocalImpl.kt b/presentation/src/main/java/com/sun/android/data/source/local/MovieLocalImpl.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/source/local/MovieLocalImpl.kt rename to presentation/src/main/java/com/sun/android/data/source/local/MovieLocalImpl.kt diff --git a/app/src/main/java/com/sun/android/data/source/local/TokenLocalImpl.kt b/presentation/src/main/java/com/sun/android/data/source/local/TokenLocalImpl.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/source/local/TokenLocalImpl.kt rename to presentation/src/main/java/com/sun/android/data/source/local/TokenLocalImpl.kt diff --git a/app/src/main/java/com/sun/android/data/source/local/api/SharedPrefsApi.kt b/presentation/src/main/java/com/sun/android/data/source/local/api/SharedPrefsApi.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/source/local/api/SharedPrefsApi.kt rename to presentation/src/main/java/com/sun/android/data/source/local/api/SharedPrefsApi.kt diff --git a/app/src/main/java/com/sun/android/data/source/local/api/sharedpref/SharedPrefsImpl.kt b/presentation/src/main/java/com/sun/android/data/source/local/api/sharedpref/SharedPrefsImpl.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/source/local/api/sharedpref/SharedPrefsImpl.kt rename to presentation/src/main/java/com/sun/android/data/source/local/api/sharedpref/SharedPrefsImpl.kt diff --git a/app/src/main/java/com/sun/android/data/source/local/api/sharedpref/SharedPrefsKey.kt b/presentation/src/main/java/com/sun/android/data/source/local/api/sharedpref/SharedPrefsKey.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/source/local/api/sharedpref/SharedPrefsKey.kt rename to presentation/src/main/java/com/sun/android/data/source/local/api/sharedpref/SharedPrefsKey.kt diff --git a/app/src/main/java/com/sun/android/data/source/local/room/AppDatabase.kt b/presentation/src/main/java/com/sun/android/data/source/local/room/AppDatabase.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/source/local/room/AppDatabase.kt rename to presentation/src/main/java/com/sun/android/data/source/local/room/AppDatabase.kt diff --git a/app/src/main/java/com/sun/android/data/source/local/room/MovieDao.kt b/presentation/src/main/java/com/sun/android/data/source/local/room/MovieDao.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/source/local/room/MovieDao.kt rename to presentation/src/main/java/com/sun/android/data/source/local/room/MovieDao.kt diff --git a/app/src/main/java/com/sun/android/data/source/remote/MovieRemoteImpl.kt b/presentation/src/main/java/com/sun/android/data/source/remote/MovieRemoteImpl.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/source/remote/MovieRemoteImpl.kt rename to presentation/src/main/java/com/sun/android/data/source/remote/MovieRemoteImpl.kt diff --git a/app/src/main/java/com/sun/android/data/source/remote/api/ApiService.kt b/presentation/src/main/java/com/sun/android/data/source/remote/api/ApiService.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/source/remote/api/ApiService.kt rename to presentation/src/main/java/com/sun/android/data/source/remote/api/ApiService.kt diff --git a/app/src/main/java/com/sun/android/data/source/remote/api/error/ErrorResponse.kt b/presentation/src/main/java/com/sun/android/data/source/remote/api/error/ErrorResponse.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/source/remote/api/error/ErrorResponse.kt rename to presentation/src/main/java/com/sun/android/data/source/remote/api/error/ErrorResponse.kt diff --git a/app/src/main/java/com/sun/android/data/source/remote/api/error/RetrofitException.kt b/presentation/src/main/java/com/sun/android/data/source/remote/api/error/RetrofitException.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/source/remote/api/error/RetrofitException.kt rename to presentation/src/main/java/com/sun/android/data/source/remote/api/error/RetrofitException.kt diff --git a/app/src/main/java/com/sun/android/data/source/remote/api/error/Type.kt b/presentation/src/main/java/com/sun/android/data/source/remote/api/error/Type.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/source/remote/api/error/Type.kt rename to presentation/src/main/java/com/sun/android/data/source/remote/api/error/Type.kt diff --git a/app/src/main/java/com/sun/android/data/source/remote/api/middleware/BooleanAdapter.kt b/presentation/src/main/java/com/sun/android/data/source/remote/api/middleware/BooleanAdapter.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/source/remote/api/middleware/BooleanAdapter.kt rename to presentation/src/main/java/com/sun/android/data/source/remote/api/middleware/BooleanAdapter.kt diff --git a/app/src/main/java/com/sun/android/data/source/remote/api/middleware/DoubleAdapter.kt b/presentation/src/main/java/com/sun/android/data/source/remote/api/middleware/DoubleAdapter.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/source/remote/api/middleware/DoubleAdapter.kt rename to presentation/src/main/java/com/sun/android/data/source/remote/api/middleware/DoubleAdapter.kt diff --git a/app/src/main/java/com/sun/android/data/source/remote/api/middleware/IntegerAdapter.kt b/presentation/src/main/java/com/sun/android/data/source/remote/api/middleware/IntegerAdapter.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/source/remote/api/middleware/IntegerAdapter.kt rename to presentation/src/main/java/com/sun/android/data/source/remote/api/middleware/IntegerAdapter.kt diff --git a/app/src/main/java/com/sun/android/data/source/remote/api/middleware/InterceptorImpl.kt b/presentation/src/main/java/com/sun/android/data/source/remote/api/middleware/InterceptorImpl.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/source/remote/api/middleware/InterceptorImpl.kt rename to presentation/src/main/java/com/sun/android/data/source/remote/api/middleware/InterceptorImpl.kt diff --git a/app/src/main/java/com/sun/android/data/source/remote/api/response/BaseResponse.kt b/presentation/src/main/java/com/sun/android/data/source/remote/api/response/BaseResponse.kt similarity index 100% rename from app/src/main/java/com/sun/android/data/source/remote/api/response/BaseResponse.kt rename to presentation/src/main/java/com/sun/android/data/source/remote/api/response/BaseResponse.kt diff --git a/app/src/main/java/com/sun/android/di/AppModule.kt b/presentation/src/main/java/com/sun/android/di/AppModule.kt similarity index 100% rename from app/src/main/java/com/sun/android/di/AppModule.kt rename to presentation/src/main/java/com/sun/android/di/AppModule.kt diff --git a/app/src/main/java/com/sun/android/di/DataSourceModule.kt b/presentation/src/main/java/com/sun/android/di/DataSourceModule.kt similarity index 100% rename from app/src/main/java/com/sun/android/di/DataSourceModule.kt rename to presentation/src/main/java/com/sun/android/di/DataSourceModule.kt diff --git a/app/src/main/java/com/sun/android/di/NetWorkModule.kt b/presentation/src/main/java/com/sun/android/di/NetWorkModule.kt similarity index 100% rename from app/src/main/java/com/sun/android/di/NetWorkModule.kt rename to presentation/src/main/java/com/sun/android/di/NetWorkModule.kt diff --git a/app/src/main/java/com/sun/android/di/RepositoryModule.kt b/presentation/src/main/java/com/sun/android/di/RepositoryModule.kt similarity index 100% rename from app/src/main/java/com/sun/android/di/RepositoryModule.kt rename to presentation/src/main/java/com/sun/android/di/RepositoryModule.kt diff --git a/app/src/main/java/com/sun/android/di/ViewModelModule.kt b/presentation/src/main/java/com/sun/android/di/ViewModelModule.kt similarity index 100% rename from app/src/main/java/com/sun/android/di/ViewModelModule.kt rename to presentation/src/main/java/com/sun/android/di/ViewModelModule.kt diff --git a/app/src/main/java/com/sun/android/ui/MainActivity.kt b/presentation/src/main/java/com/sun/android/ui/MainActivity.kt similarity index 100% rename from app/src/main/java/com/sun/android/ui/MainActivity.kt rename to presentation/src/main/java/com/sun/android/ui/MainActivity.kt diff --git a/app/src/main/java/com/sun/android/ui/MainViewModel.kt b/presentation/src/main/java/com/sun/android/ui/MainViewModel.kt similarity index 100% rename from app/src/main/java/com/sun/android/ui/MainViewModel.kt rename to presentation/src/main/java/com/sun/android/ui/MainViewModel.kt diff --git a/app/src/main/java/com/sun/android/ui/detail/DetailFragment.kt b/presentation/src/main/java/com/sun/android/ui/detail/DetailFragment.kt similarity index 100% rename from app/src/main/java/com/sun/android/ui/detail/DetailFragment.kt rename to presentation/src/main/java/com/sun/android/ui/detail/DetailFragment.kt diff --git a/app/src/main/java/com/sun/android/ui/detail/MovieDetailViewModel.kt b/presentation/src/main/java/com/sun/android/ui/detail/MovieDetailViewModel.kt similarity index 100% rename from app/src/main/java/com/sun/android/ui/detail/MovieDetailViewModel.kt rename to presentation/src/main/java/com/sun/android/ui/detail/MovieDetailViewModel.kt diff --git a/app/src/main/java/com/sun/android/ui/listmovie/MoviesFragment.kt b/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesFragment.kt similarity index 100% rename from app/src/main/java/com/sun/android/ui/listmovie/MoviesFragment.kt rename to presentation/src/main/java/com/sun/android/ui/listmovie/MoviesFragment.kt diff --git a/app/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt b/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt similarity index 100% rename from app/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt rename to presentation/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt diff --git a/app/src/main/java/com/sun/android/ui/listmovie/adapter/MoviesAdapter.kt b/presentation/src/main/java/com/sun/android/ui/listmovie/adapter/MoviesAdapter.kt similarity index 100% rename from app/src/main/java/com/sun/android/ui/listmovie/adapter/MoviesAdapter.kt rename to presentation/src/main/java/com/sun/android/ui/listmovie/adapter/MoviesAdapter.kt diff --git a/app/src/main/java/com/sun/android/utils/Constant.kt b/presentation/src/main/java/com/sun/android/utils/Constant.kt similarity index 100% rename from app/src/main/java/com/sun/android/utils/Constant.kt rename to presentation/src/main/java/com/sun/android/utils/Constant.kt diff --git a/app/src/main/java/com/sun/android/utils/DateTimeUtils.kt b/presentation/src/main/java/com/sun/android/utils/DateTimeUtils.kt similarity index 100% rename from app/src/main/java/com/sun/android/utils/DateTimeUtils.kt rename to presentation/src/main/java/com/sun/android/utils/DateTimeUtils.kt diff --git a/app/src/main/java/com/sun/android/utils/LogUtils.kt b/presentation/src/main/java/com/sun/android/utils/LogUtils.kt similarity index 100% rename from app/src/main/java/com/sun/android/utils/LogUtils.kt rename to presentation/src/main/java/com/sun/android/utils/LogUtils.kt diff --git a/app/src/main/java/com/sun/android/utils/dispatchers/BaseDispatcherProvider.kt b/presentation/src/main/java/com/sun/android/utils/dispatchers/BaseDispatcherProvider.kt similarity index 100% rename from app/src/main/java/com/sun/android/utils/dispatchers/BaseDispatcherProvider.kt rename to presentation/src/main/java/com/sun/android/utils/dispatchers/BaseDispatcherProvider.kt diff --git a/app/src/main/java/com/sun/android/utils/dispatchers/DispatcherProvider.kt b/presentation/src/main/java/com/sun/android/utils/dispatchers/DispatcherProvider.kt similarity index 100% rename from app/src/main/java/com/sun/android/utils/dispatchers/DispatcherProvider.kt rename to presentation/src/main/java/com/sun/android/utils/dispatchers/DispatcherProvider.kt diff --git a/app/src/main/java/com/sun/android/utils/extension/AnyExtension.kt b/presentation/src/main/java/com/sun/android/utils/extension/AnyExtension.kt similarity index 100% rename from app/src/main/java/com/sun/android/utils/extension/AnyExtension.kt rename to presentation/src/main/java/com/sun/android/utils/extension/AnyExtension.kt diff --git a/app/src/main/java/com/sun/android/utils/extension/ContextExtension.kt b/presentation/src/main/java/com/sun/android/utils/extension/ContextExtension.kt similarity index 100% rename from app/src/main/java/com/sun/android/utils/extension/ContextExtension.kt rename to presentation/src/main/java/com/sun/android/utils/extension/ContextExtension.kt diff --git a/app/src/main/java/com/sun/android/utils/extension/FragmentExtension.kt b/presentation/src/main/java/com/sun/android/utils/extension/FragmentExtension.kt similarity index 100% rename from app/src/main/java/com/sun/android/utils/extension/FragmentExtension.kt rename to presentation/src/main/java/com/sun/android/utils/extension/FragmentExtension.kt diff --git a/app/src/main/java/com/sun/android/utils/extension/ImageViewExtention.kt b/presentation/src/main/java/com/sun/android/utils/extension/ImageViewExtention.kt similarity index 100% rename from app/src/main/java/com/sun/android/utils/extension/ImageViewExtention.kt rename to presentation/src/main/java/com/sun/android/utils/extension/ImageViewExtention.kt diff --git a/app/src/main/java/com/sun/android/utils/livedata/SafeObserver.kt b/presentation/src/main/java/com/sun/android/utils/livedata/SafeObserver.kt similarity index 100% rename from app/src/main/java/com/sun/android/utils/livedata/SafeObserver.kt rename to presentation/src/main/java/com/sun/android/utils/livedata/SafeObserver.kt diff --git a/app/src/main/java/com/sun/android/utils/livedata/SingleLiveData.kt b/presentation/src/main/java/com/sun/android/utils/livedata/SingleLiveData.kt similarity index 100% rename from app/src/main/java/com/sun/android/utils/livedata/SingleLiveData.kt rename to presentation/src/main/java/com/sun/android/utils/livedata/SingleLiveData.kt diff --git a/app/src/main/java/com/sun/android/utils/recycler/OnItemRecyclerViewClickListener.kt b/presentation/src/main/java/com/sun/android/utils/recycler/OnItemRecyclerViewClickListener.kt similarity index 100% rename from app/src/main/java/com/sun/android/utils/recycler/OnItemRecyclerViewClickListener.kt rename to presentation/src/main/java/com/sun/android/utils/recycler/OnItemRecyclerViewClickListener.kt diff --git a/app/src/main/res/anim/slide_in_right.xml b/presentation/src/main/res/anim/slide_in_right.xml similarity index 100% rename from app/src/main/res/anim/slide_in_right.xml rename to presentation/src/main/res/anim/slide_in_right.xml diff --git a/app/src/main/res/anim/slide_out_right.xml b/presentation/src/main/res/anim/slide_out_right.xml similarity index 100% rename from app/src/main/res/anim/slide_out_right.xml rename to presentation/src/main/res/anim/slide_out_right.xml diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/presentation/src/main/res/drawable-v24/ic_launcher_foreground.xml similarity index 100% rename from app/src/main/res/drawable-v24/ic_launcher_foreground.xml rename to presentation/src/main/res/drawable-v24/ic_launcher_foreground.xml diff --git a/app/src/main/res/drawable/ic_back.xml b/presentation/src/main/res/drawable/ic_back.xml similarity index 100% rename from app/src/main/res/drawable/ic_back.xml rename to presentation/src/main/res/drawable/ic_back.xml diff --git a/app/src/main/res/drawable/ic_corona.xml b/presentation/src/main/res/drawable/ic_corona.xml similarity index 100% rename from app/src/main/res/drawable/ic_corona.xml rename to presentation/src/main/res/drawable/ic_corona.xml diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/presentation/src/main/res/drawable/ic_launcher_background.xml similarity index 100% rename from app/src/main/res/drawable/ic_launcher_background.xml rename to presentation/src/main/res/drawable/ic_launcher_background.xml diff --git a/app/src/main/res/drawable/ic_star.xml b/presentation/src/main/res/drawable/ic_star.xml similarity index 100% rename from app/src/main/res/drawable/ic_star.xml rename to presentation/src/main/res/drawable/ic_star.xml diff --git a/app/src/main/res/layout/activity_main.xml b/presentation/src/main/res/layout/activity_main.xml similarity index 100% rename from app/src/main/res/layout/activity_main.xml rename to presentation/src/main/res/layout/activity_main.xml diff --git a/app/src/main/res/layout/fragment_detail.xml b/presentation/src/main/res/layout/fragment_detail.xml similarity index 100% rename from app/src/main/res/layout/fragment_detail.xml rename to presentation/src/main/res/layout/fragment_detail.xml diff --git a/app/src/main/res/layout/item_layout_movie.xml b/presentation/src/main/res/layout/item_layout_movie.xml similarity index 100% rename from app/src/main/res/layout/item_layout_movie.xml rename to presentation/src/main/res/layout/item_layout_movie.xml diff --git a/app/src/main/res/layout/movies_fragment.xml b/presentation/src/main/res/layout/movies_fragment.xml similarity index 100% rename from app/src/main/res/layout/movies_fragment.xml rename to presentation/src/main/res/layout/movies_fragment.xml diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/presentation/src/main/res/mipmap-anydpi-v26/ic_launcher.xml similarity index 100% rename from app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml rename to presentation/src/main/res/mipmap-anydpi-v26/ic_launcher.xml diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/presentation/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml similarity index 100% rename from app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml rename to presentation/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/presentation/src/main/res/mipmap-hdpi/ic_launcher.webp similarity index 100% rename from app/src/main/res/mipmap-hdpi/ic_launcher.webp rename to presentation/src/main/res/mipmap-hdpi/ic_launcher.webp diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/presentation/src/main/res/mipmap-hdpi/ic_launcher_round.webp similarity index 100% rename from app/src/main/res/mipmap-hdpi/ic_launcher_round.webp rename to presentation/src/main/res/mipmap-hdpi/ic_launcher_round.webp diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/presentation/src/main/res/mipmap-mdpi/ic_launcher.webp similarity index 100% rename from app/src/main/res/mipmap-mdpi/ic_launcher.webp rename to presentation/src/main/res/mipmap-mdpi/ic_launcher.webp diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/presentation/src/main/res/mipmap-mdpi/ic_launcher_round.webp similarity index 100% rename from app/src/main/res/mipmap-mdpi/ic_launcher_round.webp rename to presentation/src/main/res/mipmap-mdpi/ic_launcher_round.webp diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/presentation/src/main/res/mipmap-xhdpi/ic_launcher.webp similarity index 100% rename from app/src/main/res/mipmap-xhdpi/ic_launcher.webp rename to presentation/src/main/res/mipmap-xhdpi/ic_launcher.webp diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/presentation/src/main/res/mipmap-xhdpi/ic_launcher_round.webp similarity index 100% rename from app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp rename to presentation/src/main/res/mipmap-xhdpi/ic_launcher_round.webp diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/presentation/src/main/res/mipmap-xxhdpi/ic_launcher.webp similarity index 100% rename from app/src/main/res/mipmap-xxhdpi/ic_launcher.webp rename to presentation/src/main/res/mipmap-xxhdpi/ic_launcher.webp diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/presentation/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp similarity index 100% rename from app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp rename to presentation/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/presentation/src/main/res/mipmap-xxxhdpi/ic_launcher.webp similarity index 100% rename from app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp rename to presentation/src/main/res/mipmap-xxxhdpi/ic_launcher.webp diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/presentation/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp similarity index 100% rename from app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp rename to presentation/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp diff --git a/app/src/main/res/values-night/themes.xml b/presentation/src/main/res/values-night/themes.xml similarity index 100% rename from app/src/main/res/values-night/themes.xml rename to presentation/src/main/res/values-night/themes.xml diff --git a/app/src/main/res/values-sw1024dp/auto_dimens.xml b/presentation/src/main/res/values-sw1024dp/auto_dimens.xml similarity index 100% rename from app/src/main/res/values-sw1024dp/auto_dimens.xml rename to presentation/src/main/res/values-sw1024dp/auto_dimens.xml diff --git a/app/src/main/res/values-sw1080dp/auto_dimens.xml b/presentation/src/main/res/values-sw1080dp/auto_dimens.xml similarity index 100% rename from app/src/main/res/values-sw1080dp/auto_dimens.xml rename to presentation/src/main/res/values-sw1080dp/auto_dimens.xml diff --git a/app/src/main/res/values-sw1280dp/auto_dimens.xml b/presentation/src/main/res/values-sw1280dp/auto_dimens.xml similarity index 100% rename from app/src/main/res/values-sw1280dp/auto_dimens.xml rename to presentation/src/main/res/values-sw1280dp/auto_dimens.xml diff --git a/app/src/main/res/values-sw1440dp/auto_dimens.xml b/presentation/src/main/res/values-sw1440dp/auto_dimens.xml similarity index 100% rename from app/src/main/res/values-sw1440dp/auto_dimens.xml rename to presentation/src/main/res/values-sw1440dp/auto_dimens.xml diff --git a/app/src/main/res/values-sw2560dp/auto_dimens.xml b/presentation/src/main/res/values-sw2560dp/auto_dimens.xml similarity index 100% rename from app/src/main/res/values-sw2560dp/auto_dimens.xml rename to presentation/src/main/res/values-sw2560dp/auto_dimens.xml diff --git a/app/src/main/res/values-sw320dp/auto_dimens.xml b/presentation/src/main/res/values-sw320dp/auto_dimens.xml similarity index 100% rename from app/src/main/res/values-sw320dp/auto_dimens.xml rename to presentation/src/main/res/values-sw320dp/auto_dimens.xml diff --git a/app/src/main/res/values-sw360dp/auto_dimens.xml b/presentation/src/main/res/values-sw360dp/auto_dimens.xml similarity index 100% rename from app/src/main/res/values-sw360dp/auto_dimens.xml rename to presentation/src/main/res/values-sw360dp/auto_dimens.xml diff --git a/app/src/main/res/values-sw3840dp/auto_dimens.xml b/presentation/src/main/res/values-sw3840dp/auto_dimens.xml similarity index 100% rename from app/src/main/res/values-sw3840dp/auto_dimens.xml rename to presentation/src/main/res/values-sw3840dp/auto_dimens.xml diff --git a/app/src/main/res/values-sw384dp/auto_dimens.xml b/presentation/src/main/res/values-sw384dp/auto_dimens.xml similarity index 100% rename from app/src/main/res/values-sw384dp/auto_dimens.xml rename to presentation/src/main/res/values-sw384dp/auto_dimens.xml diff --git a/app/src/main/res/values-sw411dp/auto_dimens.xml b/presentation/src/main/res/values-sw411dp/auto_dimens.xml similarity index 100% rename from app/src/main/res/values-sw411dp/auto_dimens.xml rename to presentation/src/main/res/values-sw411dp/auto_dimens.xml diff --git a/app/src/main/res/values-sw480dp/auto_dimens.xml b/presentation/src/main/res/values-sw480dp/auto_dimens.xml similarity index 100% rename from app/src/main/res/values-sw480dp/auto_dimens.xml rename to presentation/src/main/res/values-sw480dp/auto_dimens.xml diff --git a/app/src/main/res/values-sw540dp/auto_dimens.xml b/presentation/src/main/res/values-sw540dp/auto_dimens.xml similarity index 100% rename from app/src/main/res/values-sw540dp/auto_dimens.xml rename to presentation/src/main/res/values-sw540dp/auto_dimens.xml diff --git a/app/src/main/res/values-sw600dp/auto_dimens.xml b/presentation/src/main/res/values-sw600dp/auto_dimens.xml similarity index 100% rename from app/src/main/res/values-sw600dp/auto_dimens.xml rename to presentation/src/main/res/values-sw600dp/auto_dimens.xml diff --git a/app/src/main/res/values-sw720dp/auto_dimens.xml b/presentation/src/main/res/values-sw720dp/auto_dimens.xml similarity index 100% rename from app/src/main/res/values-sw720dp/auto_dimens.xml rename to presentation/src/main/res/values-sw720dp/auto_dimens.xml diff --git a/app/src/main/res/values-sw800dp/auto_dimens.xml b/presentation/src/main/res/values-sw800dp/auto_dimens.xml similarity index 100% rename from app/src/main/res/values-sw800dp/auto_dimens.xml rename to presentation/src/main/res/values-sw800dp/auto_dimens.xml diff --git a/app/src/main/res/values-sw960dp/auto_dimens.xml b/presentation/src/main/res/values-sw960dp/auto_dimens.xml similarity index 100% rename from app/src/main/res/values-sw960dp/auto_dimens.xml rename to presentation/src/main/res/values-sw960dp/auto_dimens.xml diff --git a/app/src/main/res/values/colors.xml b/presentation/src/main/res/values/colors.xml similarity index 100% rename from app/src/main/res/values/colors.xml rename to presentation/src/main/res/values/colors.xml diff --git a/app/src/main/res/values/dimens.xml b/presentation/src/main/res/values/dimens.xml similarity index 100% rename from app/src/main/res/values/dimens.xml rename to presentation/src/main/res/values/dimens.xml diff --git a/app/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml similarity index 100% rename from app/src/main/res/values/strings.xml rename to presentation/src/main/res/values/strings.xml diff --git a/app/src/main/res/values/themes.xml b/presentation/src/main/res/values/themes.xml similarity index 100% rename from app/src/main/res/values/themes.xml rename to presentation/src/main/res/values/themes.xml diff --git a/app/src/test/java/com/sun/android/ExampleUnitTest.kt b/presentation/src/test/java/com/sun/android/ExampleUnitTest.kt similarity index 100% rename from app/src/test/java/com/sun/android/ExampleUnitTest.kt rename to presentation/src/test/java/com/sun/android/ExampleUnitTest.kt diff --git a/settings.gradle.kts b/settings.gradle.kts index 208a440..dffdb49 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,2 +1,2 @@ rootProject.name = "Structure_Android" -include (":app") +include (":presentation") From cbf9663f696d23f666c4c5b617102b268f270ca8 Mon Sep 17 00:00:00 2001 From: Company Date: Mon, 1 Apr 2024 06:05:14 +0700 Subject: [PATCH 3/6] [modify] seperate package --- data/.gitignore | 1 + data/build.gradle.kts | 66 +++++++++++++++++++ data/consumer-rules.pro | 0 data/proguard-rules.pro | 21 ++++++ .../com/sun/data/ExampleInstrumentedTest.kt | 24 +++++++ data/src/main/AndroidManifest.xml | 4 ++ .../java/com/sun/data/entities/MovieData.kt | 6 +- .../java/com/sun/data/entities/MovieDbData.kt | 15 +++++ .../data/repository/MovieRepositoryImpl.kt | 10 +-- .../data/repository/TokenRepositoryImpl.kt | 2 +- .../com/sun/data/source/MovieDataSource.kt | 24 +++++++ .../com/sun}/data/source/TokenDataSource.kt | 2 +- .../sun/data/source/local/MovieLocalImpl.kt | 18 +++++ .../sun}/data/source/local/TokenLocalImpl.kt | 8 +-- .../data/source/local/api/SharedPrefsApi.kt | 2 +- .../local/api/sharedpref/SharedPrefsImpl.kt | 4 +- .../local/api/sharedpref/SharedPrefsKey.kt | 2 +- .../data/source/local/room/AppDatabase.kt | 5 +- .../sun}/data/source/local/room/MovieDao.kt | 13 ++-- .../sun/data/source/remote/MovieRemoteImpl.kt | 17 +++++ .../sun}/data/source/remote/api/ApiService.kt | 10 +-- .../source/remote/api/error/ErrorResponse.kt | 2 +- .../remote/api/error/RetrofitException.kt | 2 +- .../sun}/data/source/remote/api/error/Type.kt | 2 +- .../remote/api/middleware/BooleanAdapter.kt | 2 +- .../remote/api/middleware/DoubleAdapter.kt | 2 +- .../remote/api/middleware/IntegerAdapter.kt | 2 +- .../remote/api/middleware/InterceptorImpl.kt | 2 +- .../remote/api/response/BaseResponse.kt | 2 +- .../test/java/com/sun/data/ExampleUnitTest.kt | 17 +++++ domain/.gitignore | 1 + domain/build.gradle.kts | 16 +++++ .../com/sun/domain/entities/MovieEntity.kt | 10 +++ .../sun/domain/repository/MovieRepository.kt | 10 +++ .../sun/domain/repository}/TokenRepository.kt | 2 +- .../com/sun/android/data/MovieRepository.kt | 10 --- .../android/data/source/MovieDataSource.kt | 24 ------- .../data/source/local/MovieLocalImpl.kt | 19 ------ .../data/source/remote/MovieRemoteImpl.kt | 17 ----- .../main/java/com/sun/android/di/AppModule.kt | 30 ++++----- .../com/sun/android/di/DataSourceModule.kt | 20 +++--- .../java/com/sun/android/di/NetWorkModule.kt | 14 ++-- .../com/sun/android/di/RepositoryModule.kt | 20 +++--- .../android/ui/detail/MovieDetailViewModel.kt | 8 +-- .../android/ui/listmovie/MoviesFragment.kt | 6 +- .../android/ui/listmovie/MoviesViewModel.kt | 8 +-- .../ui/listmovie/adapter/MoviesAdapter.kt | 18 ++--- settings.gradle.kts | 2 + 48 files changed, 349 insertions(+), 173 deletions(-) create mode 100644 data/.gitignore create mode 100644 data/build.gradle.kts create mode 100644 data/consumer-rules.pro create mode 100644 data/proguard-rules.pro create mode 100644 data/src/androidTest/java/com/sun/data/ExampleInstrumentedTest.kt create mode 100644 data/src/main/AndroidManifest.xml rename presentation/src/main/java/com/sun/android/data/model/Movie.kt => data/src/main/java/com/sun/data/entities/MovieData.kt (89%) create mode 100644 data/src/main/java/com/sun/data/entities/MovieDbData.kt rename {presentation/src/main/java/com/sun/android => data/src/main/java/com/sun}/data/repository/MovieRepositoryImpl.kt (81%) rename {presentation/src/main/java/com/sun/android => data/src/main/java/com/sun}/data/repository/TokenRepositoryImpl.kt (89%) create mode 100644 data/src/main/java/com/sun/data/source/MovieDataSource.kt rename {presentation/src/main/java/com/sun/android => data/src/main/java/com/sun}/data/source/TokenDataSource.kt (83%) create mode 100644 data/src/main/java/com/sun/data/source/local/MovieLocalImpl.kt rename {presentation/src/main/java/com/sun/android => data/src/main/java/com/sun}/data/source/local/TokenLocalImpl.kt (63%) rename {presentation/src/main/java/com/sun/android => data/src/main/java/com/sun}/data/source/local/api/SharedPrefsApi.kt (92%) rename {presentation/src/main/java/com/sun/android => data/src/main/java/com/sun}/data/source/local/api/sharedpref/SharedPrefsImpl.kt (95%) rename {presentation/src/main/java/com/sun/android => data/src/main/java/com/sun}/data/source/local/api/sharedpref/SharedPrefsKey.kt (67%) rename {presentation/src/main/java/com/sun/android => data/src/main/java/com/sun}/data/source/local/room/AppDatabase.kt (82%) rename {presentation/src/main/java/com/sun/android => data/src/main/java/com/sun}/data/source/local/room/MovieDao.kt (50%) create mode 100644 data/src/main/java/com/sun/data/source/remote/MovieRemoteImpl.kt rename {presentation/src/main/java/com/sun/android => data/src/main/java/com/sun}/data/source/remote/api/ApiService.kt (64%) rename {presentation/src/main/java/com/sun/android => data/src/main/java/com/sun}/data/source/remote/api/error/ErrorResponse.kt (97%) rename {presentation/src/main/java/com/sun/android => data/src/main/java/com/sun}/data/source/remote/api/error/RetrofitException.kt (98%) rename {presentation/src/main/java/com/sun/android => data/src/main/java/com/sun}/data/source/remote/api/error/Type.kt (92%) rename {presentation/src/main/java/com/sun/android => data/src/main/java/com/sun}/data/source/remote/api/middleware/BooleanAdapter.kt (93%) rename {presentation/src/main/java/com/sun/android => data/src/main/java/com/sun}/data/source/remote/api/middleware/DoubleAdapter.kt (94%) rename {presentation/src/main/java/com/sun/android => data/src/main/java/com/sun}/data/source/remote/api/middleware/IntegerAdapter.kt (94%) rename {presentation/src/main/java/com/sun/android => data/src/main/java/com/sun}/data/source/remote/api/middleware/InterceptorImpl.kt (97%) rename {presentation/src/main/java/com/sun/android => data/src/main/java/com/sun}/data/source/remote/api/response/BaseResponse.kt (86%) create mode 100644 data/src/test/java/com/sun/data/ExampleUnitTest.kt create mode 100644 domain/.gitignore create mode 100644 domain/build.gradle.kts create mode 100644 domain/src/main/java/com/sun/domain/entities/MovieEntity.kt create mode 100644 domain/src/main/java/com/sun/domain/repository/MovieRepository.kt rename {presentation/src/main/java/com/sun/android/data => domain/src/main/java/com/sun/domain/repository}/TokenRepository.kt (77%) delete mode 100644 presentation/src/main/java/com/sun/android/data/MovieRepository.kt delete mode 100644 presentation/src/main/java/com/sun/android/data/source/MovieDataSource.kt delete mode 100644 presentation/src/main/java/com/sun/android/data/source/local/MovieLocalImpl.kt delete mode 100644 presentation/src/main/java/com/sun/android/data/source/remote/MovieRemoteImpl.kt diff --git a/data/.gitignore b/data/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/data/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/data/build.gradle.kts b/data/build.gradle.kts new file mode 100644 index 0000000..717a4ad --- /dev/null +++ b/data/build.gradle.kts @@ -0,0 +1,66 @@ +plugins { + id("com.android.library") + kotlin(Plugins.kotlin_android) + id(Plugins.kotlin_parcelize) + id(Plugins.ksp).version(Versions.ksp) +} + +android { + namespace = "com.sun.data" + compileSdk = 34 + + defaultConfig { + minSdk = 24 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + kotlinOptions { + jvmTarget = "17" + } +} + +dependencies { + + implementation("androidx.core:core-ktx:1.12.0") + implementation("androidx.appcompat:appcompat:1.6.1") + implementation("com.google.android.material:material:1.11.0") + + // Room + implementation(Deps.room_runtime) + implementation(project(":domain")) + ksp(Deps.room_ksp) + implementation(Deps.room_ktx) + + //Retrofit + implementation(Deps.okHttp) + implementation(Deps.retrofit_runtime) + implementation(Deps.retrofit_gson) + implementation(Deps.okhttp_logging_interceptor) + + //Koin + implementation(Deps.koin) + + //Coroutine + implementation(Deps.coroutines_core) + implementation(Deps.coroutines_android) + testImplementation(Deps.coroutines_test) + + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.5") + androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") +} diff --git a/data/consumer-rules.pro b/data/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/data/proguard-rules.pro b/data/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/data/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/data/src/androidTest/java/com/sun/data/ExampleInstrumentedTest.kt b/data/src/androidTest/java/com/sun/data/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..2b2e527 --- /dev/null +++ b/data/src/androidTest/java/com/sun/data/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.sun.data + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.sun.data.test", appContext.packageName) + } +} diff --git a/data/src/main/AndroidManifest.xml b/data/src/main/AndroidManifest.xml new file mode 100644 index 0000000..8bdb7e1 --- /dev/null +++ b/data/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + diff --git a/presentation/src/main/java/com/sun/android/data/model/Movie.kt b/data/src/main/java/com/sun/data/entities/MovieData.kt similarity index 89% rename from presentation/src/main/java/com/sun/android/data/model/Movie.kt rename to data/src/main/java/com/sun/data/entities/MovieData.kt index 8ff607d..06d67aa 100644 --- a/presentation/src/main/java/com/sun/android/data/model/Movie.kt +++ b/data/src/main/java/com/sun/data/entities/MovieData.kt @@ -1,4 +1,4 @@ -package com.sun.android.data.model +package com.sun.data.entities import android.os.Parcelable import androidx.room.Entity @@ -8,9 +8,7 @@ import com.google.gson.annotations.SerializedName import kotlinx.android.parcel.Parcelize @Parcelize -@Entity(tableName = "movies") -data class Movie( - @PrimaryKey +data class MovieData( @SerializedName("id") @Expose var id: Int = -1, diff --git a/data/src/main/java/com/sun/data/entities/MovieDbData.kt b/data/src/main/java/com/sun/data/entities/MovieDbData.kt new file mode 100644 index 0000000..56963ac --- /dev/null +++ b/data/src/main/java/com/sun/data/entities/MovieDbData.kt @@ -0,0 +1,15 @@ +package com.sun.data.entities + +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity(tableName = "movies") +data class MovieDbData( + @PrimaryKey + var id: Int = -1, + val description: String, + val image: String, + val backgroundUrl: String, + val title: String, + val category: String, + ) diff --git a/presentation/src/main/java/com/sun/android/data/repository/MovieRepositoryImpl.kt b/data/src/main/java/com/sun/data/repository/MovieRepositoryImpl.kt similarity index 81% rename from presentation/src/main/java/com/sun/android/data/repository/MovieRepositoryImpl.kt rename to data/src/main/java/com/sun/data/repository/MovieRepositoryImpl.kt index 31d9cc6..50f45b7 100644 --- a/presentation/src/main/java/com/sun/android/data/repository/MovieRepositoryImpl.kt +++ b/data/src/main/java/com/sun/data/repository/MovieRepositoryImpl.kt @@ -1,9 +1,9 @@ -package com.sun.android.data.repository +package com.sun.data.repository import android.util.Log -import com.sun.android.data.MovieRepository -import com.sun.android.data.model.Movie -import com.sun.android.data.source.MovieDataSource +import com.sun.data.source.MovieDataSource +import com.sun.domain.entities.MovieEntity +import com.sun.domain.repository.MovieRepository import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import org.koin.core.component.KoinComponent @@ -14,7 +14,7 @@ class MovieRepositoryImpl( private val local: MovieDataSource.Local ) : KoinComponent, MovieRepository { - override suspend fun getMovies(): Flow> = flow { + override suspend fun getMovies(): Flow> = flow { try { val movies = remote.getMovies().data local.updateMovies(movies) diff --git a/presentation/src/main/java/com/sun/android/data/repository/TokenRepositoryImpl.kt b/data/src/main/java/com/sun/data/repository/TokenRepositoryImpl.kt similarity index 89% rename from presentation/src/main/java/com/sun/android/data/repository/TokenRepositoryImpl.kt rename to data/src/main/java/com/sun/data/repository/TokenRepositoryImpl.kt index 68ccf05..f571208 100644 --- a/presentation/src/main/java/com/sun/android/data/repository/TokenRepositoryImpl.kt +++ b/data/src/main/java/com/sun/data/repository/TokenRepositoryImpl.kt @@ -1,4 +1,4 @@ -package com.sun.android.data.repository +package com.sun.data.repository import com.sun.android.data.TokenRepository import com.sun.android.data.source.TokenDataSource diff --git a/data/src/main/java/com/sun/data/source/MovieDataSource.kt b/data/src/main/java/com/sun/data/source/MovieDataSource.kt new file mode 100644 index 0000000..f5e7c38 --- /dev/null +++ b/data/src/main/java/com/sun/data/source/MovieDataSource.kt @@ -0,0 +1,24 @@ +package com.sun.data.source + +import com.sun.data.source.remote.api.response.BaseResponse +import com.sun.domain.entities.MovieEntity + +interface MovieDataSource { + /** + * Local + */ + interface Local { + suspend fun getMoviesLocal(): List + suspend fun updateMovies(movies: List) + suspend fun getMovieDetailLocal(movieId: Int): MovieEntity + } + + /** + * Remote + */ + interface Remote { + suspend fun getMovies(): BaseResponse> + + suspend fun getMovieDetail(movieId: Int): MovieEntity + } +} diff --git a/presentation/src/main/java/com/sun/android/data/source/TokenDataSource.kt b/data/src/main/java/com/sun/data/source/TokenDataSource.kt similarity index 83% rename from presentation/src/main/java/com/sun/android/data/source/TokenDataSource.kt rename to data/src/main/java/com/sun/data/source/TokenDataSource.kt index 99a5a86..ac3dd71 100644 --- a/presentation/src/main/java/com/sun/android/data/source/TokenDataSource.kt +++ b/data/src/main/java/com/sun/data/source/TokenDataSource.kt @@ -1,4 +1,4 @@ -package com.sun.android.data.source +package com.sun.data.source interface TokenDataSource { interface Local { diff --git a/data/src/main/java/com/sun/data/source/local/MovieLocalImpl.kt b/data/src/main/java/com/sun/data/source/local/MovieLocalImpl.kt new file mode 100644 index 0000000..d555b10 --- /dev/null +++ b/data/src/main/java/com/sun/data/source/local/MovieLocalImpl.kt @@ -0,0 +1,18 @@ +package com.sun.data.source.local + +import com.sun.data.source.MovieDataSource +import com.sun.data.source.local.room.MovieDao + +class MovieLocalImpl(private val movieDao: MovieDao) : MovieDataSource.Local { + override suspend fun getMoviesLocal(): List { + return movieDao.getAllMovies() + } + + override suspend fun updateMovies(movies: List) { + return movieDao.insert(movies) + } + + override suspend fun getMovieDetailLocal(movieId: Int): com.sun.data.entities.MovieData { + return movieDao.getMovie(movieId) + } +} diff --git a/presentation/src/main/java/com/sun/android/data/source/local/TokenLocalImpl.kt b/data/src/main/java/com/sun/data/source/local/TokenLocalImpl.kt similarity index 63% rename from presentation/src/main/java/com/sun/android/data/source/local/TokenLocalImpl.kt rename to data/src/main/java/com/sun/data/source/local/TokenLocalImpl.kt index ab56822..813609c 100644 --- a/presentation/src/main/java/com/sun/android/data/source/local/TokenLocalImpl.kt +++ b/data/src/main/java/com/sun/data/source/local/TokenLocalImpl.kt @@ -1,8 +1,8 @@ -package com.sun.android.data.source.local +package com.sun.data.source.local -import com.sun.android.data.source.TokenDataSource -import com.sun.android.data.source.local.api.SharedPrefsApi -import com.sun.android.data.source.local.api.sharedpref.SharedPrefsKey +import com.sun.data.source.TokenDataSource +import com.sun.data.source.local.api.SharedPrefsApi +import com.sun.data.source.local.api.sharedpref.SharedPrefsKey class TokenLocalImpl(private val sharedPrefApi: SharedPrefsApi) : TokenDataSource.Local { diff --git a/presentation/src/main/java/com/sun/android/data/source/local/api/SharedPrefsApi.kt b/data/src/main/java/com/sun/data/source/local/api/SharedPrefsApi.kt similarity index 92% rename from presentation/src/main/java/com/sun/android/data/source/local/api/SharedPrefsApi.kt rename to data/src/main/java/com/sun/data/source/local/api/SharedPrefsApi.kt index fee46f1..9be47db 100644 --- a/presentation/src/main/java/com/sun/android/data/source/local/api/SharedPrefsApi.kt +++ b/data/src/main/java/com/sun/data/source/local/api/SharedPrefsApi.kt @@ -1,4 +1,4 @@ -package com.sun.android.data.source.local.api +package com.sun.data.source.local.api import android.content.SharedPreferences diff --git a/presentation/src/main/java/com/sun/android/data/source/local/api/sharedpref/SharedPrefsImpl.kt b/data/src/main/java/com/sun/data/source/local/api/sharedpref/SharedPrefsImpl.kt similarity index 95% rename from presentation/src/main/java/com/sun/android/data/source/local/api/sharedpref/SharedPrefsImpl.kt rename to data/src/main/java/com/sun/data/source/local/api/sharedpref/SharedPrefsImpl.kt index 51f0ec2..a8dad35 100644 --- a/presentation/src/main/java/com/sun/android/data/source/local/api/sharedpref/SharedPrefsImpl.kt +++ b/data/src/main/java/com/sun/data/source/local/api/sharedpref/SharedPrefsImpl.kt @@ -1,10 +1,10 @@ -package com.sun.android.data.source.local.api.sharedpref +package com.sun.data.source.local.api.sharedpref import android.content.Context import android.content.SharedPreferences import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.sun.android.data.source.local.api.SharedPrefsApi +import com.sun.data.source.local.api.SharedPrefsApi class SharedPrefsImpl(context: Context, private val gson: Gson) : SharedPrefsApi { diff --git a/presentation/src/main/java/com/sun/android/data/source/local/api/sharedpref/SharedPrefsKey.kt b/data/src/main/java/com/sun/data/source/local/api/sharedpref/SharedPrefsKey.kt similarity index 67% rename from presentation/src/main/java/com/sun/android/data/source/local/api/sharedpref/SharedPrefsKey.kt rename to data/src/main/java/com/sun/data/source/local/api/sharedpref/SharedPrefsKey.kt index bab3262..170e55a 100644 --- a/presentation/src/main/java/com/sun/android/data/source/local/api/sharedpref/SharedPrefsKey.kt +++ b/data/src/main/java/com/sun/data/source/local/api/sharedpref/SharedPrefsKey.kt @@ -1,4 +1,4 @@ -package com.sun.android.data.source.local.api.sharedpref +package com.sun.data.source.local.api.sharedpref object SharedPrefsKey { const val PREFS_NAME = "WSMCompanySharedPreference" diff --git a/presentation/src/main/java/com/sun/android/data/source/local/room/AppDatabase.kt b/data/src/main/java/com/sun/data/source/local/room/AppDatabase.kt similarity index 82% rename from presentation/src/main/java/com/sun/android/data/source/local/room/AppDatabase.kt rename to data/src/main/java/com/sun/data/source/local/room/AppDatabase.kt index f0764fe..3017b7d 100644 --- a/presentation/src/main/java/com/sun/android/data/source/local/room/AppDatabase.kt +++ b/data/src/main/java/com/sun/data/source/local/room/AppDatabase.kt @@ -1,13 +1,12 @@ -package com.sun.android.data.source.local.room +package com.sun.data.source.local.room import android.content.Context import androidx.room.Database import androidx.room.Room import androidx.room.RoomDatabase -import com.sun.android.data.model.Movie import com.sun.android.utils.Constant -@Database(entities = [Movie::class], version = 1, exportSchema = false) +@Database(entities = [com.sun.data.entities.MovieData::class], version = 1, exportSchema = false) abstract class AppDatabase : RoomDatabase() { abstract fun movieDao(): MovieDao diff --git a/presentation/src/main/java/com/sun/android/data/source/local/room/MovieDao.kt b/data/src/main/java/com/sun/data/source/local/room/MovieDao.kt similarity index 50% rename from presentation/src/main/java/com/sun/android/data/source/local/room/MovieDao.kt rename to data/src/main/java/com/sun/data/source/local/room/MovieDao.kt index 592fba2..a3bb458 100644 --- a/presentation/src/main/java/com/sun/android/data/source/local/room/MovieDao.kt +++ b/data/src/main/java/com/sun/data/source/local/room/MovieDao.kt @@ -1,4 +1,4 @@ -package com.sun.android.data.source.local.room +package com.sun.data.source.local.room import androidx.room.Dao import androidx.room.Delete @@ -6,22 +6,21 @@ import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query import androidx.room.Update -import com.sun.android.data.model.Movie @Dao interface MovieDao { @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insert(movies: List) + suspend fun insert(movies: List) @Update - suspend fun update(movie: Movie) + suspend fun update(movie: com.sun.data.entities.MovieData) @Delete - suspend fun delete(movie: Movie) + suspend fun delete(movie: com.sun.data.entities.MovieData) @Query("SELECT * from movies WHERE id = :id") - suspend fun getMovie(id: Int): Movie + suspend fun getMovie(id: Int): com.sun.data.entities.MovieData @Query("SELECT * from movies") - suspend fun getAllMovies(): List + suspend fun getAllMovies(): List } diff --git a/data/src/main/java/com/sun/data/source/remote/MovieRemoteImpl.kt b/data/src/main/java/com/sun/data/source/remote/MovieRemoteImpl.kt new file mode 100644 index 0000000..a6eacf0 --- /dev/null +++ b/data/src/main/java/com/sun/data/source/remote/MovieRemoteImpl.kt @@ -0,0 +1,17 @@ +package com.sun.data.source.remote + +import com.sun.android.BuildConfig +import com.sun.data.entities.MovieData +import com.sun.data.source.MovieDataSource +import com.sun.data.source.remote.api.ApiService +import com.sun.data.source.remote.api.response.BaseResponse + +class MovieRemoteImpl(private val apiService: ApiService) : MovieDataSource.Remote { + override suspend fun getMovies(): BaseResponse> { + return apiService.getTopRateMovies(apiKey = BuildConfig.API_KEY) + } + + override suspend fun getMovieDetail(movieId: Int): com.sun.data.entities.MovieData { + return apiService.getMovieDetails(movieId = movieId, apiKey = BuildConfig.API_KEY) + } +} diff --git a/presentation/src/main/java/com/sun/android/data/source/remote/api/ApiService.kt b/data/src/main/java/com/sun/data/source/remote/api/ApiService.kt similarity index 64% rename from presentation/src/main/java/com/sun/android/data/source/remote/api/ApiService.kt rename to data/src/main/java/com/sun/data/source/remote/api/ApiService.kt index 60d6c99..97c53a2 100644 --- a/presentation/src/main/java/com/sun/android/data/source/remote/api/ApiService.kt +++ b/data/src/main/java/com/sun/data/source/remote/api/ApiService.kt @@ -1,7 +1,7 @@ -package com.sun.android.data.source.remote.api +package com.sun.data.source.remote.api -import com.sun.android.data.model.Movie -import com.sun.android.data.source.remote.api.response.BaseResponse +import com.sun.data.entities.MovieData +import com.sun.data.source.remote.api.response.BaseResponse import retrofit2.http.GET import retrofit2.http.Path import retrofit2.http.Query @@ -11,11 +11,11 @@ interface ApiService { suspend fun getTopRateMovies( @Query("api_key") apiKey: String?, @Query("page") page: Int = 1 - ): BaseResponse> + ): BaseResponse> @GET("movie/{movieId}") suspend fun getMovieDetails( @Path("movieId") movieId: Int, @Query("api_key") apiKey: String? - ): Movie + ): com.sun.data.entities.MovieData } diff --git a/presentation/src/main/java/com/sun/android/data/source/remote/api/error/ErrorResponse.kt b/data/src/main/java/com/sun/data/source/remote/api/error/ErrorResponse.kt similarity index 97% rename from presentation/src/main/java/com/sun/android/data/source/remote/api/error/ErrorResponse.kt rename to data/src/main/java/com/sun/data/source/remote/api/error/ErrorResponse.kt index 555dd8d..f607b6e 100644 --- a/presentation/src/main/java/com/sun/android/data/source/remote/api/error/ErrorResponse.kt +++ b/data/src/main/java/com/sun/data/source/remote/api/error/ErrorResponse.kt @@ -1,4 +1,4 @@ -package com.sun.android.data.source.remote.api.error +package com.sun.data.source.remote.api.error import com.google.gson.Gson import com.google.gson.JsonSyntaxException diff --git a/presentation/src/main/java/com/sun/android/data/source/remote/api/error/RetrofitException.kt b/data/src/main/java/com/sun/data/source/remote/api/error/RetrofitException.kt similarity index 98% rename from presentation/src/main/java/com/sun/android/data/source/remote/api/error/RetrofitException.kt rename to data/src/main/java/com/sun/data/source/remote/api/error/RetrofitException.kt index b5455ca..db461fd 100644 --- a/presentation/src/main/java/com/sun/android/data/source/remote/api/error/RetrofitException.kt +++ b/data/src/main/java/com/sun/data/source/remote/api/error/RetrofitException.kt @@ -1,4 +1,4 @@ -package com.sun.android.data.source.remote.api.error +package com.sun.data.source.remote.api.error import java.io.IOException import java.net.HttpURLConnection diff --git a/presentation/src/main/java/com/sun/android/data/source/remote/api/error/Type.kt b/data/src/main/java/com/sun/data/source/remote/api/error/Type.kt similarity index 92% rename from presentation/src/main/java/com/sun/android/data/source/remote/api/error/Type.kt rename to data/src/main/java/com/sun/data/source/remote/api/error/Type.kt index 660f377..59f38b6 100644 --- a/presentation/src/main/java/com/sun/android/data/source/remote/api/error/Type.kt +++ b/data/src/main/java/com/sun/data/source/remote/api/error/Type.kt @@ -1,4 +1,4 @@ -package com.sun.android.data.source.remote.api.error +package com.sun.data.source.remote.api.error import java.io.IOException diff --git a/presentation/src/main/java/com/sun/android/data/source/remote/api/middleware/BooleanAdapter.kt b/data/src/main/java/com/sun/data/source/remote/api/middleware/BooleanAdapter.kt similarity index 93% rename from presentation/src/main/java/com/sun/android/data/source/remote/api/middleware/BooleanAdapter.kt rename to data/src/main/java/com/sun/data/source/remote/api/middleware/BooleanAdapter.kt index e916390..7becb13 100644 --- a/presentation/src/main/java/com/sun/android/data/source/remote/api/middleware/BooleanAdapter.kt +++ b/data/src/main/java/com/sun/data/source/remote/api/middleware/BooleanAdapter.kt @@ -1,4 +1,4 @@ -package com.sun.android.data.source.remote.api.middleware +package com.sun.data.source.remote.api.middleware import com.google.gson.TypeAdapter import com.google.gson.stream.JsonReader diff --git a/presentation/src/main/java/com/sun/android/data/source/remote/api/middleware/DoubleAdapter.kt b/data/src/main/java/com/sun/data/source/remote/api/middleware/DoubleAdapter.kt similarity index 94% rename from presentation/src/main/java/com/sun/android/data/source/remote/api/middleware/DoubleAdapter.kt rename to data/src/main/java/com/sun/data/source/remote/api/middleware/DoubleAdapter.kt index fb2fbf5..b984055 100644 --- a/presentation/src/main/java/com/sun/android/data/source/remote/api/middleware/DoubleAdapter.kt +++ b/data/src/main/java/com/sun/data/source/remote/api/middleware/DoubleAdapter.kt @@ -1,4 +1,4 @@ -package com.sun.android.data.source.remote.api.middleware +package com.sun.data.source.remote.api.middleware import com.google.gson.TypeAdapter import com.google.gson.stream.JsonReader diff --git a/presentation/src/main/java/com/sun/android/data/source/remote/api/middleware/IntegerAdapter.kt b/data/src/main/java/com/sun/data/source/remote/api/middleware/IntegerAdapter.kt similarity index 94% rename from presentation/src/main/java/com/sun/android/data/source/remote/api/middleware/IntegerAdapter.kt rename to data/src/main/java/com/sun/data/source/remote/api/middleware/IntegerAdapter.kt index 65e2332..9383a24 100644 --- a/presentation/src/main/java/com/sun/android/data/source/remote/api/middleware/IntegerAdapter.kt +++ b/data/src/main/java/com/sun/data/source/remote/api/middleware/IntegerAdapter.kt @@ -1,4 +1,4 @@ -package com.sun.android.data.source.remote.api.middleware +package com.sun.data.source.remote.api.middleware import com.google.gson.TypeAdapter import com.google.gson.stream.JsonReader diff --git a/presentation/src/main/java/com/sun/android/data/source/remote/api/middleware/InterceptorImpl.kt b/data/src/main/java/com/sun/data/source/remote/api/middleware/InterceptorImpl.kt similarity index 97% rename from presentation/src/main/java/com/sun/android/data/source/remote/api/middleware/InterceptorImpl.kt rename to data/src/main/java/com/sun/data/source/remote/api/middleware/InterceptorImpl.kt index d287dd4..0dc17ab 100644 --- a/presentation/src/main/java/com/sun/android/data/source/remote/api/middleware/InterceptorImpl.kt +++ b/data/src/main/java/com/sun/data/source/remote/api/middleware/InterceptorImpl.kt @@ -1,4 +1,4 @@ -package com.sun.android.data.source.remote.api.middleware +package com.sun.data.source.remote.api.middleware import androidx.annotation.NonNull import com.sun.android.data.TokenRepository diff --git a/presentation/src/main/java/com/sun/android/data/source/remote/api/response/BaseResponse.kt b/data/src/main/java/com/sun/data/source/remote/api/response/BaseResponse.kt similarity index 86% rename from presentation/src/main/java/com/sun/android/data/source/remote/api/response/BaseResponse.kt rename to data/src/main/java/com/sun/data/source/remote/api/response/BaseResponse.kt index 3017d14..0e55d67 100644 --- a/presentation/src/main/java/com/sun/android/data/source/remote/api/response/BaseResponse.kt +++ b/data/src/main/java/com/sun/data/source/remote/api/response/BaseResponse.kt @@ -1,4 +1,4 @@ -package com.sun.android.data.source.remote.api.response +package com.sun.data.source.remote.api.response import com.google.gson.annotations.Expose import com.google.gson.annotations.SerializedName diff --git a/data/src/test/java/com/sun/data/ExampleUnitTest.kt b/data/src/test/java/com/sun/data/ExampleUnitTest.kt new file mode 100644 index 0000000..99cba49 --- /dev/null +++ b/data/src/test/java/com/sun/data/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package com.sun.data + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} diff --git a/domain/.gitignore b/domain/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/domain/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/domain/build.gradle.kts b/domain/build.gradle.kts new file mode 100644 index 0000000..516dae9 --- /dev/null +++ b/domain/build.gradle.kts @@ -0,0 +1,16 @@ +plugins { + id("java-library") + id("org.jetbrains.kotlin.jvm") +} + +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +dependencies { + //Coroutine + implementation(Deps.coroutines_core) + implementation(Deps.coroutines_android) + testImplementation(Deps.coroutines_test) +} diff --git a/domain/src/main/java/com/sun/domain/entities/MovieEntity.kt b/domain/src/main/java/com/sun/domain/entities/MovieEntity.kt new file mode 100644 index 0000000..ec4b9ca --- /dev/null +++ b/domain/src/main/java/com/sun/domain/entities/MovieEntity.kt @@ -0,0 +1,10 @@ +package com.sun.domain.entities + +data class MovieEntity( + val id: Int, + val title: String, + val description: String, + val image: String, + val category: String, + val backgroundUrl: String +) diff --git a/domain/src/main/java/com/sun/domain/repository/MovieRepository.kt b/domain/src/main/java/com/sun/domain/repository/MovieRepository.kt new file mode 100644 index 0000000..0915541 --- /dev/null +++ b/domain/src/main/java/com/sun/domain/repository/MovieRepository.kt @@ -0,0 +1,10 @@ +package com.sun.domain.repository + +import com.sun.domain.entities.MovieEntity +import kotlinx.coroutines.flow.Flow + +interface MovieRepository { + suspend fun getMovies(): Flow> + + suspend fun getDetailMovies(movieId: Int): Flow +} diff --git a/presentation/src/main/java/com/sun/android/data/TokenRepository.kt b/domain/src/main/java/com/sun/domain/repository/TokenRepository.kt similarity index 77% rename from presentation/src/main/java/com/sun/android/data/TokenRepository.kt rename to domain/src/main/java/com/sun/domain/repository/TokenRepository.kt index b584601..75c35d0 100644 --- a/presentation/src/main/java/com/sun/android/data/TokenRepository.kt +++ b/domain/src/main/java/com/sun/domain/repository/TokenRepository.kt @@ -1,4 +1,4 @@ -package com.sun.android.data +package com.sun.domain.repository interface TokenRepository { fun getToken(): String? diff --git a/presentation/src/main/java/com/sun/android/data/MovieRepository.kt b/presentation/src/main/java/com/sun/android/data/MovieRepository.kt deleted file mode 100644 index 5b117a4..0000000 --- a/presentation/src/main/java/com/sun/android/data/MovieRepository.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.sun.android.data - -import com.sun.android.data.model.Movie -import kotlinx.coroutines.flow.Flow - -interface MovieRepository { - suspend fun getMovies(): Flow> - - suspend fun getDetailMovies(movieId: Int): Flow -} diff --git a/presentation/src/main/java/com/sun/android/data/source/MovieDataSource.kt b/presentation/src/main/java/com/sun/android/data/source/MovieDataSource.kt deleted file mode 100644 index d210543..0000000 --- a/presentation/src/main/java/com/sun/android/data/source/MovieDataSource.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.sun.android.data.source - -import com.sun.android.data.model.Movie -import com.sun.android.data.source.remote.api.response.BaseResponse - -interface MovieDataSource { - /** - * Local - */ - interface Local { - suspend fun getMoviesLocal(): List - suspend fun updateMovies(movies: List) - suspend fun getMovieDetailLocal(movieId: Int): Movie - } - - /** - * Remote - */ - interface Remote { - suspend fun getMovies(): BaseResponse> - - suspend fun getMovieDetail(movieId: Int): Movie - } -} diff --git a/presentation/src/main/java/com/sun/android/data/source/local/MovieLocalImpl.kt b/presentation/src/main/java/com/sun/android/data/source/local/MovieLocalImpl.kt deleted file mode 100644 index 18cebbe..0000000 --- a/presentation/src/main/java/com/sun/android/data/source/local/MovieLocalImpl.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.sun.android.data.source.local - -import com.sun.android.data.model.Movie -import com.sun.android.data.source.MovieDataSource -import com.sun.android.data.source.local.room.MovieDao - -class MovieLocalImpl(private val movieDao: MovieDao) : MovieDataSource.Local { - override suspend fun getMoviesLocal(): List { - return movieDao.getAllMovies() - } - - override suspend fun updateMovies(movies: List) { - return movieDao.insert(movies) - } - - override suspend fun getMovieDetailLocal(movieId: Int): Movie { - return movieDao.getMovie(movieId) - } -} diff --git a/presentation/src/main/java/com/sun/android/data/source/remote/MovieRemoteImpl.kt b/presentation/src/main/java/com/sun/android/data/source/remote/MovieRemoteImpl.kt deleted file mode 100644 index 03c5555..0000000 --- a/presentation/src/main/java/com/sun/android/data/source/remote/MovieRemoteImpl.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.sun.android.data.source.remote - -import com.sun.android.BuildConfig -import com.sun.android.data.model.Movie -import com.sun.android.data.source.MovieDataSource -import com.sun.android.data.source.remote.api.ApiService -import com.sun.android.data.source.remote.api.response.BaseResponse - -class MovieRemoteImpl(private val apiService: ApiService) : MovieDataSource.Remote { - override suspend fun getMovies(): BaseResponse> { - return apiService.getTopRateMovies(apiKey = BuildConfig.API_KEY) - } - - override suspend fun getMovieDetail(movieId: Int): Movie { - return apiService.getMovieDetails(movieId = movieId, apiKey = BuildConfig.API_KEY) - } -} diff --git a/presentation/src/main/java/com/sun/android/di/AppModule.kt b/presentation/src/main/java/com/sun/android/di/AppModule.kt index f906de8..4bf7158 100644 --- a/presentation/src/main/java/com/sun/android/di/AppModule.kt +++ b/presentation/src/main/java/com/sun/android/di/AppModule.kt @@ -5,13 +5,13 @@ import android.content.res.Resources import com.google.gson.FieldNamingPolicy import com.google.gson.Gson import com.google.gson.GsonBuilder -import com.sun.android.data.source.local.api.SharedPrefsApi -import com.sun.android.data.source.local.api.sharedpref.SharedPrefsImpl -import com.sun.android.data.source.local.room.AppDatabase -import com.sun.android.data.source.local.room.MovieDao -import com.sun.android.data.source.remote.api.middleware.BooleanAdapter -import com.sun.android.data.source.remote.api.middleware.DoubleAdapter -import com.sun.android.data.source.remote.api.middleware.IntegerAdapter +import com.sun.data.source.local.api.SharedPrefsApi +import com.sun.data.source.local.api.sharedpref.SharedPrefsImpl +import com.sun.data.source.local.room.AppDatabase +import com.sun.data.source.local.room.MovieDao +import com.sun.data.source.remote.api.middleware.BooleanAdapter +import com.sun.data.source.remote.api.middleware.DoubleAdapter +import com.sun.data.source.remote.api.middleware.IntegerAdapter import com.sun.android.utils.DateTimeUtils import com.sun.android.utils.dispatchers.BaseDispatcherProvider import com.sun.android.utils.dispatchers.DispatcherProvider @@ -35,8 +35,8 @@ fun provideResources(app: Application): Resources { return app.resources } -fun provideSharedPrefsApi(app: Application, gson: Gson): SharedPrefsApi { - return SharedPrefsImpl(app, gson) +fun provideSharedPrefsApi(app: Application, gson: Gson): com.sun.data.source.local.api.SharedPrefsApi { + return com.sun.data.source.local.api.sharedpref.SharedPrefsImpl(app, gson) } fun provideBaseDispatcherProvider(): BaseDispatcherProvider { @@ -44,9 +44,9 @@ fun provideBaseDispatcherProvider(): BaseDispatcherProvider { } fun provideGson(): Gson { - val booleanAdapter = BooleanAdapter() - val integerAdapter = IntegerAdapter() - val doubleAdapter = DoubleAdapter() + val booleanAdapter = com.sun.data.source.remote.api.middleware.BooleanAdapter() + val integerAdapter = com.sun.data.source.remote.api.middleware.IntegerAdapter() + val doubleAdapter = com.sun.data.source.remote.api.middleware.DoubleAdapter() return GsonBuilder() .registerTypeAdapter(Boolean::class.java, booleanAdapter) .registerTypeAdapter(Int::class.java, integerAdapter) @@ -57,10 +57,10 @@ fun provideGson(): Gson { .create() } -fun provideDatabase(app: Application): AppDatabase { - return AppDatabase.getDatabase(app.applicationContext) +fun provideDatabase(app: Application): com.sun.data.source.local.room.AppDatabase { + return com.sun.data.source.local.room.AppDatabase.getDatabase(app.applicationContext) } -fun provideMovieDao(database: AppDatabase): MovieDao { +fun provideMovieDao(database: com.sun.data.source.local.room.AppDatabase): com.sun.data.source.local.room.MovieDao { return database.movieDao() } diff --git a/presentation/src/main/java/com/sun/android/di/DataSourceModule.kt b/presentation/src/main/java/com/sun/android/di/DataSourceModule.kt index 7111e3c..c582236 100644 --- a/presentation/src/main/java/com/sun/android/di/DataSourceModule.kt +++ b/presentation/src/main/java/com/sun/android/di/DataSourceModule.kt @@ -1,16 +1,20 @@ package com.sun.android.di -import com.sun.android.data.source.MovieDataSource -import com.sun.android.data.source.TokenDataSource -import com.sun.android.data.source.local.MovieLocalImpl -import com.sun.android.data.source.local.TokenLocalImpl -import com.sun.android.data.source.remote.MovieRemoteImpl +import com.sun.data.source.MovieDataSource +import com.sun.data.source.TokenDataSource +import com.sun.data.source.local.MovieLocalImpl +import com.sun.data.source.local.TokenLocalImpl +import com.sun.data.source.remote.MovieRemoteImpl import org.koin.dsl.module val DataSourceModule = module { - single { TokenLocalImpl(get()) } + single { com.sun.data.source.local.TokenLocalImpl(get()) } - single { MovieRemoteImpl(get()) } + single { + com.sun.data.source.remote.MovieRemoteImpl( + get() + ) + } - single { MovieLocalImpl(get()) } + single { com.sun.data.source.local.MovieLocalImpl(get()) } } diff --git a/presentation/src/main/java/com/sun/android/di/NetWorkModule.kt b/presentation/src/main/java/com/sun/android/di/NetWorkModule.kt index 21550c7..7cc8808 100644 --- a/presentation/src/main/java/com/sun/android/di/NetWorkModule.kt +++ b/presentation/src/main/java/com/sun/android/di/NetWorkModule.kt @@ -3,9 +3,9 @@ package com.sun.android.di import android.app.Application import com.google.gson.Gson import com.sun.android.BuildConfig -import com.sun.android.data.TokenRepository -import com.sun.android.data.source.remote.api.ApiService -import com.sun.android.data.source.remote.api.middleware.InterceptorImpl +import com.sun.domain.TokenRepository +import com.sun.data.source.remote.api.ApiService +import com.sun.data.source.remote.api.middleware.InterceptorImpl import java.util.concurrent.TimeUnit import okhttp3.Cache import okhttp3.Interceptor @@ -32,8 +32,8 @@ fun provideOkHttpCache(app: Application): Cache { return Cache(app.cacheDir, cacheSize) } -fun provideInterceptor(tokenRepository: TokenRepository): Interceptor { - return InterceptorImpl(tokenRepository) +fun provideInterceptor(tokenRepository: com.sun.domain.TokenRepository): Interceptor { + return com.sun.data.source.remote.api.middleware.InterceptorImpl(tokenRepository) } fun provideOkHttpClient(cache: Cache, interceptor: Interceptor): OkHttpClient { @@ -68,8 +68,8 @@ fun provideRetrofit(gson: Gson, okHttpClient: OkHttpClient): Retrofit { .client(okHttpClient).build() } -fun provideApiService(retrofit: Retrofit): ApiService { - return retrofit.create(ApiService::class.java) +fun provideApiService(retrofit: Retrofit): com.sun.data.source.remote.api.ApiService { + return retrofit.create(com.sun.data.source.remote.api.ApiService::class.java) } object NetWorkInstant { diff --git a/presentation/src/main/java/com/sun/android/di/RepositoryModule.kt b/presentation/src/main/java/com/sun/android/di/RepositoryModule.kt index c3ed551..9bc0e5f 100644 --- a/presentation/src/main/java/com/sun/android/di/RepositoryModule.kt +++ b/presentation/src/main/java/com/sun/android/di/RepositoryModule.kt @@ -1,11 +1,11 @@ package com.sun.android.di -import com.sun.android.data.MovieRepository -import com.sun.android.data.TokenRepository -import com.sun.android.data.repository.MovieRepositoryImpl -import com.sun.android.data.repository.TokenRepositoryImpl -import com.sun.android.data.source.MovieDataSource -import com.sun.android.data.source.TokenDataSource +import com.sun.domain.MovieRepository +import com.sun.domain.TokenRepository +import com.sun.data.repository.MovieRepositoryImpl +import com.sun.data.repository.TokenRepositoryImpl +import com.sun.data.source.MovieDataSource +import com.sun.data.source.TokenDataSource import org.koin.dsl.module val RepositoryModule = module { @@ -14,10 +14,10 @@ val RepositoryModule = module { single { provideMovieRepository(get(), get()) } } -fun provideTokenRepository(local: TokenDataSource.Local): TokenRepository { - return TokenRepositoryImpl(local) +fun provideTokenRepository(local: com.sun.data.source.TokenDataSource.Local): com.sun.domain.TokenRepository { + return com.sun.data.repository.TokenRepositoryImpl(local) } -fun provideMovieRepository(remote: MovieDataSource.Remote, local: MovieDataSource.Local): MovieRepository { - return MovieRepositoryImpl(remote, local) +fun provideMovieRepository(remote: com.sun.data.source.MovieDataSource.Remote, local: com.sun.data.source.MovieDataSource.Local): com.sun.domain.MovieRepository { + return com.sun.data.repository.MovieRepositoryImpl(remote, local) } diff --git a/presentation/src/main/java/com/sun/android/ui/detail/MovieDetailViewModel.kt b/presentation/src/main/java/com/sun/android/ui/detail/MovieDetailViewModel.kt index 322769f..ad3b59b 100644 --- a/presentation/src/main/java/com/sun/android/ui/detail/MovieDetailViewModel.kt +++ b/presentation/src/main/java/com/sun/android/ui/detail/MovieDetailViewModel.kt @@ -2,15 +2,15 @@ package com.sun.android.ui.detail import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sun.android.data.MovieRepository -import com.sun.android.data.model.Movie +import com.sun.domain.MovieRepository +import com.sun.data.model.Movie import com.sun.android.utils.LogUtils import com.sun.android.utils.livedata.SingleLiveData import kotlinx.coroutines.flow.catch import kotlinx.coroutines.launch -class MovieDetailViewModel(private val movieRepository: MovieRepository) : ViewModel() { - val movie = SingleLiveData() +class MovieDetailViewModel(private val movieRepository: com.sun.domain.MovieRepository) : ViewModel() { + val movie = SingleLiveData() fun requestMovieDetails(movieId: Int) { viewModelScope.launch { diff --git a/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesFragment.kt b/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesFragment.kt index 23cc54f..a61a7c6 100644 --- a/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesFragment.kt +++ b/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesFragment.kt @@ -3,7 +3,7 @@ package com.sun.android.ui.listmovie import androidx.lifecycle.Observer import com.sun.android.R import com.sun.android.base.BaseFragment -import com.sun.android.data.model.Movie +import com.sun.data.model.Movie import com.sun.android.databinding.MoviesFragmentBinding import com.sun.android.ui.detail.DetailFragment import com.sun.android.ui.listmovie.adapter.MoviesAdapter @@ -13,7 +13,7 @@ import com.sun.android.utils.recycler.OnItemRecyclerViewClickListener import org.koin.androidx.viewmodel.ext.android.viewModel class MoviesFragment : BaseFragment(MoviesFragmentBinding::inflate), - OnItemRecyclerViewClickListener { + OnItemRecyclerViewClickListener { private val mMovieAdapter: MoviesAdapter by lazy { MoviesAdapter() } @@ -39,7 +39,7 @@ class MoviesFragment : BaseFragment(MoviesFragmentBinding ) } - override fun onItemClick(item: Movie?) { + override fun onItemClick(item: com.sun.data.model.Movie?) { item.notNull { addFragment(R.id.layoutContainer, DetailFragment.newInstance(it.id), true) } diff --git a/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt b/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt index 1870527..648e065 100644 --- a/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt +++ b/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt @@ -2,8 +2,8 @@ package com.sun.android.ui.listmovie import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sun.android.data.MovieRepository -import com.sun.android.data.model.Movie +import com.sun.domain.MovieRepository +import com.sun.data.model.Movie import com.sun.android.utils.LogUtils import com.sun.android.utils.dispatchers.DispatcherProvider import com.sun.android.utils.livedata.SingleLiveData @@ -11,8 +11,8 @@ import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.launch -class MoviesViewModel(private val movieRepository: MovieRepository) : ViewModel() { - val movies = SingleLiveData>() +class MoviesViewModel(private val movieRepository: com.sun.domain.MovieRepository) : ViewModel() { + val movies = SingleLiveData>() fun requestTopRateMovies() { viewModelScope.launch { diff --git a/presentation/src/main/java/com/sun/android/ui/listmovie/adapter/MoviesAdapter.kt b/presentation/src/main/java/com/sun/android/ui/listmovie/adapter/MoviesAdapter.kt index 13c5dfd..890a096 100644 --- a/presentation/src/main/java/com/sun/android/ui/listmovie/adapter/MoviesAdapter.kt +++ b/presentation/src/main/java/com/sun/android/ui/listmovie/adapter/MoviesAdapter.kt @@ -4,7 +4,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView -import com.sun.android.data.model.Movie +import com.sun.data.model.Movie import com.sun.android.databinding.ItemLayoutMovieBinding import com.sun.android.utils.extension.loadImageCircleWithUrl import com.sun.android.utils.extension.notNull @@ -12,8 +12,8 @@ import com.sun.android.utils.recycler.OnItemRecyclerViewClickListener class MoviesAdapter : RecyclerView.Adapter() { - private val movies = mutableListOf() - private var onItemClickListener: OnItemRecyclerViewClickListener? = null + private val movies = mutableListOf() + private var onItemClickListener: OnItemRecyclerViewClickListener? = null override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val binding = ItemLayoutMovieBinding.inflate(LayoutInflater.from(parent.context), parent, false) @@ -29,12 +29,12 @@ class MoviesAdapter : RecyclerView.Adapter() { } fun registerItemRecyclerViewClickListener( - onItemRecyclerViewClickListener: OnItemRecyclerViewClickListener? + onItemRecyclerViewClickListener: OnItemRecyclerViewClickListener? ) { onItemClickListener = onItemRecyclerViewClickListener } - fun updateData(movies: List) { + fun updateData(movies: List) { movies.notNull { this.movies.clear() this.movies.addAll(it) @@ -44,18 +44,18 @@ class MoviesAdapter : RecyclerView.Adapter() { class ViewHolder( private val binding: ItemLayoutMovieBinding, - itemClickListener: OnItemRecyclerViewClickListener? + itemClickListener: OnItemRecyclerViewClickListener? ) : RecyclerView.ViewHolder(binding.root), View.OnClickListener { - private var movieData: Movie? = null - private var listener: OnItemRecyclerViewClickListener? = null + private var movieData: com.sun.data.model.Movie? = null + private var listener: OnItemRecyclerViewClickListener? = null init { itemView.setOnClickListener(this) listener = itemClickListener } - fun bindViewData(movie: Movie) { + fun bindViewData(movie: com.sun.data.model.Movie) { movie.let { binding.textViewTitle.text = it.title binding.textViewRatting.text = it.vote.toString() diff --git a/settings.gradle.kts b/settings.gradle.kts index dffdb49..cb27995 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,2 +1,4 @@ rootProject.name = "Structure_Android" include (":presentation") +include(":data") +include(":domain") From 46a6cd5654f4b312201edb237430db5b85470851 Mon Sep 17 00:00:00 2001 From: Company Date: Wed, 3 Apr 2024 15:11:30 +0700 Subject: [PATCH 4/6] [fix] Fix can't build --- .gitignore | 1 + .idea/deploymentTargetDropDown.xml | 13 ---- .idea/misc.xml | 25 -------- buildSrc/src/main/kotlin/Config.kt | 3 +- data/build.gradle.kts | 6 +- .../src/main/java/com/sun/data}/Constant.kt | 2 +- data/src/main/java/com/sun/data/Mapper.kt | 13 ++++ .../java/com/sun/data/entities/MovieData.kt | 36 ----------- .../java/com/sun/data/entities/MovieDbData.kt | 15 ----- .../java/com/sun/data/entities/MovieLocal.kt | 43 +++++++++++++ .../java/com/sun/data/entities/MovieRemote.kt | 60 +++++++++++++++++++ .../data/repository/MovieRepositoryImpl.kt | 27 ++++++--- .../data/repository/TokenRepositoryImpl.kt | 4 +- .../com/sun/data/source/MovieDataSource.kt | 13 ++-- .../sun/data/source/local/MovieLocalImpl.kt | 7 ++- .../sun/data/source/local/room/AppDatabase.kt | 5 +- .../sun/data/source/local/room/MovieDao.kt | 11 ++-- .../sun/data/source/remote/MovieRemoteImpl.kt | 8 +-- .../sun/data/source/remote/api/ApiService.kt | 6 +- .../source/remote/api/error/ErrorResponse.kt | 58 +----------------- .../remote/api/middleware/InterceptorImpl.kt | 2 +- domain/build.gradle.kts | 9 +-- .../com/sun/domain/entities/MovieEntity.kt | 7 ++- presentation/build.gradle.kts | 4 +- .../main/java/com/sun/android/di/AppModule.kt | 13 ++-- .../com/sun/android/di/DataSourceModule.kt | 8 +-- .../java/com/sun/android/di/NetWorkModule.kt | 7 +-- .../com/sun/android/di/RepositoryModule.kt | 13 ++-- .../sun/android/ui/detail/DetailFragment.kt | 8 +-- .../android/ui/detail/MovieDetailViewModel.kt | 8 +-- .../android/ui/listmovie/MoviesFragment.kt | 6 +- .../android/ui/listmovie/MoviesViewModel.kt | 8 +-- .../ui/listmovie/adapter/MoviesAdapter.kt | 28 ++++----- 33 files changed, 229 insertions(+), 248 deletions(-) delete mode 100644 .idea/deploymentTargetDropDown.xml delete mode 100644 .idea/misc.xml rename {presentation/src/main/java/com/sun/android/utils => data/src/main/java/com/sun/data}/Constant.kt (69%) create mode 100644 data/src/main/java/com/sun/data/Mapper.kt delete mode 100644 data/src/main/java/com/sun/data/entities/MovieData.kt delete mode 100644 data/src/main/java/com/sun/data/entities/MovieDbData.kt create mode 100644 data/src/main/java/com/sun/data/entities/MovieLocal.kt create mode 100644 data/src/main/java/com/sun/data/entities/MovieRemote.kt diff --git a/.gitignore b/.gitignore index 10cfdbf..1573a77 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /.idea .DS_Store /build +/app/build /captures .externalNativeBuild .cxx diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml deleted file mode 100644 index 3211ffb..0000000 --- a/.idea/deploymentTargetDropDown.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 0bb46bb..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/Config.kt b/buildSrc/src/main/kotlin/Config.kt index c59b24e..37514b8 100644 --- a/buildSrc/src/main/kotlin/Config.kt +++ b/buildSrc/src/main/kotlin/Config.kt @@ -8,7 +8,6 @@ object Versions { const val appCompat = "1.6.1" const val material = "1.8.0" const val constraintLayout = "2.1.4" - const val coreSplashScreen = "1.0.0" const val lifecycle = "2.5" const val navigation = "2.5.3" @@ -35,7 +34,7 @@ object Versions { object AppConfigs { const val application_id = "com.sun.structure_android" const val compile_sdk_version = 34 - const val min_sdk_version = 23 + const val min_sdk_version = 24 const val target_sdk_version = 34 const val version_code = 1 const val version_name = "1.0" diff --git a/data/build.gradle.kts b/data/build.gradle.kts index 717a4ad..1df5085 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -1,3 +1,5 @@ +import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties + plugins { id("com.android.library") kotlin(Plugins.kotlin_android) @@ -12,6 +14,8 @@ android { defaultConfig { minSdk = 24 + buildConfigField("String", "API_KEY", gradleLocalProperties(rootDir).getProperty("api_key")) + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles("consumer-rules.pro") } @@ -35,6 +39,7 @@ android { } dependencies { + api(project(":domain")) implementation("androidx.core:core-ktx:1.12.0") implementation("androidx.appcompat:appcompat:1.6.1") @@ -42,7 +47,6 @@ dependencies { // Room implementation(Deps.room_runtime) - implementation(project(":domain")) ksp(Deps.room_ksp) implementation(Deps.room_ktx) diff --git a/presentation/src/main/java/com/sun/android/utils/Constant.kt b/data/src/main/java/com/sun/data/Constant.kt similarity index 69% rename from presentation/src/main/java/com/sun/android/utils/Constant.kt rename to data/src/main/java/com/sun/data/Constant.kt index 0e403f2..6d7431a 100644 --- a/presentation/src/main/java/com/sun/android/utils/Constant.kt +++ b/data/src/main/java/com/sun/data/Constant.kt @@ -1,4 +1,4 @@ -package com.sun.android.utils +package com.sun.data object Constant { const val DATABASE_NAME = "movies_database" diff --git a/data/src/main/java/com/sun/data/Mapper.kt b/data/src/main/java/com/sun/data/Mapper.kt new file mode 100644 index 0000000..6bb36b7 --- /dev/null +++ b/data/src/main/java/com/sun/data/Mapper.kt @@ -0,0 +1,13 @@ +package com.sun.data + +abstract class Mapper { + abstract fun mapToEntity(): E + + open fun mapToLocal(): L? { + return null + } + + open fun mapToRemote(): R? { + return null + } +} diff --git a/data/src/main/java/com/sun/data/entities/MovieData.kt b/data/src/main/java/com/sun/data/entities/MovieData.kt deleted file mode 100644 index 06d67aa..0000000 --- a/data/src/main/java/com/sun/data/entities/MovieData.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.sun.data.entities - -import android.os.Parcelable -import androidx.room.Entity -import androidx.room.PrimaryKey -import com.google.gson.annotations.Expose -import com.google.gson.annotations.SerializedName -import kotlinx.android.parcel.Parcelize - -@Parcelize -data class MovieData( - @SerializedName("id") - @Expose - var id: Int = -1, - @SerializedName("backdrop_path") - @Expose - var backDropImage: String = "", - @SerializedName("overview") - @Expose - var overView: String = "", - @SerializedName("vote_average") - @Expose - var vote: Double = 0.0, - @SerializedName("vote_count") - @Expose - var voteCount: Int = 0, - @SerializedName("title") - @Expose - var title: String = "", - @SerializedName("poster_path") - @Expose - var urlImage: String = "", - @SerializedName("original_title") - @Expose - var originalTitle: String = "" -) : Parcelable diff --git a/data/src/main/java/com/sun/data/entities/MovieDbData.kt b/data/src/main/java/com/sun/data/entities/MovieDbData.kt deleted file mode 100644 index 56963ac..0000000 --- a/data/src/main/java/com/sun/data/entities/MovieDbData.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.sun.data.entities - -import androidx.room.Entity -import androidx.room.PrimaryKey - -@Entity(tableName = "movies") -data class MovieDbData( - @PrimaryKey - var id: Int = -1, - val description: String, - val image: String, - val backgroundUrl: String, - val title: String, - val category: String, - ) diff --git a/data/src/main/java/com/sun/data/entities/MovieLocal.kt b/data/src/main/java/com/sun/data/entities/MovieLocal.kt new file mode 100644 index 0000000..88f175d --- /dev/null +++ b/data/src/main/java/com/sun/data/entities/MovieLocal.kt @@ -0,0 +1,43 @@ +package com.sun.data.entities + +import androidx.room.Entity +import androidx.room.PrimaryKey +import com.sun.data.Mapper +import com.sun.domain.entities.MovieEntity + +@Entity(tableName = "movies") +data class MovieLocal( + @PrimaryKey + var id: Int = -1, + val description: String, + val image: String, + val backgroundUrl: String, + val title: String, + val rating: Double, + val voteCount: Int +) : Mapper() { + + override fun mapToEntity(): MovieEntity { + return MovieEntity( + id = id, + title = title, + description = description, + avatarUrl = image, + backgroundUrl = backgroundUrl, + rating = rating, + voteCount = voteCount + ) + } + + override fun mapToRemote(): MovieRemote { + return MovieRemote( + id = id, + title = title, + overView = description, + urlImage = image, + backDropImage = backgroundUrl, + rating = rating, + voteCount = voteCount + ) + } +} diff --git a/data/src/main/java/com/sun/data/entities/MovieRemote.kt b/data/src/main/java/com/sun/data/entities/MovieRemote.kt new file mode 100644 index 0000000..27f34fe --- /dev/null +++ b/data/src/main/java/com/sun/data/entities/MovieRemote.kt @@ -0,0 +1,60 @@ +package com.sun.data.entities + +import android.os.Parcelable +import com.google.gson.annotations.Expose +import com.google.gson.annotations.SerializedName +import com.sun.data.Mapper +import com.sun.domain.entities.MovieEntity +import kotlinx.android.parcel.Parcelize + +@Parcelize +data class MovieRemote( + @SerializedName("id") + @Expose + var id: Int = -1, + @SerializedName("backdrop_path") + @Expose + var backDropImage: String = "", + @SerializedName("overview") + @Expose + var overView: String = "", + @SerializedName("vote_average") + @Expose + var rating: Double = 0.0, + @SerializedName("vote_count") + @Expose + var voteCount: Int = 0, + @SerializedName("title") + @Expose + var title: String = "", + @SerializedName("poster_path") + @Expose + var urlImage: String = "", + @SerializedName("original_title") + @Expose + var originalTitle: String = "" +) : Parcelable, Mapper() { + override fun mapToEntity(): MovieEntity { + return MovieEntity( + id = id, + title = title, + description = overView, + avatarUrl = urlImage, + backgroundUrl = backDropImage, + rating = rating, + voteCount = voteCount + ) + } + + override fun mapToLocal(): MovieLocal { + return MovieLocal( + id = id, + description = overView, + image = urlImage, + backgroundUrl = backDropImage, + title = title, + rating = rating, + voteCount = voteCount + ) + } +} diff --git a/data/src/main/java/com/sun/data/repository/MovieRepositoryImpl.kt b/data/src/main/java/com/sun/data/repository/MovieRepositoryImpl.kt index 50f45b7..a340420 100644 --- a/data/src/main/java/com/sun/data/repository/MovieRepositoryImpl.kt +++ b/data/src/main/java/com/sun/data/repository/MovieRepositoryImpl.kt @@ -1,6 +1,7 @@ package com.sun.data.repository import android.util.Log +import com.sun.data.entities.MovieLocal import com.sun.data.source.MovieDataSource import com.sun.domain.entities.MovieEntity import com.sun.domain.repository.MovieRepository @@ -15,23 +16,33 @@ class MovieRepositoryImpl( ) : KoinComponent, MovieRepository { override suspend fun getMovies(): Flow> = flow { + val movies = arrayListOf() try { - val movies = remote.getMovies().data - local.updateMovies(movies) + val movieDts = remote.getMovies().data + movieDts.forEach { + movies.add(it.mapToEntity()) + } + + val movieDbs = arrayListOf() + movieDts.forEach { + movieDbs.add(it.mapToLocal()) + } + local.updateMovies(movieDbs) } catch (e: IOException) { + val moviesDbs = local.getMoviesLocal() Log.e("MovieRepository", "getMovies failed, using local data \n Detail error:\n $e") } - emit(local.getMoviesLocal()) + emit(movies) } - override suspend fun getDetailMovies(movieId: Int) = flow { + override suspend fun getDetailMovies(movieId: Int): Flow = flow { try { - emit(local.getMovieDetailLocal(movieId)) + emit(local.getMovieDetailLocal(movieId).mapToEntity()) } catch (e: IOException) { Log.e("MovieRepository", "getDetailMovies failed, retry with network \n Detail error:\n $e") - val movie = remote.getMovieDetail(movieId = movieId) - local.updateMovies(arrayListOf(movie)) - emit(local.getMovieDetailLocal(movieId)) + val movieRemote = remote.getMovieDetail(movieId = movieId) + local.updateMovies(arrayListOf(movieRemote.mapToLocal())) + emit(movieRemote.mapToEntity()) } } } diff --git a/data/src/main/java/com/sun/data/repository/TokenRepositoryImpl.kt b/data/src/main/java/com/sun/data/repository/TokenRepositoryImpl.kt index f571208..41181a7 100644 --- a/data/src/main/java/com/sun/data/repository/TokenRepositoryImpl.kt +++ b/data/src/main/java/com/sun/data/repository/TokenRepositoryImpl.kt @@ -1,7 +1,7 @@ package com.sun.data.repository -import com.sun.android.data.TokenRepository -import com.sun.android.data.source.TokenDataSource +import com.sun.data.source.TokenDataSource +import com.sun.domain.repository.TokenRepository class TokenRepositoryImpl(private val local: TokenDataSource.Local) : TokenRepository { diff --git a/data/src/main/java/com/sun/data/source/MovieDataSource.kt b/data/src/main/java/com/sun/data/source/MovieDataSource.kt index f5e7c38..4bfc29a 100644 --- a/data/src/main/java/com/sun/data/source/MovieDataSource.kt +++ b/data/src/main/java/com/sun/data/source/MovieDataSource.kt @@ -1,24 +1,25 @@ package com.sun.data.source +import com.sun.data.entities.MovieRemote +import com.sun.data.entities.MovieLocal import com.sun.data.source.remote.api.response.BaseResponse -import com.sun.domain.entities.MovieEntity interface MovieDataSource { /** * Local */ interface Local { - suspend fun getMoviesLocal(): List - suspend fun updateMovies(movies: List) - suspend fun getMovieDetailLocal(movieId: Int): MovieEntity + suspend fun getMoviesLocal(): List + suspend fun updateMovies(movies: List) + suspend fun getMovieDetailLocal(movieId: Int): MovieLocal } /** * Remote */ interface Remote { - suspend fun getMovies(): BaseResponse> + suspend fun getMovies(): BaseResponse> - suspend fun getMovieDetail(movieId: Int): MovieEntity + suspend fun getMovieDetail(movieId: Int): MovieRemote } } diff --git a/data/src/main/java/com/sun/data/source/local/MovieLocalImpl.kt b/data/src/main/java/com/sun/data/source/local/MovieLocalImpl.kt index d555b10..6f1586c 100644 --- a/data/src/main/java/com/sun/data/source/local/MovieLocalImpl.kt +++ b/data/src/main/java/com/sun/data/source/local/MovieLocalImpl.kt @@ -1,18 +1,19 @@ package com.sun.data.source.local +import com.sun.data.entities.MovieLocal import com.sun.data.source.MovieDataSource import com.sun.data.source.local.room.MovieDao class MovieLocalImpl(private val movieDao: MovieDao) : MovieDataSource.Local { - override suspend fun getMoviesLocal(): List { + override suspend fun getMoviesLocal(): List { return movieDao.getAllMovies() } - override suspend fun updateMovies(movies: List) { + override suspend fun updateMovies(movies: List) { return movieDao.insert(movies) } - override suspend fun getMovieDetailLocal(movieId: Int): com.sun.data.entities.MovieData { + override suspend fun getMovieDetailLocal(movieId: Int): MovieLocal { return movieDao.getMovie(movieId) } } diff --git a/data/src/main/java/com/sun/data/source/local/room/AppDatabase.kt b/data/src/main/java/com/sun/data/source/local/room/AppDatabase.kt index 3017b7d..c3b6893 100644 --- a/data/src/main/java/com/sun/data/source/local/room/AppDatabase.kt +++ b/data/src/main/java/com/sun/data/source/local/room/AppDatabase.kt @@ -4,9 +4,10 @@ import android.content.Context import androidx.room.Database import androidx.room.Room import androidx.room.RoomDatabase -import com.sun.android.utils.Constant +import com.sun.data.Constant +import com.sun.data.entities.MovieLocal -@Database(entities = [com.sun.data.entities.MovieData::class], version = 1, exportSchema = false) +@Database(entities = [MovieLocal::class], version = 1, exportSchema = false) abstract class AppDatabase : RoomDatabase() { abstract fun movieDao(): MovieDao diff --git a/data/src/main/java/com/sun/data/source/local/room/MovieDao.kt b/data/src/main/java/com/sun/data/source/local/room/MovieDao.kt index a3bb458..e663305 100644 --- a/data/src/main/java/com/sun/data/source/local/room/MovieDao.kt +++ b/data/src/main/java/com/sun/data/source/local/room/MovieDao.kt @@ -6,21 +6,22 @@ import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query import androidx.room.Update +import com.sun.data.entities.MovieLocal @Dao interface MovieDao { @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insert(movies: List) + suspend fun insert(movies: List) @Update - suspend fun update(movie: com.sun.data.entities.MovieData) + suspend fun update(movie: MovieLocal) @Delete - suspend fun delete(movie: com.sun.data.entities.MovieData) + suspend fun delete(movie: MovieLocal) @Query("SELECT * from movies WHERE id = :id") - suspend fun getMovie(id: Int): com.sun.data.entities.MovieData + suspend fun getMovie(id: Int): MovieLocal @Query("SELECT * from movies") - suspend fun getAllMovies(): List + suspend fun getAllMovies(): List } diff --git a/data/src/main/java/com/sun/data/source/remote/MovieRemoteImpl.kt b/data/src/main/java/com/sun/data/source/remote/MovieRemoteImpl.kt index a6eacf0..f257bfc 100644 --- a/data/src/main/java/com/sun/data/source/remote/MovieRemoteImpl.kt +++ b/data/src/main/java/com/sun/data/source/remote/MovieRemoteImpl.kt @@ -1,17 +1,17 @@ package com.sun.data.source.remote -import com.sun.android.BuildConfig -import com.sun.data.entities.MovieData +import com.sun.data.BuildConfig +import com.sun.data.entities.MovieRemote import com.sun.data.source.MovieDataSource import com.sun.data.source.remote.api.ApiService import com.sun.data.source.remote.api.response.BaseResponse class MovieRemoteImpl(private val apiService: ApiService) : MovieDataSource.Remote { - override suspend fun getMovies(): BaseResponse> { + override suspend fun getMovies(): BaseResponse> { return apiService.getTopRateMovies(apiKey = BuildConfig.API_KEY) } - override suspend fun getMovieDetail(movieId: Int): com.sun.data.entities.MovieData { + override suspend fun getMovieDetail(movieId: Int): MovieRemote { return apiService.getMovieDetails(movieId = movieId, apiKey = BuildConfig.API_KEY) } } diff --git a/data/src/main/java/com/sun/data/source/remote/api/ApiService.kt b/data/src/main/java/com/sun/data/source/remote/api/ApiService.kt index 97c53a2..98bcf32 100644 --- a/data/src/main/java/com/sun/data/source/remote/api/ApiService.kt +++ b/data/src/main/java/com/sun/data/source/remote/api/ApiService.kt @@ -1,6 +1,6 @@ package com.sun.data.source.remote.api -import com.sun.data.entities.MovieData +import com.sun.data.entities.MovieRemote import com.sun.data.source.remote.api.response.BaseResponse import retrofit2.http.GET import retrofit2.http.Path @@ -11,11 +11,11 @@ interface ApiService { suspend fun getTopRateMovies( @Query("api_key") apiKey: String?, @Query("page") page: Int = 1 - ): BaseResponse> + ): BaseResponse> @GET("movie/{movieId}") suspend fun getMovieDetails( @Path("movieId") movieId: Int, @Query("api_key") apiKey: String? - ): com.sun.data.entities.MovieData + ): MovieRemote } diff --git a/data/src/main/java/com/sun/data/source/remote/api/error/ErrorResponse.kt b/data/src/main/java/com/sun/data/source/remote/api/error/ErrorResponse.kt index f607b6e..86c9206 100644 --- a/data/src/main/java/com/sun/data/source/remote/api/error/ErrorResponse.kt +++ b/data/src/main/java/com/sun/data/source/remote/api/error/ErrorResponse.kt @@ -1,14 +1,7 @@ package com.sun.data.source.remote.api.error -import com.google.gson.Gson -import com.google.gson.JsonSyntaxException import com.google.gson.annotations.Expose import com.google.gson.annotations.SerializedName -import com.sun.android.utils.LogUtils -import com.sun.android.utils.extension.notNull -import java.io.IOException -import java.text.ParseException -import retrofit2.HttpException data class ErrorResponse( @SerializedName("status") @@ -17,53 +10,4 @@ data class ErrorResponse( @SerializedName("messages") @Expose val messages: String? -) { - companion object { - private const val TAG = "ErrorResponse" - - fun convertToRetrofitException(throwable: Throwable): RetrofitException { - if (throwable is RetrofitException) { - return throwable - } - - // A network error happened - if (throwable is IOException) { - return RetrofitException.toNetworkError(throwable) - } - - // We had non-200 http error - if (throwable is HttpException) { - val response = throwable.response() ?: return RetrofitException.toUnexpectedError( - throwable - ) - - response.errorBody().notNull { - return try { - val errorResponse = - Gson().fromJson(it.string(), ErrorResponse::class.java) - - if (errorResponse != null && !errorResponse.messages.isNullOrBlank()) { - RetrofitException.toServerError(errorResponse) - } else { - RetrofitException.toHttpError(response) - } - } catch (e: IOException) { - LogUtils.e(TAG, e.message.toString()) - RetrofitException.toUnexpectedError(throwable) - } catch (e: ParseException) { - LogUtils.e(TAG, e.message.toString()) - RetrofitException.toUnexpectedError(throwable) - } catch (e: JsonSyntaxException) { - LogUtils.e(TAG, e.message.toString()) - RetrofitException.toUnexpectedError(throwable) - } - } - - return RetrofitException.toHttpError(response) - } - - // We don't know what happened. We need to simply convert to an unknown error - return RetrofitException.toUnexpectedError(throwable) - } - } -} +) diff --git a/data/src/main/java/com/sun/data/source/remote/api/middleware/InterceptorImpl.kt b/data/src/main/java/com/sun/data/source/remote/api/middleware/InterceptorImpl.kt index 0dc17ab..64c043d 100644 --- a/data/src/main/java/com/sun/data/source/remote/api/middleware/InterceptorImpl.kt +++ b/data/src/main/java/com/sun/data/source/remote/api/middleware/InterceptorImpl.kt @@ -1,7 +1,7 @@ package com.sun.data.source.remote.api.middleware import androidx.annotation.NonNull -import com.sun.android.data.TokenRepository +import com.sun.domain.repository.TokenRepository import java.io.IOException import java.net.HttpURLConnection import okhttp3.Interceptor diff --git a/domain/build.gradle.kts b/domain/build.gradle.kts index 516dae9..b90795a 100644 --- a/domain/build.gradle.kts +++ b/domain/build.gradle.kts @@ -1,16 +1,11 @@ plugins { - id("java-library") - id("org.jetbrains.kotlin.jvm") -} - -java { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + id("kotlin") } dependencies { //Coroutine implementation(Deps.coroutines_core) implementation(Deps.coroutines_android) + testImplementation(Deps.coroutines_test) } diff --git a/domain/src/main/java/com/sun/domain/entities/MovieEntity.kt b/domain/src/main/java/com/sun/domain/entities/MovieEntity.kt index ec4b9ca..33700bc 100644 --- a/domain/src/main/java/com/sun/domain/entities/MovieEntity.kt +++ b/domain/src/main/java/com/sun/domain/entities/MovieEntity.kt @@ -4,7 +4,8 @@ data class MovieEntity( val id: Int, val title: String, val description: String, - val image: String, - val category: String, - val backgroundUrl: String + val avatarUrl: String, + val backgroundUrl: String, + val rating: Double, + val voteCount: Int, ) diff --git a/presentation/build.gradle.kts b/presentation/build.gradle.kts index cfe85d4..ab163f3 100644 --- a/presentation/build.gradle.kts +++ b/presentation/build.gradle.kts @@ -23,7 +23,6 @@ android { versionCode = AppConfigs.version_code versionName = AppConfigs.version_name - buildConfigField("String", "API_KEY", gradleLocalProperties(rootDir).getProperty("api_key")) buildConfigField("String", "BASE_URL_IMAGE", gradleLocalProperties(rootDir).getProperty("base_url_image")) } @@ -97,6 +96,9 @@ tasks { } dependencies { + implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) + implementation(project(":data")) + implementation(Deps.core_ktx) implementation(Deps.appcompat) implementation(Deps.material) diff --git a/presentation/src/main/java/com/sun/android/di/AppModule.kt b/presentation/src/main/java/com/sun/android/di/AppModule.kt index 4bf7158..820c1c0 100644 --- a/presentation/src/main/java/com/sun/android/di/AppModule.kt +++ b/presentation/src/main/java/com/sun/android/di/AppModule.kt @@ -5,16 +5,11 @@ import android.content.res.Resources import com.google.gson.FieldNamingPolicy import com.google.gson.Gson import com.google.gson.GsonBuilder -import com.sun.data.source.local.api.SharedPrefsApi -import com.sun.data.source.local.api.sharedpref.SharedPrefsImpl -import com.sun.data.source.local.room.AppDatabase -import com.sun.data.source.local.room.MovieDao -import com.sun.data.source.remote.api.middleware.BooleanAdapter -import com.sun.data.source.remote.api.middleware.DoubleAdapter -import com.sun.data.source.remote.api.middleware.IntegerAdapter import com.sun.android.utils.DateTimeUtils import com.sun.android.utils.dispatchers.BaseDispatcherProvider import com.sun.android.utils.dispatchers.DispatcherProvider +import com.sun.data.source.local.api.SharedPrefsApi +import com.sun.data.source.local.api.sharedpref.SharedPrefsImpl import org.koin.dsl.module val AppModule = module { @@ -35,8 +30,8 @@ fun provideResources(app: Application): Resources { return app.resources } -fun provideSharedPrefsApi(app: Application, gson: Gson): com.sun.data.source.local.api.SharedPrefsApi { - return com.sun.data.source.local.api.sharedpref.SharedPrefsImpl(app, gson) +fun provideSharedPrefsApi(app: Application, gson: Gson): SharedPrefsApi { + return SharedPrefsImpl(app, gson) } fun provideBaseDispatcherProvider(): BaseDispatcherProvider { diff --git a/presentation/src/main/java/com/sun/android/di/DataSourceModule.kt b/presentation/src/main/java/com/sun/android/di/DataSourceModule.kt index c582236..2049d9a 100644 --- a/presentation/src/main/java/com/sun/android/di/DataSourceModule.kt +++ b/presentation/src/main/java/com/sun/android/di/DataSourceModule.kt @@ -8,13 +8,13 @@ import com.sun.data.source.remote.MovieRemoteImpl import org.koin.dsl.module val DataSourceModule = module { - single { com.sun.data.source.local.TokenLocalImpl(get()) } + single { TokenLocalImpl(get()) } - single { - com.sun.data.source.remote.MovieRemoteImpl( + single { + MovieRemoteImpl( get() ) } - single { com.sun.data.source.local.MovieLocalImpl(get()) } + single { MovieLocalImpl(get()) } } diff --git a/presentation/src/main/java/com/sun/android/di/NetWorkModule.kt b/presentation/src/main/java/com/sun/android/di/NetWorkModule.kt index 7cc8808..7c38beb 100644 --- a/presentation/src/main/java/com/sun/android/di/NetWorkModule.kt +++ b/presentation/src/main/java/com/sun/android/di/NetWorkModule.kt @@ -3,8 +3,7 @@ package com.sun.android.di import android.app.Application import com.google.gson.Gson import com.sun.android.BuildConfig -import com.sun.domain.TokenRepository -import com.sun.data.source.remote.api.ApiService +import com.sun.domain.repository.TokenRepository import com.sun.data.source.remote.api.middleware.InterceptorImpl import java.util.concurrent.TimeUnit import okhttp3.Cache @@ -32,8 +31,8 @@ fun provideOkHttpCache(app: Application): Cache { return Cache(app.cacheDir, cacheSize) } -fun provideInterceptor(tokenRepository: com.sun.domain.TokenRepository): Interceptor { - return com.sun.data.source.remote.api.middleware.InterceptorImpl(tokenRepository) +fun provideInterceptor(tokenRepository: TokenRepository): Interceptor { + return InterceptorImpl(tokenRepository) } fun provideOkHttpClient(cache: Cache, interceptor: Interceptor): OkHttpClient { diff --git a/presentation/src/main/java/com/sun/android/di/RepositoryModule.kt b/presentation/src/main/java/com/sun/android/di/RepositoryModule.kt index 9bc0e5f..246bb55 100644 --- a/presentation/src/main/java/com/sun/android/di/RepositoryModule.kt +++ b/presentation/src/main/java/com/sun/android/di/RepositoryModule.kt @@ -1,11 +1,10 @@ package com.sun.android.di -import com.sun.domain.MovieRepository -import com.sun.domain.TokenRepository import com.sun.data.repository.MovieRepositoryImpl import com.sun.data.repository.TokenRepositoryImpl import com.sun.data.source.MovieDataSource -import com.sun.data.source.TokenDataSource +import com.sun.domain.repository.MovieRepository +import com.sun.domain.repository.TokenRepository import org.koin.dsl.module val RepositoryModule = module { @@ -14,10 +13,10 @@ val RepositoryModule = module { single { provideMovieRepository(get(), get()) } } -fun provideTokenRepository(local: com.sun.data.source.TokenDataSource.Local): com.sun.domain.TokenRepository { - return com.sun.data.repository.TokenRepositoryImpl(local) +fun provideTokenRepository(local: com.sun.data.source.TokenDataSource.Local): TokenRepository { + return TokenRepositoryImpl(local) } -fun provideMovieRepository(remote: com.sun.data.source.MovieDataSource.Remote, local: com.sun.data.source.MovieDataSource.Local): com.sun.domain.MovieRepository { - return com.sun.data.repository.MovieRepositoryImpl(remote, local) +fun provideMovieRepository(remote: MovieDataSource.Remote, local: MovieDataSource.Local): MovieRepository { + return MovieRepositoryImpl(remote, local) } diff --git a/presentation/src/main/java/com/sun/android/ui/detail/DetailFragment.kt b/presentation/src/main/java/com/sun/android/ui/detail/DetailFragment.kt index ec43d4e..0acfa2b 100644 --- a/presentation/src/main/java/com/sun/android/ui/detail/DetailFragment.kt +++ b/presentation/src/main/java/com/sun/android/ui/detail/DetailFragment.kt @@ -26,11 +26,11 @@ class DetailFragment : BaseFragment(FragmentDetailBinding override fun bindData() { viewModel.movie.observe(viewLifecycleOwner, Observer { - binding.imageBackDrop.loadImageWithUrl(it.backDropImage) - binding.imageMovie.loadImageCircleWithUrl(it.urlImage) + binding.imageBackDrop.loadImageWithUrl(it.backgroundUrl) + binding.imageMovie.loadImageCircleWithUrl(it.avatarUrl) binding.textTitle.text = it.title - binding.textDescription.text = it.overView - binding.textRatting.text = it.vote.toString() + binding.textDescription.text = it.description + binding.textRatting.text = it.rating.toString() binding.textTotalReview.text = it.voteCount.toString() }) } diff --git a/presentation/src/main/java/com/sun/android/ui/detail/MovieDetailViewModel.kt b/presentation/src/main/java/com/sun/android/ui/detail/MovieDetailViewModel.kt index ad3b59b..1584128 100644 --- a/presentation/src/main/java/com/sun/android/ui/detail/MovieDetailViewModel.kt +++ b/presentation/src/main/java/com/sun/android/ui/detail/MovieDetailViewModel.kt @@ -2,15 +2,15 @@ package com.sun.android.ui.detail import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sun.domain.MovieRepository -import com.sun.data.model.Movie +import com.sun.domain.repository.MovieRepository import com.sun.android.utils.LogUtils import com.sun.android.utils.livedata.SingleLiveData +import com.sun.domain.entities.MovieEntity import kotlinx.coroutines.flow.catch import kotlinx.coroutines.launch -class MovieDetailViewModel(private val movieRepository: com.sun.domain.MovieRepository) : ViewModel() { - val movie = SingleLiveData() +class MovieDetailViewModel(private val movieRepository: MovieRepository) : ViewModel() { + val movie = SingleLiveData() fun requestMovieDetails(movieId: Int) { viewModelScope.launch { diff --git a/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesFragment.kt b/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesFragment.kt index a61a7c6..3c52b63 100644 --- a/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesFragment.kt +++ b/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesFragment.kt @@ -3,17 +3,17 @@ package com.sun.android.ui.listmovie import androidx.lifecycle.Observer import com.sun.android.R import com.sun.android.base.BaseFragment -import com.sun.data.model.Movie import com.sun.android.databinding.MoviesFragmentBinding import com.sun.android.ui.detail.DetailFragment import com.sun.android.ui.listmovie.adapter.MoviesAdapter import com.sun.android.utils.extension.addFragment import com.sun.android.utils.extension.notNull import com.sun.android.utils.recycler.OnItemRecyclerViewClickListener +import com.sun.domain.entities.MovieEntity import org.koin.androidx.viewmodel.ext.android.viewModel class MoviesFragment : BaseFragment(MoviesFragmentBinding::inflate), - OnItemRecyclerViewClickListener { + OnItemRecyclerViewClickListener { private val mMovieAdapter: MoviesAdapter by lazy { MoviesAdapter() } @@ -39,7 +39,7 @@ class MoviesFragment : BaseFragment(MoviesFragmentBinding ) } - override fun onItemClick(item: com.sun.data.model.Movie?) { + override fun onItemClick(item: MovieEntity?) { item.notNull { addFragment(R.id.layoutContainer, DetailFragment.newInstance(it.id), true) } diff --git a/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt b/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt index 648e065..56a58e3 100644 --- a/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt +++ b/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt @@ -2,17 +2,17 @@ package com.sun.android.ui.listmovie import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sun.domain.MovieRepository -import com.sun.data.model.Movie import com.sun.android.utils.LogUtils import com.sun.android.utils.dispatchers.DispatcherProvider import com.sun.android.utils.livedata.SingleLiveData +import com.sun.domain.entities.MovieEntity +import com.sun.domain.repository.MovieRepository import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.launch -class MoviesViewModel(private val movieRepository: com.sun.domain.MovieRepository) : ViewModel() { - val movies = SingleLiveData>() +class MoviesViewModel(private val movieRepository: MovieRepository) : ViewModel() { + val movies = SingleLiveData>() fun requestTopRateMovies() { viewModelScope.launch { diff --git a/presentation/src/main/java/com/sun/android/ui/listmovie/adapter/MoviesAdapter.kt b/presentation/src/main/java/com/sun/android/ui/listmovie/adapter/MoviesAdapter.kt index 890a096..d04d055 100644 --- a/presentation/src/main/java/com/sun/android/ui/listmovie/adapter/MoviesAdapter.kt +++ b/presentation/src/main/java/com/sun/android/ui/listmovie/adapter/MoviesAdapter.kt @@ -4,16 +4,16 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView -import com.sun.data.model.Movie import com.sun.android.databinding.ItemLayoutMovieBinding import com.sun.android.utils.extension.loadImageCircleWithUrl import com.sun.android.utils.extension.notNull import com.sun.android.utils.recycler.OnItemRecyclerViewClickListener +import com.sun.domain.entities.MovieEntity class MoviesAdapter : RecyclerView.Adapter() { - private val movies = mutableListOf() - private var onItemClickListener: OnItemRecyclerViewClickListener? = null + private val movies = mutableListOf() + private var onItemClickListener: OnItemRecyclerViewClickListener? = null override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val binding = ItemLayoutMovieBinding.inflate(LayoutInflater.from(parent.context), parent, false) @@ -29,12 +29,12 @@ class MoviesAdapter : RecyclerView.Adapter() { } fun registerItemRecyclerViewClickListener( - onItemRecyclerViewClickListener: OnItemRecyclerViewClickListener? + onItemRecyclerViewClickListener: OnItemRecyclerViewClickListener? ) { onItemClickListener = onItemRecyclerViewClickListener } - fun updateData(movies: List) { + fun updateData(movies: List) { movies.notNull { this.movies.clear() this.movies.addAll(it) @@ -44,29 +44,29 @@ class MoviesAdapter : RecyclerView.Adapter() { class ViewHolder( private val binding: ItemLayoutMovieBinding, - itemClickListener: OnItemRecyclerViewClickListener? + itemClickListener: OnItemRecyclerViewClickListener? ) : RecyclerView.ViewHolder(binding.root), View.OnClickListener { - private var movieData: com.sun.data.model.Movie? = null - private var listener: OnItemRecyclerViewClickListener? = null + private var movieEntity: MovieEntity? = null + private var listener: OnItemRecyclerViewClickListener? = null init { itemView.setOnClickListener(this) listener = itemClickListener } - fun bindViewData(movie: com.sun.data.model.Movie) { + fun bindViewData(movie: MovieEntity) { movie.let { binding.textViewTitle.text = it.title - binding.textViewRatting.text = it.vote.toString() - binding.textViewContent.text = it.originalTitle - binding.imageMovie.loadImageCircleWithUrl(it.urlImage) - movieData = it + binding.textViewRatting.text = it.rating.toString() + binding.textViewContent.text = it.description + binding.imageMovie.loadImageCircleWithUrl(it.avatarUrl) + movieEntity = it } } override fun onClick(view: View?) { - listener?.onItemClick(movieData) + listener?.onItemClick(movieEntity) } } } From 2e12dcc351c3f83f9d1116017cf29ff350de363d Mon Sep 17 00:00:00 2001 From: "le.quang.dao" Date: Mon, 22 Apr 2024 15:55:05 +0700 Subject: [PATCH 5/6] [fix] remove mapper --- data/src/main/java/com/sun/data/Mapper.kt | 13 ----- .../java/com/sun/data/entities/MovieLocal.kt | 43 --------------- .../data/repository/MovieRepositoryImpl.kt | 36 ++++++------- .../com/sun/data/source/MovieDataSource.kt | 4 +- .../sun/data/source/local/MovieLocalImpl.kt | 2 +- .../data/source/local/entities/MovieLocal.kt | 41 +++++++++++++++ .../sun/data/source/local/room/AppDatabase.kt | 2 +- .../sun/data/source/local/room/MovieDao.kt | 2 +- .../sun/data/source/remote/MovieRemoteImpl.kt | 2 +- .../sun/data/source/remote/api/ApiService.kt | 2 +- .../remote/model}/MovieRemote.kt | 52 +++++++++---------- .../entities/{MovieEntity.kt => Movie.kt} | 2 +- .../sun/domain/repository/MovieRepository.kt | 6 +-- .../android/ui/detail/MovieDetailViewModel.kt | 4 +- .../android/ui/listmovie/MoviesFragment.kt | 6 +-- .../android/ui/listmovie/MoviesViewModel.kt | 4 +- .../ui/listmovie/adapter/MoviesAdapter.kt | 18 +++---- 17 files changed, 111 insertions(+), 128 deletions(-) delete mode 100644 data/src/main/java/com/sun/data/Mapper.kt delete mode 100644 data/src/main/java/com/sun/data/entities/MovieLocal.kt create mode 100644 data/src/main/java/com/sun/data/source/local/entities/MovieLocal.kt rename data/src/main/java/com/sun/data/{entities => source/remote/model}/MovieRemote.kt (50%) rename domain/src/main/java/com/sun/domain/entities/{MovieEntity.kt => Movie.kt} (89%) diff --git a/data/src/main/java/com/sun/data/Mapper.kt b/data/src/main/java/com/sun/data/Mapper.kt deleted file mode 100644 index 6bb36b7..0000000 --- a/data/src/main/java/com/sun/data/Mapper.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.sun.data - -abstract class Mapper { - abstract fun mapToEntity(): E - - open fun mapToLocal(): L? { - return null - } - - open fun mapToRemote(): R? { - return null - } -} diff --git a/data/src/main/java/com/sun/data/entities/MovieLocal.kt b/data/src/main/java/com/sun/data/entities/MovieLocal.kt deleted file mode 100644 index 88f175d..0000000 --- a/data/src/main/java/com/sun/data/entities/MovieLocal.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.sun.data.entities - -import androidx.room.Entity -import androidx.room.PrimaryKey -import com.sun.data.Mapper -import com.sun.domain.entities.MovieEntity - -@Entity(tableName = "movies") -data class MovieLocal( - @PrimaryKey - var id: Int = -1, - val description: String, - val image: String, - val backgroundUrl: String, - val title: String, - val rating: Double, - val voteCount: Int -) : Mapper() { - - override fun mapToEntity(): MovieEntity { - return MovieEntity( - id = id, - title = title, - description = description, - avatarUrl = image, - backgroundUrl = backgroundUrl, - rating = rating, - voteCount = voteCount - ) - } - - override fun mapToRemote(): MovieRemote { - return MovieRemote( - id = id, - title = title, - overView = description, - urlImage = image, - backDropImage = backgroundUrl, - rating = rating, - voteCount = voteCount - ) - } -} diff --git a/data/src/main/java/com/sun/data/repository/MovieRepositoryImpl.kt b/data/src/main/java/com/sun/data/repository/MovieRepositoryImpl.kt index a340420..2569f68 100644 --- a/data/src/main/java/com/sun/data/repository/MovieRepositoryImpl.kt +++ b/data/src/main/java/com/sun/data/repository/MovieRepositoryImpl.kt @@ -1,9 +1,11 @@ package com.sun.data.repository import android.util.Log -import com.sun.data.entities.MovieLocal +import com.sun.data.source.local.entities.toEntity import com.sun.data.source.MovieDataSource -import com.sun.domain.entities.MovieEntity +import com.sun.data.source.remote.model.toEntity +import com.sun.data.source.remote.model.toLocal +import com.sun.domain.entities.Movie import com.sun.domain.repository.MovieRepository import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow @@ -15,34 +17,30 @@ class MovieRepositoryImpl( private val local: MovieDataSource.Local ) : KoinComponent, MovieRepository { - override suspend fun getMovies(): Flow> = flow { - val movies = arrayListOf() + override suspend fun getMovies(): Flow> = flow { + val movies = arrayListOf() try { - val movieDts = remote.getMovies().data - movieDts.forEach { - movies.add(it.mapToEntity()) - } - - val movieDbs = arrayListOf() - movieDts.forEach { - movieDbs.add(it.mapToLocal()) - } - local.updateMovies(movieDbs) + val movieRemotes = remote.getMovies().data + movies.addAll(movieRemotes.map { it.toEntity() }) + // save to locals + local.updateMovies(movieRemotes.map { it.toLocal() }) } catch (e: IOException) { - val moviesDbs = local.getMoviesLocal() + movies.addAll(local.getMoviesLocal().map { + it.toEntity() + }) Log.e("MovieRepository", "getMovies failed, using local data \n Detail error:\n $e") } emit(movies) } - override suspend fun getDetailMovies(movieId: Int): Flow = flow { + override suspend fun getDetailMovies(movieId: Int): Flow = flow { try { - emit(local.getMovieDetailLocal(movieId).mapToEntity()) + emit(local.getMovieDetailLocal(movieId).toEntity()) } catch (e: IOException) { Log.e("MovieRepository", "getDetailMovies failed, retry with network \n Detail error:\n $e") val movieRemote = remote.getMovieDetail(movieId = movieId) - local.updateMovies(arrayListOf(movieRemote.mapToLocal())) - emit(movieRemote.mapToEntity()) + local.updateMovies(arrayListOf(movieRemote.toLocal())) + emit(movieRemote.toEntity()) } } } diff --git a/data/src/main/java/com/sun/data/source/MovieDataSource.kt b/data/src/main/java/com/sun/data/source/MovieDataSource.kt index 4bfc29a..90d799b 100644 --- a/data/src/main/java/com/sun/data/source/MovieDataSource.kt +++ b/data/src/main/java/com/sun/data/source/MovieDataSource.kt @@ -1,7 +1,7 @@ package com.sun.data.source -import com.sun.data.entities.MovieRemote -import com.sun.data.entities.MovieLocal +import com.sun.data.source.remote.model.MovieRemote +import com.sun.data.source.local.entities.MovieLocal import com.sun.data.source.remote.api.response.BaseResponse interface MovieDataSource { diff --git a/data/src/main/java/com/sun/data/source/local/MovieLocalImpl.kt b/data/src/main/java/com/sun/data/source/local/MovieLocalImpl.kt index 6f1586c..233b7b4 100644 --- a/data/src/main/java/com/sun/data/source/local/MovieLocalImpl.kt +++ b/data/src/main/java/com/sun/data/source/local/MovieLocalImpl.kt @@ -1,6 +1,6 @@ package com.sun.data.source.local -import com.sun.data.entities.MovieLocal +import com.sun.data.source.local.entities.MovieLocal import com.sun.data.source.MovieDataSource import com.sun.data.source.local.room.MovieDao diff --git a/data/src/main/java/com/sun/data/source/local/entities/MovieLocal.kt b/data/src/main/java/com/sun/data/source/local/entities/MovieLocal.kt new file mode 100644 index 0000000..a91ee6a --- /dev/null +++ b/data/src/main/java/com/sun/data/source/local/entities/MovieLocal.kt @@ -0,0 +1,41 @@ +package com.sun.data.source.local.entities + +import androidx.room.Entity +import androidx.room.PrimaryKey +import com.sun.data.source.remote.model.MovieRemote +import com.sun.domain.entities.Movie + +@Entity(tableName = "movies") +data class MovieLocal( + @PrimaryKey var id: Int = -1, + val description: String, + val image: String, + val backgroundUrl: String, + val title: String, + val rating: Double, + val voteCount: Int +) + +fun MovieLocal.toEntity(): Movie { + return Movie( + id = id, + title = title, + description = description, + avatarUrl = image, + backgroundUrl = backgroundUrl, + rating = rating, + voteCount = voteCount + ) +} + +fun MovieLocal.toRemote(): MovieRemote { + return MovieRemote( + id = id, + title = title, + overView = description, + urlImage = image, + backDropImage = backgroundUrl, + rating = rating, + voteCount = voteCount + ) +} diff --git a/data/src/main/java/com/sun/data/source/local/room/AppDatabase.kt b/data/src/main/java/com/sun/data/source/local/room/AppDatabase.kt index c3b6893..e9aebcf 100644 --- a/data/src/main/java/com/sun/data/source/local/room/AppDatabase.kt +++ b/data/src/main/java/com/sun/data/source/local/room/AppDatabase.kt @@ -5,7 +5,7 @@ import androidx.room.Database import androidx.room.Room import androidx.room.RoomDatabase import com.sun.data.Constant -import com.sun.data.entities.MovieLocal +import com.sun.data.source.local.entities.MovieLocal @Database(entities = [MovieLocal::class], version = 1, exportSchema = false) abstract class AppDatabase : RoomDatabase() { diff --git a/data/src/main/java/com/sun/data/source/local/room/MovieDao.kt b/data/src/main/java/com/sun/data/source/local/room/MovieDao.kt index e663305..4bc414b 100644 --- a/data/src/main/java/com/sun/data/source/local/room/MovieDao.kt +++ b/data/src/main/java/com/sun/data/source/local/room/MovieDao.kt @@ -6,7 +6,7 @@ import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query import androidx.room.Update -import com.sun.data.entities.MovieLocal +import com.sun.data.source.local.entities.MovieLocal @Dao interface MovieDao { diff --git a/data/src/main/java/com/sun/data/source/remote/MovieRemoteImpl.kt b/data/src/main/java/com/sun/data/source/remote/MovieRemoteImpl.kt index f257bfc..c6a0bf2 100644 --- a/data/src/main/java/com/sun/data/source/remote/MovieRemoteImpl.kt +++ b/data/src/main/java/com/sun/data/source/remote/MovieRemoteImpl.kt @@ -1,7 +1,7 @@ package com.sun.data.source.remote import com.sun.data.BuildConfig -import com.sun.data.entities.MovieRemote +import com.sun.data.source.remote.model.MovieRemote import com.sun.data.source.MovieDataSource import com.sun.data.source.remote.api.ApiService import com.sun.data.source.remote.api.response.BaseResponse diff --git a/data/src/main/java/com/sun/data/source/remote/api/ApiService.kt b/data/src/main/java/com/sun/data/source/remote/api/ApiService.kt index 98bcf32..bbb7887 100644 --- a/data/src/main/java/com/sun/data/source/remote/api/ApiService.kt +++ b/data/src/main/java/com/sun/data/source/remote/api/ApiService.kt @@ -1,6 +1,6 @@ package com.sun.data.source.remote.api -import com.sun.data.entities.MovieRemote +import com.sun.data.source.remote.model.MovieRemote import com.sun.data.source.remote.api.response.BaseResponse import retrofit2.http.GET import retrofit2.http.Path diff --git a/data/src/main/java/com/sun/data/entities/MovieRemote.kt b/data/src/main/java/com/sun/data/source/remote/model/MovieRemote.kt similarity index 50% rename from data/src/main/java/com/sun/data/entities/MovieRemote.kt rename to data/src/main/java/com/sun/data/source/remote/model/MovieRemote.kt index 27f34fe..e5a0148 100644 --- a/data/src/main/java/com/sun/data/entities/MovieRemote.kt +++ b/data/src/main/java/com/sun/data/source/remote/model/MovieRemote.kt @@ -1,10 +1,10 @@ -package com.sun.data.entities +package com.sun.data.source.remote.model import android.os.Parcelable import com.google.gson.annotations.Expose import com.google.gson.annotations.SerializedName -import com.sun.data.Mapper -import com.sun.domain.entities.MovieEntity +import com.sun.data.source.local.entities.MovieLocal +import com.sun.domain.entities.Movie import kotlinx.android.parcel.Parcelize @Parcelize @@ -33,28 +33,28 @@ data class MovieRemote( @SerializedName("original_title") @Expose var originalTitle: String = "" -) : Parcelable, Mapper() { - override fun mapToEntity(): MovieEntity { - return MovieEntity( - id = id, - title = title, - description = overView, - avatarUrl = urlImage, - backgroundUrl = backDropImage, - rating = rating, - voteCount = voteCount - ) - } +) : Parcelable - override fun mapToLocal(): MovieLocal { - return MovieLocal( - id = id, - description = overView, - image = urlImage, - backgroundUrl = backDropImage, - title = title, - rating = rating, - voteCount = voteCount - ) - } +fun MovieRemote.toEntity(): Movie { + return Movie( + id = id, + title = title, + description = overView, + avatarUrl = urlImage, + backgroundUrl = backDropImage, + rating = rating, + voteCount = voteCount + ) +} + +fun MovieRemote.toLocal(): MovieLocal { + return MovieLocal( + id = id, + description = overView, + image = urlImage, + backgroundUrl = backDropImage, + title = title, + rating = rating, + voteCount = voteCount + ) } diff --git a/domain/src/main/java/com/sun/domain/entities/MovieEntity.kt b/domain/src/main/java/com/sun/domain/entities/Movie.kt similarity index 89% rename from domain/src/main/java/com/sun/domain/entities/MovieEntity.kt rename to domain/src/main/java/com/sun/domain/entities/Movie.kt index 33700bc..0990635 100644 --- a/domain/src/main/java/com/sun/domain/entities/MovieEntity.kt +++ b/domain/src/main/java/com/sun/domain/entities/Movie.kt @@ -1,6 +1,6 @@ package com.sun.domain.entities -data class MovieEntity( +data class Movie( val id: Int, val title: String, val description: String, diff --git a/domain/src/main/java/com/sun/domain/repository/MovieRepository.kt b/domain/src/main/java/com/sun/domain/repository/MovieRepository.kt index 0915541..b3fbaad 100644 --- a/domain/src/main/java/com/sun/domain/repository/MovieRepository.kt +++ b/domain/src/main/java/com/sun/domain/repository/MovieRepository.kt @@ -1,10 +1,10 @@ package com.sun.domain.repository -import com.sun.domain.entities.MovieEntity +import com.sun.domain.entities.Movie import kotlinx.coroutines.flow.Flow interface MovieRepository { - suspend fun getMovies(): Flow> + suspend fun getMovies(): Flow> - suspend fun getDetailMovies(movieId: Int): Flow + suspend fun getDetailMovies(movieId: Int): Flow } diff --git a/presentation/src/main/java/com/sun/android/ui/detail/MovieDetailViewModel.kt b/presentation/src/main/java/com/sun/android/ui/detail/MovieDetailViewModel.kt index 1584128..58dc313 100644 --- a/presentation/src/main/java/com/sun/android/ui/detail/MovieDetailViewModel.kt +++ b/presentation/src/main/java/com/sun/android/ui/detail/MovieDetailViewModel.kt @@ -5,12 +5,12 @@ import androidx.lifecycle.viewModelScope import com.sun.domain.repository.MovieRepository import com.sun.android.utils.LogUtils import com.sun.android.utils.livedata.SingleLiveData -import com.sun.domain.entities.MovieEntity +import com.sun.domain.entities.Movie import kotlinx.coroutines.flow.catch import kotlinx.coroutines.launch class MovieDetailViewModel(private val movieRepository: MovieRepository) : ViewModel() { - val movie = SingleLiveData() + val movie = SingleLiveData() fun requestMovieDetails(movieId: Int) { viewModelScope.launch { diff --git a/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesFragment.kt b/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesFragment.kt index 3c52b63..3d3d363 100644 --- a/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesFragment.kt +++ b/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesFragment.kt @@ -9,11 +9,11 @@ import com.sun.android.ui.listmovie.adapter.MoviesAdapter import com.sun.android.utils.extension.addFragment import com.sun.android.utils.extension.notNull import com.sun.android.utils.recycler.OnItemRecyclerViewClickListener -import com.sun.domain.entities.MovieEntity +import com.sun.domain.entities.Movie import org.koin.androidx.viewmodel.ext.android.viewModel class MoviesFragment : BaseFragment(MoviesFragmentBinding::inflate), - OnItemRecyclerViewClickListener { + OnItemRecyclerViewClickListener { private val mMovieAdapter: MoviesAdapter by lazy { MoviesAdapter() } @@ -39,7 +39,7 @@ class MoviesFragment : BaseFragment(MoviesFragmentBinding ) } - override fun onItemClick(item: MovieEntity?) { + override fun onItemClick(item: Movie?) { item.notNull { addFragment(R.id.layoutContainer, DetailFragment.newInstance(it.id), true) } diff --git a/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt b/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt index 56a58e3..758df26 100644 --- a/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt +++ b/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt @@ -5,14 +5,14 @@ import androidx.lifecycle.viewModelScope import com.sun.android.utils.LogUtils import com.sun.android.utils.dispatchers.DispatcherProvider import com.sun.android.utils.livedata.SingleLiveData -import com.sun.domain.entities.MovieEntity +import com.sun.domain.entities.Movie import com.sun.domain.repository.MovieRepository import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.launch class MoviesViewModel(private val movieRepository: MovieRepository) : ViewModel() { - val movies = SingleLiveData>() + val movies = SingleLiveData>() fun requestTopRateMovies() { viewModelScope.launch { diff --git a/presentation/src/main/java/com/sun/android/ui/listmovie/adapter/MoviesAdapter.kt b/presentation/src/main/java/com/sun/android/ui/listmovie/adapter/MoviesAdapter.kt index d04d055..a6a3856 100644 --- a/presentation/src/main/java/com/sun/android/ui/listmovie/adapter/MoviesAdapter.kt +++ b/presentation/src/main/java/com/sun/android/ui/listmovie/adapter/MoviesAdapter.kt @@ -8,12 +8,12 @@ import com.sun.android.databinding.ItemLayoutMovieBinding import com.sun.android.utils.extension.loadImageCircleWithUrl import com.sun.android.utils.extension.notNull import com.sun.android.utils.recycler.OnItemRecyclerViewClickListener -import com.sun.domain.entities.MovieEntity +import com.sun.domain.entities.Movie class MoviesAdapter : RecyclerView.Adapter() { - private val movies = mutableListOf() - private var onItemClickListener: OnItemRecyclerViewClickListener? = null + private val movies = mutableListOf() + private var onItemClickListener: OnItemRecyclerViewClickListener? = null override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val binding = ItemLayoutMovieBinding.inflate(LayoutInflater.from(parent.context), parent, false) @@ -29,12 +29,12 @@ class MoviesAdapter : RecyclerView.Adapter() { } fun registerItemRecyclerViewClickListener( - onItemRecyclerViewClickListener: OnItemRecyclerViewClickListener? + onItemRecyclerViewClickListener: OnItemRecyclerViewClickListener? ) { onItemClickListener = onItemRecyclerViewClickListener } - fun updateData(movies: List) { + fun updateData(movies: List) { movies.notNull { this.movies.clear() this.movies.addAll(it) @@ -44,18 +44,18 @@ class MoviesAdapter : RecyclerView.Adapter() { class ViewHolder( private val binding: ItemLayoutMovieBinding, - itemClickListener: OnItemRecyclerViewClickListener? + itemClickListener: OnItemRecyclerViewClickListener? ) : RecyclerView.ViewHolder(binding.root), View.OnClickListener { - private var movieEntity: MovieEntity? = null - private var listener: OnItemRecyclerViewClickListener? = null + private var movieEntity: Movie? = null + private var listener: OnItemRecyclerViewClickListener? = null init { itemView.setOnClickListener(this) listener = itemClickListener } - fun bindViewData(movie: MovieEntity) { + fun bindViewData(movie: Movie) { movie.let { binding.textViewTitle.text = it.title binding.textViewRatting.text = it.rating.toString() From 39e6790430ee8f482688450c298e03b567ccf3e0 Mon Sep 17 00:00:00 2001 From: "le.quang.dao" Date: Tue, 23 Apr 2024 15:31:35 +0700 Subject: [PATCH 6/6] [Fix] temp --- .../dispatchers/BaseDispatcherProvider.kt | 7 +---- .../domain}/dispatchers/DispatcherProvider.kt | 7 +---- .../domain/usecase/GetMovieDetailUseCase.kt | 4 +++ .../sun/domain/usecase/GetMovieListUseCase.kt | 16 ++++++++++++ .../domain/usecase/base/BaseDirectUseCase.kt | 14 ++++++++++ .../sun/domain/usecase/base/BaseObserver.kt | 26 +++++++++++++++++++ .../sun/domain/usecase/base/BaseUseCase.kt | 21 +++++++++++++++ .../com/sun/android/AndroidApplication.kt | 4 ++- .../main/java/com/sun/android/di/AppModule.kt | 4 +-- .../java/com/sun/android/di/UseCaseModule.kt | 8 ++++++ .../android/ui/listmovie/MoviesViewModel.kt | 17 ++++++------ 11 files changed, 104 insertions(+), 24 deletions(-) rename {presentation/src/main/java/com/sun/android/utils => domain/src/main/java/com/sun/domain}/dispatchers/BaseDispatcherProvider.kt (65%) rename {presentation/src/main/java/com/sun/android/utils => domain/src/main/java/com/sun/domain}/dispatchers/DispatcherProvider.kt (76%) create mode 100644 domain/src/main/java/com/sun/domain/usecase/GetMovieDetailUseCase.kt create mode 100644 domain/src/main/java/com/sun/domain/usecase/GetMovieListUseCase.kt create mode 100644 domain/src/main/java/com/sun/domain/usecase/base/BaseDirectUseCase.kt create mode 100644 domain/src/main/java/com/sun/domain/usecase/base/BaseObserver.kt create mode 100644 domain/src/main/java/com/sun/domain/usecase/base/BaseUseCase.kt create mode 100644 presentation/src/main/java/com/sun/android/di/UseCaseModule.kt diff --git a/presentation/src/main/java/com/sun/android/utils/dispatchers/BaseDispatcherProvider.kt b/domain/src/main/java/com/sun/domain/dispatchers/BaseDispatcherProvider.kt similarity index 65% rename from presentation/src/main/java/com/sun/android/utils/dispatchers/BaseDispatcherProvider.kt rename to domain/src/main/java/com/sun/domain/dispatchers/BaseDispatcherProvider.kt index 6171799..aa9edb4 100644 --- a/presentation/src/main/java/com/sun/android/utils/dispatchers/BaseDispatcherProvider.kt +++ b/domain/src/main/java/com/sun/domain/dispatchers/BaseDispatcherProvider.kt @@ -1,19 +1,14 @@ -package com.sun.android.utils.dispatchers +package com.sun.domain.dispatchers -import androidx.annotation.NonNull import kotlinx.coroutines.CoroutineDispatcher interface BaseDispatcherProvider { - @NonNull fun computation(): CoroutineDispatcher - @NonNull fun io(): CoroutineDispatcher - @NonNull fun ui(): CoroutineDispatcher - @NonNull fun unconfined(): CoroutineDispatcher } diff --git a/presentation/src/main/java/com/sun/android/utils/dispatchers/DispatcherProvider.kt b/domain/src/main/java/com/sun/domain/dispatchers/DispatcherProvider.kt similarity index 76% rename from presentation/src/main/java/com/sun/android/utils/dispatchers/DispatcherProvider.kt rename to domain/src/main/java/com/sun/domain/dispatchers/DispatcherProvider.kt index 77b3861..06763bc 100644 --- a/presentation/src/main/java/com/sun/android/utils/dispatchers/DispatcherProvider.kt +++ b/domain/src/main/java/com/sun/domain/dispatchers/DispatcherProvider.kt @@ -1,20 +1,15 @@ -package com.sun.android.utils.dispatchers +package com.sun.domain.dispatchers -import androidx.annotation.NonNull import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers class DispatcherProvider : BaseDispatcherProvider { - @NonNull override fun computation(): CoroutineDispatcher = Dispatchers.Default - @NonNull override fun io(): CoroutineDispatcher = Dispatchers.IO - @NonNull override fun ui(): CoroutineDispatcher = Dispatchers.Main - @NonNull override fun unconfined(): CoroutineDispatcher = Dispatchers.Unconfined } diff --git a/domain/src/main/java/com/sun/domain/usecase/GetMovieDetailUseCase.kt b/domain/src/main/java/com/sun/domain/usecase/GetMovieDetailUseCase.kt new file mode 100644 index 0000000..0c41b85 --- /dev/null +++ b/domain/src/main/java/com/sun/domain/usecase/GetMovieDetailUseCase.kt @@ -0,0 +1,4 @@ +package com.sun.domain.usecase + +class GetMovieDetailUseCase { +} diff --git a/domain/src/main/java/com/sun/domain/usecase/GetMovieListUseCase.kt b/domain/src/main/java/com/sun/domain/usecase/GetMovieListUseCase.kt new file mode 100644 index 0000000..48e91c4 --- /dev/null +++ b/domain/src/main/java/com/sun/domain/usecase/GetMovieListUseCase.kt @@ -0,0 +1,16 @@ +package com.sun.domain.usecase + +import com.sun.domain.entities.Movie +import com.sun.domain.repository.MovieRepository +import com.sun.domain.usecase.base.BaseUseCase +import kotlinx.coroutines.flow.Flow + +class GetMovieListUseCase(private val movieRepository: MovieRepository) : + BaseUseCase>() { + + class Input + + override suspend fun buildUseCase(input: Input): Flow> { + return movieRepository.getMovies() + } +} diff --git a/domain/src/main/java/com/sun/domain/usecase/base/BaseDirectUseCase.kt b/domain/src/main/java/com/sun/domain/usecase/base/BaseDirectUseCase.kt new file mode 100644 index 0000000..d6e1174 --- /dev/null +++ b/domain/src/main/java/com/sun/domain/usecase/base/BaseDirectUseCase.kt @@ -0,0 +1,14 @@ +package com.sun.domain.usecase.base + + +/** + * For using directly on current thread, not switching. + */ +abstract class BaseDirectUseCase { + + abstract fun buildUseCase(input: Input): Output + + operator fun invoke(input: Input): Output { + return buildUseCase(input) + } +} diff --git a/domain/src/main/java/com/sun/domain/usecase/base/BaseObserver.kt b/domain/src/main/java/com/sun/domain/usecase/base/BaseObserver.kt new file mode 100644 index 0000000..e40f9d0 --- /dev/null +++ b/domain/src/main/java/com/sun/domain/usecase/base/BaseObserver.kt @@ -0,0 +1,26 @@ +package com.sun.domain.usecase.base + +import kotlinx.coroutines.CancellationException + +open class BaseObserver { + private var onSubscribe: (() -> Unit)? = null + private var onSuccess: ((Output?) -> Unit)? = null + private var onError: ((Throwable) -> Unit)? = null + private var onCancel: ((CancellationException) -> Unit)? = null + + fun onSubscribe(block: () -> Unit) { + onSubscribe = block + } + + fun onSuccess(block: (Output?) -> Unit) { + onSuccess = block + } + + fun onError(block: (Throwable) -> Unit) { + onError = block + } + + operator fun invoke() = onSubscribe?.invoke() + operator fun invoke(output: Output?) = onSuccess?.invoke(output) + operator fun invoke(throwable: Throwable) = onError?.invoke(throwable) +} diff --git a/domain/src/main/java/com/sun/domain/usecase/base/BaseUseCase.kt b/domain/src/main/java/com/sun/domain/usecase/base/BaseUseCase.kt new file mode 100644 index 0000000..01a73dc --- /dev/null +++ b/domain/src/main/java/com/sun/domain/usecase/base/BaseUseCase.kt @@ -0,0 +1,21 @@ +package com.sun.domain.usecase.base + +import com.sun.domain.dispatchers.DispatcherProvider +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.flowOn + +abstract class BaseUseCase { + + protected abstract suspend fun buildUseCase(input: Input): Flow + + suspend operator fun invoke(input: Input, block: BaseObserver.() -> Unit) { + val response = BaseObserver().apply { block() } + buildUseCase(input).catch { + response(it) + }.flowOn(DispatcherProvider().io()).collect { + response(it) + } + } +} diff --git a/presentation/src/main/java/com/sun/android/AndroidApplication.kt b/presentation/src/main/java/com/sun/android/AndroidApplication.kt index a21618b..5e74d2f 100644 --- a/presentation/src/main/java/com/sun/android/AndroidApplication.kt +++ b/presentation/src/main/java/com/sun/android/AndroidApplication.kt @@ -6,13 +6,15 @@ import com.sun.android.di.NetworkModule import com.sun.android.di.RepositoryModule import com.sun.android.di.AppModule import com.sun.android.di.ViewModelModule +import com.sun.android.di.UseCaseModule import org.koin.android.ext.koin.androidContext import org.koin.android.ext.koin.androidFileProperties import org.koin.core.context.startKoin class AndroidApplication : Application() { - private val rootModule = listOf(AppModule, NetworkModule, DataSourceModule, RepositoryModule, ViewModelModule) + private val rootModule = + listOf(AppModule, NetworkModule, DataSourceModule, RepositoryModule, UseCaseModule, ViewModelModule) override fun onCreate() { super.onCreate() diff --git a/presentation/src/main/java/com/sun/android/di/AppModule.kt b/presentation/src/main/java/com/sun/android/di/AppModule.kt index 820c1c0..0154e8f 100644 --- a/presentation/src/main/java/com/sun/android/di/AppModule.kt +++ b/presentation/src/main/java/com/sun/android/di/AppModule.kt @@ -6,8 +6,8 @@ import com.google.gson.FieldNamingPolicy import com.google.gson.Gson import com.google.gson.GsonBuilder import com.sun.android.utils.DateTimeUtils -import com.sun.android.utils.dispatchers.BaseDispatcherProvider -import com.sun.android.utils.dispatchers.DispatcherProvider +import com.sun.domain.dispatchers.BaseDispatcherProvider +import com.sun.domain.dispatchers.DispatcherProvider import com.sun.data.source.local.api.SharedPrefsApi import com.sun.data.source.local.api.sharedpref.SharedPrefsImpl import org.koin.dsl.module diff --git a/presentation/src/main/java/com/sun/android/di/UseCaseModule.kt b/presentation/src/main/java/com/sun/android/di/UseCaseModule.kt new file mode 100644 index 0000000..50a24a6 --- /dev/null +++ b/presentation/src/main/java/com/sun/android/di/UseCaseModule.kt @@ -0,0 +1,8 @@ +package com.sun.android.di + +import com.sun.domain.usecase.GetMovieListUseCase +import org.koin.dsl.module + +val UseCaseModule = module { + factory { GetMovieListUseCase(get()) } +} diff --git a/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt b/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt index 758df26..5554ccc 100644 --- a/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt +++ b/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt @@ -3,25 +3,24 @@ package com.sun.android.ui.listmovie import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.sun.android.utils.LogUtils -import com.sun.android.utils.dispatchers.DispatcherProvider import com.sun.android.utils.livedata.SingleLiveData import com.sun.domain.entities.Movie -import com.sun.domain.repository.MovieRepository -import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.flowOn +import com.sun.domain.usecase.GetMovieListUseCase import kotlinx.coroutines.launch -class MoviesViewModel(private val movieRepository: MovieRepository) : ViewModel() { +class MoviesViewModel(private val getMovieListUseCase: GetMovieListUseCase) : ViewModel() { val movies = SingleLiveData>() fun requestTopRateMovies() { viewModelScope.launch { - movieRepository.getMovies().catch { e -> - LogUtils.e("requestTopRateMovies", e.toString()) - }.flowOn(DispatcherProvider().io()) - .collect { + getMovieListUseCase(GetMovieListUseCase.Input()) { + onSuccess { movies.value = it } + onError { + LogUtils.e("requestTopRateMovies", it.toString()) + } + } } } }