Rev 15834 | Rev 15836 | 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 [messages, setMessages] = useState([]);const [newMessages, setNewMessages] = useState([]);const [showEmojione, setShowEmojione] = useState(false);const [selectedFile, setSelectedFile] = useState("");const [pages, setPages] = useState(1);const [currentPage, setCurrentPage] = useState(1);const [oldMessages, setOldMessages] = useState([]);const [urlSearch, setUrlSearch] = 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;let heartBeatInterval;useEffect(() => {clearInterval(heartBeatInterval);heartBeatInterval = setInterval(() => {chatHeartbeat();}, 800);return () => {clearInterval(heartBeatInterval);};}, [newMessages, oldMessages]);// 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();};}, [pages]);useEffect(() => {loadOldMessages();}, [currentPage]);useEffect(async () => {const resData = (await axios.post(url_mark_seen)).data;resData;}, []);// heartbeat functionconst chatHeartbeat = async () => {axios.get(url_get_all_messages).then((response) => {const resData = response.data;const isNewProp = url_get_all_messages !== urlSearch;if (resData.success) {const updatedNewMessages = resData.data.items.slice();let newNewMessages = [];updatedNewMessages.map((updatedNewMessage) => {const existInNewMessages = newMessages.findIndex((newMessage) => newMessage.id === updatedNewMessage.id);if (existInNewMessages === -1) {newNewMessages = [updatedNewMessage, ...newNewMessages];setPages(resData.data.pages);}});if (newNewMessages.length > 0) {setNewMessages((prevState) => [...prevState, ...newNewMessages]);}}});};// utilsFunctionsconst scrollToBottom = () => {("scrolled");const element = bottomToScroll.current;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 < pages) {setCurrentPage((prevState) => prevState + 1);bottomToScroll.current.scrollBy(0, 200);}}};const loadOldMessages = async () => {if (currentPage < pages && 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 < pages && (<p ref={loadMoreEl} className="mt-2">Cargando...</p>)}<MessagesoldMessages={oldMessages}newMessages={newMessages}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;