Separate Hilt and Koin into their own product flavours
This commit is contained in:
parent
682fd71c2d
commit
1b8d0e836c
56 changed files with 496 additions and 72 deletions
|
|
@ -2,6 +2,8 @@ plugins {
|
||||||
id 'com.android.application'
|
id 'com.android.application'
|
||||||
id 'kotlin-android'
|
id 'kotlin-android'
|
||||||
id 'kotlin-kapt'
|
id 'kotlin-kapt'
|
||||||
|
// hilt specific
|
||||||
|
id 'dagger.hilt.android.plugin'
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
|
@ -25,6 +27,17 @@ android {
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
flavorDimensions 'di'
|
||||||
|
productFlavors {
|
||||||
|
hilt {
|
||||||
|
dimension 'di'
|
||||||
|
applicationId "org.fnives.test.showcase.hilt"
|
||||||
|
}
|
||||||
|
koin {
|
||||||
|
dimension 'di'
|
||||||
|
applicationId "org.fnives.test.showcase.koin"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
viewBinding true
|
viewBinding true
|
||||||
|
|
@ -49,10 +62,17 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hilt {
|
||||||
|
enableAggregatingTask = true
|
||||||
|
enableExperimentalClasspathAggregation = true
|
||||||
|
}
|
||||||
|
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
// making sure the :mockserver is assembled after :clean when running tests
|
// making sure the :mockserver is assembled after :clean when running tests
|
||||||
testDebugUnitTest.dependsOn tasks.getByPath(':mockserver:assemble')
|
testKoinDebugUnitTest.dependsOn tasks.getByPath(':mockserver:assemble')
|
||||||
testReleaseUnitTest.dependsOn tasks.getByPath(':mockserver:assemble')
|
testKoinReleaseUnitTest.dependsOn tasks.getByPath(':mockserver:assemble')
|
||||||
|
testHiltDebugUnitTest.dependsOn tasks.getByPath(':mockserver:assemble')
|
||||||
|
testHiltReleaseUnitTest.dependsOn tasks.getByPath(':mockserver:assemble')
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
@ -66,7 +86,14 @@ dependencies {
|
||||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:$androidx_swiperefreshlayout_version"
|
implementation "androidx.swiperefreshlayout:swiperefreshlayout:$androidx_swiperefreshlayout_version"
|
||||||
|
|
||||||
// Koin
|
// Koin
|
||||||
implementation "io.insert-koin:koin-android:$koin_version"
|
koinImplementation "io.insert-koin:koin-android:$koin_version"
|
||||||
|
|
||||||
|
// Hilt
|
||||||
|
// hiltImplementation "com.google.dagger:hilt-android:$hilt_version"
|
||||||
|
implementation "com.google.dagger:hilt-android:$hilt_version"
|
||||||
|
// implementation "com.google.dagger:hilt-core:$hilt_version"
|
||||||
|
kaptHilt "com.google.dagger:hilt-compiler:$hilt_version"
|
||||||
|
hiltImplementation "androidx.activity:activity-ktx:$activity_ktx_version"
|
||||||
|
|
||||||
implementation "androidx.room:room-runtime:$androidx_room_version"
|
implementation "androidx.room:room-runtime:$androidx_room_version"
|
||||||
kapt "androidx.room:room-compiler:$androidx_room_version"
|
kapt "androidx.room:room-compiler:$androidx_room_version"
|
||||||
|
|
@ -98,6 +125,8 @@ dependencies {
|
||||||
testImplementation "com.jakewharton.espresso:okhttp3-idling-resource:$testing_okhttp3_idling_resource_version"
|
testImplementation "com.jakewharton.espresso:okhttp3-idling-resource:$testing_okhttp3_idling_resource_version"
|
||||||
testImplementation "androidx.arch.core:core-testing:$testing_androidx_arch_core_version"
|
testImplementation "androidx.arch.core:core-testing:$testing_androidx_arch_core_version"
|
||||||
testRuntimeOnly "org.junit.vintage:junit-vintage-engine:$testing_junit5_version"
|
testRuntimeOnly "org.junit.vintage:junit-vintage-engine:$testing_junit5_version"
|
||||||
|
testImplementation "com.google.dagger:hilt-android-testing:$hilt_version"
|
||||||
|
kaptTest "com.google.dagger:hilt-compiler:$hilt_version"
|
||||||
|
|
||||||
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
|
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
|
||||||
androidTestImplementation "io.insert-koin:koin-test-junit4:$koin_version"
|
androidTestImplementation "io.insert-koin:koin-test-junit4:$koin_version"
|
||||||
|
|
@ -111,4 +140,6 @@ dependencies {
|
||||||
androidTestImplementation "com.jakewharton.espresso:okhttp3-idling-resource:$testing_okhttp3_idling_resource_version"
|
androidTestImplementation "com.jakewharton.espresso:okhttp3-idling-resource:$testing_okhttp3_idling_resource_version"
|
||||||
androidTestImplementation "androidx.arch.core:core-testing:$testing_androidx_arch_core_version"
|
androidTestImplementation "androidx.arch.core:core-testing:$testing_androidx_arch_core_version"
|
||||||
androidTestRuntimeOnly "org.junit.vintage:junit-vintage-engine:$testing_junit5_version"
|
androidTestRuntimeOnly "org.junit.vintage:junit-vintage-engine:$testing_junit5_version"
|
||||||
|
androidTestImplementation "com.google.dagger:hilt-android-testing:$hilt_version"
|
||||||
|
kaptAndroidTest "com.google.dagger:hilt-compiler:$hilt_version"
|
||||||
}
|
}
|
||||||
22
app/src/hilt/AndroidManifest.xml
Normal file
22
app/src/hilt/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
package="org.fnives.test.showcase">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
|
<application>
|
||||||
|
<activity
|
||||||
|
android:name=".ui.splash.HiltSplashActivity"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity android:name=".ui.home.HiltMainActivity" />
|
||||||
|
<activity android:name=".ui.auth.HiltAuthActivity" />
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
package org.fnives.test.showcase
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import dagger.hilt.android.HiltAndroidApp
|
||||||
|
|
||||||
|
@HiltAndroidApp
|
||||||
|
class TestShowcaseApplication : Application() {
|
||||||
|
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
53
app/src/hilt/java/org/fnives/test/showcase/di/AppModule.kt
Normal file
53
app/src/hilt/java/org/fnives/test/showcase/di/AppModule.kt
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
package org.fnives.test.showcase.di
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.Provides
|
||||||
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
import org.fnives.test.showcase.core.session.SessionExpirationListener
|
||||||
|
import org.fnives.test.showcase.core.storage.UserDataLocalStorage
|
||||||
|
import org.fnives.test.showcase.core.storage.content.FavouriteContentLocalStorage
|
||||||
|
import org.fnives.test.showcase.session.SessionExpirationListenerImpl
|
||||||
|
import org.fnives.test.showcase.storage.SharedPreferencesManagerImpl
|
||||||
|
import org.fnives.test.showcase.storage.database.DatabaseInitialization
|
||||||
|
import org.fnives.test.showcase.storage.favourite.FavouriteContentLocalStorageImpl
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
@Module
|
||||||
|
object AppModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun provideBaseUrl(): String = BaseUrlProvider.get().baseUrl
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun enableLogging(): Boolean = true
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
fun provideFavouriteDao(@ApplicationContext context: Context) =
|
||||||
|
DatabaseInitialization.create(context).favouriteDao
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun provideSharedPreferencesManagerImpl(@ApplicationContext context: Context) =
|
||||||
|
SharedPreferencesManagerImpl.create(context)
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
fun provideUserDataLocalStorage(
|
||||||
|
sharedPreferencesManagerImpl: SharedPreferencesManagerImpl
|
||||||
|
): UserDataLocalStorage = sharedPreferencesManagerImpl
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun provideFavouriteContentLocalStorage(
|
||||||
|
favouriteContentLocalStorageImpl: FavouriteContentLocalStorageImpl
|
||||||
|
): FavouriteContentLocalStorage = favouriteContentLocalStorageImpl
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
internal fun bindSessionExpirationListener(
|
||||||
|
sessionExpirationListenerImpl: SessionExpirationListenerImpl
|
||||||
|
) : SessionExpirationListener = sessionExpirationListenerImpl
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
package org.fnives.test.showcase.ui
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.fnives.test.showcase.ui.auth.HiltAuthActivity
|
||||||
|
import org.fnives.test.showcase.ui.home.HiltMainActivity
|
||||||
|
|
||||||
|
object IntentCoordinator {
|
||||||
|
|
||||||
|
fun mainActivitygetStartIntent(context: Context) =
|
||||||
|
HiltMainActivity.getStartIntent(context)
|
||||||
|
|
||||||
|
fun authActivitygetStartIntent(context: Context) =
|
||||||
|
HiltAuthActivity.getStartIntent(context)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package org.fnives.test.showcase.ui
|
||||||
|
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.ViewModelStoreOwner
|
||||||
|
import androidx.activity.viewModels as androidxViewModel
|
||||||
|
|
||||||
|
inline fun <reified T : ViewModel> ViewModelStoreOwner.viewModels(): Lazy<T> =
|
||||||
|
when (this) {
|
||||||
|
is ComponentActivity -> androidxViewModel()
|
||||||
|
else -> throw IllegalStateException("Only supports activity viewModel for now")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package org.fnives.test.showcase.ui.auth
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class HiltAuthActivity : AuthActivity() {
|
||||||
|
companion object {
|
||||||
|
fun getStartIntent(context: Context): Intent = Intent(context, HiltAuthActivity::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package org.fnives.test.showcase.ui.home
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class HiltMainActivity : MainActivity() {
|
||||||
|
companion object {
|
||||||
|
fun getStartIntent(context: Context): Intent = Intent(context, HiltMainActivity::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package org.fnives.test.showcase.ui.splash
|
||||||
|
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class HiltSplashActivity : SplashActivity()
|
||||||
21
app/src/koin/AndroidManifest.xml
Normal file
21
app/src/koin/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="org.fnives.test.showcase">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
|
<application>
|
||||||
|
<activity
|
||||||
|
android:name=".ui.splash.SplashActivity"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity android:name=".ui.home.MainActivity" />
|
||||||
|
<activity android:name=".ui.auth.AuthActivity" />
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package org.fnives.test.showcase.di
|
package org.fnives.test.showcase.di
|
||||||
|
|
||||||
import org.fnives.test.showcase.core.di.createCoreModule
|
import org.fnives.test.showcase.core.di.koin.createCoreModule
|
||||||
import org.fnives.test.showcase.model.network.BaseUrl
|
import org.fnives.test.showcase.model.network.BaseUrl
|
||||||
import org.fnives.test.showcase.session.SessionExpirationListenerImpl
|
import org.fnives.test.showcase.session.SessionExpirationListenerImpl
|
||||||
import org.fnives.test.showcase.storage.LocalDatabase
|
import org.fnives.test.showcase.storage.LocalDatabase
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
package org.fnives.test.showcase.ui
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import org.fnives.test.showcase.ui.auth.AuthActivity
|
||||||
|
import org.fnives.test.showcase.ui.home.MainActivity
|
||||||
|
|
||||||
|
object IntentCoordinator {
|
||||||
|
|
||||||
|
fun mainActivitygetStartIntent(context: Context) =
|
||||||
|
MainActivity.getStartIntent(context)
|
||||||
|
|
||||||
|
fun authActivitygetStartIntent(context: Context) =
|
||||||
|
AuthActivity.getStartIntent(context)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package org.fnives.test.showcase.ui
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.ViewModelStoreOwner
|
||||||
|
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||||
|
|
||||||
|
inline fun <reified T : ViewModel> ViewModelStoreOwner.viewModels(): Lazy<T> =
|
||||||
|
viewModel()
|
||||||
|
|
@ -6,24 +6,13 @@
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
|
android:name=".TestShowcaseApplication"
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:name=".TestShowcaseApplication"
|
|
||||||
android:theme="@style/Theme.TestShowCase"
|
android:theme="@style/Theme.TestShowCase"
|
||||||
tools:ignore="AllowBackup">
|
tools:ignore="AllowBackup"/>
|
||||||
<activity android:name=".ui.splash.SplashActivity"
|
|
||||||
android:exported="true">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN" />
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
<activity android:name=".ui.home.MainActivity"/>
|
|
||||||
<activity android:name=".ui.auth.AuthActivity"/>
|
|
||||||
</application>
|
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
@ -4,15 +4,20 @@ import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import org.fnives.test.showcase.core.session.SessionExpirationListener
|
import org.fnives.test.showcase.core.session.SessionExpirationListener
|
||||||
import org.fnives.test.showcase.ui.auth.AuthActivity
|
import org.fnives.test.showcase.ui.IntentCoordinator
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
class SessionExpirationListenerImpl(private val context: Context) : SessionExpirationListener {
|
class SessionExpirationListenerImpl @Inject constructor(
|
||||||
|
@ApplicationContext
|
||||||
|
private val context: Context
|
||||||
|
) : SessionExpirationListener {
|
||||||
|
|
||||||
override fun onSessionExpired() {
|
override fun onSessionExpired() {
|
||||||
Handler(Looper.getMainLooper()).post {
|
Handler(Looper.getMainLooper()).post {
|
||||||
context.startActivity(
|
context.startActivity(
|
||||||
AuthActivity.getStartIntent(context)
|
IntentCoordinator.authActivitygetStartIntent(context)
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import org.fnives.test.showcase.model.session.Session
|
||||||
import kotlin.properties.ReadWriteProperty
|
import kotlin.properties.ReadWriteProperty
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
class SharedPreferencesManagerImpl(private val sharedPreferences: SharedPreferences) : UserDataLocalStorage {
|
class SharedPreferencesManagerImpl constructor(private val sharedPreferences: SharedPreferences) : UserDataLocalStorage {
|
||||||
|
|
||||||
override var session: Session? by SessionDelegate(SESSION_KEY)
|
override var session: Session? by SessionDelegate(SESSION_KEY)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,9 @@ import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import org.fnives.test.showcase.core.storage.content.FavouriteContentLocalStorage
|
import org.fnives.test.showcase.core.storage.content.FavouriteContentLocalStorage
|
||||||
import org.fnives.test.showcase.model.content.ContentId
|
import org.fnives.test.showcase.model.content.ContentId
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
class FavouriteContentLocalStorageImpl(private val favouriteDao: FavouriteDao) : FavouriteContentLocalStorage {
|
class FavouriteContentLocalStorageImpl @Inject constructor(private val favouriteDao: FavouriteDao) : FavouriteContentLocalStorage {
|
||||||
override fun observeFavourites(): Flow<List<ContentId>> =
|
override fun observeFavourites(): Flow<List<ContentId>> =
|
||||||
favouriteDao.get().map { it.map(FavouriteEntity::contentId).map(::ContentId) }
|
favouriteDao.get().map { it.map(FavouriteEntity::contentId).map(::ContentId) }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,12 @@ import androidx.core.widget.doAfterTextChanged
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import org.fnives.test.showcase.R
|
import org.fnives.test.showcase.R
|
||||||
import org.fnives.test.showcase.databinding.ActivityAuthenticationBinding
|
import org.fnives.test.showcase.databinding.ActivityAuthenticationBinding
|
||||||
import org.fnives.test.showcase.ui.home.MainActivity
|
import org.fnives.test.showcase.ui.IntentCoordinator
|
||||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
import org.fnives.test.showcase.ui.viewModels
|
||||||
|
|
||||||
class AuthActivity : AppCompatActivity() {
|
open class AuthActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private val viewModel by viewModel<AuthViewModel>()
|
private val viewModel by viewModels<AuthViewModel>()
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
@ -35,7 +35,7 @@ class AuthActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
viewModel.navigateToHome.observe(this) {
|
viewModel.navigateToHome.observe(this) {
|
||||||
it.consume() ?: return@observe
|
it.consume() ?: return@observe
|
||||||
startActivity(MainActivity.getStartIntent(this))
|
startActivity(IntentCoordinator.mainActivitygetStartIntent(this))
|
||||||
finishAffinity()
|
finishAffinity()
|
||||||
}
|
}
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,17 @@ import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.fnives.test.showcase.core.login.LoginUseCase
|
import org.fnives.test.showcase.core.login.LoginUseCase
|
||||||
import org.fnives.test.showcase.model.auth.LoginCredentials
|
import org.fnives.test.showcase.model.auth.LoginCredentials
|
||||||
import org.fnives.test.showcase.model.auth.LoginStatus
|
import org.fnives.test.showcase.model.auth.LoginStatus
|
||||||
import org.fnives.test.showcase.model.shared.Answer
|
import org.fnives.test.showcase.model.shared.Answer
|
||||||
import org.fnives.test.showcase.ui.shared.Event
|
import org.fnives.test.showcase.ui.shared.Event
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
class AuthViewModel(private val loginUseCase: LoginUseCase) : ViewModel() {
|
@HiltViewModel
|
||||||
|
class AuthViewModel @Inject constructor(private val loginUseCase: LoginUseCase) : ViewModel() {
|
||||||
|
|
||||||
private val _username = MutableLiveData<String>()
|
private val _username = MutableLiveData<String>()
|
||||||
val username: LiveData<String> = _username
|
val username: LiveData<String> = _username
|
||||||
|
|
|
||||||
|
|
@ -6,17 +6,18 @@ import android.os.Bundle
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import org.fnives.test.showcase.R
|
import org.fnives.test.showcase.R
|
||||||
import org.fnives.test.showcase.databinding.ActivityMainBinding
|
import org.fnives.test.showcase.databinding.ActivityMainBinding
|
||||||
import org.fnives.test.showcase.model.content.ContentId
|
import org.fnives.test.showcase.model.content.ContentId
|
||||||
import org.fnives.test.showcase.ui.auth.AuthActivity
|
import org.fnives.test.showcase.ui.IntentCoordinator
|
||||||
import org.fnives.test.showcase.ui.shared.VerticalSpaceItemDecoration
|
import org.fnives.test.showcase.ui.shared.VerticalSpaceItemDecoration
|
||||||
import org.fnives.test.showcase.ui.shared.getThemePrimaryColor
|
import org.fnives.test.showcase.ui.shared.getThemePrimaryColor
|
||||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
import org.fnives.test.showcase.ui.viewModels
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
open class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private val viewModel by viewModel<MainViewModel>()
|
private val viewModel by viewModels<MainViewModel>()
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
@ -45,7 +46,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
viewModel.navigateToAuth.observe(this) {
|
viewModel.navigateToAuth.observe(this) {
|
||||||
it.consume() ?: return@observe
|
it.consume() ?: return@observe
|
||||||
startActivity(AuthActivity.getStartIntent(this))
|
startActivity(IntentCoordinator.authActivitygetStartIntent(this))
|
||||||
finishAffinity()
|
finishAffinity()
|
||||||
}
|
}
|
||||||
viewModel.loading.observe(this) {
|
viewModel.loading.observe(this) {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.liveData
|
import androidx.lifecycle.liveData
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.collect
|
import kotlinx.coroutines.flow.collect
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.fnives.test.showcase.core.content.AddContentToFavouriteUseCase
|
import org.fnives.test.showcase.core.content.AddContentToFavouriteUseCase
|
||||||
|
|
@ -16,8 +17,10 @@ import org.fnives.test.showcase.model.content.ContentId
|
||||||
import org.fnives.test.showcase.model.content.FavouriteContent
|
import org.fnives.test.showcase.model.content.FavouriteContent
|
||||||
import org.fnives.test.showcase.model.shared.Resource
|
import org.fnives.test.showcase.model.shared.Resource
|
||||||
import org.fnives.test.showcase.ui.shared.Event
|
import org.fnives.test.showcase.ui.shared.Event
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
class MainViewModel(
|
@HiltViewModel
|
||||||
|
class MainViewModel @Inject constructor(
|
||||||
private val getAllContentUseCase: GetAllContentUseCase,
|
private val getAllContentUseCase: GetAllContentUseCase,
|
||||||
private val logoutUseCase: LogoutUseCase,
|
private val logoutUseCase: LogoutUseCase,
|
||||||
private val fetchContentUseCase: FetchContentUseCase,
|
private val fetchContentUseCase: FetchContentUseCase,
|
||||||
|
|
|
||||||
|
|
@ -3,21 +3,20 @@ package org.fnives.test.showcase.ui.splash
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import org.fnives.test.showcase.R
|
import org.fnives.test.showcase.R
|
||||||
import org.fnives.test.showcase.ui.auth.AuthActivity
|
import org.fnives.test.showcase.ui.IntentCoordinator
|
||||||
import org.fnives.test.showcase.ui.home.MainActivity
|
import org.fnives.test.showcase.ui.viewModels
|
||||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
|
||||||
|
|
||||||
class SplashActivity : AppCompatActivity() {
|
open class SplashActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private val viewModel by viewModel<SplashViewModel>()
|
private val viewModel by viewModels<SplashViewModel>()
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_splash)
|
setContentView(R.layout.activity_splash)
|
||||||
viewModel.navigateTo.observe(this) {
|
viewModel.navigateTo.observe(this) {
|
||||||
val intent = when (it.consume()) {
|
val intent = when (it.consume()) {
|
||||||
SplashViewModel.NavigateTo.HOME -> MainActivity.getStartIntent(this)
|
SplashViewModel.NavigateTo.HOME -> IntentCoordinator.mainActivitygetStartIntent(this)
|
||||||
SplashViewModel.NavigateTo.AUTHENTICATION -> AuthActivity.getStartIntent(this)
|
SplashViewModel.NavigateTo.AUTHENTICATION -> IntentCoordinator.authActivitygetStartIntent(this)
|
||||||
null -> return@observe
|
null -> return@observe
|
||||||
}
|
}
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,15 @@ import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.fnives.test.showcase.core.login.IsUserLoggedInUseCase
|
import org.fnives.test.showcase.core.login.IsUserLoggedInUseCase
|
||||||
import org.fnives.test.showcase.ui.shared.Event
|
import org.fnives.test.showcase.ui.shared.Event
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
class SplashViewModel(isUserLoggedInUseCase: IsUserLoggedInUseCase) : ViewModel() {
|
@HiltViewModel
|
||||||
|
class SplashViewModel @Inject constructor(isUserLoggedInUseCase: IsUserLoggedInUseCase) : ViewModel() {
|
||||||
|
|
||||||
private val _navigateTo = MutableLiveData<Event<NavigateTo>>()
|
private val _navigateTo = MutableLiveData<Event<NavigateTo>>()
|
||||||
val navigateTo: LiveData<Event<NavigateTo>> = _navigateTo
|
val navigateTo: LiveData<Event<NavigateTo>> = _navigateTo
|
||||||
|
|
|
||||||
13
build.gradle
13
build.gradle
|
|
@ -2,12 +2,14 @@
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = "1.5.30"
|
ext.kotlin_version = "1.5.30"
|
||||||
ext.detekt_version = "1.18.1"
|
ext.detekt_version = "1.18.1"
|
||||||
|
ext.hilt_version = "2.38.1"
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
google()
|
google()
|
||||||
maven { url "https://plugins.gradle.org/m2/" }
|
maven { url "https://plugins.gradle.org/m2/" }
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
|
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
|
||||||
classpath 'com.android.tools.build:gradle:7.0.2'
|
classpath 'com.android.tools.build:gradle:7.0.2'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
classpath "org.jlleitschuh.gradle:ktlint-gradle:10.2.0"
|
classpath "org.jlleitschuh.gradle:ktlint-gradle:10.2.0"
|
||||||
|
|
@ -22,6 +24,15 @@ allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
google()
|
google()
|
||||||
|
maven {
|
||||||
|
url "https://maven.pkg.github.com/fknives/ReloadableHiltModule"
|
||||||
|
credentials {
|
||||||
|
username = project.findProperty("GITHUB_USERNAME") ?: System.getenv("GITHUB_USERNAME")
|
||||||
|
password = project.findProperty("GITHUB_TOKEN") ?: System.getenv("GITHUB_TOKEN")
|
||||||
|
}
|
||||||
|
// how to get token
|
||||||
|
// https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -29,7 +40,7 @@ task clean(type: Delete) {
|
||||||
delete rootProject.buildDir
|
delete rootProject.buildDir
|
||||||
}
|
}
|
||||||
|
|
||||||
task unitTests(dependsOn: ["app:testDebugUnitTest", "core:test", "network:test"]){
|
task unitTests(dependsOn: ["app:testKoinDebugUnitTest", "app:testHiltDebugUnitTest", "core:test", "network:test"]){
|
||||||
group = 'Tests'
|
group = 'Tests'
|
||||||
description = 'Run all unit tests'
|
description = 'Run all unit tests'
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
plugins {
|
plugins {
|
||||||
id 'java-library'
|
id 'java-library'
|
||||||
id 'kotlin'
|
id 'kotlin'
|
||||||
|
id 'kotlin-kapt'
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
|
|
@ -14,12 +15,22 @@ compileKotlin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kapt {
|
||||||
|
correctErrorTypes = true
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
|
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
|
||||||
|
|
||||||
api project(":model")
|
api project(":model")
|
||||||
implementation project(":network")
|
implementation project(":network")
|
||||||
|
|
||||||
|
// hilt
|
||||||
|
implementation "com.google.dagger:hilt-core:$hilt_version"
|
||||||
|
kapt "com.google.dagger:hilt-compiler:$hilt_version"
|
||||||
|
implementation "org.fnives.library.reloadable.module:annotation:$reloadable_module_version"
|
||||||
|
kapt "org.fnives.library.reloadable.module:annotation-processor:$reloadable_module_version"
|
||||||
|
|
||||||
testImplementation "io.insert-koin:koin-test-junit5:$koin_version"
|
testImplementation "io.insert-koin:koin-test-junit5:$koin_version"
|
||||||
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
|
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
|
||||||
testImplementation "org.mockito.kotlin:mockito-kotlin:$testing_kotlin_mockito_version"
|
testImplementation "org.mockito.kotlin:mockito-kotlin:$testing_kotlin_mockito_version"
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@ package org.fnives.test.showcase.core.content
|
||||||
|
|
||||||
import org.fnives.test.showcase.core.storage.content.FavouriteContentLocalStorage
|
import org.fnives.test.showcase.core.storage.content.FavouriteContentLocalStorage
|
||||||
import org.fnives.test.showcase.model.content.ContentId
|
import org.fnives.test.showcase.model.content.ContentId
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
class AddContentToFavouriteUseCase internal constructor(
|
class AddContentToFavouriteUseCase @Inject internal constructor(
|
||||||
private val favouriteContentLocalStorage: FavouriteContentLocalStorage
|
private val favouriteContentLocalStorage: FavouriteContentLocalStorage
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.flatMapLatest
|
import kotlinx.coroutines.flow.flatMapLatest
|
||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
import kotlinx.coroutines.flow.flowOf
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
import org.fnives.test.showcase.core.di.hilt.LoggedInModuleInject
|
||||||
import org.fnives.test.showcase.core.shared.Optional
|
import org.fnives.test.showcase.core.shared.Optional
|
||||||
import org.fnives.test.showcase.core.shared.mapIntoResource
|
import org.fnives.test.showcase.core.shared.mapIntoResource
|
||||||
import org.fnives.test.showcase.core.shared.wrapIntoAnswer
|
import org.fnives.test.showcase.core.shared.wrapIntoAnswer
|
||||||
|
|
@ -14,7 +15,7 @@ import org.fnives.test.showcase.model.content.Content
|
||||||
import org.fnives.test.showcase.model.shared.Resource
|
import org.fnives.test.showcase.model.shared.Resource
|
||||||
import org.fnives.test.showcase.network.content.ContentRemoteSource
|
import org.fnives.test.showcase.network.content.ContentRemoteSource
|
||||||
|
|
||||||
internal class ContentRepository(private val contentRemoteSource: ContentRemoteSource) {
|
internal class ContentRepository @LoggedInModuleInject constructor(private val contentRemoteSource: ContentRemoteSource) {
|
||||||
|
|
||||||
private val mutableContentFlow = MutableStateFlow(Optional<List<Content>>(null))
|
private val mutableContentFlow = MutableStateFlow(Optional<List<Content>>(null))
|
||||||
private val requestFlow: Flow<Resource<List<Content>>> = flow {
|
private val requestFlow: Flow<Resource<List<Content>>> = flow {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package org.fnives.test.showcase.core.content
|
package org.fnives.test.showcase.core.content
|
||||||
|
|
||||||
class FetchContentUseCase internal constructor(private val contentRepository: ContentRepository) {
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class FetchContentUseCase @Inject internal constructor(private val contentRepository: ContentRepository) {
|
||||||
|
|
||||||
fun invoke() = contentRepository.fetch()
|
fun invoke() = contentRepository.fetch()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,9 @@ import org.fnives.test.showcase.model.content.Content
|
||||||
import org.fnives.test.showcase.model.content.ContentId
|
import org.fnives.test.showcase.model.content.ContentId
|
||||||
import org.fnives.test.showcase.model.content.FavouriteContent
|
import org.fnives.test.showcase.model.content.FavouriteContent
|
||||||
import org.fnives.test.showcase.model.shared.Resource
|
import org.fnives.test.showcase.model.shared.Resource
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
class GetAllContentUseCase internal constructor(
|
class GetAllContentUseCase @Inject internal constructor(
|
||||||
private val contentRepository: ContentRepository,
|
private val contentRepository: ContentRepository,
|
||||||
private val favouriteContentLocalStorage: FavouriteContentLocalStorage
|
private val favouriteContentLocalStorage: FavouriteContentLocalStorage
|
||||||
) {
|
) {
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@ package org.fnives.test.showcase.core.content
|
||||||
|
|
||||||
import org.fnives.test.showcase.core.storage.content.FavouriteContentLocalStorage
|
import org.fnives.test.showcase.core.storage.content.FavouriteContentLocalStorage
|
||||||
import org.fnives.test.showcase.model.content.ContentId
|
import org.fnives.test.showcase.model.content.ContentId
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
class RemoveContentFromFavouritesUseCase internal constructor(
|
class RemoveContentFromFavouritesUseCase @Inject internal constructor(
|
||||||
private val favouriteContentLocalStorage: FavouriteContentLocalStorage
|
private val favouriteContentLocalStorage: FavouriteContentLocalStorage
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
package org.fnives.test.showcase.core.di.hilt
|
||||||
|
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.Provides
|
||||||
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
import org.fnives.test.showcase.core.login.LogoutUseCase
|
||||||
|
import org.fnives.test.showcase.core.session.SessionExpirationAdapter
|
||||||
|
import org.fnives.test.showcase.core.storage.NetworkSessionLocalStorageAdapter
|
||||||
|
import org.fnives.test.showcase.core.storage.UserDataLocalStorage
|
||||||
|
import org.fnives.test.showcase.network.session.NetworkSessionExpirationListener
|
||||||
|
import org.fnives.test.showcase.network.session.NetworkSessionLocalStorage
|
||||||
|
import org.fnives.test.showcase.core.di.hilt.ReloadLoggedInModuleInjectModule
|
||||||
|
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
@Module
|
||||||
|
object CoreModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
internal fun bindNetworkSessionLocalStorageAdapter(
|
||||||
|
networkSessionLocalStorageAdapter: NetworkSessionLocalStorageAdapter
|
||||||
|
): NetworkSessionLocalStorage = networkSessionLocalStorageAdapter
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
internal fun bindNetworkSessionExpirationListener(
|
||||||
|
sessionExpirationAdapter: SessionExpirationAdapter
|
||||||
|
): NetworkSessionExpirationListener = sessionExpirationAdapter
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun provideLogoutUseCase(
|
||||||
|
storage: UserDataLocalStorage,
|
||||||
|
reloadLoggedInModuleInjectModule: ReloadLoggedInModuleInjectModule
|
||||||
|
) : LogoutUseCase = LogoutUseCase(storage, reloadLoggedInModuleInjectModule)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package org.fnives.test.showcase.core.di.hilt
|
||||||
|
|
||||||
|
import org.fnives.library.reloadable.module.annotation.ReloadableModule
|
||||||
|
|
||||||
|
@ReloadableModule
|
||||||
|
@Target(AnnotationTarget.CONSTRUCTOR)
|
||||||
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
|
annotation class LoggedInModuleInject
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package org.fnives.test.showcase.core.di
|
package org.fnives.test.showcase.core.di.koin
|
||||||
|
|
||||||
import org.fnives.test.showcase.core.content.AddContentToFavouriteUseCase
|
import org.fnives.test.showcase.core.content.AddContentToFavouriteUseCase
|
||||||
import org.fnives.test.showcase.core.content.ContentRepository
|
import org.fnives.test.showcase.core.content.ContentRepository
|
||||||
|
|
@ -14,7 +14,7 @@ import org.fnives.test.showcase.core.storage.NetworkSessionLocalStorageAdapter
|
||||||
import org.fnives.test.showcase.core.storage.UserDataLocalStorage
|
import org.fnives.test.showcase.core.storage.UserDataLocalStorage
|
||||||
import org.fnives.test.showcase.core.storage.content.FavouriteContentLocalStorage
|
import org.fnives.test.showcase.core.storage.content.FavouriteContentLocalStorage
|
||||||
import org.fnives.test.showcase.model.network.BaseUrl
|
import org.fnives.test.showcase.model.network.BaseUrl
|
||||||
import org.fnives.test.showcase.network.di.createNetworkModules
|
import org.fnives.test.showcase.network.di.koin.createNetworkModules
|
||||||
import org.koin.core.module.Module
|
import org.koin.core.module.Module
|
||||||
import org.koin.core.scope.Scope
|
import org.koin.core.scope.Scope
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
@ -42,7 +42,7 @@ fun repositoryModule() = module {
|
||||||
|
|
||||||
fun useCaseModule() = module {
|
fun useCaseModule() = module {
|
||||||
factory { LoginUseCase(get(), get()) }
|
factory { LoginUseCase(get(), get()) }
|
||||||
factory { LogoutUseCase(get()) }
|
factory { LogoutUseCase(get(), null) }
|
||||||
factory { GetAllContentUseCase(get(), get()) }
|
factory { GetAllContentUseCase(get(), get()) }
|
||||||
factory { AddContentToFavouriteUseCase(get()) }
|
factory { AddContentToFavouriteUseCase(get()) }
|
||||||
factory { RemoveContentFromFavouritesUseCase(get()) }
|
factory { RemoveContentFromFavouritesUseCase(get()) }
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
package org.fnives.test.showcase.core.login
|
package org.fnives.test.showcase.core.login
|
||||||
|
|
||||||
import org.fnives.test.showcase.core.storage.UserDataLocalStorage
|
import org.fnives.test.showcase.core.storage.UserDataLocalStorage
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
class IsUserLoggedInUseCase(private val userDataLocalStorage: UserDataLocalStorage) {
|
class IsUserLoggedInUseCase @Inject constructor(
|
||||||
|
private val userDataLocalStorage: UserDataLocalStorage
|
||||||
|
) {
|
||||||
|
|
||||||
fun invoke(): Boolean = userDataLocalStorage.session != null
|
fun invoke(): Boolean = userDataLocalStorage.session != null
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,9 @@ import org.fnives.test.showcase.model.auth.LoginStatus
|
||||||
import org.fnives.test.showcase.model.shared.Answer
|
import org.fnives.test.showcase.model.shared.Answer
|
||||||
import org.fnives.test.showcase.network.auth.LoginRemoteSource
|
import org.fnives.test.showcase.network.auth.LoginRemoteSource
|
||||||
import org.fnives.test.showcase.network.auth.model.LoginStatusResponses
|
import org.fnives.test.showcase.network.auth.model.LoginStatusResponses
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
class LoginUseCase internal constructor(
|
class LoginUseCase @Inject internal constructor(
|
||||||
private val loginRemoteSource: LoginRemoteSource,
|
private val loginRemoteSource: LoginRemoteSource,
|
||||||
private val userDataLocalStorage: UserDataLocalStorage
|
private val userDataLocalStorage: UserDataLocalStorage
|
||||||
) {
|
) {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,22 @@
|
||||||
package org.fnives.test.showcase.core.login
|
package org.fnives.test.showcase.core.login
|
||||||
|
|
||||||
import org.fnives.test.showcase.core.di.repositoryModule
|
import org.fnives.test.showcase.core.di.koin.repositoryModule
|
||||||
import org.fnives.test.showcase.core.storage.UserDataLocalStorage
|
import org.fnives.test.showcase.core.storage.UserDataLocalStorage
|
||||||
import org.koin.core.context.loadKoinModules
|
import org.koin.core.context.loadKoinModules
|
||||||
|
import org.koin.mp.KoinPlatformTools
|
||||||
|
import org.fnives.test.showcase.core.di.hilt.ReloadLoggedInModuleInjectModule
|
||||||
|
|
||||||
class LogoutUseCase(private val storage: UserDataLocalStorage) {
|
class LogoutUseCase(
|
||||||
|
private val storage: UserDataLocalStorage,
|
||||||
|
private val reloadLoggedInModuleInjectModule: ReloadLoggedInModuleInjectModule?
|
||||||
|
) {
|
||||||
|
|
||||||
suspend fun invoke() {
|
suspend fun invoke() {
|
||||||
loadKoinModules(repositoryModule())
|
if (KoinPlatformTools.defaultContext().getOrNull() == null) {
|
||||||
|
reloadLoggedInModuleInjectModule?.reload()
|
||||||
|
} else {
|
||||||
|
loadKoinModules(repositoryModule())
|
||||||
|
}
|
||||||
storage.session = null
|
storage.session = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
package org.fnives.test.showcase.core.session
|
package org.fnives.test.showcase.core.session
|
||||||
|
|
||||||
import org.fnives.test.showcase.network.session.NetworkSessionExpirationListener
|
import org.fnives.test.showcase.network.session.NetworkSessionExpirationListener
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class SessionExpirationAdapter(
|
internal class SessionExpirationAdapter @Inject constructor(
|
||||||
private val sessionExpirationListener: SessionExpirationListener
|
private val sessionExpirationListener: SessionExpirationListener
|
||||||
) :
|
) : NetworkSessionExpirationListener {
|
||||||
NetworkSessionExpirationListener {
|
|
||||||
|
|
||||||
override fun onSessionExpired() = sessionExpirationListener.onSessionExpired()
|
override fun onSessionExpired() = sessionExpirationListener.onSessionExpired()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@ package org.fnives.test.showcase.core.storage
|
||||||
|
|
||||||
import org.fnives.test.showcase.model.session.Session
|
import org.fnives.test.showcase.model.session.Session
|
||||||
import org.fnives.test.showcase.network.session.NetworkSessionLocalStorage
|
import org.fnives.test.showcase.network.session.NetworkSessionLocalStorage
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class NetworkSessionLocalStorageAdapter(
|
internal class NetworkSessionLocalStorageAdapter @Inject constructor(
|
||||||
private val userDataLocalStorage: UserDataLocalStorage
|
private val userDataLocalStorage: UserDataLocalStorage
|
||||||
) : NetworkSessionLocalStorage {
|
) : NetworkSessionLocalStorage {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package org.fnives.test.showcase.core.login
|
||||||
|
|
||||||
import kotlinx.coroutines.test.runBlockingTest
|
import kotlinx.coroutines.test.runBlockingTest
|
||||||
import org.fnives.test.showcase.core.content.ContentRepository
|
import org.fnives.test.showcase.core.content.ContentRepository
|
||||||
import org.fnives.test.showcase.core.di.createCoreModule
|
import org.fnives.test.showcase.core.di.koin.createCoreModule
|
||||||
import org.fnives.test.showcase.core.storage.UserDataLocalStorage
|
import org.fnives.test.showcase.core.storage.UserDataLocalStorage
|
||||||
import org.fnives.test.showcase.model.network.BaseUrl
|
import org.fnives.test.showcase.model.network.BaseUrl
|
||||||
import org.junit.jupiter.api.AfterEach
|
import org.junit.jupiter.api.AfterEach
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ project.ext {
|
||||||
androidx_livedata_version = "2.3.1"
|
androidx_livedata_version = "2.3.1"
|
||||||
androidx_swiperefreshlayout_version = "1.1.0"
|
androidx_swiperefreshlayout_version = "1.1.0"
|
||||||
androidx_room_version = "2.3.0"
|
androidx_room_version = "2.3.0"
|
||||||
|
activity_ktx_version = "1.3.1"
|
||||||
|
|
||||||
coroutines_version = "1.4.3"
|
coroutines_version = "1.4.3"
|
||||||
koin_version = "3.1.2"
|
koin_version = "3.1.2"
|
||||||
|
|
@ -13,6 +14,7 @@ project.ext {
|
||||||
retrofit_version = "2.9.0"
|
retrofit_version = "2.9.0"
|
||||||
okhttp_version = "4.9.1"
|
okhttp_version = "4.9.1"
|
||||||
moshi_version = "1.12.0"
|
moshi_version = "1.12.0"
|
||||||
|
reloadable_module_version = "0.1.0"
|
||||||
|
|
||||||
testing_androidx_code_version = "1.4.0"
|
testing_androidx_code_version = "1.4.0"
|
||||||
testing_androidx_junit_version = "1.1.3"
|
testing_androidx_junit_version = "1.1.3"
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ dependencies {
|
||||||
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"
|
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"
|
||||||
implementation "com.squareup.okhttp3:logging-interceptor:$okhttp_version"
|
implementation "com.squareup.okhttp3:logging-interceptor:$okhttp_version"
|
||||||
api "io.insert-koin:koin-core:$koin_version"
|
api "io.insert-koin:koin-core:$koin_version"
|
||||||
|
implementation "com.google.dagger:hilt-core:$hilt_version"
|
||||||
|
kapt "com.google.dagger:hilt-compiler:$hilt_version"
|
||||||
|
|
||||||
api project(":model")
|
api project(":model")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,9 @@ import org.fnives.test.showcase.network.shared.ExceptionWrapper
|
||||||
import org.fnives.test.showcase.network.shared.exceptions.ParsingException
|
import org.fnives.test.showcase.network.shared.exceptions.ParsingException
|
||||||
import retrofit2.HttpException
|
import retrofit2.HttpException
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class LoginErrorConverter {
|
internal class LoginErrorConverter @Inject constructor() {
|
||||||
|
|
||||||
@Throws(ParsingException::class)
|
@Throws(ParsingException::class)
|
||||||
suspend fun invoke(request: suspend () -> Response<LoginResponse>): LoginStatusResponses =
|
suspend fun invoke(request: suspend () -> Response<LoginResponse>): LoginStatusResponses =
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,9 @@ import org.fnives.test.showcase.network.auth.model.LoginStatusResponses
|
||||||
import org.fnives.test.showcase.network.shared.ExceptionWrapper
|
import org.fnives.test.showcase.network.shared.ExceptionWrapper
|
||||||
import org.fnives.test.showcase.network.shared.exceptions.NetworkException
|
import org.fnives.test.showcase.network.shared.exceptions.NetworkException
|
||||||
import org.fnives.test.showcase.network.shared.exceptions.ParsingException
|
import org.fnives.test.showcase.network.shared.exceptions.ParsingException
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class LoginRemoteSourceImpl constructor(
|
internal class LoginRemoteSourceImpl @Inject constructor(
|
||||||
private val loginService: LoginService,
|
private val loginService: LoginService,
|
||||||
private val loginErrorConverter: LoginErrorConverter
|
private val loginErrorConverter: LoginErrorConverter
|
||||||
) : LoginRemoteSource {
|
) : LoginRemoteSource {
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,9 @@ import org.fnives.test.showcase.model.content.Content
|
||||||
import org.fnives.test.showcase.model.content.ContentId
|
import org.fnives.test.showcase.model.content.ContentId
|
||||||
import org.fnives.test.showcase.model.content.ImageUrl
|
import org.fnives.test.showcase.model.content.ImageUrl
|
||||||
import org.fnives.test.showcase.network.shared.ExceptionWrapper
|
import org.fnives.test.showcase.network.shared.ExceptionWrapper
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class ContentRemoteSourceImpl(private val contentService: ContentService) : ContentRemoteSource {
|
internal class ContentRemoteSourceImpl @Inject constructor(private val contentService: ContentService) : ContentRemoteSource {
|
||||||
|
|
||||||
override suspend fun get(): List<Content> =
|
override suspend fun get(): List<Content> =
|
||||||
ExceptionWrapper.wrap {
|
ExceptionWrapper.wrap {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
package org.fnives.test.showcase.network.di.hilt
|
||||||
|
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.Provides
|
||||||
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import org.fnives.test.showcase.network.auth.LoginRemoteSource
|
||||||
|
import org.fnives.test.showcase.network.auth.LoginRemoteSourceImpl
|
||||||
|
import org.fnives.test.showcase.network.auth.LoginService
|
||||||
|
import org.fnives.test.showcase.network.content.ContentRemoteSource
|
||||||
|
import org.fnives.test.showcase.network.content.ContentRemoteSourceImpl
|
||||||
|
import org.fnives.test.showcase.network.content.ContentService
|
||||||
|
import org.fnives.test.showcase.network.di.setupLogging
|
||||||
|
import org.fnives.test.showcase.network.session.AuthenticationHeaderInterceptor
|
||||||
|
import org.fnives.test.showcase.network.session.AuthenticationHeaderUtils
|
||||||
|
import org.fnives.test.showcase.network.session.SessionAuthenticator
|
||||||
|
import org.fnives.test.showcase.network.shared.PlatformInterceptor
|
||||||
|
import retrofit2.Converter
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.converter.moshi.MoshiConverterFactory
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
@Module
|
||||||
|
object HiltNetworkModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideConverterFactory(): Converter.Factory = MoshiConverterFactory.create()
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
@SessionLessQualifier
|
||||||
|
fun provideSessionLessOkHttpClient(enableLogging: Boolean) =
|
||||||
|
OkHttpClient.Builder()
|
||||||
|
.addInterceptor(PlatformInterceptor())
|
||||||
|
.setupLogging(enableLogging)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
@SessionLessQualifier
|
||||||
|
fun provideSessionLessRetrofit(
|
||||||
|
baseUrl: String,
|
||||||
|
converterFactory: Converter.Factory,
|
||||||
|
@SessionLessQualifier okHttpClient: OkHttpClient
|
||||||
|
) = Retrofit.Builder()
|
||||||
|
.baseUrl(baseUrl)
|
||||||
|
.addConverterFactory(converterFactory)
|
||||||
|
.client(okHttpClient)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
@SessionQualifier
|
||||||
|
internal fun provideSessionOkHttpClient(
|
||||||
|
@SessionLessQualifier okHttpClient: OkHttpClient,
|
||||||
|
sessionAuthenticator: SessionAuthenticator,
|
||||||
|
authenticationHeaderUtils: AuthenticationHeaderUtils
|
||||||
|
) =
|
||||||
|
okHttpClient
|
||||||
|
.newBuilder()
|
||||||
|
.authenticator(sessionAuthenticator)
|
||||||
|
.addInterceptor(AuthenticationHeaderInterceptor(authenticationHeaderUtils))
|
||||||
|
.build()
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
@SessionQualifier
|
||||||
|
fun provideSessionRetrofit(
|
||||||
|
@SessionLessQualifier retrofit: Retrofit,
|
||||||
|
@SessionQualifier okHttpClient: OkHttpClient
|
||||||
|
) = retrofit.newBuilder()
|
||||||
|
.client(okHttpClient)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
internal fun bindContentRemoteSource(
|
||||||
|
contentRemoteSourceImpl: ContentRemoteSourceImpl
|
||||||
|
): ContentRemoteSource = contentRemoteSourceImpl
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
internal fun bindLoginRemoteSource(
|
||||||
|
loginRemoteSource: LoginRemoteSourceImpl
|
||||||
|
): LoginRemoteSource = loginRemoteSource
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
internal fun provideLoginService(@SessionLessQualifier retrofit: Retrofit): LoginService =
|
||||||
|
retrofit.create(LoginService::class.java)
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
internal fun provideContentService(@SessionQualifier retrofit: Retrofit): ContentService =
|
||||||
|
retrofit.create(ContentService::class.java)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package org.fnives.test.showcase.network.di.hilt
|
||||||
|
|
||||||
|
import javax.inject.Qualifier
|
||||||
|
|
||||||
|
@Qualifier
|
||||||
|
annotation class SessionLessQualifier
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package org.fnives.test.showcase.network.di.hilt
|
||||||
|
|
||||||
|
import javax.inject.Qualifier
|
||||||
|
|
||||||
|
@Qualifier
|
||||||
|
annotation class SessionQualifier
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package org.fnives.test.showcase.network.di
|
package org.fnives.test.showcase.network.di.koin
|
||||||
|
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import org.fnives.test.showcase.model.network.BaseUrl
|
import org.fnives.test.showcase.model.network.BaseUrl
|
||||||
|
|
@ -9,6 +9,7 @@ import org.fnives.test.showcase.network.auth.LoginService
|
||||||
import org.fnives.test.showcase.network.content.ContentRemoteSource
|
import org.fnives.test.showcase.network.content.ContentRemoteSource
|
||||||
import org.fnives.test.showcase.network.content.ContentRemoteSourceImpl
|
import org.fnives.test.showcase.network.content.ContentRemoteSourceImpl
|
||||||
import org.fnives.test.showcase.network.content.ContentService
|
import org.fnives.test.showcase.network.content.ContentService
|
||||||
|
import org.fnives.test.showcase.network.di.setupLogging
|
||||||
import org.fnives.test.showcase.network.session.AuthenticationHeaderInterceptor
|
import org.fnives.test.showcase.network.session.AuthenticationHeaderInterceptor
|
||||||
import org.fnives.test.showcase.network.session.AuthenticationHeaderUtils
|
import org.fnives.test.showcase.network.session.AuthenticationHeaderUtils
|
||||||
import org.fnives.test.showcase.network.session.NetworkSessionExpirationListener
|
import org.fnives.test.showcase.network.session.NetworkSessionExpirationListener
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
package org.fnives.test.showcase.network.session
|
package org.fnives.test.showcase.network.session
|
||||||
|
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class AuthenticationHeaderUtils(private val networkSessionLocalStorage: NetworkSessionLocalStorage) {
|
internal class AuthenticationHeaderUtils @Inject constructor(private val networkSessionLocalStorage: NetworkSessionLocalStorage) {
|
||||||
|
|
||||||
fun hasToken(okhttpRequest: Request): Boolean =
|
fun hasToken(okhttpRequest: Request): Boolean =
|
||||||
okhttpRequest.header(KEY) == networkSessionLocalStorage.session?.accessToken
|
okhttpRequest.header(KEY) == networkSessionLocalStorage.session?.accessToken
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,9 @@ import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import okhttp3.Route
|
import okhttp3.Route
|
||||||
import org.fnives.test.showcase.network.auth.LoginRemoteSourceImpl
|
import org.fnives.test.showcase.network.auth.LoginRemoteSourceImpl
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class SessionAuthenticator(
|
internal class SessionAuthenticator @Inject constructor(
|
||||||
private val networkSessionLocalStorage: NetworkSessionLocalStorage,
|
private val networkSessionLocalStorage: NetworkSessionLocalStorage,
|
||||||
private val loginRemoteSource: LoginRemoteSourceImpl,
|
private val loginRemoteSource: LoginRemoteSourceImpl,
|
||||||
private val authenticationHeaderUtils: AuthenticationHeaderUtils,
|
private val authenticationHeaderUtils: AuthenticationHeaderUtils,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package org.fnives.test.showcase.network.auth
|
||||||
|
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.fnives.test.showcase.model.network.BaseUrl
|
import org.fnives.test.showcase.model.network.BaseUrl
|
||||||
import org.fnives.test.showcase.network.di.createNetworkModules
|
import org.fnives.test.showcase.network.di.koin.createNetworkModules
|
||||||
import org.fnives.test.showcase.network.mockserver.ContentData
|
import org.fnives.test.showcase.network.mockserver.ContentData
|
||||||
import org.fnives.test.showcase.network.mockserver.scenario.refresh.RefreshTokenScenario
|
import org.fnives.test.showcase.network.mockserver.scenario.refresh.RefreshTokenScenario
|
||||||
import org.fnives.test.showcase.network.session.NetworkSessionLocalStorage
|
import org.fnives.test.showcase.network.session.NetworkSessionLocalStorage
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import kotlinx.coroutines.runBlocking
|
||||||
import org.fnives.test.showcase.model.auth.LoginCredentials
|
import org.fnives.test.showcase.model.auth.LoginCredentials
|
||||||
import org.fnives.test.showcase.model.network.BaseUrl
|
import org.fnives.test.showcase.model.network.BaseUrl
|
||||||
import org.fnives.test.showcase.network.auth.model.LoginStatusResponses
|
import org.fnives.test.showcase.network.auth.model.LoginStatusResponses
|
||||||
import org.fnives.test.showcase.network.di.createNetworkModules
|
import org.fnives.test.showcase.network.di.koin.createNetworkModules
|
||||||
import org.fnives.test.showcase.network.mockserver.ContentData
|
import org.fnives.test.showcase.network.mockserver.ContentData
|
||||||
import org.fnives.test.showcase.network.mockserver.ContentData.createExpectedLoginRequestJson
|
import org.fnives.test.showcase.network.mockserver.ContentData.createExpectedLoginRequestJson
|
||||||
import org.fnives.test.showcase.network.mockserver.scenario.auth.AuthScenario
|
import org.fnives.test.showcase.network.mockserver.scenario.auth.AuthScenario
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package org.fnives.test.showcase.network.content
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import okhttp3.mockwebserver.MockWebServer
|
import okhttp3.mockwebserver.MockWebServer
|
||||||
import org.fnives.test.showcase.model.network.BaseUrl
|
import org.fnives.test.showcase.model.network.BaseUrl
|
||||||
import org.fnives.test.showcase.network.di.createNetworkModules
|
import org.fnives.test.showcase.network.di.koin.createNetworkModules
|
||||||
import org.fnives.test.showcase.network.session.NetworkSessionExpirationListener
|
import org.fnives.test.showcase.network.session.NetworkSessionExpirationListener
|
||||||
import org.fnives.test.showcase.network.session.NetworkSessionLocalStorage
|
import org.fnives.test.showcase.network.session.NetworkSessionLocalStorage
|
||||||
import org.junit.jupiter.api.AfterEach
|
import org.junit.jupiter.api.AfterEach
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package org.fnives.test.showcase.network.content
|
||||||
|
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.fnives.test.showcase.model.network.BaseUrl
|
import org.fnives.test.showcase.model.network.BaseUrl
|
||||||
import org.fnives.test.showcase.network.di.createNetworkModules
|
import org.fnives.test.showcase.network.di.koin.createNetworkModules
|
||||||
import org.fnives.test.showcase.network.mockserver.ContentData
|
import org.fnives.test.showcase.network.mockserver.ContentData
|
||||||
import org.fnives.test.showcase.network.mockserver.scenario.content.ContentScenario
|
import org.fnives.test.showcase.network.mockserver.scenario.content.ContentScenario
|
||||||
import org.fnives.test.showcase.network.session.NetworkSessionLocalStorage
|
import org.fnives.test.showcase.network.session.NetworkSessionLocalStorage
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package org.fnives.test.showcase.network.content
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.fnives.test.showcase.model.network.BaseUrl
|
import org.fnives.test.showcase.model.network.BaseUrl
|
||||||
import org.fnives.test.showcase.model.session.Session
|
import org.fnives.test.showcase.model.session.Session
|
||||||
import org.fnives.test.showcase.network.di.createNetworkModules
|
import org.fnives.test.showcase.network.di.koin.createNetworkModules
|
||||||
import org.fnives.test.showcase.network.mockserver.ContentData
|
import org.fnives.test.showcase.network.mockserver.ContentData
|
||||||
import org.fnives.test.showcase.network.mockserver.scenario.content.ContentScenario
|
import org.fnives.test.showcase.network.mockserver.scenario.content.ContentScenario
|
||||||
import org.fnives.test.showcase.network.mockserver.scenario.refresh.RefreshTokenScenario
|
import org.fnives.test.showcase.network.mockserver.scenario.refresh.RefreshTokenScenario
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue