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

made working

Browse files
client/src/ChatPage/ChatPage.jsx CHANGED
@@ -5,31 +5,13 @@ import { SocketProvider } from '../SocketProvider';
5
 
6
  function ChatPage() {
7
 
8
- useEffect(() => {
9
- // const socket = io("ws://localhost:3000", {
10
- // withCredentials: true,
11
- // });
12
-
13
- // socket.on("connect", () => {
14
- // console.log("connected", socket.id);
15
- // })
16
-
17
- // socket.on("error", () => {
18
- // console.log("socket error");
19
- // })
20
-
21
- // setInterval(() => {
22
- // socket.emit("foobar", "im alive")
23
- // }, 2000);
24
-
25
- }, [])
26
-
27
  const [currentContact, setCurrentContact] = useState({});
28
  return (
29
  <>
30
  <SocketProvider>
31
- <SideBar currentContact={currentContact} setCurrentContact={setCurrentContact} />
32
- <Chat currentContact={currentContact} />
33
  </SocketProvider>
34
  </>
35
  );
 
5
 
6
  function ChatPage() {
7
 
8
+ const [contacts, setContacts] = useState([]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  const [currentContact, setCurrentContact] = useState({});
10
  return (
11
  <>
12
  <SocketProvider>
13
+ <SideBar contacts={contacts} setContacts={setContacts} currentContact={currentContact} setCurrentContact={setCurrentContact} />
14
+ <Chat contacts={contacts} setContacts={setContacts} currentContact={currentContact} setCurrentContact={setCurrentContact} />
15
  </SocketProvider>
16
  </>
17
  );
client/src/components/Chat/Chat.jsx CHANGED
@@ -6,47 +6,75 @@ import ChatFooter from '../ChatFooter';
6
  import { SocketContext } from '../../SocketProvider';
7
 
8
  function Chat({
 
 
9
  currentContact,
 
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(() => {
@@ -54,7 +82,7 @@ function Chat({
54
  }, [messages]);
55
 
56
 
57
-
58
  // Until no chat is selected
59
  if (Object.keys(currentContact).length === 0) {
60
 
 
6
  import { SocketContext } from '../../SocketProvider';
7
 
8
  function Chat({
9
+ contacts,
10
+ setContacts,
11
  currentContact,
12
+ setCurrentContact,
13
  }) {
14
  const [messages, setMessages] = useState([]);
15
  const socket = useContext(SocketContext);
16
  const chatMainRef = useRef();
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  // to get Messages of currently opened chat
19
+ //--------------------------------------------------------------------------------------------------------------//
20
  useEffect(() => {
21
+
22
  if (Object.keys(currentContact).length === 0) return;
23
+ const fetchData = async () => {
24
+
25
+ if (!socket) return;
26
+ // console.log()
27
+ socket.on("messages", (messages) => {
28
+ // console.log(messages);
29
+ setMessages(messages);
30
+ });
31
+
32
+ socket.emit("get_messages", currentContact.id);
33
+ }
34
+ fetchData();
35
+
36
+ return () => {
37
+ if (!socket) return;
38
+ socket.off("messages");
39
+ }
40
+ }, [currentContact, socket]);
41
 
42
  // to add receive_message listener
43
  useEffect(() => {
44
  if (socket) {
45
  socket.on("receive_message", (message) => {
46
  // console.log(message);
47
+ // console.log(message.send_from,currentContact.id);
48
+ // console.log(message.send_from == currentContact.id);
49
+ if (currentContact && message.send_from == currentContact.id) {
50
+ setMessages((prev) => [...prev, message]);
51
+ }
52
+ else {
53
+ // contacts.find
54
+ var updatedContacts = structuredClone(contacts);
55
+ const idx = updatedContacts.findIndex((contact)=>message.send_from==contact.id);
56
+ updatedContacts[idx] = {
57
+ ...updatedContacts[idx],
58
+ last_message:message,
59
+ }
60
+ // console.log(contacts);
61
+ // console.log(updatedContacts);
62
+
63
+ setContacts(updatedContacts);
64
+ }
65
  });
66
 
67
  return () => {
68
+ socket.off("receive_message");
69
  };
70
  }
71
+ }, [socket,contacts,currentContact]);
72
+
73
+ const scrollToBottom = () => {
74
+ if (chatMainRef.current) {
75
+ chatMainRef.current.scrollTo(0, chatMainRef.current.scrollHeight);
76
+ }
77
+ };
78
 
79
  // when ever a chat's messages are updated, scrollToBottom
80
  useEffect(() => {
 
82
  }, [messages]);
83
 
84
 
85
+
86
  // Until no chat is selected
87
  if (Object.keys(currentContact).length === 0) {
88
 
client/src/components/Contact/Contact.css CHANGED
@@ -48,4 +48,9 @@
48
  color:rgb(234, 234, 234);
49
  font-size:0.9em;
50
  white-space: nowrap;
51
- }
 
 
 
 
 
 
48
  color:rgb(234, 234, 234);
49
  font-size:0.9em;
50
  white-space: nowrap;
51
+ }
52
+ .contact__lastmsg.new{
53
+ /* color:rgb(0, 255, 132); */
54
+ font-weight: 700;
55
+ font-size:1.1em;
56
+ }
client/src/components/Contact/Contact.jsx CHANGED
@@ -7,6 +7,7 @@ function Contact({
7
  lastmessage = "",
8
  onClick,
9
  isActive = false,
 
10
  }) {
11
 
12
 
@@ -16,7 +17,7 @@ function Contact({
16
  <div>
17
  <h4 className='contact__name'>{name}</h4>
18
  {lastmessage != "" &&
19
- <p className='contact__lastmsg'>{lastmessage}</p>
20
  }
21
  </div>
22
  </div>
 
7
  lastmessage = "",
8
  onClick,
9
  isActive = false,
10
+ is_new = false,
11
  }) {
12
 
13
 
 
17
  <div>
18
  <h4 className='contact__name'>{name}</h4>
19
  {lastmessage != "" &&
20
+ <p className={(is_new ? "new":"") + ' contact__lastmsg'}>{lastmessage}</p>
21
  }
22
  </div>
23
  </div>
client/src/components/Contacts/Contacts.jsx CHANGED
@@ -1,6 +1,7 @@
1
- import React, { useEffect, useState } from 'react'
2
  import Contact from '../Contact';
3
  import "./Contacts.css";
 
4
 
5
 
6
 
@@ -10,8 +11,8 @@ function Contacts({
10
  setCurrentContact,
11
  }) {
12
 
13
- const [activeContact, setActiveContact] = useState({});
14
-
15
  // handleClick
16
 
17
  return (
@@ -20,12 +21,15 @@ function Contacts({
20
 
21
  {
22
  allContacts.map((contact) => (
 
 
23
  <Contact
24
  key={contact.id}
25
  onClick={() => { setCurrentContact(contact) }}
26
  profile_pic={"logo512.png"}
27
  name={contact.username}
28
- lastmessage={"good morning"}
 
29
  isActive={currentContact.id == contact.id}
30
  />
31
  ))
 
1
+ import React, { useContext, useState } from 'react'
2
  import Contact from '../Contact';
3
  import "./Contacts.css";
4
+ import { UserContext } from '../../UserProvider';
5
 
6
 
7
 
 
11
  setCurrentContact,
12
  }) {
13
 
14
+ // const [activeContact, setActiveContact] = useState({});
15
+ const {user} = useContext(UserContext);
16
  // handleClick
17
 
18
  return (
 
21
 
22
  {
23
  allContacts.map((contact) => (
24
+ // console.log("contact.last_message",contact,contact.last_message),
25
+ // console.log(user.id),
26
  <Contact
27
  key={contact.id}
28
  onClick={() => { setCurrentContact(contact) }}
29
  profile_pic={"logo512.png"}
30
  name={contact.username}
31
+ lastmessage={contact.last_message.message}
32
+ is_new={user.id == contact.last_message.send_to && contact.last_message.is_seen == 0}
33
  isActive={currentContact.id == contact.id}
34
  />
35
  ))
client/src/components/SideBar/SideBar.jsx CHANGED
@@ -1,32 +1,39 @@
1
- import React, { useEffect, useState } from 'react'
2
  import Search from '../Search';
3
  import Contacts from '../Contacts';
4
  import "./SideBar.css";
 
 
5
 
6
  function SideBar({
 
 
7
  setCurrentContact,
8
  currentContact,
9
  }) {
10
- const [contacts, setContacts] = useState([]);
 
11
 
12
  useEffect(() => {
13
 
14
  const fetchData = async () => {
15
-
16
- const res = await fetch(process.env.REACT_APP_BACKEND_URL + "/contacts", { credentials: "include" });
17
- const data = await res.json();
18
-
19
- if (res.ok) {
20
- // console.log(data);
21
- setContacts(data.contacts);
22
- }
23
- else {
24
- console.error(data);
25
- }
26
  }
27
  fetchData();
28
 
29
- }, []);
 
 
 
 
30
 
31
  return (
32
 
 
1
+ import React, { useContext, useEffect, useState } from 'react'
2
  import Search from '../Search';
3
  import Contacts from '../Contacts';
4
  import "./SideBar.css";
5
+ import { SocketContext } from '../../SocketProvider';
6
+
7
 
8
  function SideBar({
9
+ contacts,
10
+ setContacts,
11
  setCurrentContact,
12
  currentContact,
13
  }) {
14
+
15
+ const socket = useContext(SocketContext);
16
 
17
  useEffect(() => {
18
 
19
  const fetchData = async () => {
20
+
21
+ if(!socket) return;
22
+ // console.log()
23
+ socket.on("contacts",(contacts)=>{
24
+ // console.log(contacts);
25
+ setContacts(contacts);
26
+ });
27
+
28
+ socket.emit("get_contacts");
 
 
29
  }
30
  fetchData();
31
 
32
+ return ()=>{
33
+ if(!socket) return;
34
+ socket.off("contacts");
35
+ }
36
+ }, [socket]);
37
 
38
  return (
39
 
server/index.ts CHANGED
@@ -217,9 +217,9 @@ app.get("/contacts", isAuthAPIMiddleware, async (req, res) => {
217
 
218
  // get currentContact's messsages route
219
  app.get("/messages/:userid", isAuthAPIMiddleware, async (req, res) => {
220
-
221
  // req.query.id
222
-
223
  var messages = await db.prepare(`select * from messages
224
  where (send_to=? and send_from=?)
225
  or
@@ -229,7 +229,7 @@ app.get("/messages/:userid", isAuthAPIMiddleware, async (req, res) => {
229
 
230
  req.params.userid,
231
  res.locals.user.id,
232
- );
233
  // const messages = await db.prepare("select * from messages").all();
234
 
235
  res.json({ "messages": messages });
@@ -268,32 +268,77 @@ const isAuth = async (req: Request, res: Response, next) => {
268
 
269
  io.engine.use(isAuth);
270
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
271
 
272
  io.on("connection", async (socket) => {
273
  console.log(`socket ${socket.id} connected`);
274
-
275
  // add user and session to the socket.data object
276
  const sessionId = lucia.readSessionCookie(socket.handshake.headers.cookie ?? "");
277
  const { session, user } = await lucia.validateSession(sessionId as string);
278
  socket.data.user = user;
279
  socket.data.session = session;
280
 
281
-
282
 
283
- // send an event to the client
284
- socket.emit("foo", "bar");
285
- // socket.on("")
286
- socket.on("foobar", (data) => {
287
- // an event was received from the client
288
- console.log("received:" + data, socket.data.user);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
289
  });
 
290
  socket.on("send_message", async (data) => {
291
  // an event was received from the client
292
 
293
  const msg_id = generateId(15);
294
-
295
  const stmt = db.prepare("insert into messages(id,message,send_to,send_from,send_at) values(?,?,?,?,?)");
296
-
297
  await stmt.run(
298
  msg_id,
299
  data.message,
@@ -301,23 +346,24 @@ io.on("connection", async (socket) => {
301
  socket.data.user.id,
302
  data.send_at,
303
  );
304
-
305
- console.log("saved message:" , data.message);
306
 
307
  const sockets = await io.fetchSockets();
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
  });
318
  }
319
  })
320
-
321
  });
322
 
323
  // upon disconnection
 
217
 
218
  // get currentContact's messsages route
219
  app.get("/messages/:userid", isAuthAPIMiddleware, async (req, res) => {
220
+
221
  // req.query.id
222
+
223
  var messages = await db.prepare(`select * from messages
224
  where (send_to=? and send_from=?)
225
  or
 
229
 
230
  req.params.userid,
231
  res.locals.user.id,
232
+ );
233
  // const messages = await db.prepare("select * from messages").all();
234
 
235
  res.json({ "messages": messages });
 
268
 
269
  io.engine.use(isAuth);
270
 
271
+ async function getLastMessage({ user_id, contact_id }: { user_id: string, contact_id: string }) {
272
+
273
+ var last_message = await db.prepare(`select * from messages
274
+ where (send_to=? and send_from=?)
275
+ or
276
+ (send_to=? and send_from=?)
277
+ ORDER BY send_at DESC
278
+ `).get(
279
+ user_id,
280
+ contact_id,
281
+
282
+ contact_id,
283
+ user_id,
284
+ );
285
+
286
+ // console.log(last_message);
287
+ if (last_message) {
288
+ return last_message;
289
+ }
290
+ else {
291
+ return {};
292
+ }
293
+
294
+ }
295
 
296
  io.on("connection", async (socket) => {
297
  console.log(`socket ${socket.id} connected`);
298
+
299
  // add user and session to the socket.data object
300
  const sessionId = lucia.readSessionCookie(socket.handshake.headers.cookie ?? "");
301
  const { session, user } = await lucia.validateSession(sessionId as string);
302
  socket.data.user = user;
303
  socket.data.session = session;
304
 
305
+ socket.on("get_contacts", async () => {
306
 
307
+ // get all contacts to client
308
+ var contacts = await db.prepare("select id,username from users where id!=?").all(socket.data.user.id);
309
+ contacts = await Promise.all(contacts.map(async (contact: any) => {
310
+ return { ...contact, last_message: await getLastMessage({ user_id: socket.data.user.id, contact_id: contact.id }) }
311
+ }))
312
+
313
+ // console.log(contacts);
314
+ socket.emit("contacts", contacts);
315
+ // socket
316
+ })
317
+
318
+
319
+
320
+ socket.on("get_messages", async (contact_id) => {
321
+ var messages = await db.prepare(`select * from messages
322
+ where (send_to=? and send_from=?)
323
+ or
324
+ (send_to=? and send_from=?)`).all(
325
+ socket.data.user.id,
326
+ contact_id,
327
+
328
+ contact_id,
329
+ socket.data.user.id,
330
+ );
331
+
332
+ socket.emit("messages", messages);
333
  });
334
+
335
  socket.on("send_message", async (data) => {
336
  // an event was received from the client
337
 
338
  const msg_id = generateId(15);
339
+
340
  const stmt = db.prepare("insert into messages(id,message,send_to,send_from,send_at) values(?,?,?,?,?)");
341
+
342
  await stmt.run(
343
  msg_id,
344
  data.message,
 
346
  socket.data.user.id,
347
  data.send_at,
348
  );
349
+
350
+ console.log("saved message:", data.message);
351
 
352
  const sockets = await io.fetchSockets();
353
 
354
+
355
+ sockets.forEach((client) => {
356
+ if (client.data.user.id == data.send_to) {
 
357
  // console.log("heyy");
358
+ return socket.to(client.id).emit("receive_message", {
359
  ...data,
360
+ "send_to": data.send_to,
361
+ "send_from": socket.data.user.id,
362
+ "is_seen": 0,
363
  });
364
  }
365
  })
366
+
367
  });
368
 
369
  // upon disconnection