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