Skip to content

Commit e676e27

Browse files
Re-add group management, sort, and archive (#770)
* re-add group management, sort, and archive * add test for group data property * additional test for sortBy parameter * lint fix * update version to 5.6.0 --------- Co-authored-by: Nicholas Molnar <65710+neekolas@users.noreply.github.com> Co-authored-by: cameronvoell <cameronvoell@users.noreply.github.com>
1 parent 1a35b49 commit e676e27

30 files changed

+1216
-289
lines changed

android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt

Lines changed: 80 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import expo.modules.xmtpreactnativesdk.wrappers.DisappearingMessageSettingsWrapp
2727
import expo.modules.xmtpreactnativesdk.wrappers.DmWrapper
2828
import expo.modules.xmtpreactnativesdk.wrappers.EncryptedLocalAttachment
2929
import expo.modules.xmtpreactnativesdk.wrappers.EnrichedMessageQueryParamsWrapper
30+
import expo.modules.xmtpreactnativesdk.wrappers.GroupSyncSummaryWrapper
3031
import expo.modules.xmtpreactnativesdk.wrappers.GroupWrapper
3132
import expo.modules.xmtpreactnativesdk.wrappers.InboxStateWrapper
3233
import expo.modules.xmtpreactnativesdk.wrappers.KeyPackageStatusWrapper
@@ -72,6 +73,7 @@ import org.xmtp.android.library.hexToByteArray
7273
import org.xmtp.android.library.libxmtp.ArchiveElement
7374
import org.xmtp.android.library.libxmtp.ArchiveOptions
7475
import org.xmtp.android.library.libxmtp.DecodedMessage
76+
import uniffi.xmtpv3.FfiContentType
7577
import org.xmtp.android.library.libxmtp.DisappearingMessageSettings
7678
import org.xmtp.android.library.libxmtp.GroupPermissionPreconfiguration
7779
import org.xmtp.android.library.libxmtp.PermissionOption
@@ -1023,7 +1025,12 @@ class XMTPModule : Module() {
10231025
afterNs = queryParams.afterNs,
10241026
direction = DecodedMessage.SortDirection.valueOf(
10251027
queryParams.direction ?: "DESCENDING"
1026-
)
1028+
),
1029+
excludedContentTypes = getExcludedContentTypes(queryParams.excludeContentTypes),
1030+
excludeSenderInboxIds = queryParams.excludeSenderInboxIds,
1031+
insertedAfterNs = queryParams.insertedAfterNs,
1032+
insertedBeforeNs = queryParams.insertedBeforeNs,
1033+
sortBy = getMessageSortBy(queryParams.sortBy)
10271034
)?.map { MessageWrapper.encode(it) }
10281035
}
10291036
}
@@ -1040,7 +1047,12 @@ class XMTPModule : Module() {
10401047
afterNs = queryParams.afterNs,
10411048
direction = DecodedMessage.SortDirection.valueOf(
10421049
queryParams.direction ?: "DESCENDING"
1043-
)
1050+
),
1051+
excludedContentTypes = getExcludedContentTypes(queryParams.excludeContentTypes),
1052+
excludeSenderInboxIds = queryParams.excludeSenderInboxIds,
1053+
insertedAfterNs = queryParams.insertedAfterNs,
1054+
insertedBeforeNs = queryParams.insertedBeforeNs,
1055+
sortBy = getMessageSortBy(queryParams.sortBy)
10441056
)?.map { MessageWrapper.encode(it) }
10451057
}
10461058
}
@@ -1437,9 +1449,8 @@ class XMTPModule : Module() {
14371449
logV("syncAllConversations")
14381450
val client = clients[installationId] ?: throw XMTPException("No client")
14391451
val consentStates = consentStringStates?.let { ConsentWrapper.getConsentStates(it) }
1440-
val numGroupsSyncedInt: Int =
1441-
client.conversations.syncAllConversations(consentStates).numSynced.toInt()
1442-
numGroupsSyncedInt
1452+
val summary = client.conversations.syncAllConversations(consentStates)
1453+
GroupSyncSummaryWrapper.encode(summary)
14431454
}
14441455
}
14451456

@@ -1557,6 +1568,26 @@ class XMTPModule : Module() {
15571568
}
15581569
}
15591570

