index.tsx 26 KB

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