index.tsx 10 KB

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