Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@
local.properties
/.kotlin/
/.idea/
/app/kotzilla.json

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could be kept in project, even empty

/app/src/main/assets/kotzilla.key
2 changes: 1 addition & 1 deletion .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ plugins {
alias(libs.plugins.detekt)
alias(libs.plugins.google.secrets.gradle.plugin)
alias(libs.plugins.automattic.measure.builds)
alias(libs.plugins.allopen)
id("io.kotzilla.kotzilla-plugin")
}
apply("$rootDir/gradle/report.gradle")

Expand Down Expand Up @@ -113,6 +115,10 @@ ksp {
arg("KOIN_CONFIG_CHECK", "true")
}

allOpen {
annotation("org.koin.core.annotation.Monitor")
}

dependencies {
implementation(project(":core"))
implementation(libs.kotlin.stdlib)
Expand Down Expand Up @@ -147,6 +153,8 @@ dependencies {
implementation(libs.koin.android)
implementation(libs.koin.androidx.compose)
implementation(libs.koin.androidx.startup)
implementation("io.kotzilla:kotzilla-sdk:1.2.3")
//implementation("io.kotzilla:kotzilla-sdk-compose:1.2.3")

compileOnly(libs.koin.annotations.core)
ksp(libs.koin.annotations.compiler)
Expand Down
7 changes: 4 additions & 3 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Expand All @@ -24,8 +25,8 @@
</activity>
<activity
android:name=".ui.xml.home.HomeViewActivity"
android:label="@string/title_activity_home_view"
android:exported="true" />
android:exported="true"
android:label="@string/title_activity_home_view" />
</application>

</manifest>
38 changes: 26 additions & 12 deletions app/src/main/java/com/santimattius/template/MainApplication.kt
Original file line number Diff line number Diff line change
@@ -1,26 +1,40 @@
package com.santimattius.template

import android.app.Application
import android.util.Log
import com.santimattius.core.CoreModule
import com.santimattius.template.di.AppModule
import com.santimattius.template.di.DataModule
import io.kotzilla.sdk.analytics.koin.analytics
import org.koin.android.ext.koin.androidContext
import org.koin.android.logger.AndroidLogger
import org.koin.androix.startup.KoinStartup
import org.koin.core.annotation.KoinApplication
import org.koin.core.annotation.KoinExperimentalAPI
import org.koin.dsl.KoinConfiguration
import org.koin.ksp.generated.com_santimattius_template_di_AppModule
import org.koin.ksp.generated.com_santimattius_template_di_DataModule
import org.koin.ksp.generated.defaultModule
import org.koin.dsl.module
import org.koin.ksp.generated.defineComSantimattiusTemplateUiComposeHomeComposeViewModel
import org.koin.ksp.generated.defineComSantimattiusTemplateUiXmlHomeHomeViewModel
import org.koin.ksp.generated.koinConfiguration

@KoinApplication(
configurations = ["default"],
modules = [CoreModule::class, DataModule::class, AppModule::class]
)
object MainKoinApplication

@OptIn(KoinExperimentalAPI::class)
class MainApplication : Application(), KoinStartup {

override fun onKoinStartup(): KoinConfiguration {
return KoinConfiguration {
Log.d(this::class.simpleName, "onKoinStartup: ${Thread.currentThread().name}")
val configuration = MainKoinApplication.koinConfiguration {
androidContext(this@MainApplication)
logger(AndroidLogger())
modules(
com_santimattius_template_di_DataModule,
com_santimattius_template_di_AppModule,
defaultModule
)
analytics()
modules(modules = module {
defineComSantimattiusTemplateUiComposeHomeComposeViewModel()
defineComSantimattiusTemplateUiXmlHomeHomeViewModel()
})
}
return KoinConfiguration(configuration)
}
}
}
34 changes: 9 additions & 25 deletions app/src/main/java/com/santimattius/template/di/AppModule.kt
Original file line number Diff line number Diff line change
@@ -1,37 +1,21 @@
package com.santimattius.template.di

import android.content.Context
import com.santimattius.core.data.client.database.TheMovieDataBase
import com.santimattius.core.data.client.network.RetrofitServiceCreator
import com.santimattius.core.data.client.network.TheMovieDBService
import com.santimattius.template.BuildConfig
import org.koin.core.annotation.Configuration
import org.koin.core.annotation.Module
import org.koin.core.annotation.Named
import org.koin.core.annotation.Singleton
import org.koin.core.annotation.Single


@Module
@Configuration
class AppModule {

@Singleton
fun provideAppDatabase(context: Context): TheMovieDataBase =
TheMovieDataBase.get(context)

@Singleton
fun provideMovieDBService(serviceCreator: RetrofitServiceCreator): TheMovieDBService =
serviceCreator.createService(TheMovieDBService::class.java)


@Singleton
fun provideRetrofit(@Named("base_url") baseUrl: String): RetrofitServiceCreator {
return RetrofitServiceCreator(
baseUrl = baseUrl,
apiKey = BuildConfig.apiKey
)
}

@Named("base_url")
@Singleton
@Suppress("FunctionOnlyReturningConstant")
@Single(createdAtStart = true)
@Named("baseUrl")
fun provideBaseUrl() = "https://api.themoviedb.org"

@Single(createdAtStart = true)
@Named("apiKey")
fun provideApiKey() = BuildConfig.apiKey
}
10 changes: 6 additions & 4 deletions app/src/main/java/com/santimattius/template/di/DataModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ import com.santimattius.core.data.datasources.implementation.RetrofitMovieNetwor
import com.santimattius.core.data.datasources.implementation.RoomMovieLocalDataSource
import com.santimattius.core.data.repositories.TMDbRepository
import com.santimattius.core.domain.repositories.MovieRepository
import org.koin.core.annotation.Configuration
import org.koin.core.annotation.Module
import org.koin.core.annotation.Singleton
import org.koin.core.annotation.Single

@Module
@Configuration
class DataModule {

@Singleton
@Single
fun provideMovieRepository(
movieNetworkDataSource: MovieNetworkDataSource,
movieLocalDataSource: MovieLocalDataSource,
Expand All @@ -23,12 +25,12 @@ class DataModule {
movieLocalDataSource = movieLocalDataSource
)

@Singleton
@Single
fun provideLocalDataSource(theMovieDataBase: TheMovieDataBase): MovieLocalDataSource {
return RoomMovieLocalDataSource(theMovieDataBase = theMovieDataBase)
}

@Singleton
@Single
fun provideRemoteDataSource(service: TheMovieDBService): MovieNetworkDataSource {
return RetrofitMovieNetworkDataSource(service = service)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,32 +40,35 @@ import com.santimattius.template.ui.compose.ui.components.snackbar.SnackBarVisua
import com.santimattius.template.ui.compose.ui.theme.AndroidTestingTheme
import com.santimattius.template.ui.xml.home.HomeViewActivity
import org.koin.androidx.compose.koinViewModel
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.compose.LocalKoinApplication
import org.koin.compose.LocalKoinScope
import org.koin.core.annotation.KoinInternalApi
import org.koin.mp.KoinPlatformTools


class HomeComposeActivity : ComponentActivity() {
private val viewModel: HomeComposeViewModel by viewModel()

@OptIn(KoinInternalApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
// This shouldn't be needed, but allows robolectric tests to run successfully
// TODO remove once a solution is found or a fix in koin?
CompositionLocalProvider(
LocalKoinScope provides KoinPlatformTools.defaultContext()
.get().scopeRegistry.rootScope,
LocalKoinApplication provides KoinPlatformTools.defaultContext().get()
) {
AndroidTestingTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
HomeRoute()
}
// CompositionLocalProvider(
// LocalKoinScope provides KoinPlatformTools.defaultContext()
// .get().scopeRegistry.rootScope,
// LocalKoinApplication provides KoinPlatformTools.defaultContext().get()
// ) {
//
// }
AndroidTestingTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
HomeRoute(viewModel)
}
}
}
Expand All @@ -74,7 +77,7 @@ class HomeComposeActivity : ComponentActivity() {

@Composable
fun HomeRoute(
viewModel: HomeComposeViewModel = koinViewModel()
viewModel: HomeComposeViewModel
) {
val snackBarHostState = remember { SnackbarHostState() }
Scaffold(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ 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.Configuration
import org.koin.core.annotation.Monitor

@KoinViewModel
@Monitor
@Configuration
class HomeComposeViewModel(
private val movieRepository: MovieRepository,
) : ViewModel() {
Expand All @@ -29,7 +33,7 @@ class HomeComposeViewModel(
if (newMovies != state.movies) {
state.copy(movies = newMovies, isLoading = false)
} else {
state // Si no ha cambiado nada, retorna el mismo estado
state
}
}.onStart {
movieRepository.refresh()
Expand Down
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ plugins {
alias(libs.plugins.detekt) apply false
alias(libs.plugins.google.secrets.gradle.plugin) apply false
alias(libs.plugins.automattic.measure.builds) apply false
alias(libs.plugins.allopen) apply false
alias(libs.plugins.room) apply false
}

buildscript {
dependencies {
classpath(libs.dep.google.secrets.gradle.plugin)
classpath("io.kotzilla:kotzilla-plugin:1.2.3")
}
}
2 changes: 2 additions & 0 deletions core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ dependencies {
implementation(platform(libs.koin.bom))
implementation(libs.koin.android)
implementation(libs.koin.androidx.compose)
compileOnly(libs.koin.annotations.core)
ksp(libs.koin.annotations.compiler)

testImplementation(project(path = ":shared-test"))
testImplementation(libs.bundles.unitTesting)
Expand Down
46 changes: 46 additions & 0 deletions core/src/main/java/com/santimattius/core/CoreModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.santimattius.core

import android.content.Context
import com.santimattius.core.data.client.database.TheMovieDataBase
import com.santimattius.core.data.client.network.RequestInterceptor
import com.santimattius.core.data.client.network.TheMovieDBService
import okhttp3.OkHttpClient
import org.koin.core.annotation.Configuration
import org.koin.core.annotation.Module
import org.koin.core.annotation.Named
import org.koin.core.annotation.Single
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

@Module
@Configuration
class CoreModule {

@Single(createdAtStart = true)
fun provideOkHttpClient(@Named("apiKey") apiKey: String): OkHttpClient {
return OkHttpClient().newBuilder()
.addInterceptor(RequestInterceptor(apiKey))
.build()
}

@Single(createdAtStart = true)
fun provideRetrofit(
@Named("baseUrl") baseUrl: String,
client: OkHttpClient
): Retrofit {
return Retrofit.Builder()
.baseUrl(baseUrl)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
}

@Single(createdAtStart = true)
fun provideService(retrofit: Retrofit): TheMovieDBService {
return retrofit.create(TheMovieDBService::class.java)
}

@Single(createdAtStart = true)
fun provideAppDatabase(context: Context): TheMovieDataBase =
TheMovieDataBase.get(context)
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,17 @@ abstract class TheMovieDataBase : RoomDatabase() {

private const val DATABASE_NAME = "tmdb_database"

fun get(context: Context) =
/*@Volatile
private var INSTANCE: TheMovieDataBase? = null

fun get(context: Context) = INSTANCE ?: synchronized(this) {
INSTANCE ?: create(context).also { INSTANCE = it }
}
*/

fun get(context: Context) = create(context)

private fun create(context: Context) =
Room.databaseBuilder(context, TheMovieDataBase::class.java, DATABASE_NAME)
.build()
}
Expand Down
Loading
Loading