diff --git a/packages/react-chat/src/components/Chat/ChatMessages.tsx b/packages/react-chat/src/components/Chat/ChatMessages.tsx
index b1579070..d82f64f2 100644
--- a/packages/react-chat/src/components/Chat/ChatMessages.tsx
+++ b/packages/react-chat/src/components/Chat/ChatMessages.tsx
@@ -1,9 +1,11 @@
import React, { useEffect, useMemo, useRef, useState } from "react";
import styled from "styled-components";
+import { useBlockedUsers } from "../../contexts/blockedUsersProvider";
import { useMessengerContext } from "../../contexts/messengerProvider";
import { ChatMessage } from "../../models/ChatMessage";
import { equalDate } from "../../utils";
+import { ContactMenu } from "../Form/ContactMenu";
import { LoadingIcon } from "../Icons/LoadingIcon";
import { UserIcon } from "../Icons/UserIcon";
import { LinkModal } from "../Modals/LinkModal";
@@ -12,6 +14,60 @@ import { textSmallStyles } from "../Text";
import { ChatMessageContent } from "./ChatMessageContent";
+const today = new Date();
+
+type ChatUiMessageProps = {
+ idx: number;
+ message: ChatMessage;
+ prevMessage: ChatMessage;
+ setImage: (img: string) => void;
+ setLink: (link: string) => void;
+};
+
+function ChatUiMessage({
+ message,
+ idx,
+ prevMessage,
+ setImage,
+ setLink,
+}: ChatUiMessageProps) {
+ const [showMenu, setShowMenu] = useState(false);
+
+ return (
+
+ {(idx === 0 || !equalDate(prevMessage.date, message.date)) && (
+
+ {equalDate(message.date, today)
+ ? "Today"
+ : message.date.toLocaleDateString()}
+
+ )}
+
+ setShowMenu((e) => !e)}>
+ {showMenu && (
+
+ )}
+
+
+
+
+
+ {message.sender.slice(0, 10)}
+ {message.date.toLocaleString()}
+
+
+
+
+
+
+
+ );
+}
+
type ChatMessagesProps = {
messages: ChatMessage[];
activeChannelId: string;
@@ -19,9 +75,10 @@ type ChatMessagesProps = {
export function ChatMessages({ messages, activeChannelId }: ChatMessagesProps) {
const { loadPrevDay, loadingMessages } = useMessengerContext();
+
const [scrollOnBot, setScrollOnBot] = useState(true);
const ref = useRef(null);
- const today = useMemo(() => new Date(), []);
+
useEffect(() => {
if (ref && ref.current && scrollOnBot) {
ref.current.scrollTop = ref.current.scrollHeight;
@@ -39,6 +96,12 @@ export function ChatMessages({ messages, activeChannelId }: ChatMessagesProps) {
}
}, [messages, messages.length, loadingMessages]);
+ const { blockedUsers } = useBlockedUsers();
+
+ const shownMessages = useMemo(() => {
+ return messages.filter((message) => !blockedUsers.includes(message.sender));
+ }, [messages, blockedUsers, messages.length]);
+
useEffect(() => {
const setScroll = () => {
if (ref && ref.current) {
@@ -76,39 +139,16 @@ export function ChatMessages({ messages, activeChannelId }: ChatMessagesProps) {
)}
- {messages.map((message, idx) => {
+ {shownMessages.map((message, idx) => {
return (
-
- {(idx === 0 ||
- !equalDate(messages[idx - 1].date, message.date)) && (
-
- {equalDate(message.date, today)
- ? "Today"
- : message.date.toLocaleDateString()}
-
- )}
-
-
-
-
-
-
-
-
- {message.sender.slice(0, 10)}
-
- {message.date.toLocaleString()}
-
-
-
-
-
-
-
+
);
})}
@@ -178,6 +218,7 @@ export const Icon = styled.div`
border-radius: 50%;
background-color: #bcbdff;
flex-shrink: 0;
+ position: relative;
`;
const UserNameWrapper = styled.div`
diff --git a/packages/react-chat/src/components/Form/ContactMenu.tsx b/packages/react-chat/src/components/Form/ContactMenu.tsx
new file mode 100644
index 00000000..90b604a4
--- /dev/null
+++ b/packages/react-chat/src/components/Form/ContactMenu.tsx
@@ -0,0 +1,38 @@
+import React, { useMemo } from "react";
+import styled from "styled-components";
+
+import { useBlockedUsers } from "../../contexts/blockedUsersProvider";
+
+import { DropdownMenu, MenuItem } from "./DropdownMenu";
+
+type ContactMenuProps = {
+ id: string;
+ setShowMenu: (val: boolean) => void;
+};
+
+export function ContactMenu({ id, setShowMenu }: ContactMenuProps) {
+ const { blockedUsers, setBlockedUsers } = useBlockedUsers();
+ const userInBlocked = useMemo(
+ () => blockedUsers.includes(id),
+ [blockedUsers, id]
+ );
+ return (
+
+
+
+ );
+}
+
+const ContactDropdown = styled(DropdownMenu)`
+ top: 20px;
+ left: 0px;
+`;
diff --git a/packages/react-chat/src/components/Members/Member.tsx b/packages/react-chat/src/components/Members/Member.tsx
index 08eae260..304b6c2b 100644
--- a/packages/react-chat/src/components/Members/Member.tsx
+++ b/packages/react-chat/src/components/Members/Member.tsx
@@ -1,8 +1,9 @@
-import React, { useCallback } from "react";
+import React, { useCallback, useState } from "react";
import styled from "styled-components";
import { useNarrow } from "../../contexts/narrowProvider";
import { Icon } from "../Chat/ChatMessages";
+import { ContactMenu } from "../Form/ContactMenu";
import { UserIcon } from "../Icons/UserIcon";
interface MemberProps {
@@ -38,6 +39,8 @@ export function Member({
setShowChannels(true);
};
+ const [showMenu, setShowMenu] = useState(false);
+
return (
{
@@ -49,7 +52,9 @@ export function Member({
backgroundImage: "unset",
}}
className={isOnline ? "online" : "offline"}
+ onClick={() => setShowMenu((e) => !e)}
>
+ {showMenu && }
{member}
diff --git a/packages/react-chat/src/components/ReactChat.tsx b/packages/react-chat/src/components/ReactChat.tsx
index d04d144d..81e406c3 100644
--- a/packages/react-chat/src/components/ReactChat.tsx
+++ b/packages/react-chat/src/components/ReactChat.tsx
@@ -2,6 +2,7 @@ import React, { useRef } from "react";
import { ThemeProvider } from "styled-components";
import styled from "styled-components";
+import { BlockedUsersProvider } from "../contexts/blockedUsersProvider";
import { FetchMetadataProvider } from "../contexts/fetchMetadataProvider";
import { NarrowProvider } from "../contexts/narrowProvider";
import { Metadata } from "../models/Metadata";
@@ -26,10 +27,12 @@ export function ReactChat({
-
-
-
-
+
+
+
+
+
+
diff --git a/packages/react-chat/src/contexts/blockedUsersProvider.tsx b/packages/react-chat/src/contexts/blockedUsersProvider.tsx
new file mode 100644
index 00000000..2250a27b
--- /dev/null
+++ b/packages/react-chat/src/contexts/blockedUsersProvider.tsx
@@ -0,0 +1,27 @@
+import React, { createContext, useContext, useState } from "react";
+
+const BlockedUsersContext = createContext<{
+ blockedUsers: string[];
+ setBlockedUsers: React.Dispatch>;
+}>({
+ blockedUsers: [],
+ setBlockedUsers: () => undefined,
+});
+
+export function useBlockedUsers() {
+ return useContext(BlockedUsersContext);
+}
+
+interface BlockedUsersProviderProps {
+ children: React.ReactNode;
+}
+
+export function BlockedUsersProvider({ children }: BlockedUsersProviderProps) {
+ const [blockedUsers, setBlockedUsers] = useState([]);
+ return (
+
+ );
+}