Skip to content

Commit

Permalink
Merge pull request #418 from xmtp/np/metadata-updates
Browse files Browse the repository at this point in the history
  • Loading branch information
nplasterer authored Jun 13, 2024
2 parents ef412d8 + 4a0017d commit bda89e3
Show file tree
Hide file tree
Showing 12 changed files with 180 additions and 21 deletions.
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ repositories {
dependencies {
implementation project(':expo-modules-core')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
implementation "org.xmtp:android:0.12.4"
implementation "org.xmtp:android:0.12.5"
implementation 'com.google.code.gson:gson:2.10.1'
implementation 'com.facebook.react:react-native:0.71.3'
implementation "com.daveanthonythomas.moshipack:moshipack:1.0.1"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -785,15 +785,20 @@ class XMTPModule : Module() {
ConversationWrapper.encode(client, conversation)
}
}
AsyncFunction("createGroup") Coroutine { inboxId: String, peerAddresses: List<String>, permission: String ->
AsyncFunction("createGroup") Coroutine { inboxId: String, peerAddresses: List<String>, permission: String, groupName: String, groupImageUrlSquare: String ->
withContext(Dispatchers.IO) {
logV("createGroup")
val client = clients[inboxId] ?: throw XMTPException("No client")
val permissionLevel = when (permission) {
"admin_only" -> GroupPermissions.ADMIN_ONLY
else -> GroupPermissions.ALL_MEMBERS
}
val group = client.conversations.newGroup(peerAddresses, permissionLevel)
val group = client.conversations.newGroup(
peerAddresses,
permissionLevel,
groupName,
groupImageUrlSquare
)
GroupWrapper.encode(client, group)
}
}
Expand Down Expand Up @@ -893,6 +898,26 @@ class XMTPModule : Module() {
}
}

AsyncFunction("groupImageUrlSquare") Coroutine { inboxId: String, id: String ->
withContext(Dispatchers.IO) {
logV("groupImageUrlSquare")
val client = clients[inboxId] ?: throw XMTPException("No client")
val group = findGroup(inboxId, id)

group?.imageUrlSquare
}
}

AsyncFunction("updateGroupImageUrlSquare") Coroutine { inboxId: String, id: String, groupImageUrl: String ->
withContext(Dispatchers.IO) {
logV("updateGroupImageUrlSquare")
val client = clients[inboxId] ?: throw XMTPException("No client")
val group = findGroup(inboxId, id)

group?.updateGroupImageUrlSquare(groupImageUrl)
}
}

AsyncFunction("isGroupActive") Coroutine { inboxId: String, id: String ->
withContext(Dispatchers.IO) {
logV("isGroupActive")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ class GroupWrapper {
"permissionLevel" to permissionString,
"creatorInboxId" to group.creatorInboxId(),
"name" to group.name,
"isActive" to group.isActive()
"isActive" to group.isActive(),
"imageUrlSquare" to group.imageUrlSquare
)
}

Expand Down
14 changes: 7 additions & 7 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ PODS:
- hermes-engine/Pre-built (= 0.71.14)
- hermes-engine/Pre-built (0.71.14)
- libevent (2.1.12)
- LibXMTP (0.5.1-beta1)
- LibXMTP (0.5.1-beta2)
- Logging (1.0.0)
- MessagePacker (0.4.7)
- MMKV (1.3.5):
Expand Down Expand Up @@ -449,16 +449,16 @@ PODS:
- GenericJSON (~> 2.0)
- Logging (~> 1.0.0)
- secp256k1.swift (~> 0.1)
- XMTP (0.11.6):
- XMTP (0.11.7):
- Connect-Swift (= 0.12.0)
- GzipSwift
- LibXMTP (= 0.5.1-beta1)
- LibXMTP (= 0.5.1-beta2)
- web3.swift
- XMTPReactNative (0.1.0):
- ExpoModulesCore
- MessagePacker
- secp256k1.swift
- XMTP (= 0.11.6)
- XMTP (= 0.11.7)
- Yoga (1.14.0)

DEPENDENCIES:
Expand Down Expand Up @@ -711,7 +711,7 @@ SPEC CHECKSUMS:
GzipSwift: 893f3e48e597a1a4f62fafcb6514220fcf8287fa
hermes-engine: d7cc127932c89c53374452d6f93473f1970d8e88
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
LibXMTP: f897dba3ea05dd5f8b9d098176cd9cb7c73ad505
LibXMTP: 954acfb393be3b19bf44ea9009af558c00222450
Logging: 9ef4ecb546ad3169398d5a723bc9bea1c46bef26
MessagePacker: ab2fe250e86ea7aedd1a9ee47a37083edd41fd02
MMKV: 506311d0494023c2f7e0b62cc1f31b7370fa3cfb
Expand Down Expand Up @@ -763,8 +763,8 @@ SPEC CHECKSUMS:
secp256k1.swift: a7e7a214f6db6ce5db32cc6b2b45e5c4dd633634
SwiftProtobuf: 407a385e97fd206c4fbe880cc84123989167e0d1
web3.swift: 2263d1e12e121b2c42ffb63a5a7beb1acaf33959
XMTP: 5986c7bc1400b8b054569d4c7c6d2f673d992be1
XMTPReactNative: ed4824399c26767008b8266992085461f0cece98
XMTP: b8ab59997ee95106778f445992fa00adce6c2d71
XMTPReactNative: fc0eae046a9a3e3031c6d3b9921e15a6d5b13e09
Yoga: e71803b4c1fff832ccf9b92541e00f9b873119b9

PODFILE CHECKSUM: 95d6ace79946933ecf80684613842ee553dd76a2
Expand Down
57 changes: 56 additions & 1 deletion example/src/tests/groupTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1004,12 +1004,67 @@ test('can stream all messages', async () => {
return true
})

test('can make a group with metadata', async () => {
const [alix, bo] = await createClients(2)

const alixGroup = await alix.conversations.newGroup([bo.address], {
name: 'Start Name',
imageUrlSquare: 'starturl.com',
})

const groupName1 = await alixGroup.groupName()
const groupImageUrl1 = await alixGroup.groupImageUrlSquare()
assert(
groupName1 === 'Start Name',
`the group should start with a name of Start Name not ${groupName1}`
)

assert(
groupImageUrl1 === 'starturl.com',
`the group should start with a name of starturl.com not ${groupImageUrl1}`
)

await alixGroup.updateGroupName('New Name')
await alixGroup.updateGroupImageUrlSquare('newurl.com')
await alixGroup.sync()
await bo.conversations.syncGroups()
const boGroups = await bo.conversations.listGroups()
const boGroup = boGroups[0]
await boGroup.sync()

const groupName2 = await alixGroup.groupName()
const groupImageUrl2 = await alixGroup.groupImageUrlSquare()
assert(
groupName2 === 'New Name',
`the group should start with a name of New Name not ${groupName2}`
)

assert(
groupImageUrl2 === 'newurl.com',
`the group should start with a name of newurl.com not ${groupImageUrl2}`
)

const groupName3 = await boGroup.groupName()
const groupImageUrl3 = await boGroup.groupImageUrlSquare()
assert(
groupName3 === 'New Name',
`the group should start with a name of New Name not ${groupName3}`
)

assert(
groupImageUrl3 === 'newurl.com',
`the group should start with a name of newurl.com not ${groupImageUrl3}`
)

return true
})

test('can make a group with admin permissions', async () => {
const [adminClient, anotherClient] = await createClients(2)

const group = await adminClient.conversations.newGroup(
[anotherClient.address],
'admin_only'
{ permissionLevel: 'admin_only' }
)

if (group.permissionLevel !== 'admin_only') {
Expand Down
3 changes: 2 additions & 1 deletion ios/Wrappers/GroupWrapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ struct GroupWrapper {
"permissionLevel": permissionString,
"creatorInboxId": try group.creatorInboxId(),
"name": try group.groupName(),
"isActive": try group.isActive()
"isActive": try group.isActive(),
"imageUrlSquare": try group.groupImageUrlSquare(),
]
}

Expand Down
29 changes: 26 additions & 3 deletions ios/XMTPModule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,7 @@ public class XMTPModule: Module {
}
}

AsyncFunction("createGroup") { (inboxId: String, peerAddresses: [String], permission: String) -> String in
AsyncFunction("createGroup") { (inboxId: String, peerAddresses: [String], permission: String, groupName: String, groupImageUrlSquare: String) -> String in
guard let client = await clientsManager.getClient(key: inboxId) else {
throw Error.noClient
}
Expand All @@ -672,7 +672,7 @@ public class XMTPModule: Module {
}
}()
do {
let group = try await client.conversations.newGroup(with: peerAddresses, permissions: permissionLevel)
let group = try await client.conversations.newGroup(with: peerAddresses, permissions: permissionLevel, name: groupName, imageUrlSquare: groupImageUrlSquare)
return try GroupWrapper.encode(group, client: client)
} catch {
print("ERRRO!: \(error.localizedDescription)")
Expand Down Expand Up @@ -769,7 +769,6 @@ public class XMTPModule: Module {
try await group.removeMembersByInboxId(inboxIds: inboxIds)
}


AsyncFunction("groupName") { (inboxId: String, id: String) -> String in
guard let client = await clientsManager.getClient(key: inboxId) else {
throw Error.noClient
Expand All @@ -794,6 +793,30 @@ public class XMTPModule: Module {
try await group.updateGroupName(groupName: groupName)
}

AsyncFunction("groupImageUrlSquare") { (inboxId: String, id: String) -> String in
guard let client = await clientsManager.getClient(key: inboxId) else {
throw Error.noClient
}

guard let group = try await findGroup(inboxId: inboxId, id: id) else {
throw Error.conversationNotFound("no group found for \(id)")
}

return try group.groupImageUrlSquare()
}

AsyncFunction("updateGroupImageUrlSquare") { (inboxId: String, id: String, groupImageUrl: String) in
guard let client = await clientsManager.getClient(key: inboxId) else {
throw Error.noClient
}

guard let group = try await findGroup(inboxId: inboxId, id: id) else {
throw Error.conversationNotFound("no group found for \(id)")
}

try await group.updateGroupImageUrlSquare(imageUrlSquare: groupImageUrl)
}

AsyncFunction("isGroupActive") { (inboxId: String, id: String) -> Bool in
guard let client = await clientsManager.getClient(key: inboxId) else {
throw Error.noClient
Expand Down
2 changes: 1 addition & 1 deletion ios/XMTPReactNative.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ Pod::Spec.new do |s|
s.source_files = "**/*.{h,m,swift}"
s.dependency 'secp256k1.swift'
s.dependency "MessagePacker"
s.dependency "XMTP", "= 0.11.6"
s.dependency "XMTP", "= 0.11.7"
end
23 changes: 21 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,19 @@ export async function createGroup<
>(
client: Client<ContentTypes>,
peerAddresses: string[],
permissionLevel: 'all_members' | 'admin_only' = 'all_members'
permissionLevel: 'all_members' | 'admin_only' = 'all_members',
name: string = '',
imageUrlSquare: string = ''
): Promise<Group<ContentTypes>> {
return new Group(
client,
JSON.parse(
await XMTPModule.createGroup(
client.inboxId,
peerAddresses,
permissionLevel
permissionLevel,
name,
imageUrlSquare
)
)
)
Expand Down Expand Up @@ -254,6 +258,21 @@ export async function removeGroupMembersByInboxId(
return XMTPModule.removeGroupMembersByInboxId(inboxId, id, inboxIds)
}

export function groupImageUrlSquare(
inboxId: string,
id: string
): string | PromiseLike<string> {
return XMTPModule.groupImageUrlSquare(inboxId, id)
}

export function updateGroupImageUrlSquare(
inboxId: string,
id: string,
imageUrlSquare: string
): Promise<void> {
return XMTPModule.updateGroupImageUrlSquare(inboxId, id, imageUrlSquare)
}

export function groupName(
inboxId: string,
id: string
Expand Down
7 changes: 5 additions & 2 deletions src/lib/Conversations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { ConversationContext } from '../XMTP.types'
import * as XMTPModule from '../index'
import { ContentCodec } from '../index'
import { getAddress } from '../utils/address'
import { CreateGroupOptions } from './types/CreateGroupOptions'

export default class Conversations<
ContentTypes extends ContentCodec<any>[] = [],
Expand Down Expand Up @@ -151,12 +152,14 @@ export default class Conversations<
*/
async newGroup(
peerAddresses: string[],
permissionLevel: 'all_members' | 'admin_only' = 'all_members'
opts?: CreateGroupOptions | undefined
): Promise<Group<ContentTypes>> {
return await XMTPModule.createGroup(
this.client,
peerAddresses,
permissionLevel
opts?.permissionLevel,
opts?.name,
opts?.imageUrlSquare
)
}

Expand Down
27 changes: 27 additions & 0 deletions src/lib/Group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export class Group<
permissionLevel: 'all_members' | 'admin_only'
name: string
isGroupActive: boolean
imageUrlSquare: string

constructor(
client: XMTP.Client<ContentTypes>,
Expand All @@ -38,6 +39,7 @@ export class Group<
topic: string
name: string
isGroupActive: boolean
imageUrlSquare: string
}
) {
this.client = client
Expand All @@ -49,6 +51,7 @@ export class Group<
this.permissionLevel = params.permissionLevel
this.name = params.name
this.isGroupActive = params.isGroupActive
this.imageUrlSquare = params.imageUrlSquare
}

/**
Expand Down Expand Up @@ -235,6 +238,30 @@ export class Group<
return XMTP.updateGroupName(this.client.inboxId, this.id, groupName)
}

/**
* Returns the group image url square.
* To get the latest group image url square from the network, call sync() first.
* @returns {string} A Promise that resolves to the group name.
*/
async groupImageUrlSquare(): Promise<string> {
return XMTP.groupImageUrlSquare(this.client.inboxId, this.id)
}

/**
* Updates the group image url square.
* Will throw if the user does not have the required permissions.
* @param {string} imageUrlSquare new group profile image url
* @returns
*/

async updateGroupImageUrlSquare(imageUrlSquare: string): Promise<void> {
return XMTP.updateGroupImageUrlSquare(
this.client.inboxId,
this.id,
imageUrlSquare
)
}

/**
* Returns whether the group is active.
* To get the latest active status from the network, call sync() first
Expand Down
5 changes: 5 additions & 0 deletions src/lib/types/CreateGroupOptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export type CreateGroupOptions = {
permissionLevel?: 'all_members' | 'admin_only' | undefined
name?: string | undefined
imageUrlSquare?: string | undefined
}

0 comments on commit bda89e3

Please sign in to comment.