Anuj-Panthri commited on
Commit
ee1fc35
·
1 Parent(s): bf65a6c

made it working

Browse files
client/src/App.js CHANGED
@@ -12,23 +12,23 @@ function App() {
12
 
13
  return (
14
  <div className="App">
15
-
16
- <Router>
17
- <Routes>
18
- <Route element={<LoginPage />} path="/login" />
19
  <Route element={<SignupPage />} path="/signup" />
20
- {/* <Route element={<ChatPage />} path="/" /> */}
 
 
 
 
 
21
 
22
-
23
- <Route element={<PrivateRoutes />}>
24
- <Route element={<ChatPage />} path="/" />
25
- </Route>
26
-
27
 
28
- </Routes>
29
- </Router>
30
-
31
 
 
32
 
33
 
34
  </div>
 
12
 
13
  return (
14
  <div className="App">
15
+ <UserProvider>
16
+ <Router>
17
+ <Routes>
18
+ <Route element={<LoginPage />} path="/login" />
19
  <Route element={<SignupPage />} path="/signup" />
20
+ {/* <Route element={<ChatPage />} path="/" /> */}
21
+
22
+
23
+ <Route element={<PrivateRoutes />}>
24
+ <Route element={<ChatPage />} path="/" />
25
+ </Route>
26
 
 
 
 
 
 
27
 
28
+ </Routes>
29
+ </Router>
 
30
 
31
+ </UserProvider>
32
 
33
 
34
  </div>
client/src/PrivateRoutes.jsx CHANGED
@@ -1,10 +1,11 @@
1
- import React, { useState, useEffect } from 'react'
2
  import { Outlet, Navigate } from "react-router-dom";
 
3
 
4
  function PrivateRoutes() {
5
-
6
  const [isAuth, setIsAuth] = useState(undefined);
7
- // const [user, setUser] = useState(null);
8
 
9
 
10
  const getAuthStatus = async () => {
@@ -13,6 +14,7 @@ function PrivateRoutes() {
13
  credentials: "include"
14
  })
15
 
 
16
  return res.ok;
17
  }
18
 
@@ -23,7 +25,6 @@ function PrivateRoutes() {
23
  })
24
  }, [])
25
 
26
-
27
  if (isAuth === undefined) {
28
  return <p>
29
  Loading ...
 
1
+ import React, { useState, useEffect, useContext } from 'react'
2
  import { Outlet, Navigate } from "react-router-dom";
3
+ import { UserContext } from './UserProvider';
4
 
5
  function PrivateRoutes() {
6
+
7
  const [isAuth, setIsAuth] = useState(undefined);
8
+ const { user, setUser } = useContext(UserContext);
9
 
10
 
11
  const getAuthStatus = async () => {
 
14
  credentials: "include"
15
  })
16
 
17
+ if (res.ok) { setUser(await res.json()) };
18
  return res.ok;
19
  }
20
 
 
25
  })
26
  }, [])
27
 
 
28
  if (isAuth === undefined) {
29
  return <p>
30
  Loading ...
client/src/UserProvider.jsx CHANGED
@@ -5,34 +5,8 @@ export const UserContext = createContext();
5
  export const UserProvider = ({ children }) => {
6
  const [user, setUser] = useState(null);
7
 
8
-
9
- const getUser = async () => {
10
-
11
- const res = await fetch(process.env.REACT_APP_BACKEND_URL + "/session", {
12
- credentials: "include"
13
- })
14
- var data;
15
- if(res.ok){
16
- data = await res.json();
17
- setUser(data);
18
- }
19
- else{
20
- setUser({});
21
- }
22
- console.log("user",data);
23
-
24
-
25
- }
26
-
27
- useEffect(()=>{
28
- getUser();
29
- },[])
30
-
31
-
32
-
33
-
34
  return (
35
- <UserContext.Provider value={user}>
36
  {children}
37
  </UserContext.Provider>
38
  );
 
5
  export const UserProvider = ({ children }) => {
6
  const [user, setUser] = useState(null);
7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  return (
9
+ <UserContext.Provider value={{user, setUser}}>
10
  {children}
11
  </UserContext.Provider>
12
  );
client/src/components/Chat/Chat.jsx CHANGED
@@ -1,4 +1,4 @@
1
- import React, { useContext, useEffect, useState } from 'react';
2
  import "./Chat.css";
3
  import ChatHeader from '../ChatHeader';
4
  import ChatMain from '../ChatMain';
@@ -10,25 +10,52 @@ function Chat({
10
  }) {
11
  const [messages, setMessages] = useState([]);
12
  const socket = useContext(SocketContext);
 
13
 
14
  const getMessages = async () => {
15
  const res = await fetch(process.env.REACT_APP_BACKEND_URL + `/messages/${currentContact.id}`, { credentials: "include" });
16
  const data = await res.json();
17
  if (res.ok) {
18
- console.log(data.messages);
19
  setMessages(data.messages);
20
  }
21
  }
22
 
23
- useEffect(() => {
 
 
 
 
24
 
25
- if (Object.keys(currentContact).length === 0) return;
26
 
 
 
 
27
  getMessages();
 
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
- }, [currentContact])
31
 
 
 
32
  if (Object.keys(currentContact).length === 0) {
33
 
34
  return (
@@ -37,10 +64,12 @@ function Chat({
37
  </div>
38
  )
39
  }
 
 
40
  return (
41
  <div className='chat'>
42
  <ChatHeader name={currentContact.username} />
43
- <ChatMain messages={messages} />
44
  <ChatFooter currentContactId={currentContact.id} setMessages={setMessages} />
45
  </div>
46
  )
 
1
+ import React, { useContext, useEffect, useState, useRef } from 'react';
2
  import "./Chat.css";
3
  import ChatHeader from '../ChatHeader';
4
  import ChatMain from '../ChatMain';
 
10
  }) {
11
  const [messages, setMessages] = useState([]);
12
  const socket = useContext(SocketContext);
13
+ const chatMainRef = useRef();
14
 
15
  const getMessages = async () => {
16
  const res = await fetch(process.env.REACT_APP_BACKEND_URL + `/messages/${currentContact.id}`, { credentials: "include" });
17
  const data = await res.json();
18
  if (res.ok) {
19
+ // console.log(data.messages);
20
  setMessages(data.messages);
21
  }
22
  }
23
 
24
+ const scrollToBottom = () => {
25
+ if(chatMainRef.current){
26
+ chatMainRef.current.scrollTo(0, chatMainRef.current.scrollHeight);
27
+ }
28
+ };
29
 
 
30
 
31
+ // to get Messages of currently opened chat
32
+ useEffect(() => {
33
+ if (Object.keys(currentContact).length === 0) return;
34
  getMessages();
35
+ }, [currentContact])
36
 
37
+ // to add receive_message listener
38
+ useEffect(() => {
39
+ if (socket) {
40
+ socket.on("receive_message", (message) => {
41
+ // console.log(message);
42
+ setMessages((prev) => [...prev, message]);
43
+ });
44
+
45
+ return () => {
46
+ socket.off("receive-message");
47
+ };
48
+ }
49
+ }, [socket]);
50
+
51
+ // when ever a chat's messages are updated, scrollToBottom
52
+ useEffect(() => {
53
+ scrollToBottom();
54
+ }, [messages]);
55
 
 
56
 
57
+
58
+ // Until no chat is selected
59
  if (Object.keys(currentContact).length === 0) {
60
 
61
  return (
 
64
  </div>
65
  )
66
  }
67
+
68
+ // once a chat is selected
69
  return (
70
  <div className='chat'>
71
  <ChatHeader name={currentContact.username} />
72
+ <ChatMain messages={messages} ref={chatMainRef} />
73
  <ChatFooter currentContactId={currentContact.id} setMessages={setMessages} />
74
  </div>
75
  )
client/src/components/ChatFooter/ChatFooter.css CHANGED
@@ -24,6 +24,7 @@
24
 
25
  .text_box{
26
  height:100%;
 
27
  flex-grow:1;
28
  border:1px solid var(--BORDER-COLOR);
29
  border-radius: 5px;
 
24
 
25
  .text_box{
26
  height:100%;
27
+ min-width:20px;
28
  flex-grow:1;
29
  border:1px solid var(--BORDER-COLOR);
30
  border-radius: 5px;
client/src/components/ChatFooter/ChatFooter.jsx CHANGED
@@ -11,29 +11,33 @@ function ChatFooter({
11
  const socket = useContext(SocketContext);
12
  const messageRef = useRef();
13
 
14
- useEffect(() => {
15
- if (socket) {
16
- console.log(socket);
17
- socket.emit("foobar");
 
18
  }
19
- }, [socket])
20
 
21
  const sendMessage = (message) => {
22
 
 
 
23
  const curr_time = Math.floor(new Date().getTime() / 1000);
24
  const message_bundle= {
25
  message,
26
  send_at:curr_time,
27
- to:currentContactId,
28
  }
29
 
30
  setMessages((prev) => [...prev, message_bundle]);
31
 
32
  if(socket){
33
-
34
  socket.emit("send_message",message_bundle);
35
  }
36
 
 
 
37
  }
38
 
39
  const handleEnter = (e) => {
 
11
  const socket = useContext(SocketContext);
12
  const messageRef = useRef();
13
 
14
+
15
+
16
+ useEffect(()=>{
17
+ if(messageRef.current){
18
+ messageRef.current.focus();
19
  }
20
+ }) // risky this running all the time
21
 
22
  const sendMessage = (message) => {
23
 
24
+ if(message.trim()==="") return;
25
+
26
  const curr_time = Math.floor(new Date().getTime() / 1000);
27
  const message_bundle= {
28
  message,
29
  send_at:curr_time,
30
+ send_to:currentContactId,
31
  }
32
 
33
  setMessages((prev) => [...prev, message_bundle]);
34
 
35
  if(socket){
 
36
  socket.emit("send_message",message_bundle);
37
  }
38
 
39
+ messageRef.current.value = "";
40
+
41
  }
42
 
43
  const handleEnter = (e) => {
client/src/components/ChatMain/ChatMain.jsx CHANGED
@@ -1,27 +1,42 @@
1
- import React from 'react'
2
  import Message from '../Message';
3
  import "./ChatMain.css";
 
4
 
5
- function ChatMain({
6
  messages,
7
- }) {
8
 
9
- const timeToReadable = (timestamp)=>{
10
- var d = new Date(timestamp*1000);
 
 
11
  return d.toLocaleTimeString();
12
  // return timestamp;
13
  }
14
 
 
 
 
 
 
 
 
15
  return (
16
- <div className='chat_main'>
17
  {
18
 
19
- messages.map((message,idx) => (
20
- <Message key={idx} message={message.message} time={timeToReadable(message.send_at)} isReceived={message.isReceived} />
 
 
 
 
 
21
  ))
22
  }
23
  </div>
24
  )
25
- }
26
 
27
  export default ChatMain
 
1
+ import React, { useContext } from 'react'
2
  import Message from '../Message';
3
  import "./ChatMain.css";
4
+ import { UserContext } from '../../UserProvider';
5
 
6
+ const ChatMain = React.forwardRef(({
7
  messages,
8
+ },ref) => {
9
 
10
+ const { user } = useContext(UserContext);
11
+
12
+ const timeToReadable = (timestamp) => {
13
+ var d = new Date(timestamp * 1000);
14
  return d.toLocaleTimeString();
15
  // return timestamp;
16
  }
17
 
18
+ const isReceived = (message) => {
19
+ // console.log("message",message.send_to);
20
+ // console.log("user",user.id);
21
+ // && user.id==message.from
22
+ return user && message.send_to == user.id;
23
+ };
24
+
25
  return (
26
+ <div className='chat_main' ref={ref}>
27
  {
28
 
29
+ messages.map((message, idx) => (
30
+ <Message
31
+ key={idx}
32
+ message={message.message}
33
+ time={timeToReadable(message.send_at)}
34
+ isReceived={isReceived(message)}
35
+ />
36
  ))
37
  }
38
  </div>
39
  )
40
+ })
41
 
42
  export default ChatMain
client/src/index.css CHANGED
@@ -2,6 +2,7 @@
2
  margin:0;
3
  padding:0;
4
  box-sizing: border-box;
 
5
  }
6
 
7
  body {
 
2
  margin:0;
3
  padding:0;
4
  box-sizing: border-box;
5
+ scroll-behavior: smooth;
6
  }
7
 
8
  body {
client/src/index.js CHANGED
@@ -6,9 +6,9 @@ import reportWebVitals from './reportWebVitals';
6
 
7
  const root = ReactDOM.createRoot(document.getElementById('root'));
8
  root.render(
9
- <React.StrictMode>
10
  <App />
11
- </React.StrictMode>
 
12
  );
13
 
14
  // If you want to start measuring performance in your app, pass a function
 
6
 
7
  const root = ReactDOM.createRoot(document.getElementById('root'));
8
  root.render(
 
9
  <App />
10
+ // <React.StrictMode>
11
+ // </React.StrictMode>
12
  );
13
 
14
  // If you want to start measuring performance in your app, pass a function
server/index.ts CHANGED
@@ -43,11 +43,6 @@ app.use(mutler().array(""));
43
  // The entire build/web directory is statically served.
44
  app.use(express.static(path.join(__dirname, "../client/build")));
45
 
46
- // Catch all. If we want to add pages later, then we should probably change this.
47
- app.get("/", (_req, res) => {
48
- res.sendFile(path.join(__dirname + "/../client/build/index.html"));
49
- });
50
-
51
  // middleware
52
  // app.use((req,res,next)=>{
53
  // if(req.method==="GET"){
@@ -146,7 +141,7 @@ app.post("/signup", async (req, res) => {
146
  })
147
  }
148
 
149
- // save to database
150
  const userId = generateId(15);
151
  const hashedPassword = await bcrypt.hash(data.password, 10);
152
 
@@ -240,6 +235,11 @@ app.get("/messages/:userid", isAuthAPIMiddleware, async (req, res) => {
240
  res.json({ "messages": messages });
241
  })
242
 
 
 
 
 
 
243
 
244
  const io = new Server(server, {
245
  cors: {
@@ -297,7 +297,7 @@ io.on("connection", async (socket) => {
297
  await stmt.run(
298
  msg_id,
299
  data.message,
300
- data.to,
301
  socket.data.user.id,
302
  data.send_at,
303
  );
@@ -308,9 +308,10 @@ io.on("connection", async (socket) => {
308
 
309
 
310
  sockets.forEach((client)=>{
311
- if(client.data.user.id==data.to)
312
  {
313
- return socket.to(client.data.user.id).emit("receive_message",{
 
314
  ...data,
315
  "from":socket.data.user.id,
316
  });
 
43
  // The entire build/web directory is statically served.
44
  app.use(express.static(path.join(__dirname, "../client/build")));
45
 
 
 
 
 
 
46
  // middleware
47
  // app.use((req,res,next)=>{
48
  // if(req.method==="GET"){
 
141
  })
142
  }
143
 
144
+ // save to data se
145
  const userId = generateId(15);
146
  const hashedPassword = await bcrypt.hash(data.password, 10);
147
 
 
235
  res.json({ "messages": messages });
236
  })
237
 
238
+ // Catch all. If we want to add pages later, then we should probably change this.
239
+ app.get("*", (_req, res) => {
240
+ res.sendFile(path.join(__dirname + "/../client/build/index.html"));
241
+ });
242
+
243
 
244
  const io = new Server(server, {
245
  cors: {
 
297
  await stmt.run(
298
  msg_id,
299
  data.message,
300
+ data.send_to,
301
  socket.data.user.id,
302
  data.send_at,
303
  );
 
308
 
309
 
310
  sockets.forEach((client)=>{
311
+ if(client.data.user.id==data.send_to)
312
  {
313
+ // console.log("heyy");
314
+ return socket.to(client.id).emit("receive_message",{
315
  ...data,
316
  "from":socket.data.user.id,
317
  });