Files
car-fetcher/frontend/src/components/camera/CameraContainer.jsx

115 lines
3.3 KiB
JavaScript

import React, {
useState, useEffect, useRef, useCallback, useContext,
} from 'react';
import Webcam from 'react-webcam';
import FacingMode from '@constant/FacingMode';
import Loader from '@components/common/Loader';
import '@style/RootContainer.scss';
import RootContext from '@context/RootContext';
import { resetResults } from '@slice/RecognitionSlice';
import CameraOptions from './CameraOptions';
import Capture from './Capture';
const CAMERA_OPTIONS = {
format: 'image/jpeg',
minHeight: 1920,
minWidth: 1080,
quality: 0.75,
defaultView: FacingMode.FRONT,
};
const CameraContainer = () => {
const { dispatch } = useContext(RootContext);
const ref = useRef(null);
const [imgSrc, setImgSrc] = useState(null);
const [captureError, setCaptureError] = useState(null);
const [videoInputs, setVideoInputs] = useState([]);
const [resetCameraView, setResetCameraView] = useState(false);
const [videoConstraints, setVideoConstraints] = useState({
facingMode: CAMERA_OPTIONS.defaultView,
});
useEffect(() => {
const gotDevices = (mediaDevices) => new Promise((resolve, reject) => {
const availableVideoInputs = mediaDevices
.filter(({ kind }) => kind === 'videoinput')
.map(({ deviceId, label }) => ({ deviceId, label }));
if (availableVideoInputs.length > 0) {
resolve(availableVideoInputs);
} else {
reject(new Error('ERR::NO_MEDIA_TO_STREAM'));
}
});
navigator.mediaDevices
.enumerateDevices()
.then(gotDevices)
.then((availableVideoInputs) => setVideoInputs({ availableVideoInputs }))
.catch((err) => console.error(err));
}, []);
const changeCameraView = () => {
if (videoInputs.length === 1) {
console.error('ERR::AVAILABLE_MEDIA_STREAMS_IS_1');
return;
}
setResetCameraView(true);
setTimeout(() => {
const { facingMode } = videoConstraints;
const newFacingMode = facingMode === FacingMode.FRONT ? FacingMode.REAR : FacingMode.FRONT;
setResetCameraView(false);
setVideoConstraints({ ...videoConstraints, facingMode: newFacingMode });
}, 100);
};
const capture = useCallback(() => {
const imageSrc = ref.current.getScreenshot();
setImgSrc(imageSrc);
if (!imageSrc) {
setCaptureError(['Failed to capture camera. Please try again.']);
} else {
setCaptureError(null);
}
}, [ref, setImgSrc]);
const onBackClick = () => {
setImgSrc(null);
dispatch(resetResults());
};
const cameraView = () => (
<>
<div className="row">
{resetCameraView ? (
<Loader />
) : (
<Webcam
mirrored={false}
width="100%"
height="100%"
audio={false}
ref={ref}
screenshotFormat={CAMERA_OPTIONS.format}
minScreenshotWidth={CAMERA_OPTIONS.minWidth}
minScreenshotHeight={CAMERA_OPTIONS.minHeight}
screenshotQuality={CAMERA_OPTIONS.quality}
videoConstraints={videoConstraints} />
)}
</div>
<CameraOptions capture={capture} changeCameraView={changeCameraView} />
</>
);
return (
<>
{imgSrc
? <Capture imgSrc={imgSrc} error={captureError} onBackClick={onBackClick} />
: cameraView()}
</>
);
};
export default CameraContainer;