* 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:
parent
486bb4b203
commit
e482d3259b
|
@ -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)',
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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:', '')
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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'
|
||||
|
|
Loading…
Reference in New Issue