Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
package com.jetbrains.spacetutorial

import android.app.Application
import com.jetbrains.spacetutorial.di.AndroidKoinApp
import com.jetbrains.spacetutorial.di.KoinApp
import org.koin.android.ext.koin.androidContext
import org.koin.ksp.generated.startKoin

class MainApplication : Application() {
override fun onCreate() {
super.onCreate()

AndroidKoinApp.initKoin(this)
// use startKoin generated in KoinApp (thanks to @KoinApplication)
// allow to pass extra arguments like androidContext
KoinApp.startKoin {
androidContext(this@MainApplication)
}
}
}
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ coroutinesVersion = "1.10.2"
dateTimeVersion = "0.7.1"
koin = "4.1.1"
koin-ksp = "2.3.1"
ksp = "2.2.21-2.0.4"
ksp = "2.3.2"
ktor = "3.1.3"
sqlDelight = "2.1.0"
lifecycleViewmodelCompose = "2.9.1"
Expand Down
37 changes: 27 additions & 10 deletions shared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -57,20 +57,14 @@ kotlin {
implementation("io.insert-koin:koin-compose:4.1.1")
}
}
}

android {
namespace = "com.jetbrains.spacetutorial.shared"
compileSdk = libs.versions.android.compileSdk.get().toInt()
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
defaultConfig {
minSdk = libs.versions.android.minSdk.get().toInt()
// KSP Common sourceSet
sourceSets.named("commonMain").configure {
kotlin.srcDir("build/generated/ksp/metadata/commonMain/kotlin")
}
}


sqldelight {
databases {
create("AppDatabase") {
Expand All @@ -79,10 +73,33 @@ sqldelight {
}
}

// KSP Tasks
dependencies {
add("kspCommonMainMetadata", libs.koin.compiler)
add("kspAndroid", libs.koin.compiler)
add("kspIosX64", libs.koin.compiler)
add("kspIosArm64", libs.koin.compiler)
add("kspIosSimulatorArm64", libs.koin.compiler)
}

// KSP Metadata Trigger
tasks.matching { it.name.startsWith("ksp") && it.name != "kspCommonMainKotlinMetadata" }.configureEach {
dependsOn("kspCommonMainKotlinMetadata")
}

ksp {
arg("KOIN_CONFIG_CHECK","true")
}

android {
namespace = "com.jetbrains.spacetutorial.shared"
compileSdk = libs.versions.android.compileSdk.get().toInt()
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
defaultConfig {
minSdk = libs.versions.android.minSdk.get().toInt()
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import android.content.Context
import app.cash.sqldelight.db.SqlDriver
import app.cash.sqldelight.driver.android.AndroidSqliteDriver

class AndroidDatabaseDriverFactory(private val context: Context) : DatabaseDriverFactory {
override fun createDriver(): SqlDriver {
return AndroidSqliteDriver(AppDatabase.Schema, context, "launch.db")
}
}
//class AndroidDatabaseDriverFactory(private val context: Context) : DatabaseDriverFactory {
// override fun createDriver(): SqlDriver {
// return AndroidSqliteDriver(AppDatabase.Schema, context, "launch.db")
// }
//}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.jetbrains.spacetutorial.cache

import app.cash.sqldelight.db.SqlDriver
import app.cash.sqldelight.driver.android.AndroidSqliteDriver
import com.jetbrains.spacetutorial.di.ContextWrapper
import org.koin.core.annotation.Single

// Singleton -
// Uses ContextWrapper to inject Android context
@Single
actual class DatabaseDriverFactory actual constructor(val contextWrapper: ContextWrapper) {
actual fun createDriver(): SqlDriver {
// use of Android context
return AndroidSqliteDriver(AppDatabase.Schema, contextWrapper.context, "launch.db")
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package com.jetbrains.spacetutorial.di

import android.content.Context
import org.koin.android.ext.koin.androidContext
import org.koin.core.annotation.KoinApplication
import org.koin.core.context.startKoin

@KoinApplication(modules = [AndroidAppModule::class])
object AndroidKoinApp {
fun initKoin(context: Context){
startKoin { androidContext(context) }
}
}
//package com.jetbrains.spacetutorial.di
//
//import android.content.Context
//import org.koin.android.ext.koin.androidContext
//import org.koin.core.annotation.KoinApplication
//import org.koin.core.context.startKoin
//
//@KoinApplication(modules = [AndroidAppModule::class])
//object AndroidKoinApp {
// fun initKoin(context: Context){
// startKoin { androidContext(context) }
// }
//}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.jetbrains.spacetutorial.di

import android.content.Context
import com.jetbrains.spacetutorial.RocketLaunchViewModel
import com.jetbrains.spacetutorial.SpaceXSDK
import org.koin.android.annotation.KoinViewModel
import org.koin.core.annotation.Module
import org.koin.core.annotation.Single
import org.koin.core.scope.Scope

// Native Context Wrapper for Android
actual class ContextWrapper(val context : Context)

// Native Module to define ContextWrapper
@Module
actual class ContextModule actual constructor() {

// Uses Scope injection to retrieve dynamically the Android context
// Allow to have a stable Wrapper
@Single
actual fun providesContextWrapper(scope: Scope): ContextWrapper = ContextWrapper(scope.get())
}

@Module(includes = [CommonModule::class])
actual class NativeModule {

@KoinViewModel
fun rocketLaunchViewModel(sdk: SpaceXSDK) = RocketLaunchViewModel(sdk)
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
package com.jetbrains.spacetutorial.di

import android.content.Context
import com.jetbrains.spacetutorial.RocketLaunchViewModel
import com.jetbrains.spacetutorial.SpaceXSDK
import com.jetbrains.spacetutorial.cache.AndroidDatabaseDriverFactory
import com.jetbrains.spacetutorial.network.SpaceXApi
import org.koin.android.annotation.KoinViewModel
import org.koin.core.annotation.Configuration
import org.koin.core.annotation.Module
import org.koin.core.annotation.Single

@Module
@Configuration
class AndroidAppModule : AppModule {
@Single
override fun spaceApi() = SpaceXApi()

@Single
fun spaceXSDK(api: SpaceXApi, context: Context) =
SpaceXSDK(databaseDriverFactory = AndroidDatabaseDriverFactory(context), api = api)

@KoinViewModel
fun rocketLaunchViewModel(sdk: SpaceXSDK) = RocketLaunchViewModel(sdk)
}

//package com.jetbrains.spacetutorial.di
//
//import android.content.Context
//import com.jetbrains.spacetutorial.RocketLaunchViewModel
//import com.jetbrains.spacetutorial.SpaceXSDK
//import com.jetbrains.spacetutorial.cache.AndroidDatabaseDriverFactory
//import com.jetbrains.spacetutorial.network.SpaceXApi
//import org.koin.android.annotation.KoinViewModel
//import org.koin.core.annotation.Configuration
//import org.koin.core.annotation.Module
//import org.koin.core.annotation.Single
//
//@Module
//@Configuration
//class AndroidAppModule : AppModule {
// @Single
// override fun spaceApi() = SpaceXApi()
//
// @Single
// fun spaceXSDK(api: SpaceXApi, context: Context) =
// SpaceXSDK(databaseDriverFactory = AndroidDatabaseDriverFactory(context), api = api)
//
// @KoinViewModel
// fun rocketLaunchViewModel(sdk: SpaceXSDK) = RocketLaunchViewModel(sdk)
//}
//
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import com.jetbrains.spacetutorial.cache.Database
import com.jetbrains.spacetutorial.cache.DatabaseDriverFactory
import com.jetbrains.spacetutorial.entity.RocketLaunch
import com.jetbrains.spacetutorial.network.SpaceXApi
import org.koin.core.annotation.Single

@Single
class SpaceXSDK(databaseDriverFactory: DatabaseDriverFactory, val api: SpaceXApi) {
private val database = Database(databaseDriverFactory)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package com.jetbrains.spacetutorial.cache

import app.cash.sqldelight.db.SqlDriver
import com.jetbrains.spacetutorial.di.ContextWrapper
import org.koin.core.annotation.Single

interface DatabaseDriverFactory {
// define Driver with ContextWrapper
@Single
expect class DatabaseDriverFactory(contextWrapper: ContextWrapper) {
fun createDriver(): SqlDriver
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,39 @@
package com.jetbrains.spacetutorial.di

import com.jetbrains.spacetutorial.network.SpaceXApi
import org.koin.core.annotation.ComponentScan
import org.koin.core.annotation.KoinApplication
import org.koin.core.annotation.Module
import org.koin.core.annotation.Single
import org.koin.core.scope.Scope

interface AppModule {
fun spaceApi(): SpaceXApi
}
// Context Wrapper Pattern, to allow pass native context as KMP
expect class ContextWrapper

// Define Context Wrapper
@Module
expect class ContextModule() {

@Single
fun providesContextWrapper(scope : Scope) : ContextWrapper
}

// Gather all common KMP components
@Module(includes = [ContextModule::class])
@ComponentScan("com.jetbrains.spacetutorial")
class CommonModule

// Native module, to give the hand back for native Components (like ViewModel on Android)
@Module(includes = [CommonModule::class])
expect class NativeModule()

// Main Module, uses includes
// KSP2 is introducing an issue and prevent any @Configuration scanning
// need to specify modules by hand
@Module(includes = [CommonModule::class, NativeModule::class])
class AppModule

// Main Koin Entry point
// includes modules to start
// KSP2 is introducing an issue and prevent any @Configuration scanning
@KoinApplication(modules = [AppModule::class])
object KoinApp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.request.get
import io.ktor.serialization.kotlinx.json.json
import kotlinx.serialization.json.Json
import org.koin.core.annotation.Single

@Single
class SpaceXApi {
private val httpClient = HttpClient {
install(ContentNegotiation) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
package com.jetbrains.spacetutorial

import com.jetbrains.spacetutorial.di.KoinApp
import org.koin.ksp.generated.*
import com.jetbrains.spacetutorial.entity.RocketLaunch
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import com.jetbrains.spacetutorial.di.IOSKoinApp

class KoinHelper : KoinComponent {
private val sdk: SpaceXSDK by inject<SpaceXSDK>()
private val sdk: SpaceXSDK by inject()

suspend fun getLaunches(forceReload: Boolean): List<RocketLaunch> {
return sdk.getLaunches(forceReload = forceReload)
}
}

fun initKoin() {
IOSKoinApp.startKoin()
KoinApp.startKoin()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.jetbrains.spacetutorial.cache

import app.cash.sqldelight.db.SqlDriver
import app.cash.sqldelight.driver.native.NativeSqliteDriver
import com.jetbrains.spacetutorial.di.ContextWrapper
import org.koin.core.annotation.Single

@Single
actual class DatabaseDriverFactory actual constructor(contextWrapper: ContextWrapper) {
actual fun createDriver(): SqlDriver = NativeSqliteDriver(AppDatabase.Schema, "launch.db")
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package com.jetbrains.spacetutorial.cache
import app.cash.sqldelight.db.SqlDriver
import app.cash.sqldelight.driver.native.NativeSqliteDriver

class IOSDatabaseDriverFactory : DatabaseDriverFactory {
override fun createDriver(): SqlDriver {
return NativeSqliteDriver(AppDatabase.Schema, "launch.db")
}
}
//class IOSDatabaseDriverFactory : DatabaseDriverFactory {
// override fun createDriver(): SqlDriver {
// return NativeSqliteDriver(AppDatabase.Schema, "launch.db")
// }
//}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.jetbrains.spacetutorial.di

import org.koin.core.annotation.ComponentScan
import org.koin.core.annotation.Module
import org.koin.core.annotation.Single
import org.koin.core.scope.Scope

actual class ContextWrapper()

@Module
actual class ContextModule actual constructor() {

@Single
actual fun providesContextWrapper(scope: Scope): ContextWrapper = ContextWrapper()
}

@Module
@ComponentScan(" com.jetbrains.spacetutorial")
actual class NativeModule
Loading