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 0c0c338..0000000 --- a/.idea/deploymentTargetDropDown.xml +++ /dev/null @@ -1,10 +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/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) - } -} diff --git a/app/src/main/java/com/sun/android/data/repository/MovieRepositoryImpl.kt b/app/src/main/java/com/sun/android/data/repository/MovieRepositoryImpl.kt deleted file mode 100644 index 31d9cc6..0000000 --- a/app/src/main/java/com/sun/android/data/repository/MovieRepositoryImpl.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.sun.android.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 kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow -import org.koin.core.component.KoinComponent -import java.io.IOException - -class MovieRepositoryImpl( - private val remote: MovieDataSource.Remote, - private val local: MovieDataSource.Local -) : KoinComponent, MovieRepository { - - override suspend fun getMovies(): Flow> = flow { - try { - val movies = remote.getMovies().data - local.updateMovies(movies) - } catch (e: IOException) { - Log.e("MovieRepository", "getMovies failed, using local data \n Detail error:\n $e") - } - emit(local.getMoviesLocal()) - } - - override suspend fun getDetailMovies(movieId: Int) = flow { - try { - emit(local.getMovieDetailLocal(movieId)) - } 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)) - } - } -} diff --git a/app/src/main/java/com/sun/android/data/source/MovieDataSource.kt b/app/src/main/java/com/sun/android/data/source/MovieDataSource.kt deleted file mode 100644 index d210543..0000000 --- a/app/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/app/src/main/java/com/sun/android/data/source/local/MovieLocalImpl.kt b/app/src/main/java/com/sun/android/data/source/local/MovieLocalImpl.kt deleted file mode 100644 index 18cebbe..0000000 --- a/app/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/app/src/main/java/com/sun/android/data/source/remote/MovieRemoteImpl.kt b/app/src/main/java/com/sun/android/data/source/remote/MovieRemoteImpl.kt deleted file mode 100644 index 03c5555..0000000 --- a/app/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/app/src/main/java/com/sun/android/data/source/remote/api/error/ErrorResponse.kt b/app/src/main/java/com/sun/android/data/source/remote/api/error/ErrorResponse.kt deleted file mode 100644 index 555dd8d..0000000 --- a/app/src/main/java/com/sun/android/data/source/remote/api/error/ErrorResponse.kt +++ /dev/null @@ -1,69 +0,0 @@ -package com.sun.android.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") - @Expose - val status: Int, - @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/app/src/main/java/com/sun/android/di/DataSourceModule.kt b/app/src/main/java/com/sun/android/di/DataSourceModule.kt deleted file mode 100644 index 7111e3c..0000000 --- a/app/src/main/java/com/sun/android/di/DataSourceModule.kt +++ /dev/null @@ -1,16 +0,0 @@ -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 org.koin.dsl.module - -val DataSourceModule = module { - single { TokenLocalImpl(get()) } - - single { MovieRemoteImpl(get()) } - - single { MovieLocalImpl(get()) } -} diff --git a/app/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt b/app/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt deleted file mode 100644 index 1870527..0000000 --- a/app/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt +++ /dev/null @@ -1,27 +0,0 @@ -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.android.utils.LogUtils -import com.sun.android.utils.dispatchers.DispatcherProvider -import com.sun.android.utils.livedata.SingleLiveData -import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.launch - -class MoviesViewModel(private val movieRepository: MovieRepository) : ViewModel() { - val movies = SingleLiveData>() - - fun requestTopRateMovies() { - viewModelScope.launch { - movieRepository.getMovies().catch { e -> - LogUtils.e("requestTopRateMovies", e.toString()) - }.flowOn(DispatcherProvider().io()) - .collect { - movies.value = it - } - } - } -} 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/app/.gitignore b/data/.gitignore similarity index 100% rename from app/.gitignore rename to data/.gitignore diff --git a/data/build.gradle.kts b/data/build.gradle.kts new file mode 100644 index 0000000..1df5085 --- /dev/null +++ b/data/build.gradle.kts @@ -0,0 +1,70 @@ +import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties + +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 + + buildConfigField("String", "API_KEY", gradleLocalProperties(rootDir).getProperty("api_key")) + + 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 { + api(project(":domain")) + + 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) + 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/app/src/main/java/com/sun/android/utils/Constant.kt b/data/src/main/java/com/sun/data/Constant.kt similarity index 69% rename from app/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/app/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/repository/MovieRepositoryImpl.kt b/data/src/main/java/com/sun/data/repository/MovieRepositoryImpl.kt new file mode 100644 index 0000000..2569f68 --- /dev/null +++ b/data/src/main/java/com/sun/data/repository/MovieRepositoryImpl.kt @@ -0,0 +1,46 @@ +package com.sun.data.repository + +import android.util.Log +import com.sun.data.source.local.entities.toEntity +import com.sun.data.source.MovieDataSource +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 +import org.koin.core.component.KoinComponent +import java.io.IOException + +class MovieRepositoryImpl( + private val remote: MovieDataSource.Remote, + private val local: MovieDataSource.Local +) : KoinComponent, MovieRepository { + + override suspend fun getMovies(): Flow> = flow { + val movies = arrayListOf() + try { + val movieRemotes = remote.getMovies().data + movies.addAll(movieRemotes.map { it.toEntity() }) + // save to locals + local.updateMovies(movieRemotes.map { it.toLocal() }) + } catch (e: IOException) { + 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 { + try { + 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.toLocal())) + emit(movieRemote.toEntity()) + } + } +} diff --git a/app/src/main/java/com/sun/android/data/repository/TokenRepositoryImpl.kt b/data/src/main/java/com/sun/data/repository/TokenRepositoryImpl.kt similarity index 66% rename from app/src/main/java/com/sun/android/data/repository/TokenRepositoryImpl.kt rename to data/src/main/java/com/sun/data/repository/TokenRepositoryImpl.kt index 68ccf05..41181a7 100644 --- a/app/src/main/java/com/sun/android/data/repository/TokenRepositoryImpl.kt +++ b/data/src/main/java/com/sun/data/repository/TokenRepositoryImpl.kt @@ -1,7 +1,7 @@ -package com.sun.android.data.repository +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 new file mode 100644 index 0000000..90d799b --- /dev/null +++ b/data/src/main/java/com/sun/data/source/MovieDataSource.kt @@ -0,0 +1,25 @@ +package com.sun.data.source + +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 { + /** + * Local + */ + interface Local { + suspend fun getMoviesLocal(): List + suspend fun updateMovies(movies: List) + suspend fun getMovieDetailLocal(movieId: Int): MovieLocal + } + + /** + * Remote + */ + interface Remote { + suspend fun getMovies(): BaseResponse> + + suspend fun getMovieDetail(movieId: Int): MovieRemote + } +} diff --git a/app/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 app/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/app/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..233b7b4 --- /dev/null +++ b/data/src/main/java/com/sun/data/source/local/MovieLocalImpl.kt @@ -0,0 +1,19 @@ +package com.sun.data.source.local + +import com.sun.data.source.local.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 { + return movieDao.getAllMovies() + } + + override suspend fun updateMovies(movies: List) { + return movieDao.insert(movies) + } + + override suspend fun getMovieDetailLocal(movieId: Int): MovieLocal { + return movieDao.getMovie(movieId) + } +} diff --git a/app/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 app/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/app/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/app/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 app/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/app/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/app/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 app/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/app/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/app/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 app/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/app/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/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/app/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 77% rename from app/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..e9aebcf 100644 --- a/app/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,13 @@ -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 +import com.sun.data.Constant +import com.sun.data.source.local.entities.MovieLocal -@Database(entities = [Movie::class], version = 1, exportSchema = false) +@Database(entities = [MovieLocal::class], version = 1, exportSchema = false) abstract class AppDatabase : RoomDatabase() { abstract fun movieDao(): MovieDao diff --git a/app/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 53% rename from app/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..4bc414b 100644 --- a/app/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,22 @@ import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query import androidx.room.Update -import com.sun.android.data.model.Movie +import com.sun.data.source.local.entities.MovieLocal @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: MovieLocal) @Delete - suspend fun delete(movie: Movie) + suspend fun delete(movie: MovieLocal) @Query("SELECT * from movies WHERE id = :id") - suspend fun getMovie(id: Int): Movie + 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 new file mode 100644 index 0000000..c6a0bf2 --- /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.data.BuildConfig +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 + +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): MovieRemote { + return apiService.getMovieDetails(movieId = movieId, apiKey = BuildConfig.API_KEY) + } +} diff --git a/app/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 65% rename from app/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..bbb7887 100644 --- a/app/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.source.remote.model.MovieRemote +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 + ): 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 new file mode 100644 index 0000000..86c9206 --- /dev/null +++ b/data/src/main/java/com/sun/data/source/remote/api/error/ErrorResponse.kt @@ -0,0 +1,13 @@ +package com.sun.data.source.remote.api.error + +import com.google.gson.annotations.Expose +import com.google.gson.annotations.SerializedName + +data class ErrorResponse( + @SerializedName("status") + @Expose + val status: Int, + @SerializedName("messages") + @Expose + val messages: String? +) diff --git a/app/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 app/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/app/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/app/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 app/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/app/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/app/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 app/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/app/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/app/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 app/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/app/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/app/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 app/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/app/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/app/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 94% rename from app/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..64c043d 100644 --- a/app/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,7 +1,7 @@ -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 +import com.sun.domain.repository.TokenRepository import java.io.IOException import java.net.HttpURLConnection import okhttp3.Interceptor diff --git a/app/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 app/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/app/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/app/src/main/java/com/sun/android/data/model/Movie.kt b/data/src/main/java/com/sun/data/source/remote/model/MovieRemote.kt similarity index 51% rename from app/src/main/java/com/sun/android/data/model/Movie.kt rename to data/src/main/java/com/sun/data/source/remote/model/MovieRemote.kt index 8ff607d..e5a0148 100644 --- a/app/src/main/java/com/sun/android/data/model/Movie.kt +++ b/data/src/main/java/com/sun/data/source/remote/model/MovieRemote.kt @@ -1,16 +1,14 @@ -package com.sun.android.data.model +package com.sun.data.source.remote.model 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 com.sun.data.source.local.entities.MovieLocal +import com.sun.domain.entities.Movie import kotlinx.android.parcel.Parcelize @Parcelize -@Entity(tableName = "movies") -data class Movie( - @PrimaryKey +data class MovieRemote( @SerializedName("id") @Expose var id: Int = -1, @@ -22,7 +20,7 @@ data class Movie( var overView: String = "", @SerializedName("vote_average") @Expose - var vote: Double = 0.0, + var rating: Double = 0.0, @SerializedName("vote_count") @Expose var voteCount: Int = 0, @@ -36,3 +34,27 @@ data class Movie( @Expose var originalTitle: String = "" ) : Parcelable + +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/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..b90795a --- /dev/null +++ b/domain/build.gradle.kts @@ -0,0 +1,11 @@ +plugins { + id("kotlin") +} + +dependencies { + //Coroutine + implementation(Deps.coroutines_core) + implementation(Deps.coroutines_android) + + testImplementation(Deps.coroutines_test) +} diff --git a/app/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 app/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/app/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/app/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 app/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/app/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/entities/Movie.kt b/domain/src/main/java/com/sun/domain/entities/Movie.kt new file mode 100644 index 0000000..0990635 --- /dev/null +++ b/domain/src/main/java/com/sun/domain/entities/Movie.kt @@ -0,0 +1,11 @@ +package com.sun.domain.entities + +data class Movie( + val id: Int, + val title: String, + val description: String, + val avatarUrl: String, + val backgroundUrl: String, + val rating: Double, + val voteCount: Int, +) diff --git a/app/src/main/java/com/sun/android/data/MovieRepository.kt b/domain/src/main/java/com/sun/domain/repository/MovieRepository.kt similarity index 71% rename from app/src/main/java/com/sun/android/data/MovieRepository.kt rename to domain/src/main/java/com/sun/domain/repository/MovieRepository.kt index 5b117a4..b3fbaad 100644 --- a/app/src/main/java/com/sun/android/data/MovieRepository.kt +++ b/domain/src/main/java/com/sun/domain/repository/MovieRepository.kt @@ -1,6 +1,6 @@ -package com.sun.android.data +package com.sun.domain.repository -import com.sun.android.data.model.Movie +import com.sun.domain.entities.Movie import kotlinx.coroutines.flow.Flow interface MovieRepository { diff --git a/app/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 app/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/app/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/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/.gitignore b/presentation/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/presentation/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle.kts b/presentation/build.gradle.kts similarity index 97% rename from app/build.gradle.kts rename to presentation/build.gradle.kts index cfe85d4..ab163f3 100644 --- a/app/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/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 78% rename from app/src/main/java/com/sun/android/AndroidApplication.kt rename to presentation/src/main/java/com/sun/android/AndroidApplication.kt index a21618b..5e74d2f 100644 --- a/app/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/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/di/AppModule.kt b/presentation/src/main/java/com/sun/android/di/AppModule.kt similarity index 60% rename from app/src/main/java/com/sun/android/di/AppModule.kt rename to presentation/src/main/java/com/sun/android/di/AppModule.kt index f906de8..0154e8f 100644 --- a/app/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.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.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 val AppModule = module { @@ -44,9 +39,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 +52,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 new file mode 100644 index 0000000..2049d9a --- /dev/null +++ b/presentation/src/main/java/com/sun/android/di/DataSourceModule.kt @@ -0,0 +1,20 @@ +package com.sun.android.di + +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 { + MovieRemoteImpl( + get() + ) + } + + single { MovieLocalImpl(get()) } +} 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 88% rename from app/src/main/java/com/sun/android/di/NetWorkModule.kt rename to presentation/src/main/java/com/sun/android/di/NetWorkModule.kt index 21550c7..7c38beb 100644 --- a/app/src/main/java/com/sun/android/di/NetWorkModule.kt +++ b/presentation/src/main/java/com/sun/android/di/NetWorkModule.kt @@ -3,9 +3,8 @@ 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.repository.TokenRepository +import com.sun.data.source.remote.api.middleware.InterceptorImpl import java.util.concurrent.TimeUnit import okhttp3.Cache import okhttp3.Interceptor @@ -68,8 +67,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/app/src/main/java/com/sun/android/di/RepositoryModule.kt b/presentation/src/main/java/com/sun/android/di/RepositoryModule.kt similarity index 50% rename from app/src/main/java/com/sun/android/di/RepositoryModule.kt rename to presentation/src/main/java/com/sun/android/di/RepositoryModule.kt index c3ed551..246bb55 100644 --- a/app/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.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.data.repository.MovieRepositoryImpl +import com.sun.data.repository.TokenRepositoryImpl +import com.sun.data.source.MovieDataSource +import com.sun.domain.repository.MovieRepository +import com.sun.domain.repository.TokenRepository import org.koin.dsl.module val RepositoryModule = module { @@ -14,7 +13,7 @@ val RepositoryModule = module { single { provideMovieRepository(get(), get()) } } -fun provideTokenRepository(local: TokenDataSource.Local): TokenRepository { +fun provideTokenRepository(local: com.sun.data.source.TokenDataSource.Local): TokenRepository { return TokenRepositoryImpl(local) } 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/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 84% 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 index ec43d4e..0acfa2b 100644 --- a/app/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/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 88% 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 index 322769f..58dc313 100644 --- a/app/src/main/java/com/sun/android/ui/detail/MovieDetailViewModel.kt +++ b/presentation/src/main/java/com/sun/android/ui/detail/MovieDetailViewModel.kt @@ -2,10 +2,10 @@ 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.repository.MovieRepository import com.sun.android.utils.LogUtils import com.sun.android.utils.livedata.SingleLiveData +import com.sun.domain.entities.Movie import kotlinx.coroutines.flow.catch import kotlinx.coroutines.launch 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 97% 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 index 23cc54f..3d3d363 100644 --- a/app/src/main/java/com/sun/android/ui/listmovie/MoviesFragment.kt +++ b/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesFragment.kt @@ -3,13 +3,13 @@ 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.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.Movie import org.koin.androidx.viewmodel.ext.android.viewModel class MoviesFragment : BaseFragment(MoviesFragmentBinding::inflate), 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 new file mode 100644 index 0000000..5554ccc --- /dev/null +++ b/presentation/src/main/java/com/sun/android/ui/listmovie/MoviesViewModel.kt @@ -0,0 +1,26 @@ +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.livedata.SingleLiveData +import com.sun.domain.entities.Movie +import com.sun.domain.usecase.GetMovieListUseCase +import kotlinx.coroutines.launch + +class MoviesViewModel(private val getMovieListUseCase: GetMovieListUseCase) : ViewModel() { + val movies = SingleLiveData>() + + fun requestTopRateMovies() { + viewModelScope.launch { + getMovieListUseCase(GetMovieListUseCase.Input()) { + onSuccess { + movies.value = it + } + onError { + LogUtils.e("requestTopRateMovies", it.toString()) + } + } + } + } +} 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 85% 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 index 13c5dfd..a6a3856 100644 --- 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 @@ -4,11 +4,11 @@ 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.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.Movie class MoviesAdapter : RecyclerView.Adapter() { @@ -47,7 +47,7 @@ class MoviesAdapter : RecyclerView.Adapter() { itemClickListener: OnItemRecyclerViewClickListener? ) : RecyclerView.ViewHolder(binding.root), View.OnClickListener { - private var movieData: Movie? = null + private var movieEntity: Movie? = null private var listener: OnItemRecyclerViewClickListener? = null init { @@ -58,15 +58,15 @@ class MoviesAdapter : RecyclerView.Adapter() { fun bindViewData(movie: Movie) { 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) } } } 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/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..cb27995 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,2 +1,4 @@ rootProject.name = "Structure_Android" -include (":app") +include (":presentation") +include(":data") +include(":domain")