Skip to content

Commit

Permalink
refactor: Created ReconnectBanner component and modify BuddyMatcher (#…
Browse files Browse the repository at this point in the history
…713)

Co-authored-by: Dunsin <[email protected]>
  • Loading branch information
Kritik-Kapoor and Dun-sin authored Oct 21, 2024
1 parent 49e432d commit 01fd570
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 97 deletions.
167 changes: 70 additions & 97 deletions client/src/components/BuddyMatcher.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Link, useNavigate } from 'react-router-dom';
import { useNavigate } from 'react-router-dom';
import {
NEW_EVENT_CHAT_RESTORE,
NEW_EVENT_CLOSED,
NEW_EVENT_CLOSED,
NEW_EVENT_INACTIVE,
NEW_EVENT_JOIN,
NEW_EVENT_JOINED,
Expand All @@ -12,7 +12,6 @@ import { connectWithId, socket } from 'src/lib/socketConnection';
import { useCallback, useEffect, useRef, useState } from 'react';

import Anonymous from 'components/Anonymous';
import { PiPlugsLight } from 'react-icons/pi';
import { ThreeDots } from 'react-loading-icons';
import { createBrowserNotification } from 'src/lib/browserNotification';
import { isExplicitDisconnection } from 'src/lib/utils';
Expand All @@ -21,6 +20,7 @@ import { useAuth } from 'src/context/AuthContext';
import { useChat } from 'src/context/ChatContext';
import useCloseChat from 'src/hooks/useCloseChat';
import { useNotification } from 'src/lib/notification';
import ReconnectBanner from './ReconnectBanner';

const stoppingSearchLoadingText = <p>Stopping the search</p>;
const defaultLoadingText = <p>Looking for a random buddy</p>;
Expand All @@ -30,19 +30,14 @@ const BuddyMatcher = () => {
const navigate = useNavigate();
const { authState } = useAuth();
const { createChat, closeChat, closeAllChats } = useChat();
const { startSearch, endSearch, app } = useApp();
const {
setLoadingText,
startNewSearch,
loadingText
} = useCloseChat()
const { startSearch, endSearch, app } = useApp();
const { setLoadingText, startNewSearch, loadingText } = useCloseChat();

const [disconnected, setDisconnected] = useState(false);
const reconnectAttempts = useRef(0);

const [isStoppingSearch, setIsStoppingSearch] = useState(false);


let timeout = null;

function disconnect() {
Expand All @@ -56,66 +51,62 @@ const BuddyMatcher = () => {
endSearch();
}



const emitStopSearch = useCallback(() => {
const emitStopSearch = useCallback(() => {
socket.emit(NEW_EVENT_STOP_SEARCH, {
loginId: authState.loginId,
email: authState.email,
});
}, [])

;
}, []);

const handleStopSearch = () => {
emitStopSearch()
emitStopSearch();
setIsStoppingSearch(true);
};

async function handleReconnect() {
async function handleReconnect() {
if (socket.connected) {
return;
}

startSearch();
setLoadingText(defaultLoadingText);
await connectWithId(app.currentChatId)
await connectWithId(app.currentChatId);
}
const onUserJoined = useCallback(({ roomId, userIds }) => {

const onUserJoined = useCallback(({ roomId, userIds }) => {
playNotification('buddyPaired');
createBrowserNotification(
"Let's Chat :)",
"You've found a match, don't keep your Partner waiting ⌛"
);
createChat(roomId, userIds);
endSearch(roomId);
}, [])
}, []);

const onRestoreChat = useCallback(({ chats, currentChatId }) => {
Object.values(chats).forEach((chat) => {
createChat(chat.id, chat.userIds, chat.messages, chat.createdAt);
});
endSearch(currentChatId);
}, [])
}, []);

const onStopSearch = useCallback( () => {
const onStopSearch = useCallback(() => {
setIsStoppingSearch(false);
endSearch();
navigate('/');
}, [])
}, []);

const onConnect = useCallback(() => {
// Here server will be informed that user is searching for
// another user
// another user
socket.emit(NEW_EVENT_JOIN, {
loginId: authState.loginId,
email: authState.email,
});
setDisconnected(false);
}, [])
}, []);

const onClose = useCallback((chatId) => {
const onClose = useCallback((chatId) => {
endSearch();
closeChat(chatId);
playNotification('chatClosed');
Expand All @@ -127,32 +118,30 @@ const BuddyMatcher = () => {

createBrowserNotification('Chat Closed', 'Your buddy left the chat');
startNewSearch();
}, [])
}, []);

const onInactive = useCallback(() => {
closeAllChats();
}, [])
}, []);

const onDisconnect = useCallback((reason) => {
const onDisconnect = useCallback((reason) => {
if (isExplicitDisconnection(reason)) {
return;
}

disconnect();
}, [])
}, []);

const onReconnectAttempt = useCallback((attempts) => {
reconnectAttempts.current = attempts;
}, [])
}, []);

const onReconnectError = useCallback(() => {
if (reconnectAttempts.current >= 3) {
disconnect();
}
}, [])
}, []);



useEffect(() => {
setLoadingText(isStoppingSearch ? stoppingSearchLoadingText : defaultLoadingText);
}, [isStoppingSearch]);
Expand Down Expand Up @@ -187,49 +176,49 @@ const BuddyMatcher = () => {
};
}, [loadingText]);

