aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/_locales/en/messages.json10
-rw-r--r--app/images/webcam.svg18
-rw-r--r--ui/app/components/modals/qr-scanner/index.scss40
-rw-r--r--ui/app/components/modals/qr-scanner/qr-scanner.component.js72
-rw-r--r--ui/app/components/modals/qr-scanner/qr-scanner.container.js6
-rw-r--r--ui/app/components/send/to-autocomplete/to-autocomplete.js8
-rw-r--r--ui/app/css/itcss/components/send.scss12
-rw-r--r--ui/lib/webcam-utils.js45
8 files changed, 166 insertions, 45 deletions
diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json
index ec96f5b08..db050e766 100644
--- a/app/_locales/en/messages.json
+++ b/app/_locales/en/messages.json
@@ -656,8 +656,11 @@
"notStarted": {
"message": "Not Started"
},
+ "noWebcamFoundTitle": {
+ "message": "Webcam not found"
+ },
"noWebcamFound": {
- "message": "We couldn't find any webcam available on your computer. Make sure the device is connected and configured correctly."
+ "message": "Your computer's webcam was not found. Please try again."
},
"oldUI": {
"message": "Old UI"
@@ -1101,8 +1104,11 @@
"unknownQrCode": {
"message": "Error: We couldn't identify that QR code"
},
+ "unknownCameraErrorTitle": {
+ "message": "Ooops! Something went wrong...."
+ },
"unknownCameraError": {
- "message": "Ooops! Something went wrong while trying to access you camera. Please try again..."
+ "message": "There was an error while trying to access you camera. Please try again..."
},
"unlock": {
"message": "Unlock"
diff --git a/app/images/webcam.svg b/app/images/webcam.svg
new file mode 100644
index 000000000..4b9b58148
--- /dev/null
+++ b/app/images/webcam.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="53px" height="53px" viewBox="0 0 53 53" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <!-- Generator: Sketch 50.2 (55047) - http://www.bohemiancoding.com/sketch -->
+ <title>webcam</title>
+ <desc>Created with Sketch.</desc>
+ <defs></defs>
+ <g id="QR-Code-Scan" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g id="Group-4-Copy" transform="translate(-482.000000, -218.000000)">
+ <g id="webcam" transform="translate(482.000000, 218.000000)">
+ <circle id="Oval" fill="#D5ECFA" cx="26.5" cy="26.5" r="26.5"></circle>
+ <g id="Group" transform="translate(14.000000, 19.000000)" fill="#259DE5">
+ <rect id="Rectangle" x="0" y="0" width="18" height="16"></rect>
+ <polygon id="Triangle" points="19 6.57142857 26 3 26 13 19 9.42857143"></polygon>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg> \ No newline at end of file
diff --git a/ui/app/components/modals/qr-scanner/index.scss b/ui/app/components/modals/qr-scanner/index.scss
index df65cfbbb..6fa81d51f 100644
--- a/ui/app/components/modals/qr-scanner/index.scss
+++ b/ui/app/components/modals/qr-scanner/index.scss
@@ -39,9 +39,45 @@
padding: 15px;
}
- &__status.error {
- padding: 60px 45px 80px;
+ &__image {
+ font-size: 1.5rem;
+ font-weight: 500;
+ padding: 16px 0 0;
+ text-align: center;
+ }
+
+ &__error {
+ text-align: center;
font-size: 16px;
+ padding: 15px;
+ }
+
+ &__footer {
+ padding: 20px;
+ flex-direction: row;
+ display: flex;
+
+ button {
+ margin-right: 15px;
+ }
+
+ button:last-of-type {
+ margin-right: 0;
+ background-color: #009eec;
+ border: none;
+ color: #fff;
+ }
+ }
+
+ &__close::after {
+ content: '\00D7';
+ font-size: 35px;
+ color: #9b9b9b;
+ position: absolute;
+ top: 4px;
+ right: 20px;
+ cursor: pointer;
+ font-weight: 300;
}
}
diff --git a/ui/app/components/modals/qr-scanner/qr-scanner.component.js b/ui/app/components/modals/qr-scanner/qr-scanner.component.js
index e6ba146d6..5ca19ccd8 100644
--- a/ui/app/components/modals/qr-scanner/qr-scanner.component.js
+++ b/ui/app/components/modals/qr-scanner/qr-scanner.component.js
@@ -9,6 +9,7 @@ export default class QrScanner extends Component {
static propTypes = {
hideModal: PropTypes.func.isRequired,
qrCodeDetected: PropTypes.func,
+ scanQrCode: PropTypes.func,
error: PropTypes.bool,
errorType: PropTypes.string,
}
@@ -20,18 +21,9 @@ export default class QrScanner extends Component {
constructor (props, context) {
super(props)
- let initialMsg = context.t('accessingYourCamera')
- if (props.error) {
- if (props.errorType === 'NO_WEBCAM_FOUND') {
- initialMsg = context.t('noWebcamFound')
- } else {
- initialMsg = context.t('unknownCameraError')
- }
- }
-
this.state = {
ready: false,
- msg: initialMsg,
+ msg: context.t('accessingYourCamera'),
}
this.codeReader = null
this.permissionChecker = null
@@ -118,11 +110,22 @@ export default class QrScanner extends Component {
stopAndClose = () => {
- this.codeReader.reset()
+ if (this.codeReader) {
+ this.codeReader.reset()
+ }
this.setState({ ready: false })
this.props.hideModal()
}
+ 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'}>
@@ -137,18 +140,61 @@ export default class QrScanner extends Component {
)
}
+ 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>
+ <div className={'qr-scanner__footer'}>
+ <button className="btn-default btn--large" onClick={this.stopAndClose}>
+ CANCEL
+ </button>
+ <button className="btn-primary btn--large" onClick={this.tryAgain}>
+ TRY AGAIN
+ </button>
+ </div>
+ </div>
+ )
+ }
+
render () {
const { t } = this.context
+ if (this.props.error) {
+ return this.renderErrorModal()
+ }
+
return (
<div className="qr-scanner">
+ <div className="qr-scanner__close" onClick={this.stopAndClose}></div>
<div className="qr-scanner__title">
{ `${t('scanQrCode')}` }
</div>
<div className="qr-scanner__content">
- { !this.props.error ? this.renderVideo() : null}
+ { this.renderVideo() }
</div>
- <div className={`qr-scanner__status ${this.props.error ? 'error' : ''}`}>
+ <div className={'qr-scanner__status'}>
{this.state.msg}
</div>
</div>
diff --git a/ui/app/components/modals/qr-scanner/qr-scanner.container.js b/ui/app/components/modals/qr-scanner/qr-scanner.container.js
index d50abe0ae..d0a35e03b 100644
--- a/ui/app/components/modals/qr-scanner/qr-scanner.container.js
+++ b/ui/app/components/modals/qr-scanner/qr-scanner.container.js
@@ -1,7 +1,10 @@
import { connect } from 'react-redux'
import QrScanner from './qr-scanner.component'
-const { hideModal, qrCodeDetected } = require('../../../actions')
+const { hideModal, qrCodeDetected, showQrScanner } = require('../../../actions')
+import {
+ SEND_ROUTE,
+} from '../../../routes'
const mapStateToProps = state => {
return {
@@ -14,6 +17,7 @@ const mapDispatchToProps = dispatch => {
return {
hideModal: () => dispatch(hideModal()),
qrCodeDetected: (data) => dispatch(qrCodeDetected(data)),
+ scanQrCode: () => dispatch(showQrScanner(SEND_ROUTE)),
}
}
diff --git a/ui/app/components/send/to-autocomplete/to-autocomplete.js b/ui/app/components/send/to-autocomplete/to-autocomplete.js
index 14e30e84c..49ebf49d9 100644
--- a/ui/app/components/send/to-autocomplete/to-autocomplete.js
+++ b/ui/app/components/send/to-autocomplete/to-autocomplete.js
@@ -4,6 +4,7 @@ const h = require('react-hyperscript')
const inherits = require('util').inherits
const AccountListItem = require('../account-list-item/account-list-item.component').default
const connect = require('react-redux').connect
+const Tooltip = require('../../tooltip')
ToAutoComplete.contextTypes = {
t: PropTypes.func,
@@ -109,10 +110,13 @@ ToAutoComplete.prototype.render = function () {
borderColor: inError ? 'red' : null,
},
}),
- qrScanner && h(`i.fa.fa-qrcode.fa-lg.send-v2__to-autocomplete__qr-code`, {
+ qrScanner && h(Tooltip, {
+ title: this.context.t('scanQrCode'),
+ position: 'bottom',
+ }, h(`i.fa.fa-qrcode.fa-lg.send-v2__to-autocomplete__qr-code`, {
style: { color: '#33333' },
onClick: () => this.props.scanQrCode(),
- }),
+ })),
!to && h(`i.fa.fa-caret-down.fa-lg.send-v2__to-autocomplete__down-caret`, {
style: { color: '#dedede' },
onClick: () => this.handleInputEvent(),
diff --git a/ui/app/css/itcss/components/send.scss b/ui/app/css/itcss/components/send.scss
index ad6199f02..806ac8536 100644
--- a/ui/app/css/itcss/components/send.scss
+++ b/ui/app/css/itcss/components/send.scss
@@ -629,13 +629,19 @@
&__qr-code {
position: absolute;
- top: 21px;
- left: 13px;
+ top: 13px;
+ right: 33px;
cursor: pointer;
+ padding: 8px 5px 5px;
+ border-radius: 4px;
+ }
+
+ &__qr-code:hover {
+ background: #f1f1f1;
}
&__input.with-qr {
- padding-left: 40px;
+ padding-right: 65px;
}
}
diff --git a/ui/lib/webcam-utils.js b/ui/lib/webcam-utils.js
index 9b507cd99..b1609ff4a 100644
--- a/ui/lib/webcam-utils.js
+++ b/ui/lib/webcam-utils.js
@@ -8,28 +8,29 @@ class WebcamUtils {
static checkStatus () {
return new Promise((resolve, reject) => {
- const isPopup = getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP
- const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1
- const isBrave = !!window.chrome.ipcRenderer
- const isFirefoxOrBrave = isFirefox || isBrave
- try {
- DetectRTC.load(_ => {
- if (DetectRTC.hasWebcam) {
- let environmentReady = true
- if ((isFirefoxOrBrave && isPopup) || (isPopup && !DetectRTC.isWebsiteHasWebcamPermissions)) {
- environmentReady = false
- }
- resolve({
- permissions: DetectRTC.isWebsiteHasWebcamPermissions,
- environmentReady,
- })
- } else {
- reject({type: 'NO_WEBCAM_FOUND'})
- }
- })
- } catch (e) {
- reject({type: 'UNKNOWN_ERROR'})
- }
+ reject({type: 'UNKNOWN_ERROR'})
+ // const isPopup = getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP
+ // const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1
+ // const isBrave = !!window.chrome.ipcRenderer
+ // const isFirefoxOrBrave = isFirefox || isBrave
+ // try {
+ // DetectRTC.load(_ => {
+ // if (DetectRTC.hasWebcam) {
+ // let environmentReady = true
+ // if ((isFirefoxOrBrave && isPopup) || (isPopup && !DetectRTC.isWebsiteHasWebcamPermissions)) {
+ // environmentReady = false
+ // }
+ // resolve({
+ // permissions: DetectRTC.isWebsiteHasWebcamPermissions,
+ // environmentReady,
+ // })
+ // } else {
+ // reject({type: 'NO_WEBCAM_FOUND'})
+ // }
+ // })
+ // } catch (e) {
+ // reject({type: 'UNKNOWN_ERROR'})
+ // }
})
}
}