From 8de05742d0079e1ab25cca92863abe0da206b92c Mon Sep 17 00:00:00 2001 From: Kgothatso Ngako Date: Tue, 28 Jul 2026 09:10:20 +0200 Subject: [PATCH] Add and broadcast chunked chapters --- .gitignore | 1 + .../mantra/compose/database/dao/MantraDao.kt | 123 +++++++++++++++++- .../repository/DatabaseMantraRepository.kt | 78 +---------- .../compose/repository/MantraRepository.kt | 4 +- 4 files changed, 129 insertions(+), 77 deletions(-) diff --git a/.gitignore b/.gitignore index adfa9bff..8a62782e 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ captures !*.xcworkspace/contents.xcworkspacedata **/xcshareddata/WorkspaceSettings.xcsettings node_modules/ +gradle/gradle-daemon-jvm.properties diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/database/dao/MantraDao.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/database/dao/MantraDao.kt index afdd5478..178cd227 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/database/dao/MantraDao.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/database/dao/MantraDao.kt @@ -8,15 +8,20 @@ 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.MantraArtifactVersion +import press.mantra.compose.database.model.MantraChapter +import press.mantra.compose.database.model.MantraChunk 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.ChapterEvent +import press.mantra.compose.nostr.nip30303.ChunkEvent 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 +import press.mantra.compose.text.Markdown @Dao abstract class MantraDao( @@ -198,10 +203,124 @@ abstract class MantraDao( return versionInnerEvent } + @Transaction + open suspend fun addChapter( + artifactId: String, + name: String, + originalText: String, + chatRoomId: String, + userPublicKey: HexKey, + ): MarmotInnerEvent? { + + // Chapters attach to an artifact version; use the latest one. + val version = database.mantraArtifactVersionDao() + .getArtifactVersionsByArtifactId(artifactId) + .firstOrNull() ?: return null + + val chapterIndex = database.mantraChapterDao() + .getChaptersByArtifactVersionId(version.id) + .size + + val chapterEventTemplate = ChapterEvent.build( + artifactVersionId = version.id, + name = name, + originalText = originalText, + index = chapterIndex, + wordCount = Markdown.wordCount(originalText), + characterCount = Markdown.characterCount(originalText), + ) + + val chapter = MantraChapter.fromChapterEventTemplate( + chapterEventTemplate = chapterEventTemplate, + chatRoomId = chatRoomId, + userPublicKey = userPublicKey, + ) ?: return null + + return try { + database.mantraChapterDao().upsert(chapter) + val chapterInnerEvent = MarmotInnerEvent( + id = chapter.id, + publicKey = chapter.publicKey, + kind = ChapterEvent.KIND, + createdAt = chapter.createdAt, + tags = chapterEventTemplate.tags, + content = chapterEventTemplate.content, + chatRoomId = chapter.chatRoomId, + ) + database.marmotInnerEventDao().upsert( + chapterInnerEvent + ) + + sendMarmotInnerEvent( + chatRoomId = chatRoomId, + userPublicKey = userPublicKey, + text = "Added chapter to artifact", // TODO: Get artifact to use in text... + marmotInnerEvent = chapterInnerEvent + ) + + // Split the markdown into paragraph chunks. + Markdown.splitParagraphs(originalText).forEachIndexed { chunkIndex, paragraph -> + val chunkEventTemplate = ChunkEvent.build( + chapterId = chapter.id, + text = paragraph, + index = chunkIndex, + wordCount = Markdown.wordCount(paragraph), + characterCount = Markdown.characterCount(paragraph), + ) + MantraChunk.fromChunkEventTemplate( + chunkEventTemplate = chunkEventTemplate, + chatRoomId = chatRoomId, + userPublicKey = userPublicKey, + )?.let { chunk -> + database.mantraChunkDao().upsert(chunk) + val chunkInnerEvent = MarmotInnerEvent( + id = chunk.id, + publicKey = chunk.publicKey, + kind = ChunkEvent.KIND, + createdAt = chunk.createdAt, + tags = chunkEventTemplate.tags, + content = chunkEventTemplate.content, + chatRoomId = chunk.chatRoomId, + ) + + database.marmotInnerEventDao().upsert( + chunkInnerEvent + ) + + sendMarmotInnerEvent( + chatRoomId = chatRoomId, + userPublicKey = userPublicKey, + text = "${chapter.name} added chunk $chunkIndex", // TODO: Use a portion of the actual chunked text... + marmotInnerEvent = chunkInnerEvent + ) + } + } + + chapterInnerEvent + } catch (error: Throwable) { + logger.e("Failed to add chapter \"$name\" to artifact $artifactId", error) + null + } + } + private suspend fun sendMarmotInnerEvent( localChatRoom: LocalChatRoom, text: String, marmotInnerEvent: MarmotInnerEvent + ) { + sendMarmotInnerEvent( + chatRoomId = localChatRoom.chatRoom.id, + userPublicKey = localChatRoom.chatRoom.userPublicKey, + text = text, + marmotInnerEvent = marmotInnerEvent + ) + } + + private suspend fun sendMarmotInnerEvent( + chatRoomId: String, + userPublicKey: HexKey, + text: String, + marmotInnerEvent: MarmotInnerEvent ) { database.marmotInnerEventDao().upsert( marmotInnerEvent @@ -210,8 +329,8 @@ abstract class MantraDao( database.chatMessageDao().upsert( ChatMessage( content = text, - chatRoomId = localChatRoom.chatRoom.id, - senderPublicKey = localChatRoom.chatRoom.userPublicKey, + chatRoomId = chatRoomId, + senderPublicKey = userPublicKey, isUserMessage = true, giftWrapPayloadId = null, marmotGroupEventId = null, diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/database/repository/DatabaseMantraRepository.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/database/repository/DatabaseMantraRepository.kt index dd0aa49d..0161d344 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/database/repository/DatabaseMantraRepository.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/database/repository/DatabaseMantraRepository.kt @@ -4,7 +4,6 @@ import co.touchlab.kermit.Logger import com.vitorpamplona.quartz.nip01Core.core.HexKey import kotlinx.coroutines.CoroutineScope 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.MantraArtifactVersion import press.mantra.compose.database.model.MantraChapter @@ -15,13 +14,11 @@ import press.mantra.compose.database.model.MantraTranslationChapter import press.mantra.compose.database.model.MantraTranslationChunk import press.mantra.compose.database.model.MarmotInnerEvent import press.mantra.compose.database.model.intermdiate.LocalChatRoom -import press.mantra.compose.nostr.nip30303.ArtifactVersionEvent import press.mantra.compose.nostr.nip30303.ChapterEvent import press.mantra.compose.nostr.nip30303.ChunkEvent import press.mantra.compose.nostr.nip30303.TranslationArtifactVersionEvent import press.mantra.compose.nostr.nip30303.TranslationChapterEvent import press.mantra.compose.nostr.nip30303.TranslationChunkEvent -import press.mantra.compose.nostr.nip30303.tags.ArtifactIdTag import press.mantra.compose.repository.MantraRepository import press.mantra.compose.text.Markdown @@ -236,79 +233,14 @@ class DatabaseMantraRepository( originalText: String, chatRoomId: String, userPublicKey: HexKey, - ): MantraChapter? { - // Chapters attach to an artifact version; use the latest one. - val version = database.mantraArtifactVersionDao() - .getArtifactVersionsByArtifactId(artifactId) - .firstOrNull() ?: return null - - val chapterIndex = database.mantraChapterDao() - .getChaptersByArtifactVersionId(version.id) - .size - - val chapterEventTemplate = ChapterEvent.build( - artifactVersionId = version.id, + ): MarmotInnerEvent? { + return database.mantraDao().addChapter( + artifactId = artifactId, name = name, originalText = originalText, - index = chapterIndex, - wordCount = Markdown.wordCount(originalText), - characterCount = Markdown.characterCount(originalText), - ) - - val chapter = MantraChapter.fromChapterEventTemplate( - chapterEventTemplate = chapterEventTemplate, chatRoomId = chatRoomId, - userPublicKey = userPublicKey, - ) ?: return null - - return try { - database.mantraChapterDao().upsert(chapter) - database.marmotInnerEventDao().upsert( - MarmotInnerEvent( - id = chapter.id, - publicKey = chapter.publicKey, - kind = ChapterEvent.KIND, - createdAt = chapter.createdAt, - tags = chapterEventTemplate.tags, - content = chapterEventTemplate.content, - chatRoomId = chapter.chatRoomId, - ) - ) - - // Split the markdown into paragraph chunks. - Markdown.splitParagraphs(originalText).forEachIndexed { chunkIndex, paragraph -> - val chunkEventTemplate = ChunkEvent.build( - chapterId = chapter.id, - text = paragraph, - index = chunkIndex, - wordCount = Markdown.wordCount(paragraph), - characterCount = Markdown.characterCount(paragraph), - ) - MantraChunk.fromChunkEventTemplate( - chunkEventTemplate = chunkEventTemplate, - chatRoomId = chatRoomId, - userPublicKey = userPublicKey, - )?.let { chunk -> - database.mantraChunkDao().upsert(chunk) - database.marmotInnerEventDao().upsert( - MarmotInnerEvent( - id = chunk.id, - publicKey = chunk.publicKey, - kind = ChunkEvent.KIND, - createdAt = chunk.createdAt, - tags = chunkEventTemplate.tags, - content = chunkEventTemplate.content, - chatRoomId = chunk.chatRoomId, - ) - ) - } - } - - chapter - } catch (error: Throwable) { - logger.e("Failed to add chapter \"$name\" to artifact $artifactId", error) - null - } + userPublicKey = userPublicKey + ) } override suspend fun getDialects(chatRoomId: String): List = diff --git a/composeApp/src/commonMain/kotlin/press/mantra/compose/repository/MantraRepository.kt b/composeApp/src/commonMain/kotlin/press/mantra/compose/repository/MantraRepository.kt index aca77e45..d83fc04f 100644 --- a/composeApp/src/commonMain/kotlin/press/mantra/compose/repository/MantraRepository.kt +++ b/composeApp/src/commonMain/kotlin/press/mantra/compose/repository/MantraRepository.kt @@ -79,7 +79,7 @@ interface MantraRepository { originalText: String, chatRoomId: String, userPublicKey: HexKey, - ): MantraChapter? + ): MarmotInnerEvent? suspend fun getDialects(chatRoomId: String): List @@ -163,7 +163,7 @@ interface MantraRepository { originalText: String, chatRoomId: String, userPublicKey: HexKey, - ): MantraChapter? = null + ): MarmotInnerEvent? = null override suspend fun getDialects(chatRoomId: String): List = emptyList()