Fix hook problems (#216)
This commit is contained in:
parent
030a33f95a
commit
bf7c15bc29
|
@ -30,7 +30,7 @@ export function ActivityCenter({
|
|||
activities.filter(
|
||||
(activity) => !contacts?.[activity.user]?.blocked ?? true
|
||||
),
|
||||
[contacts, activities, activities.length]
|
||||
[contacts, activities]
|
||||
);
|
||||
|
||||
const [hideRead, setHideRead] = useState(false);
|
||||
|
|
|
@ -3,9 +3,9 @@ import styled from "styled-components";
|
|||
|
||||
import { useMessengerContext } from "../../contexts/messengerProvider";
|
||||
import { useModal } from "../../contexts/modalProvider";
|
||||
import { useScrollToMessage } from "../../contexts/scrollProvider";
|
||||
import { ActivityAction } from "../../hooks/useActivities";
|
||||
import { useClickOutside } from "../../hooks/useClickOutside";
|
||||
import { useScrollToMessage } from "../../hooks/useScrollToMessage";
|
||||
import { Activity } from "../../models/Activity";
|
||||
import { equalDate } from "../../utils/equalDate";
|
||||
import { DownloadButton } from "../Buttons/DownloadButton";
|
||||
|
@ -169,7 +169,10 @@ export function ActivityMessage({
|
|||
<ActivityText>
|
||||
{"message" in activity && activity.message?.content && (
|
||||
<div
|
||||
onClick={() => scroll(activity.message, activity.channel.id)}
|
||||
onClick={() => {
|
||||
scroll(activity.message, activity.channel.id);
|
||||
setShowActivityCenter(false);
|
||||
}}
|
||||
>
|
||||
{elements.map((el) => el)}
|
||||
</div>
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { utils } from "@waku/status-communities/dist/cjs";
|
||||
import React, { useMemo } from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { useIdentity } from "../../contexts/identityProvider";
|
||||
import { useUserPublicKey } from "../../contexts/identityProvider";
|
||||
import { useMessengerContext } from "../../contexts/messengerProvider";
|
||||
import { useNarrow } from "../../contexts/narrowProvider";
|
||||
import { ChannelData } from "../../models/ChannelData";
|
||||
|
@ -16,17 +15,16 @@ type ChannelBeggingTextProps = {
|
|||
};
|
||||
|
||||
function ChannelBeggingText({ channel }: ChannelBeggingTextProps) {
|
||||
const identity = useIdentity();
|
||||
const userPK = useUserPublicKey();
|
||||
const { contacts } = useMessengerContext();
|
||||
const members = useMemo(() => {
|
||||
if (channel?.members && identity) {
|
||||
const publicKey = utils.bufToHex(identity.publicKey);
|
||||
if (channel?.members && userPK) {
|
||||
return channel.members
|
||||
.filter((contact) => contact.id !== publicKey)
|
||||
.filter((contact) => contact.id !== userPK)
|
||||
.map((member) => contacts?.[member.id] ?? member);
|
||||
}
|
||||
return [];
|
||||
}, [channel, contacts]);
|
||||
}, [channel, contacts, userPK]);
|
||||
|
||||
switch (channel.type) {
|
||||
case "dm":
|
||||
|
@ -40,8 +38,7 @@ function ChannelBeggingText({ channel }: ChannelBeggingTextProps) {
|
|||
case "group":
|
||||
return (
|
||||
<EmptyTextGroup>
|
||||
{identity && <span>{utils.bufToHex(identity.publicKey)}</span>}{" "}
|
||||
created a group with{" "}
|
||||
{userPK && <span>{userPK}</span>} created a group with{" "}
|
||||
{members.map((contact, idx) => (
|
||||
<span key={contact.id}>
|
||||
{contact?.customName ?? contact.trueName.slice(0, 10)}
|
||||
|
|
|
@ -116,19 +116,21 @@ export function ChatBody({
|
|||
activeChannel={activeChannel}
|
||||
/>
|
||||
) : (
|
||||
<ChatTopbar
|
||||
onClick={onClick}
|
||||
setEditGroup={setEditGroup}
|
||||
showMembers={showMembers}
|
||||
showState={showState}
|
||||
switchShowState={switchShowState}
|
||||
/>
|
||||
<>
|
||||
<ChatTopbar
|
||||
onClick={onClick}
|
||||
setEditGroup={setEditGroup}
|
||||
showMembers={showMembers}
|
||||
showState={showState}
|
||||
switchShowState={switchShowState}
|
||||
/>
|
||||
<ChatBodyContent
|
||||
showState={showState}
|
||||
switchShowState={switchShowState}
|
||||
channel={activeChannel}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<ChatBodyContent
|
||||
showState={showState}
|
||||
switchShowState={switchShowState}
|
||||
channel={activeChannel}
|
||||
/>
|
||||
</ChatBodyWrapper>
|
||||
{!permission && (
|
||||
<BluredWrapper>
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import { bufToHex } from "@waku/status-communities/dist/cjs/utils";
|
||||
import React, { useCallback, useState } from "react";
|
||||
import React, { useCallback, useMemo, useState } from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { ChatState, useChatState } from "../../contexts/chatStateProvider";
|
||||
import { useIdentity } from "../../contexts/identityProvider";
|
||||
import { useUserPublicKey } from "../../contexts/identityProvider";
|
||||
import { useMessengerContext } from "../../contexts/messengerProvider";
|
||||
import { useNarrow } from "../../contexts/narrowProvider";
|
||||
import { ChannelData } from "../../models/ChannelData";
|
||||
|
@ -27,19 +26,23 @@ export function ChatCreation({
|
|||
activeChannel,
|
||||
}: ChatCreationProps) {
|
||||
const narrow = useNarrow();
|
||||
const identity = useIdentity();
|
||||
const userPK = useUserPublicKey();
|
||||
const [query, setQuery] = useState("");
|
||||
const [styledGroup, setStyledGroup] = useState<string[]>(
|
||||
activeChannel?.members?.map(
|
||||
(member) => member?.customName ?? member.trueName
|
||||
) ?? []
|
||||
const [groupChatMembersIds, setGroupChatMembersIds] = useState<string[]>(
|
||||
activeChannel?.members?.map((member) => member.id) ?? []
|
||||
);
|
||||
const { contacts, createGroupChat, addMembers } = useMessengerContext();
|
||||
|
||||
const groupChatMembers = useMemo(
|
||||
() => groupChatMembersIds.map((id) => contacts[id]).filter((e) => !!e),
|
||||
[groupChatMembersIds, contacts]
|
||||
);
|
||||
|
||||
const setChatState = useChatState()[1];
|
||||
|
||||
const addMember = useCallback(
|
||||
(member: string) => {
|
||||
setStyledGroup((prevMembers: string[]) => {
|
||||
setGroupChatMembersIds((prevMembers: string[]) => {
|
||||
if (
|
||||
prevMembers.find((mem) => mem === member) ||
|
||||
prevMembers.length >= 5
|
||||
|
@ -50,33 +53,44 @@ export function ChatCreation({
|
|||
}
|
||||
});
|
||||
setQuery("");
|
||||
if (activeChannel) addMembers(styledGroup, activeChannel.id);
|
||||
},
|
||||
[setStyledGroup, styledGroup]
|
||||
[setGroupChatMembersIds]
|
||||
);
|
||||
const removeMember = useCallback(
|
||||
(member: string) => {
|
||||
setStyledGroup((prev) => prev.filter((e) => e != member));
|
||||
setGroupChatMembersIds((prev) => prev.filter((e) => e != member));
|
||||
},
|
||||
[setStyledGroup]
|
||||
[setGroupChatMembersIds]
|
||||
);
|
||||
|
||||
const createChat = useCallback(
|
||||
(group: string[]) => {
|
||||
if (identity) {
|
||||
if (userPK) {
|
||||
const newGroup = group.slice();
|
||||
newGroup.push(bufToHex(identity.publicKey));
|
||||
newGroup.push(userPK);
|
||||
createGroupChat(newGroup);
|
||||
setChatState(ChatState.ChatBody);
|
||||
}
|
||||
},
|
||||
[identity, createGroupChat]
|
||||
[userPK, createGroupChat, setChatState]
|
||||
);
|
||||
|
||||
const handleCreationClick = useCallback(() => {
|
||||
if (!activeChannel) {
|
||||
createChat(groupChatMembers.map((member) => member.id));
|
||||
} else {
|
||||
addMembers(
|
||||
groupChatMembers.map((member) => member.id),
|
||||
activeChannel.id
|
||||
);
|
||||
}
|
||||
setEditGroup?.(false);
|
||||
}, [activeChannel, groupChatMembers, createChat, addMembers, setEditGroup]);
|
||||
|
||||
return (
|
||||
<CreationWrapper className={`${narrow && "narrow"}`}>
|
||||
<CreationBar
|
||||
className={`${styledGroup.length === 5 && narrow && "limit"}`}
|
||||
className={`${groupChatMembers.length === 5 && narrow && "limit"}`}
|
||||
>
|
||||
{narrow && (
|
||||
<BackButton
|
||||
|
@ -88,16 +102,19 @@ export function ChatCreation({
|
|||
<InputBar>
|
||||
<InputText>To:</InputText>
|
||||
<StyledList>
|
||||
{styledGroup.map((member) => (
|
||||
<StyledMember key={member}>
|
||||
<StyledName>{member.slice(0, 10)}</StyledName>
|
||||
<CloseButton onClick={() => removeMember(member)}>
|
||||
{groupChatMembers.map((member) => (
|
||||
<StyledMember key={member.id}>
|
||||
<StyledName>
|
||||
{member?.customName?.slice(0, 10) ??
|
||||
member.trueName.slice(0, 10)}
|
||||
</StyledName>
|
||||
<CloseButton onClick={() => removeMember(member.id)}>
|
||||
<CrossIcon memberView={true} />
|
||||
</CloseButton>
|
||||
</StyledMember>
|
||||
))}
|
||||
</StyledList>
|
||||
{styledGroup.length < 5 && (
|
||||
{groupChatMembers.length < 5 && (
|
||||
<SearchMembers>
|
||||
<Input
|
||||
value={query}
|
||||
|
@ -105,31 +122,24 @@ export function ChatCreation({
|
|||
/>
|
||||
</SearchMembers>
|
||||
)}
|
||||
{!narrow && styledGroup.length === 5 && (
|
||||
{!narrow && groupChatMembers.length === 5 && (
|
||||
<LimitAlert>5 user Limit reached</LimitAlert>
|
||||
)}
|
||||
</InputBar>
|
||||
{narrow && styledGroup.length === 5 && (
|
||||
{narrow && groupChatMembers.length === 5 && (
|
||||
<LimitAlert className="narrow">5 user Limit reached</LimitAlert>
|
||||
)}
|
||||
</Column>
|
||||
<CreationBtn
|
||||
disabled={styledGroup.length === 0}
|
||||
onClick={() => {
|
||||
if (!activeChannel) {
|
||||
createChat(styledGroup);
|
||||
} else {
|
||||
addMembers(styledGroup, activeChannel.id);
|
||||
}
|
||||
setEditGroup?.(false);
|
||||
}}
|
||||
disabled={groupChatMembers.length === 0}
|
||||
onClick={handleCreationClick}
|
||||
>
|
||||
Confirm
|
||||
</CreationBtn>
|
||||
{!narrow && <ActivityButton className="creation" />}
|
||||
<SearchBlock
|
||||
query={query}
|
||||
discludeList={styledGroup}
|
||||
discludeList={groupChatMembersIds}
|
||||
onClick={addMember}
|
||||
/>
|
||||
</CreationBar>
|
||||
|
@ -137,13 +147,11 @@ export function ChatCreation({
|
|||
<Contacts>
|
||||
<ContactsHeading>Contacts</ContactsHeading>
|
||||
<ContactsList>
|
||||
{identity &&
|
||||
{userPK &&
|
||||
!query &&
|
||||
Object.values(contacts)
|
||||
.filter(
|
||||
(e) =>
|
||||
e.id != bufToHex(identity.publicKey) &&
|
||||
!styledGroup.includes(e.id)
|
||||
(e) => e.id != userPK && !groupChatMembersIds.includes(e.id)
|
||||
)
|
||||
.map((contact) => (
|
||||
<Member
|
||||
|
@ -157,7 +165,10 @@ export function ChatCreation({
|
|||
</Contacts>
|
||||
)}
|
||||
{!activeChannel && (
|
||||
<ChatInput createChat={createChat} group={styledGroup} />
|
||||
<ChatInput
|
||||
createChat={createChat}
|
||||
group={groupChatMembers.map((member) => member.id)}
|
||||
/>
|
||||
)}
|
||||
</CreationWrapper>
|
||||
);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { EmojiData } from "emoji-mart";
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
|
@ -72,16 +73,23 @@ export function ChatInput({
|
|||
[imageUint]
|
||||
);
|
||||
|
||||
const addEmoji = useCallback((e: any) => {
|
||||
const sym = e.unified.split("-");
|
||||
const codesArray: any[] = [];
|
||||
sym.forEach((el: string) => codesArray.push("0x" + el));
|
||||
const emoji = String.fromCodePoint(...codesArray);
|
||||
if (inputRef.current) {
|
||||
inputRef.current.appendChild(document.createTextNode(emoji));
|
||||
}
|
||||
setContent((p) => p + emoji);
|
||||
}, []);
|
||||
const addEmoji = useCallback(
|
||||
(e: EmojiData) => {
|
||||
if ("unified" in e) {
|
||||
const sym = e.unified.split("-");
|
||||
const codesArray: string[] = [];
|
||||
sym.forEach((el: string) => codesArray.push("0x" + el));
|
||||
const emoji = String.fromCodePoint(
|
||||
...(codesArray as unknown as number[])
|
||||
);
|
||||
if (inputRef.current) {
|
||||
inputRef.current.appendChild(document.createTextNode(emoji));
|
||||
}
|
||||
setContent((p) => p + emoji);
|
||||
}
|
||||
},
|
||||
[setContent]
|
||||
);
|
||||
|
||||
const resizeTextArea = useCallback((target: HTMLDivElement) => {
|
||||
target.style.height = "40px";
|
||||
|
@ -91,31 +99,37 @@ export function ChatInput({
|
|||
|
||||
const rowHeight = inputHeight + (image ? 73 : 0);
|
||||
|
||||
const onInputChange = useCallback((e: React.ChangeEvent<HTMLDivElement>) => {
|
||||
const element = document.getSelection();
|
||||
const inputElement = inputRef.current;
|
||||
if (inputElement && element && element.rangeCount > 0) {
|
||||
const selection = element?.getRangeAt(0)?.startOffset;
|
||||
const parentElement = element.anchorNode?.parentElement;
|
||||
if (parentElement && parentElement.tagName === "B") {
|
||||
parentElement.outerHTML = parentElement.innerText;
|
||||
const range = document.createRange();
|
||||
const sel = window.getSelection();
|
||||
if (element.anchorNode.firstChild) {
|
||||
const childNumber =
|
||||
element.focusOffset === 0 ? 0 : element.focusOffset - 1;
|
||||
range.setStart(element.anchorNode.childNodes[childNumber], selection);
|
||||
}
|
||||
range.collapse(true);
|
||||
const onInputChange = useCallback(
|
||||
(e: React.ChangeEvent<HTMLDivElement>) => {
|
||||
const element = document.getSelection();
|
||||
const inputElement = inputRef.current;
|
||||
if (inputElement && element && element.rangeCount > 0) {
|
||||
const selection = element?.getRangeAt(0)?.startOffset;
|
||||
const parentElement = element.anchorNode?.parentElement;
|
||||
if (parentElement && parentElement.tagName === "B") {
|
||||
parentElement.outerHTML = parentElement.innerText;
|
||||
const range = document.createRange();
|
||||
const sel = window.getSelection();
|
||||
if (element.anchorNode.firstChild) {
|
||||
const childNumber =
|
||||
element.focusOffset === 0 ? 0 : element.focusOffset - 1;
|
||||
range.setStart(
|
||||
element.anchorNode.childNodes[childNumber],
|
||||
selection
|
||||
);
|
||||
}
|
||||
range.collapse(true);
|
||||
|
||||
sel?.removeAllRanges();
|
||||
sel?.addRange(range);
|
||||
sel?.removeAllRanges();
|
||||
sel?.addRange(range);
|
||||
}
|
||||
}
|
||||
}
|
||||
const target = e.target;
|
||||
resizeTextArea(target);
|
||||
setContent(target.textContent ?? "");
|
||||
}, []);
|
||||
const target = e.target;
|
||||
resizeTextArea(target);
|
||||
setContent(target.textContent ?? "");
|
||||
},
|
||||
[resizeTextArea]
|
||||
);
|
||||
|
||||
const onInputKeyPress = useCallback(
|
||||
(e: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
|
@ -137,7 +151,16 @@ export function ChatInput({
|
|||
}
|
||||
}
|
||||
},
|
||||
[content, imageUint]
|
||||
[
|
||||
content,
|
||||
imageUint,
|
||||
createChat,
|
||||
group,
|
||||
sendMessage,
|
||||
reply?.id,
|
||||
setChatState,
|
||||
setReply,
|
||||
]
|
||||
);
|
||||
|
||||
const [selectedElement, setSelectedElement] = useState<{
|
||||
|
@ -176,7 +199,7 @@ export function ChatInput({
|
|||
}
|
||||
}, []);
|
||||
|
||||
useEffect(handleCursorChange, [content]);
|
||||
useEffect(handleCursorChange, [content, handleCursorChange]);
|
||||
|
||||
const addMention = useCallback(
|
||||
(contact: string) => {
|
||||
|
@ -215,7 +238,7 @@ export function ChatInput({
|
|||
}
|
||||
}
|
||||
},
|
||||
[inputRef, inputRef?.current, content, selectedElement]
|
||||
[inputRef, content, selectedElement, resizeTextArea]
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import { utils } from "@waku/status-communities/dist/cjs";
|
||||
import { decode } from "html-entities";
|
||||
import React, { useEffect, useMemo, useRef, useState } from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { useFetchMetadata } from "../../contexts/fetchMetadataProvider";
|
||||
import { useIdentity } from "../../contexts/identityProvider";
|
||||
import { useUserPublicKey } from "../../contexts/identityProvider";
|
||||
import { useMessengerContext } from "../../contexts/messengerProvider";
|
||||
import { useClickOutside } from "../../hooks/useClickOutside";
|
||||
import { ChatMessage } from "../../models/ChatMessage";
|
||||
|
@ -23,13 +22,13 @@ export function Mention({ id, setMentioned, className }: MentionProps) {
|
|||
const { contacts } = useMessengerContext();
|
||||
const contact = useMemo(() => contacts[id.slice(1)], [id, contacts]);
|
||||
const [showMenu, setShowMenu] = useState(false);
|
||||
const identity = useIdentity();
|
||||
const userPK = useUserPublicKey();
|
||||
|
||||
useEffect(() => {
|
||||
if (identity && contact) {
|
||||
if (contact.id === utils.bufToHex(identity.publicKey)) setMentioned(true);
|
||||
if (userPK && contact) {
|
||||
if (contact.id === userPK) setMentioned(true);
|
||||
}
|
||||
}, [contact, identity]);
|
||||
}, [contact, userPK, setMentioned]);
|
||||
|
||||
const ref = useRef(null);
|
||||
useClickOutside(ref, () => setShowMenu(false));
|
||||
|
@ -92,7 +91,7 @@ export function ChatMessageContent({
|
|||
newSplit.pop();
|
||||
setLink(link);
|
||||
setElements(newSplit);
|
||||
}, [content]);
|
||||
}, [content, setLink, setMentioned, setElements, setLinkOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
const updatePreview = async () => {
|
||||
|
@ -108,7 +107,7 @@ export function ChatMessageContent({
|
|||
}
|
||||
};
|
||||
updatePreview();
|
||||
}, [link]);
|
||||
}, [link, fetchMetadata]);
|
||||
|
||||
return (
|
||||
<ContentWrapper>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Picker } from "emoji-mart";
|
||||
import { EmojiData, Picker } from "emoji-mart";
|
||||
import React from "react";
|
||||
import { useTheme } from "styled-components";
|
||||
|
||||
|
@ -7,7 +7,7 @@ import { lightTheme, Theme } from "../../styles/themes";
|
|||
|
||||
type EmojiPickerProps = {
|
||||
showEmoji: boolean;
|
||||
addEmoji: (e: any) => void;
|
||||
addEmoji: (e: EmojiData) => void;
|
||||
bottom: number;
|
||||
};
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import { IdentityProvider } from "../contexts/identityProvider";
|
|||
import { MessengerProvider } from "../contexts/messengerProvider";
|
||||
import { ModalProvider } from "../contexts/modalProvider";
|
||||
import { NarrowProvider } from "../contexts/narrowProvider";
|
||||
import { ScrollProvider } from "../contexts/scrollProvider";
|
||||
import { ToastProvider } from "../contexts/toastProvider";
|
||||
import { Metadata } from "../models/Metadata";
|
||||
import { GlobalStyle } from "../styles/GlobalStyle";
|
||||
|
@ -43,8 +44,10 @@ export function CommunityChat({
|
|||
<IdentityProvider>
|
||||
<MessengerProvider communityKey={communityKey}>
|
||||
<ChatStateProvider>
|
||||
<CommunityChatRoom />
|
||||
<div id="modal-root" />
|
||||
<ScrollProvider>
|
||||
<CommunityChatRoom />
|
||||
<div id="modal-root" />
|
||||
</ScrollProvider>
|
||||
</ChatStateProvider>
|
||||
</MessengerProvider>
|
||||
</IdentityProvider>
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { bufToHex } from "@waku/status-communities/dist/cjs/utils";
|
||||
import React, { useMemo } from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { useIdentity } from "../../contexts/identityProvider";
|
||||
import { useUserPublicKey } from "../../contexts/identityProvider";
|
||||
import { useMessengerContext } from "../../contexts/messengerProvider";
|
||||
import { useModal } from "../../contexts/modalProvider";
|
||||
import { AddContactIcon } from "../Icons/AddContactIcon";
|
||||
|
@ -25,16 +24,16 @@ type ContactMenuProps = {
|
|||
};
|
||||
|
||||
export function ContactMenu({ id, setShowMenu }: ContactMenuProps) {
|
||||
const identity = useIdentity();
|
||||
const userPK = useUserPublicKey();
|
||||
const { contacts, contactsDispatch } = useMessengerContext();
|
||||
const contact = useMemo(() => contacts[id], [id, contacts]);
|
||||
const isUser = useMemo(() => {
|
||||
if (identity) {
|
||||
return id === bufToHex(identity.publicKey);
|
||||
if (userPK) {
|
||||
return id === userPK;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}, [id, identity]);
|
||||
}, [id, userPK]);
|
||||
|
||||
const { setModal } = useModal(ProfileModalName);
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import { utils } from "@waku/status-communities/dist/cjs";
|
||||
import { BaseEmoji } from "emoji-mart";
|
||||
import React, { useRef } from "react";
|
||||
import React, { useMemo, useRef } from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { useIdentity } from "../../contexts/identityProvider";
|
||||
import { useUserPublicKey } from "../../contexts/identityProvider";
|
||||
import { useMessengerContext } from "../../contexts/messengerProvider";
|
||||
import { useClickOutside } from "../../hooks/useClickOutside";
|
||||
import { useClickPosition } from "../../hooks/useClickPosition";
|
||||
|
@ -33,23 +32,27 @@ export const MessageMenu = ({
|
|||
setReply,
|
||||
messageRef,
|
||||
}: MessageMenuProps) => {
|
||||
const identity = useIdentity();
|
||||
const userPK = useUserPublicKey();
|
||||
const { activeChannel } = useMessengerContext();
|
||||
const { showMenu, setShowMenu } = useContextMenu(message.id);
|
||||
const { topPosition, leftPosition } = useClickPosition(messageRef);
|
||||
|
||||
const menuStyle = {
|
||||
top: topPosition,
|
||||
left: leftPosition,
|
||||
};
|
||||
const menuStyle = useMemo(() => {
|
||||
return {
|
||||
top: topPosition,
|
||||
left: leftPosition,
|
||||
};
|
||||
}, [topPosition, leftPosition]);
|
||||
|
||||
const ref = useRef(null);
|
||||
useClickOutside(ref, () => setShowMenu(false));
|
||||
|
||||
const userMessage =
|
||||
identity && message.sender === utils.bufToHex(identity.publicKey);
|
||||
const userMessage = useMemo(
|
||||
() => !!userPK && message.sender === userPK,
|
||||
[userPK, message]
|
||||
);
|
||||
|
||||
return identity && showMenu ? (
|
||||
return userPK && showMenu ? (
|
||||
<div ref={ref} id={"messageDropdown"}>
|
||||
<MessageDropdown style={menuStyle}>
|
||||
<MenuItem className="picker">
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { bufToHex } from "@waku/status-communities/dist/cjs/utils";
|
||||
import React, { useMemo } from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { useIdentity } from "../../contexts/identityProvider";
|
||||
import { useUserPublicKey } from "../../contexts/identityProvider";
|
||||
import { useMessengerContext } from "../../contexts/messengerProvider";
|
||||
import { useModal } from "../../contexts/modalProvider";
|
||||
import { Contact } from "../../models/Contact";
|
||||
|
@ -14,16 +13,12 @@ import { Member } from "./Member";
|
|||
|
||||
export function MembersList() {
|
||||
const { contacts, nickname, activeChannel } = useMessengerContext();
|
||||
const identity = useIdentity();
|
||||
const userPK = useMemo(
|
||||
() => (identity ? bufToHex(identity?.publicKey) : undefined),
|
||||
[identity]
|
||||
);
|
||||
const userPK = useUserPublicKey();
|
||||
const { setModal } = useModal(LogoutModalName);
|
||||
|
||||
const members = useMemo(() => {
|
||||
const contactsArray = Object.values(contacts);
|
||||
if (identity) {
|
||||
if (userPK) {
|
||||
if (
|
||||
activeChannel &&
|
||||
activeChannel.type === "group" &&
|
||||
|
@ -40,7 +35,7 @@ export function MembersList() {
|
|||
return contactsArray.filter((e) => e.id !== userPK);
|
||||
}
|
||||
return contactsArray;
|
||||
}, [activeChannel, contacts, identity, userPK]);
|
||||
}, [activeChannel, contacts, userPK]);
|
||||
|
||||
const onlineContacts = useMemo(
|
||||
() => members.filter((e) => e.online),
|
||||
|
@ -53,15 +48,15 @@ export function MembersList() {
|
|||
|
||||
return (
|
||||
<MembersListWrap>
|
||||
{identity && (
|
||||
{userPK && (
|
||||
<MemberCategory>
|
||||
<MemberCategoryName>You</MemberCategoryName>
|
||||
<Row>
|
||||
<Member
|
||||
contact={{
|
||||
id: userPK ?? "",
|
||||
id: userPK,
|
||||
customName: nickname,
|
||||
trueName: userPK ?? "",
|
||||
trueName: userPK,
|
||||
}}
|
||||
isYou={true}
|
||||
/>
|
||||
|
|
|
@ -45,7 +45,7 @@ export function UserLogo({
|
|||
return "offline";
|
||||
}
|
||||
return "";
|
||||
}, [contact]);
|
||||
}, [contact, showOnlineStatus]);
|
||||
|
||||
return (
|
||||
<Wrapper radius={radius} conicGradient={conicGradient}>
|
||||
|
|
|
@ -2,7 +2,7 @@ import React from "react";
|
|||
import styled from "styled-components";
|
||||
|
||||
import { useMessengerContext } from "../../contexts/messengerProvider";
|
||||
import { useScrollToMessage } from "../../hooks/useScrollToMessage";
|
||||
import { useScrollToMessage } from "../../contexts/scrollProvider";
|
||||
import { ChatMessage } from "../../models/ChatMessage";
|
||||
import { ReplyOn, ReplyTo } from "../Chat/ChatInput";
|
||||
import { QuoteSvg } from "../Icons/QuoteIcon";
|
||||
|
|
|
@ -30,7 +30,7 @@ export function MessagesList({ setReply, channel }: MessagesListProps) {
|
|||
messages.filter(
|
||||
(message) => !contacts?.[message.sender]?.blocked ?? true
|
||||
),
|
||||
[contacts, messages, messages.length]
|
||||
[contacts, messages]
|
||||
);
|
||||
|
||||
const [image, setImage] = useState("");
|
||||
|
@ -41,8 +41,14 @@ export function MessagesList({ setReply, channel }: MessagesListProps) {
|
|||
const { setModal: setLinkModal, isVisible: showLinkModal } =
|
||||
useModal(LinkModalName);
|
||||
|
||||
useEffect(() => (!image ? undefined : setPictureModal(true)), [image]);
|
||||
useEffect(() => (!link ? undefined : setLinkModal(true)), [link]);
|
||||
useEffect(
|
||||
() => (!image ? undefined : setPictureModal(true)),
|
||||
[image, setPictureModal]
|
||||
);
|
||||
useEffect(
|
||||
() => (!link ? undefined : setLinkModal(true)),
|
||||
[link, setLinkModal]
|
||||
);
|
||||
|
||||
useEffect(
|
||||
() => (!showPictureModal ? setImage("") : undefined),
|
||||
|
|
|
@ -27,9 +27,9 @@ export const EditModal = () => {
|
|||
const [groupName, setGroupName] = useState("");
|
||||
const [image, setImage] = useState("");
|
||||
|
||||
const handleChange = (e: any) => {
|
||||
if (e.target.files.length) {
|
||||
setImage(URL.createObjectURL(e.target.files[0]));
|
||||
const handleChange = (e: React.FormEvent<HTMLInputElement>) => {
|
||||
if (e.currentTarget?.files?.length) {
|
||||
setImage(URL.createObjectURL(e.currentTarget.files[0]));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import { utils } from "@waku/status-communities/dist/cjs";
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import {
|
||||
useIdentity,
|
||||
useSetIdentity,
|
||||
useSetNikcname,
|
||||
useUserPublicKey,
|
||||
} from "../../contexts/identityProvider";
|
||||
import { useMessengerContext } from "../../contexts/messengerProvider";
|
||||
import { useModal } from "../../contexts/modalProvider";
|
||||
|
@ -28,10 +27,10 @@ export const LogoutModal = () => {
|
|||
const { setModal } = useModal(LogoutModalName);
|
||||
const logout = useSetIdentity();
|
||||
const setNickname = useSetNikcname();
|
||||
const identity = useIdentity();
|
||||
const userPK = useUserPublicKey();
|
||||
const { nickname } = useMessengerContext();
|
||||
|
||||
if (identity) {
|
||||
if (userPK) {
|
||||
return (
|
||||
<Modal name={LogoutModalName}>
|
||||
<Section>
|
||||
|
@ -42,9 +41,9 @@ export const LogoutModal = () => {
|
|||
<UserSection>
|
||||
<UserLogo
|
||||
contact={{
|
||||
id: utils.bufToHex(identity.publicKey),
|
||||
id: userPK,
|
||||
customName: nickname,
|
||||
trueName: utils.bufToHex(identity.publicKey),
|
||||
trueName: userPK,
|
||||
}}
|
||||
radius={80}
|
||||
colorWheel={[
|
||||
|
@ -61,8 +60,8 @@ export const LogoutModal = () => {
|
|||
<UserAddressWrapper className="small">
|
||||
<UserAddress className="small">
|
||||
{" "}
|
||||
Chatkey: {identity.privateKey.slice(0, 10)}...
|
||||
{identity.privateKey.slice(-3)}{" "}
|
||||
Chatkey: {userPK.slice(0, 10)}...
|
||||
{userPK.slice(-3)}{" "}
|
||||
</UserAddress>
|
||||
</UserAddressWrapper>
|
||||
<EmojiKey className="small">🎩🍞🥑🦍🌈📡💅🏻♣️🔔⛸👵🅱</EmojiKey>
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { bufToHex } from "@waku/status-communities/dist/cjs/utils";
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { useIdentity } from "../../contexts/identityProvider";
|
||||
import { useUserPublicKey } from "../../contexts/identityProvider";
|
||||
import { useMessengerContext } from "../../contexts/messengerProvider";
|
||||
import { useModal } from "../../contexts/modalProvider";
|
||||
import { useToasts } from "../../contexts/toastProvider";
|
||||
|
@ -51,14 +50,14 @@ export const ProfileModal = () => {
|
|||
const { setToasts } = useToasts();
|
||||
const { setModal } = useModal(ProfileModalName);
|
||||
|
||||
const identity = useIdentity();
|
||||
const userPK = useUserPublicKey();
|
||||
const isUser = useMemo(() => {
|
||||
if (identity) {
|
||||
return id === bufToHex(identity.publicKey);
|
||||
if (userPK) {
|
||||
return id === userPK;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}, [id, identity]);
|
||||
}, [id, userPK]);
|
||||
|
||||
const [renaming, setRenaming] = useState(renamingState ?? false);
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@ import React, { useState } from "react";
|
|||
import styled from "styled-components";
|
||||
|
||||
import {
|
||||
useIdentity,
|
||||
useSetIdentity,
|
||||
useSetNikcname,
|
||||
useUserPublicKey,
|
||||
useWalletIdentity,
|
||||
} from "../../contexts/identityProvider";
|
||||
import { useModal } from "../../contexts/modalProvider";
|
||||
|
@ -38,7 +38,7 @@ export const UserCreationModalName = "UserCreationModal";
|
|||
|
||||
export function UserCreationModal() {
|
||||
const walletIdentity = useWalletIdentity();
|
||||
const identity = useIdentity();
|
||||
const userPK = useUserPublicKey();
|
||||
const setIdentity = useSetIdentity();
|
||||
const setNickname = useSetNikcname();
|
||||
|
||||
|
@ -107,12 +107,12 @@ export function UserCreationModal() {
|
|||
|
||||
<NameError error={error} />
|
||||
|
||||
{nextStep && identity && (
|
||||
{nextStep && userPK && (
|
||||
<>
|
||||
<UserAddress>
|
||||
{" "}
|
||||
Chatkey: {identity.privateKey.slice(0, 10)}...
|
||||
{identity.privateKey.slice(-3)}{" "}
|
||||
Chatkey: {userPK.slice(0, 10)}...
|
||||
{userPK.slice(-3)}{" "}
|
||||
</UserAddress>
|
||||
<ChainIcons>
|
||||
<ChainIcon className="transformed" />
|
||||
|
|
|
@ -26,7 +26,7 @@ export function WalletModal() {
|
|||
const { setModal } = useModal(WalletModalName);
|
||||
const setIdentity = useSetIdentity();
|
||||
const setWalletIdentity = useSetWalletIdentity();
|
||||
const userCreationModal = useModal(UserCreationModalName);
|
||||
const { setModal: setUserCreationModal } = useModal(UserCreationModalName);
|
||||
const { setModal: setWalleConnectModal } = useModal(WalletConnectModalName);
|
||||
const { setModal: setCoinbaseModal } = useModal(CoinbaseModalName);
|
||||
const { messenger } = useMessengerContext();
|
||||
|
@ -92,7 +92,7 @@ export function WalletModal() {
|
|||
setIdentity(loadedIdentity);
|
||||
} else {
|
||||
setWalletIdentity(loadedIdentity);
|
||||
userCreationModal.setModal(true);
|
||||
setUserCreationModal(true);
|
||||
}
|
||||
setModal(false);
|
||||
return;
|
||||
|
@ -102,7 +102,14 @@ export function WalletModal() {
|
|||
}
|
||||
}
|
||||
alert("Metamask not found");
|
||||
}, [messenger]);
|
||||
}, [
|
||||
messenger,
|
||||
dappUrl,
|
||||
setIdentity,
|
||||
setModal,
|
||||
setWalletIdentity,
|
||||
setUserCreationModal,
|
||||
]);
|
||||
|
||||
return (
|
||||
<Modal name={WalletModalName}>
|
||||
|
|
|
@ -36,7 +36,7 @@ export function ReactionPicker({
|
|||
? setMessageReactions((prev) => prev.filter((e) => e != emoji))
|
||||
: setMessageReactions((prev) => [...prev, emoji]);
|
||||
},
|
||||
[messageReactions]
|
||||
[messageReactions, setMessageReactions]
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import { utils } from "@waku/status-communities/dist/cjs";
|
||||
import { BaseEmoji } from "emoji-mart";
|
||||
import React from "react";
|
||||
import React, { useMemo } from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { useIdentity } from "../../contexts/identityProvider";
|
||||
import { useUserPublicKey } from "../../contexts/identityProvider";
|
||||
import { useMessengerContext } from "../../contexts/messengerProvider";
|
||||
import { Reply } from "../../hooks/useReply";
|
||||
import { ChatMessage } from "../../models/ChatMessage";
|
||||
|
@ -28,11 +27,13 @@ export function Reactions({
|
|||
messageReactions,
|
||||
setMessageReactions,
|
||||
}: ReactionsProps) {
|
||||
const identity = useIdentity();
|
||||
const userPK = useUserPublicKey();
|
||||
const { activeChannel } = useMessengerContext();
|
||||
|
||||
const userMessage =
|
||||
identity && message.sender === utils.bufToHex(identity.publicKey);
|
||||
const userMessage = useMemo(
|
||||
() => !!userPK && message.sender === userPK,
|
||||
[userPK, message]
|
||||
);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useMemo } from "react";
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { useToasts } from "../../contexts/toastProvider";
|
||||
|
@ -8,11 +8,9 @@ import { ToastMessage } from "./ToastMessage";
|
|||
export function ToastMessageList() {
|
||||
const { toasts } = useToasts();
|
||||
|
||||
const shownToasts = useMemo(() => toasts, [toasts, toasts.length]);
|
||||
|
||||
return (
|
||||
<ToastsWrapper>
|
||||
{shownToasts.map((toast) => (
|
||||
{toasts.map((toast) => (
|
||||
<ToastMessage key={toast.id} toast={toast} />
|
||||
))}
|
||||
</ToastsWrapper>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import { Identity } from "@waku/status-communities/dist/cjs";
|
||||
import React, { createContext, useContext, useState } from "react";
|
||||
import { bufToHex } from "@waku/status-communities/dist/cjs/utils";
|
||||
import React, { createContext, useContext, useMemo, useState } from "react";
|
||||
|
||||
const IdentityContext = createContext<{
|
||||
identity: Identity | undefined;
|
||||
setIdentity: React.Dispatch<React.SetStateAction<Identity | undefined>>;
|
||||
publicKey: string | undefined;
|
||||
walletIdentity: Identity | undefined;
|
||||
setWalletIdentity: React.Dispatch<React.SetStateAction<Identity | undefined>>;
|
||||
nickname: string | undefined;
|
||||
|
@ -11,6 +13,7 @@ const IdentityContext = createContext<{
|
|||
}>({
|
||||
identity: undefined,
|
||||
setIdentity: () => undefined,
|
||||
publicKey: undefined,
|
||||
walletIdentity: undefined,
|
||||
setWalletIdentity: () => undefined,
|
||||
nickname: undefined,
|
||||
|
@ -21,6 +24,10 @@ export function useIdentity() {
|
|||
return useContext(IdentityContext).identity;
|
||||
}
|
||||
|
||||
export function useUserPublicKey() {
|
||||
return useContext(IdentityContext).publicKey;
|
||||
}
|
||||
|
||||
export function useSetIdentity() {
|
||||
return useContext(IdentityContext).setIdentity;
|
||||
}
|
||||
|
@ -47,6 +54,10 @@ interface IdentityProviderProps {
|
|||
|
||||
export function IdentityProvider({ children }: IdentityProviderProps) {
|
||||
const [identity, setIdentity] = useState<Identity | undefined>(undefined);
|
||||
const publicKey = useMemo(
|
||||
() => (identity ? bufToHex(identity.publicKey) : undefined),
|
||||
[identity]
|
||||
);
|
||||
const [walletIdentity, setWalletIdentity] = useState<Identity | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
@ -57,6 +68,7 @@ export function IdentityProvider({ children }: IdentityProviderProps) {
|
|||
value={{
|
||||
identity,
|
||||
setIdentity,
|
||||
publicKey,
|
||||
nickname,
|
||||
setNickname,
|
||||
walletIdentity,
|
||||
|
|
|
@ -44,7 +44,7 @@ export function useModal<T extends string>(name: T) {
|
|||
};
|
||||
});
|
||||
},
|
||||
[name, modals]
|
||||
[name, setModals]
|
||||
);
|
||||
const isVisible = useMemo(() => !!modals?.[name], [modals, name]);
|
||||
|
||||
|
|
|
@ -1,9 +1,27 @@
|
|||
import { useCallback, useEffect, useState } from "react";
|
||||
import React, {
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useState,
|
||||
} from "react";
|
||||
|
||||
import { useMessengerContext } from "../contexts/messengerProvider";
|
||||
import { ChatMessage } from "../models/ChatMessage";
|
||||
|
||||
const ScrollContext = createContext<
|
||||
(msg: ChatMessage, channelId?: string) => void
|
||||
>(() => undefined);
|
||||
|
||||
export function useScrollToMessage() {
|
||||
return useContext(ScrollContext);
|
||||
}
|
||||
|
||||
interface ScrollProviderProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export function ScrollProvider({ children }: ScrollProviderProps) {
|
||||
const scrollToDivId = useCallback((id: string) => {
|
||||
const quoteDiv = document.getElementById(id);
|
||||
if (quoteDiv) {
|
||||
|
@ -35,17 +53,18 @@ export function useScrollToMessage() {
|
|||
setMessageChannel("");
|
||||
}
|
||||
}
|
||||
}, [activeChannel, scrollToMessage, messageChannel]);
|
||||
|
||||
const scroll = useCallback((msg: ChatMessage, channelId?: string) => {
|
||||
if (!channelId) {
|
||||
scrollToDivId(msg.id);
|
||||
} else {
|
||||
setMessageChannel(channelId);
|
||||
setScrollToMessage(msg.id);
|
||||
channelsDispatch({ type: "ChangeActive", payload: channelId });
|
||||
}
|
||||
}, []);
|
||||
|
||||
return scroll;
|
||||
}, [activeChannel, scrollToMessage, messageChannel, scrollToDivId]);
|
||||
const scroll = useCallback(
|
||||
(msg: ChatMessage, channelId?: string) => {
|
||||
if (!channelId || activeChannel?.id === channelId) {
|
||||
scrollToDivId(msg.id);
|
||||
} else {
|
||||
setMessageChannel(channelId);
|
||||
setScrollToMessage(msg.id);
|
||||
channelsDispatch({ type: "ChangeActive", payload: channelId });
|
||||
}
|
||||
},
|
||||
[scrollToDivId, channelsDispatch, activeChannel]
|
||||
);
|
||||
return <ScrollContext.Provider value={scroll} children={children} />;
|
||||
}
|
|
@ -101,7 +101,7 @@ export function useContacts(
|
|||
const [contacts, contactsDispatch] = useReducer(contactsReducer, {});
|
||||
|
||||
const contactsClass = useMemo(() => {
|
||||
if (messenger) {
|
||||
if (messenger && messenger.identity === identity) {
|
||||
const newContacts = new ContactsClass(
|
||||
identity,
|
||||
messenger.waku,
|
||||
|
@ -120,7 +120,7 @@ export function useContacts(
|
|||
);
|
||||
return newContacts;
|
||||
}
|
||||
}, [messenger, identity]);
|
||||
}, [messenger, identity, newNickname]);
|
||||
|
||||
return { contacts, contactsDispatch, contactsClass, nickname };
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ export function useGroupChats(
|
|||
handleMessage
|
||||
);
|
||||
}
|
||||
}, [messenger, identity, contactsClass]);
|
||||
}, [messenger, identity, contactsClass, addChatMessage, dispatch]);
|
||||
|
||||
const createGroupChat = useCallback(
|
||||
(members: string[]) => {
|
||||
|
|
|
@ -64,7 +64,7 @@ export function useLoadPrevDay(
|
|||
}
|
||||
}
|
||||
},
|
||||
[messenger]
|
||||
[messenger, groupChats]
|
||||
);
|
||||
return { loadingMessages, loadPrevDay };
|
||||
}
|
||||
|
|
|
@ -14,7 +14,9 @@ import { useNotifications } from "./useNotifications";
|
|||
export function useMessages(
|
||||
chatId: string,
|
||||
identity: Identity | undefined,
|
||||
subscriptions: ((msg: ChatMessage, id: string) => void)[],
|
||||
subscriptions: React.MutableRefObject<
|
||||
((msg: ChatMessage, id: string) => void)[]
|
||||
>,
|
||||
contacts?: Contacts
|
||||
) {
|
||||
const [messages, setMessages] = useState<{ [chatId: string]: ChatMessage[] }>(
|
||||
|
@ -23,18 +25,22 @@ export function useMessages(
|
|||
const { notifications, incNotification, clearNotifications } =
|
||||
useNotifications();
|
||||
|
||||
const mentions = useNotifications();
|
||||
const {
|
||||
notifications: mentions,
|
||||
incNotification: incMentions,
|
||||
clearNotifications: clearMentions,
|
||||
} = useNotifications();
|
||||
|
||||
const addChatMessage = useCallback(
|
||||
(newMessage: ChatMessage | undefined, id: string) => {
|
||||
if (newMessage) {
|
||||
contacts?.addContact(newMessage.sender);
|
||||
if (newMessage.responseTo) {
|
||||
newMessage.quote = messages[id].find(
|
||||
(msg) => msg.id === newMessage.responseTo
|
||||
);
|
||||
}
|
||||
setMessages((prev) => {
|
||||
if (newMessage.responseTo && prev[id]) {
|
||||
newMessage.quote = prev[id].find(
|
||||
(msg) => msg.id === newMessage.responseTo
|
||||
);
|
||||
}
|
||||
return {
|
||||
...prev,
|
||||
[id]: binarySetInsert(
|
||||
|
@ -45,17 +51,19 @@ export function useMessages(
|
|||
),
|
||||
};
|
||||
});
|
||||
subscriptions.forEach((subscription) => subscription(newMessage, id));
|
||||
subscriptions.current.forEach((subscription) =>
|
||||
subscription(newMessage, id)
|
||||
);
|
||||
incNotification(id);
|
||||
if (
|
||||
identity &&
|
||||
newMessage.content.includes(`@${bufToHex(identity.publicKey)}`)
|
||||
) {
|
||||
mentions.incNotification(id);
|
||||
incMentions(id);
|
||||
}
|
||||
}
|
||||
},
|
||||
[contacts, identity, subscriptions]
|
||||
[contacts, identity, subscriptions, incMentions, incNotification]
|
||||
);
|
||||
|
||||
const addMessage = useCallback(
|
||||
|
@ -63,21 +71,23 @@ export function useMessages(
|
|||
const newMessage = ChatMessage.fromMetadataMessage(msg, date);
|
||||
addChatMessage(newMessage, id);
|
||||
},
|
||||
[contacts, identity]
|
||||
[addChatMessage]
|
||||
);
|
||||
|
||||
const activeMessages = useMemo(
|
||||
() => messages?.[chatId] ?? [],
|
||||
[messages, chatId]
|
||||
);
|
||||
const activeMessages = useMemo(() => {
|
||||
if (messages?.[chatId]) {
|
||||
return [...messages[chatId]];
|
||||
}
|
||||
return [];
|
||||
}, [messages, chatId]);
|
||||
|
||||
return {
|
||||
messages: activeMessages,
|
||||
addMessage,
|
||||
notifications,
|
||||
clearNotifications,
|
||||
mentions: mentions.notifications,
|
||||
clearMentions: mentions.clearNotifications,
|
||||
mentions,
|
||||
clearMentions,
|
||||
addChatMessage,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,7 +6,14 @@ import {
|
|||
Identity,
|
||||
Messenger,
|
||||
} from "@waku/status-communities/dist/cjs";
|
||||
import { useCallback, useEffect, useMemo, useReducer, useState } from "react";
|
||||
import {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useReducer,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
|
||||
import { useConfig } from "../../contexts/configProvider";
|
||||
import { ChannelData, ChannelsData } from "../../models/ChannelData";
|
||||
|
@ -60,24 +67,33 @@ function useCreateMessenger(identity: Identity | undefined) {
|
|||
createMessenger(identity, environment).then((e) => {
|
||||
setMessenger(e);
|
||||
});
|
||||
}, [identity]);
|
||||
}, [identity, environment]);
|
||||
|
||||
return messenger;
|
||||
}
|
||||
|
||||
function useCreateCommunity(
|
||||
messenger: Messenger | undefined,
|
||||
identity: Identity | undefined,
|
||||
communityKey: string | undefined,
|
||||
addMessage: (msg: ApplicationMetadataMessage, id: string, date: Date) => void,
|
||||
contactsClass: ContactsClass | undefined
|
||||
) {
|
||||
const [community, setCommunity] = useState<Community | undefined>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
if (messenger && communityKey && contactsClass) {
|
||||
if (
|
||||
messenger &&
|
||||
communityKey &&
|
||||
contactsClass &&
|
||||
addMessage &&
|
||||
messenger.identity === identity
|
||||
) {
|
||||
createCommunity(communityKey, addMessage, messenger).then((comm) => {
|
||||
setCommunity(comm);
|
||||
});
|
||||
}
|
||||
}, [messenger, communityKey, addMessage, contactsClass]);
|
||||
}, [messenger, communityKey, addMessage, contactsClass, identity]);
|
||||
|
||||
const communityData = useMemo(() => {
|
||||
if (community?.description) {
|
||||
|
@ -101,7 +117,7 @@ function useCreateCommunity(
|
|||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}, [community]);
|
||||
}, [community, contactsClass]);
|
||||
|
||||
return { community, communityData };
|
||||
}
|
||||
|
@ -153,7 +169,11 @@ export function useMessenger(
|
|||
subscriptionReducer,
|
||||
{}
|
||||
);
|
||||
const subList = useMemo(() => Object.values(subscriptions), [subscriptions]);
|
||||
const subList = useRef<((msg: ChatMessage, id: string) => void)[]>([]);
|
||||
useEffect(() => {
|
||||
subList.current = Object.values(subscriptions);
|
||||
}, [subscriptions]);
|
||||
|
||||
const [channelsState, channelsDispatch] = useChannelsReducer();
|
||||
const messenger = useCreateMessenger(identity);
|
||||
const { contacts, contactsDispatch, contactsClass, nickname } = useContacts(
|
||||
|
@ -188,6 +208,7 @@ export function useMessenger(
|
|||
|
||||
const { community, communityData } = useCreateCommunity(
|
||||
messenger,
|
||||
identity,
|
||||
communityKey,
|
||||
addMessage,
|
||||
contactsClass
|
||||
|
@ -207,7 +228,7 @@ export function useMessenger(
|
|||
});
|
||||
}
|
||||
}
|
||||
}, [community]);
|
||||
}, [community, channelsDispatch]);
|
||||
|
||||
useEffect(() => {
|
||||
Object.values(channelsState.channels)
|
||||
|
@ -227,7 +248,7 @@ export function useMessenger(
|
|||
});
|
||||
}
|
||||
});
|
||||
}, [contacts, channelsState.channels]);
|
||||
}, [contacts, channelsState.channels, channelsDispatch]);
|
||||
|
||||
const {
|
||||
groupChat,
|
||||
|
@ -255,7 +276,7 @@ export function useMessenger(
|
|||
loadPrevDay(id)
|
||||
);
|
||||
}
|
||||
}, [messenger, community]);
|
||||
}, [messenger, community, loadPrevDay]);
|
||||
|
||||
const sendMessage = useCallback(
|
||||
async (messageText?: string, image?: Uint8Array, responseTo?: string) => {
|
||||
|
@ -299,7 +320,7 @@ export function useMessenger(
|
|||
clearMentions(channelsState.activeChannel.id);
|
||||
}
|
||||
}
|
||||
}, [notifications, channelsState]);
|
||||
}, [notifications, channelsState, clearNotifications, clearMentions]);
|
||||
|
||||
const loadingMessenger = useMemo(() => {
|
||||
return Boolean(
|
||||
|
@ -307,7 +328,7 @@ export function useMessenger(
|
|||
!messenger ||
|
||||
(communityKey && !channelsState.activeChannel.id)
|
||||
);
|
||||
}, [communityData, messenger, channelsState]);
|
||||
}, [communityData, messenger, channelsState, communityKey]);
|
||||
|
||||
return {
|
||||
messenger,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { bufToHex } from "@waku/status-communities/dist/cjs/utils";
|
||||
import { useEffect, useMemo, useReducer } from "react";
|
||||
|
||||
import { useIdentity } from "../contexts/identityProvider";
|
||||
import { useUserPublicKey } from "../contexts/identityProvider";
|
||||
import { useMessengerContext } from "../contexts/messengerProvider";
|
||||
import { Activities, Activity, ActivityStatus } from "../models/Activity";
|
||||
import { ChatMessage } from "../models/ChatMessage";
|
||||
|
@ -65,17 +64,13 @@ export function useActivities() {
|
|||
() => Object.values(activitiesObj),
|
||||
[activitiesObj]
|
||||
);
|
||||
const identity = useIdentity();
|
||||
const userPK = useMemo(
|
||||
() => (identity ? bufToHex(identity.publicKey) : undefined),
|
||||
[identity]
|
||||
);
|
||||
const userPK = useUserPublicKey();
|
||||
const { subscriptionsDispatch, channels } = useMessengerContext();
|
||||
|
||||
useEffect(() => {
|
||||
if (identity) {
|
||||
if (userPK) {
|
||||
const subscribeFunction = (message: ChatMessage, id: string) => {
|
||||
if (message.quote && identity && message.quote.sender === userPK) {
|
||||
if (message.quote && message.quote.sender === userPK) {
|
||||
const newActivity: Activity = {
|
||||
id: message.date.getTime().toString() + message.content,
|
||||
type: "reply",
|
||||
|
@ -114,7 +109,7 @@ export function useActivities() {
|
|||
type: "removeSubscription",
|
||||
payload: { name: "activityCenter" },
|
||||
});
|
||||
}, [subscriptionsDispatch, identity]);
|
||||
}, [subscriptionsDispatch, userPK, channels]);
|
||||
|
||||
return { activities, activityDispatch: dispatch };
|
||||
}
|
||||
|
|
|
@ -14,10 +14,10 @@ export function useChatScrollHandle(
|
|||
if (ref && ref.current && scrollOnBot) {
|
||||
ref.current.scrollTop = ref.current.scrollHeight;
|
||||
}
|
||||
}, [messages.length, scrollOnBot]);
|
||||
}, [messages.length, scrollOnBot, ref]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!loadingMessages && activeChannel) {
|
||||
if (activeChannel) {
|
||||
if (
|
||||
(ref?.current?.clientHeight ?? 0) >= (ref?.current?.scrollHeight ?? 0)
|
||||
) {
|
||||
|
@ -25,9 +25,10 @@ export function useChatScrollHandle(
|
|||
loadPrevDay(activeChannel.id, activeChannel.type !== "channel");
|
||||
}
|
||||
}
|
||||
}, [messages.length, activeChannel]);
|
||||
}, [messages.length, activeChannel, loadPrevDay, setScrollOnBot, ref]);
|
||||
|
||||
useEffect(() => {
|
||||
const currentRef = ref.current;
|
||||
const setScroll = () => {
|
||||
if (ref?.current && activeChannel) {
|
||||
if (ref.current.scrollTop <= 0) {
|
||||
|
@ -47,8 +48,8 @@ export function useChatScrollHandle(
|
|||
}
|
||||
}
|
||||
};
|
||||
ref.current?.addEventListener("scroll", setScroll);
|
||||
return () => ref.current?.removeEventListener("scroll", setScroll);
|
||||
}, [ref, scrollOnBot, activeChannel]);
|
||||
currentRef?.addEventListener("scroll", setScroll);
|
||||
return () => currentRef?.removeEventListener("scroll", setScroll);
|
||||
}, [ref, scrollOnBot, activeChannel, loadPrevDay]);
|
||||
return loadingMessages;
|
||||
}
|
||||
|
|
|
@ -2,8 +2,7 @@ import { RefObject, useCallback, useEffect } from "react";
|
|||
|
||||
export const useClickOutside = (
|
||||
ref: RefObject<HTMLDivElement>,
|
||||
callback: () => void,
|
||||
deps?: any[]
|
||||
callback: () => void
|
||||
) => {
|
||||
const handleClick = useCallback(
|
||||
(e: MouseEvent) => {
|
||||
|
@ -20,5 +19,5 @@ export const useClickOutside = (
|
|||
return () => {
|
||||
document.removeEventListener("mousedown", handleClick);
|
||||
};
|
||||
}, deps);
|
||||
}, [handleClick]);
|
||||
};
|
||||
|
|
|
@ -15,7 +15,7 @@ export const useClickPosition = (ref: RefObject<HTMLDivElement>) => {
|
|||
setTopPosition(imgTarget ? 0 : e.clientY - rect.top);
|
||||
}
|
||||
},
|
||||
[setTopPosition, setLeftPosition]
|
||||
[setTopPosition, setLeftPosition, ref]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -21,7 +21,7 @@ export const useContextMenu = (elementId: string) => {
|
|||
document.removeEventListener("click", () => setShowMenu(false));
|
||||
setShowMenu(false);
|
||||
};
|
||||
}, [elementId]);
|
||||
}, [elementId, handleContextMenu]);
|
||||
|
||||
return { showMenu, setShowMenu };
|
||||
};
|
||||
|
|
|
@ -12,9 +12,9 @@ export enum NameErrors {
|
|||
|
||||
export function useNameError(name: string) {
|
||||
const { contacts } = useMessengerContext();
|
||||
const RegName = new RegExp("^[a-z0-9_-]+$");
|
||||
|
||||
const error = useMemo(() => {
|
||||
const RegName = new RegExp("^[a-z0-9_-]+$");
|
||||
if (name === "") {
|
||||
return NameErrors.NoError;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ export function useRefBreak(dimension: number, sizeThreshold: number) {
|
|||
return () => {
|
||||
window.removeEventListener("resize", checkDimensions);
|
||||
};
|
||||
}, [dimension, widthBreak]);
|
||||
}, [dimension, widthBreak, sizeThreshold]);
|
||||
|
||||
return widthBreak;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue