temporal result

This commit is contained in:
InsanusMokrassar 2022-01-17 14:45:12 +06:00
parent ef372ab520
commit a651d8560e
15 changed files with 137 additions and 51 deletions

View File

@ -10,7 +10,7 @@ import org.w3c.files.Blob
fun triggerDownloadFile(fullFileInfo: FullFileInfo) {
val hiddenElement = document.createElement("a") as HTMLAnchorElement
val url = URL.createObjectURL(Blob(arrayOf(fullFileInfo.byteArrayAllocator().toArrayBuffer())))
val url = URL.createObjectURL(Blob(arrayOf(fullFileInfo.inputProvider().toArrayBuffer())))
hiddenElement.href = url
hiddenElement.target = "_blank"
hiddenElement.download = fullFileInfo.name.name

View File

@ -4,9 +4,8 @@ import dev.inmo.postssystem.features.files.common.FullFileInfo
import dev.inmo.micro_utils.common.*
import dev.inmo.micro_utils.mime_types.KnownMimeTypes
import dev.inmo.micro_utils.mime_types.findBuiltinMimeType
import kotlinx.coroutines.CoroutineScope
import io.ktor.utils.io.core.ByteReadPacket
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import org.khronos.webgl.ArrayBuffer
import org.w3c.dom.HTMLInputElement
import org.w3c.dom.events.Event
@ -14,28 +13,64 @@ import org.w3c.files.FileReader
import org.w3c.files.get
fun uploadFileCallbackForHTMLInputChange(
output: MutableStateFlow<FullFileInfo?>,
scope: CoroutineScope
onSet: (FullFileInfo) -> Unit
): (Event) -> Unit = {
(it.target as? HTMLInputElement) ?.apply {
files ?.also { files ->
files[0] ?.also { file ->
scope.launch {
val reader: FileReader = FileReader()
val reader: FileReader = FileReader()
reader.onload = {
val bytes = ((it.target.asDynamic()).result as ArrayBuffer).toByteArray()
output.value = FullFileInfo(
reader.onload = {
val bytes = ((it.target.asDynamic()).result as ArrayBuffer).toByteArray()
onSet(
FullFileInfo(
FileName(file.name),
findBuiltinMimeType(file.type) ?: KnownMimeTypes.Any,
bytes.asAllocator
)
Unit
}
reader.readAsArrayBuffer(file)
) {
ByteReadPacket(bytes)
}
)
}
reader.readAsArrayBuffer(file)
}
}
}
}
fun fileCallbackForHTMLInputChange(
onSet: (MPPFile) -> Unit
): (Event) -> Unit = {
(it.target as? HTMLInputElement) ?.apply {
files ?.also { files ->
files[0] ?.also { file ->
onSet(file)
}
}
}
}
fun uploadFileCallbackForHTMLInputChange(
output: MutableState<FullFileInfo?>
): (Event) -> Unit = uploadFileCallbackForHTMLInputChange {
output.value = it
}
fun uploadFileCallbackForHTMLInputChange(
output: MutableStateFlow<FullFileInfo?>
): (Event) -> Unit = uploadFileCallbackForHTMLInputChange {
output.value = it
}
fun fileCallbackForHTMLInputChange(
output: MutableState<MPPFile?>
): (Event) -> Unit = fileCallbackForHTMLInputChange {
output.value = it
}
fun fileCallbackForHTMLInputChange(
output: MutableStateFlow<MPPFile?>
): (Event) -> Unit = fileCallbackForHTMLInputChange {
output.value = it
}

View File

@ -15,6 +15,7 @@ kotlin {
api "io.insert-koin:koin-core:$koin_version"
api "com.benasher44:uuid:$uuid_version"
api "com.soywiz.korlibs.klock:klock:$klock_version"
api "io.ktor:ktor-http:$ktor_version"
}
}
jvmMain {

View File

@ -0,0 +1,30 @@
package dev.inmo.postssystem.features.common.common
import dev.inmo.micro_utils.common.ByteArrayAllocatorSerializer
import io.ktor.utils.io.core.*
import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
typealias SimpleInputProvider = () -> Input
object SimpleInputProviderSerializer : KSerializer<SimpleInputProvider> {
override val descriptor: SerialDescriptor
get() = ByteArrayAllocatorSerializer.descriptor
override fun deserialize(decoder: Decoder): SimpleInputProvider {
val allocator = ByteArrayAllocatorSerializer.deserialize(decoder)
return {
ByteReadPacket(allocator.invoke())
}
}
override fun serialize(encoder: Encoder, value: SimpleInputProvider) {
ByteArrayAllocatorSerializer.serialize(
encoder
) {
value().readBytes()
}
}
}

View File

@ -1,14 +0,0 @@
package dev.inmo.postssystem.features.content.binary.common
import dev.inmo.micro_utils.common.ByteArrayAllocator
import dev.inmo.micro_utils.common.FileName
import dev.inmo.micro_utils.mime_types.MimeType
import dev.inmo.postssystem.features.content.common.Content
import kotlinx.serialization.Serializable
@Serializable
data class BinaryContent(
val filename: FileName,
val mimeType: MimeType,
val bytesAllocator: ByteArrayAllocator
) : Content

View File

@ -6,6 +6,6 @@ import kotlinx.serialization.modules.PolymorphicModuleBuilder
object BinaryContentSerializerModuleConfigurator : ContentSerializersModuleConfigurator.Element {
override fun PolymorphicModuleBuilder<Content>.invoke() {
subclass(BinaryContent::class, BinaryContent.serializer())
subclass(DefaultBinaryContent::class, DefaultBinaryContent.serializer())
}
}

View File

@ -0,0 +1,14 @@
package dev.inmo.postssystem.features.content.binary.common
import dev.inmo.micro_utils.common.FileName
import dev.inmo.micro_utils.mime_types.MimeType
import dev.inmo.postssystem.features.common.common.SimpleInputProvider
import dev.inmo.postssystem.features.content.common.BinaryContent
import kotlinx.serialization.Serializable
@Serializable
data class DefaultBinaryContent(
override val filename: FileName,
override val mimeType: MimeType,
override val inputProvider: SimpleInputProvider
) : BinaryContent

View File

@ -2,7 +2,7 @@ package dev.inmo.postssystem.features.content.binary.server
import dev.inmo.micro_utils.pagination.*
import dev.inmo.micro_utils.repos.UpdatedValuePair
import dev.inmo.postssystem.features.content.binary.common.BinaryContent
import dev.inmo.postssystem.features.content.binary.common.DefaultBinaryContent
import dev.inmo.postssystem.features.content.common.*
import dev.inmo.postssystem.features.content.server.ServerContentStorage
import dev.inmo.postssystem.features.files.common.*
@ -12,7 +12,7 @@ import kotlinx.coroutines.flow.map
class BinaryServerContentStorage(
private val filesStorage: FilesStorage
) : ServerContentStorage<BinaryContent> {
) : ServerContentStorage<DefaultBinaryContent> {
private val FileId.asContentId
get() = ContentId(string)
private val ContentId.asFileId
@ -20,23 +20,23 @@ class BinaryServerContentStorage(
private val FullFileInfoStorageWrapper.asRegisteredContent
get() = RegisteredContent(
id.asContentId,
BinaryContent(
DefaultBinaryContent(
fileInfo.name,
fileInfo.mimeType,
fileInfo.byteArrayAllocator
fileInfo.inputProvider
)
)
private val BinaryContent.asFullFileInfo
private val DefaultBinaryContent.asFullFileInfo
get() = FullFileInfo(
filename,
mimeType,
bytesAllocator
inputProvider
)
override val deletedObjectsIdsFlow: Flow<ContentId> = filesStorage.deletedObjectsIdsFlow.map { it.asContentId }
override val newObjectsFlow: Flow<RegisteredContent> = filesStorage.newObjectsFlow.map { it.asRegisteredContent }
override val updatedObjectsFlow: Flow<RegisteredContent> = filesStorage.updatedObjectsFlow.map { it.asRegisteredContent }
override suspend fun create(values: List<BinaryContent>): List<RegisteredContent> {
override suspend fun create(values: List<DefaultBinaryContent>): List<RegisteredContent> {
return filesStorage.create(
values.map { it.asFullFileInfo }
).map { it.asRegisteredContent }
@ -46,14 +46,14 @@ class BinaryServerContentStorage(
filesStorage.deleteById(ids.map { it.asFileId })
}
override suspend fun update(id: ContentId, value: BinaryContent): RegisteredContent? {
override suspend fun update(id: ContentId, value: DefaultBinaryContent): RegisteredContent? {
return filesStorage.update(
id.asFileId,
value.asFullFileInfo
) ?.asRegisteredContent
}
override suspend fun update(values: List<UpdatedValuePair<ContentId, BinaryContent>>): List<RegisteredContent> {
override suspend fun update(values: List<UpdatedValuePair<ContentId, DefaultBinaryContent>>): List<RegisteredContent> {
return filesStorage.update(
values.map { (id, content) ->
id.asFileId to content.asFullFileInfo

View File

@ -11,6 +11,7 @@ kotlin {
commonMain {
dependencies {
api project(":postssystem.features.common.common")
api "dev.inmo:micro_utils.mime_types:$microutils_version"
}
}
}

View File

@ -1,5 +1,8 @@
package dev.inmo.postssystem.features.content.common
import dev.inmo.micro_utils.common.FileName
import dev.inmo.micro_utils.mime_types.MimeType
import dev.inmo.postssystem.features.common.common.SimpleInputProvider
import kotlinx.serialization.Serializable
import kotlin.jvm.JvmInline
@ -13,7 +16,21 @@ value class ContentId(val string: String)
* @see ContentSerializersModuleConfigurator.Element
* @see ContentSerializersModuleConfigurator
*/
interface Content
sealed interface Content
/**
* This type of content represents simple content which is easy to serialize/deserialize and to use
*/
interface SimpleContent : Content
/**
* This type represents some binary data which can be sent with multipart and deserialized from it
*/
interface BinaryContent : Content {
val filename: FileName
val mimeType: MimeType
val inputProvider: SimpleInputProvider
}
/**
* Content which is already registered in database. Using its [id] you can retrieve all known

View File

@ -3,6 +3,8 @@ package dev.inmo.postssystem.features.files.common
import dev.inmo.micro_utils.common.*
import dev.inmo.micro_utils.mime_types.MimeType
import dev.inmo.micro_utils.serialization.typed_serializer.TypedSerializer
import dev.inmo.postssystem.features.common.common.SimpleInputProvider
import dev.inmo.postssystem.features.common.common.SimpleInputProviderSerializer
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
@ -28,8 +30,8 @@ data class MetaFileInfo(override val name: FileName, override val mimeType: Mime
data class FullFileInfo(
override val name: FileName,
override val mimeType: MimeType,
@Serializable(ByteArrayAllocatorSerializer::class)
val byteArrayAllocator: ByteArrayAllocator
@Serializable(SimpleInputProviderSerializer::class)
val inputProvider: SimpleInputProvider
) : FileInfo
fun FullFileInfo.toMetaFileInfo() = MetaFileInfo(name, mimeType)

View File

@ -3,6 +3,7 @@ package dev.inmo.postssystem.features.files.common
import dev.inmo.postssystem.features.files.common.storage.ReadFilesStorage
import dev.inmo.micro_utils.pagination.*
import dev.inmo.micro_utils.repos.ReadKeyValueRepo
import io.ktor.utils.io.streams.asInput
import java.io.File
class DiskReadFilesStorage(
@ -38,7 +39,7 @@ class DiskReadFilesStorage(
it.fileInfo.name,
it.fileInfo.mimeType
) {
id.file.readBytes()
id.file.inputStream().asInput()
}
)
}

View File

@ -36,7 +36,7 @@ class WriteDistFilesStorage(
file = newId.file
} while (file.exists())
metasKeyValueRepo.set(newId, it.toMetaFileInfo())
file.writeBytes(it.byteArrayAllocator())
file.writeBytes(it.inputProvider())
FullFileInfoStorageWrapper(newId, it)
}
@ -52,7 +52,7 @@ class WriteDistFilesStorage(
override suspend fun update(
id: FileId,
value: FullFileInfo
): FullFileInfoStorageWrapper? = id.file.takeIf { it.exists() } ?.writeBytes(value.byteArrayAllocator()) ?.let {
): FullFileInfoStorageWrapper? = id.file.takeIf { it.exists() } ?.writeBytes(value.inputProvider()) ?.let {
val result = FullFileInfoStorageWrapper(id, value.copy())
metasKeyValueRepo.set(id, value.toMetaFileInfo())

View File

@ -1,4 +1,4 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
zipStoreBase=GRADLE_USER_HOME

View File

@ -1,13 +1,12 @@
package dev.inmo.postssystem.targets.telegram.publication.server
import dev.inmo.micro_utils.mime_types.KnownMimeTypes
import dev.inmo.postssystem.features.content.binary.common.BinaryContent
import dev.inmo.postssystem.features.content.binary.common.DefaultBinaryContent
import dev.inmo.postssystem.features.content.text.common.TextContent
import dev.inmo.postssystem.features.publication.server.PublicationPost
import dev.inmo.postssystem.features.publication.server.PublicationTarget
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.utils.shortcuts.executeUnsafe
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
import dev.inmo.tgbotapi.requests.abstracts.asMultipartFile
import dev.inmo.tgbotapi.requests.send.SendTextMessage
import dev.inmo.tgbotapi.requests.send.media.*
@ -23,7 +22,7 @@ class PublicationTargetTelegram(
post.content.mapNotNull {
val content = it.content
when (content) {
is BinaryContent -> {
is DefaultBinaryContent -> {
val storageFile by lazy {
StorageFile(content.filename.name, content.bytesAllocator()).asMultipartFile()
}