Add name and member handling in group chats (#144)
This commit is contained in:
parent
daabab46ed
commit
ff733a15fc
|
@ -76,7 +76,7 @@ function DragDiv() {
|
|||
<ReactChat
|
||||
theme={theme ? lightTheme : darkTheme}
|
||||
communityKey={
|
||||
"0x0235564b1b402e8f6ad540f4da0f6384fb828b8f7bb5a34942aa03719041b8b793"
|
||||
"0x02516353a03fc3892d268a72f4c4b2b0fad179702a996a87346407139949767ba7"
|
||||
}
|
||||
fetchMetadata={fetchMetadata}
|
||||
/>
|
||||
|
|
|
@ -56,7 +56,10 @@ export function ChatBody({ onClick, showMembers }: ChatBodyProps) {
|
|||
return (
|
||||
<ChatBodyWrapper className={className}>
|
||||
{editGroup && communityData ? (
|
||||
<ChatCreation editGroup={editGroup} />
|
||||
<ChatCreation
|
||||
setEditGroup={setEditGroup}
|
||||
activeChannel={activeChannel}
|
||||
/>
|
||||
) : (
|
||||
<ChatTopbar
|
||||
className={narrow && showState !== ChatBodyState.Chat ? "narrow" : ""}
|
||||
|
|
|
@ -5,20 +5,28 @@ import styled from "styled-components";
|
|||
import { ChatState, useChatState } from "../../contexts/chatStateProvider";
|
||||
import { useIdentity } from "../../contexts/identityProvider";
|
||||
import { useMessengerContext } from "../../contexts/messengerProvider";
|
||||
import { ChannelData } from "../../models/ChannelData";
|
||||
import { buttonStyles } from "../Buttons/buttonStyle";
|
||||
import { CrossIcon } from "../Icons/CrossIcon";
|
||||
import { Member } from "../Members/Member";
|
||||
import { SearchBlock } from "../SearchBlock";
|
||||
import { textMediumStyles } from "../Text";
|
||||
interface ChatCreationProps {
|
||||
editGroup?: boolean;
|
||||
setEditGroup?: (val: boolean) => 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<string[]>([]);
|
||||
const { contacts, createGroupChat } = useMessengerContext();
|
||||
const [styledGroup, setStyledGroup] = useState<string[]>(
|
||||
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) {
|
|||
</InputBar>
|
||||
<CreationBtn
|
||||
disabled={styledGroup.length === 0}
|
||||
onClick={() => createChat(styledGroup)}
|
||||
onClick={() => {
|
||||
if (!activeChannel) {
|
||||
createChat(styledGroup);
|
||||
} else {
|
||||
addMembers(styledGroup, activeChannel.id);
|
||||
}
|
||||
setEditGroup?.(false);
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</CreationBtn>
|
||||
</CreationBar>
|
||||
{!editGroup && !query && (
|
||||
{!setEditGroup && !query && (
|
||||
<Contacts>
|
||||
<ContactsHeading>Contacts</ContactsHeading>
|
||||
<ContactsList>
|
||||
|
|
|
@ -27,6 +27,7 @@ const MessengerContext = createContext<MessengerType>({
|
|||
setActiveChannel: () => undefined,
|
||||
createGroupChat: () => undefined,
|
||||
changeGroupChatName: () => undefined,
|
||||
addMembers: () => undefined,
|
||||
});
|
||||
|
||||
export function useMessengerContext() {
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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,8 +169,13 @@ export function useMessenger(
|
|||
});
|
||||
}, [contacts]);
|
||||
|
||||
const { groupChat, removeChannel, createGroupChat, changeGroupChatName } =
|
||||
useGroupChats(
|
||||
const {
|
||||
groupChat,
|
||||
removeChannel,
|
||||
createGroupChat,
|
||||
changeGroupChatName,
|
||||
addMembers,
|
||||
} = useGroupChats(
|
||||
messenger,
|
||||
identity,
|
||||
setChannels,
|
||||
|
@ -235,5 +241,6 @@ export function useMessenger(
|
|||
clearMentions,
|
||||
createGroupChat,
|
||||
changeGroupChatName,
|
||||
addMembers,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
) {
|
||||
if (chat) {
|
||||
chat.members = chat.members.filter(
|
||||
(member) => !event.event.members.includes(member)
|
||||
);
|
||||
if (event.event.members.includes(thisUser)) {
|
||||
await this.removeChat(
|
||||
{
|
||||
chatId: chatId,
|
||||
members: event.event.members,
|
||||
...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,20 +204,26 @@ export class GroupChats {
|
|||
}
|
||||
|
||||
private async addChat(chat: GroupChat, useCallback: boolean): Promise<void> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async removeChat(
|
||||
chat: GroupChat,
|
||||
useCallback: boolean
|
||||
): Promise<void> {
|
||||
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) => {
|
||||
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<void> {
|
||||
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
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue