Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 102 additions & 29 deletions Chat-App/app.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,110 @@
const { log } = require('console');
const express = require('express');
const path=require('path');
const app = express();
const PORT = process.env.port || 3000;
const server=app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
}
)
const io=require('socket.io')(server);
import { useState, useEffect, useRef } from 'react';
import io from 'socket.io-client';
import moment from 'moment';

const socket = io('http://localhost:3000'); // Ensure this URL is correct for your server

function App() {
const [name, setName] = useState('anonymous');
const [totalClients, setTotalClients] = useState(0);
const [messages, setMessages] = useState([]);
const [messageInput, setMessageInput] = useState('');
const [feedback, setFeedback] = useState('');

const messageTone = useRef(new Audio('/iphone_text_message.mp3'));
const messageContainerRef = useRef(null);

useEffect(() => {
if (messageContainerRef.current) {
messageContainerRef.current.scrollTo(0, messageContainerRef.current.scrollHeight);
}
}, [messages, feedback]);

useEffect(() => {
socket.on('clients-total', (data) => setTotalClients(data));
socket.on('chat-message', (data) => {
messageTone.current.play();
setMessages((prev) => [...prev, { ...data, type: 'incoming' }]);
});
socket.on('feedback', (data) => setFeedback(data.feedback));

app.use(express.static(path.join(__dirname, 'public')));
return () => {
socket.off('clients-total');
socket.off('chat-message');
socket.off('feedback');
};
}, []);

let socketsConnected=new Set();
const sendMessage = (e) => {
e.preventDefault();
if (messageInput.trim() === '') return;
const data = { name, message: messageInput, dateTime: new Date() };
socket.emit('message', data);
setMessages((prev) => [...prev, { ...data, type: 'outgoing' }]);
setMessageInput('');
socket.emit('feedback', { feedback: '' }); // Clear feedback on send
};

io.on('connection', onConnected);

const handleTyping = () => socket.emit('feedback', { feedback: `✍🏻 ${name} is typing...` });
const handleBlur = () => socket.emit('feedback', { feedback: '' });

function onConnected(socket){
socketsConnected.add(socket.id);
io.emit("clients-total", socketsConnected.size);
socket.on('disconnect', () => {
console.log("Socket disconnected: " + socket.id);
socketsConnected.delete(socket.id);
io.emit("clients-total", socketsConnected.size);
})
return (
<div className="min-h-screen bg-cover bg-center bg-fixed flex flex-col items-center justify-center p-4" style={{ backgroundImage: "url(https://coolbackgrounds.io/images/backgrounds/index/compute-ea4c57a4.png)" }}>
{/* Main Chat Container with Glassmorphism Effect */}
<div className="w-full max-w-2xl h-[90vh] flex flex-col bg-slate-800/50 backdrop-blur-xl rounded-2xl shadow-2xl border border-slate-700">

{/* Header */}
<header className="flex justify-between items-center p-4 border-b border-slate-700 shrink-0">
<h1 className="text-3xl font-bold bg-gradient-to-r from-cyan-400 to-blue-500 bg-clip-text text-transparent">
Chit Chat 🚀
</h1>
<p className="text-lg text-slate-300">👥 {totalClients} Online</p>
</header>

socket.on('message', (data) => {
// console.log(data);
socket.broadcast.emit('chat-message', data);
})
{/* Chat Window */}
<div className="flex-1 p-6 overflow-y-auto custom-scrollbar" ref={messageContainerRef}>
<div className="flex flex-col gap-4">
{messages.map((msg, index) => (
<div key={index} className={`flex animate-fade-in ${msg.type === 'outgoing' ? 'justify-end' : 'justify-start'}`}>
<div className={`max-w-xs lg:max-w-md py-2 px-4 rounded-2xl ${msg.type === 'outgoing' ? 'bg-cyan-600 rounded-br-lg' : 'bg-slate-700 rounded-bl-lg'}`}>
<p className="text-white text-md break-words">{msg.message}</p>
<p className="text-xs text-slate-300 mt-1 text-right">
{msg.name} ● {moment(msg.dateTime).fromNow()}
</p>
</div>
</div>
))}
</div>
{feedback && <p className="text-slate-400 text-sm italic pt-4 h-6">{feedback}</p>}
</div>

socket.on('feedback', (data) => {
socket.broadcast.emit('feedback', data);
})
{/* Input Form */}
<footer className="p-4 border-t border-slate-700 shrink-0">
<form className="flex items-center gap-4" onSubmit={sendMessage}>
<input
type="text"
className="w-36 p-3 bg-slate-700/80 rounded-lg border border-slate-600 focus:outline-none focus:ring-2 focus:ring-cyan-500 transition text-white placeholder:text-slate-400"
placeholder="Your name..."
value={name}
onChange={(e) => setName(e.target.value)}
/>
<input
type="text"
className="flex-1 p-3 bg-slate-700/80 rounded-lg border border-slate-600 focus:outline-none focus:ring-2 focus:ring-cyan-500 transition text-white placeholder:text-slate-400"
placeholder="Type your message..."
value={messageInput}
onChange={(e) => setMessageInput(e.target.value)}
onKeyPress={handleTyping}
onBlur={handleBlur}
/>
<button type="submit" className="bg-cyan-600 hover:bg-cyan-500 p-3 rounded-lg font-bold transition-all shadow-lg active:scale-95 text-white flex items-center gap-2">
Send <i className="fa fa-paper-plane" aria-hidden="true"></i>
</button>
</form>
</footer>
</div>
</div>
);
}

export default App;
24 changes: 24 additions & 0 deletions Chat-App/public/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* Custom Scrollbar Styling */
.custom-scrollbar::-webkit-scrollbar {
width: 8px;
}

.custom-scrollbar::-webkit-scrollbar-track {
background: transparent;
}

.custom-scrollbar::-webkit-scrollbar-thumb {
background-color: rgba(13, 187, 219, 0.5);
border-radius: 20px;
border: 2px solid transparent;
}

/* Fade-in animation for new messages */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}

