From 88e20248d8a39bcfcea8562b391c26f4ed77a35d Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Mon, 21 Oct 2024 21:53:40 -0700 Subject: [PATCH] add ability to filter consent --- .../org/xmtp/android/library/V3ClientTest.kt | 34 +++++++++++++ .../org/xmtp/android/library/Conversations.kt | 50 ++++++++++++++----- 2 files changed, 71 insertions(+), 13 deletions(-) diff --git a/library/src/androidTest/java/org/xmtp/android/library/V3ClientTest.kt b/library/src/androidTest/java/org/xmtp/android/library/V3ClientTest.kt index 3eb879ab4..5ae75845d 100644 --- a/library/src/androidTest/java/org/xmtp/android/library/V3ClientTest.kt +++ b/library/src/androidTest/java/org/xmtp/android/library/V3ClientTest.kt @@ -113,6 +113,18 @@ class V3ClientTest { } } + @Test + fun testsCanFindConversationByTopic() { + val group = + runBlocking { boV3Client.conversations.newGroup(listOf(caroV2V3.walletAddress)) } + val dm = runBlocking { boV3Client.conversations.findOrCreateDm(caroV2V3.walletAddress) } + + val sameDm = boV3Client.findConversationByTopic(dm.topic) + val sameGroup = boV3Client.findConversationByTopic(group.topic) + assertEquals(group.id, sameGroup?.id) + assertEquals(dm.id, sameDm?.id) + } + @Test fun testsCanListConversations() { val dm = runBlocking { boV3Client.conversations.findOrCreateDm(caroV2V3.walletAddress) } @@ -130,6 +142,28 @@ class V3ClientTest { assertEquals(runBlocking { caroV2V3Client.conversations.listGroups().size }, 1) } + @Test + fun testsCanListConversationsFiltered() { + val dm = runBlocking { boV3Client.conversations.findOrCreateDm(caroV2V3.walletAddress) } + val group = + runBlocking { boV3Client.conversations.newGroup(listOf(caroV2V3.walletAddress)) } + assertEquals(runBlocking { boV3Client.conversations.listConversations().size }, 2) + assertEquals( + runBlocking { boV3Client.conversations.listConversations(consentState = ConsentState.ALLOWED).size }, + 2 + ) + runBlocking { group.updateConsentState(ConsentState.DENIED) } + assertEquals( + runBlocking { boV3Client.conversations.listConversations(consentState = ConsentState.ALLOWED).size }, + 1 + ) + assertEquals( + runBlocking { boV3Client.conversations.listConversations(consentState = ConsentState.DENIED).size }, + 1 + ) + assertEquals(runBlocking { boV3Client.conversations.listConversations().size }, 2) + } + @Test fun testCanListConversationsOrder() { val dm = runBlocking { boV3Client.conversations.findOrCreateDm(caroV2V3.walletAddress) } diff --git a/library/src/main/java/org/xmtp/android/library/Conversations.kt b/library/src/main/java/org/xmtp/android/library/Conversations.kt index a50da5631..039672e4b 100644 --- a/library/src/main/java/org/xmtp/android/library/Conversations.kt +++ b/library/src/main/java/org/xmtp/android/library/Conversations.kt @@ -7,6 +7,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.merge import kotlinx.coroutines.launch +import org.xmtp.android.library.ConsentState.Companion.toFfiConsentState import org.xmtp.android.library.GRPCApiClient.Companion.makeQueryRequest import org.xmtp.android.library.Util.Companion.envelopeFromFFi import org.xmtp.android.library.libxmtp.MessageV3 @@ -36,6 +37,7 @@ import org.xmtp.proto.keystore.api.v1.Keystore.GetConversationHmacKeysResponse.H import org.xmtp.proto.keystore.api.v1.Keystore.TopicMap.TopicData import org.xmtp.proto.message.contents.Contact import org.xmtp.proto.message.contents.Invitation +import uniffi.xmtpv3.FfiConsentState import uniffi.xmtpv3.FfiConversation import uniffi.xmtpv3.FfiConversationCallback import uniffi.xmtpv3.FfiConversations @@ -342,19 +344,32 @@ data class Conversations( before: Date? = null, limit: Int? = null, order: ConversationOrder = ConversationOrder.CREATED_AT, + consentState: ConsentState? = null, ): List { - if (client.hasV2Client) throw XMTPException("Only supported for V3 only clients.") - val ffiConversation = libXMTPConversations?.list( - opts = FfiListConversationsOptions( + if (client.hasV2Client) + throw XMTPException("Only supported for V3 only clients.") + + val ffiConversations = libXMTPConversations?.list( + FfiListConversationsOptions( after?.time?.nanoseconds?.toLong(DurationUnit.NANOSECONDS), before?.time?.nanoseconds?.toLong(DurationUnit.NANOSECONDS), limit?.toLong() ) ) ?: throw XMTPException("Client does not support V3 dms") - val sortedConversations = when (order) { + val filteredConversations = filterByConsentState(ffiConversations, consentState) + val sortedConversations = sortConversations(filteredConversations, order) + + return filteredConversations.map { it.toConversation() } + } + + private fun sortConversations( + conversations: List, + order: ConversationOrder, + ): List { + return when (order) { ConversationOrder.LAST_MESSAGE -> { - ffiConversation.map { conversation -> + conversations.map { conversation -> val message = conversation.findMessages(FfiListMessagesOptions(null, null, null, null)) .lastOrNull() @@ -365,19 +380,28 @@ data class Conversations( it.first } } - - ConversationOrder.CREATED_AT -> ffiConversation + ConversationOrder.CREATED_AT -> conversations } + } - return sortedConversations.map { - if (it.groupMetadata().conversationType() == "dm") { - Conversation.Dm(Dm(client, it)) - } else { - Conversation.Group(Group(client, it)) - } + private fun filterByConsentState( + conversations: List, + consentState: ConsentState?, + ): List { + return consentState?.let { state -> + conversations.filter { it.consentState() == toFfiConsentState(state) } + } ?: conversations + } + + private fun FfiConversation.toConversation(): Conversation { + return if (groupMetadata().conversationType() == "dm") { + Conversation.Dm(Dm(client, this)) + } else { + Conversation.Group(Group(client, this)) } } + /** * Get the list of conversations that current user has * @return The list of [Conversation] that the current [Client] has.