// @flow import * as React from 'react'; import {Linking, Platform, StyleSheet, View} from 'react-native'; import {Button, Text, withTheme} from 'react-native-paper'; import {RNCamera} from 'react-native-camera'; import {BarcodeMask} from '@nartc/react-native-barcode-mask'; import i18n from 'i18n-js'; import {PERMISSIONS, request, RESULTS} from 'react-native-permissions'; import URLHandler from '../../utils/URLHandler'; import AlertDialog from '../../components/Dialogs/AlertDialog'; import CustomTabBar from '../../components/Tabbar/CustomTabBar'; import LoadingConfirmDialog from '../../components/Dialogs/LoadingConfirmDialog'; import {MASCOT_STYLE} from '../../components/Mascot/Mascot'; import MascotPopup from '../../components/Mascot/MascotPopup'; type StateType = { hasPermission: boolean, scanned: boolean, dialogVisible: boolean, mascotDialogVisible: boolean, loading: boolean, }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', }, button: { position: 'absolute', bottom: 20, width: '80%', left: '10%', }, }); class ScannerScreen extends React.Component { constructor() { super(); this.state = { hasPermission: false, scanned: false, mascotDialogVisible: false, dialogVisible: false, loading: false, }; } componentDidMount() { this.requestPermissions(); } /** * Gets a view asking user for permission to use the camera * * @returns {*} */ getPermissionScreen(): React.Node { return ( {i18n.t('screens.scanner.permissions.error')} ); } /** * Gets a view with the scanner. * This scanner uses the back camera, can only scan qr codes and has a square mask on the center. * The mask is only for design purposes as a code is scanned as soon as it enters the camera view * * @returns {*} */ getScanner(): React.Node { const {state} = this; return ( ); } /** * Requests permission to use the camera */ requestPermissions = () => { if (Platform.OS === 'android') request(PERMISSIONS.ANDROID.CAMERA).then(this.updatePermissionStatus); else request(PERMISSIONS.IOS.CAMERA).then(this.updatePermissionStatus); }; /** * Updates the state permission status * * @param result */ updatePermissionStatus = (result: RESULTS) => { this.setState({ hasPermission: result === RESULTS.GRANTED, }); }; /** * Shows a dialog indicating the user the scanned code was invalid */ // eslint-disable-next-line react/sort-comp showErrorDialog() { this.setState({ dialogVisible: true, scanned: true, }); } /** * Shows a dialog indicating how to use the scanner */ showHelpDialog = () => { this.setState({ mascotDialogVisible: true, scanned: true, }); }; /** * Shows a loading dialog */ showOpeningDialog = () => { this.setState({ loading: true, scanned: true, }); }; /** * Hide any dialog */ onDialogDismiss = () => { this.setState({ dialogVisible: false, scanned: false, }); }; onMascotDialogDismiss = () => { this.setState({ mascotDialogVisible: false, scanned: false, }); }; /** * Opens scanned link if it is a valid app link or shows and error dialog * * @param type The barcode type * @param data The scanned value */ onCodeScanned = ({data}: {data: string}) => { if (!URLHandler.isUrlValid(data)) this.showErrorDialog(); else { this.showOpeningDialog(); Linking.openURL(data); } }; render(): React.Node { const {state} = this; return ( {state.hasPermission ? this.getScanner() : this.getPermissionScreen()} ); } } export default withTheme(ScannerScreen);