index.tsx 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. import Stack from '@mui/material/Stack';
  2. import IconButton from '@mui/material/IconButton';
  3. import MenuItem from '@mui/material/MenuItem';
  4. import ListItemText from '@mui/material/ListItemText';
  5. import CloseIcon from '@mui/icons-material/Close';
  6. import MenuOpenIcon from '@mui/icons-material/MenuOpen';
  7. import Button from '@mui/material/Button';
  8. import LibraryMusicIcon from '@mui/icons-material/LibraryMusic';
  9. import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile';
  10. import ImageIcon from '@mui/icons-material/Image';
  11. import ContentCopyIcon from '@mui/icons-material/ContentCopy';
  12. import VideoLibraryIcon from '@mui/icons-material/VideoLibrary';
  13. import { makeStyles } from '@material-ui/core'
  14. import { useSelector } from 'react-redux';
  15. import { useState,useEffect} from 'react';
  16. import { TMessage } from '../../../../../typescript/redux/messages/types';
  17. import { getPinnedMessagesMemo } from '../../../../../redux/pinnedMessages/selector';
  18. import { pinMessageById } from '../../../../../api-data';
  19. const useStyles = makeStyles({
  20. container: {
  21. marginLeft: 20,
  22. display: 'flex',
  23. alignContent: 'center',
  24. alignItems: 'center',
  25. position:'relative'
  26. },
  27. iconClose: {
  28. '&:hover': {
  29. transform: 'rotate(180deg)',
  30. transition: 'all 250ms ease-out ',
  31. }
  32. },
  33. listWrapper: {
  34. background: '#fdfdfd',
  35. padding: 0,
  36. },
  37. listWrapperDashes: {
  38. position: 'absolute',
  39. top: 0,
  40. width: 2,
  41. height: '100%',
  42. display: 'flex',
  43. flexDirection: 'column',
  44. justifyContent:'space-around',
  45. flexWrap:'nowrap',
  46. listStyle:'none'
  47. },
  48. overlay: {
  49. position: 'fixed',
  50. top: 0,
  51. left: 0,
  52. width: '100vw',
  53. height: '100vh',
  54. zIndex: 100,
  55. backgroundColor: 'rgba(104, 105, 104, 0.6)',
  56. overflowY: 'hidden',
  57. },
  58. modalUnpin: {
  59. background: '#ffffff',
  60. position: 'absolute',
  61. content:'',
  62. width: '20%',
  63. height:'auto',
  64. left: '40%',
  65. bottom: '48.5%',
  66. borderRadius: 10,
  67. padding: 10,
  68. display: 'flex',
  69. flexDirection:'column'
  70. },
  71. folderIcon: {
  72. color: '#54b0fc',
  73. },
  74. })
  75. interface IPinnedBar {
  76. chatDivRef: any | null,
  77. handleOpenPinned: () => void,
  78. }
  79. const PinnedBar = ({chatDivRef,handleOpenPinned}:IPinnedBar) => {
  80. const classes = useStyles()
  81. const pinnedMessagesMemo = useSelector(getPinnedMessagesMemo)
  82. const [openedPin, setOpenedPin] = useState<TMessage | null>(null)
  83. const [openedIndex, setOpenedIndex] = useState<number>(0)
  84. const [modal, setModal] = useState<boolean>(false)
  85. const heightPerDash = 100/pinnedMessagesMemo.length
  86. const heightOfDash = heightPerDash-((heightPerDash/100)*20)
  87. const handleActivePin = () => {
  88. const childNodes = chatDivRef.current.childNodes[0].childNodes
  89. let toScrollNode: any
  90. if (pinnedMessagesMemo.length - 1 === openedIndex) {
  91. setOpenedIndex(0)
  92. toScrollNode = [ ...childNodes ].find((el:any) => el.id === pinnedMessagesMemo[0]._id)
  93. } else {
  94. setOpenedIndex(prevState => prevState + 1)
  95. toScrollNode = [...childNodes].find((el: any) => el.id === pinnedMessagesMemo[openedIndex + 1]._id)
  96. }
  97. if (toScrollNode) {
  98. toScrollNode = [...toScrollNode.childNodes].slice(-1)[0]
  99. toScrollNode.style.backgroundColor = 'rgba(70, 70, 70, 0.4)'
  100. toScrollNode.style.boxShadow = '0px 0px 6px 0px #ffffff'
  101. toScrollNode.scrollIntoView({ behavior: 'smooth' })
  102. setTimeout(() => {
  103. toScrollNode.style.backgroundColor = 'unset'
  104. toScrollNode.style.boxShadow = 'unset'
  105. }, 2000)
  106. }
  107. }
  108. const handleUnpin = (e: any) => {
  109. const id = e.target.id
  110. if (id === 'overlay' || id === 'cancel') return setModal(false)
  111. if (id === 'unpin' && openedPin) {
  112. pinMessageById(openedPin._id, !openedPin.pinned)
  113. setModal(false)
  114. if (openedIndex - 1 >= 0) {
  115. return setOpenedIndex(prevState => prevState - 1)
  116. } else {
  117. setOpenedIndex(0)
  118. }
  119. }
  120. }
  121. useEffect(() => {
  122. setOpenedPin(pinnedMessagesMemo[openedIndex])
  123. }, [pinnedMessagesMemo,openedIndex])
  124. return openedPin ?
  125. <Stack className={classes.container} direction="row">
  126. <ul className={classes.listWrapperDashes}>
  127. {pinnedMessagesMemo.map(({ _id }) =>
  128. <li key={_id} style={{backgroundColor:openedPin._id === _id? "#00aeff":"#addbf0",
  129. height: `${heightOfDash}%`}}></li>)}
  130. </ul>
  131. <ul className={classes.listWrapper}>
  132. <MenuItem onClick={handleActivePin}>
  133. <ListItemText style={{margin:'0px 10px 0px 20px'}}
  134. primary={`Pinned Message ${openedIndex + 1} of ${pinnedMessagesMemo.length}`}
  135. primaryTypographyProps={{ color: "#0379af",fontSize:16 }}
  136. secondary={`Type : ${openedPin.type.toUpperCase()}`}
  137. secondaryTypographyProps={{ fontSize:16 }}/>
  138. {openedPin.type === 'text' &&<ContentCopyIcon className={classes.folderIcon} fontSize='large' />}
  139. {openedPin.type === 'audio' &&<LibraryMusicIcon className={classes.folderIcon} fontSize='large' />}
  140. {openedPin.type === 'video' &&<VideoLibraryIcon className={classes.folderIcon} fontSize='large' />}
  141. {openedPin.type === 'image' &&<ImageIcon className={classes.folderIcon} fontSize='large' />}
  142. {openedPin.type === 'pdf'&&<InsertDriveFileIcon className={classes.folderIcon} fontSize='large' />}
  143. {openedPin.type === 'docx'&&<InsertDriveFileIcon className={classes.folderIcon} fontSize='large' />}
  144. </MenuItem>
  145. </ul>
  146. <IconButton onClick={() => setModal(true)} aria-label="delete" size="medium">
  147. <CloseIcon className={classes.iconClose} fontSize='medium'/>
  148. </IconButton>
  149. <IconButton onClick={handleOpenPinned} aria-label="delete" size="medium">
  150. <MenuOpenIcon fontSize='medium'/>
  151. </IconButton>
  152. {modal &&
  153. <div onClick={handleUnpin} className={classes.overlay} id='overlay'>
  154. <div className={classes.modalUnpin}>
  155. <h3 style={{color: '#2c2c2c'}}>Telegram</h3>
  156. <p style={{ color: '#050505' }}>Would you like to unpin this message?</p>
  157. <Button id='unpin' variant="text" color="error" style={{fontWeight:500,fontSize:22}}>
  158. UNPIN
  159. </Button>
  160. <Button id='cancel' variant="text" style={{fontWeight:500,fontSize:22}}>
  161. CANCEL
  162. </Button>
  163. </div>
  164. </div>}
  165. </Stack> :
  166. null
  167. }
  168. export default PinnedBar