diff --git a/backend/controllers/message.js b/backend/controllers/message.js index 2429696..e773eff 100644 --- a/backend/controllers/message.js +++ b/backend/controllers/message.js @@ -48,7 +48,7 @@ exports.getContactMessages = async (req, res, next) => { ), }; - let limit = 10; + let limit = 20; let offset = limit * (pageNumber - 1); try { diff --git a/backend/controllers/session.json b/backend/controllers/session.json index 2fd99be..aa161d2 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":"\"SNPReadfNoQL/i4IzN6BWtMxFsAkB5S1rvYwNsEywWs=\"","WAToken2":"\"1@6K32SNdV0LtNeieRuXYWmwUaGMsC18JBxEIlraW3rBgxeZ4DbiD2WtYs1Ekv/QO5RDPieBfHuWzZPw==\""} \ No newline at end of file +{"WABrowserId":"\"W5pw0Llb60mSeV7WOHnk8A==\"","WASecretBundle":"{\"key\":\"alDLbPjonDFzCh5PEPql9cy59LNh1HFG/AZJVoucuYI=\",\"encKey\":\"FQ1MZ2eIH9hKV4dqFoBYTv1/89aopcMAa4CXgh/9csM=\",\"macKey\":\"alDLbPjonDFzCh5PEPql9cy59LNh1HFG/AZJVoucuYI=\"}","WAToken1":"\"fpvmzsdJ0KcZfIl5G4ZTqGxvg474wEfhECz4btE0TDc=\"","WAToken2":"\"1@ueYAfj0uRoSok18uTv8xzCWlvo45N3cefA6tAkUX2iJXP+AQY35sLDxyv1F+q34Ntf9vUcoc4tQG2Q==\""} \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json index acea429..594d0e1 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -11118,6 +11118,14 @@ "camelcase": "^5.0.0" } }, + "react-infinite-scroll-reverse": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/react-infinite-scroll-reverse/-/react-infinite-scroll-reverse-1.0.3.tgz", + "integrity": "sha512-sbACmGs42B06eVnsqlCh3z5Qs7/RepuFSEPc31ByrLDFXurhZYdVT4lCB/IvMugevIWwVIOsiN/Pr0JBfhm+IQ==", + "requires": { + "prop-types": "15.7.2" + } + }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index 308b5af..7420d10 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -17,6 +17,7 @@ "react-bootstrap": "^1.0.1", "react-dom": "^16.13.1", "react-icons": "^3.10.0", + "react-infinite-scroll-reverse": "^1.0.3", "react-loading": "^2.0.3", "react-modal-image": "^2.5.0", "react-moment": "^0.9.7", diff --git a/frontend/src/components/MessageSearch/useMessageSerach.js b/frontend/src/components/MessageSearch/useMessageSerach.js deleted file mode 100644 index 988c01e..0000000 --- a/frontend/src/components/MessageSearch/useMessageSerach.js +++ /dev/null @@ -1,43 +0,0 @@ -import { useEffect, useState } from "react"; -import api from "../../util/api"; - -const useMessageSerach = (query, pageNumber, token, contactId) => { - const [loading, setLoading] = useState(true); - const [error, setError] = useState(false); - const [listMessages, setListMessages] = useState([]); - const [hasMore, setHasMore] = useState(false); - - useEffect(() => setListMessages([]), [contactId, query]); - - useEffect(() => { - console.log(pageNumber); - setLoading(true); - setError(false); - const delayDebounceFn = setTimeout(() => { - console.log(query); - const fetchMessages = async () => { - try { - const res = await api.get("/messages/" + contactId, { - headers: { Authorization: "Bearer " + token }, - params: { searchParam: query, pageNumber: pageNumber }, - }); - setListMessages(prevMessages => { - return [...res.data.messages, ...prevMessages]; - }); - setHasMore(res.data.messages.length > 0); - setLoading(false); - console.log(res.data); - } catch (err) { - console.log(err); - setError(true); - } - }; - fetchMessages(); - }, 1000); - return () => clearTimeout(delayDebounceFn); - }, [query, pageNumber, contactId, token]); - - return { loading, error, listMessages, hasMore, setListMessages }; -}; - -export default useMessageSerach; diff --git a/frontend/src/pages/Chat/Chat.css b/frontend/src/pages/Chat/Chat.css index 93bc603..0edecf9 100644 --- a/frontend/src/pages/Chat/Chat.css +++ b/frontend/src/pages/Chat/Chat.css @@ -47,6 +47,18 @@ font: 14px Arial, sans-serif; } +.viewLoading { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + /* background-color: rgba(255, 255, 255, 0.5); */ + display: flex; + align-items: center; + justify-content: center; +} + /* List user */ .viewListUser { diff --git a/frontend/src/pages/ChatBox/ChatBox.css b/frontend/src/pages/ChatBox/ChatBox.css index 491581a..99453ce 100644 --- a/frontend/src/pages/ChatBox/ChatBox.css +++ b/frontend/src/pages/ChatBox/ChatBox.css @@ -168,6 +168,35 @@ input::placeholder { color: rgb(199, 199, 199); } +.rootsearchbar { + padding: 10px; + width: 300px; + margin-bottom: 10px; + background-color: #f7f7f7; +} + +.input-container { + /* IE10 */ + display: flex; + width: 300px; + margin-bottom: 15px; +} + +.input-field { + width: 300px; + + border-radius: 10px; + + /* margin-right: 85%; */ + border: none !important; + box-shadow: none !important; + outline: none !important; + + width: 100%; + padding: 10px; + text-align: center; +} + /* View item message */ .viewItemRight { @@ -227,7 +256,7 @@ input::placeholder { } .viewWrapItemLeft { - width: 300px; + /* width: 300px; */ text-align: left; align-self: flex-start; margin-left: 20px; @@ -235,13 +264,13 @@ input::placeholder { margin-bottom: -15px; } -.viewWrapItemLeft2 { +.viewWrapItemRight { width: 300px; - align-self: flex-start; + align-self: flex-end; text-align: left; - margin-left: 20px; + /* margin-left: 20px; margin-top: 10px; - margin-bottom: -15px; + margin-bottom: -15px; */ } .viewWrapItemLeft3 { @@ -304,20 +333,7 @@ input::placeholder { border-bottom-right-radius: 8px; color: white; } -.time { - display: flex; - align-items: center; - text-align: center; - margin-left: 400px; - font: italic small-caps bold 15px/30px Georgia, serif; - width: 110px; - background-color: #e1f3fb; - padding-top: 5px; - padding-bottom: 5px; - padding-left: 5px; - padding-right: 5px; - border-radius: 10px; -} + .timesetup { align-items: center; } @@ -379,11 +395,27 @@ input::placeholder { border-bottom-right-radius: 8px; } -.textTimeLeft { +.time { + align-items: center; + text-align: center; + align-self: center; + font: italic small-caps bold 15px/30px Georgia, serif; + width: 110px; + background-color: #e1f3fb; + margin: 10px; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 5px; + padding-right: 5px; + border-radius: 10px; +} + +.textTime { color: #808888; font-size: 12px; font-style: italic; - margin-left: 50px; + align-self: center; + margin-left: 0px; } /* Stickers */ diff --git a/frontend/src/pages/ChatBox/ChatBox.js b/frontend/src/pages/ChatBox/ChatBox.js index 43dc952..ca70cb9 100644 --- a/frontend/src/pages/ChatBox/ChatBox.js +++ b/frontend/src/pages/ChatBox/ChatBox.js @@ -1,10 +1,16 @@ -import React, { useState, useEffect, useRef, useCallback } 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 React, { useState, useEffect } from "react"; +import InfiniteScrollReverse from "react-infinite-scroll-reverse"; +import ReactLoading from "react-loading"; +import { + FiPaperclip, + FiSend, + FiTrash2, + FiSmile, + FiFastForward, + FiFile, +} from "react-icons/fi"; 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"; @@ -14,17 +20,9 @@ import openSocket from "socket.io-client"; import profileDefaultPic from "../../Images/profile_default.png"; import ReactAudioPlayer from "react-audio-player"; -import ScrollToBottom from "react-scroll-to-bottom"; - import "react-toastify/dist/ReactToastify.css"; +import "emoji-mart/css/emoji-mart.css"; import "./ChatBox.css"; -import useMessageSerach from "../../components/MessageSearch/useMessageSerach"; - -// const executeScroll = myRef => -// myRef.current.scrollIntoView({ -// // behavior: "smooth", -// block: "end", -// }); const ChatBox = ({ currentPeerContact }) => { const SERVER_URL = "http://localhost:8080/"; @@ -35,43 +33,42 @@ const ChatBox = ({ currentPeerContact }) => { const token = localStorage.getItem("token"); const mediaInitialState = { preview: "", raw: "", name: "" }; - const [inputMessage, setInputMessage] = useState(""); const [media, setMedia] = useState(mediaInitialState); const [showEmoji, setShowEmoji] = useState(false); + const [loading, setLoading] = useState(true); + const [listMessages, setListMessages] = useState([]); + const [hasMore, setHasMore] = useState(false); + const [searchParam, setSearchParam] = useState(""); + const [pageNumber, setPageNumber] = useState(0); - const [query, setQuery] = useState(""); - const [pageNumber, setPageNumber] = useState(1); + useEffect(() => setListMessages([]), [searchParam]); - const { - listMessages, - setListMessages, - hasMore, - loading, - error, - } = useMessageSerach(query, pageNumber, token, contactId); - - const scrollPosition = useRef(); - const observer = useRef(); - const firstMessageRef = useCallback( - node => { - if (observer.current) observer.current.disconnect(); - observer.current = new IntersectionObserver(entries => { - if (entries[0].isIntersecting && hasMore) { - console.log("Visible"); - setPageNumber(prevPageNumber => prevPageNumber + 1); + useEffect(() => { + setLoading(true); + const delayDebounceFn = setTimeout(() => { + console.log(searchParam); + const fetchMessages = async () => { + try { + const res = await api.get("/messages/" + contactId, { + headers: { Authorization: "Bearer " + token }, + params: { searchParam, pageNumber }, + }); + setListMessages(prevMessages => { + return [...res.data.messages, ...prevMessages]; + }); + setHasMore(res.data.messages.length > 0); + setLoading(false); + console.log(res.data); + } catch (err) { + console.log(err); + alert(err); } - }); - if (node) observer.current.observe(node); - }, - [loading, hasMore] - ); - - // let lastMessageRef = useRef(); - - // useEffect(() => { - // executeScroll(lastMessageRef); - // }, [loading]); + }; + fetchMessages(); + }, 1000); + return () => clearTimeout(delayDebounceFn); + }, [searchParam, pageNumber, contactId, token]); useEffect(() => { const socket = openSocket(SERVER_URL); @@ -79,25 +76,28 @@ 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 () => { socket.disconnect(); setInputMessage(""); - setQuery(""); + setSearchParam(""); setShowEmoji(false); setPageNumber(1); setMedia({}); + setListMessages([]); }; }, [contactId]); + const loadMore = () => { + setPageNumber(prevPageNumber => prevPageNumber + 1); + }; + const updateMessageAck = message => { let id = message.id; setListMessages(prevState => { @@ -180,10 +180,34 @@ const ChatBox = ({ currentPeerContact }) => { }; const handleSearch = e => { - setQuery(e.target.value); + setSearchParam(e.target.value); setPageNumber(1); }; + const checkMessageDay = (message, index) => { + if (index < listMessages.length - 1) { + let messageDay = moment(listMessages[index].createdAt) + .tz("America/Sao_Paulo") + .format("DD"); + + let nextMessageDay = moment(listMessages[index + 1].createdAt) + .tz("America/Sao_Paulo") + .format("DD"); + + if (messageDay < nextMessageDay) { + return ( + +
+ {moment(listMessages[index + 1].createdAt) + .tz("America/Sao_Paulo") + .format("DD/MM/YY")} +
+
+ ); + } + } + }; + const renderMsgAck = message => { //todo remove timestamp logic from main return and adopt moment to timestamps if (message.ack === 0) { @@ -221,7 +245,8 @@ const ChatBox = ({ currentPeerContact }) => { .format("HH:mm")} - + , + checkMessageDay(message, index) ); } else if (message.mediaUrl && message.mediaType === "audio") { viewListMessages.push( @@ -237,7 +262,8 @@ const ChatBox = ({ currentPeerContact }) => { .format("HH:mm")} - + , + checkMessageDay(message, index) ); } else if (message.mediaUrl && message.mediaType === "video") { viewListMessages.push( @@ -255,7 +281,8 @@ const ChatBox = ({ currentPeerContact }) => { .format("HH:mm")} - + , + checkMessageDay(message, index) ); } else if (message.mediaUrl) { viewListMessages.push( @@ -266,7 +293,7 @@ const ChatBox = ({ currentPeerContact }) => { className="textContentItem" > {message.messageBody} - + {moment(message.createdAt) @@ -274,7 +301,8 @@ const ChatBox = ({ currentPeerContact }) => { .format("HH:mm")} - + , + checkMessageDay(message, index) ); } else { viewListMessages.push( @@ -287,10 +315,12 @@ const ChatBox = ({ currentPeerContact }) => { .format("HH:mm")} - + , + checkMessageDay(message, index) ); } - } else { + } // mensagens enviadas + else { if (message.mediaUrl && message.mediaType === "image") { viewListMessages.push(
@@ -310,9 +340,9 @@ const ChatBox = ({ currentPeerContact }) => { {renderMsgAck(message)}
- + , + checkMessageDay(message, index) ); - // mensagens enviadas } else if (message.mediaUrl && message.mediaType === "audio") { viewListMessages.push(
@@ -328,7 +358,8 @@ const ChatBox = ({ currentPeerContact }) => { {renderMsgAck(message)}
- + , + checkMessageDay(message, index) ); } else if (message.mediaUrl && message.mediaType === "video") { viewListMessages.push( @@ -341,7 +372,8 @@ const ChatBox = ({ currentPeerContact }) => { .format("HH:mm")}{" "} {renderMsgAck(message)} - + , + checkMessageDay(message, index) ); } else if (message.mediaUrl) { viewListMessages.push( @@ -352,7 +384,7 @@ const ChatBox = ({ currentPeerContact }) => { className="textContentItem" > {message.messageBody} - + {moment(message.createdAt) @@ -361,25 +393,8 @@ const ChatBox = ({ currentPeerContact }) => { {renderMsgAck(message)} - - ); - } else if (index === 3) { - viewListMessages.push( -
-
- {message.messageBody} - - {moment(message.createdAt) - .tz("America/Sao_Paulo") - .format("HH:mm")}{" "} - {renderMsgAck(message)} - -
-
+ , + checkMessageDay(message, index) ); } else { viewListMessages.push( @@ -393,7 +408,8 @@ const ChatBox = ({ currentPeerContact }) => { {renderMsgAck(message)} - + , + checkMessageDay(message, index) ); } } @@ -408,6 +424,8 @@ const ChatBox = ({ currentPeerContact }) => { } }; + console.log(listMessages); + return (
@@ -420,22 +438,33 @@ const ChatBox = ({ currentPeerContact }) => {

{currentPeerContact.name}

- Status do contato + +

Status do contato

+
-
- +
+
- {/* */} -
+ {renderMessages()} + - {/*
Last Message
*/} -
- {/*
*/} {media.preview ? (
- setMedia(mediaInitialState)} @@ -444,7 +473,7 @@ const ChatBox = ({ currentPeerContact }) => { {media.name} {/* */} - {
)} + {loading ? ( +
+ +
+ ) : null}
); };