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

commonMain.com.paoapps.fifi.utils.ActionHandler.kt Maven / Gradle / Ivy

Go to download

Kotlin Multiplatform Mobile framework for optimal code sharing between iOS and Android.

There is a newer version: 0.0.31
Show newest version
package com.paoapps.fifi.utils

import com.paoapps.fifi.ui.component.ConfirmationDialogDefinition
import com.paoapps.fifi.utils.flow.FlowAdapter
import com.paoapps.fifi.utils.flow.wrap
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch

interface Emitter {
    fun event(event: E)
    fun action(action: A)
}

data class ActionHandler(val scope: CoroutineScope, private val handler: suspend (E, Any?) -> EventResult?) {

    val globalActionsFlow = MutableSharedFlow()
    val globalActions = globalActionsFlow.asSharedFlow().wrap(scope)

    val actionsFlow = MutableSharedFlow()
    val actions = FlowAdapter(scope, actionsFlow.asSharedFlow())

    private val _links = MutableSharedFlow()
    val links = _links.asSharedFlow().wrap(scope)

    val events = MutableSharedFlow>()

    private val _confirmationDialogs = MutableSharedFlow>()
    val confirmationDialogs = _confirmationDialogs.asSharedFlow().wrap(scope)

    sealed interface EventResult {
        data class Event(val event: E): EventResult
        data class Action(val action: A): EventResult
//        data class Link(val link: String): EventResult
        data class ConfirmationDialog(val confirmationDialog: ConfirmationDialogDefinition.Properties): EventResult
        data class Global(val action: Any): EventResult
    }

    init {
        scope.launch {
            events.collect {
                handleEvent(it.first, it.second)
            }
        }
    }

    suspend fun emitEvent(event: E) {
        events.emit(Pair(event, null))
    }

    fun  mapToOutput(dataFlow: Flow, transform: suspend (Data, Emitter) -> Output): Flow =
        flatMapToOutput(dataFlow) { data, emitEvent ->
            flowOf(transform(data, emitEvent))
        }

    fun  mapToOutput(transform: (Emitter) -> Output): Flow =
        flatMapToOutput { emitEvent ->
            flowOf(transform(emitEvent))
        }

    fun  flatMapToOutput(dataFlow: Flow, transform: suspend (Data, Emitter) -> Flow): Flow =
        dataFlow.flatMapConcat { data ->
            val scope = this.scope
            val events = this.events
            val actions = this.actionsFlow
            transform(data, object: Emitter {
                override fun event(event: E) {
                    scope.launch {
                        events.emit(Pair(event, null))
                    }
                }

                override fun action(action: A) {
                    scope.launch {
                        actions.emit(action)
                    }
                }
            })
        }
            .distinctUntilChanged()


    fun  flatMapToOutput(transform: (Emitter) -> Flow): Flow = flatMapToOutput(flowOf(Unit)) { _, emitEvent ->
        transform(emitEvent)
    }

    fun  toOutput(transform: (Emitter) -> Output): Output {
        val scope = this.scope
        val events = this.events
        val actions = this.actionsFlow
        return transform(object: Emitter {
            override fun event(event: E) {
                scope.launch {
                    events.emit(Pair(event, null))
                }
            }

            override fun action(action: A) {
                scope.launch {
                    actions.emit(action)
                }
            }
        })
    }

    private suspend fun handleEvent(event: E, input: Any?) {
        when(val result = handler(event, input)) {
            is EventResult.Action -> actionsFlow.emit(result.action)
            is EventResult.Event -> handleEvent(result.event, input)
//            is EventResult.Link -> _links.emit(result.link)
            is EventResult.ConfirmationDialog -> _confirmationDialogs.emit(result.confirmationDialog)
            is EventResult.Global -> globalActionsFlow.emit(result.action)
            null -> {}
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy