(Fix) - #1605 QR Input address fix (#1612)

* Add types

* Fix missing address in input field

* Fix reopening file upload modal once closed

* Error first callback onFileUploadHandlerClose

* Adds error text for qrs that can't be read
Fixes popping up again for wrong qr codes

* Fix opening modal

Co-authored-by: nicolas <nicosampler@users.noreply.github.com>
This commit is contained in:
Agustin Pane 2020-11-19 12:22:48 -03:00 committed by GitHub
parent 486bb4b203
commit e482d3259b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 60 additions and 42 deletions

View File

@ -16,7 +16,7 @@ const styles = () => ({
position: 'absolute',
top: '120px',
width: '500px',
height: '530px',
height: '540px',
borderRadius: sm,
backgroundColor: '#ffffff',
boxShadow: '0 0 5px 0 rgba(74, 85, 121, 0.5)',

View File

@ -3,7 +3,7 @@ import { useState } from 'react'
import * as React from 'react'
import QRIcon from 'src/assets/icons/qrcode.svg'
import ScanQRModal from 'src/components/ScanQRModal'
import { ScanQRModal } from 'src/components/ScanQRModal'
import Img from 'src/components/layout/Img'
const useStyles = makeStyles({
@ -12,7 +12,11 @@ const useStyles = makeStyles({
},
})
export const ScanQRWrapper = (props) => {
type Props = {
handleScan: (dataResult: string, closeQrModal: () => void) => void
}
export const ScanQRWrapper = ({ handleScan }: Props): React.ReactElement => {
const classes = useStyles()
const [qrModalOpen, setQrModalOpen] = useState(false)
@ -25,7 +29,7 @@ export const ScanQRWrapper = (props) => {
}
const onScanFinished = (value) => {
props.handleScan(value, closeQrModal)
handleScan(value, closeQrModal)
}
return (
@ -34,9 +38,7 @@ export const ScanQRWrapper = (props) => {
alt="Scan QR"
className={classes.qrCodeBtn}
height={20}
onClick={() => {
openQrModal()
}}
onClick={() => openQrModal()}
role="button"
src={QRIcon}
testId="qr-icon"

View File

@ -1,6 +1,6 @@
import CircularProgress from '@material-ui/core/CircularProgress'
import IconButton from '@material-ui/core/IconButton'
import { withStyles } from '@material-ui/core/styles'
import { makeStyles } from '@material-ui/core/styles'
import Close from '@material-ui/icons/Close'
import * as React from 'react'
import QrReader from 'react-qr-reader'
@ -15,11 +15,21 @@ import Col from 'src/components/layout/Col'
import Hairline from 'src/components/layout/Hairline'
import Paragraph from 'src/components/layout/Paragraph'
import Row from 'src/components/layout/Row'
import { useEffect, useState } from 'react'
const { useEffect, useState } = React
const useStyles = makeStyles(styles)
const ScanQRModal = ({ classes, isOpen, onClose, onScan }) => {
const [hasWebcam, setHasWebcam] = useState<any>(null)
type Props = {
isOpen: boolean
onClose: () => void
onScan: (value: string) => void
}
export const ScanQRModal = ({ isOpen, onClose, onScan }: Props): React.ReactElement => {
const classes = useStyles()
const [useWebcam, setUseWebcam] = useState<boolean | null>(null)
const [fileUploadModalOpen, setFileUploadModalOpen] = useState<boolean>(false)
const [error, setError] = useState<string | null>(null)
const scannerRef: any = React.createRef()
const openImageDialog = React.useCallback(() => {
scannerRef.current.openImageDialog()
@ -28,22 +38,35 @@ const ScanQRModal = ({ classes, isOpen, onClose, onScan }) => {
useEffect(() => {
checkWebcam(
() => {
setHasWebcam(true)
setUseWebcam(true)
},
() => {
setHasWebcam(false)
setUseWebcam(false)
},
)
}, [])
useEffect(() => {
// this fires only when the hasWebcam changes to false (null > false (user doesn't have webcam)
// , true > false (user switched from webcam to file upload))
// Doesn't fire on re-render
if (hasWebcam === false) {
if (useWebcam === false && !fileUploadModalOpen && !error) {
setFileUploadModalOpen(true)
openImageDialog()
}
}, [hasWebcam, openImageDialog])
}, [useWebcam, openImageDialog, fileUploadModalOpen, setFileUploadModalOpen, error])
const onFileScannedResolve = (error: string | null, successData: string | null) => {
if (successData) {
onScan(successData)
}
if (error) {
console.error('Error uploading file', error)
setError(`The QR could not be read`)
}
if (!useWebcam) {
setError(`The QR could not be read`)
}
setFileUploadModalOpen(false)
}
return (
<Modal description="Receive Tokens Form" handleClose={onClose} open={isOpen} title="Receive Tokens">
@ -57,19 +80,16 @@ const ScanQRModal = ({ classes, isOpen, onClose, onScan }) => {
</Row>
<Hairline />
<Col className={classes.detailsContainer} layout="column" middle="xs">
{hasWebcam === null ? (
{error}
{useWebcam === null ? (
<Block className={classes.loaderContainer} justify="center">
<CircularProgress />
</Block>
) : (
<QrReader
legacyMode={!hasWebcam}
onError={(err) => {
console.error(err)
}}
onScan={(data) => {
if (data) onScan(data)
}}
legacyMode={!useWebcam}
onError={(err) => onFileScannedResolve(err, null)}
onScan={(data) => onFileScannedResolve(null, data)}
ref={scannerRef}
style={{ width: '400px', height: '400px' }}
/>
@ -85,11 +105,9 @@ const ScanQRModal = ({ classes, isOpen, onClose, onScan }) => {
color="primary"
minWidth={154}
onClick={() => {
if (hasWebcam) {
setHasWebcam(false)
} else {
openImageDialog()
}
setUseWebcam(false)
setError(null)
setFileUploadModalOpen(false)
}}
variant="contained"
>
@ -99,5 +117,3 @@ const ScanQRModal = ({ classes, isOpen, onClose, onScan }) => {
</Modal>
)
}
export default withStyles(styles as any)(ScanQRModal)

View File

@ -1,6 +1,7 @@
import { background, lg, secondaryText, sm } from 'src/theme/variables'
import { createStyles } from '@material-ui/core'
export const styles = () => ({
export const styles = createStyles({
heading: {
padding: lg,
justifyContent: 'space-between',

View File

@ -8,7 +8,7 @@ import { getAddressValidator } from './validators'
import QRIcon from 'src/assets/icons/qrcode.svg'
import trash from 'src/assets/icons/trash.svg'
import ScanQRModal from 'src/components/ScanQRModal'
import { ScanQRModal } from 'src/components/ScanQRModal'
import OpenPaper from 'src/components/Stepper/OpenPaper'
import AddressInput from 'src/components/forms/AddressInput'
import Field from 'src/components/forms/Field'
@ -97,10 +97,10 @@ const SafeOwnersForm = (props): React.ReactElement => {
setNumOwners(numOwners + 1)
}
const handleScan = (value) => {
const handleScan = (value: string | null) => {
let scannedAddress = value
if (scannedAddress.startsWith('ethereum:')) {
if (scannedAddress?.startsWith('ethereum:')) {
scannedAddress = scannedAddress.replace('ethereum:', '')
}

View File

@ -27,7 +27,7 @@ export interface EthAddressInputProps {
text: string
}
const EthAddressInput = ({
export const EthAddressInput = ({
isContract = true,
isRequired = true,
name,
@ -57,6 +57,7 @@ const EthAddressInput = ({
scannedAddress = scannedAddress.replace('ethereum:', '')
}
setSelectedEntry({ address: scannedAddress })
onScannedValue(scannedAddress)
closeQrModal()
}
@ -97,5 +98,3 @@ const EthAddressInput = ({
</>
)
}
export default EthAddressInput

View File

@ -22,7 +22,7 @@ import Hairline from 'src/components/layout/Hairline'
import Img from 'src/components/layout/Img'
import Paragraph from 'src/components/layout/Paragraph'
import Row from 'src/components/layout/Row'
import ScanQRModal from 'src/components/ScanQRModal'
import { ScanQRModal } from 'src/components/ScanQRModal'
import { safeSelector } from 'src/logic/safe/store/selectors'
import SafeInfo from 'src/routes/safe/components/Balances/SendModal/SafeInfo'
import { ContractsAddressBookInput } from 'src/routes/safe/components/Balances/SendModal/screens/AddressBookInput'

View File

@ -11,7 +11,7 @@ import { safeSelector } from 'src/logic/safe/store/selectors'
import Paragraph from 'src/components/layout/Paragraph'
import Buttons from './Buttons'
import ContractABI from './ContractABI'
import EthAddressInput from './EthAddressInput'
import { EthAddressInput } from './EthAddressInput'
import FormDivisor from './FormDivisor'
import FormErrorMessage from './FormErrorMessage'
import Header from './Header'