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
2 changes: 1 addition & 1 deletion client/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ function App() {

// Render a loading state until authentication check is complete
if (!authChecked) {
return <div>Loading...</div>;
return <div>Loading...</div>;
}

return (
Expand Down
6 changes: 4 additions & 2 deletions client/src/pages/Home/DirectAccess.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useContext } from 'react';
import IsSearchingContext from '../../Contexts/IsSearchingContext';
import PropTypes from 'prop-types';

const DirectAccess = ({ setSelectedUser }) => {
const DirectAccess = ({ setSelectedUser, selectedUser, setSelectedConnection }) => {
const [placeholderValue, setPlaceholderValue] = useState('Search Here');
const [inputValue, setInputValue] = useState('');
const [searchKey, setSearchKey] = useState(0); // Key to force remount of SearchedProfile component
Expand Down Expand Up @@ -45,13 +45,15 @@ const DirectAccess = ({ setSelectedUser }) => {
placeholder={placeholderValue}
/>
</form>
{isSearching ? <SearchedProfile searchTerm={inputValue} key={searchKey} /> : <NormalChats setSelectedUser={setSelectedUser} />}
{isSearching ? <SearchedProfile searchTerm={inputValue} key={searchKey} /> : <NormalChats setSelectedUser={setSelectedUser} selectedUser={selectedUser} setSelectedConnection={setSelectedConnection} />}
</div>
);
};

DirectAccess.propTypes = {
setSelectedUser: PropTypes.func.isRequired,
selectedUser: PropTypes.object,
setSelectedConnection: PropTypes.func,
};

export default DirectAccess;
19 changes: 5 additions & 14 deletions client/src/pages/Home/MessageComponents/ChatContainerComponent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import { useContext, useEffect, useState } from 'react';
import UserContext from '../../../Contexts/userContext';

const ChatContainerComponent = ({ selectedUser, socket }) => {
const ChatContainerComponent = ({ selectedUser, socket, selectedConnection }) => {
// State to store the messages in the chat
const [messages, setMessages] = useState([]);

Expand All @@ -17,6 +17,7 @@ const ChatContainerComponent = ({ selectedUser, socket }) => {
// Attach 'new_message' event listener when the component mounts
useEffect(() => {
socket.on('new_message', (message) => {
console.log('message received');
setMessages((prevMessages) => [...prevMessages, message]);
});

Expand All @@ -26,21 +27,10 @@ const ChatContainerComponent = ({ selectedUser, socket }) => {
};
}, [socket]);

// Connect or disconnect the socket based on selectedUser changes
useEffect(() => {
// Connect the socket if not already connected
socket.connect();

// Disconnect the socket when the component unmounts
return () => {
socket.disconnect();
};
}, [socket]);

// Fetch messages when the selected user changes or the socket changes
useEffect(() => {
searchMessages();
}, [socket, selectedUser]);
}, [socket, selectedUser, selectedConnection]);

// Function to send a message
const sendMessage = async (e) => {
Expand All @@ -59,7 +49,7 @@ const ChatContainerComponent = ({ selectedUser, socket }) => {
}),
});
const data = await response.json();
socket.emit('private_message', data);
socket.emit('private_message', { data, selectedConnection });
setTextInputValue('');
}
};
Expand Down Expand Up @@ -125,6 +115,7 @@ const ChatContainerComponent = ({ selectedUser, socket }) => {
ChatContainerComponent.propTypes = {
socket: PropTypes.object.isRequired,
selectedUser: PropTypes.object.isRequired,
selectedConnection: PropTypes.object,
};

export default ChatContainerComponent;
30 changes: 27 additions & 3 deletions client/src/pages/Home/MessageComponents/ChatMenu.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import ChatContainerComponent from './ChatContainerComponent';
import ChatInfoButtons from './ChatInfoButtons';
import PropTypes from 'prop-types';
import socket from '../../../socket';
import { useEffect, useState } from 'react';

const ChatMenu = ({ selectedUser }) => {
const ChatMenu = ({ selectedUser, selectedConnection }) => {
const [selectedUserStatus, setSelectedUserStatus] = useState(selectedUser.isOnline);
function removeHiddenClass() {
const element = document.querySelector('.chat-info');
if (element) {
Expand All @@ -22,15 +24,35 @@ const ChatMenu = ({ selectedUser }) => {
document.querySelector('.chat-menu').style.width = '100%';
}
}

useEffect(() => {
socket.on('user_status_changed_chat_menu', ({ userId, isOnline }) => {
console.log(selectedUser);
if (userId === selectedUser._id) {
setSelectedUserStatus(isOnline);
}
});
return () => {
socket.off('user_status_changed_chat_menu');
};
}, [selectedUser.isOnline]);

useEffect(() => {
setSelectedUserStatus(selectedUser.isOnline);
}, [selectedUser]);
return (
<>
<div className="chat-menu">
<div className="chat-nav">
<div className="chat-left">
<img className="user-picture" src="https://media.discordapp.net/attachments/1111323966691352629/1133682113699381288/20230726_141636.jpg?width=295&height=623"></img>
<div className="image_container">
<img className="user-picture" src="https://media.discordapp.net/attachments/1111323966691352629/1133682113699381288/20230726_141636.jpg?width=295&height=623" />
<div id={selectedUserStatus ? 'status_online' : `status_offline`}></div>
</div>
<div className="user-info">
<h6 className="user-username">{selectedUser === undefined ? 'undefined' : selectedUser.displayName}</h6>
<p className="user-status">{selectedUser === undefined ? 'undefined' : selectedUser.id}</p>
<p></p>
</div>
</div>
<div className="chat-right">
Expand All @@ -40,7 +62,7 @@ const ChatMenu = ({ selectedUser }) => {
</div>
</div>
<div className="component-div">
<ChatContainerComponent selectedUser={selectedUser} socket={socket} />
<ChatContainerComponent selectedUser={selectedUser} socket={socket} selectedConnection={selectedConnection} />
</div>
</div>
<div className="chat-info hidden">
Expand All @@ -55,6 +77,8 @@ const ChatMenu = ({ selectedUser }) => {

ChatMenu.propTypes = {
selectedUser: PropTypes.object,
setSelectedUser: PropTypes.func,
selectedConnection: PropTypes.object,
};

export default ChatMenu;
5 changes: 3 additions & 2 deletions client/src/pages/Home/MessageMenu.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import ChatMenu from './MessageComponents/ChatMenu';

const MessageMenu = () => {
const [selectedUser, setSelectedUser] = useState({});
const [selectedConnection, setSelectedConnection] = useState({});

return (
<div id="Message-Menu">
<DirectAccess setSelectedUser={setSelectedUser} selectedUser={selectedUser} />
<ChatMenu selectedUser={selectedUser} />
<DirectAccess setSelectedUser={setSelectedUser} selectedUser={selectedUser} setSelectedConnection={setSelectedConnection} />
<ChatMenu selectedUser={selectedUser} setSelectedUser={setSelectedUser} selectedConnection={selectedConnection} />
</div>
);
};
Expand Down
15 changes: 13 additions & 2 deletions client/src/pages/Home/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,19 @@ import LeftBar from './LeftBar';
import '../pages-styles.scss';
import MessageMenu from './MessageMenu';
import { IsSearchingProvider } from '../../Contexts/IsSearchingContext';
import socket from '../../socket';
import { useEffect, useContext } from 'react';
import UserContext from '../../Contexts/userContext';

const index = () => {
const Index = () => {
const user = useContext(UserContext);

useEffect(() => {
socket.connect();
socket.auth = { user };
// Remove the event listener on component unmount
return () => socket.disconnect();
});
return (
<div id="Home">
<IsSearchingProvider>
Expand All @@ -14,4 +25,4 @@ const index = () => {
);
};

export default index;
export default Index;
29 changes: 20 additions & 9 deletions client/src/pages/Home/normalChats.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import UserContext from '../../Contexts/userContext';
import PropTypes from 'prop-types';
import socket from '../../socket';

const NormalChats = ({ setSelectedUser }) => {
const NormalChats = ({ setSelectedUser, setSelectedConnection }) => {
// State to store the chat connections
const [connectionsArr, setConnectionsArr] = useState([]);

Expand All @@ -28,6 +28,15 @@ const NormalChats = ({ setSelectedUser }) => {
return () => socket.off('connect_error');
}, []);

useEffect(() => {
socket.on('user_status_changed_normal_chats', ({ userId, isOnline }) => {
// Update the user status in your connectionsArr state
setConnectionsArr((prevConnectionsArr) => prevConnectionsArr.map((connection) => (connection.userOne._id === userId || connection.userTwo._id === userId ? { ...connection, userOne: { ...connection.userOne, isOnline }, userTwo: { ...connection.userTwo, isOnline } } : connection)));
});
// Remove the event listener on component unmount
return () => socket.off('user_status_changed_normal_chats');
}, []);

// Function to fetch the user's chat connections from the server
const searchConnections = async function () {
const response = await fetch('http://localhost:3000/connection/searchConnections', {
Expand All @@ -50,15 +59,11 @@ const NormalChats = ({ setSelectedUser }) => {
}
return text;
}

// Function to handle a click on a chat connection
const handleClick = function ({ clickedOnUser, connection }) {
// Disconnect the socket before updating authentication data
socket.disconnect();
socket.auth = { connection, clickedOnUser };
// Reconnect the socket with updated authentication data
socket.connect();
// Update the selected user in the parent component
setSelectedConnection(connection);
socket.emit('connection_selected', { connection });
setSelectedUser(clickedOnUser);
};

Expand Down Expand Up @@ -105,10 +110,14 @@ const NormalChats = ({ setSelectedUser }) => {
}}
key={i}
>
<img src="https://media.discordapp.net/attachments/1111323966691352629/1133682113699381288/20230726_141636.jpg?width=295&height=623" alt="Profile" />
<div className="image_container">
<img src="https://media.discordapp.net/attachments/1111323966691352629/1133682113699381288/20230726_141636.jpg?width=295&height=623" alt="Profile" />
<div id={tmpArr[i].isOnline ? 'status_online' : `status_offline`}></div>
</div>

<div className="chat-text" onClick={removeHiddenChatMenu}>
<p className="contact-name">{truncateText(tmpArr[i].displayName, 18)}</p>
<p>default text</p>
<p>Default Placeholder</p>
</div>
</div>
);
Expand All @@ -127,6 +136,8 @@ const NormalChats = ({ setSelectedUser }) => {
// Define the PropTypes for the component
NormalChats.propTypes = {
setSelectedUser: PropTypes.func.isRequired,
selectedUser: PropTypes.object,
setSelectedConnection: PropTypes.func,
};

export default NormalChats;
57 changes: 56 additions & 1 deletion client/src/pages/pages-styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,39 @@

.chat {
@apply flex p-3 gap-3 border-y-2 border-slate-300 max-h-[5rem] items-center;

img {
@apply w-[3rem] h-[3rem] rounded-full;
}

.image_container {
position: relative;
}
.user-picture {
@apply w-[2.25rem] h-[2.25rem] rounded-full;
}
#status_offline {
position: absolute;
top: 2.1rem;
left: 2rem;
background-color: #828282;
height: 0.8rem;
width: 0.8rem;
border-radius: 50%;
// border-color: #000;
// border-width: 0.15rem;
}
#status_online {
position: absolute;
top: 2.1rem;
left: 2rem;
background-color: #5dfcc3;
height: 0.8rem;
width: 0.8rem;
border-radius: 50%;
// border-color: #000;
// border-width: 0.15rem;
}
.contact-name {
@apply text-base font-semibold;
}
Expand All @@ -115,9 +144,35 @@
.chat-left {
@apply w-[50%] h-[100%] flex items-center px-5;

.image_container {
position: relative;
}
.user-picture {
@apply w-[2.25rem] h-[2.25rem] rounded-full;
}
#status_offline {
position: absolute;
top: 1.5rem;
left: 1.5rem;
background-color: #828282;
height: 0.7rem;
width: 0.7rem;
border-radius: 50%;
// border-color: #000;
// border-width: 0.15rem;
}
#status_online {
position: absolute;
top: 1.5rem;
left: 1.5rem;
background-color: #5dfcc3;
height: 0.7rem;
width: 0.7rem;
border-radius: 50%;
// border-color: #000;
// border-width: 0.15rem;
}

.user-info {
@apply px-3;

Expand Down
13 changes: 13 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions server/config/passport.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ passport.use(
displayName: profile.displayName,
googleId: profile.id,
provider: issuer,
isOnline: false,
});
userCreate.save();

Expand Down
5 changes: 1 addition & 4 deletions server/controllers/userCRUD.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,14 @@ exports.findUser = async function findUser(reference) {
* @throws {Error} - If failed to update user.
*/
exports.updateUser = async function updateUser(_id, updateKeys) {
let user = await findUser({ _id });

try {
const updatedUser = await User.findByIdAndUpdate(_id, updateKeys, {
new: true,
});
if (!updatedUser) {
throw new Error('User not found');
}
user = updatedUser;
return user;
return updatedUser;
} catch (error) {
throw new Error('Failed to update user');
}
Expand Down
Loading