temporal unworkable progress

This commit is contained in:
InsanusMokrassar 2022-03-13 21:58:10 +06:00
parent b7bdc6cc75
commit ab10f20723
37 changed files with 313 additions and 53 deletions

View File

@ -10,6 +10,12 @@ apply from: "$mppProjectWithSerializationPresetPath"
kotlin { kotlin {
js(IR) { js(IR) {
binaries.executable() binaries.executable()
compileKotlinJs {
kotlinOptions {
freeCompilerArgs += "-Xir-property-lazy-initialization"
}
}
} }
sourceSets { sourceSets {
commonMain { commonMain {

View File

@ -23,8 +23,7 @@ import dev.inmo.postssystem.client.settings.DefaultSettings
import dev.inmo.postssystem.client.settings.Settings import dev.inmo.postssystem.client.settings.Settings
import dev.inmo.postssystem.client.settings.auth.AuthSettings import dev.inmo.postssystem.client.settings.auth.AuthSettings
import dev.inmo.postssystem.client.settings.auth.DefaultAuthSettings import dev.inmo.postssystem.client.settings.auth.DefaultAuthSettings
import dev.inmo.postssystem.features.common.common.SerializersModuleConfigurator import dev.inmo.postssystem.features.common.common.*
import dev.inmo.postssystem.features.common.common.singleWithRandomQualifier
import dev.inmo.postssystem.features.content.common.ContentSerializersModuleConfigurator import dev.inmo.postssystem.features.content.common.ContentSerializersModuleConfigurator
import dev.inmo.postssystem.features.content.common.OtherContentSerializerModuleConfigurator import dev.inmo.postssystem.features.content.common.OtherContentSerializerModuleConfigurator
import dev.inmo.postssystem.features.content.text.common.TextContentSerializerModuleConfigurator import dev.inmo.postssystem.features.content.text.common.TextContentSerializerModuleConfigurator
@ -95,6 +94,10 @@ fun baseKoin(
)) } } )) } }
single<AuthSettings> { DefaultAuthSettings(get(SettingsQualifier), get(), koin, get()) } single<AuthSettings> { DefaultAuthSettings(get(SettingsQualifier), get(), koin, get()) }
single<Settings> { DefaultSettings(get()) } single<Settings> { DefaultSettings(get()) }
AdditionalModules.modules.forEach {
it.apply { load() }
}
} }
) )
}.koin.apply { }.koin.apply {

View File

@ -13,6 +13,7 @@ import dev.inmo.micro_utils.fsm.common.StatesMachine
import dev.inmo.micro_utils.repos.mappers.withMapper import dev.inmo.micro_utils.repos.mappers.withMapper
import dev.inmo.micro_utils.serialization.typed_serializer.TypedSerializer import dev.inmo.micro_utils.serialization.typed_serializer.TypedSerializer
import dev.inmo.postssystem.client.settings.auth.AuthSettings import dev.inmo.postssystem.client.settings.auth.AuthSettings
import dev.inmo.postssystem.features.common.common.getAllDistinct
import dev.inmo.postssystem.services.posts.client.ui.create.* import dev.inmo.postssystem.services.posts.client.ui.create.*
import kotlinx.browser.* import kotlinx.browser.*
import kotlinx.coroutines.* import kotlinx.coroutines.*
@ -92,7 +93,7 @@ fun baseKoin(): Koin {
factory<PostCreateUIModel> { DefaultPostCreateUIModel(get(), get()) } factory<PostCreateUIModel> { DefaultPostCreateUIModel(get(), get()) }
factory { PostCreateUIViewModel(get()) } factory { PostCreateUIViewModel(get()) }
factory { PostCreateView(get(), get(UIScopeQualifier)) } factory { PostCreateView(get(), getAllDistinct(), get(UIScopeQualifier)) }
} }
) )
strictlyOn<AuthUIFSMState>(get<AuthView>()) strictlyOn<AuthUIFSMState>(get<AuthView>())

View File

