index.tsx 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. import { makeStyles } from "@material-ui/core/styles";
  2. import SendIcon from '@mui/icons-material/Send';
  3. import MicNoneIcon from '@mui/icons-material/MicNone';
  4. import VideocamIcon from '@mui/icons-material/Videocam';
  5. import PauseIcon from '@mui/icons-material/Pause';
  6. import AttachFileIcon from '@mui/icons-material/AttachFile';
  7. import SentimentSatisfiedAltIcon from '@mui/icons-material/SentimentSatisfiedAlt';
  8. import CloseIcon from '@mui/icons-material/Close';
  9. import PhotoCameraFrontIcon from '@mui/icons-material/PhotoCameraFront';
  10. import CommentIcon from '@mui/icons-material/Comment';
  11. import Avatar from '@mui/material/Avatar';
  12. import Webcam from "react-webcam";
  13. import CameraIcon from '@mui/icons-material/Camera';
  14. import TextField from '@mui/material/TextField';
  15. import Picker from 'emoji-picker-react';
  16. import InputAdornment from '@mui/material/InputAdornment';
  17. import { useReactMediaRecorder } from "react-media-recorder";
  18. import { useState,useEffect,useCallback } from "react";
  19. import { useSelector } from "react-redux";
  20. import FilesMenu from "./FilesMenu";
  21. import ReplyBar from './ReplyBar'
  22. import ForwardBar from "./ForwardBar";
  23. import ForwardSearchList from "./ForwardSearchList";
  24. import {
  25. sentMessageById, sentImgMessageById, sentAudioMessageById,
  26. sentVideoMessageById,sentFileMessageById,sentMessageReplyById,sentMessageForwardById
  27. } from '../../../../../api-data'
  28. import { getChat } from '../../../../../redux/chat/selector'
  29. import { getRightIsOpen } from '../../../../../redux/control/selector'
  30. import { playNotification,prodBaseURL } from "../../../../../helpers";
  31. import { typingChat } from "../../../../../api-data";
  32. import { TMessage } from "../../../../../typescript/redux/messages/types";
  33. const useStyles = makeStyles({
  34. container: {
  35. width: '35vw',
  36. height:'6vh',
  37. position: 'fixed',
  38. bottom: '2vh',
  39. borderRadius: 8,
  40. padding: 10,
  41. display: 'flex',
  42. flexWrap: 'nowrap',
  43. alignContent: 'start',
  44. alignItems: 'start',
  45. color: '#6b6b6b',
  46. border:'solid 2px #ffffff',
  47. backgroundColor: '#ffffff',
  48. },
  49. containerActive: {
  50. width: '35vw',
  51. height:'6vh',
  52. position: 'fixed',
  53. bottom: '2vh',
  54. borderRadius: 8,
  55. padding: 10,
  56. display: 'flex',
  57. flexWrap: 'nowrap',
  58. alignContent: 'start',
  59. alignItems: 'start',
  60. border:'solid 2px rgb(41, 139, 231)',
  61. backgroundColor: '#ffffff',
  62. },
  63. textarea: {
  64. width: '100%',
  65. height: '100%',
  66. outline: 'none',
  67. border:'none',
  68. padding: '0px 10px',
  69. marginLeft: 8,
  70. marginRight: 8,
  71. overflowY:'auto',
  72. resize: 'none',
  73. '&::placeholder': {
  74. color: 'inherit',
  75. fontWeight: 600,
  76. fontSize:20
  77. },
  78. },
  79. attachIcon: {
  80. transform:'rotate(30deg)',
  81. },
  82. borderTop: {
  83. position: 'absolute',
  84. left: 0,
  85. top: -21,
  86. width: '100%',
  87. height: 1,
  88. background:'#ffffff',
  89. },
  90. filesMenu: {
  91. background: '#fdfdfd',
  92. position: 'absolute',
  93. width: '15vw',
  94. maxWidth: '100%',
  95. left: '61%',
  96. bottom:'9vh',
  97. zIndex: 10,
  98. visibility: 'visible',
  99. borderRadius: 10,
  100. padding: '4px 6px',
  101. },
  102. emoji: {
  103. position: 'absolute',
  104. zIndex: 10,
  105. visibility: 'visible',
  106. },
  107. captionTextField: {
  108. zIndex: 10,
  109. visibility: 'visible',
  110. width: '35vw',
  111. backgroundColor: '#ffffff',
  112. borderRadius:4,
  113. },
  114. iconCancel: {
  115. position: 'absolute',
  116. left: -72,
  117. bottom:-1,
  118. display:'flex',
  119. backgroundColor: '#ffffff',
  120. color: 'rgb(243, 69, 69)',
  121. border:'solid 4px rgb(243, 69, 69)',
  122. borderRadius: '50%',
  123. '&:hover': {
  124. backgroundColor: 'rgb(243, 69, 69)',
  125. color: '#ffffff',
  126. }
  127. },
  128. avatarCamera: {
  129. position: 'absolute',
  130. left: -72,
  131. bottom:-1,
  132. display: 'flex',
  133. borderRadius: '50%',
  134. zIndex: 10,
  135. border: 'solid 14px #ffffff',
  136. '&:hover': {
  137. backgroundColor: 'rgb(41, 139, 231)',
  138. border:'solid 14px rgb(41, 139, 231)',
  139. color: '#ffffff',
  140. }
  141. },
  142. avatarRight: {
  143. position: 'absolute',
  144. right: -72,
  145. bottom:-1,
  146. display: 'flex',
  147. borderRadius: '50%',
  148. zIndex: 10,
  149. border: 'solid 14px #ffffff',
  150. '&:hover': {
  151. backgroundColor: 'rgb(41, 139, 231)',
  152. border:'solid 14px rgb(41, 139, 231)',
  153. color: '#ffffff'
  154. }
  155. },
  156. pauseLeft: {
  157. position: 'absolute',
  158. left: -72,
  159. bottom:-1,
  160. zIndex: 10,
  161. },
  162. pauseRight: {
  163. position: 'absolute',
  164. right: -72,
  165. bottom:-1,
  166. zIndex: 10,
  167. },
  168. avatarPause: {
  169. backgroundColor: '#ffffff',
  170. cursor: 'pointer',
  171. animation: `$shake 1s`,
  172. animationIterationCount:'infinite',
  173. '&:hover': {
  174. backgroundColor: 'rgb(41, 139, 231)',
  175. color: '#ffffff',
  176. }
  177. },
  178. overlay: {
  179. position: 'fixed',
  180. top: 0,
  181. left: 0,
  182. width: '100vw',
  183. height: '100vh',
  184. zIndex:100
  185. },
  186. ringContainerLeft: {
  187. position: 'absolute',
  188. left: -25,
  189. top: -25,
  190. zIndex: 10,
  191. },
  192. ringContainerRight: {
  193. position: 'absolute',
  194. right: -25,
  195. top: -25,
  196. zIndex: 10,
  197. },
  198. circle: {
  199. width: 15,
  200. height: 15,
  201. backgroundColor: 'rgb(255, 4, 4)',
  202. borderRadius: '50%',
  203. position: 'relative'
  204. },
  205. ringRing: {
  206. border: '3px solid rgb(255, 4, 4)',
  207. borderRadius: '50%',
  208. height: 25,
  209. width: 25,
  210. position: 'absolute',
  211. right: -5,
  212. top: -5,
  213. animation: `$pulsate 1s ease-out`,
  214. animationIterationCount: 'infinite',
  215. opacity: 0
  216. },
  217. '@keyframes pulsate': {
  218. '0%': {transform: 'scale(0.1, 0.1)', opacity: 0},
  219. '50%': { opacity: 1},
  220. '100%': {transform: 'scale(1.2, 1.2)', opacity: 0},
  221. },
  222. '@keyframes shake': {
  223. '0%': { transform: 'translate(0.5px, 0.5px) rotate(0deg)'},
  224. '10%': { transform: 'translate(-0.5px, -1px) rotate(-1deg)'},
  225. '20%': { transform: 'translate(-1.5px, 0px) rotate(1deg)'},
  226. '30%': { transform: 'translate(1.5px, 1px) rotate(0deg)'},
  227. '40%': { transform: 'translate(0.5px, -0.5px) rotate(1deg)'},
  228. '50%': { transform: 'translate(-0.5px, 1px) rotate(-1deg)'},
  229. '60%': { transform: 'translate(-1.5px, 0.5px) rotate(0deg)'},
  230. '70%': { transform: 'translate(1.5px, 0.5px) rotate(-1deg)'},
  231. '80%': { transform: 'translate(-0.5px, -0.5px) rotate(1deg)'},
  232. '90%': { transform: 'translate(0.5px, 1px) rotate(0deg)'},
  233. '100%': { transform: 'translate(0.5px, -1px) rotate(-1deg)'},
  234. },
  235. overlayCamera: {
  236. position: 'fixed',
  237. top: 0,
  238. left: 0,
  239. width: '100vw',
  240. height: '100vh',
  241. zIndex: 100,
  242. backgroundColor: 'rgba(104, 105, 104, 0.6)',
  243. overflowY: 'hidden',
  244. display: 'flex',
  245. justifyContent: 'center',
  246. alignContent: 'center',
  247. alignItems: 'center',
  248. flexDirection:'column'
  249. },
  250. capturedPicture: {
  251. borderRadius: 10,
  252. border:'solid 2px rgb(62, 149, 231)'
  253. },
  254. capturePhoto: {
  255. color: '#ffffff',
  256. cursor: 'pointer',
  257. '&:hover': {
  258. color: '#48ff00',
  259. animation: `$rotating 2s linear infinite`
  260. },
  261. },
  262. '@keyframes rotating': {
  263. 'from': { transform: 'rotate(0deg)'},
  264. 'to': { transform: 'rotate(360deg)'},
  265. },
  266. });
  267. interface ISendMessage{
  268. isArrow: boolean,
  269. silentMode: boolean,
  270. isReply:TMessage | undefined,
  271. setIsReply: React.Dispatch<React.SetStateAction<TMessage | undefined>>,
  272. isForward: TMessage | undefined,
  273. setIsForward: React.Dispatch<React.SetStateAction<TMessage | undefined>>,
  274. modalForward: boolean,
  275. setModalForward: React.Dispatch<React.SetStateAction<boolean>>,
  276. handleScrollToTheMessage: (_id: string) => void,
  277. }
  278. const SendMessage = ({isArrow,silentMode,isReply,setIsReply,isForward,setIsForward,modalForward,setModalForward,handleScrollToTheMessage }:ISendMessage) => {
  279. const classes = useStyles();
  280. const { companionId } = useSelector(getChat)
  281. const rightIsOpen = useSelector(getRightIsOpen)
  282. const [value, setValue] = useState<string>('')
  283. const [file, setFile] = useState<any>(false)
  284. const [caption, setCaption] = useState<string>('')
  285. const [isOpenCaption, setIsOpenCaption] = useState<boolean>(false)
  286. const [isOpenMenu, setIsOpenMenu] = useState<boolean>(false)
  287. const [isOpenEmoji, setIsOpenEmoji] = useState<boolean>(false)
  288. const [isOpenCaptionEmoji, setIsOpenCaptionEmoji] = useState<boolean>(false)
  289. const [isRecording, setIsRecording] = useState<boolean>(false)
  290. const [isFilming, setIsFilming] = useState<boolean>(false)
  291. const [isOpenCamera, setIsOpenCamera] = useState<boolean>(false)
  292. const [type, setType] = useState<string>('')
  293. const [status, setStatus] = useState<string | null>(null)
  294. const [_status, _setStatus] = useState<string | null>(null)
  295. const { startRecording, stopRecording, mediaBlobUrl, clearBlobUrl, } = useReactMediaRecorder({ audio: true,blobPropertyBag:{type: "audio/mp3"}});
  296. const { startRecording: _startRecording, stopRecording: _stopRecording,
  297. mediaBlobUrl: _mediaBlobUrl, clearBlobUrl: _clearBlobUrl } = useReactMediaRecorder({ video: true, blobPropertyBag: { type: "video/mp4" } });
  298. const videoConstraints = {
  299. width: 1280,
  300. height: 720,
  301. facingMode: "user"
  302. };
  303. const onEmojiClick = (_e: any, emojiObject: any, flag: string) => {
  304. if (flag === 'input') {
  305. setValue(prevValue => prevValue + emojiObject.emoji)
  306. setIsOpenEmoji(false)
  307. }
  308. if (flag ==='caption') {
  309. setCaption(prevValue => prevValue + emojiObject.emoji)
  310. setIsOpenCaptionEmoji(false)
  311. }
  312. };
  313. const clearMessage = () => {
  314. setFile(false)
  315. setIsRecording(false)
  316. setIsFilming(false)
  317. setValue('')
  318. setCaption('')
  319. setType('')
  320. clearBlobUrl()
  321. _clearBlobUrl()
  322. setIsOpenMenu(false)
  323. setIsOpenEmoji(false)
  324. setIsOpenCaption(false)
  325. setIsOpenCaptionEmoji(false)
  326. setStatus(null)
  327. _setStatus(null)
  328. }
  329. const sentMessage = async () => {
  330. if (value && !isReply && !isForward) sentMessageById(companionId, value, caption.trim())
  331. if (value && isReply && !isForward) {
  332. sentMessageReplyById(isReply._id, value, caption.trim())
  333. setIsReply(undefined)
  334. }
  335. if (value&&!isReply && isForward) {
  336. sentMessageForwardById(isForward._id,isForward.companionIdForwardToAndFrom,value,caption.trim())
  337. setIsForward(undefined)
  338. }
  339. if (mediaBlobUrl && type === 'recording') {
  340. const audio = new XMLHttpRequest();
  341. audio.open('GET', mediaBlobUrl, true);
  342. audio.responseType = 'blob';
  343. audio.onload = () => {
  344. if (audio.status === 200) {
  345. const blob = audio.response
  346. const file = new File([blob], 'audio.mp3', {
  347. type: 'audio/mpeg'
  348. })
  349. const formData: any = new FormData()
  350. formData.append("audio", file)
  351. sentAudioMessageById(companionId, formData,caption.trim())
  352. clearBlobUrl()
  353. }
  354. }
  355. audio.send();
  356. }
  357. if (_mediaBlobUrl && type === 'filming') {
  358. const video = new XMLHttpRequest();
  359. video.open('GET', _mediaBlobUrl, true);
  360. video.responseType = 'blob';
  361. video.onload = () => {
  362. if (video.status === 200) {
  363. const blob = video.response
  364. const file = new File([blob], 'video.mp4',{
  365. type: "video/mp4"
  366. })
  367. const formData: any = new FormData()
  368. formData.append("video", file)
  369. sentVideoMessageById(companionId, formData,caption.trim())
  370. _clearBlobUrl()
  371. }
  372. }
  373. video.send();
  374. }
  375. if (file && type && type !== 'base64') {
  376. if (file.type.includes('image') && type === 'content') {
  377. const formData: any = new FormData()
  378. formData.append("image", file);
  379. sentImgMessageById(companionId, formData, caption.trim())
  380. }
  381. if (file.type.includes('audio') && type === 'content') {
  382. const formData: any = new FormData()
  383. formData.append("audio", file);
  384. sentAudioMessageById(companionId, formData,caption.trim())
  385. }
  386. if (file.type.includes('video') && type === 'content') {
  387. const formData: any = new FormData()
  388. formData.append("video", file);
  389. sentVideoMessageById(companionId, formData,caption.trim())
  390. }
  391. if (file.type.includes('application') && type === 'application') {
  392. const formData: any = new FormData()
  393. formData.append("file", file);
  394. sentFileMessageById(companionId, formData,caption.trim())
  395. }
  396. }
  397. if (typeof file === 'string' && type === 'base64') {
  398. fetch(file).then(res => res.blob()).then(blob => {
  399. const imgFile = new File([blob], "selfie", { type: "image/jpeg" })
  400. const formData: any = new FormData()
  401. formData.append("image", imgFile);
  402. sentImgMessageById(companionId, formData, caption.trim())
  403. })
  404. }
  405. clearMessage()
  406. !silentMode&&playNotification(`${prodBaseURL}/send.mp3`)
  407. }
  408. const handleTextarea = (e: React.ChangeEvent<HTMLTextAreaElement>) => setValue(e.target.value)
  409. const handleTextareaCaption = (e: React.ChangeEvent<HTMLTextAreaElement>) => setCaption(e.target.value)
  410. const handleFocusTextarea = async () => await typingChat(companionId,true)
  411. const handleBlurTextarea = async () => await typingChat(companionId,false)
  412. const handleOpenFileMenu = () => !isOpenMenu&&setIsOpenMenu(true)
  413. const handleCloseFileMenu = (e:any) => e.target.id === 'overlay'&&isOpenMenu&&setIsOpenMenu(false)
  414. const handleOpenEmoji = () => !isOpenEmoji && setIsOpenEmoji(true)
  415. const handleCloseEmoji = (e: any) => e.target.id === 'overlay' && isOpenEmoji && setIsOpenEmoji(false)
  416. const handleOpenCaptionEmoji = () => !isOpenEmoji && setIsOpenCaptionEmoji(true)
  417. const handleOpenCaption = () => !isOpenCaption && setIsOpenCaption(true)
  418. const handleCloseCaption = (e: any) => {
  419. if (e.target.id === 'overlay') {
  420. if(isOpenCaptionEmoji) return setIsOpenCaptionEmoji(false)
  421. isOpenCaption && setIsOpenCaption(false)
  422. }
  423. }
  424. const handleRecording = () => {
  425. if (isRecording) {
  426. setStatus('stopped')
  427. stopRecording()
  428. return
  429. }
  430. startRecording()
  431. setStatus('recording')
  432. setType('recording')
  433. setIsRecording(true)
  434. }
  435. const handleFilming = () => {
  436. if (isFilming) {
  437. _setStatus('stopped')
  438. _stopRecording()
  439. return
  440. }
  441. _startRecording()
  442. _setStatus('recording')
  443. setType('filming')
  444. setIsFilming(true)
  445. }
  446. const handleOpenCamera = () => setIsOpenCamera(true)
  447. const handleCloseCamera = (e: any) => {
  448. const id = e.target.id
  449. if (id === 'overlay') setIsOpenCamera(false)
  450. }
  451. const handleCaptureAvatar = (getScreenshot:() => string| null) => {
  452. setFile(getScreenshot())
  453. setType('base64')
  454. !silentMode&&playNotification(`${prodBaseURL}/cameraCapture.mp3`)
  455. }
  456. const handleCloseReply = () => {
  457. setIsReply(undefined)
  458. clearMessage()
  459. }
  460. const handleCloseForward= () => {
  461. setIsForward(undefined)
  462. clearMessage()
  463. }
  464. const defaultState = useCallback(() => {
  465. stopRecording()
  466. _stopRecording()
  467. clearBlobUrl()
  468. _clearBlobUrl()
  469. setStatus(null)
  470. _setStatus(null)
  471. setIsRecording(false)
  472. setIsFilming(false)
  473. setFile(false)
  474. setValue('')
  475. setCaption('')
  476. setType('')
  477. setIsOpenMenu(false)
  478. setIsOpenEmoji(false)
  479. setIsOpenCaption(false)
  480. setIsOpenCaptionEmoji(false)
  481. },[_clearBlobUrl,clearBlobUrl,_stopRecording,stopRecording])
  482. useEffect(() => {
  483. defaultState()
  484. }, [isReply, isForward, companionId])
  485. useEffect(() => {
  486. setIsReply(undefined)
  487. }, [companionId, setIsReply])
  488. useEffect(() => {
  489. const companionIdForwardToAndFrom = isForward?.companionIdForwardToAndFrom
  490. if(companionIdForwardToAndFrom&&companionIdForwardToAndFrom !== companionId) setIsForward(undefined)
  491. },[companionId])
  492. return (
  493. <div className={value || file || status === 'stopped' || _status === 'stopped' ?classes.containerActive:classes.container}>
  494. {isArrow && <div className={classes.borderTop}></div>}
  495. {isReply && <ReplyBar isReply={isReply} handleCloseReply={handleCloseReply}
  496. handleScrollToTheMessage={handleScrollToTheMessage} />}
  497. {isForward && modalForward && <ForwardSearchList setModalForward={setModalForward}
  498. setIsForward={setIsForward} companionId={companionId}/>}
  499. {isForward && !modalForward && <ForwardBar companionId={companionId}
  500. isForward={isForward} handleCloseForward={handleCloseForward}
  501. handleScrollToTheMessage={handleScrollToTheMessage} setIsForward={setIsForward}/>}
  502. {isFilming && _status !== 'stopped' &&
  503. <>
  504. <div className={classes.pauseLeft}>
  505. <Avatar onClick={handleFilming } className={classes.avatarPause}
  506. sx={{backgroundColor: '#ffffff',color:'#6b6b6b',width: 56, height: 56}}>
  507. <PauseIcon fontSize="large"/>
  508. </Avatar>
  509. </div>
  510. <div className={classes.ringContainerLeft}>
  511. <div className={classes.ringRing}></div>
  512. <div className={classes.circle}></div>
  513. </div>
  514. </>}
  515. {isRecording && status !== 'stopped' &&
  516. <>
  517. <div className={classes.pauseRight}>
  518. <Avatar onClick={handleRecording} className={classes.avatarPause}
  519. sx={{backgroundColor: '#ffffff',color:'#6b6b6b',width: 56, height: 56}}>
  520. <PauseIcon fontSize="large"/>
  521. </Avatar>
  522. </div>
  523. <div className={classes.ringContainerRight}>
  524. <div className={classes.ringRing}></div>
  525. <div className={classes.circle}></div>
  526. </div>
  527. </>}
  528. <CloseIcon onClick={clearMessage} fontSize="small" className={classes.iconCancel}
  529. sx={{width: 56, height: 56, display: file || value || (status === 'stopped'&&type)
  530. || (_status === 'stopped'&&type) ? 'inline-block' : 'none'}} />
  531. <VideocamIcon onClick={handleFilming} className={classes.avatarCamera}
  532. sx={{backgroundColor: '#ffffff', color: '#6b6b6b', width: 56, height: 56}}
  533. style={{ display: status !== null || _status === 'stopped' || file || value || isFilming || isReply || isForward? 'none' : 'block' }} />
  534. <SendIcon onClick={sentMessage} className={classes.avatarRight}
  535. sx={{backgroundColor: '#ffffff',color: 'rgb(41, 139, 231)', width: 56, height: 56}}
  536. style={{display: value || file || status === 'stopped' || _status === 'stopped'? 'block':'none' }}/>
  537. <MicNoneIcon onClick={handleRecording} className={classes.avatarRight}
  538. sx={{backgroundColor:'#ffffff',color: '#6b6b6b', width: 56, height: 56}}
  539. style={{display: !value && !file && status !== 'stopped' && _status === null&&!isRecording && !isReply && !isForward ? 'block' : 'none'}}/>
  540. <SentimentSatisfiedAltIcon onClick={handleOpenEmoji}
  541. fontSize='medium' sx={{color: isOpenEmoji ? 'rgb(41, 139, 231)' : '#6b6b6b', cursor: 'pointer',
  542. pointerEvents: file || status || _status ? 'none' : "auto",
  543. '&:hover': { color: 'rgb(41, 139, 231)' }, marginRight:1}}/>
  544. <CommentIcon onClick={handleOpenCaption}
  545. fontSize='medium' sx={{color: isOpenCaption || caption ? 'rgb(41, 139, 231)' : '#6b6b6b', cursor: 'pointer',
  546. pointerEvents: value || file || status === 'stopped' || _status === 'stopped'? 'auto' : "none",
  547. '&:hover': { color: 'rgb(41, 139, 231)'}}} />
  548. <div onClick={handleCloseEmoji} className={classes.overlay} id='overlay'
  549. style={{ display: isOpenEmoji ? 'block':'none'}}>
  550. <div className={classes.emoji} style={{left: rightIsOpen?'32.5vw':'45vw',bottom:'9vh'}}>
  551. <Picker onEmojiClick={(e,obj) => onEmojiClick(e,obj,'input')} />
  552. </div>
  553. </div>
  554. <div onClick={handleCloseCaption} className={classes.overlay} id='overlay'
  555. style={{ display: isOpenCaption ? 'block' : 'none' }}>
  556. {isOpenCaptionEmoji && <div className={classes.emoji}
  557. style={{ left: rightIsOpen ? '32.5vw' : '45vw',bottom:isReply || isForward?'23vh':'16vh' }}>
  558. <Picker onEmojiClick={(e,obj) => onEmojiClick(e,obj,'caption')} />
  559. </div>}
  560. <TextField className={classes.captionTextField} onChange={handleTextareaCaption}
  561. style={{ left: rightIsOpen ? '32.5vw' : '45vw', top: isReply || isForward?'78.5vh':'85vh' }}
  562. placeholder='Caption' value={caption} id="caption" name='caption' variant='outlined'
  563. InputProps={{
  564. startAdornment: (<InputAdornment position="start">
  565. <SentimentSatisfiedAltIcon onClick={handleOpenCaptionEmoji}
  566. sx={{color: isOpenCaptionEmoji ? 'rgb(41, 139, 231)' : '#6b6b6b', cursor: 'pointer',
  567. '&:hover': { color: 'rgb(41, 139, 231)' }}} />
  568. </InputAdornment>
  569. ),}}/>
  570. </div>
  571. <textarea disabled={file || type === 'recording' || type === 'filming'? true : false} value={value} onBlur={handleBlurTextarea}
  572. onFocus={handleFocusTextarea} onChange={handleTextarea} className={classes.textarea}
  573. placeholder={file ? 'The File is ready to send' : status === null && _status === null ? 'Message' :
  574. `${status === 'stopped' || _status === 'stopped' ? type === 'recording' || type === 'filming'?'Recorded':'Message':'Recording in progress...'}`} rows={1}
  575. style={{color:value || file || type === 'recording' || type === 'filming' ?'rgb(41, 139, 231)':'#6b6b6b'}}>
  576. </textarea>
  577. <PhotoCameraFrontIcon onClick={handleOpenCamera} fontSize='medium'
  578. sx={{color: isOpenCamera || type === 'base64' ? 'rgb(62, 149, 231)' : '#6b6b6b', marginRight: 1, cursor: 'pointer',
  579. pointerEvents: type === 'content' || type === 'application' || value || status !== null
  580. || _status !== null || isReply || isForward ? 'none' : "auto",
  581. '&:hover': { color: 'rgb(41, 139, 231)'}}}/>
  582. <AttachFileIcon onClick={handleOpenFileMenu} className={classes.attachIcon}
  583. fontSize='medium' sx={{color: isOpenMenu || type === 'content' || type === 'application' ? 'rgb(41, 139, 231)' : '#6b6b6b', cursor: 'pointer',
  584. pointerEvents: type === 'base64' || value || status !== null || _status !== null || isReply || isForward? 'none' : "auto", '&:hover':
  585. { color: 'rgb(41, 139, 231)'}}}/>
  586. <div onClick={handleCloseFileMenu} className={classes.overlay} id='overlay'
  587. style={{ display: isOpenMenu ? 'block':'none'}}>
  588. <div className={classes.filesMenu} style={{left: rightIsOpen?'52.5vw':'65vw'}}>
  589. <FilesMenu setFile={setFile} setValue={setValue} setIsOpenMenu={setIsOpenMenu} setType={setType} type={type}/>
  590. </div>
  591. </div>
  592. {isOpenCamera &&
  593. <div onClick={handleCloseCamera} id='overlay' className={classes.overlayCamera}>
  594. <Webcam audio={false} screenshotFormat="image/jpeg" width='40%'
  595. videoConstraints={videoConstraints} style={{marginBottom:30}}>
  596. {({ getScreenshot }) => <>
  597. <CameraIcon onClick={() => handleCaptureAvatar(getScreenshot)}
  598. className={classes.capturePhoto} fontSize='large' style={{marginBottom:30}} />
  599. <img className={classes.capturedPicture} width='300' height='174'
  600. style={{visibility:file?'visible':'hidden'}} src={file} alt='chosen pic'></img>
  601. </>}
  602. </Webcam>
  603. </div>}
  604. </div>
  605. )
  606. }
  607. export default SendMessage