Merge branch 'mantra' into claude/marmot-direct-message-type-7a0473

Twenty-two commits had landed on mantra since this branch left it, several
of them in the same files. Merged this way round so mantra stayed untouched
until the result compiled and its tests passed.

The migration had to be renumbered, and this is the conflict that mattered.
mantra is at database version 7 and already has its own 5.json -- for
MarmotInnerEvent.payloadEventId, nothing to do with direct messages. This
branch had also written a 5.json, for a different schema. Resolved by
restoring mantra's 5.json untouched and moving the direct message columns
to an AutoMigration(7, 8) with a regenerated 8.json. Taking either 5.json
over the other would have left every device validating a migration chain
against a schema it was never built from; keeping version = 5 would have
made a v7 install refuse to open at all.

The regenerated 8.json is two ADD COLUMNs and nothing else, same as before.

fromGroupEventResult was restructured on mantra: the kind switch moved into
applyInnerEvent, and a SubmissionEvent envelope now wraps nip30303 payloads.
Took that structure and re-applied the direct message branch ahead of it
rather than inside it -- a gift wrap is not a nip30303 payload to apply, and
what happens to it depends only on whether this device's key opens it, so it
does not belong in a function about applying submissions.

The isUserMessage fix was re-applied to the eight call sites mantra's
version has, up from the six it had here.

ChatMessageListViewModel and ChatRoomMessagingScreen took mantra's versions
with the composer state, the two renderings and the reply action layered
back on.

docs/README.md keeps both new rows and mantra's closing note about the
skipped-keys document.

108 tests pass, up from 50 here and 83 on mantra.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kgothatso NgakoandClaude Opus 5 committed 2026-09-05 23:45:08 +02:00
commit bcdfd2ec94
72 files changed
+22707 -748

No files matched your search

@@ -16,9 +16,11 @@ import press.mantra.compose.database.dao.ChatMessageNostrEventRelationDao
import press.mantra.compose.database.dao.ChatRoomDao
import press.mantra.compose.database.dao.ConnectionDao
import press.mantra.compose.database.dao.DkgSessionDao
import press.mantra.compose.database.dao.FrostSigningSessionDao
import press.mantra.compose.database.dao.GiftWrapMessageDao
import press.mantra.compose.database.dao.GiftWrapPayloadDao
import press.mantra.compose.database.dao.GiftWrapSealDao
import press.mantra.compose.database.dao.GroupKeyStateDao
import press.mantra.compose.database.dao.InReplyToRelationDao
import press.mantra.compose.database.dao.MantraArtifactDao
import press.mantra.compose.database.dao.MantraArtifactVersionDao
@@ -70,6 +72,7 @@ import press.mantra.compose.database.model.Connection
import press.mantra.compose.database.model.GiftWrapMessage
import press.mantra.compose.database.model.GiftWrapPayload
import press.mantra.compose.database.model.GiftWrapSeal
import press.mantra.compose.database.model.GroupKeyState
import press.mantra.compose.database.model.InReplyToRelation
import press.mantra.compose.database.model.MantraArtifact
import press.mantra.compose.database.model.MantraArtifactVersion
@@ -102,6 +105,8 @@ import press.mantra.compose.database.model.Reaction
import press.mantra.compose.database.model.RecentSearch
import press.mantra.compose.database.model.DkgParticipantMessage
import press.mantra.compose.database.model.DkgSession
import press.mantra.compose.database.model.FrostSignerMessage
import press.mantra.compose.database.model.FrostSigningSession
import press.mantra.compose.database.model.Relay
import press.mantra.compose.database.model.RepostedRelation
import press.mantra.compose.database.model.SynchronizeNostrEventRequest
@@ -124,9 +129,12 @@ val GENESIS_AT = Instant.fromEpochMilliseconds(1231006505000L)
ChatRoom::class,
DkgParticipantMessage::class,
DkgSession::class,
FrostSignerMessage::class,
FrostSigningSession::class,
GiftWrapMessage::class,
GiftWrapSeal::class,
GiftWrapPayload::class,
GroupKeyState::class,
InReplyToRelation::class,
MantraArtifact::class,
MantraArtifactVersion::class,
@@ -164,7 +172,7 @@ val GENESIS_AT = Instant.fromEpochMilliseconds(1231006505000L)
UnsignedNostrEvent::class,
Zap::class
],
version = 5,
version = 8,
autoMigrations = [
// v2 only adds the DkgSession/DkgParticipantMessage tables, so Room can
// generate the migration itself — nothing existing changes shape.
@@ -178,11 +186,29 @@ val GENESIS_AT = Instant.fromEpochMilliseconds(1231006505000L)
// into one type per ritual step. Data, not shape, so it is a manual
// migration passed to the builder rather than an entry here. See
// MIGRATION_3_4.
// v5 adds a nullable direct message recipient to MarmotInnerEvent and
//
// v5 adds the nullable MarmotInnerEvent.payloadEventId, which names the
// nip30303 event a SubmissionEvent rumor carries. Rumors queued before
// this come back null, which reads as "not a submission" -- correct,
// since none of them were.
AutoMigration(from = 4, to = 5),
// v6 adds the FrostSigningSession/FrostSignerMessage tables and the
// nullable DkgSession.publicShares. New tables and a nullable column are
// both shapes Room can migrate itself. A ceremony that completed before
// this reads back null, and signing falls back to not cross-checking
// shares rather than refusing to run.
AutoMigration(from = 5, to = 6),
// v7 adds the GroupKeyState table, which records what shared key a room
// signs with instead of leaving it to be rederived. A new table is a
// shape Room migrates itself. Rooms created before this have no row and
// fall back to the rederivation scan in FrostSigningManager.completedKey,
// which is why that scan stays.
AutoMigration(from = 6, to = 7),
// v8 adds a nullable direct message recipient to MarmotInnerEvent and
// ChatMessage. Nullable additions need no default and drop no data, so Room
// generates this one. Rows written before it come back null, which reads as
// "not a direct message" -- the only answer that is true of all of them.
AutoMigration(from = 4, to = 5),
AutoMigration(from = 7, to = 8)
]
)
@ColumnTypeConverters(MantraConverters::class)
@@ -202,6 +228,10 @@ abstract class MantraDatabase: RoomDatabase() {
abstract fun dkgSessionDao(): DkgSessionDao
abstract fun frostSigningSessionDao(): FrostSigningSessionDao
abstract fun groupKeyStateDao(): GroupKeyStateDao
abstract fun connectionDao(): ConnectionDao
abstract fun giftWrapMessageDao(): GiftWrapMessageDao