index.tsx 7.3 KB

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