index.tsx 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. import { makeStyles } from "@material-ui/core/styles";
  2. import { useState, useEffect, useRef, useCallback } from "react";
  3. import { useSelector,useDispatch } from "react-redux";
  4. import ArrowBack from "./ArrowBack";
  5. import SendMessage from "./SendMessage";
  6. import MessageLeftText from './Messages/MessageLeftText'
  7. import MessageLeftImage from './Messages/MessageLeftImage'
  8. import MessageLeftAudio from './Messages/MessageLeftAudio'
  9. import MessageLeftVideo from './Messages/MessageLeftVideo'
  10. import MessageLeftFile from "./Messages/MessageLeftFile";
  11. import MessageRightText from './Messages/MessageRightText'
  12. import MessageRightImage from './Messages/MessageRightImage'
  13. import MessageRightAudio from './Messages/MessageRightAudio'
  14. import MessageRightVideo from './Messages/MessageRightVideo'
  15. import MessageRightFile from "./Messages/MessageRightFile";
  16. import MessageTime from "./Messages/MessageTime";
  17. import AlertInfo from "../../../reusableComponents/AlertInfo";
  18. import { getMessagesMemo } from '../../../../redux/messages/selector'
  19. import { getNumber } from '../../../../redux/authorization/selector'
  20. import { getChat } from '../../../../redux/chat/selector'
  21. import { getScrollChat } from '../../../../redux/control/selector'
  22. import { actionScrollChat } from '../../../../redux/control/action'
  23. import { asyncGetMessagesById } from '../../../../redux/messages/operations'
  24. import { asyncGetChatById } from "../../../../redux/chat/operations";
  25. import { seenChat } from "../../../../api-data";
  26. import { timeStampFilter,prodBaseURL,refreshAppTime } from "../../../../helpers";
  27. const debounce = require('lodash.debounce');
  28. const useStyles = makeStyles({
  29. container: {
  30. height: '93vh',
  31. width: "100%",
  32. display: "flex",
  33. alignItems: "center",
  34. alignContent:"center",
  35. flexDirection: "column",
  36. position: "relative",
  37. },
  38. messagesScroll: {
  39. paddingTop: 30,
  40. overflowY: "scroll",
  41. maxHeight: '83vh',
  42. width: "100%",
  43. display: "flex",
  44. justifyContent: 'center',
  45. '&::-webkit-scrollbar': {
  46. width: '0.4em'
  47. },
  48. '&::-webkit-scrollbar-track': {
  49. boxShadow: 'inset 0 0 6px rgba(0,0,0,0.00)',
  50. webkitBoxShadow: 'inset 0 0 6px rgba(0,0,0,0.00)',
  51. backgroundColor: '#eceeec',
  52. },
  53. '&::-webkit-scrollbar-thumb': {
  54. backgroundColor: '#ccc8c8',
  55. },
  56. "&::-webkit-scrollbar-thumb:focus": {
  57. backgroundColor: "#959595",
  58. },
  59. "&::-webkit-scrollbar-thumb:active": {
  60. backgroundColor: "#959595",
  61. },
  62. },
  63. messagesEmpty: {
  64. overflowY: "hidden",
  65. width: "100%",
  66. display: "flex",
  67. justifyContent: 'center',
  68. paddingTop: 30,
  69. },
  70. messagesBody: {
  71. width: "60%",
  72. },
  73. });
  74. const ChatBar = () => {
  75. const classes = useStyles();
  76. const dispatch = useDispatch()
  77. const messages = useSelector(getMessagesMemo)
  78. const userNumber = useSelector(getNumber)
  79. const { companionId,total,seen,mute } = useSelector(getChat)
  80. const scrollChat = useSelector(getScrollChat)
  81. const [isArrow, setIsArrow] = useState<boolean>(false)
  82. const [isNew, setIsNew] = useState<{new:number,mute:boolean}>({new:0,mute:false})
  83. const divRef = useRef<any | null>(null)
  84. let time:any
  85. const handleScrollTo = () => {
  86. divRef.current&&divRef.current.scrollTo({
  87. top: divRef.current.scrollHeight,
  88. behavior: 'smooth'
  89. })
  90. }
  91. const handleScroll = useCallback(({ target:{scrollHeight,scrollTop,clientHeight}}: any) => {
  92. const different = scrollHeight - Math.floor(scrollTop)
  93. const reached = different - clientHeight
  94. if (total !== seen&&reached < 10) seenChat(companionId)
  95. setIsArrow(different === clientHeight ? false : true)
  96. }, [total,seen, companionId])
  97. const debouncedHandleScroll = debounce(handleScroll, 300)
  98. useEffect(() => {
  99. if (scrollChat) {
  100. dispatch(asyncGetMessagesById(companionId, handleScrollTo))
  101. dispatch(actionScrollChat(false))
  102. }
  103. }, [dispatch, scrollChat, companionId])
  104. useEffect(() => {
  105. const handleReset = () => {
  106. dispatch(asyncGetChatById(companionId))
  107. dispatch(asyncGetMessagesById(companionId, null))
  108. }
  109. handleReset()
  110. const idInterval = setInterval(handleReset, refreshAppTime);
  111. return () => clearInterval(idInterval);
  112. }, [dispatch, companionId]);
  113. useEffect(() => {
  114. setIsNew({ new:total-seen,mute})
  115. }, [total,seen,mute]);
  116. useEffect(() => {
  117. if (divRef.current) {
  118. const { scrollHeight, clientHeight } = divRef.current
  119. if(total !== seen&&scrollHeight === clientHeight) seenChat(companionId)
  120. }
  121. }, [total,seen,companionId]);
  122. return (
  123. <div className={classes.container} >
  124. <ArrowBack isArrow={isArrow} isNew={isNew} handleScrollTo={handleScrollTo}/>
  125. <div ref={divRef} onScroll={debouncedHandleScroll}
  126. className={messages.length > 0 ? classes.messagesScroll : classes.messagesEmpty}>
  127. <div className={classes.messagesBody}>
  128. {messages.length > 0 ? messages.map(({ message, name, lastName, color,
  129. createdAt,number, type,fullType,_id }) => {
  130. let isTime
  131. if (!time) {
  132. isTime = true
  133. time = createdAt
  134. } else if (timeStampFilter(time) !== timeStampFilter(createdAt)) {
  135. time = createdAt
  136. isTime = true
  137. }
  138. const url = `${prodBaseURL}/${message}`
  139. if (number !== userNumber) {
  140. if (type === 'text') return (<div key={createdAt}>
  141. {isTime&&<MessageTime message={timeStampFilter(createdAt)}/>}
  142. <MessageLeftText
  143. message={message}
  144. createdAt={createdAt}
  145. name={name}
  146. lastName={lastName}
  147. _id={_id}
  148. /></div>)
  149. if (type === 'image') return (<div key={createdAt}>
  150. {isTime&&<MessageTime message={timeStampFilter(createdAt)}/>}
  151. <MessageLeftImage
  152. url={url}
  153. createdAt={createdAt}
  154. color={color}
  155. message={message}
  156. messages={messages}
  157. fullType={fullType}
  158. _id={_id}
  159. /></div>)
  160. if (type === 'audio') return (<div key={createdAt}>
  161. {isTime&&<MessageTime message={timeStampFilter(createdAt)}/>}
  162. <MessageLeftAudio
  163. url={url}
  164. createdAt={createdAt}
  165. fullType={fullType}
  166. _id={_id}
  167. /></div>)
  168. if (type === 'video') return (<div key={createdAt}>
  169. {isTime&&<MessageTime message={timeStampFilter(createdAt)}/>}
  170. <MessageLeftVideo
  171. url={url}
  172. createdAt={createdAt}
  173. fullType={fullType}
  174. _id={_id}
  175. /></div>)
  176. if (type) return (<div key={createdAt}>
  177. {isTime&&<MessageTime message={timeStampFilter(createdAt)}/>}
  178. <MessageLeftFile
  179. url={url}
  180. createdAt={createdAt}
  181. type={type}
  182. _id={_id}
  183. /></div>)
  184. } else {
  185. if (type === 'text') return (<div key={createdAt}>
  186. {isTime&&<MessageTime message={timeStampFilter(createdAt)}/>}
  187. <MessageRightText
  188. message={message}
  189. createdAt={createdAt}
  190. name={name}
  191. lastName={lastName}
  192. _id={_id}
  193. /></div>)
  194. if (type === 'image') return (<div key={createdAt}>
  195. {isTime&&<MessageTime message={timeStampFilter(createdAt)}/>}
  196. <MessageRightImage
  197. url={url}
  198. createdAt={createdAt}
  199. color={color}
  200. message={message}
  201. messages={messages}
  202. fullType={fullType}
  203. _id={_id}
  204. /></div>)
  205. if (type === 'audio') return (<div key={createdAt}>
  206. {isTime&&<MessageTime message={timeStampFilter(createdAt)}/>}
  207. <MessageRightAudio
  208. url={url}
  209. createdAt={createdAt}
  210. fullType={fullType}
  211. _id={_id}
  212. /></div>)
  213. if (type === 'video') return (<div key={createdAt}>
  214. {isTime&&<MessageTime message={timeStampFilter(createdAt)}/>}
  215. <MessageRightVideo
  216. url={url}
  217. createdAt={createdAt}
  218. fullType={fullType}
  219. _id={_id}
  220. /></div>)
  221. if (type) return (<div key={createdAt}>
  222. {isTime&&<MessageTime message={timeStampFilter(createdAt)}/>}
  223. <MessageRightFile
  224. url={url}
  225. createdAt={createdAt}
  226. type={type}
  227. _id={_id}
  228. /></div>)
  229. }
  230. }) : <AlertInfo name='You do not have messages yet!' />}
  231. </div>
  232. </div>
  233. <SendMessage isArrow={isArrow} />
  234. </div>
  235. );
  236. }
  237. export default ChatBar