@ -1,24 +1,25 @@
package dev.inmo.postssystem.client.fsm.ui package dev.inmo.postssystem.client.fsm.ui
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.*
import dev.inmo.jsuikit.elements.* import dev.inmo.jsuikit.elements.*
import dev.inmo.jsuikit.modifiers.* import dev.inmo.jsuikit.modifiers.*
import dev.inmo.micro_utils.common.* import dev.inmo.jsuikit.utils.Attrs
import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions
import dev.inmo.micro_utils.fsm.common.StatesMachine import dev.inmo.micro_utils.fsm.common.StatesMachine
import dev.inmo.postssystem.client.ui.fsm.CreatePostUIFSMState import dev.inmo.postssystem.client.ui.fsm.CreatePostUIFSMState
import dev.inmo.postssystem.client.ui.fsm.UIFSMState import dev.inmo.postssystem.client.ui.fsm.UIFSMState
import dev.inmo.postssystem.client.utils.renderComposableAndLinkToContext import dev.inmo.postssystem.client.utils.renderComposableAndLinkToContext
import dev.inmo.postssystem.features.content.common.* import dev.inmo.postssystem.features.content.client.ContentClientProvider
import dev.inmo.postssystem.features.content.text.common.TextContent
import dev.inmo.postssystem.services.posts.client.ui.create.PostCreateUIViewModel import dev.inmo.postssystem.services.posts.client.ui.create.PostCreateUIViewModel
import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import org.jetbrains.compose.web.dom.* import org.jetbrains.compose.web.dom.Div
import org.w3c.dom.HTMLElement import org.w3c.dom.HTMLElement
import org.w3c.dom.Text
class PostCreateView( class PostCreateView(
private val createPostCreateUIModel: PostCreateUIViewModel, private val createPostCreateUIModel: PostCreateUIViewModel,
private val contentClientProviders: List<ContentClientProvider>,
private val uiScope: CoroutineScope private val uiScope: CoroutineScope
) : JSView<CreatePostUIFSMState>() { ) : JSView<CreatePostUIFSMState>() {
override suspend fun StatesMachine<in UIFSMState>.safeHandleState( override suspend fun StatesMachine<in UIFSMState>.safeHandleState(
@ -27,68 +28,46 @@ class PostCreateView(
): UIFSMState? { ): UIFSMState? {
val result = CompletableDeferred<UIFSMState?>() val result = CompletableDeferred<UIFSMState?>()
val contentStatesList = mutableStateListOf<Content>() val contentProvidersList = mutableStateListOf<ContentClientProvider.ContentRenderer>()
renderComposableAndLinkToContext(htmlElement) { renderComposableAndLinkToContext(htmlElement) {
Flex( Flex(
UIKitFlex.Alignment.Horizontal.Center UIKitFlex.Alignment.Horizontal.Center
) { ) {
Div({ include(UIKitWidth.Fixed.XLarge) }) { Div ({ include(UIKitWidth.Fixed.XLarge) }) {
contentStatesList.forEachIndexed { i, it -> contentProvidersList.forEachIndexed { i, it ->
Flex(UIKitWidth.Expand) { Flex(UIKitWidth.Expand) {
when (it) { it.render()
is TextContent -> {
TextArea(it.text) {
include(UIKitWidth.Expand)
onInput { contentStatesList[i] = TextContent(it.value) }
}
}
is BinaryContent -> {
DefaultButton(it.filename.name, UIKitWidth.Expand) {
selectFile {
contentStatesList[i] = it.binaryContent()
}
}
}
}
DefaultButton("Remove") { DefaultButton("Remove") {
contentStatesList.removeAt(i) contentProvidersList.removeAt(i)
} }
} }
} }
DefaultButton("Add content") Label("Add content", Attrs.empty())
Dropdown { Dropdown {
DefaultNav { DefaultNav {
NavItemElement( contentClientProviders.forEach {
attributesCustomizer = { NavItemElement(
onClick { attributesCustomizer = {
contentStatesList.add(TextContent("")) onClick { _ ->
} contentProvidersList.add(it.createNewContentRenderer())
}
) {
Text("Text")
}
NavItemElement(
attributesCustomizer = {
onClick {
selectFile {
contentStatesList.add(it.binaryContent())
} }
} }
) {
Text(it.contentTypeNameForUser())
} }
) {
Text("File")
} }
} }
} }
DefaultButton( DefaultButton(
"Upload", "Upload",
disabled = contentStatesList.isEmpty() disabled = contentProvidersList.isEmpty()
) { ) {
it.preventDefault() it.preventDefault()
uiScope.launchSafelyWithoutExceptions { uiScope.launchSafelyWithoutExceptions {
createPostCreateUIModel.create( createPostCreateUIModel.create(
contentStatesList.toList() contentProvidersList.mapNotNull { it.state.value }
) )
} }
} }

View File

@ -2,6 +2,7 @@ plugins {
id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization" id "org.jetbrains.kotlin.plugin.serialization"
id "com.android.library" id "com.android.library"
alias(libs.plugins.compose)
} }
apply from: "$mppProjectWithSerializationPresetPath" apply from: "$mppProjectWithSerializationPresetPath"
@ -14,6 +15,15 @@ kotlin {
api libs.microutils.repos.ktor.client api libs.microutils.repos.ktor.client
api "io.ktor:ktor-client-auth:$ktor_version" api "io.ktor:ktor-client-auth:$ktor_version"
api "io.ktor:ktor-client-logging:$ktor_version" api "io.ktor:ktor-client-logging:$ktor_version"
api compose.runtime
}
}
jsMain {
dependencies {
api compose.web.core
api libs.jsuikit
} }
} }
} }

View File

@ -0,0 +1,11 @@
package dev.inmo.postssystem.features.common.common
object AdditionalModules {
private val additionalModules = mutableListOf<ModuleLoader>()
val modules: List<ModuleLoader>
get() = additionalModules.toList()
fun addModule(moduleLoader: ModuleLoader): Boolean {
return additionalModules.add(moduleLoader)
}
}

View File

@ -0,0 +1,7 @@
package dev.inmo.postssystem.features.common.common
import org.koin.core.module.Module
fun interface ModuleLoader {
fun Module.load()
}

View File

@ -34,6 +34,8 @@ expect class FileBasedInputProvider : SimpleInputProvider {
@Serializable(SimpleInputProviderSerializer::class) @Serializable(SimpleInputProviderSerializer::class)
class CustomInputProvider(private val provider: () -> Input) : SimpleInputProvider { class CustomInputProvider(private val provider: () -> Input) : SimpleInputProvider {
override val contentBytes: Long?
get() = null
override fun invoke(): Input = provider() override fun invoke(): Input = provider()
} }

View File

@ -0,0 +1,40 @@
package dev.inmo.postssystem.features.content.client
import androidx.compose.runtime.*
import dev.inmo.postssystem.features.content.common.Content
interface ContentClientProvider {
fun contentTypeNameForUser(): String
interface ContentRenderer {
val state: State<Content?>
@Composable
fun render()
class Default<T : Content?>(
initValue: T,
private val onRender: @Composable (MutableState<T>) -> Unit
) : ContentRenderer {
private val mutableState = mutableStateOf(initValue)
override val state: State<Content?>
get() = mutableState
@Composable
override fun render() { onRender(mutableState) }
}
companion object {
fun <T: Content> default(onRender: @Composable (MutableState<T?>) -> Unit) = Default(
null,
onRender
)
fun <T: Content?> default(initValue: T, onRender: @Composable (MutableState<T>) -> Unit) = Default(
initValue,
onRender
)
}
}
fun createNewContentRenderer(): ContentRenderer
}

View File

@ -12,6 +12,7 @@ kotlin {
dependencies { dependencies {
api project(":postssystem.features.content.text.common") api project(":postssystem.features.content.text.common")
api project(":postssystem.features.common.client") api project(":postssystem.features.common.client")
api project(":postssystem.features.content.client")
} }
} }
} }

View File

@ -0,0 +1,32 @@
package dev.inmo.postssystem.features.content.text.client
import androidx.compose.runtime.*
import dev.inmo.jsuikit.modifiers.UIKitWidth
import dev.inmo.jsuikit.modifiers.include
import dev.inmo.postssystem.features.common.common.*
import dev.inmo.postssystem.features.content.client.ContentClientProvider
import dev.inmo.postssystem.features.content.common.Content
import dev.inmo.postssystem.features.content.text.common.TextContent
import org.jetbrains.compose.web.dom.TextArea
import org.w3c.dom.Text
val loadingClientModule = ModuleLoader {
singleWithRandomQualifier<ContentClientProvider> {
TextContentClientProvider
}
}.also {
AdditionalModules.addModule(it)
}
object TextContentClientProvider : ContentClientProvider {
override fun contentTypeNameForUser(): String = "Text"
override fun createNewContentRenderer(): ContentClientProvider.ContentRenderer {
return ContentClientProvider.ContentRenderer.default(TextContent("")) { state ->
TextArea(state.value.text) {
include(UIKitWidth.Expand)
onInput { state.value = TextContent(it.value) }
}
}
}
}

View File

@ -15,7 +15,7 @@ kotlin_serialisation_core_version=1.3.2
koin_version=3.1.2 koin_version=3.1.2
ktor_version=1.6.7 ktor_version=1.6.7
logback_version=1.2.10 logback_version=1.2.10
uuid_version=0.3.1 uuid_version=0.4.0
# JS # JS

View File

@ -2,12 +2,12 @@
kotlin = "1.6.10" kotlin = "1.6.10"
kotlin-serialization = "1.3.2" kotlin-serialization = "1.3.2"
jsuikit = "0.0.43" jsuikit = "0.0.44"
compose = "1.1.0" compose = "1.1.1"
microutils = "0.9.12" microutils = "0.9.13"
tgbotapi = "0.38.6" tgbotapi = "0.38.7"
ktor = "1.6.7" ktor = "1.6.7"
klock = "2.6.1" klock = "2.6.2"
exposed = "0.37.3" exposed = "0.37.3"
psql = "42.3.0" psql = "42.3.0"

File diff suppressed because one or more lines are too long

View File

@ -9,6 +9,9 @@ import kotlinx.serialization.Serializable
internal data class TempFileIdentifierInputProvider( internal data class TempFileIdentifierInputProvider(
private val tempFile: FileId private val tempFile: FileId
) : SimpleInputProvider { ) : SimpleInputProvider {
override val contentBytes: Long?
get() = null
override fun invoke(): Input { override fun invoke(): Input {
TODO("Not yet implemented") TODO("Not yet implemented")
} }

View File

@ -9,6 +9,9 @@ import kotlinx.serialization.Serializable
internal data class TempFileIdentifierInputProvider( internal data class TempFileIdentifierInputProvider(
val tempFile: FileId val tempFile: FileId
) : SimpleInputProvider { ) : SimpleInputProvider {
override val contentBytes: Long?
get() = null
override fun invoke(): Input { override fun invoke(): Input {
TODO("Not yet implemented") TODO("Not yet implemented")
} }

View File

@ -58,9 +58,15 @@ String[] includes = [
":publicators:simple:server", ":publicators:simple:server",
":targets:telegram:publication:server", ":targets:telegram:publication:server",
":targets:telegram:loader:client",
":targets:telegram:loader:common", ":targets:telegram:loader:common",
":targets:telegram:loader:server", ":targets:telegram:loader:server",
":targets:telegram:content:polls:client",
":targets:telegram:content:polls:common",
":targets:telegram:content:polls:server",
":server", ":server",
":client", ":client",
":client:uikit", ":client:uikit",

View File

@ -0,0 +1,18 @@
plugins {
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
id "com.android.library"
}
apply from: "$mppProjectWithSerializationPresetPath"
kotlin {
sourceSets {
commonMain {
dependencies {
api project(":postssystem.targets.telegram.content.polls.common")
api project(":postssystem.features.common.client")
}
}
}
}

View File

@ -0,0 +1 @@
<manifest package="dev.inmo.postssystem.targets.telegram.content.polls.client"/>

View File

@ -0,0 +1,18 @@
plugins {
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
id "com.android.library"
}
apply from: "$mppProjectWithSerializationPresetPath"
kotlin {
sourceSets {
commonMain {
dependencies {
api project(":postssystem.features.common.common")
api project(":postssystem.features.content.common")
}
}
}
}

View File

@ -0,0 +1,16 @@
package dev.inmo.postssystem.targets.telegram.content.polls.common
import dev.inmo.postssystem.features.content.common.Content
import kotlinx.serialization.Serializable
@Serializable
data class PollContent(
val options: List<String>,
val answer: Int?
) : Content {
init {
require(answer == null || answer in options.indices) {
"Answer should be in indexes of options ($options), ($answer)"
}
}
}

View File

@ -0,0 +1 @@
<manifest package="dev.inmo.postssystem.targets.telegram.content.polls.common"/>

View File

@ -0,0 +1,17 @@
plugins {
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
}
apply from: "$mppJavaProjectPresetPath"
kotlin {
sourceSets {
commonMain {
dependencies {
api project(":postssystem.targets.telegram.content.polls.common")
api project(":postssystem.features.common.server")
}
}
}
}

View File

@ -12,6 +12,7 @@ kotlin {
dependencies { dependencies {
api project(":postssystem.targets.telegram.loader.common") api project(":postssystem.targets.telegram.loader.common")
api project(":postssystem.features.common.client") api project(":postssystem.features.common.client")
api project(":postssystem.targets.telegram.content.polls.client")
} }
} }
} }

View File

@ -0,0 +1,22 @@
package dev.inmo.postssystem.targets.telegram.loader.client
import dev.inmo.postssystem.features.common.common.*
import dev.inmo.postssystem.features.content.common.ContentSerializersModuleConfigurator
import dev.inmo.postssystem.targets.telegram.content.polls.common.PollContent
import org.koin.core.module.Module
val defaultTelegramTargetModuleLoader = TelegramTargetModuleLoader
object TelegramTargetModuleLoader : ModuleLoader {
init {
AdditionalModules.addModule(this)
}
override fun Module.load() {
singleWithRandomQualifier<ContentSerializersModuleConfigurator.Element> {
ContentSerializersModuleConfigurator.Element {
subclass(PollContent::class, PollContent.serializer())
}
}
}
}

View File

@ -11,6 +11,7 @@ kotlin {
dependencies { dependencies {
api project(":postssystem.targets.telegram.loader.common") api project(":postssystem.targets.telegram.loader.common")
api project(":postssystem.targets.telegram.publication.server") api project(":postssystem.targets.telegram.publication.server")
api project(":postssystem.targets.telegram.content.polls.server")
api project(":postssystem.features.common.server") api project(":postssystem.features.common.server")
} }
} }

View File

@ -2,7 +2,9 @@ package dev.inmo.postssystem.targets.telegram.loader.server
import dev.inmo.postssystem.features.common.common.singleWithRandomQualifier import dev.inmo.postssystem.features.common.common.singleWithRandomQualifier
import dev.inmo.postssystem.features.common.server.sessions.ModuleLoader import dev.inmo.postssystem.features.common.server.sessions.ModuleLoader
import dev.inmo.postssystem.features.content.common.ContentSerializersModuleConfigurator
import dev.inmo.postssystem.features.publication.server.PublicationTarget import dev.inmo.postssystem.features.publication.server.PublicationTarget
import dev.inmo.postssystem.targets.telegram.content.polls.common.PollContent
import dev.inmo.postssystem.targets.telegram.publication.server.PublicationTargetTelegram import dev.inmo.postssystem.targets.telegram.publication.server.PublicationTargetTelegram
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.types.ChatId import dev.inmo.tgbotapi.types.ChatId
@ -28,6 +30,11 @@ class TelegramTargetModuleLoader : ModuleLoader {
singleWithRandomQualifier<PublicationTarget> { singleWithRandomQualifier<PublicationTarget> {
PublicationTargetTelegram(get(), get(postingChatIdQualifier)) PublicationTargetTelegram(get(), get(postingChatIdQualifier))
} }
singleWithRandomQualifier<ContentSerializersModuleConfigurator.Element> {
ContentSerializersModuleConfigurator.Element {
subclass(PollContent::class, PollContent.serializer())
}
}
} }
} }
} }

View File

@ -0,0 +1,18 @@
plugins {
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
id "com.android.library"
}
apply from: "$mppProjectWithSerializationPresetPath"
kotlin {
sourceSets {
commonMain {
dependencies {
api project(":postssystem.targets.telegram.template.common")
api project(":postssystem.features.common.client")
}
}
}
}

View File

@ -0,0 +1 @@
<manifest package="dev.inmo.postssystem.targets.telegram.template.client"/>

View File

@ -0,0 +1,17 @@
plugins {
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
id "com.android.library"
}
apply from: "$mppProjectWithSerializationPresetPath"
kotlin {
sourceSets {
commonMain {
dependencies {
api project(":postssystem.features.common.common")
}
}
}
}

View File

@ -0,0 +1 @@
<manifest package="dev.inmo.postssystem.targets.telegram.template.common"/>

View File

@ -0,0 +1,17 @@
plugins {
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
}
apply from: "$mppJavaProjectPresetPath"
kotlin {
sourceSets {
commonMain {
dependencies {
api project(":postssystem.targets.telegram.template.common")
api project(":postssystem.features.common.server")
}
}
}
}