115 lines
3.3 KiB
JavaScript
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;
|