index.tsx 24 KB

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