123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308 |
- import { makeStyles } from "@material-ui/core/styles";
- import SendIcon from '@mui/icons-material/Send';
- import MicNoneIcon from '@mui/icons-material/MicNone';
- import AttachFileIcon from '@mui/icons-material/AttachFile';
- import SentimentSatisfiedAltIcon from '@mui/icons-material/SentimentSatisfiedAlt';
- import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward';
- import Avatar from '@mui/material/Avatar';
- import CloseIcon from '@mui/icons-material/Close';
- import { useReactMediaRecorder } from "react-media-recorder";
- import { useState } from "react";
- import { useSelector } from "react-redux";
- import FilesMenu from "../FilesMenu";
- import NotDone from "../../../../reusableComponents/NotDone";
- import {
- sentMessageById, sentImgMessageById, sentAudioMessageById,
- sentVideoMessageById,sentFileMessageById
- } from '../../../../../api-data'
- import { getChat } from '../../../../../redux/chat/selector'
- import { getIsOpen } from '../../../../../redux/control/selector'
- import { playNotification } from "../../../../../helpers";
- import { typingChat } from "../../../../../api-data";
- const useStyles = makeStyles({
- container: {
- display: "flex",
- justifyContent: "space-between",
- alignContent: 'flex-end',
- alignItems:'flex-end',
- width: 700,
- position: 'fixed',
- bottom: 20,
- paddingTop:10,
- },
- inputContainer: {
- position:'relative',
- minWidth: 634,
- maxWidth: 634,
- maxHeight:56,
- display: 'flex',
- flexWrap: 'nowrap',
- alignContent: 'center',
- alignItems: 'center',
- color: '#6b6b6b',
- backgroundColor: '#ffffff',
- borderRadius: 8,
- padding: 10,
- marginRight: 10,
- "&:after": {
- content: "''",
- position: "absolute",
- width: "0",
- height: "0",
- borderBottom: "15px solid #ffffff",
- borderLeft: "15px solid transparent",
- borderRight: "15px solid transparent",
- bottom: "0",
- right: "-15px"
- },
- "&:before": {
- content: "''",
- position: "absolute",
- width: "0",
- height: "0",
- borderBottom: "17px solid #ffffff",
- borderLeft: "16px solid transparent",
- borderRight: "16px solid transparent",
- bottom: "0px",
- right: "-17px"
- }
- },
- textarea: {
- minWidth: 550,
- maxWidth: 550,
- outline: 'none',
- border:'none',
- padding: '0px 10px',
- marginLeft: 8,
- marginRight: 8,
- overflowY:'auto',
- resize: 'none',
- height: 'auto',
- '&::placeholder': {
- color: 'rgb(82, 82, 82)',
- fontWeight: 600
- }
- },
- attachIcon: {
- transform:'rotate(30deg)',
- },
- filesMenu: {
- background: '#fdfdfd',
- position: 'absolute',
- width: 300,
- maxWidth: '100%',
- left: '61%',
- bottom:90,
- zIndex: 10,
- visibility: 'visible',
- borderRadius: 10,
- padding: '4px 6px',
- },
- emoji: {
- background: '#fdfdfd',
- position: 'absolute',
- width: 350,
- height:350,
- bottom:90,
- zIndex: 10,
- visibility: 'visible',
- borderRadius: 10,
- padding: '0px 6px',
- },
- avatar: {
- '&:hover': {
- backgroundColor: 'rgb(41, 139, 231)',
- color: '#ffffff',
- }
- },
- avatarArrow: {
- left: 120,
- bottom:200,
- '&:hover': {
- backgroundColor: 'rgb(41, 139, 231)',
- color: '#ffffff',
- }
- },
- iconCancel: {
- position: 'absolute',
- left:-45,
- display:'flex',
- backgroundColor: '#945353',
- width: 56,
- height: 56,
- color: '#6b6b6b',
- borderRadius: '50%',
- '&:hover': {
- backgroundColor: 'rgb(218, 18, 18)',
- color: '#ffffff',
- }
- },
- overlay: {
- position: 'fixed',
- top: 0,
- left: 0,
- width: '100vw',
- height: '100vh',
- zIndex:100
- },
- });
- interface ISendMessage{
- isArrow:boolean,
- handleScrollTo:() => void
- }
- const SendMessage = ({isArrow,handleScrollTo}:ISendMessage) => {
- const classes = useStyles();
- const { companionId } = useSelector(getChat)
- const isOpen = useSelector(getIsOpen)
- const [value, setValue] = useState<string>('')
- const [file, setFile] = useState<any>(null)
- const [isOpenMenu, setIsOpenMenu] = useState<boolean>(false)
- const [isOpenEmoji, setIsOpenEmoji] = useState<boolean>(false)
- const [isRecording, setIsRecording] = useState<boolean>(false)
- const [type, setType] = useState<string>('')
- const { status, startRecording, stopRecording, mediaBlobUrl,clearBlobUrl } = useReactMediaRecorder({ audio: true });
- const sentMessage = async () => {
- setFile(null)
- setIsRecording(false)
- setValue('')
- setType('')
- isOpenMenu&&setIsOpenMenu(false)
- isOpenEmoji && setIsOpenEmoji(false)
- if (value) sentMessageById(companionId, value)
- if (mediaBlobUrl && type) {
- if (type === 'recording') {
- const audio = new XMLHttpRequest();
- audio.open('GET', mediaBlobUrl, true);
- audio.responseType = 'blob';
- audio.onload = () => {
- if (audio.status === 200) {
- const name = `audioMessage${new Date().getSeconds()}.mp3`
- const blob = audio.response
- const file = new File([blob], name, {
- type: 'audio/mpeg'
- })
- const formData: any = new FormData()
- formData.append("audio", file)
- sentAudioMessageById(companionId, formData)
- clearBlobUrl()
- }
- }
- audio.send();
- }
- }
- if (file && type) {
- if (file.type.includes('image') && type === 'content') {
- const formData: any = new FormData()
- formData.append("image", file);
- await sentImgMessageById(companionId, formData)
- }
- if (file.type.includes('audio') && type === 'content') {
- const formData: any = new FormData()
- formData.append("audio", file);
- sentAudioMessageById(companionId, formData)
- }
- if (file.type.includes('video') && type === 'content') {
- const formData: any = new FormData()
- formData.append("video", file);
- sentVideoMessageById(companionId, formData)
- }
- if (file.type.includes('application') && type === 'application') {
- const formData: any = new FormData()
- formData.append("file", file);
- sentFileMessageById(companionId, formData)
- }
- }
- setTimeout(handleScrollTo, 3000);
- playNotification('http://localhost:3000/send.mp3')
- }
- const handleTextarea = (e: React.ChangeEvent<HTMLTextAreaElement>) => setValue(e.target.value)
- const handleFocusTextarea = async () => await typingChat(companionId,true)
- const handleBlurTextarea = async () => await typingChat(companionId,false)
-
- const handleKeyPres = (e: any) => {
- if(e.code === 'Enter'&& value) sentMessage()
- }
- const handleOpenFileMenu = () => !isOpenMenu&&setIsOpenMenu(true)
- const handleCloseFileMenu = (e:any) => {
- if (e.target.id === 'overlay'&&isOpenMenu) setIsOpenMenu(false)
- }
- const handleOpenEmoji = () => !isOpenEmoji&&setIsOpenEmoji(true)
- const handleCloseEmoji = (e: any) => {
- if (e.target.id === 'overlay'&&isOpenEmoji) setIsOpenEmoji(false)
- }
- const handleRecording = () => {
- if (isRecording) {
- stopRecording()
- } else {
- startRecording()
- setType('recording')
- setIsRecording(true)
- }
- }
- const handleClearMessage = () => {
- file&&setFile(null)
- value&&setValue('')
- type&&setType('')
- }
-
- return (
- <div className={classes.container} style={{borderTop:isArrow?'solid 1px #ffffff':'none'}} >
- <div onKeyPress={handleKeyPres} className={classes.inputContainer}>
- <CloseIcon onClick={handleClearMessage} fontSize="small" className={classes.iconCancel}
- sx={{backgroundColor: '#ffffff', width: 36, height: 36, color: '#949393',
- display: file || value ? 'inline-block' : 'none'}} />
- <SentimentSatisfiedAltIcon onClick={handleOpenEmoji}
- fontSize='medium' sx={{
- color: isOpenEmoji ? 'rgb(41, 139, 231)' : '#6b6b6b', cursor: 'pointer',
- '&:hover': { color: 'rgb(41, 139, 231)' }
- }} />
- <div onClick={handleCloseEmoji} className={classes.overlay} id='overlay'
- style={{ display: isOpenEmoji ? 'block':'none'}}>
- <div className={classes.emoji} style={{left: isOpen&&isOpen !== 'menu'?'31%':'44%'}}>
- <NotDone name='Emoji Bar'/>
- </div>
- </div>
- <textarea disabled={file ? true : false} value={value} onBlur={handleBlurTextarea}
- onFocus={handleFocusTextarea} onChange={handleTextarea} className={classes.textarea}
- placeholder={file ? 'The File is ready to send' : status === 'idle' ? 'Message' :
- `${status === 'recording'?'Recording':'Audio message Recorded'}`} rows={1}>
- </textarea>
- <AttachFileIcon onClick={handleOpenFileMenu} className={classes.attachIcon}
- fontSize='medium' sx={{
- color: isOpenMenu ? 'rgb(41, 139, 231)' : '#6b6b6b', cursor: 'pointer',
- '&:hover': { color: 'rgb(41, 139, 231)' }
- }} />
- <div onClick={handleCloseFileMenu} className={classes.overlay} id='overlay'
- style={{ display: isOpenMenu ? 'block':'none'}}>
- <div className={classes.filesMenu} style={{left: isOpen&&isOpen !== 'menu'?'48%':'61%'}}>
- <FilesMenu setFile={setFile} setValue={setValue} setIsOpenMenu={setIsOpenMenu} setType={setType}/>
- </div>
- </div>
- <Avatar onClick={handleScrollTo} className={classes.avatarArrow}
- sx={{backgroundColor: '#ffffff', width: 56, height: 56,
- color: '#6b6b6b', display: isArrow ? 'flex' : 'none'}}>
- <ArrowDownwardIcon fontSize="medium" />
- </Avatar>
- </div>
- {value || file || mediaBlobUrl ?
- <Avatar onClick={sentMessage} className={classes.avatar} sx={{
- backgroundColor: '#ffffff', width: 56, height: 56, color: 'rgb(41, 139, 231)',
- }}>
- <SendIcon fontSize="medium" />
- </Avatar> :
- <Avatar onClick={handleRecording} className={!isRecording ? classes.avatar : undefined}
- sx={{backgroundColor: isRecording ? 'rgb(41, 139, 231)' : '#ffffff',
- color: isRecording ? '#ffffff' : '#6b6b6b', width: 56, height: 56}}
- style={{animation: isRecording ? 'ripple 1.5s infinite ease-in-out' : 'none',
- border: isRecording?'solid 5px #ffffff':'none'}}>
- <MicNoneIcon fontSize="medium" />
- </Avatar>}
- </div>
- )
- }
- export default SendMessage
|