Proyectos de Subversion LeadersLinked - Backend

Rev

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 destructuring
  const {
    url_get_all_messages,
    url_send,
    url_upload,
    url_close,
    url_mark_seen,
    type,
  } = props.entity;

  // react hook form
  const { handleSubmit, register } = useForm();

  // states
  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([]);

  // refs
  const 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;

  // useEffects
  useEffect(() => {
    /* setInterval */
    clearInterval(heartBeatInterval);
    heartBeatInterval = setInterval(() => {
      chatHeartbeat();
    }, 800);
    return () => {
      clearInterval(heartBeatInterval);
    };
  }, [newMessages, oldMessages]);

  // infiniteScroll
  useEffect(() => {
    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 function
  const 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]);
        }
      }
    });
  };

  // utilsFunctions
  const 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 message
  const 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 file
  const 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>
          )}
          <Messages
            oldMessages={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} />}
        <form
          onSubmit={handleSubmit(onHandleSubmit)}
          encType="multipart/form-data"
        >
          <button
            type="button"
            className={`${styles.inputIcon} ti-clip icon uploadFile`}
            id="uploadFile"
            onClick={() => {
              fileInputEl.current.click();
            }}
          ></button>
          <button
            type="button"
            className={`${styles.inputIcon} ti-face-smile icon btn-emoji`}
            id="toggle-emoji"
            onClick={() => {
              setShowEmojione(!showEmojione);
            }}
          ></button>
          <input
            type="file"
            name="file"
            id="file"
            ref={(e) => {
              fileInputEl.current = e;
            }}
            accept={permittedFiles}
            hidden
            onChange={handleUploadFile}
          />
          <textarea
            className={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 && (
        <FileModal
          file={selectedFile}
          onCancel={removeSelectedFile}
          onSend={handleSendFile}
        />
      )}
    </div>
  );
};

export default Chat;