Browse Source

finished selfie

unknown 1 year ago
parent
commit
fec6881f03

File diff suppressed because it is too large
+ 1 - 1
.eslintcache


+ 25 - 25
src/components/AuthPage/Registration/UploadAvatar/index.tsx

@@ -1,5 +1,6 @@
 import { makeStyles, Typography,InputLabel,ListItem,ListItemText ,ListItemIcon } from '@material-ui/core'
 import FolderIcon from '@mui/icons-material/Folder';
+import AddAPhotoIcon from '@mui/icons-material/AddAPhoto';
 import { useDropzone } from 'react-dropzone';
 import { useEffect } from 'react';
 
@@ -20,15 +21,30 @@ const useStyles = makeStyles({
     marginBottom: 20,
     outline: '2px solid  #959696',
     '&:hover': {
-      outline: 'dashed  #0040b8',
+      outline: 'dashed  rgb(41, 139, 231)',
     },
   },
+  dropZoneActive: {
+    display: 'flex',
+    flexDirection: 'column',
+    alignItems: 'center',
+    alignContent: 'center',
+    justifyContent: 'center',
+    width: '100%',
+    padding: '10px',
+    borderRadius: 10,
+    cursor: 'pointer',
+    marginBottom: 20,
+    outline: '2px dashed  rgb(41, 139, 231)',
+  },  
 })
 
 interface IUploadAvatar {
-  setUpload: React.Dispatch<React.SetStateAction<any>>
+  setUpload: React.Dispatch<React.SetStateAction<any>>,
+  upload: any,
+  setSelfie: React.Dispatch<React.SetStateAction<any>>,
 }
-const  UploadAvatar = ({ setUpload }: IUploadAvatar) => {
+const  UploadAvatar = ({ setUpload,upload,setSelfie }: IUploadAvatar) => {
   
 const {
     acceptedFiles,
@@ -40,36 +56,20 @@ const {
 
     useEffect(() => {
       setUpload(acceptedFiles[0])
-  }, [setUpload,acceptedFiles])
+      setSelfie(null)
+  }, [setUpload,setSelfie,acceptedFiles])
 
   const classes = useStyles()
-  const acceptedFileItems = acceptedFiles.map((file: any) => (
-    <ListItem key={file.path}>
-      <ListItemIcon>
-        <FolderIcon/>
-      </ListItemIcon>
-      <ListItemText
-        primary="Avatar uploaded"
-        secondary={`${file.path} -${file.size} bytes`}/>
-   </ListItem>
-  ));
 
   return (
     <section className={classes.container} >
-      <div {...getRootProps({ className: classes.dropZone })}>
-        <InputLabel>Drag or drop avatar*</InputLabel>
+      <div {...getRootProps({ className: upload? classes.dropZoneActive:classes.dropZone})}>
+        <InputLabel>Drag or drop avatar</InputLabel>
         <input {...getInputProps()}/>
-        <img
-          alt='drop zone img'
-          src='https://imagga.com/static/images/upload.svg'
-          width={88}
-          height={72}
-        />
+        <AddAPhotoIcon fontSize='large'
+          sx={{color: upload ? 'rgb(62, 149, 231)' : '#6b6b6b',margin:'15px 0px'}} />
         <Typography variant="h6" color="initial">image/*</Typography>
       </div>
-      <aside>
-        <ul>{acceptedFileItems}</ul>
-      </aside>
     </section>
   );
 }

+ 120 - 8
src/components/AuthPage/Registration/index.tsx

@@ -1,10 +1,14 @@
-import { makeStyles, Button, TextField, Typography } from '@material-ui/core'
+import { makeStyles, Button, TextField, Typography,ListItem,ListItemIcon,ListItemText } from '@material-ui/core'
 import { useState } from 'react';
 import { useDispatch } from 'react-redux';
 
+import PhotoCameraFrontIcon from '@mui/icons-material/PhotoCameraFront';
 import UploadAvatar from './UploadAvatar'
+import FolderIcon from '@mui/icons-material/Folder';
+import Webcam from "react-webcam";
+import CameraIcon from '@mui/icons-material/Camera';
 import { asyncCreateUser } from '../../../redux/authorization/operations'
-import { format } from '../../../helpers'
+import { format,playNotification,prodBaseURL } from '../../../helpers'
 
 const useStyles = makeStyles({
   container: {
@@ -21,6 +25,13 @@ const useStyles = makeStyles({
     marginBottom: 20,
     textAlign: 'center'
   },
+  selfieWrapper: {
+    marginBottom: 20,
+    display: 'flex',
+    justifyContent: 'center',
+    alignItems: 'center',
+    alignContent: 'center',
+  },
   buttonNext: {
     marginTop: 20,
     height: 50,
@@ -29,7 +40,38 @@ const useStyles = makeStyles({
   },
   textField: {
     marginBottom:20
-  }
+  },
+  overlay: {
+    position: 'fixed',
+    top: 0,
+    left: 0,
+    width: '100vw',
+    height: '100vh',
+    zIndex: 100,
+    backgroundColor: 'rgba(104, 105, 104, 0.6)',
+    overflowY: 'hidden',
+    display: 'flex',
+    justifyContent: 'center',
+    alignContent: 'center',
+    alignItems: 'center',
+    flexDirection:'column'
+  },
+  capturedPicture: {
+    borderRadius: 10,
+    border:'solid 2px rgb(62, 149, 231)'
+  },  
+  capturePhoto: {
+    color: '#ffffff',
+    cursor: 'pointer',
+    '&:hover': {
+      color: '#48ff00',
+      animation: `$rotating 2s linear infinite`
+    },
+  },  
+  '@keyframes rotating': {
+	  'from': { transform: 'rotate(0deg)'},
+	  'to': { transform: 'rotate(360deg)'},
+   },  
 })
 
 const Registration = () => {
@@ -37,7 +79,14 @@ const Registration = () => {
   const [name, setName] = useState<string>('')
   const [lastName, setLastName] = useState<string>('')
   const [upload, setUpload] = useState<any>(null)
+  const [selfie, setSelfie] = useState<any>(null)
+  const [camera, setCamera] = useState<boolean>(false)
   const dispatch = useDispatch()
+  const videoConstraints = {
+    width: 1280,
+    height: 720,
+    facingMode: "user"
+  };
 
   const isValidCredentials = () => {
     const validName = name.length
@@ -62,19 +111,82 @@ const Registration = () => {
     }
   }
 
-  const handleUpdateUser = async () => dispatch(asyncCreateUser(name, lastName, upload))
+  const handleOpenCamera = () => {
+    setCamera(true)
+    upload&&setUpload(null)
+  }
+
+  const handleCloseCamera = (e: any) => {
+    const id = e.target.id
+    if (id === 'overlay') setCamera(false)
+  }  
+
+  const handleUpdateUser = async () => {
+    if (upload) {
+      dispatch(asyncCreateUser(name, lastName, upload))
+    }
+    if (selfie) {
+      fetch(selfie)
+       .then(res => res.blob())
+        .then(blob => {
+          const imgFile = new File([blob], "selfie", { type: "image/jpeg" })
+          dispatch(asyncCreateUser(name, lastName, imgFile))
+      })
+    }
+  }
 
   return (
     <div className={classes.container} >
+      <div className={classes.selfieWrapper}>
+        <Typography variant="h6" color="initial"
+          style={{ textAlign: "center", marginRight: 10 }}>
+          Capture avatar
+        </Typography>
+        <PhotoCameraFrontIcon onClick={handleOpenCamera} fontSize='large'
+          sx={{color: selfie ? 'rgb(62, 149, 231)' :
+          '#6b6b6b',
+          '&:hover': { color: 'rgb(41, 139, 231)' },cursor:'pointer'}}/>
+      </div>      
+      <UploadAvatar setUpload={setUpload} upload={upload} setSelfie={setSelfie} />
+      <aside>
+        <ul>
+          {upload || selfie?
+            <ListItem>
+              <ListItemIcon>
+                <FolderIcon/>
+              </ListItemIcon>
+              <ListItemText primary="Avatar uploaded"
+              secondary={`${upload?upload.path:'selfie.jpeg'} -${upload?upload.size:(selfie.length*(3/4))-2} bytes`} />
+          </ListItem>:null}
+        </ul>
+      </aside>      
+     {camera &&
+      <div onClick={handleCloseCamera} id='overlay'
+        className={classes.overlay}>
+        <Webcam
+        audio={false}
+        screenshotFormat="image/jpeg"
+        width='40%'
+        videoConstraints={videoConstraints}
+        style={{marginBottom:30}}
+      >
+          {({ getScreenshot }) => <>
+            <CameraIcon onClick={() => {
+              setSelfie(getScreenshot())
+              playNotification(`${prodBaseURL}/cameraCapture.mp3`)
+            }}
+              className={classes.capturePhoto} fontSize='large' style={{marginBottom:30}} />
+            <img className={classes.capturedPicture} width='300' height='174'
+              style={{visibility:selfie?'visible':'hidden'}} src={selfie} alt='chosen pic'></img>
+          </>}
+        </Webcam>
+      </div>}      
       <Typography
         className={classes.title}
         variant="h5"
         color="initial">
-        Please upload avatar and fill credentials*
+        Fill credentials*
       </Typography>      
-      <UploadAvatar
-        setUpload={setUpload}
-      />
       <TextField
         id="name"
         name='name'

+ 6 - 3
src/components/HomePage/CentralBar/ChatBar/FilesMenu/UploadFile/index.tsx

@@ -21,10 +21,12 @@ interface IUploadFile {
   children:React.ReactNode,
   setFile: any,
   setValue: any,
-  accept: string
+  accept: string,
+  type: string,
+  setType:any
 }
   
-const UploadFile = ({children,setFile,setValue,accept}:IUploadFile) => {
+const UploadFile = ({children,setFile,setValue,accept,type,setType}:IUploadFile) => {
   const classes = useStyles()
     const { getRootProps, getInputProps, acceptedFiles } = useDropzone({
         noDrag: true,
@@ -34,8 +36,9 @@ const UploadFile = ({children,setFile,setValue,accept}:IUploadFile) => {
         if (acceptedFiles.slice(-1)[0]) {
           setValue('')
           setFile(acceptedFiles.slice(-1)[0])
+          setType(type)
         }
-      }, [setFile,setValue, acceptedFiles])
+      }, [setFile,setValue,setType,type,acceptedFiles])
   
     return (
     <div className={classes.container} >

+ 5 - 9
src/components/HomePage/CentralBar/ChatBar/FilesMenu/index.tsx

@@ -28,23 +28,19 @@ interface IFilesMenu {
 }
 const FilesMenu = ({setIsOpenMenu,setFile,setValue,setType}:IFilesMenu) => {
   const classes = useStyles()
-  const handleClose = (type:string) => {
-    setType(type)
-    setIsOpenMenu(false)
-  }
-  
+  const handleClose = () => setIsOpenMenu(false)
   return (
     <MenuList className={classes.list}>
-      <MenuItem  onClick={() => handleClose('content')}>
-        <UploadFile setFile={setFile} setValue={setValue} accept='image/*,video/*,audio/*'>
+      <MenuItem onClick={handleClose}>
+        <UploadFile setFile={setFile} setValue={setValue} type='content' setType={setType} accept='image/*,video/*,audio/*'>
           <ListItemIcon className={classes.listIcon}>
             <InsertDriveFileIcon fontSize="medium" />
           </ListItemIcon>
           <ListItemText className={classes.listText}>Upload Image/Audio/Video</ListItemText>
         </UploadFile>
       </MenuItem>
-      <MenuItem  onClick={() => handleClose('application')}>
-        <UploadFile setFile={setFile} setValue={setValue} accept='application/pdf,
+      <MenuItem onClick={handleClose}>
+        <UploadFile setFile={setFile} setValue={setValue} type='application' setType={setType} accept='application/pdf,
         application/vnd.openxmlformats-officedocument.wordprocessingml.document'>
           <ListItemIcon className={classes.listIcon}>
             <InsertDriveFileIcon fontSize="medium" />

+ 100 - 23
src/components/HomePage/CentralBar/ChatBar/SendMessage/index.tsx

@@ -6,8 +6,11 @@ import PauseIcon from '@mui/icons-material/Pause';
 import AttachFileIcon from '@mui/icons-material/AttachFile';
 import SentimentSatisfiedAltIcon from '@mui/icons-material/SentimentSatisfiedAlt';
 import CloseIcon from '@mui/icons-material/Close';
+import PhotoCameraFrontIcon from '@mui/icons-material/PhotoCameraFront';
 import CommentIcon from '@mui/icons-material/Comment';
 import Avatar from '@mui/material/Avatar';
+import Webcam from "react-webcam";
+import CameraIcon from '@mui/icons-material/Camera';
 import TextField from '@mui/material/TextField';
 import Picker from 'emoji-picker-react';
 
@@ -230,7 +233,38 @@ const useStyles = makeStyles({
   '80%': { transform: 'translate(-0.5px, -0.5px) rotate(1deg)'},
   '90%': { transform: 'translate(0.5px, 1px) rotate(0deg)'},
   '100%': { transform: 'translate(0.5px, -1px) rotate(-1deg)'},
- },    
+  },
+  overlayCamera: {
+    position: 'fixed',
+    top: 0,
+    left: 0,
+    width: '100vw',
+    height: '100vh',
+    zIndex: 100,
+    backgroundColor: 'rgba(104, 105, 104, 0.6)',
+    overflowY: 'hidden',
+    display: 'flex',
+    justifyContent: 'center',
+    alignContent: 'center',
+    alignItems: 'center',
+    flexDirection:'column'
+  },
+  capturedPicture: {
+    borderRadius: 10,
+    border:'solid 2px rgb(62, 149, 231)'
+  },  
+  capturePhoto: {
+    color: '#ffffff',
+    cursor: 'pointer',
+    '&:hover': {
+      color: '#48ff00',
+      animation: `$rotating 2s linear infinite`
+    },
+  },  
+  '@keyframes rotating': {
+	  'from': { transform: 'rotate(0deg)'},
+	  'to': { transform: 'rotate(360deg)'},
+   },  
 });
 
 interface ISendMessage{
@@ -248,28 +282,33 @@ const SendMessage = ({isArrow }:ISendMessage) => {
     const [isOpenMenu, setIsOpenMenu] = useState<boolean>(false)
     const [isOpenEmoji, setIsOpenEmoji] = useState<boolean>(false)
     const [isRecording, setIsRecording] = useState<boolean>(false)
-    const [isFilming, setIsFilming] = useState<boolean>(false)    
+    const [isFilming, setIsFilming] = useState<boolean>(false)
+    const [isOpenCamera, setIsOpenCamera] = useState<boolean>(false)
     const [type, setType] = useState<string>('')
     const { status, startRecording, stopRecording, mediaBlobUrl, clearBlobUrl } = useReactMediaRecorder({ audio: true,blobPropertyBag:{type: "audio/mp3"}});
     const { status: _status, startRecording: _startRecording, stopRecording: _stopRecording,
-        mediaBlobUrl: _mediaBlobUrl, clearBlobUrl: _clearBlobUrl } = useReactMediaRecorder({ video: true,blobPropertyBag:{type: "video/mp4"}});
+      mediaBlobUrl: _mediaBlobUrl, clearBlobUrl: _clearBlobUrl } = useReactMediaRecorder({ video: true, blobPropertyBag: { type: "video/mp4" } });
+    const videoConstraints = {
+    width: 1280,
+    height: 720,
+    facingMode: "user"
+  };
     const onEmojiClick = (_e:any, emojiObject:any) => {
         setValue(prevValue => prevValue + emojiObject.emoji)
         setIsOpenEmoji(false)
     };    
     const clearMessage = () => {
-        file &&setFile(false)
-        isRecording && setIsRecording(false)
-        isFilming && setIsFilming(false)
-        value && setValue('')
-        caption&& setCaption('')
-        type && setType('')
-        mediaBlobUrl && clearBlobUrl()
-        _mediaBlobUrl && _clearBlobUrl()
-        isOpenMenu && setIsOpenMenu(false)
-        isOpenEmoji && setIsOpenEmoji(false)
-        isOpenCaption && setIsOpenCaption(false)
-    
+      file && setFile(false)
+      isRecording && setIsRecording(false)
+      isFilming && setIsFilming(false)
+      value && setValue('')
+      caption&& setCaption('')
+      type && setType('')
+      mediaBlobUrl && clearBlobUrl()
+      _mediaBlobUrl && _clearBlobUrl()
+      isOpenMenu && setIsOpenMenu(false)
+      isOpenEmoji && setIsOpenEmoji(false)
+      isOpenCaption && setIsOpenCaption(false)
     }
     const sentMessage = async () => {
         if (value) sentMessageById(companionId, value,caption.trim())
@@ -309,11 +348,11 @@ const SendMessage = ({isArrow }:ISendMessage) => {
             }
             video.send();
         }        
-        if (file && type) {
+      if (file && type && type !== 'base64') {         
             if (file.type.includes('image') && type === 'content') {
               const formData: any = new FormData()
               formData.append("image", file);
-              await sentImgMessageById(companionId, formData, caption.trim())
+              sentImgMessageById(companionId, formData, caption.trim())
             }
             if (file.type.includes('audio') && type === 'content') {
               const formData: any = new FormData()
@@ -329,8 +368,16 @@ const SendMessage = ({isArrow }:ISendMessage) => {
               const formData: any = new FormData()
               formData.append("file", file);
               sentFileMessageById(companionId, formData,caption.trim())   
-            }
-        }
+            }        
+      }
+      if (typeof file === 'string' && type === 'base64') {
+        fetch(file).then(res => res.blob()).then(blob => {
+          const imgFile = new File([blob], "selfie", { type: "image/jpeg" })
+          const formData: any = new FormData()
+          formData.append("image", imgFile);
+          sentImgMessageById(companionId, formData, caption.trim())
+        })
+      }         
         clearMessage()
         playNotification(`${prodBaseURL}/send.mp3`)
     }    
@@ -358,7 +405,15 @@ const SendMessage = ({isArrow }:ISendMessage) => {
         _startRecording()
         setType('filming')
         setIsFilming(true) 
-    }
+  }
+  const handleOpenCamera = () => setIsOpenCamera(true)
+
+  
+
+  const handleCloseCamera = (e: any) => {
+    const id = e.target.id
+    if (id === 'overlay') setIsOpenCamera(false)
+  }  
 
     return (
         <div className={value || file || status === 'stopped' || _status === 'stopped' ?classes.containerActive:classes.container}>
@@ -428,15 +483,37 @@ const SendMessage = ({isArrow }:ISendMessage) => {
                     `${status === 'stopped' || _status === 'stopped' ? 'Recorded' : 'Recording in progress...'}`} rows={1}
                     style={{color:value || file || status !== 'idle' || _status !== 'idle' ?'rgb(41, 139, 231)':'#6b6b6b'}}>
                 </textarea>
+                <PhotoCameraFrontIcon onClick={handleOpenCamera} fontSize='medium'
+                 sx={{color: isOpenCamera || type === 'base64' ? 'rgb(62, 149, 231)' : '#6b6b6b', marginRight: 1, cursor: 'pointer',
+                   pointerEvents: type === 'content' || type === 'application' || value || status !== 'idle'
+                   || _status !== 'idle' ? 'none' : "auto",
+                  '&:hover': { color: 'rgb(41, 139, 231)'}}}/>
                 <AttachFileIcon onClick={handleOpenFileMenu} className={classes.attachIcon}
-                  fontSize='medium' sx={{color: isOpenMenu ? 'rgb(41, 139, 231)' : '#6b6b6b', cursor: 'pointer',
-                  pointerEvents: value || status !== 'idle' || _status !== 'idle' ? 'none' : "auto",'&:hover': { color: 'rgb(41, 139, 231)'}}} />
+                  fontSize='medium' sx={{color: isOpenMenu || type === 'content' || type === 'application' ? 'rgb(41, 139, 231)' : '#6b6b6b', cursor: 'pointer',
+                    pointerEvents: type === 'base64' || value || status !== 'idle' || _status !== 'idle' ? 'none' : "auto", '&: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: rightIsOpen?'52.5vw':'65vw'}}>
                       <FilesMenu setFile={setFile} setValue={setValue} setIsOpenMenu={setIsOpenMenu} setType={setType}/>
                     </div>
-                </div>         
+                </div>
+                   {isOpenCamera &&
+                    <div onClick={handleCloseCamera} id='overlay' className={classes.overlayCamera}>
+                      <Webcam audio={false} screenshotFormat="image/jpeg" width='40%'
+                      videoConstraints={videoConstraints} style={{marginBottom:30}}>
+                     {({ getScreenshot }) => <>
+                       <CameraIcon onClick={() => {
+                         setFile(getScreenshot())
+                         setType('base64')
+                         playNotification(`${prodBaseURL}/cameraCapture.mp3`)
+                       }}
+                         className={classes.capturePhoto} fontSize='large' style={{marginBottom:30}} />
+                       <img className={classes.capturedPicture} width='300' height='174'
+                         style={{visibility:file?'visible':'hidden'}} src={file} alt='chosen pic'></img>
+                     </>}
+                   </Webcam>
+                 </div>}
         </div>            
     )
 }

+ 2 - 1
src/components/HomePage/LeftBar/EditBar/EditList/index.tsx

@@ -7,7 +7,7 @@ import CameraIcon from '@mui/icons-material/Camera';
 import { useEffect } from 'react';
 import { useDropzone } from 'react-dropzone';
 import Webcam from "react-webcam";
-import { format,firstLetter,prodAwsS3 } from '../../../../../helpers'
+import { format,firstLetter,prodAwsS3,prodBaseURL,playNotification } from '../../../../../helpers'
 import { IAuthorizationState } from '../../../../../typescript/redux/authorization/interfaces'
 
 const useStyles = makeStyles({
@@ -164,6 +164,7 @@ const EditList = (props: IEditList) => {
             <CameraIcon onClick={() => {
               setSelfie(getScreenshot())
               setOpenBtn(true)
+              playNotification(`${prodBaseURL}/cameraCapture.mp3`)
             }}
               className={classes.capturePhoto} fontSize='large' style={{marginBottom:30}} />
             <img className={classes.capturedPicture} width='300' height='174'