Last active
August 17, 2021 09:18
-
-
Save IlyaGulya/780e9e80edc28dc9dd6e34233cdc10a8 to your computer and use it in GitHub Desktop.
MVIKotlin Component Template
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#set($capitalizedFilename = $NAME.substring(0,1).toUpperCase() + $NAME.substring(1)) | |
#set($lowercaseFilename = $NAME.substring(0,1).toLowerCase() + $NAME.substring(1)) | |
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}#end | |
import com.arkivanov.essenty.lifecycle.Lifecycle | |
import com.arkivanov.essenty.lifecycle.doOnDestroy | |
import com.arkivanov.mvikotlin.core.binder.BinderLifecycleMode | |
import com.arkivanov.mvikotlin.core.store.Reducer | |
import com.arkivanov.mvikotlin.core.store.SimpleBootstrapper | |
import com.arkivanov.mvikotlin.core.store.Store | |
import com.arkivanov.mvikotlin.core.store.StoreFactory | |
import com.arkivanov.mvikotlin.core.view.MviView | |
import com.arkivanov.mvikotlin.extensions.coroutines.CoroutineExecutor | |
import com.arkivanov.mvikotlin.extensions.coroutines.bind | |
import com.arkivanov.mvikotlin.extensions.coroutines.events | |
import com.arkivanov.mvikotlin.extensions.coroutines.states | |
import dagger.assisted.Assisted | |
import dagger.assisted.AssistedFactory | |
import dagger.assisted.AssistedInject | |
import kotlinx.coroutines.ExperimentalCoroutinesApi | |
import kotlinx.coroutines.flow.mapNotNull | |
import kotlinx.coroutines.launch | |
import ${PACKAGE_NAME}.${capitalizedFilename}Store.Intent | |
import ${PACKAGE_NAME}.${capitalizedFilename}Store.State | |
import ${PACKAGE_NAME}.${capitalizedFilename}Store.Label | |
import ${PACKAGE_NAME}.${capitalizedFilename}View.Event | |
import ${PACKAGE_NAME}.${capitalizedFilename}View.Model | |
import javax.inject.Inject | |
import kotlin.coroutines.CoroutineContext | |
interface ${capitalizedFilename}View : MviView<Model, Event> { | |
sealed class Model { | |
object Initial : Model() | |
} | |
sealed class Event { | |
object Some : Event() | |
} | |
} | |
@ExperimentalCoroutinesApi | |
class ${capitalizedFilename}Controller @AssistedInject constructor( | |
@Io private val ioContext: CoroutineContext, | |
@Main private val mainContext: CoroutineContext, | |
private val ${lowercaseFilename}StoreAssistedFactory: ${capitalizedFilename}StoreFactory.Factory, | |
@Assisted private val lifecycle: Lifecycle, | |
) { | |
private val ${lowercaseFilename}Store = ${lowercaseFilename}StoreAssistedFactory().create() | |
init { | |
lifecycle.doOnDestroy { ${lowercaseFilename}Store.dispose() } | |
} | |
fun onViewCreated(${lowercaseFilename}View: ${capitalizedFilename}View, viewLifecycle: Lifecycle) { | |
bind(viewLifecycle, BinderLifecycleMode.CREATE_DESTROY, mainContext) { | |
${lowercaseFilename}View.events.mapNotNull { | |
when (it) { | |
is Event.Some -> Intent.Some | |
} | |
} bindTo ${lowercaseFilename}Store | |
} | |
bind(viewLifecycle, BinderLifecycleMode.START_STOP, mainContext) { | |
${lowercaseFilename}Store.states.mapNotNull { | |
when (it) { | |
is State.Initial -> Model.Initial | |
} | |
} bindTo ${lowercaseFilename}View | |
} | |
} | |
@AssistedFactory | |
interface Factory { | |
fun create( | |
lifecycle: Lifecycle, | |
): ${capitalizedFilename}Controller | |
} | |
} | |
interface ${capitalizedFilename}Store : Store<Intent, State, Label> { | |
sealed class Intent { | |
object Some : Intent() | |
} | |
sealed class State { | |
object Initial : State() | |
} | |
sealed class Label { | |
} | |
} | |
class ${capitalizedFilename}StoreFactory @Inject constructor( | |
@Io private val ioContext: CoroutineContext, | |
@Main private val mainContext: CoroutineContext, | |
private val storeFactory: StoreFactory, | |
) { | |
fun create(): ${capitalizedFilename}Store = | |
object : ${capitalizedFilename}Store, Store<Intent, State, Label> by storeFactory.create( | |
name = "${capitalizedFilename}Store", | |
initialState = State.Initial, | |
bootstrapper = SimpleBootstrapper(Unit), | |
executorFactory = ::ExecutorImpl, | |
reducer = ReducerImpl, | |
) {} | |
private inner class ExecutorImpl : CoroutineExecutor<Intent, Unit, State, Result, Label>(mainContext) { | |
override fun executeAction(action: Unit, getState: () -> State) { | |
super.executeAction(action, getState) | |
scope.launch { | |
} | |
} | |
override fun executeIntent(intent: Intent, getState: () -> State) { | |
super.executeIntent(intent, getState) | |
when (intent) { | |
is Intent.Some -> { | |
} | |
}.let { } | |
} | |
} | |
private object ReducerImpl : Reducer<State, Result> { | |
override fun State.reduce(result: Result): State = | |
when (this) { | |
else -> this | |
} | |
} | |
private sealed class Result { | |
object Some : Result() | |
} | |
@AssistedFactory | |
interface Factory { | |
operator fun invoke( | |
): ${capitalizedFilename}StoreFactory | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment