diff --git a/src/common/Sidebar/SidebarContext.js b/src/common/Sidebar/SidebarContext.js index 192c21f..b84cbe9 100644 --- a/src/common/Sidebar/SidebarContext.js +++ b/src/common/Sidebar/SidebarContext.js @@ -22,6 +22,7 @@ export const useCreateSidebarContext = function (props) { const [selectedCategory, setSelectedCategory] = useState(null); const isMobile = useMediaQuery({ query: '(max-width: 767px)' }); + const isTabletAndHigher = useMediaQuery({ query: '(min-width: 768px)' }); const dispatch = useDispatch(); useEffect(() => { @@ -41,5 +42,6 @@ export const useCreateSidebarContext = function (props) { selectedCategory, setSelectedCategory, isMobile, + isTabletAndHigher, }; }; diff --git a/src/common/Topics/ChatsBlock/ChatItem/ChatItem.jsx b/src/common/Topics/ChatsBlock/ChatItem/ChatItem.jsx index 0eafad1..f02a2c7 100644 --- a/src/common/Topics/ChatsBlock/ChatItem/ChatItem.jsx +++ b/src/common/Topics/ChatsBlock/ChatItem/ChatItem.jsx @@ -1,8 +1,10 @@ +/* eslint-disable no-unused-vars */ import { memo } from 'react'; import { useSelector } from 'react-redux'; import { selectChatOpened, selectContactsOpened, + selectOnlineContacts, } from '../../../../redux/chatSlice'; import Avatar from '../../../../ui-kit/components/Avatar'; import TopicDesc from './TopicDesc'; @@ -12,10 +14,12 @@ import { StyledBox, StyledChildrenBox } from './ChatItem.styled'; import { useTopicsContext } from '../../TopicsContext'; import { getTime } from '../../../../components/Chat/processMessageData'; import { useMediaQuery } from 'react-responsive'; +import { useSidebarContext } from '../../../Sidebar/SidebarContext'; // const ChatItem = ({ isActive, data, notification }) => { const ChatItem = ({ isActive, data }) => { const { isTopics } = useTopicsContext(); + const { isTabletAndHigher } = useSidebarContext(); const avatarContent = getAvatar(isTopics, data); const chatOpened = useSelector(selectChatOpened); @@ -23,8 +27,7 @@ const ChatItem = ({ isActive, data }) => { const unreadedMessages = data?.unreadMessageCount ?? null; const lastMessageContent = data?.lastMessage ?? null; - - const isTablet = useMediaQuery({ query: '(min-width: 768px' }); + const onlineContacts = useSelector(selectOnlineContacts); return ( { contactsOpened={contactsOpened} isActive={isActive} > - {avatarContent} + {avatarContent} {data && ( { : lastMessageContent.lastMessage } unreadedMessage={unreadedMessages} - // isTyping={data.isTyping} + isTyping={onlineContacts.find((el) => el.typingStatus === true)} lastMessageTime={getTime(lastMessageContent.timestamp)} /> )} diff --git a/src/common/Topics/ChatsBlock/ChatsBlock.jsx b/src/common/Topics/ChatsBlock/ChatsBlock.jsx index eb04c64..ee65668 100644 --- a/src/common/Topics/ChatsBlock/ChatsBlock.jsx +++ b/src/common/Topics/ChatsBlock/ChatsBlock.jsx @@ -73,17 +73,22 @@ const ChatsBlock = ({ filter, searchInputValue }) => { }); // eslint-disable-next-line max-len - // Useeffect for subscribing to a userOnlineStatus endpoint, and get information about online users + // Useeffect for subscribing to a userOnlineStatus endpoint, and get information + // about online users. Also there is an information about typingStatus useEffect(() => { - dispatch(subscribeOnlineOrTypingStatus()); dispatch(fetchOnlineContacts(accessTokenInStore)); + if (subscriptions.find((el) => el.type === 'onlineStatus')) { + return; + } else { + dispatch(subscribeOnlineOrTypingStatus()); + } // I'm not sure that I need to unsubscribe from online and typing user status, but // this code will be here for some time. // return () => { // dispatch(unSubscribeOnlineOrTypingStatus()); // }; - }, [dispatch, accessTokenInStore]); + }, [dispatch, accessTokenInStore, subscriptions]); useEffect(() => { if (currentPrivateTopicsData) { diff --git a/src/components/Chat/Chat.jsx b/src/components/Chat/Chat.jsx index 670a778..16d50d8 100644 --- a/src/components/Chat/Chat.jsx +++ b/src/components/Chat/Chat.jsx @@ -26,6 +26,7 @@ import { setChatOpened, setNewMessages, setHistoryMessages, + selectOnlineContacts, } from '../../redux/chatSlice'; import { subscribeToMessages, @@ -97,7 +98,6 @@ const Chat = ({ children }) => { const [currentPage, setCurrentPage] = useState(1); const [sizeOfMessages, setSizeOfMessages] = useState(30); - const [isTyping, setIsTyping] = useState(false); const currentPageRef = useRef(1); const totalPagesRef = useRef(0); @@ -156,6 +156,7 @@ const Chat = ({ children }) => { const connected = useSelector(selectConnected); const subscribed = useSelector(selectSubscribed); const isChatOpened = useSelector(selectChatOpened); + const onlineContacts = useSelector(selectOnlineContacts); const useMobileMediaQuery = () => // useMediaQuery({ query: '(max-width: 769px)' }); @@ -189,6 +190,10 @@ const Chat = ({ children }) => { currentPageRef.current = 1; setCurrentPage(1); totalPagesRef.current = 1; + // The typing status has the value which was setted at the last update - when user + // is typing. And typing status can be true - but user has closed the tab with chat + // Reset typing status always to false. + dispatch(changeTypingStatus({ isTyping: false, topicId: topicId })); }; // eslint-disable-next-line react-hooks/exhaustive-deps @@ -554,7 +559,12 @@ const Chat = ({ children }) => { {topicIdData ? topicIdData.name : getUserName()} - Ти/Пишеш... + {onlineContacts.find((el) => el.typingStatus === true) + ? `${ + onlineContacts.find((el) => el.typingStatus === true) + .nickname + } is typing` + : 'Nobody is typing'} @@ -706,10 +716,13 @@ const Chat = ({ children }) => { : null} - {topicIdData.lastMessage - ? topicIdData.lastMessage.sentFrom - : null}{' '} - / Пишеш... + {/* {topicIdData.lastMessage ? topicIdData.lastMessage.sentFrom : null} / */} + {onlineContacts.find((el) => el.typingStatus === true) + ? `${ + onlineContacts.find((el) => el.typingStatus === true) + .nickname + } is typing` + : 'Nobody is typing'} @@ -876,7 +889,7 @@ const Chat = ({ children }) => { type="text" //! maxRows={3} placeholder={'Введіть повідомлення...'} - onChange={throttle(onChangeInput, 2000)} + onChange={throttle(onChangeInput, 1500)} onKeyDown={(event) => { if (event.key === 'Enter' && !event.shiftKey) { event.preventDefault(); diff --git a/src/components/Chat/Chat.styled.js b/src/components/Chat/Chat.styled.js index d941272..2d81a62 100644 --- a/src/components/Chat/Chat.styled.js +++ b/src/components/Chat/Chat.styled.js @@ -71,9 +71,9 @@ export const InfoBox = styled(Box)` display: flex; flex-direction: column; padding: 8px; - @media screen and (min-width: calc(845px - 0.02px)) { - /* padding: 8px 12px 4px 12px; */ - } + /* @media screen and (min-width: calc(845px - 0.02px)) { + padding: 8px 12px 4px 12px; + } */ `; export const ChatUserName = styled(Typography)` diff --git a/src/redux/chat-operations.js b/src/redux/chat-operations.js index ec958f4..6ce28df 100644 --- a/src/redux/chat-operations.js +++ b/src/redux/chat-operations.js @@ -141,9 +141,11 @@ export const unsubscribeFromMessages = () => { if (subscriptions.length === 0) return; await Promise.all( - subscriptions.map(async ({ subscriptionId }) => { + subscriptions.map(async ({ subscriptionId, type }) => { if (!subscriptionId) return; + if (type === 'onlineStatus') return; + try { await client.unsubscribe(subscriptionId); @@ -343,7 +345,9 @@ export const subscribeOnlineOrTypingStatus = () => { ); } catch (error) { // eslint-disable-next-line no-console - console.log(error); + console.log('Error while subscribing to online status:', error); + // eslint-disable-next-line no-console + console.log('client', client); } }; };