import React, { useState, useEffect, useRef } from "react"; import { useParams, useHistory } from "react-router-dom"; import { toast } from "react-toastify"; import { isSameDay, parseISO, format } from "date-fns"; import openSocket from "socket.io-client"; import InfiniteScrollReverse from "react-infinite-scroll-reverse"; import ModalImage from "react-modal-image"; import { makeStyles } from "@material-ui/core/styles"; import clsx from "clsx"; import AccessTimeIcon from "@material-ui/icons/AccessTime"; import CircularProgress from "@material-ui/core/CircularProgress"; import DoneIcon from "@material-ui/icons/Done"; import DoneAllIcon from "@material-ui/icons/DoneAll"; import Card from "@material-ui/core/Card"; import CardHeader from "@material-ui/core/CardHeader"; import ReplayIcon from "@material-ui/icons/Replay"; import Avatar from "@material-ui/core/Avatar"; import Button from "@material-ui/core/Button"; import Paper from "@material-ui/core/Paper"; import { green } from "@material-ui/core/colors"; import Skeleton from "@material-ui/lab/Skeleton"; import IconButton from "@material-ui/core/IconButton"; import MoreVertIcon from "@material-ui/icons/MoreVert"; import api from "../../services/api"; import ContactDrawer from "../ContactDrawer"; import whatsBackground from "../../assets/wa-background.png"; import LinkifyWithTargetBlank from "../LinkifyWithTargetBlank"; import MessageInput from "../MessageInput/"; import TicketOptionsMenu from "../TicketOptionsMenu"; const drawerWidth = 320; const useStyles = makeStyles(theme => ({ root: { display: "flex", height: "100%", position: "relative", overflow: "hidden", }, mainWrapper: { flex: 1, height: "100%", display: "flex", flexDirection: "column", overflow: "hidden", borderTopLeftRadius: 0, borderBottomLeftRadius: 0, borderLeft: "0", marginRight: -drawerWidth, transition: theme.transitions.create("margin", { easing: theme.transitions.easing.sharp, duration: theme.transitions.duration.leavingScreen, }), }, mainWrapperShift: { borderTopRightRadius: 0, borderBottomRightRadius: 0, transition: theme.transitions.create("margin", { easing: theme.transitions.easing.easeOut, duration: theme.transitions.duration.enteringScreen, }), marginRight: 0, }, messagesHeader: { display: "flex", // cursor: "pointer", backgroundColor: "#eee", flex: "none", borderBottom: "1px solid rgba(0, 0, 0, 0.12)", }, actionButtons: { marginRight: 6, flex: "none", alignSelf: "center", marginLeft: "auto", "& > *": { margin: theme.spacing(1), }, }, 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", "&::-webkit-scrollbar": { width: "8px", height: "8px", }, "&::-webkit-scrollbar-thumb": { // borderRadius: "2px", boxShadow: "inset 0 0 6px rgba(0, 0, 0, 0.3)", backgroundColor: "#e8e8e8", }, }, 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", 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", }, messageRight: { marginLeft: 20, marginTop: 2, minWidth: 100, maxWidth: 600, height: "auto", display: "block", position: "relative", 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", }, textContentItem: { 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, }, ackDoneAllIcon: { color: green[500], fontSize: 18, verticalAlign: "middle", marginLeft: 4, }, })); const MessagesList = () => { const { ticketId } = useParams(); const history = useHistory(); const classes = useStyles(); const token = localStorage.getItem("token"); const userId = +localStorage.getItem("userId"); const [loading, setLoading] = useState(true); const [contact, setContact] = useState({}); const [ticket, setTicket] = useState({}); const [messagesList, setMessagesList] = useState([]); const [hasMore, setHasMore] = useState(false); const [pageNumber, setPageNumber] = useState(0); const [drawerOpen, setDrawerOpen] = useState(false); const lastMessageRef = useRef(); const [anchorEl, setAnchorEl] = useState(null); const moreMenuOpen = Boolean(anchorEl); useEffect(() => { setLoading(true); const delayDebounceFn = setTimeout(() => { const fetchMessages = async () => { try { const res = await api.get("/messages/" + ticketId, { params: { pageNumber }, }); setContact(res.data.ticket.contact); setTicket(res.data.ticket); setMessagesList(prevMessages => { return [...res.data.messages, ...prevMessages]; }); setHasMore(res.data.messages.length > 0); setLoading(false); if (pageNumber === 1 && res.data.messages.length > 1) { scrollToBottom(); } } catch (err) { console.log(err); toast.error("Ticket não encontrado"); history.push("/chat"); } }; fetchMessages(); }, 1000); return () => clearTimeout(delayDebounceFn); }, [pageNumber, ticketId, token, history]); useEffect(() => { const socket = openSocket(process.env.REACT_APP_BACKEND_URL); socket.emit("joinChatBox", ticketId, () => {}); socket.on("appMessage", data => { if (data.action === "create") { addMessage(data.message); scrollToBottom(); } else if (data.action === "update") { updateMessageAck(data.message); } }); socket.on("contact", data => { if (data.action === "update") { setContact(data.contact); } }); return () => { socket.disconnect(); setPageNumber(1); setMessagesList([]); }; }, [ticketId]); const loadMore = () => { setPageNumber(prevPageNumber => prevPageNumber + 1); }; const addMessage = message => { setMessagesList(prevState => { if (prevState.length >= 20) { let aux = [...prevState]; aux.shift(); aux.push(message); return aux; } else { return [...prevState, message]; } }); }; const updateMessageAck = message => { let id = message.id; setMessagesList(prevState => { let aux = [...prevState]; let messageIndex = aux.findIndex(message => message.id === id); if (messageIndex !== -1) { aux[messageIndex].ack = message.ack; } return aux; }); }; const scrollToBottom = () => { if (lastMessageRef.current) { lastMessageRef.current.scrollIntoView({}); } }; const checkMessaageMedia = message => { if (message.mediaType === "image") { return ( ); } if (message.mediaType === "audio") { return ( ); } if (message.mediaType === "video") { return (