From d140d1a9171a1bdf0a809e3fbf3620cd5ff5e302 Mon Sep 17 00:00:00 2001 From: Kgothatso Ngako Date: Thu, 4 Jun 2026 14:53:58 +0200 Subject: [PATCH] Relay hints for chat participants --- .../1.json | 18 +++++++++--- .../compose/database/dao/NostrDao.kt | 12 +++++--- .../compose/database/dao/NostrNip17Dao.kt | 5 ++-- .../compose/database/model/GiftWrapPayload.kt | 29 +++++++++++-------- .../compose/database/model/NostrEvent.kt | 5 ++++ .../compose/database/model/Participant.kt | 2 +- .../model/intermdiate/LocalChatRoom.kt | 11 +++---- .../repository/DatabaseChatRepository.kt | 22 +++++++++----- .../compose/repository/ChatRepository.kt | 9 ++++-- .../ui/composable/ChatRoomDetailScreen.kt | 3 ++ .../ui/composable/navigation/AuxNavHost.kt | 1 + .../navigation/routes/ChatRoomDetailRoute.kt | 1 + .../widgets/detail/MetadataEventDetail.kt | 3 +- .../ChatRoomDetailMessageListViewModel.kt | 2 +- .../ui/view/model/ChatRoomDetailViewModel.kt | 12 ++++++-- .../ui/view/model/ChatRoomListViewModel.kt | 3 +- 16 files changed, 92 insertions(+), 46 deletions(-) diff --git a/composeApp/schemas/ac.cord.auxiliary.compose.database.AuxDatabase/1.json b/composeApp/schemas/ac.cord.auxiliary.compose.database.AuxDatabase/1.json index 48e044a8..505de9b9 100644 --- a/composeApp/schemas/ac.cord.auxiliary.compose.database.AuxDatabase/1.json +++ b/composeApp/schemas/ac.cord.auxiliary.compose.database.AuxDatabase/1.json @@ -2,7 +2,7 @@ "formatVersion": 1, "database": { "version": 1, - "identityHash": "a7a5014361138681b4a2123531f2a0e3", + "identityHash": "7aff70ac118cd5856e8a4939d62a2ed8", "entities": [ { "tableName": "BroadcastNostrEventReceipt", @@ -1357,7 +1357,7 @@ }, { "tableName": "NostrEvent", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `pubKey` TEXT NOT NULL, `kind` INTEGER NOT NULL, `tags` TEXT NOT NULL, `content` TEXT NOT NULL, `sig` TEXT NOT NULL, `quotedNostrEventId` TEXT, `quotedAuthorPublicKey` TEXT, `inReplyToNostrEventId` TEXT, `inReplyToAuthorPublicKey` TEXT, `inReplyToRootNostrEventId` TEXT, `inReplyToRootAuthorPublicKey` TEXT, `repostedNostrEventId` TEXT, `repostedAuthorPublicKey` TEXT, `unsignedNostrEventId` INTEGER, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `savedAt` INTEGER NOT NULL, `deletedAt` INTEGER, `broadcastedAt` INTEGER, PRIMARY KEY(`id`))", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `pubKey` TEXT NOT NULL, `kind` INTEGER NOT NULL, `tags` TEXT NOT NULL, `content` TEXT NOT NULL, `sig` TEXT NOT NULL, `relayUrl` TEXT, `quotedNostrEventId` TEXT, `quotedAuthorPublicKey` TEXT, `inReplyToNostrEventId` TEXT, `inReplyToAuthorPublicKey` TEXT, `inReplyToRootNostrEventId` TEXT, `inReplyToRootAuthorPublicKey` TEXT, `repostedNostrEventId` TEXT, `repostedAuthorPublicKey` TEXT, `unsignedNostrEventId` INTEGER, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `savedAt` INTEGER NOT NULL, `deletedAt` INTEGER, `broadcastedAt` INTEGER, PRIMARY KEY(`id`))", "fields": [ { "fieldPath": "id", @@ -1395,6 +1395,11 @@ "affinity": "TEXT", "notNull": true }, + { + "fieldPath": "relayUrl", + "columnName": "relayUrl", + "affinity": "TEXT" + }, { "fieldPath": "quotedNostrEventId", "columnName": "quotedNostrEventId", @@ -1586,7 +1591,7 @@ }, { "tableName": "Participant", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `participantPublicKey` TEXT NOT NULL, `chatRoomId` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `savedAt` INTEGER NOT NULL, `deletedAt` INTEGER, `broadcastedAt` INTEGER, FOREIGN KEY(`participantPublicKey`) REFERENCES `Profile`(`publicKey`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`chatRoomId`) REFERENCES `ChatRoom`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `participantPublicKey` TEXT NOT NULL, `chatRoomId` TEXT NOT NULL, `relayHint` TEXT, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `savedAt` INTEGER NOT NULL, `deletedAt` INTEGER, `broadcastedAt` INTEGER, FOREIGN KEY(`participantPublicKey`) REFERENCES `Profile`(`publicKey`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`chatRoomId`) REFERENCES `ChatRoom`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", "fields": [ { "fieldPath": "id", @@ -1606,6 +1611,11 @@ "affinity": "TEXT", "notNull": true }, + { + "fieldPath": "relayHint", + "columnName": "relayHint", + "affinity": "TEXT" + }, { "fieldPath": "createdAt", "columnName": "createdAt", @@ -2847,7 +2857,7 @@ ], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'a7a5014361138681b4a2123531f2a0e3')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '7aff70ac118cd5856e8a4939d62a2ed8')" ] } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/dao/NostrDao.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/dao/NostrDao.kt index 9b231033..1818a23b 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/dao/NostrDao.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/dao/NostrDao.kt @@ -21,6 +21,7 @@ import androidx.room3.Dao import androidx.room3.Transaction import co.touchlab.kermit.Logger import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent +import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl import com.vitorpamplona.quartz.nip01Core.tags.events.taggedEvents import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUsers import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent @@ -376,17 +377,20 @@ abstract class NostrDao( ChatRoom( id = chatRoomId, userPublicKey = userPublicKey, - subject = decryptedGiftWrapPayload.parseSubject(), // TODO: Get subject from tags... + subject = decryptedGiftWrapPayload.parseSubject(), createdAt = decryptedGiftWrapPayload.createdAt, initialGiftWrapPayloadId = giftWrapPayload.id ) ) // Add participants... - val participants = giftWrapPayload.participantPubKeys().map { + val participants = giftWrapPayload.participantPTags( + NormalizedRelayUrl(relayURL) // TODO: Get relayURL for publicKey profile... + ).map { Participant( - participantPublicKey = it, - chatRoomId = chatRoomId + participantPublicKey = it.pubKey, + chatRoomId = chatRoomId, + relayHint = it.relayHint?.url ) } diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/dao/NostrNip17Dao.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/dao/NostrNip17Dao.kt index 5501ad49..6354557a 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/dao/NostrNip17Dao.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/dao/NostrNip17Dao.kt @@ -32,7 +32,7 @@ abstract class NostrNip17Dao( val logger = Logger.withTag(TAG) @Transaction - open suspend fun getOrCreateChatRoom(publicKey: String, defaultSubject: String? = null): LocalChatRoom? { + open suspend fun getOrCreateChatRoom(publicKey: String, relayHint: String?, defaultSubject: String? = null): LocalChatRoom? { logger.d("getOrCreateChatRoom: $publicKey") val activePublicKey = SeedManager.activePublicKey().toHexKey() @@ -64,7 +64,8 @@ abstract class NostrNip17Dao( profiles.map { Participant( participantPublicKey = it.publicKey, - chatRoomId = chatRoomId + chatRoomId = chatRoomId, + relayHint = relayHint ) } ) diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/GiftWrapPayload.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/GiftWrapPayload.kt index 7350d0d2..c3b2d36f 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/GiftWrapPayload.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/GiftWrapPayload.kt @@ -11,11 +11,10 @@ import androidx.room3.PrimaryKey import co.touchlab.kermit.Logger import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.Kind -import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray +import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl +import com.vitorpamplona.quartz.nip01Core.tags.people.PTag import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUsers import com.vitorpamplona.quartz.nip14Subject.subject -import fr.acinq.bitcoin.PublicKey -import fr.acinq.bitcoin.crypto.musig2.Musig2 import kotlin.time.Clock import kotlin.time.Instant @@ -84,27 +83,33 @@ data class GiftWrapPayload( // TODO: Rename this to GiftWrapPayload... fun aggregatedParticipantsPublicKey(): String? = try { logger.d("aggregateParticipantsPublicKeys") - val hexKeySet = participantPubKeys() + val hexKeySet = participantPTags() - return ChatRoom.deriveChatRoomId(hexKeySet) + return ChatRoom.deriveChatRoomId( + hexKeySet.map { it.pubKey }.toSet() + ) } catch (e: Throwable) { logger.e("Failed to aggregate participants publicKeys", e) return null } - fun participantPubKeys(): Set = try { - val hexKeys = mutableSetOf( - publicKey + fun participantPTags(relayUrl: NormalizedRelayUrl? = null): Set = try { + val pTags = mutableSetOf( + PTag( + pubKey = publicKey, + relayHint = relayUrl + ) ) - hexKeys.addAll( + + pTags.addAll( tags.taggedUsers().map { - it.pubKey + it } ) - return hexKeys + return pTags } catch (e: Throwable) { - logger.e("Failed to get participant public keys", e) + logger.e("Failed to get pTags", e) return emptySet() } diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/NostrEvent.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/NostrEvent.kt index 50101ffc..de585952 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/NostrEvent.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/NostrEvent.kt @@ -56,6 +56,11 @@ data class NostrEvent( val content: String, val sig: HexKey, + /** + * Knew which relay this nostr event came from and use that as a relayHint if need be... + */ + val relayUrl: String? = null, + val quotedNostrEventId: HexKey? = null, val quotedAuthorPublicKey: HexKey? = null, diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/Participant.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/Participant.kt index 35486b51..2ff6787a 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/Participant.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/Participant.kt @@ -44,7 +44,7 @@ data class Participant( val participantPublicKey: HexKey, val chatRoomId: String, - // TODO: Add relayHint... + val relayHint: String?, override val createdAt: Instant = Clock.System.now(), override val updatedAt: Instant = Clock.System.now(), diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/intermdiate/LocalChatRoom.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/intermdiate/LocalChatRoom.kt index fc64c14a..2c2856a6 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/intermdiate/LocalChatRoom.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/intermdiate/LocalChatRoom.kt @@ -1,10 +1,7 @@ package ac.cord.auxiliary.compose.database.model.intermdiate import ac.cord.auxiliary.compose.database.model.ChatRoom -import ac.cord.auxiliary.compose.database.model.Mention import ac.cord.auxiliary.compose.database.model.Participant -import ac.cord.auxiliary.compose.database.model.Post -import ac.cord.auxiliary.compose.database.model.Profile import ac.cord.auxiliary.compose.ui.composable.widgets.profile.ProfileColor import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -22,7 +19,7 @@ data class LocalChatRoom( parentColumns = ["id"], entityColumns = ["chatRoomId"], ) - val participants: List = emptyList(), + val localParticipants: List = emptyList(), ) { @Composable fun RenderChatRoomTitleText() { @@ -32,13 +29,13 @@ data class LocalChatRoom( color = ProfileColor.fromPublicKey(chatRoom.id) ) } else { - if (participants.size == 1) { + if (localParticipants.size == 1) { Text( - text = "Note to Self (${participants.first().profile?.humanReadableNameOrPubkey()})" + text = "Note to Self (${localParticipants.first().profile?.humanReadableNameOrPubkey()})" ) } else { // Remove the active user publicKey from participants... - val participantNames = participants.filter { it.participant.participantPublicKey != chatRoom.userPublicKey }.map { buildAnnotatedString { + val participantNames = localParticipants.filter { it.participant.participantPublicKey != chatRoom.userPublicKey }.map { buildAnnotatedString { withStyle(style = SpanStyle(color = ProfileColor.fromPublicKey(it.participant.participantPublicKey))) { append(it.profile?.humanReadableNameOrPubkey() ?: "unknown participant") } diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/repository/DatabaseChatRepository.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/repository/DatabaseChatRepository.kt index 795380f3..c97db587 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/repository/DatabaseChatRepository.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/repository/DatabaseChatRepository.kt @@ -3,7 +3,6 @@ package ac.cord.auxiliary.compose.database.repository import ac.cord.auxiliary.compose.database.AuxDatabase import ac.cord.auxiliary.compose.database.GENESIS_AT import ac.cord.auxiliary.compose.database.model.ChatMessage -import ac.cord.auxiliary.compose.database.model.ChatMessageNostrEventRelation import ac.cord.auxiliary.compose.database.model.ChatRoom import ac.cord.auxiliary.compose.database.model.GiftWrapPayload import ac.cord.auxiliary.compose.database.model.intermdiate.LocalChatMessage @@ -13,6 +12,7 @@ import co.touchlab.kermit.Logger import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.Kind +import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerSync import com.vitorpamplona.quartz.nip01Core.tags.people.PTag import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUsers @@ -46,9 +46,14 @@ class DatabaseChatRepository( } - override suspend fun getOrCreateChatRoom(publicKey: String, defaultSubject: String?): LocalChatRoom? = try { + override suspend fun getOrCreateChatRoom( + publicKey: String, + relayHint: String?, + defaultSubject: String? + ): LocalChatRoom? = try { return database.nostrNip17Dao().getOrCreateChatRoom( publicKey, + relayHint = relayHint, defaultSubject = defaultSubject ) } catch (e: Throwable) { @@ -91,16 +96,19 @@ class DatabaseChatRepository( ) { logger.i("sendChatMessage($text): $localChatRoom") - val receiverTags = localChatRoom.participants.filter { participant -> - participant.participant.participantPublicKey != localChatRoom.chatRoom.userPublicKey - }.map { participant -> - PTag.assemble(participant.participant.participantPublicKey, null) // TODO: Get the relays associated with the participant... + val receiverTags = localChatRoom.localParticipants.filter { participant -> + participant.participant.participantPublicKey != localChatRoom.chatRoom.userPublicKey // TODO: Allow this where it's notes to self... + }.map { localParticipant -> + PTag.assemble( + localParticipant.participant.participantPublicKey, + localParticipant.participant.relayHint?.let { NormalizedRelayUrl(it) } + ) } val giftWrapPayloadId = database.giftWrapPayloadDao().upsert( GiftWrapPayload( kind = messageType, - tags = receiverTags.toTypedArray(), // TODO: Get participants... + tags = receiverTags.toTypedArray(), content = text, publicKey = localChatRoom.chatRoom.userPublicKey ) diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/repository/ChatRepository.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/repository/ChatRepository.kt index 9ecef73a..ee7a4876 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/repository/ChatRepository.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/repository/ChatRepository.kt @@ -1,6 +1,5 @@ package ac.cord.auxiliary.compose.repository -import ac.cord.auxiliary.compose.database.model.ChatMessage import ac.cord.auxiliary.compose.database.model.ChatRoom import ac.cord.auxiliary.compose.database.model.GiftWrapPayload import ac.cord.auxiliary.compose.database.model.intermdiate.LocalChatMessage @@ -22,7 +21,7 @@ interface ChatRepository { suspend fun observeChatMessageListByChatRoomId(chatRoomId: String): Flow> - suspend fun getOrCreateChatRoom(publicKey: String, defaultSubject: String? = null): LocalChatRoom? + suspend fun getOrCreateChatRoom(publicKey: String, relayHint: String?, defaultSubject: String? = null): LocalChatRoom? suspend fun getChatMessageRelayForPublicKey(publicKey: HexKey): ChatMessageRelayListEvent? @@ -57,7 +56,11 @@ interface ChatRepository { } } - override suspend fun getOrCreateChatRoom(publicKey: String, defaultSubject: String?): LocalChatRoom? { + override suspend fun getOrCreateChatRoom( + publicKey: String, + relayHint: String?, + defaultSubject: String? + ): LocalChatRoom? { return null } diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/ChatRoomDetailScreen.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/ChatRoomDetailScreen.kt index 1b7b1130..26e5898e 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/ChatRoomDetailScreen.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/ChatRoomDetailScreen.kt @@ -50,6 +50,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun ChatRoomDetailScreen( publicKey: String, + relayHint: String?, initialChatRoomDetailUIState: ChatRoomDetailUIState = ChatRoomDetailUIState.Loading, nostrRepository: NostrRepository, chatRepository: ChatRepository @@ -57,6 +58,7 @@ fun ChatRoomDetailScreen( val chatRoomDetailViewModel: ChatRoomDetailViewModel = viewModel( factory = ChatRoomDetailViewModel.factory( publicKey = publicKey, + relayHint = relayHint, initialChatRoomDetailUIState = initialChatRoomDetailUIState, nostrRepository = nostrRepository, chatRepository = chatRepository @@ -269,6 +271,7 @@ private fun ChatRoomDetailScreenPreview() { ) { ChatRoomDetailScreen( publicKey = "publicKey", + relayHint = null, initialChatRoomDetailUIState = ChatRoomDetailUIState.Loaded( localChatRoom = LocalChatRoom( chatRoom = ChatRoom( diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/navigation/AuxNavHost.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/navigation/AuxNavHost.kt index 8e45dc09..4928e13a 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/navigation/AuxNavHost.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/navigation/AuxNavHost.kt @@ -376,6 +376,7 @@ fun AuxNavHost( ChatRoomDetailScreen( publicKey = route.directMessageIdentifier, + relayHint = route.relayHint, nostrRepository = databaseNostrRepository, chatRepository = databaseChatRepository ) diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/navigation/routes/ChatRoomDetailRoute.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/navigation/routes/ChatRoomDetailRoute.kt index cb461e8c..bde28b8c 100755 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/navigation/routes/ChatRoomDetailRoute.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/navigation/routes/ChatRoomDetailRoute.kt @@ -5,5 +5,6 @@ import kotlinx.serialization.Serializable @Serializable data class ChatRoomDetailRoute( val directMessageIdentifier: String, // TODO: have this as a publicKey + val relayHint: String? ): Route() { } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/widgets/detail/MetadataEventDetail.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/widgets/detail/MetadataEventDetail.kt index 4082b80f..3abb1e5a 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/widgets/detail/MetadataEventDetail.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/widgets/detail/MetadataEventDetail.kt @@ -227,7 +227,8 @@ fun MetadataEventDetail( onClick = { onNavigateToChatRoom.invoke( ChatRoomDetailRoute( - directMessageIdentifier = localNostrEvent.nostrEvent.pubKey + directMessageIdentifier = localNostrEvent.nostrEvent.pubKey, + relayHint = localNostrEvent.nostrEvent.relayUrl, ) ) } diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/ChatRoomDetailMessageListViewModel.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/ChatRoomDetailMessageListViewModel.kt index 356cd89c..248a9f82 100755 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/ChatRoomDetailMessageListViewModel.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/ChatRoomDetailMessageListViewModel.kt @@ -96,7 +96,7 @@ class ChatRoomDetailMessageListViewModel( viewModelScope.launch(Dispatchers.IO) { // Sync Notifications... might want to also run this in the background - localChatRoom.participants.filter { it.participant.participantPublicKey != localChatRoom.chatRoom.userPublicKey }.forEach { recipients -> + localChatRoom.localParticipants.filter { it.participant.participantPublicKey != localChatRoom.chatRoom.userPublicKey }.forEach { recipients -> val chatMessageRelayListEvent = chatRepository.getChatMessageRelayForPublicKey(recipients.participant.participantPublicKey) diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/ChatRoomDetailViewModel.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/ChatRoomDetailViewModel.kt index b477508a..fc13c4f6 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/ChatRoomDetailViewModel.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/ChatRoomDetailViewModel.kt @@ -20,6 +20,7 @@ import kotlinx.coroutines.launch class ChatRoomDetailViewModel( val directMessageId: String, + val relayHint: String?, initialChatRoomDetailUIState: ChatRoomDetailUIState, val nostrRepository: NostrRepository, val chatRepository: ChatRepository @@ -36,7 +37,7 @@ class ChatRoomDetailViewModel( fun initiateChatRoomDetail() { if (Crypto.isPubKeyCompressed(directMessageId.hexToByteArray())) { - logger.d("compressed: $directMessageId") + logger.d("compressed (most likely chat room): $directMessageId") // Get ChatRoomById viewModelScope.launch(Dispatchers.IO) { val localChatRoom = chatRepository.getChatRoomByIdentifier(directMessageId) @@ -51,10 +52,13 @@ class ChatRoomDetailViewModel( } } else { - logger.d("Not compressed key publicKey: $directMessageId") + logger.d("Uncompressed publicKey (most likely npub): $directMessageId") viewModelScope.launch(Dispatchers.IO) { // We need to get or create a chat with the user on this publicKey... - val localChatRoom = chatRepository.getOrCreateChatRoom(directMessageId) + val localChatRoom = chatRepository.getOrCreateChatRoom( + publicKey = directMessageId, + relayHint = relayHint + ) chatRoomDetailUIState = if (localChatRoom == null) { ChatRoomDetailUIState.Error @@ -73,6 +77,7 @@ class ChatRoomDetailViewModel( fun factory( publicKey: String, + relayHint: String?, initialChatRoomDetailUIState: ChatRoomDetailUIState = ChatRoomDetailUIState.Loading, nostrRepository: NostrRepository, chatRepository: ChatRepository @@ -80,6 +85,7 @@ class ChatRoomDetailViewModel( initializer { ChatRoomDetailViewModel( directMessageId = publicKey, + relayHint = relayHint, initialChatRoomDetailUIState = initialChatRoomDetailUIState, nostrRepository = nostrRepository, chatRepository = chatRepository diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/ChatRoomListViewModel.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/ChatRoomListViewModel.kt index 2745325d..8f468e93 100755 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/ChatRoomListViewModel.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/ChatRoomListViewModel.kt @@ -144,7 +144,8 @@ class ChatRoomListViewModel( onClick = { onNavigateToDirectMessageDetail.invoke( ChatRoomDetailRoute( - directMessageIdentifier = localChatRoom.chatRoom.id + directMessageIdentifier = localChatRoom.chatRoom.id, + relayHint = localChatRoom.localParticipants.firstOrNull { it.participant.participantPublicKey != localChatRoom.chatRoom.userPublicKey }?.participant?.relayHint ) ) }