added filter to ContactForm.tsx to avoid duplicated contacts, messages index, scroll to top event

This commit is contained in:
slawk0
2024-11-03 21:02:06 +01:00
parent 39a4242176
commit b99e148841
6 changed files with 55 additions and 44 deletions

View File

@@ -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">

View File

@@ -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>
);
}

View File

@@ -97,7 +97,6 @@ function Chat() {
{/*Sidebar*/}
<div className="h-screen bg-[#1E1E1E] flex flex-col">
<ContactForm
contactsList={contactsList}
setContactsList={setContactsList}
InitializeContact={InitializeContact}
/>

View File

@@ -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);

View File

@@ -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);
});

View File

@@ -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);
});