ChatPage.jsx 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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} 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. export const ChatPage = () => {
  21. const SOCKET_EVENTS = ['allmessages', 'usersOnline', 'allDbUsers']
  22. const dispatch = useDispatch();
  23. const token = useSelector(state => localStorage.getItem('token') || state.userDataReducer.token);
  24. const user = useSelector(state => state.getUserSocketReducer.socketUserData)
  25. const socket = useSelector(state => state.getUserSocketReducer.socket)
  26. const editOldMessage = useSelector(state => state.messageReducer.editMessage)
  27. let showUserInfoBox = useSelector(state => state.messageReducer.showUserInfoBox)// || localStorage.getItem('showBox');
  28. const [message, setMessage] = useState({message: ''});
  29. const [isUserTyping, setUserTyping] = useState([]);
  30. const [isCamActiv, setisCamActiv] = useState(false);
  31. const isTabletorMobile = (window.screen.width < 730);
  32. const [play] = useSound(getNotif, {volume: 0.2});
  33. const webcamEventHandler = async () => {
  34. let stream = null;
  35. try {
  36. stream = await navigator.mediaDevices.getUserMedia({ video: { width: 300 }});
  37. if (stream){
  38. setisCamActiv(!isCamActiv)
  39. }
  40. } catch(err) {
  41. console.log(err)
  42. }
  43. setisCamActiv(!isCamActiv) // test camera
  44. }
  45. useEffect(() => {
  46. if(socket) {
  47. socket.on('writing', (data) => {
  48. setUserTyping(data)
  49. setTimeout(() => setUserTyping([]), 500 )
  50. })
  51. }
  52. }, [socket])
  53. useEffect(() => {
  54. if(token){
  55. SOCKET_EVENTS.map(event => dispatch(getSocket(event)))
  56. }
  57. }, [token, editOldMessage, showUserInfoBox])
  58. return (
  59. <div className='rootContainer'>
  60. <Box className = {isTabletorMobile?'mobileRootBox':'rootBox'}>
  61. <Box className={isTabletorMobile?'usersBoxMobile':'usersBox'}
  62. sx = {showUserInfoBox ? {
  63. transform: "translateX(100%)",
  64. display: "none"
  65. }: { }}>
  66. <UserInfo/>
  67. { isTabletorMobile ? <SwitchButton/> : null}
  68. <Button
  69. style={isTabletorMobile ?
  70. {
  71. maxHeight:'20px',
  72. maxWidth: '15px',
  73. fontSize: '10px',
  74. marginLeft: '25px',
  75. marginRight: '10px'}
  76. :{margin:'10px 5px'}}
  77. variant="contained"
  78. onClick={()=> {
  79. localStorage.removeItem('token');
  80. dispatch(removeToken());
  81. socket.disconnect();
  82. }}>
  83. Logout
  84. </Button>
  85. </Box>
  86. <Box className ={isTabletorMobile ? 'rootMessageFormMobile':'rootMessageForm'} >
  87. {isCamActiv ?
  88. <div>
  89. <Button
  90. variant="contained"
  91. component="label"
  92. onClick = {() => webcamEventHandler()}
  93. >
  94. close camera
  95. </Button>
  96. <WebcamCapture />
  97. </div>
  98. :
  99. ""}
  100. <MessageForm/>
  101. {isUserTyping.isTyping && (isUserTyping.userName !== user.userName)? <span> User {isUserTyping.userName} typing..</span> : ""}
  102. <Box
  103. component="form"
  104. onSubmit = {e => {
  105. e.preventDefault()
  106. if (message.message.length){
  107. dispatch(sendMessage({user, socket}))
  108. dispatch(getSocket('allmessages'))
  109. dispatch(editMessage({editMessage: ''}))
  110. setMessage({message: ''})
  111. play()
  112. }
  113. }}
  114. sx={(isTabletorMobile)?{
  115. display: 'flex',
  116. margin: '10px 2px'}
  117. :{
  118. display: 'flex',
  119. margin: '20px 5px'}
  120. }>
  121. <Button
  122. variant="contained"
  123. component="label"
  124. sx = {{
  125. minWidth: 'auto',
  126. backgroundImage:'url(' + imgBtn + ')' ,
  127. backgroundPosition: 'center',
  128. backgroundRepeat: "no-repeat",
  129. backgroundSize: '20px 40px'
  130. }}
  131. >
  132. <input
  133. onChange={e =>{
  134. dispatch(fileMessage(e.target.files))
  135. }}
  136. type="file"
  137. multiple
  138. hidden
  139. />
  140. </Button>
  141. <Button
  142. variant="contained"
  143. component="label"
  144. sx = {{
  145. minWidth: 'auto',
  146. backgroundImage:'url(' + imgBtnPhoto + ')' ,
  147. backgroundPosition: 'center',
  148. backgroundRepeat: "no-repeat",
  149. backgroundSize: '20px 20px'
  150. }}
  151. onClick = {() => webcamEventHandler()}
  152. >
  153. </Button>
  154. <TextareaAutosize
  155. id="outlined-basic"
  156. label="Type a message..."
  157. variant="outlined"
  158. value={message.message}
  159. placeholder='type you message...'
  160. minRows={2}
  161. maxRows={4}
  162. className='textArea'
  163. onKeyPress={(e) => {
  164. if (e.key === "Enter") {
  165. e.preventDefault();
  166. dispatch(sendMessage({user, socket}))
  167. dispatch(getSocket('allmessages'))
  168. dispatch(editMessage({editMessage: ''}))
  169. setMessage({message: ''})
  170. }
  171. }}
  172. onChange={e => {
  173. dispatch(storeMessage({message: e.target.value}))
  174. socket.emit('userWriting');
  175. setMessage({message: e.target.value})}
  176. }
  177. // onFocus={ e => {
  178. // if (isTabletorMobile) {
  179. // e.target.className = 'focus'
  180. // }
  181. // }}
  182. // onBlur={e=> {
  183. // e.target.className = 'blur'
  184. // }}
  185. />
  186. <Button
  187. variant="contained"
  188. type='submit'
  189. disabled={user?.isMutted || !message.message.length}
  190. style={{width: '20%'}}
  191. >
  192. Send
  193. </Button>
  194. </Box>
  195. </Box>
  196. </Box>
  197. </div>
  198. )
  199. }