Merge pull request #593 from InsanusMokrassar/0.26.2

0.26.2
This commit is contained in:
2025-07-31 15:22:34 +06:00
committed by GitHub
12 changed files with 44 additions and 43 deletions

View File

@@ -1,5 +1,13 @@
# Changelog # Changelog
## 0.26.2
* `Versions`:
* `Ktor`: `3.2.2` -> `3.2.3`
* `Okio`: `3.15.0` -> `3.16.0`
* `Coroutines`:
* Rename `SpecialMutableStateFlow` to `MutableRedeliverStateFlow`
## 0.26.1 ## 0.26.1
* `Versions`: * `Versions`:

View File

@@ -2,11 +2,9 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.runComposeUiTest import androidx.compose.ui.test.runComposeUiTest
import dev.inmo.micro_utils.common.compose.LoadableComponent import dev.inmo.micro_utils.common.compose.LoadableComponent
import dev.inmo.micro_utils.coroutines.SpecialMutableStateFlow import dev.inmo.micro_utils.coroutines.MutableRedeliverStateFlow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.firstOrNull
import org.jetbrains.annotations.TestOnly import org.jetbrains.annotations.TestOnly
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertTrue import kotlin.test.assertTrue
@@ -16,8 +14,8 @@ class LoadableComponentTests {
@Test @Test
@TestOnly @TestOnly
fun testSimpleLoad() = runComposeUiTest { fun testSimpleLoad() = runComposeUiTest {
val loadingFlow = SpecialMutableStateFlow<Int>(0) val loadingFlow = MutableRedeliverStateFlow<Int>(0)
val loadedFlow = SpecialMutableStateFlow<Int>(0) val loadedFlow = MutableRedeliverStateFlow<Int>(0)
setContent { setContent {
LoadableComponent<Int>({ LoadableComponent<Int>({
loadingFlow.filter { it == 1 }.first() loadingFlow.filter { it == 1 }.first()

View File

@@ -3,7 +3,7 @@ package dev.inmo.micro_utils.coroutines.compose
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import dev.inmo.micro_utils.coroutines.SpecialMutableStateFlow import dev.inmo.micro_utils.coroutines.MutableRedeliverStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.debounce
@@ -16,7 +16,7 @@ import org.jetbrains.compose.web.css.StyleSheet
* to add `Style(stylesheet)` on every compose function call * to add `Style(stylesheet)` on every compose function call
*/ */
object StyleSheetsAggregator { object StyleSheetsAggregator {
private val _stylesFlow = SpecialMutableStateFlow<Set<CSSRulesHolder>>(emptySet()) private val _stylesFlow = MutableRedeliverStateFlow<Set<CSSRulesHolder>>(emptySet())
val stylesFlow: StateFlow<Set<CSSRulesHolder>> = _stylesFlow.asStateFlow() val stylesFlow: StateFlow<Set<CSSRulesHolder>> = _stylesFlow.asStateFlow()
@Composable @Composable

View File

@@ -2,7 +2,7 @@ import androidx.compose.material.Button
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.ui.test.* import androidx.compose.ui.test.*
import dev.inmo.micro_utils.coroutines.SpecialMutableStateFlow import dev.inmo.micro_utils.coroutines.MutableRedeliverStateFlow
import org.jetbrains.annotations.TestOnly import org.jetbrains.annotations.TestOnly
import kotlin.test.Test import kotlin.test.Test
@@ -11,7 +11,7 @@ class FlowStateTests {
@Test @Test
@TestOnly @TestOnly
fun simpleTest() = runComposeUiTest { fun simpleTest() = runComposeUiTest {
val flowState = SpecialMutableStateFlow(0) val flowState = MutableRedeliverStateFlow(0)
setContent { setContent {
Button({ flowState.value++ }) { Text("Click") } Button({ flowState.value++ }) { Text("Click") }
Text(flowState.collectAsState().value.toString()) Text(flowState.collectAsState().value.toString())

View File

@@ -1,7 +1,5 @@
package dev.inmo.micro_utils.coroutines package dev.inmo.micro_utils.coroutines
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.InternalCoroutinesApi import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.channels.BufferOverflow
@@ -11,13 +9,12 @@ 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
* each active subscriber * each active subscriber
*/ */
open class SpecialMutableStateFlow<T>( open class MutableRedeliverStateFlow<T>(
initialValue: T initialValue: T
) : MutableStateFlow<T>, FlowCollector<T>, MutableSharedFlow<T> { ) : MutableStateFlow<T>, FlowCollector<T>, MutableSharedFlow<T> {
@OptIn(InternalCoroutinesApi::class) @OptIn(InternalCoroutinesApi::class)
@@ -68,3 +65,6 @@ open class SpecialMutableStateFlow<T>(
override suspend fun collect(collector: FlowCollector<T>) = sharingFlow.collect(collector) override suspend fun collect(collector: FlowCollector<T>) = sharingFlow.collect(collector)
} }
@Deprecated("Renamed to MutableRedeliverStateFlow", ReplaceWith("MutableRedeliverStateFlow<T>"))
typealias SpecialMutableStateFlow<T> = MutableRedeliverStateFlow<T>

View File

@@ -1,7 +1,6 @@
package dev.inmo.micro_utils.coroutines package dev.inmo.micro_utils.coroutines
import kotlinx.coroutines.currentCoroutineContext import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
@@ -44,7 +43,7 @@ sealed interface SmartMutex {
* @param locked Preset state of [isLocked] and its internal [_lockStateFlow] * @param locked Preset state of [isLocked] and its internal [_lockStateFlow]
*/ */
class Mutable(locked: Boolean = false) : SmartMutex { class Mutable(locked: Boolean = false) : SmartMutex {
private val _lockStateFlow = SpecialMutableStateFlow<Boolean>(locked) private val _lockStateFlow = MutableRedeliverStateFlow<Boolean>(locked)
override val lockStateFlow: StateFlow<Boolean> = _lockStateFlow.asStateFlow() override val lockStateFlow: StateFlow<Boolean> = _lockStateFlow.asStateFlow()
private val internalChangesMutex = Mutex() private val internalChangesMutex = Mutex()

View File

@@ -1,7 +1,6 @@
package dev.inmo.micro_utils.coroutines package dev.inmo.micro_utils.coroutines
import kotlinx.coroutines.currentCoroutineContext import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
@@ -47,7 +46,7 @@ sealed interface SmartSemaphore {
*/ */
class Mutable(permits: Int, acquiredPermits: Int = 0) : SmartSemaphore { class Mutable(permits: Int, acquiredPermits: Int = 0) : SmartSemaphore {
override val maxPermits: Int = permits override val maxPermits: Int = permits
private val _freePermitsStateFlow = SpecialMutableStateFlow<Int>(permits - acquiredPermits) private val _freePermitsStateFlow = MutableRedeliverStateFlow<Int>(permits - acquiredPermits)
override val permitsStateFlow: StateFlow<Int> = _freePermitsStateFlow.asStateFlow() override val permitsStateFlow: StateFlow<Int> = _freePermitsStateFlow.asStateFlow()
private val internalChangesMutex = Mutex(false) private val internalChangesMutex = Mutex(false)

View File

@@ -1,33 +1,31 @@
import dev.inmo.micro_utils.coroutines.SpecialMutableStateFlow import dev.inmo.micro_utils.coroutines.MutableRedeliverStateFlow
import dev.inmo.micro_utils.coroutines.asDeferred
import dev.inmo.micro_utils.coroutines.subscribe import dev.inmo.micro_utils.coroutines.subscribe
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertTrue
class SpecialMutableStateFlowTests { class SpecialMutableStateFlowTests {
@Test @Test
fun simpleTest() = runTest { fun simpleTest() = runTest {
val specialMutableStateFlow = SpecialMutableStateFlow(0) val mutableRedeliverStateFlow = MutableRedeliverStateFlow(0)
specialMutableStateFlow.value = 1 mutableRedeliverStateFlow.value = 1
specialMutableStateFlow.first { it == 1 } mutableRedeliverStateFlow.first { it == 1 }
assertEquals(1, specialMutableStateFlow.value) assertEquals(1, mutableRedeliverStateFlow.value)
} }
@Test @Test
fun specialTest() = runTest { fun specialTest() = runTest {
val specialMutableStateFlow = SpecialMutableStateFlow(0) val mutableRedeliverStateFlow = MutableRedeliverStateFlow(0)
lateinit var subscriberJob: Job lateinit var subscriberJob: Job
subscriberJob = specialMutableStateFlow.subscribe(this) { subscriberJob = mutableRedeliverStateFlow.subscribe(this) {
when (it) { when (it) {
1 -> specialMutableStateFlow.value = 2 1 -> mutableRedeliverStateFlow.value = 2
2 -> subscriberJob.cancel() 2 -> subscriberJob.cancel()
} }
} }
specialMutableStateFlow.value = 1 mutableRedeliverStateFlow.value = 1
subscriberJob.join() subscriberJob.join()
assertEquals(2, specialMutableStateFlow.value) assertEquals(2, mutableRedeliverStateFlow.value)
} }
} }

View File

@@ -18,5 +18,5 @@ crypto_js_version=4.1.1
# Project data # Project data
group=dev.inmo group=dev.inmo
version=0.26.1 version=0.26.2
android_code_version=300 android_code_version=301

View File

@@ -17,19 +17,19 @@ sqlite = "3.50.1.0"
korlibs = "5.4.0" korlibs = "5.4.0"
uuid = "0.8.4" uuid = "0.8.4"
ktor = "3.2.2" ktor = "3.2.3"
gh-release = "2.5.2" gh-release = "2.5.2"
koin = "4.1.0" koin = "4.1.0"
okio = "3.15.0" okio = "3.16.0"
ksp = "2.2.0-2.0.2" ksp = "2.2.0-2.0.2"
kotlin-poet = "2.2.0" kotlin-poet = "2.2.0"
versions = "0.52.0" versions = "0.52.0"
nmcp = "1.0.1" nmcp = "1.0.2"
android-gradle = "8.9.+" android-gradle = "8.9.+"
dexcount = "4.0.0" dexcount = "4.0.0"
@@ -38,8 +38,8 @@ android-coreKtx = "1.16.0"
android-recyclerView = "1.4.0" android-recyclerView = "1.4.0"
android-appCompat = "1.7.1" android-appCompat = "1.7.1"
android-fragment = "1.8.8" android-fragment = "1.8.8"
android-espresso = "3.6.1" android-espresso = "3.7.0"
android-test = "1.2.1" android-test = "1.3.0"
android-props-minSdk = "21" android-props-minSdk = "21"
android-props-compileSdk = "36" android-props-compileSdk = "36"

View File

@@ -1,9 +1,8 @@
package dev.inmo.micro_utils.pagination.compose package dev.inmo.micro_utils.pagination.compose
import androidx.compose.runtime.* import androidx.compose.runtime.*
import dev.inmo.micro_utils.coroutines.SpecialMutableStateFlow import dev.inmo.micro_utils.coroutines.MutableRedeliverStateFlow
import dev.inmo.micro_utils.coroutines.launchLoggingDropExceptions import dev.inmo.micro_utils.coroutines.launchLoggingDropExceptions
import dev.inmo.micro_utils.coroutines.runCatchingLogging
import dev.inmo.micro_utils.pagination.* import dev.inmo.micro_utils.pagination.*
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@@ -27,8 +26,8 @@ class InfinityPagedComponentContext<T> internal constructor(
private val loader: suspend InfinityPagedComponentContext<T>.(Pagination) -> PaginationResult<T> private val loader: suspend InfinityPagedComponentContext<T>.(Pagination) -> PaginationResult<T>
) { ) {
internal val startPage = SimplePagination(page, size) internal val startPage = SimplePagination(page, size)
internal val latestLoadedPage = SpecialMutableStateFlow<PaginationResult<T>?>(null) internal val latestLoadedPage = MutableRedeliverStateFlow<PaginationResult<T>?>(null)
internal val dataState = SpecialMutableStateFlow<List<T>?>(null) internal val dataState = MutableRedeliverStateFlow<List<T>?>(null)
internal var loadingJob: Job? = null internal var loadingJob: Job? = null
internal val loadingMutex = Mutex() internal val loadingMutex = Mutex()

View File

@@ -1,7 +1,7 @@
package dev.inmo.micro_utils.pagination.compose package dev.inmo.micro_utils.pagination.compose
import androidx.compose.runtime.* import androidx.compose.runtime.*
import dev.inmo.micro_utils.coroutines.SpecialMutableStateFlow import dev.inmo.micro_utils.coroutines.MutableRedeliverStateFlow
import dev.inmo.micro_utils.coroutines.launchLoggingDropExceptions import dev.inmo.micro_utils.coroutines.launchLoggingDropExceptions
import dev.inmo.micro_utils.pagination.* import dev.inmo.micro_utils.pagination.*
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@@ -28,8 +28,8 @@ class PagedComponentContext<T> internal constructor(
private val loader: suspend PagedComponentContext<T>.(Pagination) -> PaginationResult<T> private val loader: suspend PagedComponentContext<T>.(Pagination) -> PaginationResult<T>
) { ) {
internal val startPage = SimplePagination(initialPage, size) internal val startPage = SimplePagination(initialPage, size)
internal val latestLoadedPage = SpecialMutableStateFlow<PaginationResult<T>?>(null) internal val latestLoadedPage = MutableRedeliverStateFlow<PaginationResult<T>?>(null)
internal val dataState = SpecialMutableStateFlow<PaginationResult<T>?>(null) internal val dataState = MutableRedeliverStateFlow<PaginationResult<T>?>(null)
internal var loadingJob: Job? = null internal var loadingJob: Job? = null
internal val loadingMutex = Mutex() internal val loadingMutex = Mutex()