MessagesArea.jsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import { connect } from "react-redux"
  2. import Message from "../Message/Message"
  3. import { DropContainer, MessageGroup, MessagesAreaWrapper, ScrollBottom, SimpleBarWrapper } from "./MessagesArea.style"
  4. import 'simplebar/dist/simplebar.min.css';
  5. import { memo, useEffect, useRef, useState } from "react";
  6. import { useDropzone } from "react-dropzone";
  7. import { addUploadDate } from "../../helpers/addUploadDate";
  8. import { convert } from "../Time/Time";
  9. import MessagesDate from "../MessageDate/MessagesDate";
  10. import { Avatar } from "@mui/material";
  11. import { backendURL } from "../../helpers/gql";
  12. import ScrollBtn from './icons8-scrollBottom.png';
  13. import { actionGetMessageForChat } from "../../actions/actionsMessages";
  14. import { actionOpenModal } from "../../actions/actionsForModal";
  15. import { actionSetDropMedia } from "../../actions/actionsForChats";
  16. const MessagesArea = ({currUser, chats, chatId, getMessages, openModal, onLoad}) => {
  17. const [isVisible, setIsVisible] = useState(false);
  18. const messagesByChat = Object.values(chats[chatId]?.messages || []);
  19. const mess = messagesByChat.reduce((p,c)=>{
  20. if( p[p.length-1][p[p.length-1].length - 1 ]?.createdAt - c.createdAt > 600000
  21. || (p[p.length-1][p[p.length-1].length - 1 ]?.createdAt ? convert(p[p.length-1][p[p.length-1].length - 1 ]?.createdAt).getDateMonthName() !== convert(c.createdAt).getDateMonthName() : false )
  22. || (p[p.length-1][p[p.length-1].length - 1 ]?.owner ? p[p.length-1][p[p.length-1].length - 1 ]?.owner?._id !== c?.owner?._id : false) ){
  23. p.push([]);
  24. }
  25. p[p.length-1].push(c);
  26. return p;
  27. }, [[]]);
  28. const OFFSET = 600;
  29. const ref = useRef();
  30. let timer
  31. function infinityScroll () {
  32. clearTimeout(timer);
  33. timer = setTimeout(async() => {
  34. const scrollElem = ref.current?.contentWrapperEl;
  35. if(scrollElem.scrollHeight - (scrollElem.clientHeight - scrollElem.scrollTop) < OFFSET){
  36. let data = await getMessages(chatId);
  37. console.log(data)
  38. if (data?.length < 20) ref.current?.contentWrapperEl.removeEventListener("scroll", infinityScroll);
  39. }
  40. },30)
  41. }
  42. function scrollBottom (){
  43. const scrollElem = ref.current?.contentWrapperEl;
  44. if(Math.abs(scrollElem.scrollTop) > OFFSET){
  45. setIsVisible(true)
  46. } else {setIsVisible(false)}
  47. }
  48. useEffect(() => {
  49. ref.current?.contentWrapperEl.addEventListener("scroll", infinityScroll);
  50. ref.current?.contentWrapperEl.addEventListener("scroll", scrollBottom);
  51. return () => {
  52. ref.current.contentWrapperEl.scrollTop = 0;
  53. ref?.current?.contentWrapperEl?.removeEventListener("scroll", infinityScroll);
  54. ref?.current?.contentWrapperEl?.removeEventListener("scroll", scrollBottom);
  55. };
  56. }, [chatId]);
  57. const {
  58. getRootProps,
  59. getInputProps,
  60. isFocused,
  61. isDragAccept,
  62. isDragReject,
  63. acceptedFiles
  64. } = useDropzone({
  65. noClick: true,
  66. multiple: true
  67. });
  68. useEffect(()=>{
  69. acceptedFiles[0] && openModal('messageMediaModal');
  70. let files = addUploadDate(acceptedFiles)
  71. acceptedFiles[0] && onLoad(chatId, files)
  72. }, [acceptedFiles])
  73. return (
  74. <DropContainer {...getRootProps({ isDragAccept, isFocused})}>
  75. <div className="drop">drop files here</div>
  76. <input {...getInputProps()} />
  77. <MessagesAreaWrapper >
  78. <ScrollBottom isVisible={isVisible}><img style={{width: '50px', height: '50px'}} onClick={() => ref.current.contentWrapperEl.scrollTop = 0} src={ScrollBtn}/></ScrollBottom>
  79. <SimpleBarWrapper ref={ref}>
  80. <div style={{height: '20px', fontSize: '6px', opacity: '0'}}>1</div>
  81. {mess[0].length > 0 && mess.map((item, i, arr) =>
  82. <div key={i}>
  83. <MessagesDate visible={
  84. convert(item[item.length-1]?.createdAt).getDateMonthName() !== convert(arr[i + 1]?.[0]?.createdAt).getDateMonthName() ? true : false
  85. } timestamp={item[item.length-1]?.createdAt}/>
  86. <MessageGroup>
  87. <div style={{display: 'flex', flexDirection: 'column-reverse', position: "relative"}}>
  88. <Avatar
  89. alt={item[0]?.nick || item[0]?.login || 'avatar'}
  90. src={`${backendURL}/${item[0]?.owner?.avatar?.url || ''}`}
  91. sx={{ width: 45, height: 45, mr: '20px', position: 'sticky', bottom: 0, marginBottom: '5px'}}
  92. />
  93. </div>
  94. <div style={{display: 'flex', flexDirection: 'column-reverse'}}>
  95. {item.map((mes, i, arr) => <Message key={mes._id} lastElem={i == 0 ? false : true} currUser={currUser} chatId={chatId} mes={mes}/> )}
  96. </div>
  97. </MessageGroup>
  98. </div>
  99. )}
  100. </SimpleBarWrapper>
  101. </MessagesAreaWrapper>
  102. </DropContainer>
  103. )
  104. }
  105. export default connect(state=>({chats: state.chats || {}, currUser: state.auth?.payload?.sub?.id}), {getMessages : actionGetMessageForChat, openModal: actionOpenModal, onLoad: actionSetDropMedia})(memo(MessagesArea))