MessegaForm.jsx 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. import { Avatar, Box, Button} from '@mui/material';
  2. import { dateFormat } from '../utils/dateFormat';
  3. import { useSelector } from 'react-redux';
  4. import { useRef, useEffect, useState} from 'react';
  5. import { scrollToBottom } from '../utils/scrollToBottom';
  6. import { useDispatch } from 'react-redux';
  7. import { editMessage } from '../../../reducers/messageReducer';
  8. import { StyledAvatar } from './StyledAvatar';
  9. import { MessageEditorMenu } from '../MessageEditorMenu.jsx';
  10. import imgBtn from '../../../assets/img/gg.png';
  11. import useSound from 'use-sound';
  12. import notifSound from '../../../assets/sendSound.mp3'
  13. export const MessageForm = () => {
  14. const dispatch = useDispatch();
  15. const socket = useSelector(state => state.getUserSocketReducer.socket)
  16. const SERVER_URL = process.env.REACT_APP_SERVER_URL|| 'http://192.168.0.107:5000/';
  17. const startMessages = useSelector(state => state.getUserSocketReducer.startMessages)
  18. const user = useSelector(state => state.getUserSocketReducer.socketUserData)
  19. const usersOnline = useSelector(state => state.getUserSocketReducer.usersOnline)
  20. const userNamesOnlineSet = new Set(usersOnline.map( i => i.userName))
  21. const storeMessageId = useSelector(state => state.messageReducer.messageId)
  22. const newMessages = useSelector(state => state.getUserSocketReducer.newMessages)
  23. let endMessages = useRef(null);
  24. const [isEditing, setIsEditing] = useState(false)
  25. const [isEditiedMessage, setIsEditiedMessage] = useState(false) //need to type in the bottom of message after message was edited
  26. const regYoutube = /http(?:s?):\/\/(?:www\.)?youtu(?:be\.com\/watch\?v=|\.be\/)([\w\-\_]*)(&(amp;)?‌​[\w\?‌​=]*)?/; //for youtube video
  27. const [play] = useSound(notifSound);
  28. useEffect(() => {
  29. if (!isEditing) {
  30. scrollToBottom((endMessages))
  31. }
  32. if(newMessages.length > 0){
  33. newMessages.map(i => console.log('newmessage', i.userName === user.userName))
  34. }
  35. }, [startMessages, newMessages]);
  36. const messages = startMessages.concat(newMessages)
  37. return (
  38. <Box className='messageBox'>
  39. {
  40. messages.map((item, i) =>
  41. <div key={i + 1} className={
  42. (item.userName === user.userName)? 'message myMessage' :'message'}
  43. onClick = {(e) => {
  44. console.log(e.target)
  45. if(e.target.closest("div").className.includes('myMessage') && (item.userName === user.userName) && (item.text === e.target.textContent)){
  46. e.currentTarget.className += ' editMessage'
  47. dispatch(editMessage({socket, editMessage: e.target.textContent, messageId: item._id}))
  48. setIsEditing(true)
  49. }
  50. }}
  51. >
  52. {storeMessageId === item._id ? <MessageEditorMenu />: ""}
  53. <StyledAvatar
  54. anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
  55. variant = {userNamesOnlineSet.has(item.userName)? 'dot' : ''}
  56. >
  57. <Avatar
  58. key={i}
  59. src= {SERVER_URL + item?.user?.avatar}
  60. sx={
  61. (item.userName === user.userName)
  62. ?
  63. {
  64. alignSelf: 'flex-end',
  65. }
  66. :
  67. {}
  68. }
  69. >
  70. {item?.userName.slice(0, 1)}
  71. </Avatar>
  72. </StyledAvatar>
  73. <div
  74. key={i}
  75. className={
  76. (item.userName === user.userName)? 'message myMessage' :'message'}>
  77. {
  78. item.text.match(regYoutube) ?
  79. <iframe
  80. width="280"
  81. height="160"
  82. src={`https://www.youtube.com/embed/`+ (item.text.match(regYoutube)[1])}
  83. title="YouTube video player"
  84. allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
  85. allowFullScreen>
  86. </iframe>
  87. :
  88. (item.file && item.fileType && item.fileType.split('/')[0] !== 'image') ?
  89. <div style={{'display': 'flex', 'alignItems': 'center'}} >
  90. <a href={SERVER_URL + item.file} download>
  91. <Button
  92. variant="contained"
  93. component="label"
  94. sx = {{
  95. minWidth: 'auto',
  96. minHeight: '25px',
  97. backgroundImage:'url(' + imgBtn + ')' ,
  98. backgroundPosition: 'center',
  99. backgroundRepeat: "no-repeat",
  100. backgroundSize: '15px 20px',
  101. backgroundColor: '#d3d3d3'
  102. }}
  103. >
  104. </Button>
  105. </a>
  106. <p style={{'marginLeft': '15px'}} >{item.text}</p>
  107. </div>
  108. :
  109. <p>{item.text}</p>
  110. }
  111. {
  112. (item.file && item.fileType && item.fileType.split('/')[0] == 'image' ) //need to fix for other type files
  113. ?
  114. <img width={'auto'} height={350} src={ SERVER_URL + item.file} alt={'error load image'}/>
  115. :
  116. ''
  117. }
  118. </div>
  119. {isEditiedMessage && <i>Edited</i>}
  120. <div className={
  121. (item.userName === user.userName)? 'myDate' :'date'}>
  122. {dateFormat(item).time}
  123. </div>
  124. </div>
  125. )}
  126. <div ref={endMessages}></div>
  127. </Box>
  128. )
  129. }