From 7514590e7d1a26c9c8399418ed3dc37f2cc315be Mon Sep 17 00:00:00 2001 From: Alex Risch Date: Wed, 14 Feb 2024 08:53:51 -0700 Subject: [PATCH] feat: Groups iOS Also native codec for group change --- .../wrappers/ContentJson.kt | 19 +++++++ example/src/GroupScreen.tsx | 56 +++++++++++++++++-- src/lib/NativeCodecs/GroupChangeCodec.ts | 9 ++- src/lib/types/ContentCodec.ts | 11 ++++ 4 files changed, 86 insertions(+), 9 deletions(-) diff --git a/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/ContentJson.kt b/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/ContentJson.kt index b46015697..ece84a14b 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/ContentJson.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/ContentJson.kt @@ -30,6 +30,9 @@ import org.xmtp.android.library.codecs.description import org.xmtp.android.library.codecs.getReactionAction import org.xmtp.android.library.codecs.getReactionSchema import org.xmtp.android.library.codecs.id +import uniffi.xmtpv3.org.xmtp.android.library.codecs.ContentTypeGroupMembershipChange +import uniffi.xmtpv3.org.xmtp.android.library.codecs.GroupMembershipChangeCodec +import uniffi.xmtpv3.org.xmtp.android.library.codecs.GroupMembershipChanges import java.net.URL class ContentJson( @@ -51,6 +54,7 @@ class ContentJson( Client.register(RemoteAttachmentCodec()) Client.register(ReplyCodec()) Client.register(ReadReceiptCodec()) + Client.register(GroupMembershipChangeCodec()) } fun fromJsonObject(obj: JsonObject): ContentJson { @@ -171,6 +175,21 @@ class ContentJson( "readReceipt" to "" ) + ContentTypeGroupMembershipChange.id -> mapOf( + "groupChange" to mapOf( + "membersAdded" to (content as GroupMembershipChanges).membersAddedList.map { + mapOf( + "address" to it.accountAddress, + "initiatedByAddress" to it.initiatedByAccountAddress + )}, + "membersRemoved" to content.membersRemovedList.map { + mapOf( + "address" to it.accountAddress, + "initiatedByAddress" to it.initiatedByAccountAddress + )}, + ) + ) + else -> { val json = JsonObject() encodedContent?.let { diff --git a/example/src/GroupScreen.tsx b/example/src/GroupScreen.tsx index 36e2bfc01..ca98f827f 100644 --- a/example/src/GroupScreen.tsx +++ b/example/src/GroupScreen.tsx @@ -8,7 +8,7 @@ import * as ImagePicker from 'expo-image-picker' import type { ImagePickerAsset } from 'expo-image-picker' import { PermissionStatus } from 'expo-modules-core' import moment from 'moment' -import React, { useCallback, useMemo, useRef, useState } from 'react' +import React, { FC, useCallback, useMemo, useRef, useState } from 'react' import { Button, FlatList, @@ -31,6 +31,7 @@ import { StaticAttachmentContent, ReplyContent, useClient, + GroupChangeContent, } from 'xmtp-react-native-sdk' import { ConversationSendPayload } from 'xmtp-react-native-sdk/lib/types' @@ -1058,6 +1059,53 @@ function RemoteAttachmentMessageContents({ ) } +function formatAddress(address: string) { + return `${address.slice(0, 6)}…${address.slice(-4)}` +} + +function GroupChangeContents({ content }: { content: GroupChangeContent }) { + return ( + <> + {content.membersAdded.length > 0 && + (content.membersAdded.length === 1 ? ( + + {`${formatAddress( + content.membersAdded[0].address + )} has been added by ${formatAddress( + content.membersAdded[0].initiatedByAddress + )}`} + + ) : ( + + {`${ + content.membersAdded.length + } members have been added by ${formatAddress( + content.membersAdded[0].initiatedByAddress + )}`} + + ))} + {content.membersRemoved.length > 0 && + (content.membersRemoved.length === 1 ? ( + + {`${formatAddress( + content.membersRemoved[0].address + )} has been removed by ${formatAddress( + content.membersRemoved[0].initiatedByAddress + )}`} + + ) : ( + + {`${ + content.membersRemoved.length + } members have been removed by ${formatAddress( + content.membersRemoved[0].initiatedByAddress + )}`} + + ))} + + ) +} + function MessageContents({ contentTypeId, content, @@ -1113,11 +1161,7 @@ function MessageContents({ ) } if (contentTypeId === 'xmtp.org/group_membership_change:1.0') { - return ( - - Group members have changed - - ) + return } return ( diff --git a/src/lib/NativeCodecs/GroupChangeCodec.ts b/src/lib/NativeCodecs/GroupChangeCodec.ts index a74be472a..96b153e4d 100644 --- a/src/lib/NativeCodecs/GroupChangeCodec.ts +++ b/src/lib/NativeCodecs/GroupChangeCodec.ts @@ -1,10 +1,13 @@ import { ContentTypeId, + GroupChangeContent, NativeContentCodec, NativeMessageContent, } from '../ContentCodec' -export class GroupChangeCodec implements NativeContentCodec { +export class GroupChangeCodec + implements NativeContentCodec +{ contentKey: 'groupChange' = 'groupChange' contentType: ContentTypeId = { authorityId: 'xmtp.org', @@ -17,8 +20,8 @@ export class GroupChangeCodec implements NativeContentCodec { return {} } - decode(nativeContent: NativeMessageContent): string { - return nativeContent.text! + decode(nativeContent: NativeMessageContent): GroupChangeContent { + return nativeContent.groupChange! } fallback(): string | undefined { diff --git a/src/lib/types/ContentCodec.ts b/src/lib/types/ContentCodec.ts index c108aa5fc..00b6c93d4 100644 --- a/src/lib/types/ContentCodec.ts +++ b/src/lib/types/ContentCodec.ts @@ -53,6 +53,16 @@ export type RemoteAttachmentContent = RemoteAttachmentMetadata & { url: string } +export type GroupChangeEntry = { + address: string + initiatedByAddress: string +} + +export type GroupChangeContent = { + membersAdded: GroupChangeEntry[] + membersRemoved: GroupChangeEntry[] +} + // This contains a message that has been prepared for sending. // It contains the message ID and the URI of a local file // containing the payload that needs to be published. @@ -91,6 +101,7 @@ export type NativeMessageContent = { remoteAttachment?: RemoteAttachmentContent readReceipt?: ReadReceiptContent encoded?: string + groupChange?: GroupChangeContent } export interface JSContentCodec {