add previews in binary content
This commit is contained in:
parent
787f8d7526
commit
72578f6b58
@ -3,13 +3,6 @@ package dev.inmo.postssystem.features.common.server.sessions
|
|||||||
import org.koin.core.qualifier.StringQualifier
|
import org.koin.core.qualifier.StringQualifier
|
||||||
|
|
||||||
object Qualifiers {
|
object Qualifiers {
|
||||||
val binaryFilesFolderQualifier = StringQualifier("binaryFilesFolder")
|
val filesFolderQualifier = StringQualifier("filesFolder")
|
||||||
val originalFilesMetasKeyValueRepoQualifier = StringQualifier("OriginalFilesMetaKV")
|
|
||||||
val binaryOriginalFilesMetasKeyValueRepoQualifier = StringQualifier("BinaryOriginalFilesMetaKV")
|
|
||||||
val commonFilesMetasKeyValueRepoQualifier = StringQualifier("CommonFilesMetaKV")
|
|
||||||
val binaryFilesMetasKeyValueRepoQualifier = StringQualifier("BinaryFilesMetaKV")
|
|
||||||
val filesFolderQualifier = StringQualifier("rootFilesFolder")
|
|
||||||
val commonFilesFolderQualifier = StringQualifier("commonFilesFolder")
|
|
||||||
val usersRolesKeyValueFactoryQualifier = StringQualifier("usersRolesKeyValueFactory")
|
val usersRolesKeyValueFactoryQualifier = StringQualifier("usersRolesKeyValueFactory")
|
||||||
val binaryStorageFilesQualifier = StringQualifier("binaryContentFiles")
|
|
||||||
}
|
}
|
||||||
|
@ -14,5 +14,10 @@ kotlin {
|
|||||||
api project(":postssystem.features.files.server")
|
api project(":postssystem.features.files.server")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
jvmMain {
|
||||||
|
dependencies {
|
||||||
|
api libs.scrimage
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,105 @@
|
|||||||
package dev.inmo.postssystem.features.content.binary.server
|
package dev.inmo.postssystem.features.content.binary.server
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.exposed.keyvalue.ExposedKeyValueRepo
|
||||||
|
import dev.inmo.postssystem.features.common.common.singleWithBinds
|
||||||
import dev.inmo.postssystem.features.common.common.singleWithRandomQualifier
|
import dev.inmo.postssystem.features.common.common.singleWithRandomQualifier
|
||||||
import dev.inmo.postssystem.features.common.server.sessions.Qualifiers
|
import dev.inmo.postssystem.features.common.server.sessions.Qualifiers
|
||||||
import dev.inmo.postssystem.features.common.server.sessions.ServerModuleLoader
|
import dev.inmo.postssystem.features.common.server.sessions.ServerModuleLoader
|
||||||
import dev.inmo.postssystem.features.content.common.BinaryContent
|
import dev.inmo.postssystem.features.content.common.BinaryContent
|
||||||
import dev.inmo.postssystem.features.content.server.ServerContentStorageWrapper
|
import dev.inmo.postssystem.features.content.server.ServerContentStorageWrapper
|
||||||
import kotlinx.serialization.json.JsonObject
|
import dev.inmo.postssystem.features.files.common.*
|
||||||
|
import dev.inmo.postssystem.features.files.common.storage.DefaultFilesStorage
|
||||||
|
import dev.inmo.postssystem.features.files.common.storage.FilesStorage
|
||||||
|
import kotlinx.serialization.json.*
|
||||||
import org.koin.core.module.Module
|
import org.koin.core.module.Module
|
||||||
|
import org.koin.core.qualifier.StringQualifier
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This provider is declaring one additional optional section: "previewDimensions". This section is an object with two
|
||||||
|
* fields:
|
||||||
|
*
|
||||||
|
* * maxWidth
|
||||||
|
* * maxHeight
|
||||||
|
*
|
||||||
|
* for preview images
|
||||||
|
*/
|
||||||
class BinaryContentServerModuleLoader : ServerModuleLoader {
|
class BinaryContentServerModuleLoader : ServerModuleLoader {
|
||||||
override fun Module.load(config: JsonObject) {
|
override fun Module.load(config: JsonObject) {
|
||||||
|
val binaryFilesFolderQualifier = StringQualifier("binaryFilesFolder")
|
||||||
|
val binaryStorageFilesQualifier = StringQualifier("binaryContentFiles")
|
||||||
|
val binaryPreviewStorageFilesQualifier = StringQualifier("binaryPreviewContentFiles")
|
||||||
|
val binaryPreviewFilesFolderQualifier = StringQualifier("binaryPreviewFilesFolder")
|
||||||
|
val binaryFilesMetasKeyValueRepoQualifier = StringQualifier("BinaryFilesMetaKV")
|
||||||
|
val binaryPreviewFilesMetasKeyValueRepoQualifier = StringQualifier("BinaryPreviewFilesMetaKV")
|
||||||
|
val binaryOriginalFilesMetasKeyValueRepoQualifier = StringQualifier("BinaryOriginalFilesMetaKV")
|
||||||
|
val binaryOriginalPreviewFilesMetasKeyValueRepoQualifier = StringQualifier("BinaryPreviewOriginalFilesMetaKV")
|
||||||
|
|
||||||
|
singleWithBinds(binaryFilesFolderQualifier) {
|
||||||
|
File(get<File>(Qualifiers.filesFolderQualifier), "binary_content").apply {
|
||||||
|
mkdirs()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
single {
|
||||||
|
val dimensionsSection = config["previewDimensions"] ?: return@single PreviewImageDimensionsConfig()
|
||||||
|
get<Json>().decodeFromJsonElement(
|
||||||
|
PreviewImageDimensionsConfig.serializer(),
|
||||||
|
dimensionsSection
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
single<ImagesCropper> {
|
||||||
|
ScrimageBasedImagesCropper(get())
|
||||||
|
}
|
||||||
|
|
||||||
|
singleWithBinds(binaryPreviewFilesFolderQualifier) {
|
||||||
|
File(get<File>(binaryFilesFolderQualifier), "preview").apply {
|
||||||
|
mkdirs()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
singleWithBinds(binaryOriginalFilesMetasKeyValueRepoQualifier) {
|
||||||
|
ExposedKeyValueRepo(get(), { text("fileid") }, { text("metaInfo") }, "BinaryContentFileIdsToMetas")
|
||||||
|
}
|
||||||
|
|
||||||
|
singleWithBinds(binaryOriginalPreviewFilesMetasKeyValueRepoQualifier) {
|
||||||
|
ExposedKeyValueRepo(get(), { text("fileid") }, { text("metaInfo") }, "BinaryPreviewContentFileIdsToMetas")
|
||||||
|
}
|
||||||
|
|
||||||
|
singleWithBinds(binaryFilesMetasKeyValueRepoQualifier) {
|
||||||
|
MetasKeyValueRepo(
|
||||||
|
get(),
|
||||||
|
get(binaryOriginalFilesMetasKeyValueRepoQualifier)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
singleWithBinds(binaryPreviewFilesMetasKeyValueRepoQualifier) {
|
||||||
|
MetasKeyValueRepo(
|
||||||
|
get(),
|
||||||
|
get(binaryOriginalPreviewFilesMetasKeyValueRepoQualifier)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
single<FilesStorage>(binaryStorageFilesQualifier) {
|
||||||
|
DefaultFilesStorage(
|
||||||
|
DiskReadFilesStorage(get(binaryFilesFolderQualifier), get(binaryFilesMetasKeyValueRepoQualifier)),
|
||||||
|
WriteDistFilesStorage(get(binaryFilesFolderQualifier), get(binaryFilesMetasKeyValueRepoQualifier))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
single<FilesStorage>(binaryPreviewStorageFilesQualifier) {
|
||||||
|
DefaultFilesStorage(
|
||||||
|
DiskReadFilesStorage(get(binaryPreviewFilesFolderQualifier), get(binaryPreviewFilesMetasKeyValueRepoQualifier)),
|
||||||
|
WriteDistFilesStorage(get(binaryPreviewFilesFolderQualifier), get(binaryPreviewFilesMetasKeyValueRepoQualifier))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
singleWithRandomQualifier {
|
singleWithRandomQualifier {
|
||||||
ServerContentStorageWrapper(
|
ServerContentStorageWrapper(
|
||||||
BinaryServerContentStorage(get(Qualifiers.binaryStorageFilesQualifier)),
|
BinaryServerContentStorage(
|
||||||
|
get(binaryStorageFilesQualifier),
|
||||||
|
get(binaryPreviewStorageFilesQualifier),
|
||||||
|
get(),
|
||||||
|
get()
|
||||||
|
),
|
||||||
BinaryContent::class
|
BinaryContent::class
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,29 @@
|
|||||||
package dev.inmo.postssystem.features.content.binary.server
|
package dev.inmo.postssystem.features.content.binary.server
|
||||||
|
|
||||||
|
import com.benasher44.uuid.uuid4
|
||||||
|
import dev.inmo.micro_utils.coroutines.plus
|
||||||
|
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
||||||
|
import dev.inmo.micro_utils.mime_types.KnownMimeTypes
|
||||||
import dev.inmo.micro_utils.pagination.*
|
import dev.inmo.micro_utils.pagination.*
|
||||||
import dev.inmo.micro_utils.repos.UpdatedValuePair
|
import dev.inmo.micro_utils.repos.*
|
||||||
|
import dev.inmo.postssystem.features.common.common.FileBasedInputProvider
|
||||||
import dev.inmo.postssystem.features.content.common.*
|
import dev.inmo.postssystem.features.content.common.*
|
||||||
import dev.inmo.postssystem.features.content.server.storage.ServerContentStorage
|
import dev.inmo.postssystem.features.content.server.storage.ServerContentStorage
|
||||||
import dev.inmo.postssystem.features.files.common.*
|
import dev.inmo.postssystem.features.files.common.*
|
||||||
import dev.inmo.postssystem.features.files.common.storage.FilesStorage
|
import dev.inmo.postssystem.features.files.common.storage.FilesStorage
|
||||||
|
import io.ktor.util.asStream
|
||||||
|
import io.ktor.utils.io.core.copyTo
|
||||||
|
import io.ktor.utils.io.streams.asOutput
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
class BinaryServerContentStorage(
|
class BinaryServerContentStorage(
|
||||||
private val filesStorage: FilesStorage
|
private val filesStorage: FilesStorage,
|
||||||
|
private val previewFilesStorage: FilesStorage,
|
||||||
|
private val cropper: ImagesCropper,
|
||||||
|
private val scope: CoroutineScope
|
||||||
) : ServerContentStorage<BinaryContent> {
|
) : ServerContentStorage<BinaryContent> {
|
||||||
private val FileId.asContentId
|
private val FileId.asContentId
|
||||||
get() = ContentId(string)
|
get() = ContentId(string)
|
||||||
@ -35,6 +48,50 @@ class BinaryServerContentStorage(
|
|||||||
override val newObjectsFlow: Flow<RegisteredContent> = filesStorage.newObjectsFlow.map { it.asRegisteredContent }
|
override val newObjectsFlow: Flow<RegisteredContent> = filesStorage.newObjectsFlow.map { it.asRegisteredContent }
|
||||||
override val updatedObjectsFlow: Flow<RegisteredContent> = filesStorage.updatedObjectsFlow.map { it.asRegisteredContent }
|
override val updatedObjectsFlow: Flow<RegisteredContent> = filesStorage.updatedObjectsFlow.map { it.asRegisteredContent }
|
||||||
|
|
||||||
|
private val fullsRemovedJob = deletedObjectsIdsFlow.subscribeSafelyWithoutExceptions(scope) {
|
||||||
|
previewFilesStorage.deleteById(it.asFileId)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val previewCroppingJob = (newObjectsFlow + updatedObjectsFlow).subscribeSafelyWithoutExceptions(scope) {
|
||||||
|
val content = it.content
|
||||||
|
val fileId = it.id.asFileId
|
||||||
|
if (content !is BinaryContent) {
|
||||||
|
return@subscribeSafelyWithoutExceptions
|
||||||
|
}
|
||||||
|
val fullFileInfo = filesStorage.getFullFileInfo(fileId) ?: return@subscribeSafelyWithoutExceptions
|
||||||
|
val fileInfo = fullFileInfo.fileInfo
|
||||||
|
|
||||||
|
if (fileInfo.mimeType is KnownMimeTypes.Image) {
|
||||||
|
cropper.crop(fileInfo.inputProvider).subscribeSafelyWithoutExceptions(scope) {
|
||||||
|
val tempFile = File.createTempFile(uuid4().toString(), ".${fileInfo.name.extension}").apply {
|
||||||
|
deleteOnExit()
|
||||||
|
createNewFile()
|
||||||
|
}
|
||||||
|
runCatching {
|
||||||
|
tempFile.outputStream().use { output ->
|
||||||
|
it.asStream().use { input ->
|
||||||
|
input.copyTo(output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val newFullFileInfo = FullFileInfo(
|
||||||
|
fileInfo.name,
|
||||||
|
fileInfo.mimeType,
|
||||||
|
FileBasedInputProvider(tempFile)
|
||||||
|
)
|
||||||
|
if (previewFilesStorage.contains(fileId)) {
|
||||||
|
previewFilesStorage.update(
|
||||||
|
fullFileInfo.id,
|
||||||
|
newFullFileInfo
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
previewFilesStorage.create(newFullFileInfo).firstOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tempFile.delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun create(values: List<BinaryContent>): List<RegisteredContent> {
|
override suspend fun create(values: List<BinaryContent>): List<RegisteredContent> {
|
||||||
return filesStorage.create(
|
return filesStorage.create(
|
||||||
values.map { it.asFullFileInfo }
|
values.map { it.asFullFileInfo }
|
||||||
@ -83,6 +140,8 @@ class BinaryServerContentStorage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getContentPreview(id: ContentId): RegisteredContent? {
|
override suspend fun getContentPreview(id: ContentId): RegisteredContent? {
|
||||||
TODO("Not yet implemented")
|
val fileId = id.asFileId
|
||||||
|
val fileInfo = previewFilesStorage.getFullFileInfo(fileId) ?: return null
|
||||||
|
return fileInfo.asRegisteredContent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
package dev.inmo.postssystem.features.content.binary.server
|
||||||
|
|
||||||
|
import dev.inmo.postssystem.features.common.common.SimpleInputProvider
|
||||||
|
import io.ktor.utils.io.core.Input
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
interface ImagesCropper {
|
||||||
|
suspend fun crop(inputProvider: SimpleInputProvider): Flow<Input>
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package dev.inmo.postssystem.features.content.binary.server
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class PreviewImageDimensionsConfig(
|
||||||
|
val maxWidth: Int = 1024,
|
||||||
|
val maxHeight: Int = 1024,
|
||||||
|
)
|
@ -0,0 +1,51 @@
|
|||||||
|
package dev.inmo.postssystem.features.content.binary.server
|
||||||
|
|
||||||
|
import com.benasher44.uuid.uuid4
|
||||||
|
import com.sksamuel.scrimage.ImmutableImage
|
||||||
|
import com.sksamuel.scrimage.nio.JpegWriter
|
||||||
|
import dev.inmo.postssystem.features.common.common.SimpleInputProvider
|
||||||
|
import io.ktor.util.asStream
|
||||||
|
import io.ktor.utils.io.core.Input
|
||||||
|
import io.ktor.utils.io.streams.asInput
|
||||||
|
import kotlinx.coroutines.currentCoroutineContext
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.flow
|
||||||
|
import kotlinx.coroutines.isActive
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class ScrimageBasedImagesCropper(
|
||||||
|
private val config: PreviewImageDimensionsConfig
|
||||||
|
) : ImagesCropper {
|
||||||
|
override suspend fun crop(inputProvider: SimpleInputProvider): Flow<Input> = flow {
|
||||||
|
val outputTempFile = File.createTempFile(uuid4().toString(), ".temp").apply {
|
||||||
|
createNewFile()
|
||||||
|
deleteOnExit()
|
||||||
|
}
|
||||||
|
ImmutableImage.loader().fromStream(
|
||||||
|
inputProvider().asStream()
|
||||||
|
).max(
|
||||||
|
config.maxWidth,
|
||||||
|
config.maxHeight
|
||||||
|
).let {
|
||||||
|
if (currentCoroutineContext().isActive) {
|
||||||
|
it.output(
|
||||||
|
JpegWriter(),
|
||||||
|
outputTempFile
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return@flow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val input = outputTempFile.inputStream().asInput()
|
||||||
|
runCatching {
|
||||||
|
emit(input)
|
||||||
|
}.onSuccess {
|
||||||
|
if (input.endOfInput) { // remove file if it was fully read inside of emit
|
||||||
|
outputTempFile.delete()
|
||||||
|
}
|
||||||
|
}.onFailure {
|
||||||
|
outputTempFile.delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -115,4 +115,25 @@ class ServerContentStorageAggregator(
|
|||||||
|
|
||||||
return currentResults.createPaginationResult(pagination, count())
|
return currentResults.createPaginationResult(pagination, count())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getContentPreview(id: ContentId): RegisteredContent? {
|
||||||
|
val result = CompletableDeferred<RegisteredContent>()
|
||||||
|
|
||||||
|
storages.map {
|
||||||
|
scope.launch {
|
||||||
|
val content = it.getContentPreview(id)
|
||||||
|
if (content != null) {
|
||||||
|
result.complete(content)
|
||||||
|
}
|
||||||
|
}.also { job ->
|
||||||
|
result.invokeOnCompletion { job.cancel() }
|
||||||
|
}
|
||||||
|
}.joinAll()
|
||||||
|
|
||||||
|
return if (result.isCompleted) {
|
||||||
|
result.getCompleted()
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,9 @@ class WriteDistFilesStorage(
|
|||||||
input.copyTo(output)
|
input.copyTo(output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FullFileInfoStorageWrapper(newId, it)
|
FullFileInfoStorageWrapper(newId, it).also {
|
||||||
|
_newObjectsFlow.emit(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun deleteById(ids: List<FileId>) {
|
override suspend fun deleteById(ids: List<FileId>) {
|
||||||
|
@ -10,6 +10,7 @@ ktor = "1.6.8"
|
|||||||
klock = "2.6.3"
|
klock = "2.6.3"
|
||||||
exposed = "0.37.3"
|
exposed = "0.37.3"
|
||||||
psql = "42.3.0"
|
psql = "42.3.0"
|
||||||
|
scrimage = "4.0.31"
|
||||||
|
|
||||||
android-dexcount = "3.0.1"
|
android-dexcount = "3.0.1"
|
||||||
android-junit = "4.12"
|
android-junit = "4.12"
|
||||||
@ -50,6 +51,8 @@ tgbotapi = { module = "dev.inmo:tgbotapi", version.ref = "tgbotapi" }
|
|||||||
|
|
||||||
klock = { module = "com.soywiz.korlibs.klock:klock", version.ref = "klock" }
|
klock = { module = "com.soywiz.korlibs.klock:klock", version.ref = "klock" }
|
||||||
|
|
||||||
|
scrimage = { module = "com.sksamuel.scrimage:scrimage-core", version.ref = "scrimage" }
|
||||||
|
|
||||||
androidx-test-junit = { module = "androidx.test.ext:junit", version.ref = "android-test-junit" }
|
androidx-test-junit = { module = "androidx.test.ext:junit", version.ref = "android-test-junit" }
|
||||||
androidx-espresso = { module = "androidx.test.espresso:espresso-core", version.ref = "android-espresso-core" }
|
androidx-espresso = { module = "androidx.test.espresso:espresso-core", version.ref = "android-espresso-core" }
|
||||||
|
|
||||||
|
@ -32,9 +32,4 @@ data class Config(
|
|||||||
}.getOrNull()
|
}.getOrNull()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val commonFilesFolder: File
|
|
||||||
get() = File(filesFolderFile, "common").also { it.mkdirs() }
|
|
||||||
val binaryFilesFolder: File
|
|
||||||
get() = File(filesFolderFile, "binary_content").also { it.mkdirs() }
|
|
||||||
}
|
}
|
||||||
|
@ -94,25 +94,8 @@ fun getDIModule(
|
|||||||
singleWithBinds { get<Config>().databaseConfig }
|
singleWithBinds { get<Config>().databaseConfig }
|
||||||
singleWithBinds { get<Config>().authConfig }
|
singleWithBinds { get<Config>().authConfig }
|
||||||
singleWithBinds(Qualifiers.filesFolderQualifier) { get<Config>().filesFolderFile }
|
singleWithBinds(Qualifiers.filesFolderQualifier) { get<Config>().filesFolderFile }
|
||||||
singleWithBinds(Qualifiers.commonFilesFolderQualifier) { get<Config>().commonFilesFolder }
|
|
||||||
singleWithBinds(Qualifiers.binaryFilesFolderQualifier) { get<Config>().binaryFilesFolder }
|
|
||||||
|
|
||||||
singleWithBinds { get<DatabaseConfig>().database }
|
singleWithBinds { get<DatabaseConfig>().database }
|
||||||
singleWithBinds(Qualifiers.originalFilesMetasKeyValueRepoQualifier) {
|
|
||||||
ExposedKeyValueRepo(get(), { text("fileid") }, { text("metaInfo") }, "FileIdsToMetas")
|
|
||||||
}
|
|
||||||
singleWithBinds(Qualifiers.binaryOriginalFilesMetasKeyValueRepoQualifier) {
|
|
||||||
ExposedKeyValueRepo(get(), { text("fileid") }, { text("metaInfo") }, "BinaryContentFileIdsToMetas")
|
|
||||||
}
|
|
||||||
singleWithBinds(Qualifiers.commonFilesMetasKeyValueRepoQualifier) {
|
|
||||||
MetasKeyValueRepo(
|
|
||||||
get(),
|
|
||||||
get(Qualifiers.originalFilesMetasKeyValueRepoQualifier)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
single<ReadFilesStorage> { DiskReadFilesStorage(get(Qualifiers.commonFilesFolderQualifier), get(Qualifiers.commonFilesMetasKeyValueRepoQualifier)) }
|
|
||||||
single<WriteFilesStorage> { WriteDistFilesStorage(get(Qualifiers.commonFilesFolderQualifier), get(Qualifiers.commonFilesMetasKeyValueRepoQualifier)) }
|
|
||||||
single<FilesStorage> { DefaultFilesStorage(get(), get()) }
|
|
||||||
singleWithBinds { ExposedUsersStorage(get()) }
|
singleWithBinds { ExposedUsersStorage(get()) }
|
||||||
singleWithBinds { exposedUsersAuthenticator(get(), get()) }
|
singleWithBinds { exposedUsersAuthenticator(get(), get()) }
|
||||||
|
|
||||||
@ -139,18 +122,6 @@ fun getDIModule(
|
|||||||
factory<CoroutineScope> { baseScope.LinkedSupervisorScope() }
|
factory<CoroutineScope> { baseScope.LinkedSupervisorScope() }
|
||||||
|
|
||||||
// Content storages
|
// Content storages
|
||||||
singleWithBinds(Qualifiers.binaryFilesMetasKeyValueRepoQualifier) {
|
|
||||||
MetasKeyValueRepo(
|
|
||||||
get(),
|
|
||||||
get(Qualifiers.binaryOriginalFilesMetasKeyValueRepoQualifier)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
single<FilesStorage>(Qualifiers.binaryStorageFilesQualifier) {
|
|
||||||
DefaultFilesStorage(
|
|
||||||
DiskReadFilesStorage(get(Qualifiers.binaryFilesFolderQualifier), get(Qualifiers.binaryFilesMetasKeyValueRepoQualifier)),
|
|
||||||
WriteDistFilesStorage(get(Qualifiers.binaryFilesFolderQualifier), get(Qualifiers.binaryFilesMetasKeyValueRepoQualifier))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
single<ServerContentStorage<Content>> { ServerContentStorageAggregator(getAll(), get()) } binds arrayOf(
|
single<ServerContentStorage<Content>> { ServerContentStorageAggregator(getAll(), get()) } binds arrayOf(
|
||||||
ServerReadContentStorage::class,
|
ServerReadContentStorage::class,
|
||||||
|
@ -20,7 +20,7 @@ class DefaultPostCreateUIModel(
|
|||||||
FullNewPost(content)
|
FullNewPost(content)
|
||||||
) ?: return@runCatching
|
) ?: return@runCatching
|
||||||
delay(1000L)
|
delay(1000L)
|
||||||
publicationService.publish(post.id)
|
// publicationService.publish(post.id)
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
_currentState.value = PostCreateUIState.Fail
|
_currentState.value = PostCreateUIState.Fail
|
||||||
}.onSuccess {
|
}.onSuccess {
|
||||||
|
Loading…
Reference in New Issue
Block a user