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