Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
y9san9 committed Jun 14, 2021
1 parent 2dfbbd7 commit 8166404
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 2 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,10 @@ fun main() = startApplication(::App)
<summary>Expand</summary>

```kotlin

object CoroutinesStorage : ... {
// Use it everywhere you need to save state flow values
val stateFlow by mutableStateFlow<String>()
}
```

</details>
Expand Down
28 changes: 28 additions & 0 deletions extensions/extensions-coroutines/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
@file:Suppress("UNUSED_VARIABLE")

plugins {
kotlin(plugin.multiplatform)
}

kotlin {
explicitApi()

jvm()
js(IR) {
nodejs()
browser()
}

sourceSets {
val commonMain by getting {
dependencies {
api(core)
implementation(coroutines)
}
}

all {
languageSettings.useExperimentalAnnotation("kotlin.RequiresOptIn")
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,96 @@
package `fun`.kotlingang.kds.coroutines.mutable_state_flow

import `fun`.kotlingang.kds.annotation.RawSetterGetter
import `fun`.kotlingang.kds.annotation.UnsafeKType
import `fun`.kotlingang.kds.optional.getOrDefault
import `fun`.kotlingang.kds.storage.KTypeDataStorage
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlin.reflect.KProperty
import kotlin.reflect.KType
import kotlin.reflect.typeOf

class StorageMutableStateFlow {

public inline fun <reified T> KTypeDataStorage.mutableStateFlow(): StorageMutableStateFlowProvider<T?> =
mutableStateFlow { null }

@OptIn(ExperimentalStdlibApi::class, UnsafeKType::class)
public inline fun <reified T> KTypeDataStorage.mutableStateFlow (
noinline defaultValue: () -> T,
): StorageMutableStateFlowProvider<T> = StorageMutableStateFlowProvider (
storage = this,
type = typeOf<T>(),
defaultValue = defaultValue
)

@OptIn(UnsafeKType::class)
public class StorageMutableStateFlowProvider<T> @UnsafeKType constructor (
private val storage: KTypeDataStorage,
private val type: KType,
private val defaultValue: () -> T
) {
private lateinit var name: String
private val state by lazy { StorageMutableStateFlow(storage, name, type, defaultValue) }

public operator fun getValue (
thisRef: Any?, property: KProperty<*>
): StorageMutableStateFlow<T> {
name = property.name
return state
}
}

@OptIn(RawSetterGetter::class, UnsafeKType::class)
public class StorageMutableStateFlow<T> @UnsafeKType constructor (
private val storage: KTypeDataStorage,
private val key: String,
private val type: KType,
defaultValue: () -> T
) : MutableStateFlow<T> {
private val state = MutableStateFlow (
storage.getWithKType<T>(key, type).getOrDefault(defaultValue)
)

override var value: T
get() = state.value
set(value) {
storage.putWithKType(key, type, value)
state.value = value
}

public operator fun getValue(thisRef: Any?, property: KProperty<*>): T = value
public operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
this.value = value
}

@InternalCoroutinesApi
override suspend fun collect(collector: FlowCollector<T>) {
state.collect(collector)
}

override val subscriptionCount: StateFlow<Int> = state.subscriptionCount

override suspend fun emit(value: T) {
state.emit(value)
storage.putWithKType(key, type, value)
}

@ExperimentalCoroutinesApi
override fun resetReplayCache() {
state.resetReplayCache()
}

override fun tryEmit(value: T): Boolean = state.tryEmit(value).also { emitted ->
if (emitted) storage.putWithKType(key, type, value)
}

override fun compareAndSet(expect: T, update: T): Boolean =
state.compareAndSet(expect, update).also { set ->
if (set) storage.putWithKType(key, type, update)
}

override val replayCache: List<T> = state.replayCache
}

0 comments on commit 8166404

Please sign in to comment.