Send artifacts inner events

This commit is contained in:
Kgothatso Ngako
2026-07-28 00:52:21 +02:00
parent 0c65f61ea2
commit 33c4d1000f
6 changed files with 327 additions and 179 deletions

View File

@@ -22,6 +22,7 @@ import press.mantra.compose.database.dao.MantraArtifactDao
import press.mantra.compose.database.dao.MantraArtifactVersionDao import press.mantra.compose.database.dao.MantraArtifactVersionDao
import press.mantra.compose.database.dao.MantraChapterDao import press.mantra.compose.database.dao.MantraChapterDao
import press.mantra.compose.database.dao.MantraChunkDao import press.mantra.compose.database.dao.MantraChunkDao
import press.mantra.compose.database.dao.MantraDao
import press.mantra.compose.database.dao.MantraDialectDao import press.mantra.compose.database.dao.MantraDialectDao
import press.mantra.compose.database.dao.MantraTranslationArtifactVersionDao import press.mantra.compose.database.dao.MantraTranslationArtifactVersionDao
import press.mantra.compose.database.dao.MantraTranslationArtifactVersionContributorDao import press.mantra.compose.database.dao.MantraTranslationArtifactVersionContributorDao
@@ -184,6 +185,8 @@ abstract class MantraDatabase: RoomDatabase() {
abstract fun inReplyToRelationDao(): InReplyToRelationDao abstract fun inReplyToRelationDao(): InReplyToRelationDao
abstract fun mantraDao(): MantraDao
abstract fun mantraArtifactDao(): MantraArtifactDao abstract fun mantraArtifactDao(): MantraArtifactDao
abstract fun mantraArtifactVersionDao(): MantraArtifactVersionDao abstract fun mantraArtifactVersionDao(): MantraArtifactVersionDao

View File

@@ -0,0 +1,220 @@
package press.mantra.compose.database.dao
import androidx.room3.Transaction
import co.touchlab.kermit.Logger
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import press.mantra.compose.database.model.ChatMessage
import press.mantra.compose.database.model.MantraArtifact
import press.mantra.compose.database.model.MantraArtifactVersion
import press.mantra.compose.database.model.MantraDialect
import press.mantra.compose.database.model.MarmotInnerEvent
import press.mantra.compose.database.model.intermdiate.LocalChatRoom
import press.mantra.compose.nostr.nip30303.ArtifactEvent
import press.mantra.compose.nostr.nip30303.ArtifactVersionEvent
import press.mantra.compose.nostr.nip30303.DialectEvent
import press.mantra.compose.nostr.nip30303.tags.ArtifactIdTag
import press.mantra.compose.repository.MantraRepository.Companion.DEFAULT_LICENSE
import press.mantra.compose.repository.MantraRepository.Companion.DEFAULT_VISIBILITY
abstract class MantraDao(
private val database: press.mantra.compose.database.MantraDatabase,
) {
val logger = Logger.withTag("NostrDao")
@Transaction
open suspend fun addDialect(
localChatRoom: LocalChatRoom,
name: String,
country: String,
language: String,
userPublicKey: HexKey,
): MarmotInnerEvent? {
logger.d("addDialect: $name")
val dialectEventTemplate = DialectEvent.build(
name = name,
country = country,
language = language,
)
val mantraDialect = MantraDialect.fromDialectEventTemplate(
dialectEventTemplate = dialectEventTemplate,
chatRoomId = localChatRoom.chatRoom.id,
userPublicKey = userPublicKey,
) ?: return null
val dialectInnerEvent = MarmotInnerEvent(
id = mantraDialect.id,
publicKey = mantraDialect.publicKey,
kind = DialectEvent.KIND,
createdAt = mantraDialect.createdAt,
tags = dialectEventTemplate.tags,
content = dialectEventTemplate.content,
chatRoomId = mantraDialect.chatRoomId,
)
return try {
database.mantraDialectDao().upsert(mantraDialect)
database.marmotInnerEventDao().upsert(dialectInnerEvent)
sendMarmotInnerEvent(
localChatRoom = localChatRoom,
text = "Added $name as a dialect",
marmotInnerEvent = dialectInnerEvent
)
dialectInnerEvent
} catch (error: Throwable) {
logger.e("Failed to add dialect \"$name\" to chat room ${localChatRoom.chatRoom.id}", error)
null
}
}
@Transaction
open suspend fun addArtifact(
localChatRoom: LocalChatRoom,
name: String,
url: String,
versionLabel: String,
dialectId: HexKey,
userPublicKey: HexKey,
visibility: String = DEFAULT_VISIBILITY,
license: String = DEFAULT_LICENSE,
): MarmotInnerEvent? {
// TODO: Verify the active user is an admin of the chat room before allowing this.
val artifactEventTemplate = ArtifactEvent.build(
name = name,
url = url,
visibility = visibility,
license = license,
dialectId = dialectId,
)
val mantraArtifact = MantraArtifact.fromArtifactEventTemplate(
artifactEventTemplate = artifactEventTemplate,
chatRoomId = localChatRoom.chatRoom.id,
userPublicKey = userPublicKey,
) ?: return null
// Persist the artifact together with an unprocessed marmot inner event
// (a rumor). Inner events with a null marmotGroupEventId are later
// picked up by the outbound pipeline and encrypted into a kind:445
// group event for the chat room.
//
// This covers the "private" visibility case. Permissioned artifacts
// (published as a PublicMessage) and public artifacts (published as a
// plain nostr event) are not implemented yet.
val artifactInnerEvent = MarmotInnerEvent(
id = mantraArtifact.id,
publicKey = mantraArtifact.publicKey,
kind = ArtifactEvent.KIND,
createdAt = mantraArtifact.createdAt,
tags = artifactEventTemplate.tags,
content = artifactEventTemplate.content,
chatRoomId = mantraArtifact.chatRoomId,
)
return try {
database.mantraArtifactDao().upsert(mantraArtifact)
database.marmotInnerEventDao().upsert(artifactInnerEvent)
sendMarmotInnerEvent(
localChatRoom = localChatRoom,
text = "Added $name to artifacts",
marmotInnerEvent = artifactInnerEvent
)
// Every artifact starts with an initial version.
addArtifactVersionInternal(
localChatRoom = localChatRoom,
artifactId = mantraArtifact.id,
versionLabel = versionLabel,
userPublicKey = userPublicKey,
)
artifactInnerEvent
} catch (error: Throwable) {
logger.e("Failed to add artifact \"$name\" to chat room ${localChatRoom.chatRoom.id}", error)
null
}
}
@Transaction
open suspend fun addArtifactVersion(
localChatRoom: LocalChatRoom,
artifactId: HexKey,
versionLabel: String,
userPublicKey: HexKey,
): MarmotInnerEvent? {
return addArtifactVersionInternal(
localChatRoom = localChatRoom,
artifactId = artifactId,
versionLabel = versionLabel,
userPublicKey = userPublicKey
)
}
private suspend fun addArtifactVersionInternal(
localChatRoom: LocalChatRoom,
artifactId: HexKey,
versionLabel: String,
userPublicKey: HexKey,
): MarmotInnerEvent? {
// The version label is carried in the event content (see
// MantraArtifactVersion.fromArtifactVersionEvent).
val artifactVersionEventTemplate = ArtifactVersionEvent.build(
content = versionLabel,
) {
addUnique(ArtifactIdTag.assemble(artifactId))
}
val mantraArtifactVersion = MantraArtifactVersion.fromArtifactVersionEventTemplate(
artifactVersionEventTemplate = artifactVersionEventTemplate,
chatRoomId = localChatRoom.chatRoom.id,
userPublicKey = userPublicKey,
) ?: return null
val versionInnerEvent = MarmotInnerEvent(
id = mantraArtifactVersion.id,
publicKey = mantraArtifactVersion.publicKey,
kind = ArtifactVersionEvent.KIND,
createdAt = mantraArtifactVersion.createdAt,
tags = artifactVersionEventTemplate.tags,
content = artifactVersionEventTemplate.content,
chatRoomId = mantraArtifactVersion.chatRoomId,
)
database.mantraArtifactVersionDao().upsert(mantraArtifactVersion)
database.marmotInnerEventDao().upsert(versionInnerEvent)
sendMarmotInnerEvent(
localChatRoom = localChatRoom,
text = "Add the ${artifactVersionEventTemplate.content} version",
marmotInnerEvent = versionInnerEvent
)
return versionInnerEvent
}
private suspend fun sendMarmotInnerEvent(
localChatRoom: LocalChatRoom,
text: String,
marmotInnerEvent: MarmotInnerEvent
) {
database.marmotInnerEventDao().upsert(
marmotInnerEvent
)
database.chatMessageDao().upsert(
ChatMessage(
content = text,
chatRoomId = localChatRoom.chatRoom.id,
senderPublicKey = localChatRoom.chatRoom.userPublicKey,
isUserMessage = true,
giftWrapPayloadId = null,
marmotGroupEventId = null,
marmotInnerEventId = marmotInnerEvent.id,
)
)
// TODO: Depending on visibility (if signature is non-empty) might want to queue this event for broadcasting...
}
}

View File

@@ -4,6 +4,7 @@ import co.touchlab.kermit.Logger
import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.HexKey
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import press.mantra.compose.database.MantraDatabase import press.mantra.compose.database.MantraDatabase
import press.mantra.compose.database.model.ChatMessage
import press.mantra.compose.database.model.MantraArtifact import press.mantra.compose.database.model.MantraArtifact
import press.mantra.compose.database.model.MantraArtifactVersion import press.mantra.compose.database.model.MantraArtifactVersion
import press.mantra.compose.database.model.MantraChapter import press.mantra.compose.database.model.MantraChapter
@@ -13,11 +14,10 @@ import press.mantra.compose.database.model.MantraTranslationArtifactVersion
import press.mantra.compose.database.model.MantraTranslationChapter import press.mantra.compose.database.model.MantraTranslationChapter
import press.mantra.compose.database.model.MantraTranslationChunk import press.mantra.compose.database.model.MantraTranslationChunk
import press.mantra.compose.database.model.MarmotInnerEvent import press.mantra.compose.database.model.MarmotInnerEvent
import press.mantra.compose.nostr.nip30303.ArtifactEvent import press.mantra.compose.database.model.intermdiate.LocalChatRoom
import press.mantra.compose.nostr.nip30303.ArtifactVersionEvent import press.mantra.compose.nostr.nip30303.ArtifactVersionEvent
import press.mantra.compose.nostr.nip30303.ChapterEvent import press.mantra.compose.nostr.nip30303.ChapterEvent
import press.mantra.compose.nostr.nip30303.ChunkEvent import press.mantra.compose.nostr.nip30303.ChunkEvent
import press.mantra.compose.nostr.nip30303.DialectEvent
import press.mantra.compose.nostr.nip30303.TranslationArtifactVersionEvent import press.mantra.compose.nostr.nip30303.TranslationArtifactVersionEvent
import press.mantra.compose.nostr.nip30303.TranslationChapterEvent import press.mantra.compose.nostr.nip30303.TranslationChapterEvent
import press.mantra.compose.nostr.nip30303.TranslationChunkEvent import press.mantra.compose.nostr.nip30303.TranslationChunkEvent
@@ -318,140 +318,55 @@ class DatabaseMantraRepository(
database.mantraDialectDao().getDialectById(id) database.mantraDialectDao().getDialectById(id)
override suspend fun addDialect( override suspend fun addDialect(
localChatRoom: LocalChatRoom,
name: String, name: String,
country: String, country: String,
language: String, language: String,
chatRoomId: String,
userPublicKey: HexKey, userPublicKey: HexKey,
): MantraDialect? { ): MarmotInnerEvent? {
val dialectEventTemplate = DialectEvent.build( return database.mantraDao().addDialect(
localChatRoom = localChatRoom,
name = name, name = name,
country = country, country = country,
language = language, language = language,
userPublicKey = userPublicKey
) )
val mantraDialect = MantraDialect.fromDialectEventTemplate(
dialectEventTemplate = dialectEventTemplate,
chatRoomId = chatRoomId,
userPublicKey = userPublicKey,
) ?: return null
val dialectInnerEvent = MarmotInnerEvent(
id = mantraDialect.id,
publicKey = mantraDialect.publicKey,
kind = DialectEvent.KIND,
createdAt = mantraDialect.createdAt,
tags = dialectEventTemplate.tags,
content = dialectEventTemplate.content,
chatRoomId = mantraDialect.chatRoomId,
)
return try {
database.mantraDialectDao().upsert(mantraDialect)
database.marmotInnerEventDao().upsert(dialectInnerEvent)
mantraDialect
} catch (error: Throwable) {
logger.e("Failed to add dialect \"$name\" to chat room $chatRoomId", error)
null
}
} }
override suspend fun addArtifact( override suspend fun addArtifact(
localChatRoom: LocalChatRoom,
name: String, name: String,
url: String, url: String,
versionLabel: String, versionLabel: String,
dialectId: HexKey, dialectId: HexKey,
chatRoomId: String,
userPublicKey: HexKey, userPublicKey: HexKey,
visibility: String, visibility: String,
license: String, license: String,
): MarmotInnerEvent? { ): MarmotInnerEvent? {
// TODO: Verify the active user is an admin of the chat room before allowing this. return database.mantraDao().addArtifact(
val artifactEventTemplate = ArtifactEvent.build( localChatRoom = localChatRoom,
name = name, name = name,
url = url, url = url,
visibility = visibility, versionLabel = versionLabel,
license = license,
dialectId = dialectId, dialectId = dialectId,
)
val mantraArtifact = MantraArtifact.fromArtifactEventTemplate(
artifactEventTemplate = artifactEventTemplate,
chatRoomId = chatRoomId,
userPublicKey = userPublicKey, userPublicKey = userPublicKey,
) ?: return null visibility = visibility,
license = license
// Persist the artifact together with an unprocessed marmot inner event
// (a rumor). Inner events with a null marmotGroupEventId are later
// picked up by the outbound pipeline and encrypted into a kind:445
// group event for the chat room.
//
// This covers the "private" visibility case. Permissioned artifacts
// (published as a PublicMessage) and public artifacts (published as a
// plain nostr event) are not implemented yet.
val artifactInnerEvent = MarmotInnerEvent(
id = mantraArtifact.id,
publicKey = mantraArtifact.publicKey,
kind = ArtifactEvent.KIND,
createdAt = mantraArtifact.createdAt,
tags = artifactEventTemplate.tags,
content = artifactEventTemplate.content,
chatRoomId = mantraArtifact.chatRoomId,
) )
return try {
database.mantraArtifactDao().upsert(mantraArtifact)
database.marmotInnerEventDao().upsert(artifactInnerEvent)
// Every artifact starts with an initial version.
addArtifactVersion(
artifactId = mantraArtifact.id,
versionLabel = versionLabel,
chatRoomId = chatRoomId,
userPublicKey = userPublicKey,
)
artifactInnerEvent
} catch (error: Throwable) {
logger.e("Failed to add artifact \"$name\" to chat room $chatRoomId", error)
null
}
} }
override suspend fun addArtifactVersion( override suspend fun addArtifactVersion(
localChatRoom: LocalChatRoom,
artifactId: HexKey, artifactId: HexKey,
versionLabel: String, versionLabel: String,
chatRoomId: String,
userPublicKey: HexKey, userPublicKey: HexKey,
): MarmotInnerEvent? { ): MarmotInnerEvent? {
// The version label is carried in the event content (see return database.mantraDao().addArtifactVersion(
// MantraArtifactVersion.fromArtifactVersionEvent). localChatRoom = localChatRoom,
val artifactVersionEventTemplate = ArtifactVersionEvent.build( artifactId = artifactId,
content = versionLabel, versionLabel = versionLabel,
) { userPublicKey = userPublicKey
addUnique(ArtifactIdTag.assemble(artifactId))
}
val mantraArtifactVersion = MantraArtifactVersion.fromArtifactVersionEventTemplate(
artifactVersionEventTemplate = artifactVersionEventTemplate,
chatRoomId = chatRoomId,
userPublicKey = userPublicKey,
) ?: return null
val versionInnerEvent = MarmotInnerEvent(
id = mantraArtifactVersion.id,
publicKey = mantraArtifactVersion.publicKey,
kind = ArtifactVersionEvent.KIND,
createdAt = mantraArtifactVersion.createdAt,
tags = artifactVersionEventTemplate.tags,
content = artifactVersionEventTemplate.content,
chatRoomId = mantraArtifactVersion.chatRoomId,
) )
database.mantraArtifactVersionDao().upsert(mantraArtifactVersion)
database.marmotInnerEventDao().upsert(versionInnerEvent)
return versionInnerEvent
} }
companion object { companion object {

View File

@@ -10,6 +10,7 @@ import press.mantra.compose.database.model.MantraTranslationArtifactVersion
import press.mantra.compose.database.model.MantraTranslationChapter import press.mantra.compose.database.model.MantraTranslationChapter
import press.mantra.compose.database.model.MantraTranslationChunk import press.mantra.compose.database.model.MantraTranslationChunk
import press.mantra.compose.database.model.MarmotInnerEvent import press.mantra.compose.database.model.MarmotInnerEvent
import press.mantra.compose.database.model.intermdiate.LocalChatRoom
interface MantraRepository { interface MantraRepository {
suspend fun getArtifacts(chatRoomId: String): List<MantraArtifact> suspend fun getArtifacts(chatRoomId: String): List<MantraArtifact>
@@ -85,28 +86,28 @@ interface MantraRepository {
suspend fun getDialect(id: String): MantraDialect? suspend fun getDialect(id: String): MantraDialect?
suspend fun addDialect( suspend fun addDialect(
localChatRoom: LocalChatRoom,
name: String, name: String,
country: String, country: String,
language: String, language: String,
chatRoomId: String,
userPublicKey: HexKey, userPublicKey: HexKey,
): MantraDialect? ): MarmotInnerEvent?
suspend fun addArtifact( suspend fun addArtifact(
localChatRoom: LocalChatRoom,
name: String, name: String,
url: String, url: String,
versionLabel: String, versionLabel: String,
dialectId: HexKey, dialectId: HexKey,
chatRoomId: String,
userPublicKey: HexKey, userPublicKey: HexKey,
visibility: String = DEFAULT_VISIBILITY, visibility: String = DEFAULT_VISIBILITY,
license: String = DEFAULT_LICENSE, license: String = DEFAULT_LICENSE,
): MarmotInnerEvent? ): MarmotInnerEvent?
suspend fun addArtifactVersion( suspend fun addArtifactVersion(
localChatRoom: LocalChatRoom,
artifactId: HexKey, artifactId: HexKey,
versionLabel: String, versionLabel: String,
chatRoomId: String,
userPublicKey: HexKey, userPublicKey: HexKey,
): MarmotInnerEvent? ): MarmotInnerEvent?
@@ -169,28 +170,28 @@ interface MantraRepository {
override suspend fun getDialect(id: String): MantraDialect? = null override suspend fun getDialect(id: String): MantraDialect? = null
override suspend fun addDialect( override suspend fun addDialect(
localChatRoom: LocalChatRoom,
name: String, name: String,
country: String, country: String,
language: String, language: String,
chatRoomId: String,
userPublicKey: HexKey, userPublicKey: HexKey,
): MantraDialect? = null ): MarmotInnerEvent? = null
override suspend fun addArtifact( override suspend fun addArtifact(
localChatRoom: LocalChatRoom,
name: String, name: String,
url: String, url: String,
versionLabel: String, versionLabel: String,
dialectId: HexKey, dialectId: HexKey,
chatRoomId: String,
userPublicKey: HexKey, userPublicKey: HexKey,
visibility: String, visibility: String,
license: String, license: String,
): MarmotInnerEvent? = null ): MarmotInnerEvent? = null
override suspend fun addArtifactVersion( override suspend fun addArtifactVersion(
localChatRoom: LocalChatRoom,
artifactId: HexKey, artifactId: HexKey,
versionLabel: String, versionLabel: String,
chatRoomId: String,
userPublicKey: HexKey, userPublicKey: HexKey,
): MarmotInnerEvent? = null ): MarmotInnerEvent? = null
} }

View File

@@ -14,13 +14,14 @@ import androidx.lifecycle.viewmodel.viewModelFactory
import press.mantra.compose.repository.ChatRepository import press.mantra.compose.repository.ChatRepository
import press.mantra.compose.repository.NostrRepository import press.mantra.compose.repository.NostrRepository
import co.touchlab.kermit.Logger import co.touchlab.kermit.Logger
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroup
import com.vitorpamplona.quartz.marmot.mls.group.MlsGroupState
import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.HexKey
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO import kotlinx.coroutines.IO
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import press.mantra.compose.database.model.intermdiate.LocalChatRoom import press.mantra.compose.database.model.intermdiate.LocalChatRoom
import press.mantra.compose.repository.MantraRepository import press.mantra.compose.repository.MantraRepository
import press.mantra.compose.repository.MarmotRepository
import press.mantra.compose.ui.view.state.AddArtifactUIState import press.mantra.compose.ui.view.state.AddArtifactUIState
class AddArtifactViewModel( class AddArtifactViewModel(
@@ -72,75 +73,83 @@ class AddArtifactViewModel(
onSuccess: (artifactId: String) -> Unit, onSuccess: (artifactId: String) -> Unit,
onFailure: () -> Unit onFailure: () -> Unit
) { ) {
val name = nameField.text.toString() localChatRoom.chatRoom.mlsGroupState?.let { mlsGroupState ->
val url = urlField.text.toString() MlsGroup.restore(
val versionLabel = versionLabelField.text.toString() MlsGroupState.decodeTls(
val dialectName = dialectNameField.text.toString() mlsGroupState.hexToByteArray()
val dialectCountry = dialectCountryField.text.toString()
val dialectLanguage = dialectLanguageField.text.toString()
// When no existing dialect is selected, the new-dialect fields are required.
val creatingNewDialect = existingDialectId.isNullOrBlank()
val newDialectIncomplete = dialectName.isBlank() || dialectCountry.isBlank() || dialectLanguage.isBlank()
if (name.isBlank() || url.isBlank() || versionLabel.isBlank() ||
(creatingNewDialect && newDialectIncomplete)
) {
onFailure.invoke()
return
}
// Guard against double submits from repeated FAB taps.
if (isActionPending.value) return
isActionPending.value = true
viewModelScope.launch(Dispatchers.IO) {
val marmotInnerEvent = runCatching {
// Reuse the selected dialect, or create a new source dialect and
// reference it by id. addArtifact requires a valid dialectId.
val dialectId = if (creatingNewDialect) {
mantraRepository.addDialect(
name = dialectName,
country = dialectCountry,
language = dialectLanguage,
chatRoomId = localChatRoom.chatRoom.id,
userPublicKey = activeUserPublicKey,
)?.id ?: return@runCatching null
} else {
existingDialectId!!
}
mantraRepository.addArtifact(
name = name,
url = url,
versionLabel = versionLabel,
dialectId = dialectId,
chatRoomId = localChatRoom.chatRoom.id,
userPublicKey = activeUserPublicKey,
visibility = visibility,
license = license,
) )
}.onFailure { error -> )
logger.e("Failed to add artifact", error) }?.let { mlsGroup ->
}.getOrNull() val name = nameField.text.toString()
val url = urlField.text.toString()
val versionLabel = versionLabelField.text.toString()
val dialectName = dialectNameField.text.toString()
val dialectCountry = dialectCountryField.text.toString()
val dialectLanguage = dialectLanguageField.text.toString()
if (marmotInnerEvent != null) { // When no existing dialect is selected, the new-dialect fields are required.
nameField.clearText() val creatingNewDialect = existingDialectId.isNullOrBlank()
urlField.clearText() val newDialectIncomplete = dialectName.isBlank() || dialectCountry.isBlank() || dialectLanguage.isBlank()
versionLabelField.clearText() if (name.isBlank() || url.isBlank() || versionLabel.isBlank() ||
dialectNameField.clearText() (creatingNewDialect && newDialectIncomplete)
dialectCountryField.clearText() ) {
dialectLanguageField.clearText() onFailure.invoke()
return
viewModelScope.launch(Dispatchers.Main) {
onSuccess.invoke(marmotInnerEvent.id)
}
} else {
viewModelScope.launch(Dispatchers.Main) {
onFailure.invoke()
}
} }
isActionPending.value = false // Guard against double submits from repeated FAB taps.
if (isActionPending.value) return
isActionPending.value = true
viewModelScope.launch(Dispatchers.IO) {
val artifactInnerEvent = runCatching {
// Reuse the selected dialect, or create a new source dialect and
// reference it by id. addArtifact requires a valid dialectId.
val dialectId = if (creatingNewDialect) {
mantraRepository.addDialect(
localChatRoom = localChatRoom,
name = dialectName,
country = dialectCountry,
language = dialectLanguage,
userPublicKey = activeUserPublicKey,
)?.id ?: return@runCatching null
} else {
existingDialectId
}
mantraRepository.addArtifact(
localChatRoom = localChatRoom,
name = name,
url = url,
versionLabel = versionLabel,
dialectId = dialectId,
userPublicKey = activeUserPublicKey,
visibility = visibility,
license = license,
)
}.onFailure { error ->
logger.e("Failed to add artifact", error)
}.getOrNull()
if (artifactInnerEvent != null) {
nameField.clearText()
urlField.clearText()
versionLabelField.clearText()
dialectNameField.clearText()
dialectCountryField.clearText()
dialectLanguageField.clearText()
viewModelScope.launch(Dispatchers.Main) {
onSuccess.invoke(artifactInnerEvent.id)
}
} else {
viewModelScope.launch(Dispatchers.Main) {
onFailure.invoke()
}
}
isActionPending.value = false
}
} }
} }

View File

@@ -81,10 +81,10 @@ class AddTranslationViewModel(
// Reuse the selected dialect, or create a new one for the translation. // Reuse the selected dialect, or create a new one for the translation.
val dialectId = if (creatingNewDialect) { val dialectId = if (creatingNewDialect) {
mantraRepository.addDialect( mantraRepository.addDialect(
,
name = dialectName, name = dialectName,
country = dialectCountry, country = dialectCountry,
language = dialectLanguage, language = dialectLanguage,
chatRoomId = chatRoomId,
userPublicKey = activeUserPublicKey, userPublicKey = activeUserPublicKey,
)?.id ?: return@runCatching null )?.id ?: return@runCatching null
} else { } else {