diff --git a/app-watch/app/build.gradle.kts b/app-watch/app/build.gradle.kts index be703251..9871f408 100644 --- a/app-watch/app/build.gradle.kts +++ b/app-watch/app/build.gradle.kts @@ -1,7 +1,7 @@ plugins { id("composenews.android.application") id("composenews.android.application.compose") - id("composenews.android.hilt") + id("composenews.android.koin") } android { @@ -43,9 +43,7 @@ dependencies { } libs.apply { implementation(androidx.ktx) - implementation(hilt.work) implementation(lifecycle.runtime.ktx) - implementation(hilt.navigation.compose) implementation(work.runtime.ktx) implementation(compose.activity) implementation(compose.ui.preview.wear) diff --git a/app-watch/app/src/main/java/ir/composenews/ComposeNewsWearApplication.kt b/app-watch/app/src/main/java/ir/composenews/ComposeNewsWearApplication.kt index a716208e..de0ddf62 100644 --- a/app-watch/app/src/main/java/ir/composenews/ComposeNewsWearApplication.kt +++ b/app-watch/app/src/main/java/ir/composenews/ComposeNewsWearApplication.kt @@ -1,7 +1,30 @@ package ir.composenews import android.app.Application -import dagger.hilt.android.HiltAndroidApp +import ir.composenews.data.di.repositoryModule +import ir.composenews.marketdetail.marketDetailFeatureModule +import ir.composenews.marketlist.marketListFeatureModule +import org.koin.android.ext.koin.androidContext +import org.koin.android.ext.koin.androidLogger +import org.koin.core.context.GlobalContext.startKoin +import org.koin.core.logger.Level -@HiltAndroidApp -class ComposeNewsWearApplication : Application() \ No newline at end of file +class ComposeNewsWearApplication : Application() { + override fun onCreate() { + super.onCreate() + + startKoin { + androidContext(this@ComposeNewsWearApplication) + androidLogger(Level.DEBUG) + + modules( + listOf( + mainViewModelModule, + marketListFeatureModule, marketDetailFeatureModule, + + repositoryModule, + ) + ) + } + } +} \ No newline at end of file diff --git a/app-watch/app/src/main/java/ir/composenews/MainViewModel.kt b/app-watch/app/src/main/java/ir/composenews/MainViewModel.kt index 472caecc..ef30d481 100644 --- a/app-watch/app/src/main/java/ir/composenews/MainViewModel.kt +++ b/app-watch/app/src/main/java/ir/composenews/MainViewModel.kt @@ -1,7 +1,6 @@ package ir.composenews import androidx.lifecycle.viewModelScope -import dagger.hilt.android.lifecycle.HiltViewModel import ir.composenews.appwatch.navigation.MainContract import ir.composenews.base.BaseViewModel import ir.composenews.core_test.dispatcher.DispatcherProvider @@ -10,12 +9,13 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch -import javax.inject.Inject +import org.koin.android.annotation.KoinViewModel +import org.koin.core.component.KoinComponent -@HiltViewModel -class MainViewModel @Inject constructor( +@KoinViewModel +class MainViewModel( dispatcherProvider: DispatcherProvider, -) : BaseViewModel(dispatcherProvider), MainContract { +) : BaseViewModel(dispatcherProvider), MainContract{ private val mutableState = MutableStateFlow(MainContract.State()) override val state: StateFlow = mutableState.asStateFlow() diff --git a/app-watch/app/src/main/java/ir/composenews/mainViewModelModule.kt b/app-watch/app/src/main/java/ir/composenews/mainViewModelModule.kt new file mode 100644 index 00000000..810fb63a --- /dev/null +++ b/app-watch/app/src/main/java/ir/composenews/mainViewModelModule.kt @@ -0,0 +1,9 @@ +package ir.composenews + +import org.koin.androidx.viewmodel.dsl.viewModel +import org.koin.dsl.module + +val mainViewModelModule =module { + viewModel { + MainViewModel(get())} +} diff --git a/app-watch/app/src/main/java/ir/composenews/ui/MainActivity.kt b/app-watch/app/src/main/java/ir/composenews/ui/MainActivity.kt index b11a80a5..98c5ef4d 100644 --- a/app-watch/app/src/main/java/ir/composenews/ui/MainActivity.kt +++ b/app-watch/app/src/main/java/ir/composenews/ui/MainActivity.kt @@ -3,7 +3,6 @@ package ir.composenews.ui import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.activity.viewModels import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.ui.Modifier @@ -13,17 +12,16 @@ import androidx.wear.compose.navigation.rememberSwipeDismissableNavController import androidx.wear.tooling.preview.devices.WearDevices import com.google.android.horologist.compose.layout.AppScaffold import com.google.android.horologist.compose.layout.ScreenScaffold -import dagger.hilt.android.AndroidEntryPoint import ir.composenews.MainViewModel -import ir.composenews.appwatch.navigation.graph.Destinations import ir.composenews.appwatch.navigation.MainContract +import ir.composenews.appwatch.navigation.graph.Destinations import ir.composenews.designsystem.theme.ComposeNewsTheme import ir.composenews.navigation.ComposeNewsWearNavHost +import org.koin.androidx.viewmodel.ext.android.viewModel -@AndroidEntryPoint class MainActivity : ComponentActivity() { - private val mainViewModel: MainViewModel by viewModels() + private val mainViewModel: MainViewModel by viewModel() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app-watch/navigation/build.gradle.kts b/app-watch/navigation/build.gradle.kts index 9d68faf7..9c080533 100644 --- a/app-watch/navigation/build.gradle.kts +++ b/app-watch/navigation/build.gradle.kts @@ -9,7 +9,7 @@ android { dependencies { projects.apply { - implementation(appWatch.ui) + api(appWatch.ui) implementation(core.uimarket) } implementation(libs.navigation.compose.wear) diff --git a/app-watch/ui/build.gradle.kts b/app-watch/ui/build.gradle.kts index 3782c4c5..32d3343a 100644 --- a/app-watch/ui/build.gradle.kts +++ b/app-watch/ui/build.gradle.kts @@ -1,5 +1,6 @@ plugins { id("composenews.android.feature") + id("composenews.android.koin") } android { @@ -14,8 +15,8 @@ configurations.all { dependencies { projects.apply { - implementation(feature.marketlist) - implementation(feature.marketdetail) + api(feature.marketlist) + api(feature.marketdetail) implementation(core.uimarket) implementation(core.extensions) implementation(data.marketRepository) diff --git a/app-watch/ui/src/main/java/ir/composenews/appwatch/ui/details/MarketWearDetails.kt b/app-watch/ui/src/main/java/ir/composenews/appwatch/ui/details/MarketWearDetails.kt index 2fc5da25..8abce54b 100644 --- a/app-watch/ui/src/main/java/ir/composenews/appwatch/ui/details/MarketWearDetails.kt +++ b/app-watch/ui/src/main/java/ir/composenews/appwatch/ui/details/MarketWearDetails.kt @@ -21,7 +21,6 @@ import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel import androidx.wear.compose.material.MaterialTheme import androidx.wear.compose.material.Text import androidx.wear.tooling.preview.devices.WearDevices @@ -42,12 +41,13 @@ import ir.composenews.marketdetail.MarketDetailViewModel import ir.composenews.marketdetail.formatNumber import ir.composenews.marketdetail.preview_provider.MarketDetailStateProvider import ir.composenews.uimarket.model.MarketModel +import org.koin.androidx.compose.koinViewModel @Composable fun MarketDetailWearRoute( market: MarketModel?, ) { - val viewModel: MarketDetailViewModel = hiltViewModel() + val viewModel: MarketDetailViewModel = koinViewModel() val (state, event) = use(viewModel = viewModel) LaunchedEffect(key1 = market) { event.invoke(MarketDetailContract.Event.SetMarket(market = market)) diff --git a/app-watch/ui/src/main/java/ir/composenews/appwatch/ui/list/MarketListWearScreen.kt b/app-watch/ui/src/main/java/ir/composenews/appwatch/ui/list/MarketListWearScreen.kt index 92fbc916..3b7bfd7e 100644 --- a/app-watch/ui/src/main/java/ir/composenews/appwatch/ui/list/MarketListWearScreen.kt +++ b/app-watch/ui/src/main/java/ir/composenews/appwatch/ui/list/MarketListWearScreen.kt @@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Modifier -import androidx.hilt.navigation.compose.hiltViewModel import androidx.wear.compose.foundation.lazy.items import com.google.android.horologist.annotations.ExperimentalHorologistApi import com.google.android.horologist.compose.layout.ScalingLazyColumn @@ -22,13 +21,14 @@ import ir.composenews.extensions.roundToTwoDecimalPlaces import ir.composenews.marketlist.MarketListContract import ir.composenews.marketlist.MarketListViewModel import ir.composenews.uimarket.model.MarketModel +import org.koin.androidx.compose.koinViewModel @Composable fun MarketListWearRoute( showFavoriteList: Boolean = false, onNavigateToDetailScreen: (market: MarketModel) -> Unit, ) { - val viewModel: MarketListViewModel = hiltViewModel() + val viewModel: MarketListViewModel = koinViewModel() val (state, event) = use(viewModel = viewModel) LaunchedEffect(key1 = Unit) { event.invoke(MarketListContract.Event.OnSetShowFavoriteList(showFavoriteList = showFavoriteList)) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c3e94a29..2ab456f5 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,7 +1,7 @@ plugins { id("composenews.android.application") id("composenews.android.application.compose") - id("composenews.android.hilt") + id("composenews.android.koin") } android { @@ -44,10 +44,8 @@ dependencies { libs.apply { implementation(compose.activity) implementation(androidx.ktx) - implementation(hilt.work) implementation(lifecycle.runtime.ktx) implementation(work.runtime.ktx) - implementation(hilt.navigation.compose) implementation(compose.material3.adaptive.navigation.suite) implementation(compose.material3.adaptive.navigation) implementation(espresso.core) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index a0900546..9ed0507d 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -44,11 +44,6 @@ -keep class * extends androidx.compose.runtime.Composable { *; } --keepclassmembers class * { - @dagger.hilt.android.lifecycle.HiltViewModel *; -} --keep,@dagger.hilt.InstallIn class * { *; } --keep class dagger.hilt.** { *; } -dontwarn dagger.internal.codegen.ComponentProcessor -keep class retrofit2.** { *; } diff --git a/app/src/main/java/ir/composenews/ComposeNewsApplication.kt b/app/src/main/java/ir/composenews/ComposeNewsApplication.kt index 37829bf5..0c18cafd 100644 --- a/app/src/main/java/ir/composenews/ComposeNewsApplication.kt +++ b/app/src/main/java/ir/composenews/ComposeNewsApplication.kt @@ -1,15 +1,31 @@ package ir.composenews import android.app.Application -import dagger.hilt.android.HiltAndroidApp +import ir.composenews.data.di.repositoryModule +import ir.composenews.marketdetail.marketDetailFeatureModule +import ir.composenews.marketlist.marketListFeatureModule import ir.composenews.sync.Sync +import org.koin.android.ext.koin.androidContext +import org.koin.android.ext.koin.androidLogger +import org.koin.core.context.startKoin +import org.koin.core.logger.Level -@HiltAndroidApp class ComposeNewsApplication : Application() { override fun onCreate() { super.onCreate() Sync.init(this) - } + startKoin { + androidContext(this@ComposeNewsApplication) + androidLogger(Level.DEBUG) + + modules( + listOf( + marketListFeatureModule, marketDetailFeatureModule, + repositoryModule, + ) + ) + } + } } \ No newline at end of file diff --git a/app/src/main/java/ir/composenews/ui/MainActivity.kt b/app/src/main/java/ir/composenews/ui/MainActivity.kt index 6a2f4e2a..a5c544d9 100644 --- a/app/src/main/java/ir/composenews/ui/MainActivity.kt +++ b/app/src/main/java/ir/composenews/ui/MainActivity.kt @@ -5,13 +5,11 @@ import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.Preview -import dagger.hilt.android.AndroidEntryPoint import ir.composenews.designsystem.theme.ComposeNewsTheme import ir.composenews.permission.enum.PermissionType import ir.composenews.permission.manager.PermissionManager import ir.composenews.permission.manager.PermissionManagerImpl -@AndroidEntryPoint class MainActivity : ComponentActivity(), PermissionManager by PermissionManagerImpl() { override fun onCreate(savedInstanceState: Bundle?) { diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts index 5c1e824b..8ddde35d 100644 --- a/build-logic/convention/build.gradle.kts +++ b/build-logic/convention/build.gradle.kts @@ -31,10 +31,9 @@ gradlePlugin { id = "composenews.android.application.compose" implementationClass = "AndroidApplicationComposeConventionPlugin" } - - register("androidHilt") { - id = "composenews.android.hilt" - implementationClass = "HiltConventionPlugin" + register("androidKoin") { + id = "composenews.android.koin" + implementationClass = "KoinConventionPlugin" } register("androidLibrary") { id = "composenews.android.library" diff --git a/build-logic/convention/src/main/kotlin/AndroidFeatureConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidFeatureConventionPlugin.kt index 44a3e2f3..db20b6ce 100644 --- a/build-logic/convention/src/main/kotlin/AndroidFeatureConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidFeatureConventionPlugin.kt @@ -21,13 +21,12 @@ class AndroidFeatureConventionPlugin : Plugin { pluginManager.apply { apply("composenews.android.library") apply("composenews.android.library.compose") - apply("composenews.android.hilt") + apply("composenews.android.koin") } } private fun Project.applyDependencies() { dependencies { - "implementation"(libs.findLibrary("hilt.navigation.compose").get()) "androidTestImplementation"(libs.findLibrary("runner").get()) "testImplementation"(project(":core:test")) diff --git a/build-logic/convention/src/main/kotlin/HiltConventionPlugin.kt b/build-logic/convention/src/main/kotlin/HiltConventionPlugin.kt deleted file mode 100644 index 7463814e..00000000 --- a/build-logic/convention/src/main/kotlin/HiltConventionPlugin.kt +++ /dev/null @@ -1,29 +0,0 @@ -import ir.composenews.libs -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.kotlin.dsl.dependencies - -class HiltConventionPlugin : Plugin { - override fun apply(project: Project) { - project.run { - applyPlugins() - applyDependencies() - } - } - - private fun Project.applyPlugins() { - pluginManager.apply { - apply("dagger.hilt.android.plugin") - apply("org.jetbrains.kotlin.kapt") -// apply("com.google.devtools.ksp") - } - } - - private fun Project.applyDependencies() { - dependencies { - "implementation"(libs.findLibrary("hilt.android").get()) -// "ksp"(libs.findLibrary("hilt.compiler").get()) - "kapt"(libs.findLibrary("hilt.compiler").get()) - } - } -} \ No newline at end of file diff --git a/build-logic/convention/src/main/kotlin/KoinConventionPlugin.kt b/build-logic/convention/src/main/kotlin/KoinConventionPlugin.kt new file mode 100644 index 00000000..d7a3645c --- /dev/null +++ b/build-logic/convention/src/main/kotlin/KoinConventionPlugin.kt @@ -0,0 +1,24 @@ +import ir.composenews.libs +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.dependencies + +class KoinConventionPlugin : Plugin { + override fun apply(target: Project) { + target.run { + applyDependencies() + } + } + + private fun Project.applyPlugins() { + pluginManager.apply { +// apply("org.jetbrains.kotlin.kapt") + } + } + + private fun Project.applyDependencies() { + dependencies { + "implementation"(libs.findBundle("koin").get()) + } + } +} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 3586ee01..c4226ecd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,10 +4,8 @@ plugins { alias(kotlin.parcelize) apply false alias(android.library) apply false alias(kotlin.android) apply false - alias(hilt.android) apply false alias(kotliner) apply false alias(detekt) apply false -// alias(ksp) apply false alias(compose) apply false } } diff --git a/core/sync/build.gradle.kts b/core/sync/build.gradle.kts index 83079d66..cf8533fb 100644 --- a/core/sync/build.gradle.kts +++ b/core/sync/build.gradle.kts @@ -1,6 +1,6 @@ plugins { id("composenews.android.library") - id("composenews.android.hilt") + id("composenews.android.koin") } android { @@ -10,7 +10,6 @@ android { dependencies { api(projects.domain.market) libs.apply { - implementation(hilt.work) implementation(startup.runtime) implementation(work.runtime.ktx) } diff --git a/core/sync/src/main/java/ir/composenews/sync/Sync.kt b/core/sync/src/main/java/ir/composenews/sync/Sync.kt index e6b79f0d..04f3273f 100644 --- a/core/sync/src/main/java/ir/composenews/sync/Sync.kt +++ b/core/sync/src/main/java/ir/composenews/sync/Sync.kt @@ -58,7 +58,6 @@ private fun Context.syncWorkNotification(): Notification { // TODO return NotificationCompat .Builder(this, SyncNotificationChannelID) -// .setSmallIcon(androidx.hilt.work.R.drawable.notification_action_background) .setContentTitle("Background tasks for Compose News") .setPriority(NotificationCompat.PRIORITY_DEFAULT) .build() diff --git a/core/sync/src/main/java/ir/composenews/sync/worker/DelegatingWorker.kt b/core/sync/src/main/java/ir/composenews/sync/worker/DelegatingWorker.kt index dbc6c575..cdec6f67 100644 --- a/core/sync/src/main/java/ir/composenews/sync/worker/DelegatingWorker.kt +++ b/core/sync/src/main/java/ir/composenews/sync/worker/DelegatingWorker.kt @@ -8,31 +8,17 @@ package ir.composenews.sync.worker import android.content.Context -import androidx.hilt.work.HiltWorkerFactory import androidx.work.CoroutineWorker import androidx.work.Data import androidx.work.ForegroundInfo import androidx.work.WorkerParameters -import dagger.hilt.EntryPoint -import dagger.hilt.InstallIn -import dagger.hilt.android.EntryPointAccessors -import dagger.hilt.components.SingletonComponent +import org.koin.core.component.KoinComponent import kotlin.reflect.KClass -/** - * An entry point to retrieve the [HiltWorkerFactory] at runtime - */ -@EntryPoint -@InstallIn(SingletonComponent::class) -interface HiltWorkerFactoryEntryPoint { - fun hiltWorkerFactory(): HiltWorkerFactory -} - private const val WORKER_CLASS_NAME = "RouterWorkerDelegateClassName" /** - * Adds metadata to a WorkRequest to identify what [CoroutineWorker] the [DelegatingWorker] should - * delegate to + * Adds metadata to a WorkRequest to identify what [CoroutineWorker] the [DelegatingWorker] should delegate to */ internal fun KClass.delegatedData() = Data.Builder() @@ -40,32 +26,25 @@ internal fun KClass.delegatedData() = .build() /** - * A worker that delegates sync to another [CoroutineWorker] constructed with a [HiltWorkerFactory]. - * - * This allows for creating and using [CoroutineWorker] instances with extended arguments - * without having to provide a custom WorkManager configuration that the app module needs to utilize. - * - * In other words, it allows for custom workers in a library module without having to own - * configuration of the WorkManager singleton. + * A worker that delegates sync to another [CoroutineWorker] constructed with Koin dependency injection. */ class DelegatingWorker( appContext: Context, workerParams: WorkerParameters, -) : CoroutineWorker(appContext, workerParams) { +) : CoroutineWorker(appContext, workerParams), KoinComponent { private val workerClassName = workerParams.inputData.getString(WORKER_CLASS_NAME).orEmpty() private val delegateWorker = try { - EntryPointAccessors.fromApplication(appContext) - .hiltWorkerFactory() - .createWorker( - appContext, - workerClassName, - workerParams, - ) as CoroutineWorker + // Dynamically create worker using Koin + val workerClass = Class.forName(workerClassName).kotlin + val worker = workerClass.constructors.first { it.parameters.size == 2 } + .call(appContext, workerParams) as CoroutineWorker + + worker } catch (e: Exception) { - throw IllegalArgumentException("Unable to find appropriate worker " + e.message) + throw IllegalArgumentException("Unable to find appropriate worker: ${e.message}") } override suspend fun getForegroundInfo(): ForegroundInfo = delegateWorker.getForegroundInfo() diff --git a/core/sync/src/main/java/ir/composenews/sync/worker/SyncWorker.kt b/core/sync/src/main/java/ir/composenews/sync/worker/SyncWorker.kt index d34aa830..3bb7b467 100644 --- a/core/sync/src/main/java/ir/composenews/sync/worker/SyncWorker.kt +++ b/core/sync/src/main/java/ir/composenews/sync/worker/SyncWorker.kt @@ -3,23 +3,19 @@ package ir.composenews.sync.worker import android.content.Context -import androidx.hilt.work.HiltWorker import androidx.work.CoroutineWorker import androidx.work.ForegroundInfo import androidx.work.OneTimeWorkRequestBuilder import androidx.work.OutOfQuotaPolicy import androidx.work.WorkerParameters -import dagger.assisted.Assisted -import dagger.assisted.AssistedInject import ir.composenews.domain.use_case.SyncMarketListUseCase import ir.composenews.sync.SyncConstraints import ir.composenews.sync.syncForegroundInfo -@HiltWorker -class SyncWorker @AssistedInject constructor( - @Assisted private val appContext: Context, - @Assisted workerParams: WorkerParameters, - private val syncMarketListUseCase: SyncMarketListUseCase, +class SyncWorker( + private val appContext: Context, + workerParams: WorkerParameters, + private val syncMarketListUseCase: SyncMarketListUseCase ) : CoroutineWorker(appContext, workerParams) { override suspend fun doWork(): Result { @@ -41,4 +37,4 @@ class SyncWorker @AssistedInject constructor( .setInputData(SyncWorker::class.delegatedData()) .build() } -} +} \ No newline at end of file diff --git a/core/test/build.gradle.kts b/core/test/build.gradle.kts index 9ba892f7..1de75d4e 100644 --- a/core/test/build.gradle.kts +++ b/core/test/build.gradle.kts @@ -1,6 +1,6 @@ plugins { id("composenews.android.library") - id("composenews.android.hilt") + id("composenews.android.koin") } android { diff --git a/core/test/src/main/java/ir/composenews/core_test/di/DispatcherModule.kt b/core/test/src/main/java/ir/composenews/core_test/di/DispatcherModule.kt index 7ac787e3..a2a4eef1 100644 --- a/core/test/src/main/java/ir/composenews/core_test/di/DispatcherModule.kt +++ b/core/test/src/main/java/ir/composenews/core_test/di/DispatcherModule.kt @@ -2,16 +2,12 @@ package ir.composenews.core_test.di -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent import ir.composenews.core_test.dispatcher.DispatcherProvider import ir.composenews.core_test.dispatcher.PlatformDispatcherProvider +import org.koin.core.module.dsl.singleOf +import org.koin.dsl.bind +import org.koin.dsl.module -@Module -@InstallIn(SingletonComponent::class) -interface DispatcherModule { - @Binds - fun bindDispatcherProvider(impl: PlatformDispatcherProvider): DispatcherProvider -} +val DispatcherModule = module { + singleOf(::PlatformDispatcherProvider).bind() +} \ No newline at end of file diff --git a/core/test/src/main/java/ir/composenews/core_test/dispatcher/PlatformDispatcherProvider.kt b/core/test/src/main/java/ir/composenews/core_test/dispatcher/PlatformDispatcherProvider.kt index 6efabe63..da2f37fc 100644 --- a/core/test/src/main/java/ir/composenews/core_test/dispatcher/PlatformDispatcherProvider.kt +++ b/core/test/src/main/java/ir/composenews/core_test/dispatcher/PlatformDispatcherProvider.kt @@ -4,9 +4,8 @@ package ir.composenews.core_test.dispatcher import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers -import javax.inject.Inject -class PlatformDispatcherProvider @Inject constructor() : DispatcherProvider { +class PlatformDispatcherProvider() : DispatcherProvider { override val ui: CoroutineDispatcher = Dispatchers.Main override val io: CoroutineDispatcher = Dispatchers.IO override val bg: CoroutineDispatcher = Dispatchers.Default diff --git a/data/market-local/build.gradle.kts b/data/market-local/build.gradle.kts index f9b60b16..a1a6d374 100644 --- a/data/market-local/build.gradle.kts +++ b/data/market-local/build.gradle.kts @@ -1,6 +1,6 @@ plugins { alias(libs.plugins.composenews.android.library) - id("composenews.android.hilt") + id("composenews.android.koin") alias(libs.plugins.sqldelight) } diff --git a/data/market-local/src/main/java/ir/composenews/localdatasource/database/MarketDaoImpl.kt b/data/market-local/src/main/java/ir/composenews/localdatasource/database/MarketDaoImpl.kt index 195aaca0..8626b84a 100644 --- a/data/market-local/src/main/java/ir/composenews/localdatasource/database/MarketDaoImpl.kt +++ b/data/market-local/src/main/java/ir/composenews/localdatasource/database/MarketDaoImpl.kt @@ -7,9 +7,8 @@ import ir.composenews.db.MarketEntity import ir.composenews.localdatasource.dto.RemoteMarketDto import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow -import javax.inject.Inject -class MarketDaoImpl @Inject constructor( +class MarketDaoImpl( db: MarketDatabase, ) : MarketDao { diff --git a/data/market-local/src/main/java/ir/composenews/localdatasource/di/LocalDatasourceModule.kt b/data/market-local/src/main/java/ir/composenews/localdatasource/di/LocalDatasourceModule.kt index 259bbbca..a502cd50 100644 --- a/data/market-local/src/main/java/ir/composenews/localdatasource/di/LocalDatasourceModule.kt +++ b/data/market-local/src/main/java/ir/composenews/localdatasource/di/LocalDatasourceModule.kt @@ -1,29 +1,27 @@ package ir.composenews.localdatasource.di -import android.content.Context import app.cash.sqldelight.db.SqlDriver import app.cash.sqldelight.driver.android.AndroidSqliteDriver -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext -import dagger.hilt.components.SingletonComponent import ir.composenews.db.MarketDatabase import ir.composenews.localdatasource.database.MarketDao import ir.composenews.localdatasource.database.MarketDaoImpl -import javax.inject.Singleton +import org.koin.android.ext.koin.androidContext +import org.koin.dsl.module -@Module -@InstallIn(SingletonComponent::class) -object LocalDatasourceModule { +val localDatasourceModule = module { + single { + AndroidSqliteDriver( + schema = MarketDatabase.Schema, + context = androidContext(), + name = "MarketDatabase" + ) + } - @Singleton - @Provides - fun provideMarketsDatabase(@ApplicationContext context: Context): MarketDatabase { - val driver: SqlDriver = AndroidSqliteDriver(MarketDatabase.Schema, context, "MarketDatabase") - return MarketDatabase(driver) + single { + MarketDatabase(driver = get()) } - @Provides - fun provideMarketsDao(dao: MarketDaoImpl): MarketDao = dao -} + single { + MarketDaoImpl(get()) + } +} \ No newline at end of file diff --git a/data/market-remote/build.gradle.kts b/data/market-remote/build.gradle.kts index deb68685..33e7ae7f 100644 --- a/data/market-remote/build.gradle.kts +++ b/data/market-remote/build.gradle.kts @@ -1,6 +1,7 @@ plugins { id("composenews.android.library") - id("composenews.android.hilt") + id("composenews.android.koin") + libs.plugins.apply { alias(kotlinx.serialization) } diff --git a/data/market-remote/src/main/java/ir/composenews/remotedatasource/api/MarketsApiImpl.kt b/data/market-remote/src/main/java/ir/composenews/remotedatasource/api/MarketsApiImpl.kt index b135443f..67b224d3 100644 --- a/data/market-remote/src/main/java/ir/composenews/remotedatasource/api/MarketsApiImpl.kt +++ b/data/market-remote/src/main/java/ir/composenews/remotedatasource/api/MarketsApiImpl.kt @@ -18,9 +18,8 @@ import ir.composenews.remotedatasource.util.HttpRoutes.SPARKLINE import ir.composenews.remotedatasource.util.HttpRoutes.VS_CURRENCY import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import javax.inject.Inject -class MarketsApiImpl @Inject constructor( +class MarketsApiImpl( private val httpClient: HttpClient, ) : MarketsApi { override suspend fun getMarkets( @@ -67,4 +66,4 @@ class MarketsApiImpl @Inject constructor( } response } -} +} \ No newline at end of file diff --git a/data/market-remote/src/main/java/ir/composenews/remotedatasource/di/ApiModule.kt b/data/market-remote/src/main/java/ir/composenews/remotedatasource/di/ApiModule.kt index 7226d17d..9eacb2b2 100644 --- a/data/market-remote/src/main/java/ir/composenews/remotedatasource/di/ApiModule.kt +++ b/data/market-remote/src/main/java/ir/composenews/remotedatasource/di/ApiModule.kt @@ -1,16 +1,11 @@ package ir.composenews.remotedatasource.di -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent import ir.composenews.remotedatasource.api.MarketsApi import ir.composenews.remotedatasource.api.MarketsApiImpl +import org.koin.core.module.dsl.singleOf +import org.koin.dsl.bind +import org.koin.dsl.module -@Module -@InstallIn(SingletonComponent::class) -abstract class ApiModule { - - @Binds - abstract fun bindMarketsApi(marketsApi: MarketsApiImpl): MarketsApi +val apiModule = module { + singleOf(::MarketsApiImpl).bind() } diff --git a/data/market-remote/src/main/java/ir/composenews/remotedatasource/di/RemoteDatasourceModule.kt b/data/market-remote/src/main/java/ir/composenews/remotedatasource/di/RemoteDatasourceModule.kt index b92f075a..123f768e 100644 --- a/data/market-remote/src/main/java/ir/composenews/remotedatasource/di/RemoteDatasourceModule.kt +++ b/data/market-remote/src/main/java/ir/composenews/remotedatasource/di/RemoteDatasourceModule.kt @@ -1,59 +1,9 @@ package ir.composenews.remotedatasource.di -import android.content.Context -import com.chuckerteam.chucker.api.ChuckerInterceptor -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext -import dagger.hilt.components.SingletonComponent -import io.ktor.client.HttpClient -import io.ktor.client.engine.okhttp.OkHttp -import io.ktor.client.plugins.contentnegotiation.ContentNegotiation -import io.ktor.client.plugins.defaultRequest -import io.ktor.client.plugins.logging.LogLevel -import io.ktor.client.plugins.logging.Logger -import io.ktor.client.plugins.logging.Logging -import io.ktor.serialization.kotlinx.json.json -import ir.composenews.remotedatasource.util.HttpRoutes -import kotlinx.serialization.json.Json +import ir.composenews.remotedatasource.okttpClient.provideHttpClient +import org.koin.dsl.module -@Module -@InstallIn(SingletonComponent::class) -object RemoteDatasourceModule { - - @Provides - fun provideHttpClient( - @ApplicationContext context: Context, - ): HttpClient { - return HttpClient(OkHttp) { - defaultRequest { - url(urlString = HttpRoutes.BASE_URL) - } - - install(Logging) { - level = LogLevel.BODY - - logger = object : Logger { - override fun log(message: String) { - println("LOG-NET: $message") - } - } - } - - install(ContentNegotiation) { - json( - Json { - prettyPrint = true - isLenient = true - ignoreUnknownKeys = true - }, - ) - } - - engine { - addInterceptor(ChuckerInterceptor.Builder(context).build()) - } - } - } +val remoteDatasourceModule = module { + single { provideHttpClient(get()) } } + diff --git a/data/market-remote/src/main/java/ir/composenews/remotedatasource/okttpClient/OkHttpClient.kt b/data/market-remote/src/main/java/ir/composenews/remotedatasource/okttpClient/OkHttpClient.kt new file mode 100644 index 00000000..fa03a8b6 --- /dev/null +++ b/data/market-remote/src/main/java/ir/composenews/remotedatasource/okttpClient/OkHttpClient.kt @@ -0,0 +1,44 @@ +package ir.composenews.remotedatasource.okttpClient + +import android.content.Context +import com.chuckerteam.chucker.api.ChuckerInterceptor +import io.ktor.client.HttpClient +import io.ktor.client.engine.okhttp.OkHttp +import io.ktor.client.plugins.contentnegotiation.ContentNegotiation +import io.ktor.client.plugins.defaultRequest +import io.ktor.client.plugins.logging.LogLevel +import io.ktor.client.plugins.logging.Logger +import io.ktor.client.plugins.logging.Logging +import io.ktor.serialization.kotlinx.json.json +import ir.composenews.remotedatasource.util.HttpRoutes +import kotlinx.serialization.json.Json + +fun provideHttpClient(context: Context) = HttpClient(OkHttp) { + defaultRequest { + url(urlString = HttpRoutes.BASE_URL) + } + + install(Logging) { + level = LogLevel.BODY + + logger = object : Logger { + override fun log(message: String) { + println("LOG-NET: $message") + } + } + } + + install(ContentNegotiation) { + json( + Json { + prettyPrint = true + isLenient = true + ignoreUnknownKeys = true + }, + ) + } + + engine { + addInterceptor(ChuckerInterceptor.Builder(context).build()) + } +} \ No newline at end of file diff --git a/data/market-repository/build.gradle.kts b/data/market-repository/build.gradle.kts index dd01e11a..edd33e65 100644 --- a/data/market-repository/build.gradle.kts +++ b/data/market-repository/build.gradle.kts @@ -1,6 +1,6 @@ plugins { id("composenews.android.library") - id("composenews.android.hilt") + id("composenews.android.koin") } android { @@ -13,8 +13,8 @@ android { dependencies { projects.apply { api(domain.market) - implementation(data.marketRemote) - implementation(data.marketLocal) + api(data.marketRemote) + api(data.marketLocal) } libs.apply { testImplementation(bundles.kotest) diff --git a/data/market-repository/src/main/java/ir/composenews/data/di/DataModule.kt b/data/market-repository/src/main/java/ir/composenews/data/di/DataModule.kt index a0984c67..6a4e55a3 100644 --- a/data/market-repository/src/main/java/ir/composenews/data/di/DataModule.kt +++ b/data/market-repository/src/main/java/ir/composenews/data/di/DataModule.kt @@ -1,18 +1,21 @@ package ir.composenews.data.di -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent +import ir.composenews.core_test.di.DispatcherModule import ir.composenews.data.repository.MarketRepositoryImpl import ir.composenews.domain.repository.MarketRepository +import ir.composenews.localdatasource.di.localDatasourceModule +import ir.composenews.remotedatasource.di.apiModule +import ir.composenews.remotedatasource.di.remoteDatasourceModule +import org.koin.core.module.dsl.singleOf +import org.koin.dsl.bind +import org.koin.dsl.module -@Module -@InstallIn(SingletonComponent::class) -interface DataModule { +val repositoryModule = module { + singleOf(::MarketRepositoryImpl).bind() - @Binds - fun bindMarketRepository( - marketsRepository: MarketRepositoryImpl, - ): MarketRepository -} + includes( + DispatcherModule, + apiModule, remoteDatasourceModule, + localDatasourceModule + ) +} \ No newline at end of file diff --git a/data/market-repository/src/main/java/ir/composenews/data/repository/MarketRepositoryImpl.kt b/data/market-repository/src/main/java/ir/composenews/data/repository/MarketRepositoryImpl.kt index fbc41205..8b679c92 100644 --- a/data/market-repository/src/main/java/ir/composenews/data/repository/MarketRepositoryImpl.kt +++ b/data/market-repository/src/main/java/ir/composenews/data/repository/MarketRepositoryImpl.kt @@ -27,9 +27,8 @@ import ir.composenews.remotedatasource.api.MarketsApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map -import javax.inject.Inject -class MarketRepositoryImpl @Inject constructor( +class MarketRepositoryImpl( private val api: MarketsApi, private val dao: MarketDao, ) : MarketRepository { diff --git a/domain/market/build.gradle.kts b/domain/market/build.gradle.kts index c04e9ed3..4a0a4526 100644 --- a/domain/market/build.gradle.kts +++ b/domain/market/build.gradle.kts @@ -1,6 +1,6 @@ plugins { id("composenews.android.library") - id("composenews.android.hilt") + id("composenews.android.koin") libs.plugins.apply { alias(kotlin.parcelize) } @@ -17,7 +17,6 @@ dependencies { api(core.network.ktor) } libs.apply { - implementation(javax.inject) implementation(coroutines) implementation(lifecycle.viewmodel.ktx) api(kotlinx.collections.immutable) diff --git a/domain/market/src/main/java/ir/composenews/domain/domainModule.kt b/domain/market/src/main/java/ir/composenews/domain/domainModule.kt new file mode 100644 index 00000000..9abcfdd6 --- /dev/null +++ b/domain/market/src/main/java/ir/composenews/domain/domainModule.kt @@ -0,0 +1,20 @@ +package ir.composenews.domain + +import ir.composenews.domain.use_case.GetFavoriteMarketListUseCase +import ir.composenews.domain.use_case.GetMarketChartUseCase +import ir.composenews.domain.use_case.GetMarketDetailUseCase +import ir.composenews.domain.use_case.GetMarketListUseCase +import ir.composenews.domain.use_case.SyncMarketListUseCase +import ir.composenews.domain.use_case.ToggleFavoriteMarketListUseCase +import org.koin.core.module.dsl.factoryOf +import org.koin.dsl.module + +val domainModule = module { + + factoryOf(::GetFavoriteMarketListUseCase) + factoryOf(::GetMarketChartUseCase) + factoryOf(::GetMarketDetailUseCase) + factoryOf(::GetMarketListUseCase) + factoryOf(::SyncMarketListUseCase) + factoryOf(::ToggleFavoriteMarketListUseCase) +} \ No newline at end of file diff --git a/domain/market/src/main/java/ir/composenews/domain/use_case/GetFavoriteMarketListUseCase.kt b/domain/market/src/main/java/ir/composenews/domain/use_case/GetFavoriteMarketListUseCase.kt index e81b6d2a..53d9fc9f 100644 --- a/domain/market/src/main/java/ir/composenews/domain/use_case/GetFavoriteMarketListUseCase.kt +++ b/domain/market/src/main/java/ir/composenews/domain/use_case/GetFavoriteMarketListUseCase.kt @@ -5,9 +5,8 @@ package ir.composenews.domain.use_case import ir.composenews.domain.model.Market import ir.composenews.domain.repository.MarketRepository import kotlinx.coroutines.flow.Flow -import javax.inject.Inject -class GetFavoriteMarketListUseCase @Inject constructor( +class GetFavoriteMarketListUseCase( private val repository: MarketRepository, ) { operator fun invoke(): Flow> = repository.getFavoriteMarketList() diff --git a/domain/market/src/main/java/ir/composenews/domain/use_case/GetMarketChartUseCase.kt b/domain/market/src/main/java/ir/composenews/domain/use_case/GetMarketChartUseCase.kt index 0f4b1da3..d4911881 100644 --- a/domain/market/src/main/java/ir/composenews/domain/use_case/GetMarketChartUseCase.kt +++ b/domain/market/src/main/java/ir/composenews/domain/use_case/GetMarketChartUseCase.kt @@ -7,9 +7,8 @@ import ir.composenews.domain.repository.MarketRepository import ir.composenews.network.Errors import ir.composenews.network.Resource import kotlinx.coroutines.flow.Flow -import javax.inject.Inject -open class GetMarketChartUseCase @Inject constructor( +open class GetMarketChartUseCase( private val repository: MarketRepository, ) { open operator fun invoke(id: String): Flow> = diff --git a/domain/market/src/main/java/ir/composenews/domain/use_case/GetMarketDetailUseCase.kt b/domain/market/src/main/java/ir/composenews/domain/use_case/GetMarketDetailUseCase.kt index 6a10d9f2..0ebf8a5d 100644 --- a/domain/market/src/main/java/ir/composenews/domain/use_case/GetMarketDetailUseCase.kt +++ b/domain/market/src/main/java/ir/composenews/domain/use_case/GetMarketDetailUseCase.kt @@ -7,9 +7,8 @@ import ir.composenews.domain.repository.MarketRepository import ir.composenews.network.Errors import ir.composenews.network.Resource import kotlinx.coroutines.flow.Flow -import javax.inject.Inject -open class GetMarketDetailUseCase @Inject constructor( +open class GetMarketDetailUseCase( private val repository: MarketRepository, ) { open operator fun invoke(id: String): Flow> = repository.fetchDetail(id = id) diff --git a/domain/market/src/main/java/ir/composenews/domain/use_case/GetMarketListUseCase.kt b/domain/market/src/main/java/ir/composenews/domain/use_case/GetMarketListUseCase.kt index 86c63cff..7e5eb9c0 100644 --- a/domain/market/src/main/java/ir/composenews/domain/use_case/GetMarketListUseCase.kt +++ b/domain/market/src/main/java/ir/composenews/domain/use_case/GetMarketListUseCase.kt @@ -5,9 +5,8 @@ package ir.composenews.domain.use_case import ir.composenews.domain.model.Market import ir.composenews.domain.repository.MarketRepository import kotlinx.coroutines.flow.Flow -import javax.inject.Inject -class GetMarketListUseCase @Inject constructor( +class GetMarketListUseCase( private val repository: MarketRepository, ) { suspend operator fun invoke(): Flow> { diff --git a/domain/market/src/main/java/ir/composenews/domain/use_case/SyncMarketListUseCase.kt b/domain/market/src/main/java/ir/composenews/domain/use_case/SyncMarketListUseCase.kt index 412bbeff..b8b59750 100644 --- a/domain/market/src/main/java/ir/composenews/domain/use_case/SyncMarketListUseCase.kt +++ b/domain/market/src/main/java/ir/composenews/domain/use_case/SyncMarketListUseCase.kt @@ -3,9 +3,8 @@ package ir.composenews.domain.use_case import ir.composenews.domain.repository.MarketRepository -import javax.inject.Inject -class SyncMarketListUseCase @Inject constructor( +class SyncMarketListUseCase( private val repository: MarketRepository, ) { suspend operator fun invoke() = repository.syncMarketList() diff --git a/domain/market/src/main/java/ir/composenews/domain/use_case/ToggleFavoriteMarketListUseCase.kt b/domain/market/src/main/java/ir/composenews/domain/use_case/ToggleFavoriteMarketListUseCase.kt index 98d42bfa..a073ef0c 100644 --- a/domain/market/src/main/java/ir/composenews/domain/use_case/ToggleFavoriteMarketListUseCase.kt +++ b/domain/market/src/main/java/ir/composenews/domain/use_case/ToggleFavoriteMarketListUseCase.kt @@ -4,9 +4,8 @@ package ir.composenews.domain.use_case import ir.composenews.domain.model.Market import ir.composenews.domain.repository.MarketRepository -import javax.inject.Inject -open class ToggleFavoriteMarketListUseCase @Inject constructor( +open class ToggleFavoriteMarketListUseCase( private val repository: MarketRepository, ) { open suspend operator fun invoke(news: Market) = repository.toggleFavoriteMarket(news) diff --git a/feature/marketdetail/build.gradle.kts b/feature/marketdetail/build.gradle.kts index 2c43f514..d844357a 100644 --- a/feature/marketdetail/build.gradle.kts +++ b/feature/marketdetail/build.gradle.kts @@ -14,7 +14,7 @@ configurations.all { dependencies { projects.apply { - implementation(data.marketRepository) + api(data.marketRepository) implementation(core.uimarket) } libs.apply { diff --git a/feature/marketdetail/src/main/java/ir/composenews/marketdetail/MarketDetailModule.kt b/feature/marketdetail/src/main/java/ir/composenews/marketdetail/MarketDetailModule.kt new file mode 100644 index 00000000..9bd56d41 --- /dev/null +++ b/feature/marketdetail/src/main/java/ir/composenews/marketdetail/MarketDetailModule.kt @@ -0,0 +1,15 @@ +package ir.composenews.marketdetail + +import ir.composenews.domain.domainModule +import org.koin.androidx.viewmodel.dsl.viewModel +import org.koin.dsl.module + +val marketDetailFeatureModule = module { + viewModel { + MarketDetailViewModel( + get(), get(), get(), get() + ) + } + + includes(domainModule) +} \ No newline at end of file diff --git a/feature/marketdetail/src/main/java/ir/composenews/marketdetail/MarketDetailScreen.kt b/feature/marketdetail/src/main/java/ir/composenews/marketdetail/MarketDetailScreen.kt index aa874921..8a9dd397 100644 --- a/feature/marketdetail/src/main/java/ir/composenews/marketdetail/MarketDetailScreen.kt +++ b/feature/marketdetail/src/main/java/ir/composenews/marketdetail/MarketDetailScreen.kt @@ -27,7 +27,6 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel import coil.compose.rememberAsyncImagePainter import ir.composenews.base.BaseRoute import ir.composenews.base.use @@ -38,11 +37,12 @@ import ir.composenews.designsystem.theme.ComposeNewsTheme import ir.composenews.marketdetail.MarketDetailContract.State import ir.composenews.marketdetail.preview_provider.MarketDetailStateProvider import ir.composenews.uimarket.model.MarketModel +import org.koin.androidx.compose.koinViewModel @Composable fun MarketDetailRoute( market: MarketModel?, - viewModel: MarketDetailViewModel = hiltViewModel(), + viewModel: MarketDetailViewModel = koinViewModel(), ) { val (state, event) = use(viewModel = viewModel) LaunchedEffect(key1 = market) { diff --git a/feature/marketdetail/src/main/java/ir/composenews/marketdetail/MarketDetailViewModel.kt b/feature/marketdetail/src/main/java/ir/composenews/marketdetail/MarketDetailViewModel.kt index b3c3f7d5..b13e5bc0 100644 --- a/feature/marketdetail/src/main/java/ir/composenews/marketdetail/MarketDetailViewModel.kt +++ b/feature/marketdetail/src/main/java/ir/composenews/marketdetail/MarketDetailViewModel.kt @@ -3,7 +3,6 @@ package ir.composenews.marketdetail import androidx.lifecycle.viewModelScope -import dagger.hilt.android.lifecycle.HiltViewModel import ir.composenews.base.BaseContract import ir.composenews.base.BaseViewModel import ir.composenews.core_test.dispatcher.DispatcherProvider @@ -22,10 +21,10 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch -import javax.inject.Inject +import org.koin.android.annotation.KoinViewModel -@HiltViewModel -class MarketDetailViewModel @Inject constructor( +@KoinViewModel +class MarketDetailViewModel( private val getMarketChartUseCase: GetMarketChartUseCase, private val getMarketDetailUseCase: GetMarketDetailUseCase, private val toggleFavoriteMarketListUseCase: ToggleFavoriteMarketListUseCase, diff --git a/feature/marketlist/build.gradle.kts b/feature/marketlist/build.gradle.kts index cb61c56e..d0b7114b 100644 --- a/feature/marketlist/build.gradle.kts +++ b/feature/marketlist/build.gradle.kts @@ -14,7 +14,7 @@ configurations.all { dependencies { projects.apply { - implementation(data.marketRepository) + api(data.marketRepository) implementation(core.uimarket) implementation(core.extensions) } diff --git a/feature/marketlist/src/main/java/ir/composenews/marketlist/MarketListScreen.kt b/feature/marketlist/src/main/java/ir/composenews/marketlist/MarketListScreen.kt index 35cad8a1..170b545c 100644 --- a/feature/marketlist/src/main/java/ir/composenews/marketlist/MarketListScreen.kt +++ b/feature/marketlist/src/main/java/ir/composenews/marketlist/MarketListScreen.kt @@ -18,7 +18,6 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.PreviewParameter -import androidx.hilt.navigation.compose.hiltViewModel import com.airbnb.lottie.compose.LottieCompositionSpec import ir.composenews.base.BaseRoute import ir.composenews.base.use @@ -33,13 +32,14 @@ import ir.composenews.designsystem.theme.ComposeNewsTheme import ir.composenews.marketlist.component.MarketListItem import ir.composenews.marketlist.preview_provider.MarketListStateProvider import ir.composenews.uimarket.model.MarketModel +import org.koin.androidx.compose.koinViewModel /** * LongParameterList - > compose unimited */ @Composable fun MarketListRoute( - viewModel: MarketListViewModel = hiltViewModel(), + viewModel: MarketListViewModel = koinViewModel(), showFavoriteList: Boolean = false, onNavigateToDetailScreen: (market: MarketModel) -> Unit, ) { diff --git a/feature/marketlist/src/main/java/ir/composenews/marketlist/MarketListViewModel.kt b/feature/marketlist/src/main/java/ir/composenews/marketlist/MarketListViewModel.kt index 8198cfb4..29ba0972 100644 --- a/feature/marketlist/src/main/java/ir/composenews/marketlist/MarketListViewModel.kt +++ b/feature/marketlist/src/main/java/ir/composenews/marketlist/MarketListViewModel.kt @@ -3,7 +3,6 @@ package ir.composenews.marketlist import androidx.lifecycle.viewModelScope -import dagger.hilt.android.lifecycle.HiltViewModel import ir.composenews.base.BaseContract import ir.composenews.base.BaseViewModel import ir.composenews.core_test.dispatcher.DispatcherProvider @@ -23,10 +22,10 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch -import javax.inject.Inject +import org.koin.android.annotation.KoinViewModel -@HiltViewModel -class MarketListViewModel @Inject constructor( +@KoinViewModel +class MarketListViewModel( private val getMarketListUseCase: GetMarketListUseCase, private val getFavoriteMarketListUseCase: GetFavoriteMarketListUseCase, private val toggleFavoriteMarketListUseCase: ToggleFavoriteMarketListUseCase, diff --git a/feature/marketlist/src/main/java/ir/composenews/marketlist/marketListModule.kt b/feature/marketlist/src/main/java/ir/composenews/marketlist/marketListModule.kt new file mode 100644 index 00000000..8870ece9 --- /dev/null +++ b/feature/marketlist/src/main/java/ir/composenews/marketlist/marketListModule.kt @@ -0,0 +1,14 @@ +package ir.composenews.marketlist + +import ir.composenews.domain.domainModule +import org.koin.androidx.viewmodel.dsl.viewModel +import org.koin.dsl.module + +val marketListFeatureModule = module { + viewModel { + MarketListViewModel( + get(), get(), get(), get() + ) + } + includes(domainModule) +} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2cbe0d2c..a280823b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -25,10 +25,6 @@ wearToolingPreview = "1.0.0" horologistComposeLayout = "0.6.17" detekt = "1.23.2" -hilt = "2.52" -androidHiltCompiler = "1.2.0" -hiltNavigationCompose = "1.2.0" -hiltWork = "1.2.0" javaxInject = "1" lottieAnimation = "6.3.0" @@ -68,6 +64,9 @@ konsist = "0.16.1" kotest = "5.7.2" espressoCore = "3.6.1" +koin = "3.5.6" +koin-annotations = "1.3.1" + [libraries] androidx-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "ktx" } @@ -88,13 +87,6 @@ compose-foundation-wear = { group = "androidx.wear.compose", name = "compose-fou compose-ui-preview-wear = { group = "androidx.wear", name = "wear-tooling-preview", version.ref = "wearToolingPreview" } compose-horologist-layout = { module = "com.google.android.horologist:horologist-compose-layout", version.ref = "horologistComposeLayout" } -hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" } -hilt-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" } -hilt-ext-compiler = { group = "androidx.hilt", name = "hilt-compiler", version.ref = "androidHiltCompiler" } -hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hiltNavigationCompose" } -hilt-work = { group = "androidx.hilt", name = "hilt-work", version.ref = "hiltWork" } -javax-inject = { group = "javax.inject", name = "javax.inject", version.ref = "javaxInject" } - coroutines = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core-jvm", version.ref = "coroutinesCore" } lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifeCycle" } @@ -153,11 +145,18 @@ kotest-property = { module = "io.kotest:kotest-property", version.ref = "kotest" kotest-runnerJUnit5 = { module = "io.kotest:kotest-runner-junit5", version.ref = "kotest" } espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } +# koin +koin-core = { group = "io.insert-koin", name = "koin-core", version.ref = "koin" } +koin-android = { group = "io.insert-koin", name = "koin-android", version.ref = "koin" } +koin-compose = { group = "io.insert-koin", name = "koin-androidx-compose", version.ref = "koin" } +koin-annotations = { group = "io.insert-koin", name = "koin-annotations", version.ref = "koin-annotations" } +koin-viewmodel = { group = "io.insert-koin", name = "koin-androidx-viewmodel", version.ref = "koin" } +koin-compiler = { group = "io.insert-koin", name = "koin-compiler", version.ref = "koin" } + [plugins] android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } -hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } #ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } kotlinx-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } @@ -186,4 +185,10 @@ ktor = [ "ktor-contentNegotiation", "ktor-json", "ktor-logging" +] +koin = [ + "koin-core", + "koin-android", + "koin-compose", + "koin-annotations", ] \ No newline at end of file diff --git a/library/navigation/build.gradle.kts b/library/navigation/build.gradle.kts index 78d75caf..1f2f9940 100644 --- a/library/navigation/build.gradle.kts +++ b/library/navigation/build.gradle.kts @@ -9,8 +9,8 @@ android { dependencies { projects.apply { - implementation(feature.marketlist) - implementation(feature.marketdetail) + api(feature.marketlist) + api(feature.marketdetail) implementation(core.uimarket) implementation(domain.market) }