import React, { useState, useEffect, useContext, useRef } from "react"; import "emoji-mart/css/emoji-mart.css"; import { useParams } from "react-router-dom"; import { Picker } from "emoji-mart"; import MicRecorder from "mic-recorder-to-mp3"; import clsx from "clsx"; import { makeStyles } from "@material-ui/core/styles"; import Paper from "@material-ui/core/Paper"; import InputBase from "@material-ui/core/InputBase"; import CircularProgress from "@material-ui/core/CircularProgress"; import { green } from "@material-ui/core/colors"; import AttachFileIcon from "@material-ui/icons/AttachFile"; import IconButton from "@material-ui/core/IconButton"; import MoreVert from "@material-ui/icons/MoreVert"; import MoodIcon from "@material-ui/icons/Mood"; import SendIcon from "@material-ui/icons/Send"; import CancelIcon from "@material-ui/icons/Cancel"; import ClearIcon from "@material-ui/icons/Clear"; import MicIcon from "@material-ui/icons/Mic"; import CheckCircleOutlineIcon from "@material-ui/icons/CheckCircleOutline"; import HighlightOffIcon from "@material-ui/icons/HighlightOff"; import { FormControlLabel, Hidden, Menu, MenuItem, Switch, } from "@material-ui/core"; import ClickAwayListener from "@material-ui/core/ClickAwayListener"; import { i18n } from "../../translate/i18n"; import api from "../../services/api"; import RecordingTimer from "./RecordingTimer"; import { ReplyMessageContext } from "../../context/ReplyingMessage/ReplyingMessageContext"; import { AuthContext } from "../../context/Auth/AuthContext"; import { useLocalStorage } from "../../hooks/useLocalStorage"; import toastError from "../../errors/toastError"; const Mp3Recorder = new MicRecorder({ bitRate: 128 }); const useStyles = makeStyles((theme) => ({ mainWrapper: { background: "#eee", display: "flex", flexDirection: "column", alignItems: "center", borderTop: "1px solid rgba(0, 0, 0, 0.12)", [theme.breakpoints.down("sm")]: { position: "fixed", bottom: 0, width: "100%", }, }, newMessageBox: { background: "#eee", width: "100%", display: "flex", padding: "7px", alignItems: "center", }, messageInputWrapper: { padding: 6, marginRight: 7, background: "#fff", display: "flex", borderRadius: 20, flex: 1, position: "relative", }, messageInput: { paddingLeft: 10, flex: 1, border: "none", }, sendMessageIcons: { color: "grey", }, uploadInput: { display: "none", }, viewMediaInputWrapper: { display: "flex", padding: "10px 13px", position: "relative", justifyContent: "space-between", alignItems: "center", backgroundColor: "#eee", borderTop: "1px solid rgba(0, 0, 0, 0.12)", }, emojiBox: { position: "absolute", bottom: 63, width: 40, borderTop: "1px solid #e8e8e8", }, circleLoading: { color: green[500], opacity: "70%", position: "absolute", top: "20%", left: "50%", marginLeft: -12, }, audioLoading: { color: green[500], opacity: "70%", }, recorderWrapper: { display: "flex", alignItems: "center", alignContent: "middle", }, cancelAudioIcon: { color: "red", }, sendAudioIcon: { color: "green", }, replyginMsgWrapper: { display: "flex", width: "100%", alignItems: "center", justifyContent: "center", paddingTop: 8, paddingLeft: 73, paddingRight: 7, }, replyginMsgContainer: { flex: 1, marginRight: 5, overflowY: "hidden", backgroundColor: "rgba(0, 0, 0, 0.05)", borderRadius: "7.5px", display: "flex", position: "relative", }, replyginMsgBody: { padding: 10, height: "auto", display: "block", whiteSpace: "pre-wrap", overflow: "hidden", }, replyginContactMsgSideColor: { flex: "none", width: "4px", backgroundColor: "#35cd96", }, replyginSelfMsgSideColor: { flex: "none", width: "4px", backgroundColor: "#6bcbef", }, messageContactName: { display: "flex", color: "#6bcbef", fontWeight: 500, }, messageQuickAnswersWrapper: { margin: 0, position: "absolute", bottom: "50px", background: "#ffffff", padding: "2px", border: "1px solid #CCC", left: 0, width: "100%", "& li": { listStyle: "none", "& a": { display: "block", padding: "8px", textOverflow: "ellipsis", overflow: "hidden", maxHeight: "32px", "&:hover": { background: "#F1F1F1", cursor: "pointer", }, }, }, }, })); const MessageInput = ({ ticketStatus }) => { const classes = useStyles(); const { ticketId } = useParams(); const [medias, setMedias] = useState([]); const [inputMessage, setInputMessage] = useState(""); const [showEmoji, setShowEmoji] = useState(false); const [loading, setLoading] = useState(false); const [recording, setRecording] = useState(false); const [quickAnswers, setQuickAnswer] = useState([]); const [typeBar, setTypeBar] = useState(false); const inputRef = useRef(); const [anchorEl, setAnchorEl] = useState(null); const { setReplyingMessage, replyingMessage } = useContext(ReplyMessageContext); const { user } = useContext(AuthContext); const [signMessage, setSignMessage] = useLocalStorage("signOption", true); useEffect(() => { inputRef.current.focus(); }, [replyingMessage]); useEffect(() => { inputRef.current.focus(); return () => { setInputMessage(""); setShowEmoji(false); setMedias([]); setReplyingMessage(null); }; }, [ticketId, setReplyingMessage]); const handleChangeInput = (e) => { setInputMessage(e.target.value); handleLoadQuickAnswer(e.target.value); }; const handleQuickAnswersClick = (value) => { setInputMessage(value); setTypeBar(false); }; const handleAddEmoji = (e) => { let emoji = e.native; setInputMessage((prevState) => prevState + emoji); }; const handleChangeMedias = (e) => { if (!e.target.files) { return; } const selectedMedias = Array.from(e.target.files); setMedias(selectedMedias); }; const handleInputPaste = (e) => { if (e.clipboardData.files[0]) { setMedias([e.clipboardData.files[0]]); } }; const handleUploadMedia = async (e) => { setLoading(true); e.preventDefault(); const formData = new FormData(); formData.append("fromMe", true); medias.forEach((media) => { formData.append("medias", media); formData.append("body", media.name); }); try { await api.post(`/messages/${ticketId}`, formData); } catch (err) { toastError(err); } setLoading(false); setMedias([]); }; const handleSendMessage = async () => { if (inputMessage.trim() === "") return; setLoading(true); const message = { read: 1, fromMe: true, mediaUrl: "", body: signMessage ? `*${user?.name}:*\n${inputMessage.trim()}` : inputMessage.trim(), quotedMsg: replyingMessage, }; try { await api.post(`/messages/${ticketId}`, message); } catch (err) { toastError(err); } setInputMessage(""); setShowEmoji(false); setLoading(false); setReplyingMessage(null); }; const handleStartRecording = async () => { setLoading(true); try { await navigator.mediaDevices.getUserMedia({ audio: true }); await Mp3Recorder.start(); setRecording(true); setLoading(false); } catch (err) { toastError(err); setLoading(false); } }; const handleLoadQuickAnswer = async (value) => { if (value && value.indexOf("/") === 0) { try { const { data } = await api.get("/quickAnswers/", { params: { searchParam: inputMessage.substring(1) }, }); setQuickAnswer(data.quickAnswers); if (data.quickAnswers.length > 0) { setTypeBar(true); } else { setTypeBar(false); } } catch (err) { setTypeBar(false); } } else { setTypeBar(false); } }; const handleUploadAudio = async () => { setLoading(true); try { const [, blob] = await Mp3Recorder.stop().getMp3(); if (blob.size < 10000) { setLoading(false); setRecording(false); return; } const formData = new FormData(); const filename = `${new Date().getTime()}.mp3`; formData.append("medias", blob, filename); formData.append("body", filename); formData.append("fromMe", true); await api.post(`/messages/${ticketId}`, formData); } catch (err) { toastError(err); } setRecording(false); setLoading(false); }; const handleCancelAudio = async () => { try { await Mp3Recorder.stop().getMp3(); setRecording(false); } catch (err) { toastError(err); } }; const handleOpenMenuClick = (event) => { setAnchorEl(event.currentTarget); }; const handleMenuItemClick = (event) => { setAnchorEl(null); }; const renderReplyingMessage = (message) => { return (
{!message.fromMe && ( {message.contact?.name} )} {message.body}
setReplyingMessage(null)} >
); }; if (medias.length > 0) return ( setMedias([])} > {loading ? (
) : ( {medias[0]?.name} {/* */} )}
); else { return ( {replyingMessage && renderReplyingMessage(replyingMessage)}
setShowEmoji((prevState) => !prevState)} > {showEmoji ? (
setShowEmoji(false)}>
) : null} { setSignMessage(e.target.checked); }} name="showAllTickets" color="primary" /> } />
setShowEmoji((prevState) => !prevState)} > { setSignMessage(e.target.checked); }} name="showAllTickets" color="primary" /> } />
{ input && input.focus(); input && (inputRef.current = input); }} className={classes.messageInput} placeholder={ ticketStatus === "open" ? i18n.t("messagesInput.placeholderOpen") : i18n.t("messagesInput.placeholderClosed") } multiline rowsMax={5} value={inputMessage} onChange={handleChangeInput} disabled={recording || loading || ticketStatus !== "open"} onPaste={(e) => { ticketStatus === "open" && handleInputPaste(e); }} onKeyPress={(e) => { if (loading || e.shiftKey) return; else if (e.key === "Enter") { handleSendMessage(); } }} /> {typeBar ? ( ) : (
)}
{inputMessage ? ( ) : recording ? (
{loading ? (
) : ( )}
) : ( )}
); } }; export default MessageInput;