From ff733a15fc5ca90e9df35dcc465e67c0df4dfa32 Mon Sep 17 00:00:00 2001
From: Szymon Szlachtowicz <38212223+Szymx95@users.noreply.github.com>
Date: Fri, 3 Dec 2021 11:51:55 +0100
Subject: [PATCH] Add name and member handling in group chats (#144)
---
packages/react-chat-example/src/index.tsx | 2 +-
.../src/components/Chat/ChatBody.tsx | 5 +-
.../src/components/Chat/ChatCreation.tsx | 28 ++++--
.../src/contexts/messengerProvider.tsx | 1 +
.../src/hooks/messenger/useGroupChats.ts | 17 +++-
.../src/hooks/messenger/useMessenger.ts | 25 ++++--
packages/status-communities/src/groupChats.ts | 86 ++++++++++++++-----
7 files changed, 125 insertions(+), 39 deletions(-)
diff --git a/packages/react-chat-example/src/index.tsx b/packages/react-chat-example/src/index.tsx
index ec517b04..0f73f52f 100644
--- a/packages/react-chat-example/src/index.tsx
+++ b/packages/react-chat-example/src/index.tsx
@@ -76,7 +76,7 @@ function DragDiv() {
diff --git a/packages/react-chat/src/components/Chat/ChatBody.tsx b/packages/react-chat/src/components/Chat/ChatBody.tsx
index b5c245c5..d0c2923e 100644
--- a/packages/react-chat/src/components/Chat/ChatBody.tsx
+++ b/packages/react-chat/src/components/Chat/ChatBody.tsx
@@ -56,7 +56,10 @@ export function ChatBody({ onClick, showMembers }: ChatBodyProps) {
return (
{editGroup && communityData ? (
-
+
) : (
void;
+ activeChannel?: ChannelData;
}
-export function ChatCreation({ editGroup }: ChatCreationProps) {
+export function ChatCreation({
+ setEditGroup,
+ activeChannel,
+}: ChatCreationProps) {
const identity = useIdentity();
const [query, setQuery] = useState("");
- const [styledGroup, setStyledGroup] = useState([]);
- const { contacts, createGroupChat } = useMessengerContext();
+ const [styledGroup, setStyledGroup] = useState(
+ activeChannel?.members?.map((member) => member?.customName ?? member.id) ??
+ []
+ );
+ const { contacts, createGroupChat, addMembers } = useMessengerContext();
const setChatState = useChatState()[1];
const addMember = useCallback(
@@ -33,7 +41,6 @@ export function ChatCreation({ editGroup }: ChatCreationProps) {
},
[setStyledGroup, styledGroup]
);
-
const removeMember = (member: string) => {
setStyledGroup((prev) => prev.filter((e) => e != member));
};
@@ -85,12 +92,19 @@ export function ChatCreation({ editGroup }: ChatCreationProps) {
createChat(styledGroup)}
+ onClick={() => {
+ if (!activeChannel) {
+ createChat(styledGroup);
+ } else {
+ addMembers(styledGroup, activeChannel.id);
+ }
+ setEditGroup?.(false);
+ }}
>
Confirm
- {!editGroup && !query && (
+ {!setEditGroup && !query && (
Contacts
diff --git a/packages/react-chat/src/contexts/messengerProvider.tsx b/packages/react-chat/src/contexts/messengerProvider.tsx
index e4e9949a..49bb1bad 100644
--- a/packages/react-chat/src/contexts/messengerProvider.tsx
+++ b/packages/react-chat/src/contexts/messengerProvider.tsx
@@ -27,6 +27,7 @@ const MessengerContext = createContext({
setActiveChannel: () => undefined,
createGroupChat: () => undefined,
changeGroupChatName: () => undefined,
+ addMembers: () => undefined,
});
export function useMessengerContext() {
diff --git a/packages/react-chat/src/hooks/messenger/useGroupChats.ts b/packages/react-chat/src/hooks/messenger/useGroupChats.ts
index e4cf07af..736c8043 100644
--- a/packages/react-chat/src/hooks/messenger/useGroupChats.ts
+++ b/packages/react-chat/src/hooks/messenger/useGroupChats.ts
@@ -96,5 +96,20 @@ export function useGroupChats(
[channels, groupChat]
);
- return { createGroupChat, removeChannel, groupChat, changeGroupChatName };
+ const addMembers = useCallback(
+ (members: string[], chatId: string) => {
+ if (groupChat) {
+ groupChat.addMembers(chatId, members);
+ }
+ },
+ [groupChat]
+ );
+
+ return {
+ createGroupChat,
+ removeChannel,
+ groupChat,
+ changeGroupChatName,
+ addMembers,
+ };
}
diff --git a/packages/react-chat/src/hooks/messenger/useMessenger.ts b/packages/react-chat/src/hooks/messenger/useMessenger.ts
index 279a6e63..62fb68d5 100644
--- a/packages/react-chat/src/hooks/messenger/useMessenger.ts
+++ b/packages/react-chat/src/hooks/messenger/useMessenger.ts
@@ -44,6 +44,7 @@ export type MessengerType = {
setActiveChannel: (channel: ChannelData) => void;
createGroupChat: (members: string[]) => void;
changeGroupChatName: (name: string, chatId: string) => void;
+ addMembers: (members: string[], chatId: string) => void;
};
function useCreateMessenger(identity: Identity | undefined) {
@@ -168,15 +169,20 @@ export function useMessenger(
});
}, [contacts]);
- const { groupChat, removeChannel, createGroupChat, changeGroupChatName } =
- useGroupChats(
- messenger,
- identity,
- setChannels,
- setActiveChannel,
- addChatMessage,
- channels
- );
+ const {
+ groupChat,
+ removeChannel,
+ createGroupChat,
+ changeGroupChatName,
+ addMembers,
+ } = useGroupChats(
+ messenger,
+ identity,
+ setChannels,
+ setActiveChannel,
+ addChatMessage,
+ channels
+ );
const { loadPrevDay, loadingMessages } = useLoadPrevDay(
activeChannel.id,
@@ -235,5 +241,6 @@ export function useMessenger(
clearMentions,
createGroupChat,
changeGroupChatName,
+ addMembers,
};
}
diff --git a/packages/status-communities/src/groupChats.ts b/packages/status-communities/src/groupChats.ts
index 94cd3b0c..d3ceb692 100644
--- a/packages/status-communities/src/groupChats.ts
+++ b/packages/status-communities/src/groupChats.ts
@@ -13,6 +13,7 @@ export type GroupChat = {
members: string[];
admins?: string[];
name?: string;
+ removed: boolean;
};
export type GroupChatsType = {
@@ -95,9 +96,11 @@ export class GroupChats {
);
await Promise.all(
membershipUpdate.events.map(async (event) => {
- const bufSigner = event.signer;
- const signer = bufSigner ? bufToHex(bufSigner) : "";
+ const signer = event.signer ? bufToHex(event.signer) : "";
+ const thisUser = bufToHex(this.identity.publicKey);
const chatId = membershipUpdate.chatId;
+ const chat: GroupChat | undefined = this.chats[chatId];
+
if (signer) {
switch (event.event.type) {
case MembershipUpdateEvent_EventType.CHAT_CREATED: {
@@ -106,27 +109,47 @@ export class GroupChats {
chatId: chatId,
members: event.event.members,
admins: [signer],
+ removed: false,
},
useCallback
);
break;
}
case MembershipUpdateEvent_EventType.MEMBER_REMOVED: {
- if (
- event.event.members[0] == bufToHex(this.identity.publicKey)
- ) {
- await this.removeChat(
- {
- chatId: chatId,
- members: event.event.members,
- },
- useCallback
+ if (chat) {
+ chat.members = chat.members.filter(
+ (member) => !event.event.members.includes(member)
);
+ if (event.event.members.includes(thisUser)) {
+ await this.removeChat(
+ {
+ ...chat,
+ removed: true,
+ },
+ useCallback
+ );
+ } else {
+ if (!chat.removed && useCallback) {
+ this.callback(this.chats[chatId]);
+ }
+ }
+ }
+ break;
+ }
+ case MembershipUpdateEvent_EventType.MEMBERS_ADDED: {
+ if (chat) {
+ chat.members.push(...event.event.members);
+ if (
+ chat.members.includes(thisUser) &&
+ chat.admins?.includes(signer)
+ ) {
+ chat.removed = false;
+ await this.addChat(chat, useCallback);
+ }
}
break;
}
case MembershipUpdateEvent_EventType.NAME_CHANGED: {
- const chat = this.chats[chatId];
if (chat) {
if (chat.admins?.includes(signer)) {
chat.name = event.event.name;
@@ -181,10 +204,17 @@ export class GroupChats {
}
private async addChat(chat: GroupChat, useCallback: boolean): Promise {
- this.chats[chat.chatId] = chat;
- if (useCallback) {
- await this.handleChatObserver(chat);
- this.callback(chat);
+ if (this.chats[chat.chatId]) {
+ this.chats[chat.chatId] = chat;
+ if (useCallback) {
+ this.callback(chat);
+ }
+ } else {
+ this.chats[chat.chatId] = chat;
+ if (useCallback) {
+ await this.handleChatObserver(chat);
+ this.callback(chat);
+ }
}
}
@@ -192,9 +222,8 @@ export class GroupChats {
chat: GroupChat,
useCallback: boolean
): Promise {
- delete this.chats[chat.chatId];
+ this.chats[chat.chatId] = chat;
if (useCallback) {
- await this.handleChatObserver(chat, true);
this.removeCallback(chat);
}
}
@@ -214,8 +243,10 @@ export class GroupChats {
);
await Promise.all(
Object.values(this.chats).map(async (chat) => {
- await this.handleChatObserver(chat);
- this.callback(chat);
+ if (!chat?.removed) {
+ await this.handleChatObserver(chat);
+ this.callback(chat);
+ }
})
);
this.waku.relay.addObserver(
@@ -246,6 +277,21 @@ export class GroupChats {
}
}
+ public async addMembers(chatId: string, members: string[]): Promise {
+ const payload = MembershipUpdateMessage.create(chatId, this.identity);
+ const chat = this.chats[chatId];
+ if (chat && payload) {
+ const newMembers = members.filter(
+ (member) => !chat.members.includes(member)
+ );
+ payload.addMembersAddedEvent(newMembers);
+ await this.sendUpdateMessage(payload.encode(), [
+ ...chat.members,
+ ...newMembers,
+ ]);
+ }
+ }
+
/**
* Sends a create group chat membership update message with given members
*