commonMain.com.eygraber.vice.sources.LoadableFlowSource.kt Maven / Gradle / Ivy
package com.eygraber.vice.sources
import androidx.compose.runtime.Stable
import com.eygraber.vice.loadable.ViceLoadable
import com.eygraber.vice.loadable.isLoading
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
import kotlin.time.TimeSource
@Stable
public abstract class LoadableFlowSource : StateFlowSource>() {
private val mutableFlow by lazy {
MutableStateFlow>(ViceLoadable.Loading(placeholder))
}
override val flow: StateFlow> by lazy { mutableFlow }
protected abstract val dataFlow: Flow
protected abstract val placeholder: T
protected open val initialLoadingThreshold: Duration = 200.milliseconds
protected open val minLoadingDuration: Duration = 1.seconds
protected open val isBufferingEmissionsWhileLoading: Boolean = false
override suspend fun onAttached(scope: CoroutineScope) {
val initialLoadingThreshold = TimeSource.Monotonic.markNow() + initialLoadingThreshold
val minLoadingThreshold = initialLoadingThreshold + minLoadingDuration
val collector: suspend (T) -> Unit = { value ->
if(flow.value.isLoading) {
val now = TimeSource.Monotonic.markNow()
if(now in initialLoadingThreshold.. dataFlow.collect(collector)
else -> dataFlow.collectLatest(collector)
}
}
}