mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2024-11-04 15:33:48 +00:00
almost updated dependencies and modules hierarchy
This commit is contained in:
parent
aee4a6243b
commit
a1854b68d8
@ -7,9 +7,6 @@ import androidx.compose.foundation.gestures.*
|
|||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.text.KeyboardActions
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material.ContentAlpha
|
|
||||||
import androidx.compose.material.IconButton
|
|
||||||
import androidx.compose.material.ProvideTextStyle
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.KeyboardArrowDown
|
import androidx.compose.material.icons.filled.KeyboardArrowDown
|
||||||
import androidx.compose.material.icons.filled.KeyboardArrowUp
|
import androidx.compose.material.icons.filled.KeyboardArrowUp
|
||||||
@ -75,7 +72,7 @@ fun NumberPicker(
|
|||||||
}
|
}
|
||||||
val coercedAnimatedOffset = animatedOffset.value % halvedNumbersColumnHeightPx
|
val coercedAnimatedOffset = animatedOffset.value % halvedNumbersColumnHeightPx
|
||||||
val animatedStateValue = animatedStateValue(animatedOffset.value)
|
val animatedStateValue = animatedStateValue(animatedOffset.value)
|
||||||
val disabledArrowsColor = arrowsColor.copy(alpha = ContentAlpha.disabled)
|
val disabledArrowsColor = arrowsColor.copy(alpha = 0f)
|
||||||
|
|
||||||
val inputFieldShown = if (allowUseManualInput) {
|
val inputFieldShown = if (allowUseManualInput) {
|
||||||
remember { mutableStateOf(false) }
|
remember { mutableStateOf(false) }
|
||||||
|
@ -5,7 +5,6 @@ import androidx.compose.animation.core.exponentialDecay
|
|||||||
import androidx.compose.foundation.gestures.*
|
import androidx.compose.foundation.gestures.*
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.material.ContentAlpha
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.KeyboardArrowDown
|
import androidx.compose.material.icons.filled.KeyboardArrowDown
|
||||||
import androidx.compose.material.icons.filled.KeyboardArrowUp
|
import androidx.compose.material.icons.filled.KeyboardArrowUp
|
||||||
@ -62,9 +61,7 @@ fun <T> SetPicker(
|
|||||||
(index - ceil(animatedOffset.value / halvedNumbersColumnHeightPx).toInt())
|
(index - ceil(animatedOffset.value / halvedNumbersColumnHeightPx).toInt())
|
||||||
}
|
}
|
||||||
val coercedAnimatedOffset = animatedOffset.value % halvedNumbersColumnHeightPx
|
val coercedAnimatedOffset = animatedOffset.value % halvedNumbersColumnHeightPx
|
||||||
val boxOffset = (indexAnimatedOffset * halvedNumbersColumnHeightPx) - coercedAnimatedOffset
|
val disabledArrowsColor = arrowsColor.copy(alpha = 0f)
|
||||||
val disabledArrowsColor = arrowsColor.copy(alpha = ContentAlpha.disabled)
|
|
||||||
val scrollState = rememberScrollState()
|
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
|
@ -20,23 +20,11 @@ kotlin {
|
|||||||
}
|
}
|
||||||
androidMain {
|
androidMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
api project(":micro_utils.coroutines")
|
|
||||||
api libs.android.fragment
|
api libs.android.fragment
|
||||||
}
|
}
|
||||||
dependsOn jvmMain
|
|
||||||
}
|
}
|
||||||
|
|
||||||
linuxX64Main {
|
nativeMain {
|
||||||
dependencies {
|
|
||||||
api libs.okio
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mingwX64Main {
|
|
||||||
dependencies {
|
|
||||||
api libs.okio
|
|
||||||
}
|
|
||||||
}
|
|
||||||
linuxArm64Main {
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api libs.okio
|
api libs.okio
|
||||||
}
|
}
|
||||||
|
@ -1 +0,0 @@
|
|||||||
<manifest/>
|
|
@ -8,7 +8,9 @@ import kotlinx.serialization.descriptors.SerialDescriptor
|
|||||||
import kotlinx.serialization.encoding.Decoder
|
import kotlinx.serialization.encoding.Decoder
|
||||||
import kotlinx.serialization.encoding.Encoder
|
import kotlinx.serialization.encoding.Encoder
|
||||||
|
|
||||||
@Serializer(DateTime::class)
|
/**
|
||||||
|
* Serializes [DateTime] as its raw [DateTime.unixMillis] and deserializes in the same way
|
||||||
|
*/
|
||||||
object DateTimeSerializer : KSerializer<DateTime> {
|
object DateTimeSerializer : KSerializer<DateTime> {
|
||||||
override val descriptor: SerialDescriptor
|
override val descriptor: SerialDescriptor
|
||||||
get() = Double.serializer().descriptor
|
get() = Double.serializer().descriptor
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
package dev.inmo.micro_utils.common
|
|
||||||
|
|
||||||
import okio.FileSystem
|
|
||||||
import okio.Path
|
|
||||||
import okio.use
|
|
||||||
|
|
||||||
actual typealias MPPFile = Path
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @suppress
|
|
||||||
*/
|
|
||||||
actual val MPPFile.filename: FileName
|
|
||||||
get() = FileName(toString())
|
|
||||||
/**
|
|
||||||
* @suppress
|
|
||||||
*/
|
|
||||||
actual val MPPFile.filesize: Long
|
|
||||||
get() = FileSystem.SYSTEM.openReadOnly(this).use {
|
|
||||||
it.size()
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @suppress
|
|
||||||
*/
|
|
||||||
actual val MPPFile.bytesAllocatorSync: ByteArrayAllocator
|
|
||||||
get() = {
|
|
||||||
FileSystem.SYSTEM.read(this) {
|
|
||||||
readByteArray()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @suppress
|
|
||||||
*/
|
|
||||||
actual val MPPFile.bytesAllocator: SuspendByteArrayAllocator
|
|
||||||
get() = {
|
|
||||||
bytesAllocatorSync()
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package dev.inmo.micro_utils.common
|
|
||||||
|
|
||||||
import kotlinx.cinterop.*
|
|
||||||
import platform.posix.snprintf
|
|
||||||
import platform.posix.sprintf
|
|
||||||
|
|
||||||
@OptIn(ExperimentalForeignApi::class)
|
|
||||||
actual fun Float.fixed(signs: Int): Float {
|
|
||||||
return memScoped {
|
|
||||||
val buff = allocArray<ByteVar>(Float.SIZE_BYTES * 2)
|
|
||||||
|
|
||||||
sprintf(buff, "%.${signs}f", this@fixed)
|
|
||||||
buff.toKString().toFloat()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalForeignApi::class)
|
|
||||||
actual fun Double.fixed(signs: Int): Double {
|
|
||||||
return memScoped {
|
|
||||||
val buff = allocArray<ByteVar>(Double.SIZE_BYTES * 2)
|
|
||||||
|
|
||||||
sprintf(buff, "%.${signs}f", this@fixed)
|
|
||||||
buff.toKString().toDouble()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
package dev.inmo.micro_utils.common
|
|
||||||
|
|
||||||
import okio.FileSystem
|
|
||||||
import okio.Path
|
|
||||||
import okio.use
|
|
||||||
|
|
||||||
actual typealias MPPFile = Path
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @suppress
|
|
||||||
*/
|
|
||||||
actual val MPPFile.filename: FileName
|
|
||||||
get() = FileName(toString())
|
|
||||||
/**
|
|
||||||
* @suppress
|
|
||||||
*/
|
|
||||||
actual val MPPFile.filesize: Long
|
|
||||||
get() = FileSystem.SYSTEM.openReadOnly(this).use {
|
|
||||||
it.size()
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @suppress
|
|
||||||
*/
|
|
||||||
actual val MPPFile.bytesAllocatorSync: ByteArrayAllocator
|
|
||||||
get() = {
|
|
||||||
FileSystem.SYSTEM.read(this) {
|
|
||||||
readByteArray()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @suppress
|
|
||||||
*/
|
|
||||||
actual val MPPFile.bytesAllocator: SuspendByteArrayAllocator
|
|
||||||
get() = {
|
|
||||||
bytesAllocatorSync()
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package dev.inmo.micro_utils.common
|
|
||||||
|
|
||||||
import kotlinx.cinterop.*
|
|
||||||
import platform.posix.snprintf
|
|
||||||
import platform.posix.sprintf
|
|
||||||
|
|
||||||
@OptIn(ExperimentalForeignApi::class)
|
|
||||||
actual fun Float.fixed(signs: Int): Float {
|
|
||||||
return memScoped {
|
|
||||||
val buff = allocArray<ByteVar>(Float.SIZE_BYTES * 2)
|
|
||||||
|
|
||||||
sprintf(buff, "%.${signs}f", this@fixed)
|
|
||||||
buff.toKString().toFloat()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalForeignApi::class)
|
|
||||||
actual fun Double.fixed(signs: Int): Double {
|
|
||||||
return memScoped {
|
|
||||||
val buff = allocArray<ByteVar>(Double.SIZE_BYTES * 2)
|
|
||||||
|
|
||||||
sprintf(buff, "%.${signs}f", this@fixed)
|
|
||||||
buff.toKString().toDouble()
|
|
||||||
}
|
|
||||||
}
|
|
@ -22,7 +22,6 @@ kotlin {
|
|||||||
dependencies {
|
dependencies {
|
||||||
api libs.kt.coroutines.android
|
api libs.kt.coroutines.android
|
||||||
}
|
}
|
||||||
dependsOn(jvmMain)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,8 @@ class DoWithFirstBuilder<T>(
|
|||||||
operator fun plus(block: suspend CoroutineScope.() -> T) {
|
operator fun plus(block: suspend CoroutineScope.() -> T) {
|
||||||
deferreds.add(scope.async(start = CoroutineStart.LAZY, block = block))
|
deferreds.add(scope.async(start = CoroutineStart.LAZY, block = block))
|
||||||
}
|
}
|
||||||
inline fun add(noinline block: suspend CoroutineScope.() -> T) = plus(block)
|
fun add(block: suspend CoroutineScope.() -> T) = plus(block)
|
||||||
inline fun include(noinline block: suspend CoroutineScope.() -> T) = plus(block)
|
fun include(block: suspend CoroutineScope.() -> T) = plus(block)
|
||||||
|
|
||||||
fun build() = deferreds.toList()
|
fun build() = deferreds.toList()
|
||||||
}
|
}
|
||||||
|
@ -85,32 +85,32 @@ fun <T, M> Flow<T>.subscribeAsync(
|
|||||||
return job
|
return job
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <T, M> Flow<T>.subscribeSafelyAsync(
|
fun <T, M> Flow<T>.subscribeSafelyAsync(
|
||||||
scope: CoroutineScope,
|
scope: CoroutineScope,
|
||||||
noinline markerFactory: suspend (T) -> M,
|
markerFactory: suspend (T) -> M,
|
||||||
noinline onException: ExceptionHandler<Unit> = defaultSafelyExceptionHandler,
|
onException: ExceptionHandler<Unit> = defaultSafelyExceptionHandler,
|
||||||
noinline block: suspend (T) -> Unit
|
block: suspend (T) -> Unit
|
||||||
) = subscribeAsync(scope, markerFactory) {
|
) = subscribeAsync(scope, markerFactory) {
|
||||||
safely(onException) {
|
safely(onException) {
|
||||||
block(it)
|
block(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <T, M> Flow<T>.subscribeSafelyWithoutExceptionsAsync(
|
fun <T, M> Flow<T>.subscribeSafelyWithoutExceptionsAsync(
|
||||||
scope: CoroutineScope,
|
scope: CoroutineScope,
|
||||||
noinline markerFactory: suspend (T) -> M,
|
markerFactory: suspend (T) -> M,
|
||||||
noinline onException: ExceptionHandler<T?> = defaultSafelyWithoutExceptionHandlerWithNull,
|
onException: ExceptionHandler<T?> = defaultSafelyWithoutExceptionHandlerWithNull,
|
||||||
noinline block: suspend (T) -> Unit
|
block: suspend (T) -> Unit
|
||||||
) = subscribeAsync(scope, markerFactory) {
|
) = subscribeAsync(scope, markerFactory) {
|
||||||
safelyWithoutExceptions(onException) {
|
safelyWithoutExceptions(onException) {
|
||||||
block(it)
|
block(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <T, M> Flow<T>.subscribeSafelySkippingExceptionsAsync(
|
fun <T, M> Flow<T>.subscribeSafelySkippingExceptionsAsync(
|
||||||
scope: CoroutineScope,
|
scope: CoroutineScope,
|
||||||
noinline markerFactory: suspend (T) -> M,
|
markerFactory: suspend (T) -> M,
|
||||||
noinline block: suspend (T) -> Unit
|
block: suspend (T) -> Unit
|
||||||
) = subscribeAsync(scope, markerFactory) {
|
) = subscribeAsync(scope, markerFactory) {
|
||||||
safelyWithoutExceptions({ /* do nothing */}) {
|
safelyWithoutExceptions({ /* do nothing */}) {
|
||||||
block(it)
|
block(it)
|
||||||
|
@ -51,7 +51,7 @@ class ContextSafelyExceptionHandler(
|
|||||||
* @see ContextSafelyExceptionHandler
|
* @see ContextSafelyExceptionHandler
|
||||||
* @see ContextSafelyExceptionHandlerKey
|
* @see ContextSafelyExceptionHandlerKey
|
||||||
*/
|
*/
|
||||||
suspend inline fun contextSafelyExceptionHandler() = coroutineContext[ContextSafelyExceptionHandlerKey]
|
suspend fun contextSafelyExceptionHandler() = coroutineContext[ContextSafelyExceptionHandlerKey]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will set new [coroutineContext] with [ContextSafelyExceptionHandler]. In case if [coroutineContext]
|
* This method will set new [coroutineContext] with [ContextSafelyExceptionHandler]. In case if [coroutineContext]
|
||||||
@ -96,9 +96,9 @@ suspend fun <T> safelyWithContextExceptionHandler(
|
|||||||
* @see safelyWithoutExceptions
|
* @see safelyWithoutExceptions
|
||||||
* @see safelyWithContextExceptionHandler
|
* @see safelyWithContextExceptionHandler
|
||||||
*/
|
*/
|
||||||
suspend inline fun <T> safely(
|
suspend fun <T> safely(
|
||||||
noinline onException: ExceptionHandler<T> = defaultSafelyExceptionHandler,
|
onException: ExceptionHandler<T> = defaultSafelyExceptionHandler,
|
||||||
noinline block: suspend CoroutineScope.() -> T
|
block: suspend CoroutineScope.() -> T
|
||||||
): T {
|
): T {
|
||||||
return try {
|
return try {
|
||||||
supervisorScope(block)
|
supervisorScope(block)
|
||||||
@ -108,26 +108,26 @@ suspend inline fun <T> safely(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend inline fun <T> runCatchingSafely(
|
suspend fun <T> runCatchingSafely(
|
||||||
noinline onException: ExceptionHandler<T> = defaultSafelyExceptionHandler,
|
onException: ExceptionHandler<T> = defaultSafelyExceptionHandler,
|
||||||
noinline block: suspend CoroutineScope.() -> T
|
block: suspend CoroutineScope.() -> T
|
||||||
): Result<T> = runCatching {
|
): Result<T> = runCatching {
|
||||||
safely(onException, block)
|
safely(onException, block)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend inline fun <T, R> T.runCatchingSafely(
|
suspend fun <T, R> T.runCatchingSafely(
|
||||||
noinline onException: ExceptionHandler<R> = defaultSafelyExceptionHandler,
|
onException: ExceptionHandler<R> = defaultSafelyExceptionHandler,
|
||||||
noinline block: suspend T.() -> R
|
block: suspend T.() -> R
|
||||||
): Result<R> = runCatching {
|
): Result<R> = runCatching {
|
||||||
safely(onException) { block() }
|
safely(onException) { block() }
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend inline fun <T> safelyWithResult(
|
suspend fun <T> safelyWithResult(
|
||||||
noinline block: suspend CoroutineScope.() -> T
|
block: suspend CoroutineScope.() -> T
|
||||||
): Result<T> = runCatchingSafely(defaultSafelyExceptionHandler, block)
|
): Result<T> = runCatchingSafely(defaultSafelyExceptionHandler, block)
|
||||||
|
|
||||||
suspend inline fun <T, R> T.safelyWithResult(
|
suspend fun <T, R> T.safelyWithResult(
|
||||||
noinline block: suspend T.() -> R
|
block: suspend T.() -> R
|
||||||
): Result<R> = runCatchingSafely(defaultSafelyExceptionHandler, block)
|
): Result<R> = runCatchingSafely(defaultSafelyExceptionHandler, block)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -147,21 +147,21 @@ val defaultSafelyWithoutExceptionHandlerWithNull: ExceptionHandler<Nothing?> = {
|
|||||||
* Shortcut for [safely] with exception handler, that as expected must return null in case of impossible creating of
|
* Shortcut for [safely] with exception handler, that as expected must return null in case of impossible creating of
|
||||||
* result from exception (instead of throwing it, by default always returns null)
|
* result from exception (instead of throwing it, by default always returns null)
|
||||||
*/
|
*/
|
||||||
suspend inline fun <T> safelyWithoutExceptions(
|
suspend fun <T> safelyWithoutExceptions(
|
||||||
noinline onException: ExceptionHandler<T?> = defaultSafelyWithoutExceptionHandlerWithNull,
|
onException: ExceptionHandler<T?> = defaultSafelyWithoutExceptionHandlerWithNull,
|
||||||
noinline block: suspend CoroutineScope.() -> T
|
block: suspend CoroutineScope.() -> T
|
||||||
): T? = safely(onException, block)
|
): T? = safely(onException, block)
|
||||||
|
|
||||||
suspend inline fun <T> runCatchingSafelyWithoutExceptions(
|
suspend fun <T> runCatchingSafelyWithoutExceptions(
|
||||||
noinline onException: ExceptionHandler<T?> = defaultSafelyWithoutExceptionHandlerWithNull,
|
onException: ExceptionHandler<T?> = defaultSafelyWithoutExceptionHandlerWithNull,
|
||||||
noinline block: suspend CoroutineScope.() -> T
|
block: suspend CoroutineScope.() -> T
|
||||||
): Result<T?> = runCatching {
|
): Result<T?> = runCatching {
|
||||||
safelyWithoutExceptions(onException, block)
|
safelyWithoutExceptions(onException, block)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun CoroutineScope(
|
fun CoroutineScope(
|
||||||
context: CoroutineContext,
|
context: CoroutineContext,
|
||||||
noinline defaultExceptionsHandler: ExceptionHandler<Unit>
|
defaultExceptionsHandler: ExceptionHandler<Unit>
|
||||||
) = CoroutineScope(
|
) = CoroutineScope(
|
||||||
context + ContextSafelyExceptionHandler(defaultExceptionsHandler)
|
context + ContextSafelyExceptionHandler(defaultExceptionsHandler)
|
||||||
)
|
)
|
||||||
|
@ -4,38 +4,38 @@ import kotlinx.coroutines.*
|
|||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
import kotlin.coroutines.EmptyCoroutineContext
|
import kotlin.coroutines.EmptyCoroutineContext
|
||||||
|
|
||||||
inline fun CoroutineScope.launchSafely(
|
fun CoroutineScope.launchSafely(
|
||||||
context: CoroutineContext = EmptyCoroutineContext,
|
context: CoroutineContext = EmptyCoroutineContext,
|
||||||
start: CoroutineStart = CoroutineStart.DEFAULT,
|
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||||
noinline onException: ExceptionHandler<Unit> = defaultSafelyExceptionHandler,
|
onException: ExceptionHandler<Unit> = defaultSafelyExceptionHandler,
|
||||||
noinline block: suspend CoroutineScope.() -> Unit
|
block: suspend CoroutineScope.() -> Unit
|
||||||
) = launch(context, start) {
|
) = launch(context, start) {
|
||||||
safely(onException, block)
|
safely(onException, block)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun CoroutineScope.launchSafelyWithoutExceptions(
|
fun CoroutineScope.launchSafelyWithoutExceptions(
|
||||||
context: CoroutineContext = EmptyCoroutineContext,
|
context: CoroutineContext = EmptyCoroutineContext,
|
||||||
start: CoroutineStart = CoroutineStart.DEFAULT,
|
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||||
noinline onException: ExceptionHandler<Unit?> = defaultSafelyWithoutExceptionHandlerWithNull,
|
onException: ExceptionHandler<Unit?> = defaultSafelyWithoutExceptionHandlerWithNull,
|
||||||
noinline block: suspend CoroutineScope.() -> Unit
|
block: suspend CoroutineScope.() -> Unit
|
||||||
) = launch(context, start) {
|
) = launch(context, start) {
|
||||||
safelyWithoutExceptions(onException, block)
|
safelyWithoutExceptions(onException, block)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <T> CoroutineScope.asyncSafely(
|
fun <T> CoroutineScope.asyncSafely(
|
||||||
context: CoroutineContext = EmptyCoroutineContext,
|
context: CoroutineContext = EmptyCoroutineContext,
|
||||||
start: CoroutineStart = CoroutineStart.DEFAULT,
|
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||||
noinline onException: ExceptionHandler<T> = defaultSafelyExceptionHandler,
|
onException: ExceptionHandler<T> = defaultSafelyExceptionHandler,
|
||||||
noinline block: suspend CoroutineScope.() -> T
|
block: suspend CoroutineScope.() -> T
|
||||||
) = async(context, start) {
|
) = async(context, start) {
|
||||||
safely(onException, block)
|
safely(onException, block)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <T> CoroutineScope.asyncSafelyWithoutExceptions(
|
fun <T> CoroutineScope.asyncSafelyWithoutExceptions(
|
||||||
context: CoroutineContext = EmptyCoroutineContext,
|
context: CoroutineContext = EmptyCoroutineContext,
|
||||||
start: CoroutineStart = CoroutineStart.DEFAULT,
|
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||||
noinline onException: ExceptionHandler<T?> = defaultSafelyWithoutExceptionHandlerWithNull,
|
onException: ExceptionHandler<T?> = defaultSafelyWithoutExceptionHandlerWithNull,
|
||||||
noinline block: suspend CoroutineScope.() -> T
|
block: suspend CoroutineScope.() -> T
|
||||||
) = async(context, start) {
|
) = async(context, start) {
|
||||||
safelyWithoutExceptions(onException, block)
|
safelyWithoutExceptions(onException, block)
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.internal.SynchronizedObject
|
import kotlinx.coroutines.internal.SynchronizedObject
|
||||||
import kotlinx.coroutines.internal.synchronized
|
import kotlinx.coroutines.internal.synchronized
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Works like [StateFlow], but guarantee that latest value update will always be delivered to
|
* Works like [StateFlow], but guarantee that latest value update will always be delivered to
|
||||||
@ -18,7 +19,7 @@ import kotlinx.coroutines.internal.synchronized
|
|||||||
*/
|
*/
|
||||||
open class SpecialMutableStateFlow<T>(
|
open class SpecialMutableStateFlow<T>(
|
||||||
initialValue: T,
|
initialValue: T,
|
||||||
internalScope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
internalScope: CoroutineScope
|
||||||
) : MutableStateFlow<T>, FlowCollector<T>, MutableSharedFlow<T> {
|
) : MutableStateFlow<T>, FlowCollector<T>, MutableSharedFlow<T> {
|
||||||
@OptIn(InternalCoroutinesApi::class)
|
@OptIn(InternalCoroutinesApi::class)
|
||||||
private val syncObject = SynchronizedObject()
|
private val syncObject = SynchronizedObject()
|
||||||
@ -37,7 +38,7 @@ open class SpecialMutableStateFlow<T>(
|
|||||||
override var value: T
|
override var value: T
|
||||||
get() = _value
|
get() = _value
|
||||||
set(value) {
|
set(value) {
|
||||||
doOnChangeAction(value)
|
internalSharedFlow.tryEmit(value)
|
||||||
}
|
}
|
||||||
protected val job = internalSharedFlow.subscribe(internalScope) {
|
protected val job = internalSharedFlow.subscribe(internalScope) {
|
||||||
doOnChangeAction(it)
|
doOnChangeAction(it)
|
||||||
@ -48,6 +49,11 @@ open class SpecialMutableStateFlow<T>(
|
|||||||
override val subscriptionCount: StateFlow<Int>
|
override val subscriptionCount: StateFlow<Int>
|
||||||
get() = publicSharedFlow.subscriptionCount
|
get() = publicSharedFlow.subscriptionCount
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
initialValue: T,
|
||||||
|
internalContext: CoroutineContext = Dispatchers.Default
|
||||||
|
) : this(initialValue, CoroutineScope(internalContext))
|
||||||
|
|
||||||
@OptIn(InternalCoroutinesApi::class)
|
@OptIn(InternalCoroutinesApi::class)
|
||||||
override fun compareAndSet(expect: T, update: T): Boolean {
|
override fun compareAndSet(expect: T, update: T): Boolean {
|
||||||
return synchronized(syncObject) {
|
return synchronized(syncObject) {
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
import dev.inmo.micro_utils.coroutines.SpecialMutableStateFlow
|
||||||
|
import dev.inmo.micro_utils.coroutines.subscribe
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class SpecialMutableStateFlowTests {
|
||||||
|
@Test
|
||||||
|
fun simpleTest() {
|
||||||
|
val specialMutableStateFlow = SpecialMutableStateFlow(0)
|
||||||
|
runTest {
|
||||||
|
specialMutableStateFlow.value = 1
|
||||||
|
specialMutableStateFlow.first { it == 1 }
|
||||||
|
}
|
||||||
|
assertEquals(1, specialMutableStateFlow.value)
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun specialTest() {
|
||||||
|
val specialMutableStateFlow = SpecialMutableStateFlow(0)
|
||||||
|
runTest {
|
||||||
|
lateinit var subscriberJob: Job
|
||||||
|
subscriberJob = specialMutableStateFlow.subscribe(this) {
|
||||||
|
when (it) {
|
||||||
|
1 -> specialMutableStateFlow.value = 2
|
||||||
|
2 -> subscriberJob.cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
specialMutableStateFlow.value = 1
|
||||||
|
subscriberJob.join()
|
||||||
|
}
|
||||||
|
assertEquals(2, specialMutableStateFlow.value)
|
||||||
|
}
|
||||||
|
}
|
@ -2,18 +2,18 @@
|
|||||||
|
|
||||||
kt = "1.9.23"
|
kt = "1.9.23"
|
||||||
kt-serialization = "1.6.3"
|
kt-serialization = "1.6.3"
|
||||||
kt-coroutines = "1.8.0"
|
kt-coroutines = "1.8.1"
|
||||||
|
|
||||||
kslog = "1.3.3"
|
kslog = "1.3.4"
|
||||||
|
|
||||||
jb-compose = "1.6.2"
|
jb-compose = "1.6.2"
|
||||||
jb-exposed = "0.50.0"
|
jb-exposed = "0.50.1"
|
||||||
jb-dokka = "1.9.20"
|
jb-dokka = "1.9.20"
|
||||||
|
|
||||||
korlibs = "5.4.0"
|
korlibs = "5.4.0"
|
||||||
uuid = "0.8.4"
|
uuid = "0.8.4"
|
||||||
|
|
||||||
ktor = "2.3.10"
|
ktor = "2.3.11"
|
||||||
|
|
||||||
gh-release = "2.5.2"
|
gh-release = "2.5.2"
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ kotlin-poet = "1.16.0"
|
|||||||
|
|
||||||
versions = "0.51.0"
|
versions = "0.51.0"
|
||||||
|
|
||||||
android-gradle = "8.4.0"
|
android-gradle = "8.3.2"
|
||||||
dexcount = "4.0.0"
|
dexcount = "4.0.0"
|
||||||
|
|
||||||
android-coreKtx = "1.13.1"
|
android-coreKtx = "1.13.1"
|
||||||
|
@ -15,9 +15,6 @@ kotlin {
|
|||||||
api libs.ktor.client
|
api libs.ktor.client
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
androidMain {
|
|
||||||
dependsOn jvmMain
|
|
||||||
}
|
|
||||||
|
|
||||||
linuxX64Main {
|
linuxX64Main {
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -16,8 +16,5 @@ kotlin {
|
|||||||
api libs.ktor.io
|
api libs.ktor.io
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
androidMain {
|
|
||||||
dependsOn jvmMain
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,3 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$mppJvmJsAndroidLinuxMingwLinuxArm64ProjectPresetPath"
|
apply from: "$mppJvmJsAndroidLinuxMingwLinuxArm64ProjectPresetPath"
|
||||||
|
|
||||||
kotlin {
|
|
||||||
sourceSets {
|
|
||||||
androidMain {
|
|
||||||
dependsOn jvmMain
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
@file:Suppress("SERIALIZER_TYPE_INCOMPATIBLE") // for suppressing of @Serializable(IetfLangSerializer::class) on inheritors of IetfLang
|
||||||
|
|
||||||
package dev.inmo.micro_utils.language_codes
|
package dev.inmo.micro_utils.language_codes
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
@ -60,6 +60,12 @@ kotlin {
|
|||||||
implementation kotlin('test-junit')
|
implementation kotlin('test-junit')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
nativeMain.dependsOn commonMain
|
||||||
|
linuxX64Main.dependsOn nativeMain
|
||||||
|
mingwX64Main.dependsOn nativeMain
|
||||||
|
linuxArm64Main.dependsOn nativeMain
|
||||||
|
|
||||||
|
androidMain.dependsOn jvmMain
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,13 @@ kotlin {
|
|||||||
implementation kotlin('test-junit')
|
implementation kotlin('test-junit')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nativeMain.dependsOn commonMain
|
||||||
|
linuxX64Main.dependsOn nativeMain
|
||||||
|
mingwX64Main.dependsOn nativeMain
|
||||||
|
linuxArm64Main.dependsOn nativeMain
|
||||||
|
|
||||||
|
androidMain.dependsOn jvmMain
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +55,10 @@ kotlin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nativeMain.dependsOn commonMain
|
||||||
|
linuxX64Main.dependsOn nativeMain
|
||||||
|
mingwX64Main.dependsOn nativeMain
|
||||||
|
|
||||||
androidMain.dependsOn jvmMain
|
androidMain.dependsOn jvmMain
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,8 +67,6 @@ kotlin {
|
|||||||
implementation libs.android.espresso
|
implementation libs.android.espresso
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
androidMain.dependsOn jvmMain
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,6 @@ kotlin {
|
|||||||
api internalProject("micro_utils.common")
|
api internalProject("micro_utils.common")
|
||||||
api internalProject("micro_utils.coroutines")
|
api internalProject("micro_utils.coroutines")
|
||||||
}
|
}
|
||||||
dependsOn jvmMain
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,9 +13,5 @@ kotlin {
|
|||||||
api project(":micro_utils.language_codes")
|
api project(":micro_utils.language_codes")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
androidMain {
|
|
||||||
dependsOn(jvmMain)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user