From 4852d90546a90946923c90ceb67ace2ab5a15985 Mon Sep 17 00:00:00 2001 From: Szymon Szlachtowicz <38212223+Szymx95@users.noreply.github.com> Date: Fri, 19 Nov 2021 09:31:49 +0100 Subject: [PATCH] Refactor channels and providers (#134) --- .../src/components/Channels/Channel.tsx | 132 +++++++++--------- .../src/components/Channels/Channels.tsx | 43 ++---- .../src/components/Channels/EmptyChannel.tsx | 10 +- packages/react-chat/src/components/Chat.tsx | 15 +- .../src/components/Chat/ChatBody.tsx | 13 +- .../src/components/Chat/ChatCreation.tsx | 7 +- .../react-chat/src/components/ChatLoader.tsx | 5 +- .../src/components/Form/ContactMenu.tsx | 15 +- .../src/components/Modals/EditModal.tsx | 10 +- .../src/components/Modals/ProfileModal.tsx | 26 ++-- .../components/NarrowMode/NarrowChannels.tsx | 11 +- .../react-chat/src/components/ReactChat.tsx | 17 +-- .../react-chat/src/components/SearchBlock.tsx | 12 +- .../src/contexts/chatStateProvider.tsx | 25 ++++ .../src/contexts/friendsProvider.tsx | 27 ---- .../src/contexts/messengerProvider.tsx | 1 + .../src/hooks/messenger/useMessenger.ts | 1 + .../react-chat/src/hooks/useManageContact.ts | 20 ++- packages/react-chat/src/models/ChannelData.ts | 2 +- packages/react-chat/src/models/Contact.ts | 1 + .../react-chat/src/styles/GlobalStyle.tsx | 1 - 21 files changed, 178 insertions(+), 216 deletions(-) create mode 100644 packages/react-chat/src/contexts/chatStateProvider.tsx delete mode 100644 packages/react-chat/src/contexts/friendsProvider.tsx diff --git a/packages/react-chat/src/components/Channels/Channel.tsx b/packages/react-chat/src/components/Channels/Channel.tsx index 59443e5..8b849bc 100644 --- a/packages/react-chat/src/components/Channels/Channel.tsx +++ b/packages/react-chat/src/components/Channels/Channel.tsx @@ -1,4 +1,4 @@ -import React, { useMemo } from "react"; +import React from "react"; import styled from "styled-components"; import { useNarrow } from "../../contexts/narrowProvider"; @@ -7,12 +7,51 @@ import { GroupIcon } from "../Icons/GroupIcon"; import { MutedIcon } from "../Icons/MutedIcon"; import { textMediumStyles } from "../Text"; +function RenderChannelName({ + channel, + className, +}: { + channel: ChannelData; + className?: string; +}) { + switch (channel.type) { + case "group": + return ( +
+ + {channel.name} +
+ ); + case "channel": + return
{`# ${channel.name}`}
; + case "dm": + return
{channel.name}
; + } +} + +function ChannelIcon({ + channel, + activeView, +}: { + channel: ChannelData; + activeView?: boolean; +}) { + const narrow = useNarrow(); + return ( + + {!channel.icon && channel.name.slice(0, 1).toUpperCase()} + + ); +} + interface ChannelProps { channel: ChannelData; - notification?: number; + notified?: boolean; mention?: number; isActive: boolean; - isMuted: boolean; activeView?: boolean; onClick?: () => void; } @@ -20,75 +59,48 @@ interface ChannelProps { export function Channel({ channel, isActive, - isMuted, activeView, onClick, - notification, + notified, mention, }: ChannelProps) { const narrow = useNarrow(); - const className = useMemo( - () => (narrow && !activeView ? "narrow" : activeView ? "active" : ""), - [narrow] - ); + return ( - - {!channel.icon && channel.name.slice(0, 1).toUpperCase()} - + 0 - ? "notified" - : isMuted - ? "muted" - : "" - } - > - {channel.type && channel.type === "group" ? ( - - ) : channel.type === "dm" ? ( - "" - ) : ( - "#" - )}{" "} - {channel.name} - + channel={channel} + active={isActive || narrow} + muted={channel?.isMuted} + notified={notified} + /> {activeView && ( - {channel.description} + {channel.description} )} - {notification && notification > 0 && !activeView && mention && ( + {!activeView && !!mention && mention > 0 && !channel?.isMuted && ( {mention} )} - {isMuted && !notification && } + {channel?.isMuted && } ); } -const ChannelWrapper = styled.div` +const ChannelWrapper = styled.div<{ isNarrow?: boolean }>` display: flex; justify-content: space-between; align-items: center; padding: 8px; cursor: pointer; - + width: ${({ isNarrow }) => (isNarrow ? "calc(100% - 162px)" : "100%")}; &.active { background-color: ${({ theme }) => theme.activeChannelBackground}; border-radius: 8px; @@ -109,7 +121,7 @@ const ChannelTextInfo = styled.div` white-space: nowrap; `; -export const ChannelLogo = styled.div` +export const ChannelLogo = styled.div<{ icon?: string }>` width: 24px; height: 24px; display: flex; @@ -124,45 +136,37 @@ export const ChannelLogo = styled.div` background-color: ${({ theme }) => theme.iconColor}; background-size: cover; background-repeat: no-repeat; + backgroundimage: ${({ icon }) => icon && `url(${icon}`}; color: ${({ theme }) => theme.iconTextColor}; &.active { width: 36px; height: 36px; font-size: 20px; - line-height: 20px; } &.narrow { width: 40px; height: 40px; font-size: 20px; - line-height: 20px; } `; -export const ChannelName = styled.div` - font-weight: 500; - opacity: 0.7; +export const ChannelName = styled(RenderChannelName)<{ + muted?: boolean; + notified?: boolean; + active?: boolean; +}>` + font-weight: ${({ notified, muted, active }) => + notified && !muted && !active ? "600" : "500"}; + opacity: ${({ notified, muted, active }) => + muted ? "0.4" : notified || active ? "1.0" : "0.7"}; color: ${({ theme }) => theme.primary}; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; ${textMediumStyles} - - &.active, - &.notified { - opacity: 1; - } - - &.muted { - opacity: 0.4; - } - - &.notified { - font-weight: 600; - } `; const ChannelDescription = styled.p` diff --git a/packages/react-chat/src/components/Channels/Channels.tsx b/packages/react-chat/src/components/Channels/Channels.tsx index 6833f46..e863277 100644 --- a/packages/react-chat/src/components/Channels/Channels.tsx +++ b/packages/react-chat/src/components/Channels/Channels.tsx @@ -1,13 +1,13 @@ import React, { useEffect } from "react"; import styled from "styled-components"; +import { ChatState, useChatState } from "../../contexts/chatStateProvider"; import { useMessengerContext } from "../../contexts/messengerProvider"; import { CreateIcon } from "../Icons/CreateIcon"; import { Channel } from "./Channel"; interface ChannelsProps { - setCreateChat: (val: boolean) => void; onCommunityClick?: () => void; } @@ -15,13 +15,10 @@ type GenerateChannelsProps = ChannelsProps & { type: string; }; -function GenerateChannels({ - type, - onCommunityClick, - setCreateChat, -}: GenerateChannelsProps) { +function GenerateChannels({ type, onCommunityClick }: GenerateChannelsProps) { const { mentions, notifications, activeChannel, setActiveChannel, channels } = useMessengerContext(); + const setChatState = useChatState()[1]; return ( <> {Object.values(channels) @@ -31,23 +28,14 @@ function GenerateChannels({ key={channel.id} channel={channel} isActive={channel.id === activeChannel.id} - isMuted={channel.isMuted || false} - notification={ - notifications[channel.id] > 0 && !channel.isMuted - ? notifications[channel.id] - : undefined - } - mention={ - mentions[channel.id] > 0 && !channel.isMuted - ? mentions[channel.id] - : undefined - } + notified={notifications?.[channel.id] > 0} + mention={mentions?.[channel.id]} onClick={() => { setActiveChannel(channel); if (onCommunityClick) { onCommunityClick(); } - setCreateChat(false); + setChatState(ChatState.ChatBody); }} /> ))} @@ -55,7 +43,7 @@ function GenerateChannels({ ); } -export function Channels({ setCreateChat, onCommunityClick }: ChannelsProps) { +export function Channels({ onCommunityClick }: ChannelsProps) { const { clearNotifications, clearMentions, notifications, activeChannel } = useMessengerContext(); useEffect(() => { @@ -66,19 +54,15 @@ export function Channels({ setCreateChat, onCommunityClick }: ChannelsProps) { } } }, [notifications, activeChannel]); - + const setChatState = useChatState()[1]; return ( - + Chat - setCreateChat(true)}> + setChatState(ChatState.ChatCreation)}> @@ -86,13 +70,8 @@ export function Channels({ setCreateChat, onCommunityClick }: ChannelsProps) { - + diff --git a/packages/react-chat/src/components/Channels/EmptyChannel.tsx b/packages/react-chat/src/components/Channels/EmptyChannel.tsx index e9298c0..873a984 100644 --- a/packages/react-chat/src/components/Channels/EmptyChannel.tsx +++ b/packages/react-chat/src/components/Channels/EmptyChannel.tsx @@ -16,17 +16,11 @@ export function EmptyChannel({ channel }: EmptyChannelProps) { return ( - + {" "} {!channel.icon && channel.name.slice(0, 1).toUpperCase()} - - {channel.name.slice(0, 10)} - + {channel.type === "dm" ? ( diff --git a/packages/react-chat/src/components/Chat.tsx b/packages/react-chat/src/components/Chat.tsx index 6fa9a2b..99149af 100644 --- a/packages/react-chat/src/components/Chat.tsx +++ b/packages/react-chat/src/components/Chat.tsx @@ -1,6 +1,7 @@ import React, { useState } from "react"; import styled from "styled-components"; +import { ChatState, useChatState } from "../contexts/chatStateProvider"; import { useNarrow } from "../contexts/narrowProvider"; import { Channels } from "./Channels/Channels"; @@ -23,9 +24,8 @@ function Modals() { } export function Chat() { - const [showMembers, setShowMembers] = useState(true); - const [createChat, setCreateChat] = useState(false); - + const [state] = useChatState(); + const [showMembers, setShowMembers] = useState(false); const narrow = useNarrow(); return ( @@ -33,18 +33,17 @@ export function Chat() { {!narrow && ( - + )} - {!createChat && ( + {state === ChatState.ChatBody && ( setShowMembers(!showMembers)} showMembers={showMembers} - setCreateChat={setCreateChat} /> )} - {showMembers && !narrow && !createChat && } - {createChat && } + {showMembers && !narrow && state === ChatState.ChatBody && } + {state === ChatState.ChatCreation && } ); diff --git a/packages/react-chat/src/components/Chat/ChatBody.tsx b/packages/react-chat/src/components/Chat/ChatBody.tsx index f322eea..b5c245c 100644 --- a/packages/react-chat/src/components/Chat/ChatBody.tsx +++ b/packages/react-chat/src/components/Chat/ChatBody.tsx @@ -27,14 +27,9 @@ enum ChatBodyState { interface ChatBodyProps { onClick: () => void; showMembers: boolean; - setCreateChat: (val: boolean) => void; } -export function ChatBody({ - onClick, - showMembers, - setCreateChat, -}: ChatBodyProps) { +export function ChatBody({ onClick, showMembers }: ChatBodyProps) { const { messenger, activeChannel, communityData } = useMessengerContext(); const narrow = useNarrow(); const [showChannelMenu, setShowChannelMenu] = useState(false); @@ -61,7 +56,7 @@ export function ChatBody({ return ( {editGroup && communityData ? ( - + ) : ( switchShowState(ChatBodyState.Channels)} /> @@ -132,7 +126,6 @@ export function ChatBody({ {showState === ChatBodyState.Channels && ( switchShowState(ChatBodyState.Channels)} - setCreateChat={setCreateChat} /> )} {showState === ChatBodyState.Members && ( diff --git a/packages/react-chat/src/components/Chat/ChatCreation.tsx b/packages/react-chat/src/components/Chat/ChatCreation.tsx index 57dc1e3..ccb9e9c 100644 --- a/packages/react-chat/src/components/Chat/ChatCreation.tsx +++ b/packages/react-chat/src/components/Chat/ChatCreation.tsx @@ -2,6 +2,7 @@ import React, { useCallback, useState } from "react"; import { bufToHex } from "status-communities/dist/cjs/utils"; import styled from "styled-components"; +import { ChatState, useChatState } from "../../contexts/chatStateProvider"; import { useIdentity } from "../../contexts/identityProvider"; import { useMessengerContext } from "../../contexts/messengerProvider"; import { buttonStyles } from "../Buttons/buttonStyle"; @@ -10,16 +11,16 @@ import { Member } from "../Members/Member"; import { SearchBlock } from "../SearchBlock"; import { textMediumStyles } from "../Text"; interface ChatCreationProps { - setCreateChat: (val: boolean) => void; editGroup?: boolean; } -export function ChatCreation({ setCreateChat, editGroup }: ChatCreationProps) { +export function ChatCreation({ editGroup }: ChatCreationProps) { const identity = useIdentity(); const [query, setQuery] = useState(""); const [styledGroup, setStyledGroup] = useState([]); const { contacts, setChannel } = useMessengerContext(); + const setChatState = useChatState()[1]; const addMember = useCallback( (member: string) => { @@ -51,7 +52,7 @@ export function ChatCreation({ setCreateChat, editGroup }: ChatCreationProps) { type: "dm", description: "Contact", }); - setCreateChat(false); + setChatState(ChatState.ChatBody); }; return ( diff --git a/packages/react-chat/src/components/ChatLoader.tsx b/packages/react-chat/src/components/ChatLoader.tsx index f58e44a..a3a6c8d 100644 --- a/packages/react-chat/src/components/ChatLoader.tsx +++ b/packages/react-chat/src/components/ChatLoader.tsx @@ -1,6 +1,7 @@ import React, { useState } from "react"; import { Identity } from "status-communities/dist/cjs"; +import { ChatStateProvider } from "../contexts/chatStateProvider"; import { IdentityProvider } from "../contexts/identityProvider"; import { MessengerProvider } from "../contexts/messengerProvider"; @@ -18,7 +19,9 @@ export function ChatLoader({ communityKey }: ChatLoaderProps) { return ( - + + + ); diff --git a/packages/react-chat/src/components/Form/ContactMenu.tsx b/packages/react-chat/src/components/Form/ContactMenu.tsx index 58fedc8..3dca75e 100644 --- a/packages/react-chat/src/components/Form/ContactMenu.tsx +++ b/packages/react-chat/src/components/Form/ContactMenu.tsx @@ -2,7 +2,6 @@ import React, { useMemo } from "react"; import { bufToHex } from "status-communities/dist/cjs/utils"; import styled from "styled-components"; -import { useFriends } from "../../contexts/friendsProvider"; import { useIdentity } from "../../contexts/identityProvider"; import { useModal } from "../../contexts/modalProvider"; import { useManageContact } from "../../hooks/useManageContact"; @@ -33,10 +32,8 @@ export function ContactMenu({ id, setShowMenu }: ContactMenuProps) { ); const { setModal } = useModal(ProfileModalName); - const { friends, setFriends } = useFriends(); - - const userIsFriend = useMemo(() => friends.includes(id), [friends, id]); - const { contact, setBlocked, setIsUntrustworthy } = useManageContact(id); + const { contact, setBlocked, setIsUntrustworthy, setIsUserFriend } = + useManageContact(id); if (!contact) return null; return ( @@ -63,13 +60,13 @@ export function ContactMenu({ id, setShowMenu }: ContactMenuProps) { View Profile - {!userIsFriend && ( - setFriends((prev) => [...prev, id])}> + {!contact.isFriend && ( + setIsUserFriend(true)}> Send Contact Request )} - {userIsFriend && ( + {contact.isFriend && ( Send Message @@ -98,7 +95,7 @@ export function ContactMenu({ id, setShowMenu }: ContactMenuProps) { - {!userIsFriend && !isUser && ( + {!contact.isFriend && !isUser && ( { setBlocked(!contact.blocked); diff --git a/packages/react-chat/src/components/Modals/EditModal.tsx b/packages/react-chat/src/components/Modals/EditModal.tsx index 69e5f0e..3c412f9 100644 --- a/packages/react-chat/src/components/Modals/EditModal.tsx +++ b/packages/react-chat/src/components/Modals/EditModal.tsx @@ -55,15 +55,7 @@ export const EditModal = () => { - + {!activeChannel.icon && !image && activeChannel.name.slice(0, 1).toUpperCase()} diff --git a/packages/react-chat/src/components/Modals/ProfileModal.tsx b/packages/react-chat/src/components/Modals/ProfileModal.tsx index 21a1914..c4a8c37 100644 --- a/packages/react-chat/src/components/Modals/ProfileModal.tsx +++ b/packages/react-chat/src/components/Modals/ProfileModal.tsx @@ -2,7 +2,6 @@ import React, { useEffect, useMemo, useState } from "react"; import { bufToHex } from "status-communities/dist/cjs/utils"; import styled from "styled-components"; -import { useFriends } from "../../contexts/friendsProvider"; import { useIdentity } from "../../contexts/identityProvider"; import { useModal } from "../../contexts/modalProvider"; import { useManageContact } from "../../hooks/useManageContact"; @@ -40,17 +39,18 @@ export const ProfileModal = () => { [id, identity] ); - const { friends, setFriends } = useFriends(); - - const userIsFriend = useMemo(() => friends.includes(id), [friends, id]); - const [renaming, setRenaming] = useState(renamingState ?? false); useEffect(() => { setRenaming(renamingState ?? false); }, [renamingState]); - const { contact, setBlocked, setCustomName, setIsUntrustworthy } = - useManageContact(id); + const { + contact, + setBlocked, + setCustomName, + setIsUntrustworthy, + setIsUserFriend, + } = useManageContact(id); const [customNameInput, setCustomNameInput] = useState(""); if (!contact) return null; @@ -134,7 +134,7 @@ export const ProfileModal = () => { ) : ( <> - {!userIsFriend && !isUser && ( + {!contact.isFriend && !isUser && ( { @@ -144,12 +144,10 @@ export const ProfileModal = () => { {contact.blocked ? "Unblock" : "Block"} )} - {userIsFriend && ( + {contact.isFriend && ( - setFriends((prev) => prev.filter((e) => e != id)) - } + onClick={() => setIsUserFriend(false)} > Remove Contact @@ -162,8 +160,8 @@ export const ProfileModal = () => { ? "Remove Untrustworthy Mark" : "Mark as Untrustworthy"} - {!userIsFriend && ( - setFriends((prev) => [...prev, id])}> + {!contact.isFriend && ( + setIsUserFriend(true)}> Send Contact Request )} diff --git a/packages/react-chat/src/components/NarrowMode/NarrowChannels.tsx b/packages/react-chat/src/components/NarrowMode/NarrowChannels.tsx index b7be428..508e4b8 100644 --- a/packages/react-chat/src/components/NarrowMode/NarrowChannels.tsx +++ b/packages/react-chat/src/components/NarrowMode/NarrowChannels.tsx @@ -7,20 +7,13 @@ import { NarrowTopbar } from "./NarrowTopbar"; interface NarrowChannelsProps { setShowChannels: (val: boolean) => void; - setCreateChat: (val: boolean) => void; } -export function NarrowChannels({ - setShowChannels, - setCreateChat, -}: NarrowChannelsProps) { +export function NarrowChannels({ setShowChannels }: NarrowChannelsProps) { return ( - setShowChannels(false)} - setCreateChat={setCreateChat} - /> + setShowChannels(false)} /> ); } diff --git a/packages/react-chat/src/components/ReactChat.tsx b/packages/react-chat/src/components/ReactChat.tsx index 4a66e93..9482598 100644 --- a/packages/react-chat/src/components/ReactChat.tsx +++ b/packages/react-chat/src/components/ReactChat.tsx @@ -3,7 +3,6 @@ import { ThemeProvider } from "styled-components"; import styled from "styled-components"; import { FetchMetadataProvider } from "../contexts/fetchMetadataProvider"; -import { FriendsProvider } from "../contexts/friendsProvider"; import { ModalProvider } from "../contexts/modalProvider"; import { NarrowProvider } from "../contexts/narrowProvider"; import { Metadata } from "../models/Metadata"; @@ -28,15 +27,13 @@ export function ReactChat({ - - - - - -