diff --git a/packages/react-chat/src/components/Channels/Channel.tsx b/packages/react-chat/src/components/Channels/Channel.tsx index 8b849bc1..09b6ae53 100644 --- a/packages/react-chat/src/components/Channels/Channel.tsx +++ b/packages/react-chat/src/components/Channels/Channel.tsx @@ -1,6 +1,7 @@ import React from "react"; import styled from "styled-components"; +import { useMessengerContext } from "../../contexts/messengerProvider"; import { useNarrow } from "../../contexts/narrowProvider"; import { ChannelData } from "../../models/ChannelData"; import { GroupIcon } from "../Icons/GroupIcon"; @@ -14,12 +15,13 @@ function RenderChannelName({ channel: ChannelData; className?: string; }) { + const { activeChannel } = useMessengerContext(); switch (channel.type) { case "group": return (
- - {channel.name} + + {` ${channel.name}`}
); case "channel": @@ -77,7 +79,7 @@ export function Channel({ @@ -89,7 +91,7 @@ export function Channel({ {!activeView && !!mention && mention > 0 && !channel?.isMuted && ( {mention} )} - {channel?.isMuted && } + {channel?.isMuted && !activeView && } ); } @@ -101,6 +103,7 @@ const ChannelWrapper = styled.div<{ isNarrow?: boolean }>` padding: 8px; cursor: pointer; width: ${({ isNarrow }) => (isNarrow ? "calc(100% - 162px)" : "100%")}; + &.active { background-color: ${({ theme }) => theme.activeChannelBackground}; border-radius: 8px; @@ -136,7 +139,7 @@ export const ChannelLogo = styled.div<{ icon?: string }>` background-color: ${({ theme }) => theme.iconColor}; background-size: cover; background-repeat: no-repeat; - backgroundimage: ${({ icon }) => icon && `url(${icon}`}; + background-image: ${({ icon }) => icon && `url(${icon}`}; color: ${({ theme }) => theme.iconTextColor}; &.active { diff --git a/packages/react-chat/src/components/Channels/EmptyChannel.tsx b/packages/react-chat/src/components/Channels/EmptyChannel.tsx index 873a984c..9c966b53 100644 --- a/packages/react-chat/src/components/Channels/EmptyChannel.tsx +++ b/packages/react-chat/src/components/Channels/EmptyChannel.tsx @@ -1,6 +1,8 @@ import React from "react"; +import { utils } from "status-communities/dist/cjs"; import styled from "styled-components"; +import { useIdentity } from "../../contexts/identityProvider"; import { ChannelData } from "../../models/ChannelData"; import { textMediumStyles } from "../Text"; @@ -12,6 +14,7 @@ type EmptyChannelProps = { export function EmptyChannel({ channel }: EmptyChannelProps) { const groupName = channel.name.split(", "); + const identity = useIdentity(); return ( @@ -31,7 +34,7 @@ export function EmptyChannel({ channel }: EmptyChannelProps) { ) : channel.type === "group" ? ( - You created a group with{" "} + {utils.bufToHex(identity.publicKey)} created a group with{" "} {groupName.slice(groupName.length - 1)} and{" "} {groupName.at(-1)} @@ -88,5 +91,7 @@ const EmptyText = styled.p` `; const EmptyTextGroup = styled(EmptyText)` - word-break: break-all; + & > span { + word-break: break-all; + } `; diff --git a/packages/react-chat/src/components/Chat/ChatCreation.tsx b/packages/react-chat/src/components/Chat/ChatCreation.tsx index ccb9e9cc..4a1e3160 100644 --- a/packages/react-chat/src/components/Chat/ChatCreation.tsx +++ b/packages/react-chat/src/components/Chat/ChatCreation.tsx @@ -45,6 +45,7 @@ export function ChatCreation({ editGroup }: ChatCreationProps) { id: group.join(""), name: group.join(", "), type: "group", + description: `${group.length + 1} members`, }) : setChannel({ id: group[0], diff --git a/packages/react-chat/src/components/Chat/ChatMessageContent.tsx b/packages/react-chat/src/components/Chat/ChatMessageContent.tsx index d5b2258e..7f062065 100644 --- a/packages/react-chat/src/components/Chat/ChatMessageContent.tsx +++ b/packages/react-chat/src/components/Chat/ChatMessageContent.tsx @@ -124,11 +124,11 @@ const MessageImage = styled.img` height: 100%; object-fit: cover; border-radius: 16px; - cursor; pointer; + cursor: pointer; `; const PreviewSiteNameWrapper = styled.div` - font-family: Inter; + font-family: "Inter"; font-style: normal; font-weight: normal; font-size: 12px; diff --git a/packages/react-chat/src/components/CommunityIdentity.tsx b/packages/react-chat/src/components/CommunityIdentity.tsx index 30aa2dca..445eeb84 100644 --- a/packages/react-chat/src/components/CommunityIdentity.tsx +++ b/packages/react-chat/src/components/CommunityIdentity.tsx @@ -70,6 +70,7 @@ const Name = styled.p` font-weight: 500; text-align: left; color: ${({ theme }) => theme.primary}; + white-space: nowrap; ${textMediumStyles} `; diff --git a/packages/react-chat/src/components/Form/ChannelMenu.tsx b/packages/react-chat/src/components/Form/ChannelMenu.tsx index e6c2cad5..2593d4bb 100644 --- a/packages/react-chat/src/components/Form/ChannelMenu.tsx +++ b/packages/react-chat/src/components/Form/ChannelMenu.tsx @@ -31,8 +31,9 @@ export const ChannelMenu = ({ const narrow = useNarrow(); const { clearNotifications, removeChannel } = useMessengerContext(); const { setModal } = useModal(EditModalName); + return ( - + {narrow && ( { @@ -63,12 +64,15 @@ export const ChannelMenu = ({ )} { - channel.isMuted = true; + channel.isMuted = !channel.isMuted; setShowChannelMenu(false); }} > - Mute Chat + + {(channel.isMuted ? "Unmute" : "Mute") + + (channel.type === "group" ? " Group" : " Chat")} + clearNotifications(channel.id)}> diff --git a/packages/react-chat/src/components/Form/ContactMenu.tsx b/packages/react-chat/src/components/Form/ContactMenu.tsx index 3dca75e5..51381445 100644 --- a/packages/react-chat/src/components/Form/ContactMenu.tsx +++ b/packages/react-chat/src/components/Form/ContactMenu.tsx @@ -37,7 +37,7 @@ export function ContactMenu({ id, setShowMenu }: ContactMenuProps) { if (!contact) return null; return ( - + diff --git a/packages/react-chat/src/components/Form/DropdownMenu.tsx b/packages/react-chat/src/components/Form/DropdownMenu.tsx index c1b02ecc..aae50c4e 100644 --- a/packages/react-chat/src/components/Form/DropdownMenu.tsx +++ b/packages/react-chat/src/components/Form/DropdownMenu.tsx @@ -1,16 +1,25 @@ -import React, { ReactNode } from "react"; +import React, { ReactNode, useRef } from "react"; import styled from "styled-components"; +import { useClickOutside } from "../../hooks/useClickOutside"; import { textSmallStyles } from "../Text"; type DropdownMenuProps = { children: ReactNode; className?: string; + closeMenu: (val: boolean) => void; }; -export function DropdownMenu({ children, className }: DropdownMenuProps) { +export function DropdownMenu({ + children, + className, + closeMenu, +}: DropdownMenuProps) { + const ref = useRef(null); + useClickOutside(ref, () => closeMenu(false)); + return ( - + {children} ); diff --git a/packages/react-chat/src/components/Form/ImageMenu.tsx b/packages/react-chat/src/components/Form/ImageMenu.tsx index e50a8c65..5879edaf 100644 --- a/packages/react-chat/src/components/Form/ImageMenu.tsx +++ b/packages/react-chat/src/components/Form/ImageMenu.tsx @@ -14,10 +14,10 @@ interface ImageMenuProps { } export const ImageMenu = ({ imageId }: ImageMenuProps) => { - const { showMenu } = useContextMenu(imageId); + const { showMenu, setShowMenu } = useContextMenu(imageId); return showMenu ? ( - + copyImg(imageId)}> Copy image diff --git a/packages/react-chat/src/components/Icons/GroupIcon.tsx b/packages/react-chat/src/components/Icons/GroupIcon.tsx index e54312c2..c11f793e 100644 --- a/packages/react-chat/src/components/Icons/GroupIcon.tsx +++ b/packages/react-chat/src/components/Icons/GroupIcon.tsx @@ -1,7 +1,11 @@ import React from "react"; import styled from "styled-components"; -export const GroupIcon = () => { +interface GroupIconProps { + activeView?: boolean; +} + +export const GroupIcon = ({ activeView }: GroupIconProps) => { return ( { viewBox="0 0 14 10" fill="none" xmlns="http://www.w3.org/2000/svg" + className={`${activeView && "active"}`} > @@ -19,7 +24,9 @@ export const GroupIcon = () => { }; const Icon = styled.svg` - & > path { - fill: ${({ theme }) => theme.secondary}; + fill: ${({ theme }) => theme.secondary}; + + &.active { + fill: ${({ theme }) => theme.primary}; } `; diff --git a/packages/react-chat/src/components/Members/Member.tsx b/packages/react-chat/src/components/Members/Member.tsx index 0e69c37f..222848ed 100644 --- a/packages/react-chat/src/components/Members/Member.tsx +++ b/packages/react-chat/src/components/Members/Member.tsx @@ -30,7 +30,7 @@ export function Member({ id: contact.id, name: contact.customName ?? contact.trueName, type: "dm", - description: "DM", + description: "Contact", members: [contact], }); }; diff --git a/packages/react-chat/src/components/Members/MembersList.tsx b/packages/react-chat/src/components/Members/MembersList.tsx index a4b9c867..289041b7 100644 --- a/packages/react-chat/src/components/Members/MembersList.tsx +++ b/packages/react-chat/src/components/Members/MembersList.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useMemo } from "react"; import { utils } from "status-communities/dist/cjs"; import { bufToHex } from "status-communities/dist/cjs/utils"; import styled from "styled-components"; @@ -16,6 +16,21 @@ interface MembersListProps { export function MembersList({ switchShowMembers }: MembersListProps) { const { contacts } = useMessengerContext(); const identity = useIdentity(); + const userContacts = useMemo( + () => + Object.values(contacts).filter( + (e) => e.id != bufToHex(identity.publicKey) + ), + [contacts, identity] + ); + const onlineContacts = useMemo( + () => userContacts.filter((e) => e.online), + [userContacts] + ); + const offlineContacts = useMemo( + () => userContacts.filter((e) => !e.online), + [userContacts] + ); return ( @@ -28,12 +43,10 @@ export function MembersList({ switchShowMembers }: MembersListProps) { {utils.bufToHex(identity.publicKey)} - - Online - {Object.values(contacts) - .filter((e) => e.id != bufToHex(identity.publicKey)) - .filter((e) => e.online) - .map((contact) => ( + {onlineContacts.length > 0 && ( + + Online + {onlineContacts.map((contact) => ( ))} - - - Offline - {Object.values(contacts) - .filter((e) => e.id != bufToHex(identity.publicKey)) - .filter((e) => !e.online) - .map((contact) => ( + + )} + {offlineContacts.length > 0 && ( + + Offline + {offlineContacts.map((contact) => ( ))} - + + )} ); } diff --git a/packages/react-chat/src/hooks/useClickOutside.ts b/packages/react-chat/src/hooks/useClickOutside.ts new file mode 100644 index 00000000..7a7d01b8 --- /dev/null +++ b/packages/react-chat/src/hooks/useClickOutside.ts @@ -0,0 +1,24 @@ +import { RefObject, useCallback, useEffect } from "react"; + +export const useClickOutside = ( + ref: RefObject, + callback: () => void, + deps?: any[] +) => { + const handleClick = useCallback( + (e: MouseEvent) => { + if (ref.current && !ref.current.contains(e.target as HTMLInputElement)) { + callback(); + } + }, + [ref, callback] + ); + + useEffect(() => { + document.addEventListener("mousedown", handleClick); + + return () => { + document.removeEventListener("mousedown", handleClick); + }; + }, deps); +}; diff --git a/packages/react-chat/src/hooks/useContextMenu.ts b/packages/react-chat/src/hooks/useContextMenu.ts index 45b47b44..3db1c6f9 100644 --- a/packages/react-chat/src/hooks/useContextMenu.ts +++ b/packages/react-chat/src/hooks/useContextMenu.ts @@ -28,5 +28,5 @@ export const useContextMenu = (elementId: string) => { }; }); - return { showMenu }; + return { showMenu, setShowMenu }; };