You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
5.4 KiB
186 lines
5.4 KiB
import React, { Component } from 'react'
|
|
import PropTypes from 'prop-types'
|
|
import {connect} from 'react-redux'
|
|
import { BrowserQRCodeReader } from '@zxing/library'
|
|
import adapter from 'webrtc-adapter' // eslint-disable-line import/no-nodejs-modules, no-unused-vars
|
|
import { hideQrScanner, qrCodeDetected} from '../../actions'
|
|
import Spinner from '../spinner'
|
|
|
|
class QrScanner extends Component {
|
|
static propTypes = {
|
|
visible: PropTypes.bool,
|
|
hideQrScanner: PropTypes.func,
|
|
qrCodeDetected: PropTypes.func,
|
|
}
|
|
constructor (props) {
|
|
super(props)
|
|
this.state = {
|
|
ready: false,
|
|
msg: 'Accesing your camera...',
|
|
}
|
|
this.scanning = false
|
|
this.codeReader = null
|
|
}
|
|
|
|
componentDidUpdate () {
|
|
if (this.props.visible && this.camera && !this.scanning) {
|
|
this.scanning = true
|
|
this.initCamera()
|
|
}
|
|
}
|
|
|
|
initCamera () {
|
|
console.log('QR-SCANNER: initCamera ')
|
|
this.codeReader = new BrowserQRCodeReader()
|
|
this.codeReader.getVideoInputDevices()
|
|
.then(videoInputDevices => {
|
|
console.log('QR-SCANNER: getVideoInputDevices ', videoInputDevices)
|
|
setTimeout(_ => {
|
|
this.setState({
|
|
ready: true,
|
|
msg: 'Place the QR code in front of your camera so we can read it...'})
|
|
console.log('QR-SCANNER: this.state.ready = true')
|
|
}, 2000)
|
|
|
|
console.log('QR-SCANNER: started scanning...')
|
|
this.codeReader.decodeFromInputVideoDevice(videoInputDevices[0].deviceId, 'video')
|
|
.then(content => {
|
|
console.log('QR-SCANNER: content found!', content)
|
|
this.codeReader.reset()
|
|
console.log('QR-SCANNER: stopped scanning...')
|
|
const result = this.parseContent(content.text)
|
|
if (result.type !== 'unknown') {
|
|
console.log('QR-SCANNER: CODE DETECTED', result)
|
|
this.props.qrCodeDetected(result)
|
|
this.props.hideQrScanner()
|
|
this.setState({ ready: false })
|
|
} else {
|
|
this.setState({msg: 'Error: We couldn\'t identify that QR code'})
|
|
console.log('QR-SCANNER: Unknown code')
|
|
}
|
|
})
|
|
.catch(err => {
|
|
console.log('QR-SCANNER: decodeFromInputVideoDevice threw an exception: ', err)
|
|
})
|
|
}).catch(err => {
|
|
console.log('QR-SCANNER: getVideoInputDevices threw an exception: ', err)
|
|
})
|
|
}
|
|
|
|
parseContent (content) {
|
|
let type = 'unknown'
|
|
let values = {}
|
|
|
|
// Here we could add more cases
|
|
// To parse other codes (transactions for ex.)
|
|
|
|
if (content.split('ethereum:').length > 1) {
|
|
type = 'address'
|
|
values = {'address': content.split('ethereum:')[1] }
|
|
}
|
|
return {type, values}
|
|
}
|
|
|
|
|
|
stopAndClose = () => {
|
|
console.log('QR-SCANNER: stopping scanner...')
|
|
this.codeReader.reset()
|
|
this.scanning = false
|
|
this.props.hideQrScanner()
|
|
this.setState({ ready: false })
|
|
}
|
|
|
|
render () {
|
|
const { visible } = this.props
|
|
|
|
if (!visible) {
|
|
return null
|
|
}
|
|
|
|
return (
|
|
<div className={'qr-code-modal-wrapper'}>
|
|
<div className={'qr-scanner'}
|
|
style={{
|
|
position: 'fixed',
|
|
top: '50%',
|
|
left: '50%',
|
|
zIndex: 1050,
|
|
minWidth: '320px',
|
|
minHeight: '400px',
|
|
maxWidth: '300px',
|
|
maxHeight: '300px',
|
|
transform: 'translate(-50%, -50%)',
|
|
backgroundColor: '#ffffff',
|
|
padding: '15px',
|
|
}}
|
|
>
|
|
<h3 style={{
|
|
textAlign: 'center',
|
|
marginBottom: '20px',
|
|
fontSize: '1.5rem',
|
|
fontWeight: '500',
|
|
}}>
|
|
Scan QR code
|
|
</h3>
|
|
<div
|
|
className={'qr-code-video-wrapper'}
|
|
style={{
|
|
overflow: 'hidden',
|
|
width: '100%',
|
|
height: '275px',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
}}>
|
|
<video
|
|
id="video"
|
|
style={{
|
|
width: 'auto',
|
|
height: '275px',
|
|
marginLeft: '-15%',
|
|
display: this.state.ready ? 'block' : 'none',
|
|
transform: 'scaleX(-1)',
|
|
}}
|
|
ref={(cam) => {
|
|
this.camera = cam
|
|
}}
|
|
/>
|
|
{ !this.state.ready ? <Spinner color={'#F7C06C'} /> : null}
|
|
</div>
|
|
<div className={'qr-code-help'} style={{textAlign: 'center', fontSize: '12px', padding: '15px'}}>
|
|
{this.state.msg}
|
|
</div>
|
|
</div>
|
|
<div
|
|
className={'qr-code-modal-overlay'}
|
|
style={{
|
|
position: 'fixed',
|
|
top: '0',
|
|
right: '0',
|
|
bottom: '0',
|
|
left: '0',
|
|
zIndex: '1040',
|
|
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
animationFillMode: 'forwards',
|
|
animationDuration: '0.3s',
|
|
animationName: 'anim_171532470906313',
|
|
animationTimingFunction: 'ease-out',
|
|
}}
|
|
onClick={this.stopAndClose}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|
|
}
|
|
|
|
function mapDispatchToProps (dispatch) {
|
|
return {
|
|
hideQrScanner: () => dispatch(hideQrScanner()),
|
|
qrCodeDetected: (data) => dispatch(qrCodeDetected(data)),
|
|
}
|
|
}
|
|
function mapStateToProps (state) {
|
|
return {}
|
|
}
|
|
|
|
export default connect(mapStateToProps, mapDispatchToProps)(QrScanner)
|
|
|