Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/filesharing is added #44

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
980 changes: 812 additions & 168 deletions public/package-lock.json

Large diffs are not rendered by default.

60 changes: 51 additions & 9 deletions public/src/components/ChatContainer.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React, { useState, useEffect, useRef } from "react";
import styled from "styled-components";
import ChatInput from "./ChatInput";
import ChatInput, { ChatMessage } from "./ChatInput";
import Logout from "./Logout";
import { v4 as uuidv4 } from "uuid";
import axios from "axios";
import { sendMessageRoute, recieveMessageRoute } from "../utils/APIRoutes";
import { sendMessageRoute, recieveMessageRoute, sendFileRoute } from "../utils/APIRoutes"; // Add your file route

export default function ChatContainer({ currentChat, socket }) {
const [messages, setMessages] = useState([]);
@@ -20,6 +20,7 @@ export default function ChatContainer({ currentChat, socket }) {
to: currentChat._id,
});
setMessages(response.data);
console.log(response.data);
}, [currentChat]);

useEffect(() => {
@@ -33,26 +34,57 @@ export default function ChatContainer({ currentChat, socket }) {
getCurrentChat();
}, [currentChat]);

const handleSendMsg = async (msg) => {
const handleSendMsg = async (message) => {
const data = await JSON.parse(
localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)
);
socket.current.emit("send-msg", {
to: currentChat._id,
from: data._id,
msg,
message,
});
await axios.post(sendMessageRoute, {
from: data._id,
to: currentChat._id,
message: msg,
message: message,
});

const msgs = [...messages];
msgs.push({ fromSelf: true, message: msg });
msgs.push({ fromSelf: true, message: message });
setMessages(msgs);
};

// New function to handle file sending
const handleSendFile = async (file) => {
const data = await JSON.parse(
localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)
);
const formData = new FormData();
formData.append("file", file);
formData.append("from", data._id);
formData.append("to", currentChat._id);

try {
const response = await axios.post(sendFileRoute, formData, {
headers: {
"Content-Type": "multipart/form-data",
},
});

const fileMessage = {
fromSelf: true,
message: response.data.message, // The file URL sent from the server
fileUrl: response.data.fileUrl, // URL to the uploaded file
};

const msgs = [...messages];
msgs.push(fileMessage);
setMessages(msgs);
} catch (error) {
console.error("Error uploading file", error);
}
};

