Fix the media stream not being stopped; mirror the QR camera (#2165)

Co-authored-by: katspaugh <--replace-all>
Co-authored-by: Fernando <fernando.greco@gmail.com>
This commit is contained in:
katspaugh 2021-04-16 01:21:27 +02:00 committed by GitHub
parent b8de127c42
commit 82d8ab357d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 33 additions and 60 deletions

View File

@ -21,6 +21,6 @@ jobs:
path-to-signatures: 'signatures/version1/cla.json' path-to-signatures: 'signatures/version1/cla.json'
path-to-cla-document: 'https://github.com/gnosis/safe-react/blob/master/GNOSISCLA.md' path-to-cla-document: 'https://github.com/gnosis/safe-react/blob/master/GNOSISCLA.md'
branch: 'cla-signatures' branch: 'cla-signatures'
allowlist: lukasschor,mikheevm,rmeissner,germartinez,fernandomg,Agupane,nicosampler,matextrem,gabitoesmiapodo,davidalbela,alongoni,Uxio0,dasanra,miguelmota,francovenica,tschubotz,luarx,giacomolicari,gnosis-info,bot* allowlist: lukasschor,mikheevm,rmeissner,germartinez,fernandomg,Agupane,nicosampler,matextrem,gabitoesmiapodo,davidalbela,alongoni,Uxio0,dasanra,miguelmota,francovenica,tschubotz,luarx,giacomolicari,gnosis-info,bot*,katspaugh
empty-commit-flag: false empty-commit-flag: false
blockchain-storage-flag: false blockchain-storage-flag: false

View File

@ -27,7 +27,7 @@ export const ScanQRWrapper = ({ handleScan }: Props): ReactElement => {
setQrModalOpen(false) setQrModalOpen(false)
} }
const onScanFinished = (value) => { const onScanFinished = (value: string) => {
handleScan(value, closeQrModal) handleScan(value, closeQrModal)
} }

View File

@ -1,4 +1,3 @@
import { Loader } from '@gnosis.pm/safe-react-components'
import IconButton from '@material-ui/core/IconButton' import IconButton from '@material-ui/core/IconButton'
import { makeStyles } from '@material-ui/core/styles' import { makeStyles } from '@material-ui/core/styles'
import Close from '@material-ui/icons/Close' import Close from '@material-ui/icons/Close'
@ -6,7 +5,6 @@ import * as React from 'react'
import QrReader from 'react-qr-reader' import QrReader from 'react-qr-reader'
import { styles } from './style' import { styles } from './style'
import { checkWebcam } from './utils'
import Modal from 'src/components/Modal' import Modal from 'src/components/Modal'
import Block from 'src/components/layout/Block' import Block from 'src/components/layout/Block'
@ -27,45 +25,39 @@ type Props = {
export const ScanQRModal = ({ isOpen, onClose, onScan }: Props): React.ReactElement => { export const ScanQRModal = ({ isOpen, onClose, onScan }: Props): React.ReactElement => {
const classes = useStyles() const classes = useStyles()
const [useWebcam, setUseWebcam] = useState<boolean | null>(null)
const [fileUploadModalOpen, setFileUploadModalOpen] = useState<boolean>(false) const [fileUploadModalOpen, setFileUploadModalOpen] = useState<boolean>(false)
const [error, setError] = useState<string | null>(null) const [error, setError] = useState<string | null>(null)
const [cameraBlocked, setCameraBlocked] = useState<boolean>(false)
const scannerRef: any = React.createRef() const scannerRef: any = React.createRef()
const openImageDialog = React.useCallback(() => { const openImageDialog = React.useCallback(() => {
scannerRef.current.openImageDialog() scannerRef.current.openImageDialog()
}, [scannerRef]) }, [scannerRef])
useEffect(() => { useEffect(() => {
checkWebcam( if (!fileUploadModalOpen && cameraBlocked && !error) {
() => {
setUseWebcam(true)
},
() => {
setUseWebcam(false)
},
)
}, [])
useEffect(() => {
if (useWebcam === false && !fileUploadModalOpen && !error) {
setFileUploadModalOpen(true) setFileUploadModalOpen(true)
openImageDialog() openImageDialog()
} }
}, [useWebcam, openImageDialog, fileUploadModalOpen, setFileUploadModalOpen, error]) }, [cameraBlocked, openImageDialog, fileUploadModalOpen, setFileUploadModalOpen, error])
const onFileScannedResolve = (error: Error | null, successData: string | null) => {
if (error) {
console.error('QR code error', error)
if (error.name === 'NotAllowedError' || error.name === 'PermissionDismissedError') {
setCameraBlocked(true)
setFileUploadModalOpen(false)
} else {
setError('The QR could not be read')
}
return
}
const onFileScannedResolve = (error: string | null, successData: string | null) => {
if (successData) { if (successData) {
onScan(successData) onScan(successData)
} else if (cameraBlocked) {
setError('The QR could not be read')
} }
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 ( return (
@ -80,20 +72,19 @@ export const ScanQRModal = ({ isOpen, onClose, onScan }: Props): React.ReactElem
</Row> </Row>
<Hairline /> <Hairline />
<Col className={classes.detailsContainer} layout="column" middle="xs"> <Col className={classes.detailsContainer} layout="column" middle="xs">
{error} {error && (
{useWebcam === null ? ( <Block padding="md" margin="md">
<Block className={classes.loaderContainer} justify="center"> {error}
<Loader size="md" />
</Block> </Block>
) : (
<QrReader
legacyMode={!useWebcam}
onError={(err) => onFileScannedResolve(err, null)}
onScan={(data) => onFileScannedResolve(null, data)}
ref={scannerRef}
style={{ width: '400px', height: '400px' }}
/>
)} )}
<QrReader
legacyMode={cameraBlocked}
onError={(err: Error) => onFileScannedResolve(err, null)}
onScan={(data: string) => onFileScannedResolve(null, data)}
ref={scannerRef}
style={{ width: '400px', height: '400px' }}
facingMode="user"
/>
</Col> </Col>
<Hairline /> <Hairline />
<Row align="center" className={classes.buttonRow}> <Row align="center" className={classes.buttonRow}>
@ -105,7 +96,7 @@ export const ScanQRModal = ({ isOpen, onClose, onScan }: Props): React.ReactElem
color="primary" color="primary"
minWidth={154} minWidth={154}
onClick={() => { onClick={() => {
setUseWebcam(false) setCameraBlocked(true)
setError(null) setError(null)
setFileUploadModalOpen(false) setFileUploadModalOpen(false)
}} }}

View File

@ -19,7 +19,7 @@ export const styles = createStyles({
}, },
detailsContainer: { detailsContainer: {
backgroundColor: background, backgroundColor: background,
maxHeight: '420px', maxHeight: '450px',
}, },
buttonRow: { buttonRow: {
height: '84px', height: '84px',

View File

@ -1,18 +0,0 @@
const navigatorCp: any = navigator
navigatorCp.getMedia =
navigatorCp.getUserMedia || // use the proper vendor prefix
navigatorCp.webkitGetUserMedia ||
navigatorCp.mozGetUserMedia ||
navigatorCp.msGetUserMedia
export const checkWebcam = (success, err) =>
navigatorCp.getMedia(
{ video: true },
() => {
success()
},
() => {
err()
},
)