fixed fetching previous messages
This commit is contained in:
@@ -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<HTMLDivElement>(null);
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
const { user } = useContext(AuthContext);
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const [shouldScrollToBottom, setShouldScrollToBottom] = useState(true);
|
||||
const previousMessagesLength = useRef(messages.length);
|
||||
const previousMessagesLength = useRef<number>(messages.length);
|
||||
const isFocused = useWindowFocus();
|
||||
const previousTitle = useRef(document.title);
|
||||
const previousTitle = useRef<string>(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 (
|
||||
<div ref={containerRef} className="flex flex-col h-full overflow-y-auto">
|
||||
<p className="text-center text-gray-400">{errorMessage}</p>
|
||||
@@ -281,7 +251,7 @@ function MessagesArea() {
|
||||
<AnimatedMessage
|
||||
key={msg.message_id}
|
||||
message={msg}
|
||||
onDelete={deleteMessage}
|
||||
onDelete={() => deleteMessage(msg.message_id)}
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
Reference in New Issue
Block a user