useEffect(() => {
if (socket.current) {
socket.current.on("msg-recieve", (msg) => {
@@ -86,7 +118,7 @@ export default function ChatContainer({ currentChat, socket }) {
<Logout />
</div>
<div className="chat-messages">
{messages.map((message) => {
{messages.map((message) => {
return (
<div ref={scrollRef} key={uuidv4()}>
<div
@@ -95,14 +127,24 @@ export default function ChatContainer({ currentChat, socket }) {
}`}
>
<div className="content ">
<p>{message.message}</p>
{message?.message?.fileUrl ? (
<a href={message?.fileUrl} target="_blank" rel="noopener noreferrer">
{message.message?.fileUrl?.endsWith(".png") || message?.message?.fileUrl.endsWith(".jpg") ? (
<img src={`http://localhost:5000${message?.message?.fileUrl}`} height = {250} width = {250} alt="attachment" />
) : (
"Download File"
)}
</a>
) : (
<p>{message.message.msg }</p>
)}
</div>
</div>
</div>
);
})}
</div>
<ChatInput handleSendMsg={handleSendMsg} />
<ChatInput handleSendMsg={handleSendMsg} handleSendFile={handleSendFile} />
</Container>
);
}
88 changes: 81 additions & 7 deletions public/src/components/ChatInput.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import React, { useState } from "react";
import { BsEmojiSmileFill } from "react-icons/bs";
import { IoMdSend } from "react-icons/io";
import { MdAttachFile } from "react-icons/md"; // Import attachment icon
import styled from "styled-components";
import Picker from "emoji-picker-react";
import axios from "axios"; // Import Axios for HTTP requests
import { useEffect } from "react/cjs/react.production.min";

export default function ChatInput({ handleSendMsg }) {
const [msg, setMsg] = useState("");
const [showEmojiPicker, setShowEmojiPicker] = useState(false);
const [file, setFile] = useState(null); // State to handle file

const handleEmojiPickerhideShow = () => {
setShowEmojiPicker(!showEmojiPicker);
};
@@ -17,11 +22,42 @@ export default function ChatInput({ handleSendMsg }) {
setMsg(message);
};

const sendChat = (event) => {
const handleFileChange = (event) => {
setFile(event.target.files[0]); // Save the selected file to state
};

const sendChat = async (event) => {
event.preventDefault();
if (msg.length > 0) {
handleSendMsg(msg);
setMsg("");

let messageData = {msg} ; // Initialize the message data

// Send file if exists
if (file) {
const formData = new FormData();

formData.append("file", file);

try {
const res = await axios.post("http://127.0.0.1:5000/upload", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
});

const fileData = res.data;
console.log("File uploaded successfully: ", fileData);

messageData.fileUrl = fileData.filePath;
setFile(null);
} catch (err) {
console.error("File upload failed: ", err);
}
}

// Send message and file URL to the parent component
if (msg.length > 0 || messageData.fileUrl) {
handleSendMsg(messageData);
setMsg(""); // Clear message after sending
}
};

@@ -36,10 +72,19 @@ export default function ChatInput({ handleSendMsg }) {
<form className="input-container" onSubmit={(event) => sendChat(event)}>
<input
type="text"
placeholder="type your message here"
placeholder={file ? "File selected" : "Type a message"}
onChange={(e) => setMsg(e.target.value)}
value={msg}
/>
<label htmlFor="file-upload" className="file-attach">
<MdAttachFile />
</label>
<input
id="file-upload"
type="file"
style={{ display: "none" }} // Hide the default file input
onChange={handleFileChange}
/>
<button type="submit">
<IoMdSend />
</button>
@@ -48,6 +93,28 @@ export default function ChatInput({ handleSendMsg }) {
);
}

export function ChatMessage({ message }) {

return (
<div className="chat-message">
<p>{message?.msg || "Hrllo"}</p>
{message?.fileUrl && (
<div className="file-attachment">
{/* Render the file URL */}
<a href={`http://localhost:5000${message?.fileUrl}`} target="_blank" rel="noopener noreferrer">
{/* {message?.fileUrl?.endsWith(".png") || message?.fileUrl?.endsWith(".jpg") ? (
<img src={`http://localhost:5000${message?.fileUrl}`} alt="attachment" />
) : (
"Download File"
)} */}
</a>
</div>
)}
</div>
);
}


const Container = styled.div`
display: grid;
align-items: center;
@@ -103,10 +170,10 @@ const Container = styled.div`
border-radius: 2rem;
display: flex;
align-items: center;
gap: 2rem;
gap: 1rem;
background-color: #ffffff34;
input {
width: 90%;
width: 75%;
height: 60%;
background-color: transparent;
color: white;
@@ -121,6 +188,13 @@ const Container = styled.div`
outline: none;
}
}
.file-attach {
cursor: pointer;
svg {
font-size: 1.5rem;
color: #9a86f3;
}
}
button {
padding: 0.3rem 2rem;
border-radius: 2rem;
2 changes: 2 additions & 0 deletions public/src/utils/APIRoutes.js
Original file line number Diff line number Diff line change
@@ -6,3 +6,5 @@ export const allUsersRoute = `${host}/api/auth/allusers`;
export const sendMessageRoute = `${host}/api/messages/addmsg`;
export const recieveMessageRoute = `${host}/api/messages/getmsg`;
export const setAvatarRoute = `${host}/api/auth/setavatar`;

export const sendFileRoute = `${host}/upload`; // Add this
Loading
Oops, something went wrong.