From 3b17b2810ac30e330ed945e7f75a1171ded37199 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Mon, 4 Nov 2024 14:47:35 -0800 Subject: [PATCH] Fix pagination not being respected in group messages (#318) * add a test for it * update to nanoseconds * fix up linter issue --- .../xmtp/android/library/ConversationTest.kt | 9 +++- .../org/xmtp/android/library/GroupTest.kt | 24 +++++++++ .../android/library/LocalInstrumentedTest.kt | 15 +++++- .../org/xmtp/android/library/Conversation.kt | 51 +++++++++++++------ .../main/java/org/xmtp/android/library/Dm.kt | 18 +++---- .../java/org/xmtp/android/library/Group.kt | 18 +++---- .../xmtp/android/library/libxmtp/MessageV3.kt | 3 ++ 7 files changed, 100 insertions(+), 38 deletions(-) diff --git a/library/src/androidTest/java/org/xmtp/android/library/ConversationTest.kt b/library/src/androidTest/java/org/xmtp/android/library/ConversationTest.kt index c520796b7..c8b8a6afb 100644 --- a/library/src/androidTest/java/org/xmtp/android/library/ConversationTest.kt +++ b/library/src/androidTest/java/org/xmtp/android/library/ConversationTest.kt @@ -45,6 +45,8 @@ import org.xmtp.proto.message.contents.Invitation import org.xmtp.proto.message.contents.Invitation.InvitationV1.Context import java.nio.charset.StandardCharsets import java.util.Date +import kotlin.time.Duration.Companion.nanoseconds +import kotlin.time.DurationUnit @RunWith(AndroidJUnit4::class) class ConversationTest { @@ -418,7 +420,12 @@ class ConversationTest { val messages = aliceConversation.messages(limit = 1) assertEquals(1, messages.size) assertEquals("hey alice 3", messages[0].body) - val messages2 = aliceConversation.messages(limit = 1, after = date) + val messages2 = aliceConversation.messages( + limit = 1, + afterNs = date.time.nanoseconds.toLong( + DurationUnit.NANOSECONDS + ) + ) assertEquals(1, messages2.size) assertEquals("hey alice 3", messages2[0].body) val messagesAsc = diff --git a/library/src/androidTest/java/org/xmtp/android/library/GroupTest.kt b/library/src/androidTest/java/org/xmtp/android/library/GroupTest.kt index f3169ffec..3b3d23a1b 100644 --- a/library/src/androidTest/java/org/xmtp/android/library/GroupTest.kt +++ b/library/src/androidTest/java/org/xmtp/android/library/GroupTest.kt @@ -585,6 +585,30 @@ class GroupTest { assertEquals(sameGroup.messages(deliveryStatus = MessageDeliveryStatus.PUBLISHED).size, 2) } + @Test + fun testCanListGroupMessagesAfter() { + val group = runBlocking { boClient.conversations.newGroup(listOf(alix.walletAddress)) } + val messageId = runBlocking { + group.send("howdy") + group.send("gm") + } + val message = boClient.findMessage(messageId) + assertEquals(group.messages().size, 3) + assertEquals(group.messages(afterNs = message?.sentAtNs).size, 0) + runBlocking { + group.send("howdy") + group.send("gm") + } + assertEquals(group.messages().size, 5) + assertEquals(group.messages(afterNs = message?.sentAtNs).size, 2) + + runBlocking { alixClient.conversations.syncConversations() } + val sameGroup = runBlocking { alixClient.conversations.listGroups().last() } + runBlocking { sameGroup.sync() } + assertEquals(sameGroup.messages().size, 4) + assertEquals(sameGroup.messages(afterNs = message?.sentAtNs).size, 2) + } + @Test fun testCanSendContentTypesToGroup() { Client.register(codec = ReactionCodec()) diff --git a/library/src/androidTest/java/org/xmtp/android/library/LocalInstrumentedTest.kt b/library/src/androidTest/java/org/xmtp/android/library/LocalInstrumentedTest.kt index c636fde56..21c1aa060 100644 --- a/library/src/androidTest/java/org/xmtp/android/library/LocalInstrumentedTest.kt +++ b/library/src/androidTest/java/org/xmtp/android/library/LocalInstrumentedTest.kt @@ -29,6 +29,8 @@ import org.xmtp.proto.message.contents.PrivateKeyOuterClass import org.xmtp.proto.message.contents.PrivateKeyOuterClass.PrivateKeyBundle import uniffi.xmtpv3.createV2Client import java.util.Date +import kotlin.time.Duration.Companion.nanoseconds +import kotlin.time.DurationUnit @RunWith(AndroidJUnit4::class) class LocalInstrumentedTest { @@ -163,10 +165,19 @@ class LocalInstrumentedTest { assertEquals(2, messagesLimit.size) val nowMessage = messages[0] assertEquals("now", nowMessage.body) - val messages2 = convo.messages(limit = 1, before = nowMessage.sent) + val messages2 = convo.messages( + limit = 1, + beforeNs = nowMessage.sent.time.nanoseconds.toLong( + DurationUnit.NANOSECONDS + ) + ) val tenSecondsAgoMessage = messages2[0] assertEquals("now first", tenSecondsAgoMessage.body) - val messages3 = convo.messages(after = tenSecondsAgoMessage.sent) + val messages3 = convo.messages( + afterNs = tenSecondsAgoMessage.sent.time.nanoseconds.toLong( + DurationUnit.NANOSECONDS + ) + ) val nowMessage2 = messages3[0] assertEquals("now", nowMessage2.body) val messagesAsc = diff --git a/library/src/main/java/org/xmtp/android/library/Conversation.kt b/library/src/main/java/org/xmtp/android/library/Conversation.kt index 5a701bb4f..fa48a04a3 100644 --- a/library/src/main/java/org/xmtp/android/library/Conversation.kt +++ b/library/src/main/java/org/xmtp/android/library/Conversation.kt @@ -169,50 +169,71 @@ sealed class Conversation { */ suspend fun messages( limit: Int? = null, - before: Date? = null, - after: Date? = null, + beforeNs: Long? = null, + afterNs: Long? = null, direction: PagingInfoSortDirection = MessageApiOuterClass.SortDirection.SORT_DIRECTION_DESCENDING, ): List { return when (this) { is V1 -> conversationV1.messages( limit = limit, - before = before, - after = after, + before = beforeNs?.let { Date(it / 1_000_000) }, + after = afterNs?.let { Date(it / 1_000_000) }, direction = direction, ) is V2 -> conversationV2.messages( limit = limit, - before = before, - after = after, + before = beforeNs?.let { Date(it / 1_000_000) }, + after = afterNs?.let { Date(it / 1_000_000) }, direction = direction, ) is Group -> { group.messages( limit = limit, - before = before, - after = after, + beforeNs = beforeNs, + afterNs = afterNs, direction = direction, ) } - is Dm -> dm.messages(limit, before, after, direction) + is Dm -> dm.messages(limit, beforeNs, afterNs, direction) } } suspend fun decryptedMessages( limit: Int? = null, - before: Date? = null, - after: Date? = null, + beforeNs: Long? = null, + afterNs: Long? = null, direction: PagingInfoSortDirection = MessageApiOuterClass.SortDirection.SORT_DIRECTION_DESCENDING, ): List { return when (this) { - is V1 -> conversationV1.decryptedMessages(limit, before, after, direction) - is V2 -> conversationV2.decryptedMessages(limit, before, after, direction) - is Group -> group.decryptedMessages(limit, before, after, direction) - is Dm -> dm.decryptedMessages(limit, before, after, direction) + is V1 -> conversationV1.decryptedMessages( + limit = limit, + before = beforeNs?.let { Date(it / 1_000_000) }, + after = afterNs?.let { Date(it / 1_000_000) }, + direction = direction, + ) + + is V2 -> + conversationV2.decryptedMessages( + limit = limit, + before = beforeNs?.let { Date(it / 1_000_000) }, + after = afterNs?.let { Date(it / 1_000_000) }, + direction = direction, + ) + + is Group -> { + group.decryptedMessages( + limit = limit, + beforeNs = beforeNs, + afterNs = afterNs, + direction = direction, + ) + } + + is Dm -> dm.decryptedMessages(limit, beforeNs, afterNs, direction) } } diff --git a/library/src/main/java/org/xmtp/android/library/Dm.kt b/library/src/main/java/org/xmtp/android/library/Dm.kt index 64ace0606..a1e3c785a 100644 --- a/library/src/main/java/org/xmtp/android/library/Dm.kt +++ b/library/src/main/java/org/xmtp/android/library/Dm.kt @@ -23,8 +23,6 @@ import uniffi.xmtpv3.FfiMessage import uniffi.xmtpv3.FfiMessageCallback import uniffi.xmtpv3.FfiSubscribeException import java.util.Date -import kotlin.time.Duration.Companion.nanoseconds -import kotlin.time.DurationUnit class Dm(val client: Client, private val libXMTPGroup: FfiConversation) { val id: String @@ -103,15 +101,15 @@ class Dm(val client: Client, private val libXMTPGroup: FfiConversation) { fun messages( limit: Int? = null, - before: Date? = null, - after: Date? = null, + beforeNs: Long? = null, + afterNs: Long? = null, direction: PagingInfoSortDirection = SortDirection.SORT_DIRECTION_DESCENDING, deliveryStatus: MessageDeliveryStatus = MessageDeliveryStatus.ALL, ): List { return libXMTPGroup.findMessages( opts = FfiListMessagesOptions( - sentBeforeNs = before?.time?.nanoseconds?.toLong(DurationUnit.NANOSECONDS), - sentAfterNs = after?.time?.nanoseconds?.toLong(DurationUnit.NANOSECONDS), + sentBeforeNs = beforeNs, + sentAfterNs = afterNs, limit = limit?.toLong(), deliveryStatus = when (deliveryStatus) { MessageDeliveryStatus.PUBLISHED -> FfiDeliveryStatus.PUBLISHED @@ -131,15 +129,15 @@ class Dm(val client: Client, private val libXMTPGroup: FfiConversation) { fun decryptedMessages( limit: Int? = null, - before: Date? = null, - after: Date? = null, + beforeNs: Long? = null, + afterNs: Long? = null, direction: PagingInfoSortDirection = SortDirection.SORT_DIRECTION_DESCENDING, deliveryStatus: MessageDeliveryStatus = MessageDeliveryStatus.ALL, ): List { return libXMTPGroup.findMessages( opts = FfiListMessagesOptions( - sentBeforeNs = before?.time?.nanoseconds?.toLong(DurationUnit.NANOSECONDS), - sentAfterNs = after?.time?.nanoseconds?.toLong(DurationUnit.NANOSECONDS), + sentBeforeNs = beforeNs, + sentAfterNs = afterNs, limit = limit?.toLong(), deliveryStatus = when (deliveryStatus) { MessageDeliveryStatus.PUBLISHED -> FfiDeliveryStatus.PUBLISHED diff --git a/library/src/main/java/org/xmtp/android/library/Group.kt b/library/src/main/java/org/xmtp/android/library/Group.kt index eca6771d9..3fbfbe190 100644 --- a/library/src/main/java/org/xmtp/android/library/Group.kt +++ b/library/src/main/java/org/xmtp/android/library/Group.kt @@ -29,8 +29,6 @@ import uniffi.xmtpv3.FfiSubscribeException import uniffi.xmtpv3.org.xmtp.android.library.libxmtp.PermissionOption import uniffi.xmtpv3.org.xmtp.android.library.libxmtp.PermissionPolicySet import java.util.Date -import kotlin.time.Duration.Companion.nanoseconds -import kotlin.time.DurationUnit class Group(val client: Client, private val libXMTPGroup: FfiConversation) { val id: String @@ -121,15 +119,15 @@ class Group(val client: Client, private val libXMTPGroup: FfiConversation) { fun messages( limit: Int? = null, - before: Date? = null, - after: Date? = null, + beforeNs: Long? = null, + afterNs: Long? = null, direction: PagingInfoSortDirection = SORT_DIRECTION_DESCENDING, deliveryStatus: MessageDeliveryStatus = MessageDeliveryStatus.ALL, ): List { return libXMTPGroup.findMessages( opts = FfiListMessagesOptions( - sentBeforeNs = before?.time?.nanoseconds?.toLong(DurationUnit.NANOSECONDS), - sentAfterNs = after?.time?.nanoseconds?.toLong(DurationUnit.NANOSECONDS), + sentBeforeNs = beforeNs, + sentAfterNs = afterNs, limit = limit?.toLong(), deliveryStatus = when (deliveryStatus) { MessageDeliveryStatus.PUBLISHED -> FfiDeliveryStatus.PUBLISHED @@ -149,15 +147,15 @@ class Group(val client: Client, private val libXMTPGroup: FfiConversation) { fun decryptedMessages( limit: Int? = null, - before: Date? = null, - after: Date? = null, + beforeNs: Long? = null, + afterNs: Long? = null, direction: PagingInfoSortDirection = SORT_DIRECTION_DESCENDING, deliveryStatus: MessageDeliveryStatus = MessageDeliveryStatus.ALL, ): List { return libXMTPGroup.findMessages( opts = FfiListMessagesOptions( - sentBeforeNs = before?.time?.nanoseconds?.toLong(DurationUnit.NANOSECONDS), - sentAfterNs = after?.time?.nanoseconds?.toLong(DurationUnit.NANOSECONDS), + sentBeforeNs = beforeNs, + sentAfterNs = afterNs, limit = limit?.toLong(), deliveryStatus = when (deliveryStatus) { MessageDeliveryStatus.PUBLISHED -> FfiDeliveryStatus.PUBLISHED diff --git a/library/src/main/java/org/xmtp/android/library/libxmtp/MessageV3.kt b/library/src/main/java/org/xmtp/android/library/libxmtp/MessageV3.kt index 631fd2e5f..f26ae2fd5 100644 --- a/library/src/main/java/org/xmtp/android/library/libxmtp/MessageV3.kt +++ b/library/src/main/java/org/xmtp/android/library/libxmtp/MessageV3.kt @@ -29,6 +29,9 @@ data class MessageV3(val client: Client, private val libXMTPMessage: FfiMessage) val sentAt: Date get() = Date(libXMTPMessage.sentAtNs / 1_000_000) + val sentAtNs: Long + get() = libXMTPMessage.sentAtNs + val deliveryStatus: MessageDeliveryStatus get() = when (libXMTPMessage.deliveryStatus) { FfiDeliveryStatus.UNPUBLISHED -> MessageDeliveryStatus.UNPUBLISHED