Send artifacts inner events
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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...
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user