Relay hints for chat participants
This commit is contained in:
1 parent
0d4b517506
commit
d140d1a917
16 files changed
+92
-46
No files matched your search
@@ -2,7 +2,7 @@
|
|||||||
"formatVersion": 1,
|
"formatVersion": 1,
|
||||||
"database": {
|
"database": {
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"identityHash": "a7a5014361138681b4a2123531f2a0e3",
|
"identityHash": "7aff70ac118cd5856e8a4939d62a2ed8",
|
||||||
"entities": [
|
"entities": [
|
||||||
{
|
{
|
||||||
"tableName": "BroadcastNostrEventReceipt",
|
"tableName": "BroadcastNostrEventReceipt",
|
||||||
@@ -1357,7 +1357,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tableName": "NostrEvent",
|
"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": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldPath": "id",
|
"fieldPath": "id",
|
||||||
@@ -1395,6 +1395,11 @@
|
|||||||
"affinity": "TEXT",
|
"affinity": "TEXT",
|
||||||
"notNull": true
|
"notNull": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "relayUrl",
|
||||||
|
"columnName": "relayUrl",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldPath": "quotedNostrEventId",
|
"fieldPath": "quotedNostrEventId",
|
||||||
"columnName": "quotedNostrEventId",
|
"columnName": "quotedNostrEventId",
|
||||||
@@ -1586,7 +1591,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tableName": "Participant",
|
"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": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldPath": "id",
|
"fieldPath": "id",
|
||||||
@@ -1606,6 +1611,11 @@
|
|||||||
"affinity": "TEXT",
|
"affinity": "TEXT",
|
||||||
"notNull": true
|
"notNull": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "relayHint",
|
||||||
|
"columnName": "relayHint",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldPath": "createdAt",
|
"fieldPath": "createdAt",
|
||||||
"columnName": "createdAt",
|
"columnName": "createdAt",
|
||||||
@@ -2847,7 +2857,7 @@
|
|||||||
],
|
],
|
||||||
"setupQueries": [
|
"setupQueries": [
|
||||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
"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')"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -21,6 +21,7 @@ import androidx.room3.Dao
|
|||||||
import androidx.room3.Transaction
|
import androidx.room3.Transaction
|
||||||
import co.touchlab.kermit.Logger
|
import co.touchlab.kermit.Logger
|
||||||
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
|
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.events.taggedEvents
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUsers
|
import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUsers
|
||||||
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
|
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
|
||||||
@@ -376,17 +377,20 @@ abstract class NostrDao(
|
|||||||
ChatRoom(
|
ChatRoom(
|
||||||
id = chatRoomId,
|
id = chatRoomId,
|
||||||
userPublicKey = userPublicKey,
|
userPublicKey = userPublicKey,
|
||||||
subject = decryptedGiftWrapPayload.parseSubject(), // TODO: Get subject from tags...
|
subject = decryptedGiftWrapPayload.parseSubject(),
|
||||||
createdAt = decryptedGiftWrapPayload.createdAt,
|
createdAt = decryptedGiftWrapPayload.createdAt,
|
||||||
initialGiftWrapPayloadId = giftWrapPayload.id
|
initialGiftWrapPayloadId = giftWrapPayload.id
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Add participants...
|
// Add participants...
|
||||||
val participants = giftWrapPayload.participantPubKeys().map {
|
val participants = giftWrapPayload.participantPTags(
|
||||||
|
NormalizedRelayUrl(relayURL) // TODO: Get relayURL for publicKey profile...
|
||||||
|
).map {
|
||||||
Participant(
|
Participant(
|
||||||
participantPublicKey = it,
|
participantPublicKey = it.pubKey,
|
||||||
chatRoomId = chatRoomId
|
chatRoomId = chatRoomId,
|
||||||
|
relayHint = it.relayHint?.url
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -32,7 +32,7 @@ abstract class NostrNip17Dao(
|
|||||||
val logger = Logger.withTag(TAG)
|
val logger = Logger.withTag(TAG)
|
||||||
|
|
||||||
@Transaction
|
@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")
|
logger.d("getOrCreateChatRoom: $publicKey")
|
||||||
|
|
||||||
val activePublicKey = SeedManager.activePublicKey().toHexKey()
|
val activePublicKey = SeedManager.activePublicKey().toHexKey()
|
||||||
@@ -64,7 +64,8 @@ abstract class NostrNip17Dao(
|
|||||||
profiles.map {
|
profiles.map {
|
||||||
Participant(
|
Participant(
|
||||||
participantPublicKey = it.publicKey,
|
participantPublicKey = it.publicKey,
|
||||||
chatRoomId = chatRoomId
|
chatRoomId = chatRoomId,
|
||||||
|
relayHint = relayHint
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
+17
-12
@@ -11,11 +11,10 @@ import androidx.room3.PrimaryKey
|
|||||||
import co.touchlab.kermit.Logger
|
import co.touchlab.kermit.Logger
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.Kind
|
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.nip01Core.tags.people.taggedUsers
|
||||||
import com.vitorpamplona.quartz.nip14Subject.subject
|
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.Clock
|
||||||
import kotlin.time.Instant
|
import kotlin.time.Instant
|
||||||
|
|
||||||
@@ -84,27 +83,33 @@ data class GiftWrapPayload( // TODO: Rename this to GiftWrapPayload...
|
|||||||
fun aggregatedParticipantsPublicKey(): String? = try {
|
fun aggregatedParticipantsPublicKey(): String? = try {
|
||||||
logger.d("aggregateParticipantsPublicKeys")
|
logger.d("aggregateParticipantsPublicKeys")
|
||||||
|
|
||||||
val hexKeySet = participantPubKeys()
|
val hexKeySet = participantPTags()
|
||||||
|
|
||||||
return ChatRoom.deriveChatRoomId(hexKeySet)
|
return ChatRoom.deriveChatRoomId(
|
||||||
|
hexKeySet.map { it.pubKey }.toSet()
|
||||||
|
)
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
logger.e("Failed to aggregate participants publicKeys", e)
|
logger.e("Failed to aggregate participants publicKeys", e)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun participantPubKeys(): Set<HexKey> = try {
|
fun participantPTags(relayUrl: NormalizedRelayUrl? = null): Set<PTag> = try {
|
||||||
val hexKeys = mutableSetOf(
|
val pTags = mutableSetOf(
|
||||||
publicKey
|
PTag(
|
||||||
|
pubKey = publicKey,
|
||||||
|
relayHint = relayUrl
|
||||||
|
)
|
||||||
)
|
)
|
||||||
hexKeys.addAll(
|
|
||||||
|
pTags.addAll(
|
||||||
tags.taggedUsers().map {
|
tags.taggedUsers().map {
|
||||||
it.pubKey
|
it
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
return hexKeys
|
return pTags
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
logger.e("Failed to get participant public keys", e)
|
logger.e("Failed to get pTags", e)
|
||||||
return emptySet()
|
return emptySet()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
@@ -56,6 +56,11 @@ data class NostrEvent(
|
|||||||
val content: String,
|
val content: String,
|
||||||
val sig: HexKey,
|
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 quotedNostrEventId: HexKey? = null,
|
||||||
val quotedAuthorPublicKey: HexKey? = null,
|
val quotedAuthorPublicKey: HexKey? = null,
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -44,7 +44,7 @@ data class Participant(
|
|||||||
val participantPublicKey: HexKey,
|
val participantPublicKey: HexKey,
|
||||||
val chatRoomId: String,
|
val chatRoomId: String,
|
||||||
|
|
||||||
// TODO: Add relayHint...
|
val relayHint: String?,
|
||||||
|
|
||||||
override val createdAt: Instant = Clock.System.now(),
|
override val createdAt: Instant = Clock.System.now(),
|
||||||
override val updatedAt: Instant = Clock.System.now(),
|
override val updatedAt: Instant = Clock.System.now(),
|
||||||
|
|||||||
+4
-7
@@ -1,10 +1,7 @@
|
|||||||
package ac.cord.auxiliary.compose.database.model.intermdiate
|
package ac.cord.auxiliary.compose.database.model.intermdiate
|
||||||
|
|
||||||
import ac.cord.auxiliary.compose.database.model.ChatRoom
|
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.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 ac.cord.auxiliary.compose.ui.composable.widgets.profile.ProfileColor
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -22,7 +19,7 @@ data class LocalChatRoom(
|
|||||||
parentColumns = ["id"],
|
parentColumns = ["id"],
|
||||||
entityColumns = ["chatRoomId"],
|
entityColumns = ["chatRoomId"],
|
||||||
)
|
)
|
||||||
val participants: List<LocalParticipant> = emptyList(),
|
val localParticipants: List<LocalParticipant> = emptyList(),
|
||||||
) {
|
) {
|
||||||
@Composable
|
@Composable
|
||||||
fun RenderChatRoomTitleText() {
|
fun RenderChatRoomTitleText() {
|
||||||
@@ -32,13 +29,13 @@ data class LocalChatRoom(
|
|||||||
color = ProfileColor.fromPublicKey(chatRoom.id)
|
color = ProfileColor.fromPublicKey(chatRoom.id)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
if (participants.size == 1) {
|
if (localParticipants.size == 1) {
|
||||||
Text(
|
Text(
|
||||||
text = "Note to Self (${participants.first().profile?.humanReadableNameOrPubkey()})"
|
text = "Note to Self (${localParticipants.first().profile?.humanReadableNameOrPubkey()})"
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// Remove the active user publicKey from participants...
|
// 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))) {
|
withStyle(style = SpanStyle(color = ProfileColor.fromPublicKey(it.participant.participantPublicKey))) {
|
||||||
append(it.profile?.humanReadableNameOrPubkey() ?: "unknown participant")
|
append(it.profile?.humanReadableNameOrPubkey() ?: "unknown participant")
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-7
@@ -3,7 +3,6 @@ package ac.cord.auxiliary.compose.database.repository
|
|||||||
import ac.cord.auxiliary.compose.database.AuxDatabase
|
import ac.cord.auxiliary.compose.database.AuxDatabase
|
||||||
import ac.cord.auxiliary.compose.database.GENESIS_AT
|
import ac.cord.auxiliary.compose.database.GENESIS_AT
|
||||||
import ac.cord.auxiliary.compose.database.model.ChatMessage
|
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.ChatRoom
|
||||||
import ac.cord.auxiliary.compose.database.model.GiftWrapPayload
|
import ac.cord.auxiliary.compose.database.model.GiftWrapPayload
|
||||||
import ac.cord.auxiliary.compose.database.model.intermdiate.LocalChatMessage
|
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.Event
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.Kind
|
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.signers.NostrSignerSync
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUsers
|
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(
|
return database.nostrNip17Dao().getOrCreateChatRoom(
|
||||||
publicKey,
|
publicKey,
|
||||||
|
relayHint = relayHint,
|
||||||
defaultSubject = defaultSubject
|
defaultSubject = defaultSubject
|
||||||
)
|
)
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
@@ -91,16 +96,19 @@ class DatabaseChatRepository(
|
|||||||
) {
|
) {
|
||||||
logger.i("sendChatMessage($text): $localChatRoom")
|
logger.i("sendChatMessage($text): $localChatRoom")
|
||||||
|
|
||||||
val receiverTags = localChatRoom.participants.filter { participant ->
|
val receiverTags = localChatRoom.localParticipants.filter { participant ->
|
||||||
participant.participant.participantPublicKey != localChatRoom.chatRoom.userPublicKey
|
participant.participant.participantPublicKey != localChatRoom.chatRoom.userPublicKey // TODO: Allow this where it's notes to self...
|
||||||
}.map { participant ->
|
}.map { localParticipant ->
|
||||||
PTag.assemble(participant.participant.participantPublicKey, null) // TODO: Get the relays associated with the participant...
|
PTag.assemble(
|
||||||
|
localParticipant.participant.participantPublicKey,
|
||||||
|
localParticipant.participant.relayHint?.let { NormalizedRelayUrl(it) }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val giftWrapPayloadId = database.giftWrapPayloadDao().upsert(
|
val giftWrapPayloadId = database.giftWrapPayloadDao().upsert(
|
||||||
GiftWrapPayload(
|
GiftWrapPayload(
|
||||||
kind = messageType,
|
kind = messageType,
|
||||||
tags = receiverTags.toTypedArray(), // TODO: Get participants...
|
tags = receiverTags.toTypedArray(),
|
||||||
content = text,
|
content = text,
|
||||||
publicKey = localChatRoom.chatRoom.userPublicKey
|
publicKey = localChatRoom.chatRoom.userPublicKey
|
||||||
)
|
)
|
||||||
|
|||||||
+6
-3
@@ -1,6 +1,5 @@
|
|||||||
package ac.cord.auxiliary.compose.repository
|
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.ChatRoom
|
||||||
import ac.cord.auxiliary.compose.database.model.GiftWrapPayload
|
import ac.cord.auxiliary.compose.database.model.GiftWrapPayload
|
||||||
import ac.cord.auxiliary.compose.database.model.intermdiate.LocalChatMessage
|
import ac.cord.auxiliary.compose.database.model.intermdiate.LocalChatMessage
|
||||||
@@ -22,7 +21,7 @@ interface ChatRepository {
|
|||||||
|
|
||||||
suspend fun observeChatMessageListByChatRoomId(chatRoomId: String): Flow<List<LocalChatMessage>>
|
suspend fun observeChatMessageListByChatRoomId(chatRoomId: String): Flow<List<LocalChatMessage>>
|
||||||
|
|
||||||
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?
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
@@ -50,6 +50,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel
|
|||||||
@Composable
|
@Composable
|
||||||
fun ChatRoomDetailScreen(
|
fun ChatRoomDetailScreen(
|
||||||
publicKey: String,
|
publicKey: String,
|
||||||
|
relayHint: String?,
|
||||||
initialChatRoomDetailUIState: ChatRoomDetailUIState = ChatRoomDetailUIState.Loading,
|
initialChatRoomDetailUIState: ChatRoomDetailUIState = ChatRoomDetailUIState.Loading,
|
||||||
nostrRepository: NostrRepository,
|
nostrRepository: NostrRepository,
|
||||||
chatRepository: ChatRepository
|
chatRepository: ChatRepository
|
||||||
@@ -57,6 +58,7 @@ fun ChatRoomDetailScreen(
|
|||||||
val chatRoomDetailViewModel: ChatRoomDetailViewModel = viewModel(
|
val chatRoomDetailViewModel: ChatRoomDetailViewModel = viewModel(
|
||||||
factory = ChatRoomDetailViewModel.factory(
|
factory = ChatRoomDetailViewModel.factory(
|
||||||
publicKey = publicKey,
|
publicKey = publicKey,
|
||||||
|
relayHint = relayHint,
|
||||||
initialChatRoomDetailUIState = initialChatRoomDetailUIState,
|
initialChatRoomDetailUIState = initialChatRoomDetailUIState,
|
||||||
nostrRepository = nostrRepository,
|
nostrRepository = nostrRepository,
|
||||||
chatRepository = chatRepository
|
chatRepository = chatRepository
|
||||||
@@ -269,6 +271,7 @@ private fun ChatRoomDetailScreenPreview() {
|
|||||||
) {
|
) {
|
||||||
ChatRoomDetailScreen(
|
ChatRoomDetailScreen(
|
||||||
publicKey = "publicKey",
|
publicKey = "publicKey",
|
||||||
|
relayHint = null,
|
||||||
initialChatRoomDetailUIState = ChatRoomDetailUIState.Loaded(
|
initialChatRoomDetailUIState = ChatRoomDetailUIState.Loaded(
|
||||||
localChatRoom = LocalChatRoom(
|
localChatRoom = LocalChatRoom(
|
||||||
chatRoom = ChatRoom(
|
chatRoom = ChatRoom(
|
||||||
|
|||||||
+1
@@ -376,6 +376,7 @@ fun AuxNavHost(
|
|||||||
|
|
||||||
ChatRoomDetailScreen(
|
ChatRoomDetailScreen(
|
||||||
publicKey = route.directMessageIdentifier,
|
publicKey = route.directMessageIdentifier,
|
||||||
|
relayHint = route.relayHint,
|
||||||
nostrRepository = databaseNostrRepository,
|
nostrRepository = databaseNostrRepository,
|
||||||
chatRepository = databaseChatRepository
|
chatRepository = databaseChatRepository
|
||||||
)
|
)
|
||||||
|
|||||||
+1
@@ -5,5 +5,6 @@ import kotlinx.serialization.Serializable
|
|||||||
@Serializable
|
@Serializable
|
||||||
data class ChatRoomDetailRoute(
|
data class ChatRoomDetailRoute(
|
||||||
val directMessageIdentifier: String, // TODO: have this as a publicKey
|
val directMessageIdentifier: String, // TODO: have this as a publicKey
|
||||||
|
val relayHint: String?
|
||||||
): Route() {
|
): Route() {
|
||||||
}
|
}
|
||||||
+2
-1
@@ -227,7 +227,8 @@ fun MetadataEventDetail(
|
|||||||
onClick = {
|
onClick = {
|
||||||
onNavigateToChatRoom.invoke(
|
onNavigateToChatRoom.invoke(
|
||||||
ChatRoomDetailRoute(
|
ChatRoomDetailRoute(
|
||||||
directMessageIdentifier = localNostrEvent.nostrEvent.pubKey
|
directMessageIdentifier = localNostrEvent.nostrEvent.pubKey,
|
||||||
|
relayHint = localNostrEvent.nostrEvent.relayUrl,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -96,7 +96,7 @@ class ChatRoomDetailMessageListViewModel(
|
|||||||
|
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
// Sync Notifications... might want to also run this in the background
|
// 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)
|
val chatMessageRelayListEvent = chatRepository.getChatMessageRelayForPublicKey(recipients.participant.participantPublicKey)
|
||||||
|
|
||||||
|
|||||||
+9
-3
@@ -20,6 +20,7 @@ import kotlinx.coroutines.launch
|
|||||||
|
|
||||||
class ChatRoomDetailViewModel(
|
class ChatRoomDetailViewModel(
|
||||||
val directMessageId: String,
|
val directMessageId: String,
|
||||||
|
val relayHint: String?,
|
||||||
initialChatRoomDetailUIState: ChatRoomDetailUIState,
|
initialChatRoomDetailUIState: ChatRoomDetailUIState,
|
||||||
val nostrRepository: NostrRepository,
|
val nostrRepository: NostrRepository,
|
||||||
val chatRepository: ChatRepository
|
val chatRepository: ChatRepository
|
||||||
@@ -36,7 +37,7 @@ class ChatRoomDetailViewModel(
|
|||||||
|
|
||||||
fun initiateChatRoomDetail() {
|
fun initiateChatRoomDetail() {
|
||||||
if (Crypto.isPubKeyCompressed(directMessageId.hexToByteArray())) {
|
if (Crypto.isPubKeyCompressed(directMessageId.hexToByteArray())) {
|
||||||
logger.d("compressed: $directMessageId")
|
logger.d("compressed (most likely chat room): $directMessageId")
|
||||||
// Get ChatRoomById
|
// Get ChatRoomById
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val localChatRoom = chatRepository.getChatRoomByIdentifier(directMessageId)
|
val localChatRoom = chatRepository.getChatRoomByIdentifier(directMessageId)
|
||||||
@@ -51,10 +52,13 @@ class ChatRoomDetailViewModel(
|
|||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.d("Not compressed key publicKey: $directMessageId")
|
logger.d("Uncompressed publicKey (most likely npub): $directMessageId")
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
// We need to get or create a chat with the user on this publicKey...
|
// 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 = if (localChatRoom == null) {
|
||||||
ChatRoomDetailUIState.Error
|
ChatRoomDetailUIState.Error
|
||||||
@@ -73,6 +77,7 @@ class ChatRoomDetailViewModel(
|
|||||||
|
|
||||||
fun factory(
|
fun factory(
|
||||||
publicKey: String,
|
publicKey: String,
|
||||||
|
relayHint: String?,
|
||||||
initialChatRoomDetailUIState: ChatRoomDetailUIState = ChatRoomDetailUIState.Loading,
|
initialChatRoomDetailUIState: ChatRoomDetailUIState = ChatRoomDetailUIState.Loading,
|
||||||
nostrRepository: NostrRepository,
|
nostrRepository: NostrRepository,
|
||||||
chatRepository: ChatRepository
|
chatRepository: ChatRepository
|
||||||
@@ -80,6 +85,7 @@ class ChatRoomDetailViewModel(
|
|||||||
initializer {
|
initializer {
|
||||||
ChatRoomDetailViewModel(
|
ChatRoomDetailViewModel(
|
||||||
directMessageId = publicKey,
|
directMessageId = publicKey,
|
||||||
|
relayHint = relayHint,
|
||||||
initialChatRoomDetailUIState = initialChatRoomDetailUIState,
|
initialChatRoomDetailUIState = initialChatRoomDetailUIState,
|
||||||
nostrRepository = nostrRepository,
|
nostrRepository = nostrRepository,
|
||||||
chatRepository = chatRepository
|
chatRepository = chatRepository
|
||||||
|
|||||||
+2
-1
@@ -144,7 +144,8 @@ class ChatRoomListViewModel(
|
|||||||
onClick = {
|
onClick = {
|
||||||
onNavigateToDirectMessageDetail.invoke(
|
onNavigateToDirectMessageDetail.invoke(
|
||||||
ChatRoomDetailRoute(
|
ChatRoomDetailRoute(
|
||||||
directMessageIdentifier = localChatRoom.chatRoom.id
|
directMessageIdentifier = localChatRoom.chatRoom.id,
|
||||||
|
relayHint = localChatRoom.localParticipants.firstOrNull { it.participant.participantPublicKey != localChatRoom.chatRoom.userPublicKey }?.participant?.relayHint
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user