added filter to ContactForm.tsx to avoid duplicated contacts, messages index, scroll to top event
This commit is contained in:
@@ -13,27 +13,27 @@ type ContactsProps = {
|
||||
type InitializeContactsProps = {
|
||||
InitializeContact: (contact: string) => void;
|
||||
setContactsList: React.Dispatch<React.SetStateAction<ContactsProps[]>>;
|
||||
contactsList: ContactsProps[];
|
||||
};
|
||||
|
||||
function ContactForm({
|
||||
InitializeContact,
|
||||
setContactsList,
|
||||
contactsList,
|
||||
}: InitializeContactsProps) {
|
||||
const { register, handleSubmit, reset } = useForm<Input>();
|
||||
|
||||
const submitContact: SubmitHandler<Input> = (data) => {
|
||||
const contact = data.contact.toLowerCase().trim();
|
||||
sendContact(contact);
|
||||
InitializeContact(contact);
|
||||
setContactsList([
|
||||
...contactsList,
|
||||
{ usernamecontact: contact, read: true },
|
||||
]);
|
||||
const contact = data.contact.trim();
|
||||
setContactsList((prevContacts) => {
|
||||
if (!prevContacts.some((c) => c.usernamecontact === contact)) {
|
||||
sendContact(contact);
|
||||
InitializeContact(contact);
|
||||
return [...prevContacts, { usernamecontact: contact, read: true }];
|
||||
}
|
||||
return prevContacts;
|
||||
});
|
||||
|
||||
reset({ contact: '' });
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="text-center">
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useEffect, useRef } from 'react';
|
||||
import { socket } from '../../socket/socket.tsx';
|
||||
import { useOutletContext } from 'react-router-dom';
|
||||
import { UsernameType } from '../../utils/ProtectedRoutes.tsx';
|
||||
|
||||
type ChatMessages = {
|
||||
sender: string;
|
||||
message: string;
|
||||
@@ -31,11 +32,11 @@ function MessagesArea({
|
||||
updateStatus,
|
||||
}: MessagesAreaProps) {
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const { username }: UsernameType = useOutletContext();
|
||||
|
||||
function messageHandler(msg: ChatMessages) {
|
||||
setMessages((prevMessages) => {
|
||||
// Check if the message already exists in the state
|
||||
if (!prevMessages.some((m) => m.message_id === msg.message_id)) {
|
||||
return [...prevMessages, msg];
|
||||
}
|
||||
@@ -49,11 +50,20 @@ function MessagesArea({
|
||||
return;
|
||||
}
|
||||
|
||||
window.onscroll = () => {
|
||||
window.scrollY === 0 && console.log('scrolled to top');
|
||||
return () => window.onscroll == null;
|
||||
const handleScroll = () => {
|
||||
const container = containerRef.current;
|
||||
if (container) {
|
||||
if (container.scrollTop === 0) {
|
||||
console.log('Scrolled to top!');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const currentContainer = containerRef.current;
|
||||
if (currentContainer) {
|
||||
currentContainer.addEventListener('scroll', handleScroll);
|
||||
}
|
||||
|
||||
socket.on('chat message', (msg: ChatMessages) => {
|
||||
console.log('Received message: ', msg);
|
||||
if (msg.sender !== currentContact && msg.sender !== username) {
|
||||
@@ -68,16 +78,20 @@ function MessagesArea({
|
||||
|
||||
socket.on('historical messages', (msg: ChatMessages[]) => {
|
||||
console.log('Received historical messages: ', msg);
|
||||
|
||||
msg.forEach((historicalMsg) => {
|
||||
messageHandler(historicalMsg);
|
||||
});
|
||||
});
|
||||
|
||||
return () => {
|
||||
if (!socket) {
|
||||
console.error('Socket not initialized');
|
||||
return;
|
||||
}
|
||||
// Clean up event listeners
|
||||
if (currentContainer) {
|
||||
currentContainer.removeEventListener('scroll', handleScroll);
|
||||
}
|
||||
socket.off('chat message');
|
||||
socket.off('historical');
|
||||
};
|
||||
@@ -94,12 +108,10 @@ function MessagesArea({
|
||||
));
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col">
|
||||
<ul className="flex-grow-1 list-none">{messageList}</ul>
|
||||
<div ref={messagesEndRef}></div>
|
||||
</div>
|
||||
</>
|
||||
<div ref={containerRef} className="flex flex-col h-full overflow-y-auto">
|
||||
<ul className="flex-grow list-none">{messageList}</ul>
|
||||
<div ref={messagesEndRef} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +97,6 @@ function Chat() {
|
||||
{/*Sidebar*/}
|
||||
<div className="h-screen bg-[#1E1E1E] flex flex-col">
|
||||
<ContactForm
|
||||
contactsList={contactsList}
|
||||
setContactsList={setContactsList}
|
||||
InitializeContact={InitializeContact}
|
||||
/>
|
||||
|
||||
@@ -30,9 +30,9 @@ async function createTables() {
|
||||
try {
|
||||
await client.query(`
|
||||
CREATE TABLE IF NOT EXISTS accounts (
|
||||
username VARCHAR(20),
|
||||
password VARCHAR(128),
|
||||
user_id VARCHAR(128),
|
||||
username VARCHAR(20) NOT NULL UNIQUE,
|
||||
password VARCHAR(128) NOT NULL,
|
||||
user_id VARCHAR(128) PRIMARY KEY,
|
||||
created_at VARCHAR(100)
|
||||
);
|
||||
`);
|
||||
@@ -49,6 +49,8 @@ async function createTables() {
|
||||
timestamp VARCHAR(100) NOT NULL,
|
||||
message_id SERIAL PRIMARY KEY
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_messages_conversation
|
||||
ON messages(sender, recipient, message_id ASC)
|
||||
`);
|
||||
} catch (e) {
|
||||
console.error("Failed to create messages table ", e);
|
||||
@@ -115,15 +117,21 @@ async function insertMessage(sender, recipient, message, timestamp) {
|
||||
}
|
||||
}
|
||||
|
||||
async function getMessages(username, recipient) {
|
||||
async function getMessages(username, recipient, limit = 50, cursor = 0) {
|
||||
console.log(`getMessages for Username: ${username}, recipient: ${recipient}`);
|
||||
const query = `
|
||||
SELECT * FROM messages
|
||||
WHERE (sender = $1 AND recipient = $2) OR (sender = $2 AND recipient = $1)
|
||||
ORDER BY message_id ASC;
|
||||
ORDER BY message_id ASC
|
||||
LIMIT $3 OFFSET $4;
|
||||
`;
|
||||
try {
|
||||
const results = await client.query(query, [username, recipient]);
|
||||
const results = await client.query(query, [
|
||||
username,
|
||||
recipient,
|
||||
limit,
|
||||
offset,
|
||||
]);
|
||||
return results.rows;
|
||||
} catch (e) {
|
||||
console.error("Failed to get messages ", e);
|
||||
|
||||
@@ -186,8 +186,15 @@ app.get("/api/chat/messages/:contact", authorizeUser, async (req, res) => {
|
||||
if (!req.params.contact) {
|
||||
return res.status(400).json({ message: "Missing contact parameter" });
|
||||
}
|
||||
const limit = parseInt(req.query.limit);
|
||||
const offset = parseInt(req.query.offset);
|
||||
|
||||
const messages = await getMessages(req.user.username, req.params.contact);
|
||||
const messages = await getMessages(
|
||||
req.user.username,
|
||||
req.params.contact,
|
||||
limit,
|
||||
offset,
|
||||
);
|
||||
console.log("Sent messages for: ", req.user.username, "messages: ", messages);
|
||||
return res.status(200).json(messages);
|
||||
});
|
||||
|
||||
@@ -84,21 +84,6 @@ function initializeSocket(io) {
|
||||
});
|
||||
});
|
||||
|
||||
socket.on("add contact", (contactInf) => {
|
||||
let { contact, read } = contactInf;
|
||||
|
||||
contact = filter(contact);
|
||||
if (contact) {
|
||||
insertContact(username, contact, read);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("get contacts list", async () => {
|
||||
const contacts = await getContacts(username);
|
||||
io.to(username).emit("get contacts list", contacts);
|
||||
console.log("(socket) sent on 'get contacts list: ", contacts);
|
||||
});
|
||||
|
||||
socket.on("disconnect", (reason) => {
|
||||
console.log("(socket)", socket.id, " disconnected due to: ", reason);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user