First version with MVVM
This commit is contained in:
@@ -4,11 +4,17 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
|
||||
|
||||
val lifecycle_version = "2.6.1"
|
||||
val arch_version = "2.2.0"
|
||||
|
||||
plugins {
|
||||
|
||||
alias(libs.plugins.kotlinMultiplatform)
|
||||
alias(libs.plugins.androidApplication)
|
||||
alias(libs.plugins.composeMultiplatform)
|
||||
alias(libs.plugins.composeCompiler)
|
||||
|
||||
|
||||
}
|
||||
|
||||
kotlin {
|
||||
@@ -66,9 +72,18 @@ kotlin {
|
||||
implementation(compose.ui)
|
||||
implementation(compose.components.resources)
|
||||
implementation(compose.components.uiToolingPreview)
|
||||
implementation(libs.androidx.lifecycle.livedata.core)
|
||||
implementation(libs.androidx.lifecycle.viewmodel)
|
||||
implementation(libs.androidx.lifecycle.runtime.compose)
|
||||
implementation(libs.lifecycle.runtime.compose)
|
||||
implementation(libs.lifecycle.viewmodel.compose)
|
||||
implementation(libs.androidx.lifecycle.viewmodel.compose)
|
||||
implementation(projects.shared)
|
||||
implementation(project.dependencies.platform(libs.koin.bom))
|
||||
implementation(libs.koin.core)
|
||||
implementation(libs.koin.compose)
|
||||
implementation(libs.koin.compose.viewmodel)
|
||||
|
||||
|
||||
}
|
||||
desktopMain.dependencies {
|
||||
@@ -106,6 +121,7 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.androidx.lifecycle.livedata.core.ktx)
|
||||
debugImplementation(compose.uiTooling)
|
||||
}
|
||||
|
||||
|
||||
@@ -29,76 +29,23 @@ import service.TermService
|
||||
import service.TermServiceImpl
|
||||
import service.SearchType
|
||||
import service.DatabaseFactory
|
||||
import org.koin.compose.KoinApplication
|
||||
import org.koin.compose.koinInject
|
||||
import org.koin.core.parameter.parametersOf
|
||||
import org.neutrino.ktans.di.appModule
|
||||
import org.koin.compose.viewmodel.dsl.viewModelOf
|
||||
import org.neutrino.ktans.view.MainView
|
||||
|
||||
@Composable
|
||||
fun SearchBarTextField() {
|
||||
val query = remember { mutableStateOf("") }
|
||||
val termService = TermServiceImpl()
|
||||
var showResults by remember { mutableStateOf(false) }
|
||||
var terms: List<TermFull>? = null
|
||||
|
||||
TextField(
|
||||
value = query.value,
|
||||
onValueChange = {
|
||||
query.value = it
|
||||
var sType = SearchType.START
|
||||
sType = if (query.value.length > 2) {
|
||||
SearchType.START
|
||||
} else {
|
||||
SearchType.EXACT
|
||||
}
|
||||
|
||||
val translation = getTranslationForLanguages("an","sl") ?: return@TextField
|
||||
println(translation)
|
||||
terms = termService.getTranslationForTerm(it,translation,sType)
|
||||
showResults = terms != null
|
||||
println(terms)
|
||||
|
||||
},
|
||||
placeholder = { Text("Prelož...") },
|
||||
singleLine = true,
|
||||
leadingIcon = { Icon(Icons.Filled.Search, contentDescription = "Search Icon") },
|
||||
trailingIcon = {
|
||||
if (query.value.isNotEmpty()) {
|
||||
IconButton(onClick = { query.value = "" }) {
|
||||
Icon(Icons.Filled.Clear, contentDescription = "Clear Text")
|
||||
}
|
||||
}
|
||||
},
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
)
|
||||
|
||||
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) {
|
||||
if (showResults && terms != null) {
|
||||
for (term in terms!!) {
|
||||
Text(term.string1)
|
||||
Text("${term.string2},")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun App() {
|
||||
DatabaseFactory.connectAndMigrate()
|
||||
DatabaseFactory.connectAll()
|
||||
|
||||
KoinApplication(application = {
|
||||
modules(appModule())
|
||||
}) {
|
||||
MaterialTheme {
|
||||
var showContent by remember { mutableStateOf(false) }
|
||||
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
SearchBarTextField()
|
||||
Button(onClick = { showContent = !showContent }) {
|
||||
Text("Click me!")
|
||||
}
|
||||
AnimatedVisibility(showContent) {
|
||||
val greeting = remember { Greeting().greet() }
|
||||
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Image(painterResource(Res.drawable.compose_multiplatform), null)
|
||||
Text("Compose: $greeting")
|
||||
}
|
||||
}
|
||||
MainView()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.neutrino.ktans.di
|
||||
|
||||
import org.koin.core.module.dsl.singleOf
|
||||
import org.koin.dsl.module
|
||||
import service.TermServiceImpl
|
||||
import service.DatabaseFactory
|
||||
import org.koin.compose.viewmodel.dsl.viewModelOf
|
||||
import org.neutrino.ktans.viewmodel.MainModelView
|
||||
import org.koin.core.module.dsl.factoryOf
|
||||
|
||||
fun appModule() = module {
|
||||
singleOf(::TermServiceImpl)
|
||||
viewModelOf(::MainModelView)
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package org.neutrino.ktans.view
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.material.TextField
|
||||
import androidx.compose.material.IconButton
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material.icons.filled.Clear
|
||||
import androidx.compose.runtime.Composable
|
||||
import kotlinx.coroutines.flow.observeOn
|
||||
import org.koin.compose.koinInject
|
||||
import org.neutrino.ktans.viewmodel.MainModelView
|
||||
import org.neutrino.ktans.viewmodel.Status
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
|
||||
@Composable
|
||||
fun RowScope.TableCell(
|
||||
text: String,
|
||||
weight: Float
|
||||
) {
|
||||
Text(
|
||||
text = text,
|
||||
Modifier
|
||||
.border(1.dp, Color.Black)
|
||||
.weight(weight)
|
||||
.padding(8.dp)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun SearchBarTextField(viewModel: MainModelView) {
|
||||
val query = remember { mutableStateOf("") }
|
||||
Column {
|
||||
TextField(
|
||||
value = query.value,
|
||||
onValueChange = {
|
||||
query.value = it
|
||||
viewModel.getTerms(query.value)
|
||||
},
|
||||
placeholder = { Text("Prelož...") },
|
||||
singleLine = true,
|
||||
leadingIcon = { Icon(Icons.Filled.Search, contentDescription = "Search Icon") },
|
||||
trailingIcon = {
|
||||
if (query.value.isNotEmpty()) {
|
||||
IconButton(onClick = {
|
||||
query.value = ""
|
||||
viewModel.clearSearch()
|
||||
}) {
|
||||
Icon(Icons.Filled.Clear, contentDescription = "Clear Text")
|
||||
}
|
||||
}
|
||||
},
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
)
|
||||
|
||||
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) {
|
||||
val terms by viewModel.terms.collectAsState()
|
||||
|
||||
if (terms != null) {
|
||||
SelectionContainer {
|
||||
Column {
|
||||
Row(Modifier.background(Color.Gray)) {
|
||||
TableCell(text = "Anglicky", weight = .5f)
|
||||
TableCell(text = "Slovensky", weight = .5f)
|
||||
}
|
||||
val column1Weight = .5f // 50%
|
||||
val column2Weight = .5f // 50%
|
||||
// The LazyColumn will be our table. Notice the use of the weights below
|
||||
LazyColumn(Modifier.fillMaxSize().padding(0.dp)) {
|
||||
// Here is the header
|
||||
|
||||
items(items = terms!!, itemContent = { t ->
|
||||
|
||||
Row(Modifier.fillMaxWidth()) {
|
||||
TableCell(text = t.string1, weight = column1Weight)
|
||||
TableCell(text = t.string2, weight = column2Weight)
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Composable
|
||||
fun MainView(viewModel: MainModelView = koinInject<MainModelView>(),) {
|
||||
SearchBarTextField(viewModel)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package org.neutrino.ktans.viewmodel
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import models.TermFull
|
||||
import service.TermService
|
||||
import service.TermServiceImpl
|
||||
import service.DatabaseFactory.getTranslationForLanguages
|
||||
import service.SearchType
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
class MainModelView(private val repository: TermServiceImpl): ViewModel() {
|
||||
val terms : StateFlow<List<TermFull>?> get() = _terms
|
||||
private val _terms = MutableStateFlow<List<TermFull>?>(null)
|
||||
|
||||
fun getTerms(term: String) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
var sType = SearchType.START
|
||||
sType = if (term.length > 2) SearchType.START else SearchType.EXACT
|
||||
val trans = getTranslationForLanguages("an","sl") ?: return@launch
|
||||
val transTerms = repository.getTranslationForTerm(term,trans,sType)
|
||||
_terms.value = transTerms
|
||||
|
||||
}
|
||||
}
|
||||
fun clearSearch() {
|
||||
_terms.value = listOf()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package org.neutrino.ktans.viewmodel
|
||||
|
||||
/**
|
||||
* A generic class that holds a value with its loading status.
|
||||
* @param <T>
|
||||
</T> */
|
||||
data class State<out T>(val status: Status, val data: T?, val message: String?)
|
||||
{
|
||||
companion object {
|
||||
fun <T> success(data: T?): State<T> {
|
||||
return State(Status.SUCCESS, data, null)
|
||||
}
|
||||
|
||||
fun <T> empty(): State<T> {
|
||||
return State(Status.SUCCESS, null, null)
|
||||
}
|
||||
|
||||
fun <T> error(msg: String?): State<T> {
|
||||
return State(Status.ERROR, null, msg)
|
||||
}
|
||||
|
||||
fun <T> loading(): State<T> {
|
||||
return State(Status.LOADING, null, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class Status {
|
||||
SUCCESS,
|
||||
ERROR,
|
||||
LOADING
|
||||
}
|
||||
@@ -2,12 +2,15 @@ package org.neutrino.ktans
|
||||
|
||||
import androidx.compose.ui.window.Window
|
||||
import androidx.compose.ui.window.application
|
||||
import service.DatabaseFactory
|
||||
|
||||
fun main() = application {
|
||||
Window(
|
||||
onCloseRequest = ::exitApplication,
|
||||
title = "KTrans",
|
||||
) {
|
||||
DatabaseFactory.connectAndMigrate()
|
||||
DatabaseFactory.connectAll()
|
||||
App()
|
||||
}
|
||||
}
|
||||
@@ -11,16 +11,27 @@ androidx-espresso-core = "3.6.1"
|
||||
androidx-lifecycle = "2.8.4"
|
||||
androidx-material = "1.12.0"
|
||||
androidx-test-junit = "1.2.1"
|
||||
androidxLifecycleLivedataKtx = "2.6.1"
|
||||
androidxRuntimeLivedata = "x.x.x"
|
||||
assertjVersion = "3.26.3"
|
||||
compose-multiplatform = "1.7.0"
|
||||
coreKtx = "1.9.0"
|
||||
exposedVersion = "0.55.0"
|
||||
flywayVersion = "10.20.1"
|
||||
h2 = "2.3.232"
|
||||
hikariCpVersion = "5.1.0"
|
||||
koin = "4.0.2"
|
||||
koin-bom = "4.0.2"
|
||||
koinComposeMultiplatform = "4.0.2"
|
||||
koin-compose = "1.0.4"
|
||||
hiltNavigationCompose = "1.2.0"
|
||||
junit = "4.13.2"
|
||||
junitVersion = "5.11.3"
|
||||
kformat = "0.11"
|
||||
koinAndroidxCompose = "4.0.2)"
|
||||
koinCore = "3.1.2"
|
||||
kotlin = "2.1.0"
|
||||
ksp = "2.1.0-1.0.29"
|
||||
kotlinSerializationCompilerPluginEmbeddable = "1.9.22"
|
||||
kotlinx-coroutines = "1.9.0"
|
||||
kotlinxSerializationCore = "1.8.0"
|
||||
@@ -45,12 +56,38 @@ ktorServerCore = "3.0.2"
|
||||
ktorServerCors = "3.0.2"
|
||||
ktorServerNetty = "3.0.2"
|
||||
ktorServerRequestValidation = "3.0.2"
|
||||
lifecycleLivedataCore = "2.8.7"
|
||||
lifecycleLivedataKtx = "2.8.7"
|
||||
lifecycleLivedataKtxVersion = "x.x.x"
|
||||
lifecycleRuntimeCompose = "2.8.7"
|
||||
lifecycle = "2.3.1"
|
||||
lifecycleRuntimeComposeVersion = "2.6.1"
|
||||
lifecycleViewmodelKtx = "2.6.1"
|
||||
lifecycleViewmodelCompose = "2.8.4"
|
||||
logback = "1.5.12"
|
||||
material = "1.7.6"
|
||||
psqlVersion = "42.7.4"
|
||||
restAssuredVersion = "5.5.0"
|
||||
runtimeLivedata = "1.7.6"
|
||||
runtimeLivedataVersion = "1.0.0-beta01"
|
||||
symbolProcessingApi = "2.1.0-1.0.29"
|
||||
lifecycleLivedataCoreKtx = "2.8.7"
|
||||
|
||||
[libraries]
|
||||
androidx-core-ktx-v190 = { module = "androidx.core:core-ktx", version.ref = "coreKtx" }
|
||||
androidx-lifecycle-livedata-core = { module = "androidx.lifecycle:lifecycle-livedata-core", version.ref = "lifecycleLivedataCore" }
|
||||
androidx-lifecycle-livedata-ktx-v261 = { module = "androidx.lifecycle:lifecycle-livedata-ktx", version.ref = "androidxLifecycleLivedataKtx" }
|
||||
androidx-lifecycle-livedata-ktx-v287 = { module = "androidx.lifecycle:lifecycle-livedata-ktx", version.ref = "lifecycleLivedataKtx" }
|
||||
androidx-lifecycle-livedata-ktx-vxxx = { module = "androidx.lifecycle:lifecycle-livedata-ktx", version.ref = "lifecycleLivedataKtxVersion" }
|
||||
androidx-lifecycle-runtime-compose-v261 = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycleRuntimeComposeVersion" }
|
||||
androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidxLifecycleLivedataKtx" }
|
||||
androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycleViewmodelCompose" }
|
||||
androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleLivedataCore" }
|
||||
androidx-lifecycle-viewmodel-ktx-v261 = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" }
|
||||
androidx-lifecycle-viewmodel-savedstate = { module = "androidx.lifecycle:lifecycle-viewmodel-savedstate", version.ref = "androidxLifecycleLivedataKtx" }
|
||||
androidx-runtime-livedata = { module = "androidx.compose.runtime:runtime-livedata", version.ref = "runtimeLivedata" }
|
||||
androidx-runtime-livedata-v100beta01 = { module = "androidx.compose.runtime:runtime-livedata", version.ref = "runtimeLivedataVersion" }
|
||||
androidx-runtime-livedata-vxxx = { module = "androidx.compose.runtime:runtime-livedata", version.ref = "androidxRuntimeLivedata" }
|
||||
assertj-core = { module = "org.assertj:assertj-core", version.ref = "assertjVersion" }
|
||||
exposed-core = { module = "org.jetbrains.exposed:exposed-core", version.ref = "exposedVersion" }
|
||||
exposed-dao = { module = "org.jetbrains.exposed:exposed-dao", version.ref = "exposedVersion" }
|
||||
@@ -59,17 +96,23 @@ exposed-json = { module = "org.jetbrains.exposed:exposed-json", version.ref = "e
|
||||
flyway-core = { module = "org.flywaydb:flyway-core", version.ref = "flywayVersion" }
|
||||
h2 = { module = "com.h2database:h2", version.ref = "h2" }
|
||||
hikaricp = { module = "com.zaxxer:HikariCP", version.ref = "hikariCpVersion" }
|
||||
insert-koin-koin-compose = { module = "io.insert-koin:koin-compose" }
|
||||
io-ktor-ktor-server-core = { module = "io.ktor:ktor-server-core", version.ref = "ktor" }
|
||||
io-ktor-ktor-server-netty = { module = "io.ktor:ktor-server-netty" }
|
||||
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junitVersion" }
|
||||
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junitVersion" }
|
||||
kformat = { module = "de.m3y.kformat:kformat", version.ref = "kformat" }
|
||||
|
||||
|
||||
koin-compose = { module = "io.insert-koin:koin-compose" }
|
||||
koin-compose-viewmodel = { module = "io.insert-koin:koin-compose-viewmodel", version.ref = "koinComposeMultiplatform" }
|
||||
kotlin-serialization-compiler-plugin-embeddable = { module = "org.jetbrains.kotlin:kotlin-serialization-compiler-plugin-embeddable", version.ref = "kotlinSerializationCompilerPluginEmbeddable" }
|
||||
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
|
||||
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
|
||||
kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" }
|
||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "androidx-core-ktx" }
|
||||
androidx-lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "lifecycle" }
|
||||
androidx-test-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-junit" }
|
||||
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "androidx-espresso-core" }
|
||||
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidx-appcompat" }
|
||||
@@ -113,6 +156,8 @@ ktor-server-netty-v302 = { module = "io.ktor:ktor-server-netty", version.ref = "
|
||||
ktor-server-request-validation = { module = "io.ktor:ktor-server-request-validation", version.ref = "ktorServerRequestValidation" }
|
||||
ktor-server-test-host-jvm = { module = "io.ktor:ktor-server-test-host-jvm" }
|
||||
ktor-server-websockets = { module = "io.ktor:ktor-server-websockets", version.ref = "ktor" }
|
||||
lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycleRuntimeCompose" }
|
||||
lifecycle-viewmodel-compose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycleViewmodelCompose" }
|
||||
logback = { module = "ch.qos.logback:logback-classic", version.ref = "logback" }
|
||||
ktor-server-core = { module = "io.ktor:ktor-server-core-jvm", version.ref = "ktor" }
|
||||
ktor-server-netty = { module = "io.ktor:ktor-server-netty-jvm", version.ref = "ktor" }
|
||||
@@ -120,6 +165,10 @@ ktor-server-tests = { module = "io.ktor:ktor-server-tests-jvm", version.ref = "k
|
||||
material = { module = "androidx.compose.material:material", version.ref = "material" }
|
||||
postgresql = { module = "org.postgresql:postgresql", version.ref = "psqlVersion" }
|
||||
rest-assured = { module = "io.rest-assured:rest-assured", version.ref = "restAssuredVersion" }
|
||||
symbol-processing-api = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "symbolProcessingApi" }
|
||||
koin-bom = { module = "io.insert-koin:koin-bom", version.ref = "koin-bom" }
|
||||
koin-core = { module = "io.insert-koin:koin-core" }
|
||||
androidx-lifecycle-livedata-core-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-core-ktx", version.ref = "lifecycleLivedataCoreKtx" }
|
||||
|
||||
[plugins]
|
||||
androidApplication = { id = "com.android.application", version.ref = "agp" }
|
||||
|
||||
@@ -3,6 +3,8 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
|
||||
|
||||
|
||||
|
||||
val ktorVersion = "3.0.2"
|
||||
val exposedVersion = "0.55.0"
|
||||
val h2Version = "2.3.232"
|
||||
@@ -18,7 +20,6 @@ plugins {
|
||||
alias(libs.plugins.kotlinMultiplatform)
|
||||
alias(libs.plugins.androidLibrary)
|
||||
kotlin("plugin.serialization")
|
||||
|
||||
}
|
||||
|
||||
repositories {
|
||||
@@ -94,6 +95,8 @@ kotlin {
|
||||
implementation(libs.flyway.core)
|
||||
implementation(libs.logback)
|
||||
implementation(libs.kformat)
|
||||
implementation(project.dependencies.platform(libs.koin.bom))
|
||||
implementation(libs.koin.core)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user