Rev 15805 | Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
import {axios} from "../../../utils";import React, { useEffect, useRef } from "react";import { useState } from "react";import styles from "./chat.module.scss";import { useForm } from "react-hook-form";import Emojione from "./emojione/Emojione";import FileModal from "./fileModal/FileModal";import Messages from "./messages/Messages";const permittedFiles ="video/mp4, video/mpeg, video/webm, application/pdf, image/jpeg, image/png, image/jpg";const Chat = (props) => {// props destructuringconst {url_get_all_messages,url_send,url_upload,url_close,url_mark_seen,type,} = props.entity;// react hook formconst { handleSubmit, register } = useForm();// statesconst [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([]);// refsconst bottomToScroll = useRef(null);const inputTextEl = useRef(null);const fileInputEl = useRef(null);const loadMoreEl = useRef();const divToScroll = useRef(null);const [urlSearch, setUrlSearch] = useState(url_get_all_messages || '')let heartBeatInterval;// useEffectsuseEffect(() => {/* setInterval */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);}, []);// useEffect(() => {// shouldScrollToBottom.current = true;// }, [newMessages]);// useEffect(() => {// setMessages([...oldMessages, ...newMessages]);// ("before scroll");// }, [newMessages, oldMessages]);// useEffect(() => {// if (shouldScrollToBottom.current) {// scrollToBottom();// shouldScrollToBottom.current = false;// }// }, [shouldScrollToBottom.current]);// heartbeat functionconst chatHeartbeat = async () => {axios.get(url_get_all_messages).then((response) => {const resData = response.data;const isNewProp = url_get_all_messages !== urlSearchif (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} style={{ marginTop: ".5rem" }}>Cargando...</p>)}<MessagesoldMessages={oldMessages}newMessages={newMessages}onScrollToBottom={scrollToBottom}chatType={type}/>{/* {messages.map((message) => (<Message message={message} />))} */}<div ref={divToScroll}></div></div></div><div className={styles.chatInputContainer}>{showEmojione && <Emojione onClickEmoji={onClickEmoji} />}<formonSubmit={handleSubmit(onHandleSubmit)}encType="multipart/form-data"><buttontype="button"className={`${styles.inputIcon} ti-clip icon uploadFile`}id="uploadFile"onClick={() => {fileInputEl.current.click();}}></button><buttontype="button"className={`${styles.inputIcon} ti-face-smile icon btn-emoji`}id="toggle-emoji"onClick={() => {setShowEmojione(!showEmojione);}}></button><inputtype="file"name="file"id="file"ref={(e) => {fileInputEl.current = e;}}accept={permittedFiles}hiddenonChange={handleUploadFile}/><textareaclassName={styles.chatInput}id="message"name="message"placeholder="Escribe un mensaje"rows="1"ref={inputTextEl}></textarea><button type="submit" href="#" className={styles.sendBtn}>Enviar</button></form></div>{selectedFile && (<FileModalfile={selectedFile}onCancel={removeSelectedFile}onSend={handleSendFile}/>)}</div>);};export default Chat;