chatWindow.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import { useEffect, useRef, useState } from "react"
  2. import { Message, ShortMessage } from "./message"
  3. import { MyDropzone } from "./dropzone"
  4. const updateScroll = (el) => {
  5. el.scrollTop = el.scrollHeight
  6. }
  7. const Chat = ({ chat_id, chat_title, user_id, messages, onUpload, onSend, onMSGEdit, onScrollTopComplete, onInfo }) => {
  8. let [msg, setMSG] = useState("")
  9. let [isUpload, setIsUpload] = useState(false)
  10. let [files, setFiles] = useState([])
  11. let [isForward, setIsForward] = useState([false, ""])
  12. let [isReply, setIsReply] = useState([false, ""])
  13. let [skip, setSkip] = useState(20)
  14. let [isScroll, setIsScroll] = useState(true)
  15. let scrollRef = useRef(null)
  16. let input = useRef(null)
  17. useEffect(() => {
  18. if (isScroll) {
  19. updateScroll(scrollRef.current)
  20. }
  21. }, [messages, isScroll])
  22. useEffect(() => {
  23. input.current && input.current.focus()
  24. }, [isReply, isForward])
  25. let filesHandler = (file) => {
  26. setFiles(file)
  27. }
  28. let buttonScrollHandler = () => {
  29. setIsScroll(true)
  30. updateScroll(scrollRef.current)
  31. }
  32. let scrollHandler = (el) => {
  33. setIsScroll(Math.round(el.scrollTop + el.clientHeight) === el.scrollHeight)
  34. if (el && el.scrollTop === 0) {
  35. el.scrollTop = el.scrollHeight / 30
  36. !isScroll && onScrollTopComplete(chat_id, skip)
  37. setSkip(skip + 20)
  38. }
  39. }
  40. let sendHandler = (e) => {
  41. if (e.key === "Escape") {
  42. setIsReply([false, ""])
  43. setMSG("")
  44. }
  45. if ((e.key === "Enter" && !e.shiftKey) || e.type === "click") {
  46. if (!isReply[0] && !isForward[0]) { //отправить обычное сообщение
  47. onSend(chat_id, msg, files)
  48. }
  49. if (isReply[0]) {
  50. onSend(chat_id, msg, files, isReply[1]) //ответить на сообщение (isReply[1] - id msg на какое отвечаем)
  51. setIsReply([false, ""])
  52. }
  53. if (isForward[0]) {
  54. onSend(chat_id, msg, files, false, isForward[1]) //переслать (isForward[1] - id чата куда переслать)
  55. setIsForward([false, ""])
  56. }
  57. setMSG("")
  58. updateScroll(scrollRef.current)
  59. setFiles([])
  60. setIsUpload(false)
  61. e.preventDefault()
  62. }
  63. }
  64. return (
  65. <div className="chat-window">
  66. <div className="chat-nav">
  67. <span>{chat_title}</span>
  68. <button onClick={() => onInfo()}>Инфо</button>
  69. </div>
  70. <ul ref={scrollRef} onScroll={() => scrollHandler(scrollRef.current)} className="message-list">
  71. {messages.length > 0 &&
  72. messages.map(message => {
  73. return <Message key={message._id}
  74. id={message._id}
  75. nick={message.owner.nick || message.owner.login}
  76. msg={message.text}
  77. date={message.createdAt}
  78. media={message.media}
  79. own={message.owner._id === user_id}
  80. replyTo={message.replyTo}
  81. onMSGEdit={onMSGEdit}
  82. onMSGReply={setIsReply}
  83. onMSGForward={setIsForward} />
  84. })}
  85. </ul>
  86. {isReply[0] &&
  87. messages.filter(message => message._id === isReply[1]).map(m =>
  88. <ShortMessage key={m._id} nick={m.owner.nick || m.owner.login}
  89. text={m.text}
  90. date={m.createdAt} />)}
  91. {!isScroll && <button className="btn-scroll" onClick={() => buttonScrollHandler()}>Вниз</button>}
  92. <div className="message-input">
  93. <textarea ref={input} placeholder="Введите сообщение..." value={msg} onFocus={() => updateScroll(scrollRef.current)} onInput={(e) => setMSG(e.target.value)} onKeyDown={(e) => sendHandler(e)} />
  94. <button onClick={() => setIsUpload(!isUpload)}>Прикрепить файл</button>
  95. {isUpload && <MyDropzone onUpload={onUpload} onSet={filesHandler} />}
  96. <button onClick={(e) => sendHandler(e)}>Отправить</button>
  97. </div>
  98. </div >
  99. )
  100. }
  101. export default Chat