temporal unworkable progress

This commit is contained in:
2022-03-13 21:58:10 +06:00
parent b7bdc6cc75
commit ab10f20723
37 changed files with 313 additions and 53 deletions
client
build.gradle
src
commonMain
kotlin
dev
inmo
postssystem
client
jsMain
kotlin
dev
inmo
postssystem
features
common
client
build.gradle
src
commonMain
kotlin
dev
inmo
postssystem
common
src
commonMain
kotlin
dev
inmo
postssystem
features
content
client
src
jsMain
kotlin
dev
inmo
postssystem
features
text
client
build.gradle
src
jsMain
kotlin
dev
inmo
postssystem
features
gradle.properties
gradle
server/src/main/resources/web
services/posts
client
src
commonMain
kotlin
dev
inmo
postssystem
server
src
jvmMain
kotlin
dev
inmo
postssystem
settings.gradle
targets/telegram
content
polls
client
build.gradle
src
commonMain
kotlin
dev
inmo
postssystem
targets
telegram
content
polls
client
main
common
build.gradle
src
commonMain
kotlin
dev
inmo
postssystem
targets
telegram
content
polls
main
server
build.gradle
src
jvmMain
kotlin
dev
inmo
postssystem
targets
telegram
content
polls
server
loader
client
build.gradle
src
commonMain
kotlin
dev
inmo
postssystem
targets
telegram
server
build.gradle
src
jvmMain
kotlin
dev
inmo
postssystem
targets
telegram
template
client
build.gradle
src
commonMain
kotlin
dev
inmo
postssystem
targets
telegram
template
client
main
common
build.gradle
src
commonMain
kotlin
dev
inmo
postssystem
targets
telegram
template
common
main
server
build.gradle
src
jvmMain
kotlin
dev
inmo
postssystem
targets
telegram
template
server

@ -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 {

@ -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 {

@ -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>())

@ -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 }
) )
} }
} }

@ -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
} }
} }
} }

@ -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)
}
}

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

@ -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()
} }

@ -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
}

@ -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")
} }
} }
} }

@ -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) }
}
}
}
}

@ -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

@ -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

@ -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")
} }

@ -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")
} }

@ -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",

@ -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")
}
}
}
}

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

@ -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")
}
}
}
}

@ -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)"
}
}
}

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

@ -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")
}
}
}
}

@ -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")
} }
} }
} }

@ -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())
}
}
}
}

@ -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")
} }
} }

@ -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())
}
}
} }
} }
} }

@ -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")
}
}
}
}

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

@ -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")
}
}
}
}

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

@ -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")
}
}
}
}