index.tsx 8.9 KB

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