ChatPage.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. import { useEffect, useState, useMemo, useRef, Fragment} from 'react';
  2. import { MessageForm } from './messageForm/MessageForm';
  3. import {Button,Avatar, Box, Container} from '@mui/material';
  4. import { UserInfo } from './userInfo/UserInfo';
  5. import { dateFormat } from './utils/dateFormat';
  6. import {io} from 'socket.io-client';
  7. import './chatPage.scss';
  8. import { scrollToBottom } from './utils/scrollToBottom';
  9. import { banUser } from './service/banUser';
  10. import { muteUser } from './service/muteUser';
  11. import {sendMessage} from './service/sendMessage';
  12. export const ChatPage = ({ onExit, token }) => {
  13. const [socket, setSocket] = useState(null);
  14. const [messages, setMessages] = useState([])
  15. const [user, setUser] = useState({})
  16. const [usersOnline, setUsersOnline] = useState([])
  17. const [allUsers, setAllUsers] = useState([])
  18. const randomColor = require('randomcolor');
  19. const endMessages = useRef(null);
  20. const audio = useRef(null)
  21. useEffect(() => {
  22. if(token){
  23. try {
  24. setSocket(io.connect(
  25. process.env.REACT_APP_SERVER_URL || 'http://localhost:5000',
  26. {auth: {token}})
  27. )
  28. } catch (error) {
  29. console.log(error)
  30. }
  31. }
  32. }, [token])
  33. useEffect(() => {
  34. if(socket){
  35. socket.on('connected', (data) => {
  36. setUser(data);
  37. }).on('error', (e) => {
  38. console.log('On connected', e)
  39. });
  40. socket.on('allmessages', (data) => {
  41. setMessages(data)
  42. }).on('error', (e) => {
  43. console.log('allmessages', e)
  44. });
  45. socket.on('usersOnline', (data) => {
  46. setUsersOnline(data)
  47. }).on('error', (e) => {
  48. console.log(e)
  49. });
  50. socket.on('allDbUsers', (data) => {
  51. setAllUsers(data);
  52. }).on('error', (e) => {
  53. console.log(e)
  54. });
  55. socket.on('disconnect', (data) => {
  56. if(data === 'io server disconnect') {
  57. socket.disconnect();
  58. onExit();
  59. }
  60. }).on('error', (e) => {
  61. console.log('error token', e)
  62. });
  63. socket.on('message', (data) => {
  64. setMessages((messages) => [...messages, data] )
  65. }).on('error', (e) => {
  66. console.log(e)
  67. });
  68. }
  69. // return () => {
  70. // socket.off('connected');
  71. // socket.off('allmessages');
  72. // }
  73. }, [socket])
  74. useEffect(() => {
  75. scrollToBottom(endMessages)
  76. }, [messages]);
  77. let userColor = useMemo(() => randomColor(),[]);//color for myavatar
  78. return (
  79. <Container maxWidth="lg">
  80. <Box
  81. sx={{
  82. display: 'flex',
  83. height: '100vh'
  84. }}>
  85. <Box
  86. sx={{
  87. display: 'flex',
  88. flexGrow:'2',
  89. flexDirection: 'column',
  90. }}>
  91. <Box
  92. className='messageBox'
  93. sx={{
  94. display: 'flex',
  95. flexGrow:'2',
  96. flexDirection: 'column',
  97. overflow: 'scroll',
  98. height: '90vh'
  99. }}>
  100. {
  101. messages.map((item, i) =>
  102. <Fragment key={i} >
  103. <Avatar
  104. sx={
  105. (item.userName == user.userName)
  106. ?
  107. {
  108. alignSelf: 'flex-end',
  109. fontSize: 10,
  110. width: '60px',
  111. height: '60px',
  112. color:'black',
  113. backgroundColor: userColor
  114. }
  115. :
  116. {
  117. backgroundColor: (usersOnline.map(current =>{
  118. if(item.userName == current.userName ) {
  119. return current.color
  120. }
  121. } )),
  122. fontSize: 10,
  123. width: '60px',
  124. height: '60px',
  125. color:'black'
  126. }
  127. }>
  128. {item.userName}
  129. </Avatar>
  130. <div
  131. key={item._id}
  132. className={
  133. (item.userName == user.userName)
  134. ?
  135. 'message myMessage'
  136. :
  137. 'message'}
  138. >
  139. <p>{item.text}</p>
  140. <div
  141. style={{fontStyle:'italic',
  142. color: 'grey',
  143. fontSize: 14}}>
  144. {dateFormat(item).time}
  145. </div>
  146. <div
  147. style={{fontStyle:'italic',
  148. fontSize: 12,
  149. color: 'grey'}}>
  150. {dateFormat(item).year}
  151. </div>
  152. </div>
  153. </Fragment>
  154. )}
  155. <div ref={endMessages}></div>
  156. </Box>
  157. <MessageForm
  158. data = {user}
  159. sendMessage = {(data) => {
  160. sendMessage(data, socket)
  161. }}>
  162. </MessageForm>
  163. </Box>
  164. <Box
  165. className='usersBox'
  166. sx={{
  167. overflow: 'scroll',
  168. }}>
  169. <Button
  170. sx={{margin:'10px 5px'}}
  171. variant="outlined"
  172. onClick={(e)=> {
  173. socket.disconnect()
  174. onExit()
  175. }}>
  176. Logout
  177. </Button>
  178. <UserInfo
  179. data = {user.userName}
  180. color={userColor}/>
  181. {
  182. user.isAdmin
  183. ?
  184. allUsers.map((item) =>
  185. <div
  186. key={item._id}
  187. className='online'>
  188. <div style={
  189. {color: (usersOnline.map(current =>{
  190. if(item.userName == current.userName ) {
  191. return current.color
  192. }
  193. }))}}>{item.userName}</div>
  194. <div>
  195. <Button
  196. variant="contained"
  197. onClick={()=>{
  198. muteUser(item.userName, item.isMutted, socket)
  199. }}
  200. sx={{
  201. margin:'3px',
  202. height: '25px'
  203. }}>
  204. {item.isMutted
  205. ?
  206. 'unmute'
  207. : 'mute'}
  208. </Button>
  209. <Button
  210. variant="contained"
  211. onClick={()=>{
  212. banUser(item.userName, item.isBanned, socket)
  213. }}
  214. sx={{
  215. margin:'3px',
  216. height: '25px'
  217. }}>
  218. {item.isBanned
  219. ? 'unban'
  220. : 'ban'}
  221. </Button>
  222. </div>
  223. {
  224. usersOnline.map((user, i) =>{
  225. if(item.userName == user.userName){
  226. return <span key={i} style={{color: 'green'}}>online</span>
  227. }
  228. })
  229. }
  230. </div>)
  231. :
  232. usersOnline.map((item, i) =>
  233. <div
  234. key={i}
  235. className='online'>
  236. <div style={{color: item.color}}>
  237. {item.userName}
  238. </div>
  239. <span style={{color: 'green'}}>
  240. online
  241. </span>
  242. </div>)
  243. }
  244. </Box>
  245. </Box>
  246. </Container>
  247. )
  248. }