diff --git a/CHANGELOG.md b/CHANGELOG.md index 60ec2d06892..778de2ec70a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 0.12.13 + +* `Coroutines`: + * Add opportunity to use markers in actors (solution of [#160](https://github.com/InsanusMokrassar/MicroUtils/issues/160)) +* `Koin`: + * Module inited :) +* `Repos`: + * `Android`: + * Add typealias `KeyValueSPRepo` and opportunity to create shared preferences `KeyValue` repo with `KeyValueStore(...)` (fix of [#155](https://github.com/InsanusMokrassar/MicroUtils/issues/155)) + ## 0.12.12 * `Common`: diff --git a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/Actor.kt b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/Actor.kt index b3e641059b8..01c53023e97 100644 --- a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/Actor.kt +++ b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/Actor.kt @@ -1,28 +1,27 @@ package dev.inmo.micro_utils.coroutines -import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.* import kotlinx.coroutines.channels.Channel -import kotlinx.coroutines.launch +import kotlinx.coroutines.flow.consumeAsFlow fun CoroutineScope.actor( channelCapacity: Int = Channel.UNLIMITED, + markerFactory: suspend (T) -> Any? = { null }, block: suspend (T) -> Unit ): Channel { val channel = Channel(channelCapacity) - launch { - for (data in channel) { - block(data) - } - } + channel.consumeAsFlow().subscribeAsync(this, markerFactory, block) return channel } inline fun CoroutineScope.safeActor( channelCapacity: Int = Channel.UNLIMITED, noinline onException: ExceptionHandler = defaultSafelyExceptionHandler, + noinline markerFactory: suspend (T) -> Any? = { null }, crossinline block: suspend (T) -> Unit ): Channel = actor( - channelCapacity + channelCapacity, + markerFactory ) { safely(onException) { block(it) diff --git a/gradle.properties b/gradle.properties index 3951f3c7e6e..0ace4b26bc3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,5 +14,5 @@ crypto_js_version=4.1.1 # Project data group=dev.inmo -version=0.12.12 -android_code_version=151 +version=0.12.13 +android_code_version=152 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 57445abebbf..13617be09b3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,6 +15,8 @@ ktor = "2.1.1" gh-release = "2.4.1" +koin = "3.2.0" + android-gradle = "7.2.2" dexcount = "3.1.0" @@ -31,6 +33,7 @@ android-props-buildTools = "32.0.0" [libraries] kt-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kt" } +kt-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kt" } kt-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kt-serialization" } kt-serialization-cbor = { module = "org.jetbrains.kotlinx:kotlinx-serialization-cbor", version.ref = "kt-serialization" } @@ -59,6 +62,7 @@ ktor-server-content-negotiation = { module = "io.ktor:ktor-server-content-negoti klock = { module = "com.soywiz.korlibs.klock:klock", version.ref = "klock" } uuid = { module = "com.benasher44:uuid", version.ref = "uuid" } +koin = { module = "io.insert-koin:koin-core", version.ref = "koin" } jb-exposed = { module = "org.jetbrains.exposed:exposed-core", version.ref = "jb-exposed" } diff --git a/koin/build.gradle b/koin/build.gradle new file mode 100644 index 00000000000..ecb3b5dcc29 --- /dev/null +++ b/koin/build.gradle @@ -0,0 +1,28 @@ +plugins { + id "org.jetbrains.kotlin.multiplatform" + id "org.jetbrains.kotlin.plugin.serialization" + id "com.android.library" +} + +apply from: "$mppProjectWithSerializationPresetPath" + +kotlin { + sourceSets { + commonMain { + dependencies { + api libs.koin + api libs.uuid + } + } + jvmMain { + dependencies { + api libs.kt.reflect + } + } + androidMain { + dependencies { + api libs.kt.reflect + } + } + } +} diff --git a/koin/src/commonMain/kotlin/FactoryWithRandomQualifier.kt b/koin/src/commonMain/kotlin/FactoryWithRandomQualifier.kt new file mode 100644 index 00000000000..e00675e1ff8 --- /dev/null +++ b/koin/src/commonMain/kotlin/FactoryWithRandomQualifier.kt @@ -0,0 +1,12 @@ +package dev.inmo.micro_utils.koin + +import org.koin.core.definition.Definition +import org.koin.core.module.Module + +/** + * Will be useful in case you need to declare some singles with one type several types, but need to separate them and do + * not care about how :) + */ +inline fun Module.factoryWithRandomQualifier( + noinline definition: Definition +) = factory(RandomQualifier(), definition) diff --git a/koin/src/commonMain/kotlin/FactoryWithStringQualifier.kt b/koin/src/commonMain/kotlin/FactoryWithStringQualifier.kt new file mode 100644 index 00000000000..0bf7301b107 --- /dev/null +++ b/koin/src/commonMain/kotlin/FactoryWithStringQualifier.kt @@ -0,0 +1,12 @@ +package dev.inmo.micro_utils.koin + +import org.koin.core.definition.Definition +import org.koin.core.module.Module +import org.koin.core.qualifier.StringQualifier + +inline fun Module.factory( + qualifier: String, + noinline definition: Definition +) = factory(StringQualifier(qualifier), definition) + + diff --git a/koin/src/commonMain/kotlin/GetAllDistinct.kt b/koin/src/commonMain/kotlin/GetAllDistinct.kt new file mode 100644 index 00000000000..59a610217cb --- /dev/null +++ b/koin/src/commonMain/kotlin/GetAllDistinct.kt @@ -0,0 +1,8 @@ +package dev.inmo.micro_utils.koin + +import org.koin.core.Koin +import org.koin.core.scope.Scope + +inline fun Scope.getAllDistinct() = getAll().distinct() +inline fun Koin.getAllDistinct() = getAll().distinct() + diff --git a/koin/src/commonMain/kotlin/GetAny.kt b/koin/src/commonMain/kotlin/GetAny.kt new file mode 100644 index 00000000000..351a1272fe0 --- /dev/null +++ b/koin/src/commonMain/kotlin/GetAny.kt @@ -0,0 +1,8 @@ +package dev.inmo.micro_utils.koin + +import org.koin.core.Koin +import org.koin.core.scope.Scope + +inline fun Scope.getAny() = getAll().first() +inline fun Koin.getAny() = getAll().first() + diff --git a/koin/src/commonMain/kotlin/RandomQualifier.kt b/koin/src/commonMain/kotlin/RandomQualifier.kt new file mode 100644 index 00000000000..9b5b1a39c62 --- /dev/null +++ b/koin/src/commonMain/kotlin/RandomQualifier.kt @@ -0,0 +1,6 @@ +package dev.inmo.micro_utils.koin + +import com.benasher44.uuid.uuid4 +import org.koin.core.qualifier.StringQualifier + +fun RandomQualifier(randomFun: () -> String = { uuid4().toString() }) = StringQualifier(randomFun()) diff --git a/koin/src/commonMain/kotlin/SingleWithRandomQualifier.kt b/koin/src/commonMain/kotlin/SingleWithRandomQualifier.kt new file mode 100644 index 00000000000..ef7068076e2 --- /dev/null +++ b/koin/src/commonMain/kotlin/SingleWithRandomQualifier.kt @@ -0,0 +1,13 @@ +package dev.inmo.micro_utils.koin + +import org.koin.core.definition.Definition +import org.koin.core.module.Module + +/** + * Will be useful in case you need to declare some singles with one type several types, but need to separate them and do + * not care about how :) + */ +inline fun Module.singleWithRandomQualifier( + createdAtStart: Boolean = false, + noinline definition: Definition +) = single(RandomQualifier(), createdAtStart, definition) diff --git a/koin/src/commonMain/kotlin/SingleWithStringQualifier.kt b/koin/src/commonMain/kotlin/SingleWithStringQualifier.kt new file mode 100644 index 00000000000..cdde37efcca --- /dev/null +++ b/koin/src/commonMain/kotlin/SingleWithStringQualifier.kt @@ -0,0 +1,12 @@ +package dev.inmo.micro_utils.koin + +import org.koin.core.definition.Definition +import org.koin.core.module.Module +import org.koin.core.qualifier.StringQualifier + +inline fun Module.single( + qualifier: String, + createdAtStart: Boolean = false, + noinline definition: Definition +) = single(StringQualifier(qualifier), createdAtStart, definition) + diff --git a/koin/src/jvmMain/kotlin/FactoryWithBinds.kt b/koin/src/jvmMain/kotlin/FactoryWithBinds.kt new file mode 100644 index 00000000000..de91acff060 --- /dev/null +++ b/koin/src/jvmMain/kotlin/FactoryWithBinds.kt @@ -0,0 +1,27 @@ +package dev.inmo.micro_utils.koin + +import org.koin.core.definition.Definition +import org.koin.core.instance.InstanceFactory +import org.koin.core.module.Module +import org.koin.core.qualifier.Qualifier +import org.koin.dsl.binds +import kotlin.reflect.KClass +import kotlin.reflect.full.allSuperclasses + + +inline fun Module.factoryWithBinds( + qualifier: Qualifier? = null, + bindFilter: (KClass<*>) -> Boolean = { true }, + noinline definition: Definition +): Pair> { + return factory(qualifier, definition) binds (T::class.allSuperclasses.filter(bindFilter).toTypedArray()) +} + +inline fun Module.factoryWithBinds( + qualifier: String, + bindFilter: (KClass<*>) -> Boolean = { true }, + noinline definition: Definition +): Pair> { + return factory(qualifier, definition) binds (T::class.allSuperclasses.filter(bindFilter).toTypedArray()) +} + diff --git a/koin/src/jvmMain/kotlin/FactoryWithBindsAndRandomQualifier.kt b/koin/src/jvmMain/kotlin/FactoryWithBindsAndRandomQualifier.kt new file mode 100644 index 00000000000..6231bec8b40 --- /dev/null +++ b/koin/src/jvmMain/kotlin/FactoryWithBindsAndRandomQualifier.kt @@ -0,0 +1,13 @@ +package dev.inmo.micro_utils.koin + +import org.koin.core.definition.Definition +import org.koin.core.instance.InstanceFactory +import org.koin.core.module.Module +import kotlin.reflect.KClass + +inline fun Module.factoryWithRandomQualifierAndBinds( + bindFilter: (KClass<*>) -> Boolean = { true }, + noinline definition: Definition +): Pair> { + return factoryWithBinds(RandomQualifier(), bindFilter, definition) +} diff --git a/koin/src/jvmMain/kotlin/SignleWithBinds.kt b/koin/src/jvmMain/kotlin/SignleWithBinds.kt new file mode 100644 index 00000000000..091ad6a8ca6 --- /dev/null +++ b/koin/src/jvmMain/kotlin/SignleWithBinds.kt @@ -0,0 +1,30 @@ +package dev.inmo.micro_utils.koin + +import org.koin.core.definition.Definition +import org.koin.core.instance.InstanceFactory +import org.koin.core.module.Module +import org.koin.core.qualifier.Qualifier +import org.koin.dsl.binds +import kotlin.reflect.KClass +import kotlin.reflect.full.allSuperclasses + + +inline fun Module.singleWithBinds( + qualifier: Qualifier? = null, + createdAtStart: Boolean = false, + bindFilter: (KClass<*>) -> Boolean = { true }, + noinline definition: Definition +): Pair> { + return single(qualifier, createdAtStart, definition) binds (T::class.allSuperclasses.filter(bindFilter).toTypedArray()) +} + + +inline fun Module.singleWithBinds( + qualifier: String, + createdAtStart: Boolean = false, + bindFilter: (KClass<*>) -> Boolean = { true }, + noinline definition: Definition +): Pair> { + return single(qualifier, createdAtStart, definition) binds (T::class.allSuperclasses.filter(bindFilter).toTypedArray()) +} + diff --git a/koin/src/jvmMain/kotlin/SingleWithBindsAndRandomQualifier.kt b/koin/src/jvmMain/kotlin/SingleWithBindsAndRandomQualifier.kt new file mode 100644 index 00000000000..3839a1dd1c3 --- /dev/null +++ b/koin/src/jvmMain/kotlin/SingleWithBindsAndRandomQualifier.kt @@ -0,0 +1,14 @@ +package dev.inmo.micro_utils.koin + +import org.koin.core.definition.Definition +import org.koin.core.instance.InstanceFactory +import org.koin.core.module.Module +import kotlin.reflect.KClass + +inline fun Module.singleWithRandomQualifierAndBinds( + createdAtStart: Boolean = false, + bindFilter: (KClass<*>) -> Boolean = { true }, + noinline definition: Definition +): Pair> { + return singleWithBinds(RandomQualifier(), createdAtStart, bindFilter, definition) +} diff --git a/koin/src/main/AndroidManifest.xml b/koin/src/main/AndroidManifest.xml new file mode 100644 index 00000000000..a96d3e1aa05 --- /dev/null +++ b/koin/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/repos/common/src/main/kotlin/dev/inmo/micro_utils/repos/keyvalue/KeyValueStore.kt b/repos/common/src/main/kotlin/dev/inmo/micro_utils/repos/keyvalue/KeyValueStore.kt index ccbc93fe0b7..1e5dda1a78f 100644 --- a/repos/common/src/main/kotlin/dev/inmo/micro_utils/repos/keyvalue/KeyValueStore.kt +++ b/repos/common/src/main/kotlin/dev/inmo/micro_utils/repos/keyvalue/KeyValueStore.kt @@ -17,7 +17,7 @@ fun Context.keyValueStore( ): KeyValueRepo { @Suppress("UNCHECKED_CAST") return cache.getOrPut(name) { - KeyValueStore(this, name, cacheValues) + KeyValueStore(c = this, preferencesName = name, useCache = cacheValues) } as KeyValueStore } @@ -149,6 +149,14 @@ class KeyValueStore internal constructor ( _onValueRemovedFlow.emit(it) } } + + companion object { + operator fun invoke( + context: Context, + name: String = "default", + cacheValues: Boolean = false + ) = context.keyValueStore(name, cacheValues) + } } inline fun SharedPreferencesKeyValueRepo( @@ -156,3 +164,5 @@ inline fun SharedPreferencesKeyValueRepo( name: String = "default", cacheValues: Boolean = false ) = context.keyValueStore(name, cacheValues) + +typealias KeyValueSPRepo = KeyValueStore diff --git a/settings.gradle b/settings.gradle index d7471ac4ccc..ccd2dc06d84 100644 --- a/settings.gradle +++ b/settings.gradle @@ -5,6 +5,7 @@ String[] includes = [ ":common:compose", ":matrix", ":crypto", + ":koin", ":selector:common", ":pagination:common", ":pagination:exposed",