.animate-fade-in {
animation: fadeIn 0.3s ease-out;
}
31 changes: 11 additions & 20 deletions Chat-App/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,55 +4,46 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css"/>
<link rel="stylesheet" href="index.css"/>
<title>Chat App</title>
<script src="https://kit.fontawesome.com/ff53e12c48.js" crossorigin="anonymous"></script>
</head>
<body>
<h1 class="title" style="color: aliceblue;">Chit Chat🚀</h1>
<div class="main">
<div class="name">
<span><i class="fas fa-user-friends "></i></span>
<span><i class="fas fa-user-friends"></i></span>
<input type="text" id="name-input" class="name-input" value="anonymous" maxlength="20"/>

</div>
<ul class="message-container" id="message-container">
</div>
<ul class="message-container custom-scrollbar" id="message-container">
<li class="message-left">
<p class="message">Hello
<span>10:10 AM ⚫️ Today </span>
</span>
</p>
</li>
<li class="message-right">
<p class="message">Hello
<span>10:10 AM, ⚫️ Today</span>
</span>
</p>
</li>

<li class="message-feedback">
<p class="feedback" id="feedback">Hello is typing...

<p class="feedback" id="feedback">Someone is typing...
</p>
</li>
</li>
</ul>
<form class="message-form" id="message-form">
<input type="text" class="message-input" id="message-input" placeholder="Type something here...">
<div class="v-divider">

</div>
<div class="v-divider"></div>
<button type="submit" class="send-button">Send
<span>
<i class="fa fa-rocket" aria-hidden="true"></i>
</span>
</button>
<i class="fa fa-paper-plane" aria-hidden="true"></i>
</span>
</button>
</form>
</div>
<h3 class="clients-total" id="client-total">Total clients: 2</h3>
<script src="/socket.io/socket.io.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.28.0/moment.min.js" integrity="sha512-Q1f3TS3vSt1jQ8AwP2OuenztnLU6LwxgyyYOG1jgMW/cbEMHps/3wjvnl1P3WTrF3chJUWEoxDUEjMxDV8pujg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.28.0/moment.min.js" integrity="sha512-Q1f3TS3vSt1jQ8AwP2OuenztnLU6LwxgyyYOG1jgMW/cbEMHps/3wjvnl1P3WTrF3chJUWEoxDUEjMxDV8pujg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="main.js"></script>

</body>
</html>
Loading