From 8f25f13838a3fb5c51dc182758bbc62c3a48f29c Mon Sep 17 00:00:00 2001 From: slwk0 Date: Thu, 16 Jan 2025 16:36:40 +0100 Subject: [PATCH] fixed fetching previous messages --- .../components/chat/chatArea/MessagesArea.tsx | 206 ++++++++---------- 1 file changed, 88 insertions(+), 118 deletions(-) diff --git a/client/src/components/chat/chatArea/MessagesArea.tsx b/client/src/components/chat/chatArea/MessagesArea.tsx index 57b0836..d48c5bf 100644 --- a/client/src/components/chat/chatArea/MessagesArea.tsx +++ b/client/src/components/chat/chatArea/MessagesArea.tsx @@ -1,4 +1,4 @@ -import { useContext, useEffect, useRef, useState } from 'react'; +import { useContext, useEffect, useRef, useState, useCallback } from 'react'; import { socket } from '@/socket/socket.ts'; import { sendContact } from '@/api/contactsApi.tsx'; import LoadingWheel from '../LoadingWheel.tsx'; @@ -20,13 +20,14 @@ function MessagesArea() { contactsList, setCurrentContact, } = useChat(); - const containerRef = useRef(null); + const containerRef = useRef(null); const { user } = useContext(AuthContext); const [isLoading, setIsLoading] = useState(false); const [shouldScrollToBottom, setShouldScrollToBottom] = useState(true); - const previousMessagesLength = useRef(messages.length); + const previousMessagesLength = useRef(messages.length); const isFocused = useWindowFocus(); - const previousTitle = useRef(document.title); + const previousTitle = useRef(document.title); + const scrollToBottom = () => { const container = containerRef.current; if (container && shouldScrollToBottom) { @@ -34,18 +35,16 @@ function MessagesArea() { } }; - const handleScroll = async () => { + const handleScroll = useCallback(async () => { const container = containerRef.current; - if (!container) return; + if (!container || isLoading) return; if (container.scrollTop === 0) { setIsLoading(true); - setShouldScrollToBottom(false); - const previousScrollHeight = container.scrollHeight; - try { + const previousScrollHeight = container.scrollHeight; await fetchPreviousMessages(currentContact!.conversation_id); - + // Adjust scroll position after fetching new messages container.scrollTop = container.scrollHeight - previousScrollHeight; } catch (e) { console.error('Error fetching previous messages:', e); @@ -58,39 +57,22 @@ function MessagesArea() { container.scrollHeight - container.scrollTop <= container.clientHeight + 200; setShouldScrollToBottom(isAtBottom); - }; + }, [isLoading, currentContact, fetchPreviousMessages]); - const deleteMessage = async (message_id: number) => { - try { - socket?.emit( - 'delete message', - { - message_id, - conversation_id: currentContact?.conversation_id, - }, - (response: { status: string; message: string }) => { - if (response.status !== 'ok') { - console.error('Failed to delete message: ', response.message); - } - }, - ); - } catch (e) { - if (e instanceof Error) { - console.error('Failed to delete message'); - } - } - }; + useEffect(() => { + const currentContainer = containerRef.current; + if (!currentContainer) return; + + currentContainer.addEventListener('scroll', handleScroll); + + return () => { + currentContainer.removeEventListener('scroll', handleScroll); + }; + }, [handleScroll]); useEffect(() => { if (!socket) return; - const currentContainer = containerRef.current; - if (currentContainer) { - currentContainer.addEventListener('scroll', handleScroll); - } - socket.on('chat message', (msg: ChatMessagesProps) => { - console.log('Received message: ', msg); - const isFromCurrentConversation = msg.conversation_id === currentContact?.conversation_id; const isFromCurrentUser = msg.sender === user?.username; @@ -98,58 +80,50 @@ function MessagesArea() { if (isFromCurrentConversation) { messageHandler(msg); if (!isFocused) { - setContactsList((prevContacts) => { - return prevContacts.map((contact) => + setContactsList((prevContacts) => + prevContacts.map((contact) => contact.conversation_id === currentContact?.conversation_id - ? { - ...contact, - read: false, - } + ? { ...contact, read: false } : contact, - ); - }); - + ), + ); document.title = 'New message ❗'; } else { socket?.emit('read message', { conversation_id: msg.conversation_id, - message_id: msg.conversation_id, + message_id: msg.message_id, }); } } - // Handle contact list updates setContactsList((prevContacts) => { - // If message is from another conversation - if (!isFromCurrentConversation && !isFromCurrentUser) { - // Check if contact exists - const existingContact = prevContacts.find( - (c) => c.conversation_id === msg.conversation_id, - ); + const isFromAnotherConversation = + !isFromCurrentConversation && !isFromCurrentUser; + const existingContact = prevContacts.find( + (c) => c.conversation_id === msg.conversation_id, + ); - if (!existingContact) { - sendContact(msg.sender); - return [ - ...prevContacts, - { - read: false, - username: msg.sender, - id: msg.message_id, - user_id: msg.sender_id, - conversation_id: msg.conversation_id, - type: 'direct', - last_active: new Date().toString(), - last_message: msg.message, - last_message_id: msg.message_id, - last_message_sender: msg.sender, - last_message_time: new Date().toString(), - last_read_message_id: prevContacts[0]?.last_message_id || null, - }, - ]; - } + if (isFromAnotherConversation && !existingContact) { + sendContact(msg.sender); + return [ + ...prevContacts, + { + read: false, + username: msg.sender, + user_id: msg.sender_id, + conversation_id: msg.conversation_id, + type: 'direct', + id: msg.message_id, + last_active: new Date().toISOString(), + last_message: msg.message, + last_message_id: msg.message_id, + last_message_sender: msg.sender, + last_message_time: new Date().toISOString(), + last_read_message_id: prevContacts[0]?.last_message_id || null, + }, + ]; } - // Update existing contact if found return prevContacts.map((contact) => contact.conversation_id === msg.conversation_id ? { @@ -174,9 +148,8 @@ function MessagesArea() { (message) => message.message_id !== msg.message_id, ), ); - console.log('deleted message from state'); - setContactsList((prevContacts) => { - return prevContacts.map((contact) => + setContactsList((prevContacts) => + prevContacts.map((contact) => contact.last_message_id === msg.message_id ? { ...contact, @@ -185,20 +158,13 @@ function MessagesArea() { last_message_time: new Date().toString(), } : contact, - ); - }); + ), + ); }, ); return () => { - if (!socket) { - console.error('Socket not initialized'); - return; - } - - if (currentContainer) { - currentContainer.removeEventListener('scroll', handleScroll); - } + if (!socket) return; socket.off('chat message'); socket.off('delete message'); }; @@ -206,35 +172,22 @@ function MessagesArea() { useEffect(() => { if (!currentContact) return; - const currentContactOnList = contactsList.find((contact) => { - return contact.conversation_id == currentContact?.conversation_id; - }); + const currentContactOnList = contactsList.find( + (contact) => contact.conversation_id === currentContact.conversation_id, + ); if (currentContactOnList && messages.length > 1) { socket?.emit('message read', { - conversation_id: currentContact?.conversation_id, + conversation_id: currentContact.conversation_id, message_id: messages[messages.length - 1].message_id, }); - setCurrentContact({ ...currentContact, read: currentContactOnList.read }); } - return () => { - if (!socket) return; - socket.off('message read'); - }; }, [contactsList, currentContact?.conversation_id]); useEffect(() => { - if (currentContact?.read == true) { - return; - } + if (currentContact?.read) return; document.title = previousTitle.current; if (messages.length > 1) { - console.error( - 'read !== true, emiting message read socket for: ', - currentContact?.username, - messages[messages.length - 1].message_id, - ); - socket?.emit('message read', { conversation_id: currentContact?.conversation_id, message_id: messages[messages.length - 1].message_id, @@ -242,16 +195,13 @@ function MessagesArea() { } const timeout = setTimeout(() => { - setContactsList((prevContacts) => { - return prevContacts.map((contact) => - contact?.conversation_id === currentContact?.conversation_id - ? { - ...contact, - read: true, - } + setContactsList((prevContacts) => + prevContacts.map((contact) => + contact.conversation_id === currentContact?.conversation_id + ? { ...contact, read: true } : contact, - ); - }); + ), + ); }, 800); return () => clearTimeout(timeout); @@ -263,7 +213,6 @@ function MessagesArea() { if (hasNewMessages && shouldScrollToBottom) { scrollToBottom(); - setTimeout(scrollToBottom, 100); } }, [messages, shouldScrollToBottom]); @@ -272,6 +221,27 @@ function MessagesArea() { scrollToBottom(); }, []); + const deleteMessage = async (message_id: number) => { + try { + socket?.emit( + 'delete message', + { + message_id, + conversation_id: currentContact?.conversation_id, + }, + (response: { status: string; message: string }) => { + if (response.status !== 'ok') { + console.error('Failed to delete message: ', response.message); + } + }, + ); + } catch (e) { + if (e instanceof Error) { + console.error('Failed to delete message:', e); + } + } + }; + return (

{errorMessage}

@@ -281,7 +251,7 @@ function MessagesArea() { deleteMessage(msg.message_id)} /> ))}