PrivateChat.jsx 7.0 KB

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