Skip to content

Commit

Permalink
created individual chat component
Browse files Browse the repository at this point in the history
  • Loading branch information
SimerusM committed Aug 31, 2024
1 parent c486f7a commit e9bc4b1
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 59 deletions.
54 changes: 54 additions & 0 deletions client/src/components/Chat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React, { useState, useEffect, useCallback } from 'react';
import PropTypes from 'prop-types';
import toast from 'react-hot-toast';
import ChatInput from './ChatInput';

const Chat = ({ chatHandler, initialChatHistory }) => {
const [chatHistory, setChatHistory] = useState(initialChatHistory);

useEffect(() => {
// Setting the listener so that chatHandler can update chatHistory when new messages arrive
chatHandler.setChatHistoryListener(setChatHistory);
}, [chatHandler]);

const handleSendMessage = useCallback((message) => {
if (!message.trim()) {
toast.error('Please enter a message before sending.');
return;
}
chatHandler.sendMessage(message);
setChatHistory(prevHistory => [...prevHistory, { sender: chatHandler.username, text: message }]);
}, [chatHandler]);

const getProfilePicture = (name) => {
return `https://ui-avatars.com/api/?name=${encodeURIComponent(name)}&background=random`;
};

return (
<div className="w-1/4 bg-white p-4 flex flex-col">
<h2 className="text-xl mb-4">Chat</h2>
<div className="flex-1 overflow-y-auto mb-4">
{chatHistory.map((msg, index) => (
<div key={index} className="mb-2 flex items-center">
<img
src={getProfilePicture(msg.sender)}
alt={`${msg.sender}'s avatar`}
className="w-8 h-8 rounded-full mr-2"
/>
<div>
<strong>{msg.sender}:</strong> {msg.text}
</div>
</div>
))}
</div>
<ChatInput onSend={handleSendMessage} />
</div>
);
};

Chat.propTypes = {
chatHandler: PropTypes.object.isRequired,
initialChatHistory: PropTypes.array.isRequired,
};

export default Chat;
81 changes: 22 additions & 59 deletions client/src/pages/MeetingPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useParams, useLocation, useNavigate } from 'react-router-dom';
import io from 'socket.io-client';
import ChatHandler from '../services/chatHandler';
import RTCHandler from '../services/rtcHandler';
import ChatInput from '../components/ChatInput';
import Chat from '../components/Chat';

import Button from '../components/Button';
import toast, { Toaster } from 'react-hot-toast';
Expand All @@ -24,9 +24,8 @@ const MeetingPage = () => {

const chatHandler = useRef(null);
const [chatHistory, setChatHistory] = useState([]);
const [message, setMessage] = useState('');

useEffect(() => {
const initializeMeeting = async () => {
if (!username) {
toast.error('Please enter a username before joining a meeting.');
navigate('/');
Expand All @@ -44,28 +43,43 @@ const MeetingPage = () => {
newSocket.emit('join', { meeting_id: meeting_id, username: username });
});

// Fetch chat history manually
try {
const response = await fetch(`${apiUrl}/api/chat_history/${meeting_id}`);
const history = await response.json();
console.log('Fetched chat history:', history);
setChatHistory(history); // Set the fetched chat history
} catch (error) {
console.error('Failed to fetch chat history:', error);
toast.error('Failed to load chat history');
}

// Initialize the ChatHandler after fetching history
chatHandler.current = new ChatHandler(meeting_id, username, socketRef.current, setChatHistory);
chatHandler.current.initialize();

const handlePeerUpdate = (update) => {
setPeers(prevPeers => ({...prevPeers, ...update}));
setPeers(prevPeers => ({ ...prevPeers, ...update }));
console.debug('Updated peers:', peers);
}
rtcHandler.current = new RTCHandler(meeting_id, username, socketRef.current, handlePeerUpdate);
rtcHandler.current.initialize();
};

useEffect(() => {
initializeMeeting();

return () => {
rtcHandler.current.cleanup();
socketRef.current.disconnect();
}
};
}, []);

const toggleMute = () => {
setIsMuted(prevState => {
const newMutedState = !prevState;
// Mute or unmute the audio track in the local stream
if (rtcHandler.current && rtcHandler.current.localStream) {
rtcHandler.current.localStream.getAudioTracks().forEach(track => {
console.log(track);
track.enabled = !newMutedState;
});
}
Expand All @@ -76,39 +90,15 @@ const MeetingPage = () => {
const toggleVideo = () => {
setIsVideoOff(prevState => {
const newVideoState = !prevState;
// Turn on or off the video track in the local stream
if (rtcHandler.current && rtcHandler.current.localStream) {
rtcHandler.current.localStream.getVideoTracks().forEach(track => {
console.log(track);
track.enabled = !newVideoState;
});
}
return newVideoState;
});
};

// const sendMessage = (e) => {
// e.preventDefault();
// if (!message.trim()) {
// toast.error('Please enter a message before sending.');
// return;
// }
// chatHandler.current.sendMessage(message);
// setMessage('');
// };
const handleSendMessage = useCallback((message) => {
if (!message.trim()) {
toast.error('Please enter a message before sending.');
return;
}
chatHandler.current.sendMessage(message);
setChatHistory(prevHistory => [...prevHistory, { sender: username, text: message }]);
}, [username]);

const getProfilePicture = (name) => {
return `https://ui-avatars.com/api/?name=${encodeURIComponent(name)}&background=random`;
};

if (!username || !rtcHandler.current) {
return null;
}
Expand Down Expand Up @@ -149,34 +139,7 @@ const MeetingPage = () => {
/>
))}
</div>
<div className="w-1/4 bg-white p-4 flex flex-col">
<h2 className="text-xl mb-4">Chat</h2>
<div className="flex-1 overflow-y-auto mb-4">
{chatHistory.map((msg, index) => (
<div key={index} className="mb-2 flex items-center">
<img
src={getProfilePicture(msg.sender)}
alt={`${msg.sender}'s avatar`}
className="w-8 h-8 rounded-full mr-2"
/>
<div>
<strong>{msg.sender}:</strong> {msg.text}
</div>
</div>
))}
</div>
<ChatInput onSend={handleSendMessage} />
{/* <form onSubmit={sendMessage} className="flex">
<input
type="text"
value={message}
onChange={(e) => setMessage(e.target.value)}
className="flex-1 px-2 py-1 border rounded-l"
placeholder="Type a message..."
/>
<Button type="submit" className="rounded-l-none">Send</Button>
</form> */}
</div>
<Chat chatHandler={chatHandler.current} initialChatHistory={chatHistory} />
</main>
<footer className="bg-gray-200 p-4 flex justify-center space-x-4">
<Button onClick={toggleMute}>{isMuted ? 'Unmute' : 'Mute'}</Button>
Expand Down
4 changes: 4 additions & 0 deletions client/src/services/chatHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ class ChatHandler {
sendMessage(text) {
this.socket.emit('chat_message', { meeting_id: this.meeting_id, text: text, sender: this.username });
}

setChatHistoryListener(listener) {
this.setChatHistory = listener;
}
}

export default ChatHandler;

0 comments on commit e9bc4b1

Please sign in to comment.