1571+
AsyncFunction("groupAppData") Coroutine { installationId: String, groupId: String ->
1572+
withContext(Dispatchers.IO) {
1573+
logV("groupAppData")
1574+
val client = clients[installationId] ?: throw XMTPException("No client")
1575+
val group = client.conversations.findGroup(groupId)
1576+
?: throw XMTPException("no group found for $groupId")
1577+
group.appData()
1578+
}
1579+
}
1580+
1581+
AsyncFunction("updateGroupAppData") Coroutine { installationId: String, groupId: String, appData: String ->
1582+
withContext(Dispatchers.IO) {
1583+
logV("updateGroupAppData")
1584+
val client = clients[installationId] ?: throw XMTPException("No client")
1585+
val group = client.conversations.findGroup(groupId)
1586+
?: throw XMTPException("no group found for $groupId")
1587+
group.updateAppData(appData)
1588+
}
1589+
}
1590+
15601591
AsyncFunction("disappearingMessageSettings") Coroutine { installationId: String, conversationId: String ->
15611592
withContext(Dispatchers.IO) {
15621593
logV("disappearingMessageSettings")
@@ -2111,15 +2142,15 @@ class XMTPModule : Module() {
21112142
}
21122143
}
21132144

2114-
AsyncFunction("createArchive") Coroutine { installationId: String, path: String, encryptionKey: List<Int>, startNs: Int?, endNs: Int?, archiveElements: List<String>? ->
2145+
AsyncFunction("createArchive") Coroutine { installationId: String, path: String, encryptionKey: List<Int>, startNs: Int?, endNs: Int?, archiveElements: List<String>?, excludeDisappearingMessages: Boolean? ->
21152146
withContext(Dispatchers.IO) {
21162147
val client = clients[installationId] ?: throw XMTPException("No client")
21172148
val encryptionKeyBytes =
21182149
encryptionKey.foldIndexed(ByteArray(encryptionKey.size)) { i, a, v ->
21192150
a.apply { set(i, v.toByte()) }
21202151
}
21212152
val elements = archiveElements?.map { getArchiveElement(it) } ?: listOf(ArchiveElement.MESSAGES, ArchiveElement.CONSENT)
2122-
val archiveOptions = ArchiveOptions(startNs?.toLong(), endNs?.toLong(), elements)
2153+
val archiveOptions = ArchiveOptions(startNs?.toLong(), endNs?.toLong(), elements, excludeDisappearingMessages ?: false)
21232154
client.createArchive(path, encryptionKeyBytes, archiveOptions)
21242155
}
21252156
}
@@ -2459,6 +2490,48 @@ class XMTPModule : Module() {
24592490
}
24602491
}
24612492

2493+
private fun getMessageSortBy(sortBy: String?): DecodedMessage.SortBy {
2494+
return when (sortBy) {
2495+
"INSERTED_TIME" -> DecodedMessage.SortBy.INSERTED_TIME
2496+
else -> DecodedMessage.SortBy.SENT_TIME
2497+
}
2498+
}
2499+
2500+
/**
2501+
* Converts content type ID strings (e.g. "xmtp.org/text:1.0") to [List][FfiContentType] for the SDK.
2502+
* Unrecognized or custom content types are skipped.
2503+
*/
2504+
private fun getExcludedContentTypes(strings: List<String>?): List<FfiContentType>? {
2505+
if (strings.isNullOrEmpty()) return null
2506+
val mapped = strings.mapNotNull { contentTypeIdString ->
2507+
val typeId = if (contentTypeIdString.contains(":")) {
2508+
contentTypeIdString.substringBefore(":").substringAfterLast("/")
2509+
} else {
2510+
contentTypeIdString
2511+
}
2512+
when (typeId.lowercase()) {
2513+
"text" -> FfiContentType.TEXT
2514+
"group_updated" -> FfiContentType.GROUP_UPDATED
2515+
"group_membership_change" -> FfiContentType.GROUP_MEMBERSHIP_CHANGE
2516+
"reaction" -> FfiContentType.REACTION
2517+
"read_receipt" -> FfiContentType.READ_RECEIPT
2518+
"reply" -> FfiContentType.REPLY
2519+
"attachment" -> FfiContentType.ATTACHMENT
2520+
"remote_attachment" -> FfiContentType.REMOTE_ATTACHMENT
2521+
"multi_remote_attachment" -> FfiContentType.MULTI_REMOTE_ATTACHMENT
2522+
"leave_request" -> FfiContentType.LEAVE_REQUEST
2523+
"delete_message" -> FfiContentType.UNKNOWN
2524+
"markdown" -> FfiContentType.MARKDOWN
2525+
"actions" -> FfiContentType.ACTIONS
2526+
"intent" -> FfiContentType.INTENT
2527+
"transaction_reference" -> FfiContentType.TRANSACTION_REFERENCE
2528+
"wallet_send_calls" -> FfiContentType.WALLET_SEND_CALLS
2529+
else -> null
2530+
}
2531+
}
2532+
return mapped.ifEmpty { null }
2533+
}
2534+
24622535
private val preAuthenticateToInboxCallback: suspend () -> Unit = {
24632536
sendEvent("preAuthenticateToInboxCallback")
24642537
preAuthenticateToInboxCallbackDeferred?.await()

0 commit comments

Comments
 (0)