Skip to content

Commit

Permalink
added pinned frame url
Browse files Browse the repository at this point in the history
  • Loading branch information
cameronvoell committed Jul 3, 2024
1 parent c74fc24 commit ff6aed3
Show file tree
Hide file tree
Showing 11 changed files with 209 additions and 24 deletions.
22 changes: 11 additions & 11 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -98,19 +98,19 @@ repositories {
dependencies {
implementation project(':expo-modules-core')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
implementation "org.xmtp:android:0.14.2"
// implementation "org.xmtp:android:0.14.2"
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"
// xmtp-android local testing setup below (comment org.xmtp:android above)
// implementation files('<PATH TO XMTP-ANDROID>/xmtp-android/library/build/outputs/aar/library-debug.aar')
// implementation 'com.google.crypto.tink:tink-android:1.8.0'
// implementation 'io.grpc:grpc-kotlin-stub:1.4.1'
// implementation 'io.grpc:grpc-okhttp:1.62.2'
// implementation 'io.grpc:grpc-protobuf-lite:1.62.2'
// implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3'
// implementation 'org.web3j:crypto:5.0.0'
// implementation "net.java.dev.jna:jna:5.14.0@aar"
// api 'com.google.protobuf:protobuf-kotlin-lite:3.22.3'
// api 'org.xmtp:proto-kotlin:3.61.1'
implementation files('/Users/cameronvoell/XMTP/xmtp-android/library/build/outputs/aar/library-debug.aar')
implementation 'com.google.crypto.tink:tink-android:1.8.0'
implementation 'io.grpc:grpc-kotlin-stub:1.4.1'
implementation 'io.grpc:grpc-okhttp:1.62.2'
implementation 'io.grpc:grpc-protobuf-lite:1.62.2'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0'
implementation 'org.web3j:crypto:5.0.0'
implementation "net.java.dev.jna:jna:5.14.0@aar"
api 'com.google.protobuf:protobuf-kotlin-lite:3.22.3'
api 'org.xmtp:proto-kotlin:3.62.1'
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import expo.modules.xmtpreactnativesdk.wrappers.ConsentWrapper.Companion.consent
import expo.modules.xmtpreactnativesdk.wrappers.ContentJson
import expo.modules.xmtpreactnativesdk.wrappers.ConversationContainerWrapper
import expo.modules.xmtpreactnativesdk.wrappers.ConversationWrapper
import expo.modules.xmtpreactnativesdk.wrappers.CreateGroupParamsWrapper
import expo.modules.xmtpreactnativesdk.wrappers.DecodedMessageWrapper
import expo.modules.xmtpreactnativesdk.wrappers.DecryptedLocalAttachment
import expo.modules.xmtpreactnativesdk.wrappers.EncryptedLocalAttachment
Expand Down Expand Up @@ -834,25 +835,28 @@ class XMTPModule : Module() {
ConversationWrapper.encode(client, conversation)
}
}
AsyncFunction("createGroup") Coroutine { inboxId: String, peerAddresses: List<String>, permission: String, groupName: String, groupImageUrlSquare: String, groupDescription: String ->
AsyncFunction("createGroup") Coroutine { inboxId: String, peerAddresses: List<String>, permission: String, groupOptionsJson: String ->
withContext(Dispatchers.IO) {
logV("createGroup")
val client = clients[inboxId] ?: throw XMTPException("No client")
val permissionLevel = when (permission) {
"admin_only" -> GroupPermissionPreconfiguration.ADMIN_ONLY
else -> GroupPermissionPreconfiguration.ALL_MEMBERS
}
val createGroupParams = CreateGroupParamsWrapper.createGroupParamsFromJson(groupOptionsJson)
val group = client.conversations.newGroup(
peerAddresses,
permissionLevel,
groupName,
groupImageUrlSquare,
groupDescription
createGroupParams.groupName,
createGroupParams.groupImageUrlSquare,
createGroupParams.groupDescription,
createGroupParams.groupPinnedFrameUrl
)
GroupWrapper.encode(client, group)
}
}


AsyncFunction("listMemberInboxIds") Coroutine { inboxId: String, groupId: String ->
withContext(Dispatchers.IO) {
logV("listMembers")
Expand Down Expand Up @@ -988,6 +992,26 @@ class XMTPModule : Module() {
}
}

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

group?.pinnedFrameUrl
}
}

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

group?.updateGroupPinnedFrameUrl(pinnedFrameUrl)
}
}

