import React, { useContext, useState, useEffect, useReducer, useRef } from "react" import { isSameDay, parseISO, format } from "date-fns" //import openSocket from "socket.io-client" import { socket } from "../../services/socket" import clsx from "clsx" import { AuthContext } from "../../context/Auth/AuthContext" 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 VcardPreview from "../VcardPreview" import LocationPreview from "../LocationPreview" import Audio from "../Audio" 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" import { countTicketMsgContext } from "../../context/CountTicketMsgProvider/CountTicketMsgProvider" 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) } 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) const [sendSeen, setSendSeen] = useState(false) const { user } = useContext(AuthContext) const { setCountTicketMsg } = useContext(countTicketMsgContext) useEffect(() => { dispatch({ type: "RESET" }) setPageNumber(1) currentTicketId.current = ticketId }, [ticketId]) useEffect(() => { let url_split let url_ticketId try { url_split = window.location.href.split('tickets') url_ticketId = url_split[url_split.length - 1].match(/\d+/)[0] } catch (error) { console.log('error on try do the send seen: ', error) } if (!url_ticketId) return if (!sendSeen) return const delayDebounceFn = setTimeout(() => { const sendSeenMessage = async () => { try { const { data } = await api.get("/messages/" + ticketId, { params: { pageNumber }, }) setSendSeen(false) if (!data) return if (data.ticket.status === "open" && /*data.ticket.unreadMessages > 0 &&*/ data.ticket.userId === user.id) { let fromMe = false if (data.messages.length > 0) { fromMe = data.messages[data.messages.length - 1].fromMe } // Atualiza Unread messages para 0 // Atualizei função no back-end para receber o novo parametro unreadMessages const ticketUpdate = { ...data.ticket, unreadMessages: 0, fromMe } await api.put("/tickets/" + ticketId, ticketUpdate) } } catch (err) { setLoading(false) toastError(err) } } sendSeenMessage() }, 500) return () => { clearTimeout(delayDebounceFn) } }, [sendSeen, pageNumber, ticketId, user.id]) useEffect(() => { setLoading(true) const delayDebounceFn = setTimeout(() => { const fetchMessages = async () => { try { const { data } = await api.get("/messages/" + ticketId, { params: { pageNumber }, }) if (currentTicketId.current === ticketId) { if (data?.messages) { setCountTicketMsg(data.messages.length) } 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) const onConnectMessagesList = () => { socket.emit("joinChatBox", ticketId) } onConnectMessagesList() socket.on("connect", onConnectMessagesList) onAppMessageMessagesList = (data) => { if (data.action === "create" && data.ticket.id === ticketId) { dispatch({ type: "ADD_MESSAGE", payload: data.message }) scrollToBottom() } if (data.action === "update" && data.ticket.id === ticketId) { dispatch({ type: "UPDATE_MESSAGE", payload: data.message }) } } socket.on("appMessage", onAppMessageMessagesList) return () => { socket.off("connect", onConnectMessagesList) socket.off("appMessage", onAppMessageMessagesList) } }, [ticketId]) const loadMore = () => { setPageNumber((prevPageNumber) => prevPageNumber + 1) } const scrollToBottom = () => { if (lastMessageRef.current) { setSendSeen(true) 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 ( //