@@ -27,6 +27,7 @@ import expo.modules.xmtpreactnativesdk.wrappers.DisappearingMessageSettingsWrapp
2727import expo.modules.xmtpreactnativesdk.wrappers.DmWrapper
2828import expo.modules.xmtpreactnativesdk.wrappers.EncryptedLocalAttachment
2929import expo.modules.xmtpreactnativesdk.wrappers.EnrichedMessageQueryParamsWrapper
30+ import expo.modules.xmtpreactnativesdk.wrappers.GroupSyncSummaryWrapper
3031import expo.modules.xmtpreactnativesdk.wrappers.GroupWrapper
3132import expo.modules.xmtpreactnativesdk.wrappers.InboxStateWrapper
3233import expo.modules.xmtpreactnativesdk.wrappers.KeyPackageStatusWrapper
@@ -72,6 +73,7 @@ import org.xmtp.android.library.hexToByteArray
7273import org.xmtp.android.library.libxmtp.ArchiveElement
7374import org.xmtp.android.library.libxmtp.ArchiveOptions
7475import org.xmtp.android.library.libxmtp.DecodedMessage
76+ import uniffi.xmtpv3.FfiContentType
7577import org.xmtp.android.library.libxmtp.DisappearingMessageSettings
7678import org.xmtp.android.library.libxmtp.GroupPermissionPreconfiguration
7779import 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