almost complete rework of ui up to module ui
This commit is contained in:
@@ -16,6 +16,11 @@ kotlin {
|
||||
api "io.ktor:ktor-client-auth:$ktor_version"
|
||||
api "io.ktor:ktor-client-logging:$ktor_version"
|
||||
|
||||
api libs.microutils.common.compose
|
||||
api libs.microutils.coroutines.compose
|
||||
api libs.microutils.fsm.common
|
||||
api libs.microutils.fsm.repos.common
|
||||
|
||||
api compose.runtime
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
package dev.inmo.postssystem.features.common.common
|
||||
|
||||
object AdditionalModules {
|
||||
class AdditionalModules {
|
||||
private val additionalModules = mutableListOf<ModuleLoader>()
|
||||
val modules: List<ModuleLoader>
|
||||
get() = additionalModules.toList()
|
||||
@@ -8,4 +8,8 @@ object AdditionalModules {
|
||||
fun addModule(moduleLoader: ModuleLoader): Boolean {
|
||||
return additionalModules.add(moduleLoader)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val Default = AdditionalModules()
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,12 @@
|
||||
package dev.inmo.postssystem.features.common.common
|
||||
|
||||
import dev.inmo.micro_utils.pagination.utils.getAllByWithNextPaging
|
||||
import dev.inmo.micro_utils.repos.KeyValueRepo
|
||||
|
||||
class DBDropper(
|
||||
private val repo: KeyValueRepo<String, Any>
|
||||
) {
|
||||
suspend operator fun invoke() {
|
||||
repo.unset(repo.getAllByWithNextPaging { keys(it) })
|
||||
}
|
||||
}
|
@@ -0,0 +1,67 @@
|
||||
package dev.inmo.postssystem.features.common.common
|
||||
|
||||
import dev.inmo.micro_utils.coroutines.LinkedSupervisorScope
|
||||
import dev.inmo.micro_utils.fsm.common.StatesMachine
|
||||
import dev.inmo.micro_utils.fsm.common.dsl.FSMBuilder
|
||||
import dev.inmo.micro_utils.fsm.common.managers.DefaultStatesManagerRepo
|
||||
import dev.inmo.micro_utils.repos.KeyValueRepo
|
||||
import dev.inmo.postssystem.features.common.common.ui.fsm.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.serialization.BinaryFormat
|
||||
import kotlinx.serialization.StringFormat
|
||||
import kotlinx.serialization.cbor.Cbor
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.modules.SerializersModule
|
||||
import org.koin.core.Koin
|
||||
import org.koin.core.context.startKoin
|
||||
import org.koin.core.scope.Scope
|
||||
import org.koin.dsl.module
|
||||
|
||||
/**
|
||||
* Entrypoint for getting [org.koin.core.Koin] DI for the client
|
||||
*
|
||||
* @param repoFactory Factory for creating of [DefaultStatesManagerRepo] for [dev.inmo.postssystem.client.ui.fsm.UIFSM]
|
||||
*/
|
||||
fun baseKoin(
|
||||
defaultScope: CoroutineScope,
|
||||
settingsFactory: Scope.() -> KeyValueRepo<String, Any>,
|
||||
repoFactory: Scope.() -> DefaultStatesManagerRepo<UIFSMState>,
|
||||
handlersSetter: Pair<Scope, FSMBuilder<UIFSMState>>.() -> Unit
|
||||
): Koin = startKoin {
|
||||
modules(
|
||||
module {
|
||||
single {
|
||||
Json {
|
||||
ignoreUnknownKeys = true
|
||||
serializersModule = SerializersModule { get<SerializersModuleConfigurator>().apply { invoke() } }
|
||||
}
|
||||
}
|
||||
single<StringFormat> { get<Json>() }
|
||||
single {
|
||||
Cbor { serializersModule = SerializersModule { get<SerializersModuleConfigurator>().apply { invoke() } } }
|
||||
}
|
||||
single<BinaryFormat> { get<Cbor>() }
|
||||
|
||||
single(DefaultQualifiers.SettingsQualifier) { settingsFactory() }
|
||||
single { DBDropper(get(DefaultQualifiers.SettingsQualifier)) }
|
||||
single(DefaultQualifiers.FSMHandlersBuilderQualifier) { handlersSetter }
|
||||
single { repoFactory() }
|
||||
single { defaultScope }
|
||||
single(DefaultQualifiers.UIScopeQualifier) { get<CoroutineScope>().LinkedSupervisorScope(Dispatchers.Main) }
|
||||
single<StatesMachine<UIFSMState>>(UIFSMQualifier) { UIFSM(get()) { (this@single to this@UIFSM).apply(get(
|
||||
DefaultQualifiers.FSMHandlersBuilderQualifier
|
||||
)) } }
|
||||
|
||||
AdditionalModules.Default.modules.forEach {
|
||||
it.apply { load() }
|
||||
}
|
||||
}
|
||||
)
|
||||
}.koin.apply {
|
||||
loadModules(
|
||||
listOf(
|
||||
module { single<Koin> { this@apply } }
|
||||
)
|
||||
)
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
package dev.inmo.postssystem.features.common.common
|
||||
|
||||
import org.koin.core.qualifier.StringQualifier
|
||||
|
||||
object DefaultQualifiers {
|
||||
val SettingsQualifier = StringQualifier("Settings")
|
||||
val FSMHandlersBuilderQualifier = StringQualifier("FSMHandlersBuilder")
|
||||
val UIScopeQualifier = StringQualifier("CoroutineScopeUI")
|
||||
val UIFSMQualifier = StringQualifier("FSM")
|
||||
}
|
@@ -2,6 +2,18 @@ package dev.inmo.postssystem.features.common.common
|
||||
|
||||
import org.koin.core.module.Module
|
||||
|
||||
fun interface ModuleLoader {
|
||||
interface ModuleLoader {
|
||||
fun Module.load()
|
||||
|
||||
class ByCallback(private val loadingBlock: Module.() -> Unit) : ModuleLoader {
|
||||
override fun Module.load() {
|
||||
loadingBlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun DefaultModuleLoader(loadingBlock: Module.() -> Unit): ModuleLoader.ByCallback {
|
||||
val newModuleLoader = ModuleLoader.ByCallback(loadingBlock)
|
||||
AdditionalModules.Default.addModule(newModuleLoader)
|
||||
return newModuleLoader
|
||||
}
|
||||
|
@@ -1,4 +0,0 @@
|
||||
package dev.inmo.postssystem.features.common.common
|
||||
|
||||
interface UIView {
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package dev.inmo.postssystem.features.common.common
|
||||
package dev.inmo.postssystem.features.common.common.ui
|
||||
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package dev.inmo.postssystem.features.common.common
|
||||
package dev.inmo.postssystem.features.common.common.ui
|
||||
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
@@ -0,0 +1,4 @@
|
||||
package dev.inmo.postssystem.features.common.common.ui
|
||||
|
||||
interface UIView {
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package dev.inmo.postssystem.features.common.common
|
||||
package dev.inmo.postssystem.features.common.common.ui
|
||||
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
@@ -7,9 +7,7 @@ interface UIViewModel<StateType> {
|
||||
val currentState: StateFlow<StateType>
|
||||
}
|
||||
|
||||
abstract class AbstractUIViewModel<StateType> : UIViewModel<StateType> {
|
||||
protected val _currentState = DefaultMVVMStateFlow(initState())
|
||||
abstract class AbstractUIViewModel<StateType>(initState: StateType) : UIViewModel<StateType> {
|
||||
protected val _currentState = DefaultMVVMStateFlow(initState)
|
||||
override val currentState: StateFlow<StateType> = _currentState.asStateFlow()
|
||||
|
||||
abstract fun initState(): StateType
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
package dev.inmo.postssystem.features.common.common.ui.fsm
|
||||
|
||||
import dev.inmo.micro_utils.fsm.common.dsl.FSMBuilder
|
||||
import dev.inmo.micro_utils.fsm.common.dsl.buildFSM
|
||||
import dev.inmo.micro_utils.fsm.common.managers.DefaultStatesManager
|
||||
import dev.inmo.micro_utils.fsm.common.managers.DefaultStatesManagerRepo
|
||||
import org.koin.core.qualifier.StringQualifier
|
||||
|
||||
val UIFSMQualifier = StringQualifier("UIFSM")
|
||||
|
||||
fun UIFSM(
|
||||
repo: DefaultStatesManagerRepo<UIFSMState>,
|
||||
handlersSetter: FSMBuilder<UIFSMState>.() -> Unit
|
||||
) = buildFSM<UIFSMState> {
|
||||
statesManager = DefaultStatesManager(repo)
|
||||
handlersSetter()
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
package dev.inmo.postssystem.features.common.common.ui.fsm
|
||||
|
||||
import dev.inmo.micro_utils.common.Optional
|
||||
|
||||
fun interface UIFSMExceptionHandler {
|
||||
suspend fun handle(currentState: UIFSMState, exception: Throwable): Optional<UIFSMState?>
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
package dev.inmo.postssystem.features.common.common.ui.fsm
|
||||
|
||||
import dev.inmo.micro_utils.common.onPresented
|
||||
import dev.inmo.micro_utils.fsm.common.*
|
||||
import dev.inmo.micro_utils.fsm.common.dsl.FSMBuilder
|
||||
import org.koin.core.scope.Scope
|
||||
|
||||
interface UIFSMHandler<T : UIFSMState> : StatesHandler<T, UIFSMState> {
|
||||
fun interface Registrator {
|
||||
fun FSMBuilder<UIFSMState>.include()
|
||||
}
|
||||
val defaultExceptionsHandlers: Iterable<UIFSMExceptionHandler>
|
||||
|
||||
suspend fun StatesMachine<in UIFSMState>.safeHandleState(state: T): UIFSMState?
|
||||
override suspend fun StatesMachine<in UIFSMState>.handleState(state: T): UIFSMState? {
|
||||
return runCatching {
|
||||
safeHandleState(state).also(::println)
|
||||
}.getOrElse {
|
||||
errorToNextStep(state, it) ?.let { return it } ?: throw it
|
||||
}.also(::println)
|
||||
}
|
||||
|
||||
suspend fun errorToNextStep(
|
||||
currentState: T,
|
||||
e: Throwable
|
||||
): UIFSMState? {
|
||||
defaultExceptionsHandlers.forEach {
|
||||
it.handle(currentState, e).onPresented { state ->
|
||||
return state
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
package dev.inmo.postssystem.features.common.common.ui.fsm
|
||||
|
||||
import dev.inmo.micro_utils.fsm.common.State
|
||||
import dev.inmo.micro_utils.serialization.typed_serializer.TypedSerializer
|
||||
import kotlinx.serialization.*
|
||||
|
||||
@Serializable(UIFSMStateSerializer::class)
|
||||
interface UIFSMState : State {
|
||||
val from: UIFSMState?
|
||||
get() = null
|
||||
override val context: String
|
||||
get() = "main"
|
||||
}
|
||||
|
||||
object UIFSMStateSerializer : KSerializer<UIFSMState>, TypedSerializer<UIFSMState>(
|
||||
UIFSMState::class
|
||||
)
|
@@ -0,0 +1,19 @@
|
||||
package dev.inmo.postssystem.features.common.common.ui
|
||||
|
||||
import dev.inmo.micro_utils.fsm.common.StatesMachine
|
||||
import dev.inmo.postssystem.features.common.common.ui.fsm.*
|
||||
import kotlinx.browser.document
|
||||
import org.w3c.dom.HTMLElement
|
||||
|
||||
abstract class JSView<T : UIFSMState>(
|
||||
override val defaultExceptionsHandlers: Iterable<UIFSMExceptionHandler>
|
||||
) : UIFSMHandler<T> {
|
||||
open suspend fun StatesMachine<in UIFSMState>.safeHandleState(
|
||||
htmlElement: HTMLElement,
|
||||
state: T
|
||||
): UIFSMState? = null
|
||||
|
||||
override suspend fun StatesMachine<in UIFSMState>.safeHandleState(state: T): UIFSMState? {
|
||||
return safeHandleState(document.getElementById(state.context) as? HTMLElement ?: return null, state)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user