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

commonMain.oolong.runtime.kt Maven / Gradle / Ivy

The newest version!
package oolong

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlin.coroutines.CoroutineContext
import kotlin.jvm.JvmOverloads

/**
 * Create a runtime.
 */
@JvmOverloads
fun  runtime(
    init: () -> Pair>,
    update: (Msg, Model) -> Pair>,
    view: (Model, Dispatch) -> Any?,
    runtimeContext: CoroutineContext = Dispatchers.Default,
    renderContext: CoroutineContext = Dispatchers.Main,
    effectContext: CoroutineContext = Dispatchers.Default
): Job = runtime(init, update, { it }, view, runtimeContext, renderContext, effectContext)

/**
 * Create a runtime.
 */
@JvmOverloads
fun  runtime(
    init: () -> Pair>,
    update: (Msg, Model) -> Pair>,
    view: (Model) -> Props,
    render: (Props, Dispatch) -> Any?,
    runtimeContext: CoroutineContext = Dispatchers.Default,
    renderContext: CoroutineContext = Dispatchers.Main,
    effectContext: CoroutineContext = Dispatchers.Default
): Job {
    val runtime = RuntimeImpl(
        init, update, view, render,
        runtimeContext, renderContext, effectContext
    )
    return runtime.job
}

/**
 * Oolong runtime module.
 */
@Deprecated("To be removed in the next major release")
object Oolong {
    /**
     * Create a runtime.
     */
    @JvmOverloads
    @Deprecated(
        "Use oolong.runtime(init, update, view, render, runtimeContext, renderContext, effectContext) instead",
        ReplaceWith(
            "oolong.runtime(init, update, view, render, runtimeContext, renderContext, effectContext)",
            "oolong"
        )
    )
    fun  runtime(
        init: () -> Pair>,
        update: (Msg, Model) -> Pair>,
        view: (Model) -> Props,
        render: (Props, Dispatch) -> Any?,
        runtimeContext: CoroutineContext = Dispatchers.Default,
        renderContext: CoroutineContext = Dispatchers.Main,
        effectContext: CoroutineContext = Dispatchers.Default
    ): Dispose {
        val runtime = RuntimeImpl(
            init, update, view, render,
            runtimeContext, renderContext, effectContext
        )
        return { runtime.job.cancel() }
    }

}

private class RuntimeImpl(
    init: () -> Pair>,
    private val update: (Msg, Model) -> Pair>,
    private val view: (Model) -> Props,
    private val render: (Props, Dispatch) -> Any?,
    private val runtimeContext: CoroutineContext,
    private val renderContext: CoroutineContext,
    private val effectContext: CoroutineContext
) : CoroutineScope {

    val job: Job = SupervisorJob()

    override val coroutineContext: CoroutineContext
        get() = runtimeContext + job

    private var currentState: Model

    init {
        val initNext = init()
        currentState = initNext.first
        launch(runtimeContext) { step(initNext) }
    }

    private fun dispatch(msg: Msg) {
        if (isActive) {
            launch(runtimeContext) { step(update(msg, currentState)) }
        }
    }

    private fun step(next: Pair>) {
        val (state, effect) = next
        val props = view(state)
        currentState = state
        launch(renderContext) { render(props, ::dispatch) }
        launch(effectContext) { effect(::dispatch) }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy