Skip to content

Conversation

@cameronvoell
Copy link
Contributor

@cameronvoell cameronvoell commented Jan 23, 2026

Add Conversations.streamMessageDeletions, Conversation.deleteMessage, and Conversation.prepareMessage(noSend) for libxmtp 1.9.0 updates

Add message deletion streaming and events, support deleting messages, and allow preparing messages without sending; expose publishMessage and noSend across DM/Group, propagate appData in group creation, and expand permission policies.

📍Where to Start

Start with the native event stream and handlers in XMTPModule.kt, then review the JS wiring in Conversations.ts and the new DM/Group methods in Dm.ts and Group.ts.


📊 Macroscope summarized e060fca. 10 files reviewed, 15 issues evaluated, 2 issues filtered, 4 comments posted

🗂️ Filtered Issues

android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt — 2 comments posted, 5 evaluated, 2 filtered
  • line 1168: The prepareMessage function signature changed from 3 parameters to 4 parameters with the addition of noSend: Boolean. If JavaScript callers have not been updated to pass this required parameter, the Expo module framework will likely throw a runtime error due to argument count mismatch. [ Low confidence ]
  • line 1183: The prepareEncodedMessage function signature changed from 4 parameters to 5 parameters with the addition of noSend: Boolean. Existing JavaScript callers not passing this parameter will experience a runtime argument mismatch error. [ Low confidence ]

@changeset-bot
Copy link

changeset-bot bot commented Jan 23, 2026

⚠️ No Changeset found

Latest commit: e060fca

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

dbEncryptionKey = encryptionKeyBytes,
dbDirectory = authOptions.dbDirectory,
historySyncUrl = historySyncUrl,
deviceSyncEnabled = authOptions.deviceSyncEnabled,
Copy link

Choose a reason for hiding this comment

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

debugEventsEnabled is parsed from authParams but no longer passed to ClientOptions, so the user's setting is silently ignored. Consider re-adding it.

🚀 Want me to fix this? Reply ex: "fix it for me".

Comment on lines +572 to +573
): Promise<() => void> {
await XMTPModule.subscribeToMessageDeletions(this.client.installationId)
Copy link

Choose a reason for hiding this comment

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

Consider removing existing subscriptions before assigning new ones. If streamMessageDeletions is called multiple times without cleanup, previous subscriptions remain active but become unreachable, causing memory leaks and duplicate callbacks.

-  ): Promise<() => void> {
+  ): Promise<() => void> {
+    this.subscriptions[EventTypes.MessageDeletion]?.remove()
+    this.subscriptions[EventTypes.MessageDeletionClosed]?.remove()
     await XMTPModule.subscribeToMessageDeletions(this.client.installationId)

🚀 Want me to fix this? Reply ex: "fix it for me".

}
} catch (e: Exception) {
Log.e("XMTPModule", "Error in message deletions subscription: $e")
subscriptions[getMessageDeletionsCacheKey(installationId)]?.cancel()
Copy link

Choose a reason for hiding this comment

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

The cancel() call in the catch block is redundant since the coroutine is already completing. It could also cancel a newer subscription if a race condition occurs where another call replaced this entry in the map. Consider removing this line.

Suggested change
subscriptions[getMessageDeletionsCacheKey(installationId)]?.cancel()

🚀 Want me to fix this? Reply ex: "fix it for me".

updateGroupDescriptionPolicy = createPermissionOptionFromString(jsonObj.get("updateGroupDescriptionPolicy").asString),
updateGroupImagePolicy = createPermissionOptionFromString(jsonObj.get("updateGroupImagePolicy").asString),
updateMessageDisappearingPolicy = createPermissionOptionFromString(jsonObj.get("updateMessageDisappearingPolicy").asString),
updateAppDataPolicy = createPermissionOptionFromString(jsonObj.get("updateAppDataPolicy").asString),
Copy link

Choose a reason for hiding this comment

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

Parsing updateAppDataPolicy with jsonObj.get() can throw NullPointerException when the field is absent (e.g., older clients). Suggest guarding with has() and a default, consistent with CreateGroupParamsWrapper.

Suggested change
updateAppDataPolicy = createPermissionOptionFromString(jsonObj.get("updateAppDataPolicy").asString),
updateAppDataPolicy = if (jsonObj.has("updateAppDataPolicy")) createPermissionOptionFromString(jsonObj.get("updateAppDataPolicy").asString) else PermissionOption.Unknown,

🚀 Want me to fix this? Reply ex: "fix it for me".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants