mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2025-09-17 14:29:24 +00:00
Compare commits
32 Commits
Author | SHA1 | Date | |
---|---|---|---|
10e03bb951 | |||
aa4f392948 | |||
f51b59ec02 | |||
8c76834ae4 | |||
4a454f3d67 | |||
151aa1863d | |||
3bf6896296 | |||
0d01561476 | |||
f6ded92251 | |||
d01b735cc6 | |||
6c12001080 | |||
1afbf03606 | |||
f6ef5c61c5 | |||
c18fee8107 | |||
d9df7a4384 | |||
87c2230e8e | |||
da7eb6de0a | |||
ed3815118f | |||
be726f42bd | |||
a91006132f | |||
9a9f741a0b | |||
5028f130e9 | |||
77fa019651 | |||
9715da9384 | |||
f6d5035c1a | |||
43e782ab6f | |||
f3f9920bfb | |||
2bfd615812 | |||
ebfacb3659 | |||
c71d557eec | |||
e0398cef21 | |||
f91599e9c6 |
33
CHANGELOG.md
33
CHANGELOG.md
@@ -1,5 +1,38 @@
|
||||
# Changelog
|
||||
|
||||
## 0.20.22
|
||||
|
||||
* `Common`:
|
||||
* Add opportunity to create own `Diff` with base constructor
|
||||
|
||||
## 0.20.21
|
||||
|
||||
* `Resources`:
|
||||
* Inited
|
||||
|
||||
## 0.20.20
|
||||
|
||||
* `Repos`:
|
||||
* `Exposed`:
|
||||
* Add opportunity for setup flows in `AbstractExposedCRUDRepo`
|
||||
|
||||
## 0.20.19
|
||||
|
||||
* `Versions`:
|
||||
* `Ktor`: `2.3.6` -> `2.3.7`
|
||||
|
||||
## 0.20.18
|
||||
|
||||
* `Coroutines`:
|
||||
* `SpecialMutableStateFlow` now extends `MutableStateFlow`
|
||||
* `Compose`:
|
||||
* Deprecate `FlowState` due to its complexity in fixes
|
||||
|
||||
## 0.20.17
|
||||
|
||||
* `Versions`:
|
||||
* `Serialization`: `1.6.1` -> `1.6.2`
|
||||
|
||||
## 0.20.16
|
||||
|
||||
* `Versions`:
|
||||
|
@@ -27,7 +27,7 @@ allprojects {
|
||||
mavenCentral()
|
||||
google()
|
||||
maven { url "https://maven.pkg.jetbrains.space/public/p/compose/dev" }
|
||||
maven { url "https://git.inmo.dev/api/packages/InsanusMokrassar/maven" }
|
||||
maven { url "https://nexus.inmo.dev/repository/maven-releases/" }
|
||||
}
|
||||
|
||||
// temporal crutch until legacy tests will be stabled or legacy target will be removed
|
||||
|
@@ -27,7 +27,7 @@ private inline fun <T> getObject(
|
||||
* @see calculateDiff
|
||||
*/
|
||||
@Serializable
|
||||
data class Diff<T> internal constructor(
|
||||
data class Diff<T> @Warning(warning) constructor(
|
||||
val removed: List<@Serializable(IndexedValueSerializer::class) IndexedValue<T>>,
|
||||
/**
|
||||
* Old-New values pairs
|
||||
@@ -36,6 +36,10 @@ data class Diff<T> internal constructor(
|
||||
val added: List<@Serializable(IndexedValueSerializer::class) IndexedValue<T>>
|
||||
) {
|
||||
fun isEmpty(): Boolean = removed.isEmpty() && replaced.isEmpty() && added.isEmpty()
|
||||
|
||||
companion object {
|
||||
private const val warning = "This feature can be changed without any warranties. Use with caution and only in case you know what you are doing"
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> emptyDiff(): Diff<T> = Diff(emptyList(), emptyList(), emptyList())
|
||||
|
@@ -1,10 +1,7 @@
|
||||
package dev.inmo.micro_utils.coroutines.compose
|
||||
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import dev.inmo.micro_utils.coroutines.SpecialMutableStateFlow
|
||||
import dev.inmo.micro_utils.coroutines.doInUI
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
||||
@@ -12,6 +9,7 @@ import kotlinx.coroutines.Dispatchers
|
||||
* This type works like [MutableState], [kotlinx.coroutines.flow.StateFlow] and [kotlinx.coroutines.flow.MutableSharedFlow].
|
||||
* Based on [SpecialMutableStateFlow]
|
||||
*/
|
||||
@Deprecated("Will be removed soon")
|
||||
class FlowState<T>(
|
||||
initial: T,
|
||||
internalScope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
||||
@@ -25,9 +23,9 @@ class FlowState<T>(
|
||||
tryEmit(value)
|
||||
}
|
||||
|
||||
override suspend fun onChange(value: T) {
|
||||
override fun onChangeWithoutSync(value: T) {
|
||||
internalValue = value
|
||||
super.onChange(value)
|
||||
super.onChangeWithoutSync(value)
|
||||
}
|
||||
|
||||
override fun component1(): T = value
|
||||
|
@@ -3,10 +3,14 @@ package dev.inmo.micro_utils.coroutines
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.InternalCoroutinesApi
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
import kotlinx.coroutines.flow.FlowCollector
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.internal.SynchronizedObject
|
||||
import kotlinx.coroutines.internal.synchronized
|
||||
|
||||
/**
|
||||
* Works like [StateFlow], but guarantee that latest value update will always be delivered to
|
||||
@@ -15,7 +19,9 @@ import kotlinx.coroutines.flow.StateFlow
|
||||
open class SpecialMutableStateFlow<T>(
|
||||
initialValue: T,
|
||||
internalScope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
||||
) : StateFlow<T>, FlowCollector<T>, MutableSharedFlow<T> {
|
||||
) : MutableStateFlow<T>, FlowCollector<T>, MutableSharedFlow<T> {
|
||||
@OptIn(InternalCoroutinesApi::class)
|
||||
private val syncObject = SynchronizedObject()
|
||||
protected val internalSharedFlow: MutableSharedFlow<T> = MutableSharedFlow(
|
||||
replay = 0,
|
||||
extraBufferCapacity = 2,
|
||||
@@ -28,16 +34,13 @@ open class SpecialMutableStateFlow<T>(
|
||||
)
|
||||
|
||||
protected var _value: T = initialValue
|
||||
override val value: T
|
||||
override var value: T
|
||||
get() = _value
|
||||
protected open suspend fun onChange(value: T) {
|
||||
_value = value
|
||||
publicSharedFlow.emit(value)
|
||||
set(value) {
|
||||
doOnChangeAction(value)
|
||||
}
|
||||
protected val job = internalSharedFlow.subscribe(internalScope) {
|
||||
if (_value != it) {
|
||||
onChange(it)
|
||||
}
|
||||
doOnChangeAction(it)
|
||||
}
|
||||
|
||||
override val replayCache: List<T>
|
||||
@@ -45,6 +48,29 @@ open class SpecialMutableStateFlow<T>(
|
||||
override val subscriptionCount: StateFlow<Int>
|
||||
get() = publicSharedFlow.subscriptionCount
|
||||
|
||||
@OptIn(InternalCoroutinesApi::class)
|
||||
override fun compareAndSet(expect: T, update: T): Boolean {
|
||||
return synchronized(syncObject) {
|
||||
if (expect == _value && update != _value) {
|
||||
doOnChangeAction(update)
|
||||
}
|
||||
expect == _value
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun onChangeWithoutSync(value: T) {
|
||||
_value = value
|
||||
publicSharedFlow.tryEmit(value)
|
||||
}
|
||||
@OptIn(InternalCoroutinesApi::class)
|
||||
protected open fun doOnChangeAction(value: T) {
|
||||
synchronized(syncObject) {
|
||||
if (_value != value) {
|
||||
onChangeWithoutSync(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
override fun resetReplayCache() = publicSharedFlow.resetReplayCache()
|
||||
|
||||
|
@@ -6,7 +6,7 @@ kotlin.incremental.js=true
|
||||
#kotlin.experimental.tryK2=true
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
org.gradle.jvmargs=-Xmx2500m
|
||||
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=2g
|
||||
|
||||
# JS NPM
|
||||
|
||||
@@ -15,5 +15,5 @@ crypto_js_version=4.1.1
|
||||
# Project data
|
||||
|
||||
group=dev.inmo
|
||||
version=0.20.16
|
||||
android_code_version=222
|
||||
version=0.20.22
|
||||
android_code_version=228
|
||||
|
@@ -1,7 +1,7 @@
|
||||
[versions]
|
||||
|
||||
kt = "1.9.21"
|
||||
kt-serialization = "1.6.1"
|
||||
kt-serialization = "1.6.2"
|
||||
kt-coroutines = "1.7.3"
|
||||
|
||||
kslog = "1.3.1"
|
||||
@@ -13,7 +13,7 @@ jb-dokka = "1.9.10"
|
||||
korlibs = "4.0.10"
|
||||
uuid = "0.8.2"
|
||||
|
||||
ktor = "2.3.6"
|
||||
ktor = "2.3.7"
|
||||
|
||||
gh-release = "2.4.1"
|
||||
|
||||
@@ -21,12 +21,12 @@ koin = "3.5.0"
|
||||
|
||||
okio = "3.6.0"
|
||||
|
||||
ksp = "1.9.21-1.0.15"
|
||||
kotlin-poet = "1.15.1"
|
||||
ksp = "1.9.21-1.0.16"
|
||||
kotlin-poet = "1.15.3"
|
||||
|
||||
versions = "0.50.0"
|
||||
|
||||
android-gradle = "8.1.4"
|
||||
android-gradle = "8.2.0"
|
||||
dexcount = "4.0.0"
|
||||
|
||||
android-coreKtx = "1.12.0"
|
||||
|
@@ -68,18 +68,14 @@ publishing {
|
||||
|
||||
}
|
||||
}
|
||||
if (project.hasProperty('GITEA_TOKEN') || System.getenv('GITEA_TOKEN') != null) {
|
||||
if ((project.hasProperty('INMONEXUS_USER') || System.getenv('INMONEXUS_USER') != null) && (project.hasProperty('INMONEXUS_PASSWORD') || System.getenv('INMONEXUS_PASSWORD') != null)) {
|
||||
maven {
|
||||
name = "Gitea"
|
||||
url = uri("https://git.inmo.dev/api/packages/InsanusMokrassar/maven")
|
||||
name = "InmoNexus"
|
||||
url = uri("https://nexus.inmo.dev/repository/maven-releases/")
|
||||
|
||||
credentials(HttpHeaderCredentials) {
|
||||
name = "Authorization"
|
||||
value = project.hasProperty('GITEA_TOKEN') ? project.property('GITEA_TOKEN') : System.getenv('GITEA_TOKEN')
|
||||
}
|
||||
|
||||
authentication {
|
||||
header(HttpHeaderAuthentication)
|
||||
credentials {
|
||||
username = project.hasProperty('INMONEXUS_USER') ? project.property('INMONEXUS_USER') : System.getenv('INMONEXUS_USER')
|
||||
password = project.hasProperty('INMONEXUS_PASSWORD') ? project.property('INMONEXUS_PASSWORD') : System.getenv('INMONEXUS_PASSWORD')
|
||||
}
|
||||
|
||||
}
|
||||
@@ -121,4 +117,21 @@ if (project.hasProperty("signing.gnupg.keyName")) {
|
||||
def signingTasks = project.getTasks().withType(Sign.class)
|
||||
mustRunAfter(signingTasks)
|
||||
}
|
||||
// Workaround to make test tasks use sign
|
||||
project.getTasks().withType(Sign.class).configureEach { signTask ->
|
||||
def withoutSign = (signTask.name.startsWith("sign") ? signTask.name.minus("sign") : signTask.name)
|
||||
def pubName = withoutSign.endsWith("Publication") ? withoutSign.substring(0, withoutSign.length() - "Publication".length()) : withoutSign
|
||||
// These tasks only exist for native targets, hence findByName() to avoid trying to find them for other targets
|
||||
|
||||
// Task ':linkDebugTest<platform>' uses this output of task ':sign<platform>Publication' without declaring an explicit or implicit dependency
|
||||
def debugTestTask = tasks.findByName("linkDebugTest$pubName")
|
||||
if (debugTestTask != null) {
|
||||
signTask.mustRunAfter(debugTestTask)
|
||||
}
|
||||
// Task ':compileTestKotlin<platform>' uses this output of task ':sign<platform>Publication' without declaring an explicit or implicit dependency
|
||||
def testTask = tasks.findByName("compileTestKotlin$pubName")
|
||||
if (testTask != null) {
|
||||
signTask.mustRunAfter(testTask)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1 +1 @@
|
||||
{"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/MicroUtils/blob/master/LICENSE"}],"mavenConfig":{"name":"${project.name}","description":"It is set of projects with micro tools for avoiding of routines coding","url":"https://github.com/InsanusMokrassar/MicroUtils/","vcsUrl":"https://github.com/InsanusMokrassar/MicroUtils.git","developers":[{"id":"InsanusMokrassar","name":"Aleksei Ovsiannikov","eMail":"ovsyannikov.alexey95@gmail.com"},{"id":"000Sanya","name":"Syrov Aleksandr","eMail":"000sanya.000sanya@gmail.com"}],"repositories":[{"name":"GithubPackages","url":"https://maven.pkg.github.com/InsanusMokrassar/MicroUtils"},{"name":"Gitea","url":"https://git.inmo.dev/api/packages/InsanusMokrassar/maven","credsType":{"type":"dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository.CredentialsType.HttpHeaderCredentials","headerName":"Authorization","headerValueProperty":"GITEA_TOKEN"}},{"name":"sonatype","url":"https://oss.sonatype.org/service/local/staging/deploy/maven2/"}],"gpgSigning":{"type":"dev.inmo.kmppscriptbuilder.core.models.GpgSigning.Optional"}},"type":"JVM"}
|
||||
{"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/MicroUtils/blob/master/LICENSE"}],"mavenConfig":{"name":"${project.name}","description":"It is set of projects with micro tools for avoiding of routines coding","url":"https://github.com/InsanusMokrassar/MicroUtils/","vcsUrl":"https://github.com/InsanusMokrassar/MicroUtils.git","developers":[{"id":"InsanusMokrassar","name":"Aleksei Ovsiannikov","eMail":"ovsyannikov.alexey95@gmail.com"},{"id":"000Sanya","name":"Syrov Aleksandr","eMail":"000sanya.000sanya@gmail.com"}],"repositories":[{"name":"GithubPackages","url":"https://maven.pkg.github.com/InsanusMokrassar/MicroUtils"},{"name":"InmoNexus","url":"https://nexus.inmo.dev/repository/maven-releases/"},{"name":"sonatype","url":"https://oss.sonatype.org/service/local/staging/deploy/maven2/"}],"gpgSigning":{"type":"dev.inmo.kmppscriptbuilder.core.models.GpgSigning.Optional"}},"type":"JVM"}
|
@@ -57,18 +57,14 @@ publishing {
|
||||
|
||||
}
|
||||
}
|
||||
if (project.hasProperty('GITEA_TOKEN') || System.getenv('GITEA_TOKEN') != null) {
|
||||
if ((project.hasProperty('INMONEXUS_USER') || System.getenv('INMONEXUS_USER') != null) && (project.hasProperty('INMONEXUS_PASSWORD') || System.getenv('INMONEXUS_PASSWORD') != null)) {
|
||||
maven {
|
||||
name = "Gitea"
|
||||
url = uri("https://git.inmo.dev/api/packages/InsanusMokrassar/maven")
|
||||
name = "InmoNexus"
|
||||
url = uri("https://nexus.inmo.dev/repository/maven-releases/")
|
||||
|
||||
credentials(HttpHeaderCredentials) {
|
||||
name = "Authorization"
|
||||
value = project.hasProperty('GITEA_TOKEN') ? project.property('GITEA_TOKEN') : System.getenv('GITEA_TOKEN')
|
||||
}
|
||||
|
||||
authentication {
|
||||
header(HttpHeaderAuthentication)
|
||||
credentials {
|
||||
username = project.hasProperty('INMONEXUS_USER') ? project.property('INMONEXUS_USER') : System.getenv('INMONEXUS_USER')
|
||||
password = project.hasProperty('INMONEXUS_PASSWORD') ? project.property('INMONEXUS_PASSWORD') : System.getenv('INMONEXUS_PASSWORD')
|
||||
}
|
||||
|
||||
}
|
||||
@@ -109,4 +105,21 @@ if (project.hasProperty("signing.gnupg.keyName")) {
|
||||
def signingTasks = project.getTasks().withType(Sign.class)
|
||||
mustRunAfter(signingTasks)
|
||||
}
|
||||
// Workaround to make test tasks use sign
|
||||
project.getTasks().withType(Sign.class).configureEach { signTask ->
|
||||
def withoutSign = (signTask.name.startsWith("sign") ? signTask.name.minus("sign") : signTask.name)
|
||||
def pubName = withoutSign.endsWith("Publication") ? withoutSign.substring(0, withoutSign.length() - "Publication".length()) : withoutSign
|
||||
// These tasks only exist for native targets, hence findByName() to avoid trying to find them for other targets
|
||||
|
||||
// Task ':linkDebugTest<platform>' uses this output of task ':sign<platform>Publication' without declaring an explicit or implicit dependency
|
||||
def debugTestTask = tasks.findByName("linkDebugTest$pubName")
|
||||
if (debugTestTask != null) {
|
||||
signTask.mustRunAfter(debugTestTask)
|
||||
}
|
||||
// Task ':compileTestKotlin<platform>' uses this output of task ':sign<platform>Publication' without declaring an explicit or implicit dependency
|
||||
def testTask = tasks.findByName("compileTestKotlin$pubName")
|
||||
if (testTask != null) {
|
||||
signTask.mustRunAfter(testTask)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1 +1 @@
|
||||
{"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/MicroUtils/blob/master/LICENSE"}],"mavenConfig":{"name":"${project.name}","description":"It is set of projects with micro tools for avoiding of routines coding","url":"https://github.com/InsanusMokrassar/MicroUtils/","vcsUrl":"https://github.com/InsanusMokrassar/MicroUtils.git","developers":[{"id":"InsanusMokrassar","name":"Aleksei Ovsiannikov","eMail":"ovsyannikov.alexey95@gmail.com"},{"id":"000Sanya","name":"Syrov Aleksandr","eMail":"000sanya.000sanya@gmail.com"}],"repositories":[{"name":"GithubPackages","url":"https://maven.pkg.github.com/InsanusMokrassar/MicroUtils"},{"name":"Gitea","url":"https://git.inmo.dev/api/packages/InsanusMokrassar/maven","credsType":{"type":"dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository.CredentialsType.HttpHeaderCredentials","headerName":"Authorization","headerValueProperty":"GITEA_TOKEN"}},{"name":"sonatype","url":"https://oss.sonatype.org/service/local/staging/deploy/maven2/"}],"gpgSigning":{"type":"dev.inmo.kmppscriptbuilder.core.models.GpgSigning.Optional"}}}
|
||||
{"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/MicroUtils/blob/master/LICENSE"}],"mavenConfig":{"name":"${project.name}","description":"It is set of projects with micro tools for avoiding of routines coding","url":"https://github.com/InsanusMokrassar/MicroUtils/","vcsUrl":"https://github.com/InsanusMokrassar/MicroUtils.git","developers":[{"id":"InsanusMokrassar","name":"Aleksei Ovsiannikov","eMail":"ovsyannikov.alexey95@gmail.com"},{"id":"000Sanya","name":"Syrov Aleksandr","eMail":"000sanya.000sanya@gmail.com"}],"repositories":[{"name":"GithubPackages","url":"https://maven.pkg.github.com/InsanusMokrassar/MicroUtils"},{"name":"InmoNexus","url":"https://nexus.inmo.dev/repository/maven-releases/"},{"name":"sonatype","url":"https://oss.sonatype.org/service/local/staging/deploy/maven2/"}],"gpgSigning":{"type":"dev.inmo.kmppscriptbuilder.core.models.GpgSigning.Optional"}}}
|
@@ -1,14 +1,19 @@
|
||||
package dev.inmo.micro_utils.repos.exposed
|
||||
|
||||
import dev.inmo.micro_utils.repos.CRUDRepo
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
|
||||
abstract class AbstractExposedCRUDRepo<ObjectType, IdType, InputValueType>(
|
||||
flowsChannelsSize: Int = 0,
|
||||
tableName: String = ""
|
||||
tableName: String = "",
|
||||
replyCacheInFlows: Int = 0,
|
||||
onBufferOverflowBehaviour: BufferOverflow = BufferOverflow.SUSPEND
|
||||
) :
|
||||
AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
|
||||
flowsChannelsSize,
|
||||
tableName
|
||||
tableName,
|
||||
replyCacheInFlows,
|
||||
onBufferOverflowBehaviour
|
||||
),
|
||||
ExposedCRUDRepo<ObjectType, IdType>,
|
||||
CRUDRepo<ObjectType, IdType, InputValueType>
|
||||
|
@@ -2,6 +2,7 @@ package dev.inmo.micro_utils.repos.exposed
|
||||
|
||||
import dev.inmo.micro_utils.repos.UpdatedValuePair
|
||||
import dev.inmo.micro_utils.repos.WriteCRUDRepo
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
import kotlinx.coroutines.flow.*
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import org.jetbrains.exposed.sql.statements.*
|
||||
@@ -11,19 +12,26 @@ import java.util.Objects
|
||||
abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
|
||||
flowsChannelsSize: Int = 0,
|
||||
tableName: String = "",
|
||||
replyCacheInFlows: Int = 0
|
||||
replyCacheInFlows: Int = 0,
|
||||
onBufferOverflowBehaviour: BufferOverflow = BufferOverflow.SUSPEND
|
||||
) :
|
||||
AbstractExposedReadCRUDRepo<ObjectType, IdType>(tableName),
|
||||
ExposedCRUDRepo<ObjectType, IdType>,
|
||||
WriteCRUDRepo<ObjectType, IdType, InputValueType>
|
||||
{
|
||||
protected val _newObjectsFlow = MutableSharedFlow<ObjectType>(replyCacheInFlows, flowsChannelsSize)
|
||||
protected val _updatedObjectsFlow = MutableSharedFlow<ObjectType>(replyCacheInFlows, flowsChannelsSize)
|
||||
protected val _deletedObjectsIdsFlow = MutableSharedFlow<IdType>(replyCacheInFlows, flowsChannelsSize)
|
||||
protected open val _newObjectsFlow = MutableSharedFlow<ObjectType>(replyCacheInFlows, flowsChannelsSize, onBufferOverflowBehaviour)
|
||||
protected open val _updatedObjectsFlow = MutableSharedFlow<ObjectType>(replyCacheInFlows, flowsChannelsSize, onBufferOverflowBehaviour)
|
||||
protected open val _deletedObjectsIdsFlow = MutableSharedFlow<IdType>(replyCacheInFlows, flowsChannelsSize, onBufferOverflowBehaviour)
|
||||
|
||||
override val newObjectsFlow: Flow<ObjectType> = _newObjectsFlow.asSharedFlow()
|
||||
override val updatedObjectsFlow: Flow<ObjectType> = _updatedObjectsFlow.asSharedFlow()
|
||||
override val deletedObjectsIdsFlow: Flow<IdType> = _deletedObjectsIdsFlow.asSharedFlow()
|
||||
override val newObjectsFlow: Flow<ObjectType> by lazy {
|
||||
_newObjectsFlow.asSharedFlow()
|
||||
}
|
||||
override val updatedObjectsFlow: Flow<ObjectType> by lazy {
|
||||
_updatedObjectsFlow.asSharedFlow()
|
||||
}
|
||||
override val deletedObjectsIdsFlow: Flow<IdType> by lazy {
|
||||
_deletedObjectsIdsFlow.asSharedFlow()
|
||||
}
|
||||
|
||||
protected abstract fun InsertStatement<Number>.asObject(value: InputValueType): ObjectType
|
||||
|
||||
|
21
resources/build.gradle
Normal file
21
resources/build.gradle
Normal file
@@ -0,0 +1,21 @@
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.multiplatform"
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "com.android.library"
|
||||
}
|
||||
|
||||
apply from: "$mppJvmJsAndroidLinuxMingwLinuxArm64ProjectPresetPath"
|
||||
|
||||
kotlin {
|
||||
sourceSets {
|
||||
commonMain {
|
||||
dependencies {
|
||||
api project(":micro_utils.language_codes")
|
||||
}
|
||||
}
|
||||
|
||||
androidMain {
|
||||
dependsOn(jvmMain)
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package dev.inmo.micro_utils.strings
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.content.res.Resources
|
||||
import android.os.Build
|
||||
import dev.inmo.micro_utils.language_codes.toIetfLanguageCode
|
||||
|
||||
fun StringResource.translation(configuration: Configuration): String = translation(
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
configuration.locales[0]
|
||||
} else {
|
||||
configuration.locale
|
||||
}
|
||||
)
|
||||
fun StringResource.translation(resources: Resources): String = translation(resources.configuration)
|
||||
fun StringResource.translation(context: Context): String = translation(context.resources)
|
||||
|
||||
fun Configuration.translation(resource: StringResource): String = resource.translation(this)
|
||||
fun Resources.translation(resource: StringResource): String = configuration.translation(resource)
|
||||
fun Context.translation(resource: StringResource): String = resources.translation(resource)
|
32
resources/src/commonMain/kotlin/StringResource.kt
Normal file
32
resources/src/commonMain/kotlin/StringResource.kt
Normal file
@@ -0,0 +1,32 @@
|
||||
package dev.inmo.micro_utils.strings
|
||||
|
||||
import dev.inmo.micro_utils.language_codes.IetfLanguageCode
|
||||
|
||||
class StringResource(
|
||||
val default: String,
|
||||
val map: Map<IetfLanguageCode, Lazy<String>>
|
||||
) {
|
||||
class Builder(
|
||||
var default: String
|
||||
) {
|
||||
private val map = mutableMapOf<IetfLanguageCode, Lazy<String>>()
|
||||
|
||||
infix fun IetfLanguageCode.variant(value: Lazy<String>) {
|
||||
map[this] = value
|
||||
}
|
||||
infix fun IetfLanguageCode.variant(value: String) = this variant lazyOf(value)
|
||||
infix fun String.variant(value: Lazy<String>) = IetfLanguageCode(this) variant value
|
||||
infix fun String.variant(value: String) = this variant lazyOf(value)
|
||||
|
||||
fun build() = StringResource(default, map.toMap())
|
||||
}
|
||||
|
||||
fun translation(languageCode: IetfLanguageCode): String = (map[languageCode] ?: map[IetfLanguageCode(languageCode.withoutDialect)]) ?.value ?: default
|
||||
}
|
||||
|
||||
inline fun buildStringResource(
|
||||
default: String,
|
||||
builder: StringResource.Builder.() -> Unit
|
||||
): StringResource {
|
||||
return StringResource.Builder(default).apply(builder).build()
|
||||
}
|
10
resources/src/jvmMain/kotlin/StringResourceLocaleGetter.kt
Normal file
10
resources/src/jvmMain/kotlin/StringResourceLocaleGetter.kt
Normal file
@@ -0,0 +1,10 @@
|
||||
package dev.inmo.micro_utils.strings
|
||||
|
||||
import dev.inmo.micro_utils.language_codes.toIetfLanguageCode
|
||||
import java.util.Locale
|
||||
|
||||
fun StringResource.translation(locale: Locale = Locale.getDefault()): String {
|
||||
return translation(locale.toIetfLanguageCode())
|
||||
}
|
||||
|
||||
fun Locale.translation(resource: StringResource): String = resource.translation(this)
|
@@ -43,6 +43,8 @@ String[] includes = [
|
||||
":startup:plugin",
|
||||
":startup:launcher",
|
||||
|
||||
":resources",
|
||||
|
||||
":fsm:common",
|
||||
":fsm:repos:common",
|
||||
|
||||
|
Reference in New Issue
Block a user