import React, { useState, useEffect, useReducer, useRef } from "react"; import { isSameDay, parseISO, format } from "date-fns"; import openSocket from "socket.io-client"; import clsx from "clsx"; import { green } from "@material-ui/core/colors"; import { Button, CircularProgress, Divider, IconButton, makeStyles, } from "@material-ui/core"; import { AccessTime, Block, Done, DoneAll, ExpandMore, GetApp, } from "@material-ui/icons"; import MarkdownWrapper from "../MarkdownWrapper"; import ModalImageCors from "../ModalImageCors"; import MessageOptionsMenu from "../MessageOptionsMenu"; import whatsBackground from "../../assets/wa-background.png"; import api from "../../services/api"; import toastError from "../../errors/toastError"; const useStyles = makeStyles((theme) => ({ messagesListWrapper: { overflow: "hidden", position: "relative", display: "flex", flexDirection: "column", flexGrow: 1, }, messagesList: { backgroundImage: `url(${whatsBackground})`, display: "flex", flexDirection: "column", flexGrow: 1, padding: "20px 20px 20px 20px", overflowY: "scroll", [theme.breakpoints.down("sm")]: { paddingBottom: "90px", }, ...theme.scrollbarStyles, }, circleLoading: { color: green[500], position: "absolute", opacity: "70%", top: 0, left: "50%", marginTop: 12, }, messageLeft: { marginRight: 20, marginTop: 2, minWidth: 100, maxWidth: 600, height: "auto", display: "block", position: "relative", "&:hover #messageActionsButton": { display: "flex", position: "absolute", top: 0, right: 0, }, whiteSpace: "pre-wrap", backgroundColor: "#ffffff", color: "#303030", alignSelf: "flex-start", borderTopLeftRadius: 0, borderTopRightRadius: 8, borderBottomLeftRadius: 8, borderBottomRightRadius: 8, paddingLeft: 5, paddingRight: 5, paddingTop: 5, paddingBottom: 0, boxShadow: "0 1px 1px #b3b3b3", }, quotedContainerLeft: { margin: "-3px -80px 6px -6px", overflow: "hidden", backgroundColor: "#f0f0f0", borderRadius: "7.5px", display: "flex", position: "relative", }, quotedMsg: { padding: 10, maxWidth: 300, height: "auto", display: "block", whiteSpace: "pre-wrap", overflow: "hidden", }, quotedSideColorLeft: { flex: "none", width: "4px", backgroundColor: "#6bcbef", }, messageRight: { marginLeft: 20, marginTop: 2, minWidth: 100, maxWidth: 600, height: "auto", display: "block", position: "relative", "&:hover #messageActionsButton": { display: "flex", position: "absolute", top: 0, right: 0, }, whiteSpace: "pre-wrap", backgroundColor: "#dcf8c6", color: "#303030", alignSelf: "flex-end", borderTopLeftRadius: 8, borderTopRightRadius: 8, borderBottomLeftRadius: 8, borderBottomRightRadius: 0, paddingLeft: 5, paddingRight: 5, paddingTop: 5, paddingBottom: 0, boxShadow: "0 1px 1px #b3b3b3", }, quotedContainerRight: { margin: "-3px -80px 6px -6px", overflowY: "hidden", backgroundColor: "#cfe9ba", borderRadius: "7.5px", display: "flex", position: "relative", }, quotedMsgRight: { padding: 10, maxWidth: 300, height: "auto", whiteSpace: "pre-wrap", }, quotedSideColorRight: { flex: "none", width: "4px", backgroundColor: "#35cd96", }, messageActionsButton: { display: "none", position: "relative", color: "#999", zIndex: 1, backgroundColor: "inherit", opacity: "90%", "&:hover, &.Mui-focusVisible": { backgroundColor: "inherit" }, }, messageContactName: { display: "flex", color: "#6bcbef", fontWeight: 500, }, textContentItem: { overflowWrap: "break-word", padding: "3px 80px 6px 6px", }, textContentItemDeleted: { fontStyle: "italic", color: "rgba(0, 0, 0, 0.36)", overflowWrap: "break-word", padding: "3px 80px 6px 6px", }, messageMedia: { objectFit: "cover", width: 250, height: 200, borderTopLeftRadius: 8, borderTopRightRadius: 8, borderBottomLeftRadius: 8, borderBottomRightRadius: 8, }, timestamp: { fontSize: 11, position: "absolute", bottom: 0, right: 5, color: "#999", }, dailyTimestamp: { alignItems: "center", textAlign: "center", alignSelf: "center", width: "110px", backgroundColor: "#e1f3fb", margin: "10px", borderRadius: "10px", boxShadow: "0 1px 1px #b3b3b3", }, dailyTimestampText: { color: "#808888", padding: 8, alignSelf: "center", marginLeft: "0px", }, ackIcons: { fontSize: 18, verticalAlign: "middle", marginLeft: 4, }, deletedIcon: { fontSize: 18, verticalAlign: "middle", marginRight: 4, }, ackDoneAllIcon: { color: green[500], fontSize: 18, verticalAlign: "middle", marginLeft: 4, }, downloadMedia: { display: "flex", alignItems: "center", justifyContent: "center", backgroundColor: "inherit", padding: 10, }, })); const reducer = (state, action) => { if (action.type === "LOAD_MESSAGES") { const messages = action.payload; const newMessages = []; messages.forEach((message) => { const messageIndex = state.findIndex((m) => m.id === message.id); if (messageIndex !== -1) { state[messageIndex] = message; } else { newMessages.push(message); } }); return [...newMessages, ...state]; } if (action.type === "ADD_MESSAGE") { const newMessage = action.payload; const messageIndex = state.findIndex((m) => m.id === newMessage.id); if (messageIndex !== -1) { state[messageIndex] = newMessage; } else { state.push(newMessage); // console.log(' TESTANDO NOVA MENSAGEM: ', newMessage) } return [...state]; } if (action.type === "UPDATE_MESSAGE") { const messageToUpdate = action.payload; const messageIndex = state.findIndex((m) => m.id === messageToUpdate.id); if (messageIndex !== -1) { state[messageIndex] = messageToUpdate; } return [...state]; } if (action.type === "RESET") { return []; } }; const MessagesList = ({ ticketId, isGroup }) => { const classes = useStyles(); const [messagesList, dispatch] = useReducer(reducer, []); const [pageNumber, setPageNumber] = useState(1); const [hasMore, setHasMore] = useState(false); const [loading, setLoading] = useState(false); const lastMessageRef = useRef(); const [selectedMessage, setSelectedMessage] = useState({}); const [anchorEl, setAnchorEl] = useState(null); const messageOptionsMenuOpen = Boolean(anchorEl); const currentTicketId = useRef(ticketId); useEffect(() => { dispatch({ type: "RESET" }); setPageNumber(1); currentTicketId.current = ticketId; }, [ticketId]); useEffect(() => { setLoading(true); const delayDebounceFn = setTimeout(() => { const fetchMessages = async () => { try { const { data } = await api.get("/messages/" + ticketId, { params: { pageNumber }, }); if (currentTicketId.current === ticketId) { dispatch({ type: "LOAD_MESSAGES", payload: data.messages }); setHasMore(data.hasMore); setLoading(false); } if (pageNumber === 1 && data.messages.length > 1) { scrollToBottom(); } } catch (err) { setLoading(false); toastError(err); } }; fetchMessages(); }, 500); return () => { clearTimeout(delayDebounceFn); }; }, [pageNumber, ticketId]); useEffect(() => { const socket = openSocket(process.env.REACT_APP_BACKEND_URL); socket.on("connect", () => socket.emit("joinChatBox", ticketId)); socket.on("appMessage", (data) => { if (data.action === "create") { dispatch({ type: "ADD_MESSAGE", payload: data.message }); // console.log('* NOVA MENSAGEM CAP: ', data.message) scrollToBottom(); } if (data.action === "update") { dispatch({ type: "UPDATE_MESSAGE", payload: data.message }); } }); return () => { socket.disconnect(); }; }, [ticketId]); const loadMore = () => { setPageNumber((prevPageNumber) => prevPageNumber + 1); }; const scrollToBottom = () => { if (lastMessageRef.current) { lastMessageRef.current.scrollIntoView({}); } }; const handleScroll = (e) => { if (!hasMore) return; const { scrollTop } = e.currentTarget; if (scrollTop === 0) { document.getElementById("messagesList").scrollTop = 1; } if (loading) { return; } if (scrollTop < 50) { loadMore(); } }; const handleOpenMessageOptionsMenu = (e, message) => { setAnchorEl(e.currentTarget); setSelectedMessage(message); }; const handleCloseMessageOptionsMenu = (e) => { setAnchorEl(null); }; const checkMessageMedia = (message) => { if (message.mediaType === "image") { return ; } if (message.mediaType === "audio") { return ( ); } if (message.mediaType === "video") { return (