useEffect(() => {
const setupSocket = async () => {
if (!app.currentChatId) {
startSearch();
}

if (!socket.connected) {
try {
await connectWithId(app.currentChatId);
} catch (error) {
console.error('Failed to connect:', error);
}
}
};

setupSocket();

socket.on('connect', onConnect);
socket.on(NEW_EVENT_CLOSED, onClose);
socket.on(NEW_EVENT_JOINED, onUserJoined);
socket.on(NEW_EVENT_CHAT_RESTORE, onRestoreChat);
socket.on(NEW_EVENT_INACTIVE, onInactive);
socket.on(NEW_EVENT_STOP_SEARCH_SUCCESS, onStopSearch);
socket.on('disconnect', onDisconnect);
socket.io.on('reconnect_attempt', onReconnectAttempt);
socket.io.on('reconnect_error', onReconnectError);

return () => {
socket
.off('connect', onConnect)
.off(NEW_EVENT_JOINED, onUserJoined)
.off(NEW_EVENT_CHAT_RESTORE, onRestoreChat)
.off(NEW_EVENT_CLOSED, onClose)
.off(NEW_EVENT_INACTIVE, onInactive)
.off('disconnect', onDisconnect);

socket.io
.off('reconnect_attempt', onReconnectAttempt)
.off('reconnect_error', onReconnectError);

socket.disconnect();
};
}, [app.currentChatId]);
useEffect(() => {
const setupSocket = async () => {
if (!app.currentChatId) {
startSearch();
}

if (!socket.connected) {
try {
await connectWithId(app.currentChatId);
} catch (error) {
console.error('Failed to connect:', error);
}
}
};

setupSocket();

socket.on('connect', onConnect);
socket.on(NEW_EVENT_CLOSED, onClose);
socket.on(NEW_EVENT_JOINED, onUserJoined);
socket.on(NEW_EVENT_CHAT_RESTORE, onRestoreChat);
socket.on(NEW_EVENT_INACTIVE, onInactive);
socket.on(NEW_EVENT_STOP_SEARCH_SUCCESS, onStopSearch);
socket.on('disconnect', onDisconnect);
socket.io.on('reconnect_attempt', onReconnectAttempt);
socket.io.on('reconnect_error', onReconnectError);

return () => {
socket
.off('connect', onConnect)
.off(NEW_EVENT_JOINED, onUserJoined)
.off(NEW_EVENT_CHAT_RESTORE, onRestoreChat)
.off(NEW_EVENT_CLOSED, onClose)
.off(NEW_EVENT_INACTIVE, onInactive)
.off('disconnect', onDisconnect);

socket.io
.off('reconnect_attempt', onReconnectAttempt)
.off('reconnect_error', onReconnectError);

socket.disconnect();
};
}, [app.currentChatId]);

return app.isSearching || !app.currentChatId ? (
<div className="flex w-full justify-center items-center min-h-[calc(100vh-70px)] flex-col bg-light dark:bg-primary">
Expand All @@ -247,25 +236,9 @@ const BuddyMatcher = () => {
)}
</div>
) : disconnected ? (
<div className="flex flex-col w-full justify-center items-center h-full bg-primary">
<PiPlugsLight className="text-secondary text-8xl" />
<p className="text-lg text-center text-white">Sorry, it seems you&apos;re not connected</p>
<div className="flex flex-col sm:flex-row gap-1 sm:gap-4 text-[1.5em] mt-4 font-medium items-center">
<button
onClick={handleReconnect}
className={
'hover:no-underline hover:text-black text-black w-[8em] h-[2.3em] rounded-[30px] bg-[#FF9F1C] flex flex-col items-center justify-center'
}
>
Try again
</button>
<Link to="/" className="underline text-white hover:text-white text-lg">
Return Home
</Link>
</div>
</div>
<ReconnectBanner handleReconnect={handleReconnect} />
) : (
<Anonymous />
<Anonymous />
);
};

Expand Down
31 changes: 31 additions & 0 deletions client/src/components/ReconnectBanner.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';
import { PiPlugsLight } from 'react-icons/pi';
import { Link } from 'react-router-dom';
import PropTypes from 'prop-types';

export default function ReconnectBanner({ handleReconnect }) {
return (
<div className="flex flex-col w-full justify-center items-center h-full bg-primary">
<PiPlugsLight className="text-secondary text-8xl" />
<p className="text-lg text-center text-white">Sorry, it seems you&apos;re not connected</p>
<div className="flex flex-col sm:flex-row gap-1 sm:gap-4 text-[1.5em] mt-4 font-medium items-center">
<button
onClick={handleReconnect}
className={
'hover:no-underline hover:text-black text-black w-[8em] h-[2.3em] rounded-[30px] bg-[#FF9F1C] flex flex-col items-center justify-center'
}
>
Try again
</button>
<Link to="/" className="underline text-white hover:text-white text-lg">
Return Home
</Link>
</div>
</div>
);
}

ReconnectBanner.propTypes = {
handleReconnect: PropTypes.func,
};

0 comments on commit 01fd570

Please sign in to comment.