simpliest version of content upload
This commit is contained in:
@@ -18,7 +18,13 @@ object UIFSMStateSerializer : KSerializer<UIFSMState> by TypedSerializer(
|
||||
|
||||
@Serializable
|
||||
data class AuthUIFSMState(
|
||||
override val from: UIFSMState? = null,
|
||||
override val from: UIFSMState? = CreatePostUIFSMState(),
|
||||
override val context: String = "main"
|
||||
) : UIFSMState
|
||||
val DefaultAuthUIFSMState = AuthUIFSMState()
|
||||
|
||||
@Serializable
|
||||
data class CreatePostUIFSMState(
|
||||
override val from: UIFSMState? = null,
|
||||
override val context: String = "main"
|
||||
) : UIFSMState
|
||||
|
@@ -13,8 +13,8 @@ import dev.inmo.micro_utils.fsm.common.StatesMachine
|
||||
import dev.inmo.micro_utils.repos.mappers.withMapper
|
||||
import dev.inmo.micro_utils.serialization.typed_serializer.TypedSerializer
|
||||
import dev.inmo.postssystem.client.settings.auth.AuthSettings
|
||||
import kotlinx.browser.document
|
||||
import kotlinx.browser.localStorage
|
||||
import dev.inmo.postssystem.services.posts.client.ui.create.*
|
||||
import kotlinx.browser.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import kotlinx.serialization.serializer
|
||||
@@ -77,7 +77,7 @@ fun baseKoin(): Koin {
|
||||
)
|
||||
},
|
||||
{
|
||||
JSUIFSMStatesRepo(get(), localStorage)
|
||||
JSUIFSMStatesRepo(window.history)
|
||||
}
|
||||
) {
|
||||
first.apply {
|
||||
@@ -89,6 +89,10 @@ fun baseKoin(): Koin {
|
||||
factory<AuthUIModel> { DefaultAuthUIModel(get(), get()) }
|
||||
factory { AuthUIViewModel(get()) }
|
||||
factory { AuthView(get(), get(UIScopeQualifier)) }
|
||||
|
||||
factory<PostCreateUIModel> { DefaultPostCreateUIModel(get()) }
|
||||
factory { PostCreateUIViewModel(get()) }
|
||||
factory { PostCreateView(get(), get(UIScopeQualifier)) }
|
||||
}
|
||||
)
|
||||
strictlyOn<AuthUIFSMState>(get<AuthView>())
|
||||
@@ -135,6 +139,7 @@ fun baseKoin(): Koin {
|
||||
)
|
||||
)
|
||||
|
||||
registerHandler(PostCreateView::class)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,62 +2,78 @@ package dev.inmo.postssystem.client
|
||||
|
||||
import dev.inmo.postssystem.client.ui.fsm.*
|
||||
import dev.inmo.micro_utils.fsm.common.managers.DefaultStatesManagerRepo
|
||||
import kotlinx.browser.window
|
||||
import kotlinx.serialization.StringFormat
|
||||
import org.w3c.dom.*
|
||||
import org.w3c.dom.url.URL
|
||||
|
||||
class JSUIFSMStatesRepo(
|
||||
private val serialFormat: StringFormat,
|
||||
private val storage: Storage,
|
||||
private val initialState: UIFSMState = DefaultAuthUIFSMState
|
||||
) : DefaultStatesManagerRepo<UIFSMState> {
|
||||
private val String.storageKey
|
||||
get() = "${FSMStateSettingsFieldPrefix}$this"
|
||||
private val String.UIFSMState
|
||||
get() = runCatching {
|
||||
serialFormat.decodeFromString(UIFSMStateSerializer, this)
|
||||
}.onFailure { it.printStackTrace() }.getOrNull()
|
||||
|
||||
init {
|
||||
if (states().isEmpty()) {
|
||||
setState(initialState)
|
||||
private fun History.refreshHistory(
|
||||
states: Iterable<UIFSMState>,
|
||||
) {
|
||||
val currentUrl = window.location.pathname
|
||||
val params = states.mapNotNull<UIFSMState, Pair<String, String>> {
|
||||
when (it) {
|
||||
is AuthUIFSMState -> null
|
||||
is CreatePostUIFSMState -> null
|
||||
}
|
||||
}
|
||||
pushState(
|
||||
null,
|
||||
"Posts System",
|
||||
"$currentUrl${params.joinToString("&", "?") { "${it.first}=${it.second}" }}"
|
||||
)
|
||||
}
|
||||
|
||||
private fun setState(state: UIFSMState) {
|
||||
storage[state.context.storageKey] = serialFormat.encodeToString(UIFSMStateSerializer, state)
|
||||
private fun takeStates(initialState: UIFSMState): List<UIFSMState> {
|
||||
val params = (URL(window.location.href)).searchParams
|
||||
val additionalStates = listOfNotNull<UIFSMState>()
|
||||
|
||||
return additionalStates + listOfNotNull(
|
||||
if (additionalStates.isEmpty()) {
|
||||
initialState
|
||||
} else {
|
||||
null
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
class JSUIFSMStatesRepo(
|
||||
private val history: History,
|
||||
private val initialState: UIFSMState = DefaultAuthUIFSMState
|
||||
) : DefaultStatesManagerRepo<UIFSMState> {
|
||||
private val statesMap = mutableMapOf<String, UIFSMState>()
|
||||
|
||||
init {
|
||||
val states = takeStates(initialState)
|
||||
states.forEach {
|
||||
statesMap[it.context] = it
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getContextState(context: Any): UIFSMState? {
|
||||
return when (context) {
|
||||
is String -> storage[context.storageKey] ?.UIFSMState ?: return DefaultAuthUIFSMState
|
||||
is String -> statesMap[context]
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun contains(context: Any): Boolean = when (context) {
|
||||
is String -> storage.get(context) ?.UIFSMState != null
|
||||
is String -> statesMap.contains(context)
|
||||
else -> super.contains(context)
|
||||
}
|
||||
|
||||
private fun states(): List<UIFSMState> = storage.iterator().asSequence().mapNotNull { (k, v) ->
|
||||
if (k.startsWith(FSMStateSettingsFieldPrefix)) {
|
||||
v.UIFSMState
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}.toList()
|
||||
|
||||
override suspend fun getStates(): List<UIFSMState> = states()
|
||||
override suspend fun getStates(): List<UIFSMState> = statesMap.values.toList()
|
||||
|
||||
override suspend fun removeState(state: UIFSMState) {
|
||||
storage.removeItem((state.context as? String) ?.storageKey ?: return)
|
||||
statesMap.remove((state.context as? String) ?: return)
|
||||
history.refreshHistory(statesMap.values)
|
||||
}
|
||||
|
||||
override suspend fun set(state: UIFSMState) {
|
||||
setState(state)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val FSMStateSettingsFieldPrefix = "UIFSMState_"
|
||||
console.log(state)
|
||||
statesMap[state.context] = state
|
||||
history.refreshHistory(statesMap.values)
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,81 @@
|
||||
package dev.inmo.postssystem.client.fsm.ui
|
||||
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import dev.inmo.jsuikit.elements.DefaultButton
|
||||
import dev.inmo.jsuikit.elements.DropArea
|
||||
import dev.inmo.jsuikit.utils.InputAttrs
|
||||
import dev.inmo.micro_utils.common.MPPFile
|
||||
import dev.inmo.micro_utils.common.filename
|
||||
import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions
|
||||
import dev.inmo.micro_utils.fsm.common.StatesMachine
|
||||
import dev.inmo.postssystem.client.ui.fsm.CreatePostUIFSMState
|
||||
import dev.inmo.postssystem.client.ui.fsm.UIFSMState
|
||||
import dev.inmo.postssystem.client.utils.renderComposableAndLinkToContext
|
||||
import dev.inmo.postssystem.features.common.common.*
|
||||
import dev.inmo.postssystem.features.content.common.BinaryContent
|
||||
import dev.inmo.postssystem.features.content.text.common.TextContent
|
||||
import dev.inmo.postssystem.services.posts.client.ui.create.PostCreateUIModel
|
||||
import dev.inmo.postssystem.services.posts.client.ui.create.PostCreateUIViewModel
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import org.jetbrains.compose.web.dom.*
|
||||
import org.w3c.dom.HTMLElement
|
||||
import org.w3c.files.get
|
||||
|
||||
class PostCreateView(
|
||||
private val createPostCreateUIModel: PostCreateUIViewModel,
|
||||
private val uiScope: CoroutineScope
|
||||
) : JSView<CreatePostUIFSMState>() {
|
||||
override suspend fun StatesMachine<in UIFSMState>.safeHandleState(
|
||||
htmlElement: HTMLElement,
|
||||
state: CreatePostUIFSMState
|
||||
): UIFSMState? {
|
||||
val result = CompletableDeferred<UIFSMState?>()
|
||||
|
||||
val textContent = mutableStateOf("")
|
||||
val fileState = mutableStateOf<MPPFile?>(null)
|
||||
|
||||
renderComposableAndLinkToContext(htmlElement) {
|
||||
Form {
|
||||
TextArea(textContent.value) {
|
||||
onInput { textContent.value = it.value }
|
||||
}
|
||||
DropArea (
|
||||
inputAttrs = InputAttrs {
|
||||
onInput {
|
||||
it.target.files ?.get(0) ?.let {
|
||||
fileState.value = it
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
DefaultButton(
|
||||
"Upload",
|
||||
disabled = fileState.value == null || textContent.value.isBlank()
|
||||
) {
|
||||
it.preventDefault()
|
||||
fileState.value ?.let { file ->
|
||||
uiScope.launchSafelyWithoutExceptions {
|
||||
createPostCreateUIModel.create(
|
||||
listOf(
|
||||
TextContent(
|
||||
textContent.value
|
||||
),
|
||||
BinaryContent(
|
||||
file.filename,
|
||||
file.mimeType,
|
||||
file.inputProvider()
|
||||
)
|
||||
)
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
console.log("")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.await()
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user