Feature - Scanner for Bar and QR code (#11)
* Added: code reader component * Added: no device detected handler * Update: ID hooking to video element * Update: Defer stream start * Linted * Added: grant permissions * Added: media device scan * Removed loggers and cleanup Co-authored-by: Llewellyn D'souza <lledsouza2209@gmail.com>
This commit is contained in:
97
src/components/CodeScanner/index.js
Normal file
97
src/components/CodeScanner/index.js
Normal file
@@ -0,0 +1,97 @@
|
||||
import React, { useState, useEffect, useMemo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import LOGGER from 'services/Logger';
|
||||
|
||||
import { BrowserMultiFormatReader, NotFoundException } from '@zxing/library';
|
||||
|
||||
export default function CodeScanner({ onDetect, width, height }) {
|
||||
// const [decoded, setDecoded] = useState(null);
|
||||
const [selectedDeviceId, setSelectedDeviceId] = useState(null);
|
||||
const [videoInputDevices, setVideoInputDevices] = useState(null);
|
||||
const getMediaDevices = (reader) => {
|
||||
reader
|
||||
.listVideoInputDevices()
|
||||
.then((videoIPDevices) => {
|
||||
setVideoInputDevices(videoIPDevices);
|
||||
if (videoIPDevices && videoIPDevices.length > 0) {
|
||||
setSelectedDeviceId(videoIPDevices[0].deviceId);
|
||||
}
|
||||
})
|
||||
.catch(LOGGER.log);
|
||||
};
|
||||
|
||||
const codeReader = useMemo(() => {
|
||||
// LOGGER.log('Initializing code reader');
|
||||
const reader = new BrowserMultiFormatReader();
|
||||
getMediaDevices(reader);
|
||||
return reader;
|
||||
}, []);
|
||||
|
||||
// LOGGER.log('hasNavigator', codeReader.hasNavigator);
|
||||
// LOGGER.log('isMediaDeviceSupported', codeReader.isMediaDevicesSuported);
|
||||
|
||||
useEffect(() => {
|
||||
!selectedDeviceId && getMediaDevices(codeReader);
|
||||
|
||||
async function startStream() {
|
||||
// LOGGER.log('Starting stream');
|
||||
if (videoInputDevices) {
|
||||
codeReader
|
||||
.decodeFromVideoDevice(selectedDeviceId, '#scan-view', (result, err) => {
|
||||
if (result) {
|
||||
LOGGER.log(result);
|
||||
onDetect(result.text);
|
||||
// setDecoded(result.text);
|
||||
}
|
||||
if (err && !(err instanceof NotFoundException)) {
|
||||
LOGGER.error(err);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
getMediaDevices(codeReader);
|
||||
});
|
||||
}
|
||||
}
|
||||
startStream();
|
||||
return () => {
|
||||
// LOGGER.log('resetting code reader');
|
||||
codeReader.reset();
|
||||
};
|
||||
}, [selectedDeviceId]);
|
||||
|
||||
// Use when debugging
|
||||
// return videoInputDevices && selectedDeviceId ? (
|
||||
// <div>
|
||||
// <video id="#scan-view" width={width.toString()} height={height.toString()} />
|
||||
// <p>Value: {decoded}</p>
|
||||
// <br />
|
||||
// <br />
|
||||
// <pre style={{ fontSize: 12 }}>
|
||||
// Debug data: <br /> {JSON.stringify(videoInputDevices, null, 4)}
|
||||
// </pre>
|
||||
// </div>
|
||||
// ) : (
|
||||
// <p>Not supported</p>
|
||||
// );
|
||||
|
||||
return codeReader.hasNavigator && codeReader.isMediaDevicesSuported ? (
|
||||
videoInputDevices && selectedDeviceId ? (
|
||||
<video id="#scan-view" width={width.toString()} height={height.toString()} />
|
||||
) : (
|
||||
<p>Please grant camera permissions</p>
|
||||
)
|
||||
) : (
|
||||
<p>Not supported</p>
|
||||
);
|
||||
}
|
||||
|
||||
CodeScanner.defaultProps = {
|
||||
width: 300,
|
||||
height: 200
|
||||
};
|
||||
|
||||
CodeScanner.propTypes = {
|
||||
onDetect: PropTypes.func.isRequired,
|
||||
width: PropTypes.number,
|
||||
height: PropTypes.number
|
||||
};
|
||||
Reference in New Issue
Block a user