From c23df0b25f0be1bdd76bc6fc6342f7ac9bb79b06 Mon Sep 17 00:00:00 2001 From: Gabriel Moro Date: Wed, 6 May 2026 15:58:38 -0300 Subject: [PATCH 1/6] Refactor dependency injection to use Koin annotations and centralize module loading - Convert `ProfilePickerStreamModule` from a DSL-based module to an annotation-based `@Module` using `@ComponentScan`. - Annotate `ProfilePickerStreamViewModel`, `UseCase`, `Repository`, and `Service` with `@KoinViewModel` and `@Factory`. - Add `com.streamplayer.koin-annotations-setup` plugin to the `feature-profile` build script. - Centralize the initialization of `SearchModule` and `ProfilePickerStreamModule` within the main `AppModule`. - Remove manual `rememberKoinModules` loading from `ProfilePickerStreamNavigation` and `SearchStreamNavigation`. --- .../di/AppModule.kt | 5 +++ feature-profile/build.gradle.kts | 1 + .../data/ProfilePickerStreamRepository.kt | 2 + .../data/ProfilePickerStreamService.kt | 5 ++- .../profile/di/ProfilePickerStreamModule.kt | 41 +++---------------- .../domain/ProfilePickerStreamUseCase.kt | 2 + .../ProfilePickerStreamNavigation.kt | 5 --- .../screens/ProfilePickerStreamViewModel.kt | 2 + .../navigation/SearchStreamNavigation.kt | 8 ---- 9 files changed, 21 insertions(+), 50 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/com.codandotv.streamplayerapp/di/AppModule.kt b/composeApp/src/commonMain/kotlin/com.codandotv.streamplayerapp/di/AppModule.kt index 5da57d51..ae959490 100644 --- a/composeApp/src/commonMain/kotlin/com.codandotv.streamplayerapp/di/AppModule.kt +++ b/composeApp/src/commonMain/kotlin/com.codandotv.streamplayerapp/di/AppModule.kt @@ -5,6 +5,9 @@ import com.codandotv.streamplayerapp.core_local_storage.di.LocalStorageModule import com.codandotv.streamplayerapp.core_networking.di.NetworkModule import com.codandotv.streamplayerapp.core_shared.qualifier.QualifierDispatcherIO import com.codandotv.streamplayerapp.feature_list_streams.list.di.ListStreamModule +import com.codandotv.streamplayerapp.feature_search.di.SearchModule +import com.codandotv.streamplayerapp.feature_search.presentation.widgets.StreamsError +import com.codandotv.streamplayerapp.profile.di.ProfilePickerStreamModule import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.IO import org.koin.core.KoinApplication @@ -21,6 +24,8 @@ fun streamPlayerApplication(platformBlock: KoinApplication.() -> Unit): KoinAppl LocalStorageModule.module, SyncModule.module, ListStreamModule.module, + SearchModule().module, + ProfilePickerStreamModule().module ) } } diff --git a/feature-profile/build.gradle.kts b/feature-profile/build.gradle.kts index 59bc51e2..36b4c3b0 100644 --- a/feature-profile/build.gradle.kts +++ b/feature-profile/build.gradle.kts @@ -4,6 +4,7 @@ plugins { id("com.streamplayer.kmp-library") alias(libs.plugins.jetbrains.compose) alias(libs.plugins.compose.compiler) + id("com.streamplayer.koin-annotations-setup") } kotlin { diff --git a/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/data/ProfilePickerStreamRepository.kt b/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/data/ProfilePickerStreamRepository.kt index 793670c5..827f6151 100644 --- a/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/data/ProfilePickerStreamRepository.kt +++ b/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/data/ProfilePickerStreamRepository.kt @@ -7,11 +7,13 @@ import com.codandotv.streamplayerapp.profile.domain.toProfiles import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map +import org.koin.core.annotation.Factory interface ProfilePickerStreamRepository { suspend fun getProfiles(): Flow> } +@Factory class ProfilePickerStreamRepositoryImpl( private val service: ProfilePickerStreamService ) : ProfilePickerStreamRepository { diff --git a/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/data/ProfilePickerStreamService.kt b/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/data/ProfilePickerStreamService.kt index e071ddf2..f1d6ca32 100644 --- a/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/data/ProfilePickerStreamService.kt +++ b/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/data/ProfilePickerStreamService.kt @@ -5,13 +5,16 @@ import com.codandotv.streamplayerapp.core_networking.handleError.safeRequest import com.codandotv.streamplayerapp.profile.data.model.ProfilesResponse import io.ktor.client.HttpClient import io.ktor.client.request.url +import org.koin.core.annotation.Factory +import org.koin.core.annotation.Provided interface ProfilePickerStreamService { suspend fun getProfiles(): NetworkResponse } +@Factory class ProfilePickerStreamServiceImpl( - private val client: HttpClient + @Provided private val client: HttpClient ) : ProfilePickerStreamService { override suspend fun getProfiles(): NetworkResponse = client.safeRequest { diff --git a/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/di/ProfilePickerStreamModule.kt b/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/di/ProfilePickerStreamModule.kt index 76e222d8..400f7936 100644 --- a/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/di/ProfilePickerStreamModule.kt +++ b/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/di/ProfilePickerStreamModule.kt @@ -1,39 +1,8 @@ package com.codandotv.streamplayerapp.profile.di -import com.codandotv.streamplayerapp.profile.data.ProfilePickerStreamRepository -import com.codandotv.streamplayerapp.profile.data.ProfilePickerStreamRepositoryImpl -import com.codandotv.streamplayerapp.profile.data.ProfilePickerStreamService -import com.codandotv.streamplayerapp.profile.data.ProfilePickerStreamServiceImpl -import com.codandotv.streamplayerapp.profile.domain.ProfilePickerStreamUseCase -import com.codandotv.streamplayerapp.profile.domain.ProfilePickerStreamUseCaseImpl -import com.codandotv.streamplayerapp.profile.presentation.screens.ProfilePickerStreamViewModel -import org.koin.core.module.dsl.viewModel -import org.koin.dsl.module +import org.koin.core.annotation.ComponentScan +import org.koin.core.annotation.Module -object ProfilePickerStreamModule { - val module = module { - viewModel { - ProfilePickerStreamViewModel( - useCase = get() - ) - } - - factory { - ProfilePickerStreamUseCaseImpl( - profilePickerStreamRepository = get() - ) - } - - factory { - ProfilePickerStreamRepositoryImpl( - service = get() - ) - } - - factory { - ProfilePickerStreamServiceImpl( - client = get() - ) - } - } -} +@Module +@ComponentScan("com.codandotv.streamplayerapp.profile") +class ProfilePickerStreamModule \ No newline at end of file diff --git a/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/domain/ProfilePickerStreamUseCase.kt b/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/domain/ProfilePickerStreamUseCase.kt index abf1a4a6..490d855b 100644 --- a/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/domain/ProfilePickerStreamUseCase.kt +++ b/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/domain/ProfilePickerStreamUseCase.kt @@ -3,6 +3,7 @@ package com.codandotv.streamplayerapp.profile.domain import com.codandotv.streamplayerapp.profile.data.ProfilePickerStreamRepository import kotlinx.coroutines.flow.Flow +import org.koin.core.annotation.Factory interface ProfilePickerStreamUseCase { suspend fun getProfile(): Flow> @@ -21,6 +22,7 @@ interface ProfilePickerStreamUseCase { ): Pair } +@Factory class ProfilePickerStreamUseCaseImpl( private val profilePickerStreamRepository: ProfilePickerStreamRepository ) : ProfilePickerStreamUseCase { diff --git a/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/presentation/navigation/ProfilePickerStreamNavigation.kt b/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/presentation/navigation/ProfilePickerStreamNavigation.kt index eb885448..a50acfc5 100644 --- a/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/presentation/navigation/ProfilePickerStreamNavigation.kt +++ b/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/presentation/navigation/ProfilePickerStreamNavigation.kt @@ -6,17 +6,12 @@ import androidx.navigation.compose.composable import com.codandotv.streamplayerapp.core_navigation.routes.BottomNavRoutes.HOME import com.codandotv.streamplayerapp.core_navigation.routes.BottomNavRoutes.PARAM.PROFILE_ID import com.codandotv.streamplayerapp.core_navigation.routes.Routes -import com.codandotv.streamplayerapp.profile.di.ProfilePickerStreamModule import com.codandotv.streamplayerapp.profile.presentation.screens.ProfilePickerStreamScreen -import org.koin.compose.module.rememberKoinModules import org.koin.core.annotation.KoinExperimentalAPI @OptIn(KoinExperimentalAPI::class) fun NavGraphBuilder.profilePickerStreamNavGraph(navController: NavHostController) { composable(Routes.PROFILE_PICKER) { - rememberKoinModules { - listOf(ProfilePickerStreamModule.module) - } ProfilePickerStreamScreen( onNavigateListStreams = { profilePic -> navController.navigate("$HOME?$PROFILE_ID=$profilePic") diff --git a/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/presentation/screens/ProfilePickerStreamViewModel.kt b/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/presentation/screens/ProfilePickerStreamViewModel.kt index 1eac734f..2dc3c90f 100644 --- a/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/presentation/screens/ProfilePickerStreamViewModel.kt +++ b/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/presentation/screens/ProfilePickerStreamViewModel.kt @@ -11,7 +11,9 @@ import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import org.koin.android.annotation.KoinViewModel +@KoinViewModel class ProfilePickerStreamViewModel( private val useCase: ProfilePickerStreamUseCase, ) : ViewModel() { diff --git a/feature-search/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_search/presentation/navigation/SearchStreamNavigation.kt b/feature-search/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_search/presentation/navigation/SearchStreamNavigation.kt index a46a09fd..bddaadad 100644 --- a/feature-search/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_search/presentation/navigation/SearchStreamNavigation.kt +++ b/feature-search/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_search/presentation/navigation/SearchStreamNavigation.kt @@ -4,20 +4,12 @@ import androidx.navigation.NavGraphBuilder import androidx.navigation.NavHostController import androidx.navigation.compose.composable import com.codandotv.streamplayerapp.core_navigation.routes.Routes -import com.codandotv.streamplayerapp.feature_search.di.SearchModule import com.codandotv.streamplayerapp.feature_search.presentation.screens.SearchScreen -import org.koin.compose.module.rememberKoinModules import org.koin.core.annotation.KoinExperimentalAPI -import org.koin.ksp.generated.module @OptIn(KoinExperimentalAPI::class) fun NavGraphBuilder.searchStreamsNavGraph(navController: NavHostController) { composable(Routes.SEARCH) { _ -> - rememberKoinModules { - listOf( - SearchModule().module - ) - } SearchScreen( navController = navController, onNavigateDetailList = { id -> From e3aee81a171b694dab92e731c8c7cbf5b718ea51 Mon Sep 17 00:00:00 2001 From: Gabriel Moro Date: Wed, 6 May 2026 16:28:48 -0300 Subject: [PATCH 2/6] Refactor News feature dependency injection to use Koin Annotations - Migrate `NewsScreenModule` from manual DSL to Koin Annotations using `@Module` and `@ComponentScan`. - Update `NewsScreenViewModel` with `@KoinViewModel` and `@Provided` annotations for automated dependency injection. - Centralize DI configuration by moving `NewsScreenModule` and `PermissionsModule` initialization into the global `AppModule`. - Remove on-demand module loading (`rememberKoinModules`) from `NewsNavigation`. - Apply `com.streamplayer.koin-annotations-setup` plugin to the `feature-news` module. - Organize `AppModule` with regions to better categorize shared and feature-specific modules. --- .../com.codandotv.streamplayerapp/di/AppModule.kt | 12 +++++++++++- feature-news/build.gradle.kts | 1 + .../feature_news/di/NewsScreenModule.kt | 15 +++++---------- .../presentation/NewsScreenViewModel.kt | 5 ++++- .../presentation/navigation/NewsNavigation.kt | 7 ------- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/com.codandotv.streamplayerapp/di/AppModule.kt b/composeApp/src/commonMain/kotlin/com.codandotv.streamplayerapp/di/AppModule.kt index ae959490..7258d159 100644 --- a/composeApp/src/commonMain/kotlin/com.codandotv.streamplayerapp/di/AppModule.kt +++ b/composeApp/src/commonMain/kotlin/com.codandotv.streamplayerapp/di/AppModule.kt @@ -5,6 +5,7 @@ import com.codandotv.streamplayerapp.core_local_storage.di.LocalStorageModule import com.codandotv.streamplayerapp.core_networking.di.NetworkModule import com.codandotv.streamplayerapp.core_shared.qualifier.QualifierDispatcherIO import com.codandotv.streamplayerapp.feature_list_streams.list.di.ListStreamModule +import com.codandotv.streamplayerapp.feature_news.di.NewsScreenModule import com.codandotv.streamplayerapp.feature_search.di.SearchModule import com.codandotv.streamplayerapp.feature_search.presentation.widgets.StreamsError import com.codandotv.streamplayerapp.profile.di.ProfilePickerStreamModule @@ -19,13 +20,22 @@ fun streamPlayerApplication(platformBlock: KoinApplication.() -> Unit): KoinAppl return startKoin { platformBlock() modules( - module { single(QualifierDispatcherIO) { Dispatchers.IO } }, + module { + single(QualifierDispatcherIO) { + Dispatchers.IO + } + }, NetworkModule().module, LocalStorageModule.module, SyncModule.module, + PermissionsModule.module, + + // region feature_modules ListStreamModule.module, SearchModule().module, + NewsScreenModule().module, ProfilePickerStreamModule().module + // endregion ) } } diff --git a/feature-news/build.gradle.kts b/feature-news/build.gradle.kts index a3f9747e..733114e7 100644 --- a/feature-news/build.gradle.kts +++ b/feature-news/build.gradle.kts @@ -4,6 +4,7 @@ plugins { id("com.streamplayer.kmp-library") alias(libs.plugins.jetbrains.compose) alias(libs.plugins.compose.compiler) + id("com.streamplayer.koin-annotations-setup") } kotlin { diff --git a/feature-news/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_news/di/NewsScreenModule.kt b/feature-news/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_news/di/NewsScreenModule.kt index bbc52bfe..0b1ab285 100644 --- a/feature-news/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_news/di/NewsScreenModule.kt +++ b/feature-news/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_news/di/NewsScreenModule.kt @@ -1,13 +1,8 @@ package com.codandotv.streamplayerapp.feature_news.di -import com.codandotv.streamplayerapp.feature_news.presentation.NewsScreenViewModel -import org.koin.core.module.dsl.viewModel -import org.koin.dsl.module +import org.koin.core.annotation.ComponentScan +import org.koin.core.annotation.Module -object NewsScreenModule { - val module = module { - viewModel { - NewsScreenViewModel( permissionsManager = get()) - } - } -} +@Module +@ComponentScan("com.codandotv.streamplayerapp.feature_news") +class NewsScreenModule diff --git a/feature-news/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_news/presentation/NewsScreenViewModel.kt b/feature-news/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_news/presentation/NewsScreenViewModel.kt index 6188c6d2..005fe60d 100644 --- a/feature-news/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_news/presentation/NewsScreenViewModel.kt +++ b/feature-news/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_news/presentation/NewsScreenViewModel.kt @@ -13,6 +13,8 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import org.koin.android.annotation.KoinViewModel +import org.koin.core.annotation.Provided data class NewsScreenUiState( val showPermissionDialog: Boolean = false, @@ -23,8 +25,9 @@ sealed class NewsScreenActionTakeImage { data object Gallery : NewsScreenActionTakeImage() } +@KoinViewModel class NewsScreenViewModel( - val permissionsManager: PermissionsManager + @Provided val permissionsManager: PermissionsManager ) : ViewModel() { private val _actionTakeImage = MutableSharedFlow() val actionTakeImage: SharedFlow = _actionTakeImage diff --git a/feature-news/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_news/presentation/navigation/NewsNavigation.kt b/feature-news/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_news/presentation/navigation/NewsNavigation.kt index 7641657b..56ada54d 100644 --- a/feature-news/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_news/presentation/navigation/NewsNavigation.kt +++ b/feature-news/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_news/presentation/navigation/NewsNavigation.kt @@ -4,19 +4,12 @@ import androidx.navigation.NavGraphBuilder import androidx.navigation.NavHostController import androidx.navigation.compose.composable import com.codandotv.streamplayerapp.core_navigation.routes.BottomNavRoutes -import com.codandotv.streamplayerapp.core_navigation.routes.Routes.DETAIL_COMPLETE -import com.codandotv.streamplayerapp.feature_news.di.NewsScreenModule -import com.codandotv.streamplayerapp.feature_news.presentation.screens.NewsScreen import com.codandotv.streamplayerapp.feature_news.presentation.screens.NewsScreenContent -import org.koin.compose.module.rememberKoinModules import org.koin.core.annotation.KoinExperimentalAPI @OptIn(KoinExperimentalAPI::class) fun NavGraphBuilder.newsStreamNavGraph(navController: NavHostController) { composable(BottomNavRoutes.NEWS) { _ -> - rememberKoinModules { - listOf(NewsScreenModule.module,PermissionsModule.module) - } NewsScreenContent(navController) } } From 67a617f16138f3158d48f9787ecd749f721f23c7 Mon Sep 17 00:00:00 2001 From: Gabriel Moro Date: Wed, 6 May 2026 17:17:55 -0300 Subject: [PATCH 3/6] Refactor Koin initialization to support lazy modules and coroutines - Add `koin-core-coroutines` dependency to `libs.versions.toml`, `composeApp`, and `core-permission` modules. - Convert `PermissionsModule` from a standard Koin module to a `lazyModule`. - Update `AppModule` to load `PermissionsModule` using the `lazyModules` configuration. - Fix minor whitespace formatting in `libs.versions.toml`. --- composeApp/build.gradle.kts | 1 + .../com.codandotv.streamplayerapp/di/AppModule.kt | 4 +++- core-permission/build.gradle.kts | 1 + .../core_permission/di/PermissionsModule.kt | 4 ++-- gradle/libs.versions.toml | 15 ++++++++------- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts index 9bc52423..938730cb 100644 --- a/composeApp/build.gradle.kts +++ b/composeApp/build.gradle.kts @@ -33,6 +33,7 @@ kotlin { implementation(libs.bundles.compose) implementation(libs.koin.core) + implementation(libs.koin.core.coroutines) api(libs.kmpnotifier) implementation(libs.kotzilla.sdk.compose) diff --git a/composeApp/src/commonMain/kotlin/com.codandotv.streamplayerapp/di/AppModule.kt b/composeApp/src/commonMain/kotlin/com.codandotv.streamplayerapp/di/AppModule.kt index 7258d159..7fec5ce7 100644 --- a/composeApp/src/commonMain/kotlin/com.codandotv.streamplayerapp/di/AppModule.kt +++ b/composeApp/src/commonMain/kotlin/com.codandotv.streamplayerapp/di/AppModule.kt @@ -13,12 +13,15 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.IO import org.koin.core.KoinApplication import org.koin.core.context.startKoin +import org.koin.core.lazyModules import org.koin.dsl.module import org.koin.ksp.generated.module fun streamPlayerApplication(platformBlock: KoinApplication.() -> Unit): KoinApplication { return startKoin { platformBlock() + lazyModules(PermissionsModule.module) + modules( module { single(QualifierDispatcherIO) { @@ -28,7 +31,6 @@ fun streamPlayerApplication(platformBlock: KoinApplication.() -> Unit): KoinAppl NetworkModule().module, LocalStorageModule.module, SyncModule.module, - PermissionsModule.module, // region feature_modules ListStreamModule.module, diff --git a/core-permission/build.gradle.kts b/core-permission/build.gradle.kts index c20e96af..ba47d694 100644 --- a/core-permission/build.gradle.kts +++ b/core-permission/build.gradle.kts @@ -16,6 +16,7 @@ kotlin { implementation(libs.moko.permissions.camera) implementation(libs.moko.permissions.gallery) implementation(libs.koin.core) + implementation(libs.koin.core.coroutines) } } } diff --git a/core-permission/src/commonMain/kotlin/com/codandotv/streamplayerapp/core_permission/di/PermissionsModule.kt b/core-permission/src/commonMain/kotlin/com/codandotv/streamplayerapp/core_permission/di/PermissionsModule.kt index e6cb1bfd..281c3461 100644 --- a/core-permission/src/commonMain/kotlin/com/codandotv/streamplayerapp/core_permission/di/PermissionsModule.kt +++ b/core-permission/src/commonMain/kotlin/com/codandotv/streamplayerapp/core_permission/di/PermissionsModule.kt @@ -1,9 +1,9 @@ import com.codandotv.streamplayerapp.core_permission.permission.PermissionsManager -import org.koin.dsl.module +import org.koin.dsl.lazyModule object PermissionsModule { - val module = module { + val module = lazyModule { single { com.codandotv.streamplayerapp.core_permission.permission.PermissionsManagerImpl( controller = com.codandotv.streamplayerapp.core_permission.permission.PermissionFactory() diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a39e80bc..e0124dfe 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -66,7 +66,7 @@ serialization = { module = "org.jetbrains.kotlin.plugin.serialization:org.jetbra com-google-devtools-ksp-gradle-plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" } coil = { group = "io.coil-kt.coil3", name = "coil-compose", version.ref = "coil" } -coil-network-ktor3 = { module = "io.coil-kt.coil3:coil-network-ktor3", version.ref="coil"} +coil-network-ktor3 = { module = "io.coil-kt.coil3:coil-network-ktor3", version.ref = "coil" } lottie = { group = "com.airbnb.android", name = "lottie-compose", version.ref = "lottie" } @@ -90,6 +90,7 @@ koin-annotations = { module = "io.insert-koin:koin-annotations", version.ref = " koin-ksp-compiler = { module = "io.insert-koin:koin-ksp-compiler", version.ref = "koin-annotations" } koin_compose = { module = "io.insert-koin:koin-compose", version.ref = "koin" } koin_compose_viewmodel = { module = "io.insert-koin:koin-compose-viewmodel", version.ref = "koin" } +koin_core_coroutines = { module = "io.insert-koin:koin-core-coroutines", version.ref = "koin" } #Networking okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" } @@ -124,9 +125,9 @@ activity-compose = { module = "androidx.activity:activity-compose", version = "a #Firebase -firebase-bom = { group = "com.google.firebase", name = "firebase-bom", version.ref = "firebase-bom"} -firebase-analytics = { group = "com.google.firebase", name = "firebase-analytics"} -firebase-crashlytics = { group = "com.google.firebase", name = "firebase-crashlytics"} +firebase-bom = { group = "com.google.firebase", name = "firebase-bom", version.ref = "firebase-bom" } +firebase-analytics = { group = "com.google.firebase", name = "firebase-analytics" } +firebase-crashlytics = { group = "com.google.firebase", name = "firebase-crashlytics" } #Test kotlin_test = { group = "org.jetbrains.kotlin", name = "kotlin-test", version.ref = "kotlin" } @@ -155,7 +156,7 @@ compose_ui-util = { module = "org.jetbrains.compose.ui:ui-util", version.ref = " [bundles] test = ["junit", "mockk", "mockk_android", "viewmodel_test", "koin_test", "coroutines_test"] -test_multiplatform = ["kotlin_test", "kotlin_test_common", "coroutines_test",] +test_multiplatform = ["kotlin_test", "kotlin_test_common", "coroutines_test", ] camera = [ "androidx-camera-camera2", "androidx-camera-core", @@ -180,6 +181,6 @@ ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" } buildkonfig_plugin = { id = "com.codingfeline.buildkonfig", version.ref = "buildkonfig" } -google-services = { id = "com.google.gms.google-services", version.ref = "google-services"} +google-services = { id = "com.google.gms.google-services", version.ref = "google-services" } -firebase-crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebase-crashlytics"} +firebase-crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebase-crashlytics" } From 2a96d5dd56f689387d3b31dd2439e318abb9a0d8 Mon Sep 17 00:00:00 2001 From: Gabriel Moro Date: Wed, 6 May 2026 17:40:44 -0300 Subject: [PATCH 4/6] Update Search screen layout and project configuration - Add `statusBarsPadding` to the search top bar in `SearchScreen` to improve edge-to-edge support. - Add a `modifier` parameter to the search top bar widget to allow for flexible layout adjustments. - Remove the `kotzilla.sdk.compose` dependency from `composeApp`. - Increment `versionName` to `1.5` in the build configuration. --- build-logic/src/main/java/Config.kt | 2 +- composeApp/build.gradle.kts | 2 -- .../feature_search/presentation/screens/SearchScreen.kt | 2 ++ .../feature_search/presentation/widgets/SearchStreams.kt | 5 +++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/build-logic/src/main/java/Config.kt b/build-logic/src/main/java/Config.kt index f4f99b92..2d4891cb 100644 --- a/build-logic/src/main/java/Config.kt +++ b/build-logic/src/main/java/Config.kt @@ -10,7 +10,7 @@ object Config { const val compileSdkVersion = 36 const val minSdkVersion = 28 const val targetSdkVersion = 36 - const val versionName = "1.4" + const val versionName = "1.5" const val versionCode = 1 const val testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts index 938730cb..08c0b27e 100644 --- a/composeApp/build.gradle.kts +++ b/composeApp/build.gradle.kts @@ -35,8 +35,6 @@ kotlin { implementation(libs.koin.core) implementation(libs.koin.core.coroutines) api(libs.kmpnotifier) - - implementation(libs.kotzilla.sdk.compose) } } } diff --git a/feature-search/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_search/presentation/screens/SearchScreen.kt b/feature-search/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_search/presentation/screens/SearchScreen.kt index c3067ecb..885f13b6 100644 --- a/feature-search/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_search/presentation/screens/SearchScreen.kt +++ b/feature-search/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_search/presentation/screens/SearchScreen.kt @@ -4,6 +4,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.CircularProgressIndicator @@ -87,6 +88,7 @@ private fun SetupSearchScreen( topBar = { val currentText by viewModel.currentSearchText.collectAsState() SearchableTopBar( + modifier = Modifier.statusBarsPadding(), currentSearchText = currentText, onSearchTextChanged = { value -> viewModel.setCurrentSearchText( diff --git a/feature-search/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_search/presentation/widgets/SearchStreams.kt b/feature-search/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_search/presentation/widgets/SearchStreams.kt index 01775583..b86c064f 100644 --- a/feature-search/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_search/presentation/widgets/SearchStreams.kt +++ b/feature-search/src/commonMain/kotlin/com/codandotv/streamplayerapp/feature_search/presentation/widgets/SearchStreams.kt @@ -49,9 +49,10 @@ fun SearchableTopBar( onSearchDispatched: () -> Unit, onSearchIconPressed: () -> Unit, onBackPressed: () -> Unit, - onCleanTextPressed: () -> Unit + onCleanTextPressed: () -> Unit, + modifier: Modifier = Modifier, ) { - Column { + Column(modifier = modifier) { StreamPlayerTopBar( onBackPressed = onBackPressed ) From 9429baa3df9556f2c3f09da3458d1e7359c0b604 Mon Sep 17 00:00:00 2001 From: Gabriel Moro Date: Wed, 6 May 2026 20:08:50 -0300 Subject: [PATCH 5/6] Update Kotzilla SDK and configure monitoring - Upgrade Kotzilla version to 2.1.3 in the version catalog. - Apply the Kotzilla plugin and add the SDK dependency to `composeApp`. - Add the `kotzilla.json` configuration file to the `composeApp` module. - Initialize Kotzilla monitoring in `AppModule.kt` and set `useIosCrashReport` to `false`. - Add a new "Kotzilla Dsym" shell script build phase to the iOS Xcode project to automate Dsym uploads. --- composeApp/build.gradle.kts | 2 ++ composeApp/kotzilla.json | 11 ++++++++++ .../di/AppModule.kt | 7 +++++++ gradle/libs.versions.toml | 2 +- iosApp/iosApp.xcodeproj/project.pbxproj | 21 ++++++++++++++++++- 5 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 composeApp/kotzilla.json diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts index 08c0b27e..5d3d0841 100644 --- a/composeApp/build.gradle.kts +++ b/composeApp/build.gradle.kts @@ -4,6 +4,7 @@ plugins { id("com.streamplayer.kmp-library") alias(libs.plugins.jetbrains.compose) alias(libs.plugins.compose.compiler) + alias(libs.plugins.kotzilla) } kotlin { @@ -16,6 +17,7 @@ kotlin { implementation(libs.firebase.crashlytics) } commonMain.dependencies { + implementation(libs.kotzilla.sdk.compose) implementation(projects.featureListStreams) implementation(projects.featureDetail) implementation(projects.featureSearch) diff --git a/composeApp/kotzilla.json b/composeApp/kotzilla.json new file mode 100644 index 00000000..f62cf1f7 --- /dev/null +++ b/composeApp/kotzilla.json @@ -0,0 +1,11 @@ +{ + "keys": [ + { + "appId": "019cca1a-c2ae-79d5-bf91-20316edd8f11", + "applicationPackageName": "com.codandotv.streamplayerapp", + "keyId": "019dfef9-3830-749f-a89e-77c18e51f663", + "apiKey": "ktz-sdk-5N2sXcaobPbX6erWh9cF4lC1HGztC9qBIXzvMc873o8", + "isDefault": true + } + ] +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com.codandotv.streamplayerapp/di/AppModule.kt b/composeApp/src/commonMain/kotlin/com.codandotv.streamplayerapp/di/AppModule.kt index 7fec5ce7..c10fa4a8 100644 --- a/composeApp/src/commonMain/kotlin/com.codandotv.streamplayerapp/di/AppModule.kt +++ b/composeApp/src/commonMain/kotlin/com.codandotv.streamplayerapp/di/AppModule.kt @@ -9,6 +9,7 @@ import com.codandotv.streamplayerapp.feature_news.di.NewsScreenModule import com.codandotv.streamplayerapp.feature_search.di.SearchModule import com.codandotv.streamplayerapp.feature_search.presentation.widgets.StreamsError import com.codandotv.streamplayerapp.profile.di.ProfilePickerStreamModule +import io.kotzilla.generated.monitoring import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.IO import org.koin.core.KoinApplication @@ -39,6 +40,12 @@ fun streamPlayerApplication(platformBlock: KoinApplication.() -> Unit): KoinAppl ProfilePickerStreamModule().module // endregion ) + + monitoring { + onConfig { + useIosCrashReport = false + } + } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e0124dfe..86b8306d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,7 +4,7 @@ android_gradle_plugin = "9.1.0" koin = "4.2.0" koin-annotations = "2.3.1" ksp = "2.3.5" -kotzilla = "2.0.8" +kotzilla = "2.1.3" lifecycle-viewmodel-compose-version = "2.9.6" dokka = "1.9.10" diff --git a/iosApp/iosApp.xcodeproj/project.pbxproj b/iosApp/iosApp.xcodeproj/project.pbxproj index afe73fa0..780eecb4 100644 --- a/iosApp/iosApp.xcodeproj/project.pbxproj +++ b/iosApp/iosApp.xcodeproj/project.pbxproj @@ -207,7 +207,8 @@ 7555FF77242A565900829871 /* Sources */, B92378962B6B1156000C7307 /* Frameworks */, 7555FF79242A565900829871 /* Resources */, - ); + + 5B6CA7F380A0493998D6B4A3 /* Kotzilla Dsym */,); buildRules = ( ); dependencies = ( @@ -326,6 +327,24 @@ shellPath = /bin/sh; shellScript = "if [ \"YES\" = \"$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED\" ]; then\n echo \"Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \\\"YES\\\"\"\n exit 0\nfi\ncd \"$SRCROOT/..\"\n./gradlew :composeApp:embedAndSignAppleFrameworkForXcode\n"; }; + 5B6CA7F380A0493998D6B4A3 /* Kotzilla Dsym */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Kotzilla Dsym"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# KOTZILLA_SCRIPT_VERSION=9\nset -e\nM=$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.app/kotzilla-debug\n[ \"$CONFIGURATION\" = Release ] && rm -f \"$M\" 2>/dev/null || touch \"$M\" 2>/dev/null\n[ -z \"$DWARF_DSYM_FOLDER_PATH\" ] && exit 0\ncd \"$SRCROOT/..\"\n./gradlew ':composeApp:uploadDsymFile' --dsymPath=\"$DWARF_DSYM_FOLDER_PATH\"\n"; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ From a41e557cb6f2a4b7075709f65dfeea42680d4c50 Mon Sep 17 00:00:00 2001 From: Gabriel Moro Date: Wed, 6 May 2026 20:11:47 -0300 Subject: [PATCH 6/6] Solve lint issue --- .../streamplayerapp/profile/di/ProfilePickerStreamModule.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/di/ProfilePickerStreamModule.kt b/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/di/ProfilePickerStreamModule.kt index 400f7936..f06a7da4 100644 --- a/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/di/ProfilePickerStreamModule.kt +++ b/feature-profile/src/commonMain/kotlin/com/codandotv/streamplayerapp/profile/di/ProfilePickerStreamModule.kt @@ -5,4 +5,4 @@ import org.koin.core.annotation.Module @Module @ComponentScan("com.codandotv.streamplayerapp.profile") -class ProfilePickerStreamModule \ No newline at end of file +class ProfilePickerStreamModule