Spaces:
Runtime error
Runtime error
Commit
·
ee1fc35
1
Parent(s):
bf65a6c
made it working
Browse files- client/src/App.js +13 -13
- client/src/PrivateRoutes.jsx +5 -4
- client/src/UserProvider.jsx +1 -27
- client/src/components/Chat/Chat.jsx +35 -6
- client/src/components/ChatFooter/ChatFooter.css +1 -0
- client/src/components/ChatFooter/ChatFooter.jsx +11 -7
- client/src/components/ChatMain/ChatMain.jsx +24 -9
- client/src/index.css +1 -0
- client/src/index.js +2 -2
- server/index.ts +10 -9
client/src/App.js
CHANGED
@@ -12,23 +12,23 @@ function App() {
|
|
12 |
|
13 |
return (
|
14 |
<div className="App">
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
<Route element={<SignupPage />} path="/signup" />
|
20 |
-
|
|
|
|
|
|
|
|
|
|
|
21 |
|
22 |
-
|
23 |
-
<Route element={<PrivateRoutes />}>
|
24 |
-
<Route element={<ChatPage />} path="/" />
|
25 |
-
</Route>
|
26 |
-
|
27 |
|
28 |
-
|
29 |
-
|
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 |
-
|
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 |
-
|
|
|
|
|
|
|
|
|
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 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
|
|
18 |
}
|
19 |
-
}
|
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 |
-
|
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 |
-
|
6 |
messages,
|
7 |
-
}) {
|
8 |
|
9 |
-
const
|
10 |
-
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
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 |
-
|
|
|
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
|
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.
|
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.
|
312 |
{
|
313 |
-
|
|
|
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 |
});
|