Skip to content

Commit 5191cc5

Browse files
committed
get groups working again with signer improvements and membership changes
1 parent 5099e29 commit 5191cc5

File tree

5 files changed

+50
-15
lines changed

5 files changed

+50
-15
lines changed

example/src/main/java/org/xmtp/android/example/ClientManager.kt

+4-1
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,16 @@ import org.xmtp.android.library.Client
1111
import org.xmtp.android.library.ClientOptions
1212
import org.xmtp.android.library.XMTPEnvironment
1313
import org.xmtp.android.library.messages.PrivateKeyBundleV1Builder
14+
import uniffi.xmtpv3.org.xmtp.android.library.codecs.GroupMembershipChangeCodec
1415

1516
object ClientManager {
1617

1718
fun clientOptions(appContext: Context?): ClientOptions {
1819
return ClientOptions(
1920
api = ClientOptions.Api(
2021
XMTPEnvironment.LOCAL,
21-
appVersion = "XMTPAndroidExample/v1.0.0"
22+
appVersion = "XMTPAndroidExample/v1.0.0",
23+
isSecure = false
2224
),
2325
enableAlphaMls = true,
2426
appContext = appContext
@@ -45,6 +47,7 @@ object ClientManager {
4547
val v1Bundle =
4648
PrivateKeyBundleV1Builder.fromEncodedData(data = encodedPrivateKeyData)
4749
_client = Client().buildFrom(v1Bundle, clientOptions(appContext))
50+
Client.register(codec = GroupMembershipChangeCodec())
4851
_clientState.value = ClientState.Ready
4952
} catch (e: Exception) {
5053
_clientState.value = ClientState.Error(e.localizedMessage.orEmpty())

example/src/main/java/org/xmtp/android/example/connect/ConnectWalletViewModel.kt

+3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import org.xmtp.android.library.Client
2121
import org.xmtp.android.library.XMTPException
2222
import org.xmtp.android.library.messages.PrivateKeyBuilder
2323
import org.xmtp.android.library.messages.PrivateKeyBundleV1Builder
24+
import uniffi.xmtpv3.org.xmtp.android.library.codecs.GroupMembershipChangeCodec
2425

2526
class ConnectWalletViewModel(application: Application) : AndroidViewModel(application) {
2627

@@ -86,6 +87,7 @@ class ConnectWalletViewModel(application: Application) : AndroidViewModel(applic
8687
try {
8788
val wallet = PrivateKeyBuilder()
8889
val client = Client().create(wallet, ClientManager.clientOptions(getApplication()))
90+
Client.register(codec = GroupMembershipChangeCodec())
8991
_uiState.value = ConnectUiState.Success(
9092
wallet.address,
9193
PrivateKeyBundleV1Builder.encodeData(client.privateKeyBundleV1)
@@ -110,6 +112,7 @@ class ConnectWalletViewModel(application: Application) : AndroidViewModel(applic
110112
}
111113
}
112114
val client = Client().create(wallet, ClientManager.clientOptions(getApplication()))
115+
Client.register(codec = GroupMembershipChangeCodec())
113116
_uiState.value = ConnectUiState.Success(
114117
wallet.address,
115118
PrivateKeyBundleV1Builder.encodeData(client.privateKeyBundleV1)

example/src/main/java/org/xmtp/android/example/conversation/ConversationViewHolder.kt

+13-2
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ import org.xmtp.android.example.R
77
import org.xmtp.android.example.databinding.ListItemConversationBinding
88
import org.xmtp.android.example.extension.truncatedAddress
99
import org.xmtp.android.library.Conversation
10+
import uniffi.xmtpv3.org.xmtp.android.library.codecs.GroupMembershipChanges
1011

1112
class ConversationViewHolder(
1213
private val binding: ListItemConversationBinding,
13-
clickListener: ConversationsClickListener
14+
clickListener: ConversationsClickListener,
1415
) : RecyclerView.ViewHolder(binding.root) {
1516

1617
private var conversation: Conversation? = null
@@ -33,7 +34,17 @@ class ConversationViewHolder(
3334
} else {
3435
item.conversation.peerAddress.truncatedAddress()
3536
}
36-
val messageBody = item.mostRecentMessage?.body.orEmpty()
37+
38+
val messageBody: String = if (item.mostRecentMessage?.content<Any>() is String) {
39+
item.mostRecentMessage.body.orEmpty()
40+
} else if (item.mostRecentMessage?.content<Any>() is GroupMembershipChanges) {
41+
val changes = item.mostRecentMessage.content() as? GroupMembershipChanges
42+
"Membership Changed ${
43+
changes?.membersAddedList?.mapNotNull { it.accountAddress }.toString()
44+
}"
45+
} else {
46+
""
47+
}
3748
val isMe = item.mostRecentMessage?.senderAddress == ClientManager.client.address
3849
if (messageBody.isNotBlank()) {
3950
binding.messageBody.text = if (isMe) binding.root.resources.getString(

example/src/main/java/org/xmtp/android/example/message/MessageViewHolder.kt

+16-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.xmtp.android.example.message
22

3+
import android.annotation.SuppressLint
34
import android.graphics.Color
45
import androidx.constraintlayout.widget.ConstraintLayout
56
import androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.PARENT_ID
@@ -10,9 +11,11 @@ import org.xmtp.android.example.R
1011
import org.xmtp.android.example.conversation.ConversationDetailViewModel
1112
import org.xmtp.android.example.databinding.ListItemMessageBinding
1213
import org.xmtp.android.example.extension.margins
14+
import org.xmtp.proto.mls.message.contents.TranscriptMessages
15+
import uniffi.xmtpv3.org.xmtp.android.library.codecs.GroupMembershipChanges
1316

1417
class MessageViewHolder(
15-
private val binding: ListItemMessageBinding
18+
private val binding: ListItemMessageBinding,
1619
) : RecyclerView.ViewHolder(binding.root) {
1720

1821
private val marginLarge = binding.root.resources.getDimensionPixelSize(R.dimen.message_margin)
@@ -21,8 +24,10 @@ class MessageViewHolder(
2124
private val backgroundPeer =
2225
binding.root.resources.getColor(R.color.teal_700, binding.root.context.theme)
2326

27+
@SuppressLint("SetTextI18n")
2428
fun bind(item: ConversationDetailViewModel.MessageListItem.Message) {
25-
val isFromMe = ClientManager.client.address.lowercase() == item.message.senderAddress.lowercase()
29+
val isFromMe =
30+
ClientManager.client.address.lowercase() == item.message.senderAddress.lowercase()
2631
val params = binding.messageContainer.layoutParams as ConstraintLayout.LayoutParams
2732
if (isFromMe) {
2833
params.rightToRight = PARENT_ID
@@ -38,6 +43,14 @@ class MessageViewHolder(
3843
binding.messageBody.setTextColor(Color.WHITE)
3944
}
4045
binding.messageContainer.layoutParams = params
41-
binding.messageBody.text = item.message.body
46+
if (item.message.content<Any>() is String) {
47+
binding.messageBody.text = item.message.body
48+
} else if (item.message.content<Any>() is GroupMembershipChanges) {
49+
val changes = item.message.content() as? GroupMembershipChanges
50+
binding.messageBody.text =
51+
"Membership Changed ${
52+
changes?.membersAddedList?.mapNotNull { it.accountAddress }.toString()
53+
}"
54+
}
4255
}
4356
}

library/src/main/java/org/xmtp/android/library/Client.kt

+14-9
Original file line numberDiff line numberDiff line change
@@ -175,14 +175,14 @@ class Client() {
175175
val apiClient =
176176
GRPCApiClient(environment = clientOptions.api.env, secure = clientOptions.api.isSecure)
177177
val v3Client: FfiXmtpClient? = if (isAlphaMlsEnabled(options)) {
178-
if (account == null) throw XMTPException("Signing Key required to use groups.")
179178
runBlocking {
180179
ffiXmtpClient(
181180
options,
182181
account,
183182
options?.appContext,
184183
bundle,
185-
LegacyIdentitySource.STATIC
184+
LegacyIdentitySource.STATIC,
185+
address
186186
)
187187
}
188188
} else null
@@ -227,14 +227,15 @@ class Client() {
227227
account,
228228
options?.appContext,
229229
privateKeyBundleV1,
230-
legacyIdentityKey
230+
legacyIdentityKey,
231+
account.address
231232
)
232233
val client =
233234
Client(account.address, privateKeyBundleV1, apiClient, libXMTPClient)
234235
client.ensureUserContactPublished()
235236
client
236237
} catch (e: java.lang.Exception) {
237-
throw XMTPException("Error creating client", e)
238+
throw XMTPException("Error creating client ${e.message}", e)
238239
}
239240
}
240241
}
@@ -263,7 +264,8 @@ class Client() {
263264
account,
264265
options?.appContext,
265266
v1Bundle,
266-
LegacyIdentitySource.STATIC
267+
LegacyIdentitySource.STATIC,
268+
address
267269
)
268270
}
269271
} else null
@@ -282,14 +284,15 @@ class Client() {
282284

283285
private suspend fun ffiXmtpClient(
284286
options: ClientOptions?,
285-
account: SigningKey,
287+
account: SigningKey?,
286288
appContext: Context?,
287289
privateKeyBundleV1: PrivateKeyBundleV1,
288290
legacyIdentitySource: LegacyIdentitySource,
291+
accountAddress: String,
289292
): FfiXmtpClient? {
290293
val v3Client: FfiXmtpClient? =
291294
if (isAlphaMlsEnabled(options)) {
292-
val alias = "xmtp-${options!!.api.env}-${account.address.lowercase()}"
295+
val alias = "xmtp-${options!!.api.env}-${accountAddress.lowercase()}"
293296

294297
val dbDir = File(appContext?.filesDir?.absolutePath, "xmtp_db")
295298
dbDir.mkdir()
@@ -325,7 +328,7 @@ class Client() {
325328
isSecure = false,
326329
db = dbPath,
327330
encryptionKey = retrievedKey.encoded,
328-
accountAddress = account.address.lowercase(),
331+
accountAddress = accountAddress.lowercase(),
329332
legacyIdentitySource = legacyIdentitySource,
330333
legacySignedPrivateKeyProto = privateKeyBundleV1.toV2().identityKey.toByteArray()
331334
)
@@ -335,10 +338,12 @@ class Client() {
335338

336339
if (v3Client?.textToSign() == null) {
337340
v3Client?.registerIdentity(null)
338-
} else {
341+
} else if (account != null) {
339342
v3Client.textToSign()?.let {
340343
v3Client.registerIdentity(account.sign(it))
341344
}
345+
} else {
346+
Log.i(TAG, "No signer passed but signer was required.")
342347
}
343348

344349
return v3Client

0 commit comments

Comments
 (0)