2019-09-21 13:37:37 -04:00
|
|
|
/* global alert */
|
2020-06-10 23:54:47 -04:00
|
|
|
import React, { useState } from 'react';
|
2020-05-31 16:30:01 +03:00
|
|
|
import { Image, View, TouchableOpacity, StatusBar, Platform, StyleSheet } from 'react-native';
|
2019-05-02 16:33:03 -04:00
|
|
|
import { RNCamera } from 'react-native-camera';
|
2019-09-21 13:37:37 -04:00
|
|
|
import { Icon } from 'react-native-elements';
|
|
|
|
import ImagePicker from 'react-native-image-picker';
|
2020-05-28 11:44:15 +03:00
|
|
|
import { useNavigation, useRoute, useIsFocused } from '@react-navigation/native';
|
2019-12-31 21:31:04 -06:00
|
|
|
import DocumentPicker from 'react-native-document-picker';
|
|
|
|
import RNFS from 'react-native-fs';
|
2020-07-20 16:38:46 +03:00
|
|
|
import loc from '../../loc';
|
2019-09-21 13:37:37 -04:00
|
|
|
const LocalQRCode = require('@remobile/react-native-qrcode-local-image');
|
2020-03-13 14:23:12 +00:00
|
|
|
const createHash = require('create-hash');
|
2018-01-30 22:42:38 +00:00
|
|
|
|
2020-05-24 12:17:26 +03:00
|
|
|
const styles = StyleSheet.create({
|
|
|
|
root: {
|
|
|
|
flex: 1,
|
|
|
|
backgroundColor: '#000000',
|
|
|
|
},
|
|
|
|
rnCamera: {
|
|
|
|
flex: 1,
|
|
|
|
},
|
|
|
|
closeTouch: {
|
|
|
|
width: 40,
|
|
|
|
height: 40,
|
|
|
|
backgroundColor: 'rgba(0,0,0,0.4)',
|
|
|
|
justifyContent: 'center',
|
|
|
|
borderRadius: 20,
|
|
|
|
position: 'absolute',
|
|
|
|
right: 16,
|
|
|
|
top: 44,
|
|
|
|
},
|
|
|
|
closeImage: {
|
|
|
|
alignSelf: 'center',
|
|
|
|
},
|
|
|
|
imagePickerTouch: {
|
|
|
|
width: 40,
|
|
|
|
height: 40,
|
|
|
|
backgroundColor: 'rgba(0,0,0,0.4)',
|
|
|
|
justifyContent: 'center',
|
|
|
|
borderRadius: 20,
|
|
|
|
position: 'absolute',
|
|
|
|
left: 24,
|
|
|
|
bottom: 48,
|
|
|
|
},
|
|
|
|
filePickerTouch: {
|
|
|
|
width: 40,
|
|
|
|
height: 40,
|
|
|
|
backgroundColor: 'rgba(0,0,0,0.4)',
|
|
|
|
justifyContent: 'center',
|
|
|
|
borderRadius: 20,
|
|
|
|
position: 'absolute',
|
|
|
|
left: 96,
|
|
|
|
bottom: 48,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2020-05-28 11:44:15 +03:00
|
|
|
const ScanQRCode = () => {
|
2019-12-27 18:53:34 -06:00
|
|
|
const [isLoading, setIsLoading] = useState(false);
|
2020-05-31 16:30:01 +03:00
|
|
|
const navigation = useNavigation();
|
2020-05-27 14:12:17 +03:00
|
|
|
const route = useRoute();
|
2020-05-28 11:44:15 +03:00
|
|
|
const showFileImportButton = route.params.showFileImportButton || false;
|
2020-05-27 14:12:17 +03:00
|
|
|
const { launchedBy, onBarScanned } = route.params;
|
2020-03-13 14:23:12 +00:00
|
|
|
const scannedCache = {};
|
2020-05-28 11:44:15 +03:00
|
|
|
const isFocused = useIsFocused();
|
2020-03-13 14:23:12 +00:00
|
|
|
|
2020-06-01 15:54:23 +03:00
|
|
|
const HashIt = function (s) {
|
|
|
|
return createHash('sha256').update(s).digest().toString('hex');
|
2020-03-13 14:23:12 +00:00
|
|
|
};
|
|
|
|
|
2019-12-27 18:53:34 -06:00
|
|
|
const onBarCodeRead = ret => {
|
2020-03-13 14:23:12 +00:00
|
|
|
const h = HashIt(ret.data);
|
|
|
|
if (scannedCache[h]) {
|
|
|
|
// this QR was already scanned by this ScanQRCode, lets prevent firing duplicate callbacks
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
scannedCache[h] = +new Date();
|
|
|
|
|
2020-05-21 11:36:03 -04:00
|
|
|
if (!isLoading) {
|
2019-12-27 18:53:34 -06:00
|
|
|
setIsLoading(true);
|
|
|
|
try {
|
2020-05-28 11:44:15 +03:00
|
|
|
if (launchedBy) {
|
2020-05-31 16:30:01 +03:00
|
|
|
navigation.navigate(launchedBy);
|
2019-12-27 18:53:34 -06:00
|
|
|
}
|
2019-12-31 21:31:04 -06:00
|
|
|
if (ret.additionalProperties) {
|
|
|
|
onBarScanned(ret.data, ret.additionalProperties);
|
|
|
|
} else {
|
|
|
|
onBarScanned(ret.data);
|
|
|
|
}
|
2019-12-27 18:53:34 -06:00
|
|
|
} catch (e) {
|
|
|
|
console.log(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
setIsLoading(false);
|
|
|
|
};
|
2018-01-30 22:42:38 +00:00
|
|
|
|
2019-12-31 21:31:04 -06:00
|
|
|
const showFilePicker = async () => {
|
|
|
|
setIsLoading(true);
|
|
|
|
try {
|
|
|
|
const res = await DocumentPicker.pick();
|
|
|
|
const file = await RNFS.readFile(res.uri);
|
|
|
|
const fileParsed = JSON.parse(file);
|
|
|
|
if (fileParsed.keystore.xpub) {
|
2020-01-02 14:54:34 -06:00
|
|
|
let masterFingerprint;
|
|
|
|
if (fileParsed.keystore.ckcc_xfp) {
|
2020-01-02 22:02:41 -06:00
|
|
|
masterFingerprint = Number(fileParsed.keystore.ckcc_xfp);
|
2020-01-02 14:54:34 -06:00
|
|
|
}
|
2020-03-05 15:16:34 +00:00
|
|
|
onBarCodeRead({ data: fileParsed.keystore.xpub, additionalProperties: { masterFingerprint, label: fileParsed.keystore.label } });
|
2019-12-31 21:31:04 -06:00
|
|
|
} else {
|
|
|
|
throw new Error();
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
if (!DocumentPicker.isCancel(err)) {
|
2020-07-20 16:38:46 +03:00
|
|
|
alert(loc.send.qr_error_no_wallet);
|
2019-12-31 21:31:04 -06:00
|
|
|
}
|
|
|
|
setIsLoading(false);
|
|
|
|
}
|
|
|
|
setIsLoading(false);
|
|
|
|
};
|
2018-01-30 22:42:38 +00:00
|
|
|
|
2020-05-28 11:44:15 +03:00
|
|
|
const showImagePicker = () => {
|
|
|
|
if (!isLoading) {
|
|
|
|
setIsLoading(true);
|
|
|
|
ImagePicker.launchImageLibrary(
|
|
|
|
{
|
|
|
|
title: null,
|
|
|
|
mediaType: 'photo',
|
|
|
|
takePhotoButtonTitle: null,
|
|
|
|
},
|
|
|
|
response => {
|
|
|
|
if (response.uri) {
|
|
|
|
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.path.toString();
|
|
|
|
LocalQRCode.decode(uri, (error, result) => {
|
|
|
|
if (!error) {
|
|
|
|
onBarCodeRead({ data: result });
|
|
|
|
} else {
|
2020-07-20 16:38:46 +03:00
|
|
|
alert(loc.send.qr_error_no_qrcode);
|
2020-05-28 11:44:15 +03:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
setIsLoading(false);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const dismiss = () => {
|
2020-05-31 16:30:01 +03:00
|
|
|
navigation.navigate(launchedBy);
|
2020-05-28 11:44:15 +03:00
|
|
|
};
|
|
|
|
|
2019-12-27 18:53:34 -06:00
|
|
|
return (
|
2020-05-24 12:17:26 +03:00
|
|
|
<View style={styles.root}>
|
2020-06-02 22:00:45 -04:00
|
|
|
<StatusBar hidden />
|
2020-05-28 11:44:15 +03:00
|
|
|
{!isLoading && isFocused && (
|
2019-05-02 16:33:03 -04:00
|
|
|
<RNCamera
|
|
|
|
captureAudio={false}
|
|
|
|
androidCameraPermissionOptions={{
|
2020-07-20 16:38:46 +03:00
|
|
|
title: loc.send.permission_camera_title,
|
|
|
|
message: loc.send.permission_camera_message,
|
|
|
|
buttonPositive: loc._.ok,
|
|
|
|
buttonNegative: loc._.cancel,
|
2019-05-02 16:33:03 -04:00
|
|
|
}}
|
2020-05-24 12:17:26 +03:00
|
|
|
style={styles.rnCamera}
|
2019-12-27 18:53:34 -06:00
|
|
|
onBarCodeRead={onBarCodeRead}
|
2019-05-02 16:33:03 -04:00
|
|
|
barCodeTypes={[RNCamera.Constants.BarCodeType.qr]}
|
|
|
|
/>
|
2019-12-27 18:53:34 -06:00
|
|
|
)}
|
2020-05-30 10:47:32 +03:00
|
|
|
<TouchableOpacity style={styles.closeTouch} onPress={dismiss}>
|
|
|
|
<Image style={styles.closeImage} source={require('../../img/close-white.png')} />
|
2020-05-28 11:44:15 +03:00
|
|
|
</TouchableOpacity>
|
2020-05-30 10:47:32 +03:00
|
|
|
<TouchableOpacity style={styles.imagePickerTouch} onPress={showImagePicker}>
|
2020-05-21 15:55:03 +02:00
|
|
|
<Icon name="image" type="font-awesome" color="#ffffff" />
|
2019-12-27 18:53:34 -06:00
|
|
|
</TouchableOpacity>
|
2019-12-31 21:31:04 -06:00
|
|
|
{showFileImportButton && (
|
2020-05-24 12:17:26 +03:00
|
|
|
<TouchableOpacity style={styles.filePickerTouch} onPress={showFilePicker}>
|
2020-05-21 15:55:03 +02:00
|
|
|
<Icon name="file-import" type="material-community" color="#ffffff" />
|
2019-09-21 13:37:37 -04:00
|
|
|
</TouchableOpacity>
|
2019-12-31 21:31:04 -06:00
|
|
|
)}
|
2019-12-27 18:53:34 -06:00
|
|
|
</View>
|
|
|
|
);
|
|
|
|
};
|
2018-03-18 02:48:23 +00:00
|
|
|
|
2019-12-27 18:53:34 -06:00
|
|
|
ScanQRCode.navigationOptions = {
|
2020-05-27 14:12:17 +03:00
|
|
|
headerShown: false,
|
2019-12-27 18:53:34 -06:00
|
|
|
};
|
2020-05-28 11:44:15 +03:00
|
|
|
|
2019-12-27 18:53:34 -06:00
|
|
|
export default ScanQRCode;
|