Skip to content

Instantly share code, notes, and snippets.

@IlyaGulya
Last active August 17, 2021 09:18
Show Gist options
  • Save IlyaGulya/780e9e80edc28dc9dd6e34233cdc10a8 to your computer and use it in GitHub Desktop.
Save IlyaGulya/780e9e80edc28dc9dd6e34233cdc10a8 to your computer and use it in GitHub Desktop.
MVIKotlin Component Template
#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