AsyncFunction("isGroupActive") Coroutine { inboxId: String, id: String ->
withContext(Dispatchers.IO) {
logV("isGroupActive")
Expand Down Expand Up @@ -1166,6 +1190,16 @@ class XMTPModule : Module() {
}
}

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

group?.updateGroupPinnedFrameUrlPermission(getPermissionOption(newPermission))
}
}

AsyncFunction("permissionPolicySet") Coroutine { inboxId: String, id: String ->
withContext(Dispatchers.IO) {
logV("groupImageUrlSquare")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package expo.modules.xmtpreactnativesdk.wrappers

import com.google.gson.JsonParser

class CreateGroupParamsWrapper(
val groupName: String,
val groupImageUrlSquare: String,
val groupDescription: String,
val groupPinnedFrameUrl: String,
) {
companion object {
fun createGroupParamsFromJson(authParams: String): CreateGroupParamsWrapper {
val jsonOptions = JsonParser.parseString(authParams).asJsonObject
return CreateGroupParamsWrapper(
if (jsonOptions.has("name")) jsonOptions.get("name").asString else "",
if (jsonOptions.has("imageUrlSquare")) jsonOptions.get("imageUrlSquare").asString else "",
if (jsonOptions.has("description")) jsonOptions.get("description").asString else "",
if (jsonOptions.has("pinnedFrameUrl")) jsonOptions.get("pinnedFrameUrl").asString else "",
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ class GroupWrapper {

companion object {
fun encodeToObj(client: Client, group: Group): Map<String, Any> {
val permissionPolicySet = PermissionPolicySetWrapper.encodeToJsonString(group.permissionPolicySet())
return mapOf(
"clientAddress" to client.address,
"id" to group.id.toHex(),
Expand All @@ -18,10 +17,7 @@ class GroupWrapper {
"version" to "GROUP",
"topic" to group.topic,
"creatorInboxId" to group.creatorInboxId(),
"name" to group.name,
"isActive" to group.isActive(),
"imageUrlSquare" to group.imageUrlSquare,
"description" to group.description
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class PermissionPolicySetWrapper {
"updateGroupNamePolicy" to fromPermissionOption(policySet.updateGroupNamePolicy),
"updateGroupDescriptionPolicy" to fromPermissionOption(policySet.updateGroupDescriptionPolicy),
"updateGroupImagePolicy" to fromPermissionOption(policySet.updateGroupImagePolicy),
"updateGroupPinnedFrameUrlPolicy" to fromPermissionOption(policySet.updateGroupPinnedFrameUrlPolicy),
)
}

Expand Down
50 changes: 50 additions & 0 deletions example/src/tests/groupPermissionsTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -463,3 +463,53 @@ test('can update group permissions', async () => {

return true
})

test('can update group pinned frame', async () => {
// Create clients
const [alix, bo, caro] = await createClients(3)

// Bo creates a group with Alix and Caro
const boGroup = await bo.conversations.newGroup(
[alix.address, caro.address],
{ permissionLevel: 'admin_only' }
)

// Verify that alix can not update the group pinned frame
await alix.conversations.syncGroups()
const alixGroup = (await alix.conversations.listGroups())[0]
try {
await alixGroup.updateGroupPinnedFrameUrl('new pinned frame')
assert(false, 'Alix should not be able to update the group pinned frame')
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (error) {
// expected
}

// Verify that bo can update the group pinned frame
await boGroup.updateGroupPinnedFrameUrl('new pinned frame 2')
await boGroup.sync()
assert(
(await boGroup.groupPinnedFrameUrl()) === 'new pinned frame 2',
`boGroup.groupPinnedFrameUrl should be "new pinned frame 2" but was ${boGroup.groupPinnedFrameUrl}`
)

// Verify that bo can update the pinned frame permission
await boGroup.updateGroupPinnedFrameUrlPermission('allow')
await boGroup.sync()
assert(
(await boGroup.permissionPolicySet()).updateGroupPinnedFrameUrlPolicy ===
'allow',
`boGroup.permissionPolicySet.updateGroupPinnedFrameUrlPolicy should be allow but was ${(await boGroup.permissionPolicySet()).updateGroupPinnedFrameUrlPolicy}`
)

// Verify that Alix can now update pinned frames
await alixGroup.updateGroupPinnedFrameUrl('new pinned frame 3')
await alixGroup.sync()
await boGroup.sync()
assert(
(await boGroup.groupPinnedFrameUrl()) === 'new pinned frame 3',
`alixGroup.groupPinnedFrameUrl should be "new pinned frame 3" but was ${boGroup.groupPinnedFrameUrl}`
)

return true
})
47 changes: 43 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,18 +169,23 @@ export async function createGroup<
permissionLevel: 'all_members' | 'admin_only' = 'all_members',
name: string = '',
imageUrlSquare: string = '',
description: string = ''
description: string = '',
pinnedFrameUrl: string = ''
): Promise<Group<ContentTypes>> {
const options: CreateGroupParams = {
name,
imageUrlSquare,
description,
pinnedFrameUrl,
}
return new Group(
client,
JSON.parse(
await XMTPModule.createGroup(
client.inboxId,
peerAddresses,
permissionLevel,
name,
imageUrlSquare,
description
JSON.stringify(options)
)
)
)
Expand Down Expand Up @@ -364,6 +369,21 @@ export function updateGroupName(
return XMTPModule.updateGroupName(inboxId, id, groupName)
}

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

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

export async function sign(
inboxId: string,
digest: Uint8Array,
Expand Down Expand Up @@ -964,6 +984,18 @@ export async function updateGroupDescriptionPermission(
)
}

export async function updateGroupPinnedFrameUrlPermission(
clientInboxId: string,
id: string,
permissionOption: PermissionUpdateOption
): Promise<void> {
return XMTPModule.updateGroupPinnedFrameUrlPermission(
clientInboxId,
id,
permissionOption
)
}

export async function permissionPolicySet(
clientInboxId: string,
id: string
Expand Down Expand Up @@ -1066,6 +1098,13 @@ interface AuthParams {
historySyncUrl?: string
}

interface CreateGroupParams {
name: string
imageUrlSquare: string
description: string
pinnedFrameUrl: string
}

export * from './XMTP.types'
export { Client } from './lib/Client'
export * from './lib/ContentCodec'
Expand Down
3 changes: 2 additions & 1 deletion src/lib/Conversations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ export default class Conversations<
opts?.permissionLevel,
opts?.name,
opts?.imageUrlSquare,
opts?.description
opts?.description,
opts?.pinnedFrameUrl
)
}

Expand Down
40 changes: 40 additions & 0 deletions src/lib/Group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,30 @@ export class Group<
)
}

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

/**
* Updates the group pinned frame url.
* Will throw if the user does not have the required permissions.
* @param {string} pinnedFrameUrl new group pinned frame url
* @returns
*/

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

/**
* Returns whether the group is active.
* To get the latest active status from the network, call sync() first
Expand Down Expand Up @@ -495,6 +519,22 @@ export class Group<
)
}

/**
*
* @param {PermissionOption} permissionOption
* @returns {Promise<void>} A Promise that resolves when the groupPinnedFrameUrl permission is updated for the group.
* Will throw if the user does not have the required permissions.
*/
async updateGroupPinnedFrameUrlPermission(
permissionOption: PermissionUpdateOption
): Promise<void> {
return XMTP.updateGroupPinnedFrameUrlPermission(
this.client.inboxId,
this.id,
permissionOption
)
}

/**
*
* @returns {Promise<PermissionPolicySet>} A {PermissionPolicySet} object representing the group's permission policy set.
Expand Down
1 change: 1 addition & 0 deletions src/lib/types/CreateGroupOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ export type CreateGroupOptions = {
name?: string | undefined
imageUrlSquare?: string | undefined
description?: string | undefined
pinnedFrameUrl?: string | undefined
}
1 change: 1 addition & 0 deletions src/lib/types/PermissionPolicySet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ export type PermissionPolicySet = {
updateGroupNamePolicy: PermissionOption
updateGroupDescriptionPolicy: PermissionOption
updateGroupImagePolicy: PermissionOption
updateGroupPinnedFrameUrlPolicy: PermissionOption
}

0 comments on commit ff6aed3

Please sign in to comment.