All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.ProgressiveFlow.kt Maven / Gradle / Ivy

package opensavvy.state.coroutines

import kotlinx.coroutines.flow.*
import opensavvy.progress.Progress
import opensavvy.progress.coroutines.report
import opensavvy.progress.done
import opensavvy.state.progressive.ProgressiveOutcome
import opensavvy.state.progressive.asOutcome

/**
 * Successive values of the same object as time passes.
 *
 * Using this type alias instead of a regular flow communicates the intent that this flow contains successive values of
 * a unique target, and thus that each value emitted by the flow is more recent than any other previous values.
 *
 * To ignore loading values, see [filterNotLoading]. To suspend until the first value is available, use [now].
 */
typealias ProgressiveFlow = Flow>

/**
 * Filters out all the values with a non-[done][done] [progress][ProgressiveOutcome.progress] from this flow.
 *
 * All [progress information][Progress] from filtered-out values is re-emitted to the calling flow.
 *
 * @see now Return only the first non-loading value, instead of returning a flow.
 */
fun  ProgressiveFlow.filterNotLoading() = this
	.onEach { report(it.progress) }
	.filter { it.progress == done() }
	.mapNotNull { it.asOutcome() }

/**
 * Suspends until the first complete value is available (success or failure).
 *
 * This function assumes that the flow represents subsequent values of the same object as time passes.
 * In this interpretation, the first complete value is the current value; hence the name `now`.
 *
 * Because this function only returns a single value, it exits the reactive model. It is therefore discouraged to use
 * this function in UI code, as the calling code will not be made aware of new values arriving in the future.
 *
 * A complete value is a value which has a [progress][ProgressiveOutcome.progress] of [done].
 * All [progress information][Progress] from previous values is re-emitted in the calling coroutine.
 *
 * @throws NoSuchElementException In case the flow terminates before emitting a complete element.
 * @see filterNotLoading Return all complete elements instead of just the first one.
 */
suspend fun  ProgressiveFlow.now() = this
	.filterNotLoading()
	.first()




© 2015 - 2024 Weber Informatics LLC | Privacy Policy