From 71b29c7619b89b13579e944cecb3eb2d68289995 Mon Sep 17 00:00:00 2001 From: "murat.cakir" Date: Thu, 22 Jun 2023 15:54:53 +0300 Subject: [PATCH 1/2] Conversion from Dagger to Hilt --- app/build.gradle | 3 +- .../movee/application/MainApplication.kt | 6 +- .../com/adesso/movee/base/BaseActivity.kt | 13 ++-- .../base/BaseBottomSheetDialogFragment.kt | 17 +---- .../com/adesso/movee/base/BaseFragment.kt | 23 ++++--- .../internal/injection/DaggerApplication.kt | 23 ------- .../injection/component/AppComponent.kt | 33 ---------- .../injection/module/ActivitiesModule.kt | 19 ------ .../internal/injection/module/AppModule.kt | 14 ++-- .../internal/injection/module/CacheModule.kt | 4 +- .../injection/module/DatabaseModule.kt | 39 ++++++----- .../injection/module/FragmentsModule.kt | 64 ------------------- .../internal/injection/module/MoshiModule.kt | 5 +- .../injection/module/NetworkModule.kt | 25 ++++---- .../injection/viewmodel/ViewModelModule.kt | 24 +++---- .../adesso/movee/scene/login/LoginFragment.kt | 3 +- .../adesso/movee/scene/login/LoginModule.kt | 6 -- .../adesso/movee/scene/main/MainActivity.kt | 2 + .../com/adesso/movee/scene/main/MainModule.kt | 6 -- .../adesso/movee/scene/movie/MovieFragment.kt | 2 + .../adesso/movee/scene/movie/MovieModule.kt | 6 -- .../scene/moviedetail/MovieDetailFragment.kt | 2 + .../scene/moviedetail/MovieDetailModule.kt | 6 -- .../persondetail/PersonDetailFragment.kt | 2 + .../scene/persondetail/PersonDetailModule.kt | 6 -- .../movee/scene/profile/ProfileFragment.kt | 2 + .../movee/scene/profile/ProfileModule.kt | 6 -- .../movee/scene/search/SearchFragment.kt | 2 + .../adesso/movee/scene/search/SearchModule.kt | 6 -- .../movee/scene/splash/SplashActivity.kt | 4 ++ .../movee/scene/tvshow/TvShowFragment.kt | 2 + .../adesso/movee/scene/tvshow/TvShowModule.kt | 6 -- .../tvshowdetail/TvShowDetailFragment.kt | 2 + .../scene/tvshowdetail/TvShowDetailModule.kt | 6 -- build.gradle | 1 + config/dependencies.gradle | 12 ++-- 36 files changed, 111 insertions(+), 291 deletions(-) delete mode 100644 app/src/main/kotlin/com/adesso/movee/internal/injection/DaggerApplication.kt delete mode 100644 app/src/main/kotlin/com/adesso/movee/internal/injection/component/AppComponent.kt delete mode 100644 app/src/main/kotlin/com/adesso/movee/internal/injection/module/ActivitiesModule.kt delete mode 100644 app/src/main/kotlin/com/adesso/movee/internal/injection/module/FragmentsModule.kt delete mode 100644 app/src/main/kotlin/com/adesso/movee/scene/login/LoginModule.kt delete mode 100644 app/src/main/kotlin/com/adesso/movee/scene/main/MainModule.kt delete mode 100644 app/src/main/kotlin/com/adesso/movee/scene/movie/MovieModule.kt delete mode 100644 app/src/main/kotlin/com/adesso/movee/scene/moviedetail/MovieDetailModule.kt delete mode 100644 app/src/main/kotlin/com/adesso/movee/scene/persondetail/PersonDetailModule.kt delete mode 100644 app/src/main/kotlin/com/adesso/movee/scene/profile/ProfileModule.kt delete mode 100644 app/src/main/kotlin/com/adesso/movee/scene/search/SearchModule.kt delete mode 100644 app/src/main/kotlin/com/adesso/movee/scene/tvshow/TvShowModule.kt delete mode 100644 app/src/main/kotlin/com/adesso/movee/scene/tvshowdetail/TvShowDetailModule.kt diff --git a/app/build.gradle b/app/build.gradle index e1a793f..c21b19e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,6 +1,7 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' +apply plugin: 'dagger.hilt.android.plugin' apply plugin: 'androidx.navigation.safeargs' apply from: "$rootDir/config/git-hooks.gradle.kts" apply from: "$rootDir/config/detekt.gradle" @@ -108,7 +109,7 @@ dependencies { implementation androidx implementation common implementation network - implementation dagger + implementation hiltt kapt commonKapt debugImplementation commonDebug diff --git a/app/src/main/kotlin/com/adesso/movee/application/MainApplication.kt b/app/src/main/kotlin/com/adesso/movee/application/MainApplication.kt index 9b0e28e..e5f3d83 100644 --- a/app/src/main/kotlin/com/adesso/movee/application/MainApplication.kt +++ b/app/src/main/kotlin/com/adesso/movee/application/MainApplication.kt @@ -1,11 +1,13 @@ package com.adesso.movee.application +import android.app.Application import com.adesso.movee.BuildConfig -import com.adesso.movee.internal.injection.DaggerApplication import com.adesso.movee.internal.util.TimberTree +import dagger.hilt.android.HiltAndroidApp import timber.log.Timber -class MainApplication : DaggerApplication() { +@HiltAndroidApp +class MainApplication : Application() { override fun onCreate() { super.onCreate() diff --git a/app/src/main/kotlin/com/adesso/movee/base/BaseActivity.kt b/app/src/main/kotlin/com/adesso/movee/base/BaseActivity.kt index b391f92..90ff34a 100644 --- a/app/src/main/kotlin/com/adesso/movee/base/BaseActivity.kt +++ b/app/src/main/kotlin/com/adesso/movee/base/BaseActivity.kt @@ -1,21 +1,22 @@ package com.adesso.movee.base +import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.ViewModelProvider import com.adesso.movee.internal.util.functional.lazyThreadSafetyNone -import dagger.android.support.DaggerAppCompatActivity import java.lang.reflect.ParameterizedType import javax.inject.Inject -abstract class BaseActivity : DaggerAppCompatActivity() { +abstract class BaseActivity : AppCompatActivity() { @Inject lateinit var viewModelFactory: ViewModelProvider.Factory @Suppress("UNCHECKED_CAST") protected val viewModel by lazyThreadSafetyNone { - val persistentViewModelClass = (javaClass.genericSuperclass as ParameterizedType) - .actualTypeArguments[0] as Class - return@lazyThreadSafetyNone ViewModelProvider(this, viewModelFactory) - .get(persistentViewModelClass) + val persistentViewModelClass = + (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class + return@lazyThreadSafetyNone ViewModelProvider(this, viewModelFactory).get( + persistentViewModelClass + ) } } diff --git a/app/src/main/kotlin/com/adesso/movee/base/BaseBottomSheetDialogFragment.kt b/app/src/main/kotlin/com/adesso/movee/base/BaseBottomSheetDialogFragment.kt index cab9879..fa71952 100644 --- a/app/src/main/kotlin/com/adesso/movee/base/BaseBottomSheetDialogFragment.kt +++ b/app/src/main/kotlin/com/adesso/movee/base/BaseBottomSheetDialogFragment.kt @@ -1,6 +1,5 @@ package com.adesso.movee.base -import android.content.Context import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -26,18 +25,11 @@ import com.adesso.movee.navigation.NavigationCommand import com.adesso.movee.scene.main.MainActivity import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.snackbar.Snackbar -import dagger.android.AndroidInjector -import dagger.android.DispatchingAndroidInjector -import dagger.android.HasAndroidInjector -import dagger.android.support.AndroidSupportInjection import java.lang.reflect.ParameterizedType import javax.inject.Inject abstract class BaseBottomSheetDialogFragment : - BottomSheetDialogFragment(), HasAndroidInjector { - - @Inject - lateinit var androidInjector: DispatchingAndroidInjector + BottomSheetDialogFragment() { @Inject lateinit var viewModelFactory: ViewModelProvider.Factory @@ -74,13 +66,6 @@ abstract class BaseBottomSheetDialogFragment = androidInjector - override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) diff --git a/app/src/main/kotlin/com/adesso/movee/base/BaseFragment.kt b/app/src/main/kotlin/com/adesso/movee/base/BaseFragment.kt index cb210d1..ada375b 100644 --- a/app/src/main/kotlin/com/adesso/movee/base/BaseFragment.kt +++ b/app/src/main/kotlin/com/adesso/movee/base/BaseFragment.kt @@ -9,6 +9,7 @@ import androidx.annotation.LayoutRes import androidx.core.net.toUri import androidx.databinding.DataBindingUtil import androidx.databinding.ViewDataBinding +import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels import androidx.lifecycle.ViewModel @@ -24,12 +25,10 @@ import com.adesso.movee.internal.util.functional.lazyThreadSafetyNone import com.adesso.movee.navigation.NavigationCommand import com.adesso.movee.scene.main.MainActivity import com.google.android.material.snackbar.Snackbar -import dagger.android.support.DaggerFragment import java.lang.reflect.ParameterizedType import javax.inject.Inject -abstract class BaseFragment : - DaggerFragment() { +abstract class BaseFragment : Fragment() { @Inject lateinit var viewModelFactory: ViewModelProvider.Factory @@ -43,10 +42,11 @@ abstract class BaseFragment : @Suppress("UNCHECKED_CAST") protected open val viewModel by lazyThreadSafetyNone { - val persistentViewModelClass = (javaClass.genericSuperclass as ParameterizedType) - .actualTypeArguments[0] as Class - return@lazyThreadSafetyNone ViewModelProvider(this, viewModelFactory) - .get(persistentViewModelClass) + val persistentViewModelClass = + (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class + return@lazyThreadSafetyNone ViewModelProvider(this, viewModelFactory).get( + persistentViewModelClass + ) } protected inline fun activityViewModels(): Lazy { @@ -100,16 +100,19 @@ abstract class BaseFragment : is NavigationCommand.ToDirection -> { findNavController().navigate(command.directions, getExtras()) } + is NavigationCommand.ToDeepLink -> { - (activity as? MainActivity) - ?.navController - ?.navigate(command.deepLink.toUri(), null, getExtras()) + (activity as? MainActivity)?.navController?.navigate( + command.deepLink.toUri(), null, getExtras() + ) } + is NavigationCommand.Popup -> { with(command) { context?.showPopup(model, callback) } } + is NavigationCommand.Back -> findNavController().navigateUp() } } diff --git a/app/src/main/kotlin/com/adesso/movee/internal/injection/DaggerApplication.kt b/app/src/main/kotlin/com/adesso/movee/internal/injection/DaggerApplication.kt deleted file mode 100644 index aa7553d..0000000 --- a/app/src/main/kotlin/com/adesso/movee/internal/injection/DaggerApplication.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.adesso.movee.internal.injection - -import android.app.Application -import com.adesso.movee.internal.injection.component.DaggerAppComponent -import dagger.android.AndroidInjector -import dagger.android.DispatchingAndroidInjector -import dagger.android.HasAndroidInjector -import javax.inject.Inject - -abstract class DaggerApplication : - Application(), - HasAndroidInjector { - - @Inject - lateinit var androidInjector: DispatchingAndroidInjector - - override fun androidInjector(): AndroidInjector = androidInjector - - override fun onCreate() { - super.onCreate() - DaggerAppComponent.factory().create(this).inject(this) - } -} diff --git a/app/src/main/kotlin/com/adesso/movee/internal/injection/component/AppComponent.kt b/app/src/main/kotlin/com/adesso/movee/internal/injection/component/AppComponent.kt deleted file mode 100644 index 04570ba..0000000 --- a/app/src/main/kotlin/com/adesso/movee/internal/injection/component/AppComponent.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.adesso.movee.internal.injection.component - -import com.adesso.movee.internal.injection.DaggerApplication -import com.adesso.movee.internal.injection.module.ActivitiesModule -import com.adesso.movee.internal.injection.module.AppModule -import com.adesso.movee.internal.injection.module.CacheModule -import com.adesso.movee.internal.injection.module.DatabaseModule -import com.adesso.movee.internal.injection.module.FragmentsModule -import com.adesso.movee.internal.injection.module.NetworkModule -import com.adesso.movee.internal.injection.viewmodel.ViewModelModule -import dagger.Component -import dagger.android.AndroidInjectionModule -import dagger.android.AndroidInjector -import javax.inject.Singleton - -@Singleton -@Component( - modules = [ - AndroidInjectionModule::class, - ActivitiesModule::class, - FragmentsModule::class, - AppModule::class, - NetworkModule::class, - CacheModule::class, - ViewModelModule::class, - DatabaseModule::class - ] -) -internal interface AppComponent : AndroidInjector { - - @Component.Factory - abstract class Factory : AndroidInjector.Factory -} diff --git a/app/src/main/kotlin/com/adesso/movee/internal/injection/module/ActivitiesModule.kt b/app/src/main/kotlin/com/adesso/movee/internal/injection/module/ActivitiesModule.kt deleted file mode 100644 index e1b3c7b..0000000 --- a/app/src/main/kotlin/com/adesso/movee/internal/injection/module/ActivitiesModule.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.adesso.movee.internal.injection.module - -import com.adesso.movee.internal.injection.scope.MainScope -import com.adesso.movee.scene.main.MainActivity -import com.adesso.movee.scene.main.MainModule -import com.adesso.movee.scene.splash.SplashActivity -import dagger.Module -import dagger.android.ContributesAndroidInjector - -@Module -abstract class ActivitiesModule { - - @MainScope - @ContributesAndroidInjector(modules = [MainModule::class]) - internal abstract fun contributeMainActivity(): MainActivity - - @ContributesAndroidInjector() - internal abstract fun contributeSplashActivity(): SplashActivity -} diff --git a/app/src/main/kotlin/com/adesso/movee/internal/injection/module/AppModule.kt b/app/src/main/kotlin/com/adesso/movee/internal/injection/module/AppModule.kt index d4a6033..45de83f 100644 --- a/app/src/main/kotlin/com/adesso/movee/internal/injection/module/AppModule.kt +++ b/app/src/main/kotlin/com/adesso/movee/internal/injection/module/AppModule.kt @@ -2,23 +2,19 @@ package com.adesso.movee.internal.injection.module import android.app.Application import android.content.Context -import com.adesso.movee.internal.injection.DaggerApplication import dagger.Module import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent import javax.inject.Singleton @Module(includes = [MoshiModule::class]) -internal class AppModule { +@InstallIn(SingletonComponent::class) +object AppModule { @Provides @Singleton - internal fun provideApplicationContext(application: DaggerApplication): Context { + fun provideApplicationContext(application: Application): Context { return application.applicationContext } - - @Provides - @Singleton - internal fun provideApplication(application: DaggerApplication): Application { - return application - } } diff --git a/app/src/main/kotlin/com/adesso/movee/internal/injection/module/CacheModule.kt b/app/src/main/kotlin/com/adesso/movee/internal/injection/module/CacheModule.kt index 736521a..c2ff6cf 100644 --- a/app/src/main/kotlin/com/adesso/movee/internal/injection/module/CacheModule.kt +++ b/app/src/main/kotlin/com/adesso/movee/internal/injection/module/CacheModule.kt @@ -5,12 +5,14 @@ import android.content.SharedPreferences import androidx.preference.PreferenceManager import dagger.Module import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent @Module +@InstallIn(SingletonComponent::class) object CacheModule { @Provides - @JvmStatic fun provideSharedPreferences(application: Application): SharedPreferences { return PreferenceManager.getDefaultSharedPreferences( application.applicationContext diff --git a/app/src/main/kotlin/com/adesso/movee/internal/injection/module/DatabaseModule.kt b/app/src/main/kotlin/com/adesso/movee/internal/injection/module/DatabaseModule.kt index bb0af2b..46b0eac 100644 --- a/app/src/main/kotlin/com/adesso/movee/internal/injection/module/DatabaseModule.kt +++ b/app/src/main/kotlin/com/adesso/movee/internal/injection/module/DatabaseModule.kt @@ -15,84 +15,81 @@ import com.adesso.movee.data.local.database.dao.TvShowGenreCrossRefDao import com.adesso.movee.data.local.database.dao.TvShowGenreDao import dagger.Module import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent import javax.inject.Singleton @Module -internal class DatabaseModule { +@InstallIn(SingletonComponent::class) +object DatabaseModule { - companion object { - private const val DATABASE_NAME = "movee.db" - } + private const val DATABASE_NAME = "movee.db" @Provides @Singleton - internal fun provideMainDatabase(application: Application): MainDatabase { + fun provideMainDatabase(application: Application): MainDatabase { return Room.databaseBuilder( - application.applicationContext, - MainDatabase::class.java, - DATABASE_NAME - ) - .fallbackToDestructiveMigration() - .build() + application.applicationContext, MainDatabase::class.java, DATABASE_NAME + ).fallbackToDestructiveMigration().build() } @Provides @Singleton - internal fun provideMovieDao(mainDatabase: MainDatabase): MovieDao { + fun provideMovieDao(mainDatabase: MainDatabase): MovieDao { return mainDatabase.movieDao() } @Provides @Singleton - internal fun providePopularMovieIdDao(mainDatabase: MainDatabase): PopularMovieIdDao { + fun providePopularMovieIdDao(mainDatabase: MainDatabase): PopularMovieIdDao { return mainDatabase.popularMovieIdDao() } @Provides @Singleton - internal fun provideNowPlayingMovieIdDao(mainDatabase: MainDatabase): NowPlayingMovieIdDao { + fun provideNowPlayingMovieIdDao(mainDatabase: MainDatabase): NowPlayingMovieIdDao { return mainDatabase.nowPlayingMovieIdDao() } @Provides @Singleton - internal fun provideMovieGenreDao(mainDatabase: MainDatabase): MovieGenreDao { + fun provideMovieGenreDao(mainDatabase: MainDatabase): MovieGenreDao { return mainDatabase.movieGenreDao() } @Provides @Singleton - internal fun provideMovieGenreCrossRefDao(mainDatabase: MainDatabase): MovieGenreCrossRefDao { + fun provideMovieGenreCrossRefDao(mainDatabase: MainDatabase): MovieGenreCrossRefDao { return mainDatabase.movieGenreCrossRefDao() } @Provides @Singleton - internal fun provideTvShowDao(mainDatabase: MainDatabase): TvShowDao { + fun provideTvShowDao(mainDatabase: MainDatabase): TvShowDao { return mainDatabase.tvShowDao() } @Provides @Singleton - internal fun provideTopRatedTvShowIdDao(mainDatabase: MainDatabase): TopRatedTvShowIdDao { + fun provideTopRatedTvShowIdDao(mainDatabase: MainDatabase): TopRatedTvShowIdDao { return mainDatabase.topRatedTvShowIdDao() } @Provides @Singleton - internal fun provideNowPlayingTvShowIdDao(mainDatabase: MainDatabase): NowPlayingTvShowIdDao { + fun provideNowPlayingTvShowIdDao(mainDatabase: MainDatabase): NowPlayingTvShowIdDao { return mainDatabase.nowPlayingTvShowIdDao() } @Provides @Singleton - internal fun provideTvShowGenreDao(mainDatabase: MainDatabase): TvShowGenreDao { + fun provideTvShowGenreDao(mainDatabase: MainDatabase): TvShowGenreDao { return mainDatabase.tvShowGenreDao() } @Provides @Singleton - internal fun provideTvShowGenreCrossRefDao(mainDatabase: MainDatabase): TvShowGenreCrossRefDao { + fun provideTvShowGenreCrossRefDao(mainDatabase: MainDatabase): TvShowGenreCrossRefDao { return mainDatabase.tvShowGenreCrossRefDao() } } diff --git a/app/src/main/kotlin/com/adesso/movee/internal/injection/module/FragmentsModule.kt b/app/src/main/kotlin/com/adesso/movee/internal/injection/module/FragmentsModule.kt deleted file mode 100644 index a8e2739..0000000 --- a/app/src/main/kotlin/com/adesso/movee/internal/injection/module/FragmentsModule.kt +++ /dev/null @@ -1,64 +0,0 @@ -package com.adesso.movee.internal.injection.module - -import com.adesso.movee.internal.injection.scope.LoginScope -import com.adesso.movee.internal.injection.scope.MovieDetailScope -import com.adesso.movee.internal.injection.scope.MovieScope -import com.adesso.movee.internal.injection.scope.PersonDetailScope -import com.adesso.movee.internal.injection.scope.ProfileScope -import com.adesso.movee.internal.injection.scope.SearchScope -import com.adesso.movee.internal.injection.scope.TvShowDetailScope -import com.adesso.movee.internal.injection.scope.TvShowScope -import com.adesso.movee.scene.login.LoginFragment -import com.adesso.movee.scene.login.LoginModule -import com.adesso.movee.scene.movie.MovieFragment -import com.adesso.movee.scene.movie.MovieModule -import com.adesso.movee.scene.moviedetail.MovieDetailFragment -import com.adesso.movee.scene.moviedetail.MovieDetailModule -import com.adesso.movee.scene.persondetail.PersonDetailFragment -import com.adesso.movee.scene.persondetail.PersonDetailModule -import com.adesso.movee.scene.profile.ProfileFragment -import com.adesso.movee.scene.profile.ProfileModule -import com.adesso.movee.scene.search.SearchFragment -import com.adesso.movee.scene.search.SearchModule -import com.adesso.movee.scene.tvshow.TvShowFragment -import com.adesso.movee.scene.tvshow.TvShowModule -import com.adesso.movee.scene.tvshowdetail.TvShowDetailFragment -import com.adesso.movee.scene.tvshowdetail.TvShowDetailModule -import dagger.Module -import dagger.android.ContributesAndroidInjector - -@Module -internal abstract class FragmentsModule { - - @MovieScope - @ContributesAndroidInjector(modules = [MovieModule::class]) - abstract fun contributeMovieFragment(): MovieFragment - - @TvShowScope - @ContributesAndroidInjector(modules = [TvShowModule::class]) - abstract fun contributeTvShowFragment(): TvShowFragment - - @TvShowDetailScope - @ContributesAndroidInjector(modules = [TvShowDetailModule::class]) - abstract fun contributeTvShowDetailFragment(): TvShowDetailFragment - - @MovieDetailScope - @ContributesAndroidInjector(modules = [MovieDetailModule::class]) - abstract fun contributeMovieDetailFragment(): MovieDetailFragment - - @PersonDetailScope - @ContributesAndroidInjector(modules = [PersonDetailModule::class]) - abstract fun contributePersonDetailFragment(): PersonDetailFragment - - @SearchScope - @ContributesAndroidInjector(modules = [SearchModule::class]) - abstract fun contributeSearchFragment(): SearchFragment - - @ProfileScope - @ContributesAndroidInjector(modules = [ProfileModule::class]) - abstract fun contributeProfileFragment(): ProfileFragment - - @LoginScope - @ContributesAndroidInjector(modules = [LoginModule::class]) - abstract fun contributeLoginFragment(): LoginFragment -} diff --git a/app/src/main/kotlin/com/adesso/movee/internal/injection/module/MoshiModule.kt b/app/src/main/kotlin/com/adesso/movee/internal/injection/module/MoshiModule.kt index b4e18c2..b59dba3 100644 --- a/app/src/main/kotlin/com/adesso/movee/internal/injection/module/MoshiModule.kt +++ b/app/src/main/kotlin/com/adesso/movee/internal/injection/module/MoshiModule.kt @@ -16,10 +16,13 @@ import com.squareup.moshi.adapters.PolymorphicJsonAdapterFactory import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import dagger.Module import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent import javax.inject.Singleton @Module -internal class MoshiModule { +@InstallIn(SingletonComponent::class) +object MoshiModule { @Provides @Singleton diff --git a/app/src/main/kotlin/com/adesso/movee/internal/injection/module/NetworkModule.kt b/app/src/main/kotlin/com/adesso/movee/internal/injection/module/NetworkModule.kt index ef379e7..6925a7b 100644 --- a/app/src/main/kotlin/com/adesso/movee/internal/injection/module/NetworkModule.kt +++ b/app/src/main/kotlin/com/adesso/movee/internal/injection/module/NetworkModule.kt @@ -20,30 +20,31 @@ import com.squareup.moshi.Moshi import dagger.Lazy import dagger.Module import dagger.Provides -import java.io.File -import java.util.concurrent.TimeUnit -import javax.inject.Singleton +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent import okhttp3.Cache import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Retrofit import retrofit2.converter.moshi.MoshiConverterFactory +import java.io.File +import java.util.concurrent.TimeUnit +import javax.inject.Singleton @Module -internal class NetworkModule { +@InstallIn(SingletonComponent::class) +object NetworkModule { - companion object { - private const val CLIENT_TIME_OUT = 120L - private const val CLIENT_CACHE_SIZE = 10 * 1024 * 1024L - private const val CLIENT_CACHE_DIRECTORY = "http" - } + private const val CLIENT_TIME_OUT = 120L + private const val CLIENT_CACHE_SIZE = 10 * 1024 * 1024L + private const val CLIENT_CACHE_DIRECTORY = "http" /** * Create Cache object for OkHttp instance */ @Provides @Singleton - internal fun providesCache(context: Context): Cache = Cache( + fun providesCache(context: Context): Cache = Cache( File( context.cacheDir, CLIENT_CACHE_DIRECTORY @@ -53,7 +54,7 @@ internal class NetworkModule { @Provides @Singleton - internal fun provideLoggingInterceptor(): HttpLoggingInterceptor { + fun provideLoggingInterceptor(): HttpLoggingInterceptor { val loggingInterceptor = HttpLoggingInterceptor() loggingInterceptor.level = if (BuildConfig.DEBUG) { HttpLoggingInterceptor.Level.BODY @@ -65,7 +66,7 @@ internal class NetworkModule { @Provides @Singleton - internal fun provideCurlInterceptor(): CurlInterceptor { + fun provideCurlInterceptor(): CurlInterceptor { return CurlInterceptor( logger = object : Logger { override fun log(message: String) { diff --git a/app/src/main/kotlin/com/adesso/movee/internal/injection/viewmodel/ViewModelModule.kt b/app/src/main/kotlin/com/adesso/movee/internal/injection/viewmodel/ViewModelModule.kt index d31c4cb..4835f52 100644 --- a/app/src/main/kotlin/com/adesso/movee/internal/injection/viewmodel/ViewModelModule.kt +++ b/app/src/main/kotlin/com/adesso/movee/internal/injection/viewmodel/ViewModelModule.kt @@ -1,5 +1,4 @@ package com.adesso.movee.internal.injection.viewmodel - import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import com.adesso.movee.scene.login.LoginViewModel @@ -14,9 +13,12 @@ import com.adesso.movee.scene.tvshow.TvShowViewModel import com.adesso.movee.scene.tvshowdetail.TvShowDetailViewModel import dagger.Binds import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent import dagger.multibindings.IntoMap @Module +@InstallIn(SingletonComponent::class) abstract class ViewModelModule { @Binds @@ -25,50 +27,50 @@ abstract class ViewModelModule { @Binds @IntoMap @ViewModelKey(MainViewModel::class) - abstract fun bindsMainViewModel(viewModel: MainViewModel): ViewModel + abstract fun bindMainViewModel(viewModel: MainViewModel): ViewModel @Binds @IntoMap @ViewModelKey(SplashViewModel::class) - abstract fun bindsSplashViewModel(viewModel: SplashViewModel): ViewModel + abstract fun bindSplashViewModel(viewModel: SplashViewModel): ViewModel @Binds @IntoMap @ViewModelKey(MovieViewModel::class) - abstract fun bindsMovieViewModel(viewModel: MovieViewModel): ViewModel + abstract fun bindMovieViewModel(viewModel: MovieViewModel): ViewModel @Binds @IntoMap @ViewModelKey(TvShowViewModel::class) - abstract fun bindsTvShowViewModel(viewModel: TvShowViewModel): ViewModel + abstract fun bindTvShowViewModel(viewModel: TvShowViewModel): ViewModel @Binds @IntoMap @ViewModelKey(TvShowDetailViewModel::class) - abstract fun bindsTvShowDetailViewModel(viewModel: TvShowDetailViewModel): ViewModel + abstract fun bindTvShowDetailViewModel(viewModel: TvShowDetailViewModel): ViewModel @Binds @IntoMap @ViewModelKey(MovieDetailViewModel::class) - abstract fun bindsMovieDetailViewModel(viewModel: MovieDetailViewModel): ViewModel + abstract fun bindMovieDetailViewModel(viewModel: MovieDetailViewModel): ViewModel @Binds @IntoMap @ViewModelKey(PersonDetailViewModel::class) - abstract fun bindsPersonDetailViewModel(viewModel: PersonDetailViewModel): ViewModel + abstract fun bindPersonDetailViewModel(viewModel: PersonDetailViewModel): ViewModel @Binds @IntoMap @ViewModelKey(SearchViewModel::class) - abstract fun bindsSearchViewModel(viewModel: SearchViewModel): ViewModel + abstract fun bindSearchViewModel(viewModel: SearchViewModel): ViewModel @Binds @IntoMap @ViewModelKey(ProfileViewModel::class) - abstract fun bindsProfileViewModel(viewModel: ProfileViewModel): ViewModel + abstract fun bindProfileViewModel(viewModel: ProfileViewModel): ViewModel @Binds @IntoMap @ViewModelKey(LoginViewModel::class) - abstract fun bindsLoginViewModel(viewModel: LoginViewModel): ViewModel + abstract fun bindLoginViewModel(viewModel: LoginViewModel): ViewModel } diff --git a/app/src/main/kotlin/com/adesso/movee/scene/login/LoginFragment.kt b/app/src/main/kotlin/com/adesso/movee/scene/login/LoginFragment.kt index 56bf540..a38b992 100644 --- a/app/src/main/kotlin/com/adesso/movee/scene/login/LoginFragment.kt +++ b/app/src/main/kotlin/com/adesso/movee/scene/login/LoginFragment.kt @@ -7,11 +7,12 @@ import com.adesso.movee.base.BaseTransparentStatusBarFragment import com.adesso.movee.databinding.FragmentLoginBinding import com.adesso.movee.internal.extension.observeNonNull import com.adesso.movee.internal.util.Event +import dagger.hilt.android.AndroidEntryPoint +@AndroidEntryPoint class LoginFragment : BaseTransparentStatusBarFragment() { override val layoutId = R.layout.fragment_login - override fun initialize() { super.initialize() diff --git a/app/src/main/kotlin/com/adesso/movee/scene/login/LoginModule.kt b/app/src/main/kotlin/com/adesso/movee/scene/login/LoginModule.kt deleted file mode 100644 index 7ecf0a4..0000000 --- a/app/src/main/kotlin/com/adesso/movee/scene/login/LoginModule.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.adesso.movee.scene.login - -import dagger.Module - -@Module -internal abstract class LoginModule diff --git a/app/src/main/kotlin/com/adesso/movee/scene/main/MainActivity.kt b/app/src/main/kotlin/com/adesso/movee/scene/main/MainActivity.kt index 6ff1bad..d511817 100644 --- a/app/src/main/kotlin/com/adesso/movee/scene/main/MainActivity.kt +++ b/app/src/main/kotlin/com/adesso/movee/scene/main/MainActivity.kt @@ -14,7 +14,9 @@ import com.adesso.movee.databinding.ActivityMainBinding import com.adesso.movee.internal.extension.observeNonNull import com.adesso.movee.internal.extension.showPopup import com.adesso.movee.navigation.NavigationCommand +import dagger.hilt.android.AndroidEntryPoint +@AndroidEntryPoint class MainActivity : BaseBindingActivity() { override val layoutId get() = R.layout.activity_main diff --git a/app/src/main/kotlin/com/adesso/movee/scene/main/MainModule.kt b/app/src/main/kotlin/com/adesso/movee/scene/main/MainModule.kt deleted file mode 100644 index 88f2854..0000000 --- a/app/src/main/kotlin/com/adesso/movee/scene/main/MainModule.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.adesso.movee.scene.main - -import dagger.Module - -@Module -internal abstract class MainModule diff --git a/app/src/main/kotlin/com/adesso/movee/scene/movie/MovieFragment.kt b/app/src/main/kotlin/com/adesso/movee/scene/movie/MovieFragment.kt index b224a9e..9fba8ce 100644 --- a/app/src/main/kotlin/com/adesso/movee/scene/movie/MovieFragment.kt +++ b/app/src/main/kotlin/com/adesso/movee/scene/movie/MovieFragment.kt @@ -7,7 +7,9 @@ import com.adesso.movee.internal.util.addAppBarStateChangeListener import com.adesso.movee.uimodel.MovieUiModel import com.adesso.movee.uimodel.ShowUiModel import com.adesso.movee.widget.nowplayingshow.NowPlayingShowCallback +import dagger.hilt.android.AndroidEntryPoint +@AndroidEntryPoint class MovieFragment : BaseFragment(), PopularMovieCallback, diff --git a/app/src/main/kotlin/com/adesso/movee/scene/movie/MovieModule.kt b/app/src/main/kotlin/com/adesso/movee/scene/movie/MovieModule.kt deleted file mode 100644 index 17019e1..0000000 --- a/app/src/main/kotlin/com/adesso/movee/scene/movie/MovieModule.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.adesso.movee.scene.movie - -import dagger.Module - -@Module -abstract class MovieModule diff --git a/app/src/main/kotlin/com/adesso/movee/scene/moviedetail/MovieDetailFragment.kt b/app/src/main/kotlin/com/adesso/movee/scene/moviedetail/MovieDetailFragment.kt index 21b4238..2891c5a 100644 --- a/app/src/main/kotlin/com/adesso/movee/scene/moviedetail/MovieDetailFragment.kt +++ b/app/src/main/kotlin/com/adesso/movee/scene/moviedetail/MovieDetailFragment.kt @@ -4,7 +4,9 @@ import androidx.navigation.fragment.navArgs import com.adesso.movee.R import com.adesso.movee.base.BaseTransparentStatusBarFragment import com.adesso.movee.databinding.FragmentMovieDetailBinding +import dagger.hilt.android.AndroidEntryPoint +@AndroidEntryPoint class MovieDetailFragment : BaseTransparentStatusBarFragment() { diff --git a/app/src/main/kotlin/com/adesso/movee/scene/moviedetail/MovieDetailModule.kt b/app/src/main/kotlin/com/adesso/movee/scene/moviedetail/MovieDetailModule.kt deleted file mode 100644 index 8780665..0000000 --- a/app/src/main/kotlin/com/adesso/movee/scene/moviedetail/MovieDetailModule.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.adesso.movee.scene.moviedetail - -import dagger.Module - -@Module -internal abstract class MovieDetailModule diff --git a/app/src/main/kotlin/com/adesso/movee/scene/persondetail/PersonDetailFragment.kt b/app/src/main/kotlin/com/adesso/movee/scene/persondetail/PersonDetailFragment.kt index c5e6ce2..53e9a56 100644 --- a/app/src/main/kotlin/com/adesso/movee/scene/persondetail/PersonDetailFragment.kt +++ b/app/src/main/kotlin/com/adesso/movee/scene/persondetail/PersonDetailFragment.kt @@ -5,7 +5,9 @@ import com.adesso.movee.R import com.adesso.movee.base.BaseTransparentStatusBarFragment import com.adesso.movee.databinding.FragmentPersonDetailBinding import com.adesso.movee.internal.util.addAppBarStateChangeListener +import dagger.hilt.android.AndroidEntryPoint +@AndroidEntryPoint class PersonDetailFragment : BaseTransparentStatusBarFragment() { diff --git a/app/src/main/kotlin/com/adesso/movee/scene/persondetail/PersonDetailModule.kt b/app/src/main/kotlin/com/adesso/movee/scene/persondetail/PersonDetailModule.kt deleted file mode 100644 index 13715c4..0000000 --- a/app/src/main/kotlin/com/adesso/movee/scene/persondetail/PersonDetailModule.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.adesso.movee.scene.persondetail - -import dagger.Module - -@Module -internal abstract class PersonDetailModule diff --git a/app/src/main/kotlin/com/adesso/movee/scene/profile/ProfileFragment.kt b/app/src/main/kotlin/com/adesso/movee/scene/profile/ProfileFragment.kt index f4b16b4..ec22d79 100644 --- a/app/src/main/kotlin/com/adesso/movee/scene/profile/ProfileFragment.kt +++ b/app/src/main/kotlin/com/adesso/movee/scene/profile/ProfileFragment.kt @@ -3,7 +3,9 @@ package com.adesso.movee.scene.profile import com.adesso.movee.R import com.adesso.movee.base.BaseFragment import com.adesso.movee.databinding.FragmentProfileBinding +import dagger.hilt.android.AndroidEntryPoint +@AndroidEntryPoint class ProfileFragment : BaseFragment() { override val layoutId = R.layout.fragment_profile diff --git a/app/src/main/kotlin/com/adesso/movee/scene/profile/ProfileModule.kt b/app/src/main/kotlin/com/adesso/movee/scene/profile/ProfileModule.kt deleted file mode 100644 index 2bf820c..0000000 --- a/app/src/main/kotlin/com/adesso/movee/scene/profile/ProfileModule.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.adesso.movee.scene.profile - -import dagger.Module - -@Module -internal abstract class ProfileModule diff --git a/app/src/main/kotlin/com/adesso/movee/scene/search/SearchFragment.kt b/app/src/main/kotlin/com/adesso/movee/scene/search/SearchFragment.kt index 54c797c..ec1e00c 100644 --- a/app/src/main/kotlin/com/adesso/movee/scene/search/SearchFragment.kt +++ b/app/src/main/kotlin/com/adesso/movee/scene/search/SearchFragment.kt @@ -5,7 +5,9 @@ import com.adesso.movee.base.BaseFragment import com.adesso.movee.databinding.FragmentSearchBinding import com.adesso.movee.internal.databinding.TextChangeCallback import com.adesso.movee.uimodel.MultiSearchUiModel +import dagger.hilt.android.AndroidEntryPoint +@AndroidEntryPoint class SearchFragment : BaseFragment(), MultiSearchCallback, diff --git a/app/src/main/kotlin/com/adesso/movee/scene/search/SearchModule.kt b/app/src/main/kotlin/com/adesso/movee/scene/search/SearchModule.kt deleted file mode 100644 index ceaa497..0000000 --- a/app/src/main/kotlin/com/adesso/movee/scene/search/SearchModule.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.adesso.movee.scene.search - -import dagger.Module - -@Module -internal abstract class SearchModule diff --git a/app/src/main/kotlin/com/adesso/movee/scene/splash/SplashActivity.kt b/app/src/main/kotlin/com/adesso/movee/scene/splash/SplashActivity.kt index 2f1282e..da21763 100644 --- a/app/src/main/kotlin/com/adesso/movee/scene/splash/SplashActivity.kt +++ b/app/src/main/kotlin/com/adesso/movee/scene/splash/SplashActivity.kt @@ -1,9 +1,13 @@ package com.adesso.movee.scene.splash +import android.annotation.SuppressLint import android.os.Bundle import com.adesso.movee.base.BaseActivity import com.adesso.movee.scene.main.MainActivity +import dagger.hilt.android.AndroidEntryPoint +@SuppressLint("CustomSplashScreen") +@AndroidEntryPoint class SplashActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/kotlin/com/adesso/movee/scene/tvshow/TvShowFragment.kt b/app/src/main/kotlin/com/adesso/movee/scene/tvshow/TvShowFragment.kt index 769eadc..42bc3e1 100644 --- a/app/src/main/kotlin/com/adesso/movee/scene/tvshow/TvShowFragment.kt +++ b/app/src/main/kotlin/com/adesso/movee/scene/tvshow/TvShowFragment.kt @@ -7,7 +7,9 @@ import com.adesso.movee.internal.util.addAppBarStateChangeListener import com.adesso.movee.uimodel.ShowUiModel import com.adesso.movee.uimodel.TvShowUiModel import com.adesso.movee.widget.nowplayingshow.NowPlayingShowCallback +import dagger.hilt.android.AndroidEntryPoint +@AndroidEntryPoint class TvShowFragment : BaseFragment(), TopRatedTvShowCallback, diff --git a/app/src/main/kotlin/com/adesso/movee/scene/tvshow/TvShowModule.kt b/app/src/main/kotlin/com/adesso/movee/scene/tvshow/TvShowModule.kt deleted file mode 100644 index d4325a6..0000000 --- a/app/src/main/kotlin/com/adesso/movee/scene/tvshow/TvShowModule.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.adesso.movee.scene.tvshow - -import dagger.Module - -@Module -abstract class TvShowModule diff --git a/app/src/main/kotlin/com/adesso/movee/scene/tvshowdetail/TvShowDetailFragment.kt b/app/src/main/kotlin/com/adesso/movee/scene/tvshowdetail/TvShowDetailFragment.kt index fd2962e..ece730a 100644 --- a/app/src/main/kotlin/com/adesso/movee/scene/tvshowdetail/TvShowDetailFragment.kt +++ b/app/src/main/kotlin/com/adesso/movee/scene/tvshowdetail/TvShowDetailFragment.kt @@ -5,7 +5,9 @@ import com.adesso.movee.R import com.adesso.movee.base.BaseTransparentStatusBarFragment import com.adesso.movee.databinding.FragmentTvShowDetailBinding import com.adesso.movee.uimodel.TvShowCastUiModel +import dagger.hilt.android.AndroidEntryPoint +@AndroidEntryPoint class TvShowDetailFragment : BaseTransparentStatusBarFragment(), TvShowCastCallback { diff --git a/app/src/main/kotlin/com/adesso/movee/scene/tvshowdetail/TvShowDetailModule.kt b/app/src/main/kotlin/com/adesso/movee/scene/tvshowdetail/TvShowDetailModule.kt deleted file mode 100644 index 75ad756..0000000 --- a/app/src/main/kotlin/com/adesso/movee/scene/tvshowdetail/TvShowDetailModule.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.adesso.movee.scene.tvshowdetail - -import dagger.Module - -@Module -internal abstract class TvShowDetailModule diff --git a/build.gradle b/build.gradle index db9d923..75f6913 100644 --- a/build.gradle +++ b/build.gradle @@ -15,6 +15,7 @@ buildscript { classpath "com.diffplug.spotless:spotless-plugin-gradle:$it.version.spotless" classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:$version.detekt" classpath "com.github.ben-manes:gradle-versions-plugin:$version.gradleVersions" + classpath "com.google.dagger:hilt-android-gradle-plugin:$version.hilt" } } diff --git a/config/dependencies.gradle b/config/dependencies.gradle index 3f0e931..62f3d4d 100644 --- a/config/dependencies.gradle +++ b/config/dependencies.gradle @@ -27,7 +27,6 @@ ext { ] version = [ - dagger : '2.45', retrofit : '2.9.0', okhttp : '4.10.0', moshi : '1.14.0', @@ -58,7 +57,8 @@ ext { crypto : '1.1.0-alpha03', robolectric : '4.9', ktlint : '0.40.0', - kotlinResult : '1.1.16' + kotlinResult : '1.1.16', + hilt : '2.44' ] dependency = [ @@ -83,9 +83,8 @@ ext { "androidx.lifecycle:lifecycle-common-java8:$version.lifecycle", ], - dagger = [ - "com.google.dagger:dagger:$version.dagger", - "com.google.dagger:dagger-android-support:$version.dagger", + hiltt = [ + "com.google.dagger:hilt-android:$version.hilt", ], common = [ @@ -96,9 +95,8 @@ ext { ], commonKapt = [ - "com.google.dagger:dagger-compiler:$version.dagger", - "com.google.dagger:dagger-android-processor:$version.dagger", "androidx.room:room-compiler:$version.room", + "com.google.dagger:hilt-android-compiler:$version.hilt" ], network = [ From e53901ff8b8d49e58ce308732c9076bf0ec22c8a Mon Sep 17 00:00:00 2001 From: "murat.cakir" Date: Wed, 26 Jul 2023 12:17:05 +0300 Subject: [PATCH 2/2] Refactoring the search page using Jetpack Compose. --- app/build.gradle | 6 + .../movee/scene/profile/ProfileViewModel.kt | 10 +- .../movee/scene/search/MultiSearchAdapter.kt | 26 -- .../movee/scene/search/SearchFragment.kt | 21 +- .../movee/scene/search/SearchViewModel.kt | 17 +- .../scene/search/jetpack/ContentListRow.kt | 158 ++++++++++ .../scene/search/jetpack/SearchScreen.kt | 278 ++++++++++++++++++ .../tvshowdetail/TvShowDetailViewModel.kt | 9 +- .../movee/uimodel/MultiSearchUiModel.kt | 9 + app/src/main/res/layout/fragment_search.xml | 118 +------- app/src/main/res/layout/item_multi_search.xml | 81 ----- app/src/main/res/values/dimens.xml | 21 ++ app/src/main/res/values/strings.xml | 3 + config/dependencies.gradle | 80 +++-- 14 files changed, 556 insertions(+), 281 deletions(-) delete mode 100644 app/src/main/kotlin/com/adesso/movee/scene/search/MultiSearchAdapter.kt create mode 100644 app/src/main/kotlin/com/adesso/movee/scene/search/jetpack/ContentListRow.kt create mode 100644 app/src/main/kotlin/com/adesso/movee/scene/search/jetpack/SearchScreen.kt delete mode 100644 app/src/main/res/layout/item_multi_search.xml diff --git a/app/build.gradle b/app/build.gradle index c21b19e..25f5a5a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -85,6 +85,11 @@ android { buildFeatures { dataBinding true + compose true + } + + composeOptions { + kotlinCompilerExtensionVersion '1.4.3' } packagingOptions { @@ -110,6 +115,7 @@ dependencies { implementation common implementation network implementation hiltt + implementation compose kapt commonKapt debugImplementation commonDebug diff --git a/app/src/main/kotlin/com/adesso/movee/scene/profile/ProfileViewModel.kt b/app/src/main/kotlin/com/adesso/movee/scene/profile/ProfileViewModel.kt index 08355df..0813263 100644 --- a/app/src/main/kotlin/com/adesso/movee/scene/profile/ProfileViewModel.kt +++ b/app/src/main/kotlin/com/adesso/movee/scene/profile/ProfileViewModel.kt @@ -3,7 +3,6 @@ package com.adesso.movee.scene.profile import android.app.Application import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.Transformations import com.adesso.movee.base.BaseAndroidViewModel import com.adesso.movee.domain.FetchUserDetailsUseCase import com.adesso.movee.domain.GetLoginStateUseCase @@ -24,9 +23,12 @@ class ProfileViewModel @Inject constructor( private val _userDetails = MutableLiveData() val userDetails: LiveData get() = _userDetails private val _loginState = MutableLiveData() - val shouldShowUserDetails: LiveData = Transformations.map(_userDetails) { it != null } - val shouldShowLoginView: LiveData = Transformations.map(_loginState) { loginState -> - loginState == LoginState.LOGGED_IN + val shouldShowUserDetails: LiveData = MutableLiveData().apply { + value = _userDetails.value != null + } + + val shouldShowLoginView: LiveData = MutableLiveData().apply { + value = _loginState.value == LoginState.LOGGED_IN } init { diff --git a/app/src/main/kotlin/com/adesso/movee/scene/search/MultiSearchAdapter.kt b/app/src/main/kotlin/com/adesso/movee/scene/search/MultiSearchAdapter.kt deleted file mode 100644 index ec3984d..0000000 --- a/app/src/main/kotlin/com/adesso/movee/scene/search/MultiSearchAdapter.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.adesso.movee.scene.search - -import com.adesso.movee.R -import com.adesso.movee.base.BaseListAdapter -import com.adesso.movee.databinding.ItemMultiSearchBinding -import com.adesso.movee.internal.extension.executeAfter -import com.adesso.movee.uimodel.MultiSearchUiModel - -interface MultiSearchCallback { - - fun onMultiSearchClick(multiSearch: MultiSearchUiModel) -} - -class MultiSearchAdapter( - private val multiSearchCallback: MultiSearchCallback -) : BaseListAdapter() { - - override val layoutRes: Int get() = R.layout.item_multi_search - - override fun bind(binding: ItemMultiSearchBinding, item: MultiSearchUiModel) { - binding.executeAfter { - callback = multiSearchCallback - multiSearch = item - } - } -} diff --git a/app/src/main/kotlin/com/adesso/movee/scene/search/SearchFragment.kt b/app/src/main/kotlin/com/adesso/movee/scene/search/SearchFragment.kt index ec1e00c..5a2a211 100644 --- a/app/src/main/kotlin/com/adesso/movee/scene/search/SearchFragment.kt +++ b/app/src/main/kotlin/com/adesso/movee/scene/search/SearchFragment.kt @@ -3,30 +3,21 @@ package com.adesso.movee.scene.search import com.adesso.movee.R import com.adesso.movee.base.BaseFragment import com.adesso.movee.databinding.FragmentSearchBinding -import com.adesso.movee.internal.databinding.TextChangeCallback -import com.adesso.movee.uimodel.MultiSearchUiModel +import com.adesso.movee.scene.search.jetpack.SearchScreenComposable import dagger.hilt.android.AndroidEntryPoint +// TODO: Remove all classes which related SearchFragment after all classes refactored jetpack compose. @AndroidEntryPoint class SearchFragment : - BaseFragment(), - MultiSearchCallback, - TextChangeCallback { + BaseFragment() { override val layoutId = R.layout.fragment_search override fun initialize() { super.initialize() - binder.multiSearchAdapter = MultiSearchAdapter(multiSearchCallback = this) - binder.textChangeCallback = this - } - - override fun onMultiSearchClick(multiSearch: MultiSearchUiModel) { - viewModel.onMultiSearchClick(multiSearch) - } - - override fun onTextChange(text: String?) { - viewModel.onTextChange(text) + binder.composeView.setContent { + SearchScreenComposable() + } } } diff --git a/app/src/main/kotlin/com/adesso/movee/scene/search/SearchViewModel.kt b/app/src/main/kotlin/com/adesso/movee/scene/search/SearchViewModel.kt index e1b02c1..6c27b62 100644 --- a/app/src/main/kotlin/com/adesso/movee/scene/search/SearchViewModel.kt +++ b/app/src/main/kotlin/com/adesso/movee/scene/search/SearchViewModel.kt @@ -1,6 +1,8 @@ package com.adesso.movee.scene.search import android.app.Application +import androidx.compose.runtime.State +import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import com.adesso.movee.base.BaseAndroidViewModel @@ -22,12 +24,12 @@ class SearchViewModel @Inject constructor( application: Application ) : BaseAndroidViewModel(application) { - private val _multiSearchResults = MutableLiveData>() - private val _shouldShowEmptyResultView = MutableLiveData() - val multiSearchResults: LiveData> = _multiSearchResults + private val _multiSearchResults = mutableStateOf>(listOf()) + val multiSearchResults: State> = _multiSearchResults + + private val _shouldShowEmptyResultView = MutableLiveData(false) val shouldShowEmptyResultView: LiveData get() = _shouldShowEmptyResultView private var multiSearchJob: Job? = null - val searchDebounce = DURATION_MS_INPUT_TIMEOUT fun onTextChange(text: String?) { val query = text?.trim() ?: return @@ -38,12 +40,16 @@ class SearchViewModel @Inject constructor( onUIThread { searchResult .onSuccess(::postMultiSearchResult) - .onFailure(::handleFailure) + .onFailure(::handleSearchFailure) } } } } + fun refreshData() { + _multiSearchResults.value = emptyList() + } + private fun handleSearchFailure(failure: Failure) { if (failure is Failure.UnknownError && failure.exception is CancellationException) { return @@ -72,6 +78,5 @@ class SearchViewModel @Inject constructor( companion object { private const val MIN_SEARCHABLE_LENGTH = 2 - private const val DURATION_MS_INPUT_TIMEOUT = 250L } } diff --git a/app/src/main/kotlin/com/adesso/movee/scene/search/jetpack/ContentListRow.kt b/app/src/main/kotlin/com/adesso/movee/scene/search/jetpack/ContentListRow.kt new file mode 100644 index 0000000..731720b --- /dev/null +++ b/app/src/main/kotlin/com/adesso/movee/scene/search/jetpack/ContentListRow.kt @@ -0,0 +1,158 @@ +package com.adesso.movee.scene.search.jetpack + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.IntrinsicSize +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Card +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Alignment.Companion.CenterVertically +import androidx.compose.ui.Alignment.Companion.Top +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.RectangleShape +import androidx.compose.ui.res.colorResource +import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.sp +import coil.compose.rememberImagePainter +import com.adesso.movee.R +import com.adesso.movee.uimodel.MultiSearchUiModel + +private const val MAX_LINES = 1 + +@Composable +fun ContentListRow( + movie: MultiSearchUiModel, + onItemClick: (movie: MultiSearchUiModel) -> Unit +) { + Card( + modifier = Modifier + .fillMaxSize() + .background(Color.White) + .padding( + bottom = dimensionResource(id = R.dimen.margin_small), + start = dimensionResource(id = R.dimen.margin_large), + top = dimensionResource(id = R.dimen.margin_small), + end = dimensionResource(id = R.dimen.margin_large) + ), + elevation = dimensionResource(id = R.dimen.elevation_small), + shape = RoundedCornerShape(dimensionResource(id = R.dimen.radius_small)) + ) { + Row( + modifier = Modifier + .height(IntrinsicSize.Min) + .background(Color.White) + .clickable { onItemClick(movie) } + ) { + Image( + painter = rememberImagePainter(data = movie.getImagePath()), + contentDescription = movie.getTitle(), + modifier = Modifier + .fillMaxHeight() + .width(dimensionResource(id = R.dimen.search_list_item_width)) + .clip(RectangleShape), + alignment = Alignment.CenterStart + ) + Column( + modifier = Modifier + .fillMaxWidth() + .align(Top), + horizontalAlignment = Alignment.Start + ) { + Text( + movie.getTitle(), + style = TextStyle( + fontSize = dimensionResource( + id = R.dimen.search_list_item_title_text_size + ).value.sp + ), + overflow = TextOverflow.Ellipsis, + color = colorResource(id = R.color.almost_black), + textAlign = TextAlign.Start, + modifier = Modifier.padding( + top = dimensionResource(id = R.dimen.margin_small), + start = dimensionResource(id = R.dimen.margin_small), + end = dimensionResource(id = R.dimen.margin_small) + ), + maxLines = MAX_LINES + ) + + Text( + movie.getSubtitle(), + style = TextStyle( + fontSize = dimensionResource( + id = R.dimen.search_list_item_subtitle_text_size + ).value.sp + ), + overflow = TextOverflow.Ellipsis, + color = colorResource(id = R.color.almost_black), + textAlign = TextAlign.Start, + maxLines = MAX_LINES, + modifier = Modifier.padding( + top = dimensionResource(id = R.dimen.margin_small), + start = dimensionResource(id = R.dimen.margin_small), + end = dimensionResource(id = R.dimen.margin_small) + ) + ) + + Row { + Image( + painter = painterResource(id = movie.getTypeDrawableId()), + contentDescription = stringResource( + id = R.string.search_content_type_icon_content_description + ), + modifier = Modifier + .height( + dimensionResource( + id = R.dimen.search_list_item_type_icon_width + ) + ) + .padding( + top = dimensionResource(id = R.dimen.margin_small), + start = dimensionResource(id = R.dimen.margin_small) + ) + ) + Text( + "Tv Series", + style = TextStyle( + fontSize = dimensionResource( + id = R.dimen.search_list_item_type_title_text_size + ).value.sp + ), + overflow = TextOverflow.Ellipsis, + color = colorResource(id = R.color.almost_black_60), + textAlign = TextAlign.Start, + maxLines = MAX_LINES, + modifier = Modifier + .align(CenterVertically) + .wrapContentHeight() + .padding( + top = dimensionResource(id = R.dimen.margin_medium), + start = dimensionResource(id = R.dimen.margin_extra_small), + end = dimensionResource(id = R.dimen.margin_medium), + bottom = dimensionResource(id = R.dimen.margin_large) + ) + ) + } + } + } + } +} diff --git a/app/src/main/kotlin/com/adesso/movee/scene/search/jetpack/SearchScreen.kt b/app/src/main/kotlin/com/adesso/movee/scene/search/jetpack/SearchScreen.kt new file mode 100644 index 0000000..391cdb3 --- /dev/null +++ b/app/src/main/kotlin/com/adesso/movee/scene/search/jetpack/SearchScreen.kt @@ -0,0 +1,278 @@ +package com.adesso.movee.scene.search.jetpack + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Surface +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Alignment.Companion.CenterHorizontally +import androidx.compose.ui.Alignment.Companion.CenterVertically +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.onFocusChanged +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.colorResource +import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel +import com.adesso.movee.R +import com.adesso.movee.scene.search.SearchViewModel + +private const val MAX_LINES = 1 + +@Composable +fun SearchScreenComposable( + viewModel: SearchViewModel = hiltViewModel() +) { + + val state = viewModel.multiSearchResults.value + + LaunchedEffect(Unit) { + viewModel.refreshData() + } + + Box( + modifier = Modifier + .fillMaxWidth() + .height(dimensionResource(id = R.dimen.search_page_toolbar_height)) + .background(colorResource(id = R.color.colorPrimary)) + ) { + + Column { + Text( + text = stringResource(id = R.string.search_message_search), + style = TextStyle( + color = Color.White, + fontSize = dimensionResource(id = R.dimen.search_toolbar_title_size).value.sp + ), + modifier = Modifier.padding( + horizontal = dimensionResource( + id = R.dimen.search_title_horizontal_padding + ), + vertical = dimensionResource( + id = R.dimen.search_title_vertical_padding + ) + ) + ) + + MovieSearchBar( + modifier = Modifier + .fillMaxWidth() + .background(Color.Transparent) + .padding( + top = dimensionResource( + id = R.dimen.search_bar_top_padding + ), + bottom = dimensionResource( + id = R.dimen.search_bar_bottom_end_start_padding + ), + start = dimensionResource( + id = R.dimen.search_bar_bottom_end_start_padding + ), + end = dimensionResource( + id = R.dimen.search_bar_bottom_end_start_padding + ) + ), + hint = stringResource(id = R.string.search_message_movies_or_series), + onSearch = { searchKey -> + viewModel.onTextChange(searchKey) + } + ) + + if (viewModel.shouldShowEmptyResultView.value == true) { + EmptyScreen() + } else { + LazyColumn( + modifier = Modifier + .fillMaxSize() + .background(Color.White) + ) { + items(state) { contentList -> + ContentListRow( + movie = contentList, + onItemClick = { + viewModel.onMultiSearchClick(contentList) + } + ) + } + } + } + } + } +} + +@Composable +fun MovieSearchBar( + modifier: Modifier, + hint: String, + onSearch: (String) -> Unit = {} +) { + var text by remember { + mutableStateOf("") + } + var isHintDisplayed by remember { + mutableStateOf(hint != "") + } + + Box(modifier = modifier) { + Surface( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.CenterStart) + .background(Color.Transparent) + .onFocusChanged { + isHintDisplayed = it.isFocused != true && text.isEmpty() + }, + elevation = dimensionResource(id = R.dimen.elevation_small), + shape = RoundedCornerShape(dimensionResource(id = R.dimen.radius_small)) + ) { + Row { + Image( + painter = painterResource(id = R.drawable.ic_search), + contentDescription = stringResource( + id = R.string.search_bar_icon_content_description + ), + modifier = Modifier + .align(CenterVertically) + .padding( + start = dimensionResource( + id = R.dimen.search_bar_icon_start_padding + ), + top = dimensionResource( + id = R.dimen.search_bar_icon_top_bottom_end_padding + ), + bottom = dimensionResource( + id = R.dimen.search_bar_icon_top_bottom_end_padding + ), + end = dimensionResource( + id = R.dimen.search_bar_icon_top_bottom_end_padding + ) + ) + ) + BasicTextField( + value = text, + onValueChange = { searchKey -> + text = searchKey + onSearch(text) + }, + modifier = Modifier.padding( + horizontal = dimensionResource( + id = R.dimen.search_text_field_horizontal_padding + ), + vertical = dimensionResource( + id = R.dimen.search_text_field_vertical_padding + ), + ), + maxLines = MAX_LINES, + singleLine = true, + textStyle = MaterialTheme.typography.body1.copy(color = Color.Black), + ) + } + + if (isHintDisplayed) { + Row( + modifier = Modifier.align(Alignment.Center) + ) { + Image( + painter = painterResource(id = R.drawable.ic_search), + contentDescription = stringResource( + id = R.string.search_bar_icon_content_description + ), + modifier = Modifier + .align(CenterVertically) + .padding( + start = dimensionResource( + id = R.dimen.search_bar_icon_start_padding + ), + top = dimensionResource( + id = R.dimen.search_bar_icon_top_bottom_end_padding + ), + bottom = dimensionResource( + id = R.dimen.search_bar_icon_top_bottom_end_padding + ), + end = dimensionResource( + id = R.dimen.search_bar_icon_top_bottom_end_padding + ) + ) + ) + + Text( + text = hint, + color = Color.LightGray, + textAlign = TextAlign.Start, + modifier = Modifier + .fillMaxWidth() + .align(CenterVertically) + .padding( + start = dimensionResource( + id = R.dimen.search_hint_text_start_padding + ), + top = dimensionResource( + id = R.dimen.search_hint_text_top_padding + ), + bottom = dimensionResource( + id = R.dimen.search_hint_text_bottom_end_padding + ), + end = dimensionResource( + id = R.dimen.search_hint_text_bottom_end_padding + ) + ) + ) + } + } + } + } +} + +@Composable +fun EmptyScreen() { + Column( + modifier = Modifier + .fillMaxSize() + .background(Color.White) + ) { + Spacer( + modifier = Modifier + .height(dimensionResource(id = R.dimen.search_page_empty_view_top_margin)) + .fillMaxWidth() + .background(Color.White) + ) + Image( + painter = painterResource(id = R.drawable.ic_empty_multi_search), + contentDescription = stringResource( + id = R.string.search_content_item_empty_view_content_description + ), + modifier = Modifier + .align(CenterHorizontally) + .height(dimensionResource(id = R.dimen.search_page_empty_view_image_height)) + .width(dimensionResource(id = R.dimen.search_page_empty_view_image_width)) + ) + Text( + text = stringResource(id = R.string.search_message_empty_search_result), + modifier = Modifier.align(CenterHorizontally) + ) + } +} diff --git a/app/src/main/kotlin/com/adesso/movee/scene/tvshowdetail/TvShowDetailViewModel.kt b/app/src/main/kotlin/com/adesso/movee/scene/tvshowdetail/TvShowDetailViewModel.kt index 43a4ecc..cf4d505 100644 --- a/app/src/main/kotlin/com/adesso/movee/scene/tvshowdetail/TvShowDetailViewModel.kt +++ b/app/src/main/kotlin/com/adesso/movee/scene/tvshowdetail/TvShowDetailViewModel.kt @@ -3,7 +3,6 @@ package com.adesso.movee.scene.tvshowdetail import android.app.Application import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.Transformations import com.adesso.movee.base.BaseAndroidViewModel import com.adesso.movee.domain.FetchTvShowCreditsUseCase import com.adesso.movee.domain.FetchTvShowDetailUseCase @@ -25,8 +24,8 @@ class TvShowDetailViewModel @Inject constructor( val tvShowDetails: LiveData get() = _tvShowDetails private val _tvShowCredits = MutableLiveData() val tvShowCasts: LiveData> = - Transformations.map(_tvShowCredits) { tvShowCredits -> - tvShowCredits.cast + MutableLiveData>().apply { + value = _tvShowCredits.value?.cast.orEmpty() } fun fetchTvShowDetail(id: Long) { @@ -55,9 +54,7 @@ class TvShowDetailViewModel @Inject constructor( fetchTvShowCreditsUseCase.run(FetchTvShowCreditsUseCase.Params(id)) onUIThread { - tvShowCreditResult - .onSuccess(::postTvShowCredits) - .onFailure(::handleFailure) + tvShowCreditResult.onSuccess(::postTvShowCredits).onFailure(::handleFailure) } } } diff --git a/app/src/main/kotlin/com/adesso/movee/uimodel/MultiSearchUiModel.kt b/app/src/main/kotlin/com/adesso/movee/uimodel/MultiSearchUiModel.kt index 131a676..94e4f8d 100644 --- a/app/src/main/kotlin/com/adesso/movee/uimodel/MultiSearchUiModel.kt +++ b/app/src/main/kotlin/com/adesso/movee/uimodel/MultiSearchUiModel.kt @@ -25,6 +25,15 @@ sealed class MultiSearchUiModel : ListAdapterItem, Serializable { return ContextCompat.getDrawable(context, typeDrawableRes) } + fun getTypeDrawableId(): Int { + val typeDrawableRes = when (this) { + is MovieMultiSearchUiModel -> R.drawable.ic_movie + is TvShowMultiSearchUiModel -> R.drawable.ic_tv_show + is PersonMultiSearchUiModel -> R.drawable.ic_person + } + return typeDrawableRes + } + @StringRes fun getTypeStringRes(): Int { return when (this) { diff --git a/app/src/main/res/layout/fragment_search.xml b/app/src/main/res/layout/fragment_search.xml index 9fd32cf..e45e1dd 100644 --- a/app/src/main/res/layout/fragment_search.xml +++ b/app/src/main/res/layout/fragment_search.xml @@ -1,119 +1,15 @@ - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - + android:visibility="visible" + android:id="@+id/compose_view" + android:layout_height="match_parent"> + diff --git a/app/src/main/res/layout/item_multi_search.xml b/app/src/main/res/layout/item_multi_search.xml deleted file mode 100644 index bbaa488..0000000 --- a/app/src/main/res/layout/item_multi_search.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 8dfd80c..7482914 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -51,6 +51,27 @@ 10dp + 80dp + 30dp + 20sp + 15sp + 12sp + 176dp + 34sp + 32dp + 24dp + 0dp + 16dp + 12dp + 8dp + 4dp + 8dp + 10dp + 4dp + 8dp + 100dp + 160dp + 180dp 100dp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ad04406..791983f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -67,6 +67,9 @@ Writer Crew Your search didn’t have any results + Content item type icon + @string/search_message_empty_search_result + Search bar icon diff --git a/config/dependencies.gradle b/config/dependencies.gradle index 62f3d4d..a9e722d 100644 --- a/config/dependencies.gradle +++ b/config/dependencies.gradle @@ -27,38 +27,43 @@ ext { ] version = [ - retrofit : '2.9.0', - okhttp : '4.10.0', - moshi : '1.14.0', - moshiLazyAdapter: '2.2', - constraintLayout: '2.1.4', - navigation : '2.5.3', - lifecycle : '2.5.1', - androidKtx : '1.9.0', - appCompat : '1.6.1', - coroutines : '1.3.9', - espresso : '3.0.2', - chucker : '3.5.2', - gson : '2.8.2', - glide : '4.14.2', - ok2curl : '0.8.0', - room : '2.5.0', - jUnit : '4.13.2', - mockito : '2.13.+', - lottie : '5.2.0', - material : '1.0.0', - preference : '1.2.0', - viewPager2 : '1.0.0', - timber : '5.0.1', - spotless : '6.15.0', - detekt : '1.21.0', - gradleVersions : '0.33.0', - playServices : '18.1.0', - crypto : '1.1.0-alpha03', - robolectric : '4.9', - ktlint : '0.40.0', - kotlinResult : '1.1.16', - hilt : '2.44' + dagger : '2.45', + retrofit : '2.9.0', + okhttp : '4.10.0', + moshi : '1.14.0', + moshiLazyAdapter : '2.2', + constraintLayout : '2.1.4', + navigation : '2.5.3', + lifecycle : '2.5.1', + androidKtx : '1.9.0', + appCompat : '1.6.1', + coroutines : '1.3.9', + espresso : '3.0.2', + chucker : '3.5.2', + gson : '2.8.2', + glide : '4.14.2', + ok2curl : '0.8.0', + room : '2.5.0', + jUnit : '4.13.2', + mockito : '2.13.+', + lottie : '5.2.0', + material : '1.0.0', + preference : '1.2.0', + viewPager2 : '1.0.0', + timber : '5.0.1', + spotless : '6.15.0', + detekt : '1.21.0', + gradleVersions : '0.33.0', + playServices : '18.1.0', + crypto : '1.1.0-alpha03', + robolectric : '4.9', + ktlint : '0.40.0', + kotlinResult : '1.1.16', + compose : '1.4.3', + composeContraint : '1.0.1', + hilt : '2.44', + coilCompose : '1.3.2', + hiltCompose : '1.0.0' ] dependency = [ @@ -87,6 +92,17 @@ ext { "com.google.dagger:hilt-android:$version.hilt", ], + compose = [ + "androidx.compose.ui:ui:$version.compose", + "androidx.compose.material:material:$version.compose", + "androidx.constraintlayout:constraintlayout-compose:$version.composeContraint", + "androidx.compose.ui:ui-tooling-preview:$version.compose", + "androidx.compose.foundation:foundation:$version.compose", + "androidx.hilt:hilt-navigation-compose:$version.hiltCompose", + "io.coil-kt:coil-compose:$version.coilCompose", + "androidx.compose.ui:ui-tooling-preview:$version.compose" + ], + common = [ "com.github.bumptech.glide:glide:$version.glide", "com.airbnb.android:lottie:$version.lottie",