temporal result
This commit is contained in:
parent
ef372ab520
commit
a651d8560e
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -11,6 +11,7 @@ kotlin {
|
||||
commonMain {
|
||||
dependencies {
|
||||
api project(":postssystem.features.common.common")
|
||||
api "dev.inmo:micro_utils.mime_types:$microutils_version"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -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())
|
||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -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
|
||||
|
@ -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()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user