index.tsx 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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,prodAwsS3,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,caption,emoji,emojiCompanion,_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 = `${prodAwsS3}/${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. caption={caption}
  148. emoji={emoji}
  149. emojiCompanion={emojiCompanion}
  150. _id={_id}
  151. /></div>)
  152. if (type === 'image') return (<div key={createdAt}>
  153. {isTime&&<MessageTime message={timeStampFilter(createdAt)}/>}
  154. <MessageLeftImage
  155. url={url}
  156. createdAt={createdAt}
  157. color={color}
  158. fullType={fullType}
  159. caption={caption}
  160. emoji={emoji}
  161. emojiCompanion={emojiCompanion}
  162. _id={_id}
  163. /></div>)
  164. if (type === 'audio') return (<div key={createdAt}>
  165. {isTime&&<MessageTime message={timeStampFilter(createdAt)}/>}
  166. <MessageLeftAudio
  167. url={url}
  168. createdAt={createdAt}
  169. fullType={fullType}
  170. caption={caption}
  171. emoji={emoji}
  172. emojiCompanion={emojiCompanion}
  173. _id={_id}
  174. /></div>)
  175. if (type === 'video') return (<div key={createdAt}>
  176. {isTime&&<MessageTime message={timeStampFilter(createdAt)}/>}
  177. <MessageLeftVideo
  178. url={url}
  179. createdAt={createdAt}
  180. fullType={fullType}
  181. caption={caption}
  182. emoji={emoji}
  183. emojiCompanion={emojiCompanion}
  184. _id={_id}
  185. /></div>)
  186. if (type) return (<div key={createdAt}>
  187. {isTime&&<MessageTime message={timeStampFilter(createdAt)}/>}
  188. <MessageLeftFile
  189. url={url}
  190. createdAt={createdAt}
  191. type={type}
  192. caption={caption}
  193. emoji={emoji}
  194. emojiCompanion={emojiCompanion}
  195. _id={_id}
  196. /></div>)
  197. } else {
  198. if (type === 'text') return (<div key={createdAt}>
  199. {isTime&&<MessageTime message={timeStampFilter(createdAt)}/>}
  200. <MessageRightText
  201. message={message}
  202. createdAt={createdAt}
  203. name={name}
  204. lastName={lastName}
  205. caption={caption}
  206. emoji={emoji}
  207. emojiCompanion={emojiCompanion}
  208. _id={_id}
  209. /></div>)
  210. if (type === 'image') return (<div key={createdAt}>
  211. {isTime&&<MessageTime message={timeStampFilter(createdAt)}/>}
  212. <MessageRightImage
  213. url={url}
  214. createdAt={createdAt}
  215. color={color}
  216. fullType={fullType}
  217. caption={caption}
  218. emoji={emoji}
  219. emojiCompanion={emojiCompanion}
  220. _id={_id}
  221. /></div>)
  222. if (type === 'audio') return (<div key={createdAt}>
  223. {isTime&&<MessageTime message={timeStampFilter(createdAt)}/>}
  224. <MessageRightAudio
  225. url={url}
  226. createdAt={createdAt}
  227. fullType={fullType}
  228. caption={caption}
  229. emoji={emoji}
  230. emojiCompanion={emojiCompanion}
  231. _id={_id}
  232. /></div>)
  233. if (type === 'video') return (<div key={createdAt}>
  234. {isTime&&<MessageTime message={timeStampFilter(createdAt)}/>}
  235. <MessageRightVideo
  236. url={url}
  237. createdAt={createdAt}
  238. fullType={fullType}
  239. caption={caption}
  240. emoji={emoji}
  241. emojiCompanion={emojiCompanion}
  242. _id={_id}
  243. /></div>)
  244. if (type) return (<div key={createdAt}>
  245. {isTime&&<MessageTime message={timeStampFilter(createdAt)}/>}
  246. <MessageRightFile
  247. url={url}
  248. createdAt={createdAt}
  249. type={type}
  250. caption={caption}
  251. emoji={emoji}
  252. emojiCompanion={emojiCompanion}
  253. _id={_id}
  254. /></div>)
  255. }
  256. }) : <AlertInfo name='You do not have messages yet!' />}
  257. </div>
  258. </div>
  259. <SendMessage isArrow={isArrow} />
  260. </div>
  261. );
  262. }
  263. export default ChatBar