Rev 15836 | Rev 15844 | Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
import React, { useEffect, useRef, useState } from "react";import { axios } from "../../../utils";import { useForm } from "react-hook-form";import Emojione from "./emojione/Emojione";import FileModal from "./fileModal/FileModal";import Messages from "./messages/Messages";import AttachFileIcon from "@mui/icons-material/AttachFile";import InsertEmoticonIcon from "@mui/icons-material/InsertEmoticon";import SendIcon from "@mui/icons-material/Send";import styles from "./chat.module.scss";const permittedFiles ="video/mp4, video/mpeg, video/webm, application/pdf, image/jpeg, image/png, image/jpg";const Chat = ({ entity }) => {const [oldMessages, setOldMessages] = useState([]);const [messages, setmessages] = useState([]);const [totalPages, setTotalPages] = useState(1);const [currentPage, setCurrentPage] = useState(1);const [loading, setLoading] = useState(false);const [showEmojione, setShowEmojione] = useState(false);const [selectedFile, setSelectedFile] = useState("");const { handleSubmit, register } = useForm();const bottomToScroll = useRef(null);const inputTextEl = useRef(null);const fileInputEl = useRef(null);const loadMoreEl = useRef();const divToScroll = useRef(null);const {url_get_all_messages,url_send,url_upload,url_close,url_mark_seen,type,} = entity;useEffect(() => {let timeInterval;if (loading) return;timeInterval = setTimeout(() => chatHeartbeat(), 2000);return () => {clearTimeout(timeInterval);};}, [loading, entity]);// infiniteScrolluseEffect(() => {const options = {root: null,rootMargin: "0px",threshold: 1.0,};const observer = new IntersectionObserver(handleObserver, options);if (loadMoreEl.current) {observer.observe(loadMoreEl.current);}return () => {observer.disconnect();};}, [totalPages]);useEffect(() => {loadOldMessages();}, [currentPage]);useEffect(() => {axios.post(url_mark_seen);}, []);// heartbeat functionconst chatHeartbeat = () => {setLoading(true);axios.get(url_get_all_messages).then(({ data: response }) => {const { data, success } = response;if (!success) {return console.log("Ha ocurrido un error");}const messageResponse = [...data.items].reverse();const updatedMessages = messageResponse.reduce((acum, updatedMessage) => {if (messages.findIndex((message) => message.id === updatedMessage.id) === -1) {acum = [...acum, updatedMessage];}return acum;},[]);if (updatedMessages.length > 0) {setmessages([...messages, ...updatedMessages]);setTotalPages(data.pages);scrollToBottom();}}).finally(() => setLoading(false));};// utilsFunctionsconst scrollToBottom = () => {const divToScrollEl = divToScroll.current;divToScrollEl.scrollIntoView({ behavior: "smooth" });};const onClickEmoji = (event) => {const shortname = event.currentTarget.dataset.shortname;const currentText = inputTextEl.current.value;let cursorPosition = inputTextEl.current.selectionStart;const textBehind = currentText.substring(0, cursorPosition);const textForward = currentText.substring(cursorPosition);inputTextEl.current.value = `${textBehind}${shortname}${textForward}`;inputTextEl.current.focus();inputTextEl.current.setSelectionRange(cursorPosition + shortname.length,cursorPosition + shortname.length);};const handleUploadFile = (e) => {const file = e.target.files[0];if (file) {setSelectedFile(file);}};const removeSelectedFile = () => {setSelectedFile("");};const handleObserver = async (entities) => {const target = entities[0];if (target.isIntersecting) {if (currentPage < totalPages) {setCurrentPage((prevState) => prevState + 1);bottomToScroll.current.scrollBy(0, 200);}}};const loadOldMessages = async () => {if (currentPage < totalPages && currentPage > 1) {}await axios.get(url_get_all_messages, {params: {page: currentPage,},}).then(async (response) => {const resData = response.data;if (resData.success) {if (resData.data.page > 1) {setOldMessages([...resData.data.items.slice().reverse(),...oldMessages,]);}}});};// on send messageconst onHandleSubmit = (data, event) => {const formData = new FormData();Object.entries(data).map(([key, value]) => {formData.append(key, value);});event.target.reset();axios.post(url_send, formData).then((response) => {setShowEmojione(false);});};// on send fileconst handleSendFile = () => {const formData = new FormData();formData.append("file", selectedFile);axios.post(url_upload, formData).then(async (response) => {const resData = response.data;if (resData.success) {setSelectedFile("");setShowEmojione(false);}});};return (<div className={styles.chat}><div className={styles.messagesContainer} ref={bottomToScroll}><div className={styles.messageWrapper}>{currentPage < totalPages && (<p ref={loadMoreEl} className="mt-2">Cargando...</p>)}<MessagesoldMessages={oldMessages}messages={messages}onScrollToBottom={scrollToBottom}chatType={type}/><div ref={divToScroll}></div></div></div><div className={styles.chat__input__container}>{showEmojione && <Emojione onClickEmoji={onClickEmoji} />}<formonSubmit={handleSubmit(onHandleSubmit)}encType="multipart/form-data"><buttontype="button"className={"btn " + styles.icon_btn}onClick={() => fileInputEl.current.click()}><AttachFileIcon /></button><buttontype="button"className={"btn " + styles.icon_btn}onClick={() => setShowEmojione(!showEmojione)}><InsertEmoticonIcon /></button><inputtype="file"ref={(e) => (fileInputEl.current = e)}accept={permittedFiles}onChange={handleUploadFile}hidden/><textareaclassName={styles.chatInput}placeholder="Escribe un mensaje"rows="1"ref={inputTextEl}/><button type="submit" className={"btn " + styles.send_btn}><SendIcon /></button></form></div>{selectedFile && (<FileModalfile={selectedFile}onCancel={removeSelectedFile}onSend={handleSendFile}/>)}</div>);};export default Chat;