Rev 16288 | 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 MessagesList from "./messages/MessagesList";import ConferenceModal from "./components/ConferenceModal";import IconButton from "@mui/material/IconButton";import AttachFileIcon from "@mui/icons-material/AttachFile";import InsertEmoticonIcon from "@mui/icons-material/InsertEmoticon";import SendIcon from "@mui/icons-material/Send";import MoreVertIcon from "@mui/icons-material/MoreVert";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, timezones }) => {const [oldMessages, setOldMessages] = useState([]);const [messages, setMessages] = useState([]);const [totalPages, setTotalPages] = useState(1);const [currentPage, setCurrentPage] = useState(1);const [loading, setLoading] = useState(false);const [isGettingMessages, setIsGettingMessages] = useState(false);const [showEmojione, setShowEmojione] = useState(false);const [selectedFile, setSelectedFile] = useState("");const { handleSubmit } = useForm();const scrollList = useRef(null);const inputTextEl = useRef(null);const fileInputEl = useRef(null);const {url_get_all_messages,url_send,url_upload,url_close,url_mark_seen,url_zoom,type,} = entity;// Get messagesconst getMessages = () => {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((prevMessages) => [...prevMessages, ...updatedMessages]);setTotalPages(data.pages);scrollTo(scrollList);}}).finally(() => setLoading(false));};const onIntersection = (entities) => {const target = entities[0];if (target.isIntersecting && currentPage < totalPages) {setIsGettingMessages(true);setCurrentPage((prevState) => prevState + 1);scrollTo(scrollList, 200);}};const getOldMessages = () => {setIsGettingMessages(true);axios.get(`${url_get_all_messages}?page=${currentPage}`).then(({ data: response }) => {const { data, success } = response;if (success && data.page > 1) {setOldMessages([...data.items.slice().reverse(), ...oldMessages]);}}).finally(() => setIsGettingMessages(false));};//Utilitysconst scrollTo = (element, distance) => {const divToScrollEl = element.current;const options = {top: distance,behavior: "smooth",};if (!distance) {divToScrollEl.scrollBy({ ...options, top: divToScrollEl.scrollHeight });return;}divToScrollEl.scrollBy(options);};const onClickEmoji = (event) => {const shortname = event.currentTarget.dataset.shortname;const currentText = inputTextEl.current.value;const cursorPosition = inputTextEl.current.selectionStart;const textBehind = currentText.substring(0, cursorPosition);const textForward = currentText.substring(cursorPosition);const unicode = emojione.shortnameToUnicode(shortname);inputTextEl.current.value = `${textBehind}${unicode}${textForward}`;inputTextEl.current.focus();inputTextEl.current.setSelectionRange(cursorPosition + unicode.length,cursorPosition + unicode.length);};const handleUploadFile = ({ target }) => {const file = target.files[0];if (!file) return;setSelectedFile(file);};const removeSelectedFile = () => {setSelectedFile("");};// On sendconst handleKeyDown = (e) => {if (e.key !== "Enter") return false;e.preventDefault();onHandleSubmit();};const onHandleSubmit = () => {const formData = new FormData();formData.append("message", emojione.toShort(inputTextEl.current.value));axios.post(url_send, formData).then(({ data: response }) => {const { data, success } = response;if (!success) {console.log("Ha ocurrido un error: " + data);return;}inputTextEl.current.value = "";setShowEmojione(false);scrollTo(scrollList);});};const handleSendFile = () => {const formData = new FormData();formData.append("file", selectedFile);axios.post(url_upload, formData).then(({ data: response }) => {const { success, data } = response;if (!success) {console.log("Ha ocurrido un error: " + data);return;}setSelectedFile("");setShowEmojione(false);scrollTo(scrollList);});};useEffect(() => {let timeInterval;if (loading) return;timeInterval = setTimeout(() => getMessages(), 2000);return () => {clearTimeout(timeInterval);};}, [loading]);useEffect(() => {setMessages([]);setOldMessages([]);setTotalPages(1);setCurrentPage(1);}, [entity]);useEffect(() => getOldMessages(), [currentPage]);useEffect(() => axios.post(url_mark_seen), []);return (<div className={styles.chat}><Chat.Headername={entity.name}conferenceUrl={url_zoom}timezones={timezones}/><MessagesListisLastPage={currentPage >= totalPages}messages={[...oldMessages, ...messages]}onIntersection={onIntersection}scrollRef={scrollList}isLoading={isGettingMessages}/><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"onKeyDown={handleKeyDown}ref={inputTextEl}rows="1"/><button type="submit" className={"btn " + styles.send_btn}><SendIcon /></button></form></div>{selectedFile && (<FileModalfile={selectedFile}onCancel={removeSelectedFile}onSend={handleSendFile}/>)}</div>);};const Header = ({ name, conferenceUrl, timezones }) => {const [isShowConferenceModal, setisShowConferenceModal] = useState(false);const toggleConferenceModal = () =>setisShowConferenceModal(!isShowConferenceModal);const options = [{ label: "Crear Conferencia", action: toggleConferenceModal },];return (<div className={styles.chat_header}><h2>{name}</h2><Header.Options options={options} /><ConferenceModalisShow={isShowConferenceModal}onClose={toggleConferenceModal}timezones={timezones}zoomUrl={conferenceUrl}onCreate={toggleConferenceModal}/></div>);};const Options = ({ options }) => {const [isShowMenu, setIsShowMenu] = useState(false);const toggleOptions = () => {setIsShowMenu(!isShowMenu);};return (<div className="header-options"><IconButton onClick={toggleOptions}><MoreVertIcon /></IconButton><div className="position-relative"><div className={`feed-options ${isShowMenu ? "active" : ""}`}><ul>{options.map((option, index) => (<li key={index}><buttonclassName="btn option-btn"onClick={() => {toggleOptions();option.action();}}>{option.label}</button></li>))}</ul></div></div></div>);};Chat.Header = Header;Header.Options = Options;export default Chat;