ChatPage.jsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. import { useEffect, useState} from 'react';
  2. import {Button, Box} from '@mui/material';
  3. import TextareaAutosize from '@mui/material/TextareaAutosize';
  4. import { MessageForm } from './messageForm/MessegaForm';
  5. import { UserInfo } from './userInfo/UserInfo';
  6. import { store } from '../../store';
  7. import { removeToken, isPrivatChat, privateMessage} from '../../reducers/userDataReducer'
  8. import { useDispatch, useSelector } from 'react-redux';
  9. import {getSocket} from'../../reducers/socketReducer';
  10. import { sendMessage, storeMessage, fileMessage } from '../../reducers/messageReducer';
  11. import { editMessage } from '../../reducers/messageReducer';
  12. import { SwitchButton } from './SwitchButton';
  13. import { MessageEditorMenu } from './MessageEditorMenu.jsx';
  14. import imgBtn from '../../assets/img/gg.png';
  15. import imgBtnPhoto from '../../assets/img/photo.png'
  16. import './chatPage.scss';
  17. import WebcamCapture from './service/webCam/WebcamCapture';
  18. import useSound from 'use-sound';
  19. import getNotif from '../../assets/sendSound.mp3'
  20. import { PrivateChat } from './privateChat/PrivateChat';
  21. import { PrivatChatHeader } from './privateChat/PrivatChatHeader';
  22. import { socketEvents } from '../../utils/socketsEvents';
  23. export const ChatPage = () => {
  24. console.log('render')
  25. const dispatch = useDispatch();
  26. const token = useSelector(state => localStorage.getItem('token') || state.userDataReducer.token);
  27. const user = useSelector(state => state.getUserSocketReducer.socketUserData)
  28. const socket = useSelector(state => state.getUserSocketReducer.socket)
  29. const editOldMessage = useSelector(state => state.messageReducer.editMessage)
  30. let showUserInfoBox = useSelector(state => state.messageReducer.showUserInfoBox)// || localStorage.getItem('showBox');
  31. const toUser = useSelector(state => state.userDataReducer.toUser)
  32. const chatId = useSelector(state => state.userDataReducer.toUser.socketId)
  33. const isPrivatChat = useSelector(state => state.userDataReducer.isPrivatChat)
  34. const newPrivateMessages = useSelector(state => state.getUserSocketReducer.newPrivateMessages)
  35. const [message, setMessage] = useState({message: ''});
  36. const [isUserTyping, setUserTyping] = useState([]);
  37. const [isCamActiv, setisCamActiv] = useState(false);
  38. const [showSpinner, setshowSpinner] = useState(false);
  39. const [loadingPercentage, setLoadPercentage] = useState(0)
  40. const isTabletorMobile = (window.screen.width < 730);
  41. const isNewMessage = newPrivateMessages.length > 0
  42. const [play] = useSound(getNotif, {volume: 0.005});
  43. const axiosConfig = {
  44. headers: {
  45. "Content-type": "multipart/form-data"
  46. },
  47. onUploadProgress: (progress) => {
  48. const {loaded, total} = progress;
  49. const loadStatus = Math.floor(loaded * 100 / total);
  50. setLoadPercentage(loadStatus)
  51. if(loadStatus == 100) {
  52. setshowSpinner(false)
  53. }
  54. }}
  55. const webcamEventHandler = async () => {
  56. let stream = null;
  57. try {
  58. stream = await navigator.mediaDevices.getUserMedia({ video: { width: 300 }});
  59. if (stream){
  60. setisCamActiv(!isCamActiv)
  61. }
  62. } catch(err) {
  63. console.log(err)
  64. }
  65. setisCamActiv(!isCamActiv) // test camera
  66. }
  67. console.log('************render*************')
  68. const sendPrivateMessage = () => {
  69. console.log(toUser.socketId)
  70. socket.emit("private message", {
  71. fromUser: user,
  72. message: message.message,
  73. to: chatId,
  74. toUser
  75. })
  76. }
  77. useEffect(() => {
  78. if(socket) {
  79. socket.on('writing', (data) => {
  80. setUserTyping(data)
  81. setTimeout(() => setUserTyping([]), 500 )
  82. })
  83. }
  84. }, [socket, token])
  85. useEffect(() => {
  86. if(token && socket){
  87. console.log('useEffect...')
  88. socketEvents(socket)
  89. }
  90. }, [token, socket, user])
  91. return (
  92. <div className='rootContainer'>
  93. <Box className = {isTabletorMobile?'mobileRootBox':'rootBox'}>
  94. <Box className={isTabletorMobile?'usersBoxMobile':'usersBox'}
  95. sx = {showUserInfoBox ? {
  96. transform: "translateX(100%)",
  97. display: "block"
  98. }: { }}>
  99. <UserInfo/>
  100. { isTabletorMobile ? <SwitchButton/> : null}
  101. <Button
  102. style={isTabletorMobile ?
  103. {
  104. maxHeight:'20px',
  105. maxWidth: '15px',
  106. fontSize: '10px',
  107. marginLeft: '25px',
  108. marginRight: '10px'}
  109. :{margin:'10px 5px'}}
  110. variant="contained"
  111. onClick={()=> {
  112. localStorage.removeItem('token');
  113. dispatch(removeToken());
  114. socket.disconnect();
  115. }}>
  116. Logout
  117. </Button>
  118. </Box>
  119. <Box className ={isTabletorMobile ? 'rootMessageFormMobile':'rootMessageForm'} >
  120. {isCamActiv ?
  121. <div>
  122. <Button
  123. variant="contained"
  124. component="label"
  125. onClick = {() => webcamEventHandler()}
  126. >
  127. close camera
  128. </Button>
  129. <WebcamCapture />
  130. </div>
  131. :
  132. ""}
  133. {isPrivatChat? <PrivateChat/> : <MessageForm/>}
  134. {isUserTyping.isTyping && (isUserTyping.userName !== user.userName)? <span> User {isUserTyping.userName} typing..</span> : ""}
  135. <Box
  136. component="form"
  137. onSubmit = {e => {
  138. e.preventDefault()
  139. if (message.message.length){
  140. isPrivatChat? sendPrivateMessage() : dispatch(sendMessage({user, socket}));
  141. // isPrivatChat && dispatch(getSocket('allmessages'))
  142. isPrivatChat &&dispatch(editMessage({editMessage: ''}))
  143. setMessage({message: ''})
  144. play()
  145. }
  146. }}
  147. sx={(isTabletorMobile)?{
  148. display: 'flex',
  149. margin: '10px 2px'}
  150. :{
  151. display: 'flex',
  152. margin: '20px 5px'}
  153. }>
  154. <Button
  155. disabled={showSpinner}
  156. variant="contained"
  157. component="label"
  158. sx = {showSpinner?
  159. {
  160. minWidth: 'auto'}
  161. :
  162. {
  163. minWidth: 'auto',
  164. backgroundImage:'url(' + imgBtn + ')' ,
  165. backgroundPosition: 'center',
  166. backgroundRepeat: "no-repeat",
  167. backgroundSize: '20px 20px'
  168. }}
  169. style = {{color: 'green'}}
  170. >
  171. <input
  172. onChange={e =>{
  173. setshowSpinner(true)
  174. dispatch(fileMessage({files: e.target.files, axiosConfig}))
  175. }}
  176. type="file"
  177. multiple
  178. hidden
  179. />
  180. {showSpinner? loadingPercentage : ""}
  181. </Button>
  182. <Button
  183. variant="contained"
  184. component="label"
  185. sx = {{
  186. minWidth: 'auto',
  187. backgroundImage:'url(' + imgBtnPhoto + ')' ,
  188. backgroundPosition: 'center',
  189. backgroundRepeat: "no-repeat",
  190. backgroundSize: '20px 20px'
  191. }}
  192. onClick = {() => webcamEventHandler()}
  193. >
  194. </Button>
  195. <TextareaAutosize
  196. id="outlined-basic"
  197. label="Type a message..."
  198. variant="outlined"
  199. value={message.message}
  200. placeholder='type you message...'
  201. minRows={2}
  202. maxRows={4}
  203. className='textArea'
  204. onKeyPress={(e) => {
  205. if (e.key === "Enter") {
  206. e.preventDefault();
  207. isPrivatChat? sendPrivateMessage() : dispatch(sendMessage({user, socket}));
  208. //dispatch(getSocket('allmessages'))
  209. dispatch(editMessage({editMessage: ''}))
  210. setMessage({message: ''})
  211. }
  212. }}
  213. onChange={e => {
  214. dispatch(storeMessage({message: e.target.value}))
  215. !isPrivatChat &&socket.emit('userWriting');
  216. setMessage({message: e.target.value})}
  217. }
  218. // onFocus={ e => {
  219. // if (isTabletorMobile) {
  220. // e.target.className = 'focus'
  221. // }
  222. // }}
  223. // onBlur={e=> {
  224. // e.target.className = 'blur'
  225. // }}
  226. />
  227. <Button
  228. variant="contained"
  229. type='submit'
  230. disabled={user?.isMutted || !message.message.length}
  231. style={{width: '20%'}}
  232. >
  233. Send
  234. </Button>
  235. </Box>
  236. </Box>
  237. </Box>
  238. </div>
  239. )
  240. }