From 57090f79bcb7742f7da0c6fa3c4314bf4cdcec1e Mon Sep 17 00:00:00 2001 From: Anshu Sharma Date: Fri, 2 Feb 2024 00:45:55 +0530 Subject: [PATCH] one to one msg send added --- public/ads.txt | 1 - public/index.html | 5 -- src/{App.js => App.jsx} | 67 ++++++++++----- src/components/ChatPage.jsx | 5 +- src/components/MessageForm.jsx | 8 +- src/components/Navbar/NavbarReact.jsx | 7 +- src/components/ProtectedPages.js | 11 --- src/components/ProtectedPages.jsx | 11 +++ src/constants/index.js | 1 + src/context/Socket.jsx | 30 +++++++ src/context/UserDetails.jsx | 23 +++++ src/index.css | 1 + src/index.js | 12 ++- src/pages/ChatToUser/index.jsx | 95 +++++++++++++++++++++ src/pages/Home/{index.js => index.jsx} | 1 - src/pages/LoginPage/{index.js => index.jsx} | 6 +- src/pages/SignUp/{index.js => index.jsx} | 0 src/pages/VerifyOtp/{index.js => index.jsx} | 0 18 files changed, 232 insertions(+), 52 deletions(-) delete mode 100644 public/ads.txt rename src/{App.js => App.jsx} (62%) delete mode 100644 src/components/ProtectedPages.js create mode 100644 src/components/ProtectedPages.jsx create mode 100644 src/constants/index.js create mode 100644 src/context/Socket.jsx create mode 100644 src/context/UserDetails.jsx create mode 100644 src/pages/ChatToUser/index.jsx rename src/pages/Home/{index.js => index.jsx} (97%) rename src/pages/LoginPage/{index.js => index.jsx} (97%) rename src/pages/SignUp/{index.js => index.jsx} (100%) rename src/pages/VerifyOtp/{index.js => index.jsx} (100%) diff --git a/public/ads.txt b/public/ads.txt deleted file mode 100644 index b1343b2..0000000 --- a/public/ads.txt +++ /dev/null @@ -1 +0,0 @@ -google.com, pub-4780451799247980, DIRECT, f08c47fec0942fa0 \ No newline at end of file diff --git a/public/index.html b/public/index.html index 471f90a..21cd0f7 100644 --- a/public/index.html +++ b/public/index.html @@ -21,11 +21,6 @@ iMessage - diff --git a/src/App.js b/src/App.jsx similarity index 62% rename from src/App.js rename to src/App.jsx index e8d5fd4..57a8251 100644 --- a/src/App.js +++ b/src/App.jsx @@ -1,22 +1,24 @@ import React, { useState, useEffect, Suspense, lazy } from "react"; -import io from "socket.io-client"; import { Routes, Route, BrowserRouter, Navigate } from "react-router-dom"; import LoadingBar from "react-top-loading-bar"; import { ProtectedPages, ProtectedAuthPages, } from "./components/ProtectedPages"; +import { useSocket } from "./context/Socket"; import Loader from "./components/Loader"; import { Toaster } from "react-hot-toast"; import { decodeToken } from "react-jwt"; +import { authtoken } from "./constants"; +import ChatToUser from "./pages/ChatToUser"; +import { useUserContext } from "./context/UserDetails"; const Home = lazy(() => import("./pages/Home")); const SignUp = lazy(() => import("./pages/SignUp")); const LoginPage = lazy(() => import("./pages/LoginPage")); const VerifyOtp = lazy(() => import("./pages/VerifyOtp")); -const socket = io(process.env.REACT_APP_SOCKET_URL); -const token = localStorage.getItem("authtoken"); + function App() { - const myDecodedToken = decodeToken(token); + const { user } = useUserContext(); const [msg, setMsg] = useState(""); const [room, setRoom] = useState(""); const [msgRec, setmsgRec] = useState([]); @@ -24,29 +26,48 @@ function App() { let UserName = localStorage?.getItem("name") ?? ""; const [Usrname, setmUserName] = useState(UserName); const [userCount, setUserCount] = useState(0); + // const [socket, setSocket] = useState(null); + const { socket } = useSocket(); const sendMsg = async () => { - socket.emit("send_msg", { msg, Usrname, id:myDecodedToken.id }); + socket.emit("send_msg", { msg, Usrname, id: user.id }); setMsg(""); }; const sendPvtMsg = async () => { - socket.emit("send_pvt_msg", { msg, room, Usrname, id:myDecodedToken.id }); + socket.emit("send_pvt_msg", { msg, room, Usrname, id: user.id }); setMsg(""); }; + const set_old_messages_Messages = async (data) => { + setmsgRec(data); + }; + const getAllMessages = async (data) => { + setmsgRec((prev) => [...prev, data]); + }; + const getAll_PVT_Messages = async (data) => { + // this will braodcast message to other open another window to see result + setpvtmsg((prev) => [...prev, data]); + }; + const get_user_count = (data) => { + setUserCount(data); + }; + const sendJWT = () => { + socket.emit("jwtToken", authtoken); + }; + useEffect(() => { - socket.on("all_messages", async (data) => { - setmsgRec(data); - }); - socket.on("received_msg", async (data) => { - setmsgRec((prev) => [...prev, data]); - }); - socket.on("pvt_received_msg", async (data) => { - // this will braodcast message to other open another window to see result - setpvtmsg((prev) => [...prev, data]); - }); - socket.on("userCount", (data) => { - setUserCount(data); - }); - // eslint-disable-next-line + if (!socket) { + return; + } + socket.on("old_messages", set_old_messages_Messages); + socket.on("received_msg", getAllMessages); + socket.on("pvt_received_msg", getAll_PVT_Messages); + socket.on("userCount", get_user_count); + socket.on("connect", sendJWT); + return () => { + socket.off("old_messages", set_old_messages_Messages); + socket.off("received_msg", getAllMessages); + socket.off("pvt_received_msg", getAll_PVT_Messages); + socket.off("userCount", get_user_count); + }; }, [socket]); const joinRoom = () => { if (room !== "") { @@ -56,6 +77,7 @@ function App() { socket.emit("join_room", room); } }; + return ( <> } /> } /> - }> + }> } /> + } /> } /> diff --git a/src/components/ChatPage.jsx b/src/components/ChatPage.jsx index c4c4aef..03bf132 100644 --- a/src/components/ChatPage.jsx +++ b/src/components/ChatPage.jsx @@ -3,9 +3,10 @@ import { useRef } from "react"; import moment from "moment"; import { Container } from "@nextui-org/react"; import { decodeToken } from "react-jwt"; -const token = localStorage.getItem("authtoken"); +import {authtoken} from "../constants" + const ChatPage = ({ msgRec, pvtmsg, room }) => { - const myDecodedToken = decodeToken(token); + const myDecodedToken = decodeToken(authtoken); const msgref = useRef(); const scrolltoView = () => { let windowHeight = window.innerHeight; diff --git a/src/components/MessageForm.jsx b/src/components/MessageForm.jsx index 38b8549..aeeabf8 100644 --- a/src/components/MessageForm.jsx +++ b/src/components/MessageForm.jsx @@ -2,7 +2,13 @@ import React, { useRef } from "react"; import { Input, Container } from "@nextui-org/react"; import { SendButton } from "./SendButton.jsx"; import { SendIcon } from "./SendIcon.jsx"; -const MessageForm = ({ msg, sendMsg, setMsg, room, sendPvtMsg }) => { +const MessageForm = ({ + msg, + sendMsg = () => {}, + setMsg, + room = "", + sendPvtMsg = () => {}, +}) => { const msgInput = useRef(null); const appendElem = () => { const para = document.createElement("p"); diff --git a/src/components/Navbar/NavbarReact.jsx b/src/components/Navbar/NavbarReact.jsx index e9865fc..566f7c6 100644 --- a/src/components/Navbar/NavbarReact.jsx +++ b/src/components/Navbar/NavbarReact.jsx @@ -10,7 +10,8 @@ import { import React, { useEffect, useState } from "react"; import { decodeToken } from "react-jwt"; import { useNavigate } from "react-router-dom"; -const token = localStorage.getItem("authtoken"); +import {authtoken} from "../../constants" + export default function NavbarReact({ room, setRoom, @@ -32,7 +33,7 @@ export default function NavbarReact({ }; useEffect(() => { const fetchUserDetails = async () => { - const myDecodedToken = decodeToken(token); + const myDecodedToken = decodeToken(authtoken); try { if (myDecodedToken.name) { setmUserName(myDecodedToken.name); @@ -45,7 +46,7 @@ export default function NavbarReact({ navigate(0); } }; - if (token !== undefined || null) { + if (authtoken !== undefined || null) { fetchUserDetails(); } }, [navigate, setmUserName]); diff --git a/src/components/ProtectedPages.js b/src/components/ProtectedPages.js deleted file mode 100644 index f0ce12d..0000000 --- a/src/components/ProtectedPages.js +++ /dev/null @@ -1,11 +0,0 @@ -import React from "react"; -import { Outlet, Navigate } from "react-router-dom"; -const authToken = localStorage.getItem("authtoken"); - -export const ProtectedPages = () => { - return authToken ? : ; -}; - -export const ProtectedAuthPages = () => { - return authToken ? : ; -}; diff --git a/src/components/ProtectedPages.jsx b/src/components/ProtectedPages.jsx new file mode 100644 index 0000000..1825a0d --- /dev/null +++ b/src/components/ProtectedPages.jsx @@ -0,0 +1,11 @@ +import React from "react"; +import { Outlet, Navigate } from "react-router-dom"; +import {authtoken} from "../constants" + +export const ProtectedPages = () => { + return authtoken ? : ; +}; + +export const ProtectedAuthPages = () => { + return authtoken ? : ; +}; diff --git a/src/constants/index.js b/src/constants/index.js new file mode 100644 index 0000000..4997393 --- /dev/null +++ b/src/constants/index.js @@ -0,0 +1 @@ +export const authtoken = localStorage.getItem("authtoken") \ No newline at end of file diff --git a/src/context/Socket.jsx b/src/context/Socket.jsx new file mode 100644 index 0000000..e04f844 --- /dev/null +++ b/src/context/Socket.jsx @@ -0,0 +1,30 @@ +import React, { useContext, useEffect, useState } from "react"; +import { io } from "socket.io-client"; + +const SocketContext = React.createContext(null); + +export const useSocket = () => { + const state = useContext(SocketContext); + if (!state) throw new Error(`state is undefined`); + return state; +}; + +// useCallback hook to prevent unneccesary rerender + +export const SocketProvider = ({ children }) => { + const [socket, setSocket] = useState(null); + useEffect(() => { + const _socket = io(process.env.REACT_APP_SOCKET_URL); + setSocket(_socket); + return () => { + _socket.disconnect(); + setSocket(undefined); + }; + }, []); + + return ( + + {children} + + ); +}; diff --git a/src/context/UserDetails.jsx b/src/context/UserDetails.jsx new file mode 100644 index 0000000..87bad07 --- /dev/null +++ b/src/context/UserDetails.jsx @@ -0,0 +1,23 @@ +import React, { useContext, useState } from "react"; +import { decodeToken } from "react-jwt"; +import { authtoken } from "../constants"; + +const UserContext = React.createContext(null); + +export const useUserContext = () => { + const state = useContext(UserContext); + if (!state) throw new Error(`state is undefined`); + return state; +}; + +// useCallback hook to prevent unneccesary rerender + +export const UserDetails = ({ children }) => { + console.log(decodeToken(authtoken)); + const [user, setUser] = useState(decodeToken(authtoken)); + return ( + + {children} + + ); +}; diff --git a/src/index.css b/src/index.css index cffa445..714a0c0 100644 --- a/src/index.css +++ b/src/index.css @@ -17,6 +17,7 @@ body { height: 100vh; position: relative; user-select: none; + width: 100%; } .modal-header .btn-close { diff --git a/src/index.js b/src/index.js index 4ffd76f..82e06b1 100644 --- a/src/index.js +++ b/src/index.js @@ -6,11 +6,17 @@ import "bootstrap/dist/css/bootstrap.min.css"; import "./index.css"; import * as serviceWorkerRegistration from "./serviceWorkerRegistration"; import { NextUIProvider } from "@nextui-org/react"; +import { SocketProvider } from "./context/Socket"; +import { UserDetails } from "./context/UserDetails"; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( - - - + + + + + + + ); // If you want your app to work offline and load faster, you can change diff --git a/src/pages/ChatToUser/index.jsx b/src/pages/ChatToUser/index.jsx new file mode 100644 index 0000000..0f16fc9 --- /dev/null +++ b/src/pages/ChatToUser/index.jsx @@ -0,0 +1,95 @@ +import React, { useEffect, useState } from "react"; +import { useRef } from "react"; +import moment from "moment"; +import { Container } from "@nextui-org/react"; +import { decodeToken } from "react-jwt"; +import { authtoken } from "../../constants"; +import { SocketProvider, useSocket } from "../../context/Socket"; +import { useUserContext } from "../../context/UserDetails"; +import MessageForm from "../../components/MessageForm"; +import { useParams } from "react-router-dom"; +const Index = ({ }) => { + const { socket } = useSocket(); + const { user } = useUserContext(); + const [msg, setMsg] = useState(""); + const { receiverId } = useParams(); + const [msgRec,setmsgRec] = useState([]) + const msgref = useRef(); + const scrolltoView = () => { + let windowHeight = window.innerHeight; + if (msgref.current?.lastChild) { + msgref.current?.lastChild.scrollIntoView() || + window.scrollTo(0, windowHeight * windowHeight); + } + }; + const tapToScroll = (event) => { + if (msgref.current?.contains(event.target)) { + scrolltoView(); + } + }; + useEffect(() => { + scrolltoView(); + }, [msgRec, msgref.current?.lastChild]); + + const sendMsg = async () => { + socket.emit("send_personal_msg", { msg, Usrname:user.name, receiverId, id: user.id }); + setMsg(""); + }; + useEffect(() => { + if (!socket) { + return; + } + // Send message to specific user + // socket.on("send_personal_msg", async (data) => { + // const { id, msg, Usrname } = data; + // let socketIdTosend = onlineUser.get(id); + // const newMsg = new Msg(data); + // await newMsg.save(); + // }); + + socket.on("received_personal_msg", (data) => { + console.log(data); + setmsgRec((prev) => [...prev, data]); + }); + return () => {}; + }, [socket]); + + return ( + <> +
+ +
+ {msgRec?.map((data, index) => { + return ( +
+ + {data?.Usrname} + +
  • {data?.msg}
  • + + {moment(data?.timeStamp).format("LTS").toString()} + +
    + ); + })} +
    +
    +
    + + + ); +}; + +export default Index; diff --git a/src/pages/Home/index.js b/src/pages/Home/index.jsx similarity index 97% rename from src/pages/Home/index.js rename to src/pages/Home/index.jsx index 1ac416b..879f90b 100644 --- a/src/pages/Home/index.js +++ b/src/pages/Home/index.jsx @@ -42,7 +42,6 @@ import NavbarReact from "../../components/Navbar/NavbarReact"; sendMsg={sendMsg} setMsg={setMsg} room={room} - socket={socket} /> ); diff --git a/src/pages/LoginPage/index.js b/src/pages/LoginPage/index.jsx similarity index 97% rename from src/pages/LoginPage/index.js rename to src/pages/LoginPage/index.jsx index af567f6..f541b87 100644 --- a/src/pages/LoginPage/index.js +++ b/src/pages/LoginPage/index.jsx @@ -33,8 +33,8 @@ export function LoginPage() { toast.success("Logged in successfully !"); } } catch (error) { - console.log(error?.response); - toast.error(error?.response?.data); + console.log(error); + toast.error(error?.response?.data || error?.message); } finally { setIsloading(false); } @@ -53,7 +53,7 @@ export function LoginPage() {