Skip to content

Commit

Permalink
get groups working again with signer improvements and membership changes
Browse files Browse the repository at this point in the history
  • Loading branch information
nplasterer committed Jan 30, 2024
1 parent 5099e29 commit 5191cc5
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ import org.xmtp.android.library.Client
import org.xmtp.android.library.ClientOptions
import org.xmtp.android.library.XMTPEnvironment
import org.xmtp.android.library.messages.PrivateKeyBundleV1Builder
import uniffi.xmtpv3.org.xmtp.android.library.codecs.GroupMembershipChangeCodec

object ClientManager {

fun clientOptions(appContext: Context?): ClientOptions {
return ClientOptions(
api = ClientOptions.Api(
XMTPEnvironment.LOCAL,
appVersion = "XMTPAndroidExample/v1.0.0"
appVersion = "XMTPAndroidExample/v1.0.0",
isSecure = false
),
enableAlphaMls = true,
appContext = appContext
Expand All @@ -45,6 +47,7 @@ object ClientManager {
val v1Bundle =
PrivateKeyBundleV1Builder.fromEncodedData(data = encodedPrivateKeyData)
_client = Client().buildFrom(v1Bundle, clientOptions(appContext))
Client.register(codec = GroupMembershipChangeCodec())
_clientState.value = ClientState.Ready
} catch (e: Exception) {
_clientState.value = ClientState.Error(e.localizedMessage.orEmpty())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import org.xmtp.android.library.Client
import org.xmtp.android.library.XMTPException
import org.xmtp.android.library.messages.PrivateKeyBuilder
import org.xmtp.android.library.messages.PrivateKeyBundleV1Builder
import uniffi.xmtpv3.org.xmtp.android.library.codecs.GroupMembershipChangeCodec

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

Expand Down Expand Up @@ -86,6 +87,7 @@ class ConnectWalletViewModel(application: Application) : AndroidViewModel(applic
try {
val wallet = PrivateKeyBuilder()
val client = Client().create(wallet, ClientManager.clientOptions(getApplication()))
Client.register(codec = GroupMembershipChangeCodec())
_uiState.value = ConnectUiState.Success(
wallet.address,
PrivateKeyBundleV1Builder.encodeData(client.privateKeyBundleV1)
Expand All @@ -110,6 +112,7 @@ class ConnectWalletViewModel(application: Application) : AndroidViewModel(applic
}
}
val client = Client().create(wallet, ClientManager.clientOptions(getApplication()))
Client.register(codec = GroupMembershipChangeCodec())
_uiState.value = ConnectUiState.Success(
wallet.address,
PrivateKeyBundleV1Builder.encodeData(client.privateKeyBundleV1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import org.xmtp.android.example.R
import org.xmtp.android.example.databinding.ListItemConversationBinding
import org.xmtp.android.example.extension.truncatedAddress
import org.xmtp.android.library.Conversation
import uniffi.xmtpv3.org.xmtp.android.library.codecs.GroupMembershipChanges

class ConversationViewHolder(
private val binding: ListItemConversationBinding,
clickListener: ConversationsClickListener
clickListener: ConversationsClickListener,
) : RecyclerView.ViewHolder(binding.root) {

private var conversation: Conversation? = null
Expand All @@ -33,7 +34,17 @@ class ConversationViewHolder(
} else {
item.conversation.peerAddress.truncatedAddress()
}
val messageBody = item.mostRecentMessage?.body.orEmpty()

val messageBody: String = if (item.mostRecentMessage?.content<Any>() is String) {
item.mostRecentMessage.body.orEmpty()
} else if (item.mostRecentMessage?.content<Any>() is GroupMembershipChanges) {
val changes = item.mostRecentMessage.content() as? GroupMembershipChanges
"Membership Changed ${
changes?.membersAddedList?.mapNotNull { it.accountAddress }.toString()
}"
} else {
""
}
val isMe = item.mostRecentMessage?.senderAddress == ClientManager.client.address
if (messageBody.isNotBlank()) {
binding.messageBody.text = if (isMe) binding.root.resources.getString(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.xmtp.android.example.message

import android.annotation.SuppressLint
import android.graphics.Color
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.PARENT_ID
Expand All @@ -10,9 +11,11 @@ import org.xmtp.android.example.R
import org.xmtp.android.example.conversation.ConversationDetailViewModel
import org.xmtp.android.example.databinding.ListItemMessageBinding
import org.xmtp.android.example.extension.margins
import org.xmtp.proto.mls.message.contents.TranscriptMessages
import uniffi.xmtpv3.org.xmtp.android.library.codecs.GroupMembershipChanges

class MessageViewHolder(
private val binding: ListItemMessageBinding
private val binding: ListItemMessageBinding,
) : RecyclerView.ViewHolder(binding.root) {

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

@SuppressLint("SetTextI18n")
fun bind(item: ConversationDetailViewModel.MessageListItem.Message) {
val isFromMe = ClientManager.client.address.lowercase() == item.message.senderAddress.lowercase()
val isFromMe =
ClientManager.client.address.lowercase() == item.message.senderAddress.lowercase()
val params = binding.messageContainer.layoutParams as ConstraintLayout.LayoutParams
if (isFromMe) {
params.rightToRight = PARENT_ID
Expand All @@ -38,6 +43,14 @@ class MessageViewHolder(
binding.messageBody.setTextColor(Color.WHITE)
}
binding.messageContainer.layoutParams = params
binding.messageBody.text = item.message.body
if (item.message.content<Any>() is String) {
binding.messageBody.text = item.message.body
} else if (item.message.content<Any>() is GroupMembershipChanges) {
val changes = item.message.content() as? GroupMembershipChanges
binding.messageBody.text =
"Membership Changed ${
changes?.membersAddedList?.mapNotNull { it.accountAddress }.toString()
}"
}
}
}
23 changes: 14 additions & 9 deletions library/src/main/java/org/xmtp/android/library/Client.kt
Original file line number Diff line number Diff line change
Expand Up @@ -175,14 +175,14 @@ class Client() {
val apiClient =
GRPCApiClient(environment = clientOptions.api.env, secure = clientOptions.api.isSecure)
val v3Client: FfiXmtpClient? = if (isAlphaMlsEnabled(options)) {
if (account == null) throw XMTPException("Signing Key required to use groups.")
runBlocking {
ffiXmtpClient(
options,
account,
options?.appContext,
bundle,
LegacyIdentitySource.STATIC
LegacyIdentitySource.STATIC,
address
)
}
} else null
Expand Down Expand Up @@ -227,14 +227,15 @@ class Client() {
account,
options?.appContext,
privateKeyBundleV1,
legacyIdentityKey
legacyIdentityKey,
account.address
)
val client =
Client(account.address, privateKeyBundleV1, apiClient, libXMTPClient)
client.ensureUserContactPublished()
client
} catch (e: java.lang.Exception) {
throw XMTPException("Error creating client", e)
throw XMTPException("Error creating client ${e.message}", e)
}
}
}
Expand Down Expand Up @@ -263,7 +264,8 @@ class Client() {
account,
options?.appContext,
v1Bundle,
LegacyIdentitySource.STATIC
LegacyIdentitySource.STATIC,
address
)
}
} else null
Expand All @@ -282,14 +284,15 @@ class Client() {

private suspend fun ffiXmtpClient(
options: ClientOptions?,
account: SigningKey,
account: SigningKey?,
appContext: Context?,
privateKeyBundleV1: PrivateKeyBundleV1,
legacyIdentitySource: LegacyIdentitySource,
accountAddress: String,
): FfiXmtpClient? {
val v3Client: FfiXmtpClient? =
if (isAlphaMlsEnabled(options)) {
val alias = "xmtp-${options!!.api.env}-${account.address.lowercase()}"
val alias = "xmtp-${options!!.api.env}-${accountAddress.lowercase()}"

val dbDir = File(appContext?.filesDir?.absolutePath, "xmtp_db")
dbDir.mkdir()
Expand Down Expand Up @@ -325,7 +328,7 @@ class Client() {
isSecure = false,
db = dbPath,
encryptionKey = retrievedKey.encoded,
accountAddress = account.address.lowercase(),
accountAddress = accountAddress.lowercase(),
legacyIdentitySource = legacyIdentitySource,
legacySignedPrivateKeyProto = privateKeyBundleV1.toV2().identityKey.toByteArray()
)
Expand All @@ -335,10 +338,12 @@ class Client() {

if (v3Client?.textToSign() == null) {
v3Client?.registerIdentity(null)
} else {
} else if (account != null) {
v3Client.textToSign()?.let {
v3Client.registerIdentity(account.sign(it))
}
} else {
Log.i(TAG, "No signer passed but signer was required.")
}

return v3Client
Expand Down

0 comments on commit 5191cc5

Please sign in to comment.