diff --git a/backend/controllers/message.js b/backend/controllers/message.js
index 08a6651..fac431b 100644
--- a/backend/controllers/message.js
+++ b/backend/controllers/message.js
@@ -35,6 +35,10 @@ exports.getContactMessages = async (req, res, next) => {
const io = getIO();
const { contactId } = req.params;
+ const { search, page = 1 } = req.query;
+
+ let limit = 5;
+ let offset = limit * (page - 1);
try {
const contact = await Contact.findByPk(contactId);
@@ -45,9 +49,14 @@ exports.getContactMessages = async (req, res, next) => {
}
setMessagesAsRead(contactId);
- const contactMessages = await contact.getMessages();
- return res.json(contactMessages);
+ const contactMessages = await contact.getMessages({
+ limit,
+ offset,
+ order: [["createdAt", "DESC"]],
+ });
+
+ return res.json(contactMessages.reverse());
} catch (err) {
next(err);
}
diff --git a/backend/controllers/session.json b/backend/controllers/session.json
index 6d94970..38138e9 100644
--- a/backend/controllers/session.json
+++ b/backend/controllers/session.json
@@ -1 +1 @@
-{"WABrowserId":"\"W5pw0Llb60mSeV7WOHnk8A==\"","WASecretBundle":"{\"key\":\"alDLbPjonDFzCh5PEPql9cy59LNh1HFG/AZJVoucuYI=\",\"encKey\":\"FQ1MZ2eIH9hKV4dqFoBYTv1/89aopcMAa4CXgh/9csM=\",\"macKey\":\"alDLbPjonDFzCh5PEPql9cy59LNh1HFG/AZJVoucuYI=\"}","WAToken1":"\"cCkFiHM1JR5ck9OMV+WCiBG6QLCjsCjifdel3jRQ56k=\"","WAToken2":"\"1@0Y7HKBGDZWNuaYV7LiEwm0Y8xzlGoUGoyI8OD/KWjEH7UqVxJWfeT+pMNF4XBO7LeyEjpXVljC6rvQ==\""}
\ No newline at end of file
+{"WABrowserId":"\"W5pw0Llb60mSeV7WOHnk8A==\"","WASecretBundle":"{\"key\":\"alDLbPjonDFzCh5PEPql9cy59LNh1HFG/AZJVoucuYI=\",\"encKey\":\"FQ1MZ2eIH9hKV4dqFoBYTv1/89aopcMAa4CXgh/9csM=\",\"macKey\":\"alDLbPjonDFzCh5PEPql9cy59LNh1HFG/AZJVoucuYI=\"}","WAToken1":"\"GvHbBS6HkZD8f5nYpOxt5qsna4XaDx3JPsjoxwKiM6g=\"","WAToken2":"\"1@P1h9eDyW0m0ILzNfgs6sEF35E66OndfdlOjm3oYzeV13cg82FjBbRvhsma9+p5+/R7zjMUv6L+l/gg==\""}
\ No newline at end of file
diff --git a/backend/controllers/wbotMessageListener.js b/backend/controllers/wbotMessageListener.js
index 0cd0cdf..69212fe 100644
--- a/backend/controllers/wbotMessageListener.js
+++ b/backend/controllers/wbotMessageListener.js
@@ -84,23 +84,27 @@ const wbotMessageListener = () => {
}
});
- wbot.on("message_ack", (msg, ack) => {
- // console.log("alteração do ack da msg", msg);
+ wbot.on("message_ack", async (msg, ack) => {
try {
- const result = Message.update({ ack: ack }, { where: { id: msg.id.id } });
-
- if (!result) {
+ const messageToUpdate = await Message.findOne({
+ where: { id: msg.id.id },
+ });
+ if (!messageToUpdate) {
const error = new Error(
- "Erro ao definir as mensagens como lidas no banco de dados"
+ "Erro ao alterar o ack da mensagem no banco de dados"
);
error.satusCode = 501;
throw error;
}
+ await messageToUpdate.update({ ack: ack });
+
+ io.to(messageToUpdate.contactId).emit("appMessage", {
+ action: "update",
+ message: messageToUpdate,
+ });
} catch (err) {
console.log(err);
}
-
- console.log("ack da msg", ack);
});
};
diff --git a/backend/middleware/is-auth.js b/backend/middleware/is-auth.js
index 7841141..c4800a1 100644
--- a/backend/middleware/is-auth.js
+++ b/backend/middleware/is-auth.js
@@ -7,6 +7,7 @@ module.exports = (req, res, next) => {
decodedToken = jwt.verify(token, "mysecret");
} catch (err) {
err.statusCode = 401;
+ err.message = "invalidToken";
next(err);
}
diff --git a/backend/util/database.js b/backend/util/database.js
index 0123800..7651be1 100644
--- a/backend/util/database.js
+++ b/backend/util/database.js
@@ -6,6 +6,7 @@ const sequelize = new Sequelize("econo_whatsbot", "root", "nodecomplete", {
collate: "utf8mb4_bin",
},
dialect: "mysql",
+ timezone: "-03:00",
host: "localhost",
logging: false,
});
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 9d961e4..acea429 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -8691,6 +8691,14 @@
"resolved": "https://registry.npmjs.org/moment/-/moment-2.26.0.tgz",
"integrity": "sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw=="
},
+ "moment-timezone": {
+ "version": "0.5.31",
+ "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz",
+ "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==",
+ "requires": {
+ "moment": ">= 2.9.0"
+ }
+ },
"move-concurrently": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index b3befac..308b5af 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -11,6 +11,7 @@
"bootstrap": "^4.5.0",
"emoji-mart": "^3.0.0",
"moment": "^2.26.0",
+ "moment-timezone": "^0.5.31",
"react": "^16.13.1",
"react-audio-player": "^0.13.0",
"react-bootstrap": "^1.0.1",
diff --git a/frontend/src/components/MessageSearch/useMessageSerach.js b/frontend/src/components/MessageSearch/useMessageSerach.js
new file mode 100644
index 0000000..aa44e04
--- /dev/null
+++ b/frontend/src/components/MessageSearch/useMessageSerach.js
@@ -0,0 +1,22 @@
+import { useEffect, useState } from "react";
+import api from "../../util/api";
+
+const useMessageSerach = (query, pageNumber) => {
+ useEffect(() => {
+ const fetchMessages = async () => {
+ try {
+ const res = await api.get("/messages/" + contactId, {
+ headers: { Authorization: "Bearer " + token },
+ params: { serach: query, page: pageNumber },
+ });
+ setListMessages(res.data);
+ } catch (err) {
+ alert(err);
+ }
+ };
+ }, [query, pageNumber]);
+
+ return null;
+};
+
+export default useMessageSerach;
diff --git a/frontend/src/pages/Chat/Chat.js b/frontend/src/pages/Chat/Chat.js
index f59fa69..0f71c8f 100644
--- a/frontend/src/pages/Chat/Chat.js
+++ b/frontend/src/pages/Chat/Chat.js
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react";
-import "./Chat.css";
+import { useHistory } from "react-router-dom";
import api from "../../util/api";
import profilePic from "../../Images/canove.png";
import profileDefaultPic from "../../Images/profile_default.png";
@@ -10,12 +10,15 @@ import LogedinNavbar from "../../components/Navbar/LogedinNavbar";
import DefaultNavbar from "../../components/Navbar/DefaultNavbar";
import ChatBox from "../ChatBox/ChatBox";
+import "./Chat.css";
// let socket;
const Chat = ({ showToast }) => {
const token = localStorage.getItem("token");
const username = localStorage.getItem("username");
+ const history = useHistory();
+
const [currentPeerContact, setCurrentPeerContact] = useState(null);
const [contacts, setContacts] = useState([]);
const [displayedContacts, setDisplayedContacts] = useState([]);
@@ -30,11 +33,18 @@ const Chat = ({ showToast }) => {
setContacts(res.data);
setDisplayedContacts(res.data);
} catch (err) {
- alert(err.response.data.message);
+ if (err.response.data.message === "invalidToken") {
+ localStorage.removeItem("token");
+ localStorage.removeItem("username");
+ localStorage.removeItem("userId");
+ history.push("/login");
+ alert("Sessão expirada, por favor, faça login novamente.");
+ }
+ console.log(err);
}
};
fetchContacts();
- }, [currentPeerContact, token, notification]);
+ }, [currentPeerContact, token, notification, history]);
useEffect(() => {
const socket = openSocket("http://localhost:8080");
@@ -42,7 +52,6 @@ const Chat = ({ showToast }) => {
socket.emit("joinNotification");
socket.on("contact", data => {
- console.log("mensagem de um novo contato");
if (data.action === "create") {
addContact(data.contact);
setNotification(prevState => !prevState);
@@ -50,7 +59,6 @@ const Chat = ({ showToast }) => {
});
socket.on("appMessage", data => {
- console.log("mensagem de contato existente");
setNotification(prevState => !prevState);
// handleUnreadMessages(data.message.contactId);
});
diff --git a/frontend/src/pages/ChatBox/ChatBox.css b/frontend/src/pages/ChatBox/ChatBox.css
index b3a391c..491581a 100644
--- a/frontend/src/pages/ChatBox/ChatBox.css
+++ b/frontend/src/pages/ChatBox/ChatBox.css
@@ -171,40 +171,43 @@ input::placeholder {
/* View item message */
.viewItemRight {
+ margin-right: 20px;
+ margin-top: 5px;
min-width: 100px;
max-width: 600px;
height: auto;
-
- margin-right: 20px;
- margin-top: 5px;
- background-color: #dcf8c6;
+ display: block;
+ position: relative;
align-self: flex-end;
+ text-align: left;
+ background-color: #dcf8c6;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
border-bottom-left-radius: 8px;
border-bottom-right-radius: 0px;
- padding-left: 20px;
- padding-right: 20px;
- padding-top: 10px;
- padding-bottom: 10px;
- color: #203152;
box-shadow: 0 5px 5px #808888;
+ padding-left: 10px;
+ padding-right: 40px;
+ padding-top: 5px;
+ padding-bottom: 0px;
+ color: #203152;
}
.viewItemRight2 {
- width: 300px;
- padding: 4px;
+ width: 315px;
+ padding: 8px;
height: auto;
background-color: #dcf8c6;
align-self: flex-end;
margin-right: 20px;
margin-top: 10px;
+ display: block;
+ position: relative;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
border-bottom-left-radius: 8px;
border-bottom-right-radius: 0px;
color: #203152;
- /* text-align: left; */
box-shadow: 0 5px 5px #808888;
}
@@ -214,6 +217,8 @@ input::placeholder {
align-self: flex-end;
margin-right: 20px;
margin-top: 10px;
+ display: block;
+ position: relative;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
border-bottom-left-radius: 8px;
@@ -247,33 +252,37 @@ input::placeholder {
}
.viewItemLeft {
+ margin-left: 20px;
+ margin-top: 5px;
min-width: 100px;
max-width: 600px;
height: auto;
+ display: block;
+ position: relative;
- margin-left: 20px;
- margin-top: 5px;
background-color: #ffffff;
align-self: flex-start;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
border-bottom-left-radius: 0px;
border-bottom-right-radius: 8px;
- padding-left: 20px;
- padding-right: 20px;
- padding-top: 10px;
- padding-bottom: 10px;
+ padding-left: 10px;
+ padding-right: 40px;
+ padding-top: 5px;
+ padding-bottom: 0px;
color: #303030;
box-shadow: 0 5px 5px #808888;
}
.viewItemLeft2 {
- width: 300px;
- padding: 4px;
+ width: 315px;
+ padding: 8px;
height: auto;
+ background-color: #ffffff;
margin-left: 10px;
margin-top: 10px;
- background-color: #ffffff;
+ display: block;
+ position: relative;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
border-bottom-left-radius: 0px;
@@ -287,6 +296,8 @@ input::placeholder {
margin-top: 10px;
width: 300px;
height: auto;
+ display: block;
+ position: relative;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
border-bottom-left-radius: 0px;
@@ -330,10 +341,16 @@ input::placeholder {
.textContentItem {
font-size: 16px;
overflow-wrap: break-word;
+ padding: 0px 50px 0px 0px;
}
-.messageAck {
- font-size: 10px;
+.timestamp {
+ font-size: 11px;
+ position: absolute;
+ bottom: 5px;
+ right: 10px;
+ text-transform: uppercase;
+ color: #999;
}
.viewListContentChat div:last-child {
@@ -354,7 +371,7 @@ input::placeholder {
.imgItemLeft {
object-fit: cover;
- width: 300px;
+ width: 290px;
height: 300px;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
diff --git a/frontend/src/pages/ChatBox/ChatBox.js b/frontend/src/pages/ChatBox/ChatBox.js
index cf619b8..580d546 100644
--- a/frontend/src/pages/ChatBox/ChatBox.js
+++ b/frontend/src/pages/ChatBox/ChatBox.js
@@ -1,10 +1,13 @@
-import React, { useState, useEffect } from "react";
-import { Card } from "react-bootstrap";
-import { FiPaperclip, FiSend, FiX, FiSmile, FiDownload } from "react-icons/fi";
+import React, { useState, useEffect, useRef } from "react";
+// import { Card } from "react-bootstrap"; alterei pra DIV, remover caso não dê problemas
+import { FiPaperclip, FiSend, FiX, FiSmile } from "react-icons/fi";
import { RiSendPlane2Line } from "react-icons/ri";
+import { BsCheck, BsCheckAll, BsClock } from "react-icons/bs";
+import { FaFileDownload } from "react-icons/fa";
import "emoji-mart/css/emoji-mart.css";
import { Picker } from "emoji-mart";
import ModalImage from "react-modal-image";
+import moment from "moment-timezone";
import api from "../../util/api";
import openSocket from "socket.io-client";
@@ -15,7 +18,12 @@ import ScrollToBottom from "react-scroll-to-bottom";
import "react-toastify/dist/ReactToastify.css";
import "./ChatBox.css";
-// let socket;
+
+// const executeScroll = myRef =>
+// myRef.current.scrollIntoView({
+// // behavior: "smooth",
+// block: "end",
+// });
const ChatBox = ({ currentPeerContact }) => {
const SERVER_URL = "http://localhost:8080/";
@@ -25,19 +33,29 @@ const ChatBox = ({ currentPeerContact }) => {
const username = localStorage.getItem("username");
const token = localStorage.getItem("token");
const mediaInitialState = { preview: "", raw: "", name: "" };
+ // const [isLoading, setIsLoading] = useState(true);
const [listMessages, setListMessages] = useState([]);
const [inputMessage, setInputMessage] = useState("");
const [media, setMedia] = useState(mediaInitialState);
const [showEmoji, setShowEmoji] = useState(false);
+ // let lastMessageRef = useRef();
+
+ // useEffect(() => {
+ // executeScroll(lastMessageRef);
+ // }, [isLoading]);
+
useEffect(() => {
const fetchMessages = async () => {
+ // setIsLoading(true);
try {
const res = await api.get("/messages/" + contactId, {
headers: { Authorization: "Bearer " + token },
+ params: { page: 3 },
});
setListMessages(res.data);
+ // setIsLoading(false);
} catch (err) {
alert(err);
}
@@ -58,9 +76,13 @@ const ChatBox = ({ currentPeerContact }) => {
socket.emit("joinChatBox", contactId, () => {});
socket.on("appMessage", data => {
+ // setIsLoading(true);
if (data.action === "create") {
addMessage(data.message);
+ } else if (data.action === "update") {
+ updateMessageAck(data.message);
}
+ // setIsLoading(false);
});
return () => {
@@ -68,6 +90,18 @@ const ChatBox = ({ currentPeerContact }) => {
};
}, [contactId]);
+ const updateMessageAck = message => {
+ let id = message.id;
+ setListMessages(prevState => {
+ console.log("mudando o ack da mensagem");
+ let aux = [...prevState];
+ let messageIndex = aux.findIndex(message => message.id === id);
+ aux[messageIndex].ack = message.ack;
+
+ return aux;
+ });
+ };
+
const addMessage = message => {
setListMessages(prevState => [...prevState, message]);
};
@@ -140,10 +174,24 @@ const ChatBox = ({ currentPeerContact }) => {
console.log(listMessages);
+ const renderMsgAck = message => {
+ //todo remove timestamp logic from main return and adopt moment to timestamps
+ if (message.ack === 0) {
+ return
{currentPeerContact.name}
Status do contato
- + Status do contato