1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-24 19:10:22 +01:00
metamask-extension/ui/app/components/modals/qr-scanner/qr-scanner.component.js

217 lines
5.7 KiB
JavaScript
Raw Normal View History

2018-07-30 23:50:05 +02:00
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { BrowserQRCodeReader } from '@zxing/library'
import adapter from 'webrtc-adapter' // eslint-disable-line import/no-nodejs-modules, no-unused-vars
import Spinner from '../../spinner'
import WebcamUtils from '../../../../lib/webcam-utils'
2018-08-08 09:21:37 +02:00
import PageContainerFooter from '../../page-container/page-container-footer/page-container-footer.component'
2018-07-30 23:50:05 +02:00
export default class QrScanner extends Component {
static propTypes = {
hideModal: PropTypes.func.isRequired,
qrCodeDetected: PropTypes.func,
2018-08-04 00:57:23 +02:00
scanQrCode: PropTypes.func,
error: PropTypes.bool,
errorType: PropTypes.string,
2018-07-30 23:50:05 +02:00
}
static contextTypes = {
t: PropTypes.func,
}
constructor (props, context) {
super(props)
2018-07-30 23:50:05 +02:00
this.state = {
ready: false,
2018-08-04 00:57:23 +02:00
msg: context.t('accessingYourCamera'),
2018-07-30 23:50:05 +02:00
}
this.codeReader = null
this.permissionChecker = null
2018-08-01 00:58:54 +02:00
this.needsToReinit = false
2018-08-04 01:36:01 +02:00
// Clear pre-existing qr code data before scanning
this.props.qrCodeDetected(null)
2018-07-30 23:50:05 +02:00
}
componentDidMount () {
this.initCamera()
}
async checkPermisisions () {
const { permissions } = await WebcamUtils.checkStatus()
if (permissions) {
clearTimeout(this.permissionChecker)
// Let the video stream load first...
setTimeout(_ => {
this.setState({
ready: true,
msg: this.context.t('scanInstructions'),
})
2018-08-01 00:58:54 +02:00
if (this.needsToReinit) {
this.initCamera()
this.needsToReinit = false
}
}, 2000)
} else {
// Keep checking for permissions
this.permissionChecker = setTimeout(_ => {
this.checkPermisisions()
}, 1000)
2018-07-30 23:50:05 +02:00
}
}
2018-07-31 00:40:00 +02:00
componentWillUnmount () {
clearTimeout(this.permissionChecker)
if (this.codeReader) {
this.codeReader.reset()
}
2018-07-31 00:40:00 +02:00
}
2018-07-30 23:50:05 +02:00
initCamera () {
this.codeReader = new BrowserQRCodeReader()
this.codeReader.getVideoInputDevices()
.then(videoInputDevices => {
clearTimeout(this.permissionChecker)
this.checkPermisisions()
this.codeReader.decodeFromInputVideoDevice(undefined, 'video')
2018-07-30 23:50:05 +02:00
.then(content => {
const result = this.parseContent(content.text)
if (result.type !== 'unknown') {
this.props.qrCodeDetected(result)
this.stopAndClose()
} else {
this.setState({msg: this.context.t('unknownQrCode')})
}
})
.catch(err => {
if (err && err.name === 'NotAllowedError') {
this.setState({msg: this.context.t('youNeedToAllowCameraAccess')})
clearTimeout(this.permissionChecker)
2018-08-01 00:58:54 +02:00
this.needsToReinit = true
this.checkPermisisions()
}
2018-07-30 23:50:05 +02:00
})
}).catch(err => {
console.error('[QR-SCANNER]: getVideoInputDevices threw an exception: ', err)
2018-07-30 23:50:05 +02:00
})
}
parseContent (content) {
let type = 'unknown'
let values = {}
// Here we could add more cases
// To parse other type of links
// For ex. EIP-681 (https://eips.ethereum.org/EIPS/eip-681)
2018-07-30 23:50:05 +02:00
2018-08-08 09:00:39 +02:00
// Ethereum address links - fox ex. ethereum:0x.....1111
2018-07-30 23:50:05 +02:00
if (content.split('ethereum:').length > 1) {
2018-08-08 09:00:39 +02:00
2018-07-30 23:50:05 +02:00
type = 'address'
values = {'address': content.split('ethereum:')[1] }
2018-08-08 09:00:39 +02:00
// Regular ethereum addresses - fox ex. 0x.....1111
} else if (content.substring(0, 2).toLowerCase() === '0x') {
type = 'address'
values = {'address': content }
2018-07-30 23:50:05 +02:00
}
return {type, values}
}
stopAndClose = () => {
2018-08-04 00:57:23 +02:00
if (this.codeReader) {
this.codeReader.reset()
}
2018-07-30 23:50:05 +02:00
this.setState({ ready: false })
this.props.hideModal()
}
2018-08-04 00:57:23 +02:00
tryAgain = () => {
// close the modal
this.stopAndClose()
// wait for the animation and try again
setTimeout(_ => {
this.props.scanQrCode()
}, 1000)
}
renderVideo () {
return (
<div className={'qr-scanner__content__video-wrapper'}>
<video
id="video"
style={{
display: this.state.ready ? 'block' : 'none',
}}
/>
{ !this.state.ready ? <Spinner color={'#F7C06C'} /> : null}
</div>
)
}
2018-08-04 00:57:23 +02:00
renderErrorModal () {
let title, msg
if (this.props.error) {
if (this.props.errorType === 'NO_WEBCAM_FOUND') {
title = this.context.t('noWebcamFoundTitle')
msg = this.context.t('noWebcamFound')
} else {
title = this.context.t('unknownCameraErrorTitle')
msg = this.context.t('unknownCameraError')
}
}
return (
<div className="qr-scanner">
<div className="qr-scanner__close" onClick={this.stopAndClose}></div>
<div className="qr-scanner__image">
<img src={'images/webcam.svg'} width={70} height={70} />
</div>
<div className="qr-scanner__title">
{ title }
</div>
<div className={'qr-scanner__error'}>
{msg}
</div>
2018-08-08 09:00:39 +02:00
<PageContainerFooter
onCancel={this.stopAndClose}
onSubmit={this.tryAgain}
cancelText={this.context.t('cancel')}
submitText={this.context.t('tryAgain')}
2018-08-08 18:22:48 +02:00
submitButtonType="confirm"
2018-08-08 09:00:39 +02:00
/>
2018-08-04 00:57:23 +02:00
</div>
)
}
2018-07-30 23:50:05 +02:00
render () {
const { t } = this.context
2018-08-04 00:57:23 +02:00
if (this.props.error) {
return this.renderErrorModal()
}
2018-07-30 23:50:05 +02:00
return (
2018-07-31 00:34:00 +02:00
<div className="qr-scanner">
2018-08-04 00:57:23 +02:00
<div className="qr-scanner__close" onClick={this.stopAndClose}></div>
2018-07-31 00:34:00 +02:00
<div className="qr-scanner__title">
{ `${t('scanQrCode')}` }
2018-07-31 00:34:00 +02:00
</div>
<div className="qr-scanner__content">
2018-08-04 00:57:23 +02:00
{ this.renderVideo() }
2018-07-30 23:50:05 +02:00
</div>
2018-08-04 00:57:23 +02:00
<div className={'qr-scanner__status'}>
2018-07-31 00:34:00 +02:00
{this.state.msg}
2018-07-30 23:50:05 +02:00
</div>
</div>
)
}
}