Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Group message delivery status #232

Merged
merged 6 commits into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import org.xmtp.android.library.codecs.Reaction
import org.xmtp.android.library.codecs.ReactionAction
import org.xmtp.android.library.codecs.ReactionCodec
import org.xmtp.android.library.codecs.ReactionSchema
import org.xmtp.android.library.messages.MessageDeliveryStatus
import org.xmtp.android.library.messages.PrivateKey
import org.xmtp.android.library.messages.PrivateKeyBuilder
import org.xmtp.android.library.messages.walletAddress
Expand Down Expand Up @@ -330,9 +331,11 @@ class GroupTest {
fun testCanSendMessageToGroup() {
val group = runBlocking { boClient.conversations.newGroup(listOf(alix.walletAddress)) }
runBlocking { group.send("howdy") }
runBlocking { group.send("gm") }
val messageId = runBlocking { group.send("gm") }
runBlocking { group.sync() }
assertEquals(group.messages().first().body, "gm")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that the group.send("gm") was here prior and now grabbing the messageId. However, I'm confused by how the subsequent equality test passed in the first place. Wouldn't this be the second message in the group? Asking to understand rather than request changes. 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The messages come in descending order by default since the last message is the first message you want to see.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wow! That's great to know. Thanks for sharing.

assertEquals(group.messages().first().id, messageId)
assertEquals(group.messages().first().deliveryStatus, MessageDeliveryStatus.PUBLISHED)
assertEquals(group.messages().size, 3)

runBlocking { alixClient.conversations.syncGroups() }
Expand All @@ -342,6 +345,28 @@ class GroupTest {
assertEquals(sameGroup.messages().first().body, "gm")
}

@Test
fun testCanListGroupMessages() {
val group = runBlocking { boClient.conversations.newGroup(listOf(alix.walletAddress)) }
runBlocking {
group.send("howdy")
group.send("gm")
}

assertEquals(group.messages().size, 3)
assertEquals(group.messages(deliveryStatus = MessageDeliveryStatus.UNPUBLISHED).size, 2)
assertEquals(group.messages(deliveryStatus = MessageDeliveryStatus.PUBLISHED).size, 1)
runBlocking { group.sync() }
assertEquals(group.messages().size, 3)
assertEquals(group.messages(deliveryStatus = MessageDeliveryStatus.UNPUBLISHED).size, 0)
assertEquals(group.messages(deliveryStatus = MessageDeliveryStatus.PUBLISHED).size, 3)

runBlocking { alixClient.conversations.syncGroups() }
val sameGroup = runBlocking { alixClient.conversations.listGroups().last() }
runBlocking { sameGroup.sync() }
assertEquals(sameGroup.messages(deliveryStatus = MessageDeliveryStatus.PUBLISHED).size, 2)
}

@Test
fun testCanSendContentTypesToGroup() {
Client.register(codec = ReactionCodec())
Expand Down
4 changes: 2 additions & 2 deletions library/src/main/java/libxmtp-version.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Version: 4068715
Version: 5b62701
Branch: main
Date: 2024-04-06 04:27:39 +0000
Date: 2024-04-18 03:59:02 +0000
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.xmtp.android.library

import org.xmtp.android.library.codecs.TextCodec
import org.xmtp.android.library.codecs.decoded
import org.xmtp.android.library.messages.MessageDeliveryStatus
import org.xmtp.proto.message.contents.Content
import java.util.Date

Expand All @@ -12,6 +13,7 @@ data class DecodedMessage(
var encodedContent: Content.EncodedContent,
var senderAddress: String,
var sent: Date,
var deliveryStatus: MessageDeliveryStatus = MessageDeliveryStatus.PUBLISHED
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

V2 messages default to published.

) {
companion object {
fun preview(client: Client, topic: String, body: String, senderAddress: String, sent: Date): DecodedMessage {
Expand Down
24 changes: 20 additions & 4 deletions library/src/main/java/org/xmtp/android/library/Group.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import org.xmtp.android.library.codecs.EncodedContent
import org.xmtp.android.library.codecs.compress
import org.xmtp.android.library.libxmtp.MessageV3
import org.xmtp.android.library.messages.DecryptedMessage
import org.xmtp.android.library.messages.MessageDeliveryStatus
import org.xmtp.android.library.messages.PagingInfoSortDirection
import org.xmtp.android.library.messages.Topic
import org.xmtp.proto.message.api.v1.MessageApiOuterClass
import uniffi.xmtpv3.FfiDeliveryStatus
import uniffi.xmtpv3.FfiGroup
import uniffi.xmtpv3.FfiGroupMetadata
import uniffi.xmtpv3.FfiListMessagesOptions
Expand Down Expand Up @@ -47,8 +49,8 @@ class Group(val client: Client, private val libXMTPGroup: FfiGroup) {
if (client.contacts.consentList.groupState(groupId = id) == ConsentState.UNKNOWN) {
client.contacts.allowGroup(groupIds = listOf(id))
}
libXMTPGroup.send(contentBytes = encodedContent.toByteArray())
return id.toHex()
val messageId = libXMTPGroup.send(contentBytes = encodedContent.toByteArray())
return messageId.toHex()
}

fun <T> prepareMessage(content: T, options: SendOptions?): EncodedContent {
Expand Down Expand Up @@ -86,12 +88,19 @@ class Group(val client: Client, private val libXMTPGroup: FfiGroup) {
before: Date? = null,
after: Date? = null,
direction: PagingInfoSortDirection = MessageApiOuterClass.SortDirection.SORT_DIRECTION_DESCENDING,
deliveryStatus: MessageDeliveryStatus = MessageDeliveryStatus.ALL,
): List<DecodedMessage> {
val messages = libXMTPGroup.findMessages(
opts = FfiListMessagesOptions(
sentBeforeNs = before?.time?.nanoseconds?.toLong(DurationUnit.NANOSECONDS),
sentAfterNs = after?.time?.nanoseconds?.toLong(DurationUnit.NANOSECONDS),
limit = limit?.toLong()
limit = limit?.toLong(),
deliveryStatus = when (deliveryStatus) {
MessageDeliveryStatus.PUBLISHED -> FfiDeliveryStatus.PUBLISHED
MessageDeliveryStatus.UNPUBLISHED -> FfiDeliveryStatus.UNPUBLISHED
MessageDeliveryStatus.FAILED -> FfiDeliveryStatus.FAILED
else -> null
}
)
).mapNotNull {
MessageV3(client, it).decodeOrNull()
Expand All @@ -108,12 +117,19 @@ class Group(val client: Client, private val libXMTPGroup: FfiGroup) {
before: Date? = null,
after: Date? = null,
direction: PagingInfoSortDirection = MessageApiOuterClass.SortDirection.SORT_DIRECTION_DESCENDING,
deliveryStatus: MessageDeliveryStatus = MessageDeliveryStatus.ALL,
): List<DecryptedMessage> {
val messages = libXMTPGroup.findMessages(
opts = FfiListMessagesOptions(
sentBeforeNs = before?.time?.nanoseconds?.toLong(DurationUnit.NANOSECONDS),
sentAfterNs = after?.time?.nanoseconds?.toLong(DurationUnit.NANOSECONDS),
limit = limit?.toLong()
limit = limit?.toLong(),
deliveryStatus = when (deliveryStatus) {
MessageDeliveryStatus.PUBLISHED -> FfiDeliveryStatus.PUBLISHED
MessageDeliveryStatus.UNPUBLISHED -> FfiDeliveryStatus.UNPUBLISHED
MessageDeliveryStatus.FAILED -> FfiDeliveryStatus.FAILED
else -> null
}
)
).mapNotNull {
MessageV3(client, it).decryptOrNull()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import org.xmtp.android.library.DecodedMessage
import org.xmtp.android.library.XMTPException
import org.xmtp.android.library.codecs.EncodedContent
import org.xmtp.android.library.messages.DecryptedMessage
import org.xmtp.android.library.messages.MessageDeliveryStatus
import org.xmtp.android.library.messages.Topic
import org.xmtp.android.library.toHex
import uniffi.xmtpv3.FfiDeliveryStatus
import uniffi.xmtpv3.FfiGroupMessageKind
import uniffi.xmtpv3.FfiMessage
import uniffi.xmtpv3.org.xmtp.android.library.codecs.ContentTypeGroupMembershipChange
Expand All @@ -27,6 +29,13 @@ data class MessageV3(val client: Client, private val libXMTPMessage: FfiMessage)
val sentAt: Date
get() = Date(libXMTPMessage.sentAtNs / 1_000_000)

val deliveryStatus: MessageDeliveryStatus
get() = when (libXMTPMessage.deliveryStatus) {
FfiDeliveryStatus.UNPUBLISHED -> MessageDeliveryStatus.UNPUBLISHED
FfiDeliveryStatus.PUBLISHED -> MessageDeliveryStatus.PUBLISHED
FfiDeliveryStatus.FAILED -> MessageDeliveryStatus.FAILED
}

fun decode(): DecodedMessage {
try {
val decodedMessage = DecodedMessage(
Expand All @@ -36,6 +45,7 @@ data class MessageV3(val client: Client, private val libXMTPMessage: FfiMessage)
encodedContent = EncodedContent.parseFrom(libXMTPMessage.content),
senderAddress = senderAddress,
sent = sentAt,
deliveryStatus = deliveryStatus
)
if (decodedMessage.encodedContent.type == ContentTypeGroupMembershipChange && libXMTPMessage.kind != FfiGroupMessageKind.MEMBERSHIP_CHANGE) {
throw XMTPException("Error decoding group membership change")
Expand Down Expand Up @@ -71,6 +81,7 @@ data class MessageV3(val client: Client, private val libXMTPMessage: FfiMessage)
encodedContent = decode().encodedContent,
senderAddress = senderAddress,
sentAt = Date(),
deliveryStatus = deliveryStatus
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ data class DecryptedMessage(
var senderAddress: String,
var sentAt: Date,
var topic: String = "",
var deliveryStatus: MessageDeliveryStatus = MessageDeliveryStatus.PUBLISHED
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package org.xmtp.android.library.messages

typealias Message = org.xmtp.proto.message.contents.MessageOuterClass.Message

enum class MessageDeliveryStatus {
ALL, PUBLISHED, UNPUBLISHED, FAILED
}

enum class MessageVersion(val rawValue: String) {
V1("v1"),
V2("v2");
Expand Down
84 changes: 72 additions & 12 deletions library/src/main/java/xmtpv3.kt
Original file line number Diff line number Diff line change
Expand Up @@ -854,7 +854,7 @@ private fun uniffiCheckApiChecksums(lib: _UniFFILib) {
if (lib.uniffi_xmtpv3_checksum_method_ffigroup_remove_members() != 1645.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_xmtpv3_checksum_method_ffigroup_send() != 55957.toShort()) {
if (lib.uniffi_xmtpv3_checksum_method_ffigroup_send() != 2523.toShort()) {
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
}
if (lib.uniffi_xmtpv3_checksum_method_ffigroup_stream() != 7482.toShort()) {
Expand Down Expand Up @@ -1505,7 +1505,7 @@ public interface FfiGroupInterface {
fun `listMembers`(): List<FfiGroupMember>@Throws(GenericException::class)
suspend fun `processStreamedGroupMessage`(`envelopeBytes`: ByteArray): FfiMessage@Throws(GenericException::class)
suspend fun `removeMembers`(`accountAddresses`: List<String>)@Throws(GenericException::class)
suspend fun `send`(`contentBytes`: ByteArray)@Throws(GenericException::class)
suspend fun `send`(`contentBytes`: ByteArray): ByteArray@Throws(GenericException::class)
suspend fun `stream`(`messageCallback`: FfiMessageCallback): FfiStreamCloser@Throws(GenericException::class)
suspend fun `sync`()
companion object
Expand Down Expand Up @@ -1676,20 +1676,19 @@ class FfiGroup(

@Throws(GenericException::class)
@Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
override suspend fun `send`(`contentBytes`: ByteArray) {
override suspend fun `send`(`contentBytes`: ByteArray) : ByteArray {
return uniffiRustCallAsync(
callWithPointer { thisPtr ->
_UniFFILib.INSTANCE.uniffi_xmtpv3_fn_method_ffigroup_send(
thisPtr,
FfiConverterByteArray.lower(`contentBytes`),
)
},
{ future, continuation -> _UniFFILib.INSTANCE.ffi_xmtpv3_rust_future_poll_void(future, continuation) },
{ future, continuation -> _UniFFILib.INSTANCE.ffi_xmtpv3_rust_future_complete_void(future, continuation) },
{ future -> _UniFFILib.INSTANCE.ffi_xmtpv3_rust_future_free_void(future) },
{ future, continuation -> _UniFFILib.INSTANCE.ffi_xmtpv3_rust_future_poll_rust_buffer(future, continuation) },
{ future, continuation -> _UniFFILib.INSTANCE.ffi_xmtpv3_rust_future_complete_rust_buffer(future, continuation) },
{ future -> _UniFFILib.INSTANCE.ffi_xmtpv3_rust_future_free_rust_buffer(future) },
// lift function
{ Unit },

{ FfiConverterByteArray.lift(it) },
// Error FFI converter
GenericException.ErrorHandler,
)
Expand Down Expand Up @@ -2484,7 +2483,8 @@ public object FfiConverterTypeFfiListConversationsOptions: FfiConverterRustBuffe
data class FfiListMessagesOptions (
var `sentBeforeNs`: Long?,
var `sentAfterNs`: Long?,
var `limit`: Long?
var `limit`: Long?,
var `deliveryStatus`: FfiDeliveryStatus?
) {

companion object
Expand All @@ -2496,19 +2496,22 @@ public object FfiConverterTypeFfiListMessagesOptions: FfiConverterRustBuffer<Ffi
FfiConverterOptionalLong.read(buf),
FfiConverterOptionalLong.read(buf),
FfiConverterOptionalLong.read(buf),
FfiConverterOptionalTypeFfiDeliveryStatus.read(buf),
)
}

override fun allocationSize(value: FfiListMessagesOptions) = (
FfiConverterOptionalLong.allocationSize(value.`sentBeforeNs`) +
FfiConverterOptionalLong.allocationSize(value.`sentAfterNs`) +
FfiConverterOptionalLong.allocationSize(value.`limit`)
FfiConverterOptionalLong.allocationSize(value.`limit`) +
FfiConverterOptionalTypeFfiDeliveryStatus.allocationSize(value.`deliveryStatus`)
)

override fun write(value: FfiListMessagesOptions, buf: ByteBuffer) {
FfiConverterOptionalLong.write(value.`sentBeforeNs`, buf)
FfiConverterOptionalLong.write(value.`sentAfterNs`, buf)
FfiConverterOptionalLong.write(value.`limit`, buf)
FfiConverterOptionalTypeFfiDeliveryStatus.write(value.`deliveryStatus`, buf)
}
}

Expand All @@ -2521,7 +2524,8 @@ data class FfiMessage (
var `convoId`: ByteArray,
var `addrFrom`: String,
var `content`: ByteArray,
var `kind`: FfiGroupMessageKind
var `kind`: FfiGroupMessageKind,
var `deliveryStatus`: FfiDeliveryStatus
) {

companion object
Expand All @@ -2536,6 +2540,7 @@ public object FfiConverterTypeFfiMessage: FfiConverterRustBuffer<FfiMessage> {
FfiConverterString.read(buf),
FfiConverterByteArray.read(buf),
FfiConverterTypeFfiGroupMessageKind.read(buf),
FfiConverterTypeFfiDeliveryStatus.read(buf),
)
}

Expand All @@ -2545,7 +2550,8 @@ public object FfiConverterTypeFfiMessage: FfiConverterRustBuffer<FfiMessage> {
FfiConverterByteArray.allocationSize(value.`convoId`) +
FfiConverterString.allocationSize(value.`addrFrom`) +
FfiConverterByteArray.allocationSize(value.`content`) +
FfiConverterTypeFfiGroupMessageKind.allocationSize(value.`kind`)
FfiConverterTypeFfiGroupMessageKind.allocationSize(value.`kind`) +
FfiConverterTypeFfiDeliveryStatus.allocationSize(value.`deliveryStatus`)
)

override fun write(value: FfiMessage, buf: ByteBuffer) {
Expand All @@ -2555,6 +2561,7 @@ public object FfiConverterTypeFfiMessage: FfiConverterRustBuffer<FfiMessage> {
FfiConverterString.write(value.`addrFrom`, buf)
FfiConverterByteArray.write(value.`content`, buf)
FfiConverterTypeFfiGroupMessageKind.write(value.`kind`, buf)
FfiConverterTypeFfiDeliveryStatus.write(value.`deliveryStatus`, buf)
}
}

Expand Down Expand Up @@ -2767,6 +2774,30 @@ public object FfiConverterTypeFfiV2SubscribeRequest: FfiConverterRustBuffer<FfiV



enum class FfiDeliveryStatus {
UNPUBLISHED,PUBLISHED,FAILED;
companion object
}

public object FfiConverterTypeFfiDeliveryStatus: FfiConverterRustBuffer<FfiDeliveryStatus> {
override fun read(buf: ByteBuffer) = try {
FfiDeliveryStatus.values()[buf.getInt() - 1]
} catch (e: IndexOutOfBoundsException) {
throw RuntimeException("invalid enum value, something is very wrong!!", e)
}

override fun allocationSize(value: FfiDeliveryStatus) = 4

override fun write(value: FfiDeliveryStatus, buf: ByteBuffer) {
buf.putInt(value.ordinal + 1)
}
}






enum class FfiGroupMessageKind {
APPLICATION,MEMBERSHIP_CHANGE;
companion object
Expand Down Expand Up @@ -3591,6 +3622,35 @@ public object FfiConverterOptionalTypeFfiPagingInfo: FfiConverterRustBuffer<FfiP



public object FfiConverterOptionalTypeFfiDeliveryStatus: FfiConverterRustBuffer<FfiDeliveryStatus?> {
override fun read(buf: ByteBuffer): FfiDeliveryStatus? {
if (buf.get().toInt() == 0) {
return null
}
return FfiConverterTypeFfiDeliveryStatus.read(buf)
}

override fun allocationSize(value: FfiDeliveryStatus?): Int {
if (value == null) {
return 1
} else {
return 1 + FfiConverterTypeFfiDeliveryStatus.allocationSize(value)
}
}

override fun write(value: FfiDeliveryStatus?, buf: ByteBuffer) {
if (value == null) {
buf.put(0)
} else {
buf.put(1)
FfiConverterTypeFfiDeliveryStatus.write(value, buf)
}
}
}




public object FfiConverterOptionalTypeGroupPermissions: FfiConverterRustBuffer<GroupPermissions?> {
override fun read(buf: ByteBuffer): GroupPermissions? {
if (buf.get().toInt() == 0) {
Expand Down
Binary file modified library/src/main/jniLibs/arm64-v8a/libuniffi_xmtpv3.so
Binary file not shown.
Binary file modified library/src/main/jniLibs/armeabi-v7a/libuniffi_xmtpv3.so
Binary file not shown.
Binary file modified library/src/main/jniLibs/x86/libuniffi_xmtpv3.so
Binary file not shown.
Binary file modified library/src/main/jniLibs/x86_64/libuniffi_xmtpv3.so
Binary file not shown.
Loading