Skip to content

Commit

Permalink
real-time communication happening && solved bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
ramanuj07 committed Aug 18, 2024
1 parent c6af72d commit 39e3aaf
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 53 deletions.
26 changes: 23 additions & 3 deletions backend/src/services/socket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ interface Message {
class SocketService {
private _io: Server;
private connectedUsers: Map<string, User> = new Map();
private userSocketMap: Map<string, string> = new Map();

constructor() {
console.log("Initialised socket server");
Expand All @@ -42,12 +43,17 @@ class SocketService {

socket.on("user:join", (user: User) => {
this.connectedUsers.set(socket.id, user);
this.userSocketMap.set(user.id, socket.id);
this.updateOnlineUsers();
socket.broadcast.emit("user:new", user);
console.log(`User joined: ${user.username}`);
});

socket.on("disconnect", () => {
const user = this.connectedUsers.get(socket.id);
if (user) {
this.userSocketMap.delete(user.id);
}
this.connectedUsers.delete(socket.id);
this.updateOnlineUsers();
console.log(`User disconnected: ${socket.id}`);
Expand All @@ -58,7 +64,7 @@ class SocketService {
try {
const savedMessage = await this.saveMessage(message);
if (savedMessage) {
this.sendMessage(savedMessage);
this.broadcastMessage(savedMessage);
} else {
socket.emit("error", "Failed to save message");
}
Expand Down Expand Up @@ -164,8 +170,22 @@ class SocketService {
}
}

private sendMessage(message: Message) {
this._io.to(message.recipientId).emit("chat:message", message);
private broadcastMessage(message: Message) {
// Send to sender
const senderSocketId = this.userSocketMap.get(message.senderId);
if (senderSocketId) {
this._io.to(senderSocketId).emit("chat:message", message);
}

// Send to recipient
const recipientSocketId = this.userSocketMap.get(message.recipientId);
if (recipientSocketId) {
this._io.to(recipientSocketId).emit("chat:message", message);
}

console.log(
`Message broadcasted to sender ${message.senderId} and recipient ${message.recipientId}`
);
}

private async markMessageAsRead(messageId: string) {
Expand Down
31 changes: 20 additions & 11 deletions frontend/src/components/AllUsersContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,31 @@ import SearchBar from "./SearchBar";
import SortingChatFilters from "./SortingChatFilters";
import UserChat from "./UserChat";

const AllUsersContainer: React.FC = () => {
interface AllUsersContainerProps {
onSelectChat: (userId: string) => void;
}

const AllUsersContainer: React.FC<AllUsersContainerProps> = ({
onSelectChat,
}) => {
const { users } = useSocket();

return (
<div>
<div className="h-full flex flex-col">
<SearchBar />
<SortingChatFilters />
{users.map((user) => (
<UserChat
key={user.id}
profilePic="https://via.placeholder.com/150"
name={user.username}
lastMessage="No messages yet"
lastMessageTime=""
/>
))}
<div className="flex-1 overflow-y-auto">
{users.map((user) => (
<UserChat
key={user.id}
profilePic="https://via.placeholder.com/150"
name={user.username}
lastMessage="No messages yet"
lastMessageTime=""
onClick={() => onSelectChat(user.id)}
/>
))}
</div>
</div>
);
};
Expand Down
28 changes: 21 additions & 7 deletions frontend/src/components/ChatInterface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import { useSocket } from "../context/SocketProvider";
interface ChatMessage {
id: string;
senderId: string;
recipientId: string;
content: string;
timestamp: string;
}

interface ChatInterfaceProps {
Expand All @@ -23,6 +25,7 @@ const ChatInterface: React.FC<ChatInterfaceProps> = ({
}) => {
const { sendMessage, messages } = useSocket();
const [inputMessage, setInputMessage] = useState("");
const [localMessages, setLocalMessages] = useState<ChatMessage[]>([]);
const messagesEndRef = useRef<HTMLDivElement>(null);
const fileInputRef = useRef<HTMLInputElement>(null);

Expand All @@ -32,19 +35,30 @@ const ChatInterface: React.FC<ChatInterfaceProps> = ({

useEffect(() => {
scrollToBottom();
}, [messages, scrollToBottom]);
}, [localMessages, scrollToBottom]);

useEffect(() => {
const filteredMessages = messages.filter(
(message) =>
(message.senderId === senderId &&
message.recipientId === recipientId) ||
(message.senderId === recipientId && message.recipientId === senderId)
);
setLocalMessages(filteredMessages);
}, [messages, senderId, recipientId]);

const handleSendMessage = useCallback(
(e: React.FormEvent) => {
e.preventDefault();
if (inputMessage.trim() === "") return;

sendMessage({
const newMessage: Omit<ChatMessage, "id" | "timestamp"> = {
senderId: senderId,
recipientId: recipientId,
content: inputMessage.trim(),
});
};

sendMessage(newMessage);
setInputMessage("");
},
[inputMessage, sendMessage, senderId, recipientId]
Expand All @@ -70,12 +84,12 @@ const ChatInterface: React.FC<ChatInterfaceProps> = ({
<div
key={message.id}
className={`mb-4 ${
message.senderId === "user" ? "text-right" : "text-left"
message.senderId === senderId ? "text-right" : "text-left"
}`}
>
<div
className={`inline-block p-2 text-xs rounded-lg ${
message.senderId === "user"
message.senderId === senderId
? "bg-[#EF6144] text-white"
: "bg-gray-100 text-gray-800"
}`}
Expand All @@ -84,7 +98,7 @@ const ChatInterface: React.FC<ChatInterfaceProps> = ({
</div>
</div>
),
[]
[senderId]
);

return (
Expand All @@ -102,7 +116,7 @@ const ChatInterface: React.FC<ChatInterfaceProps> = ({
</div>

<div className="flex-grow overflow-y-auto p-4">
{messages.map(renderMessage)}
{localMessages.map(renderMessage)}
<div ref={messagesEndRef} />
</div>

Expand Down
7 changes: 5 additions & 2 deletions frontend/src/components/MainContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { useState } from "react";
import AllUsersContainer from "./AllUsersContainer";
import Header from "./Header";
import PersonalChatContainer from "./PersonalChatContainer";

const MainContainer = () => {
const [selectedChat, setSelectedChat] = useState<string | null>(null);

return (
<div className="h-screen">
<div className="flex-shrink-0">
Expand All @@ -11,11 +14,11 @@ const MainContainer = () => {

<div className="grid grid-cols-12 h-full">
<div className="col-span-4 border-r border-gray-300">
<AllUsersContainer />
<AllUsersContainer onSelectChat={setSelectedChat} />
</div>

<div className="col-span-8">
<PersonalChatContainer />
<PersonalChatContainer selectedChat={selectedChat} />
</div>
</div>
</div>
Expand Down
56 changes: 27 additions & 29 deletions frontend/src/components/PersonalChatContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,39 @@
import React, { useState } from "react";
import React from "react";
import { useSocket } from "../context/SocketProvider";
import ChatInterface from "./ChatInterface";

const PersonalChatContainer: React.FC = () => {
interface PersonalChatContainerProps {
selectedChat: string | null;
}

const PersonalChatContainer: React.FC<PersonalChatContainerProps> = ({
selectedChat,
}) => {
const { users, currentUser } = useSocket();
const [selectedChat, setSelectedChat] = useState<string | null>(null);

if (!currentUser) {
return <div>Please log in</div>;
return (
<div className="flex items-center justify-center h-full">
Please log in
</div>
);
}

return (
<div className="flex">
<div className="w-1/3 border-r">
{users.map((user) => (
<div
key={user.id}
onClick={() => setSelectedChat(user.id)}
className="p-4 hover:bg-gray-100 cursor-pointer"
>
{user.username}
</div>
))}
</div>
<div className="w-2/3">
{selectedChat ? (
<ChatInterface
senderId={currentUser.id}
recipientId={selectedChat}
recipientName={
users.find((u) => u.id === selectedChat)?.username || ""
}
/>
) : (
<div className="p-4">Select a chat to start messaging</div>
)}
</div>
<div className="h-full">
{selectedChat ? (
<ChatInterface
senderId={currentUser.id}
recipientId={selectedChat}
recipientName={
users.find((u) => u.id === selectedChat)?.username || "Unknown User"
}
/>
) : (
<div className="flex items-center justify-center h-full text-gray-500">
Select a chat to start messaging
</div>
)}
</div>
);
};
Expand Down
7 changes: 6 additions & 1 deletion frontend/src/components/UserChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,22 @@ interface ChatProps {
name: string;
lastMessage: string;
lastMessageTime: string;
onClick: () => void;
}

const UserChat: React.FC<ChatProps> = ({
profilePic,
name,
lastMessage,
lastMessageTime,
onClick,
}) => {
return (
<div>
<div className="flex items-center p-4 hover:bg-gray-100 cursor-pointer mt-2">
<div
className="flex items-center p-4 hover:bg-gray-100 cursor-pointer mt-2"
onClick={onClick}
>
<img
src={profilePic}
alt={`${name} profile`}
Expand Down

0 comments on commit 39e3aaf

Please sign in to comment.